Browse Source

togl/togles: use PBO for DYNAMIC textures

pull/133/head
nillerusr 2 years ago
parent
commit
7a26688494
  1. 6
      public/togl/linuxwin/cglmtex.h
  2. 6
      public/togles/linuxwin/cglmtex.h
  3. 188
      togl/linuxwin/cglmtex.cpp
  4. 10
      togl/linuxwin/dxabstract.cpp
  5. 150
      togles/linuxwin/cglmtex.cpp
  6. 12
      togles/linuxwin/dxabstract.cpp

6
public/togl/linuxwin/cglmtex.h

@ -126,6 +126,7 @@ enum EGLMTexFlags
kGLMTexMultisampled = 0x40, // has an RBO backing it. Cannot combine with Mipped, MippedAuto. One slice maximum, only targeting GL_TEXTURE_2D. kGLMTexMultisampled = 0x40, // has an RBO backing it. Cannot combine with Mipped, MippedAuto. One slice maximum, only targeting GL_TEXTURE_2D.
// actually not 100% positive on the mipmapping, the RBO itself can't be mipped, but the resulting texture could // actually not 100% positive on the mipmapping, the RBO itself can't be mipped, but the resulting texture could
// have mipmaps generated. // have mipmaps generated.
kGLMTexDynamic = 0x80
}; };
//=============================================================================== //===============================================================================
@ -204,6 +205,7 @@ struct GLMTexLockParams
// tells GLM to force re-read of the texels back from GL // tells GLM to force re-read of the texels back from GL
// i.e. "I know I stepped on those texels with a draw or blit - the GLM copy is stale" // i.e. "I know I stepped on those texels with a draw or blit - the GLM copy is stale"
bool m_readback; bool m_readback;
bool m_readonly;
}; };
struct GLMTexLockDesc struct GLMTexLockDesc
@ -485,7 +487,7 @@ protected:
int CalcSliceIndex( int face, int mip ); int CalcSliceIndex( int face, int mip );
void CalcTexelDataOffsetAndStrides( int sliceIndex, int x, int y, int z, int *offsetOut, int *yStrideOut, int *zStrideOut ); void CalcTexelDataOffsetAndStrides( int sliceIndex, int x, int y, int z, int *offsetOut, int *yStrideOut, int *zStrideOut );
void ReadTexels( GLMTexLockDesc *desc, bool readWholeSlice=true ); GLubyte *ReadTexels( GLMTexLockDesc *desc, bool readWholeSlice=true, bool readOnly=false );
void WriteTexels( GLMTexLockDesc *desc, bool writeWholeSlice=true, bool noDataWrite=false ); void WriteTexels( GLMTexLockDesc *desc, bool writeWholeSlice=true, bool noDataWrite=false );
// last param lets us send NULL data ptr (only legal with uncompressed formats, beware) // last param lets us send NULL data ptr (only legal with uncompressed formats, beware)
// this helps out ResetSRGB. // this helps out ResetSRGB.
@ -505,6 +507,8 @@ protected:
// noWrite means send NULL for texel source addresses instead of actual data - ideal for RT's // noWrite means send NULL for texel source addresses instead of actual data - ideal for RT's
GLuint m_texName; // name of this texture in the context GLuint m_texName; // name of this texture in the context
GLuint m_pbo;
GLubyte *m_mapped;
GLenum m_texGLTarget; GLenum m_texGLTarget;
uint m_nSamplerType; // SAMPLER_2D, etc. uint m_nSamplerType; // SAMPLER_2D, etc.

6
public/togles/linuxwin/cglmtex.h

@ -126,6 +126,7 @@ enum EGLMTexFlags
kGLMTexMultisampled = 0x40, // has an RBO backing it. Cannot combine with Mipped, MippedAuto. One slice maximum, only targeting GL_TEXTURE_2D. kGLMTexMultisampled = 0x40, // has an RBO backing it. Cannot combine with Mipped, MippedAuto. One slice maximum, only targeting GL_TEXTURE_2D.
// actually not 100% positive on the mipmapping, the RBO itself can't be mipped, but the resulting texture could // actually not 100% positive on the mipmapping, the RBO itself can't be mipped, but the resulting texture could
// have mipmaps generated. // have mipmaps generated.
kGLMTexDynamic = 0x80
}; };
//=============================================================================== //===============================================================================
@ -204,6 +205,7 @@ struct GLMTexLockParams
// tells GLM to force re-read of the texels back from GL // tells GLM to force re-read of the texels back from GL
// i.e. "I know I stepped on those texels with a draw or blit - the GLM copy is stale" // i.e. "I know I stepped on those texels with a draw or blit - the GLM copy is stale"
bool m_readback; bool m_readback;
bool m_readonly;
}; };
struct GLMTexLockDesc struct GLMTexLockDesc
@ -485,7 +487,7 @@ protected:
int CalcSliceIndex( int face, int mip ); int CalcSliceIndex( int face, int mip );
void CalcTexelDataOffsetAndStrides( int sliceIndex, int x, int y, int z, int *offsetOut, int *yStrideOut, int *zStrideOut ); void CalcTexelDataOffsetAndStrides( int sliceIndex, int x, int y, int z, int *offsetOut, int *yStrideOut, int *zStrideOut );
void ReadTexels( GLMTexLockDesc *desc, bool readWholeSlice=true ); GLubyte *ReadTexels( GLMTexLockDesc *desc, bool readWholeSlice=true, bool readOnly=false );
void WriteTexels( GLMTexLockDesc *desc, bool writeWholeSlice=true, bool noDataWrite=false ); void WriteTexels( GLMTexLockDesc *desc, bool writeWholeSlice=true, bool noDataWrite=false );
// last param lets us send NULL data ptr (only legal with uncompressed formats, beware) // last param lets us send NULL data ptr (only legal with uncompressed formats, beware)
// this helps out ResetSRGB. // this helps out ResetSRGB.
@ -505,6 +507,8 @@ protected:
// noWrite means send NULL for texel source addresses instead of actual data - ideal for RT's // noWrite means send NULL for texel source addresses instead of actual data - ideal for RT's
GLuint m_texName; // name of this texture in the context GLuint m_texName; // name of this texture in the context
GLuint m_pbo;
GLubyte *m_mapped;
GLenum m_texGLTarget; GLenum m_texGLTarget;
uint m_nSamplerType; // SAMPLER_2D, etc. uint m_nSamplerType; // SAMPLER_2D, etc.

188
togl/linuxwin/cglmtex.cpp

@ -763,6 +763,17 @@ CGLMTex::CGLMTex( GLMContext *ctx, GLMTexLayout *layout, uint levels, const char
m_pBlitSrcFBO = NULL; m_pBlitSrcFBO = NULL;
m_pBlitDstFBO = NULL; m_pBlitDstFBO = NULL;
m_mapped = NULL;
m_pbo = 0;
if( m_layout->m_key.m_texFlags & kGLMTexDynamic )
{
gGL->glGenBuffersARB(1, &m_pbo);
gGL->glBindBufferARB(GL_PIXEL_UNPACK_BUFFER, m_pbo);
gGL->glBufferDataARB(GL_PIXEL_UNPACK_BUFFER, m_layout->m_storageTotalSize, 0, GL_STATIC_DRAW);
gGL->glBindBufferARB(GL_PIXEL_UNPACK_BUFFER, 0);
}
// Sense whether to try and apply client storage upon teximage/subimage. // Sense whether to try and apply client storage upon teximage/subimage.
// This should only be true if we're running on OSX 10.6 or it was explicitly // This should only be true if we're running on OSX 10.6 or it was explicitly
// enabled with -gl_texclientstorage on the command line. // enabled with -gl_texclientstorage on the command line.
@ -826,8 +837,7 @@ CGLMTex::CGLMTex( GLMContext *ctx, GLMTexLayout *layout, uint levels, const char
if ( !(layout->m_key.m_texFlags & kGLMTexRenderable) && m_texClientStorage ) if ( !(layout->m_key.m_texFlags & kGLMTexRenderable) && m_texClientStorage )
{ {
m_backing = (char *)malloc( m_layout->m_storageTotalSize ); m_backing = (char *)malloc( m_layout->m_storageTotalSize );
memset( m_backing, 0, m_layout->m_storageTotalSize );
// track bytes allocated for non-RT's // track bytes allocated for non-RT's
int formindex = sEncodeLayoutAsIndex( &layout->m_key ); int formindex = sEncodeLayoutAsIndex( &layout->m_key );
@ -1039,7 +1049,10 @@ CGLMTex::~CGLMTex( )
free( m_debugLabel ); free( m_debugLabel );
m_debugLabel = NULL; m_debugLabel = NULL;
} }
if( m_pbo )
gGL->glDeleteBuffersARB( 1, &m_pbo );
m_ctx = NULL; m_ctx = NULL;
} }
@ -1104,10 +1117,11 @@ void CGLMTex::CalcTexelDataOffsetAndStrides( int sliceIndex, int x, int y, int z
*zStrideOut = zStride; *zStrideOut = zStride;
} }
void CGLMTex::ReadTexels( GLMTexLockDesc *desc, bool readWholeSlice ) GLubyte *CGLMTex::ReadTexels( GLMTexLockDesc *desc, bool readWholeSlice, bool readOnly )
{ {
GLMRegion readBox; GLMRegion readBox;
GLubyte* data = NULL;
if (readWholeSlice) if (readWholeSlice)
{ {
readBox.xmin = readBox.ymin = readBox.zmin = 0; readBox.xmin = readBox.ymin = readBox.zmin = 0;
@ -1120,7 +1134,7 @@ void CGLMTex::ReadTexels( GLMTexLockDesc *desc, bool readWholeSlice )
{ {
readBox = desc->m_req.m_region; readBox = desc->m_req.m_region;
} }
CGLMTex *pPrevTex = m_ctx->m_samplers[0].m_pBoundTex; CGLMTex *pPrevTex = m_ctx->m_samplers[0].m_pBoundTex;
m_ctx->BindTexToTMU( this, 0 ); // SelectTMU(n) is a side effect m_ctx->BindTexToTMU( this, 0 ); // SelectTMU(n) is a side effect
@ -1132,46 +1146,52 @@ void CGLMTex::ReadTexels( GLMTexLockDesc *desc, bool readWholeSlice )
GLMTexFormatDesc *format = m_layout->m_format; GLMTexFormatDesc *format = m_layout->m_format;
GLenum target = m_layout->m_key.m_texGLTarget; GLenum target = m_layout->m_key.m_texGLTarget;
void *sliceAddress = m_backing + m_layout->m_slices[ desc->m_sliceIndex ].m_storageOffset; // this would change for PBO if( readOnly )
//int sliceSize = m_layout->m_slices[ desc->m_sliceIndex ].m_storageSize;
// interestingly enough, we can use the same path for both 2D and 3D fetch
switch( target )
{ {
case GL_TEXTURE_CUBE_MAP: data = m_backing + m_layout->m_slices[ desc->m_sliceIndex ].m_storageOffset; // this would change for PBO
//int sliceSize = m_layout->m_slices[ desc->m_sliceIndex ].m_storageSize;
// adjust target to steer to the proper face, then fall through to the 2D texture path. // interestingly enough, we can use the same path for both 2D and 3D fetch
target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + desc->m_req.m_face;
switch( target )
case GL_TEXTURE_2D:
case GL_TEXTURE_3D:
{ {
// check compressed or not case GL_TEXTURE_CUBE_MAP:
if (format->m_chunkSize != 1)
// adjust target to steer to the proper face, then fall through to the 2D texture path.
target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + desc->m_req.m_face;
case GL_TEXTURE_2D:
case GL_TEXTURE_3D:
{ {
// compressed path // check compressed or not
// http://www.opengl.org/sdk/docs/man/xhtml/glGetCompressedTexImage.xml if (format->m_chunkSize != 1)
{
gGL->glGetCompressedTexImage( target, // target // compressed path
// http://www.opengl.org/sdk/docs/man/xhtml/glGetCompressedTexImage.xml
gGL->glGetCompressedTexImage( target, // target
desc->m_req.m_mip, // level desc->m_req.m_mip, // level
sliceAddress ); // destination data ); // destination
} }
else else
{ {
// uncompressed path // uncompressed path
// http://www.opengl.org/sdk/docs/man/xhtml/glGetTexImage.xml // http://www.opengl.org/sdk/docs/man/xhtml/glGetTexImage.xml
gGL->glGetTexImage( target, // target
gGL->glGetTexImage( target, // target
desc->m_req.m_mip, // level desc->m_req.m_mip, // level
format->m_glDataFormat, // dataformat format->m_glDataFormat, // dataformat
format->m_glDataType, // datatype format->m_glDataType, // datatype
sliceAddress ); // destination data ); // destination
}
} }
break;
} }
break;
} }
else
{
gGL->glBindBufferARB(GL_PIXEL_UNPACK_BUFFER, m_pbo);
data = (GLubyte*)gGL->glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, m_layout->m_slices[ desc->m_sliceIndex ].m_storageSize, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
}
} }
else else
{ {
@ -1179,6 +1199,8 @@ void CGLMTex::ReadTexels( GLMTexLockDesc *desc, bool readWholeSlice )
} }
m_ctx->BindTexToTMU( pPrevTex, 0 ); m_ctx->BindTexToTMU( pPrevTex, 0 );
return data;
} }
// TexSubImage should work properly on every driver stack and GPU--enabling by default. // TexSubImage should work properly on every driver stack and GPU--enabling by default.
@ -1233,8 +1255,14 @@ void CGLMTex::WriteTexels( GLMTexLockDesc *desc, bool writeWholeSlice, bool noDa
GLenum glDataFormat = format->m_glDataFormat; // this could change if expansion kicks in GLenum glDataFormat = format->m_glDataFormat; // this could change if expansion kicks in
GLenum glDataType = format->m_glDataType; GLenum glDataType = format->m_glDataType;
GLMTexLayoutSlice *slice = &m_layout->m_slices[ desc->m_sliceIndex ]; GLMTexLayoutSlice *slice = &m_layout->m_slices[ desc->m_sliceIndex ];
void *sliceAddress = m_backing ? (m_backing + slice->m_storageOffset) : NULL; // this would change for PBO
void *sliceAddress = NULL;
if( m_mapped )
sliceAddress = m_mapped;
else if( m_backing )
sliceAddress = m_backing + slice->m_storageOffset;
// allow use of subimage if the target is texture2D and it has already been teximage'd // allow use of subimage if the target is texture2D and it has already been teximage'd
bool mayUseSubImage = false; bool mayUseSubImage = false;
@ -1281,7 +1309,7 @@ void CGLMTex::WriteTexels( GLMTexLockDesc *desc, bool writeWholeSlice, bool noDa
gGL->glTexParameteri( target, GL_TEXTURE_BASE_LEVEL, desc->m_req.m_mip); gGL->glTexParameteri( target, GL_TEXTURE_BASE_LEVEL, desc->m_req.m_mip);
} }
if (needsExpand) if (needsExpand && !m_mapped)
{ {
int expandSize = 0; int expandSize = 0;
@ -1361,12 +1389,13 @@ void CGLMTex::WriteTexels( GLMTexLockDesc *desc, bool writeWholeSlice, bool noDa
{ {
// go subimage2D if it's a replacement, not a creation // go subimage2D if it's a replacement, not a creation
if( !m_mapped )
{
gGL->glPixelStorei( GL_UNPACK_ROW_LENGTH, slice->m_xSize ); // in pixels
gGL->glPixelStorei( GL_UNPACK_SKIP_PIXELS, writeBox.xmin ); // in pixels
gGL->glPixelStorei( GL_UNPACK_SKIP_ROWS, writeBox.ymin ); // in pixels
gGL->glPixelStorei( GL_UNPACK_ROW_LENGTH, slice->m_xSize ); // in pixels gGL->glTexSubImage2D( target,
gGL->glPixelStorei( GL_UNPACK_SKIP_PIXELS, writeBox.xmin ); // in pixels
gGL->glPixelStorei( GL_UNPACK_SKIP_ROWS, writeBox.ymin ); // in pixels
gGL->glTexSubImage2D( target,
desc->m_req.m_mip, // level desc->m_req.m_mip, // level
writeBox.xmin, // xoffset into dest writeBox.xmin, // xoffset into dest
writeBox.ymin, // yoffset into dest writeBox.ymin, // yoffset into dest
@ -1375,25 +1404,25 @@ void CGLMTex::WriteTexels( GLMTexLockDesc *desc, bool writeWholeSlice, bool noDa
glDataFormat, // format glDataFormat, // format
glDataType, // type glDataType, // type
sliceAddress // data (will be offsetted by the SKIP_PIXELS and SKIP_ROWS - let GL do the math to find the first source texel) sliceAddress // data (will be offsetted by the SKIP_PIXELS and SKIP_ROWS - let GL do the math to find the first source texel)
); );
gGL->glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 ); gGL->glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 );
gGL->glPixelStorei( GL_UNPACK_SKIP_PIXELS, 0 ); gGL->glPixelStorei( GL_UNPACK_SKIP_PIXELS, 0 );
gGL->glPixelStorei( GL_UNPACK_SKIP_ROWS, 0 ); gGL->glPixelStorei( GL_UNPACK_SKIP_ROWS, 0 );
}
/* else
//http://www.opengl.org/sdk/docs/man/xhtml/glTexSubImage2D.xml {
glTexSubImage2D( target, gGL->glTexSubImage2D( target,
desc->m_req.m_mip, // level desc->m_req.m_mip, // level
0, // xoffset writeBox.xmin, // xoffset into dest
0, // yoffset writeBox.ymin, // yoffset into dest
slice->m_xSize, // width writeBox.xmax - writeBox.xmin, // width (was slice->m_xSize)
slice->m_ySize, // height writeBox.ymax - writeBox.ymin, // height (was slice->m_ySize)
glDataFormat, // format glDataFormat, // format
glDataType, // type glDataType, // type
sliceAddress // data 0
); );
*/ }
} }
else else
{ {
@ -1456,8 +1485,6 @@ void CGLMTex::WriteTexels( GLMTexLockDesc *desc, bool writeWholeSlice, bool noDa
} }
else else
{ {
// uncompressed path
// http://www.opengl.org/sdk/docs/man/xhtml/glTexImage3D.xml
gGL->glTexImage3D( target, // target gGL->glTexImage3D( target, // target
desc->m_req.m_mip, // level desc->m_req.m_mip, // level
intformat, // internalformat intformat, // internalformat
@ -1540,11 +1567,11 @@ void CGLMTex::Lock( GLMTexLockParams *params, char** addressOut, int* yStrideOut
unStoragePow2 |= unStoragePow2 >> 8; unStoragePow2 |= unStoragePow2 >> 8;
unStoragePow2 |= unStoragePow2 >> 16; unStoragePow2 |= unStoragePow2 >> 16;
unStoragePow2++; unStoragePow2++;
m_backing = (char *)calloc( unStoragePow2, 1 ); m_backing = (char *)malloc( unStoragePow2 );
} }
else else
{ {
m_backing = (char *)calloc( m_layout->m_storageTotalSize, 1 ); m_backing = (char *)malloc( m_layout->m_storageTotalSize );
} }
// clear the kSliceStorageValid bit on all slices // clear the kSliceStorageValid bit on all slices
@ -1639,14 +1666,18 @@ void CGLMTex::Lock( GLMTexLockParams *params, char** addressOut, int* yStrideOut
desc->m_sliceRegionOffset = offsetInSlice + desc->m_sliceBaseOffset; desc->m_sliceRegionOffset = offsetInSlice + desc->m_sliceBaseOffset;
if (copyout) if ( copyout && ( (m_layout->m_key.m_texFlags & kGLMTexDynamic) || params->m_readonly ) )
{ {
// read the whole slice *addressOut = ReadTexels( desc, true, params->m_readonly );
// (odds are we'll never request anything but a whole slice to be read..)
ReadTexels( desc, true ); if( !params->m_readonly )
} // this would be a good place to fill with scrub value if in debug... m_mapped = *addressOut;
}
*addressOut = m_backing + desc->m_sliceRegionOffset; else
{
*addressOut = m_backing + desc->m_sliceRegionOffset;
}
*yStrideOut = yStride; *yStrideOut = yStride;
*zStrideOut = zStride; *zStrideOut = zStride;
@ -1732,7 +1763,16 @@ void CGLMTex::Unlock( GLMTexLockParams *params )
// fullyDirty |= (m_sliceFlags[ desc->m_sliceIndex ] & kSliceStorageValid); // fullyDirty |= (m_sliceFlags[ desc->m_sliceIndex ] & kSliceStorageValid);
WriteTexels( desc, fullyDirty ); if( m_layout->m_key.m_texFlags & kGLMTexDynamic )
{
gGL->glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
WriteTexels( desc, fullyDirty );
m_mapped = NULL;
gGL->glBindBufferARB(GL_PIXEL_UNPACK_BUFFER, 0);
}
else
WriteTexels( desc, fullyDirty );
// logical place to trigger preloading // logical place to trigger preloading
// only do it for an RT tex, if it is not yet attached to any FBO. // only do it for an RT tex, if it is not yet attached to any FBO.

10
togl/linuxwin/dxabstract.cpp

@ -404,7 +404,7 @@ HRESULT IDirect3DDevice9::CreateTexture(UINT Width,UINT Height,UINT Levels,DWORD
if (Usage & D3DUSAGE_DYNAMIC) if (Usage & D3DUSAGE_DYNAMIC)
{ {
// GLMPRINTF(("-X- DYNAMIC tex usage ignored..")); //FIXME key.m_texFlags |= kGLMTexDynamic;
} }
if (Usage & D3DUSAGE_TEXTURE_SRGB) if (Usage & D3DUSAGE_TEXTURE_SRGB)
@ -617,7 +617,7 @@ HRESULT IDirect3DDevice9::CreateCubeTexture(UINT EdgeLength,UINT Levels,DWORD Us
if (Usage & D3DUSAGE_DYNAMIC) if (Usage & D3DUSAGE_DYNAMIC)
{ {
//GLMPRINTF(("-X- DYNAMIC tex usage ignored..")); //FIXME key.m_texFlags |= kGLMTexDynamic;
} }
if (Usage & D3DUSAGE_TEXTURE_SRGB) if (Usage & D3DUSAGE_TEXTURE_SRGB)
@ -823,7 +823,7 @@ HRESULT IDirect3DDevice9::CreateVolumeTexture(UINT Width,UINT Height,UINT Depth,
if (Usage & D3DUSAGE_DYNAMIC) if (Usage & D3DUSAGE_DYNAMIC)
{ {
GLMPRINTF(("-X- DYNAMIC tex usage ignored..")); //FIXME key.m_texFlags |= kGLMTexDynamic;
} }
if (Usage & D3DUSAGE_TEXTURE_SRGB) if (Usage & D3DUSAGE_TEXTURE_SRGB)
@ -1040,7 +1040,9 @@ HRESULT IDirect3DSurface9::LockRect(D3DLOCKED_RECT* pLockedRect,CONST RECT* pRec
// smells like readback, force texel readout // smells like readback, force texel readout
lockreq.m_readback = true; lockreq.m_readback = true;
} }
lockreq.m_readonly = Flags & D3DLOCK_READONLY;
char *lockAddress; char *lockAddress;
int yStride; int yStride;
int zStride; int zStride;

150
togles/linuxwin/cglmtex.cpp

@ -768,6 +768,17 @@ CGLMTex::CGLMTex( GLMContext *ctx, GLMTexLayout *layout, uint levels, const char
m_pBlitSrcFBO = NULL; m_pBlitSrcFBO = NULL;
m_pBlitDstFBO = NULL; m_pBlitDstFBO = NULL;
m_mapped = NULL;
m_pbo = 0;
if( m_layout->m_key.m_texFlags & kGLMTexDynamic )
{
gGL->glGenBuffers(1, &m_pbo);
gGL->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pbo);
gGL->glBufferData(GL_PIXEL_UNPACK_BUFFER, m_layout->m_storageTotalSize, 0, GL_DYNAMIC_DRAW);
gGL->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
}
// Sense whether to try and apply client storage upon teximage/subimage. // Sense whether to try and apply client storage upon teximage/subimage.
// This should only be true if we're running on OSX 10.6 or it was explicitly // This should only be true if we're running on OSX 10.6 or it was explicitly
// enabled with -gl_texclientstorage on the command line. // enabled with -gl_texclientstorage on the command line.
@ -831,8 +842,7 @@ CGLMTex::CGLMTex( GLMContext *ctx, GLMTexLayout *layout, uint levels, const char
if ( !(layout->m_key.m_texFlags & kGLMTexRenderable) && m_texClientStorage ) if ( !(layout->m_key.m_texFlags & kGLMTexRenderable) && m_texClientStorage )
{ {
m_backing = (char *)malloc( m_layout->m_storageTotalSize ); m_backing = (char *)malloc( m_layout->m_storageTotalSize );
memset( m_backing, 0, m_layout->m_storageTotalSize );
// track bytes allocated for non-RT's // track bytes allocated for non-RT's
int formindex = sEncodeLayoutAsIndex( &layout->m_key ); int formindex = sEncodeLayoutAsIndex( &layout->m_key );
@ -1041,7 +1051,10 @@ CGLMTex::~CGLMTex( )
free( m_debugLabel ); free( m_debugLabel );
m_debugLabel = NULL; m_debugLabel = NULL;
} }
if( m_pbo )
gGL->glDeleteBuffers( 1, &m_pbo );
m_ctx = NULL; m_ctx = NULL;
} }
@ -1108,10 +1121,11 @@ void CGLMTex::CalcTexelDataOffsetAndStrides( int sliceIndex, int x, int y, int z
extern void convert_texture( GLenum &internalformat, GLsizei width, GLsizei height, GLenum &format, GLenum &type, void *data ); extern void convert_texture( GLenum &internalformat, GLsizei width, GLsizei height, GLenum &format, GLenum &type, void *data );
void CGLMTex::ReadTexels( GLMTexLockDesc *desc, bool readWholeSlice ) GLubyte *CGLMTex::ReadTexels( GLMTexLockDesc *desc, bool readWholeSlice, bool readOnly )
{ {
GLMRegion readBox; GLMRegion readBox;
GLubyte* data = NULL;
if (readWholeSlice) if (readWholeSlice)
{ {
readBox.xmin = readBox.ymin = readBox.zmin = 0; readBox.xmin = readBox.ymin = readBox.zmin = 0;
@ -1137,34 +1151,20 @@ void CGLMTex::ReadTexels( GLMTexLockDesc *desc, bool readWholeSlice )
GLMTexFormatDesc *format = m_layout->m_format; GLMTexFormatDesc *format = m_layout->m_format;
GLenum target = m_layout->m_key.m_texGLTarget; GLenum target = m_layout->m_key.m_texGLTarget;
void *sliceAddress = m_backing + m_layout->m_slices[ desc->m_sliceIndex ].m_storageOffset; // this would change for PBO if( readOnly )
//int sliceSize = m_layout->m_slices[ desc->m_sliceIndex ].m_storageSize;
// interestingly enough, we can use the same path for both 2D and 3D fetch
switch( target )
{ {
case GL_TEXTURE_CUBE_MAP: data = m_backing + m_layout->m_slices[ desc->m_sliceIndex ].m_storageOffset; // this would change for PBO
//int sliceSize = m_layout->m_slices[ desc->m_sliceIndex ].m_storageSize;
// adjust target to steer to the proper face, then fall through to the 2D texture path. // interestingly enough, we can use the same path for both 2D and 3D fetch
target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + desc->m_req.m_face;
switch( target )
case GL_TEXTURE_2D:
case GL_TEXTURE_3D:
{ {
// check compressed or not case GL_TEXTURE_CUBE_MAP:
if (format->m_chunkSize != 1) // adjust target to steer to the proper face, then fall through to the 2D texture path.
{ target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + desc->m_req.m_face;
// compressed path case GL_TEXTURE_2D:
// http://www.opengl.org/sdk/docs/man/xhtml/glGetCompressedTexImage.xml case GL_TEXTURE_3D:
// TODO(nillerusr): implement me!
/*
gGL->glGetCompressedTexImage( target, // target
desc->m_req.m_mip, // level
sliceAddress ); // destination
*/
}
else
{ {
// uncompressed path // uncompressed path
// http://www.opengl.org/sdk/docs/man/xhtml/glGetTexImage.xml // http://www.opengl.org/sdk/docs/man/xhtml/glGetTexImage.xml
@ -1182,15 +1182,20 @@ void CGLMTex::ReadTexels( GLMTexLockDesc *desc, bool readWholeSlice )
GLenum dataType = format->m_glDataType; GLenum dataType = format->m_glDataType;
convert_texture(fmt, 0, 0, fmt, dataType, NULL); convert_texture(fmt, 0, 0, fmt, dataType, NULL);
gGL->glReadPixels(0, 0, m_layout->m_slices[ desc->m_sliceIndex ].m_xSize, m_layout->m_slices[ desc->m_sliceIndex ].m_ySize, fmt, dataType, sliceAddress); gGL->glReadPixels(0, 0, m_layout->m_slices[ desc->m_sliceIndex ].m_xSize, m_layout->m_slices[ desc->m_sliceIndex ].m_ySize, fmt, dataType, data);
gGL->glBindFramebuffer(GL_READ_FRAMEBUFFER, Rfbo); gGL->glBindFramebuffer(GL_READ_FRAMEBUFFER, Rfbo);
gGL->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, Dfbo); gGL->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, Dfbo);
gGL->glDeleteFramebuffers(1, &fbo); gGL->glDeleteFramebuffers(1, &fbo);
break;
} }
} }
break; }
else
{
gGL->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pbo);
data = (GLubyte*)gGL->glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, m_layout->m_slices[ desc->m_sliceIndex ].m_storageSize, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
} }
} }
else else
@ -1199,6 +1204,8 @@ void CGLMTex::ReadTexels( GLMTexLockDesc *desc, bool readWholeSlice )
} }
m_ctx->BindTexToTMU( pPrevTex, 0 ); m_ctx->BindTexToTMU( pPrevTex, 0 );
return data;
} }
struct mem_s struct mem_s
@ -3546,7 +3553,13 @@ void CGLMTex::WriteTexels( GLMTexLockDesc *desc, bool writeWholeSlice, bool noDa
GLenum glDataType = format->m_glDataType; GLenum glDataType = format->m_glDataType;
GLMTexLayoutSlice *slice = &m_layout->m_slices[ desc->m_sliceIndex ]; GLMTexLayoutSlice *slice = &m_layout->m_slices[ desc->m_sliceIndex ];
void *sliceAddress = m_backing ? (m_backing + slice->m_storageOffset) : NULL; // this would change for PBO
void *sliceAddress = NULL;
if( m_mapped )
sliceAddress = m_mapped;
else if( m_backing )
sliceAddress = m_backing + slice->m_storageOffset;
// allow use of subimage if the target is texture2D and it has already been teximage'd // allow use of subimage if the target is texture2D and it has already been teximage'd
bool mayUseSubImage = false; bool mayUseSubImage = false;
@ -3592,7 +3605,7 @@ void CGLMTex::WriteTexels( GLMTexLockDesc *desc, bool writeWholeSlice, bool noDa
gGL->glTexParameteri( target, GL_TEXTURE_BASE_LEVEL, desc->m_req.m_mip); gGL->glTexParameteri( target, GL_TEXTURE_BASE_LEVEL, desc->m_req.m_mip);
} }
if (needsExpand) if (needsExpand && !m_mapped)
{ {
int expandSize = 0; int expandSize = 0;
@ -3660,13 +3673,15 @@ void CGLMTex::WriteTexels( GLMTexLockDesc *desc, bool writeWholeSlice, bool noDa
{ {
// go subimage2D if it's a replacement, not a creation // go subimage2D if it's a replacement, not a creation
gGL->glPixelStorei( GL_UNPACK_ROW_LENGTH, slice->m_xSize ); // in pixels if( !m_mapped )
gGL->glPixelStorei( GL_UNPACK_SKIP_PIXELS, writeBox.xmin ); // in pixels {
gGL->glPixelStorei( GL_UNPACK_SKIP_ROWS, writeBox.ymin ); // in pixels gGL->glPixelStorei( GL_UNPACK_ROW_LENGTH, slice->m_xSize ); // in pixels
gGL->glPixelStorei( GL_UNPACK_SKIP_PIXELS, writeBox.xmin ); // in pixels
gGL->glPixelStorei( GL_UNPACK_SKIP_ROWS, writeBox.ymin ); // in pixels
convert_texture(intformat, writeBox.xmax - writeBox.xmin, writeBox.ymax - writeBox.ymin, glDataFormat, glDataType, sliceAddress); convert_texture(intformat, writeBox.xmax - writeBox.xmin, writeBox.ymax - writeBox.ymin, glDataFormat, glDataType, sliceAddress);
gGL->glTexSubImage2D( target, gGL->glTexSubImage2D( target,
desc->m_req.m_mip, // level desc->m_req.m_mip, // level
writeBox.xmin, // xoffset into dest writeBox.xmin, // xoffset into dest
writeBox.ymin, // yoffset into dest writeBox.ymin, // yoffset into dest
@ -3675,11 +3690,27 @@ void CGLMTex::WriteTexels( GLMTexLockDesc *desc, bool writeWholeSlice, bool noDa
glDataFormat, // format glDataFormat, // format
glDataType, // type glDataType, // type
sliceAddress // data (will be offsetted by the SKIP_PIXELS and SKIP_ROWS - let GL do the math to find the first source texel) sliceAddress // data (will be offsetted by the SKIP_PIXELS and SKIP_ROWS - let GL do the math to find the first source texel)
); );
gGL->glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 );
gGL->glPixelStorei( GL_UNPACK_SKIP_PIXELS, 0 );
gGL->glPixelStorei( GL_UNPACK_SKIP_ROWS, 0 );
}
else
{
convert_texture(intformat, writeBox.xmax - writeBox.xmin, writeBox.ymax - writeBox.ymin, glDataFormat, glDataType, NULL);
gGL->glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 ); gGL->glTexSubImage2D( target,
gGL->glPixelStorei( GL_UNPACK_SKIP_PIXELS, 0 ); desc->m_req.m_mip, // level
gGL->glPixelStorei( GL_UNPACK_SKIP_ROWS, 0 ); writeBox.xmin, // xoffset into dest
writeBox.ymin, // yoffset into dest
writeBox.xmax - writeBox.xmin, // width (was slice->m_xSize)
writeBox.ymax - writeBox.ymin, // height (was slice->m_ySize)
glDataFormat, // format
glDataType, // type
0
);
}
} }
else else
{ {
@ -3790,7 +3821,7 @@ void CGLMTex::Lock( GLMTexLockParams *params, char** addressOut, int* yStrideOut
} }
// on return, these things need to be true // on return, these things need to be true
// a - there needs to be storage allocated, which we will return an address within // a - there needs to be storage allocated, which we will return an address within
// b - the region corresponding to the slice being locked, will have valid data there for the whole slice. // b - the region corresponding to the slice being locked, will have valid data there for the whole slice.
// c - the slice is marked as locked // c - the slice is marked as locked
@ -3810,11 +3841,11 @@ void CGLMTex::Lock( GLMTexLockParams *params, char** addressOut, int* yStrideOut
unStoragePow2 |= unStoragePow2 >> 8; unStoragePow2 |= unStoragePow2 >> 8;
unStoragePow2 |= unStoragePow2 >> 16; unStoragePow2 |= unStoragePow2 >> 16;
unStoragePow2++; unStoragePow2++;
m_backing = (char *)calloc( unStoragePow2, 1 ); m_backing = (char *)malloc( unStoragePow2 );
} }
else else
{ {
m_backing = (char *)calloc( m_layout->m_storageTotalSize, 1 ); m_backing = (char *)malloc( m_layout->m_storageTotalSize );
} }
// clear the kSliceStorageValid bit on all slices // clear the kSliceStorageValid bit on all slices
@ -3909,14 +3940,20 @@ void CGLMTex::Lock( GLMTexLockParams *params, char** addressOut, int* yStrideOut
desc->m_sliceRegionOffset = offsetInSlice + desc->m_sliceBaseOffset; desc->m_sliceRegionOffset = offsetInSlice + desc->m_sliceBaseOffset;
if (copyout) if ( copyout && ( (m_layout->m_key.m_texFlags & kGLMTexDynamic) || params->m_readonly ) )
{ {
// read the whole slice // read the whole slice
// (odds are we'll never request anything but a whole slice to be read..) // (odds are we'll never request anything but a whole slice to be read..)
ReadTexels( desc, true ); *addressOut = ReadTexels( desc, true, params->m_readonly );
} // this would be a good place to fill with scrub value if in debug...
if( !params->m_readonly )
*addressOut = m_backing + desc->m_sliceRegionOffset; m_mapped = *addressOut;
}
else
{
*addressOut = m_backing + desc->m_sliceRegionOffset;
}
*yStrideOut = yStride; *yStrideOut = yStride;
*zStrideOut = zStride; *zStrideOut = zStride;
@ -4002,7 +4039,16 @@ void CGLMTex::Unlock( GLMTexLockParams *params )
// fullyDirty |= (m_sliceFlags[ desc->m_sliceIndex ] & kSliceStorageValid); // fullyDirty |= (m_sliceFlags[ desc->m_sliceIndex ] & kSliceStorageValid);
WriteTexels( desc, fullyDirty ); if( m_layout->m_key.m_texFlags & kGLMTexDynamic )
{
gGL->glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
WriteTexels( desc, fullyDirty );
m_mapped = NULL;
gGL->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
}
else
WriteTexels( desc, fullyDirty );
// logical place to trigger preloading // logical place to trigger preloading
// only do it for an RT tex, if it is not yet attached to any FBO. // only do it for an RT tex, if it is not yet attached to any FBO.

12
togles/linuxwin/dxabstract.cpp

@ -404,7 +404,7 @@ HRESULT IDirect3DDevice9::CreateTexture(UINT Width,UINT Height,UINT Levels,DWORD
if (Usage & D3DUSAGE_DYNAMIC) if (Usage & D3DUSAGE_DYNAMIC)
{ {
// GLMPRINTF(("-X- DYNAMIC tex usage ignored..")); //FIXME key.m_texFlags |= kGLMTexDynamic;
} }
if (Usage & D3DUSAGE_TEXTURE_SRGB) if (Usage & D3DUSAGE_TEXTURE_SRGB)
@ -617,7 +617,7 @@ HRESULT IDirect3DDevice9::CreateCubeTexture(UINT EdgeLength,UINT Levels,DWORD Us
if (Usage & D3DUSAGE_DYNAMIC) if (Usage & D3DUSAGE_DYNAMIC)
{ {
//GLMPRINTF(("-X- DYNAMIC tex usage ignored..")); //FIXME key.m_texFlags |= kGLMTexDynamic;
} }
if (Usage & D3DUSAGE_TEXTURE_SRGB) if (Usage & D3DUSAGE_TEXTURE_SRGB)
@ -823,7 +823,7 @@ HRESULT IDirect3DDevice9::CreateVolumeTexture(UINT Width,UINT Height,UINT Depth,
if (Usage & D3DUSAGE_DYNAMIC) if (Usage & D3DUSAGE_DYNAMIC)
{ {
GLMPRINTF(("-X- DYNAMIC tex usage ignored..")); //FIXME key.m_texFlags |= kGLMTexDynamic;
} }
if (Usage & D3DUSAGE_TEXTURE_SRGB) if (Usage & D3DUSAGE_TEXTURE_SRGB)
@ -1034,13 +1034,15 @@ HRESULT IDirect3DSurface9::LockRect(D3DLOCKED_RECT* pLockedRect,CONST RECT* pRec
lockreq.m_region.xmax = pRect->right; lockreq.m_region.xmax = pRect->right;
lockreq.m_region.ymax = pRect->bottom; lockreq.m_region.ymax = pRect->bottom;
lockreq.m_region.zmax = 1; lockreq.m_region.zmax = 1;
if ((Flags & (D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK)) == (D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK) ) if ((Flags & (D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK)) == (D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK) )
{ {
// smells like readback, force texel readout // smells like readback, force texel readout
lockreq.m_readback = true; lockreq.m_readback = true;
} }
lockreq.m_readonly = Flags & D3DLOCK_READONLY;
char *lockAddress; char *lockAddress;
int yStride; int yStride;
int zStride; int zStride;

Loading…
Cancel
Save