Skip to content

Commit

Permalink
Fix readback color conversion
Browse files Browse the repository at this point in the history
  • Loading branch information
hrydgard committed Jan 28, 2018
1 parent 19ab367 commit bd2c875
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 16 deletions.
48 changes: 32 additions & 16 deletions ext/native/thin3d/GLQueueRunner.cpp
Expand Up @@ -41,7 +41,7 @@ void GLQueueRunner::CreateDeviceObjects() {
populate(GL_RENDERER);
populate(GL_VERSION);
populate(GL_SHADING_LANGUAGE_VERSION);
populate(GL_EXTENSIONS);
populate(GL_EXTENSIONS); // TODO: Not OK to query this in core profile!
}

void GLQueueRunner::DestroyDeviceObjects() {
Expand All @@ -52,6 +52,10 @@ void GLQueueRunner::DestroyDeviceObjects() {
if (gl_extensions.ARB_vertex_array_object) {
glDeleteVertexArrays(1, &globalVAO_);
}
delete[] readbackBuffer_;
readbackBufferSize_ = 0;
delete[] tempBuffer_;
tempBufferSize_ = 0;
}

void GLQueueRunner::RunInitSteps(const std::vector<GLRInitStep> &steps) {
Expand Down Expand Up @@ -969,6 +973,8 @@ void GLQueueRunner::PerformCopy(const GLRStep &step) {
}

void GLQueueRunner::PerformReadback(const GLRStep &pass) {
using namespace Draw;

GLRFramebuffer *fb = pass.readback.src;

fbo_bind_fb_target(true, fb ? fb->handle : 0);
Expand All @@ -979,39 +985,49 @@ void GLQueueRunner::PerformReadback(const GLRStep &pass) {

CHECK_GL_ERROR_IF_DEBUG();

GLuint internalFormat;
GLuint format;
GLuint type;
int alignment;
if (!Draw::Thin3DFormatToFormatAndType(pass.readback.dstFormat, internalFormat, format, type, alignment)) {
ELOG("Readback failed - format %d not available", (int)pass.readback.dstFormat);
return;
}
// Always read back in 8888 format.
const GLuint internalFormat = GL_RGBA;
const GLuint format = GL_RGBA;
const GLuint type = GL_UNSIGNED_BYTE;
const int srcAlignment = 4;
int dstAlignment = DataFormatSizeInBytes(pass.readback.dstFormat);

int pixelStride = pass.readback.srcRect.w;
// Apply the correct alignment.
glPixelStorei(GL_PACK_ALIGNMENT, alignment);
glPixelStorei(GL_PACK_ALIGNMENT, srcAlignment);
if (!gl_extensions.IsGLES || gl_extensions.GLES3) {
// Some drivers seem to require we specify this. See #8254.
glPixelStorei(GL_PACK_ROW_LENGTH, pixelStride);
}

GLRect2D rect = pass.readback.srcRect;

int size = alignment * rect.w * rect.h;
if (size > readbackBufferSize_) {
bool convert = pass.readback.dstFormat != DataFormat::R8G8B8A8_UNORM;

int tempSize = srcAlignment * rect.w * rect.h;
int readbackSize = dstAlignment * rect.w * rect.h;
if (convert && tempSize > tempBufferSize_) {
delete[] tempBuffer_;
tempBuffer_ = new uint8_t[tempSize];
tempBufferSize_ = tempSize;
}
if (readbackSize > readbackBufferSize_) {
delete[] readbackBuffer_;
readbackBuffer_ = new uint8_t[size];
readbackBufferSize_ = size;
readbackBuffer_ = new uint8_t[readbackSize];
readbackBufferSize_ = readbackSize;
}

glReadPixels(rect.x, rect.y, rect.w, rect.h, format, type, readbackBuffer_);

glReadPixels(rect.x, rect.y, rect.w, rect.h, format, type, convert ? tempBuffer_ : readbackBuffer_);
#ifdef DEBUG_READ_PIXELS
LogReadPixelsError(glGetError());
#endif
if (!gl_extensions.IsGLES || gl_extensions.GLES3) {
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
}
if (convert) {
ConvertFromRGBA8888(readbackBuffer_, tempBuffer_, pixelStride, pixelStride, rect.w, rect.h, pass.readback.dstFormat);
}

CHECK_GL_ERROR_IF_DEBUG();
}

Expand Down
3 changes: 3 additions & 0 deletions ext/native/thin3d/GLQueueRunner.h
Expand Up @@ -375,6 +375,9 @@ class GLQueueRunner {
// We size it generously.
uint8_t *readbackBuffer_ = nullptr;
int readbackBufferSize_ = 0;
// Temp buffer for color conversion
uint8_t *tempBuffer_ = nullptr;
int tempBufferSize_ = 0;

float maxAnisotropyLevel_ = 0.0f;

Expand Down

0 comments on commit bd2c875

Please sign in to comment.