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
parent ce1189b0
......@@ -1576,8 +1576,19 @@ bool Context::getIntegerv(GLenum pname, GLint *params)
}
}
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 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height,
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 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height,
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 @@ float Context::getTextureMaxAnisotropy() const
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:
......
......@@ -78,10 +78,7 @@ enum
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 @@ class Context
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,
......
......@@ -247,15 +247,6 @@ bool validReadFormatType(GLenum format, GLenum type)
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 @@ void __stdcall glReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height,
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(&currentFormat, &currentType))
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 @@ void __stdcall glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
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(&currentFormat, &currentType))
return;
if (!(currentFormat == format && currentType == type) && !validReadFormatType(format, type))
{
return error(GL_INVALID_OPERATION);
}
context->readPixels(x, y, width, height, format, type, NULL, pixels);
}
}
......
......@@ -988,6 +988,46 @@ GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type)
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)
......
......@@ -88,6 +88,7 @@ bool IsCompressedD3DFormat(D3DFORMAT format);
GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type);
bool ConvertReadBufferFormat(D3DFORMAT d3dformat, GLenum *format, GLenum *type);
GLenum ConvertBackBufferFormat(D3DFORMAT format);
GLenum ConvertDepthStencilFormat(D3DFORMAT format);
......
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