[Mesa-dev] [PATCH v3 1/5] mesa: add support for ARB_sample_locations

Rhys Perry pendingchaos02 at gmail.com
Fri Jun 1 15:08:18 UTC 2018


Signed-off-by: Rhys Perry <pendingchaos02 at gmail.com>
Reviewed-by: Brian Paul <brianp at vmware.com> (v2)
Reviewed-by: Marek Olšák <marek.olsak at amd.com> (v2)
---
 src/mapi/glapi/gen/gl_API.xml           | 104 +++++++++++++
 src/mesa/main/config.h                  |   9 ++
 src/mesa/main/dd.h                      |   8 +
 src/mesa/main/extensions_table.h        |   2 +
 src/mesa/main/fbobject.c                | 256 ++++++++++++++++++++++++++++----
 src/mesa/main/fbobject.h                |  20 +++
 src/mesa/main/framebuffer.c             |  10 ++
 src/mesa/main/get.c                     |  31 ++++
 src/mesa/main/get_hash_params.py        |   6 +
 src/mesa/main/mtypes.h                  |   9 ++
 src/mesa/main/multisample.c             |  18 +++
 src/mesa/main/tests/dispatch_sanity.cpp |  10 ++
 12 files changed, 455 insertions(+), 28 deletions(-)

diff --git a/src/mapi/glapi/gen/gl_API.xml b/src/mapi/glapi/gen/gl_API.xml
index 8ad45970c9..49807e1ea5 100644
--- a/src/mapi/glapi/gen/gl_API.xml
+++ b/src/mapi/glapi/gen/gl_API.xml
@@ -10881,6 +10881,110 @@
 
 <!-- Extension number 180 is not listed in the extension registry. -->
 
+<category name="GL_ARB_sample_locations" number="181">
+    <enum name="SAMPLE_LOCATION_SUBPIXEL_BITS_ARB"             value="0x933D">
+        <size name="Get" mode="get"/>
+    </enum>
+
+    <enum name="SAMPLE_LOCATION_PIXEL_GRID_WIDTH_ARB"          value="0x933E">
+        <size name="Get" mode="get"/>
+    </enum>
+
+    <enum name="SAMPLE_LOCATION_PIXEL_GRID_HEIGHT_ARB"         value="0x933F">
+        <size name="Get" mode="get"/>
+    </enum>
+
+    <enum name="PROGRAMMABLE_SAMPLE_LOCATION_TABLE_SIZE_ARB"   value="0x9340">
+        <size name="Get" mode="get"/>
+    </enum>
+
+    <enum name="SAMPLE_LOCATION_ARB"                           value="0x8E50">
+        <size name="GetMultisamplefv" mode="get"/>
+    </enum>
+
+    <enum name="PROGRAMMABLE_SAMPLE_LOCATION_ARB"              value="0x9341">
+        <size name="GetMultisamplefv" mode="get"/>
+    </enum>
+
+    <enum name="FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_ARB" value="0x9342">
+        <size name="FramebufferParameteri"/>
+        <size name="GetFramebufferParameteri"/>
+    </enum>
+
+    <enum name="FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB"    value="0x9343">
+        <size name="FramebufferParameteri"/>
+        <size name="GetFramebufferParameteri"/>
+    </enum>
+
+    <function name="FramebufferSampleLocationsfvARB" no_error="true">
+        <param name="target" type="GLenum"/>
+        <param name="start"  type="GLuint"/>
+        <param name="count"  type="GLsizei"/>
+        <param name="v"      type="const GLfloat *"/>
+    </function>
+
+    <function name="NamedFramebufferSampleLocationsfvARB" no_error="true">
+        <param name="framebuffer" type="GLuint"/>
+        <param name="start"       type="GLuint"/>
+        <param name="count"       type="GLsizei"/>
+        <param name="v"           type="const GLfloat *"/>
+    </function>
+
+    <function name="EvaluateDepthValuesARB"/>
+</category>
+
+<category name="GL_NV_sample_locations" number="472">
+    <enum name="SAMPLE_LOCATION_SUBPIXEL_BITS_NV"             value="0x933D" alias="SAMPLE_LOCATION_SUBPIXEL_BITS_ARB">
+        <size name="Get" mode="get"/>
+    </enum>
+
+    <enum name="SAMPLE_LOCATION_PIXEL_GRID_WIDTH_NV"          value="0x933E" alias="SAMPLE_LOCATION_PIXEL_GRID_WIDTH_ARB">
+        <size name="Get" mode="get"/>
+    </enum>
+
+    <enum name="SAMPLE_LOCATION_PIXEL_GRID_HEIGHT_NV"         value="0x933F" alias="SAMPLE_LOCATION_PIXEL_GRID_HEIGHT_ARB">
+        <size name="Get" mode="get"/>
+    </enum>
+
+    <enum name="PROGRAMMABLE_SAMPLE_LOCATION_TABLE_SIZE_NV"   value="0x9340" alias="PROGRAMMABLE_SAMPLE_LOCATION_TABLE_SIZE_ARB">
+        <size name="Get" mode="get"/>
+    </enum>
+
+    <enum name="SAMPLE_LOCATION_NV"                           value="0x8E50" alias="SAMPLE_LOCATION_ARB">
+        <size name="GetMultisamplefv" mode="get"/>
+    </enum>
+
+    <enum name="PROGRAMMABLE_SAMPLE_LOCATION_NV"              value="0x9341" alias="PROGRAMMABLE_SAMPLE_LOCATION_ARB">
+        <size name="GetMultisamplefv" mode="get"/>
+    </enum>
+
+    <enum name="FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_NV" value="0x9342" alias="FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_ARB">
+        <size name="FramebufferParameteri"/>
+        <size name="GetFramebufferParameteri"/>
+    </enum>
+
+    <enum name="FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_NV"    value="0x9343" alias="FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB">
+        <size name="FramebufferParameteri"/>
+        <size name="GetFramebufferParameteri"/>
+    </enum>
+
+    <function name="FramebufferSampleLocationsfvNV" no_error="true" es2="3.1" alias="FramebufferSampleLocationsfvARB">
+        <param name="target" type="GLenum"/>
+        <param name="start"  type="GLuint"/>
+        <param name="count"  type="GLsizei"/>
+        <param name="v"      type="const GLfloat *"/>
+    </function>
+
+    <function name="NamedFramebufferSampleLocationsfvNV" no_error="true" es2="3.1" alias="NamedFramebufferSampleLocationsfvARB">
+        <param name="framebuffer" type="GLuint"/>
+        <param name="start"       type="GLuint"/>
+        <param name="count"       type="GLsizei"/>
+        <param name="v"           type="const GLfloat *"/>
+    </function>
+
+    <function name="ResolveDepthValuesNV" es2="3.1" alias="EvaluateDepthValuesARB"/>
+</category>
+
 <category name="GL_SUN_convolution_border_modes" number="182">
     <enum name="WRAP_BORDER_SUN"                          value="0x81D4"/>
 </category>
diff --git a/src/mesa/main/config.h b/src/mesa/main/config.h
index 81573bfbf2..6a2f766222 100644
--- a/src/mesa/main/config.h
+++ b/src/mesa/main/config.h
@@ -315,4 +315,13 @@
 #define MAX_CLIPPED_VERTICES ((2 * (6 + MAX_CLIP_PLANES))+1)
 
 
+/** For GL_ARB_sample_locations - maximum of SAMPLE_LOCATION_PIXEL_GRID_*_ARB */
+#define MAX_SAMPLE_LOCATION_GRID_SIZE 4
+
+/* It is theoretically possible for Consts.MaxSamples to be >32 but
+ * other code seems to assume that is not the case.
+ */
+#define MAX_SAMPLE_LOCATION_TABLE_SIZE \
+   (MAX_SAMPLE_LOCATION_GRID_SIZE * MAX_SAMPLE_LOCATION_GRID_SIZE * 32)
+
 #endif /* MESA_CONFIG_H_INCLUDED */
diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h
index 9f9606ac6b..1b048d3ff8 100644
--- a/src/mesa/main/dd.h
+++ b/src/mesa/main/dd.h
@@ -787,6 +787,14 @@ struct dd_function_table {
                               GLenum target, GLsizei numAttachments,
                               const GLenum *attachments);
 
+   /**
+    * \name Functions for GL_ARB_sample_locations
+    */
+   void (*GetProgrammableSampleCaps)(struct gl_context *ctx,
+                                     const struct gl_framebuffer *fb,
+                                     GLuint *bits, GLuint *width, GLuint *height);
+   void (*EvaluateDepthValues)(struct gl_context *ctx);
+
    /**
     * \name Query objects
     */
diff --git a/src/mesa/main/extensions_table.h b/src/mesa/main/extensions_table.h
index 9207e3f8c6..ab1fd170bd 100644
--- a/src/mesa/main/extensions_table.h
+++ b/src/mesa/main/extensions_table.h
@@ -103,6 +103,7 @@ EXT(ARB_provoking_vertex                    , EXT_provoking_vertex
 EXT(ARB_query_buffer_object                 , ARB_query_buffer_object                , GLL, GLC,  x ,  x , 2013)
 EXT(ARB_robust_buffer_access_behavior       , ARB_robust_buffer_access_behavior      , GLL, GLC,  x ,  x , 2012)
 EXT(ARB_robustness                          , dummy_true                             , GLL, GLC,  x ,  x , 2010)
+EXT(ARB_sample_locations                    , ARB_sample_locations                   , GLL, GLC,  x ,  x , 2015)
 EXT(ARB_sample_shading                      , ARB_sample_shading                     , GLL, GLC,  x ,  x , 2009)
 EXT(ARB_sampler_objects                     , dummy_true                             , GLL, GLC,  x ,  x , 2009)
 EXT(ARB_seamless_cube_map                   , ARB_seamless_cube_map                  , GLL, GLC,  x ,  x , 2009)
@@ -350,6 +351,7 @@ EXT(NV_read_buffer                          , dummy_true
 EXT(NV_read_depth                           , dummy_true                             ,  x ,  x ,  x , ES2, 2011)
 EXT(NV_read_depth_stencil                   , dummy_true                             ,  x ,  x ,  x , ES2, 2011)
 EXT(NV_read_stencil                         , dummy_true                             ,  x ,  x ,  x , ES2, 2011)
+EXT(NV_sample_locations                     , ARB_sample_locations                   , GLL, GLC,  x , ES2, 2015)
 EXT(NV_texgen_reflection                    , dummy_true                             , GLL,  x ,  x ,  x , 1999)
 EXT(NV_texture_barrier                      , NV_texture_barrier                     , GLL, GLC,  x ,  x , 2009)
 EXT(NV_texture_env_combine4                 , NV_texture_env_combine4                , GLL,  x ,  x ,  x , 1999)
diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c
index a63e8b8de5..5d7e5d2984 100644
--- a/src/mesa/main/fbobject.c
+++ b/src/mesa/main/fbobject.c
@@ -35,6 +35,7 @@
 
 #include "buffers.h"
 #include "context.h"
+#include "debug_output.h"
 #include "enums.h"
 #include "fbobject.h"
 #include "formats.h"
@@ -1404,14 +1405,41 @@ _mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer)
 }
 
 /**
- * ARB_framebuffer_no_attachment - Application passes requested param's
- * here. NOTE: NumSamples requested need not be _NumSamples which is
- * what the hw supports.
+ * ARB_framebuffer_no_attachment and ARB_sample_locations - Application passes
+ * requested param's here. NOTE: NumSamples requested need not be _NumSamples
+ * which is what the hw supports.
  */
 static void
 framebuffer_parameteri(struct gl_context *ctx, struct gl_framebuffer *fb,
                        GLenum pname, GLint param, const char *func)
 {
+   bool cannot_be_winsys_fbo = false;
+
+   switch (pname) {
+   case GL_FRAMEBUFFER_DEFAULT_WIDTH:
+   case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
+   case GL_FRAMEBUFFER_DEFAULT_LAYERS:
+   case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
+   case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
+      if (!ctx->Extensions.ARB_framebuffer_no_attachments)
+         goto invalid_pname_enum;
+      cannot_be_winsys_fbo = true;
+      break;
+   case GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_ARB:
+   case GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB:
+      if (!ctx->Extensions.ARB_sample_locations)
+         goto invalid_pname_enum;
+      break;
+   default:
+      goto invalid_pname_enum;
+   }
+
+   if (cannot_be_winsys_fbo && _mesa_is_winsys_fbo(fb)) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "%s(invalid pname=0x%x for default framebuffer)", func, pname);
+      return;
+   }
+
    switch (pname) {
    case GL_FRAMEBUFFER_DEFAULT_WIDTH:
       if (param < 0 || param > ctx->Const.MaxFramebufferWidth)
@@ -1448,13 +1476,30 @@ framebuffer_parameteri(struct gl_context *ctx, struct gl_framebuffer *fb,
    case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
       fb->DefaultGeometry.FixedSampleLocations = param;
       break;
+   case GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_ARB:
+      fb->ProgrammableSampleLocations = !!param;
+      break;
+   case GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB:
+      fb->SampleLocationPixelGrid = !!param;
+      break;
+   }
+
+   switch (pname) {
+   case GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_ARB:
+   case GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB:
+      if (fb == ctx->DrawBuffer)
+         ctx->NewDriverState |= ctx->DriverFlags.NewSampleLocations;
+      break;
    default:
-      _mesa_error(ctx, GL_INVALID_ENUM,
-                  "%s(pname=0x%x)", func, pname);
+      invalidate_framebuffer(fb);
+      ctx->NewState |= _NEW_BUFFERS;
+      break;
    }
 
-   invalidate_framebuffer(fb);
-   ctx->NewState |= _NEW_BUFFERS;
+   return;
+
+invalid_pname_enum:
+   _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
 }
 
 void GLAPIENTRY
@@ -1463,10 +1508,12 @@ _mesa_FramebufferParameteri(GLenum target, GLenum pname, GLint param)
    GET_CURRENT_CONTEXT(ctx);
    struct gl_framebuffer *fb;
 
-   if (!ctx->Extensions.ARB_framebuffer_no_attachments) {
+   if (!ctx->Extensions.ARB_framebuffer_no_attachments &&
+       !ctx->Extensions.ARB_sample_locations) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "glFramebufferParameteriv not supported "
-                  "(ARB_framebuffer_no_attachments not implemented)");
+                  "(neither ARB_framebuffer_no_attachments nor ARB_sample_locations"
+                  " is available)");
       return;
    }
 
@@ -1477,13 +1524,6 @@ _mesa_FramebufferParameteri(GLenum target, GLenum pname, GLint param)
       return;
    }
 
-   /* check framebuffer binding */
-   if (_mesa_is_winsys_fbo(fb)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glFramebufferParameteri");
-      return;
-   }
-
    framebuffer_parameteri(ctx, fb, pname, param, "glFramebufferParameteri");
 }
 
@@ -1528,9 +1568,14 @@ validate_get_framebuffer_parameteriv_pname(struct gl_context *ctx,
        */
       cannot_be_winsys_fbo = !_mesa_is_desktop_gl(ctx);
       break;
+   case GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_ARB:
+   case GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB:
+      if (!ctx->Extensions.ARB_sample_locations)
+         goto invalid_pname_enum;
+      cannot_be_winsys_fbo = false;
+      break;
    default:
-      _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
-      return false;
+      goto invalid_pname_enum;
    }
 
    if (cannot_be_winsys_fbo && _mesa_is_winsys_fbo(fb)) {
@@ -1540,6 +1585,10 @@ validate_get_framebuffer_parameteriv_pname(struct gl_context *ctx,
    }
 
    return true;
+
+invalid_pname_enum:
+   _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
+   return false;
 }
 
 static void
@@ -1583,6 +1632,12 @@ get_framebuffer_parameteriv(struct gl_context *ctx, struct gl_framebuffer *fb,
    case GL_STEREO:
       *params = fb->Visual.stereoMode;
       break;
+   case GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_ARB:
+      *params = fb->ProgrammableSampleLocations;
+      break;
+   case GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB:
+      *params = fb->SampleLocationPixelGrid;
+      break;
    }
 }
 
@@ -1592,10 +1647,12 @@ _mesa_GetFramebufferParameteriv(GLenum target, GLenum pname, GLint *params)
    GET_CURRENT_CONTEXT(ctx);
    struct gl_framebuffer *fb;
 
-   if (!ctx->Extensions.ARB_framebuffer_no_attachments) {
+   if (!ctx->Extensions.ARB_framebuffer_no_attachments &&
+       !ctx->Extensions.ARB_sample_locations) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "glGetFramebufferParameteriv not supported "
-                  "(ARB_framebuffer_no_attachments not implemented)");
+                  "(neither ARB_framebuffer_no_attachments nor ARB_sample_locations"
+                  " is available)");
       return;
    }
 
@@ -2694,6 +2751,7 @@ _mesa_bind_framebuffers(struct gl_context *ctx,
 
    if (bindDrawBuf) {
       FLUSH_VERTICES(ctx, _NEW_BUFFERS);
+      ctx->NewDriverState |= ctx->DriverFlags.NewSampleLocations;
 
       /* check if old framebuffer had any texture attachments */
       if (oldDrawFb)
@@ -4234,15 +4292,21 @@ _mesa_NamedFramebufferParameteri(GLuint framebuffer, GLenum pname,
    GET_CURRENT_CONTEXT(ctx);
    struct gl_framebuffer *fb = NULL;
 
-   if (!ctx->Extensions.ARB_framebuffer_no_attachments) {
+   if (!ctx->Extensions.ARB_framebuffer_no_attachments &&
+       !ctx->Extensions.ARB_sample_locations) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "glNamedFramebufferParameteri("
-                  "ARB_framebuffer_no_attachments not implemented)");
+                  "neither ARB_framebuffer_no_attachments nor "
+                  "ARB_sample_locations is available)");
       return;
    }
 
-   fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
-                                     "glNamedFramebufferParameteri");
+   if (framebuffer) {
+      fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
+                                        "glNamedFramebufferParameteri");
+   } else {
+      fb = ctx->WinSysDrawBuffer;
+   }
 
    if (fb) {
       framebuffer_parameteri(ctx, fb, pname, param,
@@ -4261,16 +4325,16 @@ _mesa_GetNamedFramebufferParameteriv(GLuint framebuffer, GLenum pname,
    if (!ctx->Extensions.ARB_framebuffer_no_attachments) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "glNamedFramebufferParameteriv("
-                  "ARB_framebuffer_no_attachments not implemented)");
+                  "neither ARB_framebuffer_no_attachments nor ARB_sample_locations"
+                  " is available)");
       return;
    }
 
-   if (framebuffer) {
+   if (framebuffer)
       fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
                                         "glGetNamedFramebufferParameteriv");
-   } else {
+   else
       fb = ctx->WinSysDrawBuffer;
-   }
 
    if (fb) {
       get_framebuffer_parameteriv(ctx, fb, pname, param,
@@ -4605,3 +4669,139 @@ invalid_enum:
                "glDiscardFramebufferEXT(attachment %s)",
               _mesa_enum_to_string(attachments[i]));
 }
+
+static void
+sample_locations(struct gl_context *ctx, struct gl_framebuffer *fb,
+                 GLuint start, GLsizei count, const GLfloat *v, bool no_error,
+                 const char *name)
+{
+   GLsizei i;
+
+   if (!no_error) {
+      if (!ctx->Extensions.ARB_sample_locations) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "%s not supported "
+                     "(ARB_sample_locations not available)", name);
+         return;
+      }
+
+      if (start + count > MAX_SAMPLE_LOCATION_TABLE_SIZE) {
+         _mesa_error(ctx, GL_INVALID_VALUE,
+                     "%s(start+size > sample location table size)", name);
+         return;
+      }
+   }
+
+   if (!fb->SampleLocationTable) {
+      size_t size = MAX_SAMPLE_LOCATION_TABLE_SIZE * 2 * sizeof(GLfloat);
+      fb->SampleLocationTable = malloc(size);
+      if (!fb->SampleLocationTable)
+         _mesa_error(ctx, GL_OUT_OF_MEMORY,
+                     "Cannot allocate sample location table");
+      for (i = 0; i < MAX_SAMPLE_LOCATION_TABLE_SIZE * 2; i++)
+         fb->SampleLocationTable[i] = 0.5f;
+   }
+
+   for (i = 0; i < count * 2; i++) {
+      /* The ARB_sample_locations spec says:
+       *
+       *    Sample locations outside of [0,1] result in undefined
+       *    behavior.
+       *
+       * To simplify driver implementations, we choose to clamp to
+       * [0,1] and change NaN into 0.5.
+       */
+      if (isnan(v[i]) || v[i] < 0.0f || v[i] > 1.0f) {
+         static GLuint msg_id = 0;
+         static const char* msg = "Invalid sample location specified";
+         _mesa_debug_get_id(&msg_id);
+
+         _mesa_log_msg(ctx, MESA_DEBUG_SOURCE_API, MESA_DEBUG_TYPE_UNDEFINED,
+                       msg_id, MESA_DEBUG_SEVERITY_HIGH, strlen(msg), msg);
+      }
+
+      if (isnan(v[i]))
+         fb->SampleLocationTable[start * 2 + i] = 0.5f;
+      else
+         fb->SampleLocationTable[start * 2 + i] = CLAMP(v[i], 0.0f, 1.0f);
+   }
+
+   if (fb == ctx->DrawBuffer)
+      ctx->NewDriverState |= ctx->DriverFlags.NewSampleLocations;
+}
+
+void GLAPIENTRY
+_mesa_FramebufferSampleLocationsfvARB(GLenum target, GLuint start,
+                                      GLsizei count, const GLfloat *v)
+{
+   struct gl_framebuffer *fb;
+
+   GET_CURRENT_CONTEXT(ctx);
+
+   fb = get_framebuffer_target(ctx, target);
+   if (!fb) {
+      _mesa_error(ctx, GL_INVALID_ENUM,
+                  "glFramebufferSampleLocationsfvARB(target %s)",
+                  _mesa_enum_to_string(target));
+      return;
+   }
+
+   sample_locations(ctx, fb, start, count, v, false,
+                    "glFramebufferSampleLocationsfvARB");
+}
+
+void GLAPIENTRY
+_mesa_NamedFramebufferSampleLocationsfvARB(GLuint framebuffer, GLuint start,
+                                           GLsizei count, const GLfloat *v)
+{
+   struct gl_framebuffer *fb;
+
+   GET_CURRENT_CONTEXT(ctx);
+
+   if (framebuffer) {
+      fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
+                                        "glNamedFramebufferSampleLocationsfvARB");
+      if (!fb)
+         return;
+   }
+   else
+      fb = ctx->WinSysDrawBuffer;
+
+   sample_locations(ctx, fb, start, count, v, false,
+                    "glNamedFramebufferSampleLocationsfvARB");
+}
+
+void GLAPIENTRY
+_mesa_FramebufferSampleLocationsfvARB_no_error(GLenum target, GLuint start,
+                                               GLsizei count, const GLfloat *v)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   sample_locations(ctx, get_framebuffer_target(ctx, target), start,
+                    count, v, true, "glFramebufferSampleLocationsfvARB");
+}
+
+void GLAPIENTRY
+_mesa_NamedFramebufferSampleLocationsfvARB_no_error(GLuint framebuffer,
+                                                    GLuint start, GLsizei count,
+                                                    const GLfloat *v)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   sample_locations(ctx, _mesa_lookup_framebuffer(ctx, framebuffer), start,
+                    count, v, true, "glNamedFramebufferSampleLocationsfvARB");
+}
+
+void GLAPIENTRY
+_mesa_EvaluateDepthValuesARB(void)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   if (!ctx->Extensions.ARB_sample_locations) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "EvaluateDepthValuesARB not supported (neither "
+                  "ARB_sample_locations nor NV_sample_locations is available)");
+      return;
+   }
+
+   if (ctx->Driver.EvaluateDepthValues)
+      ctx->Driver.EvaluateDepthValues(ctx);
+}
diff --git a/src/mesa/main/fbobject.h b/src/mesa/main/fbobject.h
index 31d743d3fb..5ba62d6cb1 100644
--- a/src/mesa/main/fbobject.h
+++ b/src/mesa/main/fbobject.h
@@ -355,4 +355,24 @@ _mesa_FramebufferParameteri(GLenum target, GLenum pname, GLint param);
 extern void GLAPIENTRY
 _mesa_GetFramebufferParameteriv(GLenum target, GLenum pname, GLint *params);
 
+extern void GLAPIENTRY
+_mesa_FramebufferSampleLocationsfvARB(GLenum target, GLuint start,
+                                      GLsizei count, const GLfloat *v);
+
+extern void GLAPIENTRY
+_mesa_NamedFramebufferSampleLocationsfvARB(GLuint framebuffer, GLuint start,
+                                           GLsizei count, const GLfloat *v);
+
+extern void GLAPIENTRY
+_mesa_FramebufferSampleLocationsfvARB_no_error(GLenum target, GLuint start,
+                                               GLsizei count, const GLfloat *v);
+
+extern void GLAPIENTRY
+_mesa_NamedFramebufferSampleLocationsfvARB_no_error(GLuint framebuffer,
+                                                    GLuint start, GLsizei count,
+                                                    const GLfloat *v);
+
+extern void GLAPIENTRY
+_mesa_EvaluateDepthValuesARB(void);
+
 #endif /* FBOBJECT_H */
diff --git a/src/mesa/main/framebuffer.c b/src/mesa/main/framebuffer.c
index 8e751b453b..3ec8b91eaa 100644
--- a/src/mesa/main/framebuffer.c
+++ b/src/mesa/main/framebuffer.c
@@ -160,6 +160,10 @@ _mesa_initialize_window_framebuffer(struct gl_framebuffer *fb,
    fb->_HasSNormOrFloatColorBuffer = visual->floatMode;
    fb->_HasAttachments = true;
 
+   fb->SampleLocationTable = NULL;
+   fb->ProgrammableSampleLocations = 0;
+   fb->SampleLocationPixelGrid = 0;
+
    compute_depth_max(fb);
 }
 
@@ -183,6 +187,9 @@ _mesa_initialize_user_framebuffer(struct gl_framebuffer *fb, GLuint name)
    fb->_ColorDrawBufferIndexes[0] = BUFFER_COLOR0;
    fb->ColorReadBuffer = GL_COLOR_ATTACHMENT0_EXT;
    fb->_ColorReadBufferIndex = BUFFER_COLOR0;
+   fb->SampleLocationTable = NULL;
+   fb->ProgrammableSampleLocations = 0;
+   fb->SampleLocationPixelGrid = 0;
    fb->Delete = _mesa_destroy_framebuffer;
    simple_mtx_init(&fb->Mutex, mtx_plain);
 }
@@ -227,6 +234,9 @@ _mesa_free_framebuffer_data(struct gl_framebuffer *fb)
       assert(!att->Texture);
       att->Type = GL_NONE;
    }
+
+   free(fb->SampleLocationTable);
+   fb->SampleLocationTable = NULL;
 }
 
 
diff --git a/src/mesa/main/get.c b/src/mesa/main/get.c
index 0bf5c1ff0c..772ca00da1 100644
--- a/src/mesa/main/get.c
+++ b/src/mesa/main/get.c
@@ -192,6 +192,7 @@ union value {
    GLenum value_enum;
    GLubyte value_ubyte;
    GLshort value_short;
+   GLuint value_uint;
 
    /* Sigh, see GL_COMPRESSED_TEXTURE_FORMATS_ARB handling */
    struct {
@@ -516,6 +517,7 @@ EXTRA_EXT(ARB_sparse_buffer);
 EXTRA_EXT(NV_conservative_raster);
 EXTRA_EXT(NV_conservative_raster_dilate);
 EXTRA_EXT(NV_conservative_raster_pre_snap_triangles);
+EXTRA_EXT(ARB_sample_locations);
 
 static const int
 extra_ARB_color_buffer_float_or_glcore[] = {
@@ -1197,6 +1199,35 @@ find_custom_value(struct gl_context *ctx, const struct value_desc *d, union valu
          simple_mtx_unlock(&ctx->Shared->Mutex);
       }
       break;
+   /* GL_ARB_sample_locations */
+   case GL_SAMPLE_LOCATION_SUBPIXEL_BITS_ARB:
+   case GL_SAMPLE_LOCATION_PIXEL_GRID_WIDTH_ARB:
+   case GL_SAMPLE_LOCATION_PIXEL_GRID_HEIGHT_ARB:
+      {
+         GLuint bits, width, height;
+
+         if (ctx->NewState & _NEW_BUFFERS)
+            _mesa_update_state(ctx);
+
+         if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE) {
+            v->value_uint = 0;
+            break;
+         }
+
+         ctx->Driver.GetProgrammableSampleCaps(ctx, ctx->DrawBuffer,
+                                               &bits, &width, &height);
+
+         if (d->pname == GL_SAMPLE_LOCATION_PIXEL_GRID_WIDTH_ARB)
+            v->value_uint = width;
+         else if (d->pname == GL_SAMPLE_LOCATION_PIXEL_GRID_HEIGHT_ARB)
+            v->value_uint = height;
+         else
+            v->value_uint = bits;
+      }
+      break;
+   case GL_PROGRAMMABLE_SAMPLE_LOCATION_TABLE_SIZE_ARB:
+      v->value_uint = MAX_SAMPLE_LOCATION_TABLE_SIZE;
+      break;
    }
 }
 
diff --git a/src/mesa/main/get_hash_params.py b/src/mesa/main/get_hash_params.py
index 7e14cf51f5..83136108e9 100644
--- a/src/mesa/main/get_hash_params.py
+++ b/src/mesa/main/get_hash_params.py
@@ -564,6 +564,12 @@ descriptor=[
   # GL_NUM_SHADING_LANGUAGE_VERSIONS
   [ "NUM_SHADING_LANGUAGE_VERSIONS", "LOC_CUSTOM, TYPE_INT, 0, extra_version_43" ],
 
+  # GL_ARB_sample_locations
+  [ "SAMPLE_LOCATION_SUBPIXEL_BITS_ARB", "LOC_CUSTOM, TYPE_UINT, 0, extra_ARB_sample_locations" ],
+  [ "SAMPLE_LOCATION_PIXEL_GRID_WIDTH_ARB", "LOC_CUSTOM, TYPE_UINT, 0, extra_ARB_sample_locations" ],
+  [ "SAMPLE_LOCATION_PIXEL_GRID_HEIGHT_ARB", "LOC_CUSTOM, TYPE_UINT, 0, extra_ARB_sample_locations" ],
+  [ "PROGRAMMABLE_SAMPLE_LOCATION_TABLE_SIZE_ARB", "LOC_CUSTOM, TYPE_UINT, 0, extra_ARB_sample_locations" ],
+
 # GL_ARB_draw_indirect / GLES 3.1
   [ "DRAW_INDIRECT_BUFFER_BINDING", "LOC_CUSTOM, TYPE_INT, 0, extra_ARB_draw_indirect" ],
 
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 93136f5f8a..29beedbe5f 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -3485,6 +3485,11 @@ struct gl_framebuffer
    GLenum16 ColorDrawBuffer[MAX_DRAW_BUFFERS];
    GLenum16 ColorReadBuffer;
 
+   /* GL_ARB_sample_locations */
+   GLfloat *SampleLocationTable; /**< If NULL, no table has been specified */
+   GLboolean ProgrammableSampleLocations;
+   GLboolean SampleLocationPixelGrid;
+
    /** Computed from ColorDraw/ReadBuffer above */
    GLuint _NumColorDrawBuffers;
    gl_buffer_index _ColorDrawBufferIndexes[MAX_DRAW_BUFFERS];
@@ -4095,6 +4100,7 @@ struct gl_extensions
    GLboolean ARB_post_depth_coverage;
    GLboolean ARB_query_buffer_object;
    GLboolean ARB_robust_buffer_access_behavior;
+   GLboolean ARB_sample_locations;
    GLboolean ARB_sample_shading;
    GLboolean ARB_seamless_cube_map;
    GLboolean ARB_shader_atomic_counter_ops;
@@ -4559,6 +4565,9 @@ struct gl_driver_flags
 
    /** Shader constants (uniforms, program parameters, state constants) */
    uint64_t NewShaderConstants[MESA_SHADER_STAGES];
+
+   /** Programmable sample location state for gl_context::DrawBuffer */
+   uint64_t NewSampleLocations;
 };
 
 struct gl_buffer_binding
diff --git a/src/mesa/main/multisample.c b/src/mesa/main/multisample.c
index dfe6a37142..f93a18832d 100644
--- a/src/mesa/main/multisample.c
+++ b/src/mesa/main/multisample.c
@@ -101,6 +101,24 @@ _mesa_GetMultisamplefv(GLenum pname, GLuint index, GLfloat * val)
       return;
    }
 
+   case GL_PROGRAMMABLE_SAMPLE_LOCATION_ARB:
+      if (!ctx->Extensions.ARB_sample_locations) {
+         _mesa_error( ctx, GL_INVALID_ENUM, "glGetMultisamplefv(pname)" );
+         return;
+      }
+
+      if (index >= MAX_SAMPLE_LOCATION_TABLE_SIZE * 2) {
+         _mesa_error( ctx, GL_INVALID_VALUE, "glGetMultisamplefv(index)" );
+         return;
+      }
+
+      if (ctx->DrawBuffer->SampleLocationTable)
+         *val = ctx->DrawBuffer->SampleLocationTable[index];
+      else
+         *val = 0.5f;
+
+      return;
+
    default:
       _mesa_error( ctx, GL_INVALID_ENUM, "glGetMultisamplefv(pname)" );
       return;
diff --git a/src/mesa/main/tests/dispatch_sanity.cpp b/src/mesa/main/tests/dispatch_sanity.cpp
index 096d16a609..96ace53920 100644
--- a/src/mesa/main/tests/dispatch_sanity.cpp
+++ b/src/mesa/main/tests/dispatch_sanity.cpp
@@ -1035,6 +1035,11 @@ const struct function common_desktop_functions_possible[] = {
    /* GL_NV_conservative_raster_pre_snap_triangles */
    { "glConservativeRasterParameteriNV", 10, -1 },
 
+   /* GL_ARB_sample_locations */
+   { "glFramebufferSampleLocationsfvARB", 30, -1 },
+   { "glNamedFramebufferSampleLocationsfvARB", 30, -1 },
+   { "glEvaluateDepthValuesARB", 30, -1 },
+
    { NULL, 0, -1 }
 };
 
@@ -2781,5 +2786,10 @@ const struct function gles31_functions_possible[] = {
    { "glDepthRangeIndexedfOES", 31, -1 },
    { "glGetFloati_vOES", 31, -1 },
 
+   /* GL_ARB_sample_locations */
+   { "glFramebufferSampleLocationsfvARB", 31, -1 },
+   { "glNamedFramebufferSampleLocationsfvARB", 31, -1 },
+   { "glEvaluateDepthValuesARB", 31, -1 },
+
    { NULL, 0, -1 },
  };
-- 
2.14.3



More information about the mesa-dev mailing list