#include "buffers.h"
#include "context.h"
+#include "debug_output.h"
#include "enums.h"
#include "fbobject.h"
#include "formats.h"
void
_mesa_init_fbobjects(struct gl_context *ctx)
{
- mtx_init(&DummyFramebuffer.Mutex, mtx_plain);
- mtx_init(&DummyRenderbuffer.Mutex, mtx_plain);
- mtx_init(&IncompleteFramebuffer.Mutex, mtx_plain);
+ simple_mtx_init(&DummyFramebuffer.Mutex, mtx_plain);
+ simple_mtx_init(&DummyRenderbuffer.Mutex, mtx_plain);
+ simple_mtx_init(&IncompleteFramebuffer.Mutex, mtx_plain);
DummyFramebuffer.Delete = delete_dummy_framebuffer;
DummyRenderbuffer.Delete = delete_dummy_renderbuffer;
IncompleteFramebuffer.Delete = delete_dummy_framebuffer;
* window-system framebuffer (not user-created framebuffer objects).
*/
static struct gl_renderbuffer_attachment *
-_mesa_get_fb0_attachment(struct gl_context *ctx, struct gl_framebuffer *fb,
- GLenum attachment)
+get_fb0_attachment(struct gl_context *ctx, struct gl_framebuffer *fb,
+ GLenum attachment)
{
assert(_mesa_is_winsys_fbo(fb));
return &fb->Attachment[BUFFER_BACK_LEFT];
return &fb->Attachment[BUFFER_FRONT_LEFT];
case GL_DEPTH:
- return &fb->Attachment[BUFFER_DEPTH];
+ return &fb->Attachment[BUFFER_DEPTH];
case GL_STENCIL:
return &fb->Attachment[BUFFER_STENCIL];
}
return &fb->Attachment[BUFFER_BACK_LEFT];
case GL_BACK_RIGHT:
return &fb->Attachment[BUFFER_BACK_RIGHT];
+ case GL_BACK:
+ /* The ARB_ES3_1_compatibility spec says:
+ *
+ * "Since this command can only query a single framebuffer
+ * attachment, BACK is equivalent to BACK_LEFT."
+ */
+ if (ctx->Extensions.ARB_ES3_1_compatibility)
+ return &fb->Attachment[BUFFER_BACK_LEFT];
+ return NULL;
case GL_AUX0:
if (fb->Visual.numAuxBuffers == 1) {
return &fb->Attachment[BUFFER_AUX0];
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture()");
return;
}
- _mesa_reference_renderbuffer(&att->Renderbuffer, rb);
+ att->Renderbuffer = rb;
/* This can't get called on a texture renderbuffer, so set it to NULL
* for clarity compared to user renderbuffers.
rb->Height = texImage->Height2;
rb->Depth = texImage->Depth2;
rb->NumSamples = texImage->NumSamples;
+ rb->NumStorageSamples = texImage->NumSamples;
rb->TexImage = texImage;
if (driver_RenderTexture_is_safe(att))
{
struct gl_renderbuffer_attachment *att;
- mtx_lock(&fb->Mutex);
+ simple_mtx_lock(&fb->Mutex);
att = get_attachment(ctx, fb, attachment, NULL);
assert(att);
invalidate_framebuffer(fb);
- mtx_unlock(&fb->Mutex);
+ simple_mtx_unlock(&fb->Mutex);
}
/* Reject additional cases for GLES */
switch (internalFormat) {
+ case GL_R8_SNORM:
+ case GL_RG8_SNORM:
case GL_RGBA8_SNORM:
+ return _mesa_has_EXT_render_snorm(ctx);
+ case GL_R16_SNORM:
+ case GL_RG16_SNORM:
+ case GL_RGBA16_SNORM:
+ return _mesa_has_EXT_texture_norm16(ctx) &&
+ _mesa_has_EXT_render_snorm(ctx);
case GL_RGB32F:
case GL_RGB32I:
case GL_RGB32UI:
case GL_RGB8I:
case GL_RGB8UI:
case GL_SRGB8:
+ case GL_RGB10:
case GL_RGB9_E5:
- case GL_RG8_SNORM:
- case GL_R8_SNORM:
return GL_FALSE;
default:
break;
}
- if (format == MESA_FORMAT_B10G10R10A2_UNORM &&
- internalFormat != GL_RGB10_A2) {
+ if (internalFormat != GL_RGB10_A2 &&
+ (format == MESA_FORMAT_B10G10R10A2_UNORM ||
+ format == MESA_FORMAT_B10G10R10X2_UNORM ||
+ format == MESA_FORMAT_R10G10B10A2_UNORM ||
+ format == MESA_FORMAT_R10G10B10X2_UNORM)) {
return GL_FALSE;
}
/* Look for reasons why the attachment might be incomplete */
if (att->Type == GL_TEXTURE) {
const struct gl_texture_object *texObj = att->Texture;
- struct gl_texture_image *texImage;
+ const struct gl_texture_image *texImage;
GLenum baseFormat;
if (!texObj) {
* these textures to be used as a render target, this is done via
* GL_EXT_color_buffer(_half)_float with set of new sized types.
*/
- if (_mesa_is_gles(ctx) && (texImage->TexObject->_IsFloat ||
- texImage->TexObject->_IsHalfFloat)) {
+ if (_mesa_is_gles(ctx) && (texObj->_IsFloat || texObj->_IsHalfFloat)) {
att_incomplete("bad internal format");
att->Complete = GL_FALSE;
return;
GLuint numImages;
GLenum intFormat = GL_NONE; /* color buffers' internal format */
GLuint minWidth = ~0, minHeight = ~0, maxWidth = 0, maxHeight = 0;
- GLint numSamples = -1;
+ GLint numColorSamples = -1;
+ GLint numColorStorageSamples = -1;
+ GLint numDepthSamples = -1;
GLint fixedSampleLocations = -1;
GLint i;
GLuint j;
/* get width, height, format of the renderbuffer/texture
*/
+ unsigned attNumSamples, attNumStorageSamples;
+
if (att->Type == GL_TEXTURE) {
const struct gl_texture_image *texImg = att->Renderbuffer->TexImage;
att_tex_target = att->Texture->Target;
return;
}
- if (numSamples < 0)
- numSamples = texImg->NumSamples;
- else if (numSamples != texImg->NumSamples) {
- fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
- fbo_incomplete(ctx, "inconsistent sample count", -1);
- return;
- }
-
if (fixedSampleLocations < 0)
fixedSampleLocations = texImg->FixedSampleLocations;
else if (fixedSampleLocations != texImg->FixedSampleLocations) {
fbo_incomplete(ctx, "inconsistent fixed sample locations", -1);
return;
}
+
+ attNumSamples = texImg->NumSamples;
+ attNumStorageSamples = texImg->NumSamples;
}
else if (att->Type == GL_RENDERBUFFER_EXT) {
minWidth = MIN2(minWidth, att->Renderbuffer->Width);
attFormat = att->Renderbuffer->Format;
numImages++;
- if (numSamples < 0)
- numSamples = att->Renderbuffer->NumSamples;
- else if (numSamples != att->Renderbuffer->NumSamples) {
- fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
- fbo_incomplete(ctx, "inconsistent sample count", -1);
- return;
- }
-
/* RENDERBUFFER has fixedSampleLocations implicitly true */
if (fixedSampleLocations < 0)
fixedSampleLocations = GL_TRUE;
fbo_incomplete(ctx, "inconsistent fixed sample locations", -1);
return;
}
+
+ attNumSamples = att->Renderbuffer->NumSamples;
+ attNumStorageSamples = att->Renderbuffer->NumStorageSamples;
}
else {
assert(att->Type == GL_NONE);
continue;
}
+ if (i >= 0) {
+ /* Color buffers. */
+ if (numColorSamples < 0) {
+ assert(numColorStorageSamples < 0);
+ numColorSamples = attNumSamples;
+ numColorStorageSamples = attNumStorageSamples;
+ } else if (numColorSamples != attNumSamples ||
+ numColorStorageSamples != attNumStorageSamples) {
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
+ fbo_incomplete(ctx, "inconsistent sample counts", -1);
+ return;
+ }
+ } else {
+ /* Depth/stencil buffers. */
+ if (numDepthSamples < 0) {
+ numDepthSamples = attNumSamples;
+ } else if (numDepthSamples != attNumSamples) {
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
+ fbo_incomplete(ctx, "inconsistent sample counts", -1);
+ return;
+ }
+ }
+
/* Update flags describing color buffer datatypes */
if (i >= 0) {
GLenum type = _mesa_get_format_datatype(attFormat);
*/
}
+ if (ctx->Extensions.AMD_framebuffer_multisample_advanced) {
+ /* See if non-matching sample counts are supported. */
+ if (numColorSamples >= 0 && numDepthSamples >= 0) {
+ bool found = false;
+
+ assert(numColorStorageSamples != -1);
+
+ numColorSamples = MAX2(numColorSamples, 1);
+ numColorStorageSamples = MAX2(numColorStorageSamples, 1);
+ numDepthSamples = MAX2(numDepthSamples, 1);
+
+ if (numColorSamples == 1 && numColorStorageSamples == 1 &&
+ numDepthSamples == 1) {
+ found = true;
+ } else {
+ for (i = 0; i < ctx->Const.NumSupportedMultisampleModes; i++) {
+ GLint *counts =
+ &ctx->Const.SupportedMultisampleModes[i].NumColorSamples;
+
+ if (counts[0] == numColorSamples &&
+ counts[1] == numColorStorageSamples &&
+ counts[2] == numDepthSamples) {
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (!found) {
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
+ fbo_incomplete(ctx, "unsupported sample counts", -1);
+ return;
+ }
+ }
+ } else {
+ /* If the extension is unsupported, all sample counts must be equal. */
+ if (numColorSamples >= 0 &&
+ (numColorSamples != numColorStorageSamples ||
+ (numDepthSamples >= 0 && numColorSamples != numDepthSamples))) {
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
+ fbo_incomplete(ctx, "inconsistent sample counts", -1);
+ return;
+ }
+ }
+
fb->MaxNumLayers = max_layer_count;
if (numImages == 0) {
GLboolean GLAPIENTRY
_mesa_IsRenderbuffer(GLuint renderbuffer)
{
+ struct gl_renderbuffer *rb;
+
GET_CURRENT_CONTEXT(ctx);
+
ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
- if (renderbuffer) {
- struct gl_renderbuffer *rb =
- _mesa_lookup_renderbuffer(ctx, renderbuffer);
- if (rb != NULL && rb != &DummyRenderbuffer)
- return GL_TRUE;
- }
- return GL_FALSE;
+
+ rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
+ return rb != NULL && rb != &DummyRenderbuffer;
}
static void
-bind_renderbuffer(GLenum target, GLuint renderbuffer, bool allow_user_names)
+bind_renderbuffer(GLenum target, GLuint renderbuffer)
{
struct gl_renderbuffer *newRb;
GET_CURRENT_CONTEXT(ctx);
/* ID was reserved, but no real renderbuffer object made yet */
newRb = NULL;
}
- else if (!newRb && !allow_user_names) {
+ else if (!newRb && ctx->API == API_OPENGL_CORE) {
/* All RB IDs must be Gen'd */
- _mesa_error(ctx, GL_INVALID_OPERATION, "glBindRenderbuffer(buffer)");
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBindRenderbuffer(non-gen name)");
return;
}
void GLAPIENTRY
_mesa_BindRenderbuffer(GLenum target, GLuint renderbuffer)
{
- GET_CURRENT_CONTEXT(ctx);
-
/* OpenGL ES glBindRenderbuffer and glBindRenderbufferOES use this same
* entry point, but they allow the use of user-generated names.
*/
- bind_renderbuffer(target, renderbuffer, _mesa_is_gles(ctx));
+ bind_renderbuffer(target, renderbuffer);
}
void GLAPIENTRY
_mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer)
{
- /* This function should not be in the dispatch table for core profile /
- * OpenGL 3.1, so execution should never get here in those cases -- no
- * need for an explicit test.
- */
- bind_renderbuffer(target, renderbuffer, true);
+ bind_renderbuffer(target, 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;
+ case GL_FRAMEBUFFER_FLIP_Y_MESA:
+ if (!ctx->Extensions.MESA_framebuffer_flip_y)
+ goto invalid_pname_enum;
+ cannot_be_winsys_fbo = true;
+ 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)
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;
+ case GL_FRAMEBUFFER_FLIP_Y_MESA:
+ fb->FlipY = 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
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;
}
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");
}
static bool
-_pname_valid_for_default_framebuffer(struct gl_context *ctx,
- GLenum pname)
+validate_get_framebuffer_parameteriv_pname(struct gl_context *ctx,
+ struct gl_framebuffer *fb,
+ GLuint pname, const char *func)
{
- if (!_mesa_is_desktop_gl(ctx))
- return false;
+ bool cannot_be_winsys_fbo = true;
switch (pname) {
+ case GL_FRAMEBUFFER_DEFAULT_LAYERS:
+ /*
+ * According to the OpenGL ES 3.1 specification section 9.2.3, the
+ * GL_FRAMEBUFFER_LAYERS parameter name is not supported.
+ */
+ if (_mesa_is_gles31(ctx) && !ctx->Extensions.OES_geometry_shader) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
+ return false;
+ }
+ break;
+ case GL_FRAMEBUFFER_DEFAULT_WIDTH:
+ case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
+ case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
+ case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
+ break;
case GL_DOUBLEBUFFER:
case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
case GL_IMPLEMENTATION_COLOR_READ_TYPE:
case GL_SAMPLES:
case GL_SAMPLE_BUFFERS:
case GL_STEREO:
- return true;
+ /* From OpenGL 4.5 spec, section 9.2.3 "Framebuffer Object Queries:
+ *
+ * "An INVALID_OPERATION error is generated by GetFramebufferParameteriv
+ * if the default framebuffer is bound to target and pname is not one
+ * of the accepted values from table 23.73, other than
+ * SAMPLE_POSITION."
+ *
+ * For OpenGL ES, using default framebuffer raises INVALID_OPERATION
+ * for any pname.
+ */
+ 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;
+ 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;
+ }
+
+ 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 false;
}
+
+ return true;
+
+invalid_pname_enum:
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
+ return false;
}
static void
get_framebuffer_parameteriv(struct gl_context *ctx, struct gl_framebuffer *fb,
GLenum pname, GLint *params, const char *func)
{
- /* From OpenGL 4.5 spec, section 9.2.3 "Framebuffer Object Queries:
- *
- * "An INVALID_OPERATION error is generated by GetFramebufferParameteriv
- * if the default framebuffer is bound to target and pname is not one
- * of the accepted values from table 23.73, other than
- * SAMPLE_POSITION."
- *
- * For OpenGL ES, using default framebuffer still raises INVALID_OPERATION
- * for any pname.
- */
- if (_mesa_is_winsys_fbo(fb) &&
- !_pname_valid_for_default_framebuffer(ctx, pname)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "%s(invalid pname=0x%x for default framebuffer)", func, pname);
+ if (!validate_get_framebuffer_parameteriv_pname(ctx, fb, pname, func))
return;
- }
switch (pname) {
case GL_FRAMEBUFFER_DEFAULT_WIDTH:
*params = fb->DefaultGeometry.Height;
break;
case GL_FRAMEBUFFER_DEFAULT_LAYERS:
- /*
- * According to the OpenGL ES 3.1 specification section 9.2.3, the
- * GL_FRAMEBUFFER_LAYERS parameter name is not supported.
- */
- if (_mesa_is_gles31(ctx) && !ctx->Extensions.OES_geometry_shader) {
- _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
- break;
- }
*params = fb->DefaultGeometry.Layers;
break;
case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
case GL_STEREO:
*params = fb->Visual.stereoMode;
break;
- default:
- _mesa_error(ctx, GL_INVALID_ENUM,
- "%s(pname=0x%x)", func, pname);
+ case GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_ARB:
+ *params = fb->ProgrammableSampleLocations;
+ break;
+ case GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB:
+ *params = fb->SampleLocationPixelGrid;
+ break;
+ case GL_FRAMEBUFFER_FLIP_Y_MESA:
+ *params = fb->FlipY;
+ break;
}
}
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;
}
GLuint first;
GLint i;
- if (n < 0) {
- _mesa_error(ctx, GL_INVALID_VALUE, "%s(n<0)", func);
- return;
- }
-
if (!renderbuffers)
return;
}
+static void
+create_render_buffers_err(struct gl_context *ctx, GLsizei n,
+ GLuint *renderbuffers, bool dsa)
+{
+ const char *func = dsa ? "glCreateRenderbuffers" : "glGenRenderbuffers";
+
+ if (n < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(n<0)", func);
+ return;
+ }
+
+ create_render_buffers(ctx, n, renderbuffers, dsa);
+}
+
+
void GLAPIENTRY
-_mesa_GenRenderbuffers(GLsizei n, GLuint *renderbuffers)
+_mesa_GenRenderbuffers_no_error(GLsizei n, GLuint *renderbuffers)
{
GET_CURRENT_CONTEXT(ctx);
create_render_buffers(ctx, n, renderbuffers, false);
void GLAPIENTRY
-_mesa_CreateRenderbuffers(GLsizei n, GLuint *renderbuffers)
+_mesa_GenRenderbuffers(GLsizei n, GLuint *renderbuffers)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ create_render_buffers_err(ctx, n, renderbuffers, false);
+}
+
+
+void GLAPIENTRY
+_mesa_CreateRenderbuffers_no_error(GLsizei n, GLuint *renderbuffers)
{
GET_CURRENT_CONTEXT(ctx);
create_render_buffers(ctx, n, renderbuffers, true);
}
+void GLAPIENTRY
+_mesa_CreateRenderbuffers(GLsizei n, GLuint *renderbuffers)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ create_render_buffers_err(ctx, n, renderbuffers, true);
+}
+
+
/**
* Given an internal format token for a render buffer, return the
* corresponding base format (one of GL_RGB, GL_RGBA, GL_STENCIL_INDEX,
* \return the base internal format, or 0 if internalFormat is illegal
*/
GLenum
-_mesa_base_fbo_format(struct gl_context *ctx, GLenum internalFormat)
+_mesa_base_fbo_format(const struct gl_context *ctx, GLenum internalFormat)
{
/*
* Notes: some formats such as alpha, luminance, etc. were added
case GL_RGBA:
case GL_RGBA2:
case GL_RGBA12:
- case GL_RGBA16:
return _mesa_is_desktop_gl(ctx) ? GL_RGBA : 0;
+ case GL_RGBA16:
+ return _mesa_is_desktop_gl(ctx) || _mesa_has_EXT_texture_norm16(ctx)
+ ? GL_RGBA : 0;
case GL_RGB10_A2:
case GL_SRGB8_ALPHA8_EXT:
return _mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx) ? GL_RGBA : 0;
ctx->Extensions.ARB_depth_buffer_float)
? GL_DEPTH_STENCIL : 0;
case GL_RED:
+ return _mesa_has_ARB_texture_rg(ctx) ? GL_RED : 0;
case GL_R16:
- return _mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_rg
+ return _mesa_has_ARB_texture_rg(ctx) || _mesa_has_EXT_texture_norm16(ctx)
? GL_RED : 0;
case GL_R8:
return ctx->API != API_OPENGLES && ctx->Extensions.ARB_texture_rg
? GL_RED : 0;
case GL_RG:
+ return _mesa_has_ARB_texture_rg(ctx) ? GL_RG : 0;
case GL_RG16:
- return _mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_rg
+ return _mesa_has_ARB_texture_rg(ctx) || _mesa_has_EXT_texture_norm16(ctx)
? GL_RG : 0;
case GL_RG8:
return ctx->API != API_OPENGLES && ctx->Extensions.ARB_texture_rg
? GL_RG : 0;
/* signed normalized texture formats */
- case GL_RED_SNORM:
case GL_R8_SNORM:
+ return _mesa_has_EXT_texture_snorm(ctx) || _mesa_has_EXT_render_snorm(ctx)
+ ? GL_RED : 0;
+ case GL_RED_SNORM:
+ return _mesa_has_EXT_texture_snorm(ctx) ? GL_RED : 0;
case GL_R16_SNORM:
- return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
+ return _mesa_has_EXT_texture_snorm(ctx) ||
+ (_mesa_has_EXT_render_snorm(ctx) &&
+ _mesa_has_EXT_texture_norm16(ctx))
? GL_RED : 0;
- case GL_RG_SNORM:
case GL_RG8_SNORM:
+ return _mesa_has_EXT_texture_snorm(ctx) || _mesa_has_EXT_render_snorm(ctx)
+ ? GL_RG : 0;
+ case GL_RG_SNORM:
+ return _mesa_has_EXT_texture_snorm(ctx) ? GL_RG : 0;
case GL_RG16_SNORM:
- return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
+ return _mesa_has_EXT_texture_snorm(ctx) ||
+ (_mesa_has_EXT_render_snorm(ctx) &&
+ _mesa_has_EXT_texture_norm16(ctx))
? GL_RG : 0;
case GL_RGB_SNORM:
case GL_RGB8_SNORM:
case GL_RGB16_SNORM:
return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
? GL_RGB : 0;
- case GL_RGBA_SNORM:
case GL_RGBA8_SNORM:
+ return _mesa_has_EXT_texture_snorm(ctx) || _mesa_has_EXT_render_snorm(ctx)
+ ? GL_RGBA : 0;
+ case GL_RGBA_SNORM:
+ return _mesa_has_EXT_texture_snorm(ctx) ? GL_RGBA : 0;
case GL_RGBA16_SNORM:
- return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
+ return _mesa_has_EXT_texture_snorm(ctx) ||
+ (_mesa_has_EXT_render_snorm(ctx) &&
+ _mesa_has_EXT_texture_norm16(ctx))
? GL_RGBA : 0;
case GL_ALPHA_SNORM:
case GL_ALPHA8_SNORM:
ctx->Extensions.ARB_texture_float) ||
_mesa_is_gles3(ctx) /* EXT_color_buffer_float */ )
? GL_RGBA : 0;
+ case GL_RGB9_E5:
+ return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_shared_exponent)
+ ? GL_RGB: 0;
case GL_ALPHA16F_ARB:
case GL_ALPHA32F_ARB:
return ctx->API == API_OPENGL_COMPAT &&
void
_mesa_renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
GLenum internalFormat, GLsizei width,
- GLsizei height, GLsizei samples)
+ GLsizei height, GLsizei samples,
+ GLsizei storageSamples)
{
const GLenum baseFormat = _mesa_base_fbo_format(ctx, internalFormat);
if (samples != 0) {
assert(samples > 0);
assert(_mesa_check_sample_count(ctx, GL_RENDERBUFFER,
- internalFormat, samples) == GL_NO_ERROR);
+ internalFormat, samples,
+ storageSamples) == GL_NO_ERROR);
}
FLUSH_VERTICES(ctx, _NEW_BUFFERS);
if (rb->InternalFormat == internalFormat &&
rb->Width == (GLuint) width &&
rb->Height == (GLuint) height &&
- rb->NumSamples == samples) {
+ rb->NumSamples == samples &&
+ rb->NumStorageSamples == storageSamples) {
/* no change in allocation needed */
return;
}
/* These MUST get set by the AllocStorage func */
rb->Format = MESA_FORMAT_NONE;
rb->NumSamples = samples;
+ rb->NumStorageSamples = storageSamples;
/* Now allocate the storage */
assert(rb->AllocStorage);
rb->InternalFormat = GL_NONE;
rb->_BaseFormat = GL_NONE;
rb->NumSamples = 0;
+ rb->NumStorageSamples = 0;
}
/* Invalidate the framebuffers the renderbuffer is attached in. */
static void
renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
GLenum internalFormat, GLsizei width,
- GLsizei height, GLsizei samples, const char *func)
+ GLsizei height, GLsizei samples, GLsizei storageSamples,
+ const char *func)
{
GLenum baseFormat;
GLenum sample_count_error;
if (samples == NO_SAMPLES) {
/* NumSamples == 0 indicates non-multisampling */
samples = 0;
+ storageSamples = 0;
}
else {
/* check the sample count;
* note: driver may choose to use more samples than what's requested
*/
sample_count_error = _mesa_check_sample_count(ctx, GL_RENDERBUFFER,
- internalFormat, samples);
+ internalFormat, samples, storageSamples);
/* Section 2.5 (GL Errors) of OpenGL 3.0 specification, page 16:
*
* "If a negative number is provided where an argument of type sizei or
* sizeiptr is specified, the error INVALID VALUE is generated."
*/
- if (samples < 0) {
+ if (samples < 0 || storageSamples < 0) {
sample_count_error = GL_INVALID_VALUE;
}
if (sample_count_error != GL_NO_ERROR) {
- _mesa_error(ctx, sample_count_error, "%s(samples=%d)", func, samples);
+ _mesa_error(ctx, sample_count_error,
+ "%s(samples=%d, storageSamples=%d)", func, samples,
+ storageSamples);
return;
}
}
- _mesa_renderbuffer_storage(ctx, rb, internalFormat, width, height, samples);
+ _mesa_renderbuffer_storage(ctx, rb, internalFormat, width, height, samples,
+ storageSamples);
}
/**
static void
renderbuffer_storage_named(GLuint renderbuffer, GLenum internalFormat,
GLsizei width, GLsizei height, GLsizei samples,
- const char *func)
+ GLsizei storageSamples, const char *func)
{
GET_CURRENT_CONTEXT(ctx);
return;
}
- renderbuffer_storage(ctx, rb, internalFormat, width, height, samples, func);
+ renderbuffer_storage(ctx, rb, internalFormat, width, height, samples,
+ storageSamples, func);
}
/**
static void
renderbuffer_storage_target(GLenum target, GLenum internalFormat,
GLsizei width, GLsizei height, GLsizei samples,
- const char *func)
+ GLsizei storageSamples, const char *func)
{
GET_CURRENT_CONTEXT(ctx);
}
renderbuffer_storage(ctx, ctx->CurrentRenderbuffer, internalFormat, width,
- height, samples, func);
+ height, samples, storageSamples, func);
}
* a token value here just for error reporting purposes.
*/
renderbuffer_storage_target(target, internalFormat, width, height,
- NO_SAMPLES, "glRenderbufferStorage");
+ NO_SAMPLES, 0, "glRenderbufferStorage");
}
GLsizei width, GLsizei height)
{
renderbuffer_storage_target(target, internalFormat, width, height,
- samples, "glRenderbufferStorageMultisample");
+ samples, samples,
+ "glRenderbufferStorageMultisample");
+}
+
+
+void GLAPIENTRY
+_mesa_RenderbufferStorageMultisampleAdvancedAMD(
+ GLenum target, GLsizei samples, GLsizei storageSamples,
+ GLenum internalFormat, GLsizei width, GLsizei height)
+{
+ renderbuffer_storage_target(target, internalFormat, width, height,
+ samples, storageSamples,
+ "glRenderbufferStorageMultisampleAdvancedAMD");
}
break;
}
- renderbuffer_storage_target(target, internalFormat, width, height, 0,
+ renderbuffer_storage_target(target, internalFormat, width, height, 0, 0,
"glRenderbufferStorageEXT");
}
* a token value here just for error reporting purposes.
*/
renderbuffer_storage_named(renderbuffer, internalformat, width, height,
- NO_SAMPLES, "glNamedRenderbufferStorage");
+ NO_SAMPLES, 0, "glNamedRenderbufferStorage");
}
void GLAPIENTRY
GLsizei width, GLsizei height)
{
renderbuffer_storage_named(renderbuffer, internalformat, width, height,
- samples,
+ samples, samples,
"glNamedRenderbufferStorageMultisample");
}
+void GLAPIENTRY
+_mesa_NamedRenderbufferStorageMultisampleAdvancedAMD(
+ GLuint renderbuffer, GLsizei samples, GLsizei storageSamples,
+ GLenum internalformat, GLsizei width, GLsizei height)
+{
+ renderbuffer_storage_named(renderbuffer, internalformat, width, height,
+ samples, storageSamples,
+ "glNamedRenderbufferStorageMultisampleAdvancedAMD");
+}
+
+
static void
get_render_buffer_parameteriv(struct gl_context *ctx,
struct gl_renderbuffer *rb, GLenum pname,
case GL_RENDERBUFFER_DEPTH_SIZE_EXT:
case GL_RENDERBUFFER_STENCIL_SIZE_EXT:
*params = get_component_bits(pname, rb->_BaseFormat, rb->Format);
- break;
+ return;
case GL_RENDERBUFFER_SAMPLES:
if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_framebuffer_object)
|| _mesa_is_gles3(ctx)) {
*params = rb->NumSamples;
- break;
+ return;
}
- /* fallthrough */
- default:
- _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid pname=%s)", func,
- _mesa_enum_to_string(pname));
- return;
+ break;
+ case GL_RENDERBUFFER_STORAGE_SAMPLES_AMD:
+ if (ctx->Extensions.AMD_framebuffer_multisample_advanced) {
+ *params = rb->NumStorageSamples;
+ return;
+ }
+ break;
}
+
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid pname=%s)", func,
+ _mesa_enum_to_string(pname));
}
static void
-bind_framebuffer(GLenum target, GLuint framebuffer, bool allow_user_names)
+bind_framebuffer(GLenum target, GLuint framebuffer)
{
struct gl_framebuffer *newDrawFb, *newReadFb;
GLboolean bindReadBuf, bindDrawBuf;
/* ID was reserved, but no real framebuffer object made yet */
newDrawFb = NULL;
}
- else if (!newDrawFb && !allow_user_names) {
+ else if (!newDrawFb && ctx->API == API_OPENGL_CORE) {
/* All FBO IDs must be Gen'd */
- _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFramebuffer(buffer)");
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBindFramebuffer(non-gen name)");
return;
}
if (bindDrawBuf) {
FLUSH_VERTICES(ctx, _NEW_BUFFERS);
+ ctx->NewDriverState |= ctx->DriverFlags.NewSampleLocations;
/* check if old framebuffer had any texture attachments */
if (oldDrawFb)
void GLAPIENTRY
_mesa_BindFramebuffer(GLenum target, GLuint framebuffer)
{
- GET_CURRENT_CONTEXT(ctx);
-
/* OpenGL ES glBindFramebuffer and glBindFramebufferOES use this same entry
* point, but they allow the use of user-generated names.
*/
- bind_framebuffer(target, framebuffer, _mesa_is_gles(ctx));
+ bind_framebuffer(target, framebuffer);
}
void GLAPIENTRY
_mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)
{
- /* This function should not be in the dispatch table for core profile /
- * OpenGL 3.1, so execution should never get here in those cases -- no
- * need for an explicit test.
- */
- bind_framebuffer(target, framebuffer, true);
+ bind_framebuffer(target, framebuffer);
}
}
+GLenum GLAPIENTRY
+_mesa_CheckFramebufferStatus_no_error(GLenum target)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ struct gl_framebuffer *fb = get_framebuffer_target(ctx, target);
+ return _mesa_check_framebuffer_status(ctx, fb);
+}
+
+
GLenum GLAPIENTRY
_mesa_CheckFramebufferStatus(GLenum target)
{
}
+static struct gl_texture_object *
+get_texture_for_framebuffer(struct gl_context *ctx, GLuint texture)
+{
+ if (!texture)
+ return NULL;
+
+ return _mesa_lookup_texture(ctx, texture);
+}
+
+
/**
* Common code called by gl*FramebufferTexture*() to retrieve the correct
* texture object pointer.
* \return true if no errors, false if errors
*/
static bool
-get_texture_for_framebuffer(struct gl_context *ctx, GLuint texture,
- bool layered, const char *caller,
- struct gl_texture_object **texObj)
+get_texture_for_framebuffer_err(struct gl_context *ctx, GLuint texture,
+ bool layered, const char *caller,
+ struct gl_texture_object **texObj)
{
*texObj = NULL; /* This will get returned if texture = 0. */
case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
return true;
case GL_TEXTURE_CUBE_MAP:
- /* We don't need to check the extension (GL_ARB_direct_state_access) or
- * GL version (4.5) for GL_TEXTURE_CUBE_MAP because DSA is always
- * enabled in core profile. This can be called from
- * _mesa_FramebufferTextureLayer in compatibility profile (OpenGL 3.0),
- * so we do have to check the profile.
+ /* GL_TEXTURE_CUBE_MAP is only allowed by OpenGL 4.5 here, which
+ * includes the DSA API.
+ *
+ * Because DSA is only enabled for GL 3.1+ and this can be called
+ * from _mesa_FramebufferTextureLayer in compatibility profile,
+ * we need to check the version.
*/
- return ctx->API == API_OPENGL_CORE;
+ return _mesa_is_desktop_gl(ctx) && ctx->Version >= 31;
}
_mesa_error(ctx, GL_INVALID_OPERATION,
* and layer is negative."
*/
if (layer < 0) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "%s(layer %u < 0)", caller, layer);
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(layer %d < 0)", caller, layer);
return false;
}
* \return true if no errors, false if errors
*/
static bool
-check_level(struct gl_context *ctx, GLenum target, GLint level,
- const char *caller)
+check_level(struct gl_context *ctx, struct gl_texture_object *texObj,
+ GLenum target, GLint level, const char *caller)
{
- if ((level < 0) ||
- (level >= _mesa_max_texture_levels(ctx, target))) {
+ /* Section 9.2.8 of the OpenGL 4.6 specification says:
+ *
+ * "If texture refers to an immutable-format texture, level must be
+ * greater than or equal to zero and smaller than the value of
+ * TEXTURE_VIEW_NUM_LEVELS for texture."
+ */
+ const int max_levels = texObj->Immutable ? texObj->ImmutableLevels :
+ _mesa_max_texture_levels(ctx, target);
+
+ if (level < 0 || level >= max_levels) {
_mesa_error(ctx, GL_INVALID_VALUE,
"%s(invalid level %d)", caller, level);
return false;
}
-void
-_mesa_framebuffer_texture(struct gl_context *ctx, struct gl_framebuffer *fb,
- GLenum attachment,
- struct gl_texture_object *texObj, GLenum textarget,
- GLint level, GLuint layer, GLboolean layered,
- const char *caller)
+struct gl_renderbuffer_attachment *
+_mesa_get_and_validate_attachment(struct gl_context *ctx,
+ struct gl_framebuffer *fb,
+ GLenum attachment, const char *caller)
{
- struct gl_renderbuffer_attachment *att;
- bool is_color_attachment;
-
/* The window-system framebuffer object is immutable */
if (_mesa_is_winsys_fbo(fb)) {
_mesa_error(ctx, GL_INVALID_OPERATION, "%s(window-system framebuffer)",
caller);
- return;
+ return NULL;
}
/* Not a hash lookup, so we can afford to get the attachment here. */
- att = get_attachment(ctx, fb, attachment, &is_color_attachment);
+ bool is_color_attachment;
+ struct gl_renderbuffer_attachment *att =
+ get_attachment(ctx, fb, attachment, &is_color_attachment);
if (att == NULL) {
if (is_color_attachment) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"%s(invalid attachment %s)", caller,
_mesa_enum_to_string(attachment));
}
- return;
+ return NULL;
}
+ return att;
+}
+
+
+void
+_mesa_framebuffer_texture(struct gl_context *ctx, struct gl_framebuffer *fb,
+ GLenum attachment,
+ struct gl_renderbuffer_attachment *att,
+ struct gl_texture_object *texObj, GLenum textarget,
+ GLint level, GLuint layer, GLboolean layered)
+{
FLUSH_VERTICES(ctx, _NEW_BUFFERS);
- mtx_lock(&fb->Mutex);
+ simple_mtx_lock(&fb->Mutex);
if (texObj) {
if (attachment == GL_DEPTH_ATTACHMENT &&
texObj == fb->Attachment[BUFFER_STENCIL].Texture &&
invalidate_framebuffer(fb);
- mtx_unlock(&fb->Mutex);
+ simple_mtx_unlock(&fb->Mutex);
+}
+
+
+static void
+framebuffer_texture_with_dims_no_error(GLenum target, GLenum attachment,
+ GLenum textarget, GLuint texture,
+ GLint level, GLint layer)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ /* Get the framebuffer object */
+ struct gl_framebuffer *fb = get_framebuffer_target(ctx, target);
+
+ /* Get the texture object */
+ struct gl_texture_object *texObj =
+ get_texture_for_framebuffer(ctx, texture);
+
+ struct gl_renderbuffer_attachment *att =
+ get_attachment(ctx, fb, attachment, NULL);
+
+ _mesa_framebuffer_texture(ctx, fb, attachment, att, texObj, textarget,
+ level, layer, GL_FALSE);
}
}
/* Get the texture object */
- if (!get_texture_for_framebuffer(ctx, texture, false, caller, &texObj))
+ if (!get_texture_for_framebuffer_err(ctx, texture, false, caller, &texObj))
return;
if (texObj) {
if ((dims == 3) && !check_layer(ctx, texObj->Target, layer, caller))
return;
- if (!check_level(ctx, textarget, level, caller))
+ if (!check_level(ctx, texObj, textarget, level, caller))
return;
}
- _mesa_framebuffer_texture(ctx, fb, attachment, texObj, textarget, level,
- layer, GL_FALSE, caller);
+ struct gl_renderbuffer_attachment *att =
+ _mesa_get_and_validate_attachment(ctx, fb, attachment, caller);
+ if (!att)
+ return;
+
+ _mesa_framebuffer_texture(ctx, fb, attachment, att, texObj, textarget,
+ level, layer, GL_FALSE);
+}
+
+
+void GLAPIENTRY
+_mesa_FramebufferTexture1D_no_error(GLenum target, GLenum attachment,
+ GLenum textarget, GLuint texture,
+ GLint level)
+{
+ framebuffer_texture_with_dims_no_error(target, attachment, textarget,
+ texture, level, 0);
}
}
+void GLAPIENTRY
+_mesa_FramebufferTexture2D_no_error(GLenum target, GLenum attachment,
+ GLenum textarget, GLuint texture,
+ GLint level)
+{
+ framebuffer_texture_with_dims_no_error(target, attachment, textarget,
+ texture, level, 0);
+}
+
+
void GLAPIENTRY
_mesa_FramebufferTexture2D(GLenum target, GLenum attachment,
GLenum textarget, GLuint texture, GLint level)
}
+void GLAPIENTRY
+_mesa_FramebufferTexture3D_no_error(GLenum target, GLenum attachment,
+ GLenum textarget, GLuint texture,
+ GLint level, GLint layer)
+{
+ framebuffer_texture_with_dims_no_error(target, attachment, textarget,
+ texture, level, layer);
+}
+
+
void GLAPIENTRY
_mesa_FramebufferTexture3D(GLenum target, GLenum attachment,
GLenum textarget, GLuint texture,
}
-void GLAPIENTRY
-_mesa_FramebufferTextureLayer(GLenum target, GLenum attachment,
- GLuint texture, GLint level, GLint layer)
+static ALWAYS_INLINE void
+frame_buffer_texture(GLuint framebuffer, GLenum target,
+ GLenum attachment, GLuint texture,
+ GLint level, GLint layer, const char *func,
+ bool dsa, bool no_error, bool check_layered)
{
GET_CURRENT_CONTEXT(ctx);
- struct gl_framebuffer *fb;
- struct gl_texture_object *texObj;
- GLenum textarget = 0;
+ GLboolean layered = GL_FALSE;
- const char *func = "glFramebufferTextureLayer";
+ if (!no_error && check_layered) {
+ if (!_mesa_has_geometry_shaders(ctx)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "unsupported function (%s) called", func);
+ return;
+ }
+ }
/* Get the framebuffer object */
- fb = get_framebuffer_target(ctx, target);
- if (!fb) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glFramebufferTextureLayer(invalid target %s)",
- _mesa_enum_to_string(target));
- return;
+ struct gl_framebuffer *fb;
+ if (no_error) {
+ if (dsa) {
+ fb = _mesa_lookup_framebuffer(ctx, framebuffer);
+ } else {
+ fb = get_framebuffer_target(ctx, target);
+ }
+ } else {
+ if (dsa) {
+ fb = _mesa_lookup_framebuffer_err(ctx, framebuffer, func);
+ if (!fb)
+ return;
+ } else {
+ fb = get_framebuffer_target(ctx, target);
+ if (!fb) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)",
+ func, _mesa_enum_to_string(target));
+ return;
+ }
+ }
}
- /* Get the texture object */
- if (!get_texture_for_framebuffer(ctx, texture, false, func, &texObj))
- return;
-
- if (texObj) {
- if (!check_texture_target(ctx, texObj->Target, func))
+ /* Get the texture object and framebuffer attachment*/
+ struct gl_renderbuffer_attachment *att;
+ struct gl_texture_object *texObj;
+ if (no_error) {
+ texObj = get_texture_for_framebuffer(ctx, texture);
+ att = get_attachment(ctx, fb, attachment, NULL);
+ } else {
+ if (!get_texture_for_framebuffer_err(ctx, texture, check_layered, func,
+ &texObj))
return;
- if (!check_layer(ctx, texObj->Target, layer, func))
+ att = _mesa_get_and_validate_attachment(ctx, fb, attachment, func);
+ if (!att)
return;
+ }
- if (!check_level(ctx, texObj->Target, level, func))
- return;
+ GLenum textarget = 0;
+ if (texObj) {
+ if (check_layered) {
+ /* We do this regardless of no_error because this sets layered */
+ if (!check_layered_texture_target(ctx, texObj->Target, func,
+ &layered))
+ return;
+ }
+
+ if (!no_error) {
+ if (!check_layered) {
+ if (!check_texture_target(ctx, texObj->Target, func))
+ return;
- if (texObj->Target == GL_TEXTURE_CUBE_MAP) {
+ if (!check_layer(ctx, texObj->Target, layer, func))
+ return;
+ }
+
+ if (!check_level(ctx, texObj, texObj->Target, level, func))
+ return;
+ }
+
+ if (!check_layered && texObj->Target == GL_TEXTURE_CUBE_MAP) {
assert(layer >= 0 && layer < 6);
textarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer;
layer = 0;
}
}
- _mesa_framebuffer_texture(ctx, fb, attachment, texObj, textarget, level,
- layer, GL_FALSE, func);
+ _mesa_framebuffer_texture(ctx, fb, attachment, att, texObj, textarget,
+ level, layer, layered);
}
-
void GLAPIENTRY
-_mesa_NamedFramebufferTextureLayer(GLuint framebuffer, GLenum attachment,
- GLuint texture, GLint level, GLint layer)
+_mesa_FramebufferTextureLayer_no_error(GLenum target, GLenum attachment,
+ GLuint texture, GLint level,
+ GLint layer)
{
- GET_CURRENT_CONTEXT(ctx);
- struct gl_framebuffer *fb;
- struct gl_texture_object *texObj;
- GLenum textarget = 0;
+ frame_buffer_texture(0, target, attachment, texture, level, layer,
+ "glFramebufferTextureLayer", false, true, false);
+}
- const char *func = "glNamedFramebufferTextureLayer";
- /* Get the framebuffer object */
- fb = _mesa_lookup_framebuffer_err(ctx, framebuffer, func);
- if (!fb)
- return;
+void GLAPIENTRY
+_mesa_FramebufferTextureLayer(GLenum target, GLenum attachment,
+ GLuint texture, GLint level, GLint layer)
+{
+ frame_buffer_texture(0, target, attachment, texture, level, layer,
+ "glFramebufferTextureLayer", false, false, false);
+}
- /* Get the texture object */
- if (!get_texture_for_framebuffer(ctx, texture, false, func, &texObj))
- return;
- if (texObj) {
- if (!check_texture_target(ctx, texObj->Target, func))
- return;
+void GLAPIENTRY
+_mesa_NamedFramebufferTextureLayer_no_error(GLuint framebuffer,
+ GLenum attachment,
+ GLuint texture, GLint level,
+ GLint layer)
+{
+ frame_buffer_texture(framebuffer, 0, attachment, texture, level, layer,
+ "glNamedFramebufferTextureLayer", true, true, false);
+}
- if (!check_layer(ctx, texObj->Target, layer, func))
- return;
- if (!check_level(ctx, texObj->Target, level, func))
- return;
+void GLAPIENTRY
+_mesa_NamedFramebufferTextureLayer(GLuint framebuffer, GLenum attachment,
+ GLuint texture, GLint level, GLint layer)
+{
+ frame_buffer_texture(framebuffer, 0, attachment, texture, level, layer,
+ "glNamedFramebufferTextureLayer", true, false, false);
+}
- if (texObj->Target == GL_TEXTURE_CUBE_MAP) {
- assert(layer >= 0 && layer < 6);
- textarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer;
- layer = 0;
- }
- }
- _mesa_framebuffer_texture(ctx, fb, attachment, texObj, textarget, level,
- layer, GL_FALSE, func);
+void GLAPIENTRY
+_mesa_FramebufferTexture_no_error(GLenum target, GLenum attachment,
+ GLuint texture, GLint level)
+{
+ frame_buffer_texture(0, target, attachment, texture, level, 0,
+ "glFramebufferTexture", false, true, true);
}
_mesa_FramebufferTexture(GLenum target, GLenum attachment,
GLuint texture, GLint level)
{
- GET_CURRENT_CONTEXT(ctx);
- struct gl_framebuffer *fb;
- struct gl_texture_object *texObj;
- GLboolean layered = GL_FALSE;
-
- const char *func = "FramebufferTexture";
-
- if (!_mesa_has_geometry_shaders(ctx)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "unsupported function (glFramebufferTexture) called");
- return;
- }
-
- /* Get the framebuffer object */
- fb = get_framebuffer_target(ctx, target);
- if (!fb) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glFramebufferTexture(invalid target %s)",
- _mesa_enum_to_string(target));
- return;
- }
-
- /* Get the texture object */
- if (!get_texture_for_framebuffer(ctx, texture, true, func, &texObj))
- return;
-
- if (texObj) {
- if (!check_layered_texture_target(ctx, texObj->Target, func, &layered))
- return;
-
- if (!check_level(ctx, texObj->Target, level, func))
- return;
- }
+ frame_buffer_texture(0, target, attachment, texture, level, 0,
+ "glFramebufferTexture", false, false, true);
+}
- _mesa_framebuffer_texture(ctx, fb, attachment, texObj, 0, level,
- 0, layered, func);
+void GLAPIENTRY
+_mesa_NamedFramebufferTexture_no_error(GLuint framebuffer, GLenum attachment,
+ GLuint texture, GLint level)
+{
+ frame_buffer_texture(framebuffer, 0, attachment, texture, level, 0,
+ "glNamedFramebufferTexture", true, true, true);
}
_mesa_NamedFramebufferTexture(GLuint framebuffer, GLenum attachment,
GLuint texture, GLint level)
{
- GET_CURRENT_CONTEXT(ctx);
- struct gl_framebuffer *fb;
- struct gl_texture_object *texObj;
- GLboolean layered = GL_FALSE;
-
- const char *func = "glNamedFramebufferTexture";
-
- if (!_mesa_has_geometry_shaders(ctx)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "unsupported function (glNamedFramebufferTexture) called");
- return;
- }
-
- /* Get the framebuffer object */
- fb = _mesa_lookup_framebuffer_err(ctx, framebuffer, func);
- if (!fb)
- return;
-
- /* Get the texture object */
- if (!get_texture_for_framebuffer(ctx, texture, true, func, &texObj))
- return;
-
- if (texObj) {
- if (!check_layered_texture_target(ctx, texObj->Target, func,
- &layered))
- return;
-
- if (!check_level(ctx, texObj->Target, level, func))
- return;
- }
-
- _mesa_framebuffer_texture(ctx, fb, attachment, texObj, 0, level,
- 0, layered, func);
+ frame_buffer_texture(framebuffer, 0, attachment, texture, level, 0,
+ "glNamedFramebufferTexture", true, false, true);
}
_mesa_update_framebuffer_visual(ctx, fb);
}
-static void
-framebuffer_renderbuffer(struct gl_context *ctx,
- struct gl_framebuffer *fb,
- GLenum attachment,
- struct gl_renderbuffer *rb,
- const char *func)
+static ALWAYS_INLINE void
+framebuffer_renderbuffer(struct gl_context *ctx, struct gl_framebuffer *fb,
+ GLenum attachment, GLenum renderbuffertarget,
+ GLuint renderbuffer, const char *func, bool no_error)
{
struct gl_renderbuffer_attachment *att;
+ struct gl_renderbuffer *rb;
bool is_color_attachment;
- if (_mesa_is_winsys_fbo(fb)) {
- /* Can't attach new renderbuffers to a window system framebuffer */
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "%s(window-system framebuffer)", func);
+ if (!no_error && renderbuffertarget != GL_RENDERBUFFER) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "%s(renderbuffertarget is not GL_RENDERBUFFER)", func);
return;
}
- att = get_attachment(ctx, fb, attachment, &is_color_attachment);
- if (att == NULL) {
- /*
- * From OpenGL 4.5 spec, section 9.2.7 "Attaching Renderbuffer Images to
- * a Framebuffer":
- *
- * "An INVALID_OPERATION error is generated if attachment is COLOR_-
- * ATTACHMENTm where m is greater than or equal to the value of
- * MAX_COLOR_- ATTACHMENTS ."
- *
- * If we are at this point, is because the attachment is not valid, so
- * if is_color_attachment is true, is because of the previous reason.
- */
- if (is_color_attachment) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "%s(invalid color attachment %s)", func,
- _mesa_enum_to_string(attachment));
+ if (renderbuffer) {
+ if (!no_error) {
+ rb = _mesa_lookup_renderbuffer_err(ctx, renderbuffer, func);
+ if (!rb)
+ return;
} else {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "%s(invalid attachment %s)", func,
- _mesa_enum_to_string(attachment));
+ rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
}
-
- return;
+ } else {
+ /* remove renderbuffer attachment */
+ rb = NULL;
}
- if (attachment == GL_DEPTH_STENCIL_ATTACHMENT &&
- rb && rb->Format != MESA_FORMAT_NONE) {
- /* make sure the renderbuffer is a depth/stencil format */
- const GLenum baseFormat = _mesa_get_format_base_format(rb->Format);
- if (baseFormat != GL_DEPTH_STENCIL) {
+ if (!no_error) {
+ if (_mesa_is_winsys_fbo(fb)) {
+ /* Can't attach new renderbuffers to a window system framebuffer */
_mesa_error(ctx, GL_INVALID_OPERATION,
- "%s(renderbuffer is not DEPTH_STENCIL format)", func);
+ "%s(window-system framebuffer)", func);
return;
}
+
+ att = get_attachment(ctx, fb, attachment, &is_color_attachment);
+ if (att == NULL) {
+ /*
+ * From OpenGL 4.5 spec, section 9.2.7 "Attaching Renderbuffer Images
+ * to a Framebuffer":
+ *
+ * "An INVALID_OPERATION error is generated if attachment is
+ * COLOR_- ATTACHMENTm where m is greater than or equal to the
+ * value of MAX_COLOR_- ATTACHMENTS ."
+ *
+ * If we are at this point, is because the attachment is not valid, so
+ * if is_color_attachment is true, is because of the previous reason.
+ */
+ if (is_color_attachment) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(invalid color attachment %s)", func,
+ _mesa_enum_to_string(attachment));
+ } else {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "%s(invalid attachment %s)", func,
+ _mesa_enum_to_string(attachment));
+ }
+
+ return;
+ }
+
+ if (attachment == GL_DEPTH_STENCIL_ATTACHMENT &&
+ rb && rb->Format != MESA_FORMAT_NONE) {
+ /* make sure the renderbuffer is a depth/stencil format */
+ const GLenum baseFormat = _mesa_get_format_base_format(rb->Format);
+ if (baseFormat != GL_DEPTH_STENCIL) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(renderbuffer is not DEPTH_STENCIL format)", func);
+ return;
+ }
+ }
}
_mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
}
+static void
+framebuffer_renderbuffer_error(struct gl_context *ctx,
+ struct gl_framebuffer *fb, GLenum attachment,
+ GLenum renderbuffertarget,
+ GLuint renderbuffer, const char *func)
+{
+ framebuffer_renderbuffer(ctx, fb, attachment, renderbuffertarget,
+ renderbuffer, func, false);
+}
+
+static void
+framebuffer_renderbuffer_no_error(struct gl_context *ctx,
+ struct gl_framebuffer *fb, GLenum attachment,
+ GLenum renderbuffertarget,
+ GLuint renderbuffer, const char *func)
+{
+ framebuffer_renderbuffer(ctx, fb, attachment, renderbuffertarget,
+ renderbuffer, func, true);
+}
+
+void GLAPIENTRY
+_mesa_FramebufferRenderbuffer_no_error(GLenum target, GLenum attachment,
+ GLenum renderbuffertarget,
+ GLuint renderbuffer)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ struct gl_framebuffer *fb = get_framebuffer_target(ctx, target);
+ framebuffer_renderbuffer_no_error(ctx, fb, attachment, renderbuffertarget,
+ renderbuffer, "glFramebufferRenderbuffer");
+}
+
void GLAPIENTRY
_mesa_FramebufferRenderbuffer(GLenum target, GLenum attachment,
GLenum renderbuffertarget,
GLuint renderbuffer)
{
struct gl_framebuffer *fb;
- struct gl_renderbuffer *rb;
GET_CURRENT_CONTEXT(ctx);
fb = get_framebuffer_target(ctx, target);
return;
}
- if (renderbuffertarget != GL_RENDERBUFFER) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glFramebufferRenderbuffer(renderbuffertarget is not "
- "GL_RENDERBUFFER)");
- return;
- }
+ framebuffer_renderbuffer_error(ctx, fb, attachment, renderbuffertarget,
+ renderbuffer, "glFramebufferRenderbuffer");
+}
- if (renderbuffer) {
- rb = _mesa_lookup_renderbuffer_err(ctx, renderbuffer,
- "glFramebufferRenderbuffer");
- if (!rb)
- return;
- }
- else {
- /* remove renderbuffer attachment */
- rb = NULL;
- }
+void GLAPIENTRY
+_mesa_NamedFramebufferRenderbuffer_no_error(GLuint framebuffer,
+ GLenum attachment,
+ GLenum renderbuffertarget,
+ GLuint renderbuffer)
+{
+ GET_CURRENT_CONTEXT(ctx);
- framebuffer_renderbuffer(ctx, fb, attachment, rb,
- "glFramebufferRenderbuffer");
+ struct gl_framebuffer *fb = _mesa_lookup_framebuffer(ctx, framebuffer);
+ framebuffer_renderbuffer_no_error(ctx, fb, attachment, renderbuffertarget,
+ renderbuffer,
+ "glNamedFramebufferRenderbuffer");
}
-
void GLAPIENTRY
_mesa_NamedFramebufferRenderbuffer(GLuint framebuffer, GLenum attachment,
GLenum renderbuffertarget,
GLuint renderbuffer)
{
struct gl_framebuffer *fb;
- struct gl_renderbuffer *rb;
GET_CURRENT_CONTEXT(ctx);
fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
if (!fb)
return;
- if (renderbuffertarget != GL_RENDERBUFFER) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glNamedFramebufferRenderbuffer(renderbuffertarget is not "
- "GL_RENDERBUFFER)");
- return;
- }
-
- if (renderbuffer) {
- rb = _mesa_lookup_renderbuffer_err(ctx, renderbuffer,
- "glNamedFramebufferRenderbuffer");
- if (!rb)
- return;
- }
- else {
- /* remove renderbuffer attachment */
- rb = NULL;
- }
-
- framebuffer_renderbuffer(ctx, fb, attachment, rb,
- "glNamedFramebufferRenderbuffer");
+ framebuffer_renderbuffer_error(ctx, fb, attachment, renderbuffertarget,
+ renderbuffer,
+ "glNamedFramebufferRenderbuffer");
}
-void
-_mesa_get_framebuffer_attachment_parameter(struct gl_context *ctx,
- struct gl_framebuffer *buffer,
- GLenum attachment, GLenum pname,
- GLint *params, const char *caller)
+static void
+get_framebuffer_attachment_parameter(struct gl_context *ctx,
+ struct gl_framebuffer *buffer,
+ GLenum attachment, GLenum pname,
+ GLint *params, const char *caller)
{
const struct gl_renderbuffer_attachment *att;
bool is_color_attachment = false;
}
/* the default / window-system FBO */
- att = _mesa_get_fb0_attachment(ctx, buffer, attachment);
+ att = get_fb0_attachment(ctx, buffer, attachment);
}
else {
/* user-created framebuffer FBO */
&& !_mesa_is_gles3(ctx)) {
goto invalid_pname_enum;
}
- else if (att->Type == GL_NONE) {
- _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
- _mesa_enum_to_string(pname));
- }
else if (att->Texture) {
const struct gl_texture_image *texImage =
_mesa_select_tex_image(att->Texture, att->Texture->Target,
att->Renderbuffer->Format);
}
else {
- _mesa_problem(ctx, "%s: invalid FBO attachment structure", caller);
+ assert(att->Type == GL_NONE);
+ _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
+ _mesa_enum_to_string(pname));
}
return;
case GL_FRAMEBUFFER_ATTACHMENT_LAYERED:
return;
}
- _mesa_get_framebuffer_attachment_parameter(ctx, buffer, attachment, pname,
- params,
+ get_framebuffer_attachment_parameter(ctx, buffer, attachment, pname,
+ params,
"glGetFramebufferAttachmentParameteriv");
}
buffer = ctx->WinSysDrawBuffer;
}
- _mesa_get_framebuffer_attachment_parameter(ctx, buffer, attachment, pname,
- params,
+ get_framebuffer_attachment_parameter(ctx, buffer, attachment, pname,
+ params,
"glGetNamedFramebufferAttachmentParameteriv");
}
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,
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,
}
+void GLAPIENTRY
+_mesa_InvalidateSubFramebuffer_no_error(GLenum target, GLsizei numAttachments,
+ const GLenum *attachments, GLint x,
+ GLint y, GLsizei width, GLsizei height)
+{
+ /* no-op */
+}
+
+
void GLAPIENTRY
_mesa_InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments,
const GLenum *attachments, GLint x, GLint y,
}
+void GLAPIENTRY
+_mesa_InvalidateFramebuffer_no_error(GLenum target, GLsizei numAttachments,
+ const GLenum *attachments)
+{
+ /* no-op */
+}
+
+
void GLAPIENTRY
_mesa_InvalidateFramebuffer(GLenum target, GLsizei numAttachments,
const GLenum *attachments)
"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");
+ return;
+ }
+ 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);
+}