X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fmain%2Ffbobject.c;h=ab53bac75399caa99756e5d2bb7f2769529d36da;hb=2aae3abd77dc28b3666bb0db04baff18d8f0aa51;hp=aefcaf35097e51ae4c17cba01fe75836abb2031a;hpb=9b1117095a78bbcbf22fef077f001d0fce969a0e;p=mesa.git diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c index aefcaf35097..ab53bac7539 100644 --- a/src/mesa/main/fbobject.c +++ b/src/mesa/main/fbobject.c @@ -31,6 +31,7 @@ * Brian Paul */ +#include #include "buffers.h" #include "context.h" @@ -38,8 +39,8 @@ #include "fbobject.h" #include "formats.h" #include "framebuffer.h" +#include "glformats.h" #include "hash.h" -#include "image.h" #include "macros.h" #include "mfeatures.h" #include "mtypes.h" @@ -49,9 +50,6 @@ #include "texobj.h" -/** Set this to 1 to help debug FBO incompleteness problems */ -#define DEBUG_FBO 0 - /** Set this to 1 to debug/log glBlitFramebuffer() calls */ #define DEBUG_BLIT 0 @@ -79,28 +77,8 @@ static struct gl_renderbuffer DummyRenderbuffer; static struct gl_framebuffer IncompleteFramebuffer; -/** - * Is the given FBO a user-created FBO? - */ -static inline GLboolean -is_user_fbo(const struct gl_framebuffer *fb) -{ - return fb->Name != 0; -} - - -/** - * Is the given FBO a window system FBO (like an X window)? - */ -static inline GLboolean -is_winsys_fbo(const struct gl_framebuffer *fb) -{ - return fb->Name == 0; -} - - static void -delete_dummy_renderbuffer(struct gl_renderbuffer *rb) +delete_dummy_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb) { /* no op */ } @@ -185,13 +163,13 @@ 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)); switch (target) { case GL_DRAW_FRAMEBUFFER: - return ctx->Extensions.EXT_framebuffer_blit && ctx->API == API_OPENGL - ? ctx->DrawBuffer : NULL; + return have_fb_blit ? ctx->DrawBuffer : NULL; case GL_READ_FRAMEBUFFER: - return ctx->Extensions.EXT_framebuffer_blit && ctx->API == API_OPENGL - ? ctx->ReadBuffer : NULL; + return have_fb_blit ? ctx->ReadBuffer : NULL; case GL_FRAMEBUFFER_EXT: return ctx->DrawBuffer; default: @@ -214,7 +192,7 @@ _mesa_get_attachment(struct gl_context *ctx, struct gl_framebuffer *fb, { GLuint i; - assert(is_user_fbo(fb)); + assert(_mesa_is_user_fbo(fb)); switch (attachment) { case GL_COLOR_ATTACHMENT0_EXT: @@ -244,7 +222,7 @@ _mesa_get_attachment(struct gl_context *ctx, struct gl_framebuffer *fb, } return &fb->Attachment[BUFFER_COLOR0 + i]; case GL_DEPTH_STENCIL_ATTACHMENT: - if (ctx->API != API_OPENGL) + if (!_mesa_is_desktop_gl(ctx)) return NULL; /* fall-through */ case GL_DEPTH_ATTACHMENT_EXT: @@ -265,7 +243,7 @@ static struct gl_renderbuffer_attachment * _mesa_get_fb0_attachment(struct gl_context *ctx, struct gl_framebuffer *fb, GLenum attachment) { - assert(is_winsys_fbo(fb)); + assert(_mesa_is_winsys_fbo(fb)); switch (attachment) { case GL_FRONT_LEFT: @@ -482,11 +460,9 @@ _mesa_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb) static void att_incomplete(const char *msg) { -#if DEBUG_FBO - _mesa_debug(NULL, "attachment incomplete: %s\n", msg); -#else - (void) msg; -#endif + if (MESA_DEBUG_FLAGS & DEBUG_INCOMPLETE_FBO) { + _mesa_debug(NULL, "attachment incomplete: %s\n", msg); + } } @@ -496,12 +472,9 @@ att_incomplete(const char *msg) static void fbo_incomplete(const char *msg, int index) { -#if DEBUG_FBO - _mesa_debug(NULL, "FBO Incomplete: %s [%d]\n", msg, index); -#else - (void) msg; - (void) index; -#endif + if (MESA_DEBUG_FLAGS & DEBUG_INCOMPLETE_FBO) { + _mesa_debug(NULL, "FBO Incomplete: %s [%d]\n", msg, index); + } } @@ -711,7 +684,10 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx, GLint i; GLuint j; - assert(is_user_fbo(fb)); + assert(_mesa_is_user_fbo(fb)); + + /* we're changing framebuffer fields here */ + FLUSH_VERTICES(ctx, _NEW_BUFFERS); numImages = 0; fb->Width = 0; @@ -833,10 +809,18 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx, return; } } + + /* Check that the format is valid. (MESA_FORMAT_NONE means unsupported) + */ + if (att->Type == GL_RENDERBUFFER && + att->Renderbuffer->Format == MESA_FORMAT_NONE) { + fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED; + fbo_incomplete("unsupported renderbuffer format", i); + return; + } } -#if FEATURE_GL - if (ctx->API == API_OPENGL && !ctx->Extensions.ARB_ES2_compatibility) { + if (_mesa_is_desktop_gl(ctx) && !ctx->Extensions.ARB_ES2_compatibility) { /* Check that all DrawBuffers are present */ for (j = 0; j < ctx->Const.MaxDrawBuffers; j++) { if (fb->ColorDrawBuffer[j] != GL_NONE) { @@ -863,9 +847,6 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx, } } } -#else - (void) j; -#endif if (numImages == 0) { fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT; @@ -903,7 +884,7 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx, GLboolean GLAPIENTRY -_mesa_IsRenderbufferEXT(GLuint renderbuffer) +_mesa_IsRenderbuffer(GLuint renderbuffer) { GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); @@ -917,7 +898,7 @@ _mesa_IsRenderbufferEXT(GLuint renderbuffer) void GLAPIENTRY -_mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer) +_mesa_BindRenderbuffer(GLenum target, GLuint renderbuffer) { struct gl_renderbuffer *newRb; GET_CURRENT_CONTEXT(ctx); @@ -939,7 +920,9 @@ _mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer) /* ID was reserved, but no real renderbuffer object made yet */ newRb = NULL; } - else if (!newRb && ctx->Extensions.ARB_framebuffer_object) { + else if (!newRb + && _mesa_is_desktop_gl(ctx) + && ctx->Extensions.ARB_framebuffer_object) { /* All RB IDs must be Gen'd */ _mesa_error(ctx, GL_INVALID_OPERATION, "glBindRenderbuffer(buffer)"); return; @@ -989,7 +972,7 @@ detach_renderbuffer(struct gl_context *ctx, void GLAPIENTRY -_mesa_DeleteRenderbuffersEXT(GLsizei n, const GLuint *renderbuffers) +_mesa_DeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers) { GLint i; GET_CURRENT_CONTEXT(ctx); @@ -1006,13 +989,13 @@ _mesa_DeleteRenderbuffersEXT(GLsizei n, const GLuint *renderbuffers) if (rb == ctx->CurrentRenderbuffer) { /* bind default */ ASSERT(rb->RefCount >= 2); - _mesa_BindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); + _mesa_BindRenderbuffer(GL_RENDERBUFFER_EXT, 0); } - if (is_user_fbo(ctx->DrawBuffer)) { + if (_mesa_is_user_fbo(ctx->DrawBuffer)) { detach_renderbuffer(ctx, ctx->DrawBuffer, rb); } - if (is_user_fbo(ctx->ReadBuffer) + if (_mesa_is_user_fbo(ctx->ReadBuffer) && ctx->ReadBuffer != ctx->DrawBuffer) { detach_renderbuffer(ctx, ctx->ReadBuffer, rb); } @@ -1034,7 +1017,7 @@ _mesa_DeleteRenderbuffersEXT(GLsizei n, const GLuint *renderbuffers) void GLAPIENTRY -_mesa_GenRenderbuffersEXT(GLsizei n, GLuint *renderbuffers) +_mesa_GenRenderbuffers(GLsizei n, GLuint *renderbuffers) { GET_CURRENT_CONTEXT(ctx); GLuint first; @@ -1091,13 +1074,15 @@ _mesa_base_fbo_format(struct gl_context *ctx, GLenum internalFormat) case GL_ALPHA8: case GL_ALPHA12: case GL_ALPHA16: - return 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->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: @@ -1105,139 +1090,160 @@ _mesa_base_fbo_format(struct gl_context *ctx, GLenum internalFormat) case GL_LUMINANCE12_ALPHA4: case GL_LUMINANCE12_ALPHA12: case GL_LUMINANCE16_ALPHA16: - return 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->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: case GL_R3_G3_B2: case GL_RGB4: case GL_RGB5: - case GL_RGB8: case GL_RGB10: case GL_RGB12: case GL_RGB16: + return _mesa_is_desktop_gl(ctx) ? GL_RGB : 0; case GL_SRGB8_EXT: - return GL_RGB; - case GL_RGBA: - case GL_RGBA2: + return _mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx) ? GL_RGB : 0; case GL_RGBA4: case GL_RGB5_A1: case GL_RGBA8: - case GL_RGB10_A2: + return GL_RGBA; + case GL_RGBA: + case GL_RGBA2: case GL_RGBA12: case GL_RGBA16: + return _mesa_is_desktop_gl(ctx) ? GL_RGBA : 0; + case GL_RGB10_A2: case GL_SRGB8_ALPHA8_EXT: - return GL_RGBA; + return _mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx) ? GL_RGBA : 0; case GL_STENCIL_INDEX: case GL_STENCIL_INDEX1_EXT: case GL_STENCIL_INDEX4_EXT: - case GL_STENCIL_INDEX8_EXT: case GL_STENCIL_INDEX16_EXT: + /* There are extensions for GL_STENCIL_INDEX1 and GL_STENCIL_INDEX4 in + * OpenGL ES, but Mesa does not currently support them. + */ + return _mesa_is_desktop_gl(ctx) ? GL_STENCIL_INDEX : 0; + case GL_STENCIL_INDEX8_EXT: return GL_STENCIL_INDEX; case GL_DEPTH_COMPONENT: + case GL_DEPTH_COMPONENT32: + return _mesa_is_desktop_gl(ctx) ? GL_DEPTH_COMPONENT : 0; case GL_DEPTH_COMPONENT16: case GL_DEPTH_COMPONENT24: - case GL_DEPTH_COMPONENT32: return GL_DEPTH_COMPONENT; case GL_DEPTH_STENCIL_EXT: + return _mesa_is_desktop_gl(ctx) + && ctx->Extensions.EXT_packed_depth_stencil + ? GL_DEPTH_STENCIL_EXT : 0; case GL_DEPTH24_STENCIL8_EXT: - if (ctx->Extensions.EXT_packed_depth_stencil) - return GL_DEPTH_STENCIL_EXT; - else - return 0; + return ctx->Extensions.EXT_packed_depth_stencil + ? GL_DEPTH_STENCIL_EXT : 0; case GL_DEPTH_COMPONENT32F: - if (ctx->Extensions.ARB_depth_buffer_float) - return GL_DEPTH_COMPONENT; - else - return 0; + return ctx->Version >= 30 + || (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ARB_depth_buffer_float) + ? GL_DEPTH_COMPONENT : 0; case GL_DEPTH32F_STENCIL8: - if (ctx->Extensions.ARB_depth_buffer_float) - return GL_DEPTH_STENCIL; - else - return 0; + return ctx->Version >= 30 + || (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ARB_depth_buffer_float) + ? GL_DEPTH_STENCIL : 0; case GL_RED: - case GL_R8: case GL_R16: - return ctx->Extensions.ARB_texture_rg ? GL_RED : 0; + return _mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_rg + ? GL_RED : 0; + case GL_R8: + return ctx->API != API_OPENGLES && ctx->Extensions.ARB_texture_rg + ? GL_RED : 0; case GL_RG: - case GL_RG8: case GL_RG16: - return ctx->Extensions.ARB_texture_rg ? GL_RG : 0; + return _mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_rg + ? 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: case GL_R16_SNORM: - return ctx->Extensions.EXT_texture_snorm ? GL_RED : 0; + return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm + ? GL_RED : 0; case GL_RG_SNORM: case GL_RG8_SNORM: case GL_RG16_SNORM: - return ctx->Extensions.EXT_texture_snorm ? GL_RG : 0; + return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm + ? GL_RG : 0; case GL_RGB_SNORM: case GL_RGB8_SNORM: case GL_RGB16_SNORM: - return ctx->Extensions.EXT_texture_snorm ? GL_RGB : 0; + return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm + ? GL_RGB : 0; case GL_RGBA_SNORM: case GL_RGBA8_SNORM: case GL_RGBA16_SNORM: - return ctx->Extensions.EXT_texture_snorm ? GL_RGBA : 0; + return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm + ? GL_RGBA : 0; case GL_ALPHA_SNORM: case GL_ALPHA8_SNORM: case GL_ALPHA16_SNORM: - return ctx->Extensions.EXT_texture_snorm && + return ctx->API == API_OPENGL_COMPAT && + ctx->Extensions.EXT_texture_snorm && ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0; - case GL_LUMINANCE_SNORM: - case GL_LUMINANCE8_SNORM: - case GL_LUMINANCE16_SNORM: - return ctx->Extensions.EXT_texture_snorm && - ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0; - case GL_LUMINANCE_ALPHA_SNORM: - case GL_LUMINANCE8_ALPHA8_SNORM: - case GL_LUMINANCE16_ALPHA16_SNORM: - return ctx->Extensions.EXT_texture_snorm && - ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0; - case GL_INTENSITY_SNORM: - case GL_INTENSITY8_SNORM: - case GL_INTENSITY16_SNORM: - return ctx->Extensions.EXT_texture_snorm && - ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0; case GL_R16F: case GL_R32F: - return ctx->Extensions.ARB_texture_rg && - ctx->Extensions.ARB_texture_float ? GL_RED : 0; + return ctx->Version >= 30 + || (ctx->API == API_OPENGL_COMPAT && + ctx->Extensions.ARB_texture_rg && + ctx->Extensions.ARB_texture_float) ? GL_RED : 0; case GL_RG16F: case GL_RG32F: - return ctx->Extensions.ARB_texture_rg && - ctx->Extensions.ARB_texture_float ? GL_RG : 0; + return ctx->Version >= 30 + || (ctx->API == API_OPENGL_COMPAT && + ctx->Extensions.ARB_texture_rg && + ctx->Extensions.ARB_texture_float) ? GL_RG : 0; case GL_RGB16F: case GL_RGB32F: - return ctx->Extensions.ARB_texture_float ? GL_RGB : 0; + return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_float) + || _mesa_is_gles3(ctx) + ? GL_RGB : 0; case GL_RGBA16F: case GL_RGBA32F: - return ctx->Extensions.ARB_texture_float ? GL_RGBA : 0; + return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_float) + || _mesa_is_gles3(ctx) + ? GL_RGBA : 0; case GL_ALPHA16F_ARB: case GL_ALPHA32F_ARB: - return ctx->Extensions.ARB_texture_float && + return ctx->API == API_OPENGL_COMPAT && + ctx->Extensions.ARB_texture_float && ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0; case GL_LUMINANCE16F_ARB: case GL_LUMINANCE32F_ARB: - return ctx->Extensions.ARB_texture_float && + return ctx->API == API_OPENGL_COMPAT && + ctx->Extensions.ARB_texture_float && ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0; case GL_LUMINANCE_ALPHA16F_ARB: case GL_LUMINANCE_ALPHA32F_ARB: - return ctx->Extensions.ARB_texture_float && + return ctx->API == API_OPENGL_COMPAT && + ctx->Extensions.ARB_texture_float && ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0; case GL_INTENSITY16F_ARB: case GL_INTENSITY32F_ARB: - return ctx->Extensions.ARB_texture_float && + return ctx->API == API_OPENGL_COMPAT && + ctx->Extensions.ARB_texture_float && ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0; case GL_RGB9_E5: - return ctx->Extensions.EXT_texture_shared_exponent ? GL_RGB : 0; + return (_mesa_is_desktop_gl(ctx) + && ctx->Extensions.EXT_texture_shared_exponent) + || _mesa_is_gles3(ctx) ? GL_RGB : 0; case GL_R11F_G11F_B10F: - return ctx->Extensions.EXT_packed_float ? GL_RGB : 0; + return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_packed_float) + || _mesa_is_gles3(ctx) ? GL_RGB : 0; case GL_RGBA8UI_EXT: case GL_RGBA16UI_EXT: @@ -1245,7 +1251,9 @@ _mesa_base_fbo_format(struct gl_context *ctx, GLenum internalFormat) case GL_RGBA8I_EXT: case GL_RGBA16I_EXT: case GL_RGBA32I_EXT: - return ctx->Extensions.EXT_texture_integer ? GL_RGBA : 0; + return ctx->Version >= 30 + || (_mesa_is_desktop_gl(ctx) && + ctx->Extensions.EXT_texture_integer) ? GL_RGBA : 0; case GL_RGB8UI_EXT: case GL_RGB16UI_EXT: @@ -1253,7 +1261,9 @@ _mesa_base_fbo_format(struct gl_context *ctx, GLenum internalFormat) case GL_RGB8I_EXT: case GL_RGB16I_EXT: case GL_RGB32I_EXT: - return ctx->Extensions.EXT_texture_integer ? GL_RGB : 0; + return ctx->Version >= 30 + || (_mesa_is_desktop_gl(ctx) && + ctx->Extensions.EXT_texture_integer) ? GL_RGB : 0; case GL_R8UI: case GL_R8I: @@ -1261,8 +1271,10 @@ _mesa_base_fbo_format(struct gl_context *ctx, GLenum internalFormat) case GL_R16I: case GL_R32UI: case GL_R32I: - return ctx->Extensions.ARB_texture_rg && - ctx->Extensions.EXT_texture_integer ? GL_RED : 0; + return ctx->Version >= 30 + || (_mesa_is_desktop_gl(ctx) && + ctx->Extensions.ARB_texture_rg && + ctx->Extensions.EXT_texture_integer) ? GL_RED : 0; case GL_RG8UI: case GL_RG8I: @@ -1270,8 +1282,10 @@ _mesa_base_fbo_format(struct gl_context *ctx, GLenum internalFormat) case GL_RG16I: case GL_RG32UI: case GL_RG32I: - return ctx->Extensions.ARB_texture_rg && - ctx->Extensions.EXT_texture_integer ? GL_RG : 0; + return ctx->Version >= 30 + || (_mesa_is_desktop_gl(ctx) && + ctx->Extensions.ARB_texture_rg && + ctx->Extensions.EXT_texture_integer) ? GL_RG : 0; case GL_INTENSITY8I_EXT: case GL_INTENSITY8UI_EXT: @@ -1279,7 +1293,8 @@ _mesa_base_fbo_format(struct gl_context *ctx, GLenum internalFormat) case GL_INTENSITY16UI_EXT: case GL_INTENSITY32I_EXT: case GL_INTENSITY32UI_EXT: - return ctx->Extensions.EXT_texture_integer && + return ctx->API == API_OPENGL_COMPAT && + ctx->Extensions.EXT_texture_integer && ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0; case GL_LUMINANCE8I_EXT: @@ -1288,7 +1303,8 @@ _mesa_base_fbo_format(struct gl_context *ctx, GLenum internalFormat) case GL_LUMINANCE16UI_EXT: case GL_LUMINANCE32I_EXT: case GL_LUMINANCE32UI_EXT: - return ctx->Extensions.EXT_texture_integer && + return ctx->API == API_OPENGL_COMPAT && + ctx->Extensions.EXT_texture_integer && ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0; case GL_LUMINANCE_ALPHA8I_EXT: @@ -1297,11 +1313,28 @@ _mesa_base_fbo_format(struct gl_context *ctx, GLenum internalFormat) case GL_LUMINANCE_ALPHA16UI_EXT: case GL_LUMINANCE_ALPHA32I_EXT: case GL_LUMINANCE_ALPHA32UI_EXT: - return ctx->Extensions.EXT_texture_integer && + return ctx->API == API_OPENGL_COMPAT && + ctx->Extensions.EXT_texture_integer && ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0; + case GL_ALPHA8I_EXT: + case GL_ALPHA8UI_EXT: + case GL_ALPHA16I_EXT: + case GL_ALPHA16UI_EXT: + case GL_ALPHA32I_EXT: + case GL_ALPHA32UI_EXT: + return ctx->API == API_OPENGL_COMPAT && + ctx->Extensions.EXT_texture_integer && + ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0; + case GL_RGB10_A2UI: - return ctx->Extensions.ARB_texture_rgb10_a2ui ? GL_RGBA : 0; + return (_mesa_is_desktop_gl(ctx) && + ctx->Extensions.ARB_texture_rgb10_a2ui) + || _mesa_is_gles3(ctx) ? GL_RGBA : 0; + + case GL_RGB565: + return _mesa_is_gles(ctx) || ctx->Extensions.ARB_ES2_compatibility + ? GL_RGB : 0; default: return 0; } @@ -1318,7 +1351,7 @@ invalidate_rb(GLuint key, void *data, void *userData) struct gl_renderbuffer *rb = (struct gl_renderbuffer *) userData; /* If this is a user-created FBO */ - if (is_user_fbo(fb)) { + if (_mesa_is_user_fbo(fb)) { GLuint i; for (i = 0; i < BUFFER_COUNT; i++) { struct gl_renderbuffer_attachment *att = fb->Attachment + i; @@ -1338,9 +1371,9 @@ invalidate_rb(GLuint key, void *data, void *userData) /** - * Helper function used by _mesa_RenderbufferStorageEXT() and + * Helper function used by _mesa_RenderbufferStorage() and * _mesa_RenderbufferStorageMultisample(). - * samples will be NO_SAMPLES if called by _mesa_RenderbufferStorageEXT(). + * samples will be NO_SAMPLES if called by _mesa_RenderbufferStorage(). */ static void renderbuffer_storage(GLenum target, GLenum internalFormat, @@ -1395,7 +1428,8 @@ renderbuffer_storage(GLenum target, GLenum internalFormat, if (rb->InternalFormat == internalFormat && rb->Width == (GLuint) width && - rb->Height == (GLuint) height) { + rb->Height == (GLuint) height && + rb->NumSamples == samples) { /* no change in allocation needed */ return; } @@ -1408,7 +1442,7 @@ renderbuffer_storage(GLenum target, GLenum internalFormat, ASSERT(rb->AllocStorage); if (rb->AllocStorage(ctx, rb, internalFormat, width, height)) { /* No error - check/set fields now */ - assert(rb->Format != MESA_FORMAT_NONE); + /* If rb->Format == MESA_FORMAT_NONE, the format is unsupported. */ assert(rb->Width == (GLuint) width); assert(rb->Height == (GLuint) height); rb->InternalFormat = internalFormat; @@ -1432,7 +1466,6 @@ renderbuffer_storage(GLenum target, GLenum internalFormat, } -#if FEATURE_OES_EGL_image void GLAPIENTRY _mesa_EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image) { @@ -1463,12 +1496,11 @@ _mesa_EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image) ctx->Driver.EGLImageTargetRenderbufferStorage(ctx, rb, image); } -#endif /** - * Helper function for _mesa_GetRenderbufferParameterivEXT() and - * _mesa_GetFramebufferAttachmentParameterivEXT() + * Helper function for _mesa_GetRenderbufferParameteriv() and + * _mesa_GetFramebufferAttachmentParameteriv() * We have to be careful to respect the base format. For example, if a * renderbuffer/texture was created with internalFormat=GL_RGB but the * driver actually chose a GL_RGBA format, when the user queries ALPHA_SIZE @@ -1486,7 +1518,7 @@ get_component_bits(GLenum pname, GLenum baseFormat, gl_format format) void GLAPIENTRY -_mesa_RenderbufferStorageEXT(GLenum target, GLenum internalFormat, +_mesa_RenderbufferStorage(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height) { /* GL_ARB_fbo says calling this function is equivalent to calling @@ -1528,7 +1560,7 @@ _es_RenderbufferStorageEXT(GLenum target, GLenum internalFormat, void GLAPIENTRY -_mesa_GetRenderbufferParameterivEXT(GLenum target, GLenum pname, GLint *params) +_mesa_GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params) { struct gl_renderbuffer *rb; GET_CURRENT_CONTEXT(ctx); @@ -1571,7 +1603,8 @@ _mesa_GetRenderbufferParameterivEXT(GLenum target, GLenum pname, GLint *params) *params = get_component_bits(pname, rb->_BaseFormat, rb->Format); break; case GL_RENDERBUFFER_SAMPLES: - if (ctx->Extensions.ARB_framebuffer_object) { + if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_framebuffer_object) + || _mesa_is_gles3(ctx)) { *params = rb->NumSamples; break; } @@ -1585,7 +1618,7 @@ _mesa_GetRenderbufferParameterivEXT(GLenum target, GLenum pname, GLint *params) GLboolean GLAPIENTRY -_mesa_IsFramebufferEXT(GLuint framebuffer) +_mesa_IsFramebuffer(GLuint framebuffer) { GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); @@ -1609,7 +1642,7 @@ check_begin_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb) GLuint i; ASSERT(ctx->Driver.RenderTexture); - if (is_winsys_fbo(fb)) + if (_mesa_is_winsys_fbo(fb)) return; /* can't render to texture with winsys framebuffers */ for (i = 0; i < BUFFER_COUNT; i++) { @@ -1629,7 +1662,7 @@ check_begin_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb) static void check_end_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb) { - if (is_winsys_fbo(fb)) + if (_mesa_is_winsys_fbo(fb)) return; /* can't render to texture with winsys framebuffers */ if (ctx->Driver.FinishRenderTexture) { @@ -1645,7 +1678,7 @@ check_end_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb) void GLAPIENTRY -_mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer) +_mesa_BindFramebuffer(GLenum target, GLuint framebuffer) { struct gl_framebuffer *newDrawFb, *newReadFb; struct gl_framebuffer *oldDrawFb, *oldReadFb; @@ -1668,7 +1701,6 @@ _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer) } switch (target) { -#if FEATURE_EXT_framebuffer_blit case GL_DRAW_FRAMEBUFFER_EXT: if (!ctx->Extensions.EXT_framebuffer_blit) { _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)"); @@ -1685,7 +1717,6 @@ _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer) bindDrawBuf = GL_FALSE; bindReadBuf = GL_TRUE; break; -#endif case GL_FRAMEBUFFER_EXT: bindDrawBuf = GL_TRUE; bindReadBuf = GL_TRUE; @@ -1702,7 +1733,9 @@ _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer) /* ID was reserved, but no real framebuffer object made yet */ newDrawFb = NULL; } - else if (!newDrawFb && ctx->Extensions.ARB_framebuffer_object) { + else if (!newDrawFb + && _mesa_is_desktop_gl(ctx) + && ctx->Extensions.ARB_framebuffer_object) { /* All FBO IDs must be Gen'd */ _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFramebuffer(buffer)"); return; @@ -1764,11 +1797,8 @@ _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer) if (bindDrawBuf) { FLUSH_VERTICES(ctx, _NEW_BUFFERS); - /* check if old read/draw buffers were render-to-texture */ - if (!bindReadBuf) - check_end_texture_render(ctx, oldReadFb); - - if (oldDrawFb != oldReadFb) + /* check if old framebuffer had any texture attachments */ + if (oldDrawFb) check_end_texture_render(ctx, oldDrawFb); /* check if newly bound framebuffer has any texture attachments */ @@ -1784,7 +1814,7 @@ _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer) void GLAPIENTRY -_mesa_DeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers) +_mesa_DeleteFramebuffers(GLsizei n, const GLuint *framebuffers) { GLint i; GET_CURRENT_CONTEXT(ctx); @@ -1805,12 +1835,12 @@ _mesa_DeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers) if (fb == ctx->DrawBuffer) { /* bind default */ ASSERT(fb->RefCount >= 2); - _mesa_BindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0); + _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, 0); } if (fb == ctx->ReadBuffer) { /* bind default */ ASSERT(fb->RefCount >= 2); - _mesa_BindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0); + _mesa_BindFramebuffer(GL_READ_FRAMEBUFFER_EXT, 0); } } else { @@ -1818,7 +1848,7 @@ _mesa_DeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers) if (fb == ctx->DrawBuffer || fb == ctx->ReadBuffer) { /* bind default */ ASSERT(fb->RefCount >= 2); - _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + _mesa_BindFramebuffer(GL_FRAMEBUFFER_EXT, 0); } } @@ -1838,7 +1868,7 @@ _mesa_DeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers) void GLAPIENTRY -_mesa_GenFramebuffersEXT(GLsizei n, GLuint *framebuffers) +_mesa_GenFramebuffers(GLsizei n, GLuint *framebuffers) { GET_CURRENT_CONTEXT(ctx); GLuint first; @@ -1869,7 +1899,7 @@ _mesa_GenFramebuffersEXT(GLsizei n, GLuint *framebuffers) GLenum GLAPIENTRY -_mesa_CheckFramebufferStatusEXT(GLenum target) +_mesa_CheckFramebufferStatus(GLenum target) { struct gl_framebuffer *buffer; GET_CURRENT_CONTEXT(ctx); @@ -1882,7 +1912,7 @@ _mesa_CheckFramebufferStatusEXT(GLenum target) return 0; } - if (is_winsys_fbo(buffer)) { + if (_mesa_is_winsys_fbo(buffer)) { /* The window system / default framebuffer is always complete */ return GL_FRAMEBUFFER_COMPLETE_EXT; } @@ -1923,7 +1953,10 @@ reuse_framebuffer_texture_attachment(struct gl_framebuffer *fb, /** - * Common code called by glFramebufferTexture1D/2D/3DEXT(). + * Common code called by glFramebufferTexture1D/2D/3DEXT() and + * glFramebufferTextureLayerEXT(). + * Note: glFramebufferTextureLayerEXT() has no textarget parameter so we'll + * get textarget=0 in that case. */ static void framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target, @@ -1933,6 +1966,7 @@ framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target, struct gl_renderbuffer_attachment *att; struct gl_texture_object *texObj = NULL; struct gl_framebuffer *fb; + GLenum maxLevelsTarget; ASSERT_OUTSIDE_BEGIN_END(ctx); @@ -1944,7 +1978,7 @@ framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target, } /* check framebuffer binding */ - if (is_winsys_fbo(fb)) { + if (_mesa_is_winsys_fbo(fb)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glFramebufferTexture%sEXT", caller); return; @@ -1959,12 +1993,18 @@ framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target, texObj = _mesa_lookup_texture(ctx, texture); if (texObj != NULL) { if (textarget == 0) { - /* XXX what's the purpose of this? */ + /* If textarget == 0 it means 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. + */ err = (texObj->Target != GL_TEXTURE_3D) && (texObj->Target != GL_TEXTURE_1D_ARRAY_EXT) && - (texObj->Target != GL_TEXTURE_2D_ARRAY_EXT); + (texObj->Target != GL_TEXTURE_2D_ARRAY_EXT) && + (texObj->Target != GL_TEXTURE_CUBE_MAP_ARRAY); } else { + /* Make sure textarget is consistent with the texture's type */ err = (texObj->Target == GL_TEXTURE_CUBE_MAP) ? !_mesa_is_cube_face(textarget) : (texObj->Target != textarget); @@ -1994,16 +2034,19 @@ framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target, } } else if ((texObj->Target == GL_TEXTURE_1D_ARRAY_EXT) || - (texObj->Target == GL_TEXTURE_2D_ARRAY_EXT)) { - if (zoffset < 0 || zoffset >= ctx->Const.MaxArrayTextureLayers) { + (texObj->Target == GL_TEXTURE_2D_ARRAY_EXT) || + (texObj->Target == GL_TEXTURE_CUBE_MAP_ARRAY)) { + if (zoffset < 0 || + zoffset >= (GLint) ctx->Const.MaxArrayTextureLayers) { _mesa_error(ctx, GL_INVALID_VALUE, "glFramebufferTexture%sEXT(layer)", caller); return; } } + maxLevelsTarget = textarget ? textarget : texObj->Target; if ((level < 0) || - (level >= _mesa_max_texture_levels(ctx, texObj->Target))) { + (level >= _mesa_max_texture_levels(ctx, maxLevelsTarget))) { _mesa_error(ctx, GL_INVALID_VALUE, "glFramebufferTexture%sEXT(level)", caller); return; @@ -2022,7 +2065,11 @@ framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target, _glthread_LOCK_MUTEX(fb->Mutex); if (texObj) { if (attachment == GL_DEPTH_ATTACHMENT && - texObj == fb->Attachment[BUFFER_STENCIL].Texture) { + texObj == fb->Attachment[BUFFER_STENCIL].Texture && + level == fb->Attachment[BUFFER_STENCIL].TextureLevel && + _mesa_tex_target_to_face(textarget) == + fb->Attachment[BUFFER_STENCIL].CubeMapFace && + zoffset == fb->Attachment[BUFFER_STENCIL].Zoffset) { /* The texture object is already attached to the stencil attachment * point. Don't create a new renderbuffer; just reuse the stencil * attachment's. This is required to prevent a GL error in @@ -2031,8 +2078,12 @@ framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target, reuse_framebuffer_texture_attachment(fb, BUFFER_DEPTH, BUFFER_STENCIL); } else if (attachment == GL_STENCIL_ATTACHMENT && - texObj == fb->Attachment[BUFFER_DEPTH].Texture) { - /* As above, but with depth and stencil juxtasposed. */ + texObj == fb->Attachment[BUFFER_DEPTH].Texture && + level == fb->Attachment[BUFFER_DEPTH].TextureLevel && + _mesa_tex_target_to_face(textarget) == + fb->Attachment[BUFFER_DEPTH].CubeMapFace && + zoffset == fb->Attachment[BUFFER_DEPTH].Zoffset) { + /* As above, but with depth and stencil transposed. */ reuse_framebuffer_texture_attachment(fb, BUFFER_STENCIL, BUFFER_DEPTH); } else { @@ -2075,7 +2126,7 @@ framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target, void GLAPIENTRY -_mesa_FramebufferTexture1DEXT(GLenum target, GLenum attachment, +_mesa_FramebufferTexture1D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) { GET_CURRENT_CONTEXT(ctx); @@ -2108,7 +2159,7 @@ _mesa_FramebufferTexture1DEXT(GLenum target, GLenum attachment, void GLAPIENTRY -_mesa_FramebufferTexture2DEXT(GLenum target, GLenum attachment, +_mesa_FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) { GET_CURRENT_CONTEXT(ctx); @@ -2121,7 +2172,8 @@ _mesa_FramebufferTexture2DEXT(GLenum target, GLenum attachment, error = GL_FALSE; break; case GL_TEXTURE_RECTANGLE: - error = !ctx->Extensions.NV_texture_rectangle; + error = _mesa_is_gles(ctx) + || !ctx->Extensions.NV_texture_rectangle; break; case GL_TEXTURE_CUBE_MAP_POSITIVE_X: case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: @@ -2132,7 +2184,8 @@ _mesa_FramebufferTexture2DEXT(GLenum target, GLenum attachment, error = !ctx->Extensions.ARB_texture_cube_map; break; case GL_TEXTURE_2D_ARRAY: - error = !ctx->Extensions.EXT_texture_array; + error = (_mesa_is_gles(ctx) && ctx->Version < 30) + || !ctx->Extensions.EXT_texture_array; break; default: error = GL_TRUE; @@ -2152,7 +2205,7 @@ _mesa_FramebufferTexture2DEXT(GLenum target, GLenum attachment, void GLAPIENTRY -_mesa_FramebufferTexture3DEXT(GLenum target, GLenum attachment, +_mesa_FramebufferTexture3D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset) { @@ -2170,7 +2223,7 @@ _mesa_FramebufferTexture3DEXT(GLenum target, GLenum attachment, void GLAPIENTRY -_mesa_FramebufferTextureLayerEXT(GLenum target, GLenum attachment, +_mesa_FramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) { GET_CURRENT_CONTEXT(ctx); @@ -2181,7 +2234,7 @@ _mesa_FramebufferTextureLayerEXT(GLenum target, GLenum attachment, void GLAPIENTRY -_mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment, +_mesa_FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbufferTarget, GLuint renderbuffer) { @@ -2204,7 +2257,7 @@ _mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment, return; } - if (is_winsys_fbo(fb)) { + if (_mesa_is_winsys_fbo(fb)) { /* Can't attach new renderbuffers to a window system framebuffer */ _mesa_error(ctx, GL_INVALID_OPERATION, "glFramebufferRenderbufferEXT"); return; @@ -2265,7 +2318,7 @@ _mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment, void GLAPIENTRY -_mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, +_mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint *params) { const struct gl_renderbuffer_attachment *att; @@ -2275,8 +2328,8 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, ASSERT_OUTSIDE_BEGIN_END(ctx); - /* The error differs in GL andd GLES. */ - err = ctx->API == API_OPENGL ? GL_INVALID_OPERATION : GL_INVALID_ENUM; + /* 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) { @@ -2285,7 +2338,7 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, return; } - if (is_winsys_fbo(buffer)) { + if (_mesa_is_winsys_fbo(buffer)) { /* Page 126 (page 136 of the PDF) of the OpenGL ES 2.0.25 spec * says: * @@ -2296,7 +2349,7 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, * OES_framebuffer_object spec refers to the EXT_framebuffer_object * spec. */ - if (ctx->API != API_OPENGL || !ctx->Extensions.ARB_framebuffer_object) { + if (!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_framebuffer_object) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetFramebufferAttachmentParameteriv(bound FBO = 0)"); return; @@ -2332,7 +2385,8 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, switch (pname) { case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT: - *params = is_winsys_fbo(buffer) ? GL_FRAMEBUFFER_DEFAULT : att->Type; + *params = _mesa_is_winsys_fbo(buffer) + ? GL_FRAMEBUFFER_DEFAULT : att->Type; return; case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT: if (att->Type == GL_RENDERBUFFER_EXT) { @@ -2343,11 +2397,10 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, } else { assert(att->Type == GL_NONE); - if (ctx->API == API_OPENGL) { + if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx)) { *params = 0; } else { - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetFramebufferAttachmentParameterivEXT(pname)"); + goto invalid_pname_enum; } } return; @@ -2360,8 +2413,7 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, "glGetFramebufferAttachmentParameterivEXT(pname)"); } else { - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetFramebufferAttachmentParameterivEXT(pname)"); + goto invalid_pname_enum; } return; case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT: @@ -2378,12 +2430,16 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, "glGetFramebufferAttachmentParameterivEXT(pname)"); } else { - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetFramebufferAttachmentParameterivEXT(pname)"); + goto invalid_pname_enum; } return; case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT: - if (att->Type == GL_TEXTURE) { + if (ctx->API == API_OPENGLES) { + goto invalid_pname_enum; + } else if (att->Type == GL_NONE) { + _mesa_error(ctx, err, + "glGetFramebufferAttachmentParameterivEXT(pname)"); + } else if (att->Type == GL_TEXTURE) { if (att->Texture && att->Texture->Target == GL_TEXTURE_3D) { *params = att->Zoffset; } @@ -2391,26 +2447,21 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, *params = 0; } } - else if (att->Type == GL_NONE) { - _mesa_error(ctx, err, - "glGetFramebufferAttachmentParameterivEXT(pname)"); - } else { - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetFramebufferAttachmentParameterivEXT(pname)"); + goto invalid_pname_enum; } return; case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING: - if (!ctx->Extensions.ARB_framebuffer_object) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetFramebufferAttachmentParameterivEXT(pname)"); + 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)"); } else { - if (ctx->Extensions.EXT_framebuffer_sRGB && ctx->Const.sRGBCapable) { + if (ctx->Extensions.EXT_framebuffer_sRGB) { *params = _mesa_get_format_color_encoding(att->Renderbuffer->Format); } else { @@ -2421,10 +2472,10 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, } return; case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE: - if (!ctx->Extensions.ARB_framebuffer_object) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetFramebufferAttachmentParameterivEXT(pname)"); - return; + 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, @@ -2456,9 +2507,9 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE: case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE: case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE: - if (!ctx->Extensions.ARB_framebuffer_object) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetFramebufferAttachmentParameterivEXT(pname)"); + 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, @@ -2486,15 +2537,20 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, } return; default: - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetFramebufferAttachmentParameterivEXT(pname)"); - return; + goto invalid_pname_enum; } + + return; + +invalid_pname_enum: + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetFramebufferAttachmentParameteriv(pname)"); + return; } void GLAPIENTRY -_mesa_GenerateMipmapEXT(GLenum target) +_mesa_GenerateMipmap(GLenum target) { struct gl_texture_image *srcImage; struct gl_texture_object *texObj; @@ -2507,16 +2563,23 @@ _mesa_GenerateMipmapEXT(GLenum target) switch (target) { case GL_TEXTURE_1D: + error = _mesa_is_gles(ctx); + break; case GL_TEXTURE_2D: - case GL_TEXTURE_3D: 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 = !ctx->Extensions.EXT_texture_array; + error = (_mesa_is_gles(ctx) && ctx->Version < 30) + || !ctx->Extensions.EXT_texture_array; break; default: error = GL_TRUE; @@ -2547,6 +2610,17 @@ _mesa_GenerateMipmapEXT(GLenum target) 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; } @@ -2564,8 +2638,6 @@ _mesa_GenerateMipmapEXT(GLenum target) } -#if FEATURE_EXT_framebuffer_blit - static const struct gl_renderbuffer_attachment * find_attachment(const struct gl_framebuffer *fb, const struct gl_renderbuffer *rb) @@ -2618,6 +2690,42 @@ compatible_color_datatypes(gl_format srcFormat, gl_format dstFormat) } +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; +} + + /** * Blit rectangular region, optionally from one framebuffer to another. * @@ -2625,7 +2733,7 @@ compatible_color_datatypes(gl_format srcFormat, gl_format dstFormat) * when the samples must be resolved to a single color. */ void GLAPIENTRY -_mesa_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, +_mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) { @@ -2727,9 +2835,13 @@ _mesa_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, if ((readRb == NULL) || (drawRb == NULL)) { mask &= ~GL_STENCIL_BUFFER_BIT; } - else if (readRb->Format != drawRb->Format) { + else 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, - "glBlitFramebufferEXT(stencil buffer format mismatch)"); + "glBlitFramebufferEXT(stencil buffer size mismatch)"); return; } } @@ -2749,7 +2861,10 @@ _mesa_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, if ((readRb == NULL) || (drawRb == NULL)) { mask &= ~GL_DEPTH_BUFFER_BIT; } - else if (readRb->Format != drawRb->Format) { + else 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, "glBlitFramebufferEXT(depth buffer format mismatch)"); return; @@ -2767,8 +2882,8 @@ _mesa_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, /* extra checks for multisample copies... */ if (readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) { /* src and dest region sizes must be the same */ - if (srcX1 - srcX0 != dstX1 - dstX0 || - srcY1 - srcY0 != dstY1 - dstY0) { + 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; @@ -2777,7 +2892,7 @@ _mesa_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, /* color formats must match */ if (colorReadRb && colorDrawRb && - colorReadRb->Format != colorDrawRb->Format) { + !compatible_resolve_formats(colorReadRb, colorDrawRb)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebufferEXT(bad src/dst multisample pixel formats)"); return; @@ -2850,28 +2965,145 @@ _mesa_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); } -#endif /* FEATURE_EXT_framebuffer_blit */ -#if FEATURE_ARB_geometry_shader4 -void GLAPIENTRY -_mesa_FramebufferTextureARB(GLenum target, GLenum attachment, - GLuint texture, GLint level) +static void +invalidate_framebuffer_storage(GLenum target, 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); - _mesa_error(ctx, GL_INVALID_OPERATION, - "glFramebufferTextureARB " - "not implemented!"); + + ASSERT_OUTSIDE_BEGIN_END(ctx); + + fb = get_framebuffer_target(ctx, target); + if (!fb) { + _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", name); + return; + } + + if (numAttachments < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, + "%s(numAttachments < 0)", name); + return; + } + + /* The GL_ARB_invalidate_subdata spec says: + * + * "If an attachment is specified that does not exist in the + * framebuffer bound to , it is ignored." + * + * It also says: + * + * "If contains COLOR_ATTACHMENTm and m is greater than + * or equal to the value of MAX_COLOR_ATTACHMENTS, then the error + * INVALID_OPERATION is generated." + * + * No mention is made of GL_AUXi being out of range. Therefore, we allow + * any enum that can be allowed by the API (OpenGL ES 3.0 has a different + * set of retrictions). + */ + for (i = 0; i < numAttachments; i++) { + if (_mesa_is_winsys_fbo(fb)) { + switch (attachments[i]) { + case GL_ACCUM: + case GL_AUX0: + case GL_AUX1: + case GL_AUX2: + case GL_AUX3: + /* Accumulation buffers and auxilary buffers were removed in + * OpenGL 3.1, and they never existed in OpenGL ES. + */ + if (ctx->API != API_OPENGL_COMPAT) + goto invalid_enum; + break; + case GL_COLOR: + case GL_DEPTH: + case GL_STENCIL: + break; + case GL_BACK_LEFT: + case GL_BACK_RIGHT: + case GL_FRONT_LEFT: + case GL_FRONT_RIGHT: + if (!_mesa_is_desktop_gl(ctx)) + goto invalid_enum; + break; + default: + goto invalid_enum; + } + } else { + switch (attachments[i]) { + case GL_DEPTH_ATTACHMENT: + case GL_STENCIL_ATTACHMENT: + break; + case GL_COLOR_ATTACHMENT0: + case GL_COLOR_ATTACHMENT1: + case GL_COLOR_ATTACHMENT2: + case GL_COLOR_ATTACHMENT3: + case GL_COLOR_ATTACHMENT4: + case GL_COLOR_ATTACHMENT5: + case GL_COLOR_ATTACHMENT6: + case GL_COLOR_ATTACHMENT7: + case GL_COLOR_ATTACHMENT8: + case GL_COLOR_ATTACHMENT9: + case GL_COLOR_ATTACHMENT10: + case GL_COLOR_ATTACHMENT11: + case GL_COLOR_ATTACHMENT12: + case GL_COLOR_ATTACHMENT13: + case GL_COLOR_ATTACHMENT14: + case GL_COLOR_ATTACHMENT15: { + unsigned k = attachments[i] - GL_COLOR_ATTACHMENT0; + if (k >= ctx->Const.MaxColorAttachments) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(attachment >= max. color attachments)", name); + return; + } + } + default: + goto invalid_enum; + } + } + } + + /* We don't actually do anything for this yet. Just return after + * validating the parameters and generating the required errors. + */ + return; + +invalid_enum: + _mesa_error(ctx, GL_INVALID_ENUM, "%s(attachment)", name); + return; } +void GLAPIENTRY +_mesa_InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, + const GLenum *attachments, GLint x, GLint y, + GLsizei width, GLsizei height) +{ + invalidate_framebuffer_storage(target, numAttachments, attachments, + x, y, width, height, + "glInvalidateSubFramebuffer"); +} void GLAPIENTRY -_mesa_FramebufferTextureFaceARB(GLenum target, GLenum attachment, - GLuint texture, GLint level, GLenum face) +_mesa_InvalidateFramebuffer(GLenum target, GLsizei numAttachments, + const GLenum *attachments) { - GET_CURRENT_CONTEXT(ctx); - _mesa_error(ctx, GL_INVALID_OPERATION, - "glFramebufferTextureFaceARB " - "not implemented!"); + /* 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 , , + * , equal to 0, 0, , + * respectively." + */ + invalidate_framebuffer_storage(target, numAttachments, attachments, + 0, 0, MAX_VIEWPORT_WIDTH, MAX_VIEWPORT_HEIGHT, + "glInvalidateFramebuffer"); } -#endif /* FEATURE_ARB_geometry_shader4 */