diff --git a/renderdoc/driver/gl/gl_driver.cpp b/renderdoc/driver/gl/gl_driver.cpp index 03e9ed0e6..42682f867 100644 --- a/renderdoc/driver/gl/gl_driver.cpp +++ b/renderdoc/driver/gl/gl_driver.cpp @@ -347,6 +347,7 @@ WrappedOpenGL::WrappedOpenGL(const char *logfile, const GLHookSet &funcs) globalExts.push_back("GL_ARB_clear_texture"); globalExts.push_back("GL_ARB_clip_control"); globalExts.push_back("GL_ARB_color_buffer_float"); + globalExts.push_back("GL_ARB_compressed_texture_pixel_storage"); globalExts.push_back("GL_ARB_compute_shader"); globalExts.push_back("GL_ARB_compute_variable_group_size"); globalExts.push_back("GL_ARB_conditional_render_inverted"); diff --git a/renderdoc/driver/gl/gl_manager.cpp b/renderdoc/driver/gl/gl_manager.cpp index 945776092..63697e02c 100644 --- a/renderdoc/driver/gl/gl_manager.cpp +++ b/renderdoc/driver/gl/gl_manager.cpp @@ -758,7 +758,7 @@ bool GLResourceManager::Serialise_InitialState(GLResource res) GLenum fmt = GetBaseFormat(details.internalFormat); GLenum type = GetDataType(details.internalFormat); - size_t size = GetByteSize(details.width, details.height, details.depth, fmt, type, 0); + size_t size = GetByteSize(details.width, details.height, details.depth, fmt, type); byte *buf = new byte[size]; @@ -780,7 +780,7 @@ bool GLResourceManager::Serialise_InitialState(GLResource res) t == eGL_TEXTURE_2D_ARRAY) d = details.depth; - size = GetByteSize(w, h, d, fmt, type, 0); + size = GetByteSize(w, h, d, fmt, type); GLenum targets[] = { eGL_TEXTURE_CUBE_MAP_POSITIVE_X, diff --git a/renderdoc/driver/gl/gl_renderstate.cpp b/renderdoc/driver/gl/gl_renderstate.cpp index 7b2e3dee1..4c0e403a5 100644 --- a/renderdoc/driver/gl/gl_renderstate.cpp +++ b/renderdoc/driver/gl/gl_renderstate.cpp @@ -25,6 +25,204 @@ #include "gl_renderstate.h" #include "gl_driver.h" +void PixelUnpackState::Fetch(const GLHookSet *funcs, bool compressed) +{ + funcs->glGetIntegerv(eGL_UNPACK_SWAP_BYTES, &swapBytes); + funcs->glGetIntegerv(eGL_UNPACK_ROW_LENGTH, &rowlength); + funcs->glGetIntegerv(eGL_UNPACK_IMAGE_HEIGHT, &imageheight); + funcs->glGetIntegerv(eGL_UNPACK_SKIP_PIXELS, &skipPixels); + funcs->glGetIntegerv(eGL_UNPACK_SKIP_ROWS, &skipRows); + funcs->glGetIntegerv(eGL_UNPACK_SKIP_IMAGES, &skipImages); + funcs->glGetIntegerv(eGL_UNPACK_ALIGNMENT, &alignment); + + if(compressed) + { + funcs->glGetIntegerv(eGL_UNPACK_COMPRESSED_BLOCK_WIDTH, &compressedBlockWidth); + funcs->glGetIntegerv(eGL_UNPACK_COMPRESSED_BLOCK_HEIGHT, &compressedBlockHeight); + funcs->glGetIntegerv(eGL_UNPACK_COMPRESSED_BLOCK_DEPTH, &compressedBlockDepth); + funcs->glGetIntegerv(eGL_UNPACK_COMPRESSED_BLOCK_SIZE, &compressedBlockSize); + } +} + +bool PixelUnpackState::FastPath(GLsizei width, GLsizei height, GLsizei depth, GLenum dataformat, GLenum basetype) +{ + if(swapBytes) + return false; + + if(skipPixels) + return false; + + if(height > 0 && skipRows) + return false; + + if(depth > 0 && skipImages) + return false; + + if(width > 0 && rowlength > 0 && width < rowlength) + return false; + + if(height > 0 && imageheight > 0 && height < imageheight) + return false; + + if(dataformat != eGL_NONE && alignment > (int32_t)GetByteSize(1, 1, 1, dataformat, basetype)) + return false; + + return true; +} + +byte *PixelUnpackState::Unpack(byte *pixels, GLsizei width, GLsizei height, GLsizei depth, GLenum dataformat, GLenum basetype) +{ + size_t pixelSize = GetByteSize(1, 1, 1, dataformat, basetype); + + size_t srcrowstride = pixelSize *RDCMAX(RDCMAX(width, 1), rowlength); + size_t srcimgstride = srcrowstride*RDCMAX(RDCMAX(height, 1), imageheight); + + size_t destrowstride = pixelSize*width; + size_t destimgstride = destrowstride*height; + + size_t elemSize = 1; + switch(basetype) + { + case eGL_UNSIGNED_BYTE: + case eGL_BYTE: + elemSize = 1; + break; + case eGL_UNSIGNED_SHORT: + case eGL_SHORT: + case eGL_HALF_FLOAT: + elemSize = 2; + break; + case eGL_UNSIGNED_INT: + case eGL_INT: + case eGL_FLOAT: + elemSize = 4; + break; + case eGL_DOUBLE: + elemSize = 8; + break; + default: + break; + } + + size_t allocsize = width*RDCMAX(1, height)*RDCMAX(1, depth)*pixelSize; + byte *ret = new byte[allocsize]; + + byte *source = pixels; + + if(skipPixels > 0) + source += skipPixels*pixelSize; + if(skipRows > 0 && height > 0) + source += skipRows*srcrowstride; + if(skipImages > 0 && depth > 0) + source += skipImages*srcimgstride; + + size_t align = 1; + // "If the number of bits per element is not 1, 2, 4, or 8 times the number of + // bits in a GL ubyte, then k = nl for all values of a" + // ie. alignment is only used for pixel formats of those pixel sizes. + if(pixelSize == 1 || pixelSize == 2 || pixelSize == 4 || pixelSize == 8) + align = RDCMAX(align, (size_t)alignment); + + byte *dest = ret; + + for(GLsizei img=0; img < RDCMAX(1, depth); img++) + { + byte *rowsource = source; + byte *rowdest = dest; + + for(GLsizei row=0; row < RDCMAX(1, height); row++) + { + memcpy(rowdest, rowsource, destrowstride); + + if(swapBytes && elemSize > 1) + { + for(size_t el=0; el < pixelSize*width; el += elemSize) + { + byte *element = rowdest + el; + + if(elemSize == 2) + { + std::swap(element[0], element[1]); + } + else if(elemSize == 4) + { + std::swap(element[0], element[3]); + std::swap(element[1], element[2]); + } + else if(elemSize == 8) + { + std::swap(element[0], element[7]); + std::swap(element[1], element[6]); + std::swap(element[2], element[5]); + std::swap(element[3], element[4]); + } + } + } + + rowdest += destrowstride; + rowsource += srcrowstride; + rowsource = (byte *)AlignUp((size_t)rowsource, align); + } + + dest += destimgstride; + source += srcimgstride; + source = (byte *)AlignUp((size_t)source, align); + } + + return ret; +} + +byte *PixelUnpackState::UnpackCompressed(byte *pixels, GLsizei width, GLsizei height, GLsizei depth, GLsizei &imageSize) +{ + size_t blocksX = (width+compressedBlockWidth-1)/compressedBlockWidth; + size_t blocksY = (height+compressedBlockHeight-1)/compressedBlockHeight; + size_t blocksZ = (depth+compressedBlockDepth-1)/compressedBlockDepth; + + blocksY = RDCMAX(1U, blocksY); + blocksZ = RDCMAX(1U, blocksZ); + + size_t srcrowstride = compressedBlockSize*RDCMAX(RDCMAX(width, compressedBlockWidth), rowlength)/compressedBlockWidth; + size_t srcimgstride = srcrowstride *RDCMAX(RDCMAX(height, compressedBlockHeight), imageheight)/compressedBlockHeight; + + size_t destrowstride = compressedBlockSize*RDCMAX(width, compressedBlockWidth)/compressedBlockWidth; + size_t destimgstride = destrowstride *RDCMAX(height, compressedBlockHeight)/compressedBlockHeight; + + size_t allocsize = blocksX*blocksY*blocksZ*compressedBlockSize; + byte *ret = new byte[allocsize]; + + imageSize = (GLsizei)allocsize; + + byte *source = pixels; + + if(skipPixels > 0) + source += (skipPixels/compressedBlockWidth)*compressedBlockSize; + if(skipRows > 0 && height > 0) + source += (skipRows/compressedBlockHeight)*srcrowstride; + if(skipImages > 0 && depth > 0) + source += skipImages*srcimgstride; + + byte *dest = ret; + + for(GLsizei img=0; img < RDCMAX(1, depth); img++) + { + byte *rowsource = source; + byte *rowdest = dest; + + for(size_t row=0; row < blocksY; row++) + { + memcpy(rowdest, rowsource, destrowstride); + + rowsource += srcrowstride; + rowdest += destrowstride; + } + + source += srcimgstride; + dest += destimgstride; + } + + return ret; +} + GLRenderState::GLRenderState(const GLHookSet *funcs, Serialiser *ser, LogState state) : m_Real(funcs) , m_pSerialiser(ser) @@ -337,6 +535,8 @@ void GLRenderState::FetchState(void *ctx, WrappedOpenGL *gl) m_Real->glGetIntegerv(eGL_FRONT_FACE, (GLint *)&FrontFace); m_Real->glGetIntegerv(eGL_CULL_FACE_MODE, (GLint *)&CullFace); + + Unpack.Fetch(m_Real, true); } void GLRenderState::ApplyState(void *ctx, WrappedOpenGL *gl) @@ -601,6 +801,18 @@ void GLRenderState::ApplyState(void *ctx, WrappedOpenGL *gl) m_Real->glFrontFace(FrontFace); m_Real->glCullFace(CullFace); + + m_Real->glPixelStorei(eGL_UNPACK_SWAP_BYTES, Unpack.swapBytes); + m_Real->glPixelStorei(eGL_UNPACK_ROW_LENGTH, Unpack.rowlength); + m_Real->glPixelStorei(eGL_UNPACK_IMAGE_HEIGHT, Unpack.imageheight); + m_Real->glPixelStorei(eGL_UNPACK_SKIP_PIXELS, Unpack.skipPixels); + m_Real->glPixelStorei(eGL_UNPACK_SKIP_ROWS, Unpack.skipRows); + m_Real->glPixelStorei(eGL_UNPACK_SKIP_IMAGES, Unpack.skipImages); + m_Real->glPixelStorei(eGL_UNPACK_ALIGNMENT, Unpack.alignment); + m_Real->glPixelStorei(eGL_UNPACK_COMPRESSED_BLOCK_WIDTH, Unpack.compressedBlockWidth); + m_Real->glPixelStorei(eGL_UNPACK_COMPRESSED_BLOCK_HEIGHT, Unpack.compressedBlockHeight); + m_Real->glPixelStorei(eGL_UNPACK_COMPRESSED_BLOCK_DEPTH, Unpack.compressedBlockDepth); + m_Real->glPixelStorei(eGL_UNPACK_COMPRESSED_BLOCK_SIZE, Unpack.compressedBlockSize); } void GLRenderState::Clear() @@ -671,6 +883,8 @@ void GLRenderState::Clear() RDCEraseEl(Hints); RDCEraseEl(FrontFace); RDCEraseEl(CullFace); + + RDCEraseEl(Unpack); } void GLRenderState::Serialise(LogState state, void *ctx, WrappedOpenGL *gl) @@ -904,4 +1118,16 @@ void GLRenderState::Serialise(LogState state, void *ctx, WrappedOpenGL *gl) m_pSerialiser->Serialise("GL_FRONT_FACE", FrontFace); m_pSerialiser->Serialise("GL_CULL_FACE_MODE", CullFace); + + m_pSerialiser->Serialise("GL_UNPACK_SWAP_BYTES", Unpack.swapBytes); + m_pSerialiser->Serialise("GL_UNPACK_ROW_LENGTH", Unpack.rowlength); + m_pSerialiser->Serialise("GL_UNPACK_IMAGE_HEIGHT", Unpack.imageheight); + m_pSerialiser->Serialise("GL_UNPACK_SKIP_PIXELS", Unpack.skipPixels); + m_pSerialiser->Serialise("GL_UNPACK_SKIP_ROWS", Unpack.skipRows); + m_pSerialiser->Serialise("GL_UNPACK_SKIP_IMAGES", Unpack.skipImages); + m_pSerialiser->Serialise("GL_UNPACK_ALIGNMENT", Unpack.alignment); + m_pSerialiser->Serialise("GL_UNPACK_COMPRESSED_BLOCK_WIDTH", Unpack.compressedBlockWidth); + m_pSerialiser->Serialise("GL_UNPACK_COMPRESSED_BLOCK_HEIGHT", Unpack.compressedBlockHeight); + m_pSerialiser->Serialise("GL_UNPACK_COMPRESSED_BLOCK_DEPTH", Unpack.compressedBlockDepth); + m_pSerialiser->Serialise("GL_UNPACK_COMPRESSED_BLOCK_SIZE", Unpack.compressedBlockSize); } diff --git a/renderdoc/driver/gl/gl_renderstate.h b/renderdoc/driver/gl/gl_renderstate.h index 22bb582fd..a1f705497 100644 --- a/renderdoc/driver/gl/gl_renderstate.h +++ b/renderdoc/driver/gl/gl_renderstate.h @@ -31,6 +31,23 @@ #include "maths/vec.h" +struct PixelUnpackState +{ + int32_t swapBytes; + int32_t rowlength, imageheight; + int32_t skipPixels, skipRows, skipImages; + int32_t alignment; + + int32_t compressedBlockWidth, compressedBlockHeight, compressedBlockDepth; + int32_t compressedBlockSize; + + void Fetch(const GLHookSet *funcs, bool compressed); + + bool FastPath(GLsizei width, GLsizei height, GLsizei depth, GLenum dataformat=eGL_NONE, GLenum basetype=eGL_NONE); + byte *Unpack(byte *pixels, GLsizei width, GLsizei height, GLsizei depth, GLenum dataformat, GLenum basetype); + byte *UnpackCompressed(byte *pixels, GLsizei width, GLsizei height, GLsizei depth, GLsizei &imageSize); +}; + struct GLRenderState { GLRenderState(const GLHookSet *funcs, Serialiser *ser, LogState state); @@ -231,7 +248,8 @@ struct GLRenderState GLenum FrontFace; GLenum CullFace; - // + + PixelUnpackState Unpack; private: Serialiser *m_pSerialiser; diff --git a/renderdoc/driver/gl/gl_replay.cpp b/renderdoc/driver/gl/gl_replay.cpp index c357e567b..3970dccb0 100644 --- a/renderdoc/driver/gl/gl_replay.cpp +++ b/renderdoc/driver/gl/gl_replay.cpp @@ -590,7 +590,7 @@ void GLReplay::CacheTexture(ResourceId id) else if(tex.format.special) { tex.byteSize += GetByteSize(RDCMAX(1U, tex.width>>m), RDCMAX(1U, tex.height>>m), RDCMAX(1U, tex.depth>>m), - GetBaseFormat((GLenum)fmt), GetDataType((GLenum)fmt), 1); + GetBaseFormat((GLenum)fmt), GetDataType((GLenum)fmt)); } else { diff --git a/renderdoc/driver/gl/gl_resources.cpp b/renderdoc/driver/gl/gl_resources.cpp index f7474df52..fa7190a0e 100644 --- a/renderdoc/driver/gl/gl_resources.cpp +++ b/renderdoc/driver/gl/gl_resources.cpp @@ -29,31 +29,10 @@ const GLenum eGL_LUMINANCE = (GLenum)0x1909; const GLenum eGL_LUMINANCE_ALPHA = (GLenum)0x190A; -size_t GetByteSize(GLsizei w, GLsizei h, GLsizei d, GLenum format, GLenum type, int align) +size_t GetByteSize(GLsizei w, GLsizei h, GLsizei d, GLenum format, GLenum type) { size_t elemSize = 0; - GLsizei alignMask = ~0x0; - GLsizei alignAdd = 0; - switch(align) - { - default: - case 1: - break; - case 2: - alignMask = ~0x1; - alignAdd = 1; - break; - case 4: - alignMask = ~0x3; - alignAdd = 3; - break; - case 8: - alignMask = ~0x7; - alignAdd = 7; - break; - } - switch(type) { case eGL_UNSIGNED_BYTE: @@ -75,14 +54,14 @@ size_t GetByteSize(GLsizei w, GLsizei h, GLsizei d, GLenum format, GLenum type, break; case eGL_UNSIGNED_BYTE_3_3_2: case eGL_UNSIGNED_BYTE_2_3_3_REV: - return ((w + alignAdd) & alignMask)*h*d; + return w*h*d; case eGL_UNSIGNED_SHORT_5_6_5: case eGL_UNSIGNED_SHORT_5_6_5_REV: case eGL_UNSIGNED_SHORT_4_4_4_4: case eGL_UNSIGNED_SHORT_4_4_4_4_REV: case eGL_UNSIGNED_SHORT_5_5_5_1: case eGL_UNSIGNED_SHORT_1_5_5_5_REV: - return ((w*2 + alignAdd) & alignMask)*h*d; + return w*h*d*2; case eGL_UNSIGNED_INT_8_8_8_8: case eGL_UNSIGNED_INT_8_8_8_8_REV: case eGL_UNSIGNED_INT_10_10_10_2: @@ -90,18 +69,18 @@ size_t GetByteSize(GLsizei w, GLsizei h, GLsizei d, GLenum format, GLenum type, case eGL_INT_2_10_10_10_REV: case eGL_UNSIGNED_INT_10F_11F_11F_REV: case eGL_UNSIGNED_INT_5_9_9_9_REV: - return ((w*4 + alignAdd) & alignMask)*h*d; + return w*h*d*4; case eGL_DEPTH_COMPONENT16: - return ((w*2 + alignAdd) & alignMask)*h*d; + return w*h*d*2; case eGL_DEPTH_COMPONENT24: case eGL_DEPTH24_STENCIL8: case eGL_DEPTH_COMPONENT32: case eGL_DEPTH_COMPONENT32F: case eGL_UNSIGNED_INT_24_8: - return ((w*4 + alignAdd) & alignMask)*h*d; + return w*h*d*4; case eGL_DEPTH32F_STENCIL8: case eGL_FLOAT_32_UNSIGNED_INT_24_8_REV: - return ((w*8 + alignAdd) & alignMask)*h*d; + return w*h*d*8; default: RDCERR("Unhandled Byte Size type %d!", type); break; @@ -118,22 +97,22 @@ size_t GetByteSize(GLsizei w, GLsizei h, GLsizei d, GLenum format, GLenum type, case eGL_LUMINANCE: case eGL_DEPTH_COMPONENT: case eGL_STENCIL_INDEX: - return ((w*elemSize + alignAdd) & alignMask)*h*d; + return w*h*d*elemSize; case eGL_RG: case eGL_RG_INTEGER: case eGL_LUMINANCE_ALPHA: case eGL_DEPTH_STENCIL: - return ((w*elemSize*2 + alignAdd) & alignMask)*h*d; + return w*h*d*elemSize*2; case eGL_RGB: case eGL_RGB_INTEGER: case eGL_BGR: case eGL_BGR_INTEGER: - return ((w*elemSize*3 + alignAdd) & alignMask)*h*d; + return w*h*d*elemSize*3; case eGL_RGBA: case eGL_RGBA_INTEGER: case eGL_BGRA: case eGL_BGRA_INTEGER: - return ((w*elemSize*4 + alignAdd) & alignMask)*h*d; + return w*h*d*elemSize*4; default: RDCERR("Unhandled Byte Size format %d!", format); break; diff --git a/renderdoc/driver/gl/gl_resources.h b/renderdoc/driver/gl/gl_resources.h index bced6ab99..73292f5f3 100644 --- a/renderdoc/driver/gl/gl_resources.h +++ b/renderdoc/driver/gl/gl_resources.h @@ -31,7 +31,7 @@ struct GLHookSet; -size_t GetByteSize(GLsizei w, GLsizei h, GLsizei d, GLenum format, GLenum type, int align); +size_t GetByteSize(GLsizei w, GLsizei h, GLsizei d, GLenum format, GLenum type); GLenum GetBaseFormat(GLenum internalFormat); GLenum GetDataType(GLenum internalFormat); GLenum GetSizedFormat(const GLHookSet &gl, GLenum target, GLenum internalFormat); diff --git a/renderdoc/driver/gl/wrappers/gl_buffer_funcs.cpp b/renderdoc/driver/gl/wrappers/gl_buffer_funcs.cpp index 47553ecfe..a70b65733 100644 --- a/renderdoc/driver/gl/wrappers/gl_buffer_funcs.cpp +++ b/renderdoc/driver/gl/wrappers/gl_buffer_funcs.cpp @@ -2091,7 +2091,7 @@ bool WrappedOpenGL::Serialise_glVertexArrayVertexAttribOffsetEXT(GLuint vaobj, G Size == 2 ? eGL_RG : Size == 3 ? eGL_RGB : eGL_RGBA; - Stride = (uint32_t)GetByteSize(1, 1, 1, SizeEnum, Type, 1); + Stride = (uint32_t)GetByteSize(1, 1, 1, SizeEnum, Type); } m_Real.glVertexArrayBindVertexBufferEXT(vaobj, Index, buffer, (GLintptr)Offset, Stride); } @@ -2186,7 +2186,7 @@ bool WrappedOpenGL::Serialise_glVertexArrayVertexAttribIOffsetEXT(GLuint vaobj, Size == 2 ? eGL_RG : Size == 3 ? eGL_RGB : eGL_RGBA; - Stride = (uint32_t)GetByteSize(1, 1, 1, SizeEnum, Type, 1); + Stride = (uint32_t)GetByteSize(1, 1, 1, SizeEnum, Type); } m_Real.glVertexArrayBindVertexBufferEXT(vaobj, Index, buffer, (GLintptr)Offset, Stride); } @@ -2281,7 +2281,7 @@ bool WrappedOpenGL::Serialise_glVertexArrayVertexAttribLOffsetEXT(GLuint vaobj, Size == 2 ? eGL_RG : Size == 3 ? eGL_RGB : eGL_RGBA; - Stride = (uint32_t)GetByteSize(1, 1, 1, SizeEnum, Type, 1); + Stride = (uint32_t)GetByteSize(1, 1, 1, SizeEnum, Type); } m_Real.glVertexArrayBindVertexBufferEXT(vaobj, Index, buffer, (GLintptr)Offset, Stride); } diff --git a/renderdoc/driver/gl/wrappers/gl_texture_funcs.cpp b/renderdoc/driver/gl/wrappers/gl_texture_funcs.cpp index fec0f45dd..da90bf407 100644 --- a/renderdoc/driver/gl/wrappers/gl_texture_funcs.cpp +++ b/renderdoc/driver/gl/wrappers/gl_texture_funcs.cpp @@ -1613,17 +1613,14 @@ void WrappedOpenGL::glPixelStorei(GLenum pname, GLint param) { m_Real.glPixelStorei(pname, param); - if(m_State >= WRITING) + // except for capturing frames we ignore this and embed the relevant + // parameters in the chunks that reference them. + if(m_State == WRITING_CAPFRAME) { SCOPED_SERIALISE_CONTEXT(PIXELSTORE); Serialise_glPixelStorei(pname, param); - if(GetCtxData().GetActiveTexRecord()) - GetCtxData().GetActiveTexRecord()->AddChunk(scope.Get()); - else if(m_State == WRITING_IDLE) - m_DeviceRecord->AddChunk(scope.Get()); - else if(m_State == WRITING_CAPFRAME) - m_ContextRecord->AddChunk(scope.Get()); + m_ContextRecord->AddChunk(scope.Get()); } } @@ -1683,16 +1680,25 @@ bool WrappedOpenGL::Serialise_glTextureImage1DEXT(GLuint texture, GLenum target, SERIALISE_ELEMENT(GLenum, Format, format); SERIALISE_ELEMENT(GLenum, Type, type); - GLint align = 1; - m_Real.glGetIntegerv(eGL_UNPACK_ALIGNMENT, &align); + byte *unpackedPixels = NULL; + byte *srcPixels = NULL; - GLint rowlen = 0; - m_Real.glGetIntegerv(eGL_UNPACK_ROW_LENGTH, &rowlen); + if(m_State >= WRITING && pixels) + { + PixelUnpackState unpack; unpack.Fetch(&m_Real, false); - size_t subimageSize = GetByteSize(rowlen > 0 ? rowlen : Width, 1, 1, Format, Type, align); + if(unpack.FastPath(Width, 0, 0, Format, Type)) + srcPixels = (byte *)pixels; + else + srcPixels = unpackedPixels = unpack.Unpack((byte *)pixels, Width, 0, 0, Format, Type); + } + + size_t subimageSize = GetByteSize(Width, 1, 1, Format, Type); SERIALISE_ELEMENT(bool, DataProvided, pixels != NULL); - SERIALISE_ELEMENT_BUF_OPT(byte *, buf, pixels, subimageSize, DataProvided); + SERIALISE_ELEMENT_BUF_OPT(byte *, buf, srcPixels, subimageSize, DataProvided); + + SAFE_DELETE_ARRAY(unpackedPixels); if(m_State == READING) { @@ -1918,16 +1924,25 @@ bool WrappedOpenGL::Serialise_glTextureImage2DEXT(GLuint texture, GLenum target, SERIALISE_ELEMENT(GLenum, Format, format); SERIALISE_ELEMENT(GLenum, Type, type); - GLint align = 1; - m_Real.glGetIntegerv(eGL_UNPACK_ALIGNMENT, &align); + byte *unpackedPixels = NULL; + byte *srcPixels = NULL; - GLint rowlen = 0; - m_Real.glGetIntegerv(eGL_UNPACK_ROW_LENGTH, &rowlen); + if(m_State >= WRITING && pixels) + { + PixelUnpackState unpack; unpack.Fetch(&m_Real, false); + + if(unpack.FastPath(Width, Height, 0, Format, Type)) + srcPixels = (byte *)pixels; + else + srcPixels = unpackedPixels = unpack.Unpack((byte *)pixels, Width, Height, 0, Format, Type); + } + + size_t subimageSize = GetByteSize(Width, Height, 1, Format, Type); - size_t subimageSize = GetByteSize(rowlen > 0 ? rowlen : Width, Height, 1, Format, Type, align); - SERIALISE_ELEMENT(bool, DataProvided, pixels != NULL); - SERIALISE_ELEMENT_BUF_OPT(byte *, buf, pixels, subimageSize, DataProvided); + SERIALISE_ELEMENT_BUF_OPT(byte *, buf, srcPixels, subimageSize, DataProvided); + + SAFE_DELETE_ARRAY(unpackedPixels); if(m_State == READING) { @@ -2160,16 +2175,25 @@ bool WrappedOpenGL::Serialise_glTextureImage3DEXT(GLuint texture, GLenum target, SERIALISE_ELEMENT(GLenum, Format, format); SERIALISE_ELEMENT(GLenum, Type, type); - GLint align = 1; - m_Real.glGetIntegerv(eGL_UNPACK_ALIGNMENT, &align); + byte *unpackedPixels = NULL; + byte *srcPixels = NULL; - GLint rowlen = 0; - m_Real.glGetIntegerv(eGL_UNPACK_ROW_LENGTH, &rowlen); + if(m_State >= WRITING && pixels) + { + PixelUnpackState unpack; unpack.Fetch(&m_Real, false); - size_t subimageSize = GetByteSize(rowlen > 0 ? rowlen : Width, Height, Depth, Format, Type, align); + if(unpack.FastPath(Width, Height, Depth, Format, Type)) + srcPixels = (byte *)pixels; + else + srcPixels = unpackedPixels = unpack.Unpack((byte *)pixels, Width, Height, Depth, Format, Type); + } + + size_t subimageSize = GetByteSize(Width, Height, Depth, Format, Type); SERIALISE_ELEMENT(bool, DataProvided, pixels != NULL); - SERIALISE_ELEMENT_BUF_OPT(byte *, buf, pixels, subimageSize, DataProvided); + SERIALISE_ELEMENT_BUF_OPT(byte *, buf, srcPixels, subimageSize, DataProvided); + + SAFE_DELETE_ARRAY(unpackedPixels); if(m_State == READING) { @@ -2400,10 +2424,25 @@ bool WrappedOpenGL::Serialise_glCompressedTextureImage1DEXT(GLuint texture, GLen SERIALISE_ELEMENT(uint32_t, Width, width); SERIALISE_ELEMENT(GLenum, fmt, internalformat); SERIALISE_ELEMENT(int32_t, Border, border); - SERIALISE_ELEMENT(uint32_t, byteSize, imageSize); + + byte *unpackedPixels = NULL; + byte *srcPixels = NULL; + + if(m_State >= WRITING && pixels) + { + PixelUnpackState unpack; unpack.Fetch(&m_Real, true); + if(unpack.FastPath(Width, 0, 0)) + srcPixels = (byte *)pixels; + else + srcPixels = unpackedPixels = unpack.UnpackCompressed((byte *)pixels, Width, 0, 0, imageSize); + } + + SERIALISE_ELEMENT(uint32_t, byteSize, imageSize); SERIALISE_ELEMENT(bool, DataProvided, pixels != NULL); - SERIALISE_ELEMENT_BUF_OPT(byte *, buf, pixels, byteSize, DataProvided); + SERIALISE_ELEMENT_BUF_OPT(byte *, buf, srcPixels, byteSize, DataProvided); + + SAFE_DELETE_ARRAY(unpackedPixels); if(m_State == READING) { @@ -2639,10 +2678,25 @@ bool WrappedOpenGL::Serialise_glCompressedTextureImage2DEXT(GLuint texture, GLen SERIALISE_ELEMENT(uint32_t, Height, height); SERIALISE_ELEMENT(GLenum, fmt, internalformat); SERIALISE_ELEMENT(int32_t, Border, border); - SERIALISE_ELEMENT(uint32_t, byteSize, imageSize); + + byte *unpackedPixels = NULL; + byte *srcPixels = NULL; + + if(m_State >= WRITING && pixels) + { + PixelUnpackState unpack; unpack.Fetch(&m_Real, true); + if(unpack.FastPath(Width, Height, 0)) + srcPixels = (byte *)pixels; + else + srcPixels = unpackedPixels = unpack.UnpackCompressed((byte *)pixels, Width, Height, 0, imageSize); + } + + SERIALISE_ELEMENT(uint32_t, byteSize, imageSize); SERIALISE_ELEMENT(bool, DataProvided, pixels != NULL); - SERIALISE_ELEMENT_BUF_OPT(byte *, buf, pixels, byteSize, DataProvided); + SERIALISE_ELEMENT_BUF_OPT(byte *, buf, srcPixels, byteSize, DataProvided); + + SAFE_DELETE_ARRAY(unpackedPixels); if(m_State == READING) { @@ -2882,10 +2936,25 @@ bool WrappedOpenGL::Serialise_glCompressedTextureImage3DEXT(GLuint texture, GLen SERIALISE_ELEMENT(uint32_t, Depth, depth); SERIALISE_ELEMENT(GLenum, fmt, internalformat); SERIALISE_ELEMENT(int32_t, Border, border); - SERIALISE_ELEMENT(uint32_t, byteSize, imageSize); + + byte *unpackedPixels = NULL; + byte *srcPixels = NULL; + + if(m_State >= WRITING && pixels) + { + PixelUnpackState unpack; unpack.Fetch(&m_Real, true); + if(unpack.FastPath(Width, Height, Depth)) + srcPixels = (byte *)pixels; + else + srcPixels = unpackedPixels = unpack.UnpackCompressed((byte *)pixels, Width, Height, Depth, imageSize); + } + + SERIALISE_ELEMENT(uint32_t, byteSize, imageSize); SERIALISE_ELEMENT(bool, DataProvided, pixels != NULL); - SERIALISE_ELEMENT_BUF_OPT(byte *, buf, pixels, byteSize, DataProvided); + SERIALISE_ELEMENT_BUF_OPT(byte *, buf, srcPixels, byteSize, DataProvided); + + SAFE_DELETE_ARRAY(unpackedPixels); if(m_State == READING) { @@ -4052,21 +4121,30 @@ bool WrappedOpenGL::Serialise_glTextureSubImage1DEXT(GLuint texture, GLenum targ SERIALISE_ELEMENT(GLenum, Type, type); SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(TextureRes(GetCtx(), texture))); - GLint align = 1; - m_Real.glGetIntegerv(eGL_UNPACK_ALIGNMENT, &align); - - GLint rowlen = 0; - m_Real.glGetIntegerv(eGL_UNPACK_ROW_LENGTH, &rowlen); - - size_t subimageSize = GetByteSize(rowlen > 0 ? rowlen : Width, 1, 1, Format, Type, align); - GLint unpackbuf = 0; m_Real.glGetIntegerv(eGL_PIXEL_UNPACK_BUFFER_BINDING, &unpackbuf); SERIALISE_ELEMENT(bool, UnpackBufBound, unpackbuf != 0); - SERIALISE_ELEMENT_BUF_OPT(byte *, buf, pixels, subimageSize, !UnpackBufBound); + byte *unpackedPixels = NULL; + byte *srcPixels = NULL; + + if(m_State >= WRITING && pixels && !UnpackBufBound) + { + PixelUnpackState unpack; unpack.Fetch(&m_Real, false); + + if(unpack.FastPath(Width, 0, 0, Format, Type)) + srcPixels = (byte *)pixels; + else + srcPixels = unpackedPixels = unpack.Unpack((byte *)pixels, Width, 0, 0, format, type); + } + + size_t subimageSize = GetByteSize(Width, 1, 1, Format, Type); + + SERIALISE_ELEMENT_BUF_OPT(byte *, buf, srcPixels, subimageSize, !UnpackBufBound); SERIALISE_ELEMENT(uint64_t, bufoffs, (uint64_t)pixels); + + SAFE_DELETE_ARRAY(unpackedPixels); if(m_State <= EXECUTING) { @@ -4235,25 +4313,31 @@ bool WrappedOpenGL::Serialise_glTextureSubImage2DEXT(GLuint texture, GLenum targ SERIALISE_ELEMENT(GLenum, Format, format); SERIALISE_ELEMENT(GLenum, Type, type); SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(TextureRes(GetCtx(), texture))); - - GLint align = 1; - m_Real.glGetIntegerv(eGL_UNPACK_ALIGNMENT, &align); - - GLint rowlen = 0; - m_Real.glGetIntegerv(eGL_UNPACK_ROW_LENGTH, &rowlen); - - GLint imgheight = 0; - m_Real.glGetIntegerv(eGL_UNPACK_IMAGE_HEIGHT, &imgheight); - - size_t subimageSize = GetByteSize(rowlen > 0 ? rowlen : Width, imgheight > 0 ? imgheight : Height, 1, Format, Type, align); GLint unpackbuf = 0; m_Real.glGetIntegerv(eGL_PIXEL_UNPACK_BUFFER_BINDING, &unpackbuf); SERIALISE_ELEMENT(bool, UnpackBufBound, unpackbuf != 0); - SERIALISE_ELEMENT_BUF_OPT(byte *, buf, pixels, subimageSize, !UnpackBufBound); + byte *unpackedPixels = NULL; + byte *srcPixels = NULL; + + if(m_State >= WRITING && pixels && !UnpackBufBound) + { + PixelUnpackState unpack; unpack.Fetch(&m_Real, false); + + if(unpack.FastPath(Width, Height, 0, Format, Type)) + srcPixels = (byte *)pixels; + else + srcPixels = unpackedPixels = unpack.Unpack((byte *)pixels, Width, Height, 0, Format, Type); + } + + size_t subimageSize = GetByteSize(Width, Height, 1, Format, Type); + + SERIALISE_ELEMENT_BUF_OPT(byte *, buf, srcPixels, subimageSize, !UnpackBufBound); SERIALISE_ELEMENT(uint64_t, bufoffs, (uint64_t)pixels); + + SAFE_DELETE_ARRAY(unpackedPixels); if(m_State <= EXECUTING) { @@ -4424,25 +4508,31 @@ bool WrappedOpenGL::Serialise_glTextureSubImage3DEXT(GLuint texture, GLenum targ SERIALISE_ELEMENT(GLenum, Format, format); SERIALISE_ELEMENT(GLenum, Type, type); SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(TextureRes(GetCtx(), texture))); - - GLint align = 1; - m_Real.glGetIntegerv(eGL_UNPACK_ALIGNMENT, &align); - - GLint rowlen = 0; - m_Real.glGetIntegerv(eGL_UNPACK_ROW_LENGTH, &rowlen); - - GLint imgheight = 0; - m_Real.glGetIntegerv(eGL_UNPACK_IMAGE_HEIGHT, &imgheight); - - size_t subimageSize = GetByteSize(rowlen > 0 ? rowlen : Width, imgheight > 0 ? imgheight : Height, Depth, Format, Type, align); GLint unpackbuf = 0; m_Real.glGetIntegerv(eGL_PIXEL_UNPACK_BUFFER_BINDING, &unpackbuf); - + SERIALISE_ELEMENT(bool, UnpackBufBound, unpackbuf != 0); - SERIALISE_ELEMENT_BUF_OPT(byte *, buf, pixels, subimageSize, !UnpackBufBound); + byte *unpackedPixels = NULL; + byte *srcPixels = NULL; + + if(m_State >= WRITING && pixels && !UnpackBufBound) + { + PixelUnpackState unpack; unpack.Fetch(&m_Real, false); + + if(unpack.FastPath(Width, Height, Depth, Format, Type)) + srcPixels = (byte *)pixels; + else + srcPixels = unpackedPixels = unpack.Unpack((byte *)pixels, Width, Height, Depth, Format, Type); + } + + size_t subimageSize = GetByteSize(Width, Height, Depth, Format, Type); + + SERIALISE_ELEMENT_BUF_OPT(byte *, buf, srcPixels, subimageSize, !UnpackBufBound); SERIALISE_ELEMENT(uint64_t, bufoffs, (uint64_t)pixels); + + SAFE_DELETE_ARRAY(unpackedPixels); if(m_State <= EXECUTING) { @@ -4607,17 +4697,32 @@ bool WrappedOpenGL::Serialise_glCompressedTextureSubImage1DEXT(GLuint texture, G SERIALISE_ELEMENT(int32_t, xoff, xoffset); SERIALISE_ELEMENT(uint32_t, Width, width); SERIALISE_ELEMENT(GLenum, fmt, format); - SERIALISE_ELEMENT(uint32_t, byteSize, imageSize); SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(TextureRes(GetCtx(), texture))); GLint unpackbuf = 0; m_Real.glGetIntegerv(eGL_PIXEL_UNPACK_BUFFER_BINDING, &unpackbuf); SERIALISE_ELEMENT(bool, UnpackBufBound, unpackbuf != 0); - SERIALISE_ELEMENT_BUF_OPT(byte *, buf, pixels, byteSize, !UnpackBufBound); + byte *unpackedPixels = NULL; + byte *srcPixels = NULL; + + if(m_State >= WRITING && pixels && !UnpackBufBound) + { + PixelUnpackState unpack; unpack.Fetch(&m_Real, true); + + if(unpack.FastPath(Width, 0, 0)) + srcPixels = (byte *)pixels; + else + srcPixels = unpackedPixels = unpack.UnpackCompressed((byte *)pixels, Width, 0, 0, imageSize); + } + + SERIALISE_ELEMENT(uint32_t, byteSize, imageSize); + SERIALISE_ELEMENT_BUF_OPT(byte *, buf, srcPixels, byteSize, !UnpackBufBound); SERIALISE_ELEMENT(uint64_t, bufoffs, (uint64_t)pixels); + SAFE_DELETE_ARRAY(unpackedPixels); + if(m_State <= EXECUTING) { if(!UnpackBufBound && m_State == READING && m_CurEventID == 0) @@ -4783,16 +4888,31 @@ bool WrappedOpenGL::Serialise_glCompressedTextureSubImage2DEXT(GLuint texture, G SERIALISE_ELEMENT(uint32_t, Width, width); SERIALISE_ELEMENT(uint32_t, Height, height); SERIALISE_ELEMENT(GLenum, fmt, format); - SERIALISE_ELEMENT(uint32_t, byteSize, imageSize); SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(TextureRes(GetCtx(), texture))); GLint unpackbuf = 0; m_Real.glGetIntegerv(eGL_PIXEL_UNPACK_BUFFER_BINDING, &unpackbuf); SERIALISE_ELEMENT(bool, UnpackBufBound, unpackbuf != 0); - SERIALISE_ELEMENT_BUF_OPT(byte *, buf, pixels, byteSize, !UnpackBufBound); + byte *unpackedPixels = NULL; + byte *srcPixels = NULL; + + if(m_State >= WRITING && pixels && !UnpackBufBound) + { + PixelUnpackState unpack; unpack.Fetch(&m_Real, true); + + if(unpack.FastPath(Width, Height, 0)) + srcPixels = (byte *)pixels; + else + srcPixels = unpackedPixels = unpack.UnpackCompressed((byte *)pixels, Width, Height, 0, imageSize); + } + + SERIALISE_ELEMENT(uint32_t, byteSize, imageSize); + SERIALISE_ELEMENT_BUF_OPT(byte *, buf, srcPixels, byteSize, !UnpackBufBound); SERIALISE_ELEMENT(uint64_t, bufoffs, (uint64_t)pixels); + + SAFE_DELETE_ARRAY(unpackedPixels); if(m_State <= EXECUTING) { @@ -4961,16 +5081,31 @@ bool WrappedOpenGL::Serialise_glCompressedTextureSubImage3DEXT(GLuint texture, G SERIALISE_ELEMENT(uint32_t, Height, height); SERIALISE_ELEMENT(uint32_t, Depth, depth); SERIALISE_ELEMENT(GLenum, fmt, format); - SERIALISE_ELEMENT(uint32_t, byteSize, imageSize); SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(TextureRes(GetCtx(), texture))); - + GLint unpackbuf = 0; m_Real.glGetIntegerv(eGL_PIXEL_UNPACK_BUFFER_BINDING, &unpackbuf); SERIALISE_ELEMENT(bool, UnpackBufBound, unpackbuf != 0); - SERIALISE_ELEMENT_BUF_OPT(byte *, buf, pixels, byteSize, !UnpackBufBound); + byte *unpackedPixels = NULL; + byte *srcPixels = NULL; + + if(m_State >= WRITING && pixels && !UnpackBufBound) + { + PixelUnpackState unpack; unpack.Fetch(&m_Real, true); + + if(unpack.FastPath(Width, Height, Depth)) + srcPixels = (byte *)pixels; + else + srcPixels = unpackedPixels = unpack.UnpackCompressed((byte *)pixels, Width, Height, Depth, imageSize); + } + + SERIALISE_ELEMENT(uint32_t, byteSize, imageSize); + SERIALISE_ELEMENT_BUF_OPT(byte *, buf, srcPixels, byteSize, !UnpackBufBound); SERIALISE_ELEMENT(uint64_t, bufoffs, (uint64_t)pixels); + + SAFE_DELETE_ARRAY(unpackedPixels); if(m_State <= EXECUTING) { @@ -5146,7 +5281,7 @@ bool WrappedOpenGL::Serialise_glTextureBufferRangeEXT(GLuint texture, GLenum tar if(m_State == READING && m_CurEventID == 0) { ResourceId liveId = GetResourceManager()->GetLiveID(texid); - m_Textures[liveId].width = uint32_t(Size)/uint32_t(GetByteSize(1, 1, 1, GetBaseFormat(fmt), GetDataType(fmt), 1)); + m_Textures[liveId].width = uint32_t(Size)/uint32_t(GetByteSize(1, 1, 1, GetBaseFormat(fmt), GetDataType(fmt))); m_Textures[liveId].height = 1; m_Textures[liveId].depth = 1; m_Textures[liveId].curType = TextureTarget(Target); @@ -5197,7 +5332,7 @@ void WrappedOpenGL::glTextureBufferRangeEXT(GLuint texture, GLenum target, GLenu m_Real.glGetIntegerv(TextureBinding(target), (GLint *)&texture); ResourceId texId = GetResourceManager()->GetID(TextureRes(GetCtx(), texture)); - m_Textures[texId].width = uint32_t(size)/uint32_t(GetByteSize(1, 1, 1, GetBaseFormat(internalformat), GetDataType(internalformat), 1)); + m_Textures[texId].width = uint32_t(size)/uint32_t(GetByteSize(1, 1, 1, GetBaseFormat(internalformat), GetDataType(internalformat))); m_Textures[texId].height = 1; m_Textures[texId].depth = 1; m_Textures[texId].curType = TextureTarget(target); @@ -5242,7 +5377,7 @@ void WrappedOpenGL::glTexBufferRange(GLenum target, GLenum internalformat, GLuin m_Real.glGetIntegerv(TextureBinding(target), (GLint *)&texture); ResourceId texId = GetResourceManager()->GetID(TextureRes(GetCtx(), texture)); - m_Textures[texId].width = uint32_t(size)/uint32_t(GetByteSize(1, 1, 1, GetBaseFormat(internalformat), GetDataType(internalformat), 1)); + m_Textures[texId].width = uint32_t(size)/uint32_t(GetByteSize(1, 1, 1, GetBaseFormat(internalformat), GetDataType(internalformat))); m_Textures[texId].height = 1; m_Textures[texId].depth = 1; m_Textures[texId].curType = TextureTarget(target); @@ -5267,7 +5402,7 @@ bool WrappedOpenGL::Serialise_glTextureBufferEXT(GLuint texture, GLenum target, ResourceId liveId = GetResourceManager()->GetLiveID(texid); uint32_t Size = 1; m_Real.glGetNamedBufferParameterivEXT(buffer, eGL_BUFFER_SIZE, (GLint *)&Size); - m_Textures[liveId].width = Size/uint32_t(GetByteSize(1, 1, 1, GetBaseFormat(fmt), GetDataType(fmt), 1)); + m_Textures[liveId].width = Size/uint32_t(GetByteSize(1, 1, 1, GetBaseFormat(fmt), GetDataType(fmt))); m_Textures[liveId].height = 1; m_Textures[liveId].depth = 1; m_Textures[liveId].curType = TextureTarget(Target); @@ -5321,7 +5456,7 @@ void WrappedOpenGL::glTextureBufferEXT(GLuint texture, GLenum target, GLenum int uint32_t size = 1; m_Real.glGetNamedBufferParameterivEXT(buffer, eGL_BUFFER_SIZE, (GLint *)&size); - m_Textures[texId].width = uint32_t(size)/uint32_t(GetByteSize(1, 1, 1, GetBaseFormat(internalformat), GetDataType(internalformat), 1)); + m_Textures[texId].width = uint32_t(size)/uint32_t(GetByteSize(1, 1, 1, GetBaseFormat(internalformat), GetDataType(internalformat))); m_Textures[texId].height = 1; m_Textures[texId].depth = 1; m_Textures[texId].curType = TextureTarget(target); @@ -5370,7 +5505,7 @@ void WrappedOpenGL::glTexBuffer(GLenum target, GLenum internalformat, GLuint buf uint32_t size = 1; m_Real.glGetNamedBufferParameterivEXT(buffer, eGL_BUFFER_SIZE, (GLint *)&size); - m_Textures[texId].width = uint32_t(size)/uint32_t(GetByteSize(1, 1, 1, GetBaseFormat(internalformat), GetDataType(internalformat), 1)); + m_Textures[texId].width = uint32_t(size)/uint32_t(GetByteSize(1, 1, 1, GetBaseFormat(internalformat), GetDataType(internalformat))); m_Textures[texId].height = 1; m_Textures[texId].depth = 1; m_Textures[texId].curType = TextureTarget(target); @@ -5419,7 +5554,7 @@ void WrappedOpenGL::glMultiTexBufferEXT(GLenum texunit, GLenum target, GLenum in uint32_t size = 1; m_Real.glGetNamedBufferParameterivEXT(buffer, eGL_BUFFER_SIZE, (GLint *)&size); - m_Textures[texId].width = uint32_t(size)/uint32_t(GetByteSize(1, 1, 1, GetBaseFormat(internalformat), GetDataType(internalformat), 1)); + m_Textures[texId].width = uint32_t(size)/uint32_t(GetByteSize(1, 1, 1, GetBaseFormat(internalformat), GetDataType(internalformat))); m_Textures[texId].height = 1; m_Textures[texId].depth = 1; m_Textures[texId].curType = TextureTarget(target);