fb->Height = 0;
fb->_AllColorBuffersFixedPoint = GL_TRUE;
fb->_HasSNormOrFloatColorBuffer = GL_FALSE;
+ fb->_HasAttachments = true;
/* Start at -2 to more easily loop over all attachment points.
* -2: depth buffer
} else if (att_layer_count > max_layer_count) {
max_layer_count = att_layer_count;
}
+
+ /*
+ * The extension GL_ARB_framebuffer_no_attachments places additional
+ * requirement on each attachment. Those additional requirements are
+ * tighter that those of previous versions of GL. In interest of better
+ * compatibility, we will not enforce these restrictions. For the record
+ * those additional restrictions are quoted below:
+ *
+ * "The width and height of image are greater than zero and less than or
+ * equal to the values of the implementation-dependent limits
+ * MAX_FRAMEBUFFER_WIDTH and MAX_FRAMEBUFFER_HEIGHT, respectively."
+ *
+ * "If <image> is a three-dimensional texture or a one- or two-dimensional
+ * array texture and the attachment is layered, the depth or layer count
+ * of the texture is less than or equal to the implementation-dependent
+ * limit MAX_FRAMEBUFFER_LAYERS."
+ *
+ * "If image has multiple samples, its sample count is less than or equal
+ * to the value of the implementation-dependent limit
+ * MAX_FRAMEBUFFER_SAMPLES."
+ *
+ * The same requirements are also in place for GL 4.5,
+ * Section 9.4.1 "Framebuffer Attachment Completeness", pg 310-311
+ */
}
fb->MaxNumLayers = max_layer_count;
if (numImages == 0) {
- fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT;
- fbo_incomplete(ctx, "no attachments", -1);
- return;
+ fb->_HasAttachments = false;
+
+ if (!ctx->Extensions.ARB_framebuffer_no_attachments) {
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT;
+ fbo_incomplete(ctx, "no attachments", -1);
+ return;
+ }
+
+ if (fb->DefaultGeometry.Width == 0 || fb->DefaultGeometry.Height == 0) {
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT;
+ fbo_incomplete(ctx, "no attachments and default width or height is 0", -1);
+ return;
+ }
}
if (_mesa_is_desktop_gl(ctx) && !ctx->Extensions.ARB_ES2_compatibility) {
* renderbuffers/textures are different sizes, the framebuffer
* width/height will be set to the smallest width/height.
*/
- fb->Width = minWidth;
- fb->Height = minHeight;
+ if (numImages != 0) {
+ fb->Width = minWidth;
+ fb->Height = minHeight;
+ }
/* finally, update the visual info for the framebuffer */
_mesa_update_framebuffer_visual(ctx, fb);
bind_renderbuffer(target, renderbuffer, true);
}
+static void
+framebuffer_parameteri(struct gl_context *ctx, struct gl_framebuffer *fb,
+ GLenum pname, GLint param, const char *func)
+{
+ switch (pname) {
+ case GL_FRAMEBUFFER_DEFAULT_WIDTH:
+ if (param < 0 || param > ctx->Const.MaxFramebufferWidth)
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s", func);
+ else
+ fb->DefaultGeometry.Width = param;
+ break;
+ case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
+ if (param < 0 || param > ctx->Const.MaxFramebufferHeight)
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s", func);
+ else
+ fb->DefaultGeometry.Height = param;
+ break;
+ case GL_FRAMEBUFFER_DEFAULT_LAYERS:
+ if (param < 0 || param > ctx->Const.MaxFramebufferLayers)
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s", func);
+ else
+ fb->DefaultGeometry.Layers = param;
+ break;
+ case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
+ if (param < 0 || param > ctx->Const.MaxFramebufferSamples)
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s", func);
+ else
+ fb->DefaultGeometry.NumSamples = param;
+ break;
+ case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
+ fb->DefaultGeometry.FixedSampleLocations = param;
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "%s(pname=0x%x)", func, pname);
+ }
+}
+
+void GLAPIENTRY
+_mesa_FramebufferParameteri(GLenum target, GLenum pname, GLint param)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_framebuffer *fb;
+
+ if (!ctx->Extensions.ARB_framebuffer_no_attachments) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glFramebufferParameteriv not supported "
+ "(ARB_framebuffer_no_attachments not implemented)");
+ return;
+ }
+
+ fb = get_framebuffer_target(ctx, target);
+ if (!fb) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glFramebufferParameteri(target=0x%x)", target);
+ 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 void
+get_framebuffer_parameteriv(struct gl_context *ctx, struct gl_framebuffer *fb,
+ GLenum pname, GLint *params, const char *func)
+{
+ switch (pname) {
+ case GL_FRAMEBUFFER_DEFAULT_WIDTH:
+ *params = fb->DefaultGeometry.Width;
+ break;
+ case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
+ *params = fb->DefaultGeometry.Height;
+ break;
+ case GL_FRAMEBUFFER_DEFAULT_LAYERS:
+ *params = fb->DefaultGeometry.Layers;
+ break;
+ case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
+ *params = fb->DefaultGeometry.NumSamples;
+ break;
+ case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
+ *params = fb->DefaultGeometry.FixedSampleLocations;
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "%s(pname=0x%x)", func, pname);
+ }
+}
+
+void GLAPIENTRY
+_mesa_GetFramebufferParameteriv(GLenum target, GLenum pname, GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_framebuffer *fb;
+
+ if (!ctx->Extensions.ARB_framebuffer_no_attachments) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetFramebufferParameteriv not supported "
+ "(ARB_framebuffer_no_attachments not implemented)");
+ return;
+ }
+
+ fb = get_framebuffer_target(ctx, target);
+ if (!fb) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetFramebufferParameteriv(target=0x%x)", target);
+ return;
+ }
+
+ /* check framebuffer binding */
+ if (_mesa_is_winsys_fbo(fb)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetFramebufferParameteriv");
+ return;
+ }
+
+ get_framebuffer_parameteriv(ctx, fb, pname, params,
+ "glGetFramebufferParameteriv");
+}
+
/**
* Remove the specified renderbuffer or texture from any attachment point in
baseFormat = _mesa_base_fbo_format(ctx, internalFormat);
if (baseFormat == 0) {
_mesa_error(ctx, GL_INVALID_ENUM, "%s(internalFormat=%s)",
- func, _mesa_lookup_enum_by_nr(internalFormat));
+ func, _mesa_enum_to_string(internalFormat));
return;
}
if (samples == NO_SAMPLES)
_mesa_debug(ctx, "%s(%u, %s, %d, %d)\n",
func, renderbuffer,
- _mesa_lookup_enum_by_nr(internalFormat),
+ _mesa_enum_to_string(internalFormat),
width, height);
else
_mesa_debug(ctx, "%s(%u, %s, %d, %d, %d)\n",
func, renderbuffer,
- _mesa_lookup_enum_by_nr(internalFormat),
+ _mesa_enum_to_string(internalFormat),
width, height, samples);
}
if (samples == NO_SAMPLES)
_mesa_debug(ctx, "%s(%s, %s, %d, %d)\n",
func,
- _mesa_lookup_enum_by_nr(target),
- _mesa_lookup_enum_by_nr(internalFormat),
+ _mesa_enum_to_string(target),
+ _mesa_enum_to_string(internalFormat),
width, height);
else
_mesa_debug(ctx, "%s(%s, %s, %d, %d, %d)\n",
func,
- _mesa_lookup_enum_by_nr(target),
- _mesa_lookup_enum_by_nr(internalFormat),
+ _mesa_enum_to_string(target),
+ _mesa_enum_to_string(internalFormat),
width, height, samples);
}
/* fallthrough */
default:
_mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid pname=%s)", func,
- _mesa_lookup_enum_by_nr(pname));
+ _mesa_enum_to_string(pname));
return;
}
}
if (MESA_VERBOSE & VERBOSE_API)
_mesa_debug(ctx, "glCheckFramebufferStatus(%s)\n",
- _mesa_lookup_enum_by_nr(target));
+ _mesa_enum_to_string(target));
fb = get_framebuffer_target(ctx, target);
if (!fb) {
_mesa_error(ctx, GL_INVALID_ENUM,
"glCheckFramebufferStatus(invalid target %s)",
- _mesa_lookup_enum_by_nr(target));
+ _mesa_enum_to_string(target));
return 0;
}
default:
_mesa_error(ctx, GL_INVALID_ENUM,
"glCheckNamedFramebufferStatus(invalid target %s)",
- _mesa_lookup_enum_by_nr(target));
+ _mesa_enum_to_string(target));
return 0;
}
_mesa_error(ctx, GL_INVALID_OPERATION,
"%s(invalid texture target %s)", caller,
- _mesa_lookup_enum_by_nr(target));
+ _mesa_enum_to_string(target));
return false;
}
check_texture_target(struct gl_context *ctx, GLenum target,
const char *caller)
{
- /* We're being called by glFramebufferTextureLayer() and
- * textarget is not used. The only legal texture types for
- * that function are 3D and 1D/2D arrays textures.
+ /* We're being called by glFramebufferTextureLayer().
+ * The only legal texture types for that function are 3D,
+ * cube-map, and 1D/2D/cube-map array textures.
+ *
+ * We don't need to check for GL_ARB_texture_cube_map_array because the
+ * application wouldn't have been able to create a texture with a
+ * GL_TEXTURE_CUBE_MAP_ARRAY target if the extension were not enabled.
*/
switch (target) {
case GL_TEXTURE_3D:
case GL_TEXTURE_CUBE_MAP_ARRAY:
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.
+ */
+ return ctx->API == API_OPENGL_CORE;
}
_mesa_error(ctx, GL_INVALID_OPERATION,
"%s(invalid texture target %s)", caller,
- _mesa_lookup_enum_by_nr(target));
+ _mesa_enum_to_string(target));
return false;
}
if (err) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"%s(invalid textarget %s)",
- caller, _mesa_lookup_enum_by_nr(textarget));
+ caller, _mesa_enum_to_string(textarget));
return false;
}
return false;
}
}
+ else if (target == GL_TEXTURE_CUBE_MAP) {
+ if (layer >= 6) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "%s(layer %u >= 6)", caller, layer);
+ return false;
+ }
+ }
return true;
}
att = get_attachment(ctx, fb, attachment);
if (att == NULL) {
_mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid attachment %s)", caller,
- _mesa_lookup_enum_by_nr(attachment));
+ _mesa_enum_to_string(attachment));
return;
}
fb = get_framebuffer_target(ctx, target);
if (!fb) {
_mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", caller,
- _mesa_lookup_enum_by_nr(target));
+ _mesa_enum_to_string(target));
return;
}
GET_CURRENT_CONTEXT(ctx);
struct gl_framebuffer *fb;
struct gl_texture_object *texObj;
+ GLenum textarget = 0;
const char *func = "glFramebufferTextureLayer";
if (!fb) {
_mesa_error(ctx, GL_INVALID_ENUM,
"glFramebufferTextureLayer(invalid target %s)",
- _mesa_lookup_enum_by_nr(target));
+ _mesa_enum_to_string(target));
return;
}
if (!check_level(ctx, texObj->Target, level, func))
return;
+
+ 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, 0, level,
+ _mesa_framebuffer_texture(ctx, fb, attachment, texObj, textarget, level,
layer, GL_FALSE, func);
}
GET_CURRENT_CONTEXT(ctx);
struct gl_framebuffer *fb;
struct gl_texture_object *texObj;
+ GLenum textarget = 0;
const char *func = "glNamedFramebufferTextureLayer";
if (!check_level(ctx, texObj->Target, level, func))
return;
+
+ 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, 0, level,
+ _mesa_framebuffer_texture(ctx, fb, attachment, texObj, textarget, level,
layer, GL_FALSE, func);
}
if (!fb) {
_mesa_error(ctx, GL_INVALID_ENUM,
"glFramebufferTexture(invalid target %s)",
- _mesa_lookup_enum_by_nr(target));
+ _mesa_enum_to_string(target));
return;
}
if (att == NULL) {
_mesa_error(ctx, GL_INVALID_ENUM,
"%s(invalid attachment %s)", func,
- _mesa_lookup_enum_by_nr(attachment));
+ _mesa_enum_to_string(attachment));
return;
}
if (!fb) {
_mesa_error(ctx, GL_INVALID_ENUM,
"glFramebufferRenderbuffer(invalid target %s)",
- _mesa_lookup_enum_by_nr(target));
+ _mesa_enum_to_string(target));
return;
}
fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
"glNamedFramebufferRenderbuffer");
+ if (!fb)
+ return;
if (renderbuffertarget != GL_RENDERBUFFER) {
_mesa_error(ctx, GL_INVALID_ENUM,
}
-void GLAPIENTRY
-_mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
- GLenum pname, GLint *params)
+void
+_mesa_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;
- struct gl_framebuffer *buffer;
GLenum err;
- GET_CURRENT_CONTEXT(ctx);
/* The error differs in GL and GLES. */
err = _mesa_is_desktop_gl(ctx) ? GL_INVALID_OPERATION : GL_INVALID_ENUM;
- buffer = get_framebuffer_target(ctx, target);
- if (!buffer) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glGetFramebufferAttachmentParameteriv(target)");
- return;
- }
-
if (_mesa_is_winsys_fbo(buffer)) {
/* Page 126 (page 136 of the PDF) of the OpenGL ES 2.0.25 spec
* says:
!ctx->Extensions.ARB_framebuffer_object)
&& !_mesa_is_gles3(ctx)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetFramebufferAttachmentParameteriv(bound FBO = 0)");
+ "%s(window-system framebuffer)", caller);
return;
}
if (_mesa_is_gles3(ctx) && attachment != GL_BACK &&
attachment != GL_DEPTH && attachment != GL_STENCIL) {
_mesa_error(ctx, GL_INVALID_ENUM,
- "glGetFramebufferAttachmentParameteriv(attachment)");
+ "%s(invalid attachment %s)", caller,
+ _mesa_enum_to_string(attachment));
return;
}
/* the default / window-system FBO */
}
if (att == NULL) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glGetFramebufferAttachmentParameteriv(attachment)");
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid attachment %s)", caller,
+ _mesa_enum_to_string(attachment));
return;
}
* attachment, since it does not have a single format."
*/
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetFramebufferAttachmentParameteriv("
- "GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE"
- " is invalid for depth+stencil attachment)");
+ "%s(GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE"
+ " is invalid for depth+stencil attachment)", caller);
return;
}
/* the depth and stencil attachments must point to the same buffer */
stencilAtt = get_attachment(ctx, buffer, GL_STENCIL_ATTACHMENT);
if (depthAtt->Renderbuffer != stencilAtt->Renderbuffer) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetFramebufferAttachmentParameteriv(DEPTH/STENCIL"
- " attachments differ)");
+ "%s(DEPTH/STENCIL attachments differ)", caller);
return;
}
}
*params = att->TextureLevel;
}
else if (att->Type == GL_NONE) {
- _mesa_error(ctx, err,
- "glGetFramebufferAttachmentParameteriv(pname)");
+ _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
+ _mesa_enum_to_string(pname));
}
else {
goto invalid_pname_enum;
}
}
else if (att->Type == GL_NONE) {
- _mesa_error(ctx, err,
- "glGetFramebufferAttachmentParameteriv(pname)");
+ _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
+ _mesa_enum_to_string(pname));
}
else {
goto invalid_pname_enum;
if (ctx->API == API_OPENGLES) {
goto invalid_pname_enum;
} else if (att->Type == GL_NONE) {
- _mesa_error(ctx, err,
- "glGetFramebufferAttachmentParameteriv(pname)");
+ _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
+ _mesa_enum_to_string(pname));
} else if (att->Type == GL_TEXTURE) {
if (att->Texture && (att->Texture->Target == GL_TEXTURE_3D ||
att->Texture->Target == GL_TEXTURE_2D_ARRAY)) {
goto invalid_pname_enum;
}
else if (att->Type == GL_NONE) {
- _mesa_error(ctx, err,
- "glGetFramebufferAttachmentParameteriv(pname)");
+ _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
+ _mesa_enum_to_string(pname));
}
else {
if (ctx->Extensions.EXT_framebuffer_sRGB) {
goto invalid_pname_enum;
}
else if (att->Type == GL_NONE) {
- _mesa_error(ctx, err,
- "glGetFramebufferAttachmentParameteriv(pname)");
+ _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
+ _mesa_enum_to_string(pname));
}
else {
mesa_format format = att->Renderbuffer->Format;
if (_mesa_is_gles3(ctx) &&
attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetFramebufferAttachmentParameteriv(cannot query "
+ "%s(cannot query "
"GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE of "
- "GL_DEPTH_STENCIL_ATTACHMENT");
+ "GL_DEPTH_STENCIL_ATTACHMENT)", caller);
return;
}
goto invalid_pname_enum;
}
else if (att->Type == GL_NONE) {
- _mesa_error(ctx, err,
- "glGetFramebufferAttachmentParameteriv(pname)");
+ _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
+ _mesa_enum_to_string(pname));
}
else if (att->Texture) {
const struct gl_texture_image *texImage =
att->Renderbuffer->Format);
}
else {
- _mesa_problem(ctx, "glGetFramebufferAttachmentParameterivEXT:"
- " invalid FBO attachment structure");
+ _mesa_problem(ctx, "%s: invalid FBO attachment structure", caller);
}
return;
case GL_FRAMEBUFFER_ATTACHMENT_LAYERED:
} else if (att->Type == GL_TEXTURE) {
*params = att->Layered;
} else if (att->Type == GL_NONE) {
- _mesa_error(ctx, err,
- "glGetFramebufferAttachmentParameteriv(pname)");
+ _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
+ _mesa_enum_to_string(pname));
} else {
goto invalid_pname_enum;
}
return;
invalid_pname_enum:
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glGetFramebufferAttachmentParameteriv(pname)");
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid pname %s)", caller,
+ _mesa_enum_to_string(pname));
return;
}
+void GLAPIENTRY
+_mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
+ GLenum pname, GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_framebuffer *buffer;
+
+ buffer = get_framebuffer_target(ctx, target);
+ if (!buffer) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetFramebufferAttachmentParameteriv(invalid target %s)",
+ _mesa_enum_to_string(target));
+ return;
+ }
+
+ _mesa_get_framebuffer_attachment_parameter(ctx, buffer, attachment, pname,
+ params,
+ "glGetFramebufferAttachmentParameteriv");
+}
+
+
+void GLAPIENTRY
+_mesa_GetNamedFramebufferAttachmentParameteriv(GLuint framebuffer,
+ GLenum attachment,
+ GLenum pname, GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_framebuffer *buffer;
+
+ if (framebuffer) {
+ buffer = _mesa_lookup_framebuffer_err(ctx, framebuffer,
+ "glGetNamedFramebufferAttachmentParameteriv");
+ if (!buffer)
+ return;
+ }
+ else {
+ /*
+ * Section 9.2 Binding and Managing Framebuffer Objects of the OpenGL
+ * 4.5 core spec (30.10.2014, PDF page 314):
+ * "If framebuffer is zero, then the default draw framebuffer is
+ * queried."
+ */
+ buffer = ctx->WinSysDrawBuffer;
+ }
+
+ _mesa_get_framebuffer_attachment_parameter(ctx, buffer, attachment, pname,
+ params,
+ "glGetNamedFramebufferAttachmentParameteriv");
+}
+
+
+void GLAPIENTRY
+_mesa_NamedFramebufferParameteri(GLuint framebuffer, GLenum pname,
+ GLint param)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_framebuffer *fb = NULL;
+
+ if (!ctx->Extensions.ARB_framebuffer_no_attachments) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glNamedFramebufferParameteri("
+ "ARB_framebuffer_no_attachments not implemented)");
+ return;
+ }
+
+ fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
+ "glNamedFramebufferParameteri");
+
+ if (fb) {
+ framebuffer_parameteri(ctx, fb, pname, param,
+ "glNamedFramebufferParameteriv");
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_GetNamedFramebufferParameteriv(GLuint framebuffer, GLenum pname,
+ GLint *param)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_framebuffer *fb;
+
+ if (!ctx->Extensions.ARB_framebuffer_no_attachments) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glNamedFramebufferParameteriv("
+ "ARB_framebuffer_no_attachments not implemented)");
+ return;
+ }
+
+ if (framebuffer) {
+ fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
+ "glGetNamedFramebufferParameteriv");
+ } else {
+ fb = ctx->WinSysDrawBuffer;
+ }
+
+ if (fb) {
+ get_framebuffer_parameteriv(ctx, fb, pname, param,
+ "glGetNamedFramebufferParameteriv");
+ }
+}
+
+
static void
-invalidate_framebuffer_storage(GLenum target, GLsizei numAttachments,
+invalidate_framebuffer_storage(struct gl_context *ctx,
+ struct gl_framebuffer *fb,
+ GLsizei numAttachments,
const GLenum *attachments, GLint x, GLint y,
GLsizei width, GLsizei height, const char *name)
{
int i;
- struct gl_framebuffer *fb;
- GET_CURRENT_CONTEXT(ctx);
- fb = get_framebuffer_target(ctx, target);
- if (!fb) {
- _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", name);
+ /* Section 17.4 Whole Framebuffer Operations of the OpenGL 4.5 Core
+ * Spec (2.2.2015, PDF page 522) says:
+ * "An INVALID_VALUE error is generated if numAttachments, width, or
+ * height is negative."
+ */
+ if (numAttachments < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "%s(numAttachments < 0)", name);
return;
}
- if (numAttachments < 0) {
+ if (width < 0) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "%s(numAttachments < 0)", name);
+ "%s(width < 0)", name);
+ return;
+ }
+
+ if (height < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "%s(height < 0)", name);
return;
}
return;
invalid_enum:
- _mesa_error(ctx, GL_INVALID_ENUM, "%s(attachment)", name);
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid attachment %s)", name,
+ _mesa_enum_to_string(attachments[i]));
return;
}
const GLenum *attachments, GLint x, GLint y,
GLsizei width, GLsizei height)
{
- invalidate_framebuffer_storage(target, numAttachments, attachments,
+ struct gl_framebuffer *fb;
+ GET_CURRENT_CONTEXT(ctx);
+
+ fb = get_framebuffer_target(ctx, target);
+ if (!fb) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glInvalidateSubFramebuffer(invalid target %s)",
+ _mesa_enum_to_string(target));
+ return;
+ }
+
+ invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments,
x, y, width, height,
"glInvalidateSubFramebuffer");
}
+void GLAPIENTRY
+_mesa_InvalidateNamedFramebufferSubData(GLuint framebuffer,
+ GLsizei numAttachments,
+ const GLenum *attachments,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height)
+{
+ struct gl_framebuffer *fb;
+ GET_CURRENT_CONTEXT(ctx);
+
+ /* The OpenGL 4.5 core spec (02.02.2015) says (in Section 17.4 Whole
+ * Framebuffer Operations, PDF page 522): "If framebuffer is zero, the
+ * default draw framebuffer is affected."
+ */
+ if (framebuffer) {
+ fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
+ "glInvalidateNamedFramebufferSubData");
+ if (!fb)
+ return;
+ }
+ else
+ fb = ctx->WinSysDrawBuffer;
+
+ invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments,
+ x, y, width, height,
+ "glInvalidateNamedFramebufferSubData");
+}
+
+
void GLAPIENTRY
_mesa_InvalidateFramebuffer(GLenum target, GLsizei numAttachments,
const GLenum *attachments)
{
+ struct gl_framebuffer *fb;
+ GET_CURRENT_CONTEXT(ctx);
+
+ fb = get_framebuffer_target(ctx, target);
+ if (!fb) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glInvalidateFramebuffer(invalid target %s)",
+ _mesa_enum_to_string(target));
+ return;
+ }
+
/* The GL_ARB_invalidate_subdata spec says:
*
* "The command
* <width>, <height> equal to 0, 0, <MAX_VIEWPORT_DIMS[0]>,
* <MAX_VIEWPORT_DIMS[1]> respectively."
*/
- invalidate_framebuffer_storage(target, numAttachments, attachments,
+ invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments,
0, 0,
MAX_VIEWPORT_WIDTH, MAX_VIEWPORT_HEIGHT,
"glInvalidateFramebuffer");
}
+void GLAPIENTRY
+_mesa_InvalidateNamedFramebufferData(GLuint framebuffer,
+ GLsizei numAttachments,
+ const GLenum *attachments)
+{
+ struct gl_framebuffer *fb;
+ GET_CURRENT_CONTEXT(ctx);
+
+ /* The OpenGL 4.5 core spec (02.02.2015) says (in Section 17.4 Whole
+ * Framebuffer Operations, PDF page 522): "If framebuffer is zero, the
+ * default draw framebuffer is affected."
+ */
+ if (framebuffer) {
+ fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
+ "glInvalidateNamedFramebufferData");
+ if (!fb)
+ return;
+ }
+ else
+ fb = ctx->WinSysDrawBuffer;
+
+ /* The GL_ARB_invalidate_subdata spec says:
+ *
+ * "The command
+ *
+ * void InvalidateFramebuffer(enum target,
+ * sizei numAttachments,
+ * const enum *attachments);
+ *
+ * is equivalent to the command InvalidateSubFramebuffer with <x>, <y>,
+ * <width>, <height> equal to 0, 0, <MAX_VIEWPORT_DIMS[0]>,
+ * <MAX_VIEWPORT_DIMS[1]> respectively."
+ */
+ invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments,
+ 0, 0,
+ MAX_VIEWPORT_WIDTH, MAX_VIEWPORT_HEIGHT,
+ "glInvalidateNamedFramebufferData");
+}
+
+
void GLAPIENTRY
_mesa_DiscardFramebufferEXT(GLenum target, GLsizei numAttachments,
const GLenum *attachments)
if (!fb) {
_mesa_error(ctx, GL_INVALID_ENUM,
"glDiscardFramebufferEXT(target %s)",
- _mesa_lookup_enum_by_nr(target));
+ _mesa_enum_to_string(target));
return;
}
invalid_enum:
_mesa_error(ctx, GL_INVALID_ENUM,
"glDiscardFramebufferEXT(attachment %s)",
- _mesa_lookup_enum_by_nr(attachments[i]));
+ _mesa_enum_to_string(attachments[i]));
}