Commit 56d46abe by bsalomon@google.com

Add GL_ANGLE_pack_reverse_row_order. Performs vertical flip in readPixels and

may write direct to client ptr. Bug=none Test= Tested in a modified version of Chromium using canvas2D. Review URL: http://codereview.appspot.com/5373104 git-svn-id: https://angleproject.googlecode.com/svn/trunk@889 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent 205fef33
Name
ANGLE_pack_reverse_row_order
Name Strings
GL_ANGLE_pack_reverse_row_order
Contact
Daniel Koch, TransGaming (daniel 'at' transgaming.com)
Contributors
Brian Salomon
Daniel Koch
Status
XXX - Not complete yet!!!
Version
Last Modified Date: November 22, 2011
Author Revision: 1
Number
XXX not yet
Dependencies
OpenGL 1.5 or OpenGL ES 1.0 are required.
Some of the functionality of this extension is not supported
when implemented against OpenGL ES.
EXT_texture_rg interacts with this extension.
The extension is written against the OpenGL 3.2 Specification
(Core Profile).
Overview
This extension introduces a mechanism to allow reversing the order
in which image rows are written into a pack destination. This
effectively allows an application to flip the results of a ReadPixels
in the y direction operation without having to render upside down.
The coordinate system of OpenGL is vertically reversed in comparison to a
number of other graphics systems such as native windowing APIs. Applications
that perform ReadPixels may have to either render to an intermediate color
buffer before calling ReadPixels or perform a flip in software after
ReadPixels. In some systems the GL can perform the row reversal during
ReadPixels without incurring additional cost.
IP Status
No known IP claims.
Issues
New Procedures and Functions
None
New Types
None
New Tokens
Accepted by the <pname> parameter of PixelStore{if}, GetIntegerv(),
GetBooleanv(), and GetFloatv():
PACK_REVERSE_ROW_ORDER_ANGLE 0x93A4
Additions to Chapter 3 of the OpenGL 3.2 Specification (Rasterization)
In Section 4.3.1 (Reading Pixels) add a row to table 4.7:
+------------------------------+---------+---------------+-------------+
| Parameter Name | Type | Initial Value | Valid Range |
+------------------------------+---------+---------------+-------------+
| PACK_REVERSE_ROW_ORDER_ANGLE | boolean | FALSE | TRUE/FALSE |
+------------------------------+---------+---------------+-------------+
In Section 4.3.1 (Reading Pixels) modify the second paragraph of subsection
"Placement in Pixel Pack Buffer or Client Memory" to read:
When PACK_REVERSE_ROW_ORDER_ANGLE is FALSE groups of elements are placed
in memory just as they are taken from memory when transferring pixel
rectangles to the GL. That is, the ith group of the jth row
(corresponding to the ith pixel in the jth row) is placed in memory just
where the ith group of the jth row would be taken from when transferring
pixels. See Unpacking under section 3.7.2. The only difference is that
the storage mode parameters whose names begin with PACK_ are used
instead of those whose names begin with UNPACK_. If the format is RED,
GREEN, BLUE, or ALPHA, only the corresponding single element is written.
Likewise if the format is RG, RGB, or BGR, only the corresponding two or
three elements are written. Otherwise all the elements of each group are
written. When PACK_REVERSE_ROW_ORDER_ANGLE is TRUE the order of the rows
of elements is reversed before the data is packed. That is, the element
corresponding to pixel (x, y + height - 1) becomes the first element
packed, followed by (x + 1, y + height - 1), etc. Otherwise, pixel data
is packed in the same manner as when PACK_REVERSE_ROW_ORDER_ANGLE is
FALSE.
In Section 6.1.4 add the following sentence to the fifth paragraph
(beginning with "For three-dimensional and two-dimensional array
textures..."):
When PACK_REVERSE_ROW_ORDER_ANGLE is TRUE the order of rows within
each image are reversed without reordering the images themselves.
Dependencies on OpenGL ES
If implemented for OpenGL ES, this extension behaves as specified, except:
-Delete all references to formats RED, GREEN, BLUE, RG, and BGR.
-The language about image order in Section 6.1.4 does not apply as OpenGL ES
does not have GetTexImage.
Dependencies on EXT_texture_rg
If EXT_texture_rg is present reinsert language about formats RED and RG
into the OpenGL ES 2.0 specification.
Errors
None
New State
Initial
Get Value Type Get Command Value Description Sec.
--------- ---- ----------- ------- ----------- ----
PACK_REVERSE_ROW_ORDER_ANGLE B GetIntegerv FALSE Pixel pack row order reversal 4.3.1
New Implementation Dependent State
None
Sample Code
/* Allocate space to hold the pixel data */
const GLvoid* pixels = malloc(width * height * 4);
/* Bind the framebuffer object to be read */
glBindFramebuffer(READ_FRAMEBUFFER, framebuffer);
/* Enable row order reversal */
glPixelStore(PACK_REVERSE_ROW_ORDER_ANGLE, TRUE);
/* The pixel data stored in pixels will be in top-down order, ready for
* use with a windowing system API that expects this order.
*/
glReadPixels(x, y, width, height, RGBA, UNSIGNED_BYTE, pixels);
Revision History
Revision 1, 2011/11/22 (Brian Salomon)
- First version
......@@ -207,6 +207,11 @@ typedef void* GLeglImageOES;
#define GL_MAX_SAMPLES_ANGLE 0x8D57
#endif
/* GL_ANGLE_pack_reverse_row_order */
#ifndef GL_ANGLE_pack_reverse_row_order
#define GL_PACK_REVERSE_ROW_ORDER_ANGLE 0x93A4
#endif
/* GL_ANGLE_texture_compression_dxt3 */
#ifndef GL_ANGLE_texture_compression_dxt3
#define GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE 0x83F2
......@@ -847,6 +852,11 @@ GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleANGLE (GLenum target
typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEANGLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
#endif
/* GL_ANGLE_pack_reverse_row_order */
#ifndef GL_ANGLE_pack_reverse_row_order
#define GL_ANGLE_pack_reverse_row_order 1
#endif
/* GL_ANGLE_texture_compression_dxt3 */
#ifndef GL_ANGLE_texture_compression_dxt3
#define GL_ANGLE_texture_compression_dxt3 1
......
#define MAJOR_VERSION 0
#define MINOR_VERSION 0
#define BUILD_VERSION 0
#define BUILD_REVISION 888
#define BUILD_REVISION 889
#define STRINGIFY(x) #x
#define MACRO_STRINGIFY(x) STRINGIFY(x)
......
......@@ -147,6 +147,7 @@ Context::Context(const egl::Config *config, const gl::Context *shareContext, boo
mState.packAlignment = 4;
mState.unpackAlignment = 4;
mState.packReverseRowOrder = false;
mVertexDataManager = NULL;
mIndexDataManager = NULL;
......@@ -855,6 +856,16 @@ GLint Context::getUnpackAlignment() const
return mState.unpackAlignment;
}
void Context::setPackReverseRowOrder(bool reverseRowOrder)
{
mState.packReverseRowOrder = reverseRowOrder;
}
bool Context::getPackReverseRowOrder() const
{
return mState.packReverseRowOrder;
}
GLuint Context::createBuffer()
{
return mResourceManager->createBuffer();
......@@ -1273,6 +1284,7 @@ bool Context::getIntegerv(GLenum pname, GLint *params)
case GL_RENDERBUFFER_BINDING: *params = mState.renderbuffer.id(); break;
case GL_CURRENT_PROGRAM: *params = mState.currentProgram; break;
case GL_PACK_ALIGNMENT: *params = mState.packAlignment; break;
case GL_PACK_REVERSE_ROW_ORDER_ANGLE: *params = mState.packReverseRowOrder; break;
case GL_UNPACK_ALIGNMENT: *params = mState.unpackAlignment; break;
case GL_GENERATE_MIPMAP_HINT: *params = mState.generateMipmapHint; break;
case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: *params = mState.fragmentShaderDerivativeHint; break;
......@@ -1512,6 +1524,7 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu
case GL_RENDERBUFFER_BINDING:
case GL_CURRENT_PROGRAM:
case GL_PACK_ALIGNMENT:
case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
case GL_UNPACK_ALIGNMENT:
case GL_GENERATE_MIPMAP_HINT:
case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
......@@ -2244,19 +2257,38 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height,
D3DSURFACE_DESC desc;
renderTarget->GetDesc(&desc);
IDirect3DSurface9 *systemSurface;
HRESULT result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &systemSurface, NULL);
if (FAILED(result))
if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target
return error(GL_OUT_OF_MEMORY);
}
if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
HRESULT result;
IDirect3DSurface9 *systemSurface = NULL;
bool directToPixels = getPackReverseRowOrder() && getPackAlignment() <= 4 && mDisplay->isD3d9ExDevice() &&
x == 0 && y == 0 && width == desc.Width && height == desc.Height &&
desc.Format == D3DFMT_A8R8G8B8 && format == GL_BGRA_EXT && type == GL_UNSIGNED_BYTE;
if (directToPixels)
{
UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target
return error(GL_OUT_OF_MEMORY);
// Use the pixels ptr as a shared handle to write directly into client's memory
result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format,
D3DPOOL_SYSTEMMEM, &systemSurface, &pixels);
if (FAILED(result))
{
// Try again without the shared handle
directToPixels = false;
}
}
if (!directToPixels)
{
result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format,
D3DPOOL_SYSTEMMEM, &systemSurface, NULL);
if (FAILED(result))
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
return error(GL_OUT_OF_MEMORY);
}
}
result = mDevice->GetRenderTargetData(renderTarget, systemSurface);
......@@ -2277,6 +2309,12 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height,
}
if (directToPixels)
{
systemSurface->Release();
return;
}
D3DLOCKED_RECT lock;
RECT rect = transformPixelRect(x, y, width, height, desc.Height);
rect.left = clamp(rect.left, 0L, static_cast<LONG>(desc.Width));
......@@ -2294,10 +2332,21 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height,
return; // No sensible error to generate
}
unsigned char *source = ((unsigned char*)lock.pBits) + lock.Pitch * (rect.bottom - rect.top - 1);
unsigned char *dest = (unsigned char*)pixels;
unsigned short *dest16 = (unsigned short*)pixels;
int inputPitch = -lock.Pitch;
unsigned char *source;
int inputPitch;
if (getPackReverseRowOrder())
{
source = (unsigned char*)lock.pBits;
inputPitch = lock.Pitch;
}
else
{
source = ((unsigned char*)lock.pBits) + lock.Pitch * (rect.bottom - rect.top - 1);
inputPitch = -lock.Pitch;
}
for (int j = 0; j < rect.bottom - rect.top; j++)
{
......@@ -3448,6 +3497,8 @@ void Context::initExtensionString()
mExtensionString += "GL_ANGLE_framebuffer_multisample ";
}
mExtensionString += "GL_ANGLE_pack_reverse_row_order ";
if (supportsDXT3Textures())
{
mExtensionString += "GL_ANGLE_texture_compression_dxt3 ";
......
......@@ -219,6 +219,7 @@ struct State
GLint unpackAlignment;
GLint packAlignment;
bool packReverseRowOrder;
};
// Helper class to construct and cache vertex declarations
......@@ -360,6 +361,9 @@ class Context
void setPackAlignment(GLint alignment);
GLint getPackAlignment() const;
void setPackReverseRowOrder(bool reverseRowOrder);
bool getPackReverseRowOrder() const;
// These create and destroy methods are merely pass-throughs to
// ResourceManager, which owns these object types
GLuint createBuffer();
......
......@@ -4154,6 +4154,10 @@ void __stdcall glPixelStorei(GLenum pname, GLint param)
context->setPackAlignment(param);
break;
case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
context->setPackReverseRowOrder(param != 0);
break;
default:
return error(GL_INVALID_ENUM);
}
......
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