diff --git a/public/togl/linuxwin/cglmtex.h b/public/togl/linuxwin/cglmtex.h index 55321316..7c1e4172 100644 --- a/public/togl/linuxwin/cglmtex.h +++ b/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. // actually not 100% positive on the mipmapping, the RBO itself can't be mipped, but the resulting texture could // have mipmaps generated. + kGLMTexDynamic = 0x80 }; //=============================================================================== @@ -204,6 +205,7 @@ struct GLMTexLockParams // 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" bool m_readback; + bool m_readonly; }; struct GLMTexLockDesc @@ -485,7 +487,7 @@ protected: int CalcSliceIndex( int face, int mip ); 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 ); // last param lets us send NULL data ptr (only legal with uncompressed formats, beware) // 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 GLuint m_texName; // name of this texture in the context + GLuint m_pbo; + GLubyte *m_mapped; GLenum m_texGLTarget; uint m_nSamplerType; // SAMPLER_2D, etc. diff --git a/public/togles/linuxwin/cglmtex.h b/public/togles/linuxwin/cglmtex.h index 3a312c67..32c7ed04 100644 --- a/public/togles/linuxwin/cglmtex.h +++ b/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. // actually not 100% positive on the mipmapping, the RBO itself can't be mipped, but the resulting texture could // have mipmaps generated. + kGLMTexDynamic = 0x80 }; //=============================================================================== @@ -204,6 +205,7 @@ struct GLMTexLockParams // 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" bool m_readback; + bool m_readonly; }; struct GLMTexLockDesc @@ -485,7 +487,7 @@ protected: int CalcSliceIndex( int face, int mip ); 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 ); // last param lets us send NULL data ptr (only legal with uncompressed formats, beware) // 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 GLuint m_texName; // name of this texture in the context + GLuint m_pbo; + GLubyte *m_mapped; GLenum m_texGLTarget; uint m_nSamplerType; // SAMPLER_2D, etc. diff --git a/togl/linuxwin/cglmtex.cpp b/togl/linuxwin/cglmtex.cpp index 30eb9e46..b0da0518 100644 --- a/togl/linuxwin/cglmtex.cpp +++ b/togl/linuxwin/cglmtex.cpp @@ -763,6 +763,17 @@ CGLMTex::CGLMTex( GLMContext *ctx, GLMTexLayout *layout, uint levels, const char m_pBlitSrcFBO = 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. // 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. @@ -826,8 +837,7 @@ CGLMTex::CGLMTex( GLMContext *ctx, GLMTexLayout *layout, uint levels, const char if ( !(layout->m_key.m_texFlags & kGLMTexRenderable) && m_texClientStorage ) { m_backing = (char *)malloc( m_layout->m_storageTotalSize ); - memset( m_backing, 0, m_layout->m_storageTotalSize ); - + // track bytes allocated for non-RT's int formindex = sEncodeLayoutAsIndex( &layout->m_key ); @@ -1039,7 +1049,10 @@ CGLMTex::~CGLMTex( ) free( m_debugLabel ); m_debugLabel = NULL; } - + + if( m_pbo ) + gGL->glDeleteBuffersARB( 1, &m_pbo ); + m_ctx = NULL; } @@ -1104,10 +1117,11 @@ void CGLMTex::CalcTexelDataOffsetAndStrides( int sliceIndex, int x, int y, int z *zStrideOut = zStride; } -void CGLMTex::ReadTexels( GLMTexLockDesc *desc, bool readWholeSlice ) +GLubyte *CGLMTex::ReadTexels( GLMTexLockDesc *desc, bool readWholeSlice, bool readOnly ) { GLMRegion readBox; - + GLubyte* data = NULL; + if (readWholeSlice) { readBox.xmin = readBox.ymin = readBox.zmin = 0; @@ -1120,7 +1134,7 @@ void CGLMTex::ReadTexels( GLMTexLockDesc *desc, bool readWholeSlice ) { readBox = desc->m_req.m_region; } - + CGLMTex *pPrevTex = m_ctx->m_samplers[0].m_pBoundTex; 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; 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 - //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 ) + + if( readOnly ) { - 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. - target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + desc->m_req.m_face; - - case GL_TEXTURE_2D: - case GL_TEXTURE_3D: + // interestingly enough, we can use the same path for both 2D and 3D fetch + + switch( target ) { - // check compressed or not - if (format->m_chunkSize != 1) + case GL_TEXTURE_CUBE_MAP: + + // 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 - // http://www.opengl.org/sdk/docs/man/xhtml/glGetCompressedTexImage.xml - - gGL->glGetCompressedTexImage( target, // target + // check compressed or not + if (format->m_chunkSize != 1) + { + // compressed path + // http://www.opengl.org/sdk/docs/man/xhtml/glGetCompressedTexImage.xml + gGL->glGetCompressedTexImage( target, // target desc->m_req.m_mip, // level - sliceAddress ); // destination - } - else - { - // uncompressed path - // http://www.opengl.org/sdk/docs/man/xhtml/glGetTexImage.xml - - gGL->glGetTexImage( target, // target + data ); // destination + } + else + { + // uncompressed path + // http://www.opengl.org/sdk/docs/man/xhtml/glGetTexImage.xml + gGL->glGetTexImage( target, // target desc->m_req.m_mip, // level format->m_glDataFormat, // dataformat 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 { @@ -1179,6 +1199,8 @@ void CGLMTex::ReadTexels( GLMTexLockDesc *desc, bool readWholeSlice ) } m_ctx->BindTexToTMU( pPrevTex, 0 ); + + return data; } // 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 glDataType = format->m_glDataType; - GLMTexLayoutSlice *slice = &m_layout->m_slices[ desc->m_sliceIndex ]; - void *sliceAddress = m_backing ? (m_backing + slice->m_storageOffset) : NULL; // this would change for PBO + GLMTexLayoutSlice *slice = &m_layout->m_slices[ desc->m_sliceIndex ]; + + 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 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); } - if (needsExpand) + if (needsExpand && !m_mapped) { 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 + 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->glPixelStorei( GL_UNPACK_SKIP_PIXELS, writeBox.xmin ); // in pixels - gGL->glPixelStorei( GL_UNPACK_SKIP_ROWS, writeBox.ymin ); // in pixels - - gGL->glTexSubImage2D( target, + gGL->glTexSubImage2D( target, desc->m_req.m_mip, // level writeBox.xmin, // xoffset into dest writeBox.ymin, // yoffset into dest @@ -1375,25 +1404,25 @@ void CGLMTex::WriteTexels( GLMTexLockDesc *desc, bool writeWholeSlice, bool noDa glDataFormat, // format 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) - ); - - gGL->glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 ); - gGL->glPixelStorei( GL_UNPACK_SKIP_PIXELS, 0 ); - gGL->glPixelStorei( GL_UNPACK_SKIP_ROWS, 0 ); - - /* - //http://www.opengl.org/sdk/docs/man/xhtml/glTexSubImage2D.xml - glTexSubImage2D( target, - desc->m_req.m_mip, // level - 0, // xoffset - 0, // yoffset - slice->m_xSize, // width - slice->m_ySize, // height - glDataFormat, // format - glDataType, // type - sliceAddress // data - ); - */ + ); + + gGL->glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 ); + gGL->glPixelStorei( GL_UNPACK_SKIP_PIXELS, 0 ); + gGL->glPixelStorei( GL_UNPACK_SKIP_ROWS, 0 ); + } + else + { + gGL->glTexSubImage2D( target, + desc->m_req.m_mip, // level + 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 { @@ -1456,8 +1485,6 @@ void CGLMTex::WriteTexels( GLMTexLockDesc *desc, bool writeWholeSlice, bool noDa } else { - // uncompressed path - // http://www.opengl.org/sdk/docs/man/xhtml/glTexImage3D.xml gGL->glTexImage3D( target, // target desc->m_req.m_mip, // level intformat, // internalformat @@ -1540,11 +1567,11 @@ void CGLMTex::Lock( GLMTexLockParams *params, char** addressOut, int* yStrideOut unStoragePow2 |= unStoragePow2 >> 8; unStoragePow2 |= unStoragePow2 >> 16; unStoragePow2++; - m_backing = (char *)calloc( unStoragePow2, 1 ); + m_backing = (char *)malloc( unStoragePow2 ); } 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 @@ -1639,14 +1666,18 @@ void CGLMTex::Lock( GLMTexLockParams *params, char** addressOut, int* yStrideOut 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 - // (odds are we'll never request anything but a whole slice to be read..) - ReadTexels( desc, true ); - } // this would be a good place to fill with scrub value if in debug... - - *addressOut = m_backing + desc->m_sliceRegionOffset; + *addressOut = ReadTexels( desc, true, params->m_readonly ); + + if( !params->m_readonly ) + m_mapped = *addressOut; + } + else + { + *addressOut = m_backing + desc->m_sliceRegionOffset; + } + *yStrideOut = yStride; *zStrideOut = zStride; @@ -1732,7 +1763,16 @@ void CGLMTex::Unlock( GLMTexLockParams *params ) // 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 // only do it for an RT tex, if it is not yet attached to any FBO. diff --git a/togl/linuxwin/dxabstract.cpp b/togl/linuxwin/dxabstract.cpp index 87c64f2c..bb62845f 100644 --- a/togl/linuxwin/dxabstract.cpp +++ b/togl/linuxwin/dxabstract.cpp @@ -404,7 +404,7 @@ HRESULT IDirect3DDevice9::CreateTexture(UINT Width,UINT Height,UINT Levels,DWORD if (Usage & D3DUSAGE_DYNAMIC) { - // GLMPRINTF(("-X- DYNAMIC tex usage ignored..")); //FIXME + key.m_texFlags |= kGLMTexDynamic; } if (Usage & D3DUSAGE_TEXTURE_SRGB) @@ -617,7 +617,7 @@ HRESULT IDirect3DDevice9::CreateCubeTexture(UINT EdgeLength,UINT Levels,DWORD Us if (Usage & D3DUSAGE_DYNAMIC) { - //GLMPRINTF(("-X- DYNAMIC tex usage ignored..")); //FIXME + key.m_texFlags |= kGLMTexDynamic; } if (Usage & D3DUSAGE_TEXTURE_SRGB) @@ -823,7 +823,7 @@ HRESULT IDirect3DDevice9::CreateVolumeTexture(UINT Width,UINT Height,UINT Depth, if (Usage & D3DUSAGE_DYNAMIC) { - GLMPRINTF(("-X- DYNAMIC tex usage ignored..")); //FIXME + key.m_texFlags |= kGLMTexDynamic; } if (Usage & D3DUSAGE_TEXTURE_SRGB) @@ -1040,7 +1040,9 @@ HRESULT IDirect3DSurface9::LockRect(D3DLOCKED_RECT* pLockedRect,CONST RECT* pRec // smells like readback, force texel readout lockreq.m_readback = true; } - + + lockreq.m_readonly = Flags & D3DLOCK_READONLY; + char *lockAddress; int yStride; int zStride; diff --git a/togles/linuxwin/cglmtex.cpp b/togles/linuxwin/cglmtex.cpp index 5230ad11..53b9ee8d 100644 --- a/togles/linuxwin/cglmtex.cpp +++ b/togles/linuxwin/cglmtex.cpp @@ -768,6 +768,17 @@ CGLMTex::CGLMTex( GLMContext *ctx, GLMTexLayout *layout, uint levels, const char m_pBlitSrcFBO = 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. // 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. @@ -831,8 +842,7 @@ CGLMTex::CGLMTex( GLMContext *ctx, GLMTexLayout *layout, uint levels, const char if ( !(layout->m_key.m_texFlags & kGLMTexRenderable) && m_texClientStorage ) { m_backing = (char *)malloc( m_layout->m_storageTotalSize ); - memset( m_backing, 0, m_layout->m_storageTotalSize ); - + // track bytes allocated for non-RT's int formindex = sEncodeLayoutAsIndex( &layout->m_key ); @@ -1041,7 +1051,10 @@ CGLMTex::~CGLMTex( ) free( m_debugLabel ); m_debugLabel = NULL; } - + + if( m_pbo ) + gGL->glDeleteBuffers( 1, &m_pbo ); + 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 ); -void CGLMTex::ReadTexels( GLMTexLockDesc *desc, bool readWholeSlice ) +GLubyte *CGLMTex::ReadTexels( GLMTexLockDesc *desc, bool readWholeSlice, bool readOnly ) { GLMRegion readBox; - + GLubyte* data = NULL; + if (readWholeSlice) { readBox.xmin = readBox.ymin = readBox.zmin = 0; @@ -1137,34 +1151,20 @@ void CGLMTex::ReadTexels( GLMTexLockDesc *desc, bool readWholeSlice ) GLMTexFormatDesc *format = m_layout->m_format; 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 - //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 ) + if( readOnly ) { - 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. - target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + desc->m_req.m_face; - - case GL_TEXTURE_2D: - case GL_TEXTURE_3D: + // interestingly enough, we can use the same path for both 2D and 3D fetch + + switch( target ) { - // check compressed or not - if (format->m_chunkSize != 1) - { - // compressed path - // http://www.opengl.org/sdk/docs/man/xhtml/glGetCompressedTexImage.xml - // TODO(nillerusr): implement me! -/* - gGL->glGetCompressedTexImage( target, // target - desc->m_req.m_mip, // level - sliceAddress ); // destination -*/ - } - else + case GL_TEXTURE_CUBE_MAP: + // 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: { // uncompressed path // 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; 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_DRAW_FRAMEBUFFER, Dfbo); 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 @@ -1199,6 +1204,8 @@ void CGLMTex::ReadTexels( GLMTexLockDesc *desc, bool readWholeSlice ) } m_ctx->BindTexToTMU( pPrevTex, 0 ); + + return data; } struct mem_s @@ -3546,7 +3553,13 @@ void CGLMTex::WriteTexels( GLMTexLockDesc *desc, bool writeWholeSlice, bool noDa GLenum glDataType = format->m_glDataType; 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 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); } - if (needsExpand) + if (needsExpand && !m_mapped) { 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 - 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 + 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 - 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 writeBox.xmin, // xoffset into dest writeBox.ymin, // yoffset into dest @@ -3675,11 +3690,27 @@ void CGLMTex::WriteTexels( GLMTexLockDesc *desc, bool writeWholeSlice, bool noDa glDataFormat, // format 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) - ); + ); + + 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->glPixelStorei( GL_UNPACK_SKIP_PIXELS, 0 ); - gGL->glPixelStorei( GL_UNPACK_SKIP_ROWS, 0 ); + gGL->glTexSubImage2D( target, + desc->m_req.m_mip, // level + 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 { @@ -3790,7 +3821,7 @@ void CGLMTex::Lock( GLMTexLockParams *params, char** addressOut, int* yStrideOut } // on return, these things need to be true - + // 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. // 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 >> 16; unStoragePow2++; - m_backing = (char *)calloc( unStoragePow2, 1 ); + m_backing = (char *)malloc( unStoragePow2 ); } 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 @@ -3909,14 +3940,20 @@ void CGLMTex::Lock( GLMTexLockParams *params, char** addressOut, int* yStrideOut 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 // (odds are we'll never request anything but a whole slice to be read..) - ReadTexels( desc, true ); - } // this would be a good place to fill with scrub value if in debug... - - *addressOut = m_backing + desc->m_sliceRegionOffset; + *addressOut = ReadTexels( desc, true, params->m_readonly ); + + if( !params->m_readonly ) + m_mapped = *addressOut; + } + else + { + *addressOut = m_backing + desc->m_sliceRegionOffset; + } + *yStrideOut = yStride; *zStrideOut = zStride; @@ -4002,7 +4039,16 @@ void CGLMTex::Unlock( GLMTexLockParams *params ) // 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 // only do it for an RT tex, if it is not yet attached to any FBO. diff --git a/togles/linuxwin/dxabstract.cpp b/togles/linuxwin/dxabstract.cpp index dbe485f0..4496fc4d 100644 --- a/togles/linuxwin/dxabstract.cpp +++ b/togles/linuxwin/dxabstract.cpp @@ -404,7 +404,7 @@ HRESULT IDirect3DDevice9::CreateTexture(UINT Width,UINT Height,UINT Levels,DWORD if (Usage & D3DUSAGE_DYNAMIC) { - // GLMPRINTF(("-X- DYNAMIC tex usage ignored..")); //FIXME + key.m_texFlags |= kGLMTexDynamic; } if (Usage & D3DUSAGE_TEXTURE_SRGB) @@ -617,7 +617,7 @@ HRESULT IDirect3DDevice9::CreateCubeTexture(UINT EdgeLength,UINT Levels,DWORD Us if (Usage & D3DUSAGE_DYNAMIC) { - //GLMPRINTF(("-X- DYNAMIC tex usage ignored..")); //FIXME + key.m_texFlags |= kGLMTexDynamic; } if (Usage & D3DUSAGE_TEXTURE_SRGB) @@ -823,7 +823,7 @@ HRESULT IDirect3DDevice9::CreateVolumeTexture(UINT Width,UINT Height,UINT Depth, if (Usage & D3DUSAGE_DYNAMIC) { - GLMPRINTF(("-X- DYNAMIC tex usage ignored..")); //FIXME + key.m_texFlags |= kGLMTexDynamic; } 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.ymax = pRect->bottom; lockreq.m_region.zmax = 1; - + if ((Flags & (D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK)) == (D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK) ) { // smells like readback, force texel readout lockreq.m_readback = true; } - + + lockreq.m_readonly = Flags & D3DLOCK_READONLY; + char *lockAddress; int yStride; int zStride;