Adds support for per-framebuffer IMPLEMENTATION_COLOR_READ_FORMAT and TYPE
TRAC #21607
Signed-off-by: Nicolas Capens
Signed-off-by: Daniel Koch
Author: Shannon Woods
git-svn-id: https://angleproject.googlecode.com/svn/trunk@1283 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/libGLESv2/Context.cpp b/src/libGLESv2/Context.cpp
index 76f0693..1363ed6 100644
--- a/src/libGLESv2/Context.cpp
+++ b/src/libGLESv2/Context.cpp
@@ -1576,8 +1576,19 @@
}
}
break;
- case GL_IMPLEMENTATION_COLOR_READ_TYPE: *params = gl::IMPLEMENTATION_COLOR_READ_TYPE; break;
- case GL_IMPLEMENTATION_COLOR_READ_FORMAT: *params = gl::IMPLEMENTATION_COLOR_READ_FORMAT; break;
+ case GL_IMPLEMENTATION_COLOR_READ_TYPE:
+ case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
+ {
+ GLenum format, type;
+ if (getCurrentReadFormatType(&format, &type))
+ {
+ if (pname == GL_IMPLEMENTATION_COLOR_READ_FORMAT)
+ *params = format;
+ else
+ *params = type;
+ }
+ }
+ break;
case GL_MAX_VIEWPORT_DIMS:
{
int maxDimension = std::max(getMaximumRenderbufferDimension(), getMaximumTextureDimension());
@@ -2611,18 +2622,51 @@
inputPitch = lock.Pitch;
}
+ unsigned int fastPixelSize = 0;
+
+ if (desc.Format == D3DFMT_A8R8G8B8 &&
+ format == GL_BGRA_EXT &&
+ type == GL_UNSIGNED_BYTE)
+ {
+ fastPixelSize = 4;
+ }
+ else if ((desc.Format == D3DFMT_A4R4G4B4 &&
+ format == GL_BGRA_EXT &&
+ type == GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT) ||
+ (desc.Format == D3DFMT_A1R5G5B5 &&
+ format == GL_BGRA_EXT &&
+ type == GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT))
+ {
+ fastPixelSize = 2;
+ }
+ else if (desc.Format == D3DFMT_A16B16G16R16F &&
+ format == GL_RGBA &&
+ type == GL_HALF_FLOAT_OES)
+ {
+ fastPixelSize = 8;
+ }
+ else if (desc.Format == D3DFMT_A32B32G32R32F &&
+ format == GL_RGBA &&
+ type == GL_FLOAT)
+ {
+ fastPixelSize = 16;
+ }
+
for (int j = 0; j < rect.bottom - rect.top; j++)
{
- if (desc.Format == D3DFMT_A8R8G8B8 &&
- format == GL_BGRA_EXT &&
- type == GL_UNSIGNED_BYTE)
+ if (fastPixelSize != 0)
{
- // Fast path for EXT_read_format_bgra, given
- // an RGBA source buffer. Note that buffers with no
- // alpha go through the slow path below.
+ // Fast path for formats which require no translation:
+ // D3DFMT_A8R8G8B8 to BGRA/UNSIGNED_BYTE
+ // D3DFMT_A4R4G4B4 to BGRA/UNSIGNED_SHORT_4_4_4_4_REV_EXT
+ // D3DFMT_A1R5G5B5 to BGRA/UNSIGNED_SHORT_1_5_5_5_REV_EXT
+ // D3DFMT_A16B16G16R16F to RGBA/HALF_FLOAT_OES
+ // D3DFMT_A32B32G32R32F to RGBA/FLOAT
+ //
+ // Note that buffers with no alpha go through the slow path below.
memcpy(dest + j * outputPitch,
source + j * inputPitch,
- (rect.right - rect.left) * 4);
+ (rect.right - rect.left) * fastPixelSize);
continue;
}
@@ -2763,15 +2807,20 @@
default: UNREACHABLE();
}
break;
- case GL_RGB: // IMPLEMENTATION_COLOR_READ_FORMAT
+ case GL_RGB:
switch (type)
{
- case GL_UNSIGNED_SHORT_5_6_5: // IMPLEMENTATION_COLOR_READ_TYPE
+ case GL_UNSIGNED_SHORT_5_6_5:
dest16[i + j * outputPitch / sizeof(unsigned short)] =
((unsigned short)(31 * b + 0.5f) << 0) |
((unsigned short)(63 * g + 0.5f) << 5) |
((unsigned short)(31 * r + 0.5f) << 11);
break;
+ case GL_UNSIGNED_BYTE:
+ dest[3 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f);
+ dest[3 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
+ dest[3 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f);
+ break;
default: UNREACHABLE();
}
break;
@@ -3581,6 +3630,29 @@
return mMaxTextureAnisotropy;
}
+bool Context::getCurrentReadFormatType(GLenum *format, GLenum *type)
+{
+ Framebuffer *framebuffer = getReadFramebuffer();
+ if (!framebuffer || framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
+ {
+ return error(GL_INVALID_OPERATION, false);
+ }
+
+ Renderbuffer *renderbuffer = framebuffer->getColorbuffer();
+ if (!renderbuffer)
+ {
+ return error(GL_INVALID_OPERATION, false);
+ }
+
+ if(!dx2es::ConvertReadBufferFormat(renderbuffer->getD3DFormat(), format, type))
+ {
+ ASSERT(false);
+ return false;
+ }
+
+ return true;
+}
+
void Context::detachBuffer(GLuint buffer)
{
// [OpenGL ES 2.0.24] section 2.9 page 22:
diff --git a/src/libGLESv2/Context.h b/src/libGLESv2/Context.h
index c3b562c..d312918 100644
--- a/src/libGLESv2/Context.h
+++ b/src/libGLESv2/Context.h
@@ -78,10 +78,7 @@
MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF = MAX_TEXTURE_IMAGE_UNITS + MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF,
MAX_FRAGMENT_UNIFORM_VECTORS_SM2 = 32 - 3, // Reserve space for dx_Coord, dx_Depth, and dx_DepthRange. dx_PointOrLines and dx_FrontCCW use separate bool registers.
MAX_FRAGMENT_UNIFORM_VECTORS_SM3 = 224 - 3,
- MAX_DRAW_BUFFERS = 1,
-
- IMPLEMENTATION_COLOR_READ_FORMAT = GL_RGB,
- IMPLEMENTATION_COLOR_READ_TYPE = GL_UNSIGNED_SHORT_5_6_5
+ MAX_DRAW_BUFFERS = 1
};
enum QueryType
@@ -510,6 +507,8 @@
bool supportsInstancing() const;
bool supportsTextureFilterAnisotropy() const;
+ bool getCurrentReadFormatType(GLenum *format, GLenum *type);
+
float getTextureMaxAnisotropy() const;
void blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
diff --git a/src/libGLESv2/libGLESv2.cpp b/src/libGLESv2/libGLESv2.cpp
index 40a7067..62bf20f 100644
--- a/src/libGLESv2/libGLESv2.cpp
+++ b/src/libGLESv2/libGLESv2.cpp
@@ -247,15 +247,6 @@
return false;
}
break;
- case gl::IMPLEMENTATION_COLOR_READ_FORMAT:
- switch (type)
- {
- case gl::IMPLEMENTATION_COLOR_READ_TYPE:
- break;
- default:
- return false;
- }
- break;
default:
return false;
}
@@ -4720,15 +4711,23 @@
return error(GL_INVALID_VALUE);
}
- if (!validReadFormatType(format, type))
- {
- return error(GL_INVALID_OPERATION);
- }
-
gl::Context *context = gl::getNonLostContext();
if (context)
{
+ GLenum currentFormat, currentType;
+
+ // Failure in getCurrentReadFormatType indicates that no color attachment is currently bound,
+ // and attempting to read back if that's the case is an error. The error will be registered
+ // by getCurrentReadFormat.
+ if (!context->getCurrentReadFormatType(¤tFormat, ¤tType))
+ return;
+
+ if (!(currentFormat == format && currentType == type) && !validReadFormatType(format, type))
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
context->readPixels(x, y, width, height, format, type, &bufSize, data);
}
}
@@ -4752,15 +4751,23 @@
return error(GL_INVALID_VALUE);
}
- if (!validReadFormatType(format, type))
- {
- return error(GL_INVALID_OPERATION);
- }
-
gl::Context *context = gl::getNonLostContext();
if (context)
{
+ GLenum currentFormat, currentType;
+
+ // Failure in getCurrentReadFormatType indicates that no color attachment is currently bound,
+ // and attempting to read back if that's the case is an error. The error will be registered
+ // by getCurrentReadFormat.
+ if (!context->getCurrentReadFormatType(¤tFormat, ¤tType))
+ return;
+
+ if (!(currentFormat == format && currentType == type) && !validReadFormatType(format, type))
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
context->readPixels(x, y, width, height, format, type, NULL, pixels);
}
}
diff --git a/src/libGLESv2/utilities.cpp b/src/libGLESv2/utilities.cpp
index e6f8993..47d2379 100644
--- a/src/libGLESv2/utilities.cpp
+++ b/src/libGLESv2/utilities.cpp
@@ -988,6 +988,46 @@
return type;
}
+bool ConvertReadBufferFormat(D3DFORMAT d3dformat, GLenum *format, GLenum *type)
+{
+ switch (d3dformat)
+ {
+ case D3DFMT_A8R8G8B8:
+ *type = GL_UNSIGNED_BYTE;
+ *format = GL_BGRA_EXT;
+ break;
+ case D3DFMT_X8R8G8B8:
+ *type = GL_UNSIGNED_BYTE;
+ *format = GL_RGB;
+ break;
+ case D3DFMT_R5G6B5:
+ *type = GL_UNSIGNED_SHORT_5_6_5;
+ *format = GL_RGB;
+ break;
+ case D3DFMT_A16B16G16R16F:
+ *type = GL_HALF_FLOAT_OES;
+ *format = GL_RGBA;
+ break;
+ case D3DFMT_A32B32G32R32F:
+ *type = GL_FLOAT;
+ *format = GL_RGBA;
+ break;
+ case D3DFMT_A4R4G4B4:
+ *type = GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT;
+ *format = GL_BGRA_EXT;
+ break;
+ case D3DFMT_A1R5G5B5:
+ *type = GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT;
+ *format = GL_BGRA_EXT;
+ break;
+ default:
+ *type = GL_NONE;
+ *format = GL_NONE;
+ return false;
+ }
+ return true;
+}
+
GLenum ConvertBackBufferFormat(D3DFORMAT format)
{
switch (format)
diff --git a/src/libGLESv2/utilities.h b/src/libGLESv2/utilities.h
index 3357eb0..3e270c0 100644
--- a/src/libGLESv2/utilities.h
+++ b/src/libGLESv2/utilities.h
@@ -88,6 +88,7 @@
GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type);
+bool ConvertReadBufferFormat(D3DFORMAT d3dformat, GLenum *format, GLenum *type);
GLenum ConvertBackBufferFormat(D3DFORMAT format);
GLenum ConvertDepthStencilFormat(D3DFORMAT format);