diff options
Diffstat (limited to 'src/mesa/main')
57 files changed, 3291 insertions, 939 deletions
diff --git a/src/mesa/main/api_exec.h b/src/mesa/main/api_exec.h index 12249fec228..655cb32d0a4 100644 --- a/src/mesa/main/api_exec.h +++ b/src/mesa/main/api_exec.h @@ -38,6 +38,9 @@ _mesa_initialize_exec_table(struct gl_context *ctx); extern void _mesa_initialize_dispatch_tables(struct gl_context *ctx); +extern struct _glapi_table * +_mesa_new_nop_table(unsigned numEntries); + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/mesa/main/api_loopback.c b/src/mesa/main/api_loopback.c index 9932a837336..a7fd82c531f 100644 --- a/src/mesa/main/api_loopback.c +++ b/src/mesa/main/api_loopback.c @@ -1772,7 +1772,9 @@ _mesa_loopback_init_api_table(const struct gl_context *ctx, SET_VertexAttribI4sv(dest, _mesa_VertexAttribI4sv); SET_VertexAttribI4ubv(dest, _mesa_VertexAttribI4ubv); SET_VertexAttribI4usv(dest, _mesa_VertexAttribI4usv); + } + if (ctx->API == API_OPENGL_CORE) { /* GL 4.1 / GL_ARB_vertex_attrib_64bit */ SET_VertexAttribL1d(dest, _mesa_VertexAttribL1d); SET_VertexAttribL2d(dest, _mesa_VertexAttribL2d); diff --git a/src/mesa/main/attrib.c b/src/mesa/main/attrib.c index b163c0aa699..53626e38be9 100644 --- a/src/mesa/main/attrib.c +++ b/src/mesa/main/attrib.c @@ -177,6 +177,10 @@ struct texture_state }; +/** An unused GL_*_BIT value */ +#define DUMMY_BIT 0x10000000 + + /** * Allocate new attribute node of given type/kind. Attach payload data. * Insert it into the linked list named by 'head'. @@ -253,6 +257,15 @@ _mesa_PushAttrib(GLbitfield mask) /* groups specified by the mask. */ head = NULL; + if (mask == 0) { + /* if mask is zero we still need to push something so that we + * don't get a GL_STACK_UNDERFLOW error in glPopAttrib(). + */ + GLuint dummy = 0; + if (!push_attrib(ctx, &head, DUMMY_BIT, sizeof(dummy), &dummy)) + goto end; + } + if (mask & GL_ACCUM_BUFFER_BIT) { if (!push_attrib(ctx, &head, GL_ACCUM_BUFFER_BIT, sizeof(struct gl_accum_attrib), @@ -928,6 +941,10 @@ _mesa_PopAttrib(void) } switch (attr->kind) { + case DUMMY_BIT: + /* do nothing */ + break; + case GL_ACCUM_BUFFER_BIT: { const struct gl_accum_attrib *accum; @@ -1074,6 +1091,11 @@ _mesa_PopAttrib(void) _mesa_ClearDepth(depth->Clear); _mesa_set_enable(ctx, GL_DEPTH_TEST, depth->Test); _mesa_DepthMask(depth->Mask); + if (ctx->Extensions.EXT_depth_bounds_test) { + _mesa_set_enable(ctx, GL_DEPTH_BOUNDS_TEST_EXT, + depth->BoundsTest); + _mesa_DepthBoundsEXT(depth->BoundsMin, depth->BoundsMax); + } } break; case GL_ENABLE_BIT: diff --git a/src/mesa/main/blend.c b/src/mesa/main/blend.c index 774fc888ec4..d869fa2aa09 100644 --- a/src/mesa/main/blend.c +++ b/src/mesa/main/blend.c @@ -769,7 +769,7 @@ _mesa_ClampColor(GLenum target, GLenum clamp) } FLUSH_VERTICES(ctx, _NEW_LIGHT); ctx->Light.ClampVertexColor = clamp; - _mesa_update_clamp_vertex_color(ctx); + _mesa_update_clamp_vertex_color(ctx, ctx->DrawBuffer); break; case GL_CLAMP_FRAGMENT_COLOR_ARB: if (ctx->API == API_OPENGL_CORE && @@ -778,7 +778,7 @@ _mesa_ClampColor(GLenum target, GLenum clamp) } FLUSH_VERTICES(ctx, _NEW_FRAG_CLAMP); ctx->Color.ClampFragmentColor = clamp; - _mesa_update_clamp_fragment_color(ctx); + _mesa_update_clamp_fragment_color(ctx, ctx->DrawBuffer); break; case GL_CLAMP_READ_COLOR_ARB: ctx->Color.ClampReadColor = clamp; @@ -807,50 +807,55 @@ get_clamp_color(const struct gl_framebuffer *fb, GLenum clamp) } GLboolean -_mesa_get_clamp_fragment_color(const struct gl_context *ctx) +_mesa_get_clamp_fragment_color(const struct gl_context *ctx, + const struct gl_framebuffer *drawFb) { - return get_clamp_color(ctx->DrawBuffer, - ctx->Color.ClampFragmentColor); + return get_clamp_color(drawFb, ctx->Color.ClampFragmentColor); } GLboolean -_mesa_get_clamp_vertex_color(const struct gl_context *ctx) +_mesa_get_clamp_vertex_color(const struct gl_context *ctx, + const struct gl_framebuffer *drawFb) { - return get_clamp_color(ctx->DrawBuffer, ctx->Light.ClampVertexColor); + return get_clamp_color(drawFb, ctx->Light.ClampVertexColor); } GLboolean -_mesa_get_clamp_read_color(const struct gl_context *ctx) +_mesa_get_clamp_read_color(const struct gl_context *ctx, + const struct gl_framebuffer *readFb) { - return get_clamp_color(ctx->ReadBuffer, ctx->Color.ClampReadColor); + return get_clamp_color(readFb, ctx->Color.ClampReadColor); } /** * Update the ctx->Color._ClampFragmentColor field */ void -_mesa_update_clamp_fragment_color(struct gl_context *ctx) +_mesa_update_clamp_fragment_color(struct gl_context *ctx, + const struct gl_framebuffer *drawFb) { - struct gl_framebuffer *fb = ctx->DrawBuffer; - /* Don't clamp if: * - there is no colorbuffer * - all colorbuffers are unsigned normalized, so clamping has no effect * - there is an integer colorbuffer */ - if (!fb || !fb->_HasSNormOrFloatColorBuffer || fb->_IntegerColor) + if (!drawFb || !drawFb->_HasSNormOrFloatColorBuffer || + drawFb->_IntegerColor) ctx->Color._ClampFragmentColor = GL_FALSE; else - ctx->Color._ClampFragmentColor = _mesa_get_clamp_fragment_color(ctx); + ctx->Color._ClampFragmentColor = + _mesa_get_clamp_fragment_color(ctx, drawFb); } /** * Update the ctx->Color._ClampVertexColor field */ void -_mesa_update_clamp_vertex_color(struct gl_context *ctx) +_mesa_update_clamp_vertex_color(struct gl_context *ctx, + const struct gl_framebuffer *drawFb) { - ctx->Light._ClampVertexColor = _mesa_get_clamp_vertex_color(ctx); + ctx->Light._ClampVertexColor = + _mesa_get_clamp_vertex_color(ctx, drawFb); } /** diff --git a/src/mesa/main/blend.h b/src/mesa/main/blend.h index fe31a7440f0..8ab9e02fc13 100644 --- a/src/mesa/main/blend.h +++ b/src/mesa/main/blend.h @@ -37,6 +37,7 @@ #include "formats.h" struct gl_context; +struct gl_framebuffer; extern void GLAPIENTRY @@ -101,19 +102,24 @@ extern void GLAPIENTRY _mesa_ClampColor(GLenum target, GLenum clamp); extern GLboolean -_mesa_get_clamp_fragment_color(const struct gl_context *ctx); +_mesa_get_clamp_fragment_color(const struct gl_context *ctx, + const struct gl_framebuffer *drawFb); extern GLboolean -_mesa_get_clamp_vertex_color(const struct gl_context *ctx); +_mesa_get_clamp_vertex_color(const struct gl_context *ctx, + const struct gl_framebuffer *drawFb); extern GLboolean -_mesa_get_clamp_read_color(const struct gl_context *ctx); +_mesa_get_clamp_read_color(const struct gl_context *ctx, + const struct gl_framebuffer *readFb); extern void -_mesa_update_clamp_fragment_color(struct gl_context *ctx); +_mesa_update_clamp_fragment_color(struct gl_context *ctx, + const struct gl_framebuffer *drawFb); extern void -_mesa_update_clamp_vertex_color(struct gl_context *ctx); +_mesa_update_clamp_vertex_color(struct gl_context *ctx, + const struct gl_framebuffer *drawFb); extern mesa_format _mesa_get_render_format(const struct gl_context *ctx, mesa_format format); diff --git a/src/mesa/main/blit.c b/src/mesa/main/blit.c index 0694466eb75..db8fee5a414 100644 --- a/src/mesa/main/blit.c +++ b/src/mesa/main/blit.c @@ -34,6 +34,7 @@ #include "enums.h" #include "blit.h" #include "fbobject.h" +#include "framebuffer.h" #include "glformats.h" #include "mtypes.h" #include "state.h" @@ -148,38 +149,25 @@ is_valid_blit_filter(const struct gl_context *ctx, GLenum filter) } -/** - * 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) +void +_mesa_blit_framebuffer(struct gl_context *ctx, + struct gl_framebuffer *readFb, + struct gl_framebuffer *drawFb, + GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, + GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, + GLbitfield mask, GLenum filter, const char *func) { 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); - } + /* Update completeness status of readFb and drawFb. */ + _mesa_update_framebuffer(ctx, readFb, drawFb); - readFb = ctx->ReadBuffer; - drawFb = ctx->DrawBuffer; + /* Make sure drawFb has an initialized bounding box. */ + _mesa_update_draw_buffer_bounds(ctx, drawFb); if (!readFb || !drawFb) { /* This will normally never happen but someday we may want to @@ -192,12 +180,12 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, 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)"); + "%s(incomplete draw/read buffers)", func); return; } if (!is_valid_blit_filter(ctx, filter)) { - _mesa_error(ctx, GL_INVALID_ENUM, "glBlitFramebufferEXT(%s)", + _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid filter %s)", func, _mesa_lookup_enum_by_nr(filter)); return; } @@ -205,13 +193,13 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, 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_error(ctx, GL_INVALID_OPERATION, "%s(%s: invalid samples)", func, _mesa_lookup_enum_by_nr(filter)); return; } if (mask & ~legalMaskBits) { - _mesa_error( ctx, GL_INVALID_VALUE, "glBlitFramebufferEXT(mask)"); + _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid mask bits set)", func); return; } @@ -219,13 +207,13 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, 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)"); + "%s(depth/stencil requires GL_NEAREST filter)", func); return; } /* get color read/draw renderbuffers */ if (mask & GL_COLOR_BUFFER_BIT) { - const GLuint numColorDrawBuffers = ctx->DrawBuffer->_NumColorDrawBuffers; + const GLuint numColorDrawBuffers = drawFb->_NumColorDrawBuffers; const struct gl_renderbuffer *colorReadRb = readFb->_ColorReadBuffer; const struct gl_renderbuffer *colorDrawRb = NULL; GLuint i; @@ -241,7 +229,7 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, } else { for (i = 0; i < numColorDrawBuffers; i++) { - colorDrawRb = ctx->DrawBuffer->_ColorDrawBuffers[i]; + colorDrawRb = drawFb->_ColorDrawBuffers[i]; if (!colorDrawRb) continue; @@ -257,15 +245,15 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, */ if (_mesa_is_gles3(ctx) && (colorDrawRb == colorReadRb)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glBlitFramebuffer(source and destination color " - "buffer cannot be the same)"); + "%s(source and destination color " + "buffer cannot be the same)", func); return; } if (!compatible_color_datatypes(colorReadRb->Format, colorDrawRb->Format)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glBlitFramebufferEXT(color buffer datatypes mismatch)"); + "%s(color buffer datatypes mismatch)", func); return; } /* extra checks for multisample copies... */ @@ -273,7 +261,7 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, /* color formats must match */ if (!compatible_resolve_formats(colorReadRb, colorDrawRb)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glBlitFramebufferEXT(bad src/dst multisample pixel formats)"); + "%s(bad src/dst multisample pixel formats)", func); return; } } @@ -286,7 +274,7 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, 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)"); + "%s(integer color type)", func); return; } } @@ -306,15 +294,15 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, * ignored." */ if ((readRb == NULL) || (drawRb == NULL)) { - mask &= ~GL_STENCIL_BUFFER_BIT; + 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)"); + "%s(source and destination stencil " + "buffer cannot be the same)", func); return; } @@ -324,7 +312,7 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, * there is only one: GL_UNSIGNED_INT. */ _mesa_error(ctx, GL_INVALID_OPERATION, - "glBlitFramebuffer(stencil attachment format mismatch)"); + "%s(stencil attachment format mismatch)", func); return; } @@ -340,8 +328,8 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, _mesa_get_format_datatype(readRb->Format) != _mesa_get_format_datatype(drawRb->Format))) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebuffer" - "(stencil attachment depth format mismatch)"); + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(stencil attachment depth format mismatch)", func); return; } } @@ -360,15 +348,15 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, * ignored." */ if ((readRb == NULL) || (drawRb == NULL)) { - mask &= ~GL_DEPTH_BUFFER_BIT; + 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)"); + "%s(source and destination depth " + "buffer cannot be the same)", func); return; } @@ -377,7 +365,7 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, (_mesa_get_format_datatype(readRb->Format) != _mesa_get_format_datatype(drawRb->Format))) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glBlitFramebuffer(depth attachment format mismatch)"); + "%s(depth attachment format mismatch)", func); return; } @@ -389,8 +377,8 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, * 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)"); + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(depth attachment stencil bits mismatch)", func); return; } } @@ -406,7 +394,7 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, */ if (drawFb->Visual.samples > 0) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glBlitFramebuffer(destination samples must be 0)"); + "%s(destination samples must be 0)", func); return; } @@ -426,7 +414,7 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, && (srcX0 != dstX0 || srcY0 != dstY0 || srcX1 != dstX1 || srcY1 != dstY1)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glBlitFramebuffer(bad src/dst multisample region)"); + "%s(bad src/dst multisample region)", func); return; } } else { @@ -434,7 +422,7 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, drawFb->Visual.samples > 0 && readFb->Visual.samples != drawFb->Visual.samples) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glBlitFramebufferEXT(mismatched samples)"); + "%s(mismatched samples)", func); return; } @@ -445,7 +433,7 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, 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)"); + "%s(bad src/dst multisample region sizes)", func); return; } } @@ -457,43 +445,44 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, 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); + printf("%s(%d, %d, %d, %d, %d, %d, %d, %d," + " 0x%x, 0x%x)\n", func, + 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); + 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); + 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]; + for (i = 0; i < drawFb->_NumColorDrawBuffers; i++) { + colorDrawRb = drawFb->_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); + 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); + att->Texture->Name, + att->Texture->Target, + att->TextureLevel, + att->CubeMapFace); } printf("\n"); } @@ -507,8 +496,87 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, } assert(ctx->Driver.BlitFramebuffer); - ctx->Driver.BlitFramebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer, + ctx->Driver.BlitFramebuffer(ctx, readFb, drawFb, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); } + + +/** + * 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) +{ + GET_CURRENT_CONTEXT(ctx); + + 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)); + + _mesa_blit_framebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer, + srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1, + mask, filter, "glBlitFramebuffer"); +} + + +void GLAPIENTRY +_mesa_BlitNamedFramebuffer(GLuint readFramebuffer, GLuint drawFramebuffer, + GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, + GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, + GLbitfield mask, GLenum filter) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_framebuffer *readFb, *drawFb; + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, + "glBlitNamedFramebuffer(%u %u %d, %d, %d, %d, " + " %d, %d, %d, %d, 0x%x, %s)\n", + readFramebuffer, drawFramebuffer, + srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1, + mask, _mesa_lookup_enum_by_nr(filter)); + + /* + * According to PDF page 533 of the OpenGL 4.5 core spec (30.10.2014, + * Section 18.3 Copying Pixels): + * "... if readFramebuffer or drawFramebuffer is zero (for + * BlitNamedFramebuffer), then the default read or draw framebuffer is + * used as the corresponding source or destination framebuffer, + * respectively." + */ + if (readFramebuffer) { + readFb = _mesa_lookup_framebuffer_err(ctx, readFramebuffer, + "glBlitNamedFramebuffer"); + if (!readFb) + return; + } + else + readFb = ctx->WinSysReadBuffer; + + if (drawFramebuffer) { + drawFb = _mesa_lookup_framebuffer_err(ctx, drawFramebuffer, + "glBlitNamedFramebuffer"); + if (!drawFb) + return; + } + else + drawFb = ctx->WinSysDrawBuffer; + + _mesa_blit_framebuffer(ctx, readFb, drawFb, + srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1, + mask, filter, "glBlitNamedFramebuffer"); +} diff --git a/src/mesa/main/blit.h b/src/mesa/main/blit.h index 01a958af5a2..54b946e3192 100644 --- a/src/mesa/main/blit.h +++ b/src/mesa/main/blit.h @@ -28,11 +28,24 @@ #include "glheader.h" +extern void +_mesa_blit_framebuffer(struct gl_context *ctx, + struct gl_framebuffer *readFb, + struct gl_framebuffer *drawFb, + GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, + GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, + GLbitfield mask, GLenum filter, const char *func); extern void GLAPIENTRY _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +extern void GLAPIENTRY +_mesa_BlitNamedFramebuffer(GLuint readFramebuffer, GLuint drawFramebuffer, + GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, + GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, + GLbitfield mask, GLenum filter); + #endif /* BLIT_H */ diff --git a/src/mesa/main/buffers.c b/src/mesa/main/buffers.c index 37a9790923b..0536266d756 100644 --- a/src/mesa/main/buffers.c +++ b/src/mesa/main/buffers.c @@ -242,16 +242,16 @@ read_buffer_enum_to_index(GLenum buffer) * * See the GL_EXT_framebuffer_object spec for more info. */ -void GLAPIENTRY -_mesa_DrawBuffer(GLenum buffer) +void +_mesa_draw_buffer(struct gl_context *ctx, struct gl_framebuffer *fb, + GLenum buffer, const char *caller) { GLbitfield destMask; - GET_CURRENT_CONTEXT(ctx); FLUSH_VERTICES(ctx, 0); if (MESA_VERBOSE & VERBOSE_API) { - _mesa_debug(ctx, "glDrawBuffer %s\n", _mesa_lookup_enum_by_nr(buffer)); + _mesa_debug(ctx, "%s %s\n", caller, _mesa_lookup_enum_by_nr(buffer)); } if (buffer == GL_NONE) { @@ -259,33 +259,60 @@ _mesa_DrawBuffer(GLenum buffer) } else { const GLbitfield supportedMask - = supported_buffer_bitmask(ctx, ctx->DrawBuffer); + = supported_buffer_bitmask(ctx, fb); destMask = draw_buffer_enum_to_bitmask(ctx, buffer); if (destMask == BAD_MASK) { /* totally bogus buffer */ - _mesa_error(ctx, GL_INVALID_ENUM, - "glDrawBuffer(buffer=0x%x)", buffer); + _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid buffer %s)", caller, + _mesa_lookup_enum_by_nr(buffer)); return; } destMask &= supportedMask; if (destMask == 0x0) { /* none of the named color buffers exist! */ - _mesa_error(ctx, GL_INVALID_OPERATION, - "glDrawBuffer(buffer=0x%x)", buffer); + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid buffer %s)", + caller, _mesa_lookup_enum_by_nr(buffer)); return; } } /* if we get here, there's no error so set new state */ - _mesa_drawbuffers(ctx, 1, &buffer, &destMask); + _mesa_drawbuffers(ctx, fb, 1, &buffer, &destMask); + + /* Call device driver function only if fb is the bound draw buffer */ + if (fb == ctx->DrawBuffer) { + if (ctx->Driver.DrawBuffers) + ctx->Driver.DrawBuffers(ctx, 1, &buffer); + else if (ctx->Driver.DrawBuffer) + ctx->Driver.DrawBuffer(ctx, buffer); + } +} - /* - * Call device driver function. - */ - if (ctx->Driver.DrawBuffers) - ctx->Driver.DrawBuffers(ctx, 1, &buffer); - else if (ctx->Driver.DrawBuffer) - ctx->Driver.DrawBuffer(ctx, buffer); + +void GLAPIENTRY +_mesa_DrawBuffer(GLenum buffer) +{ + GET_CURRENT_CONTEXT(ctx); + _mesa_draw_buffer(ctx, ctx->DrawBuffer, buffer, "glDrawBuffer"); +} + + +void GLAPIENTRY +_mesa_NamedFramebufferDrawBuffer(GLuint framebuffer, GLenum buf) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_framebuffer *fb; + + if (framebuffer) { + fb = _mesa_lookup_framebuffer_err(ctx, framebuffer, + "glNamedFramebufferDrawBuffer"); + if (!fb) + return; + } + else + fb = ctx->WinSysDrawBuffer; + + _mesa_draw_buffer(ctx, fb, buf, "glNamedFramebufferDrawBuffer"); } @@ -298,13 +325,13 @@ _mesa_DrawBuffer(GLenum buffer) * names cannot specify more than one buffer. For example, * GL_FRONT_AND_BACK is illegal. */ -void GLAPIENTRY -_mesa_DrawBuffers(GLsizei n, const GLenum *buffers) +void +_mesa_draw_buffers(struct gl_context *ctx, struct gl_framebuffer *fb, + GLsizei n, const GLenum *buffers, const char *caller) { GLuint output; GLbitfield usedBufferMask, supportedMask; GLbitfield destMask[MAX_DRAW_BUFFERS]; - GET_CURRENT_CONTEXT(ctx); FLUSH_VERTICES(ctx, 0); @@ -315,12 +342,18 @@ _mesa_DrawBuffers(GLsizei n, const GLenum *buffers) * "An INVALID_VALUE error is generated if n is greater than * MAX_DRAW_BUFFERS." */ - if (n < 0 || n > (GLsizei) ctx->Const.MaxDrawBuffers) { - _mesa_error(ctx, GL_INVALID_VALUE, "glDrawBuffersARB(n)"); + if (n < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", caller); + return; + } + + if (n > (GLsizei) ctx->Const.MaxDrawBuffers) { + _mesa_error(ctx, GL_INVALID_VALUE, + "%s(n > maximum number of draw buffers)", caller); return; } - supportedMask = supported_buffer_bitmask(ctx, ctx->DrawBuffer); + supportedMask = supported_buffer_bitmask(ctx, fb); usedBufferMask = 0x0; /* From the ES 3.0 specification, page 180: @@ -328,9 +361,9 @@ _mesa_DrawBuffers(GLsizei n, const GLenum *buffers) * and the constant must be BACK or NONE." * (same restriction applies with GL_EXT_draw_buffers specification) */ - if (ctx->API == API_OPENGLES2 && _mesa_is_winsys_fbo(ctx->DrawBuffer) && + if (ctx->API == API_OPENGLES2 && _mesa_is_winsys_fbo(fb) && (n != 1 || (buffers[0] != GL_NONE && buffers[0] != GL_BACK))) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffers(buffer)"); + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid buffers)", caller); return; } @@ -362,9 +395,11 @@ _mesa_DrawBuffers(GLsizei n, const GLenum *buffers) * or equal to the value of MAX_COLOR_ATTACHMENTS, then the error * INVALID_OPERATION results." */ - if (_mesa_is_user_fbo(ctx->DrawBuffer) && buffers[output] >= + if (_mesa_is_user_fbo(fb) && buffers[output] >= GL_COLOR_ATTACHMENT0 + ctx->Const.MaxDrawBuffers) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffersARB(buffer)"); + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(buffers[%d] >= maximum number of draw buffers)", + caller, output); return; } @@ -375,9 +410,10 @@ _mesa_DrawBuffers(GLsizei n, const GLenum *buffers) * 4.5 or 4.6. Otherwise, an INVALID_ENUM error is generated. */ if (destMask[output] == BAD_MASK) { - _mesa_error(ctx, GL_INVALID_ENUM, "glDrawBuffersARB(buffer)"); + _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid buffer %s)", + caller, _mesa_lookup_enum_by_nr(buffers[output])); return; - } + } /* From the OpenGL 4.0 specification, page 256: * "For both the default framebuffer and framebuffer objects, the @@ -390,7 +426,8 @@ _mesa_DrawBuffers(GLsizei n, const GLenum *buffers) * but the Khronos conformance tests expect INVALID_ENUM. */ if (_mesa_bitcount(destMask[output]) > 1) { - _mesa_error(ctx, GL_INVALID_ENUM, "glDrawBuffersARB(buffer)"); + _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid buffer %s)", + caller, _mesa_lookup_enum_by_nr(buffers[output])); return; } @@ -407,7 +444,8 @@ _mesa_DrawBuffers(GLsizei n, const GLenum *buffers) destMask[output] &= supportedMask; if (destMask[output] == 0) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glDrawBuffersARB(unsupported buffer)"); + "%s(unsupported buffer %s)", + caller, _mesa_lookup_enum_by_nr(buffers[output])); return; } @@ -416,10 +454,12 @@ _mesa_DrawBuffers(GLsizei n, const GLenum *buffers) * in bufs must be COLOR_ATTACHMENTi or NONE. [...] INVALID_OPERATION." * (same restriction applies with GL_EXT_draw_buffers specification) */ - if (ctx->API == API_OPENGLES2 && _mesa_is_user_fbo(ctx->DrawBuffer) && + if (ctx->API == API_OPENGLES2 && _mesa_is_user_fbo(fb) && buffers[output] != GL_NONE && buffers[output] != GL_COLOR_ATTACHMENT0 + output) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffers(buffer)"); + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(unsupported buffer %s)", + caller, _mesa_lookup_enum_by_nr(buffers[output])); return; } @@ -430,7 +470,8 @@ _mesa_DrawBuffers(GLsizei n, const GLenum *buffers) */ if (destMask[output] & usedBufferMask) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glDrawBuffersARB(duplicated buffer)"); + "%s(duplicated buffer %s)", + caller, _mesa_lookup_enum_by_nr(buffers[output])); return; } @@ -440,17 +481,48 @@ _mesa_DrawBuffers(GLsizei n, const GLenum *buffers) } /* OK, if we get here, there were no errors so set the new state */ - _mesa_drawbuffers(ctx, n, buffers, destMask); + _mesa_drawbuffers(ctx, fb, n, buffers, destMask); /* - * Call device driver function. Note that n can be equal to 0, + * Call device driver function if fb is the bound draw buffer. + * Note that n can be equal to 0, * in which case we don't want to reference buffers[0], which * may not be valid. */ - if (ctx->Driver.DrawBuffers) - ctx->Driver.DrawBuffers(ctx, n, buffers); - else if (ctx->Driver.DrawBuffer) - ctx->Driver.DrawBuffer(ctx, n > 0 ? buffers[0] : GL_NONE); + if (fb == ctx->DrawBuffer) { + if (ctx->Driver.DrawBuffers) + ctx->Driver.DrawBuffers(ctx, n, buffers); + else if (ctx->Driver.DrawBuffer) + ctx->Driver.DrawBuffer(ctx, n > 0 ? buffers[0] : GL_NONE); + } +} + + +void GLAPIENTRY +_mesa_DrawBuffers(GLsizei n, const GLenum *buffers) +{ + GET_CURRENT_CONTEXT(ctx); + _mesa_draw_buffers(ctx, ctx->DrawBuffer, n, buffers, "glDrawBuffers"); +} + + +void GLAPIENTRY +_mesa_NamedFramebufferDrawBuffers(GLuint framebuffer, GLsizei n, + const GLenum *bufs) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_framebuffer *fb; + + if (framebuffer) { + fb = _mesa_lookup_framebuffer_err(ctx, framebuffer, + "glNamedFramebufferDrawBuffers"); + if (!fb) + return; + } + else + fb = ctx->WinSysDrawBuffer; + + _mesa_draw_buffers(ctx, fb, n, bufs, "glNamedFramebufferDrawBuffers"); } @@ -459,13 +531,11 @@ _mesa_DrawBuffers(GLsizei n, const GLenum *buffers) * actual change. */ static void -updated_drawbuffers(struct gl_context *ctx) +updated_drawbuffers(struct gl_context *ctx, struct gl_framebuffer *fb) { FLUSH_VERTICES(ctx, _NEW_BUFFERS); if (ctx->API == API_OPENGL_COMPAT && !ctx->Extensions.ARB_ES2_compatibility) { - struct gl_framebuffer *fb = ctx->DrawBuffer; - /* Flag the FBO as requiring validation. */ if (_mesa_is_user_fbo(fb)) { fb->_Status = 0; @@ -482,6 +552,7 @@ updated_drawbuffers(struct gl_context *ctx) * so nothing should go wrong at this point. * * \param ctx current context + * \param fb the desired draw buffer * \param n number of color outputs to set * \param buffers array[n] of colorbuffer names, like GL_LEFT. * \param destMask array[n] of BUFFER_BIT_* bitmasks which correspond to the @@ -489,10 +560,9 @@ updated_drawbuffers(struct gl_context *ctx) * BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT). */ void -_mesa_drawbuffers(struct gl_context *ctx, GLuint n, const GLenum *buffers, - const GLbitfield *destMask) +_mesa_drawbuffers(struct gl_context *ctx, struct gl_framebuffer *fb, + GLuint n, const GLenum *buffers, const GLbitfield *destMask) { - struct gl_framebuffer *fb = ctx->DrawBuffer; GLbitfield mask[MAX_DRAW_BUFFERS]; GLuint buf; @@ -518,7 +588,7 @@ _mesa_drawbuffers(struct gl_context *ctx, GLuint n, const GLenum *buffers, while (destMask0) { GLint bufIndex = ffs(destMask0) - 1; if (fb->_ColorDrawBufferIndexes[count] != bufIndex) { - updated_drawbuffers(ctx); + updated_drawbuffers(ctx, fb); fb->_ColorDrawBufferIndexes[count] = bufIndex; } count++; @@ -535,14 +605,14 @@ _mesa_drawbuffers(struct gl_context *ctx, GLuint n, const GLenum *buffers, /* only one bit should be set in the destMask[buf] field */ assert(_mesa_bitcount(destMask[buf]) == 1); if (fb->_ColorDrawBufferIndexes[buf] != bufIndex) { - updated_drawbuffers(ctx); + updated_drawbuffers(ctx, fb); fb->_ColorDrawBufferIndexes[buf] = bufIndex; } count = buf + 1; } else { if (fb->_ColorDrawBufferIndexes[buf] != -1) { - updated_drawbuffers(ctx); + updated_drawbuffers(ctx, fb); fb->_ColorDrawBufferIndexes[buf] = -1; } } @@ -554,7 +624,7 @@ _mesa_drawbuffers(struct gl_context *ctx, GLuint n, const GLenum *buffers, /* set remaining outputs to -1 (GL_NONE) */ for (buf = fb->_NumColorDrawBuffers; buf < ctx->Const.MaxDrawBuffers; buf++) { if (fb->_ColorDrawBufferIndexes[buf] != -1) { - updated_drawbuffers(ctx); + updated_drawbuffers(ctx, fb); fb->_ColorDrawBufferIndexes[buf] = -1; } } @@ -566,7 +636,7 @@ _mesa_drawbuffers(struct gl_context *ctx, GLuint n, const GLenum *buffers, /* also set context drawbuffer state */ for (buf = 0; buf < ctx->Const.MaxDrawBuffers; buf++) { if (ctx->Color.DrawBuffer[buf] != fb->ColorDrawBuffer[buf]) { - updated_drawbuffers(ctx); + updated_drawbuffers(ctx, fb); ctx->Color.DrawBuffer[buf] = fb->ColorDrawBuffer[buf]; } } @@ -585,7 +655,7 @@ _mesa_update_draw_buffers(struct gl_context *ctx) /* should be a window system FBO */ assert(_mesa_is_winsys_fbo(ctx->DrawBuffer)); - _mesa_drawbuffers(ctx, ctx->Const.MaxDrawBuffers, + _mesa_drawbuffers(ctx, ctx->DrawBuffer, ctx->Const.MaxDrawBuffers, ctx->Color.DrawBuffer, NULL); } @@ -598,11 +668,10 @@ _mesa_update_draw_buffers(struct gl_context *ctx) * \param bufferIndex the numerical index corresponding to 'buffer' */ void -_mesa_readbuffer(struct gl_context *ctx, GLenum buffer, GLint bufferIndex) +_mesa_readbuffer(struct gl_context *ctx, struct gl_framebuffer *fb, + GLenum buffer, GLint bufferIndex) { - struct gl_framebuffer *fb = ctx->ReadBuffer; - - if (_mesa_is_winsys_fbo(fb)) { + if ((fb == ctx->ReadBuffer) && _mesa_is_winsys_fbo(fb)) { /* Only update the per-context READ_BUFFER state if we're bound to * a window-system framebuffer. */ @@ -621,23 +690,17 @@ _mesa_readbuffer(struct gl_context *ctx, GLenum buffer, GLint bufferIndex) * Called by glReadBuffer to set the source renderbuffer for reading pixels. * \param mode color buffer such as GL_FRONT, GL_BACK, etc. */ -void GLAPIENTRY -_mesa_ReadBuffer(GLenum buffer) +void +_mesa_read_buffer(struct gl_context *ctx, struct gl_framebuffer *fb, + GLenum buffer, const char *caller) { - struct gl_framebuffer *fb; GLbitfield supportedMask; GLint srcBuffer; - GET_CURRENT_CONTEXT(ctx); FLUSH_VERTICES(ctx, 0); if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glReadBuffer %s\n", _mesa_lookup_enum_by_nr(buffer)); - - fb = ctx->ReadBuffer; - - if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glReadBuffer %s\n", _mesa_lookup_enum_by_nr(buffer)); + _mesa_debug(ctx, "%s %s\n", caller, _mesa_lookup_enum_by_nr(buffer)); if (buffer == GL_NONE) { /* This is legal--it means that no buffer should be bound for reading. */ @@ -648,24 +711,53 @@ _mesa_ReadBuffer(GLenum buffer) srcBuffer = read_buffer_enum_to_index(buffer); if (srcBuffer == -1) { _mesa_error(ctx, GL_INVALID_ENUM, - "glReadBuffer(buffer=0x%x)", buffer); + "%s(invalid buffer %s)", caller, + _mesa_lookup_enum_by_nr(buffer)); return; } supportedMask = supported_buffer_bitmask(ctx, fb); if (((1 << srcBuffer) & supportedMask) == 0) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glReadBuffer(buffer=0x%x)", buffer); + "%s(invalid buffer %s)", caller, + _mesa_lookup_enum_by_nr(buffer)); return; } } /* OK, all error checking has been completed now */ - _mesa_readbuffer(ctx, buffer, srcBuffer); + _mesa_readbuffer(ctx, fb, buffer, srcBuffer); - /* - * Call device driver function. - */ - if (ctx->Driver.ReadBuffer) - (*ctx->Driver.ReadBuffer)(ctx, buffer); + /* Call the device driver function only if fb is the bound read buffer */ + if (fb == ctx->ReadBuffer) { + if (ctx->Driver.ReadBuffer) + (*ctx->Driver.ReadBuffer)(ctx, buffer); + } +} + + +void GLAPIENTRY +_mesa_ReadBuffer(GLenum buffer) +{ + GET_CURRENT_CONTEXT(ctx); + _mesa_read_buffer(ctx, ctx->ReadBuffer, buffer, "glReadBuffer"); +} + + +void GLAPIENTRY +_mesa_NamedFramebufferReadBuffer(GLuint framebuffer, GLenum src) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_framebuffer *fb; + + if (framebuffer) { + fb = _mesa_lookup_framebuffer_err(ctx, framebuffer, + "glNamedFramebufferReadBuffer"); + if (!fb) + return; + } + else + fb = ctx->WinSysReadBuffer; + + _mesa_read_buffer(ctx, fb, src, "glNamedFramebufferReadBuffer"); } diff --git a/src/mesa/main/buffers.h b/src/mesa/main/buffers.h index ebcfa1c1e74..5aa79fda54b 100644 --- a/src/mesa/main/buffers.h +++ b/src/mesa/main/buffers.h @@ -36,26 +36,51 @@ #include "glheader.h" struct gl_context; +struct gl_framebuffer; + +extern void +_mesa_draw_buffer(struct gl_context *ctx, struct gl_framebuffer *fb, + GLenum buffer, const char *caller); extern void GLAPIENTRY _mesa_DrawBuffer( GLenum mode ); extern void GLAPIENTRY +_mesa_NamedFramebufferDrawBuffer(GLuint framebuffer, GLenum buf); + +extern void +_mesa_draw_buffers(struct gl_context *ctx, struct gl_framebuffer *fb, + GLsizei n, const GLenum *buffers, const char *caller); + +extern void GLAPIENTRY _mesa_DrawBuffers(GLsizei n, const GLenum *buffers); +extern void GLAPIENTRY +_mesa_NamedFramebufferDrawBuffers(GLuint framebuffer, GLsizei n, + const GLenum *bufs); + extern void -_mesa_drawbuffers(struct gl_context *ctx, GLuint n, const GLenum *buffers, +_mesa_drawbuffers(struct gl_context *ctx, struct gl_framebuffer *fb, + GLuint n, const GLenum *buffers, const GLbitfield *destMask); extern void -_mesa_readbuffer(struct gl_context *ctx, GLenum buffer, GLint bufferIndex); +_mesa_readbuffer(struct gl_context *ctx, struct gl_framebuffer *fb, + GLenum buffer, GLint bufferIndex); extern void _mesa_update_draw_buffers(struct gl_context *ctx); +extern void +_mesa_read_buffer(struct gl_context *ctx, struct gl_framebuffer *fb, + GLenum buffer, const char *caller); + extern void GLAPIENTRY _mesa_ReadBuffer( GLenum mode ); +extern void GLAPIENTRY +_mesa_NamedFramebufferReadBuffer(GLuint framebuffer, GLenum src); + #endif diff --git a/src/mesa/main/clear.c b/src/mesa/main/clear.c index 8d707bc34a1..426caea4709 100644 --- a/src/mesa/main/clear.c +++ b/src/mesa/main/clear.c @@ -34,6 +34,8 @@ #include "clear.h" #include "context.h" #include "enums.h" +#include "fbobject.h" +#include "get.h" #include "macros.h" #include "mtypes.h" #include "state.h" @@ -400,6 +402,24 @@ _mesa_ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value) /** + * The ClearBuffer framework is so complicated and so riddled with the + * assumption that the framebuffer is bound that, for now, we will just fake + * direct state access clearing for the user. + */ +void GLAPIENTRY +_mesa_ClearNamedFramebufferiv(GLuint framebuffer, GLenum buffer, + GLint drawbuffer, const GLint *value) +{ + GLint oldfb; + + _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb); + _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer); + _mesa_ClearBufferiv(buffer, drawbuffer, value); + _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb); +} + + +/** * New in GL 3.0 * Clear unsigned integer color buffer (not depth, not stencil). */ @@ -472,6 +492,24 @@ _mesa_ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value) /** + * The ClearBuffer framework is so complicated and so riddled with the + * assumption that the framebuffer is bound that, for now, we will just fake + * direct state access clearing for the user. + */ +void GLAPIENTRY +_mesa_ClearNamedFramebufferuiv(GLuint framebuffer, GLenum buffer, + GLint drawbuffer, const GLuint *value) +{ + GLint oldfb; + + _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb); + _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer); + _mesa_ClearBufferuiv(buffer, drawbuffer, value); + _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb); +} + + +/** * New in GL 3.0 * Clear fixed-pt or float color buffer or depth buffer (not stencil). */ @@ -565,6 +603,24 @@ _mesa_ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value) /** + * The ClearBuffer framework is so complicated and so riddled with the + * assumption that the framebuffer is bound that, for now, we will just fake + * direct state access clearing for the user. + */ +void GLAPIENTRY +_mesa_ClearNamedFramebufferfv(GLuint framebuffer, GLenum buffer, + GLint drawbuffer, const GLfloat *value) +{ + GLint oldfb; + + _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb); + _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer); + _mesa_ClearBufferfv(buffer, drawbuffer, value); + _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb); +} + + +/** * New in GL 3.0 * Clear depth/stencil buffer only. */ @@ -626,3 +682,21 @@ _mesa_ClearBufferfi(GLenum buffer, GLint drawbuffer, ctx->Stencil.Clear = clearStencilSave; } } + + +/** + * The ClearBuffer framework is so complicated and so riddled with the + * assumption that the framebuffer is bound that, for now, we will just fake + * direct state access clearing for the user. + */ +void GLAPIENTRY +_mesa_ClearNamedFramebufferfi(GLuint framebuffer, GLenum buffer, + GLfloat depth, GLint stencil) +{ + GLint oldfb; + + _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb); + _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer); + _mesa_ClearBufferfi(buffer, 0, depth, stencil); + _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb); +} diff --git a/src/mesa/main/clear.h b/src/mesa/main/clear.h index 96ce47b929e..c29850676ca 100644 --- a/src/mesa/main/clear.h +++ b/src/mesa/main/clear.h @@ -52,13 +52,29 @@ extern void GLAPIENTRY _mesa_ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value); extern void GLAPIENTRY +_mesa_ClearNamedFramebufferiv(GLuint framebuffer, GLenum buffer, + GLint drawbuffer, const GLint *value); + +extern void GLAPIENTRY _mesa_ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value); extern void GLAPIENTRY +_mesa_ClearNamedFramebufferuiv(GLuint framebuffer, GLenum buffer, + GLint drawbuffer, const GLuint *value); + +extern void GLAPIENTRY _mesa_ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value); extern void GLAPIENTRY +_mesa_ClearNamedFramebufferfv(GLuint framebuffer, GLenum buffer, + GLint drawbuffer, const GLfloat *value); + +extern void GLAPIENTRY _mesa_ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); +extern void GLAPIENTRY +_mesa_ClearNamedFramebufferfi(GLuint framebuffer, GLenum buffer, + GLfloat depth, GLint stencil); + #endif diff --git a/src/mesa/main/config.h b/src/mesa/main/config.h index 5a66a4eec90..9c3baf4c6aa 100644 --- a/src/mesa/main/config.h +++ b/src/mesa/main/config.h @@ -213,19 +213,10 @@ /** For GL_ARB_fragment_program */ /*@{*/ #define MAX_FRAGMENT_PROGRAM_ADDRESS_REGS 0 +#define MAX_FRAGMENT_PROGRAM_PARAMS 64 +#define MAX_FRAGMENT_PROGRAM_INPUTS 12 /*@}*/ -/** For GL_NV_fragment_program */ -/*@{*/ -#define MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS 1024 /* 72 for GL_ARB_f_p */ -#define MAX_NV_FRAGMENT_PROGRAM_TEMPS 96 -#define MAX_NV_FRAGMENT_PROGRAM_PARAMS 64 -#define MAX_NV_FRAGMENT_PROGRAM_INPUTS 12 -#define MAX_NV_FRAGMENT_PROGRAM_OUTPUTS 3 -#define MAX_NV_FRAGMENT_PROGRAM_WRITE_ONLYS 2 -/*@}*/ - - /** For GL_ARB_vertex_shader */ /*@{*/ #define MAX_VERTEX_GENERIC_ATTRIBS 16 diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c index 0a192de8c0a..79fa01849e0 100644 --- a/src/mesa/main/context.c +++ b/src/mesa/main/context.c @@ -489,8 +489,8 @@ init_program_limits(struct gl_constants *consts, gl_shader_stage stage, prog->MaxOutputComponents = 16 * 4; /* old limit not to break tnl and swrast */ break; case MESA_SHADER_FRAGMENT: - prog->MaxParameters = MAX_NV_FRAGMENT_PROGRAM_PARAMS; - prog->MaxAttribs = MAX_NV_FRAGMENT_PROGRAM_INPUTS; + prog->MaxParameters = MAX_FRAGMENT_PROGRAM_PARAMS; + prog->MaxAttribs = MAX_FRAGMENT_PROGRAM_INPUTS; prog->MaxAddressRegs = MAX_FRAGMENT_PROGRAM_ADDRESS_REGS; prog->MaxUniformComponents = 4 * MAX_UNIFORMS; prog->MaxInputComponents = 16 * 4; /* old limit not to break tnl and swrast */ @@ -883,6 +883,19 @@ update_default_objects(struct gl_context *ctx) } +/* XXX this is temporary and should be removed at some point in the + * future when there's a reasonable expectation that the libGL library + * contains the _glapi_new_nop_table() and _glapi_set_nop_handler() + * functions which were added in Mesa 10.6. + */ +#if !defined(_WIN32) +/* Avoid libGL / driver ABI break */ +#define USE_GLAPI_NOP_FEATURES 0 +#else +#define USE_GLAPI_NOP_FEATURES 1 +#endif + + /** * This function is called by the glapi no-op functions. For each OpenGL * function/entrypoint there's a simple no-op function. These "no-op" @@ -898,6 +911,7 @@ update_default_objects(struct gl_context *ctx) * * \param name the name of the OpenGL function */ +#if USE_GLAPI_NOP_FEATURES static void nop_handler(const char *name) { @@ -914,6 +928,7 @@ nop_handler(const char *name) } #endif } +#endif /** @@ -923,12 +938,52 @@ nop_handler(const char *name) static void GLAPIENTRY nop_glFlush(void) { - /* don't record an error like we do in _mesa_generic_nop() */ + /* don't record an error like we do in nop_handler() */ +} +#endif + + +#if !USE_GLAPI_NOP_FEATURES +static int +generic_nop(void) +{ + GET_CURRENT_CONTEXT(ctx); + _mesa_error(ctx, GL_INVALID_OPERATION, + "unsupported function called " + "(unsupported extension or deprecated function?)"); + return 0; } #endif /** + * Create a new API dispatch table in which all entries point to the + * generic_nop() function. This will not work on Windows because of + * the __stdcall convention which requires the callee to clean up the + * call stack. That's impossible with one generic no-op function. + */ +struct _glapi_table * +_mesa_new_nop_table(unsigned numEntries) +{ + struct _glapi_table *table; + +#if !USE_GLAPI_NOP_FEATURES + table = malloc(numEntries * sizeof(_glapi_proc)); + if (table) { + _glapi_proc *entry = (_glapi_proc *) table; + unsigned i; + for (i = 0; i < numEntries; i++) { + entry[i] = (_glapi_proc) generic_nop; + } + } +#else + table = _glapi_new_nop_table(numEntries); +#endif + return table; +} + + +/** * Allocate and initialize a new dispatch table. The table will be * populated with pointers to "no-op" functions. In turn, the no-op * functions will call nop_handler() above. @@ -941,8 +996,9 @@ alloc_dispatch_table(void) * Mesa we do this to accommodate different versions of libGL and various * DRI drivers. */ - GLint numEntries = MAX2(_glapi_get_dispatch_table_size(), _gloffset_COUNT); - struct _glapi_table *table = _glapi_new_nop_table(numEntries); + int numEntries = MAX2(_glapi_get_dispatch_table_size(), _gloffset_COUNT); + + struct _glapi_table *table = _mesa_new_nop_table(numEntries); #if defined(_WIN32) if (table) { @@ -966,7 +1022,9 @@ alloc_dispatch_table(void) } #endif +#if USE_GLAPI_NOP_FEATURES _glapi_set_nop_handler(nop_handler); +#endif return table; } @@ -1111,9 +1169,7 @@ _mesa_initialize_context(struct gl_context *ctx, ctx->HasConfig = GL_FALSE; } - if (_mesa_is_desktop_gl(ctx)) { - _mesa_override_gl_version(ctx); - } + _mesa_override_gl_version(ctx); /* misc one-time initializations */ one_time_init(ctx); @@ -1275,7 +1331,6 @@ _mesa_free_context_data( struct gl_context *ctx ) _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, NULL); _mesa_reference_vertprog(ctx, &ctx->VertexProgram._TnlProgram, NULL); - _mesa_reference_geomprog(ctx, &ctx->GeometryProgram.Current, NULL); _mesa_reference_geomprog(ctx, &ctx->GeometryProgram._Current, NULL); _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, NULL); @@ -1565,7 +1620,8 @@ handle_first_current(struct gl_context *ctx) else buffer = GL_FRONT; - _mesa_drawbuffers(ctx, 1, &buffer, NULL /* destMask */); + _mesa_drawbuffers(ctx, ctx->DrawBuffer, 1, &buffer, + NULL /* destMask */); } if (ctx->ReadBuffer != _mesa_get_incomplete_framebuffer()) { @@ -1578,7 +1634,7 @@ handle_first_current(struct gl_context *ctx) bufferIndex = BUFFER_FRONT_LEFT; } - _mesa_readbuffer(ctx, buffer, bufferIndex); + _mesa_readbuffer(ctx, ctx->ReadBuffer, buffer, bufferIndex); } } diff --git a/src/mesa/main/copyimage.c b/src/mesa/main/copyimage.c index fd22f28892c..e8732c6175b 100644 --- a/src/mesa/main/copyimage.c +++ b/src/mesa/main/copyimage.c @@ -40,14 +40,25 @@ enum mesa_block_class { BLOCK_CLASS_64_BITS }; +/** + * Prepare the source or destination resource, including: + * - Error checking + * - Creating texture wrappers for renderbuffers + * \param name the texture or renderbuffer name + * \param target GL_TEXTURE target or GL_RENDERBUFFER. For the later, will + * be changed to a compatible GL_TEXTURE target. + * \param level mipmap level + * \param tex_obj returns a pointer to a texture object + * \param tex_image returns a pointer to a texture image + * \param tmp_tex returns temporary texture object name + * \return true if success, false if error + */ static bool prepare_target(struct gl_context *ctx, GLuint name, GLenum *target, int level, struct gl_texture_object **tex_obj, struct gl_texture_image **tex_image, GLuint *tmp_tex, const char *dbg_prefix) { - struct gl_renderbuffer *rb; - if (name == 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glCopyImageSubData(%sName = %d)", dbg_prefix, name); @@ -87,7 +98,7 @@ prepare_target(struct gl_context *ctx, GLuint name, GLenum *target, int level, } if (*target == GL_RENDERBUFFER) { - rb = _mesa_lookup_renderbuffer(ctx, name); + struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, name); if (!rb) { _mesa_error(ctx, GL_INVALID_VALUE, "glCopyImageSubData(%sName = %u)", dbg_prefix, name); @@ -169,8 +180,15 @@ prepare_target(struct gl_context *ctx, GLuint name, GLenum *target, int level, return true; } + +/** + * Check that the x,y,z,width,height,region is within the texture image + * dimensions. + * \return true if bounds OK, false if regions is out of bounds + */ static bool -check_region_bounds(struct gl_context *ctx, struct gl_texture_image *tex_image, +check_region_bounds(struct gl_context *ctx, + const struct gl_texture_image *tex_image, int x, int y, int z, int width, int height, int depth, const char *dbg_prefix) { @@ -188,6 +206,7 @@ check_region_bounds(struct gl_context *ctx, struct gl_texture_image *tex_image, return false; } + /* Check X direction */ if (x + width > tex_image->Width) { _mesa_error(ctx, GL_INVALID_VALUE, "glCopyImageSubData(%sX or %sWidth exceeds image bounds)", @@ -195,6 +214,7 @@ check_region_bounds(struct gl_context *ctx, struct gl_texture_image *tex_image, return false; } + /* Check Y direction */ switch (tex_image->TexObject->Target) { case GL_TEXTURE_1D: case GL_TEXTURE_1D_ARRAY: @@ -215,6 +235,7 @@ check_region_bounds(struct gl_context *ctx, struct gl_texture_image *tex_image, break; } + /* Check Z direction */ switch (tex_image->TexObject->Target) { case GL_TEXTURE_1D: case GL_TEXTURE_2D: @@ -260,7 +281,7 @@ check_region_bounds(struct gl_context *ctx, struct gl_texture_image *tex_image, } static bool -compressed_format_compatible(struct gl_context *ctx, +compressed_format_compatible(const struct gl_context *ctx, GLenum compressedFormat, GLenum otherFormat) { enum mesa_block_class compressedClass, otherClass; @@ -348,8 +369,8 @@ compressed_format_compatible(struct gl_context *ctx, } static bool -copy_format_compatible(struct gl_context *ctx, - GLenum srcFormat, GLenum dstFormat) +copy_format_compatible(const struct gl_context *ctx, + GLenum srcFormat, GLenum dstFormat) { /* * From ARB_copy_image spec: @@ -389,7 +410,7 @@ _mesa_CopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel, struct gl_texture_object *srcTexObj, *dstTexObj; struct gl_texture_image *srcTexImage, *dstTexImage; GLuint src_bw, src_bh, dst_bw, dst_bh; - int i, srcNewZ, dstNewZ; + int i; if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glCopyImageSubData(%u, %s, %d, %d, %d, %d, " @@ -447,6 +468,8 @@ _mesa_CopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel, } for (i = 0; i < srcDepth; ++i) { + int srcNewZ, dstNewZ; + if (srcTexObj->Target == GL_TEXTURE_CUBE_MAP) { srcTexImage = srcTexObj->Image[i + srcZ][srcLevel]; srcNewZ = 0; diff --git a/src/mesa/main/depth.c b/src/mesa/main/depth.c index 29851ecb8a4..bb4591cf152 100644 --- a/src/mesa/main/depth.c +++ b/src/mesa/main/depth.c @@ -65,6 +65,9 @@ _mesa_DepthFunc( GLenum func ) if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glDepthFunc %s\n", _mesa_lookup_enum_by_nr(func)); + if (ctx->Depth.Func == func) + return; + switch (func) { case GL_LESS: /* (default) pass if incoming z < stored z */ case GL_GEQUAL: @@ -80,9 +83,6 @@ _mesa_DepthFunc( GLenum func ) return; } - if (ctx->Depth.Func == func) - return; - FLUSH_VERTICES(ctx, _NEW_DEPTH); ctx->Depth.Func = func; diff --git a/src/mesa/main/dlist.c b/src/mesa/main/dlist.c index 431c4b48b79..aafe486fb60 100644 --- a/src/mesa/main/dlist.c +++ b/src/mesa/main/dlist.c @@ -7592,28 +7592,6 @@ save_FramebufferTexture(GLenum target, GLenum attachment, } } -static void GLAPIENTRY -save_FramebufferTextureFace(GLenum target, GLenum attachment, - GLuint texture, GLint level, GLenum face) -{ - Node *n; - GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_FRAMEBUFFER_TEXTURE_FACE, 5); - if (n) { - n[1].e = target; - n[2].e = attachment; - n[3].ui = texture; - n[4].i = level; - n[5].e = face; - } - if (ctx->ExecuteFlag) { - CALL_FramebufferTextureFaceARB(ctx->Exec, (target, attachment, texture, - level, face)); - } -} - - static void GLAPIENTRY save_WaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) @@ -8873,11 +8851,6 @@ execute_list(struct gl_context *ctx, GLuint list) CALL_FramebufferTexture(ctx->Exec, (n[1].e, n[2].e, n[3].ui, n[4].i)); break; - case OPCODE_FRAMEBUFFER_TEXTURE_FACE: - CALL_FramebufferTextureFaceARB(ctx->Exec, (n[1].e, n[2].e, - n[3].ui, n[4].i, n[5].e)); - break; - /* GL_ARB_sync */ case OPCODE_WAIT_SYNC: { @@ -9644,10 +9617,9 @@ _mesa_initialize_save_table(const struct gl_context *ctx) SET_BlendEquationiARB(table, save_BlendEquationi); SET_BlendEquationSeparateiARB(table, save_BlendEquationSeparatei); - /* GL_ARB_geometry_shader4 */ + /* OpenGL 3.2 */ SET_ProgramParameteri(table, save_ProgramParameteri); SET_FramebufferTexture(table, save_FramebufferTexture); - SET_FramebufferTextureFaceARB(table, save_FramebufferTextureFace); /* GL_NV_conditional_render */ SET_BeginConditionalRender(table, save_BeginConditionalRender); diff --git a/src/mesa/main/errors.c b/src/mesa/main/errors.c index 2aa1deb635f..b3406665d94 100644 --- a/src/mesa/main/errors.c +++ b/src/mesa/main/errors.c @@ -39,6 +39,7 @@ #include "mtypes.h" #include "version.h" #include "util/hash_table.h" +#include "util/simple_list.h" static mtx_t DynamicIDMutex = _MTX_INITIALIZER_NP; static GLuint NextDynamicID = 1; @@ -1412,6 +1413,26 @@ should_output(struct gl_context *ctx, GLenum error, const char *fmtString) void +_mesa_gl_vdebug(struct gl_context *ctx, + GLuint *id, + enum mesa_debug_source source, + enum mesa_debug_type type, + enum mesa_debug_severity severity, + const char *fmtString, + va_list args) +{ + char s[MAX_DEBUG_MESSAGE_LENGTH]; + int len; + + debug_get_id(id); + + len = _mesa_vsnprintf(s, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args); + + log_msg(ctx, source, type, *id, severity, len, s); +} + + +void _mesa_gl_debug(struct gl_context *ctx, GLuint *id, enum mesa_debug_source source, @@ -1419,17 +1440,10 @@ _mesa_gl_debug(struct gl_context *ctx, enum mesa_debug_severity severity, const char *fmtString, ...) { - char s[MAX_DEBUG_MESSAGE_LENGTH]; - int len; va_list args; - - debug_get_id(id); - va_start(args, fmtString); - len = _mesa_vsnprintf(s, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args); + _mesa_gl_vdebug(ctx, id, source, type, severity, fmtString, args); va_end(args); - - log_msg(ctx, source, type, *id, severity, len, s); } diff --git a/src/mesa/main/errors.h b/src/mesa/main/errors.h index e6dc9b5f1b9..24f234f7f10 100644 --- a/src/mesa/main/errors.h +++ b/src/mesa/main/errors.h @@ -76,6 +76,15 @@ extern FILE * _mesa_get_log_file(void); extern void +_mesa_gl_vdebug(struct gl_context *ctx, + GLuint *id, + enum mesa_debug_source source, + enum mesa_debug_type type, + enum mesa_debug_severity severity, + const char *fmtString, + va_list args); + +extern void _mesa_gl_debug(struct gl_context *ctx, GLuint *id, enum mesa_debug_source source, diff --git a/src/mesa/main/extensions.c b/src/mesa/main/extensions.c index f7ce0642aef..4176a69ed7c 100644 --- a/src/mesa/main/extensions.c +++ b/src/mesa/main/extensions.c @@ -104,7 +104,7 @@ static const struct extension extension_table[] = { { "GL_ARB_depth_clamp", o(ARB_depth_clamp), GL, 2003 }, { "GL_ARB_depth_texture", o(ARB_depth_texture), GLL, 2001 }, { "GL_ARB_derivative_control", o(ARB_derivative_control), GL, 2014 }, - { "GL_ARB_direct_state_access", o(dummy_false), GL, 2014 }, + { "GL_ARB_direct_state_access", o(dummy_true), GLC, 2014 }, { "GL_ARB_draw_buffers", o(dummy_true), GL, 2002 }, { "GL_ARB_draw_buffers_blend", o(ARB_draw_buffers_blend), GL, 2009 }, { "GL_ARB_draw_elements_base_vertex", o(ARB_draw_elements_base_vertex), GL, 2009 }, @@ -117,6 +117,7 @@ static const struct extension extension_table[] = { { "GL_ARB_fragment_program", o(ARB_fragment_program), GLL, 2002 }, { "GL_ARB_fragment_program_shadow", o(ARB_fragment_program_shadow), GLL, 2003 }, { "GL_ARB_fragment_shader", o(ARB_fragment_shader), GL, 2002 }, + { "GL_ARB_framebuffer_no_attachments", o(ARB_framebuffer_no_attachments), GL, 2012 }, { "GL_ARB_framebuffer_object", o(ARB_framebuffer_object), GL, 2005 }, { "GL_ARB_framebuffer_sRGB", o(EXT_framebuffer_sRGB), GL, 1998 }, { "GL_ARB_get_program_binary", o(dummy_true), GL, 2010 }, diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c index 27cf97f1778..f8dcf122d99 100644 --- a/src/mesa/main/fbobject.c +++ b/src/mesa/main/fbobject.c @@ -121,6 +121,27 @@ _mesa_lookup_renderbuffer(struct gl_context *ctx, GLuint id) /** + * A convenience function for direct state access that throws + * GL_INVALID_OPERATION if the renderbuffer doesn't exist. + */ +struct gl_renderbuffer * +_mesa_lookup_renderbuffer_err(struct gl_context *ctx, GLuint id, + const char *func) +{ + struct gl_renderbuffer *rb; + + rb = _mesa_lookup_renderbuffer(ctx, id); + if (!rb || rb == &DummyRenderbuffer) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(non-existent renderbuffer %u)", func, id); + return NULL; + } + + return rb; +} + + +/** * Helper routine for getting a gl_framebuffer. */ struct gl_framebuffer * @@ -138,6 +159,27 @@ _mesa_lookup_framebuffer(struct gl_context *ctx, GLuint id) /** + * A convenience function for direct state access that throws + * GL_INVALID_OPERATION if the framebuffer doesn't exist. + */ +struct gl_framebuffer * +_mesa_lookup_framebuffer_err(struct gl_context *ctx, GLuint id, + const char *func) +{ + struct gl_framebuffer *fb; + + fb = _mesa_lookup_framebuffer(ctx, id); + if (!fb || fb == &DummyFramebuffer) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(non-existent framebuffer %u)", func, id); + return NULL; + } + + return fb; +} + + +/** * Mark the given framebuffer as invalid. This will force the * test for framebuffer completeness to be done before the framebuffer * is used. @@ -423,7 +465,7 @@ 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, + GLenum texTarget, GLuint level, GLuint layer, GLboolean layered) { struct gl_renderbuffer *rb = att->Renderbuffer; @@ -447,7 +489,7 @@ set_texture_attachment(struct gl_context *ctx, /* always update these fields */ att->TextureLevel = level; att->CubeMapFace = _mesa_tex_target_to_face(texTarget); - att->Zoffset = zoffset; + att->Zoffset = layer; att->Layered = layered; att->Complete = GL_FALSE; @@ -479,9 +521,10 @@ set_renderbuffer_attachment(struct gl_context *ctx, * Attach a renderbuffer object to a framebuffer object. */ void -_mesa_framebuffer_renderbuffer(struct gl_context *ctx, - struct gl_framebuffer *fb, - GLenum attachment, struct gl_renderbuffer *rb) +_mesa_FramebufferRenderbuffer_sw(struct gl_context *ctx, + struct gl_framebuffer *fb, + GLenum attachment, + struct gl_renderbuffer *rb) { struct gl_renderbuffer_attachment *att; @@ -914,6 +957,7 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx, fb->Height = 0; fb->_AllColorBuffersFixedPoint = GL_TRUE; fb->_HasSNormOrFloatColorBuffer = GL_FALSE; + fb->_HasAttachments = true; /* Start at -2 to more easily loop over all attachment points. * -2: depth buffer @@ -1112,14 +1156,48 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx, } else if (att_layer_count > max_layer_count) { max_layer_count = att_layer_count; } + + /* + * The extension GL_ARB_framebuffer_no_attachments places additional + * requirement on each attachment. Those additional requirements are + * tighter that those of previous versions of GL. In interest of better + * compatibility, we will not enforce these restrictions. For the record + * those additional restrictions are quoted below: + * + * "The width and height of image are greater than zero and less than or + * equal to the values of the implementation-dependent limits + * MAX_FRAMEBUFFER_WIDTH and MAX_FRAMEBUFFER_HEIGHT, respectively." + * + * "If <image> is a three-dimensional texture or a one- or two-dimensional + * array texture and the attachment is layered, the depth or layer count + * of the texture is less than or equal to the implementation-dependent + * limit MAX_FRAMEBUFFER_LAYERS." + * + * "If image has multiple samples, its sample count is less than or equal + * to the value of the implementation-dependent limit + * MAX_FRAMEBUFFER_SAMPLES." + * + * The same requirements are also in place for GL 4.5, + * Section 9.4.1 "Framebuffer Attachment Completeness", pg 310-311 + */ } fb->MaxNumLayers = max_layer_count; if (numImages == 0) { - fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT; - fbo_incomplete(ctx, "no attachments", -1); - return; + fb->_HasAttachments = false; + + if (!ctx->Extensions.ARB_framebuffer_no_attachments) { + fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT; + fbo_incomplete(ctx, "no attachments", -1); + return; + } + + if (fb->DefaultGeometry.Width == 0 || fb->DefaultGeometry.Height == 0) { + fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT; + fbo_incomplete(ctx, "no attachments and default width or height is 0", -1); + return; + } } if (_mesa_is_desktop_gl(ctx) && !ctx->Extensions.ARB_ES2_compatibility) { @@ -1184,8 +1262,10 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx, * renderbuffers/textures are different sizes, the framebuffer * width/height will be set to the smallest width/height. */ - fb->Width = minWidth; - fb->Height = minHeight; + if (numImages != 0) { + fb->Width = minWidth; + fb->Height = minHeight; + } /* finally, update the visual info for the framebuffer */ _mesa_update_framebuffer_visual(ctx, fb); @@ -1291,6 +1371,131 @@ _mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer) bind_renderbuffer(target, renderbuffer, true); } +static void +framebuffer_parameteri(struct gl_context *ctx, struct gl_framebuffer *fb, + GLenum pname, GLint param, const char *func) +{ + switch (pname) { + case GL_FRAMEBUFFER_DEFAULT_WIDTH: + if (param < 0 || param > ctx->Const.MaxFramebufferWidth) + _mesa_error(ctx, GL_INVALID_VALUE, "%s", func); + else + fb->DefaultGeometry.Width = param; + break; + case GL_FRAMEBUFFER_DEFAULT_HEIGHT: + if (param < 0 || param > ctx->Const.MaxFramebufferHeight) + _mesa_error(ctx, GL_INVALID_VALUE, "%s", func); + else + fb->DefaultGeometry.Height = param; + break; + case GL_FRAMEBUFFER_DEFAULT_LAYERS: + if (param < 0 || param > ctx->Const.MaxFramebufferLayers) + _mesa_error(ctx, GL_INVALID_VALUE, "%s", func); + else + fb->DefaultGeometry.Layers = param; + break; + case GL_FRAMEBUFFER_DEFAULT_SAMPLES: + if (param < 0 || param > ctx->Const.MaxFramebufferSamples) + _mesa_error(ctx, GL_INVALID_VALUE, "%s", func); + else + fb->DefaultGeometry.NumSamples = param; + break; + case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS: + fb->DefaultGeometry.FixedSampleLocations = param; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, + "%s(pname=0x%x)", func, pname); + } +} + +void GLAPIENTRY +_mesa_FramebufferParameteri(GLenum target, GLenum pname, GLint param) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_framebuffer *fb; + + if (!ctx->Extensions.ARB_framebuffer_no_attachments) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glFramebufferParameteriv not supported " + "(ARB_framebuffer_no_attachments not implemented)"); + return; + } + + fb = get_framebuffer_target(ctx, target); + if (!fb) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glFramebufferParameteri(target=0x%x)", target); + return; + } + + /* check framebuffer binding */ + if (_mesa_is_winsys_fbo(fb)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glFramebufferParameteri"); + return; + } + + framebuffer_parameteri(ctx, fb, pname, param, "glFramebufferParameteri"); +} + +static void +get_framebuffer_parameteriv(struct gl_context *ctx, struct gl_framebuffer *fb, + GLenum pname, GLint *params, const char *func) +{ + switch (pname) { + case GL_FRAMEBUFFER_DEFAULT_WIDTH: + *params = fb->DefaultGeometry.Width; + break; + case GL_FRAMEBUFFER_DEFAULT_HEIGHT: + *params = fb->DefaultGeometry.Height; + break; + case GL_FRAMEBUFFER_DEFAULT_LAYERS: + *params = fb->DefaultGeometry.Layers; + break; + case GL_FRAMEBUFFER_DEFAULT_SAMPLES: + *params = fb->DefaultGeometry.NumSamples; + break; + case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS: + *params = fb->DefaultGeometry.FixedSampleLocations; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, + "%s(pname=0x%x)", func, pname); + } +} + +void GLAPIENTRY +_mesa_GetFramebufferParameteriv(GLenum target, GLenum pname, GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_framebuffer *fb; + + if (!ctx->Extensions.ARB_framebuffer_no_attachments) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetFramebufferParameteriv not supported " + "(ARB_framebuffer_no_attachments not implemented)"); + return; + } + + fb = get_framebuffer_target(ctx, target); + if (!fb) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetFramebufferParameteriv(target=0x%x)", target); + return; + } + + /* check framebuffer binding */ + if (_mesa_is_winsys_fbo(fb)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetFramebufferParameteriv"); + return; + } + + get_framebuffer_parameteriv(ctx, fb, pname, params, + "glGetFramebufferParameteriv"); +} + /** * Remove the specified renderbuffer or texture from any attachment point in @@ -2396,15 +2601,23 @@ _mesa_DeleteFramebuffers(GLsizei n, const GLuint *framebuffers) } -void GLAPIENTRY -_mesa_GenFramebuffers(GLsizei n, GLuint *framebuffers) +/** + * This is the implementation for glGenFramebuffers and glCreateFramebuffers. + * It is not exposed to the rest of Mesa to encourage the use of + * nameless buffers in driver internals. + */ +static void +create_framebuffers(GLsizei n, GLuint *framebuffers, bool dsa) { GET_CURRENT_CONTEXT(ctx); GLuint first; GLint i; + struct gl_framebuffer *fb; + + const char *func = dsa ? "glCreateFramebuffers" : "glGenFramebuffers"; if (n < 0) { - _mesa_error(ctx, GL_INVALID_VALUE, "glGenFramebuffersEXT(n)"); + _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func); return; } @@ -2416,31 +2629,43 @@ _mesa_GenFramebuffers(GLsizei n, GLuint *framebuffers) for (i = 0; i < n; i++) { GLuint name = first + i; framebuffers[i] = name; - /* insert dummy placeholder into hash table */ + + if (dsa) { + fb = ctx->Driver.NewFramebuffer(ctx, framebuffers[i]); + if (!fb) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func); + return; + } + } + else + fb = &DummyFramebuffer; + mtx_lock(&ctx->Shared->Mutex); - _mesa_HashInsert(ctx->Shared->FrameBuffers, name, &DummyFramebuffer); + _mesa_HashInsert(ctx->Shared->FrameBuffers, name, fb); mtx_unlock(&ctx->Shared->Mutex); } } -GLenum GLAPIENTRY -_mesa_CheckFramebufferStatus(GLenum target) +void GLAPIENTRY +_mesa_GenFramebuffers(GLsizei n, GLuint *framebuffers) { - struct gl_framebuffer *buffer; - GET_CURRENT_CONTEXT(ctx); + create_framebuffers(n, framebuffers, false); +} - ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0); - if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glCheckFramebufferStatus(%s)\n", - _mesa_lookup_enum_by_nr(target)); +void GLAPIENTRY +_mesa_CreateFramebuffers(GLsizei n, GLuint *framebuffers) +{ + create_framebuffers(n, framebuffers, true); +} - buffer = get_framebuffer_target(ctx, target); - if (!buffer) { - _mesa_error(ctx, GL_INVALID_ENUM, "glCheckFramebufferStatus(target)"); - return 0; - } + +GLenum +_mesa_check_framebuffer_status(struct gl_context *ctx, + struct gl_framebuffer *buffer) +{ + ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0); if (_mesa_is_winsys_fbo(buffer)) { /* EGL_KHR_surfaceless_context allows the winsys FBO to be incomplete. */ @@ -2461,6 +2686,67 @@ _mesa_CheckFramebufferStatus(GLenum target) } +GLenum GLAPIENTRY +_mesa_CheckFramebufferStatus(GLenum target) +{ + struct gl_framebuffer *fb; + GET_CURRENT_CONTEXT(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glCheckFramebufferStatus(%s)\n", + _mesa_lookup_enum_by_nr(target)); + + fb = get_framebuffer_target(ctx, target); + if (!fb) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glCheckFramebufferStatus(invalid target %s)", + _mesa_lookup_enum_by_nr(target)); + return 0; + } + + return _mesa_check_framebuffer_status(ctx, fb); +} + + +GLenum GLAPIENTRY +_mesa_CheckNamedFramebufferStatus(GLuint framebuffer, GLenum target) +{ + struct gl_framebuffer *fb; + GET_CURRENT_CONTEXT(ctx); + + /* Validate the target (for conformance's sake) and grab a reference to the + * default framebuffer in case framebuffer = 0. + * Section 9.4 Framebuffer Completeness of the OpenGL 4.5 core spec + * (30.10.2014, PDF page 336) says: + * "If framebuffer is zero, then the status of the default read or + * draw framebuffer (as determined by target) is returned." + */ + switch (target) { + case GL_DRAW_FRAMEBUFFER: + case GL_FRAMEBUFFER: + fb = ctx->WinSysDrawBuffer; + break; + case GL_READ_FRAMEBUFFER: + fb = ctx->WinSysReadBuffer; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, + "glCheckNamedFramebufferStatus(invalid target %s)", + _mesa_lookup_enum_by_nr(target)); + return 0; + } + + if (framebuffer) { + fb = _mesa_lookup_framebuffer_err(ctx, framebuffer, + "glCheckNamedFramebufferStatus"); + if (!fb) + return 0; + } + + return _mesa_check_framebuffer_status(ctx, fb); +} + + /** * Replicate the src attachment point. Used by framebuffer_texture() when * the same texture is attached at GL_DEPTH_ATTACHMENT and @@ -2487,144 +2773,308 @@ reuse_framebuffer_texture_attachment(struct gl_framebuffer *fb, /** - * Common code called by glFramebufferTexture1D/2D/3D() and - * glFramebufferTextureLayer(). + * Common code called by gl*FramebufferTexture*() to retrieve the correct + * texture object pointer. * - * \param textarget is the textarget that was passed to the - * glFramebufferTexture...() function, or 0 if the corresponding function - * doesn't have a textarget parameter. + * \param texObj where the pointer to the texture object is returned. Note + * that a successful call may return texObj = NULL. * - * \param layered is true if this function was called from - * glFramebufferTexture(), false otherwise. + * \return true if no errors, false if errors */ -static void -framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target, - GLenum attachment, GLenum textarget, GLuint texture, - GLint level, GLuint zoffset, GLboolean layered) +static bool +get_texture_for_framebuffer(struct gl_context *ctx, GLuint texture, + bool layered, const char *caller, + struct gl_texture_object **texObj) { - struct gl_renderbuffer_attachment *att; - struct gl_texture_object *texObj = NULL; - struct gl_framebuffer *fb; - GLenum maxLevelsTarget; + *texObj = NULL; /* This will get returned if texture = 0. */ - fb = get_framebuffer_target(ctx, target); - if (!fb) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glFramebufferTexture%s(target=0x%x)", caller, target); - return; + if (!texture) + return true; + + *texObj = _mesa_lookup_texture(ctx, texture); + if (*texObj == NULL || (*texObj)->Target == 0) { + /* Can't render to a non-existent texture object. + * + * The OpenGL 4.5 core spec (02.02.2015) in Section 9.2 Binding and + * Managing Framebuffer Objects specifies a different error + * depending upon the calling function (PDF pages 325-328). + * *FramebufferTexture (where layered = GL_TRUE) throws invalid + * value, while the other commands throw invalid operation (where + * layered = GL_FALSE). + */ + const GLenum error = layered ? GL_INVALID_VALUE : + GL_INVALID_OPERATION; + _mesa_error(ctx, error, + "%s(non-existent texture %u)", caller, texture); + return false; } - /* check framebuffer binding */ - if (_mesa_is_winsys_fbo(fb)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glFramebufferTexture%s", caller); - return; + return true; +} + + +/** + * Common code called by gl*FramebufferTexture() to verify the texture target + * and decide whether or not the attachment should truly be considered + * layered. + * + * \param layered true if attachment should be considered layered, false if + * not + * + * \return true if no errors, false if errors + */ +static bool +check_layered_texture_target(struct gl_context *ctx, GLenum target, + const char *caller, GLboolean *layered) +{ + *layered = GL_TRUE; + + switch (target) { + case GL_TEXTURE_3D: + case GL_TEXTURE_1D_ARRAY_EXT: + case GL_TEXTURE_2D_ARRAY_EXT: + case GL_TEXTURE_CUBE_MAP: + case GL_TEXTURE_CUBE_MAP_ARRAY: + case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: + return true; + case GL_TEXTURE_1D: + case GL_TEXTURE_2D: + case GL_TEXTURE_RECTANGLE: + case GL_TEXTURE_2D_MULTISAMPLE: + /* These texture types are valid to pass to + * glFramebufferTexture(), but since they aren't layered, it + * is equivalent to calling glFramebufferTexture{1D,2D}(). + */ + *layered = GL_FALSE; + return true; } - /* The textarget, level, and zoffset parameters are only validated if - * texture is non-zero. + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(invalid texture target %s)", caller, + _mesa_lookup_enum_by_nr(target)); + return false; +} + + +/** + * Common code called by gl*FramebufferTextureLayer() to verify the texture + * target. + * + * \return true if no errors, false if errors + */ +static bool +check_texture_target(struct gl_context *ctx, GLenum target, + const char *caller) +{ + /* We're being called by glFramebufferTextureLayer(). + * The only legal texture types for that function are 3D, + * cube-map, and 1D/2D/cube-map array textures. + * + * We don't need to check for GL_ARB_texture_cube_map_array because the + * application wouldn't have been able to create a texture with a + * GL_TEXTURE_CUBE_MAP_ARRAY target if the extension were not enabled. */ - if (texture) { - GLboolean err = GL_TRUE; - - texObj = _mesa_lookup_texture(ctx, texture); - if (texObj != NULL) { - if (textarget == 0) { - if (layered) { - /* We're being called by glFramebufferTexture() and textarget - * is not used. - */ - switch (texObj->Target) { - case GL_TEXTURE_3D: - case GL_TEXTURE_1D_ARRAY_EXT: - case GL_TEXTURE_2D_ARRAY_EXT: - case GL_TEXTURE_CUBE_MAP: - case GL_TEXTURE_CUBE_MAP_ARRAY: - case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: - err = false; - break; - case GL_TEXTURE_1D: - case GL_TEXTURE_2D: - case GL_TEXTURE_RECTANGLE: - case GL_TEXTURE_2D_MULTISAMPLE: - /* These texture types are valid to pass to - * glFramebufferTexture(), but since they aren't layered, it - * is equivalent to calling glFramebufferTexture{1D,2D}(). - */ - err = false; - layered = false; - textarget = texObj->Target; - break; - default: - err = true; - break; - } - } else { - /* 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_CUBE_MAP_ARRAY) && - (texObj->Target != GL_TEXTURE_2D_MULTISAMPLE_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); - } + switch (target) { + case GL_TEXTURE_3D: + case GL_TEXTURE_1D_ARRAY: + case GL_TEXTURE_2D_ARRAY: + case GL_TEXTURE_CUBE_MAP_ARRAY: + case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: + return true; + case GL_TEXTURE_CUBE_MAP: + /* We don't need to check the extension (GL_ARB_direct_state_access) or + * GL version (4.5) for GL_TEXTURE_CUBE_MAP because DSA is always + * enabled in core profile. This can be called from + * _mesa_FramebufferTextureLayer in compatibility profile (OpenGL 3.0), + * so we do have to check the profile. + */ + return ctx->API == API_OPENGL_CORE; + } + + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(invalid texture target %s)", caller, + _mesa_lookup_enum_by_nr(target)); + return false; +} + + +/** + * Common code called by glFramebufferTexture*D() to verify the texture + * target. + * + * \return true if no errors, false if errors + */ +static bool +check_textarget(struct gl_context *ctx, int dims, GLenum target, + GLenum textarget, const char *caller) +{ + bool err = false; + + switch (dims) { + case 1: + switch (textarget) { + case GL_TEXTURE_1D: + break; + case GL_TEXTURE_1D_ARRAY: + err = !ctx->Extensions.EXT_texture_array; + break; + default: + err = true; } - else { - /* can't render to a non-existant texture */ - _mesa_error(ctx, GL_INVALID_OPERATION, - "glFramebufferTexture%s(non existant texture)", - caller); - return; + break; + case 2: + switch (textarget) { + case GL_TEXTURE_2D: + break; + case GL_TEXTURE_RECTANGLE: + err = _mesa_is_gles(ctx) + || !ctx->Extensions.NV_texture_rectangle; + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + err = !ctx->Extensions.ARB_texture_cube_map; + break; + case GL_TEXTURE_2D_ARRAY: + err = (_mesa_is_gles(ctx) && ctx->Version < 30) + || !ctx->Extensions.EXT_texture_array; + break; + case GL_TEXTURE_2D_MULTISAMPLE: + case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: + err = _mesa_is_gles(ctx) + || !ctx->Extensions.ARB_texture_multisample; + break; + default: + err = true; } + break; + case 3: + if (textarget != GL_TEXTURE_3D) + err = true; + break; + default: + err = true; + } - if (err) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glFramebufferTexture%s(texture target mismatch)", - caller); - return; - } + if (err) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(invalid textarget %s)", + caller, _mesa_lookup_enum_by_nr(textarget)); + return false; + } - if (texObj->Target == GL_TEXTURE_3D) { - const GLuint maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1); - if (zoffset >= maxSize) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glFramebufferTexture%s(zoffset)", caller); - return; - } + /* Make sure textarget is consistent with the texture's type */ + err = (target == GL_TEXTURE_CUBE_MAP) ? + !_mesa_is_cube_face(textarget): (target != textarget); + + if (err) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(mismatched texture target)", caller); + return false; + } + + return true; +} + + +/** + * Common code called by gl*FramebufferTextureLayer() and + * glFramebufferTexture3D() to validate the layer. + * + * \return true if no errors, false if errors + */ +static bool +check_layer(struct gl_context *ctx, GLenum target, GLint layer, + const char *caller) +{ + /* Page 306 (page 328 of the PDF) of the OpenGL 4.5 (Core Profile) + * spec says: + * + * "An INVALID_VALUE error is generated if texture is non-zero + * and layer is negative." + */ + if (layer < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, + "%s(layer %u < 0)", caller, layer); + return false; + } + + if (target == GL_TEXTURE_3D) { + const GLuint maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1); + if (layer >= maxSize) { + _mesa_error(ctx, GL_INVALID_VALUE, + "%s(invalid layer %u)", caller, layer); + return false; } - else if ((texObj->Target == GL_TEXTURE_1D_ARRAY_EXT) || - (texObj->Target == GL_TEXTURE_2D_ARRAY_EXT) || - (texObj->Target == GL_TEXTURE_CUBE_MAP_ARRAY) || - (texObj->Target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)) { - if (zoffset >= ctx->Const.MaxArrayTextureLayers) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glFramebufferTexture%s(layer)", caller); - return; - } + } + else if ((target == GL_TEXTURE_1D_ARRAY) || + (target == GL_TEXTURE_2D_ARRAY) || + (target == GL_TEXTURE_CUBE_MAP_ARRAY) || + (target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)) { + if (layer >= ctx->Const.MaxArrayTextureLayers) { + _mesa_error(ctx, GL_INVALID_VALUE, + "%s(layer %u >= GL_MAX_ARRAY_TEXTURE_LAYERS)", + caller, layer); + return false; } - - maxLevelsTarget = textarget ? textarget : texObj->Target; - if ((level < 0) || - (level >= _mesa_max_texture_levels(ctx, maxLevelsTarget))) { + } + else if (target == GL_TEXTURE_CUBE_MAP) { + if (layer >= 6) { _mesa_error(ctx, GL_INVALID_VALUE, - "glFramebufferTexture%s(level)", caller); - return; + "%s(layer %u >= 6)", caller, layer); + return false; } } + return true; +} + + +/** + * Common code called by all gl*FramebufferTexture*() entry points to verify + * the level. + * + * \return true if no errors, false if errors + */ +static bool +check_level(struct gl_context *ctx, GLenum target, GLint level, + const char *caller) +{ + if ((level < 0) || + (level >= _mesa_max_texture_levels(ctx, target))) { + _mesa_error(ctx, GL_INVALID_VALUE, + "%s(invalid level %d)", caller, level); + return false; + } + + return true; +} + + +void +_mesa_framebuffer_texture(struct gl_context *ctx, struct gl_framebuffer *fb, + GLenum attachment, + struct gl_texture_object *texObj, GLenum textarget, + GLint level, GLuint layer, GLboolean layered, + const char *caller) +{ + struct gl_renderbuffer_attachment *att; + + /* The window-system framebuffer object is immutable */ + if (_mesa_is_winsys_fbo(fb)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(window-system framebuffer)", + caller); + return; + } + + /* Not a hash lookup, so we can afford to get the attachment here. */ att = get_attachment(ctx, fb, attachment); if (att == NULL) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glFramebufferTexture%s(attachment)", caller); + _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid attachment %s)", caller, + _mesa_lookup_enum_by_nr(attachment)); return; } @@ -2637,7 +3087,7 @@ framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target, level == fb->Attachment[BUFFER_STENCIL].TextureLevel && _mesa_tex_target_to_face(textarget) == fb->Attachment[BUFFER_STENCIL].CubeMapFace && - zoffset == fb->Attachment[BUFFER_STENCIL].Zoffset) { + layer == 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 @@ -2650,13 +3100,14 @@ framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target, level == fb->Attachment[BUFFER_DEPTH].TextureLevel && _mesa_tex_target_to_face(textarget) == fb->Attachment[BUFFER_DEPTH].CubeMapFace && - zoffset == fb->Attachment[BUFFER_DEPTH].Zoffset) { + layer == fb->Attachment[BUFFER_DEPTH].Zoffset) { /* As above, but with depth and stencil transposed. */ reuse_framebuffer_texture_attachment(fb, BUFFER_STENCIL, BUFFER_DEPTH); } else { set_texture_attachment(ctx, fb, att, texObj, textarget, - level, zoffset, layered); + level, layer, layered); + if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) { /* Above we created a new renderbuffer and attached it to the * depth attachment point. Now attach it to the stencil attachment @@ -2692,116 +3143,157 @@ framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target, } -void GLAPIENTRY -_mesa_FramebufferTexture1D(GLenum target, GLenum attachment, - GLenum textarget, GLuint texture, GLint level) +static void +framebuffer_texture_with_dims(int dims, GLenum target, + GLenum attachment, GLenum textarget, + GLuint texture, GLint level, GLint layer, + const char *caller) { GET_CURRENT_CONTEXT(ctx); + struct gl_framebuffer *fb; + struct gl_texture_object *texObj; + + /* Get the framebuffer object */ + fb = get_framebuffer_target(ctx, target); + if (!fb) { + _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", caller, + _mesa_lookup_enum_by_nr(target)); + return; + } - if (texture != 0) { - GLboolean error; + /* Get the texture object */ + if (!get_texture_for_framebuffer(ctx, texture, false, caller, &texObj)) + return; - switch (textarget) { - case GL_TEXTURE_1D: - error = GL_FALSE; - break; - case GL_TEXTURE_1D_ARRAY: - error = !ctx->Extensions.EXT_texture_array; - break; - default: - error = GL_TRUE; - } + if (texObj) { + if (!check_textarget(ctx, dims, texObj->Target, textarget, caller)) + return; - if (error) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glFramebufferTexture1D(textarget=%s)", - _mesa_lookup_enum_by_nr(textarget)); + if ((dims == 3) && !check_layer(ctx, texObj->Target, layer, caller)) return; - } } - framebuffer_texture(ctx, "1D", target, attachment, textarget, texture, - level, 0, GL_FALSE); + if (!check_level(ctx, textarget, level, caller)) + return; + + _mesa_framebuffer_texture(ctx, fb, attachment, texObj, textarget, level, + layer, GL_FALSE, caller); } void GLAPIENTRY -_mesa_FramebufferTexture2D(GLenum target, GLenum attachment, +_mesa_FramebufferTexture1D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) { - GET_CURRENT_CONTEXT(ctx); - - if (texture != 0) { - GLboolean error; - - switch (textarget) { - case GL_TEXTURE_2D: - error = GL_FALSE; - break; - case GL_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: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - error = !ctx->Extensions.ARB_texture_cube_map; - break; - case GL_TEXTURE_2D_ARRAY: - error = (_mesa_is_gles(ctx) && ctx->Version < 30) - || !ctx->Extensions.EXT_texture_array; - break; - case GL_TEXTURE_2D_MULTISAMPLE: - case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: - error = _mesa_is_gles(ctx) - || !ctx->Extensions.ARB_texture_multisample; - break; - default: - error = GL_TRUE; - } + framebuffer_texture_with_dims(1, target, attachment, textarget, texture, + level, 0, "glFramebufferTexture1D"); +} - if (error) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glFramebufferTexture2D(textarget=%s)", - _mesa_lookup_enum_by_nr(textarget)); - return; - } - } - framebuffer_texture(ctx, "2D", target, attachment, textarget, texture, - level, 0, GL_FALSE); +void GLAPIENTRY +_mesa_FramebufferTexture2D(GLenum target, GLenum attachment, + GLenum textarget, GLuint texture, GLint level) +{ + framebuffer_texture_with_dims(2, target, attachment, textarget, texture, + level, 0, "glFramebufferTexture2D"); } void GLAPIENTRY _mesa_FramebufferTexture3D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, - GLint level, GLint zoffset) + GLint level, GLint layer) +{ + framebuffer_texture_with_dims(3, target, attachment, textarget, texture, + level, layer, "glFramebufferTexture3D"); +} + + +void GLAPIENTRY +_mesa_FramebufferTextureLayer(GLenum target, GLenum attachment, + GLuint texture, GLint level, GLint layer) { GET_CURRENT_CONTEXT(ctx); + struct gl_framebuffer *fb; + struct gl_texture_object *texObj; + GLenum textarget = 0; - if ((texture != 0) && (textarget != GL_TEXTURE_3D)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glFramebufferTexture3D(textarget)"); + const char *func = "glFramebufferTextureLayer"; + + /* Get the framebuffer object */ + fb = get_framebuffer_target(ctx, target); + if (!fb) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glFramebufferTextureLayer(invalid target %s)", + _mesa_lookup_enum_by_nr(target)); return; } - framebuffer_texture(ctx, "3D", target, attachment, textarget, texture, - level, zoffset, GL_FALSE); + /* Get the texture object */ + if (!get_texture_for_framebuffer(ctx, texture, false, func, &texObj)) + return; + + if (texObj) { + if (!check_texture_target(ctx, texObj->Target, func)) + return; + + if (!check_layer(ctx, texObj->Target, layer, func)) + return; + + if (!check_level(ctx, texObj->Target, level, func)) + return; + + if (texObj->Target == GL_TEXTURE_CUBE_MAP) { + assert(layer >= 0 && layer < 6); + textarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer; + layer = 0; + } + } + + _mesa_framebuffer_texture(ctx, fb, attachment, texObj, textarget, level, + layer, GL_FALSE, func); } void GLAPIENTRY -_mesa_FramebufferTextureLayer(GLenum target, GLenum attachment, - GLuint texture, GLint level, GLint layer) +_mesa_NamedFramebufferTextureLayer(GLuint framebuffer, GLenum attachment, + GLuint texture, GLint level, GLint layer) { GET_CURRENT_CONTEXT(ctx); + struct gl_framebuffer *fb; + struct gl_texture_object *texObj; + GLenum textarget = 0; + + const char *func = "glNamedFramebufferTextureLayer"; + + /* Get the framebuffer object */ + fb = _mesa_lookup_framebuffer_err(ctx, framebuffer, func); + if (!fb) + return; + + /* Get the texture object */ + if (!get_texture_for_framebuffer(ctx, texture, false, func, &texObj)) + return; + + if (texObj) { + if (!check_texture_target(ctx, texObj->Target, func)) + return; - framebuffer_texture(ctx, "Layer", target, attachment, 0, texture, - level, layer, GL_FALSE); + if (!check_layer(ctx, texObj->Target, layer, func)) + return; + + if (!check_level(ctx, texObj->Target, level, func)) + return; + + if (texObj->Target == GL_TEXTURE_CUBE_MAP) { + assert(layer >= 0 && layer < 6); + textarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer; + layer = 0; + } + } + + _mesa_framebuffer_texture(ctx, fb, attachment, texObj, textarget, level, + layer, GL_FALSE, func); } @@ -2810,82 +3302,115 @@ _mesa_FramebufferTexture(GLenum target, GLenum attachment, GLuint texture, GLint level) { GET_CURRENT_CONTEXT(ctx); + struct gl_framebuffer *fb; + struct gl_texture_object *texObj; + GLboolean layered; - if (_mesa_has_geometry_shaders(ctx)) { - framebuffer_texture(ctx, "", target, attachment, 0, texture, - level, 0, GL_TRUE); - } else { + const char *func = "FramebufferTexture"; + + if (!_mesa_has_geometry_shaders(ctx)) { _mesa_error(ctx, GL_INVALID_OPERATION, "unsupported function (glFramebufferTexture) called"); + return; } + + /* Get the framebuffer object */ + fb = get_framebuffer_target(ctx, target); + if (!fb) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glFramebufferTexture(invalid target %s)", + _mesa_lookup_enum_by_nr(target)); + return; + } + + /* Get the texture object */ + if (!get_texture_for_framebuffer(ctx, texture, true, func, &texObj)) + return; + + if (texObj) { + if (!check_layered_texture_target(ctx, texObj->Target, func, &layered)) + return; + + if (!check_level(ctx, texObj->Target, level, func)) + return; + } + + _mesa_framebuffer_texture(ctx, fb, attachment, texObj, 0, level, + 0, layered, func); } void GLAPIENTRY -_mesa_FramebufferRenderbuffer(GLenum target, GLenum attachment, - GLenum renderbufferTarget, - GLuint renderbuffer) +_mesa_NamedFramebufferTexture(GLuint framebuffer, GLenum attachment, + GLuint texture, GLint level) { - struct gl_renderbuffer_attachment *att; - struct gl_framebuffer *fb; - struct gl_renderbuffer *rb; GET_CURRENT_CONTEXT(ctx); + struct gl_framebuffer *fb; + struct gl_texture_object *texObj; + GLboolean layered; - fb = get_framebuffer_target(ctx, target); - if (!fb) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glFramebufferRenderbuffer(target)"); + const char *func = "glNamedFramebufferTexture"; + + if (!_mesa_has_geometry_shaders(ctx)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "unsupported function (glNamedFramebufferTexture) called"); return; } - if (renderbufferTarget != GL_RENDERBUFFER_EXT) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glFramebufferRenderbuffer(renderbufferTarget)"); + /* Get the framebuffer object */ + fb = _mesa_lookup_framebuffer_err(ctx, framebuffer, func); + if (!fb) return; + + /* Get the texture object */ + if (!get_texture_for_framebuffer(ctx, texture, true, func, &texObj)) + return; + + if (texObj) { + if (!check_layered_texture_target(ctx, texObj->Target, func, + &layered)) + return; + + if (!check_level(ctx, texObj->Target, level, func)) + return; } + _mesa_framebuffer_texture(ctx, fb, attachment, texObj, 0, level, + 0, layered, func); +} + + +void +_mesa_framebuffer_renderbuffer(struct gl_context *ctx, + struct gl_framebuffer *fb, + GLenum attachment, + struct gl_renderbuffer *rb, + const char *func) +{ + struct gl_renderbuffer_attachment *att; + if (_mesa_is_winsys_fbo(fb)) { /* Can't attach new renderbuffers to a window system framebuffer */ - _mesa_error(ctx, GL_INVALID_OPERATION, "glFramebufferRenderbuffer"); + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(window-system framebuffer)", func); return; } att = get_attachment(ctx, fb, attachment); if (att == NULL) { _mesa_error(ctx, GL_INVALID_ENUM, - "glFramebufferRenderbuffer(invalid attachment %s)", + "%s(invalid attachment %s)", func, _mesa_lookup_enum_by_nr(attachment)); return; } - if (renderbuffer) { - rb = _mesa_lookup_renderbuffer(ctx, renderbuffer); - if (!rb) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glFramebufferRenderbuffer(non-existant" - " renderbuffer %u)", renderbuffer); - return; - } - else if (rb == &DummyRenderbuffer) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glFramebufferRenderbuffer(renderbuffer %u)", - renderbuffer); - return; - } - } - else { - /* remove renderbuffer attachment */ - rb = NULL; - } - if (attachment == GL_DEPTH_STENCIL_ATTACHMENT && rb && rb->Format != MESA_FORMAT_NONE) { /* make sure the renderbuffer is a depth/stencil format */ const GLenum baseFormat = _mesa_get_format_base_format(rb->Format); if (baseFormat != GL_DEPTH_STENCIL) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glFramebufferRenderbuffer(renderbuffer" - " is not DEPTH_STENCIL format)"); + "%s(renderbuffer is not DEPTH_STENCIL format)", func); return; } } @@ -2903,24 +3428,94 @@ _mesa_FramebufferRenderbuffer(GLenum target, GLenum attachment, void GLAPIENTRY -_mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, - GLenum pname, GLint *params) +_mesa_FramebufferRenderbuffer(GLenum target, GLenum attachment, + GLenum renderbuffertarget, + GLuint renderbuffer) { - const struct gl_renderbuffer_attachment *att; - struct gl_framebuffer *buffer; - GLenum err; + struct gl_framebuffer *fb; + struct gl_renderbuffer *rb; GET_CURRENT_CONTEXT(ctx); - /* The error differs in GL and GLES. */ - err = _mesa_is_desktop_gl(ctx) ? GL_INVALID_OPERATION : GL_INVALID_ENUM; + fb = get_framebuffer_target(ctx, target); + if (!fb) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glFramebufferRenderbuffer(invalid target %s)", + _mesa_lookup_enum_by_nr(target)); + return; + } - buffer = get_framebuffer_target(ctx, target); - if (!buffer) { + if (renderbuffertarget != GL_RENDERBUFFER) { _mesa_error(ctx, GL_INVALID_ENUM, - "glGetFramebufferAttachmentParameteriv(target)"); + "glFramebufferRenderbuffer(renderbuffertarget is not " + "GL_RENDERBUFFER)"); return; } + if (renderbuffer) { + rb = _mesa_lookup_renderbuffer_err(ctx, renderbuffer, + "glFramebufferRenderbuffer"); + if (!rb) + return; + } + else { + /* remove renderbuffer attachment */ + rb = NULL; + } + + _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb, + "glFramebufferRenderbuffer"); +} + + +void GLAPIENTRY +_mesa_NamedFramebufferRenderbuffer(GLuint framebuffer, GLenum attachment, + GLenum renderbuffertarget, + GLuint renderbuffer) +{ + struct gl_framebuffer *fb; + struct gl_renderbuffer *rb; + GET_CURRENT_CONTEXT(ctx); + + fb = _mesa_lookup_framebuffer_err(ctx, framebuffer, + "glNamedFramebufferRenderbuffer"); + if (!fb) + return; + + if (renderbuffertarget != GL_RENDERBUFFER) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glNamedFramebufferRenderbuffer(renderbuffertarget is not " + "GL_RENDERBUFFER)"); + return; + } + + if (renderbuffer) { + rb = _mesa_lookup_renderbuffer_err(ctx, renderbuffer, + "glNamedFramebufferRenderbuffer"); + if (!rb) + return; + } + else { + /* remove renderbuffer attachment */ + rb = NULL; + } + + _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb, + "glNamedFramebufferRenderbuffer"); +} + + +void +_mesa_get_framebuffer_attachment_parameter(struct gl_context *ctx, + struct gl_framebuffer *buffer, + GLenum attachment, GLenum pname, + GLint *params, const char *caller) +{ + const struct gl_renderbuffer_attachment *att; + GLenum err; + + /* The error differs in GL and GLES. */ + err = _mesa_is_desktop_gl(ctx) ? GL_INVALID_OPERATION : GL_INVALID_ENUM; + if (_mesa_is_winsys_fbo(buffer)) { /* Page 126 (page 136 of the PDF) of the OpenGL ES 2.0.25 spec * says: @@ -2936,14 +3531,15 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, !ctx->Extensions.ARB_framebuffer_object) && !_mesa_is_gles3(ctx)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glGetFramebufferAttachmentParameteriv(bound FBO = 0)"); + "%s(window-system framebuffer)", caller); return; } if (_mesa_is_gles3(ctx) && attachment != GL_BACK && attachment != GL_DEPTH && attachment != GL_STENCIL) { _mesa_error(ctx, GL_INVALID_ENUM, - "glGetFramebufferAttachmentParameteriv(attachment)"); + "%s(invalid attachment %s)", caller, + _mesa_lookup_enum_by_nr(attachment)); return; } /* the default / window-system FBO */ @@ -2955,8 +3551,8 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, } if (att == NULL) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetFramebufferAttachmentParameteriv(attachment)"); + _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid attachment %s)", caller, + _mesa_lookup_enum_by_nr(attachment)); return; } @@ -2970,9 +3566,8 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, * attachment, since it does not have a single format." */ _mesa_error(ctx, GL_INVALID_OPERATION, - "glGetFramebufferAttachmentParameteriv(" - "GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE" - " is invalid for depth+stencil attachment)"); + "%s(GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE" + " is invalid for depth+stencil attachment)", caller); return; } /* the depth and stencil attachments must point to the same buffer */ @@ -2980,8 +3575,7 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, stencilAtt = get_attachment(ctx, buffer, GL_STENCIL_ATTACHMENT); if (depthAtt->Renderbuffer != stencilAtt->Renderbuffer) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glGetFramebufferAttachmentParameteriv(DEPTH/STENCIL" - " attachments differ)"); + "%s(DEPTH/STENCIL attachments differ)", caller); return; } } @@ -3014,8 +3608,8 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, *params = att->TextureLevel; } else if (att->Type == GL_NONE) { - _mesa_error(ctx, err, - "glGetFramebufferAttachmentParameteriv(pname)"); + _mesa_error(ctx, err, "%s(invalid pname %s)", caller, + _mesa_lookup_enum_by_nr(pname)); } else { goto invalid_pname_enum; @@ -3031,8 +3625,8 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, } } else if (att->Type == GL_NONE) { - _mesa_error(ctx, err, - "glGetFramebufferAttachmentParameteriv(pname)"); + _mesa_error(ctx, err, "%s(invalid pname %s)", caller, + _mesa_lookup_enum_by_nr(pname)); } else { goto invalid_pname_enum; @@ -3042,8 +3636,8 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, if (ctx->API == API_OPENGLES) { goto invalid_pname_enum; } else if (att->Type == GL_NONE) { - _mesa_error(ctx, err, - "glGetFramebufferAttachmentParameteriv(pname)"); + _mesa_error(ctx, err, "%s(invalid pname %s)", caller, + _mesa_lookup_enum_by_nr(pname)); } else if (att->Type == GL_TEXTURE) { if (att->Texture && (att->Texture->Target == GL_TEXTURE_3D || att->Texture->Target == GL_TEXTURE_2D_ARRAY)) { @@ -3064,8 +3658,8 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, goto invalid_pname_enum; } else if (att->Type == GL_NONE) { - _mesa_error(ctx, err, - "glGetFramebufferAttachmentParameteriv(pname)"); + _mesa_error(ctx, err, "%s(invalid pname %s)", caller, + _mesa_lookup_enum_by_nr(pname)); } else { if (ctx->Extensions.EXT_framebuffer_sRGB) { @@ -3087,8 +3681,8 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, goto invalid_pname_enum; } else if (att->Type == GL_NONE) { - _mesa_error(ctx, err, - "glGetFramebufferAttachmentParameteriv(pname)"); + _mesa_error(ctx, err, "%s(invalid pname %s)", caller, + _mesa_lookup_enum_by_nr(pname)); } else { mesa_format format = att->Renderbuffer->Format; @@ -3103,9 +3697,9 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, if (_mesa_is_gles3(ctx) && attachment == GL_DEPTH_STENCIL_ATTACHMENT) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glGetFramebufferAttachmentParameteriv(cannot query " + "%s(cannot query " "GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE of " - "GL_DEPTH_STENCIL_ATTACHMENT"); + "GL_DEPTH_STENCIL_ATTACHMENT)", caller); return; } @@ -3139,8 +3733,8 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, goto invalid_pname_enum; } else if (att->Type == GL_NONE) { - _mesa_error(ctx, err, - "glGetFramebufferAttachmentParameteriv(pname)"); + _mesa_error(ctx, err, "%s(invalid pname %s)", caller, + _mesa_lookup_enum_by_nr(pname)); } else if (att->Texture) { const struct gl_texture_image *texImage = @@ -3159,8 +3753,7 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, att->Renderbuffer->Format); } else { - _mesa_problem(ctx, "glGetFramebufferAttachmentParameterivEXT:" - " invalid FBO attachment structure"); + _mesa_problem(ctx, "%s: invalid FBO attachment structure", caller); } return; case GL_FRAMEBUFFER_ATTACHMENT_LAYERED: @@ -3169,8 +3762,8 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, } else if (att->Type == GL_TEXTURE) { *params = att->Layered; } else if (att->Type == GL_NONE) { - _mesa_error(ctx, err, - "glGetFramebufferAttachmentParameteriv(pname)"); + _mesa_error(ctx, err, "%s(invalid pname %s)", caller, + _mesa_lookup_enum_by_nr(pname)); } else { goto invalid_pname_enum; } @@ -3182,30 +3775,144 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, return; invalid_pname_enum: - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetFramebufferAttachmentParameteriv(pname)"); + _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid pname %s)", caller, + _mesa_lookup_enum_by_nr(pname)); return; } +void GLAPIENTRY +_mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, + GLenum pname, GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_framebuffer *buffer; + + buffer = get_framebuffer_target(ctx, target); + if (!buffer) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetFramebufferAttachmentParameteriv(invalid target %s)", + _mesa_lookup_enum_by_nr(target)); + return; + } + + _mesa_get_framebuffer_attachment_parameter(ctx, buffer, attachment, pname, + params, + "glGetFramebufferAttachmentParameteriv"); +} + + +void GLAPIENTRY +_mesa_GetNamedFramebufferAttachmentParameteriv(GLuint framebuffer, + GLenum attachment, + GLenum pname, GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_framebuffer *buffer; + + if (framebuffer) { + buffer = _mesa_lookup_framebuffer_err(ctx, framebuffer, + "glGetNamedFramebufferAttachmentParameteriv"); + if (!buffer) + return; + } + else { + /* + * Section 9.2 Binding and Managing Framebuffer Objects of the OpenGL + * 4.5 core spec (30.10.2014, PDF page 314): + * "If framebuffer is zero, then the default draw framebuffer is + * queried." + */ + buffer = ctx->WinSysDrawBuffer; + } + + _mesa_get_framebuffer_attachment_parameter(ctx, buffer, attachment, pname, + params, + "glGetNamedFramebufferAttachmentParameteriv"); +} + + +void GLAPIENTRY +_mesa_NamedFramebufferParameteri(GLuint framebuffer, GLenum pname, + GLint param) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_framebuffer *fb = NULL; + + if (!ctx->Extensions.ARB_framebuffer_no_attachments) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glNamedFramebufferParameteri(" + "ARB_framebuffer_no_attachments not implemented)"); + return; + } + + fb = _mesa_lookup_framebuffer_err(ctx, framebuffer, + "glNamedFramebufferParameteri"); + + if (fb) { + framebuffer_parameteri(ctx, fb, pname, param, + "glNamedFramebufferParameteriv"); + } +} + + +void GLAPIENTRY +_mesa_GetNamedFramebufferParameteriv(GLuint framebuffer, GLenum pname, + GLint *param) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_framebuffer *fb; + + if (!ctx->Extensions.ARB_framebuffer_no_attachments) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glNamedFramebufferParameteriv(" + "ARB_framebuffer_no_attachments not implemented)"); + return; + } + + if (framebuffer) { + fb = _mesa_lookup_framebuffer_err(ctx, framebuffer, + "glGetNamedFramebufferParameteriv"); + } else { + fb = ctx->WinSysDrawBuffer; + } + + if (fb) { + get_framebuffer_parameteriv(ctx, fb, pname, param, + "glGetNamedFramebufferParameteriv"); + } +} + + static void -invalidate_framebuffer_storage(GLenum target, GLsizei numAttachments, +invalidate_framebuffer_storage(struct gl_context *ctx, + struct gl_framebuffer *fb, + GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height, const char *name) { int i; - struct gl_framebuffer *fb; - GET_CURRENT_CONTEXT(ctx); - fb = get_framebuffer_target(ctx, target); - if (!fb) { - _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", name); + /* Section 17.4 Whole Framebuffer Operations of the OpenGL 4.5 Core + * Spec (2.2.2015, PDF page 522) says: + * "An INVALID_VALUE error is generated if numAttachments, width, or + * height is negative." + */ + if (numAttachments < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, + "%s(numAttachments < 0)", name); return; } - if (numAttachments < 0) { + if (width < 0) { _mesa_error(ctx, GL_INVALID_VALUE, - "%s(numAttachments < 0)", name); + "%s(width < 0)", name); + return; + } + + if (height < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, + "%s(height < 0)", name); return; } @@ -3301,7 +4008,8 @@ invalidate_framebuffer_storage(GLenum target, GLsizei numAttachments, return; invalid_enum: - _mesa_error(ctx, GL_INVALID_ENUM, "%s(attachment)", name); + _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid attachment %s)", name, + _mesa_lookup_enum_by_nr(attachments[i])); return; } @@ -3311,16 +4019,67 @@ _mesa_InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height) { - invalidate_framebuffer_storage(target, numAttachments, attachments, + struct gl_framebuffer *fb; + GET_CURRENT_CONTEXT(ctx); + + fb = get_framebuffer_target(ctx, target); + if (!fb) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glInvalidateSubFramebuffer(invalid target %s)", + _mesa_lookup_enum_by_nr(target)); + return; + } + + invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments, x, y, width, height, "glInvalidateSubFramebuffer"); } void GLAPIENTRY +_mesa_InvalidateNamedFramebufferSubData(GLuint framebuffer, + GLsizei numAttachments, + const GLenum *attachments, + GLint x, GLint y, + GLsizei width, GLsizei height) +{ + struct gl_framebuffer *fb; + GET_CURRENT_CONTEXT(ctx); + + /* The OpenGL 4.5 core spec (02.02.2015) says (in Section 17.4 Whole + * Framebuffer Operations, PDF page 522): "If framebuffer is zero, the + * default draw framebuffer is affected." + */ + if (framebuffer) { + fb = _mesa_lookup_framebuffer_err(ctx, framebuffer, + "glInvalidateNamedFramebufferSubData"); + if (!fb) + return; + } + else + fb = ctx->WinSysDrawBuffer; + + invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments, + x, y, width, height, + "glInvalidateNamedFramebufferSubData"); +} + + +void GLAPIENTRY _mesa_InvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum *attachments) { + struct gl_framebuffer *fb; + GET_CURRENT_CONTEXT(ctx); + + fb = get_framebuffer_target(ctx, target); + if (!fb) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glInvalidateFramebuffer(invalid target %s)", + _mesa_lookup_enum_by_nr(target)); + return; + } + /* The GL_ARB_invalidate_subdata spec says: * * "The command @@ -3333,7 +4092,7 @@ _mesa_InvalidateFramebuffer(GLenum target, GLsizei numAttachments, * <width>, <height> equal to 0, 0, <MAX_VIEWPORT_DIMS[0]>, * <MAX_VIEWPORT_DIMS[1]> respectively." */ - invalidate_framebuffer_storage(target, numAttachments, attachments, + invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments, 0, 0, MAX_VIEWPORT_WIDTH, MAX_VIEWPORT_HEIGHT, "glInvalidateFramebuffer"); @@ -3341,6 +4100,46 @@ _mesa_InvalidateFramebuffer(GLenum target, GLsizei numAttachments, void GLAPIENTRY +_mesa_InvalidateNamedFramebufferData(GLuint framebuffer, + GLsizei numAttachments, + const GLenum *attachments) +{ + struct gl_framebuffer *fb; + GET_CURRENT_CONTEXT(ctx); + + /* The OpenGL 4.5 core spec (02.02.2015) says (in Section 17.4 Whole + * Framebuffer Operations, PDF page 522): "If framebuffer is zero, the + * default draw framebuffer is affected." + */ + if (framebuffer) { + fb = _mesa_lookup_framebuffer_err(ctx, framebuffer, + "glInvalidateNamedFramebufferData"); + if (!fb) + return; + } + else + fb = ctx->WinSysDrawBuffer; + + /* The GL_ARB_invalidate_subdata spec says: + * + * "The command + * + * void InvalidateFramebuffer(enum target, + * sizei numAttachments, + * const enum *attachments); + * + * is equivalent to the command InvalidateSubFramebuffer with <x>, <y>, + * <width>, <height> equal to 0, 0, <MAX_VIEWPORT_DIMS[0]>, + * <MAX_VIEWPORT_DIMS[1]> respectively." + */ + invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments, + 0, 0, + MAX_VIEWPORT_WIDTH, MAX_VIEWPORT_HEIGHT, + "glInvalidateNamedFramebufferData"); +} + + +void GLAPIENTRY _mesa_DiscardFramebufferEXT(GLenum target, GLsizei numAttachments, const GLenum *attachments) { diff --git a/src/mesa/main/fbobject.h b/src/mesa/main/fbobject.h index 61aa1f50308..8dad0ff34e7 100644 --- a/src/mesa/main/fbobject.h +++ b/src/mesa/main/fbobject.h @@ -64,9 +64,17 @@ _mesa_get_incomplete_framebuffer(void); extern struct gl_renderbuffer * _mesa_lookup_renderbuffer(struct gl_context *ctx, GLuint id); +extern struct gl_renderbuffer * +_mesa_lookup_renderbuffer_err(struct gl_context *ctx, GLuint id, + const char *func); + extern struct gl_framebuffer * _mesa_lookup_framebuffer(struct gl_context *ctx, GLuint id); +extern struct gl_framebuffer * +_mesa_lookup_framebuffer_err(struct gl_context *ctx, GLuint id, + const char *func); + void _mesa_update_texture_renderbuffer(struct gl_context *ctx, @@ -74,9 +82,17 @@ _mesa_update_texture_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer_attachment *att); extern void +_mesa_FramebufferRenderbuffer_sw(struct gl_context *ctx, + struct gl_framebuffer *fb, + GLenum attachment, + struct gl_renderbuffer *rb); + +extern void _mesa_framebuffer_renderbuffer(struct gl_context *ctx, struct gl_framebuffer *fb, - GLenum attachment, struct gl_renderbuffer *rb); + GLenum attachment, + struct gl_renderbuffer *rb, + const char *func); extern void _mesa_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb); @@ -99,6 +115,24 @@ _mesa_detach_renderbuffer(struct gl_context *ctx, struct gl_framebuffer *fb, const void *att); +extern void +_mesa_framebuffer_texture(struct gl_context *ctx, struct gl_framebuffer *fb, + GLenum attachment, + struct gl_texture_object *texObj, GLenum textarget, + GLint level, GLuint layer, GLboolean layered, + const char *caller); + +extern GLenum +_mesa_check_framebuffer_status(struct gl_context *ctx, + struct gl_framebuffer *fb); + +extern void +_mesa_get_framebuffer_attachment_parameter(struct gl_context *ctx, + struct gl_framebuffer *buffer, + GLenum attachment, GLenum pname, + GLint *params, const char *caller); + + extern GLboolean GLAPIENTRY _mesa_IsRenderbuffer(GLuint renderbuffer); @@ -165,9 +199,15 @@ _mesa_DeleteFramebuffers(GLsizei n, const GLuint *framebuffers); extern void GLAPIENTRY _mesa_GenFramebuffers(GLsizei n, GLuint *framebuffers); +extern void GLAPIENTRY +_mesa_CreateFramebuffers(GLsizei n, GLuint *framebuffers); + extern GLenum GLAPIENTRY _mesa_CheckFramebufferStatus(GLenum target); +extern GLenum GLAPIENTRY +_mesa_CheckNamedFramebufferStatus(GLuint framebuffer, GLenum target); + extern void GLAPIENTRY _mesa_FramebufferTexture1D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); @@ -179,24 +219,49 @@ _mesa_FramebufferTexture2D(GLenum target, GLenum attachment, extern void GLAPIENTRY _mesa_FramebufferTexture3D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, - GLint level, GLint zoffset); + GLint level, GLint layer); extern void GLAPIENTRY _mesa_FramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); extern void GLAPIENTRY +_mesa_NamedFramebufferTextureLayer(GLuint framebuffer, GLenum attachment, + GLuint texture, GLint level, GLint layer); + +extern void GLAPIENTRY _mesa_FramebufferTexture(GLenum target, GLenum attachment, GLuint texture, GLint level); extern void GLAPIENTRY +_mesa_NamedFramebufferTexture(GLuint framebuffer, GLenum attachment, + GLuint texture, GLint level); + +extern void GLAPIENTRY _mesa_FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); extern void GLAPIENTRY +_mesa_NamedFramebufferRenderbuffer(GLuint framebuffer, GLenum attachment, + GLenum renderbuffertarget, + GLuint renderbuffer); + +extern void GLAPIENTRY _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint *params); +extern void GLAPIENTRY +_mesa_GetNamedFramebufferAttachmentParameteriv(GLuint framebuffer, + GLenum attachment, + GLenum pname, GLint *params); + +extern void GLAPIENTRY +_mesa_NamedFramebufferParameteri(GLuint framebuffer, GLenum pname, + GLint param); + +extern void GLAPIENTRY +_mesa_GetNamedFramebufferParameteriv(GLuint framebuffer, GLenum pname, + GLint *param); extern void GLAPIENTRY _mesa_InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, @@ -204,11 +269,29 @@ _mesa_InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, GLsizei width, GLsizei height); extern void GLAPIENTRY +_mesa_InvalidateNamedFramebufferSubData(GLuint framebuffer, + GLsizei numAttachments, + const GLenum *attachments, + GLint x, GLint y, + GLsizei width, GLsizei height); + +extern void GLAPIENTRY _mesa_InvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum *attachments); extern void GLAPIENTRY +_mesa_InvalidateNamedFramebufferData(GLuint framebuffer, + GLsizei numAttachments, + const GLenum *attachments); + +extern void GLAPIENTRY _mesa_DiscardFramebufferEXT(GLenum target, GLsizei numAttachments, const GLenum *attachments); +extern void GLAPIENTRY +_mesa_FramebufferParameteri(GLenum target, GLenum pname, GLint param); + +extern void GLAPIENTRY +_mesa_GetFramebufferParameteriv(GLenum target, GLenum pname, GLint *params); + #endif /* FBOBJECT_H */ diff --git a/src/mesa/main/formats.c b/src/mesa/main/formats.c index 8af44e90520..baeb1bfe5de 100644 --- a/src/mesa/main/formats.c +++ b/src/mesa/main/formats.c @@ -397,6 +397,11 @@ format_array_format_table_init(void) format_array_format_table = _mesa_hash_table_create(NULL, NULL, array_formats_equal); + if (!format_array_format_table) { + _mesa_error_no_memory(__func__); + return; + } + for (f = 1; f < MESA_FORMAT_COUNT; ++f) { info = _mesa_get_format_info(f); if (!info->ArrayFormat) @@ -432,6 +437,12 @@ _mesa_format_from_array_format(uint32_t array_format) call_once(&format_array_format_table_exists, format_array_format_table_init); + if (!format_array_format_table) { + static const once_flag once_flag_init = ONCE_FLAG_INIT; + format_array_format_table_exists = once_flag_init; + return MESA_FORMAT_NONE; + } + entry = _mesa_hash_table_search_pre_hashed(format_array_format_table, array_format, (void *)(intptr_t)array_format); diff --git a/src/mesa/main/framebuffer.c b/src/mesa/main/framebuffer.c index 4f7736a64d0..77c04b8dab8 100644 --- a/src/mesa/main/framebuffer.c +++ b/src/mesa/main/framebuffer.c @@ -157,6 +157,7 @@ _mesa_initialize_window_framebuffer(struct gl_framebuffer *fb, fb->_Status = GL_FRAMEBUFFER_COMPLETE_EXT; fb->_AllColorBuffersFixedPoint = !visual->floatMode; fb->_HasSNormOrFloatColorBuffer = visual->floatMode; + fb->_HasAttachments = true; compute_depth_max(fb); } @@ -312,7 +313,7 @@ _mesa_resize_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb, if (ctx) { /* update scissor / window bounds */ - _mesa_update_draw_buffer_bounds(ctx); + _mesa_update_draw_buffer_bounds(ctx, ctx->DrawBuffer); /* Signal new buffer state so that swrast will update its clipping * info (the CLIP_BIT flag). */ @@ -356,30 +357,20 @@ update_framebuffer_size(struct gl_context *ctx, struct gl_framebuffer *fb) } + /** - * Calculate the inclusive bounding box for the scissor of a specific viewport + * Given a bounding box, intersect the bounding box with the scissor of + * a specified vieport. * * \param ctx GL context. - * \param buffer Framebuffer to be checked against * \param idx Index of the desired viewport * \param bbox Bounding box for the scissored viewport. Stored as xmin, * xmax, ymin, ymax. - * - * \warning This function assumes that the framebuffer dimensions are up to - * date (e.g., update_framebuffer_size has been recently called on \c buffer). - * - * \sa _mesa_clip_to_region */ void -_mesa_scissor_bounding_box(const struct gl_context *ctx, - const struct gl_framebuffer *buffer, - unsigned idx, int *bbox) +_mesa_intersect_scissor_bounding_box(const struct gl_context *ctx, + unsigned idx, int *bbox) { - bbox[0] = 0; - bbox[2] = 0; - bbox[1] = buffer->Width; - bbox[3] = buffer->Height; - if (ctx->Scissor.EnableFlags & (1u << idx)) { if (ctx->Scissor.ScissorArray[idx].X > bbox[0]) { bbox[0] = ctx->Scissor.ScissorArray[idx].X; @@ -401,6 +392,33 @@ _mesa_scissor_bounding_box(const struct gl_context *ctx, bbox[2] = bbox[3]; } } +} + +/** + * Calculate the inclusive bounding box for the scissor of a specific viewport + * + * \param ctx GL context. + * \param buffer Framebuffer to be checked against + * \param idx Index of the desired viewport + * \param bbox Bounding box for the scissored viewport. Stored as xmin, + * xmax, ymin, ymax. + * + * \warning This function assumes that the framebuffer dimensions are up to + * date (e.g., update_framebuffer_size has been recently called on \c buffer). + * + * \sa _mesa_clip_to_region + */ +void +_mesa_scissor_bounding_box(const struct gl_context *ctx, + const struct gl_framebuffer *buffer, + unsigned idx, int *bbox) +{ + bbox[0] = 0; + bbox[2] = 0; + bbox[1] = buffer->Width; + bbox[3] = buffer->Height; + + _mesa_intersect_scissor_bounding_box(ctx, idx, bbox); assert(bbox[0] <= bbox[1]); assert(bbox[2] <= bbox[3]); @@ -413,9 +431,9 @@ _mesa_scissor_bounding_box(const struct gl_context *ctx, * \param ctx the GL context. */ void -_mesa_update_draw_buffer_bounds(struct gl_context *ctx) +_mesa_update_draw_buffer_bounds(struct gl_context *ctx, + struct gl_framebuffer *buffer) { - struct gl_framebuffer *buffer = ctx->DrawBuffer; int bbox[4]; if (!buffer) @@ -652,7 +670,7 @@ update_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb) * context state (GL_READ_BUFFER too). */ if (fb->ColorDrawBuffer[0] != ctx->Color.DrawBuffer[0]) { - _mesa_drawbuffers(ctx, ctx->Const.MaxDrawBuffers, + _mesa_drawbuffers(ctx, fb, ctx->Const.MaxDrawBuffers, ctx->Color.DrawBuffer, NULL); } } @@ -678,24 +696,21 @@ update_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb) /** - * Update state related to the current draw/read framebuffers. + * Update state related to the draw/read framebuffers. */ void -_mesa_update_framebuffer(struct gl_context *ctx) +_mesa_update_framebuffer(struct gl_context *ctx, + struct gl_framebuffer *readFb, + struct gl_framebuffer *drawFb) { - struct gl_framebuffer *drawFb; - struct gl_framebuffer *readFb; - assert(ctx); - drawFb = ctx->DrawBuffer; - readFb = ctx->ReadBuffer; update_framebuffer(ctx, drawFb); if (readFb != drawFb) update_framebuffer(ctx, readFb); - _mesa_update_clamp_vertex_color(ctx); - _mesa_update_clamp_fragment_color(ctx); + _mesa_update_clamp_vertex_color(ctx, drawFb); + _mesa_update_clamp_fragment_color(ctx, drawFb); } diff --git a/src/mesa/main/framebuffer.h b/src/mesa/main/framebuffer.h index a4274216ec2..08e43222045 100644 --- a/src/mesa/main/framebuffer.h +++ b/src/mesa/main/framebuffer.h @@ -75,16 +75,50 @@ extern void _mesa_scissor_bounding_box(const struct gl_context *ctx, const struct gl_framebuffer *buffer, unsigned idx, int *bbox); +extern void +_mesa_intersect_scissor_bounding_box(const struct gl_context *ctx, + unsigned idx, int *bbox); + +static inline GLuint +_mesa_geometric_width(const struct gl_framebuffer *buffer) +{ + return buffer->_HasAttachments ? + buffer->Width : buffer->DefaultGeometry.Width; +} + +static inline GLuint +_mesa_geometric_height(const struct gl_framebuffer *buffer) +{ + return buffer->_HasAttachments ? + buffer->Height : buffer->DefaultGeometry.Height; +} + +static inline GLuint +_mesa_geometric_samples(const struct gl_framebuffer *buffer) +{ + return buffer->_HasAttachments ? + buffer->Visual.samples : buffer->DefaultGeometry.NumSamples; +} + +static inline GLuint +_mesa_geometric_layers(const struct gl_framebuffer *buffer) +{ + return buffer->_HasAttachments ? + buffer->MaxNumLayers : buffer->DefaultGeometry.Layers; +} extern void -_mesa_update_draw_buffer_bounds(struct gl_context *ctx); +_mesa_update_draw_buffer_bounds(struct gl_context *ctx, + struct gl_framebuffer *drawFb); extern void _mesa_update_framebuffer_visual(struct gl_context *ctx, struct gl_framebuffer *fb); extern void -_mesa_update_framebuffer(struct gl_context *ctx); +_mesa_update_framebuffer(struct gl_context *ctx, + struct gl_framebuffer *readFb, + struct gl_framebuffer *drawFb); extern GLboolean _mesa_source_buffer_exists(struct gl_context *ctx, GLenum format); diff --git a/src/mesa/main/get.c b/src/mesa/main/get.c index a881bc589ba..3d6d63916b3 100644 --- a/src/mesa/main/get.c +++ b/src/mesa/main/get.c @@ -138,6 +138,7 @@ enum value_extra { EXTRA_API_GL_CORE, EXTRA_API_ES2, EXTRA_API_ES3, + EXTRA_API_ES31, EXTRA_NEW_BUFFERS, EXTRA_NEW_FRAG_CLAMP, EXTRA_VALID_DRAW_BUFFER, @@ -348,6 +349,12 @@ static const int extra_ARB_shader_image_load_store_and_geometry_shader[] = { EXTRA_END }; +static const int extra_ARB_draw_indirect_es31[] = { + EXT(ARB_draw_indirect), + EXTRA_API_ES31, + EXTRA_END +}; + EXTRA_EXT(ARB_texture_cube_map); EXTRA_EXT(EXT_texture_array); EXTRA_EXT(NV_fog_distance); @@ -393,6 +400,7 @@ EXTRA_EXT(INTEL_performance_query); EXTRA_EXT(ARB_explicit_uniform_location); EXTRA_EXT(ARB_clip_control); EXTRA_EXT(EXT_polygon_offset_clamp); +EXTRA_EXT(ARB_framebuffer_no_attachments); static const int extra_ARB_color_buffer_float_or_glcore[] = { @@ -909,13 +917,13 @@ find_custom_value(struct gl_context *ctx, const struct value_desc *d, union valu break; case GL_FOG_COLOR: - if (_mesa_get_clamp_fragment_color(ctx)) + if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer)) COPY_4FV(v->value_float_4, ctx->Fog.Color); else COPY_4FV(v->value_float_4, ctx->Fog.ColorUnclamped); break; case GL_COLOR_CLEAR_VALUE: - if (_mesa_get_clamp_fragment_color(ctx)) { + if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer)) { v->value_float_4[0] = CLAMP(ctx->Color.ClearColor.f[0], 0.0F, 1.0F); v->value_float_4[1] = CLAMP(ctx->Color.ClearColor.f[1], 0.0F, 1.0F); v->value_float_4[2] = CLAMP(ctx->Color.ClearColor.f[2], 0.0F, 1.0F); @@ -924,13 +932,13 @@ find_custom_value(struct gl_context *ctx, const struct value_desc *d, union valu COPY_4FV(v->value_float_4, ctx->Color.ClearColor.f); break; case GL_BLEND_COLOR_EXT: - if (_mesa_get_clamp_fragment_color(ctx)) + if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer)) COPY_4FV(v->value_float_4, ctx->Color.BlendColor); else COPY_4FV(v->value_float_4, ctx->Color.BlendColorUnclamped); break; case GL_ALPHA_TEST_REF: - if (_mesa_get_clamp_fragment_color(ctx)) + if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer)) v->value_float = ctx->Color.AlphaRef; else v->value_float = ctx->Color.AlphaRefUnclamped; @@ -1078,6 +1086,11 @@ check_extra(struct gl_context *ctx, const char *func, const struct value_desc *d if (_mesa_is_gles3(ctx)) api_found = GL_TRUE; break; + case EXTRA_API_ES31: + api_check = GL_TRUE; + if (_mesa_is_gles31(ctx)) + api_found = GL_TRUE; + break; case EXTRA_API_GL: api_check = GL_TRUE; if (_mesa_is_desktop_gl(ctx)) @@ -1911,6 +1924,7 @@ find_value_indexed(const char *func, GLenum pname, GLuint index, union value *v) if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) goto invalid_value; v->value_int = ctx->Array.VAO->VertexBinding[VERT_ATTRIB_GENERIC(index)].Stride; + return TYPE_INT; /* ARB_shader_image_load_store */ case GL_IMAGE_BINDING_NAME: { diff --git a/src/mesa/main/get_hash_params.py b/src/mesa/main/get_hash_params.py index 41cb2c17b60..74ff3ba6619 100644 --- a/src/mesa/main/get_hash_params.py +++ b/src/mesa/main/get_hash_params.py @@ -409,6 +409,12 @@ descriptor=[ [ "SAMPLER_BINDING", "LOC_CUSTOM, TYPE_INT, GL_SAMPLER_BINDING, NO_EXTRA" ], ]}, +# Enums in OpenGL Core profile and ES 3.1 +{ "apis": ["GL_CORE", "GLES3"], "params": [ +# GL_ARB_draw_indirect / GLES 3.1 + [ "DRAW_INDIRECT_BUFFER_BINDING", "LOC_CUSTOM, TYPE_INT, 0, extra_ARB_draw_indirect_es31" ], +]}, + # Remaining enums are only in OpenGL { "apis": ["GL", "GL_CORE"], "params": [ [ "ACCUM_RED_BITS", "BUFFER_INT(Visual.accumRedBits), NO_EXTRA" ], @@ -793,19 +799,20 @@ descriptor=[ [ "MAX_COMPUTE_UNIFORM_COMPONENTS", "CONST(MAX_COMPUTE_UNIFORM_COMPONENTS), extra_ARB_compute_shader" ], [ "MAX_COMPUTE_IMAGE_UNIFORMS", "CONST(MAX_COMPUTE_IMAGE_UNIFORMS), extra_ARB_compute_shader" ], -# GL_ARB_gpu_shader5 - [ "MAX_GEOMETRY_SHADER_INVOCATIONS", "CONST(MAX_GEOMETRY_SHADER_INVOCATIONS), extra_ARB_gpu_shader5" ], - [ "MIN_FRAGMENT_INTERPOLATION_OFFSET", "CONTEXT_FLOAT(Const.MinFragmentInterpolationOffset), extra_ARB_gpu_shader5" ], - [ "MAX_FRAGMENT_INTERPOLATION_OFFSET", "CONTEXT_FLOAT(Const.MaxFragmentInterpolationOffset), extra_ARB_gpu_shader5" ], - [ "FRAGMENT_INTERPOLATION_OFFSET_BITS", "CONST(FRAGMENT_INTERPOLATION_OFFSET_BITS), extra_ARB_gpu_shader5" ], +# GL_ARB_framebuffer_no_attachments + ["MAX_FRAMEBUFFER_WIDTH", "CONTEXT_INT(Const.MaxFramebufferWidth), extra_ARB_framebuffer_no_attachments"], + ["MAX_FRAMEBUFFER_HEIGHT", "CONTEXT_INT(Const.MaxFramebufferHeight), extra_ARB_framebuffer_no_attachments"], + ["MAX_FRAMEBUFFER_LAYERS", "CONTEXT_INT(Const.MaxFramebufferLayers), extra_ARB_framebuffer_no_attachments"], + ["MAX_FRAMEBUFFER_SAMPLES", "CONTEXT_INT(Const.MaxFramebufferSamples), extra_ARB_framebuffer_no_attachments"], + +# GL_EXT_polygon_offset_clamp + [ "POLYGON_OFFSET_CLAMP_EXT", "CONTEXT_FLOAT(Polygon.OffsetClamp), extra_EXT_polygon_offset_clamp" ], ]}, # Enums restricted to OpenGL Core profile { "apis": ["GL_CORE"], "params": [ # GL_ARB_texture_buffer_range [ "TEXTURE_BUFFER_OFFSET_ALIGNMENT", "CONTEXT_INT(Const.TextureBufferOffsetAlignment), extra_ARB_texture_buffer_range" ], -# GL_ARB_draw_indirect - [ "DRAW_INDIRECT_BUFFER_BINDING", "LOC_CUSTOM, TYPE_INT, 0, extra_ARB_draw_indirect" ], # GL_ARB_viewport_array [ "MAX_VIEWPORTS", "CONTEXT_INT(Const.MaxViewports), extra_ARB_viewport_array" ], @@ -814,8 +821,11 @@ descriptor=[ [ "LAYER_PROVOKING_VERTEX", "CONTEXT_ENUM(Light.ProvokingVertex), extra_ARB_viewport_array" ], [ "VIEWPORT_INDEX_PROVOKING_VERTEX", "CONTEXT_ENUM(Light.ProvokingVertex), extra_ARB_viewport_array" ], -# GL_EXT_polygon_offset_clamp - [ "POLYGON_OFFSET_CLAMP_EXT", "CONTEXT_FLOAT(Polygon.OffsetClamp), extra_EXT_polygon_offset_clamp" ], +# GL_ARB_gpu_shader5 + [ "MAX_GEOMETRY_SHADER_INVOCATIONS", "CONST(MAX_GEOMETRY_SHADER_INVOCATIONS), extra_ARB_gpu_shader5" ], + [ "MIN_FRAGMENT_INTERPOLATION_OFFSET", "CONTEXT_FLOAT(Const.MinFragmentInterpolationOffset), extra_ARB_gpu_shader5" ], + [ "MAX_FRAGMENT_INTERPOLATION_OFFSET", "CONTEXT_FLOAT(Const.MaxFragmentInterpolationOffset), extra_ARB_gpu_shader5" ], + [ "FRAGMENT_INTERPOLATION_OFFSET_BITS", "CONST(FRAGMENT_INTERPOLATION_OFFSET_BITS), extra_ARB_gpu_shader5" ], ]} ] diff --git a/src/mesa/main/getstring.c b/src/mesa/main/getstring.c index 1b2c7f054f6..72d99ca4e22 100644 --- a/src/mesa/main/getstring.c +++ b/src/mesa/main/getstring.c @@ -72,10 +72,18 @@ shading_language_version(struct gl_context *ctx) break; case API_OPENGLES2: - return (ctx->Version < 30) - ? (const GLubyte *) "OpenGL ES GLSL ES 1.0.16" - : (const GLubyte *) "OpenGL ES GLSL ES 3.00"; - + switch (ctx->Version) { + case 20: + return (const GLubyte *) "OpenGL ES GLSL ES 1.0.16"; + case 30: + return (const GLubyte *) "OpenGL ES GLSL ES 3.00"; + case 31: + return (const GLubyte *) "OpenGL ES GLSL ES 3.10"; + default: + _mesa_problem(ctx, + "Invalid OpenGL ES version in shading_language_version()"); + return (const GLubyte *) 0; + } case API_OPENGLES: /* fall-through */ diff --git a/src/mesa/main/glformats.c b/src/mesa/main/glformats.c index 8ced5794938..ac69fabccaa 100644 --- a/src/mesa/main/glformats.c +++ b/src/mesa/main/glformats.c @@ -1200,7 +1200,7 @@ _mesa_is_depth_or_stencil_format(GLenum format) * \return GL_TRUE if compressed, GL_FALSE if uncompressed */ GLboolean -_mesa_is_compressed_format(struct gl_context *ctx, GLenum format) +_mesa_is_compressed_format(const struct gl_context *ctx, GLenum format) { switch (format) { case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: @@ -1678,6 +1678,10 @@ _mesa_error_check_format_and_type(const struct gl_context *ctx, case GL_LUMINANCE: case GL_ALPHA: return GL_NO_ERROR; + case GL_RG: + case GL_RED: + if (_mesa_is_gles3(ctx) || ctx->Extensions.ARB_texture_rg) + return GL_NO_ERROR; default: return GL_INVALID_OPERATION; } @@ -2292,8 +2296,18 @@ _mesa_es3_error_check_format_and_type(const struct gl_context *ctx, break; case GL_HALF_FLOAT: - if (internalFormat != GL_RG16F) - return GL_INVALID_OPERATION; + case GL_HALF_FLOAT_OES: + switch (internalFormat) { + case GL_RG16F: + break; + case GL_RG: + if (ctx->Extensions.ARB_texture_rg && + ctx->Extensions.OES_texture_half_float) + break; + /* fallthrough */ + default: + return GL_INVALID_OPERATION; + } break; case GL_FLOAT: @@ -2301,6 +2315,11 @@ _mesa_es3_error_check_format_and_type(const struct gl_context *ctx, case GL_RG16F: case GL_RG32F: break; + case GL_RG: + if (ctx->Extensions.ARB_texture_rg && + ctx->Extensions.OES_texture_float) + break; + /* fallthrough */ default: return GL_INVALID_OPERATION; } @@ -2361,8 +2380,19 @@ _mesa_es3_error_check_format_and_type(const struct gl_context *ctx, break; case GL_HALF_FLOAT: - if (internalFormat != GL_R16F) + case GL_HALF_FLOAT_OES: + switch (internalFormat) { + case GL_R16F: + break; + case GL_RG: + case GL_RED: + if (ctx->Extensions.ARB_texture_rg && + ctx->Extensions.OES_texture_half_float) + break; + /* fallthrough */ + default: return GL_INVALID_OPERATION; + } break; case GL_FLOAT: @@ -2370,6 +2400,11 @@ _mesa_es3_error_check_format_and_type(const struct gl_context *ctx, case GL_R16F: case GL_R32F: break; + case GL_RED: + if (ctx->Extensions.ARB_texture_rg && + ctx->Extensions.OES_texture_float) + break; + /* fallthrough */ default: return GL_INVALID_OPERATION; } diff --git a/src/mesa/main/glformats.h b/src/mesa/main/glformats.h index e1ecd64d5f9..8881cb7d86b 100644 --- a/src/mesa/main/glformats.h +++ b/src/mesa/main/glformats.h @@ -96,7 +96,7 @@ extern GLboolean _mesa_is_depth_or_stencil_format(GLenum format); extern GLboolean -_mesa_is_compressed_format(struct gl_context *ctx, GLenum format); +_mesa_is_compressed_format(const struct gl_context *ctx, GLenum format); extern GLenum _mesa_base_format_to_integer_format(GLenum format); diff --git a/src/mesa/main/glheader.h b/src/mesa/main/glheader.h index 7f7f9a39b3b..a2d98d4ddff 100644 --- a/src/mesa/main/glheader.h +++ b/src/mesa/main/glheader.h @@ -135,12 +135,6 @@ typedef void *GLeglImageOES; #define GL_SHADER_PROGRAM_MESA 0x9999 -/** - * Internal token for geometry programs. - * Use the value for GL_GEOMETRY_PROGRAM_NV for now. - */ -#define MESA_GEOMETRY_PROGRAM 0x8c26 - /* Several fields of struct gl_config can take these as values. Since * GLX header files may not be available everywhere they need to be used, * redefine them here. diff --git a/src/mesa/main/hash.c b/src/mesa/main/hash.c index d04cccd94d2..315b5d64004 100644 --- a/src/mesa/main/hash.c +++ b/src/mesa/main/hash.c @@ -389,34 +389,6 @@ _mesa_HashDeleteAll(struct _mesa_HashTable *table, /** - * Clone all entries in a hash table, into a new table. - * - * \param table the hash table to clone - */ -struct _mesa_HashTable * -_mesa_HashClone(const struct _mesa_HashTable *table) -{ - /* cast-away const */ - struct _mesa_HashTable *table2 = (struct _mesa_HashTable *) table; - struct hash_entry *entry; - struct _mesa_HashTable *clonetable; - - assert(table); - mtx_lock(&table2->Mutex); - - clonetable = _mesa_NewHashTable(); - assert(clonetable); - hash_table_foreach(table->ht, entry) { - _mesa_HashInsert(clonetable, (GLint)(uintptr_t)entry->key, entry->data); - } - - mtx_unlock(&table2->Mutex); - - return clonetable; -} - - -/** * Walk over all entries in a hash table, calling callback function for each. * Note: we use a separate mutex in this function to avoid a recursive * locking deadlock (in case the callback calls _mesa_HashRemove()) and to diff --git a/src/mesa/main/hash.h b/src/mesa/main/hash.h index e3e8f492e8b..da3b9973d24 100644 --- a/src/mesa/main/hash.h +++ b/src/mesa/main/hash.h @@ -59,9 +59,6 @@ _mesa_HashDeleteAll(struct _mesa_HashTable *table, void (*callback)(GLuint key, void *data, void *userData), void *userData); -extern struct _mesa_HashTable * -_mesa_HashClone(const struct _mesa_HashTable *table); - extern void _mesa_HashWalk(const struct _mesa_HashTable *table, void (*callback)(GLuint key, void *data, void *userData), diff --git a/src/mesa/main/imports.h b/src/mesa/main/imports.h index c4d917ebba4..9ffe3decd0f 100644 --- a/src/mesa/main/imports.h +++ b/src/mesa/main/imports.h @@ -230,38 +230,6 @@ static inline int IFLOOR(float f) } -/** Return (as an integer) ceiling of float */ -static inline int ICEIL(float f) -{ -#if defined(USE_X86_ASM) && defined(__GNUC__) && defined(__i386__) - /* - * IEEE ceil for computers that round to nearest or even. - * 'f' must be between -4194304 and 4194303. - * This ceil operation is done by "(iround(f + .5) + iround(f - .5) + 1) >> 1", - * but uses some IEEE specific tricks for better speed. - * Contributed by Josh Vanderhoof - */ - int ai, bi; - double af, bf; - af = (3 << 22) + 0.5 + (double)f; - bf = (3 << 22) + 0.5 - (double)f; - /* GCC generates an extra fstp/fld without this. */ - __asm__ ("fstps %0" : "=m" (ai) : "t" (af) : "st"); - __asm__ ("fstps %0" : "=m" (bi) : "t" (bf) : "st"); - return (ai - bi + 1) >> 1; -#else - int ai, bi; - double af, bf; - fi_type u; - af = (3 << 22) + 0.5 + (double)f; - bf = (3 << 22) + 0.5 - (double)f; - u.f = (float) af; ai = u.i; - u.f = (float) bf; bi = u.i; - return (ai - bi + 1) >> 1; -#endif -} - - /** * Is x a power of two? */ diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index bd84113ea91..481fd5e7fdf 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -43,7 +43,6 @@ #include "glapi/glapi.h" #include "math/m_matrix.h" /* GLmatrix */ #include "glsl/shader_enums.h" -#include "util/simple_list.h" /* struct simple_node */ #include "main/formats.h" /* MESA_FORMAT_COUNT */ @@ -398,7 +397,6 @@ struct gl_config { GLboolean rgbMode; GLboolean floatMode; - GLboolean colorIndexMode; /* XXX is this used anywhere? */ GLuint doubleBufferMode; GLuint stereoMode; @@ -2099,8 +2097,6 @@ struct gl_program GLbitfield64 DoubleInputsRead; /**< Bitmask of which input regs are read and are doubles */ GLbitfield64 OutputsWritten; /**< Bitmask of which output regs are written */ GLbitfield SystemValuesRead; /**< Bitmask of SYSTEM_VALUE_x inputs used */ - GLbitfield InputFlags[MAX_PROGRAM_INPUTS]; /**< PROG_PARAM_BIT_x flags */ - GLbitfield OutputFlags[MAX_PROGRAM_OUTPUTS]; /**< PROG_PARAM_BIT_x flags */ GLbitfield TexturesUsed[MAX_COMBINED_TEXTURE_IMAGE_UNITS]; /**< TEXTURE_x_BIT bitmask */ GLbitfield SamplersUsed; /**< Bitfield of which samplers are used */ GLbitfield ShadowSamplers; /**< Texture units used for shadow sampling. */ @@ -2275,16 +2271,10 @@ struct gl_vertex_program_state */ struct gl_geometry_program_state { - GLboolean Enabled; /**< GL_ARB_GEOMETRY_SHADER4 */ - GLboolean _Enabled; /**< Enabled and valid program? */ - struct gl_geometry_program *Current; /**< user-bound geometry program */ - /** Currently enabled and valid program (including internal programs * and compiled shader programs). */ struct gl_geometry_program *_Current; - - GLfloat Parameters[MAX_PROGRAM_ENV_PARAMS][4]; /**< Env params */ }; /** @@ -2320,8 +2310,6 @@ struct gl_fragment_program_state */ struct gl_compute_program_state { - struct gl_compute_program *Current; /**< user-bound compute program */ - /** Currently enabled and valid program (including internal programs * and compiled shader programs). */ @@ -2733,7 +2721,7 @@ struct gl_shader_program } Comp; /* post-link info: */ - unsigned NumUserUniformStorage; + unsigned NumUniformStorage; unsigned NumHiddenUniforms; struct gl_uniform_storage *UniformStorage; @@ -2832,6 +2820,8 @@ struct gl_pipeline_object mtx_t Mutex; + GLchar *Label; /**< GL_KHR_debug */ + /** * Programs used for rendering * @@ -3009,7 +2999,6 @@ struct gl_shared_state struct _mesa_HashTable *Programs; /**< All vertex/fragment programs */ struct gl_vertex_program *DefaultVertexProgram; struct gl_fragment_program *DefaultFragmentProgram; - struct gl_geometry_program *DefaultGeometryProgram; /*@}*/ /* GL_ATI_fragment_shader */ @@ -3151,12 +3140,29 @@ struct gl_framebuffer */ struct gl_config Visual; - GLuint Width, Height; /**< size of frame buffer in pixels */ + /** + * Size of frame buffer in pixels. If there are no attachments, then both + * of these are 0. + */ + GLuint Width, Height; - /** \name Drawing bounds (Intersection of buffer size and scissor box) */ + /** + * In the case that the framebuffer has no attachment (i.e. + * GL_ARB_framebuffer_no_attachments) then the geometry of + * the framebuffer is specified by the default values. + */ + struct { + GLuint Width, Height, Layers, NumSamples; + GLboolean FixedSampleLocations; + } DefaultGeometry; + + /** \name Drawing bounds (Intersection of buffer size and scissor box) + * The drawing region is given by [_Xmin, _Xmax) x [_Ymin, _Ymax), + * (inclusive for _Xmin and _Ymin while exclusive for _Xmax and _Ymax) + */ /*@{*/ - GLint _Xmin, _Xmax; /**< inclusive */ - GLint _Ymin, _Ymax; /**< exclusive */ + GLint _Xmin, _Xmax; + GLint _Ymin, _Ymax; /*@}*/ /** \name Derived Z buffer stuff */ @@ -3169,6 +3175,22 @@ struct gl_framebuffer /** One of the GL_FRAMEBUFFER_(IN)COMPLETE_* tokens */ GLenum _Status; + /** Whether one of Attachment has Type != GL_NONE + * NOTE: the values for Width and Height are set to 0 in case of having + * no attachments, a backend driver supporting the extension + * GL_ARB_framebuffer_no_attachments must check for the flag _HasAttachments + * and if GL_FALSE, must then use the values in DefaultGeometry to initialize + * its viewport, scissor and so on (in particular _Xmin, _Xmax, _Ymin and + * _Ymax do NOT take into account _HasAttachments being false). To get the + * geometry of the framebuffer, the helper functions + * _mesa_geometric_width(), + * _mesa_geometric_height(), + * _mesa_geometric_samples() and + * _mesa_geometric_layers() + * are available that check _HasAttachments. + */ + bool _HasAttachments; + /** Integer color values */ GLboolean _IntegerColor; @@ -3179,7 +3201,9 @@ struct gl_framebuffer /** * The maximum number of layers in the framebuffer, or 0 if the framebuffer * is not layered. For cube maps and cube map arrays, each cube face - * counts as a layer. + * counts as a layer. As the case for Width, Height a backend driver + * supporting GL_ARB_framebuffer_no_attachments must use DefaultGeometry + * in the case that _HasAttachments is false */ GLuint MaxNumLayers; @@ -3358,6 +3382,14 @@ struct gl_constants GLuint MaxRenderbufferSize; /**< GL_EXT_framebuffer_object */ GLuint MaxSamples; /**< GL_ARB_framebuffer_object */ + /** + * GL_ARB_framebuffer_no_attachments + */ + GLuint MaxFramebufferWidth; + GLuint MaxFramebufferHeight; + GLuint MaxFramebufferLayers; + GLuint MaxFramebufferSamples; + /** Number of varying vectors between any two shader stages. */ GLuint MaxVarying; @@ -3635,6 +3667,7 @@ struct gl_extensions GLboolean ARB_fragment_program; GLboolean ARB_fragment_program_shadow; GLboolean ARB_fragment_shader; + GLboolean ARB_framebuffer_no_attachments; GLboolean ARB_framebuffer_object; GLboolean ARB_explicit_attrib_location; GLboolean ARB_explicit_uniform_location; @@ -4422,7 +4455,12 @@ enum _debug DEBUG_INCOMPLETE_FBO = (1 << 3) }; - +static inline bool +_mesa_active_fragment_shader_has_atomic_ops(const struct gl_context *ctx) +{ + return ctx->Shader._CurrentFragmentProgram != NULL && + ctx->Shader._CurrentFragmentProgram->NumAtomicBuffers > 0; +} #ifdef __cplusplus } diff --git a/src/mesa/main/objectlabel.c b/src/mesa/main/objectlabel.c index aecb5b1fa51..5626054687b 100644 --- a/src/mesa/main/objectlabel.c +++ b/src/mesa/main/objectlabel.c @@ -30,6 +30,7 @@ #include "enums.h" #include "fbobject.h" #include "objectlabel.h" +#include "pipelineobj.h" #include "queryobj.h" #include "samplerobj.h" #include "shaderobj.h" @@ -214,8 +215,13 @@ get_label_pointer(struct gl_context *ctx, GLenum identifier, GLuint name, } break; case GL_PROGRAM_PIPELINE: - /* requires GL 4.2 */ - goto invalid_enum; + { + struct gl_pipeline_object *pipe = + _mesa_lookup_pipeline_object(ctx, name); + if (pipe) + labelPtr = &pipe->Label; + } + break; default: goto invalid_enum; } diff --git a/src/mesa/main/pipelineobj.c b/src/mesa/main/pipelineobj.c index 0fefa7d568b..279ae2078fe 100644 --- a/src/mesa/main/pipelineobj.c +++ b/src/mesa/main/pipelineobj.c @@ -65,6 +65,7 @@ _mesa_delete_pipeline_object(struct gl_context *ctx, _mesa_reference_shader_program(ctx, &obj->ActiveProgram, NULL); mtx_destroy(&obj->Mutex); + free(obj->Label); ralloc_free(obj); } @@ -136,8 +137,8 @@ _mesa_free_pipeline_data(struct gl_context *ctx) * a non-existent ID. The spec defines ID 0 as being technically * non-existent. */ -static inline struct gl_pipeline_object * -lookup_pipeline_object(struct gl_context *ctx, GLuint id) +struct gl_pipeline_object * +_mesa_lookup_pipeline_object(struct gl_context *ctx, GLuint id) { if (id == 0) return NULL; @@ -225,7 +226,7 @@ _mesa_UseProgramStages(GLuint pipeline, GLbitfield stages, GLuint program) { GET_CURRENT_CONTEXT(ctx); - struct gl_pipeline_object *pipe = lookup_pipeline_object(ctx, pipeline); + struct gl_pipeline_object *pipe = _mesa_lookup_pipeline_object(ctx, pipeline); struct gl_shader_program *shProg = NULL; GLbitfield any_valid_stages; @@ -337,7 +338,7 @@ _mesa_ActiveShaderProgram(GLuint pipeline, GLuint program) { GET_CURRENT_CONTEXT(ctx); struct gl_shader_program *shProg = NULL; - struct gl_pipeline_object *pipe = lookup_pipeline_object(ctx, pipeline); + struct gl_pipeline_object *pipe = _mesa_lookup_pipeline_object(ctx, pipeline); if (program != 0) { shProg = _mesa_lookup_shader_program_err(ctx, program, @@ -399,7 +400,7 @@ _mesa_BindProgramPipeline(GLuint pipeline) */ if (pipeline) { /* non-default pipeline object */ - newObj = lookup_pipeline_object(ctx, pipeline); + newObj = _mesa_lookup_pipeline_object(ctx, pipeline); if (!newObj) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBindProgramPipeline(non-gen name)"); @@ -468,7 +469,7 @@ _mesa_DeleteProgramPipelines(GLsizei n, const GLuint *pipelines) for (i = 0; i < n; i++) { struct gl_pipeline_object *obj = - lookup_pipeline_object(ctx, pipelines[i]); + _mesa_lookup_pipeline_object(ctx, pipelines[i]); if (obj) { assert(obj->Name == pipelines[i]); @@ -568,7 +569,7 @@ _mesa_IsProgramPipeline(GLuint pipeline) { GET_CURRENT_CONTEXT(ctx); - struct gl_pipeline_object *obj = lookup_pipeline_object(ctx, pipeline); + struct gl_pipeline_object *obj = _mesa_lookup_pipeline_object(ctx, pipeline); if (obj == NULL) return GL_FALSE; @@ -582,7 +583,7 @@ void GLAPIENTRY _mesa_GetProgramPipelineiv(GLuint pipeline, GLenum pname, GLint *params) { GET_CURRENT_CONTEXT(ctx); - struct gl_pipeline_object *pipe = lookup_pipeline_object(ctx, pipeline); + struct gl_pipeline_object *pipe = _mesa_lookup_pipeline_object(ctx, pipeline); /* Are geometry shaders available in this context? */ @@ -673,6 +674,38 @@ program_stages_all_active(struct gl_pipeline_object *pipe, return status; } +static bool +program_stages_interleaved_illegally(const struct gl_pipeline_object *pipe) +{ + struct gl_shader_program *prev = NULL; + unsigned i, j; + + /* Look for programs bound to stages: A -> B -> A, with any intervening + * sequence of unrelated programs or empty stages. + */ + for (i = 0; i < MESA_SHADER_STAGES; i++) { + struct gl_shader_program *cur = pipe->CurrentProgram[i]; + + /* Empty stages anywhere in the pipe are OK */ + if (!cur || cur == prev) + continue; + + if (prev) { + /* We've seen an A -> B transition; look at the rest of the pipe + * to see if we ever see A again. + */ + for (j = i + 1; j < MESA_SHADER_STAGES; j++) { + if (pipe->CurrentProgram[j] == prev) + return true; + } + } + + prev = cur; + } + + return false; +} + extern GLboolean _mesa_validate_program_pipeline(struct gl_context* ctx, struct gl_pipeline_object *pipe, @@ -721,24 +754,13 @@ _mesa_validate_program_pipeline(struct gl_context* ctx, * - One program object is active for at least two shader stages * and a second program is active for a shader stage between two * stages for which the first program was active." - * - * Without Tesselation, the only case where this can occur is the geometry - * shader between the fragment shader and vertex shader. */ - if (pipe->CurrentProgram[MESA_SHADER_GEOMETRY] - && pipe->CurrentProgram[MESA_SHADER_FRAGMENT] - && pipe->CurrentProgram[MESA_SHADER_VERTEX]) { - if (pipe->CurrentProgram[MESA_SHADER_VERTEX]->Name == pipe->CurrentProgram[MESA_SHADER_FRAGMENT]->Name && - pipe->CurrentProgram[MESA_SHADER_GEOMETRY]->Name != pipe->CurrentProgram[MESA_SHADER_VERTEX]->Name) { - pipe->InfoLog = - ralloc_asprintf(pipe, - "Program %d is active for geometry stage between " - "two stages for which another program %d is " - "active", - pipe->CurrentProgram[MESA_SHADER_GEOMETRY]->Name, - pipe->CurrentProgram[MESA_SHADER_VERTEX]->Name); - goto err; - } + if (program_stages_interleaved_illegally(pipe)) { + pipe->InfoLog = + ralloc_strdup(pipe, + "Program is active for multiple shader stages with an " + "intervening stage provided by another program"); + goto err; } /* Section 2.11.11 (Shader Execution), subheading "Validation," of the @@ -820,7 +842,7 @@ _mesa_ValidateProgramPipeline(GLuint pipeline) { GET_CURRENT_CONTEXT(ctx); - struct gl_pipeline_object *pipe = lookup_pipeline_object(ctx, pipeline); + struct gl_pipeline_object *pipe = _mesa_lookup_pipeline_object(ctx, pipeline); if (!pipe) { _mesa_error(ctx, GL_INVALID_OPERATION, @@ -838,7 +860,7 @@ _mesa_GetProgramPipelineInfoLog(GLuint pipeline, GLsizei bufSize, { GET_CURRENT_CONTEXT(ctx); - struct gl_pipeline_object *pipe = lookup_pipeline_object(ctx, pipeline); + struct gl_pipeline_object *pipe = _mesa_lookup_pipeline_object(ctx, pipeline); if (!pipe) { _mesa_error(ctx, GL_INVALID_VALUE, diff --git a/src/mesa/main/pipelineobj.h b/src/mesa/main/pipelineobj.h index b57bcb99e5c..6dee775ab5e 100644 --- a/src/mesa/main/pipelineobj.h +++ b/src/mesa/main/pipelineobj.h @@ -45,6 +45,9 @@ _mesa_init_pipeline(struct gl_context *ctx); extern void _mesa_free_pipeline_data(struct gl_context *ctx); +extern struct gl_pipeline_object * +_mesa_lookup_pipeline_object(struct gl_context *ctx, GLuint id); + extern void _mesa_reference_pipeline_object_(struct gl_context *ctx, struct gl_pipeline_object **ptr, diff --git a/src/mesa/main/program_resource.c b/src/mesa/main/program_resource.c index b15a13210c0..d857b84e60d 100644 --- a/src/mesa/main/program_resource.c +++ b/src/mesa/main/program_resource.c @@ -220,12 +220,12 @@ _mesa_GetProgramResourceIndex(GLuint program, GLenum programInterface, case GL_PROGRAM_INPUT: case GL_PROGRAM_OUTPUT: case GL_UNIFORM: - case GL_UNIFORM_BLOCK: case GL_TRANSFORM_FEEDBACK_VARYING: - /* Validate name syntax for arrays. */ + /* Validate name syntax for array variables */ if (!valid_program_resource_index_name(name)) return GL_INVALID_INDEX; - + /* fall-through */ + case GL_UNIFORM_BLOCK: res = _mesa_program_resource_find_name(shProg, programInterface, name); if (!res) return GL_INVALID_INDEX; diff --git a/src/mesa/main/readpix.c b/src/mesa/main/readpix.c index ed0104c9e46..a3357cd6419 100644 --- a/src/mesa/main/readpix.c +++ b/src/mesa/main/readpix.c @@ -46,15 +46,18 @@ /** * Return true if the conversion L=R+G+B is needed. */ -static GLboolean -need_rgb_to_luminance_conversion(mesa_format texFormat, GLenum format) +GLboolean +_mesa_need_rgb_to_luminance_conversion(mesa_format texFormat, GLenum format) { GLenum baseTexFormat = _mesa_get_format_base_format(texFormat); return (baseTexFormat == GL_RG || baseTexFormat == GL_RGB || baseTexFormat == GL_RGBA) && - (format == GL_LUMINANCE || format == GL_LUMINANCE_ALPHA); + (format == GL_LUMINANCE || + format == GL_LUMINANCE_ALPHA || + format == GL_LUMINANCE_INTEGER_EXT || + format == GL_LUMINANCE_ALPHA_INTEGER_EXT); } @@ -83,7 +86,7 @@ get_readpixels_transfer_ops(const struct gl_context *ctx, mesa_format texFormat, if (uses_blit) { /* For blit-based ReadPixels packing, the clamping is done automatically * unless the type is float. */ - if (_mesa_get_clamp_read_color(ctx) && + if (_mesa_get_clamp_read_color(ctx, ctx->ReadBuffer) && (type == GL_FLOAT || type == GL_HALF_FLOAT)) { transferOps |= IMAGE_CLAMP_BIT; } @@ -91,7 +94,7 @@ get_readpixels_transfer_ops(const struct gl_context *ctx, mesa_format texFormat, else { /* For CPU-based ReadPixels packing, the clamping must always be done * for non-float types, */ - if (_mesa_get_clamp_read_color(ctx) || + if (_mesa_get_clamp_read_color(ctx, ctx->ReadBuffer) || (type != GL_FLOAT && type != GL_HALF_FLOAT)) { transferOps |= IMAGE_CLAMP_BIT; } @@ -102,7 +105,7 @@ get_readpixels_transfer_ops(const struct gl_context *ctx, mesa_format texFormat, * have any effect anyway. */ if (_mesa_get_format_datatype(texFormat) == GL_UNSIGNED_NORMALIZED && - !need_rgb_to_luminance_conversion(texFormat, format)) { + !_mesa_need_rgb_to_luminance_conversion(texFormat, format)) { transferOps &= ~IMAGE_CLAMP_BIT; } @@ -146,7 +149,7 @@ _mesa_readpixels_needs_slow_path(const struct gl_context *ctx, GLenum format, default: /* Color formats. */ - if (need_rgb_to_luminance_conversion(rb->Format, format)) { + if (_mesa_need_rgb_to_luminance_conversion(rb->Format, format)) { return GL_TRUE; } @@ -418,7 +421,7 @@ read_rgba_pixels( struct gl_context *ctx, const struct gl_pixelstore_attrib *packing ) { GLbitfield transferOps; - bool dst_is_integer, dst_is_luminance, needs_rebase; + bool dst_is_integer, convert_rgb_to_lum, needs_rebase; int dst_stride, src_stride, rb_stride; uint32_t dst_format, src_format; GLubyte *dst, *map; @@ -439,10 +442,8 @@ read_rgba_pixels( struct gl_context *ctx, dst_is_integer = _mesa_is_enum_format_integer(format); dst_stride = _mesa_image_row_stride(packing, width, format, type); dst_format = _mesa_format_from_format_and_type(format, type); - dst_is_luminance = format == GL_LUMINANCE || - format == GL_LUMINANCE_ALPHA || - format == GL_LUMINANCE_INTEGER_EXT || - format == GL_LUMINANCE_ALPHA_INTEGER_EXT; + convert_rgb_to_lum = + _mesa_need_rgb_to_luminance_conversion(rb->Format, format); dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height, format, type, 0, 0); @@ -490,7 +491,7 @@ read_rgba_pixels( struct gl_context *ctx, */ assert(!transferOps || (transferOps && !dst_is_integer)); - needs_rgba = transferOps || dst_is_luminance; + needs_rgba = transferOps || convert_rgb_to_lum; rgba = NULL; if (needs_rgba) { uint32_t rgba_format; @@ -563,7 +564,7 @@ read_rgba_pixels( struct gl_context *ctx, * If the dst format is Luminance, we need to do the conversion by computing * L=R+G+B values. */ - if (!dst_is_luminance) { + if (!convert_rgb_to_lum) { _mesa_format_convert(dst, dst_format, dst_stride, src, src_format, src_stride, width, height, diff --git a/src/mesa/main/readpix.h b/src/mesa/main/readpix.h index 4bb35e17e4d..1636dd9ce3e 100644 --- a/src/mesa/main/readpix.h +++ b/src/mesa/main/readpix.h @@ -37,6 +37,9 @@ extern GLboolean _mesa_readpixels_needs_slow_path(const struct gl_context *ctx, GLenum format, GLenum type, GLboolean uses_blit); +extern GLboolean +_mesa_need_rgb_to_luminance_conversion(mesa_format texFormat, GLenum format); + extern void _mesa_readpixels(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei height, diff --git a/src/mesa/main/shader_query.cpp b/src/mesa/main/shader_query.cpp index 6e46553724b..a6246a39aad 100644 --- a/src/mesa/main/shader_query.cpp +++ b/src/mesa/main/shader_query.cpp @@ -28,6 +28,7 @@ * \author Ian Romanick <[email protected]> */ +#include "main/context.h" #include "main/core.h" #include "glsl_symbol_table.h" #include "ir.h" @@ -478,12 +479,20 @@ _mesa_GetFragDataLocation(GLuint program, const GLchar *name) const char* _mesa_program_resource_name(struct gl_program_resource *res) { + const ir_variable *var; switch (res->Type) { case GL_UNIFORM_BLOCK: return RESOURCE_UBO(res)->Name; case GL_TRANSFORM_FEEDBACK_VARYING: return RESOURCE_XFB(res)->Name; case GL_PROGRAM_INPUT: + var = RESOURCE_VAR(res); + /* Special case gl_VertexIDMESA -> gl_VertexID. */ + if (var->data.mode == ir_var_system_value && + var->data.location == SYSTEM_VALUE_VERTEX_ID_ZERO_BASE) { + return "gl_VertexID"; + } + /* fallthrough */ case GL_PROGRAM_OUTPUT: return RESOURCE_VAR(res)->name; case GL_UNIFORM: @@ -538,6 +547,17 @@ struct gl_program_resource * _mesa_program_resource_find_name(struct gl_shader_program *shProg, GLenum programInterface, const char *name) { + GET_CURRENT_CONTEXT(ctx); + const char *full_name = name; + + /* When context has 'VertexID_is_zero_based' set, gl_VertexID has been + * lowered to gl_VertexIDMESA. + */ + if (name && ctx->Const.VertexID_is_zero_based) { + if (strcmp(name, "gl_VertexID") == 0) + full_name = "gl_VertexIDMESA"; + } + struct gl_program_resource *res = shProg->ProgramResourceList; for (unsigned i = 0; i < shProg->NumProgramResourceList; i++, res++) { if (res->Type != programInterface) @@ -562,7 +582,7 @@ _mesa_program_resource_find_name(struct gl_shader_program *shProg, break; case GL_PROGRAM_INPUT: case GL_PROGRAM_OUTPUT: - if (array_index_of_resource(res, name) >= 0) + if (array_index_of_resource(res, full_name) >= 0) return res; break; default: @@ -727,6 +747,10 @@ program_resource_location(struct gl_shader_program *shProg, return -1; } + /* Built-in locations should report GL_INVALID_INDEX. */ + if (is_gl_identifier(name)) + return GL_INVALID_INDEX; + /* VERT_ATTRIB_GENERIC0 and FRAG_RESULT_DATA0 are decremented as these * offsets are used internally to differentiate between built-in attributes * and user-defined attributes. @@ -986,8 +1010,9 @@ _mesa_program_resource_prop(struct gl_shader_program *shProg, case GL_ACTIVE_VARIABLES: return get_buffer_property(shProg, res, prop, val, caller); case GL_REFERENCED_BY_COMPUTE_SHADER: - if (!ctx->Extensions.ARB_compute_shader) + if (!_mesa_has_compute_shaders(ctx)) goto invalid_enum; + /* fallthrough */ case GL_REFERENCED_BY_VERTEX_SHADER: case GL_REFERENCED_BY_GEOMETRY_SHADER: case GL_REFERENCED_BY_FRAGMENT_SHADER: diff --git a/src/mesa/main/shaderapi.c b/src/mesa/main/shaderapi.c index a04b28711f7..a4296adf799 100644 --- a/src/mesa/main/shaderapi.c +++ b/src/mesa/main/shaderapi.c @@ -532,7 +532,7 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname, /* True if geometry shaders (of the form that was adopted into GLSL 1.50 * and GL 3.2) are available in this context */ - const bool has_core_gs = _mesa_is_desktop_gl(ctx) && ctx->Version >= 32; + const bool has_core_gs = _mesa_has_geometry_shaders(ctx); /* Are uniform buffer objects available in this context? */ @@ -569,13 +569,13 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname, *params = _mesa_longest_attribute_name_length(shProg); return; case GL_ACTIVE_UNIFORMS: - *params = shProg->NumUserUniformStorage - shProg->NumHiddenUniforms; + *params = shProg->NumUniformStorage - shProg->NumHiddenUniforms; return; case GL_ACTIVE_UNIFORM_MAX_LENGTH: { unsigned i; GLint max_len = 0; const unsigned num_uniforms = - shProg->NumUserUniformStorage - shProg->NumHiddenUniforms; + shProg->NumUniformStorage - shProg->NumHiddenUniforms; for (i = 0; i < num_uniforms; i++) { /* Add one for the terminating NUL character for a non-array, and diff --git a/src/mesa/main/shaderobj.c b/src/mesa/main/shaderobj.c index e428960362d..110a18e1e2c 100644 --- a/src/mesa/main/shaderobj.c +++ b/src/mesa/main/shaderobj.c @@ -282,10 +282,10 @@ _mesa_clear_shader_program_data(struct gl_shader_program *shProg) unsigned i; if (shProg->UniformStorage) { - for (i = 0; i < shProg->NumUserUniformStorage; ++i) + for (i = 0; i < shProg->NumUniformStorage; ++i) _mesa_uniform_detach_all_driver_storage(&shProg->UniformStorage[i]); ralloc_free(shProg->UniformStorage); - shProg->NumUserUniformStorage = 0; + shProg->NumUniformStorage = 0; shProg->UniformStorage = NULL; } diff --git a/src/mesa/main/shared.c b/src/mesa/main/shared.c index 0b76cc01218..d5ac9f1fb13 100644 --- a/src/mesa/main/shared.c +++ b/src/mesa/main/shared.c @@ -313,7 +313,6 @@ free_shared_state(struct gl_context *ctx, struct gl_shared_state *shared) _mesa_DeleteHashTable(shared->Programs); _mesa_reference_vertprog(ctx, &shared->DefaultVertexProgram, NULL); - _mesa_reference_geomprog(ctx, &shared->DefaultGeometryProgram, NULL); _mesa_reference_fragprog(ctx, &shared->DefaultFragmentProgram, NULL); _mesa_HashDeleteAll(shared->ATIShaders, delete_fragshader_cb, ctx); diff --git a/src/mesa/main/state.c b/src/mesa/main/state.c index 99db37bafd7..bede7fe1d0e 100644 --- a/src/mesa/main/state.c +++ b/src/mesa/main/state.c @@ -225,7 +225,7 @@ update_program(struct gl_context *ctx) if (ctx->GeometryProgram._Current != prevGP) { new_state |= _NEW_PROGRAM; if (ctx->Driver.BindProgram) { - ctx->Driver.BindProgram(ctx, MESA_GEOMETRY_PROGRAM, + ctx->Driver.BindProgram(ctx, GL_GEOMETRY_PROGRAM_NV, (struct gl_program *) ctx->GeometryProgram._Current); } } @@ -266,15 +266,9 @@ update_program_constants(struct gl_context *ctx) } } - if (ctx->GeometryProgram._Current) { - const struct gl_program_parameter_list *params = - ctx->GeometryProgram._Current->Base.Parameters; - /*FIXME: StateFlags is always 0 because we have unnamed constant - * not state changes */ - if (params /*&& params->StateFlags & ctx->NewState*/) { - new_state |= _NEW_PROGRAM_CONSTANTS; - } - } + /* Don't handle geometry shaders here. They don't use any state + * constants. + */ if (ctx->VertexProgram._Current) { const struct gl_program_parameter_list *params = @@ -389,10 +383,10 @@ _mesa_update_state_locked( struct gl_context *ctx ) update_frontbit( ctx ); if (new_state & _NEW_BUFFERS) - _mesa_update_framebuffer(ctx); + _mesa_update_framebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer); if (new_state & (_NEW_SCISSOR | _NEW_BUFFERS | _NEW_VIEWPORT)) - _mesa_update_draw_buffer_bounds( ctx ); + _mesa_update_draw_buffer_bounds(ctx, ctx->DrawBuffer); if (new_state & _NEW_LIGHT) _mesa_update_lighting( ctx ); diff --git a/src/mesa/main/tests/dispatch_sanity.cpp b/src/mesa/main/tests/dispatch_sanity.cpp index ccd0124a2bb..800720b798e 100644 --- a/src/mesa/main/tests/dispatch_sanity.cpp +++ b/src/mesa/main/tests/dispatch_sanity.cpp @@ -68,10 +68,13 @@ struct function { int offset; }; +extern const struct function common_desktop_functions_possible[]; +extern const struct function gl_compatibility_functions_possible[]; extern const struct function gl_core_functions_possible[]; extern const struct function gles11_functions_possible[]; extern const struct function gles2_functions_possible[]; extern const struct function gles3_functions_possible[]; +extern const struct function gles31_functions_possible[]; class DispatchSanity_test : public ::testing::Test { public: @@ -96,7 +99,7 @@ DispatchSanity_test::SetUp() _mesa_init_driver_functions(&driver_functions); const unsigned size = _glapi_get_dispatch_table_size(); - nop_table = (_glapi_proc *) _glapi_new_nop_table(size); + nop_table = (_glapi_proc *) _mesa_new_nop_table(size); } void @@ -175,10 +178,19 @@ validate_nops(struct gl_context *ctx, const _glapi_proc *nop_table) TEST_F(DispatchSanity_test, GL31_CORE) { SetUpCtx(API_OPENGL_CORE, 31); + validate_functions(&ctx, common_desktop_functions_possible, nop_table); validate_functions(&ctx, gl_core_functions_possible, nop_table); validate_nops(&ctx, nop_table); } +TEST_F(DispatchSanity_test, GL30) +{ + SetUpCtx(API_OPENGL_COMPAT, 30); + validate_functions(&ctx, common_desktop_functions_possible, nop_table); + validate_functions(&ctx, gl_compatibility_functions_possible, nop_table); + validate_nops(&ctx, nop_table); +} + TEST_F(DispatchSanity_test, GLES11) { SetUpCtx(API_OPENGLES, 11); @@ -201,7 +213,16 @@ TEST_F(DispatchSanity_test, GLES3) validate_nops(&ctx, nop_table); } -const struct function gl_core_functions_possible[] = { +TEST_F(DispatchSanity_test, GLES31) +{ + SetUpCtx(API_OPENGLES2, 31); + validate_functions(&ctx, gles2_functions_possible, nop_table); + validate_functions(&ctx, gles3_functions_possible, nop_table); + validate_functions(&ctx, gles31_functions_possible, nop_table); + validate_nops(&ctx, nop_table); +} + +const struct function common_desktop_functions_possible[] = { { "glCullFace", 10, -1 }, { "glFrontFace", 10, -1 }, { "glHint", 10, -1 }, @@ -213,8 +234,8 @@ const struct function gl_core_functions_possible[] = { { "glTexParameterfv", 10, -1 }, { "glTexParameteri", 10, -1 }, { "glTexParameteriv", 10, -1 }, - { "glTexImage1D", 10, -1 }, - { "glTexImage2D", 10, -1 }, + { "glTexImage1D", 10, _gloffset_TexImage1D }, + { "glTexImage2D", 10, _gloffset_TexImage2D }, { "glDrawBuffer", 10, -1 }, { "glClear", 10, -1 }, { "glClearColor", 10, -1 }, @@ -482,7 +503,6 @@ const struct function gl_core_functions_possible[] = { /* GL 3.1 */ { "glDrawArraysInstanced", 31, -1 }, { "glDrawElementsInstanced", 31, -1 }, - { "glTexBuffer", 31, -1 }, { "glPrimitiveRestartIndex", 31, -1 }, /* GL_ARB_shader_objects */ @@ -535,12 +555,8 @@ const struct function gl_core_functions_possible[] = { { "glGetInteger64i_v", 32, -1 }, { "glGetBufferParameteri64v", 32, -1 }, { "glFramebufferTexture", 32, -1 }, - - /* GL_ARB_geometry_shader4 */ - { "glProgramParameteriARB", 32, -1 }, - { "glFramebufferTextureARB", 32, -1 }, - { "glFramebufferTextureLayerARB", 32, -1 }, - { "glFramebufferTextureFaceARB", 32, -1 }, + { "glProgramParameteri", 32, -1 }, + { "glFramebufferTextureLayer", 32, -1 }, /* GL 3.3 */ { "glVertexAttribDivisor", 33, -1 }, @@ -673,34 +689,6 @@ const struct function gl_core_functions_possible[] = { { "glVertexAttribP4uiv", 43, -1 }, { "glDrawArraysIndirect", 43, -1 }, { "glDrawElementsIndirect", 43, -1 }, - { "glUniform1d", 40, -1 }, - { "glUniform2d", 40, -1 }, - { "glUniform3d", 40, -1 }, - { "glUniform4d", 40, -1 }, - { "glUniform1dv", 40, -1 }, - { "glUniform2dv", 40, -1 }, - { "glUniform3dv", 40, -1 }, - { "glUniform4dv", 40, -1 }, - { "glUniformMatrix2dv", 40, -1 }, - { "glUniformMatrix3dv", 40, -1 }, - { "glUniformMatrix4dv", 40, -1 }, - { "glUniformMatrix2x3dv", 40, -1 }, - { "glUniformMatrix2x4dv", 40, -1 }, - { "glUniformMatrix3x2dv", 40, -1 }, - { "glUniformMatrix3x4dv", 40, -1 }, - { "glUniformMatrix4x2dv", 40, -1 }, - { "glUniformMatrix4x3dv", 40, -1 }, - { "glGetUniformdv", 43, -1 }, -// { "glGetSubroutineUniformLocation", 43, -1 }, // XXX: Add to xml -// { "glGetSubroutineIndex", 43, -1 }, // XXX: Add to xml -// { "glGetActiveSubroutineUniformiv", 43, -1 }, // XXX: Add to xml -// { "glGetActiveSubroutineUniformName", 43, -1 }, // XXX: Add to xml -// { "glGetActiveSubroutineName", 43, -1 }, // XXX: Add to xml -// { "glUniformSubroutinesuiv", 43, -1 }, // XXX: Add to xml -// { "glGetUniformSubroutineuiv", 43, -1 }, // XXX: Add to xml -// { "glGetProgramStageiv", 43, -1 }, // XXX: Add to xml -// { "glPatchParameteri", 43, -1 }, // XXX: Add to xml -// { "glPatchParameterfv", 43, -1 }, // XXX: Add to xml { "glBindTransformFeedback", 43, -1 }, { "glDeleteTransformFeedbacks", 43, -1 }, { "glGenTransformFeedbacks", 43, -1 }, @@ -728,12 +716,12 @@ const struct function gl_core_functions_possible[] = { { "glGenProgramPipelines", 43, -1 }, { "glIsProgramPipeline", 43, -1 }, { "glGetProgramPipelineiv", 43, -1 }, + { "glProgramUniform1d", 43, -1 }, + { "glProgramUniform1dv", 43, -1 }, { "glProgramUniform1i", 43, -1 }, { "glProgramUniform1iv", 43, -1 }, { "glProgramUniform1f", 43, -1 }, { "glProgramUniform1fv", 43, -1 }, - { "glProgramUniform1d", 40, -1 }, - { "glProgramUniform1dv", 40, -1 }, { "glProgramUniform1ui", 43, -1 }, { "glProgramUniform1uiv", 43, -1 }, { "glProgramUniform2i", 43, -1 }, @@ -754,50 +742,32 @@ const struct function gl_core_functions_possible[] = { { "glProgramUniform3uiv", 43, -1 }, { "glProgramUniform4i", 43, -1 }, { "glProgramUniform4iv", 43, -1 }, + { "glProgramUniform4d", 43, -1 }, + { "glProgramUniform4dv", 43, -1 }, { "glProgramUniform4f", 43, -1 }, { "glProgramUniform4fv", 43, -1 }, - { "glProgramUniform4d", 40, -1 }, - { "glProgramUniform4dv", 40, -1 }, { "glProgramUniform4ui", 43, -1 }, { "glProgramUniform4uiv", 43, -1 }, + { "glProgramUniformMatrix2dv", 43, -1 }, { "glProgramUniformMatrix2fv", 43, -1 }, + { "glProgramUniformMatrix3dv", 43, -1 }, { "glProgramUniformMatrix3fv", 43, -1 }, + { "glProgramUniformMatrix4dv", 43, -1 }, { "glProgramUniformMatrix4fv", 43, -1 }, - { "glProgramUniformMatrix2dv", 40, -1 }, - { "glProgramUniformMatrix3dv", 40, -1 }, - { "glProgramUniformMatrix4dv", 40, -1 }, + { "glProgramUniformMatrix2x3dv", 43, -1 }, { "glProgramUniformMatrix2x3fv", 43, -1 }, + { "glProgramUniformMatrix3x2dv", 43, -1 }, { "glProgramUniformMatrix3x2fv", 43, -1 }, + { "glProgramUniformMatrix2x4dv", 43, -1 }, { "glProgramUniformMatrix2x4fv", 43, -1 }, + { "glProgramUniformMatrix4x2dv", 43, -1 }, { "glProgramUniformMatrix4x2fv", 43, -1 }, + { "glProgramUniformMatrix3x4dv", 43, -1 }, { "glProgramUniformMatrix3x4fv", 43, -1 }, + { "glProgramUniformMatrix4x3dv", 43, -1 }, { "glProgramUniformMatrix4x3fv", 43, -1 }, - { "glProgramUniformMatrix2x3dv", 40, -1 }, - { "glProgramUniformMatrix3x2dv", 40, -1 }, - { "glProgramUniformMatrix2x4dv", 40, -1 }, - { "glProgramUniformMatrix4x2dv", 40, -1 }, - { "glProgramUniformMatrix3x4dv", 40, -1 }, - { "glProgramUniformMatrix4x3dv", 40, -1 }, { "glValidateProgramPipeline", 43, -1 }, { "glGetProgramPipelineInfoLog", 43, -1 }, - { "glVertexAttribL1d", 41, -1 }, - { "glVertexAttribL2d", 41, -1 }, - { "glVertexAttribL3d", 41, -1 }, - { "glVertexAttribL4d", 41, -1 }, - { "glVertexAttribL1dv", 41, -1 }, - { "glVertexAttribL2dv", 41, -1 }, - { "glVertexAttribL3dv", 41, -1 }, - { "glVertexAttribL4dv", 41, -1 }, - { "glVertexAttribLPointer", 41, -1 }, - { "glGetVertexAttribLdv", 41, -1 }, - { "glViewportArrayv", 43, -1 }, - { "glViewportIndexedf", 43, -1 }, - { "glViewportIndexedfv", 43, -1 }, - { "glScissorArrayv", 43, -1 }, - { "glScissorIndexed", 43, -1 }, - { "glScissorIndexedv", 43, -1 }, - { "glDepthRangeArrayv", 43, -1 }, - { "glDepthRangeIndexed", 43, -1 }, { "glGetFloati_v", 43, -1 }, { "glGetDoublei_v", 43, -1 }, // { "glCreateSyncFromCLeventARB", 43, -1 }, // XXX: Add to xml @@ -840,8 +810,6 @@ const struct function gl_core_functions_possible[] = { { "glClearBufferSubData", 43, -1 }, // { "glClearNamedBufferDataEXT", 43, -1 }, // XXX: Add to xml // { "glClearNamedBufferSubDataEXT", 43, -1 }, // XXX: Add to xml - { "glDispatchCompute", 43, -1 }, - { "glDispatchComputeIndirect", 43, -1 }, { "glCopyImageSubData", 43, -1 }, { "glTextureView", 43, -1 }, { "glBindVertexBuffer", 43, -1 }, @@ -853,11 +821,10 @@ const struct function gl_core_functions_possible[] = { // { "glVertexArrayBindVertexBufferEXT", 43, -1 }, // XXX: Add to xml // { "glVertexArrayVertexAttribFormatEXT", 43, -1 }, // XXX: Add to xml // { "glVertexArrayVertexAttribIFormatEXT", 43, -1 }, // XXX: Add to xml -// { "glVertexArrayVertexAttribLFormatEXT", 43, -1 }, // XXX: Add to xml // { "glVertexArrayVertexAttribBindingEXT", 43, -1 }, // XXX: Add to xml // { "glVertexArrayVertexBindingDivisorEXT", 43, -1 }, // XXX: Add to xml -// { "glFramebufferParameteri", 43, -1 }, // XXX: Add to xml -// { "glGetFramebufferParameteriv", 43, -1 }, // XXX: Add to xml + { "glFramebufferParameteri", 43, -1 }, + { "glGetFramebufferParameteriv", 43, -1 }, // { "glNamedFramebufferParameteriEXT", 43, -1 }, // XXX: Add to xml // { "glGetNamedFramebufferParameterivEXT", 43, -1 }, // XXX: Add to xml // { "glGetInternalformati64v", 43, -1 }, // XXX: Add to xml @@ -876,7 +843,6 @@ const struct function gl_core_functions_possible[] = { { "glGetProgramResourceLocation", 43, -1 }, { "glGetProgramResourceLocationIndex", 43, -1 }, // { "glShaderStorageBlockBinding", 43, -1 }, // XXX: Add to xml - { "glTexBufferRange", 43, -1 }, // { "glTextureBufferRangeEXT", 43, -1 }, // XXX: Add to xml { "glTexStorage2DMultisample", 43, -1 }, { "glTexStorage3DMultisample", 43, -1 }, @@ -958,6 +924,814 @@ const struct function gl_core_functions_possible[] = { /* GL_ARB_clip_control */ { "glClipControl", 45, -1 }, + /* GL_ARB_compute_shader */ + { "glDispatchCompute", 43, -1 }, + { "glDispatchComputeIndirect", 43, -1 }, + + /* GL_EXT_polygon_offset_clamp */ + { "glPolygonOffsetClampEXT", 11, -1 }, + { NULL, 0, -1 } +}; + +const struct function gl_compatibility_functions_possible[] = { + { "glBindVertexArrayAPPLE", 10, -1 }, + { "glGenVertexArraysAPPLE", 10, -1 }, + { "glBindRenderbufferEXT", 10, -1 }, + { "glBindFramebufferEXT", 10, -1 }, + { "glNewList", 10, _gloffset_NewList }, + { "glEndList", 10, _gloffset_EndList }, + { "glCallList", 10, _gloffset_CallList }, + { "glCallLists", 10, _gloffset_CallLists }, + { "glDeleteLists", 10, _gloffset_DeleteLists }, + { "glGenLists", 10, _gloffset_GenLists }, + { "glListBase", 10, _gloffset_ListBase }, + { "glBegin", 10, _gloffset_Begin }, + { "glBitmap", 10, _gloffset_Bitmap }, + { "glColor3b", 10, _gloffset_Color3b }, + { "glColor3bv", 10, _gloffset_Color3bv }, + { "glColor3d", 10, _gloffset_Color3d }, + { "glColor3dv", 10, _gloffset_Color3dv }, + { "glColor3f", 10, _gloffset_Color3f }, + { "glColor3fv", 10, _gloffset_Color3fv }, + { "glColor3i", 10, _gloffset_Color3i }, + { "glColor3iv", 10, _gloffset_Color3iv }, + { "glColor3s", 10, _gloffset_Color3s }, + { "glColor3sv", 10, _gloffset_Color3sv }, + { "glColor3ub", 10, _gloffset_Color3ub }, + { "glColor3ubv", 10, _gloffset_Color3ubv }, + { "glColor3ui", 10, _gloffset_Color3ui }, + { "glColor3uiv", 10, _gloffset_Color3uiv }, + { "glColor3us", 10, _gloffset_Color3us }, + { "glColor3usv", 10, _gloffset_Color3usv }, + { "glColor4b", 10, _gloffset_Color4b }, + { "glColor4bv", 10, _gloffset_Color4bv }, + { "glColor4d", 10, _gloffset_Color4d }, + { "glColor4dv", 10, _gloffset_Color4dv }, + { "glColor4f", 10, _gloffset_Color4f }, + { "glColor4fv", 10, _gloffset_Color4fv }, + { "glColor4i", 10, _gloffset_Color4i }, + { "glColor4iv", 10, _gloffset_Color4iv }, + { "glColor4s", 10, _gloffset_Color4s }, + { "glColor4sv", 10, _gloffset_Color4sv }, + { "glColor4ub", 10, _gloffset_Color4ub }, + { "glColor4ubv", 10, _gloffset_Color4ubv }, + { "glColor4ui", 10, _gloffset_Color4ui }, + { "glColor4uiv", 10, _gloffset_Color4uiv }, + { "glColor4us", 10, _gloffset_Color4us }, + { "glColor4usv", 10, _gloffset_Color4usv }, + { "glEdgeFlag", 10, _gloffset_EdgeFlag }, + { "glEdgeFlagv", 10, _gloffset_EdgeFlagv }, + { "glEnd", 10, _gloffset_End }, + { "glIndexd", 10, _gloffset_Indexd }, + { "glIndexdv", 10, _gloffset_Indexdv }, + { "glIndexf", 10, _gloffset_Indexf }, + { "glIndexfv", 10, _gloffset_Indexfv }, + { "glIndexi", 10, _gloffset_Indexi }, + { "glIndexiv", 10, _gloffset_Indexiv }, + { "glIndexs", 10, _gloffset_Indexs }, + { "glIndexsv", 10, _gloffset_Indexsv }, + { "glNormal3b", 10, _gloffset_Normal3b }, + { "glNormal3bv", 10, _gloffset_Normal3bv }, + { "glNormal3d", 10, _gloffset_Normal3d }, + { "glNormal3dv", 10, _gloffset_Normal3dv }, + { "glNormal3f", 10, _gloffset_Normal3f }, + { "glNormal3fv", 10, _gloffset_Normal3fv }, + { "glNormal3i", 10, _gloffset_Normal3i }, + { "glNormal3iv", 10, _gloffset_Normal3iv }, + { "glNormal3s", 10, _gloffset_Normal3s }, + { "glNormal3sv", 10, _gloffset_Normal3sv }, + { "glRasterPos2d", 10, _gloffset_RasterPos2d }, + { "glRasterPos2dv", 10, _gloffset_RasterPos2dv }, + { "glRasterPos2f", 10, _gloffset_RasterPos2f }, + { "glRasterPos2fv", 10, _gloffset_RasterPos2fv }, + { "glRasterPos2i", 10, _gloffset_RasterPos2i }, + { "glRasterPos2iv", 10, _gloffset_RasterPos2iv }, + { "glRasterPos2s", 10, _gloffset_RasterPos2s }, + { "glRasterPos2sv", 10, _gloffset_RasterPos2sv }, + { "glRasterPos3d", 10, _gloffset_RasterPos3d }, + { "glRasterPos3dv", 10, _gloffset_RasterPos3dv }, + { "glRasterPos3f", 10, _gloffset_RasterPos3f }, + { "glRasterPos3fv", 10, _gloffset_RasterPos3fv }, + { "glRasterPos3i", 10, _gloffset_RasterPos3i }, + { "glRasterPos3iv", 10, _gloffset_RasterPos3iv }, + { "glRasterPos3s", 10, _gloffset_RasterPos3s }, + { "glRasterPos3sv", 10, _gloffset_RasterPos3sv }, + { "glRasterPos4d", 10, _gloffset_RasterPos4d }, + { "glRasterPos4dv", 10, _gloffset_RasterPos4dv }, + { "glRasterPos4f", 10, _gloffset_RasterPos4f }, + { "glRasterPos4fv", 10, _gloffset_RasterPos4fv }, + { "glRasterPos4i", 10, _gloffset_RasterPos4i }, + { "glRasterPos4iv", 10, _gloffset_RasterPos4iv }, + { "glRasterPos4s", 10, _gloffset_RasterPos4s }, + { "glRasterPos4sv", 10, _gloffset_RasterPos4sv }, + { "glRectd", 10, _gloffset_Rectd }, + { "glRectdv", 10, _gloffset_Rectdv }, + { "glRectf", 10, _gloffset_Rectf }, + { "glRectfv", 10, _gloffset_Rectfv }, + { "glRecti", 10, _gloffset_Recti }, + { "glRectiv", 10, _gloffset_Rectiv }, + { "glRects", 10, _gloffset_Rects }, + { "glRectsv", 10, _gloffset_Rectsv }, + { "glTexCoord1d", 10, _gloffset_TexCoord1d }, + { "glTexCoord1dv", 10, _gloffset_TexCoord1dv }, + { "glTexCoord1f", 10, _gloffset_TexCoord1f }, + { "glTexCoord1fv", 10, _gloffset_TexCoord1fv }, + { "glTexCoord1i", 10, _gloffset_TexCoord1i }, + { "glTexCoord1iv", 10, _gloffset_TexCoord1iv }, + { "glTexCoord1s", 10, _gloffset_TexCoord1s }, + { "glTexCoord1sv", 10, _gloffset_TexCoord1sv }, + { "glTexCoord2d", 10, _gloffset_TexCoord2d }, + { "glTexCoord2dv", 10, _gloffset_TexCoord2dv }, + { "glTexCoord2f", 10, _gloffset_TexCoord2f }, + { "glTexCoord2fv", 10, _gloffset_TexCoord2fv }, + { "glTexCoord2i", 10, _gloffset_TexCoord2i }, + { "glTexCoord2iv", 10, _gloffset_TexCoord2iv }, + { "glTexCoord2s", 10, _gloffset_TexCoord2s }, + { "glTexCoord2sv", 10, _gloffset_TexCoord2sv }, + { "glTexCoord3d", 10, _gloffset_TexCoord3d }, + { "glTexCoord3dv", 10, _gloffset_TexCoord3dv }, + { "glTexCoord3f", 10, _gloffset_TexCoord3f }, + { "glTexCoord3fv", 10, _gloffset_TexCoord3fv }, + { "glTexCoord3i", 10, _gloffset_TexCoord3i }, + { "glTexCoord3iv", 10, _gloffset_TexCoord3iv }, + { "glTexCoord3s", 10, _gloffset_TexCoord3s }, + { "glTexCoord3sv", 10, _gloffset_TexCoord3sv }, + { "glTexCoord4d", 10, _gloffset_TexCoord4d }, + { "glTexCoord4dv", 10, _gloffset_TexCoord4dv }, + { "glTexCoord4f", 10, _gloffset_TexCoord4f }, + { "glTexCoord4fv", 10, _gloffset_TexCoord4fv }, + { "glTexCoord4i", 10, _gloffset_TexCoord4i }, + { "glTexCoord4iv", 10, _gloffset_TexCoord4iv }, + { "glTexCoord4s", 10, _gloffset_TexCoord4s }, + { "glTexCoord4sv", 10, _gloffset_TexCoord4sv }, + { "glVertex2d", 10, _gloffset_Vertex2d }, + { "glVertex2dv", 10, _gloffset_Vertex2dv }, + { "glVertex2f", 10, _gloffset_Vertex2f }, + { "glVertex2fv", 10, _gloffset_Vertex2fv }, + { "glVertex2i", 10, _gloffset_Vertex2i }, + { "glVertex2iv", 10, _gloffset_Vertex2iv }, + { "glVertex2s", 10, _gloffset_Vertex2s }, + { "glVertex2sv", 10, _gloffset_Vertex2sv }, + { "glVertex3d", 10, _gloffset_Vertex3d }, + { "glVertex3dv", 10, _gloffset_Vertex3dv }, + { "glVertex3f", 10, _gloffset_Vertex3f }, + { "glVertex3fv", 10, _gloffset_Vertex3fv }, + { "glVertex3i", 10, _gloffset_Vertex3i }, + { "glVertex3iv", 10, _gloffset_Vertex3iv }, + { "glVertex3s", 10, _gloffset_Vertex3s }, + { "glVertex3sv", 10, _gloffset_Vertex3sv }, + { "glVertex4d", 10, _gloffset_Vertex4d }, + { "glVertex4dv", 10, _gloffset_Vertex4dv }, + { "glVertex4f", 10, _gloffset_Vertex4f }, + { "glVertex4fv", 10, _gloffset_Vertex4fv }, + { "glVertex4i", 10, _gloffset_Vertex4i }, + { "glVertex4iv", 10, _gloffset_Vertex4iv }, + { "glVertex4s", 10, _gloffset_Vertex4s }, + { "glVertex4sv", 10, _gloffset_Vertex4sv }, + { "glClipPlane", 10, _gloffset_ClipPlane }, + { "glColorMaterial", 10, _gloffset_ColorMaterial }, + { "glFogf", 10, _gloffset_Fogf }, + { "glFogfv", 10, _gloffset_Fogfv }, + { "glFogi", 10, _gloffset_Fogi }, + { "glFogiv", 10, _gloffset_Fogiv }, + { "glLightf", 10, _gloffset_Lightf }, + { "glLightfv", 10, _gloffset_Lightfv }, + { "glLighti", 10, _gloffset_Lighti }, + { "glLightiv", 10, _gloffset_Lightiv }, + { "glLightModelf", 10, _gloffset_LightModelf }, + { "glLightModelfv", 10, _gloffset_LightModelfv }, + { "glLightModeli", 10, _gloffset_LightModeli }, + { "glLightModeliv", 10, _gloffset_LightModeliv }, + { "glLineStipple", 10, _gloffset_LineStipple }, + { "glMaterialf", 10, _gloffset_Materialf }, + { "glMaterialfv", 10, _gloffset_Materialfv }, + { "glMateriali", 10, _gloffset_Materiali }, + { "glMaterialiv", 10, _gloffset_Materialiv }, + { "glPolygonStipple", 10, _gloffset_PolygonStipple }, + { "glShadeModel", 10, _gloffset_ShadeModel }, + { "glTexEnvf", 10, _gloffset_TexEnvf }, + { "glTexEnvfv", 10, _gloffset_TexEnvfv }, + { "glTexEnvi", 10, _gloffset_TexEnvi }, + { "glTexEnviv", 10, _gloffset_TexEnviv }, + { "glTexGend", 10, _gloffset_TexGend }, + { "glTexGendv", 10, _gloffset_TexGendv }, + { "glTexGenf", 10, _gloffset_TexGenf }, + { "glTexGenfv", 10, _gloffset_TexGenfv }, + { "glTexGeni", 10, _gloffset_TexGeni }, + { "glTexGeniv", 10, _gloffset_TexGeniv }, + { "glFeedbackBuffer", 10, _gloffset_FeedbackBuffer }, + { "glSelectBuffer", 10, _gloffset_SelectBuffer }, + { "glRenderMode", 10, _gloffset_RenderMode }, + { "glInitNames", 10, _gloffset_InitNames }, + { "glLoadName", 10, _gloffset_LoadName }, + { "glPassThrough", 10, _gloffset_PassThrough }, + { "glPopName", 10, _gloffset_PopName }, + { "glPushName", 10, _gloffset_PushName }, + { "glClearAccum", 10, _gloffset_ClearAccum }, + { "glClearIndex", 10, _gloffset_ClearIndex }, + { "glIndexMask", 10, _gloffset_IndexMask }, + { "glAccum", 10, _gloffset_Accum }, + { "glPopAttrib", 10, _gloffset_PopAttrib }, + { "glPushAttrib", 10, _gloffset_PushAttrib }, + { "glMap1d", 10, _gloffset_Map1d }, + { "glMap1f", 10, _gloffset_Map1f }, + { "glMap2d", 10, _gloffset_Map2d }, + { "glMap2f", 10, _gloffset_Map2f }, + { "glMapGrid1d", 10, _gloffset_MapGrid1d }, + { "glMapGrid1f", 10, _gloffset_MapGrid1f }, + { "glMapGrid2d", 10, _gloffset_MapGrid2d }, + { "glMapGrid2f", 10, _gloffset_MapGrid2f }, + { "glEvalCoord1d", 10, _gloffset_EvalCoord1d }, + { "glEvalCoord1dv", 10, _gloffset_EvalCoord1dv }, + { "glEvalCoord1f", 10, _gloffset_EvalCoord1f }, + { "glEvalCoord1fv", 10, _gloffset_EvalCoord1fv }, + { "glEvalCoord2d", 10, _gloffset_EvalCoord2d }, + { "glEvalCoord2dv", 10, _gloffset_EvalCoord2dv }, + { "glEvalCoord2f", 10, _gloffset_EvalCoord2f }, + { "glEvalCoord2fv", 10, _gloffset_EvalCoord2fv }, + { "glEvalMesh1", 10, _gloffset_EvalMesh1 }, + { "glEvalPoint1", 10, _gloffset_EvalPoint1 }, + { "glEvalMesh2", 10, _gloffset_EvalMesh2 }, + { "glEvalPoint2", 10, _gloffset_EvalPoint2 }, + { "glAlphaFunc", 10, _gloffset_AlphaFunc }, + { "glPixelZoom", 10, _gloffset_PixelZoom }, + { "glPixelTransferf", 10, _gloffset_PixelTransferf }, + { "glPixelTransferi", 10, _gloffset_PixelTransferi }, + { "glPixelMapfv", 10, _gloffset_PixelMapfv }, + { "glPixelMapuiv", 10, _gloffset_PixelMapuiv }, + { "glPixelMapusv", 10, _gloffset_PixelMapusv }, + { "glCopyPixels", 10, _gloffset_CopyPixels }, + { "glDrawPixels", 10, _gloffset_DrawPixels }, + { "glGetClipPlane", 10, _gloffset_GetClipPlane }, + { "glGetLightfv", 10, _gloffset_GetLightfv }, + { "glGetLightiv", 10, _gloffset_GetLightiv }, + { "glGetMapdv", 10, _gloffset_GetMapdv }, + { "glGetMapfv", 10, _gloffset_GetMapfv }, + { "glGetMapiv", 10, _gloffset_GetMapiv }, + { "glGetMaterialfv", 10, _gloffset_GetMaterialfv }, + { "glGetMaterialiv", 10, _gloffset_GetMaterialiv }, + { "glGetPixelMapfv", 10, _gloffset_GetPixelMapfv }, + { "glGetPixelMapuiv", 10, _gloffset_GetPixelMapuiv }, + { "glGetPixelMapusv", 10, _gloffset_GetPixelMapusv }, + { "glGetPolygonStipple", 10, _gloffset_GetPolygonStipple }, + { "glGetTexEnvfv", 10, _gloffset_GetTexEnvfv }, + { "glGetTexEnviv", 10, _gloffset_GetTexEnviv }, + { "glGetTexGendv", 10, _gloffset_GetTexGendv }, + { "glGetTexGenfv", 10, _gloffset_GetTexGenfv }, + { "glGetTexGeniv", 10, _gloffset_GetTexGeniv }, + { "glIsList", 10, _gloffset_IsList }, + { "glFrustum", 10, _gloffset_Frustum }, + { "glLoadIdentity", 10, _gloffset_LoadIdentity }, + { "glLoadMatrixf", 10, _gloffset_LoadMatrixf }, + { "glLoadMatrixd", 10, _gloffset_LoadMatrixd }, + { "glMatrixMode", 10, _gloffset_MatrixMode }, + { "glMultMatrixf", 10, _gloffset_MultMatrixf }, + { "glMultMatrixd", 10, _gloffset_MultMatrixd }, + { "glOrtho", 10, _gloffset_Ortho }, + { "glPopMatrix", 10, _gloffset_PopMatrix }, + { "glPushMatrix", 10, _gloffset_PushMatrix }, + { "glRotated", 10, _gloffset_Rotated }, + { "glRotatef", 10, _gloffset_Rotatef }, + { "glScaled", 10, _gloffset_Scaled }, + { "glScalef", 10, _gloffset_Scalef }, + { "glTranslated", 10, _gloffset_Translated }, + { "glTranslatef", 10, _gloffset_Translatef }, + { "glArrayElement", 10, _gloffset_ArrayElement }, + { "glColorPointer", 10, _gloffset_ColorPointer }, + { "glDisableClientState", 10, _gloffset_DisableClientState }, + { "glEdgeFlagPointer", 10, _gloffset_EdgeFlagPointer }, + { "glEnableClientState", 10, _gloffset_EnableClientState }, + { "glIndexPointer", 10, _gloffset_IndexPointer }, + { "glInterleavedArrays", 10, _gloffset_InterleavedArrays }, + { "glNormalPointer", 10, _gloffset_NormalPointer }, + { "glTexCoordPointer", 10, _gloffset_TexCoordPointer }, + { "glVertexPointer", 10, _gloffset_VertexPointer }, + { "glAreTexturesResident", 10, _gloffset_AreTexturesResident }, + { "glPrioritizeTextures", 10, _gloffset_PrioritizeTextures }, + { "glIndexub", 10, _gloffset_Indexub }, + { "glIndexubv", 10, _gloffset_Indexubv }, + { "glPopClientAttrib", 10, _gloffset_PopClientAttrib }, + { "glPushClientAttrib", 10, _gloffset_PushClientAttrib }, + { "glColorTable", 10, _gloffset_ColorTable }, + { "glColorTableParameterfv", 10, _gloffset_ColorTableParameterfv }, + { "glColorTableParameteriv", 10, _gloffset_ColorTableParameteriv }, + { "glCopyColorTable", 10, _gloffset_CopyColorTable }, + { "glGetColorTable", 10, _gloffset_GetColorTable }, + { "glGetColorTableParameterfv", 10, _gloffset_GetColorTableParameterfv }, + { "glGetColorTableParameteriv", 10, _gloffset_GetColorTableParameteriv }, + { "glColorSubTable", 10, _gloffset_ColorSubTable }, + { "glCopyColorSubTable", 10, _gloffset_CopyColorSubTable }, + { "glConvolutionFilter1D", 10, _gloffset_ConvolutionFilter1D }, + { "glConvolutionFilter2D", 10, _gloffset_ConvolutionFilter2D }, + { "glConvolutionParameterf", 10, _gloffset_ConvolutionParameterf }, + { "glConvolutionParameterfv", 10, _gloffset_ConvolutionParameterfv }, + { "glConvolutionParameteri", 10, _gloffset_ConvolutionParameteri }, + { "glConvolutionParameteriv", 10, _gloffset_ConvolutionParameteriv }, + { "glCopyConvolutionFilter1D", 10, _gloffset_CopyConvolutionFilter1D }, + { "glCopyConvolutionFilter2D", 10, _gloffset_CopyConvolutionFilter2D }, + { "glGetConvolutionFilter", 10, _gloffset_GetConvolutionFilter }, + { "glGetConvolutionParameterfv", 10, _gloffset_GetConvolutionParameterfv }, + { "glGetConvolutionParameteriv", 10, _gloffset_GetConvolutionParameteriv }, + { "glGetSeparableFilter", 10, _gloffset_GetSeparableFilter }, + { "glSeparableFilter2D", 10, _gloffset_SeparableFilter2D }, + { "glGetHistogram", 10, _gloffset_GetHistogram }, + { "glGetHistogramParameterfv", 10, _gloffset_GetHistogramParameterfv }, + { "glGetHistogramParameteriv", 10, _gloffset_GetHistogramParameteriv }, + { "glGetMinmax", 10, _gloffset_GetMinmax }, + { "glGetMinmaxParameterfv", 10, _gloffset_GetMinmaxParameterfv }, + { "glGetMinmaxParameteriv", 10, _gloffset_GetMinmaxParameteriv }, + { "glHistogram", 10, _gloffset_Histogram }, + { "glMinmax", 10, _gloffset_Minmax }, + { "glResetHistogram", 10, _gloffset_ResetHistogram }, + { "glResetMinmax", 10, _gloffset_ResetMinmax }, + { "glClientActiveTexture", 10, _gloffset_ClientActiveTexture }, + { "glMultiTexCoord1d", 10, _gloffset_MultiTexCoord1d }, + { "glMultiTexCoord1dv", 10, _gloffset_MultiTexCoord1dv }, + { "glMultiTexCoord1f", 10, _gloffset_MultiTexCoord1fARB }, + { "glMultiTexCoord1fv", 10, _gloffset_MultiTexCoord1fvARB }, + { "glMultiTexCoord1i", 10, _gloffset_MultiTexCoord1i }, + { "glMultiTexCoord1iv", 10, _gloffset_MultiTexCoord1iv }, + { "glMultiTexCoord1s", 10, _gloffset_MultiTexCoord1s }, + { "glMultiTexCoord1sv", 10, _gloffset_MultiTexCoord1sv }, + { "glMultiTexCoord2d", 10, _gloffset_MultiTexCoord2d }, + { "glMultiTexCoord2dv", 10, _gloffset_MultiTexCoord2dv }, + { "glMultiTexCoord2f", 10, _gloffset_MultiTexCoord2fARB }, + { "glMultiTexCoord2fv", 10, _gloffset_MultiTexCoord2fvARB }, + { "glMultiTexCoord2i", 10, _gloffset_MultiTexCoord2i }, + { "glMultiTexCoord2iv", 10, _gloffset_MultiTexCoord2iv }, + { "glMultiTexCoord2s", 10, _gloffset_MultiTexCoord2s }, + { "glMultiTexCoord2sv", 10, _gloffset_MultiTexCoord2sv }, + { "glMultiTexCoord3d", 10, _gloffset_MultiTexCoord3d }, + { "glMultiTexCoord3dv", 10, _gloffset_MultiTexCoord3dv }, + { "glMultiTexCoord3f", 10, _gloffset_MultiTexCoord3fARB }, + { "glMultiTexCoord3fv", 10, _gloffset_MultiTexCoord3fvARB }, + { "glMultiTexCoord3i", 10, _gloffset_MultiTexCoord3i }, + { "glMultiTexCoord3iv", 10, _gloffset_MultiTexCoord3iv }, + { "glMultiTexCoord3s", 10, _gloffset_MultiTexCoord3s }, + { "glMultiTexCoord3sv", 10, _gloffset_MultiTexCoord3sv }, + { "glMultiTexCoord4d", 10, _gloffset_MultiTexCoord4d }, + { "glMultiTexCoord4dv", 10, _gloffset_MultiTexCoord4dv }, + { "glMultiTexCoord4f", 10, _gloffset_MultiTexCoord4fARB }, + { "glMultiTexCoord4fv", 10, _gloffset_MultiTexCoord4fvARB }, + { "glMultiTexCoord4i", 10, _gloffset_MultiTexCoord4i }, + { "glMultiTexCoord4iv", 10, _gloffset_MultiTexCoord4iv }, + { "glMultiTexCoord4s", 10, _gloffset_MultiTexCoord4s }, + { "glMultiTexCoord4sv", 10, _gloffset_MultiTexCoord4sv }, + { "glLoadTransposeMatrixf", 10, -1 }, + { "glLoadTransposeMatrixd", 10, -1 }, + { "glMultTransposeMatrixf", 10, -1 }, + { "glMultTransposeMatrixd", 10, -1 }, + { "glFogCoordf", 10, -1 }, + { "glFogCoordfv", 10, -1 }, + { "glFogCoordd", 10, -1 }, + { "glFogCoorddv", 10, -1 }, + { "glFogCoordPointer", 10, -1 }, + { "glSecondaryColor3b", 10, -1 }, + { "glSecondaryColor3bv", 10, -1 }, + { "glSecondaryColor3d", 10, -1 }, + { "glSecondaryColor3dv", 10, -1 }, + { "glSecondaryColor3f", 10, -1 }, + { "glSecondaryColor3fv", 10, -1 }, + { "glSecondaryColor3i", 10, -1 }, + { "glSecondaryColor3iv", 10, -1 }, + { "glSecondaryColor3s", 10, -1 }, + { "glSecondaryColor3sv", 10, -1 }, + { "glSecondaryColor3ub", 10, -1 }, + { "glSecondaryColor3ubv", 10, -1 }, + { "glSecondaryColor3ui", 10, -1 }, + { "glSecondaryColor3uiv", 10, -1 }, + { "glSecondaryColor3us", 10, -1 }, + { "glSecondaryColor3usv", 10, -1 }, + { "glSecondaryColorPointer", 10, -1 }, + { "glWindowPos2d", 10, -1 }, + { "glWindowPos2dv", 10, -1 }, + { "glWindowPos2f", 10, -1 }, + { "glWindowPos2fv", 10, -1 }, + { "glWindowPos2i", 10, -1 }, + { "glWindowPos2iv", 10, -1 }, + { "glWindowPos2s", 10, -1 }, + { "glWindowPos2sv", 10, -1 }, + { "glWindowPos3d", 10, -1 }, + { "glWindowPos3dv", 10, -1 }, + { "glWindowPos3f", 10, -1 }, + { "glWindowPos3fv", 10, -1 }, + { "glWindowPos3i", 10, -1 }, + { "glWindowPos3iv", 10, -1 }, + { "glWindowPos3s", 10, -1 }, + { "glWindowPos3sv", 10, -1 }, + { "glProgramStringARB", 10, -1 }, + { "glProgramEnvParameter4dARB", 10, -1 }, + { "glProgramEnvParameter4dvARB", 10, -1 }, + { "glProgramEnvParameter4fARB", 10, -1 }, + { "glProgramEnvParameter4fvARB", 10, -1 }, + { "glProgramLocalParameter4dARB", 10, -1 }, + { "glProgramLocalParameter4dvARB", 10, -1 }, + { "glProgramLocalParameter4fARB", 10, -1 }, + { "glProgramLocalParameter4fvARB", 10, -1 }, + { "glGetProgramEnvParameterdvARB", 10, -1 }, + { "glGetProgramEnvParameterfvARB", 10, -1 }, + { "glGetProgramLocalParameterdvARB", 10, -1 }, + { "glGetProgramLocalParameterfvARB", 10, -1 }, + { "glGetProgramivARB", 10, -1 }, + { "glGetProgramStringARB", 10, -1 }, + { "glPolygonOffsetEXT", 10, -1 }, + { "glColorPointerEXT", 10, -1 }, + { "glEdgeFlagPointerEXT", 10, -1 }, + { "glIndexPointerEXT", 10, -1 }, + { "glNormalPointerEXT", 10, -1 }, + { "glTexCoordPointerEXT", 10, -1 }, + { "glVertexPointerEXT", 10, -1 }, + { "glLockArraysEXT", 10, -1 }, + { "glUnlockArraysEXT", 10, -1 }, + { "glWindowPos4dMESA", 10, -1 }, + { "glWindowPos4dvMESA", 10, -1 }, + { "glWindowPos4fMESA", 10, -1 }, + { "glWindowPos4fvMESA", 10, -1 }, + { "glWindowPos4iMESA", 10, -1 }, + { "glWindowPos4ivMESA", 10, -1 }, + { "glWindowPos4sMESA", 10, -1 }, + { "glWindowPos4svMESA", 10, -1 }, + { "glBindProgramNV", 10, -1 }, + { "glDeleteProgramsNV", 10, -1 }, + { "glGenProgramsNV", 10, -1 }, + { "glIsProgramNV", 10, -1 }, + { "glVertexAttrib1sNV", 10, -1 }, + { "glVertexAttrib1svNV", 10, -1 }, + { "glVertexAttrib2sNV", 10, -1 }, + { "glVertexAttrib2svNV", 10, -1 }, + { "glVertexAttrib3sNV", 10, -1 }, + { "glVertexAttrib3svNV", 10, -1 }, + { "glVertexAttrib4sNV", 10, -1 }, + { "glVertexAttrib4svNV", 10, -1 }, + { "glVertexAttrib1fNV", 10, -1 }, + { "glVertexAttrib1fvNV", 10, -1 }, + { "glVertexAttrib2fNV", 10, -1 }, + { "glVertexAttrib2fvNV", 10, -1 }, + { "glVertexAttrib3fNV", 10, -1 }, + { "glVertexAttrib3fvNV", 10, -1 }, + { "glVertexAttrib4fNV", 10, -1 }, + { "glVertexAttrib4fvNV", 10, -1 }, + { "glVertexAttrib1dNV", 10, -1 }, + { "glVertexAttrib1dvNV", 10, -1 }, + { "glVertexAttrib2dNV", 10, -1 }, + { "glVertexAttrib2dvNV", 10, -1 }, + { "glVertexAttrib3dNV", 10, -1 }, + { "glVertexAttrib3dvNV", 10, -1 }, + { "glVertexAttrib4dNV", 10, -1 }, + { "glVertexAttrib4dvNV", 10, -1 }, + { "glVertexAttrib4ubNV", 10, -1 }, + { "glVertexAttrib4ubvNV", 10, -1 }, + { "glVertexAttribs1svNV", 10, -1 }, + { "glVertexAttribs2svNV", 10, -1 }, + { "glVertexAttribs3svNV", 10, -1 }, + { "glVertexAttribs4svNV", 10, -1 }, + { "glVertexAttribs1fvNV", 10, -1 }, + { "glVertexAttribs2fvNV", 10, -1 }, + { "glVertexAttribs3fvNV", 10, -1 }, + { "glVertexAttribs4fvNV", 10, -1 }, + { "glVertexAttribs1dvNV", 10, -1 }, + { "glVertexAttribs2dvNV", 10, -1 }, + { "glVertexAttribs3dvNV", 10, -1 }, + { "glVertexAttribs4dvNV", 10, -1 }, + { "glVertexAttribs4ubvNV", 10, -1 }, + { "glGenFragmentShadersATI", 10, -1 }, + { "glBindFragmentShaderATI", 10, -1 }, + { "glDeleteFragmentShaderATI", 10, -1 }, + { "glBeginFragmentShaderATI", 10, -1 }, + { "glEndFragmentShaderATI", 10, -1 }, + { "glPassTexCoordATI", 10, -1 }, + { "glSampleMapATI", 10, -1 }, + { "glColorFragmentOp1ATI", 10, -1 }, + { "glColorFragmentOp2ATI", 10, -1 }, + { "glColorFragmentOp3ATI", 10, -1 }, + { "glAlphaFragmentOp1ATI", 10, -1 }, + { "glAlphaFragmentOp2ATI", 10, -1 }, + { "glAlphaFragmentOp3ATI", 10, -1 }, + { "glSetFragmentShaderConstantATI", 10, -1 }, + { "glActiveStencilFaceEXT", 10, -1 }, + { "glStencilFuncSeparateATI", 10, -1 }, + { "glProgramEnvParameters4fvEXT", 10, -1 }, + { "glProgramLocalParameters4fvEXT", 10, -1 }, + { "glPrimitiveRestartNV", 10, -1 }, + + { NULL, 0, -1 } +}; + +const struct function gl_core_functions_possible[] = { + /* GL 3.1 */ + { "glTexBuffer", 31, -1 }, + + /* GL 3.2 */ + { "glFramebufferTexture", 32, -1 }, + + /* GL 4.3 */ + { "glIsRenderbuffer", 43, -1 }, + { "glBindRenderbuffer", 43, -1 }, + { "glDeleteRenderbuffers", 43, -1 }, + { "glGenRenderbuffers", 43, -1 }, + { "glRenderbufferStorage", 43, -1 }, + { "glGetRenderbufferParameteriv", 43, -1 }, + { "glIsFramebuffer", 43, -1 }, + { "glBindFramebuffer", 43, -1 }, + { "glDeleteFramebuffers", 43, -1 }, + { "glGenFramebuffers", 43, -1 }, + { "glCheckFramebufferStatus", 43, -1 }, + { "glFramebufferTexture1D", 43, -1 }, + { "glFramebufferTexture2D", 43, -1 }, + { "glFramebufferTexture3D", 43, -1 }, + { "glFramebufferRenderbuffer", 43, -1 }, + { "glGetFramebufferAttachmentParameteriv", 43, -1 }, + { "glGenerateMipmap", 43, -1 }, + { "glBlitFramebuffer", 43, -1 }, + { "glRenderbufferStorageMultisample", 43, -1 }, + { "glFramebufferTextureLayer", 43, -1 }, + { "glMapBufferRange", 43, -1 }, + { "glFlushMappedBufferRange", 43, -1 }, + { "glBindVertexArray", 43, -1 }, + { "glDeleteVertexArrays", 43, -1 }, + { "glGenVertexArrays", 43, -1 }, + { "glIsVertexArray", 43, -1 }, + { "glGetUniformIndices", 43, -1 }, + { "glGetActiveUniformsiv", 43, -1 }, + { "glGetActiveUniformName", 43, -1 }, + { "glGetUniformBlockIndex", 43, -1 }, + { "glGetActiveUniformBlockiv", 43, -1 }, + { "glGetActiveUniformBlockName", 43, -1 }, + { "glUniformBlockBinding", 43, -1 }, + { "glCopyBufferSubData", 43, -1 }, + { "glDrawElementsBaseVertex", 43, -1 }, + { "glDrawRangeElementsBaseVertex", 43, -1 }, + { "glDrawElementsInstancedBaseVertex", 43, -1 }, + { "glMultiDrawElementsBaseVertex", 43, -1 }, + { "glProvokingVertex", 43, -1 }, + { "glFenceSync", 43, -1 }, + { "glIsSync", 43, -1 }, + { "glDeleteSync", 43, -1 }, + { "glClientWaitSync", 43, -1 }, + { "glWaitSync", 43, -1 }, + { "glGetInteger64v", 43, -1 }, + { "glGetSynciv", 43, -1 }, + { "glTexImage2DMultisample", 43, -1 }, + { "glTexImage3DMultisample", 43, -1 }, + { "glGetMultisamplefv", 43, -1 }, + { "glSampleMaski", 43, -1 }, + { "glBlendEquationiARB", 43, -1 }, + { "glBlendEquationSeparateiARB", 43, -1 }, + { "glBlendFunciARB", 43, -1 }, + { "glBlendFuncSeparateiARB", 43, -1 }, + { "glMinSampleShadingARB", 43, -1 }, // XXX: Add to xml +// { "glNamedStringARB", 43, -1 }, // XXX: Add to xml +// { "glDeleteNamedStringARB", 43, -1 }, // XXX: Add to xml +// { "glCompileShaderIncludeARB", 43, -1 }, // XXX: Add to xml +// { "glIsNamedStringARB", 43, -1 }, // XXX: Add to xml +// { "glGetNamedStringARB", 43, -1 }, // XXX: Add to xml +// { "glGetNamedStringivARB", 43, -1 }, // XXX: Add to xml + { "glBindFragDataLocationIndexed", 43, -1 }, + { "glGetFragDataIndex", 43, -1 }, + { "glGenSamplers", 43, -1 }, + { "glDeleteSamplers", 43, -1 }, + { "glIsSampler", 43, -1 }, + { "glBindSampler", 43, -1 }, + { "glSamplerParameteri", 43, -1 }, + { "glSamplerParameteriv", 43, -1 }, + { "glSamplerParameterf", 43, -1 }, + { "glSamplerParameterfv", 43, -1 }, + { "glSamplerParameterIiv", 43, -1 }, + { "glSamplerParameterIuiv", 43, -1 }, + { "glGetSamplerParameteriv", 43, -1 }, + { "glGetSamplerParameterIiv", 43, -1 }, + { "glGetSamplerParameterfv", 43, -1 }, + { "glGetSamplerParameterIuiv", 43, -1 }, + { "glQueryCounter", 43, -1 }, + { "glGetQueryObjecti64v", 43, -1 }, + { "glGetQueryObjectui64v", 43, -1 }, + { "glVertexP2ui", 43, -1 }, + { "glVertexP2uiv", 43, -1 }, + { "glVertexP3ui", 43, -1 }, + { "glVertexP3uiv", 43, -1 }, + { "glVertexP4ui", 43, -1 }, + { "glVertexP4uiv", 43, -1 }, + { "glTexCoordP1ui", 43, -1 }, + { "glTexCoordP1uiv", 43, -1 }, + { "glTexCoordP2ui", 43, -1 }, + { "glTexCoordP2uiv", 43, -1 }, + { "glTexCoordP3ui", 43, -1 }, + { "glTexCoordP3uiv", 43, -1 }, + { "glTexCoordP4ui", 43, -1 }, + { "glTexCoordP4uiv", 43, -1 }, + { "glMultiTexCoordP1ui", 43, -1 }, + { "glMultiTexCoordP1uiv", 43, -1 }, + { "glMultiTexCoordP2ui", 43, -1 }, + { "glMultiTexCoordP2uiv", 43, -1 }, + { "glMultiTexCoordP3ui", 43, -1 }, + { "glMultiTexCoordP3uiv", 43, -1 }, + { "glMultiTexCoordP4ui", 43, -1 }, + { "glMultiTexCoordP4uiv", 43, -1 }, + { "glNormalP3ui", 43, -1 }, + { "glNormalP3uiv", 43, -1 }, + { "glColorP3ui", 43, -1 }, + { "glColorP3uiv", 43, -1 }, + { "glColorP4ui", 43, -1 }, + { "glColorP4uiv", 43, -1 }, + { "glVertexAttribP1ui", 43, -1 }, + { "glVertexAttribP1uiv", 43, -1 }, + { "glVertexAttribP2ui", 43, -1 }, + { "glVertexAttribP2uiv", 43, -1 }, + { "glVertexAttribP3ui", 43, -1 }, + { "glVertexAttribP3uiv", 43, -1 }, + { "glVertexAttribP4ui", 43, -1 }, + { "glVertexAttribP4uiv", 43, -1 }, + { "glDrawArraysIndirect", 43, -1 }, + { "glDrawElementsIndirect", 43, -1 }, + + { "glUniform1d", 40, -1 }, + { "glUniform2d", 40, -1 }, + { "glUniform3d", 40, -1 }, + { "glUniform4d", 40, -1 }, + { "glUniform1dv", 40, -1 }, + { "glUniform2dv", 40, -1 }, + { "glUniform3dv", 40, -1 }, + { "glUniform4dv", 40, -1 }, + { "glUniformMatrix2dv", 40, -1 }, + { "glUniformMatrix3dv", 40, -1 }, + { "glUniformMatrix4dv", 40, -1 }, + { "glUniformMatrix2x3dv", 40, -1 }, + { "glUniformMatrix2x4dv", 40, -1 }, + { "glUniformMatrix3x2dv", 40, -1 }, + { "glUniformMatrix3x4dv", 40, -1 }, + { "glUniformMatrix4x2dv", 40, -1 }, + { "glUniformMatrix4x3dv", 40, -1 }, + { "glGetUniformdv", 43, -1 }, +// { "glGetSubroutineUniformLocation", 43, -1 }, // XXX: Add to xml +// { "glGetSubroutineIndex", 43, -1 }, // XXX: Add to xml +// { "glGetActiveSubroutineUniformiv", 43, -1 }, // XXX: Add to xml +// { "glGetActiveSubroutineUniformName", 43, -1 }, // XXX: Add to xml +// { "glGetActiveSubroutineName", 43, -1 }, // XXX: Add to xml +// { "glUniformSubroutinesuiv", 43, -1 }, // XXX: Add to xml +// { "glGetUniformSubroutineuiv", 43, -1 }, // XXX: Add to xml +// { "glGetProgramStageiv", 43, -1 }, // XXX: Add to xml +// { "glPatchParameteri", 43, -1 }, // XXX: Add to xml +// { "glPatchParameterfv", 43, -1 }, // XXX: Add to xml + + { "glBindTransformFeedback", 43, -1 }, + { "glDeleteTransformFeedbacks", 43, -1 }, + { "glGenTransformFeedbacks", 43, -1 }, + { "glIsTransformFeedback", 43, -1 }, + { "glPauseTransformFeedback", 43, -1 }, + { "glResumeTransformFeedback", 43, -1 }, + { "glDrawTransformFeedback", 43, -1 }, + { "glDrawTransformFeedbackStream", 43, -1 }, + { "glBeginQueryIndexed", 43, -1 }, + { "glEndQueryIndexed", 43, -1 }, + { "glGetQueryIndexediv", 43, -1 }, + { "glReleaseShaderCompiler", 43, -1 }, + { "glShaderBinary", 43, -1 }, + { "glGetShaderPrecisionFormat", 43, -1 }, + { "glDepthRangef", 43, -1 }, + { "glClearDepthf", 43, -1 }, + { "glGetProgramBinary", 43, -1 }, + { "glProgramBinary", 43, -1 }, + { "glProgramParameteri", 43, -1 }, + { "glUseProgramStages", 43, -1 }, + { "glActiveShaderProgram", 43, -1 }, + { "glCreateShaderProgramv", 43, -1 }, + { "glBindProgramPipeline", 43, -1 }, + { "glDeleteProgramPipelines", 43, -1 }, + { "glGenProgramPipelines", 43, -1 }, + { "glIsProgramPipeline", 43, -1 }, + { "glGetProgramPipelineiv", 43, -1 }, + { "glProgramUniform1i", 43, -1 }, + { "glProgramUniform1iv", 43, -1 }, + { "glProgramUniform1f", 43, -1 }, + { "glProgramUniform1fv", 43, -1 }, + { "glProgramUniform1d", 40, -1 }, + { "glProgramUniform1dv", 40, -1 }, + { "glProgramUniform1ui", 43, -1 }, + { "glProgramUniform1uiv", 43, -1 }, + { "glProgramUniform2i", 43, -1 }, + { "glProgramUniform2iv", 43, -1 }, + { "glProgramUniform2f", 43, -1 }, + { "glProgramUniform2fv", 43, -1 }, + { "glProgramUniform2d", 40, -1 }, + { "glProgramUniform2dv", 40, -1 }, + { "glProgramUniform2ui", 43, -1 }, + { "glProgramUniform2uiv", 43, -1 }, + { "glProgramUniform3i", 43, -1 }, + { "glProgramUniform3iv", 43, -1 }, + { "glProgramUniform3f", 43, -1 }, + { "glProgramUniform3fv", 43, -1 }, + { "glProgramUniform3d", 40, -1 }, + { "glProgramUniform3dv", 40, -1 }, + { "glProgramUniform3ui", 43, -1 }, + { "glProgramUniform3uiv", 43, -1 }, + { "glProgramUniform4i", 43, -1 }, + { "glProgramUniform4iv", 43, -1 }, + { "glProgramUniform4f", 43, -1 }, + { "glProgramUniform4fv", 43, -1 }, + { "glProgramUniform4d", 40, -1 }, + { "glProgramUniform4dv", 40, -1 }, + { "glProgramUniform4ui", 43, -1 }, + { "glProgramUniform4uiv", 43, -1 }, + { "glProgramUniformMatrix2fv", 43, -1 }, + { "glProgramUniformMatrix3fv", 43, -1 }, + { "glProgramUniformMatrix4fv", 43, -1 }, + { "glProgramUniformMatrix2dv", 40, -1 }, + { "glProgramUniformMatrix3dv", 40, -1 }, + { "glProgramUniformMatrix4dv", 40, -1 }, + { "glProgramUniformMatrix2x3fv", 43, -1 }, + { "glProgramUniformMatrix3x2fv", 43, -1 }, + { "glProgramUniformMatrix2x4fv", 43, -1 }, + { "glProgramUniformMatrix4x2fv", 43, -1 }, + { "glProgramUniformMatrix3x4fv", 43, -1 }, + { "glProgramUniformMatrix4x3fv", 43, -1 }, + { "glProgramUniformMatrix2x3dv", 40, -1 }, + { "glProgramUniformMatrix3x2dv", 40, -1 }, + { "glProgramUniformMatrix2x4dv", 40, -1 }, + { "glProgramUniformMatrix4x2dv", 40, -1 }, + { "glProgramUniformMatrix3x4dv", 40, -1 }, + { "glProgramUniformMatrix4x3dv", 40, -1 }, + { "glValidateProgramPipeline", 43, -1 }, + { "glGetProgramPipelineInfoLog", 43, -1 }, + + { "glVertexAttribL1d", 41, -1 }, + { "glVertexAttribL2d", 41, -1 }, + { "glVertexAttribL3d", 41, -1 }, + { "glVertexAttribL4d", 41, -1 }, + { "glVertexAttribL1dv", 41, -1 }, + { "glVertexAttribL2dv", 41, -1 }, + { "glVertexAttribL3dv", 41, -1 }, + { "glVertexAttribL4dv", 41, -1 }, + { "glVertexAttribLPointer", 41, -1 }, + { "glGetVertexAttribLdv", 41, -1 }, + { "glViewportArrayv", 43, -1 }, + { "glViewportIndexedf", 43, -1 }, + { "glViewportIndexedfv", 43, -1 }, + { "glScissorArrayv", 43, -1 }, + { "glScissorIndexed", 43, -1 }, + { "glScissorIndexedv", 43, -1 }, + { "glDepthRangeArrayv", 43, -1 }, + { "glDepthRangeIndexed", 43, -1 }, + +// { "glCreateSyncFromCLeventARB", 43, -1 }, // XXX: Add to xml + + { "glDrawArraysInstancedBaseInstance", 43, -1 }, + { "glDrawElementsInstancedBaseInstance", 43, -1 }, + { "glDrawElementsInstancedBaseVertexBaseInstance", 43, -1 }, + { "glDrawTransformFeedbackInstanced", 43, -1 }, + { "glDrawTransformFeedbackStreamInstanced", 43, -1 }, + { "glGetActiveAtomicCounterBufferiv", 43, -1 }, + { "glBindImageTexture", 43, -1 }, + { "glMemoryBarrier", 43, -1 }, + { "glTexStorage1D", 43, -1 }, + { "glTexStorage2D", 43, -1 }, + { "glTexStorage3D", 43, -1 }, + { "glTextureStorage1DEXT", 43, -1 }, + { "glTextureStorage2DEXT", 43, -1 }, + { "glTextureStorage3DEXT", 43, -1 }, + { "glClearBufferData", 43, -1 }, + { "glClearBufferSubData", 43, -1 }, +// { "glClearNamedBufferDataEXT", 43, -1 }, // XXX: Add to xml +// { "glClearNamedBufferSubDataEXT", 43, -1 }, // XXX: Add to xml + { "glCopyImageSubData", 43, -1 }, + { "glTextureView", 43, -1 }, + { "glBindVertexBuffer", 43, -1 }, + { "glVertexAttribFormat", 43, -1 }, + { "glVertexAttribIFormat", 43, -1 }, + { "glVertexAttribBinding", 43, -1 }, + { "glVertexBindingDivisor", 43, -1 }, +// { "glVertexArrayBindVertexBufferEXT", 43, -1 }, // XXX: Add to xml +// { "glVertexArrayVertexAttribFormatEXT", 43, -1 }, // XXX: Add to xml +// { "glVertexArrayVertexAttribIFormatEXT", 43, -1 }, // XXX: Add to xml +// { "glVertexArrayVertexAttribLFormatEXT", 43, -1 }, // XXX: Add to xml +// { "glVertexArrayVertexAttribBindingEXT", 43, -1 }, // XXX: Add to xml +// { "glVertexArrayVertexBindingDivisorEXT", 43, -1 }, // XXX: Add to xml +// { "glFramebufferParameteri", 43, -1 }, // XXX: Add to xml +// { "glGetFramebufferParameteriv", 43, -1 }, // XXX: Add to xml +// { "glNamedFramebufferParameteriEXT", 43, -1 }, // XXX: Add to xml +// { "glGetNamedFramebufferParameterivEXT", 43, -1 }, // XXX: Add to xml +// { "glGetInternalformati64v", 43, -1 }, // XXX: Add to xml + { "glInvalidateTexSubImage", 43, -1 }, + { "glInvalidateTexImage", 43, -1 }, + { "glInvalidateBufferSubData", 43, -1 }, + { "glInvalidateBufferData", 43, -1 }, + { "glInvalidateFramebuffer", 43, -1 }, + { "glInvalidateSubFramebuffer", 43, -1 }, + { "glMultiDrawArraysIndirect", 43, -1 }, + { "glMultiDrawElementsIndirect", 43, -1 }, + { "glGetProgramInterfaceiv", 43, -1 }, + { "glGetProgramResourceIndex", 43, -1 }, + { "glGetProgramResourceName", 43, -1 }, + { "glGetProgramResourceiv", 43, -1 }, + { "glGetProgramResourceLocation", 43, -1 }, + { "glGetProgramResourceLocationIndex", 43, -1 }, +// { "glShaderStorageBlockBinding", 43, -1 }, // XXX: Add to xml + { "glTexBufferRange", 43, -1 }, +// { "glTextureBufferRangeEXT", 43, -1 }, // XXX: Add to xml + { "glTexStorage2DMultisample", 43, -1 }, + { "glTexStorage3DMultisample", 43, -1 }, +// { "glTextureStorage2DMultisampleEXT", 43, -1 }, // XXX: Add to xml +// { "glTextureStorage3DMultisampleEXT", 43, -1 }, // XXX: Add to xml + /* GL_ARB_direct_state_access */ { "glCreateTransformFeedbacks", 45, -1 }, { "glTransformFeedbackBufferBase", 45, -1 }, @@ -980,6 +1754,24 @@ const struct function gl_core_functions_possible[] = { { "glGetNamedBufferParameteri64v", 45, -1 }, { "glGetNamedBufferPointerv", 45, -1 }, { "glGetNamedBufferSubData", 45, -1 }, + { "glCreateFramebuffers", 45, -1 }, + { "glNamedFramebufferRenderbuffer", 45, -1 }, + { "glNamedFramebufferParameteri", 45, -1 }, + { "glNamedFramebufferTexture", 45, -1 }, + { "glNamedFramebufferTextureLayer", 45, -1 }, + { "glNamedFramebufferDrawBuffer", 45, -1 }, + { "glNamedFramebufferDrawBuffers", 45, -1 }, + { "glNamedFramebufferReadBuffer", 45, -1 }, + { "glInvalidateNamedFramebufferSubData", 45, -1 }, + { "glInvalidateNamedFramebufferData", 45, -1 }, + { "glClearNamedFramebufferiv", 45, -1 }, + { "glClearNamedFramebufferuiv", 45, -1 }, + { "glClearNamedFramebufferfv", 45, -1 }, + { "glClearNamedFramebufferfi", 45, -1 }, + { "glBlitNamedFramebuffer", 45, -1 }, + { "glCheckNamedFramebufferStatus", 45, -1 }, + { "glGetNamedFramebufferParameteriv", 45, -1 }, + { "glGetNamedFramebufferAttachmentParameteriv", 45, -1 }, { "glCreateRenderbuffers", 45, -1 }, { "glNamedRenderbufferStorage", 45, -1 }, { "glNamedRenderbufferStorageMultisample", 45, -1 }, @@ -1039,9 +1831,6 @@ const struct function gl_core_functions_possible[] = { { "glGetQueryBufferObjecti64v", 45, -1 }, { "glGetQueryBufferObjectui64v", 45, -1 }, - /* GL_EXT_polygon_offset_clamp */ - { "glPolygonOffsetClampEXT", 11, -1 }, - { NULL, 0, -1 } }; @@ -1596,3 +2385,88 @@ const struct function gles3_functions_possible[] = { { NULL, 0, -1 } }; + +const struct function gles31_functions_possible[] = { + { "glDispatchCompute", 31, -1 }, + { "glDispatchComputeIndirect", 31, -1 }, + { "glDrawArraysIndirect", 31, -1 }, + { "glDrawElementsIndirect", 31, -1 }, + + // FINISHME: These two functions have not been implemented yet. They come + // FINISHME: from the ARB_framebuffer_no_attachments extension. + // { "glFramebufferParameteri", 31, -1 }, + // { "glGetFramebufferParameteriv", 31, -1 }, + + { "glGetProgramInterfaceiv", 31, -1 }, + { "glGetProgramResourceIndex", 31, -1 }, + { "glGetProgramResourceName", 31, -1 }, + { "glGetProgramResourceiv", 31, -1 }, + { "glGetProgramResourceLocation", 31, -1 }, + + // We check for the aliased EXT versions in GLES 2 + // { "glUseProgramStages", 31, -1 }, + // { "glActiveShaderProgram", 31, -1 }, + // { "glCreateShaderProgramv", 31, -1 }, + // { "glBindProgramPipeline", 31, -1 }, + // { "glDeleteProgramPipelines", 31, -1 }, + // { "glGenProgramPipelines", 31, -1 }, + // { "glIsProgramPipeline", 31, -1 }, + // { "glGetProgramPipelineiv", 31, -1 }, + // { "glProgramUniform1i", 31, -1 }, + // { "glProgramUniform2i", 31, -1 }, + // { "glProgramUniform3i", 31, -1 }, + // { "glProgramUniform4i", 31, -1 }, + // { "glProgramUniform1f", 31, -1 }, + // { "glProgramUniform2f", 31, -1 }, + // { "glProgramUniform3f", 31, -1 }, + // { "glProgramUniform4f", 31, -1 }, + // { "glProgramUniform1iv", 31, -1 }, + // { "glProgramUniform2iv", 31, -1 }, + // { "glProgramUniform3iv", 31, -1 }, + // { "glProgramUniform4iv", 31, -1 }, + // { "glProgramUniform1fv", 31, -1 }, + // { "glProgramUniform2fv", 31, -1 }, + // { "glProgramUniform3fv", 31, -1 }, + // { "glProgramUniform4fv", 31, -1 }, + // { "glProgramUniformMatrix2fv", 31, -1 }, + // { "glProgramUniformMatrix3fv", 31, -1 }, + // { "glProgramUniformMatrix4fv", 31, -1 }, + // { "glProgramUniformMatrix2x3fv", 31, -1 }, + // { "glProgramUniformMatrix3x2fv", 31, -1 }, + // { "glProgramUniformMatrix2x4fv", 31, -1 }, + // { "glProgramUniformMatrix4x2fv", 31, -1 }, + // { "glProgramUniformMatrix3x4fv", 31, -1 }, + // { "glProgramUniformMatrix4x3fv", 31, -1 }, + // { "glValidateProgramPipeline", 31, -1 }, + // { "glGetProgramPipelineInfoLog", 31, -1 }, + + // We check for the aliased EXT versions in GLES 3 + // { "glProgramUniform1ui", 31, -1 }, + // { "glProgramUniform2ui", 31, -1 }, + // { "glProgramUniform3ui", 31, -1 }, + // { "glProgramUniform4ui", 31, -1 }, + // { "glProgramUniform1uiv", 31, -1 }, + // { "glProgramUniform2uiv", 31, -1 }, + // { "glProgramUniform3uiv", 31, -1 }, + // { "glProgramUniform4uiv", 31, -1 }, + + { "glBindImageTexture", 31, -1 }, + { "glGetBooleani_v", 31, -1 }, + { "glMemoryBarrier", 31, -1 }, + + // FINISHME: This function has not been implemented yet. + // { "glMemoryBarrierByRegion", 31, -1 }, + + { "glTexStorage2DMultisample", 31, -1 }, + { "glGetMultisamplefv", 31, -1 }, + { "glSampleMaski", 31, -1 }, + { "glGetTexLevelParameteriv", 31, -1 }, + { "glGetTexLevelParameterfv", 31, -1 }, + { "glBindVertexBuffer", 31, -1 }, + { "glVertexAttribFormat", 31, -1 }, + { "glVertexAttribIFormat", 31, -1 }, + { "glVertexAttribBinding", 31, -1 }, + { "glVertexBindingDivisor", 31, -1 }, + + { NULL, 0, -1 }, + }; diff --git a/src/mesa/main/texenv.c b/src/mesa/main/texenv.c index ec521e6c6e5..3edafc0f776 100644 --- a/src/mesa/main/texenv.c +++ b/src/mesa/main/texenv.c @@ -646,7 +646,7 @@ _mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params ) if (pname == GL_TEXTURE_ENV_COLOR) { if(ctx->NewState & (_NEW_BUFFERS | _NEW_FRAG_CLAMP)) _mesa_update_state(ctx); - if (_mesa_get_clamp_fragment_color(ctx)) + if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer)) COPY_4FV( params, texUnit->EnvColor ); else COPY_4FV( params, texUnit->EnvColorUnclamped ); diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c index 7bc1da7f805..3d85615fa45 100644 --- a/src/mesa/main/teximage.c +++ b/src/mesa/main/teximage.c @@ -222,7 +222,7 @@ _mesa_base_tex_format( struct gl_context *ctx, GLint internalFormat ) } } - if (ctx->Extensions.ARB_stencil_texturing) { + if (ctx->Extensions.ARB_texture_stencil8) { switch (internalFormat) { case GL_STENCIL_INDEX: case GL_STENCIL_INDEX1: diff --git a/src/mesa/main/texparam.c b/src/mesa/main/texparam.c index b5d42d3047f..d74134f41b1 100644 --- a/src/mesa/main/texparam.c +++ b/src/mesa/main/texparam.c @@ -1709,7 +1709,7 @@ get_tex_parameterfv(struct gl_context *ctx, if (ctx->NewState & (_NEW_BUFFERS | _NEW_FRAG_CLAMP)) _mesa_update_state_locked(ctx); - if (_mesa_get_clamp_fragment_color(ctx)) { + if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer)) { params[0] = CLAMP(obj->Sampler.BorderColor.f[0], 0.0F, 1.0F); params[1] = CLAMP(obj->Sampler.BorderColor.f[1], 0.0F, 1.0F); params[2] = CLAMP(obj->Sampler.BorderColor.f[2], 0.0F, 1.0F); diff --git a/src/mesa/main/textureview.c b/src/mesa/main/textureview.c index cd87a27d2db..6b0aed4ea1a 100644 --- a/src/mesa/main/textureview.c +++ b/src/mesa/main/textureview.c @@ -167,7 +167,7 @@ static const struct internal_format_class_info s3tc_compatible_internal_formats[ * \return VIEW_CLASS if internalformat found in table, false otherwise. */ static GLenum -lookup_view_class(struct gl_context *ctx, GLenum internalformat) +lookup_view_class(const struct gl_context *ctx, GLenum internalformat) { GLuint i; @@ -176,9 +176,11 @@ lookup_view_class(struct gl_context *ctx, GLenum internalformat) return compatible_internal_formats[i].view_class; } - if (ctx->Extensions.EXT_texture_compression_s3tc && ctx->Extensions.EXT_texture_sRGB) { + if (ctx->Extensions.EXT_texture_compression_s3tc && + ctx->Extensions.EXT_texture_sRGB) { for (i = 0; i < ARRAY_SIZE(s3tc_compatible_internal_formats); i++) { - if (s3tc_compatible_internal_formats[i].internal_format == internalformat) + if (s3tc_compatible_internal_formats[i].internal_format + == internalformat) return s3tc_compatible_internal_formats[i].view_class; } } @@ -226,7 +228,8 @@ initialize_texture_fields(struct gl_context *ctx, 0, internalFormat, texFormat); } - _mesa_next_mipmap_level_size(target, 0, levelWidth, levelHeight, levelDepth, + _mesa_next_mipmap_level_size(target, 0, + levelWidth, levelHeight, levelDepth, &levelWidth, &levelHeight, &levelDepth); } @@ -320,8 +323,8 @@ target_valid(struct gl_context *ctx, GLenum origTarget, GLenum newTarget) * If an error is found, record it with _mesa_error() * \return false if any error, true otherwise. */ -GLboolean -_mesa_texture_view_compatible_format(struct gl_context *ctx, +bool +_mesa_texture_view_compatible_format(const struct gl_context *ctx, GLenum origInternalFormat, GLenum newInternalFormat) { @@ -334,15 +337,16 @@ _mesa_texture_view_compatible_format(struct gl_context *ctx, * or an INVALID_OPERATION error is generated. */ if (origInternalFormat == newInternalFormat) - return GL_TRUE; + return true; origViewClass = lookup_view_class(ctx, origInternalFormat); newViewClass = lookup_view_class(ctx, newInternalFormat); if ((origViewClass == newViewClass) && origViewClass != false) - return GL_TRUE; + return true; - return GL_FALSE; + return false; } + /** * Helper function for TexStorage and teximagemultisample to set immutable * texture state needed by ARB_texture_view. @@ -357,17 +361,19 @@ _mesa_set_texture_view_state(struct gl_context *ctx, /* Get a reference to what will become this View's base level */ texImage = _mesa_select_tex_image(texObj, target, 0); - /* When an immutable texture is created via glTexStorage or glTexImageMultisample, + /* When an immutable texture is created via glTexStorage or + * glTexImageMultisample, * TEXTURE_IMMUTABLE_FORMAT becomes TRUE. * TEXTURE_IMMUTABLE_LEVELS and TEXTURE_VIEW_NUM_LEVELS become levels. * If the texture target is TEXTURE_1D_ARRAY then * TEXTURE_VIEW_NUM_LAYERS becomes height. * If the texture target is TEXTURE_2D_ARRAY, TEXTURE_CUBE_MAP_ARRAY, - * or TEXTURE_2D_MULTISAMPLE_ARRAY then TEXTURE_VIEW_NUM_LAYERS becomes depth. + * or TEXTURE_2D_MULTISAMPLE_ARRAY then TEXTURE_VIEW_NUM_LAYERS becomes + * depth. * If the texture target is TEXTURE_CUBE_MAP, then * TEXTURE_VIEW_NUM_LAYERS becomes 6. * For any other texture target, TEXTURE_VIEW_NUM_LAYERS becomes 1. - * + * * ARB_texture_multisample: Multisample textures do * not have multiple image levels. */ @@ -401,7 +407,6 @@ _mesa_set_texture_view_state(struct gl_context *ctx, case GL_TEXTURE_CUBE_MAP: texObj->NumLayers = 6; break; - } } @@ -435,16 +440,20 @@ _mesa_TextureView(GLuint texture, GLenum target, GLuint origtexture, minlevel, numlevels, minlayer, numlayers); if (origtexture == 0) { - _mesa_error(ctx, GL_INVALID_VALUE, "glTextureView(origtexture = %u)", origtexture); + _mesa_error(ctx, GL_INVALID_VALUE, "glTextureView(origtexture = %u)", + origtexture); return; } /* Need original texture information to validate arguments */ origTexObj = _mesa_lookup_texture(ctx, origtexture); - /* If <origtexture> is not the name of a texture, INVALID_VALUE is generated. */ + /* If <origtexture> is not the name of a texture, INVALID_VALUE + * is generated. + */ if (!origTexObj) { - _mesa_error(ctx, GL_INVALID_VALUE, "glTextureView(origtexture = %u)", origtexture); + _mesa_error(ctx, GL_INVALID_VALUE, "glTextureView(origtexture = %u)", + origtexture); return; } @@ -452,7 +461,8 @@ _mesa_TextureView(GLuint texture, GLenum target, GLuint origtexture, * INVALID_OPERATION is generated. */ if (!origTexObj->Immutable) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glTextureView(origtexture not immutable)"); + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTextureView(origtexture not immutable)"); return; } @@ -467,7 +477,8 @@ _mesa_TextureView(GLuint texture, GLenum target, GLuint origtexture, */ texObj = _mesa_lookup_texture(ctx, texture); if (texObj == NULL) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glTextureView(texture = %u non-gen name)", texture); + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTextureView(texture = %u non-gen name)", texture); return; } @@ -475,7 +486,8 @@ _mesa_TextureView(GLuint texture, GLenum target, GLuint origtexture, * the error INVALID_OPERATION is generated. */ if (texObj->Target) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glTextureView(texture = %u already bound)", texture); + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTextureView(texture = %u already bound)", texture); return; } @@ -484,33 +496,35 @@ _mesa_TextureView(GLuint texture, GLenum target, GLuint origtexture, return; /* error was recorded */ } - /* minlevel and minlayer are relative to the view of origtexture + /* minlevel and minlayer are relative to the view of origtexture. * If minlevel or minlayer is greater than level or layer, respectively, - * of origtexture return INVALID_VALUE. + * return INVALID_VALUE. */ newViewMinLevel = origTexObj->MinLevel + minlevel; newViewMinLayer = origTexObj->MinLayer + minlayer; if (newViewMinLevel >= (origTexObj->MinLevel + origTexObj->NumLevels)) { _mesa_error(ctx, GL_INVALID_VALUE, - "glTextureView(new minlevel (%d) > orig minlevel (%d) + orig numlevels (%d))", + "glTextureView(new minlevel (%d) > orig minlevel (%d)" + " + orig numlevels (%d))", newViewMinLevel, origTexObj->MinLevel, origTexObj->NumLevels); return; } if (newViewMinLayer >= (origTexObj->MinLayer + origTexObj->NumLayers)) { _mesa_error(ctx, GL_INVALID_VALUE, - "glTextureView(new minlayer (%d) > orig minlayer (%d) + orig numlayers (%d))", + "glTextureView(new minlayer (%d) > orig minlayer (%d)" + " + orig numlayers (%d))", newViewMinLayer, origTexObj->MinLayer, origTexObj->NumLayers); return; } if (!_mesa_texture_view_compatible_format(ctx, - origTexObj->Image[0][0]->InternalFormat, - internalformat)) { + origTexObj->Image[0][0]->InternalFormat, + internalformat)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glTextureView(internalformat %s not compatible with origtexture %s)", - _mesa_lookup_enum_by_nr(internalformat), - _mesa_lookup_enum_by_nr(origTexObj->Image[0][0]->InternalFormat)); + "glTextureView(internalformat %s not compatible with origtexture %s)", + _mesa_lookup_enum_by_nr(internalformat), + _mesa_lookup_enum_by_nr(origTexObj->Image[0][0]->InternalFormat)); return; } @@ -569,14 +583,16 @@ _mesa_TextureView(GLuint texture, GLenum target, GLuint origtexture, dimensionsOK = _mesa_legal_texture_dimensions(ctx, target, 0, width, height, depth, 0); if (!dimensionsOK) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glTextureView(invalid width or height or depth)"); + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTextureView(invalid width or height or depth)"); return; } sizeOK = ctx->Driver.TestProxyTexImage(ctx, target, 0, texFormat, width, height, depth, 0); if (!sizeOK) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glTextureView(invalid texture size)"); + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTextureView(invalid texture size)"); return; } @@ -591,17 +607,19 @@ _mesa_TextureView(GLuint texture, GLenum target, GLuint origtexture, case GL_TEXTURE_RECTANGLE: case GL_TEXTURE_2D_MULTISAMPLE: if (numlayers != 1) { - _mesa_error(ctx, GL_INVALID_VALUE, "glTextureView(numlayers %d != 1)", numlayers); + _mesa_error(ctx, GL_INVALID_VALUE, "glTextureView(numlayers %d != 1)", + numlayers); return; } break; case GL_TEXTURE_CUBE_MAP: - /* If the new texture's target is TEXTURE_CUBE_MAP, the clamped <numlayers> - * must be equal to 6. + /* If the new texture's target is TEXTURE_CUBE_MAP, the clamped + * <numlayers> must be equal to 6. */ if (newViewNumLayers != 6) { - _mesa_error(ctx, GL_INVALID_VALUE, "glTextureView(clamped numlayers %d != 6)", + _mesa_error(ctx, GL_INVALID_VALUE, + "glTextureView(clamped numlayers %d != 6)", newViewNumLayers); return; } @@ -615,7 +633,8 @@ _mesa_TextureView(GLuint texture, GLenum target, GLuint origtexture, */ if ((newViewNumLayers % 6) != 0) { _mesa_error(ctx, GL_INVALID_VALUE, - "glTextureView(clamped numlayers %d is not a multiple of 6)", + "glTextureView(clamped numlayers %d is not" + " a multiple of 6)", newViewNumLayers); return; } @@ -628,7 +647,8 @@ _mesa_TextureView(GLuint texture, GLenum target, GLuint origtexture, */ if ((target == GL_TEXTURE_CUBE_MAP || target == GL_TEXTURE_CUBE_MAP_ARRAY) && (origTexImage->Width != origTexImage->Height)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glTextureView(origtexture width (%d) != height (%d))", + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTextureView(origtexture width (%d) != height (%d))", origTexImage->Width, origTexImage->Height); return; } @@ -662,7 +682,8 @@ _mesa_TextureView(GLuint texture, GLenum target, GLuint origtexture, texObj->ImmutableLevels = origTexObj->ImmutableLevels; texObj->Target = target; - if (ctx->Driver.TextureView != NULL && !ctx->Driver.TextureView(ctx, texObj, origTexObj)) { + if (ctx->Driver.TextureView != NULL && + !ctx->Driver.TextureView(ctx, texObj, origTexObj)) { return; /* driver recorded error */ } } diff --git a/src/mesa/main/textureview.h b/src/mesa/main/textureview.h index 549a13cd809..59e24b68dd0 100644 --- a/src/mesa/main/textureview.h +++ b/src/mesa/main/textureview.h @@ -29,8 +29,8 @@ #ifndef TEXTUREVIEW_H #define TEXTUREVIEW_H -GLboolean -_mesa_texture_view_compatible_format(struct gl_context *ctx, +bool +_mesa_texture_view_compatible_format(const struct gl_context *ctx, GLenum origInternalFormat, GLenum newInternalFormat); @@ -41,7 +41,8 @@ _mesa_TextureView(GLuint texture, GLenum target, GLuint origtexture, GLuint minlayer, GLuint numlayers); extern void -_mesa_set_texture_view_state(struct gl_context *ctx, struct gl_texture_object *texObj, - GLenum target, GLuint levels); +_mesa_set_texture_view_state(struct gl_context *ctx, + struct gl_texture_object *texObj, + GLenum target, GLuint levels); #endif /* TEXTUREVIEW_H */ diff --git a/src/mesa/main/uniform_query.cpp b/src/mesa/main/uniform_query.cpp index 728bd1bac10..cab5083e81b 100644 --- a/src/mesa/main/uniform_query.cpp +++ b/src/mesa/main/uniform_query.cpp @@ -237,6 +237,13 @@ validate_uniform_parameters(struct gl_context *ctx, struct gl_uniform_storage *const uni = shProg->UniformRemapTable[location]; + /* Even though no location is assigned to a built-in uniform and this + * function should already have returned NULL, this test makes it explicit + * that we are not allowing to update the value of a built-in. + */ + if (uni->builtin) + return NULL; + if (uni->array_elements == 0) { if (count > 1) { _mesa_error(ctx, GL_INVALID_OPERATION, @@ -1028,6 +1035,10 @@ _mesa_get_uniform_location(struct gl_shader_program *shProg, if (!found) return GL_INVALID_INDEX; + /* If the uniform is built-in, fail. */ + if (shProg->UniformStorage[location].builtin) + return GL_INVALID_INDEX; + /* If the uniform is an array, fail if the index is out of bounds. * (A negative index is caught above.) This also fails if the uniform * is not an array, but the user is trying to index it, because @@ -1047,7 +1058,7 @@ _mesa_sampler_uniforms_are_valid(const struct gl_shader_program *shProg, char *errMsg, size_t errMsgLength) { /* Shader does not have samplers. */ - if (shProg->NumUserUniformStorage == 0) + if (shProg->NumUniformStorage == 0) return true; if (!shProg->SamplersValidated) { @@ -1087,7 +1098,7 @@ _mesa_sampler_uniforms_pipeline_are_valid(struct gl_pipeline_object *pipeline) if (!shProg[idx]) continue; - for (unsigned i = 0; i < shProg[idx]->NumUserUniformStorage; i++) { + for (unsigned i = 0; i < shProg[idx]->NumUniformStorage; i++) { const struct gl_uniform_storage *const storage = &shProg[idx]->UniformStorage[i]; const glsl_type *const t = (storage->type->is_array()) diff --git a/src/mesa/main/uniforms.h b/src/mesa/main/uniforms.h index 55fa2357e38..bd7b05e207a 100644 --- a/src/mesa/main/uniforms.h +++ b/src/mesa/main/uniforms.h @@ -343,10 +343,6 @@ void GLAPIENTRY _mesa_ProgramUniformMatrix4x3dv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -long -_mesa_parse_program_resource_name(const GLchar *name, - const GLchar **out_base_name_end); - unsigned _mesa_get_uniform_location(struct gl_shader_program *shProg, const GLchar *name, unsigned *offset); diff --git a/src/mesa/main/varray.c b/src/mesa/main/varray.c index 7389037ae85..ebdd9eaf02e 100644 --- a/src/mesa/main/varray.c +++ b/src/mesa/main/varray.c @@ -2309,10 +2309,10 @@ print_array(const char *name, GLint index, const struct gl_client_array *array) fprintf(stderr, " %s[%d]: ", name, index); else fprintf(stderr, " %s: ", name); - fprintf(stderr, "Ptr=%p, Type=0x%x, Size=%d, ElemSize=%u, Stride=%d, Buffer=%u(Size %lu)\n", - array->Ptr, array->Type, array->Size, - array->_ElementSize, array->StrideB, - array->BufferObj->Name, (unsigned long) array->BufferObj->Size); + fprintf(stderr, "Ptr=%p, Type=%s, Size=%d, ElemSize=%u, Stride=%d, Buffer=%u(Size %lu)\n", + array->Ptr, _mesa_lookup_enum_by_nr(array->Type), array->Size, + array->_ElementSize, array->StrideB, array->BufferObj->Name, + (unsigned long) array->BufferObj->Size); } diff --git a/src/mesa/main/version.c b/src/mesa/main/version.c index 699a0de46c2..8bc00ace5c4 100644 --- a/src/mesa/main/version.c +++ b/src/mesa/main/version.c @@ -51,31 +51,51 @@ check_for_ending(const char *string, const char *ending) * fwd_context is only valid if version > 0 */ static void -get_gl_override(int *version, bool *fwd_context, bool *compat_context) +get_gl_override(gl_api api, int *version, bool *fwd_context, + bool *compat_context) { - const char *env_var = "MESA_GL_VERSION_OVERRIDE"; + const char *env_var = (api == API_OPENGL_CORE || api == API_OPENGL_COMPAT) + ? "MESA_GL_VERSION_OVERRIDE" : "MESA_GLES_VERSION_OVERRIDE"; const char *version_str; int major, minor, n; - static int override_version = -1; - static bool fc_suffix = false; - static bool compat_suffix = false; + static struct override_info { + int version; + bool fc_suffix; + bool compat_suffix; + } override[] = { + { -1, false, false}, + { -1, false, false}, + { -1, false, false}, + { -1, false, false}, + }; - if (override_version < 0) { - override_version = 0; + STATIC_ASSERT(ARRAY_SIZE(override) == API_OPENGL_LAST + 1); + + if (api == API_OPENGLES) + goto exit; + + if (override[api].version < 0) { + override[api].version = 0; version_str = getenv(env_var); if (version_str) { - fc_suffix = check_for_ending(version_str, "FC"); - compat_suffix = check_for_ending(version_str, "COMPAT"); + override[api].fc_suffix = check_for_ending(version_str, "FC"); + override[api].compat_suffix = check_for_ending(version_str, "COMPAT"); n = sscanf(version_str, "%u.%u", &major, &minor); if (n != 2) { fprintf(stderr, "error: invalid value for %s: %s\n", env_var, version_str); - override_version = 0; + override[api].version = 0; } else { - override_version = major * 10 + minor; - if (override_version < 30 && fc_suffix) { + override[api].version = major * 10 + minor; + + /* There is no such thing as compatibility or forward-compatible for + * OpenGL ES 2.0 or 3.x APIs. + */ + if ((override[api].version < 30 && override[api].fc_suffix) || + (api == API_OPENGLES2 && (override[api].fc_suffix || + override[api].compat_suffix))) { fprintf(stderr, "error: invalid value for %s: %s\n", env_var, version_str); } @@ -83,9 +103,10 @@ get_gl_override(int *version, bool *fwd_context, bool *compat_context) } } - *version = override_version; - *fwd_context = fc_suffix; - *compat_context = compat_suffix; +exit: + *version = override[api].version; + *fwd_context = override[api].fc_suffix; + *compat_context = override[api].compat_suffix; } /** @@ -130,18 +151,26 @@ _mesa_override_gl_version_contextless(struct gl_constants *consts, int version; bool fwd_context, compat_context; - get_gl_override(&version, &fwd_context, &compat_context); + get_gl_override(*apiOut, &version, &fwd_context, &compat_context); if (version > 0) { *versionOut = version; - if (version >= 30 && fwd_context) { - *apiOut = API_OPENGL_CORE; - consts->ContextFlags |= GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT; - } else if (version >= 31 && !compat_context) { - *apiOut = API_OPENGL_CORE; - } else { - *apiOut = API_OPENGL_COMPAT; + + /* If the API is a desktop API, adjust the context flags. We may also + * need to modify the API depending on the version. For example, Mesa + * does not support a GL 3.3 compatibility profile. + */ + if (*apiOut == API_OPENGL_CORE || *apiOut == API_OPENGL_COMPAT) { + if (version >= 30 && fwd_context) { + *apiOut = API_OPENGL_CORE; + consts->ContextFlags |= GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT; + } else if (version >= 31 && !compat_context) { + *apiOut = API_OPENGL_CORE; + } else { + *apiOut = API_OPENGL_COMPAT; + } } + return true; } return false; @@ -157,22 +186,6 @@ _mesa_override_gl_version(struct gl_context *ctx) } /** - * Returns the gl override value - * - * version > 0 indicates there is an override requested - */ -int -_mesa_get_gl_version_override(void) -{ - int version; - bool fwd_context, compat_context; - - get_gl_override(&version, &fwd_context, &compat_context); - - return version; -} - -/** * Override the context's GLSL version if the environment variable * MESA_GLSL_VERSION_OVERRIDE is set. Valid values for * MESA_GLSL_VERSION_OVERRIDE are integers, such as "130". @@ -433,7 +446,23 @@ compute_version_es2(const struct gl_extensions *extensions) extensions->EXT_texture_snorm && extensions->NV_primitive_restart && extensions->OES_depth_texture_cube_map); - if (ver_3_0) { + const bool ver_3_1 = (ver_3_0 && + extensions->ARB_arrays_of_arrays && + extensions->ARB_compute_shader && + extensions->ARB_draw_indirect && + false /*extensions->ARB_framebuffer_no_attachments*/ && + extensions->ARB_shader_atomic_counters && + extensions->ARB_shader_image_load_store && + false /*extensions->ARB_shader_image_size*/ && + false /*extensions->ARB_shader_storage_buffer_object*/ && + extensions->ARB_shading_language_packing && + extensions->ARB_stencil_texturing && + extensions->ARB_gpu_shader5 && + extensions->EXT_shader_integer_mix); + + if (ver_3_1) { + return 31; + } else if (ver_3_0) { return 30; } else if (ver_2_0) { return 20; diff --git a/src/mesa/main/version.h b/src/mesa/main/version.h index 450a0e31d3d..ee7cb7501eb 100644 --- a/src/mesa/main/version.h +++ b/src/mesa/main/version.h @@ -47,7 +47,4 @@ _mesa_override_gl_version(struct gl_context *ctx); extern void _mesa_override_glsl_version(struct gl_constants *consts); -extern int -_mesa_get_gl_version_override(void); - #endif /* VERSION_H */ diff --git a/src/mesa/main/vtxfmt.c b/src/mesa/main/vtxfmt.c index d7ef7e278cd..81bf4c589ea 100644 --- a/src/mesa/main/vtxfmt.c +++ b/src/mesa/main/vtxfmt.c @@ -207,7 +207,7 @@ install_vtxfmt(struct gl_context *ctx, struct _glapi_table *tab, SET_VertexAttribP4uiv(tab, vfmt->VertexAttribP4uiv); } - if (_mesa_is_desktop_gl(ctx)) { + if (ctx->API == API_OPENGL_CORE) { SET_VertexAttribL1d(tab, vfmt->VertexAttribL1d); SET_VertexAttribL2d(tab, vfmt->VertexAttribL2d); SET_VertexAttribL3d(tab, vfmt->VertexAttribL3d); |