}
else {
remove_attachment(ctx, att);
+ if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
+ /* detach stencil (depth was detached above) */
+ att = get_attachment(ctx, fb, GL_STENCIL_ATTACHMENT_EXT);
+ assert(att);
+ remove_attachment(ctx, att);
+ }
}
invalidate_framebuffer(fb);
static GLuint msg_id;
_mesa_gl_debug(ctx, &msg_id,
+ MESA_DEBUG_SOURCE_API,
MESA_DEBUG_TYPE_OTHER,
MESA_DEBUG_SEVERITY_MEDIUM,
"FBO incomplete: %s [%d]\n", msg, index);
* Is the given base format a legal format for a color renderbuffer?
*/
static GLboolean
-is_format_color_renderable(const struct gl_context *ctx, mesa_format format, GLenum internalFormat)
+is_format_color_renderable(const struct gl_context *ctx, mesa_format format,
+ GLenum internalFormat)
{
const GLenum baseFormat =
_mesa_get_format_base_format(format);
break;
}
- if (format == MESA_FORMAT_B10G10R10A2_UNORM && internalFormat != GL_RGB10_A2) {
+ if (format == MESA_FORMAT_B10G10R10A2_UNORM &&
+ internalFormat != GL_RGB10_A2) {
return GL_FALSE;
}
attFormat = texImg->TexFormat;
numImages++;
- if (!is_format_color_renderable(ctx, attFormat, texImg->InternalFormat) &&
+ if (!is_format_color_renderable(ctx, attFormat,
+ texImg->InternalFormat) &&
!is_legal_depth_format(ctx, f)) {
fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT;
fbo_incomplete(ctx, "texture attachment incomplete", -1);
if (att->Layered) {
if (att_tex_target == GL_TEXTURE_CUBE_MAP)
att_layer_count = 6;
+ else if (att_tex_target == GL_TEXTURE_1D_ARRAY)
+ att_layer_count = att->Renderbuffer->Height;
else
att_layer_count = att->Renderbuffer->Depth;
} else {
return;
} else if (is_layered != att->Layered) {
fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS;
- fbo_incomplete(ctx, "framebuffer attachment layer mode is inconsistent", i);
+ fbo_incomplete(ctx,
+ "framebuffer attachment layer mode is inconsistent",
+ i);
return;
} else if (att_layer_count > max_layer_count) {
max_layer_count = att_layer_count;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
if (renderbuffer) {
- struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
+ struct gl_renderbuffer *rb =
+ _mesa_lookup_renderbuffer(ctx, renderbuffer);
if (rb != NULL && rb != &DummyRenderbuffer)
return GL_TRUE;
}
}
/* Section 4.4.2 (Attaching Images to Framebuffer Objects),
- * subsection "Attaching Renderbuffer Images to a Framebuffer," of
- * the OpenGL 3.1 spec says:
+ * subsection "Attaching Renderbuffer Images to a Framebuffer,"
+ * of the OpenGL 3.1 spec says:
*
* "If a renderbuffer object is deleted while its image is
* attached to one or more attachment points in the currently
case GL_ALPHA8:
case GL_ALPHA12:
case GL_ALPHA16:
- return ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ARB_framebuffer_object
- ? GL_ALPHA : 0;
+ return (ctx->API == API_OPENGL_COMPAT &&
+ ctx->Extensions.ARB_framebuffer_object) ? GL_ALPHA : 0;
case GL_LUMINANCE:
case GL_LUMINANCE4:
case GL_LUMINANCE8:
case GL_LUMINANCE12:
case GL_LUMINANCE16:
- return ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ARB_framebuffer_object
- ? GL_LUMINANCE : 0;
+ return (ctx->API == API_OPENGL_COMPAT &&
+ ctx->Extensions.ARB_framebuffer_object) ? GL_LUMINANCE : 0;
case GL_LUMINANCE_ALPHA:
case GL_LUMINANCE4_ALPHA4:
case GL_LUMINANCE6_ALPHA2:
case GL_LUMINANCE12_ALPHA4:
case GL_LUMINANCE12_ALPHA12:
case GL_LUMINANCE16_ALPHA16:
- return ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ARB_framebuffer_object
- ? GL_LUMINANCE_ALPHA : 0;
+ return (ctx->API == API_OPENGL_COMPAT &&
+ ctx->Extensions.ARB_framebuffer_object) ? GL_LUMINANCE_ALPHA : 0;
case GL_INTENSITY:
case GL_INTENSITY4:
case GL_INTENSITY8:
case GL_INTENSITY12:
case GL_INTENSITY16:
- return ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ARB_framebuffer_object
- ? GL_INTENSITY : 0;
+ return (ctx->API == API_OPENGL_COMPAT &&
+ ctx->Extensions.ARB_framebuffer_object) ? GL_INTENSITY : 0;
case GL_RGB8:
return GL_RGB;
case GL_RGB:
+ if (_mesa_is_gles3(ctx))
+ return GL_RGB;
+ /* fallthrough */
case GL_R3_G3_B2:
case GL_RGB4:
case GL_RGB5:
case GL_RGBA8:
return GL_RGBA;
case GL_RGBA:
+ if (_mesa_is_gles3(ctx))
+ return GL_RGBA;
+ /* fallthrough */
case GL_RGBA2:
case GL_RGBA12:
case GL_RGBA16:
return GL_DEPTH_STENCIL;
case GL_DEPTH_COMPONENT32F:
return ctx->Version >= 30
- || (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ARB_depth_buffer_float)
+ || (ctx->API == API_OPENGL_COMPAT &&
+ ctx->Extensions.ARB_depth_buffer_float)
? GL_DEPTH_COMPONENT : 0;
case GL_DEPTH32F_STENCIL8:
return ctx->Version >= 30
- || (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ARB_depth_buffer_float)
+ || (ctx->API == API_OPENGL_COMPAT &&
+ ctx->Extensions.ARB_depth_buffer_float)
? GL_DEPTH_STENCIL : 0;
case GL_RED:
case GL_R16:
/**
- * Helper function used by _mesa_RenderbufferStorage() and
+ * Helper function used by _mesa_RenderbufferStorage() and
* _mesa_RenderbufferStorageMultisample().
* samples will be NO_SAMPLES if called by _mesa_RenderbufferStorage().
*/
static void
check_end_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb)
{
- if (_mesa_is_winsys_fbo(fb))
- return; /* can't render to texture with winsys framebuffers */
+ /* Skip if we know NeedsFinishRenderTexture won't be set. */
+ if (_mesa_is_winsys_fbo(fb) && !ctx->Driver.BindRenderbufferTexImage)
+ return;
if (ctx->Driver.FinishRenderTexture) {
GLuint i;
bind_framebuffer(target, framebuffer, _mesa_is_gles(ctx));
}
+
void GLAPIENTRY
_mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)
{
bind_framebuffer(target, framebuffer, true);
}
+
void GLAPIENTRY
_mesa_DeleteFramebuffers(GLsizei n, const GLuint *framebuffers)
{
}
-
GLenum GLAPIENTRY
_mesa_CheckFramebufferStatus(GLenum target)
{
/**
- * Common code called by glFramebufferTexture1D/2D/3DEXT() and
- * glFramebufferTextureLayerEXT().
+ * Common code called by glFramebufferTexture1D/2D/3D() and
+ * glFramebufferTextureLayer().
*
* \param textarget is the textarget that was passed to the
* glFramebufferTexture...() function, or 0 if the corresponding function
* glFramebufferTexture(), false otherwise.
*/
static void
-framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target,
+framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target,
GLenum attachment, GLenum textarget, GLuint texture,
GLint level, GLint zoffset, GLboolean layered)
{
fb = get_framebuffer_target(ctx, target);
if (!fb) {
_mesa_error(ctx, GL_INVALID_ENUM,
- "glFramebufferTexture%sEXT(target=0x%x)", caller, target);
+ "glFramebufferTexture%s(target=0x%x)", caller, target);
return;
}
/* check framebuffer binding */
if (_mesa_is_winsys_fbo(fb)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glFramebufferTexture%sEXT", caller);
+ "glFramebufferTexture%s", caller);
return;
}
else {
/* can't render to a non-existant texture */
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glFramebufferTexture%sEXT(non existant texture)",
+ "glFramebufferTexture%s(non existant texture)",
caller);
return;
}
if (err) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glFramebufferTexture%sEXT(texture target mismatch)",
+ "glFramebufferTexture%s(texture target mismatch)",
caller);
return;
}
const GLint maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1);
if (zoffset < 0 || zoffset >= maxSize) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glFramebufferTexture%sEXT(zoffset)", caller);
+ "glFramebufferTexture%s(zoffset)", caller);
return;
}
}
if (zoffset < 0 ||
zoffset >= (GLint) ctx->Const.MaxArrayTextureLayers) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glFramebufferTexture%sEXT(layer)", caller);
+ "glFramebufferTexture%s(layer)", caller);
return;
}
}
if ((level < 0) ||
(level >= _mesa_max_texture_levels(ctx, maxLevelsTarget))) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glFramebufferTexture%sEXT(level)", caller);
+ "glFramebufferTexture%s(level)", caller);
return;
}
}
att = get_attachment(ctx, fb, attachment);
if (att == NULL) {
_mesa_error(ctx, GL_INVALID_ENUM,
- "glFramebufferTexture%sEXT(attachment)", caller);
+ "glFramebufferTexture%s(attachment)", caller);
return;
}
}
-
void GLAPIENTRY
_mesa_FramebufferTexture1D(GLenum target, GLenum attachment,
- GLenum textarget, GLuint texture, GLint level)
+ GLenum textarget, GLuint texture, GLint level)
{
GET_CURRENT_CONTEXT(ctx);
if (error) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glFramebufferTexture1DEXT(textarget=%s)",
+ "glFramebufferTexture1D(textarget=%s)",
_mesa_lookup_enum_by_nr(textarget));
return;
}
void GLAPIENTRY
_mesa_FramebufferTexture2D(GLenum target, GLenum attachment,
- GLenum textarget, GLuint texture, GLint level)
+ GLenum textarget, GLuint texture, GLint level)
{
GET_CURRENT_CONTEXT(ctx);
if (error) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glFramebufferTexture2DEXT(textarget=%s)",
+ "glFramebufferTexture2D(textarget=%s)",
_mesa_lookup_enum_by_nr(textarget));
return;
}
void GLAPIENTRY
_mesa_FramebufferTexture3D(GLenum target, GLenum attachment,
- GLenum textarget, GLuint texture,
- GLint level, GLint zoffset)
+ GLenum textarget, GLuint texture,
+ GLint level, GLint zoffset)
{
GET_CURRENT_CONTEXT(ctx);
if ((texture != 0) && (textarget != GL_TEXTURE_3D)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glFramebufferTexture3DEXT(textarget)");
+ "glFramebufferTexture3D(textarget)");
return;
}
void GLAPIENTRY
_mesa_FramebufferTextureLayer(GLenum target, GLenum attachment,
- GLuint texture, GLint level, GLint layer)
+ GLuint texture, GLint level, GLint layer)
{
GET_CURRENT_CONTEXT(ctx);
GET_CURRENT_CONTEXT(ctx);
if (_mesa_has_geometry_shaders(ctx)) {
- framebuffer_texture(ctx, "Layer", target, attachment, 0, texture,
+ framebuffer_texture(ctx, "", target, attachment, 0, texture,
level, 0, GL_TRUE);
} else {
_mesa_error(ctx, GL_INVALID_OPERATION,
void GLAPIENTRY
_mesa_FramebufferRenderbuffer(GLenum target, GLenum attachment,
- GLenum renderbufferTarget,
- GLuint renderbuffer)
+ GLenum renderbufferTarget,
+ GLuint renderbuffer)
{
struct gl_renderbuffer_attachment *att;
struct gl_framebuffer *fb;
fb = get_framebuffer_target(ctx, target);
if (!fb) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glFramebufferRenderbufferEXT(target)");
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glFramebufferRenderbuffer(target)");
return;
}
if (renderbufferTarget != GL_RENDERBUFFER_EXT) {
_mesa_error(ctx, GL_INVALID_ENUM,
- "glFramebufferRenderbufferEXT(renderbufferTarget)");
+ "glFramebufferRenderbuffer(renderbufferTarget)");
return;
}
if (_mesa_is_winsys_fbo(fb)) {
/* Can't attach new renderbuffers to a window system framebuffer */
- _mesa_error(ctx, GL_INVALID_OPERATION, "glFramebufferRenderbufferEXT");
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glFramebufferRenderbuffer");
return;
}
att = get_attachment(ctx, fb, attachment);
if (att == NULL) {
_mesa_error(ctx, GL_INVALID_ENUM,
- "glFramebufferRenderbufferEXT(invalid attachment %s)",
+ "glFramebufferRenderbuffer(invalid attachment %s)",
_mesa_lookup_enum_by_nr(attachment));
return;
}
rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
if (!rb) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glFramebufferRenderbufferEXT(non-existant"
+ "glFramebufferRenderbuffer(non-existant"
" renderbuffer %u)", renderbuffer);
return;
}
else if (rb == &DummyRenderbuffer) {
- /* This is what NVIDIA does */
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glFramebufferRenderbufferEXT(renderbuffer %u)",
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glFramebufferRenderbuffer(renderbuffer %u)",
renderbuffer);
return;
}
const GLenum baseFormat = _mesa_get_format_base_format(rb->Format);
if (baseFormat != GL_DEPTH_STENCIL) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glFramebufferRenderbufferEXT(renderbuffer"
+ "glFramebufferRenderbuffer(renderbuffer"
" is not DEPTH_STENCIL format)");
return;
}
}
-
FLUSH_VERTICES(ctx, _NEW_BUFFERS);
assert(ctx->Driver.FramebufferRenderbuffer);
void GLAPIENTRY
_mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
- GLenum pname, GLint *params)
+ GLenum pname, GLint *params)
{
const struct gl_renderbuffer_attachment *att;
struct gl_framebuffer *buffer;
buffer = get_framebuffer_target(ctx, target);
if (!buffer) {
_mesa_error(ctx, GL_INVALID_ENUM,
- "glGetFramebufferAttachmentParameterivEXT(target)");
+ "glGetFramebufferAttachmentParameteriv(target)");
return;
}
* OES_framebuffer_object spec refers to the EXT_framebuffer_object
* spec.
*/
- if ((!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_framebuffer_object)
+ if ((!_mesa_is_desktop_gl(ctx) ||
+ !ctx->Extensions.ARB_framebuffer_object)
&& !_mesa_is_gles3(ctx)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glGetFramebufferAttachmentParameteriv(bound FBO = 0)");
if (att == NULL) {
_mesa_error(ctx, GL_INVALID_ENUM,
- "glGetFramebufferAttachmentParameterivEXT(attachment)");
+ "glGetFramebufferAttachmentParameteriv(attachment)");
return;
}
if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
- /* the depth and stencil attachments must point to the same buffer */
const struct gl_renderbuffer_attachment *depthAtt, *stencilAtt;
+ if (pname == GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE) {
+ /* This behavior is first specified in OpenGL 4.4 specification.
+ *
+ * From the OpenGL 4.4 spec page 275:
+ * "This query cannot be performed for a combined depth+stencil
+ * 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)");
+ return;
+ }
+ /* the depth and stencil attachments must point to the same buffer */
depthAtt = get_attachment(ctx, buffer, GL_DEPTH_ATTACHMENT);
stencilAtt = get_attachment(ctx, buffer, GL_STENCIL_ATTACHMENT);
if (depthAtt->Renderbuffer != stencilAtt->Renderbuffer) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetFramebufferAttachmentParameterivEXT(DEPTH/STENCIL"
+ "glGetFramebufferAttachmentParameteriv(DEPTH/STENCIL"
" attachments differ)");
return;
}
}
else if (att->Type == GL_NONE) {
_mesa_error(ctx, err,
- "glGetFramebufferAttachmentParameterivEXT(pname)");
+ "glGetFramebufferAttachmentParameteriv(pname)");
}
else {
goto invalid_pname_enum;
}
else if (att->Type == GL_NONE) {
_mesa_error(ctx, err,
- "glGetFramebufferAttachmentParameterivEXT(pname)");
+ "glGetFramebufferAttachmentParameteriv(pname)");
}
else {
goto invalid_pname_enum;
goto invalid_pname_enum;
} else if (att->Type == GL_NONE) {
_mesa_error(ctx, err,
- "glGetFramebufferAttachmentParameterivEXT(pname)");
+ "glGetFramebufferAttachmentParameteriv(pname)");
} else if (att->Type == GL_TEXTURE) {
if (att->Texture && att->Texture->Target == GL_TEXTURE_3D) {
*params = att->Zoffset;
}
return;
case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
- if ((!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_framebuffer_object)
+ if ((!_mesa_is_desktop_gl(ctx) ||
+ !ctx->Extensions.ARB_framebuffer_object)
&& !_mesa_is_gles3(ctx)) {
goto invalid_pname_enum;
}
else if (att->Type == GL_NONE) {
_mesa_error(ctx, err,
- "glGetFramebufferAttachmentParameterivEXT(pname)");
+ "glGetFramebufferAttachmentParameteriv(pname)");
}
else {
if (ctx->Extensions.EXT_framebuffer_sRGB) {
- *params = _mesa_get_format_color_encoding(att->Renderbuffer->Format);
+ *params =
+ _mesa_get_format_color_encoding(att->Renderbuffer->Format);
}
else {
/* According to ARB_framebuffer_sRGB, we should return LINEAR
}
return;
case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
- if ((ctx->API != API_OPENGL_COMPAT || !ctx->Extensions.ARB_framebuffer_object)
+ if ((ctx->API != API_OPENGL_COMPAT ||
+ !ctx->Extensions.ARB_framebuffer_object)
&& ctx->API != API_OPENGL_CORE
&& !_mesa_is_gles3(ctx)) {
goto invalid_pname_enum;
}
else if (att->Type == GL_NONE) {
_mesa_error(ctx, err,
- "glGetFramebufferAttachmentParameterivEXT(pname)");
+ "glGetFramebufferAttachmentParameteriv(pname)");
}
else {
mesa_format format = att->Renderbuffer->Format;
* attachment is DEPTH_STENCIL_ATTACHMENT the query will fail and
* generate an INVALID_OPERATION error.
*/
- if (_mesa_is_gles3(ctx) && attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
+ if (_mesa_is_gles3(ctx) &&
+ attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glGetFramebufferAttachmentParameteriv(cannot query "
"GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE of "
case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
- if ((!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_framebuffer_object)
+ if ((!_mesa_is_desktop_gl(ctx) ||
+ !ctx->Extensions.ARB_framebuffer_object)
&& !_mesa_is_gles3(ctx)) {
goto invalid_pname_enum;
}
else if (att->Type == GL_NONE) {
_mesa_error(ctx, err,
- "glGetFramebufferAttachmentParameterivEXT(pname)");
+ "glGetFramebufferAttachmentParameteriv(pname)");
}
else if (att->Texture) {
const struct gl_texture_image *texImage =
case GL_DEPTH_ATTACHMENT:
case GL_STENCIL_ATTACHMENT:
break;
+ case GL_DEPTH_STENCIL_ATTACHMENT:
+ /* GL_DEPTH_STENCIL_ATTACHMENT is a valid attachment point only
+ * in desktop and ES 3.0 profiles. Note that OES_packed_depth_stencil
+ * extension does not make this attachment point valid on ES 2.0.
+ */
+ if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx))
+ break;
+ /* fallthrough */
case GL_COLOR_ATTACHMENT0:
case GL_COLOR_ATTACHMENT1:
case GL_COLOR_ATTACHMENT2:
return;
}
+
void GLAPIENTRY
_mesa_InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments,
const GLenum *attachments, GLint x, GLint y,
"glInvalidateSubFramebuffer");
}
+
void GLAPIENTRY
_mesa_InvalidateFramebuffer(GLenum target, GLsizei numAttachments,
const GLenum *attachments)
* <MAX_VIEWPORT_DIMS[1]> respectively."
*/
invalidate_framebuffer_storage(target, numAttachments, attachments,
- 0, 0, MAX_VIEWPORT_WIDTH, MAX_VIEWPORT_HEIGHT,
+ 0, 0,
+ MAX_VIEWPORT_WIDTH, MAX_VIEWPORT_HEIGHT,
"glInvalidateFramebuffer");
}
+
void GLAPIENTRY
_mesa_DiscardFramebufferEXT(GLenum target, GLsizei numAttachments,
const GLenum *attachments)