Commit 235e56fb by Geoff Lang Committed by Commit Bot

BlitGL: Support CL readback from non-renderable textures.

External textures are often not renderable for the CPU readback path. Instead, copy them into a renderable texture and then read them back. BUG=906724 Change-Id: I61bd0a9d51c4b24e1d285b5f1883e01ccb53ebea Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1680053 Commit-Queue: Geoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org>
parent c5da7997
......@@ -502,7 +502,7 @@ angle::Result BlitGL::copySubTexture(const gl::Context *context,
TextureGL *source,
size_t sourceLevel,
GLenum sourceComponentType,
TextureGL *dest,
GLuint destID,
gl::TextureTarget destTarget,
size_t destLevel,
GLenum destComponentType,
......@@ -524,7 +524,7 @@ angle::Result BlitGL::copySubTexture(const gl::Context *context,
// cube maps may not be renderable until all faces have been filled.
mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mScratchFBO);
mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, ToGLenum(destTarget),
dest->getTextureID(), static_cast<GLint>(destLevel));
destID, static_cast<GLint>(destLevel));
GLenum status = mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE)
{
......@@ -608,14 +608,17 @@ angle::Result BlitGL::copySubTexture(const gl::Context *context,
angle::Result BlitGL::copySubTextureCPUReadback(const gl::Context *context,
TextureGL *source,
size_t sourceLevel,
GLenum sourceComponentType,
GLenum sourceSizedInternalFormat,
TextureGL *dest,
gl::TextureTarget destTarget,
size_t destLevel,
GLenum destFormat,
GLenum destType,
const gl::Extents &sourceSize,
const gl::Rectangle &sourceArea,
const gl::Offset &destOffset,
bool needsLumaWorkaround,
GLenum lumaFormat,
bool unpackFlipY,
bool unpackPremultiplyAlpha,
bool unpackUnmultiplyAlpha)
......@@ -624,20 +627,65 @@ angle::Result BlitGL::copySubTextureCPUReadback(const gl::Context *context,
ContextGL *contextGL = GetImplAs<ContextGL>(context);
ASSERT(source->getType() == gl::TextureType::_2D);
ASSERT(source->getType() == gl::TextureType::_2D ||
source->getType() == gl::TextureType::External);
const auto &destInternalFormatInfo = gl::GetInternalFormatInfo(destFormat, destType);
const gl::InternalFormat &sourceInternalFormatInfo =
gl::GetSizedInternalFormatInfo(sourceSizedInternalFormat);
gl::Rectangle readPixelsArea = sourceArea;
mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mScratchFBO);
mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
source->getTextureID(), static_cast<GLint>(sourceLevel));
mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
ToGLenum(source->getType()), source->getTextureID(),
static_cast<GLint>(sourceLevel));
GLenum status = mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE)
{
// The source texture cannot be read with glReadPixels. Copy it into another RGBA texture
// and read that back instead.
nativegl::TexImageFormat texImageFormat = nativegl::GetTexImageFormat(
mFunctions, mFeatures, sourceInternalFormatInfo.internalFormat,
sourceInternalFormatInfo.format, sourceInternalFormatInfo.type);
gl::TextureType scratchTextureType = gl::TextureType::_2D;
mStateManager->bindTexture(scratchTextureType, mScratchTextures[0]);
mFunctions->texImage2D(ToGLenum(scratchTextureType), 0, texImageFormat.internalFormat,
sourceArea.width, sourceArea.height, 0, texImageFormat.format,
texImageFormat.type, nullptr);
bool copySucceeded = false;
ANGLE_TRY(copySubTexture(
context, source, sourceLevel, sourceInternalFormatInfo.componentType,
mScratchTextures[0], NonCubeTextureTypeToTarget(scratchTextureType), 0,
sourceInternalFormatInfo.componentType, sourceSize, sourceArea, gl::Offset(0, 0, 0),
needsLumaWorkaround, lumaFormat, false, false, false, &copySucceeded));
if (!copySucceeded)
{
// No fallback options if we can't render to the scratch texture.
return angle::Result::Stop;
}
// Bind the scratch texture as the readback texture
mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mScratchFBO);
mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
ToGLenum(scratchTextureType), mScratchTextures[0], 0);
// The scratch texture sized to sourceArea so adjust the readpixels area
readPixelsArea.x = 0;
readPixelsArea.y = 0;
// Recheck the status
status = mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER);
}
ASSERT(status == GL_FRAMEBUFFER_COMPLETE);
// Create a buffer for holding the source and destination memory
const size_t sourcePixelSize = 4;
size_t sourceBufferSize = sourceArea.width * sourceArea.height * sourcePixelSize;
size_t sourceBufferSize = readPixelsArea.width * readPixelsArea.height * sourcePixelSize;
size_t destBufferSize =
sourceArea.width * sourceArea.height * destInternalFormatInfo.pixelBytes;
readPixelsArea.width * readPixelsArea.height * destInternalFormatInfo.pixelBytes;
angle::MemoryBuffer *buffer = nullptr;
ANGLE_CHECK_GL_ALLOC(contextGL,
context->getScratchBuffer(sourceBufferSize + destBufferSize, &buffer));
......@@ -647,14 +695,14 @@ angle::Result BlitGL::copySubTextureCPUReadback(const gl::Context *context,
GLenum readPixelsFormat = GL_NONE;
PixelReadFunction readFunction = nullptr;
if (sourceComponentType == GL_UNSIGNED_INT)
if (sourceInternalFormatInfo.componentType == GL_UNSIGNED_INT)
{
readPixelsFormat = GL_RGBA_INTEGER;
readFunction = angle::ReadColor<angle::R8G8B8A8, GLuint>;
}
else
{
ASSERT(sourceComponentType != GL_INT);
ASSERT(sourceInternalFormatInfo.componentType != GL_INT);
readPixelsFormat = GL_RGBA;
readFunction = angle::ReadColor<angle::R8G8B8A8, GLfloat>;
}
......@@ -663,18 +711,18 @@ angle::Result BlitGL::copySubTextureCPUReadback(const gl::Context *context,
unpack.alignment = 1;
mStateManager->setPixelUnpackState(unpack);
mStateManager->setPixelUnpackBuffer(nullptr);
mFunctions->readPixels(sourceArea.x, sourceArea.y, sourceArea.width, sourceArea.height,
readPixelsFormat, GL_UNSIGNED_BYTE, sourceMemory);
mFunctions->readPixels(readPixelsArea.x, readPixelsArea.y, readPixelsArea.width,
readPixelsArea.height, readPixelsFormat, GL_UNSIGNED_BYTE, sourceMemory);
angle::FormatID destFormatID =
angle::Format::InternalFormatToID(destInternalFormatInfo.sizedInternalFormat);
const auto &destFormatInfo = angle::Format::Get(destFormatID);
CopyImageCHROMIUM(
sourceMemory, sourceArea.width * sourcePixelSize, sourcePixelSize, 0, readFunction,
destMemory, sourceArea.width * destInternalFormatInfo.pixelBytes,
sourceMemory, readPixelsArea.width * sourcePixelSize, sourcePixelSize, 0, readFunction,
destMemory, readPixelsArea.width * destInternalFormatInfo.pixelBytes,
destInternalFormatInfo.pixelBytes, 0, destFormatInfo.pixelWriteFunction,
destInternalFormatInfo.format, destInternalFormatInfo.componentType, sourceArea.width,
sourceArea.height, 1, unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha);
destInternalFormatInfo.format, destInternalFormatInfo.componentType, readPixelsArea.width,
readPixelsArea.height, 1, unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha);
gl::PixelPackState pack;
pack.alignment = 1;
......@@ -686,7 +734,7 @@ angle::Result BlitGL::copySubTextureCPUReadback(const gl::Context *context,
mStateManager->bindTexture(dest->getType(), dest->getTextureID());
mFunctions->texSubImage2D(ToGLenum(destTarget), static_cast<GLint>(destLevel), destOffset.x,
destOffset.y, sourceArea.width, sourceArea.height,
destOffset.y, readPixelsArea.width, readPixelsArea.height,
texSubImageFormat.format, texSubImageFormat.type, destMemory);
return angle::Result::Continue;
......
......@@ -75,7 +75,7 @@ class BlitGL : angle::NonCopyable
TextureGL *source,
size_t sourceLevel,
GLenum sourceComponentType,
TextureGL *dest,
GLuint destID,
gl::TextureTarget destTarget,
size_t destLevel,
GLenum destComponentType,
......@@ -92,14 +92,17 @@ class BlitGL : angle::NonCopyable
angle::Result copySubTextureCPUReadback(const gl::Context *context,
TextureGL *source,
size_t sourceLevel,
GLenum sourceComponentType,
GLenum sourceSizedInternalFormat,
TextureGL *dest,
gl::TextureTarget destTarget,
size_t destLevel,
GLenum destFormat,
GLenum destType,
const gl::Extents &sourceSize,
const gl::Rectangle &sourceArea,
const gl::Offset &destOffset,
bool needsLumaWorkaround,
GLenum lumaFormat,
bool unpackFlipY,
bool unpackPremultiplyAlpha,
bool unpackUnmultiplyAlpha);
......
......@@ -791,12 +791,13 @@ angle::Result TextureGL::copySubTextureHelper(const gl::Context *context,
sourceGL->getLevelInfo(NonCubeTextureTypeToTarget(source->getType()), sourceLevel);
bool needsLumaWorkaround = sourceLevelInfo.lumaWorkaround.enabled;
GLenum sourceFormat = sourceImageDesc.format.info->format;
const gl::InternalFormat &sourceFormatInfo = *sourceImageDesc.format.info;
GLenum sourceFormat = sourceFormatInfo.format;
bool sourceFormatContainSupersetOfDestFormat =
(sourceFormat == destFormat.format && sourceFormat != GL_BGRA_EXT) ||
(sourceFormat == GL_RGBA && destFormat.format == GL_RGB);
GLenum sourceComponentType = sourceImageDesc.format.info->componentType;
GLenum sourceComponentType = sourceFormatInfo.componentType;
GLenum destComponentType = destFormat.componentType;
bool destSRGB = destFormat.colorEncoding == GL_SRGB;
if (!unpackFlipY && unpackPremultiplyAlpha == unpackUnmultiplyAlpha && !needsLumaWorkaround &&
......@@ -819,7 +820,7 @@ angle::Result TextureGL::copySubTextureHelper(const gl::Context *context,
{
bool copySucceeded = false;
ANGLE_TRY(blitter->copySubTexture(
context, sourceGL, sourceLevel, sourceComponentType, this, target, level,
context, sourceGL, sourceLevel, sourceComponentType, mTextureID, target, level,
destComponentType, sourceImageDesc.size, sourceArea, destOffset, needsLumaWorkaround,
sourceLevelInfo.sourceFormat, unpackFlipY, unpackPremultiplyAlpha,
unpackUnmultiplyAlpha, &copySucceeded));
......@@ -830,10 +831,11 @@ angle::Result TextureGL::copySubTextureHelper(const gl::Context *context,
}
// Fall back to CPU-readback
return blitter->copySubTextureCPUReadback(context, sourceGL, sourceLevel, sourceComponentType,
this, target, level, destFormat.format,
destFormat.type, sourceArea, destOffset, unpackFlipY,
unpackPremultiplyAlpha, unpackUnmultiplyAlpha);
return blitter->copySubTextureCPUReadback(
context, sourceGL, sourceLevel, sourceFormatInfo.sizedInternalFormat, this, target, level,
destFormat.format, destFormat.type, sourceImageDesc.size, sourceArea, destOffset,
needsLumaWorkaround, sourceLevelInfo.sourceFormat, unpackFlipY, unpackPremultiplyAlpha,
unpackUnmultiplyAlpha);
}
angle::Result TextureGL::setStorage(const gl::Context *context,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment