mesa: GL_MESA_framebuffer_flip_y extension [v4]
authorFritz Koenig <frkoenig@google.com>
Mon, 23 Jul 2018 17:10:54 +0000 (10:10 -0700)
committerChad Versace <chadversary@chromium.org>
Fri, 27 Jul 2018 19:32:25 +0000 (12:32 -0700)
Adds an extension to glFramebufferParameteri
that will specify if the framebuffer is vertically
flipped. Historically system framebuffers are
vertically flipped and user framebuffers are not.
Checking to see the state was done by looking at
the name field.  This adds an explicit field.

v2:
  * updated spec language [for chadv]
  * correctly specifying ES 3.1 [for chadv]
  * refactor access to rb->Name [for jason]
  * handle GetFramebufferParameteriv [for chadv]
v3:
  * correct _mesa_GetMultisamplefv [for kusmabite]
v4:
  * update spec language [for chadv]
  * s/GLboolean/bool/g [for chadv]
  * s/InvertedY/FlipY/g [for chadv]
  * s/inverted_y/flip_y/g [for chadv]
  * assert changes [for chadv]

Reviewed-by: Chad Versace <chadversary@chromium.org>
30 files changed:
docs/specs/MESA_framebuffer_flip_y.txt [new file with mode: 0644]
docs/specs/enums.txt
include/GLES2/gl2ext.h
src/mapi/glapi/registry/gl.xml
src/mesa/drivers/dri/i915/intel_fbo.c
src/mesa/drivers/dri/i965/intel_fbo.c
src/mesa/drivers/dri/nouveau/nouveau_fbo.c
src/mesa/drivers/dri/radeon/radeon_fbo.c
src/mesa/drivers/dri/radeon/radeon_span.c
src/mesa/drivers/dri/swrast/swrast.c
src/mesa/drivers/osmesa/osmesa.c
src/mesa/drivers/x11/xm_buffer.c
src/mesa/drivers/x11/xmesaP.h
src/mesa/main/accum.c
src/mesa/main/dd.h
src/mesa/main/extensions_table.h
src/mesa/main/fbobject.c
src/mesa/main/framebuffer.c
src/mesa/main/glheader.h
src/mesa/main/mtypes.h
src/mesa/main/readpix.c
src/mesa/state_tracker/st_cb_fbo.c
src/mesa/swrast/s_blit.c
src/mesa/swrast/s_clear.c
src/mesa/swrast/s_copypix.c
src/mesa/swrast/s_depth.c
src/mesa/swrast/s_drawpix.c
src/mesa/swrast/s_renderbuffer.c
src/mesa/swrast/s_renderbuffer.h
src/mesa/swrast/s_stencil.c

diff --git a/docs/specs/MESA_framebuffer_flip_y.txt b/docs/specs/MESA_framebuffer_flip_y.txt
new file mode 100644 (file)
index 0000000..697ab4e
--- /dev/null
@@ -0,0 +1,81 @@
+Name
+
+    MESA_framebuffer_flip_y
+
+Name Strings
+
+    GL_MESA_framebuffer_flip_y
+
+Contact
+
+    Fritz Koenig <frkoenig@google.com>
+
+Contributors
+
+    Fritz Koenig, Google
+    Kristian Høgsberg, Google
+    Chad Versace, Google
+
+Status
+
+    Proposal
+
+Version
+
+    Version 1, June 7, 2018
+
+Number
+
+    302
+
+Dependencies
+
+    OpenGL ES 3.1 is required, for FramebufferParameteri.
+
+Overview
+
+    This extension defines a new framebuffer parameter,
+    GL_FRAMEBUFFER_FLIP_Y_MESA, that changes the behavior of the reads and
+    writes to the framebuffer attachment points. When GL_FRAMEBUFFER_FLIP_Y_MESA
+    is GL_TRUE, render commands and pixel transfer operations access the
+    backing store of each attachment point with an y-inverted coordinate
+    system. This y-inversion is relative to the coordinate system set when
+    GL_FRAMEBUFFER_FLIP_Y_MESA is GL_FALSE.
+
+    Access through TexSubImage2D and similar calls will notice the effect of
+    the flip when they are not attached to framebuffer objects because
+    GL_FRAMEBUFFER_FLIP_Y_MESA is associated with the framebuffer object and
+    not the attachment points.
+
+IP Status
+
+    None
+
+Issues
+
+    None
+
+New Procedures and Functions
+
+    None
+
+New Types
+
+    None
+
+New Tokens
+
+    Accepted by the <pname> argument of FramebufferParameteri and
+    GetFramebufferParameteriv:
+
+        GL_FRAMEBUFFER_FLIP_Y_MESA                      0x8BBB
+
+Errors
+
+    An INVALID_OPERATION error is generated by GetFramebufferParameteriv if the
+    default framebuffer is bound to <target> and <pname> is FRAMEBUFFER_FLIP_Y_MESA.
+
+Revision History
+
+    Version 1, June, 2018
+        Initial draft (Fritz Koenig)
index bf3ca9c1762d408ddc1385718b488b6dd5c2f886..e1b95ec8746d7aa43e69f2607728fcd30d47aff2 100644 (file)
@@ -71,6 +71,9 @@ GL_MESA_tile_raster_order
        GL_TILE_RASTER_ORDER_INCREASING_X_MESA  0x8BB9
        GL_TILE_RASTER_ORDER_INCREASING_Y_MESA  0x8BBA
 
+GL_MESA_framebuffer_flip_y
+       GL_FRAMEBUFFER_FLIP_Y_MESA           0x8BBB
+
 EGL_MESA_drm_image
         EGL_DRM_BUFFER_FORMAT_MESA             0x31D0
         EGL_DRM_BUFFER_USE_MESA                        0x31D1
index a7d19a1fc83c34c02290470131daee898776af8a..0a93bfb86529dba96cfd0298262922ef3d2ca4e8 100644 (file)
@@ -2334,6 +2334,11 @@ GL_APICALL void GL_APIENTRY glGetPerfQueryInfoINTEL (GLuint queryId, GLuint quer
 #endif
 #endif /* GL_INTEL_performance_query */
 
+#ifndef GL_MESA_framebuffer_flip_y
+#define GL_MESA_framebuffer_flip_y 1
+#define GL_FRAMEBUFFER_FLIP_Y_MESA        0x8BBB
+#endif /* GL_MESA_framebuffer_flip_y */
+
 #ifndef GL_MESA_program_binary_formats
 #define GL_MESA_program_binary_formats 1
 #define GL_PROGRAM_BINARY_FORMAT_MESA     0x875F
index 833478aa51540a2d3609c395fdde1d4d49d42b25..13882eff7bbef03160180969f15f7fb77e5f0da6 100644 (file)
@@ -6568,6 +6568,7 @@ typedef unsigned int GLhandleARB;
         <enum value="0x8BB5" name="GL_VERTEX_PROGRAM_CALLBACK_MESA"/>
         <enum value="0x8BB6" name="GL_VERTEX_PROGRAM_CALLBACK_FUNC_MESA"/>
         <enum value="0x8BB7" name="GL_VERTEX_PROGRAM_CALLBACK_DATA_MESA"/>
+        <enum value="0x8BBB" name="GL_FRAMEBUFFER_FLIP_Y_MESA"/>
     </enums>
 
     <enums namespace="GL" start="0x8BC0" end="0x8BFF" vendor="QCOM" comment="Reassigned from AMD to QCOM">
@@ -44356,6 +44357,11 @@ typedef unsigned int GLhandleARB;
                 <enum name="GL_TEXTURE_2D_STACK_BINDING_MESAX"/>
             </require>
         </extension>
+        <extension name="GL_MESA_framebuffer_flip_y" supported="gles2">
+            <require>
+                <enum name="GL_FRAMEBUFFER_FLIP_Y_MESA"/>
+            </require>
+        </extension>
         <extension name="GL_MESA_pack_invert" supported="gl">
             <require>
                 <enum name="GL_PACK_INVERT_MESA"/>
index 827a77f722300efbfdbf55dfb0b49d2dbf433541..78e2c1e66144be4fbd86fa7bc8e1f0caaff93379 100644 (file)
@@ -86,7 +86,8 @@ intel_map_renderbuffer(struct gl_context *ctx,
                       GLuint x, GLuint y, GLuint w, GLuint h,
                       GLbitfield mode,
                       GLubyte **out_map,
-                      GLint *out_stride)
+                      GLint *out_stride,
+                      bool flip_y)
 {
    struct intel_context *intel = intel_context(ctx);
    struct swrast_renderbuffer *srb = (struct swrast_renderbuffer *)rb;
@@ -94,6 +95,9 @@ intel_map_renderbuffer(struct gl_context *ctx,
    void *map;
    int stride;
 
+   /* driver does not support GL_FRAMEBUFFER_FLIP_Y_MESA */
+   assert((rb->Name == 0) == flip_y);
+
    if (srb->Buffer) {
       /* this is a malloc'd renderbuffer (accum buffer), not an irb */
       GLint bpp = _mesa_get_format_bytes(rb->Format);
index fb84b738c08592ac9b75f7966357f0ecea41c553..d370e8bb131116dffcdf2cb4a4bc854c3ae131d7 100644 (file)
@@ -105,7 +105,8 @@ intel_map_renderbuffer(struct gl_context *ctx,
                       GLuint x, GLuint y, GLuint w, GLuint h,
                       GLbitfield mode,
                       GLubyte **out_map,
-                      GLint *out_stride)
+                      GLint *out_stride,
+                      bool flip_y)
 {
    struct brw_context *brw = brw_context(ctx);
    struct swrast_renderbuffer *srb = (struct swrast_renderbuffer *)rb;
@@ -114,6 +115,9 @@ intel_map_renderbuffer(struct gl_context *ctx,
    void *map;
    ptrdiff_t stride;
 
+   /* driver does not support GL_FRAMEBUFFER_FLIP_Y_MESA */
+   assert((rb->Name == 0) == flip_y);
+
    if (srb->Buffer) {
       /* this is a malloc'd renderbuffer (accum buffer), not an irb */
       GLint bpp = _mesa_get_format_bytes(rb->Format);
index c78d4baa12446a47e967c658370e82dad833076b..77e7be1124c15bc5957a59bc904a758f05443c13 100644 (file)
@@ -133,13 +133,17 @@ nouveau_renderbuffer_map(struct gl_context *ctx,
                         GLuint x, GLuint y, GLuint w, GLuint h,
                         GLbitfield mode,
                         GLubyte **out_map,
-                        GLint *out_stride)
+                        GLint *out_stride,
+                        bool flip_y)
 {
        struct nouveau_surface *s = &to_nouveau_renderbuffer(rb)->surface;
        GLubyte *map;
        int stride;
        int flags = 0;
 
+       /* driver does not support GL_FRAMEBUFFER_FLIP_Y_MESA */
+       assert((rb->Name == 0) == flip_y);
+
        if (mode & GL_MAP_READ_BIT)
                flags |= NOUVEAU_BO_RD;
        if (mode & GL_MAP_WRITE_BIT)
index 37c9c3f094b79103856cf7980ca961ab2e700979..439b95bf7b1ecb49b494a1563090286d24cde562 100644 (file)
@@ -226,7 +226,8 @@ radeon_map_renderbuffer(struct gl_context *ctx,
                       GLuint x, GLuint y, GLuint w, GLuint h,
                       GLbitfield mode,
                       GLubyte **out_map,
-                      GLint *out_stride)
+                      GLint *out_stride,
+                      bool flip_y)
 {
    struct radeon_context *const rmesa = RADEON_CONTEXT(ctx);
    struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
@@ -236,6 +237,9 @@ radeon_map_renderbuffer(struct gl_context *ctx,
    int ret;
    int src_x, src_y;
 
+   /* driver does not support GL_FRAMEBUFFER_FLIP_Y_MESA */
+   assert((rb->Name == 0) == flip_y);
+
    if (!rrb || !rrb->bo) {
           *out_map = NULL;
           *out_stride = 0;
index 648df5cc146f5d6a28a386b1b62e905f02710002..fa5b2d98ff41e9f3816e1deeb36b097a55280d7e 100644 (file)
@@ -53,7 +53,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 
 static void
-radeon_renderbuffer_map(struct gl_context *ctx, struct gl_renderbuffer *rb)
+radeon_renderbuffer_map(struct gl_context *ctx,
+                       struct gl_renderbuffer *rb,
+                       bool flip_y)
 {
        struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
        GLubyte *map;
@@ -64,7 +66,7 @@ radeon_renderbuffer_map(struct gl_context *ctx, struct gl_renderbuffer *rb)
 
        ctx->Driver.MapRenderbuffer(ctx, rb, 0, 0, rb->Width, rb->Height,
                                    GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
-                                   &map, &stride);
+                                   &map, &stride, flip_y);
 
        rrb->base.Map = map;
        rrb->base.RowStride = stride;
@@ -96,7 +98,8 @@ radeon_map_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
 
        /* check for render to textures */
        for (i = 0; i < BUFFER_COUNT; i++)
-               radeon_renderbuffer_map(ctx, fb->Attachment[i].Renderbuffer);
+               radeon_renderbuffer_map(ctx, fb->Attachment[i].Renderbuffer,
+                       fb->FlipY);
 
         if (_mesa_is_front_buffer_drawing(fb))
                RADEON_CONTEXT(ctx)->front_buffer_dirty = true;
index a88ece97f3be248dd7982b12509221670b262f78..4be993a95325b8815e05d8e2ae7ef3b6b0807ad1 100644 (file)
@@ -470,13 +470,17 @@ swrast_map_renderbuffer(struct gl_context *ctx,
                        GLuint x, GLuint y, GLuint w, GLuint h,
                        GLbitfield mode,
                        GLubyte **out_map,
-                       GLint *out_stride)
+                       GLint *out_stride,
+                       bool flip_y)
 {
    struct dri_swrast_renderbuffer *xrb = dri_swrast_renderbuffer(rb);
    GLubyte *map = xrb->Base.Buffer;
    int cpp = _mesa_get_format_bytes(rb->Format);
    int stride = rb->Width * cpp;
 
+   /* driver does not support GL_FRAMEBUFFER_FLIP_Y_MESA */
+   assert((rb->Name == 0) == flip_y);
+
    if (rb->AllocStorage == swrast_alloc_front_storage) {
       __DRIdrawable *dPriv = xrb->dPriv;
       __DRIscreen *sPriv = dPriv->driScreenPriv;
index 3423eb632369f843fdf6116f26eabfe51c0f779a..be683d4583ed18d96763405545ab1012b0baeaa7 100644 (file)
@@ -573,7 +573,8 @@ osmesa_MapRenderbuffer(struct gl_context *ctx,
                        struct gl_renderbuffer *rb,
                        GLuint x, GLuint y, GLuint w, GLuint h,
                        GLbitfield mode,
-                       GLubyte **mapOut, GLint *rowStrideOut)
+                       GLubyte **mapOut, GLint *rowStrideOut,
+                       bool flip_y)
 {
    const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
 
@@ -601,7 +602,7 @@ osmesa_MapRenderbuffer(struct gl_context *ctx,
    }
    else {
       _swrast_map_soft_renderbuffer(ctx, rb, x, y, w, h, mode,
-                                    mapOut, rowStrideOut);
+                                    mapOut, rowStrideOut, flip_y);
    }
 }
 
index 97c781458587eea4ba5ea343d9c55d0acc7d95d6..0c39029ba011bcfcb193ce1b63c1ad761094a3d7 100644 (file)
@@ -423,7 +423,8 @@ xmesa_MapRenderbuffer(struct gl_context *ctx,
                       struct gl_renderbuffer *rb,
                       GLuint x, GLuint y, GLuint w, GLuint h,
                       GLbitfield mode,
-                      GLubyte **mapOut, GLint *rowStrideOut)
+                      GLubyte **mapOut, GLint *rowStrideOut,
+                      bool flip_y)
 {
    struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb);
 
index ff3ddc4ddd0ad35628ff1db346a0bbbfda2cfdea..97f15aba9b31e5a510a16b530153e5ae0ec72580 100644 (file)
@@ -358,7 +358,8 @@ xmesa_MapRenderbuffer(struct gl_context *ctx,
                       struct gl_renderbuffer *rb,
                       GLuint x, GLuint y, GLuint w, GLuint h,
                       GLbitfield mode,
-                      GLubyte **mapOut, GLint *rowStrideOut);
+                      GLubyte **mapOut, GLint *rowStrideOut,
+                      bool flip_y);
 
 extern void
 xmesa_UnmapRenderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb);
index f5ac8a102705b728814171d227d8497eae6c1aea..a0a206bea6720ce7c2a6c3c2bde469b404619587 100644 (file)
@@ -82,7 +82,8 @@ _mesa_clear_accum_buffer(struct gl_context *ctx)
    height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
 
    ctx->Driver.MapRenderbuffer(ctx, accRb, x, y, width, height,
-                               GL_MAP_WRITE_BIT, &accMap, &accRowStride);
+                               GL_MAP_WRITE_BIT, &accMap, &accRowStride,
+                               ctx->DrawBuffer->FlipY);
 
    if (!accMap) {
       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAccum");
@@ -137,7 +138,8 @@ accum_scale_or_bias(struct gl_context *ctx, GLfloat value,
 
    ctx->Driver.MapRenderbuffer(ctx, accRb, xpos, ypos, width, height,
                                GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
-                               &accMap, &accRowStride);
+                               &accMap, &accRowStride,
+                               ctx->DrawBuffer->FlipY);
 
    if (!accMap) {
       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAccum");
@@ -206,7 +208,8 @@ accum_or_load(struct gl_context *ctx, GLfloat value,
 
    /* Map accum buffer */
    ctx->Driver.MapRenderbuffer(ctx, accRb, xpos, ypos, width, height,
-                               mappingFlags, &accMap, &accRowStride);
+                               mappingFlags, &accMap, &accRowStride,
+                               ctx->DrawBuffer->FlipY);
    if (!accMap) {
       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAccum");
       return;
@@ -215,7 +218,8 @@ accum_or_load(struct gl_context *ctx, GLfloat value,
    /* Map color buffer */
    ctx->Driver.MapRenderbuffer(ctx, colorRb, xpos, ypos, width, height,
                                GL_MAP_READ_BIT,
-                               &colorMap, &colorRowStride);
+                               &colorMap, &colorRowStride,
+                               ctx->DrawBuffer->FlipY);
    if (!colorMap) {
       ctx->Driver.UnmapRenderbuffer(ctx, accRb);
       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAccum");
@@ -288,7 +292,7 @@ accum_return(struct gl_context *ctx, GLfloat value,
    /* Map accum buffer */
    ctx->Driver.MapRenderbuffer(ctx, accRb, xpos, ypos, width, height,
                                GL_MAP_READ_BIT,
-                               &accMap, &accRowStride);
+                               &accMap, &accRowStride, fb->FlipY);
    if (!accMap) {
       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAccum");
       return;
@@ -308,7 +312,8 @@ accum_return(struct gl_context *ctx, GLfloat value,
 
       /* Map color buffer */
       ctx->Driver.MapRenderbuffer(ctx, colorRb, xpos, ypos, width, height,
-                                  mappingFlags, &colorMap, &colorRowStride);
+                                  mappingFlags, &colorMap, &colorRowStride,
+                                  fb->FlipY);
       if (!colorMap) {
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAccum");
          continue;
index 78e99bfa235d4f96fcefa0817a2dde6a3cc38cc7..f14c3e04e91a89ad772533362ab7a5b329f537a0 100644 (file)
@@ -429,7 +429,8 @@ struct dd_function_table {
                           struct gl_renderbuffer *rb,
                           GLuint x, GLuint y, GLuint w, GLuint h,
                           GLbitfield mode,
-                          GLubyte **mapOut, GLint *rowStrideOut);
+                          GLubyte **mapOut, GLint *rowStrideOut,
+                          bool flip_y);
 
    void (*UnmapRenderbuffer)(struct gl_context *ctx,
                             struct gl_renderbuffer *rb);
index f4f7f01d6e4cacf4aeb79277e7a7ad779681a6be..3f01896cae774505666a9e0442fda05189eb1a59 100644 (file)
@@ -323,6 +323,7 @@ EXT(KHR_texture_compression_astc_hdr        , KHR_texture_compression_astc_hdr
 EXT(KHR_texture_compression_astc_ldr        , KHR_texture_compression_astc_ldr       , GLL, GLC,  x , ES2, 2012)
 EXT(KHR_texture_compression_astc_sliced_3d  , KHR_texture_compression_astc_sliced_3d , GLL, GLC,  x , ES2, 2015)
 
+EXT(MESA_framebuffer_flip_y                 , MESA_framebuffer_flip_y                ,   x,   x,  x ,  31, 2018)
 EXT(MESA_pack_invert                        , MESA_pack_invert                       , GLL, GLC,  x ,  x , 2002)
 EXT(MESA_shader_integer_functions           , MESA_shader_integer_functions          , GLL, GLC,  x ,  30, 2016)
 EXT(MESA_texture_signed_rgba                , EXT_texture_snorm                      , GLL, GLC,  x ,  x , 2009)
index fa7a9361dfcfeaa105aa40ec56397fd7438bd05a..750d7f45e3414624e3f076c75e95e76ea00bead6 100644 (file)
@@ -1430,6 +1430,10 @@ framebuffer_parameteri(struct gl_context *ctx, struct gl_framebuffer *fb,
       if (!ctx->Extensions.ARB_sample_locations)
          goto invalid_pname_enum;
       break;
+   case GL_FRAMEBUFFER_FLIP_Y_MESA:
+      if (!ctx->Extensions.MESA_framebuffer_flip_y)
+         goto invalid_pname_enum;
+      cannot_be_winsys_fbo = true;
    default:
       goto invalid_pname_enum;
    }
@@ -1482,6 +1486,9 @@ framebuffer_parameteri(struct gl_context *ctx, struct gl_framebuffer *fb,
    case GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB:
       fb->SampleLocationPixelGrid = !!param;
       break;
+   case GL_FRAMEBUFFER_FLIP_Y_MESA:
+      fb->FlipY = param;
+      break;
    }
 
    switch (pname) {
@@ -1574,6 +1581,12 @@ validate_get_framebuffer_parameteriv_pname(struct gl_context *ctx,
          goto invalid_pname_enum;
       cannot_be_winsys_fbo = false;
       break;
+   case GL_FRAMEBUFFER_FLIP_Y_MESA:
+      if (!ctx->Extensions.MESA_framebuffer_flip_y) {
+         _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
+         return false;
+      }
+      break;
    default:
       goto invalid_pname_enum;
    }
@@ -1638,6 +1651,9 @@ get_framebuffer_parameteriv(struct gl_context *ctx, struct gl_framebuffer *fb,
    case GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB:
       *params = fb->SampleLocationPixelGrid;
       break;
+   case GL_FRAMEBUFFER_FLIP_Y_MESA:
+      *params = fb->FlipY;
+      break;
    }
 }
 
index 78a80649a04447ddea412a9cac40e97267159a32..10dd2fde44661a59e04f9353d3564dca44e3026b 100644 (file)
@@ -159,6 +159,7 @@ _mesa_initialize_window_framebuffer(struct gl_framebuffer *fb,
    fb->_AllColorBuffersFixedPoint = !visual->floatMode;
    fb->_HasSNormOrFloatColorBuffer = visual->floatMode;
    fb->_HasAttachments = true;
+   fb->FlipY = true;
 
    fb->SampleLocationTable = NULL;
    fb->ProgrammableSampleLocations = 0;
index 16648820b1b6ddc9d93a5f3da09360dae7be56ba..1a91d543126d3654315793fe9e2c0a618ba7b5aa 100644 (file)
@@ -160,6 +160,9 @@ typedef void *GLeglImageOES;
 #define GL_HALF_FLOAT_OES                                       0x8D61
 #endif
 
+#ifndef GL_MESA_framebuffer_flip_y
+#define GL_FRAMEBUFFER_FLIP_Y_MESA                              0x8BBB
+#endif
 
 /**
  * Internal token to represent a GLSL shader program (a collection of
index 7ef7a3f1106e47689b639a1d3af4f4a2f976f647..d71872835d1dfc84044bc17a420ee92baa423499 100644 (file)
@@ -3507,6 +3507,9 @@ struct gl_framebuffer
    struct gl_renderbuffer *_ColorDrawBuffers[MAX_DRAW_BUFFERS];
    struct gl_renderbuffer *_ColorReadBuffer;
 
+   /* GL_MESA_framebuffer_flip_y */
+   bool FlipY;
+
    /** Delete this framebuffer */
    void (*Delete)(struct gl_framebuffer *fb);
 };
@@ -4253,6 +4256,7 @@ struct gl_extensions
    GLboolean KHR_texture_compression_astc_hdr;
    GLboolean KHR_texture_compression_astc_ldr;
    GLboolean KHR_texture_compression_astc_sliced_3d;
+   GLboolean MESA_framebuffer_flip_y;
    GLboolean MESA_tile_raster_order;
    GLboolean MESA_pack_invert;
    GLboolean EXT_shader_framebuffer_fetch;
index c5fc66988b7df1cca1dd1463037c47dd85bd8d59..e8c28d86162886c39e96a34171d8bd35567f9df8 100644 (file)
@@ -234,7 +234,7 @@ readpixels_memcpy(struct gl_context *ctx,
                                           format, type, 0, 0);
 
    ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
-                              &map, &stride);
+                              &map, &stride, ctx->ReadBuffer->FlipY);
    if (!map) {
       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
       return GL_TRUE;  /* don't bother trying the slow path */
@@ -285,7 +285,7 @@ read_uint_depth_pixels( struct gl_context *ctx,
       return GL_FALSE;
 
    ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
-                              &map, &stride);
+                              &map, &stride, fb->FlipY);
 
    if (!map) {
       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
@@ -343,7 +343,7 @@ read_depth_pixels( struct gl_context *ctx,
                                           GL_DEPTH_COMPONENT, type, 0, 0);
 
    ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
-                              &map, &stride);
+                              &map, &stride, fb->FlipY);
    if (!map) {
       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
       return;
@@ -391,7 +391,7 @@ read_stencil_pixels( struct gl_context *ctx,
       return;
 
    ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
-                              &map, &stride);
+                              &map, &stride, fb->FlipY);
    if (!map) {
       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
       return;
@@ -462,7 +462,7 @@ read_rgba_pixels( struct gl_context *ctx,
 
    /* Map the source render buffer */
    ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
-                               &map, &rb_stride);
+                               &map, &rb_stride, fb->FlipY);
    if (!map) {
       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
       return;
@@ -652,7 +652,7 @@ fast_read_depth_stencil_pixels(struct gl_context *ctx,
       return GL_FALSE;
 
    ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
-                              &map, &stride);
+                              &map, &stride, fb->FlipY);
    if (!map) {
       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
       return GL_TRUE;  /* don't bother trying the slow path */
@@ -692,14 +692,14 @@ fast_read_depth_stencil_pixels_separate(struct gl_context *ctx,
       return GL_FALSE;
 
    ctx->Driver.MapRenderbuffer(ctx, depthRb, x, y, width, height,
-                              GL_MAP_READ_BIT, &depthMap, &depthStride);
+                              GL_MAP_READ_BIT, &depthMap, &depthStride, fb->FlipY);
    if (!depthMap) {
       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
       return GL_TRUE;  /* don't bother trying the slow path */
    }
 
    ctx->Driver.MapRenderbuffer(ctx, stencilRb, x, y, width, height,
-                              GL_MAP_READ_BIT, &stencilMap, &stencilStride);
+                              GL_MAP_READ_BIT, &stencilMap, &stencilStride, fb->FlipY);
    if (!stencilMap) {
       ctx->Driver.UnmapRenderbuffer(ctx, depthRb);
       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
@@ -756,7 +756,7 @@ slow_read_depth_stencil_pixels_separate(struct gl_context *ctx,
     * If one buffer, only map it once.
     */
    ctx->Driver.MapRenderbuffer(ctx, depthRb, x, y, width, height,
-                              GL_MAP_READ_BIT, &depthMap, &depthStride);
+                              GL_MAP_READ_BIT, &depthMap, &depthStride, fb->FlipY);
    if (!depthMap) {
       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
       return;
@@ -765,7 +765,7 @@ slow_read_depth_stencil_pixels_separate(struct gl_context *ctx,
    if (stencilRb != depthRb) {
       ctx->Driver.MapRenderbuffer(ctx, stencilRb, x, y, width, height,
                                   GL_MAP_READ_BIT, &stencilMap,
-                                  &stencilStride);
+                                  &stencilStride, fb->FlipY);
       if (!stencilMap) {
          ctx->Driver.UnmapRenderbuffer(ctx, depthRb);
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
index b851db64886dacc84cb69ea3a819258c3cd49f71..698c7046c1a6c407ede2eb8accb6388d598c5af5 100644 (file)
@@ -770,7 +770,8 @@ st_MapRenderbuffer(struct gl_context *ctx,
                    struct gl_renderbuffer *rb,
                    GLuint x, GLuint y, GLuint w, GLuint h,
                    GLbitfield mode,
-                   GLubyte **mapOut, GLint *rowStrideOut)
+                   GLubyte **mapOut, GLint *rowStrideOut,
+                   bool flip_y)
 {
    struct st_context *st = st_context(ctx);
    struct st_renderbuffer *strb = st_renderbuffer(rb);
@@ -779,6 +780,9 @@ st_MapRenderbuffer(struct gl_context *ctx,
    GLuint y2;
    GLubyte *map;
 
+   /* driver does not support GL_FRAMEBUFFER_FLIP_Y_MESA */
+   assert((rb->Name == 0) == flip_y);
+
    if (strb->software) {
       /* software-allocated renderbuffer (probably an accum buffer) */
       if (strb->data) {
index 19fe8484eb914347a77bc708f1b49a49a86b36e4..107e41307ee3d198125740cc6f1f2711af016c0d 100644 (file)
@@ -253,7 +253,7 @@ blit_nearest(struct gl_context *ctx,
          ctx->Driver.MapRenderbuffer(ctx, readRb, 0, 0,
                                      readRb->Width, readRb->Height,
                                      GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
-                                     &map, &rowStride);
+                                     &map, &rowStride, readFb->FlipY);
          if (!map) {
             goto fail_no_memory;
          }
@@ -280,14 +280,16 @@ blit_nearest(struct gl_context *ctx,
          ctx->Driver.MapRenderbuffer(ctx, readRb,
                                      srcXpos, srcYpos,
                                      srcWidth, srcHeight,
-                                     GL_MAP_READ_BIT, &srcMap, &srcRowStride);
+                                     GL_MAP_READ_BIT, &srcMap, &srcRowStride,
+                                     readFb->FlipY);
          if (!srcMap) {
             goto fail_no_memory;
          }
          ctx->Driver.MapRenderbuffer(ctx, drawRb,
                                      dstXpos, dstYpos,
                                      dstWidth, dstHeight,
-                                     GL_MAP_WRITE_BIT, &dstMap, &dstRowStride);
+                                     GL_MAP_WRITE_BIT, &dstMap, &dstRowStride,
+                                     drawFb->FlipY);
          if (!dstMap) {
             ctx->Driver.UnmapRenderbuffer(ctx, readRb);
             goto fail_no_memory;
@@ -594,7 +596,8 @@ blit_linear(struct gl_context *ctx,
          ctx->Driver.MapRenderbuffer(ctx, readRb,
                                      0, 0, readRb->Width, readRb->Height,
                                      GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
-                                     &srcMap, &srcRowStride);
+                                     &srcMap, &srcRowStride,
+                                     readFb->FlipY);
          if (!srcMap) {
             goto fail_no_memory;
          }
@@ -609,13 +612,15 @@ blit_linear(struct gl_context *ctx,
           */
          ctx->Driver.MapRenderbuffer(ctx, readRb,
                                      0, 0, readRb->Width, readRb->Height,
-                                     GL_MAP_READ_BIT, &srcMap, &srcRowStride);
+                                     GL_MAP_READ_BIT, &srcMap, &srcRowStride,
+                                     readFb->FlipY);
          if (!srcMap) {
             goto fail_no_memory;
          }
          ctx->Driver.MapRenderbuffer(ctx, drawRb,
                                      0, 0, drawRb->Width, drawRb->Height,
-                                     GL_MAP_WRITE_BIT, &dstMap, &dstRowStride);
+                                     GL_MAP_WRITE_BIT, &dstMap, &dstRowStride,
+                                     drawFb->FlipY);
          if (!dstMap) {
             ctx->Driver.UnmapRenderbuffer(ctx, readRb);
             goto fail_no_memory;
index ddafb67c98f1627dba5643834a3781d3f3cd52c8..ef0f6df9d9cbcb5a98db9e681d61ac3931a90aa2 100644 (file)
@@ -66,7 +66,8 @@ clear_rgba_buffer(struct gl_context *ctx, struct gl_renderbuffer *rb,
 
    /* map dest buffer */
    ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height,
-                               mapMode, &map, &rowStride);
+                               mapMode, &map, &rowStride,
+                               ctx->DrawBuffer->FlipY);
    if (!map) {
       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClear(color)");
       return;
index 0dbccc0f61dc99c81e8ceea2f827f6cce9fe4972..d0703fa07a63cf45333c70ba71c7e941778dd36e 100644 (file)
@@ -503,7 +503,7 @@ swrast_fast_copy_pixels(struct gl_context *ctx,
       ctx->Driver.MapRenderbuffer(ctx, srcRb, 0, 0,
                                   srcRb->Width, srcRb->Height,
                                   GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
-                                  &map, &rowStride);
+                                  &map, &rowStride, srcFb->FlipY);
       if (!map) {
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels");
          return GL_TRUE; /* don't retry with slow path */
@@ -530,14 +530,16 @@ swrast_fast_copy_pixels(struct gl_context *ctx,
       /* different src/dst buffers */
       ctx->Driver.MapRenderbuffer(ctx, srcRb, srcX, srcY,
                                   width, height,
-                                  GL_MAP_READ_BIT, &srcMap, &srcRowStride);
+                                  GL_MAP_READ_BIT, &srcMap, &srcRowStride,
+                                  srcFb->FlipY);
       if (!srcMap) {
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels");
          return GL_TRUE; /* don't retry with slow path */
       }
       ctx->Driver.MapRenderbuffer(ctx, dstRb, dstX, dstY,
                                   width, height,
-                                  GL_MAP_WRITE_BIT, &dstMap, &dstRowStride);
+                                  GL_MAP_WRITE_BIT, &dstMap, &dstRowStride,
+                                  dstFb->FlipY);
       if (!dstMap) {
          ctx->Driver.UnmapRenderbuffer(ctx, srcRb);
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels");
@@ -598,7 +600,8 @@ map_readbuffer(struct gl_context *ctx, GLenum type)
    ctx->Driver.MapRenderbuffer(ctx, rb,
                                0, 0, rb->Width, rb->Height,
                                GL_MAP_READ_BIT,
-                               &srb->Map, &srb->RowStride);
+                               &srb->Map, &srb->RowStride,
+                               fb->FlipY);
 
    return rb;
 }
index ffadc05a732cc9c62c113ae1e39eb208d70f9f45..4b9640d319025f4aff8ee24db9e825e06d5863e0 100644 (file)
@@ -570,7 +570,8 @@ _swrast_clear_depth_buffer(struct gl_context *ctx)
    }
 
    ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height,
-                               mapMode, &map, &rowStride);
+                               mapMode, &map, &rowStride,
+                               ctx->DrawBuffer->FlipY);
    if (!map) {
       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClear(depth)");
       return;
@@ -695,7 +696,8 @@ _swrast_clear_depth_stencil_buffer(struct gl_context *ctx)
    }
 
    ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height,
-                               mapMode, &map, &rowStride);
+                               mapMode, &map, &rowStride,
+                               ctx->DrawBuffer->FlipY);
    if (!map) {
       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClear(depth+stencil)");
       return;
index f05528d0d27a4b06030266c7f0f70416227f3f62..7ee401b2d4ce0f9e3065b910a612502da77d07ca 100644 (file)
@@ -55,7 +55,8 @@ fast_draw_rgb_ubyte_pixels(struct gl_context *ctx,
                            GLint x, GLint y,
                            GLsizei width, GLsizei height,
                            const struct gl_pixelstore_attrib *unpack,
-                           const GLvoid *pixels)
+                           const GLvoid *pixels,
+                           bool flip_y)
 {
    const GLubyte *src = (const GLubyte *)
       _mesa_image_address2d(unpack, pixels, width,
@@ -67,7 +68,8 @@ fast_draw_rgb_ubyte_pixels(struct gl_context *ctx,
    GLint dstRowStride;
 
    ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height,
-                               GL_MAP_WRITE_BIT, &dst, &dstRowStride);
+                               GL_MAP_WRITE_BIT, &dst, &dstRowStride,
+                               flip_y);
 
    if (!dst) {
       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
@@ -102,7 +104,8 @@ fast_draw_rgba_ubyte_pixels(struct gl_context *ctx,
                            GLint x, GLint y,
                            GLsizei width, GLsizei height,
                            const struct gl_pixelstore_attrib *unpack,
-                           const GLvoid *pixels)
+                           const GLvoid *pixels,
+                           bool flip_y)
 {
    const GLubyte *src = (const GLubyte *)
       _mesa_image_address2d(unpack, pixels, width,
@@ -114,7 +117,8 @@ fast_draw_rgba_ubyte_pixels(struct gl_context *ctx,
    GLint dstRowStride;
 
    ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height,
-                               GL_MAP_WRITE_BIT, &dst, &dstRowStride);
+                               GL_MAP_WRITE_BIT, &dst, &dstRowStride,
+                               flip_y);
 
    if (!dst) {
       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
@@ -151,7 +155,8 @@ fast_draw_generic_pixels(struct gl_context *ctx,
                          GLsizei width, GLsizei height,
                          GLenum format, GLenum type,
                          const struct gl_pixelstore_attrib *unpack,
-                         const GLvoid *pixels)
+                         const GLvoid *pixels,
+                         bool flip_y)
 {
    const GLubyte *src = (const GLubyte *)
       _mesa_image_address2d(unpack, pixels, width,
@@ -164,7 +169,8 @@ fast_draw_generic_pixels(struct gl_context *ctx,
    GLint dstRowStride;
 
    ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height,
-                               GL_MAP_WRITE_BIT, &dst, &dstRowStride);
+                               GL_MAP_WRITE_BIT, &dst, &dstRowStride,
+                               flip_y);
 
    if (!dst) {
       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
@@ -197,6 +203,7 @@ fast_draw_rgba_pixels(struct gl_context *ctx, GLint x, GLint y,
                       const struct gl_pixelstore_attrib *userUnpack,
                       const GLvoid *pixels)
 {
+   struct gl_framebuffer *fb = ctx->DrawBuffer;
    struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0];
    SWcontext *swrast = SWRAST_CONTEXT(ctx);
    struct gl_pixelstore_attrib unpack;
@@ -228,7 +235,7 @@ fast_draw_rgba_pixels(struct gl_context *ctx, GLint x, GLint y,
        (rb->Format == MESA_FORMAT_B8G8R8X8_UNORM ||
         rb->Format == MESA_FORMAT_B8G8R8A8_UNORM)) {
       fast_draw_rgb_ubyte_pixels(ctx, rb, x, y, width, height,
-                                 &unpack, pixels);
+                                 &unpack, pixels, fb->FlipY);
       return GL_TRUE;
    }
 
@@ -237,14 +244,15 @@ fast_draw_rgba_pixels(struct gl_context *ctx, GLint x, GLint y,
        (rb->Format == MESA_FORMAT_B8G8R8X8_UNORM ||
         rb->Format == MESA_FORMAT_B8G8R8A8_UNORM)) {
       fast_draw_rgba_ubyte_pixels(ctx, rb, x, y, width, height,
-                                  &unpack, pixels);
+                                  &unpack, pixels, fb->FlipY);
       return GL_TRUE;
    }
 
    if (_mesa_format_matches_format_and_type(rb->Format, format, type,
                                             ctx->Unpack.SwapBytes, NULL)) {
       fast_draw_generic_pixels(ctx, rb, x, y, width, height,
-                               format, type, &unpack, pixels);
+                               format, type, &unpack, pixels,
+                               fb->FlipY);
       return GL_TRUE;
    }
 
index f76489c2005f94d19b74576cee85926623811df6..8c97e4e11b480fd83a249254a8ea1a0a074e5866 100644 (file)
@@ -180,7 +180,8 @@ _swrast_map_soft_renderbuffer(struct gl_context *ctx,
                               GLuint x, GLuint y, GLuint w, GLuint h,
                               GLbitfield mode,
                               GLubyte **out_map,
-                              GLint *out_stride)
+                              GLint *out_stride,
+                              bool flip_y)
 {
    struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
    GLubyte *map = srb->Buffer;
@@ -578,7 +579,8 @@ map_attachment(struct gl_context *ctx,
       ctx->Driver.MapRenderbuffer(ctx, rb,
                                   0, 0, rb->Width, rb->Height,
                                   GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
-                                  &srb->Map, &srb->RowStride);
+                                  &srb->Map, &srb->RowStride,
+                                  fb->FlipY);
    }
 
    assert(srb->Map);
index 2595d7c177591b6f61e91448ad2772a76d5b3234..9238d8afa493265df93027b62bc1e8392e860c34 100644 (file)
@@ -43,7 +43,8 @@ _swrast_map_soft_renderbuffer(struct gl_context *ctx,
                               GLuint x, GLuint y, GLuint w, GLuint h,
                               GLbitfield mode,
                               GLubyte **out_map,
-                              GLint *out_stride);
+                              GLint *out_stride,
+                              bool flip_y);
 
 extern void
 _swrast_unmap_soft_renderbuffer(struct gl_context *ctx,
index 7a4dc45ae868c4f420db6a9e13bafa752f32371a..8ccd5a16442cbcbcbcabbb7a826522c7266c1172 100644 (file)
@@ -579,7 +579,8 @@ _swrast_clear_stencil_buffer(struct gl_context *ctx)
    }
 
    ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height,
-                               mapMode, &map, &rowStride);
+                               mapMode, &map, &rowStride,
+                               ctx->DrawBuffer->FlipY);
    if (!map) {
       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClear(stencil)");
       return;