mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-07-30 19:31:07 +00:00
Store and load data of compressed textures on GLES
Since GLES does not support glGetCompressedTexImage function, the compressed data cannot be extracted. For solving this, we store them at glCompressedTexImage* calls, and use these data when required (however it is not necessarily correct).
This commit is contained in:
committed by
Baldur Karlsson
parent
9ef362c28e
commit
70514fc5ac
@@ -279,6 +279,11 @@ private:
|
||||
// bound to the second.
|
||||
GLuint renderbufferReadTex;
|
||||
GLuint renderbufferFBOs[2];
|
||||
|
||||
// since compressed textures cannot be read back on GLES we have to store them during the
|
||||
// uploading
|
||||
// level -> data
|
||||
map<int, vector<byte> > compressedData;
|
||||
};
|
||||
|
||||
map<ResourceId, TextureData> m_Textures;
|
||||
@@ -517,6 +522,10 @@ private:
|
||||
vector<string> m_GLExtensions;
|
||||
vector<string> m_GLESExtensions;
|
||||
|
||||
void StoreCompressedTexData(ResourceId texId, GLenum target, GLint level, GLint xoffset,
|
||||
GLint yoffset, GLint zoffset, GLsizei width, GLsizei height,
|
||||
GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels);
|
||||
|
||||
// no copy semantics
|
||||
WrappedOpenGL(const WrappedOpenGL &);
|
||||
WrappedOpenGL &operator=(const WrappedOpenGL &);
|
||||
|
||||
+121
-162
@@ -562,6 +562,102 @@ bool GLResourceManager::Prepare_InitialState(GLResource res)
|
||||
return true;
|
||||
}
|
||||
|
||||
void GLResourceManager::CreateTextureImage(GLuint tex, GLenum internalFormat, GLenum textype,
|
||||
GLint dim, GLint width, GLint height, GLint depth,
|
||||
GLint samples, int mips)
|
||||
{
|
||||
const GLHookSet &gl = m_GL->GetHookset();
|
||||
|
||||
if(textype == eGL_TEXTURE_BUFFER)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if(textype == eGL_TEXTURE_2D_MULTISAMPLE)
|
||||
{
|
||||
gl.glTextureStorage2DMultisampleEXT(tex, textype, samples, internalFormat, width, height,
|
||||
GL_TRUE);
|
||||
}
|
||||
else if(textype == eGL_TEXTURE_2D_MULTISAMPLE_ARRAY)
|
||||
{
|
||||
gl.glTextureStorage3DMultisampleEXT(tex, textype, samples, internalFormat, width, height, depth,
|
||||
GL_TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
gl.glTextureParameteriEXT(tex, textype, eGL_TEXTURE_MAX_LEVEL, mips - 1);
|
||||
|
||||
bool isCompressed = IsCompressedFormat(internalFormat);
|
||||
|
||||
GLenum baseFormat = eGL_RGBA;
|
||||
GLenum dataType = eGL_UNSIGNED_BYTE;
|
||||
if(!isCompressed)
|
||||
{
|
||||
baseFormat = GetBaseFormat(internalFormat);
|
||||
dataType = GetDataType(internalFormat);
|
||||
}
|
||||
|
||||
GLenum targets[] = {
|
||||
eGL_TEXTURE_CUBE_MAP_POSITIVE_X, eGL_TEXTURE_CUBE_MAP_NEGATIVE_X,
|
||||
eGL_TEXTURE_CUBE_MAP_POSITIVE_Y, eGL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
|
||||
eGL_TEXTURE_CUBE_MAP_POSITIVE_Z, eGL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
|
||||
};
|
||||
|
||||
int count = ARRAY_COUNT(targets);
|
||||
|
||||
if(textype != eGL_TEXTURE_CUBE_MAP)
|
||||
{
|
||||
targets[0] = textype;
|
||||
count = 1;
|
||||
}
|
||||
|
||||
GLsizei w = (GLsizei)width;
|
||||
GLsizei h = (GLsizei)height;
|
||||
GLsizei d = (GLsizei)depth;
|
||||
|
||||
for(int m = 0; m < mips; m++)
|
||||
{
|
||||
for(int t = 0; t < count; t++)
|
||||
{
|
||||
if(isCompressed)
|
||||
{
|
||||
GLsizei compSize = (GLsizei)GetCompressedByteSize(w, h, d, internalFormat);
|
||||
|
||||
vector<byte> dummy;
|
||||
dummy.resize(compSize);
|
||||
|
||||
if(dim == 1)
|
||||
gl.glCompressedTextureImage1DEXT(tex, targets[t], m, internalFormat, w, 0, compSize,
|
||||
&dummy[0]);
|
||||
else if(dim == 2)
|
||||
gl.glCompressedTextureImage2DEXT(tex, targets[t], m, internalFormat, w, h, 0, compSize,
|
||||
&dummy[0]);
|
||||
else if(dim == 3)
|
||||
gl.glCompressedTextureImage3DEXT(tex, targets[t], m, internalFormat, w, h, d, 0,
|
||||
compSize, &dummy[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(dim == 1)
|
||||
gl.glTextureImage1DEXT(tex, targets[t], m, internalFormat, w, 0, baseFormat, dataType,
|
||||
NULL);
|
||||
else if(dim == 2)
|
||||
gl.glTextureImage2DEXT(tex, targets[t], m, internalFormat, w, h, 0, baseFormat,
|
||||
dataType, NULL);
|
||||
else if(dim == 3)
|
||||
gl.glTextureImage3DEXT(tex, targets[t], m, internalFormat, w, h, d, 0, baseFormat,
|
||||
dataType, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
w = RDCMAX(1, w >> 1);
|
||||
if(textype != eGL_TEXTURE_1D_ARRAY)
|
||||
h = RDCMAX(1, h >> 1);
|
||||
if(textype != eGL_TEXTURE_2D_ARRAY && textype != eGL_TEXTURE_CUBE_MAP_ARRAY)
|
||||
d = RDCMAX(1, d >> 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GLResourceManager::PrepareTextureInitialContents(ResourceId liveid, ResourceId origid,
|
||||
GLResource res)
|
||||
{
|
||||
@@ -671,95 +767,16 @@ void GLResourceManager::PrepareTextureInitialContents(ResourceId liveid, Resourc
|
||||
gl.glBindTexture(details.curType, oldtex);
|
||||
}
|
||||
|
||||
int depth = details.depth;
|
||||
if(details.curType != eGL_TEXTURE_3D)
|
||||
depth = 1;
|
||||
|
||||
int mips =
|
||||
GetNumMips(gl, details.curType, res.name, details.width, details.height, details.depth);
|
||||
|
||||
GLenum baseFormat = eGL_RGBA;
|
||||
GLenum dataType = eGL_UNSIGNED_BYTE;
|
||||
if(!IsCompressedFormat(details.internalFormat))
|
||||
{
|
||||
baseFormat = GetBaseFormat(details.internalFormat);
|
||||
dataType = GetDataType(details.internalFormat);
|
||||
}
|
||||
if(details.curType == eGL_TEXTURE_2D_MULTISAMPLE ||
|
||||
details.curType == eGL_TEXTURE_2D_MULTISAMPLE_ARRAY)
|
||||
mips = 1;
|
||||
|
||||
// create texture of identical format/size to store initial contents
|
||||
if(details.curType == eGL_TEXTURE_2D_MULTISAMPLE)
|
||||
{
|
||||
gl.glTextureStorage2DMultisampleEXT(tex, details.curType, details.samples,
|
||||
details.internalFormat, details.width, details.height,
|
||||
GL_TRUE);
|
||||
mips = 1;
|
||||
}
|
||||
else if(details.curType == eGL_TEXTURE_2D_MULTISAMPLE_ARRAY)
|
||||
{
|
||||
gl.glTextureStorage3DMultisampleEXT(tex, details.curType, details.samples,
|
||||
details.internalFormat, details.width, details.height,
|
||||
details.depth, GL_TRUE);
|
||||
mips = 1;
|
||||
}
|
||||
else if(details.dimension == 1)
|
||||
{
|
||||
gl.glTextureParameteriEXT(tex, details.curType, eGL_TEXTURE_MAX_LEVEL, mips - 1);
|
||||
|
||||
int w = details.width;
|
||||
for(int i = 0; i < mips; i++)
|
||||
{
|
||||
gl.glTextureImage1DEXT(tex, details.curType, i, details.internalFormat, w, 0, baseFormat,
|
||||
dataType, NULL);
|
||||
w = RDCMAX(1, w >> 1);
|
||||
}
|
||||
}
|
||||
else if(details.dimension == 2)
|
||||
{
|
||||
GLenum targets[] = {
|
||||
eGL_TEXTURE_CUBE_MAP_POSITIVE_X, eGL_TEXTURE_CUBE_MAP_NEGATIVE_X,
|
||||
eGL_TEXTURE_CUBE_MAP_POSITIVE_Y, eGL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
|
||||
eGL_TEXTURE_CUBE_MAP_POSITIVE_Z, eGL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
|
||||
};
|
||||
|
||||
gl.glTextureParameteriEXT(tex, details.curType, eGL_TEXTURE_MAX_LEVEL, mips - 1);
|
||||
|
||||
int w = details.width;
|
||||
int h = details.height;
|
||||
for(int i = 0; i < mips; i++)
|
||||
{
|
||||
if(details.curType != eGL_TEXTURE_CUBE_MAP)
|
||||
{
|
||||
gl.glTextureImage2DEXT(tex, details.curType, i, details.internalFormat, w, h, 0,
|
||||
baseFormat, dataType, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(size_t t = 0; t < ARRAY_COUNT(targets); t++)
|
||||
gl.glTextureImage2DEXT(tex, targets[t], i, details.internalFormat, w, h, 0,
|
||||
baseFormat, dataType, NULL);
|
||||
}
|
||||
w = RDCMAX(1, w >> 1);
|
||||
if(details.curType != eGL_TEXTURE_1D_ARRAY)
|
||||
h = RDCMAX(1, h >> 1);
|
||||
}
|
||||
}
|
||||
else if(details.dimension == 3)
|
||||
{
|
||||
gl.glTextureParameteriEXT(tex, details.curType, eGL_TEXTURE_MAX_LEVEL, mips - 1);
|
||||
|
||||
int w = details.width;
|
||||
int h = details.height;
|
||||
int d = details.depth;
|
||||
for(int i = 0; i < mips; i++)
|
||||
{
|
||||
gl.glTextureImage3DEXT(tex, details.curType, i, details.internalFormat, w, h, d, 0,
|
||||
baseFormat, dataType, NULL);
|
||||
w = RDCMAX(1, w >> 1);
|
||||
h = RDCMAX(1, h >> 1);
|
||||
if(details.curType == eGL_TEXTURE_3D)
|
||||
d = RDCMAX(1, d >> 1);
|
||||
}
|
||||
}
|
||||
CreateTextureImage(tex, details.internalFormat, details.curType, details.dimension,
|
||||
details.width, details.height, details.depth, details.samples, mips);
|
||||
|
||||
// we need to set maxlevel appropriately for number of mips to force the texture to be
|
||||
// complete.
|
||||
@@ -1164,7 +1181,21 @@ bool GLResourceManager::Serialise_InitialState(ResourceId resid, GLResource res)
|
||||
|
||||
byte *buf = new byte[size];
|
||||
|
||||
gl.glGetCompressedTextureImageEXT(tex, targets[trg], i, buf);
|
||||
if(IsGLES)
|
||||
{
|
||||
const vector<byte> &data = details.compressedData[i];
|
||||
const byte *src =
|
||||
(count == 1) ? data.data() : data.data() + CubeTargetIndex(targets[trg]) * size;
|
||||
size_t storedSize = data.size() / count;
|
||||
if(storedSize == size)
|
||||
memcpy(buf, src, size);
|
||||
else
|
||||
RDCERR("Different expected and stored compressed texture sizes!");
|
||||
}
|
||||
else
|
||||
{
|
||||
gl.glGetCompressedTextureImageEXT(tex, targets[trg], i, buf);
|
||||
}
|
||||
|
||||
m_pSerialiser->SerialiseBuffer("image", buf, size);
|
||||
|
||||
@@ -1378,90 +1409,18 @@ bool GLResourceManager::Serialise_InitialState(ResourceId resid, GLResource res)
|
||||
GLenum dummy;
|
||||
EmulateLuminanceFormat(gl, tex, textype, internalformat, dummy);
|
||||
|
||||
GLenum baseFormat = eGL_RGBA;
|
||||
GLenum dataType = eGL_UNSIGNED_BYTE;
|
||||
if(!IsCompressedFormat(internalformat))
|
||||
{
|
||||
baseFormat = GetBaseFormat(internalformat);
|
||||
dataType = GetDataType(internalformat);
|
||||
}
|
||||
|
||||
// create texture of identical format/size to store initial contents
|
||||
if(textype == eGL_TEXTURE_BUFFER || details.view)
|
||||
{
|
||||
// no 'contents' texture to create
|
||||
}
|
||||
else if(textype == eGL_TEXTURE_2D_MULTISAMPLE)
|
||||
else
|
||||
{
|
||||
gl.glTextureStorage2DMultisampleEXT(tex, textype, samples, internalformat, width, height,
|
||||
GL_TRUE);
|
||||
CreateTextureImage(tex, internalformat, textype, dim, width, height, depth, samples, mips);
|
||||
}
|
||||
|
||||
if(textype == eGL_TEXTURE_2D_MULTISAMPLE || textype == eGL_TEXTURE_2D_MULTISAMPLE_ARRAY)
|
||||
mips = 1;
|
||||
}
|
||||
else if(textype == eGL_TEXTURE_2D_MULTISAMPLE_ARRAY)
|
||||
{
|
||||
gl.glTextureStorage3DMultisampleEXT(tex, textype, samples, internalformat, width, height,
|
||||
depth, GL_TRUE);
|
||||
mips = 1;
|
||||
}
|
||||
else if(dim == 1)
|
||||
{
|
||||
gl.glTextureParameteriEXT(tex, textype, eGL_TEXTURE_MAX_LEVEL, mips - 1);
|
||||
|
||||
int w = width;
|
||||
for(int i = 0; i < mips; i++)
|
||||
{
|
||||
gl.glTextureImage1DEXT(tex, textype, i, internalformat, w, 0, baseFormat, dataType, NULL);
|
||||
w = RDCMAX(1, w >> 1);
|
||||
}
|
||||
}
|
||||
else if(dim == 2)
|
||||
{
|
||||
GLenum targets[] = {
|
||||
eGL_TEXTURE_CUBE_MAP_POSITIVE_X, eGL_TEXTURE_CUBE_MAP_NEGATIVE_X,
|
||||
eGL_TEXTURE_CUBE_MAP_POSITIVE_Y, eGL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
|
||||
eGL_TEXTURE_CUBE_MAP_POSITIVE_Z, eGL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
|
||||
};
|
||||
|
||||
gl.glTextureParameteriEXT(tex, textype, eGL_TEXTURE_MAX_LEVEL, mips - 1);
|
||||
|
||||
int w = width;
|
||||
int h = height;
|
||||
for(int i = 0; i < mips; i++)
|
||||
{
|
||||
if(textype != eGL_TEXTURE_CUBE_MAP)
|
||||
{
|
||||
gl.glTextureImage2DEXT(tex, textype, i, internalformat, w, h, 0, baseFormat, dataType,
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(size_t t = 0; t < ARRAY_COUNT(targets); t++)
|
||||
gl.glTextureImage2DEXT(tex, targets[t], i, internalformat, w, h, 0, baseFormat,
|
||||
dataType, NULL);
|
||||
}
|
||||
|
||||
w = RDCMAX(1, w >> 1);
|
||||
if(textype != eGL_TEXTURE_1D_ARRAY)
|
||||
h = RDCMAX(1, h >> 1);
|
||||
}
|
||||
}
|
||||
else if(dim == 3)
|
||||
{
|
||||
gl.glTextureParameteriEXT(tex, textype, eGL_TEXTURE_MAX_LEVEL, mips - 1);
|
||||
|
||||
int w = width;
|
||||
int h = height;
|
||||
int d = depth;
|
||||
for(int i = 0; i < mips; i++)
|
||||
{
|
||||
gl.glTextureImage3DEXT(tex, textype, i, internalformat, w, h, d, 0, baseFormat,
|
||||
dataType, NULL);
|
||||
w = RDCMAX(1, w >> 1);
|
||||
h = RDCMAX(1, h >> 1);
|
||||
if(textype == eGL_TEXTURE_3D)
|
||||
d = RDCMAX(1, d >> 1);
|
||||
}
|
||||
}
|
||||
|
||||
if(textype == eGL_TEXTURE_BUFFER || details.view)
|
||||
{
|
||||
|
||||
@@ -220,6 +220,8 @@ private:
|
||||
bool Need_InitialStateChunk(GLResource res);
|
||||
bool Prepare_InitialState(GLResource res);
|
||||
|
||||
void CreateTextureImage(GLuint tex, GLenum internalFormat, GLenum textype, GLint dim, GLint width,
|
||||
GLint height, GLint depth, GLint samples, int mips);
|
||||
void PrepareTextureInitialContents(ResourceId liveid, ResourceId origid, GLResource res);
|
||||
|
||||
void Create_InitialState(ResourceId id, GLResource live, bool hasData);
|
||||
|
||||
@@ -2525,7 +2525,18 @@ byte *GLReplay::GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip,
|
||||
if(m_GetTexturePrevData[mip] == NULL)
|
||||
{
|
||||
m_GetTexturePrevData[mip] = new byte[dataSize * arraysize];
|
||||
gl.glGetCompressedTexImage(target, mip, m_GetTexturePrevData[mip]);
|
||||
if(IsGLES)
|
||||
{
|
||||
const vector<byte> &data = texDetails.compressedData[mip];
|
||||
if(data.size() == dataSize * arraysize)
|
||||
memcpy(m_GetTexturePrevData[mip], data.data(), data.size());
|
||||
else
|
||||
RDCERR("Different expected and stored compressed texture sizes for array texture!");
|
||||
}
|
||||
else
|
||||
{
|
||||
gl.glGetCompressedTexImage(target, mip, m_GetTexturePrevData[mip]);
|
||||
}
|
||||
}
|
||||
|
||||
// now copy the slice from the cache into ret
|
||||
@@ -2537,7 +2548,18 @@ byte *GLReplay::GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip,
|
||||
else
|
||||
{
|
||||
// for non-arrays we can just readback without caching
|
||||
gl.glGetCompressedTexImage(target, mip, ret);
|
||||
if(IsGLES)
|
||||
{
|
||||
const vector<byte> &data = texDetails.compressedData[mip];
|
||||
if(data.size() == dataSize)
|
||||
memcpy(m_GetTexturePrevData[mip], data.data(), data.size());
|
||||
else
|
||||
RDCERR("Different expected and stored compressed texture sizes!");
|
||||
}
|
||||
else
|
||||
{
|
||||
gl.glGetCompressedTexImage(target, mip, m_GetTexturePrevData[mip]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -996,6 +996,22 @@ GLenum FramebufferBinding(GLenum target)
|
||||
return eGL_NONE;
|
||||
}
|
||||
|
||||
bool IsCubeFace(GLenum target)
|
||||
{
|
||||
switch(target)
|
||||
{
|
||||
case eGL_TEXTURE_CUBE_MAP_POSITIVE_X:
|
||||
case eGL_TEXTURE_CUBE_MAP_NEGATIVE_X:
|
||||
case eGL_TEXTURE_CUBE_MAP_POSITIVE_Y:
|
||||
case eGL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
|
||||
case eGL_TEXTURE_CUBE_MAP_POSITIVE_Z:
|
||||
case eGL_TEXTURE_CUBE_MAP_NEGATIVE_Z: return true;
|
||||
default: break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
GLint CubeTargetIndex(GLenum face)
|
||||
{
|
||||
switch(face)
|
||||
|
||||
@@ -58,6 +58,7 @@ bool IsUIntFormat(GLenum internalFormat);
|
||||
bool IsSIntFormat(GLenum internalFormat);
|
||||
bool IsSRGBFormat(GLenum internalFormat);
|
||||
|
||||
bool IsCubeFace(GLenum target);
|
||||
GLint CubeTargetIndex(GLenum face);
|
||||
GLenum TextureBinding(GLenum target);
|
||||
GLenum TextureTarget(GLenum target);
|
||||
|
||||
@@ -1138,7 +1138,15 @@ void APIENTRY _glCopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLev
|
||||
for(int trg = 0; trg < count; trg++)
|
||||
{
|
||||
// read to CPU
|
||||
hookset->glGetCompressedTextureImageEXT(srcName, targets[trg], srcLevel, buf);
|
||||
if(IsGLES)
|
||||
{
|
||||
RDCERR("Can't emulate glCopyImageSubData without glGetCompressedTexImage on GLES");
|
||||
memset(buf, 0, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
hookset->glGetCompressedTextureImageEXT(srcName, targets[trg], srcLevel, buf);
|
||||
}
|
||||
|
||||
// write to GPU
|
||||
if(srcTarget == eGL_TEXTURE_1D || srcTarget == eGL_TEXTURE_1D_ARRAY)
|
||||
|
||||
@@ -2816,6 +2816,104 @@ void WrappedOpenGL::glCompressedMultiTexImage1DEXT(GLenum texunit, GLenum target
|
||||
}
|
||||
}
|
||||
|
||||
void WrappedOpenGL::StoreCompressedTexData(ResourceId texId, GLenum target, GLint level,
|
||||
GLint xoffset, GLint yoffset, GLint zoffset,
|
||||
GLsizei width, GLsizei height, GLsizei depth,
|
||||
GLenum format, GLsizei imageSize, const void *pixels)
|
||||
{
|
||||
byte *unpackedPixels = NULL;
|
||||
byte *srcPixels = NULL;
|
||||
GLint unpackbuf = 0;
|
||||
|
||||
m_Real.glGetIntegerv(eGL_PIXEL_UNPACK_BUFFER_BINDING, &unpackbuf);
|
||||
|
||||
if(unpackbuf == 0 && pixels != NULL)
|
||||
{
|
||||
PixelUnpackState unpack;
|
||||
unpack.Fetch(&m_Real, false);
|
||||
|
||||
if(unpack.FastPathCompressed(width, height, depth))
|
||||
srcPixels = (byte *)pixels;
|
||||
else
|
||||
srcPixels = unpackedPixels =
|
||||
unpack.UnpackCompressed((byte *)pixels, width, height, depth, imageSize);
|
||||
}
|
||||
|
||||
if(unpackbuf != 0)
|
||||
srcPixels = (byte *)m_Real.glMapBufferRange(eGL_PIXEL_UNPACK_BUFFER, (GLintptr)pixels,
|
||||
imageSize, eGL_MAP_READ_BIT);
|
||||
|
||||
if(srcPixels)
|
||||
{
|
||||
string error;
|
||||
|
||||
// Only the trivial case is handled yet.
|
||||
if(xoffset == 0 && yoffset == 0)
|
||||
{
|
||||
if(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
|
||||
target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X || target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
|
||||
target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y || target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z ||
|
||||
target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z || target == GL_TEXTURE_2D_ARRAY ||
|
||||
target == GL_TEXTURE_CUBE_MAP_ARRAY)
|
||||
{
|
||||
if(depth <= 1)
|
||||
{
|
||||
size_t compressedImageSize = GetCompressedByteSize(width, height, 1, format);
|
||||
RDCASSERT(compressedImageSize == (size_t)imageSize);
|
||||
auto &cd = m_Textures[texId].compressedData;
|
||||
auto &cdData = cd[level];
|
||||
GLint zoff = IsCubeFace(target) ? CubeTargetIndex(target) : zoffset;
|
||||
size_t startOffset = imageSize * zoff;
|
||||
if(cdData.size() < startOffset + imageSize)
|
||||
cdData.resize(startOffset + imageSize);
|
||||
memcpy(cdData.data() + startOffset, srcPixels, imageSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
error = StringFormat::Fmt("depth (%d)", depth);
|
||||
}
|
||||
}
|
||||
else if(target == GL_TEXTURE_3D)
|
||||
{
|
||||
if(zoffset == 0)
|
||||
{
|
||||
RDCASSERT(GetCompressedByteSize(width, height, depth, format) == (size_t)imageSize);
|
||||
auto &cd = m_Textures[texId].compressedData;
|
||||
auto &cdData = cd[level];
|
||||
cdData.resize(imageSize);
|
||||
memcpy(cdData.data(), srcPixels, imageSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
error = StringFormat::Fmt("zoffset (%d)", zoffset);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
error = "target";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
error = StringFormat::Fmt("xoffset (%d) and/or yoffset (%d)", xoffset, yoffset);
|
||||
}
|
||||
|
||||
if(unpackbuf != 0)
|
||||
m_Real.glUnmapBuffer(eGL_PIXEL_UNPACK_BUFFER);
|
||||
|
||||
if(!error.empty())
|
||||
RDCWARN("StoreCompressedTexData: Unexpected %s (tex:%llu, target:%s)", error.c_str(), texId,
|
||||
ToStr::Get(target).c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
RDCWARN("StoreCompressedTexData: No source pixels to copy from (tex:%llu, target:%s)", texId,
|
||||
ToStr::Get(target).c_str());
|
||||
}
|
||||
|
||||
SAFE_DELETE_ARRAY(unpackedPixels);
|
||||
}
|
||||
|
||||
bool WrappedOpenGL::Serialise_glCompressedTextureImage2DEXT(GLuint texture, GLenum target,
|
||||
GLint level, GLenum internalformat,
|
||||
GLsizei width, GLsizei height,
|
||||
@@ -2951,6 +3049,10 @@ void WrappedOpenGL::Common_glCompressedTextureImage2DEXT(ResourceId texId, GLenu
|
||||
GLResourceRecord *record = GetResourceManager()->GetResourceRecord(texId);
|
||||
RDCASSERT(record);
|
||||
|
||||
if(IsGLES)
|
||||
StoreCompressedTexData(record->GetResourceID(), target, level, 0, 0, 0, width, height, 0,
|
||||
internalformat, imageSize, pixels);
|
||||
|
||||
// This is kind of an arbitary heuristic, but in the past a game has re-specified a texture with
|
||||
// glTexImage over and over
|
||||
// so we need to attempt to catch the case where glTexImage is called to re-upload data, not
|
||||
@@ -3176,6 +3278,10 @@ void WrappedOpenGL::Common_glCompressedTextureImage3DEXT(ResourceId texId, GLenu
|
||||
GLResourceRecord *record = GetResourceManager()->GetResourceRecord(texId);
|
||||
RDCASSERT(record);
|
||||
|
||||
if(IsGLES)
|
||||
StoreCompressedTexData(record->GetResourceID(), target, level, 0, 0, 0, width, height, depth,
|
||||
internalformat, imageSize, pixels);
|
||||
|
||||
// This is kind of an arbitary heuristic, but in the past a game has re-specified a texture with
|
||||
// glTexImage over and over
|
||||
// so we need to attempt to catch the case where glTexImage is called to re-upload data, not
|
||||
@@ -5166,6 +5272,10 @@ void WrappedOpenGL::Common_glCompressedTextureSubImage2DEXT(GLResourceRecord *re
|
||||
GLint unpackbuf = 0;
|
||||
m_Real.glGetIntegerv(eGL_PIXEL_UNPACK_BUFFER_BINDING, &unpackbuf);
|
||||
|
||||
if(IsGLES)
|
||||
StoreCompressedTexData(record->GetResourceID(), target, level, xoffset, yoffset, 0, width,
|
||||
height, 0, format, imageSize, pixels);
|
||||
|
||||
if(m_State == WRITING_IDLE && unpackbuf != 0)
|
||||
{
|
||||
GetResourceManager()->MarkDirtyResource(record->GetResourceID());
|
||||
@@ -5360,6 +5470,10 @@ void WrappedOpenGL::Common_glCompressedTextureSubImage3DEXT(GLResourceRecord *re
|
||||
GLint unpackbuf = 0;
|
||||
m_Real.glGetIntegerv(eGL_PIXEL_UNPACK_BUFFER_BINDING, &unpackbuf);
|
||||
|
||||
if(IsGLES)
|
||||
StoreCompressedTexData(record->GetResourceID(), target, level, xoffset, yoffset, zoffset, width,
|
||||
height, depth, format, imageSize, pixels);
|
||||
|
||||
if(m_State == WRITING_IDLE && unpackbuf != 0)
|
||||
{
|
||||
GetResourceManager()->MarkDirtyResource(record->GetResourceID());
|
||||
|
||||
Reference in New Issue
Block a user