diff options
author | marha <marha@users.sourceforge.net> | 2014-02-07 23:46:30 +0100 |
---|---|---|
committer | marha <marha@users.sourceforge.net> | 2014-02-07 23:46:30 +0100 |
commit | 6daf40f6b1138efad98dbb579cd35520cbc349bb (patch) | |
tree | 7f45dbb347f5e1a73b18a720633b9d801c968490 /mesalib/src/mesa/main/fbobject.c | |
parent | 5c64f94cf4cf8457a5616fe20b9a27174895f1a8 (diff) | |
parent | 982ac918afe6a1c02d5cf735d7b6c56443a048cc (diff) | |
download | vcxsrv-6daf40f6b1138efad98dbb579cd35520cbc349bb.tar.gz vcxsrv-6daf40f6b1138efad98dbb579cd35520cbc349bb.tar.bz2 vcxsrv-6daf40f6b1138efad98dbb579cd35520cbc349bb.zip |
Merge remote-tracking branch 'origin/released'
* origin/released:
xkbcomp xkeyboard-config libxcb libxtrans fontconfig libX11 libxcb mesa xserver git update 7 Feb 2014
Conflicts:
mesalib/src/glsl/glcpp/glcpp.c
openssl/Makefile
Diffstat (limited to 'mesalib/src/mesa/main/fbobject.c')
-rw-r--r-- | mesalib/src/mesa/main/fbobject.c | 695 |
1 files changed, 52 insertions, 643 deletions
diff --git a/mesalib/src/mesa/main/fbobject.c b/mesalib/src/mesa/main/fbobject.c index 943f40bd9..e459e0c63 100644 --- a/mesalib/src/mesa/main/fbobject.c +++ b/mesalib/src/mesa/main/fbobject.c @@ -50,10 +50,6 @@ #include "texobj.h" -/** Set this to 1 to debug/log glBlitFramebuffer() calls */ -#define DEBUG_BLIT 0 - - /** * Notes: * @@ -163,8 +159,7 @@ invalidate_framebuffer(struct gl_framebuffer *fb) static struct gl_framebuffer * get_framebuffer_target(struct gl_context *ctx, GLenum target) { - bool have_fb_blit = _mesa_is_gles3(ctx) || - (ctx->Extensions.EXT_framebuffer_blit && _mesa_is_desktop_gl(ctx)); + bool have_fb_blit = _mesa_is_gles3(ctx) || _mesa_is_desktop_gl(ctx); switch (target) { case GL_DRAW_FRAMEBUFFER: return have_fb_blit ? ctx->DrawBuffer : NULL; @@ -186,9 +181,9 @@ get_framebuffer_target(struct gl_context *ctx, GLenum target) * If \p attachment is GL_DEPTH_STENCIL_ATTACHMENT, return a pointer to * the depth buffer attachment point. */ -struct gl_renderbuffer_attachment * -_mesa_get_attachment(struct gl_context *ctx, struct gl_framebuffer *fb, - GLenum attachment) +static struct gl_renderbuffer_attachment * +get_attachment(struct gl_context *ctx, struct gl_framebuffer *fb, + GLenum attachment) { GLuint i; @@ -318,9 +313,9 @@ _mesa_get_fb0_attachment(struct gl_context *ctx, struct gl_framebuffer *fb, * Remove any texture or renderbuffer attached to the given attachment * point. Update reference counts, etc. */ -void -_mesa_remove_attachment(struct gl_context *ctx, - struct gl_renderbuffer_attachment *att) +static void +remove_attachment(struct gl_context *ctx, + struct gl_renderbuffer_attachment *att) { struct gl_renderbuffer *rb = att->Renderbuffer; @@ -423,13 +418,13 @@ _mesa_update_texture_renderbuffer(struct gl_context *ctx, * Bind a texture object to an attachment point. * The previous binding, if any, will be removed first. */ -void -_mesa_set_texture_attachment(struct gl_context *ctx, - struct gl_framebuffer *fb, - struct gl_renderbuffer_attachment *att, - struct gl_texture_object *texObj, - GLenum texTarget, GLuint level, GLuint zoffset, - GLboolean layered) +static void +set_texture_attachment(struct gl_context *ctx, + struct gl_framebuffer *fb, + struct gl_renderbuffer_attachment *att, + struct gl_texture_object *texObj, + GLenum texTarget, GLuint level, GLuint zoffset, + GLboolean layered) { struct gl_renderbuffer *rb = att->Renderbuffer; @@ -442,7 +437,7 @@ _mesa_set_texture_attachment(struct gl_context *ctx, } else { /* new attachment */ - _mesa_remove_attachment(ctx, att); + remove_attachment(ctx, att); att->Type = GL_TEXTURE; assert(!att->Texture); _mesa_reference_texobj(&att->Texture, texObj); @@ -464,13 +459,13 @@ _mesa_set_texture_attachment(struct gl_context *ctx, * Bind a renderbuffer to an attachment point. * The previous binding, if any, will be removed first. */ -void -_mesa_set_renderbuffer_attachment(struct gl_context *ctx, - struct gl_renderbuffer_attachment *att, - struct gl_renderbuffer *rb) +static void +set_renderbuffer_attachment(struct gl_context *ctx, + struct gl_renderbuffer_attachment *att, + struct gl_renderbuffer *rb) { /* XXX check if re-doing same attachment, exit early */ - _mesa_remove_attachment(ctx, att); + remove_attachment(ctx, att); att->Type = GL_RENDERBUFFER_EXT; att->Texture = NULL; /* just to be safe */ att->Complete = GL_FALSE; @@ -491,20 +486,20 @@ _mesa_framebuffer_renderbuffer(struct gl_context *ctx, _glthread_LOCK_MUTEX(fb->Mutex); - att = _mesa_get_attachment(ctx, fb, attachment); + att = get_attachment(ctx, fb, attachment); ASSERT(att); if (rb) { - _mesa_set_renderbuffer_attachment(ctx, att, rb); + set_renderbuffer_attachment(ctx, att, rb); if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) { /* do stencil attachment here (depth already done above) */ - att = _mesa_get_attachment(ctx, fb, GL_STENCIL_ATTACHMENT_EXT); + att = get_attachment(ctx, fb, GL_STENCIL_ATTACHMENT_EXT); assert(att); - _mesa_set_renderbuffer_attachment(ctx, att, rb); + set_renderbuffer_attachment(ctx, att, rb); } rb->AttachedAnytime = GL_TRUE; } else { - _mesa_remove_attachment(ctx, att); + remove_attachment(ctx, att); } invalidate_framebuffer(fb); @@ -539,7 +534,7 @@ _mesa_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb) default: switch (rb->Format) { /* XXX This list is likely incomplete. */ - case MESA_FORMAT_RGB9_E5_FLOAT: + case MESA_FORMAT_R9G9B9E5_FLOAT: fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED; return; default:; @@ -637,7 +632,7 @@ _mesa_is_legal_color_format(const struct gl_context *ctx, GLenum baseFormat) * Is the given base format a legal format for a color renderbuffer? */ static GLboolean -is_format_color_renderable(const struct gl_context *ctx, gl_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); @@ -669,7 +664,7 @@ is_format_color_renderable(const struct gl_context *ctx, gl_format format, GLenu break; } - if (format == MESA_FORMAT_ARGB2101010 && internalFormat != GL_RGB10_A2) { + if (format == MESA_FORMAT_B10G10R10A2_UNORM && internalFormat != GL_RGB10_A2) { return GL_FALSE; } @@ -902,7 +897,7 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx, for (i = -2; i < (GLint) ctx->Const.MaxColorAttachments; i++) { struct gl_renderbuffer_attachment *att; GLenum f; - gl_format attFormat; + mesa_format attFormat; GLenum att_tex_target = GL_NONE; /* @@ -1090,7 +1085,7 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx, for (j = 0; j < ctx->Const.MaxDrawBuffers; j++) { if (fb->ColorDrawBuffer[j] != GL_NONE) { const struct gl_renderbuffer_attachment *att - = _mesa_get_attachment(ctx, fb, fb->ColorDrawBuffer[j]); + = get_attachment(ctx, fb, fb->ColorDrawBuffer[j]); assert(att); if (att->Type == GL_NONE) { fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT; @@ -1103,7 +1098,7 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx, /* Check that the ReadBuffer is present */ if (fb->ColorReadBuffer != GL_NONE) { const struct gl_renderbuffer_attachment *att - = _mesa_get_attachment(ctx, fb, fb->ColorReadBuffer); + = get_attachment(ctx, fb, fb->ColorReadBuffer); assert(att); if (att->Type == GL_NONE) { fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT; @@ -1251,7 +1246,7 @@ _mesa_detach_renderbuffer(struct gl_context *ctx, for (i = 0; i < BUFFER_COUNT; i++) { if (fb->Attachment[i].Texture == att || fb->Attachment[i].Renderbuffer == att) { - _mesa_remove_attachment(ctx, &fb->Attachment[i]); + remove_attachment(ctx, &fb->Attachment[i]); progress = true; } } @@ -1859,7 +1854,7 @@ _mesa_EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image) * we need to return zero. */ static GLint -get_component_bits(GLenum pname, GLenum baseFormat, gl_format format) +get_component_bits(GLenum pname, GLenum baseFormat, mesa_format format) { if (_mesa_base_format_has_channel(baseFormat, pname)) return _mesa_get_format_bits(format, pname); @@ -2037,26 +2032,12 @@ bind_framebuffer(GLenum target, GLuint framebuffer, bool allow_user_names) GLboolean bindReadBuf, bindDrawBuf; GET_CURRENT_CONTEXT(ctx); -#ifdef DEBUG - if (ctx->Extensions.ARB_framebuffer_object) { - ASSERT(ctx->Extensions.EXT_framebuffer_blit); - } -#endif - switch (target) { case GL_DRAW_FRAMEBUFFER_EXT: - if (!ctx->Extensions.EXT_framebuffer_blit) { - _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)"); - return; - } bindDrawBuf = GL_TRUE; bindReadBuf = GL_FALSE; break; case GL_READ_FRAMEBUFFER_EXT: - if (!ctx->Extensions.EXT_framebuffer_blit) { - _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)"); - return; - } bindDrawBuf = GL_FALSE; bindReadBuf = GL_TRUE; break; @@ -2190,26 +2171,15 @@ _mesa_DeleteFramebuffers(GLsizei n, const GLuint *framebuffers) ASSERT(fb == &DummyFramebuffer || fb->Name == framebuffers[i]); /* check if deleting currently bound framebuffer object */ - if (ctx->Extensions.EXT_framebuffer_blit) { - /* separate draw/read binding points */ - if (fb == ctx->DrawBuffer) { - /* bind default */ - ASSERT(fb->RefCount >= 2); - _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, 0); - } - if (fb == ctx->ReadBuffer) { - /* bind default */ - ASSERT(fb->RefCount >= 2); - _mesa_BindFramebuffer(GL_READ_FRAMEBUFFER_EXT, 0); - } + if (fb == ctx->DrawBuffer) { + /* bind default */ + ASSERT(fb->RefCount >= 2); + _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); } - else { - /* only one binding point for read/draw buffers */ - if (fb == ctx->DrawBuffer || fb == ctx->ReadBuffer) { - /* bind default */ - ASSERT(fb->RefCount >= 2); - _mesa_BindFramebuffer(GL_FRAMEBUFFER_EXT, 0); - } + if (fb == ctx->ReadBuffer) { + /* bind default */ + ASSERT(fb->RefCount >= 2); + _mesa_BindFramebuffer(GL_READ_FRAMEBUFFER, 0); } /* remove from hash table immediately, to free the ID */ @@ -2454,7 +2424,7 @@ framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target, } } - att = _mesa_get_attachment(ctx, fb, attachment); + att = get_attachment(ctx, fb, attachment); if (att == NULL) { _mesa_error(ctx, GL_INVALID_ENUM, "glFramebufferTexture%sEXT(attachment)", caller); @@ -2488,7 +2458,7 @@ framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target, reuse_framebuffer_texture_attachment(fb, BUFFER_STENCIL, BUFFER_DEPTH); } else { - _mesa_set_texture_attachment(ctx, fb, att, texObj, textarget, + set_texture_attachment(ctx, fb, att, texObj, textarget, level, zoffset, layered); if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) { /* Above we created a new renderbuffer and attached it to the @@ -2512,10 +2482,10 @@ framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target, texObj->_RenderToTexture = GL_TRUE; } else { - _mesa_remove_attachment(ctx, att); + remove_attachment(ctx, att); if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) { assert(att == &fb->Attachment[BUFFER_DEPTH]); - _mesa_remove_attachment(ctx, &fb->Attachment[BUFFER_STENCIL]); + remove_attachment(ctx, &fb->Attachment[BUFFER_STENCIL]); } } @@ -2683,7 +2653,7 @@ _mesa_FramebufferRenderbuffer(GLenum target, GLenum attachment, return; } - att = _mesa_get_attachment(ctx, fb, attachment); + att = get_attachment(ctx, fb, attachment); if (att == NULL) { _mesa_error(ctx, GL_INVALID_ENUM, "glFramebufferRenderbufferEXT(invalid attachment %s)", @@ -2785,7 +2755,7 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, } else { /* user-created framebuffer FBO */ - att = _mesa_get_attachment(ctx, buffer, attachment); + att = get_attachment(ctx, buffer, attachment); } if (att == NULL) { @@ -2797,8 +2767,8 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) { /* the depth and stencil attachments must point to the same buffer */ const struct gl_renderbuffer_attachment *depthAtt, *stencilAtt; - depthAtt = _mesa_get_attachment(ctx, buffer, GL_DEPTH_ATTACHMENT); - stencilAtt = _mesa_get_attachment(ctx, buffer, GL_STENCIL_ATTACHMENT); + 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" @@ -2908,7 +2878,7 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, "glGetFramebufferAttachmentParameterivEXT(pname)"); } else { - gl_format format = att->Renderbuffer->Format; + mesa_format format = att->Renderbuffer->Format; /* Page 235 (page 247 of the PDF) in section 6.1.13 of the OpenGL ES * 3.0.1 spec says: @@ -2925,11 +2895,11 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, return; } - if (format == MESA_FORMAT_S8) { + if (format == MESA_FORMAT_S_UINT8) { /* special cases */ *params = GL_INDEX; } - else if (format == MESA_FORMAT_Z32_FLOAT_X24S8) { + else if (format == MESA_FORMAT_Z32_FLOAT_S8X24_UINT) { /* depends on the attachment parameter */ if (attachment == GL_STENCIL_ATTACHMENT) { *params = GL_INDEX; @@ -3003,567 +2973,6 @@ invalid_pname_enum: } -void GLAPIENTRY -_mesa_GenerateMipmap(GLenum target) -{ - struct gl_texture_image *srcImage; - struct gl_texture_object *texObj; - GLboolean error; - - GET_CURRENT_CONTEXT(ctx); - - FLUSH_VERTICES(ctx, 0); - - switch (target) { - case GL_TEXTURE_1D: - error = _mesa_is_gles(ctx); - break; - case GL_TEXTURE_2D: - error = GL_FALSE; - break; - case GL_TEXTURE_3D: - error = ctx->API == API_OPENGLES; - break; - case GL_TEXTURE_CUBE_MAP: - error = !ctx->Extensions.ARB_texture_cube_map; - break; - case GL_TEXTURE_1D_ARRAY: - error = _mesa_is_gles(ctx) || !ctx->Extensions.EXT_texture_array; - break; - case GL_TEXTURE_2D_ARRAY: - error = (_mesa_is_gles(ctx) && ctx->Version < 30) - || !ctx->Extensions.EXT_texture_array; - break; - default: - error = GL_TRUE; - } - - if (error) { - _mesa_error(ctx, GL_INVALID_ENUM, "glGenerateMipmapEXT(target=%s)", - _mesa_lookup_enum_by_nr(target)); - return; - } - - texObj = _mesa_get_current_tex_object(ctx, target); - - if (texObj->BaseLevel >= texObj->MaxLevel) { - /* nothing to do */ - return; - } - - if (texObj->Target == GL_TEXTURE_CUBE_MAP && - !_mesa_cube_complete(texObj)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glGenerateMipmap(incomplete cube map)"); - return; - } - - _mesa_lock_texture(ctx, texObj); - - srcImage = _mesa_select_tex_image(ctx, texObj, target, texObj->BaseLevel); - if (!srcImage) { - _mesa_unlock_texture(ctx, texObj); - _mesa_error(ctx, GL_INVALID_OPERATION, - "glGenerateMipmap(zero size base image)"); - return; - } - - if (_mesa_is_enum_format_integer(srcImage->InternalFormat) || - _mesa_is_depthstencil_format(srcImage->InternalFormat) || - _mesa_is_stencil_format(srcImage->InternalFormat)) { - _mesa_unlock_texture(ctx, texObj); - _mesa_error(ctx, GL_INVALID_OPERATION, - "glGenerateMipmap(invalid internal format)"); - return; - } - - if (target == GL_TEXTURE_CUBE_MAP) { - GLuint face; - for (face = 0; face < 6; face++) - ctx->Driver.GenerateMipmap(ctx, - GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + face, - texObj); - } - else { - ctx->Driver.GenerateMipmap(ctx, target, texObj); - } - _mesa_unlock_texture(ctx, texObj); -} - - -static const struct gl_renderbuffer_attachment * -find_attachment(const struct gl_framebuffer *fb, - const struct gl_renderbuffer *rb) -{ - GLuint i; - for (i = 0; i < Elements(fb->Attachment); i++) { - if (fb->Attachment[i].Renderbuffer == rb) - return &fb->Attachment[i]; - } - return NULL; -} - - -/** - * Helper function for checking if the datatypes of color buffers are - * compatible for glBlitFramebuffer. From the 3.1 spec, page 198: - * - * "GL_INVALID_OPERATION is generated if mask contains GL_COLOR_BUFFER_BIT - * and any of the following conditions hold: - * - The read buffer contains fixed-point or floating-point values and any - * draw buffer contains neither fixed-point nor floating-point values. - * - The read buffer contains unsigned integer values and any draw buffer - * does not contain unsigned integer values. - * - The read buffer contains signed integer values and any draw buffer - * does not contain signed integer values." - */ -static GLboolean -compatible_color_datatypes(gl_format srcFormat, gl_format dstFormat) -{ - GLenum srcType = _mesa_get_format_datatype(srcFormat); - GLenum dstType = _mesa_get_format_datatype(dstFormat); - - if (srcType != GL_INT && srcType != GL_UNSIGNED_INT) { - assert(srcType == GL_UNSIGNED_NORMALIZED || - srcType == GL_SIGNED_NORMALIZED || - srcType == GL_FLOAT); - /* Boil any of those types down to GL_FLOAT */ - srcType = GL_FLOAT; - } - - if (dstType != GL_INT && dstType != GL_UNSIGNED_INT) { - assert(dstType == GL_UNSIGNED_NORMALIZED || - dstType == GL_SIGNED_NORMALIZED || - dstType == GL_FLOAT); - /* Boil any of those types down to GL_FLOAT */ - dstType = GL_FLOAT; - } - - return srcType == dstType; -} - - -static GLboolean -compatible_resolve_formats(const struct gl_renderbuffer *readRb, - const struct gl_renderbuffer *drawRb) -{ - GLenum readFormat, drawFormat; - - /* The simple case where we know the backing Mesa formats are the same. - */ - if (_mesa_get_srgb_format_linear(readRb->Format) == - _mesa_get_srgb_format_linear(drawRb->Format)) { - return GL_TRUE; - } - - /* The Mesa formats are different, so we must check whether the internal - * formats are compatible. - * - * Under some circumstances, the user may request e.g. two GL_RGBA8 - * textures and get two entirely different Mesa formats like RGBA8888 and - * ARGB8888. Drivers behaving like that should be able to cope with - * non-matching formats by themselves, because it's not the user's fault. - * - * Blits between linear and sRGB formats are also allowed. - */ - readFormat = _mesa_get_nongeneric_internalformat(readRb->InternalFormat); - drawFormat = _mesa_get_nongeneric_internalformat(drawRb->InternalFormat); - readFormat = _mesa_get_linear_internalformat(readFormat); - drawFormat = _mesa_get_linear_internalformat(drawFormat); - - if (readFormat == drawFormat) { - return GL_TRUE; - } - - return GL_FALSE; -} - -static GLboolean -is_valid_blit_filter(const struct gl_context *ctx, GLenum filter) -{ - switch (filter) { - case GL_NEAREST: - case GL_LINEAR: - return true; - case GL_SCALED_RESOLVE_FASTEST_EXT: - case GL_SCALED_RESOLVE_NICEST_EXT: - return ctx->Extensions.EXT_framebuffer_multisample_blit_scaled; - default: - return false; - } -} - -/** - * Blit rectangular region, optionally from one framebuffer to another. - * - * Note, if the src buffer is multisampled and the dest is not, this is - * when the samples must be resolved to a single color. - */ -void GLAPIENTRY -_mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, - GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, - GLbitfield mask, GLenum filter) -{ - const GLbitfield legalMaskBits = (GL_COLOR_BUFFER_BIT | - GL_DEPTH_BUFFER_BIT | - GL_STENCIL_BUFFER_BIT); - const struct gl_framebuffer *readFb, *drawFb; - GET_CURRENT_CONTEXT(ctx); - - FLUSH_VERTICES(ctx, 0); - - if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, - "glBlitFramebuffer(%d, %d, %d, %d, %d, %d, %d, %d, 0x%x, %s)\n", - srcX0, srcY0, srcX1, srcY1, - dstX0, dstY0, dstX1, dstY1, - mask, _mesa_lookup_enum_by_nr(filter)); - - if (ctx->NewState) { - _mesa_update_state(ctx); - } - - readFb = ctx->ReadBuffer; - drawFb = ctx->DrawBuffer; - - if (!readFb || !drawFb) { - /* This will normally never happen but someday we may want to - * support MakeCurrent() with no drawables. - */ - return; - } - - /* check for complete framebuffers */ - if (drawFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT || - readFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { - _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, - "glBlitFramebufferEXT(incomplete draw/read buffers)"); - return; - } - - if (!is_valid_blit_filter(ctx, filter)) { - _mesa_error(ctx, GL_INVALID_ENUM, "glBlitFramebufferEXT(%s)", - _mesa_lookup_enum_by_nr(filter)); - return; - } - - if ((filter == GL_SCALED_RESOLVE_FASTEST_EXT || - filter == GL_SCALED_RESOLVE_NICEST_EXT) && - (readFb->Visual.samples == 0 || drawFb->Visual.samples > 0)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebufferEXT(%s)", - _mesa_lookup_enum_by_nr(filter)); - return; - } - - if (mask & ~legalMaskBits) { - _mesa_error( ctx, GL_INVALID_VALUE, "glBlitFramebufferEXT(mask)"); - return; - } - - /* depth/stencil must be blitted with nearest filtering */ - if ((mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) - && filter != GL_NEAREST) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glBlitFramebufferEXT(depth/stencil requires GL_NEAREST filter)"); - return; - } - - /* get color read/draw renderbuffers */ - if (mask & GL_COLOR_BUFFER_BIT) { - const GLuint numColorDrawBuffers = ctx->DrawBuffer->_NumColorDrawBuffers; - const struct gl_renderbuffer *colorReadRb = readFb->_ColorReadBuffer; - const struct gl_renderbuffer *colorDrawRb = NULL; - GLuint i; - - /* From the EXT_framebuffer_object spec: - * - * "If a buffer is specified in <mask> and does not exist in both - * the read and draw framebuffers, the corresponding bit is silently - * ignored." - */ - if (!colorReadRb || numColorDrawBuffers == 0) { - mask &= ~GL_COLOR_BUFFER_BIT; - } - else { - for (i = 0; i < numColorDrawBuffers; i++) { - colorDrawRb = ctx->DrawBuffer->_ColorDrawBuffers[i]; - if (!colorDrawRb) - continue; - - /* Page 193 (page 205 of the PDF) in section 4.3.2 of the OpenGL - * ES 3.0.1 spec says: - * - * "If the source and destination buffers are identical, an - * INVALID_OPERATION error is generated. Different mipmap - * levels of a texture, different layers of a three- - * dimensional texture or two-dimensional array texture, and - * different faces of a cube map texture do not constitute - * identical buffers." - */ - if (_mesa_is_gles3(ctx) && (colorDrawRb == colorReadRb)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glBlitFramebuffer(source and destination color " - "buffer cannot be the same)"); - return; - } - - if (!compatible_color_datatypes(colorReadRb->Format, - colorDrawRb->Format)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glBlitFramebufferEXT(color buffer datatypes mismatch)"); - return; - } - /* extra checks for multisample copies... */ - if (readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) { - /* color formats must match */ - if (!compatible_resolve_formats(colorReadRb, colorDrawRb)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glBlitFramebufferEXT(bad src/dst multisample pixel formats)"); - return; - } - } - } - if (filter != GL_NEAREST) { - /* From EXT_framebuffer_multisample_blit_scaled specification: - * "Calling BlitFramebuffer will result in an INVALID_OPERATION error - * if filter is not NEAREST and read buffer contains integer data." - */ - GLenum type = _mesa_get_format_datatype(colorReadRb->Format); - if (type == GL_INT || type == GL_UNSIGNED_INT) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glBlitFramebufferEXT(integer color type)"); - return; - } - } - } - } - - if (mask & GL_STENCIL_BUFFER_BIT) { - struct gl_renderbuffer *readRb = - readFb->Attachment[BUFFER_STENCIL].Renderbuffer; - struct gl_renderbuffer *drawRb = - drawFb->Attachment[BUFFER_STENCIL].Renderbuffer; - - /* From the EXT_framebuffer_object spec: - * - * "If a buffer is specified in <mask> and does not exist in both - * the read and draw framebuffers, the corresponding bit is silently - * ignored." - */ - if ((readRb == NULL) || (drawRb == NULL)) { - mask &= ~GL_STENCIL_BUFFER_BIT; - } - else { - int read_z_bits, draw_z_bits; - - if (_mesa_is_gles3(ctx) && (drawRb == readRb)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glBlitFramebuffer(source and destination stencil " - "buffer cannot be the same)"); - return; - } - - if (_mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS) != - _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS)) { - /* There is no need to check the stencil datatype here, because - * there is only one: GL_UNSIGNED_INT. - */ - _mesa_error(ctx, GL_INVALID_OPERATION, - "glBlitFramebuffer(stencil attachment format mismatch)"); - return; - } - - read_z_bits = _mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS); - draw_z_bits = _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS); - - /* If both buffers also have depth data, the depth formats must match - * as well. If one doesn't have depth, it's not blitted, so we should - * ignore the depth format check. - */ - if (read_z_bits > 0 && draw_z_bits > 0 && - (read_z_bits != draw_z_bits || - _mesa_get_format_datatype(readRb->Format) != - _mesa_get_format_datatype(drawRb->Format))) { - - _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebuffer" - "(stencil attachment depth format mismatch)"); - return; - } - } - } - - if (mask & GL_DEPTH_BUFFER_BIT) { - struct gl_renderbuffer *readRb = - readFb->Attachment[BUFFER_DEPTH].Renderbuffer; - struct gl_renderbuffer *drawRb = - drawFb->Attachment[BUFFER_DEPTH].Renderbuffer; - - /* From the EXT_framebuffer_object spec: - * - * "If a buffer is specified in <mask> and does not exist in both - * the read and draw framebuffers, the corresponding bit is silently - * ignored." - */ - if ((readRb == NULL) || (drawRb == NULL)) { - mask &= ~GL_DEPTH_BUFFER_BIT; - } - else { - int read_s_bit, draw_s_bit; - - if (_mesa_is_gles3(ctx) && (drawRb == readRb)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glBlitFramebuffer(source and destination depth " - "buffer cannot be the same)"); - return; - } - - if ((_mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS) != - _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS)) || - (_mesa_get_format_datatype(readRb->Format) != - _mesa_get_format_datatype(drawRb->Format))) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glBlitFramebuffer(depth attachment format mismatch)"); - return; - } - - read_s_bit = _mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS); - draw_s_bit = _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS); - - /* If both buffers also have stencil data, the stencil formats must - * match as well. If one doesn't have stencil, it's not blitted, so - * we should ignore the stencil format check. - */ - if (read_s_bit > 0 && draw_s_bit > 0 && read_s_bit != draw_s_bit) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebuffer" - "(depth attachment stencil bits mismatch)"); - return; - } - } - } - - - if (_mesa_is_gles3(ctx)) { - /* Page 194 (page 206 of the PDF) in section 4.3.2 of the OpenGL ES - * 3.0.1 spec says: - * - * "If SAMPLE_BUFFERS for the draw framebuffer is greater than zero, - * an INVALID_OPERATION error is generated." - */ - if (drawFb->Visual.samples > 0) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glBlitFramebuffer(destination samples must be 0)"); - return; - } - - /* Page 194 (page 206 of the PDF) in section 4.3.2 of the OpenGL ES - * 3.0.1 spec says: - * - * "If SAMPLE_BUFFERS for the read framebuffer is greater than zero, - * no copy is performed and an INVALID_OPERATION error is generated - * if the formats of the read and draw framebuffers are not - * identical or if the source and destination rectangles are not - * defined with the same (X0, Y0) and (X1, Y1) bounds." - * - * The format check was made above because desktop OpenGL has the same - * requirement. - */ - if (readFb->Visual.samples > 0 - && (srcX0 != dstX0 || srcY0 != dstY0 - || srcX1 != dstX1 || srcY1 != dstY1)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glBlitFramebuffer(bad src/dst multisample region)"); - return; - } - } else { - if (readFb->Visual.samples > 0 && - drawFb->Visual.samples > 0 && - readFb->Visual.samples != drawFb->Visual.samples) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glBlitFramebufferEXT(mismatched samples)"); - return; - } - - /* extra checks for multisample copies... */ - if ((readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) && - (filter == GL_NEAREST || filter == GL_LINEAR)) { - /* src and dest region sizes must be the same */ - if (abs(srcX1 - srcX0) != abs(dstX1 - dstX0) || - abs(srcY1 - srcY0) != abs(dstY1 - dstY0)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glBlitFramebufferEXT(bad src/dst multisample region sizes)"); - return; - } - } - } - - if (!ctx->Extensions.EXT_framebuffer_blit) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebufferEXT"); - return; - } - - /* Debug code */ - if (DEBUG_BLIT) { - const struct gl_renderbuffer *colorReadRb = readFb->_ColorReadBuffer; - const struct gl_renderbuffer *colorDrawRb = NULL; - GLuint i = 0; - - printf("glBlitFramebuffer(%d, %d, %d, %d, %d, %d, %d, %d," - " 0x%x, 0x%x)\n", - srcX0, srcY0, srcX1, srcY1, - dstX0, dstY0, dstX1, dstY1, - mask, filter); - if (colorReadRb) { - const struct gl_renderbuffer_attachment *att; - - att = find_attachment(readFb, colorReadRb); - printf(" Src FBO %u RB %u (%dx%d) ", - readFb->Name, colorReadRb->Name, - colorReadRb->Width, colorReadRb->Height); - if (att && att->Texture) { - printf("Tex %u tgt 0x%x level %u face %u", - att->Texture->Name, - att->Texture->Target, - att->TextureLevel, - att->CubeMapFace); - } - printf("\n"); - - /* Print all active color render buffers */ - for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) { - colorDrawRb = ctx->DrawBuffer->_ColorDrawBuffers[i]; - if (!colorDrawRb) - continue; - - att = find_attachment(drawFb, colorDrawRb); - printf(" Dst FBO %u RB %u (%dx%d) ", - drawFb->Name, colorDrawRb->Name, - colorDrawRb->Width, colorDrawRb->Height); - if (att && att->Texture) { - printf("Tex %u tgt 0x%x level %u face %u", - att->Texture->Name, - att->Texture->Target, - att->TextureLevel, - att->CubeMapFace); - } - printf("\n"); - } - } - } - - if (!mask || - (srcX1 - srcX0) == 0 || (srcY1 - srcY0) == 0 || - (dstX1 - dstX0) == 0 || (dstY1 - dstY0) == 0) { - return; - } - - ASSERT(ctx->Driver.BlitFramebuffer); - ctx->Driver.BlitFramebuffer(ctx, - srcX0, srcY0, srcX1, srcY1, - dstX0, dstY0, dstX1, dstY1, - mask, filter); -} - - static void invalidate_framebuffer_storage(GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, |