summaryrefslogtreecommitdiffstats
path: root/src/mesa/main/fbobject.c
diff options
context:
space:
mode:
authorRhys Perry <[email protected]>2018-06-14 19:56:28 -0600
committerBrian Paul <[email protected]>2018-06-14 20:09:45 -0600
commit67f40dadaa6666dacd90d1540eaadef20b9d48ba (patch)
treea070a32006510b483b9710ef6acb7356f6c94b01 /src/mesa/main/fbobject.c
parentcd2e673abc436d71e304fd5ad577054197041c7f (diff)
mesa: add support for ARB_sample_locations
Signed-off-by: Rhys Perry <[email protected]> Reviewed-by: Brian Paul <[email protected]> (v2) Reviewed-by: Marek Olšák <[email protected]> (v2)
Diffstat (limited to 'src/mesa/main/fbobject.c')
-rw-r--r--src/mesa/main/fbobject.c256
1 files changed, 228 insertions, 28 deletions
diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c
index a63e8b8de52..5d7e5d29847 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);
+}