diff options
author | Jason Ekstrand <[email protected]> | 2015-08-14 17:25:04 -0700 |
---|---|---|
committer | Jason Ekstrand <[email protected]> | 2015-08-17 11:25:03 -0700 |
commit | 6a7ca4ef2cd3f39d3b5e77051cb3f3175e9e60df (patch) | |
tree | d5413781ac9e9ecfc22cf403fa7465d6a7cadb34 /src/mesa/main | |
parent | b4c02253c4e1a7bc5a7a6369045210932f5de605 (diff) | |
parent | d3e23f1ff915c01541f8df375b50b93b3da565a8 (diff) |
Merge remote-tracking branch 'mesa-public/master' into vulkan
Diffstat (limited to 'src/mesa/main')
92 files changed, 3872 insertions, 1561 deletions
diff --git a/src/mesa/main/api_validate.c b/src/mesa/main/api_validate.c index 9c2e29e6472..53c8fb893b5 100644 --- a/src/mesa/main/api_validate.c +++ b/src/mesa/main/api_validate.c @@ -69,6 +69,25 @@ check_valid_to_render(struct gl_context *ctx, const char *function) return false; } + /* The spec argues that this is allowed because a tess ctrl shader + * without a tess eval shader can be used with transform feedback. + * However, glBeginTransformFeedback doesn't allow GL_PATCHES and + * therefore doesn't allow tessellation. + * + * Further investigation showed that this is indeed a spec bug and + * a tess ctrl shader without a tess eval shader shouldn't have been + * allowed, because there is no API in GL 4.0 that can make use this + * to produce something useful. + * + * Also, all vendors except one don't support a tess ctrl shader without + * a tess eval shader anyway. + */ + if (ctx->TessCtrlProgram._Current && !ctx->TessEvalProgram._Current) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(tess eval shader is missing)", function); + return false; + } + /* Section 7.3 (Program Objects) of the OpenGL 4.5 Core Profile spec * says: * @@ -127,6 +146,9 @@ _mesa_is_valid_prim_mode(struct gl_context *ctx, GLenum mode) if (mode <= GL_TRIANGLE_STRIP_ADJACENCY) return _mesa_has_geometry_shaders(ctx); + if (mode == GL_PATCHES) + return _mesa_has_tessellation(ctx); + return false; } @@ -136,6 +158,7 @@ _mesa_is_valid_prim_mode(struct gl_context *ctx, GLenum mode) * etc? Also, do additional checking related to transformation feedback. * Note: this function cannot be called during glNewList(GL_COMPILE) because * this code depends on current transform feedback state. + * Also, do additional checking related to tessellation shaders. */ GLboolean _mesa_valid_prim_mode(struct gl_context *ctx, GLenum mode, const char *name) @@ -170,11 +193,29 @@ _mesa_valid_prim_mode(struct gl_context *ctx, GLenum mode, const char *name) * TRIANGLES_ADJACENCY_ARB and <mode> is not * TRIANGLES_ADJACENCY_ARB or TRIANGLE_STRIP_ADJACENCY_ARB. * + * The GL spec doesn't mention any interaction with tessellation, which + * is clearly a spec bug. The same rule should apply, but instead of + * the draw primitive mode, the tessellation evaluation shader primitive + * mode should be used for the checking. */ if (ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY]) { const GLenum geom_mode = ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY]->Geom.InputType; - switch (mode) { + struct gl_shader_program *tes = + ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_EVAL]; + GLenum mode_before_gs = mode; + + if (tes) { + if (tes->TessEval.PointMode) + mode_before_gs = GL_POINTS; + else if (tes->TessEval.PrimitiveMode == GL_ISOLINES) + mode_before_gs = GL_LINES; + else + /* the GL_QUADS mode generates triangles too */ + mode_before_gs = GL_TRIANGLES; + } + + switch (mode_before_gs) { case GL_POINTS: valid_enum = (geom_mode == GL_POINTS); break; @@ -209,12 +250,42 @@ _mesa_valid_prim_mode(struct gl_context *ctx, GLenum mode, const char *name) _mesa_error(ctx, GL_INVALID_OPERATION, "%s(mode=%s vs geometry shader input %s)", name, - _mesa_lookup_prim_by_nr(mode), + _mesa_lookup_prim_by_nr(mode_before_gs), _mesa_lookup_prim_by_nr(geom_mode)); return GL_FALSE; } } + /* From the OpenGL 4.0 (Core Profile) spec (section 2.12): + * + * "Tessellation operates only on patch primitives. If tessellation is + * active, any command that transfers vertices to the GL will + * generate an INVALID_OPERATION error if the primitive mode is not + * PATCHES. + * Patch primitives are not supported by pipeline stages below the + * tessellation evaluation shader. If there is no active program + * object or the active program object does not contain a tessellation + * evaluation shader, the error INVALID_OPERATION is generated by any + * command that transfers vertices to the GL if the primitive mode is + * PATCHES." + * + */ + if (ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_EVAL] || + ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_CTRL]) { + if (mode != GL_PATCHES) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "only GL_PATCHES valid with tessellation"); + return GL_FALSE; + } + } + else { + if (mode == GL_PATCHES) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "GL_PATCHES only valid with tessellation"); + return GL_FALSE; + } + } + /* From the GL_EXT_transform_feedback spec: * * "The error INVALID_OPERATION is generated if Begin, or any command @@ -247,6 +318,17 @@ _mesa_valid_prim_mode(struct gl_context *ctx, GLenum mode, const char *name) pass = GL_FALSE; } } + else if (ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_EVAL]) { + struct gl_shader_program *tes = + ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_EVAL]; + + if (tes->TessEval.PointMode) + pass = ctx->TransformFeedback.Mode == GL_POINTS; + else if (tes->TessEval.PrimitiveMode == GL_ISOLINES) + pass = ctx->TransformFeedback.Mode == GL_LINES; + else + pass = ctx->TransformFeedback.Mode == GL_TRIANGLES; + } else { switch (mode) { case GL_POINTS: @@ -291,7 +373,7 @@ valid_elements_type(struct gl_context *ctx, GLenum type, const char *name) default: _mesa_error(ctx, GL_INVALID_ENUM, "%s(type = %s)", name, - _mesa_lookup_enum_by_nr(type)); + _mesa_enum_to_string(type)); return false; } } diff --git a/src/mesa/main/atifragshader.c b/src/mesa/main/atifragshader.c index 9fc35520a38..935ba05b7cc 100644 --- a/src/mesa/main/atifragshader.c +++ b/src/mesa/main/atifragshader.c @@ -132,21 +132,21 @@ static void debug_op(GLint optype, GLuint arg_count, GLenum op, GLuint dst, op_name = atifs_ops[(arg_count-1)+(optype?3:0)]; - fprintf(stderr, "%s(%s, %s", op_name, _mesa_lookup_enum_by_nr(op), - _mesa_lookup_enum_by_nr(dst)); + fprintf(stderr, "%s(%s, %s", op_name, _mesa_enum_to_string(op), + _mesa_enum_to_string(dst)); if (!optype) fprintf(stderr, ", %d", dstMask); fprintf(stderr, ", %s", create_dst_mod_str(dstMod)); - fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg1), - _mesa_lookup_enum_by_nr(arg1Rep), arg1Mod); + fprintf(stderr, ", %s, %s, %d", _mesa_enum_to_string(arg1), + _mesa_enum_to_string(arg1Rep), arg1Mod); if (arg_count>1) - fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg2), - _mesa_lookup_enum_by_nr(arg2Rep), arg2Mod); + fprintf(stderr, ", %s, %s, %d", _mesa_enum_to_string(arg2), + _mesa_enum_to_string(arg2Rep), arg2Mod); if (arg_count>2) - fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg3), - _mesa_lookup_enum_by_nr(arg3Rep), arg3Mod); + fprintf(stderr, ", %s, %s, %d", _mesa_enum_to_string(arg3), + _mesa_enum_to_string(arg3Rep), arg3Mod); fprintf(stderr,")\n"); @@ -383,7 +383,7 @@ _mesa_EndFragmentShaderATI(void) for (j = 0; j < MAX_NUM_PASSES_ATI; j++) { for (i = 0; i < MAX_NUM_FRAGMENT_REGISTERS_ATI; i++) { GLuint op = curProg->SetupInst[j][i].Opcode; - const char *op_enum = op > 5 ? _mesa_lookup_enum_by_nr(op) : "0"; + const char *op_enum = op > 5 ? _mesa_enum_to_string(op) : "0"; GLuint src = curProg->SetupInst[j][i].src; GLuint swizzle = curProg->SetupInst[j][i].swizzle; fprintf(stderr, "%2d %04X %s %d %04X\n", i, op, op_enum, src, @@ -392,8 +392,8 @@ _mesa_EndFragmentShaderATI(void) for (i = 0; i < curProg->numArithInstr[j]; i++) { GLuint op0 = curProg->Instructions[j][i].Opcode[0]; GLuint op1 = curProg->Instructions[j][i].Opcode[1]; - const char *op0_enum = op0 > 5 ? _mesa_lookup_enum_by_nr(op0) : "0"; - const char *op1_enum = op1 > 5 ? _mesa_lookup_enum_by_nr(op1) : "0"; + const char *op0_enum = op0 > 5 ? _mesa_enum_to_string(op0) : "0"; + const char *op1_enum = op1 > 5 ? _mesa_enum_to_string(op1) : "0"; GLuint count0 = curProg->Instructions[j][i].ArgCount[0]; GLuint count1 = curProg->Instructions[j][i].ArgCount[1]; fprintf(stderr, "%2d %04X %s %d %04X %s %d\n", i, op0, op0_enum, count0, @@ -477,8 +477,8 @@ _mesa_PassTexCoordATI(GLuint dst, GLuint coord, GLenum swizzle) #if MESA_DEBUG_ATI_FS _mesa_debug(ctx, "%s(%s, %s, %s)\n", __func__, - _mesa_lookup_enum_by_nr(dst), _mesa_lookup_enum_by_nr(coord), - _mesa_lookup_enum_by_nr(swizzle)); + _mesa_enum_to_string(dst), _mesa_enum_to_string(coord), + _mesa_enum_to_string(swizzle)); #endif } @@ -550,8 +550,8 @@ _mesa_SampleMapATI(GLuint dst, GLuint interp, GLenum swizzle) #if MESA_DEBUG_ATI_FS _mesa_debug(ctx, "%s(%s, %s, %s)\n", __func__, - _mesa_lookup_enum_by_nr(dst), _mesa_lookup_enum_by_nr(interp), - _mesa_lookup_enum_by_nr(swizzle)); + _mesa_enum_to_string(dst), _mesa_enum_to_string(interp), + _mesa_enum_to_string(swizzle)); #endif } diff --git a/src/mesa/main/attrib.c b/src/mesa/main/attrib.c index 53626e38be9..08f13178f84 100644 --- a/src/mesa/main/attrib.c +++ b/src/mesa/main/attrib.c @@ -937,7 +937,7 @@ _mesa_PopAttrib(void) if (MESA_VERBOSE & VERBOSE_API) { _mesa_debug(ctx, "glPopAttrib %s\n", - _mesa_lookup_enum_by_nr(attr->kind)); + _mesa_enum_to_string(attr->kind)); } switch (attr->kind) { diff --git a/src/mesa/main/blend.c b/src/mesa/main/blend.c index d869fa2aa09..4fc32962425 100644 --- a/src/mesa/main/blend.c +++ b/src/mesa/main/blend.c @@ -128,28 +128,28 @@ validate_blend_factors(struct gl_context *ctx, const char *func, if (!legal_src_factor(ctx, sfactorRGB)) { _mesa_error(ctx, GL_INVALID_ENUM, "%s(sfactorRGB = %s)", func, - _mesa_lookup_enum_by_nr(sfactorRGB)); + _mesa_enum_to_string(sfactorRGB)); return GL_FALSE; } if (!legal_dst_factor(ctx, dfactorRGB)) { _mesa_error(ctx, GL_INVALID_ENUM, "%s(dfactorRGB = %s)", func, - _mesa_lookup_enum_by_nr(dfactorRGB)); + _mesa_enum_to_string(dfactorRGB)); return GL_FALSE; } if (sfactorA != sfactorRGB && !legal_src_factor(ctx, sfactorA)) { _mesa_error(ctx, GL_INVALID_ENUM, "%s(sfactorA = %s)", func, - _mesa_lookup_enum_by_nr(sfactorA)); + _mesa_enum_to_string(sfactorA)); return GL_FALSE; } if (dfactorA != dfactorRGB && !legal_dst_factor(ctx, dfactorA)) { _mesa_error(ctx, GL_INVALID_ENUM, "%s(dfactorA = %s)", func, - _mesa_lookup_enum_by_nr(dfactorA)); + _mesa_enum_to_string(dfactorA)); return GL_FALSE; } @@ -208,10 +208,10 @@ _mesa_BlendFuncSeparate( GLenum sfactorRGB, GLenum dfactorRGB, if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glBlendFuncSeparate %s %s %s %s\n", - _mesa_lookup_enum_by_nr(sfactorRGB), - _mesa_lookup_enum_by_nr(dfactorRGB), - _mesa_lookup_enum_by_nr(sfactorA), - _mesa_lookup_enum_by_nr(dfactorA)); + _mesa_enum_to_string(sfactorRGB), + _mesa_enum_to_string(dfactorRGB), + _mesa_enum_to_string(sfactorA), + _mesa_enum_to_string(dfactorA)); if (!validate_blend_factors(ctx, "glBlendFuncSeparate", sfactorRGB, dfactorRGB, @@ -342,7 +342,7 @@ _mesa_BlendEquation( GLenum mode ) if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glBlendEquation(%s)\n", - _mesa_lookup_enum_by_nr(mode)); + _mesa_enum_to_string(mode)); if (!legal_blend_equation(ctx, mode)) { _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquation"); @@ -385,7 +385,7 @@ _mesa_BlendEquationiARB(GLuint buf, GLenum mode) if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glBlendEquationi(%u, %s)\n", - buf, _mesa_lookup_enum_by_nr(mode)); + buf, _mesa_enum_to_string(mode)); if (buf >= ctx->Const.MaxDrawBuffers) { _mesa_error(ctx, GL_INVALID_VALUE, "glBlendFuncSeparatei(buffer=%u)", @@ -421,8 +421,8 @@ _mesa_BlendEquationSeparate( GLenum modeRGB, GLenum modeA ) if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glBlendEquationSeparateEXT(%s %s)\n", - _mesa_lookup_enum_by_nr(modeRGB), - _mesa_lookup_enum_by_nr(modeA)); + _mesa_enum_to_string(modeRGB), + _mesa_enum_to_string(modeA)); if ( (modeRGB != modeA) && !ctx->Extensions.EXT_blend_equation_separate ) { _mesa_error(ctx, GL_INVALID_OPERATION, @@ -476,8 +476,8 @@ _mesa_BlendEquationSeparateiARB(GLuint buf, GLenum modeRGB, GLenum modeA) if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glBlendEquationSeparatei(%u, %s %s)\n", buf, - _mesa_lookup_enum_by_nr(modeRGB), - _mesa_lookup_enum_by_nr(modeA)); + _mesa_enum_to_string(modeRGB), + _mesa_enum_to_string(modeA)); if (buf >= ctx->Const.MaxDrawBuffers) { _mesa_error(ctx, GL_INVALID_VALUE, "glBlendEquationSeparatei(buffer=%u)", @@ -567,7 +567,10 @@ _mesa_AlphaFunc( GLenum func, GLclampf ref ) if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glAlphaFunc(%s, %f)\n", - _mesa_lookup_enum_by_nr(func), ref); + _mesa_enum_to_string(func), ref); + + if (ctx->Color.AlphaFunc == func && ctx->Color.AlphaRefUnclamped == ref) + return; /* no change */ switch (func) { case GL_NEVER: @@ -578,9 +581,6 @@ _mesa_AlphaFunc( GLenum func, GLclampf ref ) case GL_NOTEQUAL: case GL_GEQUAL: case GL_ALWAYS: - if (ctx->Color.AlphaFunc == func && ctx->Color.AlphaRefUnclamped == ref) - return; /* no change */ - FLUSH_VERTICES(ctx, _NEW_COLOR); ctx->Color.AlphaFunc = func; ctx->Color.AlphaRefUnclamped = ref; @@ -613,7 +613,7 @@ _mesa_LogicOp( GLenum opcode ) GET_CURRENT_CONTEXT(ctx); if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glLogicOp(%s)\n", _mesa_lookup_enum_by_nr(opcode)); + _mesa_debug(ctx, "glLogicOp(%s)\n", _mesa_enum_to_string(opcode)); switch (opcode) { case GL_CLEAR: @@ -790,7 +790,7 @@ _mesa_ClampColor(GLenum target, GLenum clamp) invalid_enum: _mesa_error(ctx, GL_INVALID_ENUM, "glClampColor(%s)", - _mesa_lookup_enum_by_nr(target)); + _mesa_enum_to_string(target)); } static GLboolean @@ -930,12 +930,10 @@ void _mesa_init_color( struct gl_context * ctx ) ctx->Color._ClampFragmentColor = GL_FALSE; ctx->Color.ClampReadColor = GL_FIXED_ONLY_ARB; - if (ctx->API == API_OPENGLES2) { - /* GLES 3 behaves as though GL_FRAMEBUFFER_SRGB is always enabled. */ - ctx->Color.sRGBEnabled = GL_TRUE; - } else { - ctx->Color.sRGBEnabled = GL_FALSE; - } + /* GLES 1/2/3 behaves as though GL_FRAMEBUFFER_SRGB is always enabled + * if EGL_KHR_gl_colorspace has been used to request sRGB. + */ + ctx->Color.sRGBEnabled = _mesa_is_gles(ctx); } /*@}*/ diff --git a/src/mesa/main/blit.c b/src/mesa/main/blit.c index db8fee5a414..a32f1a42aea 100644 --- a/src/mesa/main/blit.c +++ b/src/mesa/main/blit.c @@ -37,6 +37,7 @@ #include "framebuffer.h" #include "glformats.h" #include "mtypes.h" +#include "macros.h" #include "state.h" @@ -59,6 +60,31 @@ find_attachment(const struct gl_framebuffer *fb, /** + * \return true if two regions overlap, false otherwise + */ +bool +_mesa_regions_overlap(int srcX0, int srcY0, + int srcX1, int srcY1, + int dstX0, int dstY0, + int dstX1, int dstY1) +{ + if (MAX2(srcX0, srcX1) < MIN2(dstX0, dstX1)) + return false; /* dst completely right of src */ + + if (MAX2(dstX0, dstX1) < MIN2(srcX0, srcX1)) + return false; /* dst completely left of src */ + + if (MAX2(srcY0, srcY1) < MIN2(dstY0, dstY1)) + return false; /* dst completely above src */ + + if (MAX2(dstY0, dstY1) < MIN2(srcY0, srcY1)) + return false; /* dst completely below src */ + + return true; /* some overlap */ +} + + +/** * Helper function for checking if the datatypes of color buffers are * compatible for glBlitFramebuffer. From the 3.1 spec, page 198: * @@ -186,7 +212,7 @@ _mesa_blit_framebuffer(struct gl_context *ctx, if (!is_valid_blit_filter(ctx, filter)) { _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid filter %s)", func, - _mesa_lookup_enum_by_nr(filter)); + _mesa_enum_to_string(filter)); return; } @@ -194,7 +220,7 @@ _mesa_blit_framebuffer(struct gl_context *ctx, filter == GL_SCALED_RESOLVE_NICEST_EXT) && (readFb->Visual.samples == 0 || drawFb->Visual.samples > 0)) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(%s: invalid samples)", func, - _mesa_lookup_enum_by_nr(filter)); + _mesa_enum_to_string(filter)); return; } @@ -522,7 +548,7 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, " %d, %d, %d, %d, 0x%x, %s)\n", srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, - mask, _mesa_lookup_enum_by_nr(filter)); + mask, _mesa_enum_to_string(filter)); _mesa_blit_framebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer, srcX0, srcY0, srcX1, srcY1, @@ -547,7 +573,7 @@ _mesa_BlitNamedFramebuffer(GLuint readFramebuffer, GLuint drawFramebuffer, readFramebuffer, drawFramebuffer, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, - mask, _mesa_lookup_enum_by_nr(filter)); + mask, _mesa_enum_to_string(filter)); /* * According to PDF page 533 of the OpenGL 4.5 core spec (30.10.2014, diff --git a/src/mesa/main/blit.h b/src/mesa/main/blit.h index 54b946e3192..88dd4a9ec8d 100644 --- a/src/mesa/main/blit.h +++ b/src/mesa/main/blit.h @@ -28,6 +28,12 @@ #include "glheader.h" +extern bool +_mesa_regions_overlap(int srcX0, int srcY0, + int srcX1, int srcY1, + int dstX0, int dstY0, + int dstX1, int dstY1); + extern void _mesa_blit_framebuffer(struct gl_context *ctx, struct gl_framebuffer *readFb, diff --git a/src/mesa/main/bufferobj.c b/src/mesa/main/bufferobj.c index 66dee680258..1cdea937f91 100644 --- a/src/mesa/main/bufferobj.c +++ b/src/mesa/main/bufferobj.c @@ -91,8 +91,9 @@ get_buffer_target(struct gl_context *ctx, GLenum target) case GL_COPY_WRITE_BUFFER: return &ctx->CopyWriteBuffer; case GL_DRAW_INDIRECT_BUFFER: - if (ctx->API == API_OPENGL_CORE && - ctx->Extensions.ARB_draw_indirect) { + if ((ctx->API == API_OPENGL_CORE && + ctx->Extensions.ARB_draw_indirect) || + _mesa_is_gles31(ctx)) { return &ctx->DrawIndirectBuffer; } break; @@ -112,6 +113,11 @@ get_buffer_target(struct gl_context *ctx, GLenum target) return &ctx->UniformBuffer; } break; + case GL_SHADER_STORAGE_BUFFER: + if (ctx->Extensions.ARB_shader_storage_buffer_object) { + return &ctx->ShaderStorageBuffer; + } + break; case GL_ATOMIC_COUNTER_BUFFER: if (ctx->Extensions.ARB_shader_atomic_counters) { return &ctx->AtomicBuffer; @@ -831,6 +837,9 @@ _mesa_init_buffer_objects( struct gl_context *ctx ) _mesa_reference_buffer_object(ctx, &ctx->UniformBuffer, ctx->Shared->NullBufferObj); + _mesa_reference_buffer_object(ctx, &ctx->ShaderStorageBuffer, + ctx->Shared->NullBufferObj); + _mesa_reference_buffer_object(ctx, &ctx->AtomicBuffer, ctx->Shared->NullBufferObj); @@ -845,6 +854,14 @@ _mesa_init_buffer_objects( struct gl_context *ctx ) ctx->UniformBufferBindings[i].Size = -1; } + for (i = 0; i < MAX_COMBINED_SHADER_STORAGE_BUFFERS; i++) { + _mesa_reference_buffer_object(ctx, + &ctx->ShaderStorageBufferBindings[i].BufferObject, + ctx->Shared->NullBufferObj); + ctx->ShaderStorageBufferBindings[i].Offset = -1; + ctx->ShaderStorageBufferBindings[i].Size = -1; + } + for (i = 0; i < MAX_COMBINED_ATOMIC_BUFFERS; i++) { _mesa_reference_buffer_object(ctx, &ctx->AtomicBufferBindings[i].BufferObject, @@ -867,6 +884,8 @@ _mesa_free_buffer_objects( struct gl_context *ctx ) _mesa_reference_buffer_object(ctx, &ctx->UniformBuffer, NULL); + _mesa_reference_buffer_object(ctx, &ctx->ShaderStorageBuffer, NULL); + _mesa_reference_buffer_object(ctx, &ctx->AtomicBuffer, NULL); _mesa_reference_buffer_object(ctx, &ctx->DrawIndirectBuffer, NULL); @@ -877,6 +896,12 @@ _mesa_free_buffer_objects( struct gl_context *ctx ) NULL); } + for (i = 0; i < MAX_COMBINED_SHADER_STORAGE_BUFFERS; i++) { + _mesa_reference_buffer_object(ctx, + &ctx->ShaderStorageBufferBindings[i].BufferObject, + NULL); + } + for (i = 0; i < MAX_COMBINED_ATOMIC_BUFFERS; i++) { _mesa_reference_buffer_object(ctx, &ctx->AtomicBufferBindings[i].BufferObject, @@ -1158,7 +1183,7 @@ _mesa_BindBuffer(GLenum target, GLuint buffer) if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glBindBuffer(%s, %u)\n", - _mesa_lookup_enum_by_nr(target), buffer); + _mesa_enum_to_string(target), buffer); bind_buffer_object(ctx, target, buffer); } @@ -1240,6 +1265,17 @@ _mesa_DeleteBuffers(GLsizei n, const GLuint *ids) _mesa_BindBuffer( GL_UNIFORM_BUFFER, 0 ); } + /* unbind SSBO binding points */ + for (j = 0; j < ctx->Const.MaxShaderStorageBufferBindings; j++) { + if (ctx->ShaderStorageBufferBindings[j].BufferObject == bufObj) { + _mesa_BindBufferBase(GL_SHADER_STORAGE_BUFFER, j, 0); + } + } + + if (ctx->ShaderStorageBuffer == bufObj) { + _mesa_BindBuffer(GL_SHADER_STORAGE_BUFFER, 0); + } + /* unbind Atomci Buffer binding points */ for (j = 0; j < ctx->Const.MaxAtomicBufferBindings; j++) { if (ctx->AtomicBufferBindings[j].BufferObject == bufObj) { @@ -1500,9 +1536,9 @@ _mesa_buffer_data(struct gl_context *ctx, struct gl_buffer_object *bufObj, if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "%s(%s, %ld, %p, %s)\n", func, - _mesa_lookup_enum_by_nr(target), + _mesa_enum_to_string(target), (long int) size, data, - _mesa_lookup_enum_by_nr(usage)); + _mesa_enum_to_string(usage)); if (size < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "%s(size < 0)", func); @@ -1535,7 +1571,7 @@ _mesa_buffer_data(struct gl_context *ctx, struct gl_buffer_object *bufObj, if (!valid_usage) { _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid usage: %s)", func, - _mesa_lookup_enum_by_nr(usage)); + _mesa_enum_to_string(usage)); return; } @@ -1990,7 +2026,7 @@ get_buffer_parameter(struct gl_context *ctx, invalid_pname: _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid pname: %s)", func, - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); return false; } @@ -2337,7 +2373,7 @@ _mesa_map_buffer_range(struct gl_context *ctx, if (offset + length > bufObj->Size) { _mesa_error(ctx, GL_INVALID_VALUE, - "%s(offset %ld + length %ld > buffer_size %ld)", func, + "%s(offset %td + length %td > buffer_size %td)", func, offset, length, bufObj->Size); return NULL; } @@ -2999,6 +3035,33 @@ set_ubo_binding(struct gl_context *ctx, } /** + * Binds a buffer object to a shader storage buffer binding point. + * + * The caller is responsible for flushing vertices and updating + * NewDriverState. + */ +static void +set_ssbo_binding(struct gl_context *ctx, + struct gl_shader_storage_buffer_binding *binding, + struct gl_buffer_object *bufObj, + GLintptr offset, + GLsizeiptr size, + GLboolean autoSize) +{ + _mesa_reference_buffer_object(ctx, &binding->BufferObject, bufObj); + + binding->Offset = offset; + binding->Size = size; + binding->AutomaticSize = autoSize; + + /* If this is a real buffer object, mark it has having been used + * at some point as a SSBO. + */ + if (size >= 0) + bufObj->UsageHistory |= USAGE_SHADER_STORAGE_BUFFER; +} + +/** * Binds a buffer object to a uniform buffer binding point. * * Unlike set_ubo_binding(), this function also flushes vertices @@ -3030,6 +3093,37 @@ bind_uniform_buffer(struct gl_context *ctx, } /** + * Binds a buffer object to a shader storage buffer binding point. + * + * Unlike set_ssbo_binding(), this function also flushes vertices + * and updates NewDriverState. It also checks if the binding + * has actually changed before updating it. + */ +static void +bind_shader_storage_buffer(struct gl_context *ctx, + GLuint index, + struct gl_buffer_object *bufObj, + GLintptr offset, + GLsizeiptr size, + GLboolean autoSize) +{ + struct gl_shader_storage_buffer_binding *binding = + &ctx->ShaderStorageBufferBindings[index]; + + if (binding->BufferObject == bufObj && + binding->Offset == offset && + binding->Size == size && + binding->AutomaticSize == autoSize) { + return; + } + + FLUSH_VERTICES(ctx, 0); + ctx->NewDriverState |= ctx->DriverFlags.NewShaderStorageBuffer; + + set_ssbo_binding(ctx, binding, bufObj, offset, size, autoSize); +} + +/** * Bind a region of a buffer object to a uniform block binding point. * \param index the uniform buffer binding point index * \param bufObj the buffer object @@ -3064,6 +3158,40 @@ bind_buffer_range_uniform_buffer(struct gl_context *ctx, bind_uniform_buffer(ctx, index, bufObj, offset, size, GL_FALSE); } +/** + * Bind a region of a buffer object to a shader storage block binding point. + * \param index the shader storage buffer binding point index + * \param bufObj the buffer object + * \param offset offset to the start of buffer object region + * \param size size of the buffer object region + */ +static void +bind_buffer_range_shader_storage_buffer(struct gl_context *ctx, + GLuint index, + struct gl_buffer_object *bufObj, + GLintptr offset, + GLsizeiptr size) +{ + if (index >= ctx->Const.MaxShaderStorageBufferBindings) { + _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(index=%d)", index); + return; + } + + if (offset & (ctx->Const.ShaderStorageBufferOffsetAlignment - 1)) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glBindBufferRange(offset misaligned %d/%d)", (int) offset, + ctx->Const.ShaderStorageBufferOffsetAlignment); + return; + } + + if (bufObj == ctx->Shared->NullBufferObj) { + offset = -1; + size = -1; + } + + _mesa_reference_buffer_object(ctx, &ctx->ShaderStorageBuffer, bufObj); + bind_shader_storage_buffer(ctx, index, bufObj, offset, size, GL_FALSE); +} /** * Bind a buffer object to a uniform block binding point. @@ -3088,6 +3216,28 @@ bind_buffer_base_uniform_buffer(struct gl_context *ctx, } /** + * Bind a buffer object to a shader storage block binding point. + * As above, but offset = 0. + */ +static void +bind_buffer_base_shader_storage_buffer(struct gl_context *ctx, + GLuint index, + struct gl_buffer_object *bufObj) +{ + if (index >= ctx->Const.MaxShaderStorageBufferBindings) { + _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferBase(index=%d)", index); + return; + } + + _mesa_reference_buffer_object(ctx, &ctx->ShaderStorageBuffer, bufObj); + + if (bufObj == ctx->Shared->NullBufferObj) + bind_shader_storage_buffer(ctx, index, bufObj, -1, -1, GL_TRUE); + else + bind_shader_storage_buffer(ctx, index, bufObj, 0, 0, GL_TRUE); +} + +/** * Binds a buffer object to an atomic buffer binding point. * * The caller is responsible for validating the offset, @@ -3219,6 +3369,35 @@ error_check_bind_uniform_buffers(struct gl_context *ctx, return true; } +static bool +error_check_bind_shader_storage_buffers(struct gl_context *ctx, + GLuint first, GLsizei count, + const char *caller) +{ + if (!ctx->Extensions.ARB_shader_storage_buffer_object) { + _mesa_error(ctx, GL_INVALID_ENUM, + "%s(target=GL_SHADER_STORAGE_BUFFER)", caller); + return false; + } + + /* The ARB_multi_bind_spec says: + * + * "An INVALID_OPERATION error is generated if <first> + <count> is + * greater than the number of target-specific indexed binding points, + * as described in section 6.7.1." + */ + if (first + count > ctx->Const.MaxShaderStorageBufferBindings) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(first=%u + count=%d > the value of " + "GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS=%u)", + caller, first, count, + ctx->Const.MaxShaderStorageBufferBindings); + return false; + } + + return true; +} + /** * Unbind all uniform buffers in the range * <first> through <first>+<count>-1 @@ -3234,6 +3413,22 @@ unbind_uniform_buffers(struct gl_context *ctx, GLuint first, GLsizei count) bufObj, -1, -1, GL_TRUE); } +/** + * Unbind all shader storage buffers in the range + * <first> through <first>+<count>-1 + */ +static void +unbind_shader_storage_buffers(struct gl_context *ctx, GLuint first, + GLsizei count) +{ + struct gl_buffer_object *bufObj = ctx->Shared->NullBufferObj; + GLint i; + + for (i = 0; i < count; i++) + set_ssbo_binding(ctx, &ctx->ShaderStorageBufferBindings[first + i], + bufObj, -1, -1, GL_TRUE); +} + static void bind_uniform_buffers_base(struct gl_context *ctx, GLuint first, GLsizei count, const GLuint *buffers) @@ -3301,6 +3496,73 @@ bind_uniform_buffers_base(struct gl_context *ctx, GLuint first, GLsizei count, } static void +bind_shader_storage_buffers_base(struct gl_context *ctx, GLuint first, + GLsizei count, const GLuint *buffers) +{ + GLint i; + + if (!error_check_bind_shader_storage_buffers(ctx, first, count, + "glBindBuffersBase")) + return; + + /* Assume that at least one binding will be changed */ + FLUSH_VERTICES(ctx, 0); + ctx->NewDriverState |= ctx->DriverFlags.NewShaderStorageBuffer; + + if (!buffers) { + /* The ARB_multi_bind spec says: + * + * "If <buffers> is NULL, all bindings from <first> through + * <first>+<count>-1 are reset to their unbound (zero) state." + */ + unbind_shader_storage_buffers(ctx, first, count); + return; + } + + /* Note that the error semantics for multi-bind commands differ from + * those of other GL commands. + * + * The Issues section in the ARB_multi_bind spec says: + * + * "(11) Typically, OpenGL specifies that if an error is generated by a + * command, that command has no effect. This is somewhat + * unfortunate for multi-bind commands, because it would require a + * first pass to scan the entire list of bound objects for errors + * and then a second pass to actually perform the bindings. + * Should we have different error semantics? + * + * RESOLVED: Yes. In this specification, when the parameters for + * one of the <count> binding points are invalid, that binding point + * is not updated and an error will be generated. However, other + * binding points in the same command will be updated if their + * parameters are valid and no other error occurs." + */ + + _mesa_begin_bufferobj_lookups(ctx); + + for (i = 0; i < count; i++) { + struct gl_shader_storage_buffer_binding *binding = + &ctx->ShaderStorageBufferBindings[first + i]; + struct gl_buffer_object *bufObj; + + if (binding->BufferObject && binding->BufferObject->Name == buffers[i]) + bufObj = binding->BufferObject; + else + bufObj = _mesa_multi_bind_lookup_bufferobj(ctx, buffers, i, + "glBindBuffersBase"); + + if (bufObj) { + if (bufObj == ctx->Shared->NullBufferObj) + set_ssbo_binding(ctx, binding, bufObj, -1, -1, GL_TRUE); + else + set_ssbo_binding(ctx, binding, bufObj, 0, 0, GL_TRUE); + } + } + + _mesa_end_bufferobj_lookups(ctx); +} + +static void bind_uniform_buffers_range(struct gl_context *ctx, GLuint first, GLsizei count, const GLuint *buffers, const GLintptr *offsets, const GLsizeiptr *sizes) @@ -3405,6 +3667,112 @@ bind_uniform_buffers_range(struct gl_context *ctx, GLuint first, GLsizei count, _mesa_end_bufferobj_lookups(ctx); } +static void +bind_shader_storage_buffers_range(struct gl_context *ctx, GLuint first, + GLsizei count, const GLuint *buffers, + const GLintptr *offsets, + const GLsizeiptr *sizes) +{ + GLint i; + + if (!error_check_bind_shader_storage_buffers(ctx, first, count, + "glBindBuffersRange")) + return; + + /* Assume that at least one binding will be changed */ + FLUSH_VERTICES(ctx, 0); + ctx->NewDriverState |= ctx->DriverFlags.NewShaderStorageBuffer; + + if (!buffers) { + /* The ARB_multi_bind spec says: + * + * "If <buffers> is NULL, all bindings from <first> through + * <first>+<count>-1 are reset to their unbound (zero) state. + * In this case, the offsets and sizes associated with the + * binding points are set to default values, ignoring + * <offsets> and <sizes>." + */ + unbind_shader_storage_buffers(ctx, first, count); + return; + } + + /* Note that the error semantics for multi-bind commands differ from + * those of other GL commands. + * + * The Issues section in the ARB_multi_bind spec says: + * + * "(11) Typically, OpenGL specifies that if an error is generated by a + * command, that command has no effect. This is somewhat + * unfortunate for multi-bind commands, because it would require a + * first pass to scan the entire list of bound objects for errors + * and then a second pass to actually perform the bindings. + * Should we have different error semantics? + * + * RESOLVED: Yes. In this specification, when the parameters for + * one of the <count> binding points are invalid, that binding point + * is not updated and an error will be generated. However, other + * binding points in the same command will be updated if their + * parameters are valid and no other error occurs." + */ + + _mesa_begin_bufferobj_lookups(ctx); + + for (i = 0; i < count; i++) { + struct gl_shader_storage_buffer_binding *binding = + &ctx->ShaderStorageBufferBindings[first + i]; + struct gl_buffer_object *bufObj; + + if (!bind_buffers_check_offset_and_size(ctx, i, offsets, sizes)) + continue; + + /* The ARB_multi_bind spec says: + * + * "An INVALID_VALUE error is generated by BindBuffersRange if any + * pair of values in <offsets> and <sizes> does not respectively + * satisfy the constraints described for those parameters for the + * specified target, as described in section 6.7.1 (per binding)." + * + * Section 6.7.1 refers to table 6.5, which says: + * + * "┌───────────────────────────────────────────────────────────────┐ + * │ Shader storage buffer array bindings (see sec. 7.8) │ + * ├─────────────────────┬─────────────────────────────────────────┤ + * │ ... │ ... │ + * │ offset restriction │ multiple of value of SHADER_STORAGE_- │ + * │ │ BUFFER_OFFSET_ALIGNMENT │ + * │ ... │ ... │ + * │ size restriction │ none │ + * └─────────────────────┴─────────────────────────────────────────┘" + */ + if (offsets[i] & (ctx->Const.ShaderStorageBufferOffsetAlignment - 1)) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glBindBuffersRange(offsets[%u]=%" PRId64 + " is misaligned; it must be a multiple of the value of " + "GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT=%u when " + "target=GL_SHADER_STORAGE_BUFFER)", + i, (int64_t) offsets[i], + ctx->Const.ShaderStorageBufferOffsetAlignment); + continue; + } + + if (binding->BufferObject && binding->BufferObject->Name == buffers[i]) + bufObj = binding->BufferObject; + else + bufObj = _mesa_multi_bind_lookup_bufferobj(ctx, buffers, i, + "glBindBuffersRange"); + + if (bufObj) { + if (bufObj == ctx->Shared->NullBufferObj) + set_ssbo_binding(ctx, binding, bufObj, -1, -1, GL_FALSE); + else + set_ssbo_binding(ctx, binding, bufObj, + offsets[i], sizes[i], GL_FALSE); + } + } + + _mesa_end_bufferobj_lookups(ctx); +} + static bool error_check_bind_xfb_buffers(struct gl_context *ctx, struct gl_transform_feedback_object *tfObj, @@ -3894,6 +4262,9 @@ _mesa_BindBufferRange(GLenum target, GLuint index, case GL_UNIFORM_BUFFER: bind_buffer_range_uniform_buffer(ctx, index, bufObj, offset, size); return; + case GL_SHADER_STORAGE_BUFFER: + bind_buffer_range_shader_storage_buffer(ctx, index, bufObj, offset, size); + return; case GL_ATOMIC_COUNTER_BUFFER: bind_atomic_buffer(ctx, index, bufObj, offset, size, "glBindBufferRange"); @@ -3960,6 +4331,9 @@ _mesa_BindBufferBase(GLenum target, GLuint index, GLuint buffer) case GL_UNIFORM_BUFFER: bind_buffer_base_uniform_buffer(ctx, index, bufObj); return; + case GL_SHADER_STORAGE_BUFFER: + bind_buffer_base_shader_storage_buffer(ctx, index, bufObj); + return; case GL_ATOMIC_COUNTER_BUFFER: bind_atomic_buffer(ctx, index, bufObj, 0, 0, "glBindBufferBase"); @@ -3984,13 +4358,17 @@ _mesa_BindBuffersRange(GLenum target, GLuint first, GLsizei count, case GL_UNIFORM_BUFFER: bind_uniform_buffers_range(ctx, first, count, buffers, offsets, sizes); return; + case GL_SHADER_STORAGE_BUFFER: + bind_shader_storage_buffers_range(ctx, first, count, buffers, offsets, + sizes); + return; case GL_ATOMIC_COUNTER_BUFFER: bind_atomic_buffers_range(ctx, first, count, buffers, offsets, sizes); return; default: _mesa_error(ctx, GL_INVALID_ENUM, "glBindBuffersRange(target=%s)", - _mesa_lookup_enum_by_nr(target)); + _mesa_enum_to_string(target)); break; } } @@ -4008,12 +4386,15 @@ _mesa_BindBuffersBase(GLenum target, GLuint first, GLsizei count, case GL_UNIFORM_BUFFER: bind_uniform_buffers_base(ctx, first, count, buffers); return; + case GL_SHADER_STORAGE_BUFFER: + bind_shader_storage_buffers_base(ctx, first, count, buffers); + return; case GL_ATOMIC_COUNTER_BUFFER: bind_atomic_buffers_base(ctx, first, count, buffers); return; default: _mesa_error(ctx, GL_INVALID_ENUM, "glBindBuffersBase(target=%s)", - _mesa_lookup_enum_by_nr(target)); + _mesa_enum_to_string(target)); break; } } diff --git a/src/mesa/main/buffers.c b/src/mesa/main/buffers.c index 0536266d756..93588a2ee18 100644 --- a/src/mesa/main/buffers.c +++ b/src/mesa/main/buffers.c @@ -251,7 +251,7 @@ _mesa_draw_buffer(struct gl_context *ctx, struct gl_framebuffer *fb, FLUSH_VERTICES(ctx, 0); if (MESA_VERBOSE & VERBOSE_API) { - _mesa_debug(ctx, "%s %s\n", caller, _mesa_lookup_enum_by_nr(buffer)); + _mesa_debug(ctx, "%s %s\n", caller, _mesa_enum_to_string(buffer)); } if (buffer == GL_NONE) { @@ -264,14 +264,14 @@ _mesa_draw_buffer(struct gl_context *ctx, struct gl_framebuffer *fb, if (destMask == BAD_MASK) { /* totally bogus buffer */ _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid buffer %s)", caller, - _mesa_lookup_enum_by_nr(buffer)); + _mesa_enum_to_string(buffer)); return; } destMask &= supportedMask; if (destMask == 0x0) { /* none of the named color buffers exist! */ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid buffer %s)", - caller, _mesa_lookup_enum_by_nr(buffer)); + caller, _mesa_enum_to_string(buffer)); return; } } @@ -411,7 +411,7 @@ _mesa_draw_buffers(struct gl_context *ctx, struct gl_framebuffer *fb, */ if (destMask[output] == BAD_MASK) { _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid buffer %s)", - caller, _mesa_lookup_enum_by_nr(buffers[output])); + caller, _mesa_enum_to_string(buffers[output])); return; } @@ -427,7 +427,7 @@ _mesa_draw_buffers(struct gl_context *ctx, struct gl_framebuffer *fb, */ if (_mesa_bitcount(destMask[output]) > 1) { _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid buffer %s)", - caller, _mesa_lookup_enum_by_nr(buffers[output])); + caller, _mesa_enum_to_string(buffers[output])); return; } @@ -445,7 +445,7 @@ _mesa_draw_buffers(struct gl_context *ctx, struct gl_framebuffer *fb, if (destMask[output] == 0) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported buffer %s)", - caller, _mesa_lookup_enum_by_nr(buffers[output])); + caller, _mesa_enum_to_string(buffers[output])); return; } @@ -459,7 +459,7 @@ _mesa_draw_buffers(struct gl_context *ctx, struct gl_framebuffer *fb, buffers[output] != GL_COLOR_ATTACHMENT0 + output) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported buffer %s)", - caller, _mesa_lookup_enum_by_nr(buffers[output])); + caller, _mesa_enum_to_string(buffers[output])); return; } @@ -471,7 +471,7 @@ _mesa_draw_buffers(struct gl_context *ctx, struct gl_framebuffer *fb, if (destMask[output] & usedBufferMask) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(duplicated buffer %s)", - caller, _mesa_lookup_enum_by_nr(buffers[output])); + caller, _mesa_enum_to_string(buffers[output])); return; } @@ -700,7 +700,7 @@ _mesa_read_buffer(struct gl_context *ctx, struct gl_framebuffer *fb, FLUSH_VERTICES(ctx, 0); if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "%s %s\n", caller, _mesa_lookup_enum_by_nr(buffer)); + _mesa_debug(ctx, "%s %s\n", caller, _mesa_enum_to_string(buffer)); if (buffer == GL_NONE) { /* This is legal--it means that no buffer should be bound for reading. */ @@ -712,14 +712,14 @@ _mesa_read_buffer(struct gl_context *ctx, struct gl_framebuffer *fb, if (srcBuffer == -1) { _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid buffer %s)", caller, - _mesa_lookup_enum_by_nr(buffer)); + _mesa_enum_to_string(buffer)); return; } supportedMask = supported_buffer_bitmask(ctx, fb); if (((1 << srcBuffer) & supportedMask) == 0) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid buffer %s)", caller, - _mesa_lookup_enum_by_nr(buffer)); + _mesa_enum_to_string(buffer)); return; } } diff --git a/src/mesa/main/clear.c b/src/mesa/main/clear.c index 426caea4709..3bfcc5c0e39 100644 --- a/src/mesa/main/clear.c +++ b/src/mesa/main/clear.c @@ -325,6 +325,18 @@ _mesa_ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value) _mesa_update_state( ctx ); } + /* Page 498 of the PDF, section '17.4.3.1 Clearing Individual Buffers' + * of the OpenGL 4.5 spec states: + * + * "An INVALID_ENUM error is generated by ClearBufferiv and + * ClearNamedFramebufferiv if buffer is not COLOR or STENCIL." + */ + if (buffer == GL_DEPTH || buffer == GL_DEPTH_STENCIL) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glClearBufferiv(buffer=GL_DEPTH || GL_DEPTH_STENCIL)"); + return; + } + switch (buffer) { case GL_STENCIL: /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says: @@ -395,7 +407,7 @@ _mesa_ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value) return; default: _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferiv(buffer=%s)", - _mesa_lookup_enum_by_nr(buffer)); + _mesa_enum_to_string(buffer)); return; } } @@ -485,7 +497,7 @@ _mesa_ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value) return; default: _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferuiv(buffer=%s)", - _mesa_lookup_enum_by_nr(buffer)); + _mesa_enum_to_string(buffer)); return; } } @@ -596,7 +608,7 @@ _mesa_ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value) return; default: _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfv(buffer=%s)", - _mesa_lookup_enum_by_nr(buffer)); + _mesa_enum_to_string(buffer)); return; } } @@ -636,7 +648,7 @@ _mesa_ClearBufferfi(GLenum buffer, GLint drawbuffer, if (buffer != GL_DEPTH_STENCIL) { _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfi(buffer=%s)", - _mesa_lookup_enum_by_nr(buffer)); + _mesa_enum_to_string(buffer)); return; } diff --git a/src/mesa/main/condrender.c b/src/mesa/main/condrender.c index 77e4b95ee8f..46c6036d2a5 100644 --- a/src/mesa/main/condrender.c +++ b/src/mesa/main/condrender.c @@ -87,7 +87,7 @@ _mesa_BeginConditionalRender(GLuint queryId, GLenum mode) /* fallthrough - invalid */ default: _mesa_error(ctx, GL_INVALID_ENUM, "glBeginConditionalRender(mode=%s)", - _mesa_lookup_enum_by_nr(mode)); + _mesa_enum_to_string(mode)); return; } @@ -184,7 +184,7 @@ _mesa_check_conditional_render(struct gl_context *ctx) default: _mesa_problem(ctx, "Bad cond render mode %s in " " _mesa_check_conditional_render()", - _mesa_lookup_enum_by_nr(ctx->Query.CondRenderMode)); + _mesa_enum_to_string(ctx->Query.CondRenderMode)); return GL_TRUE; } } diff --git a/src/mesa/main/config.h b/src/mesa/main/config.h index 9c3baf4c6aa..b35031db3c9 100644 --- a/src/mesa/main/config.h +++ b/src/mesa/main/config.h @@ -171,8 +171,10 @@ #define MAX_PROGRAM_LOCAL_PARAMS 4096 #define MAX_UNIFORMS 4096 #define MAX_UNIFORM_BUFFERS 15 /* + 1 default uniform buffer */ +#define MAX_SHADER_STORAGE_BUFFERS 7 /* + 1 default shader storage buffer */ /* 6 is for vertex, hull, domain, geometry, fragment, and compute shader. */ #define MAX_COMBINED_UNIFORM_BUFFERS (MAX_UNIFORM_BUFFERS * 6) +#define MAX_COMBINED_SHADER_STORAGE_BUFFERS (MAX_SHADER_STORAGE_BUFFERS * 6) #define MAX_ATOMIC_COUNTERS 4096 /* 6 is for vertex, hull, domain, geometry, fragment, and compute shader. */ #define MAX_COMBINED_ATOMIC_BUFFERS (MAX_UNIFORM_BUFFERS * 6) @@ -272,6 +274,12 @@ #define MAX_VERTEX_STREAMS 4 /*@}*/ +/** For GL_ARB_shader_subroutine */ +/*@{*/ +#define MAX_SUBROUTINES 256 +#define MAX_SUBROUTINE_UNIFORM_LOCATIONS 1024 +/*@}*/ + /** For GL_INTEL_performance_query */ /*@{*/ #define MAX_PERFQUERY_QUERY_NAME_LENGTH 256 @@ -294,6 +302,14 @@ /** For GL_ARB_pipeline_statistics_query */ #define MAX_PIPELINE_STATISTICS 11 +/** For GL_ARB_tessellation_shader */ +/*@{*/ +#define MAX_TESS_GEN_LEVEL 64 +#define MAX_PATCH_VERTICES 32 +#define MAX_TESS_PATCH_COMPONENTS 120 +#define MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS 4096 +/*@}*/ + /* * Color channel component order * diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c index 79fa01849e0..888c461d1c2 100644 --- a/src/mesa/main/context.c +++ b/src/mesa/main/context.c @@ -120,6 +120,7 @@ #include "shaderobj.h" #include "shaderimage.h" #include "util/simple_list.h" +#include "util/strtod.h" #include "state.h" #include "stencil.h" #include "texcompress_s3tc.h" @@ -338,31 +339,6 @@ _mesa_destroy_visual( struct gl_config *vis ) /** - * This is lame. gdb only seems to recognize enum types that are - * actually used somewhere. We want to be able to print/use enum - * values such as TEXTURE_2D_INDEX in gdb. But we don't actually use - * the gl_texture_index type anywhere. Thus, this lame function. - */ -static void -dummy_enum_func(void) -{ - gl_buffer_index bi = BUFFER_FRONT_LEFT; - gl_face_index fi = FACE_POS_X; - gl_frag_result fr = FRAG_RESULT_DEPTH; - gl_texture_index ti = TEXTURE_2D_ARRAY_INDEX; - gl_vert_attrib va = VERT_ATTRIB_POS; - gl_varying_slot vs = VARYING_SLOT_POS; - - (void) bi; - (void) fi; - (void) fr; - (void) ti; - (void) va; - (void) vs; -} - - -/** * One-time initialization mutex lock. * * \sa Used by one_time_init(). @@ -370,6 +346,16 @@ dummy_enum_func(void) mtx_t OneTimeLock = _MTX_INITIALIZER_NP; +/** + * Calls all the various one-time-fini functions in Mesa + */ + +static void +one_time_fini(void) +{ + _mesa_destroy_shader_compiler(); + _mesa_locale_fini(); +} /** * Calls all the various one-time-init functions in Mesa. @@ -391,13 +377,14 @@ one_time_init( struct gl_context *ctx ) if (!api_init_mask) { GLuint i; - /* do some implementation tests */ - assert( sizeof(GLbyte) == 1 ); - assert( sizeof(GLubyte) == 1 ); - assert( sizeof(GLshort) == 2 ); - assert( sizeof(GLushort) == 2 ); - assert( sizeof(GLint) == 4 ); - assert( sizeof(GLuint) == 4 ); + STATIC_ASSERT(sizeof(GLbyte) == 1); + STATIC_ASSERT(sizeof(GLubyte) == 1); + STATIC_ASSERT(sizeof(GLshort) == 2); + STATIC_ASSERT(sizeof(GLushort) == 2); + STATIC_ASSERT(sizeof(GLint) == 4); + STATIC_ASSERT(sizeof(GLuint) == 4); + + _mesa_locale_init(); _mesa_one_time_init_extension_overrides(); @@ -407,6 +394,8 @@ one_time_init( struct gl_context *ctx ) _mesa_ubyte_to_float_color_tab[i] = (float) i / 255.0F; } + atexit(one_time_fini); + #if defined(DEBUG) && defined(__DATE__) && defined(__TIME__) if (MESA_VERBOSE != 0) { _mesa_debug(ctx, "Mesa %s DEBUG build %s %s\n", @@ -429,13 +418,6 @@ one_time_init( struct gl_context *ctx ) api_init_mask |= 1 << ctx->API; mtx_unlock(&OneTimeLock); - - /* Hopefully atexit() is widely available. If not, we may need some - * #ifdef tests here. - */ - atexit(_mesa_destroy_shader_compiler); - - dummy_enum_func(); } @@ -496,6 +478,8 @@ init_program_limits(struct gl_constants *consts, gl_shader_stage stage, prog->MaxInputComponents = 16 * 4; /* old limit not to break tnl and swrast */ prog->MaxOutputComponents = 0; /* value not used */ break; + case MESA_SHADER_TESS_CTRL: + case MESA_SHADER_TESS_EVAL: case MESA_SHADER_GEOMETRY: prog->MaxParameters = MAX_VERTEX_PROGRAM_PARAMS; prog->MaxAttribs = MAX_VERTEX_GENERIC_ATTRIBS; @@ -554,6 +538,8 @@ init_program_limits(struct gl_constants *consts, gl_shader_stage stage, prog->MaxAtomicBuffers = 0; prog->MaxAtomicCounters = 0; + + prog->MaxShaderStorageBlocks = 8; } @@ -615,6 +601,12 @@ _mesa_init_constants(struct gl_constants *consts, gl_api api) consts->MaxUniformBlockSize = 16384; consts->UniformBufferOffsetAlignment = 1; + /** GL_ARB_shader_storage_buffer_object */ + consts->MaxCombinedShaderStorageBlocks = 8; + consts->MaxShaderStorageBufferBindings = 8; + consts->MaxShaderStorageBlockSize = 128 * 1024 * 1024; /* 2^27 */ + consts->ShaderStorageBufferOffsetAlignment = 256; + /* GL_ARB_explicit_uniform_location, GL_MAX_UNIFORM_LOCATIONS */ consts->MaxUserAssignableUniformLocations = 4 * MESA_SHADER_STAGES * MAX_UNIFORMS; @@ -724,6 +716,14 @@ _mesa_init_constants(struct gl_constants *consts, gl_api api) /** GL_KHR_context_flush_control */ consts->ContextReleaseBehavior = GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH; + + /** GL_ARB_tessellation_shader */ + consts->MaxTessGenLevel = MAX_TESS_GEN_LEVEL; + consts->MaxPatchVertices = MAX_PATCH_VERTICES; + consts->Program[MESA_SHADER_TESS_CTRL].MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS; + consts->Program[MESA_SHADER_TESS_EVAL].MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS; + consts->MaxTessPatchComponents = MAX_TESS_PATCH_COMPONENTS; + consts->MaxTessControlTotalOutputComponents = MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS; } @@ -1331,6 +1331,8 @@ _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_tesscprog(ctx, &ctx->TessCtrlProgram._Current, NULL); + _mesa_reference_tesseprog(ctx, &ctx->TessEvalProgram._Current, NULL); _mesa_reference_geomprog(ctx, &ctx->GeometryProgram._Current, NULL); _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, NULL); diff --git a/src/mesa/main/context.h b/src/mesa/main/context.h index 6f3c941016f..0f7529ad975 100644 --- a/src/mesa/main/context.h +++ b/src/mesa/main/context.h @@ -343,6 +343,26 @@ _mesa_has_compute_shaders(const struct gl_context *ctx) (ctx->API == API_OPENGLES2 && ctx->Version >= 31); } +/** + * Checks if the context supports shader subroutines. + */ +static inline bool +_mesa_has_shader_subroutine(const struct gl_context *ctx) +{ + return ctx->API == API_OPENGL_CORE && + (ctx->Version >= 40 || ctx->Extensions.ARB_shader_subroutine); +} + +/** + * Checks if the context supports tessellation. + */ +static inline GLboolean +_mesa_has_tessellation(const struct gl_context *ctx) +{ + return ctx->API == API_OPENGL_CORE && + ctx->Extensions.ARB_tessellation_shader; +} + #ifdef __cplusplus } diff --git a/src/mesa/main/copyimage.c b/src/mesa/main/copyimage.c index e8732c6175b..05bc50dd2c6 100644 --- a/src/mesa/main/copyimage.c +++ b/src/mesa/main/copyimage.c @@ -93,7 +93,7 @@ prepare_target(struct gl_context *ctx, GLuint name, GLenum *target, int level, default: _mesa_error(ctx, GL_INVALID_ENUM, "glCopyImageSubData(%sTarget = %s)", dbg_prefix, - _mesa_lookup_enum_by_nr(*target)); + _mesa_enum_to_string(*target)); return false; } @@ -159,7 +159,7 @@ prepare_target(struct gl_context *ctx, GLuint name, GLenum *target, int level, if ((*tex_obj)->Target != *target) { _mesa_error(ctx, GL_INVALID_ENUM, "glCopyImageSubData(%sTarget = %s)", dbg_prefix, - _mesa_lookup_enum_by_nr(*target)); + _mesa_enum_to_string(*target)); return false; } @@ -416,9 +416,9 @@ _mesa_CopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel, _mesa_debug(ctx, "glCopyImageSubData(%u, %s, %d, %d, %d, %d, " "%u, %s, %d, %d, %d, %d, " "%d, %d, %d)\n", - srcName, _mesa_lookup_enum_by_nr(srcTarget), srcLevel, + srcName, _mesa_enum_to_string(srcTarget), srcLevel, srcX, srcY, srcZ, - dstName, _mesa_lookup_enum_by_nr(dstTarget), dstLevel, + dstName, _mesa_enum_to_string(dstTarget), dstLevel, dstX, dstY, dstZ, srcWidth, srcHeight, srcWidth); diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h index d783e34222f..87eb63ea374 100644 --- a/src/mesa/main/dd.h +++ b/src/mesa/main/dd.h @@ -232,11 +232,13 @@ struct dd_function_table { /** - * Called by glGetTexImage(). + * Called by glGetTexImage(), glGetTextureSubImage(). */ - void (*GetTexImage)( struct gl_context *ctx, - GLenum format, GLenum type, GLvoid *pixels, - struct gl_texture_image *texImage ); + void (*GetTexSubImage)(struct gl_context *ctx, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, GLvoid *pixels, + struct gl_texture_image *texImage); /** * Called by glClearTex[Sub]Image @@ -326,16 +328,19 @@ struct dd_function_table { void (*CompressedTexSubImage)(struct gl_context *ctx, GLuint dims, struct gl_texture_image *texImage, GLint xoffset, GLint yoffset, GLint zoffset, - GLsizei width, GLint height, GLint depth, + GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data); /** * Called by glGetCompressedTexImage. */ - void (*GetCompressedTexImage)(struct gl_context *ctx, - struct gl_texture_image *texImage, - GLvoid *data); + void (*GetCompressedTexSubImage)(struct gl_context *ctx, + struct gl_texture_image *texImage, + GLint xoffset, GLint yoffset, + GLint zoffset, GLsizei width, + GLsizei height, GLsizei depth, + GLvoid *data); /*@}*/ /** diff --git a/src/mesa/main/debug.c b/src/mesa/main/debug.c index c93e84a04d0..5ca7d5ce500 100644 --- a/src/mesa/main/debug.c +++ b/src/mesa/main/debug.c @@ -272,7 +272,9 @@ write_texture_image(struct gl_texture_object *texObj, store = ctx->Pack; /* save */ ctx->Pack = ctx->DefaultPacking; - ctx->Driver.GetTexImage(ctx, GL_RGBA, GL_UNSIGNED_BYTE, buffer, img); + ctx->Driver.GetTexSubImage(ctx, + 0, 0, 0, img->Width, img->Height, img->Depth, + GL_RGBA, GL_UNSIGNED_BYTE, buffer, img); /* make filename */ _mesa_snprintf(s, sizeof(s), "/tmp/tex%u.l%u.f%u.ppm", texObj->Name, level, face); @@ -411,7 +413,7 @@ dump_renderbuffer(const struct gl_renderbuffer *rb, GLboolean writeImage) { printf("Renderbuffer %u: %u x %u IntFormat = %s\n", rb->Name, rb->Width, rb->Height, - _mesa_lookup_enum_by_nr(rb->InternalFormat)); + _mesa_enum_to_string(rb->InternalFormat)); if (writeImage) { _mesa_write_renderbuffer_image(rb); } diff --git a/src/mesa/main/depth.c b/src/mesa/main/depth.c index bb4591cf152..c3534407599 100644 --- a/src/mesa/main/depth.c +++ b/src/mesa/main/depth.c @@ -63,7 +63,7 @@ _mesa_DepthFunc( GLenum func ) GET_CURRENT_CONTEXT(ctx); if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glDepthFunc %s\n", _mesa_lookup_enum_by_nr(func)); + _mesa_debug(ctx, "glDepthFunc %s\n", _mesa_enum_to_string(func)); if (ctx->Depth.Func == func) return; diff --git a/src/mesa/main/dlist.c b/src/mesa/main/dlist.c index aafe486fb60..5554738d1a3 100644 --- a/src/mesa/main/dlist.c +++ b/src/mesa/main/dlist.c @@ -9000,7 +9000,7 @@ _mesa_NewList(GLuint name, GLenum mode) if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glNewList %u %s\n", name, - _mesa_lookup_enum_by_nr(mode)); + _mesa_enum_to_string(mode)); if (name == 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glNewList"); @@ -9688,7 +9688,7 @@ _mesa_initialize_save_table(const struct gl_context *ctx) static const char * enum_string(GLenum k) { - return _mesa_lookup_enum_by_nr(k); + return _mesa_enum_to_string(k); } @@ -9827,19 +9827,19 @@ print_list(struct gl_context *ctx, GLuint list, const char *fname) break; case OPCODE_BIND_TEXTURE: fprintf(f, "BindTexture %s %d\n", - _mesa_lookup_enum_by_nr(n[1].ui), n[2].ui); + _mesa_enum_to_string(n[1].ui), n[2].ui); break; case OPCODE_SHADE_MODEL: - fprintf(f, "ShadeModel %s\n", _mesa_lookup_enum_by_nr(n[1].ui)); + fprintf(f, "ShadeModel %s\n", _mesa_enum_to_string(n[1].ui)); break; case OPCODE_MAP1: fprintf(f, "Map1 %s %.3f %.3f %d %d\n", - _mesa_lookup_enum_by_nr(n[1].ui), + _mesa_enum_to_string(n[1].ui), n[2].f, n[3].f, n[4].i, n[5].i); break; case OPCODE_MAP2: fprintf(f, "Map2 %s %.3f %.3f %.3f %.3f %d %d %d %d\n", - _mesa_lookup_enum_by_nr(n[1].ui), + _mesa_enum_to_string(n[1].ui), n[2].f, n[3].f, n[4].f, n[5].f, n[6].i, n[7].i, n[8].i, n[9].i); break; @@ -9918,7 +9918,7 @@ print_list(struct gl_context *ctx, GLuint list, const char *fname) case OPCODE_PROVOKING_VERTEX: fprintf(f, "ProvokingVertex %s\n", - _mesa_lookup_enum_by_nr(n[1].ui)); + _mesa_enum_to_string(n[1].ui)); break; /* diff --git a/src/mesa/main/drawpix.c b/src/mesa/main/drawpix.c index 55035f214b3..720a082ce6d 100644 --- a/src/mesa/main/drawpix.c +++ b/src/mesa/main/drawpix.c @@ -53,10 +53,10 @@ _mesa_DrawPixels( GLsizei width, GLsizei height, if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glDrawPixels(%d, %d, %s, %s, %p) // to %s at %d, %d\n", width, height, - _mesa_lookup_enum_by_nr(format), - _mesa_lookup_enum_by_nr(type), + _mesa_enum_to_string(format), + _mesa_enum_to_string(type), pixels, - _mesa_lookup_enum_by_nr(ctx->DrawBuffer->ColorDrawBuffer[0]), + _mesa_enum_to_string(ctx->DrawBuffer->ColorDrawBuffer[0]), IROUND(ctx->Current.RasterPos[0]), IROUND(ctx->Current.RasterPos[1])); @@ -96,8 +96,8 @@ _mesa_DrawPixels( GLsizei width, GLsizei height, err = _mesa_error_check_format_and_type(ctx, format, type); if (err != GL_NO_ERROR) { _mesa_error(ctx, err, "glDrawPixels(invalid format %s and/or type %s)", - _mesa_lookup_enum_by_nr(format), - _mesa_lookup_enum_by_nr(type)); + _mesa_enum_to_string(format), + _mesa_enum_to_string(type)); goto end; } @@ -198,9 +198,9 @@ _mesa_CopyPixels( GLint srcx, GLint srcy, GLsizei width, GLsizei height, _mesa_debug(ctx, "glCopyPixels(%d, %d, %d, %d, %s) // from %s to %s at %d, %d\n", srcx, srcy, width, height, - _mesa_lookup_enum_by_nr(type), - _mesa_lookup_enum_by_nr(ctx->ReadBuffer->ColorReadBuffer), - _mesa_lookup_enum_by_nr(ctx->DrawBuffer->ColorDrawBuffer[0]), + _mesa_enum_to_string(type), + _mesa_enum_to_string(ctx->ReadBuffer->ColorReadBuffer), + _mesa_enum_to_string(ctx->DrawBuffer->ColorDrawBuffer[0]), IROUND(ctx->Current.RasterPos[0]), IROUND(ctx->Current.RasterPos[1])); @@ -218,7 +218,7 @@ _mesa_CopyPixels( GLint srcx, GLint srcy, GLsizei width, GLsizei height, type != GL_STENCIL && type != GL_DEPTH_STENCIL) { _mesa_error(ctx, GL_INVALID_ENUM, "glCopyPixels(type=%s)", - _mesa_lookup_enum_by_nr(type)); + _mesa_enum_to_string(type)); return; } diff --git a/src/mesa/main/enable.c b/src/mesa/main/enable.c index 9008a386343..42f67990784 100644 --- a/src/mesa/main/enable.c +++ b/src/mesa/main/enable.c @@ -146,7 +146,7 @@ client_state(struct gl_context *ctx, GLenum cap, GLboolean state) invalid_enum_error: _mesa_error(ctx, GL_INVALID_ENUM, "gl%sClientState(%s)", - state ? "Enable" : "Disable", _mesa_lookup_enum_by_nr(cap)); + state ? "Enable" : "Disable", _mesa_enum_to_string(cap)); } @@ -283,7 +283,7 @@ _mesa_set_enable(struct gl_context *ctx, GLenum cap, GLboolean state) if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "%s %s (newstate is %x)\n", state ? "glEnable" : "glDisable", - _mesa_lookup_enum_by_nr(cap), + _mesa_enum_to_string(cap), ctx->NewState); switch (cap) { @@ -1001,7 +1001,7 @@ _mesa_set_enable(struct gl_context *ctx, GLenum cap, GLboolean state) /* ARB_texture_multisample */ case GL_SAMPLE_MASK: - if (!_mesa_is_desktop_gl(ctx)) + if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles31(ctx)) goto invalid_enum_error; CHECK_EXTENSION(ARB_texture_multisample, cap); if (ctx->Multisample.SampleMask == state) @@ -1022,7 +1022,7 @@ _mesa_set_enable(struct gl_context *ctx, GLenum cap, GLboolean state) invalid_enum_error: _mesa_error(ctx, GL_INVALID_ENUM, "gl%s(%s)", - state ? "Enable" : "Disable", _mesa_lookup_enum_by_nr(cap)); + state ? "Enable" : "Disable", _mesa_enum_to_string(cap)); } @@ -1101,7 +1101,7 @@ _mesa_set_enablei(struct gl_context *ctx, GLenum cap, invalid_enum_error: _mesa_error(ctx, GL_INVALID_ENUM, "%s(cap=%s)", state ? "glEnablei" : "glDisablei", - _mesa_lookup_enum_by_nr(cap)); + _mesa_enum_to_string(cap)); } @@ -1143,7 +1143,7 @@ _mesa_IsEnabledi( GLenum cap, GLuint index ) return (ctx->Scissor.EnableFlags >> index) & 1; default: _mesa_error(ctx, GL_INVALID_ENUM, "glIsEnabledIndexed(cap=%s)", - _mesa_lookup_enum_by_nr(cap)); + _mesa_enum_to_string(cap)); return GL_FALSE; } } @@ -1603,7 +1603,7 @@ _mesa_IsEnabled( GLenum cap ) /* ARB_texture_multisample */ case GL_SAMPLE_MASK: - if (!_mesa_is_desktop_gl(ctx)) + if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles31(ctx)) goto invalid_enum_error; CHECK_EXTENSION(ARB_texture_multisample); return ctx->Multisample.SampleMask; @@ -1623,6 +1623,6 @@ _mesa_IsEnabled( GLenum cap ) invalid_enum_error: _mesa_error(ctx, GL_INVALID_ENUM, "glIsEnabled(%s)", - _mesa_lookup_enum_by_nr(cap)); + _mesa_enum_to_string(cap)); return GL_FALSE; } diff --git a/src/mesa/main/enums.h b/src/mesa/main/enums.h index 66bdd53bbab..0e18cd407e9 100644 --- a/src/mesa/main/enums.h +++ b/src/mesa/main/enums.h @@ -42,7 +42,7 @@ extern "C" { #endif -extern const char *_mesa_lookup_enum_by_nr( int nr ); +extern const char *_mesa_enum_to_string( int nr ); /* Get the name of an enum given that it is a primitive type. Avoids * GL_FALSE/GL_POINTS ambiguity and others. diff --git a/src/mesa/main/errors.c b/src/mesa/main/errors.c index b3406665d94..f720de316e4 100644 --- a/src/mesa/main/errors.c +++ b/src/mesa/main/errors.c @@ -1314,7 +1314,7 @@ flush_delayed_errors( struct gl_context *ctx ) if (ctx->ErrorDebugCount) { _mesa_snprintf(s, MAX_DEBUG_MESSAGE_LENGTH, "%d similar %s errors", ctx->ErrorDebugCount, - _mesa_lookup_enum_by_nr(ctx->ErrorValue)); + _mesa_enum_to_string(ctx->ErrorValue)); output_if_debug("Mesa", s, GL_TRUE); @@ -1503,7 +1503,7 @@ _mesa_error( struct gl_context *ctx, GLenum error, const char *fmtString, ... ) } len = _mesa_snprintf(s2, MAX_DEBUG_MESSAGE_LENGTH, "%s in %s", - _mesa_lookup_enum_by_nr(error), s); + _mesa_enum_to_string(error), s); if (len >= MAX_DEBUG_MESSAGE_LENGTH) { /* Same as above. */ assert(0); diff --git a/src/mesa/main/errors.h b/src/mesa/main/errors.h index 24f234f7f10..81e47a8b8c1 100644 --- a/src/mesa/main/errors.h +++ b/src/mesa/main/errors.h @@ -37,6 +37,7 @@ #include <stdio.h> +#include <stdarg.h> #include "compiler.h" #include "glheader.h" #include "mtypes.h" diff --git a/src/mesa/main/extensions.c b/src/mesa/main/extensions.c index 4176a69ed7c..d934d19c3e7 100644 --- a/src/mesa/main/extensions.c +++ b/src/mesa/main/extensions.c @@ -121,6 +121,7 @@ static const struct extension extension_table[] = { { "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 }, + { "GL_ARB_get_texture_sub_image", o(dummy_true), GL, 2014 }, { "GL_ARB_gpu_shader5", o(ARB_gpu_shader5), GLC, 2010 }, { "GL_ARB_gpu_shader_fp64", o(ARB_gpu_shader_fp64), GLC, 2010 }, { "GL_ARB_half_float_pixel", o(dummy_true), GL, 2003 }, @@ -154,6 +155,8 @@ static const struct extension extension_table[] = { { "GL_ARB_shader_objects", o(dummy_true), GL, 2002 }, { "GL_ARB_shader_precision", o(ARB_shader_precision), GL, 2010 }, { "GL_ARB_shader_stencil_export", o(ARB_shader_stencil_export), GL, 2009 }, + { "GL_ARB_shader_storage_buffer_object", o(ARB_shader_storage_buffer_object), GL, 2012 }, + { "GL_ARB_shader_subroutine", o(ARB_shader_subroutine), GLC, 2010 }, { "GL_ARB_shader_texture_lod", o(ARB_shader_texture_lod), GL, 2009 }, { "GL_ARB_shading_language_100", o(dummy_true), GLL, 2003 }, { "GL_ARB_shading_language_packing", o(ARB_shading_language_packing), GL, 2011 }, @@ -382,6 +385,9 @@ static const struct extension extension_table[] = { { "GL_NV_point_sprite", o(NV_point_sprite), GL, 2001 }, { "GL_NV_primitive_restart", o(NV_primitive_restart), GLL, 2002 }, { "GL_NV_read_buffer", o(dummy_true), ES2, 2011 }, + { "GL_NV_read_depth", o(dummy_true), ES2, 2011 }, + { "GL_NV_read_depth_stencil", o(dummy_true), ES2, 2011 }, + { "GL_NV_read_stencil", o(dummy_true), ES2, 2011 }, { "GL_NV_texgen_reflection", o(dummy_true), GLL, 1999 }, { "GL_NV_texture_barrier", o(NV_texture_barrier), GL, 2009 }, { "GL_NV_texture_env_combine4", o(NV_texture_env_combine4), GLL, 1999 }, diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c index f8dcf122d99..841834030df 100644 --- a/src/mesa/main/fbobject.c +++ b/src/mesa/main/fbobject.c @@ -2007,7 +2007,7 @@ renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *rb, baseFormat = _mesa_base_fbo_format(ctx, internalFormat); if (baseFormat == 0) { _mesa_error(ctx, GL_INVALID_ENUM, "%s(internalFormat=%s)", - func, _mesa_lookup_enum_by_nr(internalFormat)); + func, _mesa_enum_to_string(internalFormat)); return; } @@ -2095,12 +2095,12 @@ renderbuffer_storage_named(GLuint renderbuffer, GLenum internalFormat, if (samples == NO_SAMPLES) _mesa_debug(ctx, "%s(%u, %s, %d, %d)\n", func, renderbuffer, - _mesa_lookup_enum_by_nr(internalFormat), + _mesa_enum_to_string(internalFormat), width, height); else _mesa_debug(ctx, "%s(%u, %s, %d, %d, %d)\n", func, renderbuffer, - _mesa_lookup_enum_by_nr(internalFormat), + _mesa_enum_to_string(internalFormat), width, height, samples); } @@ -2131,14 +2131,14 @@ renderbuffer_storage_target(GLenum target, GLenum internalFormat, if (samples == NO_SAMPLES) _mesa_debug(ctx, "%s(%s, %s, %d, %d)\n", func, - _mesa_lookup_enum_by_nr(target), - _mesa_lookup_enum_by_nr(internalFormat), + _mesa_enum_to_string(target), + _mesa_enum_to_string(internalFormat), width, height); else _mesa_debug(ctx, "%s(%s, %s, %d, %d, %d)\n", func, - _mesa_lookup_enum_by_nr(target), - _mesa_lookup_enum_by_nr(internalFormat), + _mesa_enum_to_string(target), + _mesa_enum_to_string(internalFormat), width, height, samples); } @@ -2311,7 +2311,7 @@ get_render_buffer_parameteriv(struct gl_context *ctx, /* fallthrough */ default: _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid pname=%s)", func, - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); return; } } @@ -2694,13 +2694,13 @@ _mesa_CheckFramebufferStatus(GLenum target) if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glCheckFramebufferStatus(%s)\n", - _mesa_lookup_enum_by_nr(target)); + _mesa_enum_to_string(target)); fb = get_framebuffer_target(ctx, target); if (!fb) { _mesa_error(ctx, GL_INVALID_ENUM, "glCheckFramebufferStatus(invalid target %s)", - _mesa_lookup_enum_by_nr(target)); + _mesa_enum_to_string(target)); return 0; } @@ -2732,7 +2732,7 @@ _mesa_CheckNamedFramebufferStatus(GLuint framebuffer, GLenum target) default: _mesa_error(ctx, GL_INVALID_ENUM, "glCheckNamedFramebufferStatus(invalid target %s)", - _mesa_lookup_enum_by_nr(target)); + _mesa_enum_to_string(target)); return 0; } @@ -2851,7 +2851,7 @@ check_layered_texture_target(struct gl_context *ctx, GLenum target, _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid texture target %s)", caller, - _mesa_lookup_enum_by_nr(target)); + _mesa_enum_to_string(target)); return false; } @@ -2893,7 +2893,7 @@ check_texture_target(struct gl_context *ctx, GLenum target, _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid texture target %s)", caller, - _mesa_lookup_enum_by_nr(target)); + _mesa_enum_to_string(target)); return false; } @@ -2944,8 +2944,9 @@ check_textarget(struct gl_context *ctx, int dims, GLenum target, break; case GL_TEXTURE_2D_MULTISAMPLE: case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: - err = _mesa_is_gles(ctx) - || !ctx->Extensions.ARB_texture_multisample; + err = (_mesa_is_gles(ctx) || + !ctx->Extensions.ARB_texture_multisample) && + !_mesa_is_gles31(ctx); break; default: err = true; @@ -2962,7 +2963,7 @@ check_textarget(struct gl_context *ctx, int dims, GLenum target, if (err) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid textarget %s)", - caller, _mesa_lookup_enum_by_nr(textarget)); + caller, _mesa_enum_to_string(textarget)); return false; } @@ -3074,7 +3075,7 @@ _mesa_framebuffer_texture(struct gl_context *ctx, struct gl_framebuffer *fb, att = get_attachment(ctx, fb, attachment); if (att == NULL) { _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid attachment %s)", caller, - _mesa_lookup_enum_by_nr(attachment)); + _mesa_enum_to_string(attachment)); return; } @@ -3157,7 +3158,7 @@ framebuffer_texture_with_dims(int dims, GLenum target, fb = get_framebuffer_target(ctx, target); if (!fb) { _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", caller, - _mesa_lookup_enum_by_nr(target)); + _mesa_enum_to_string(target)); return; } @@ -3225,7 +3226,7 @@ _mesa_FramebufferTextureLayer(GLenum target, GLenum attachment, if (!fb) { _mesa_error(ctx, GL_INVALID_ENUM, "glFramebufferTextureLayer(invalid target %s)", - _mesa_lookup_enum_by_nr(target)); + _mesa_enum_to_string(target)); return; } @@ -3304,7 +3305,7 @@ _mesa_FramebufferTexture(GLenum target, GLenum attachment, GET_CURRENT_CONTEXT(ctx); struct gl_framebuffer *fb; struct gl_texture_object *texObj; - GLboolean layered; + GLboolean layered = GL_FALSE; const char *func = "FramebufferTexture"; @@ -3319,7 +3320,7 @@ _mesa_FramebufferTexture(GLenum target, GLenum attachment, if (!fb) { _mesa_error(ctx, GL_INVALID_ENUM, "glFramebufferTexture(invalid target %s)", - _mesa_lookup_enum_by_nr(target)); + _mesa_enum_to_string(target)); return; } @@ -3347,7 +3348,7 @@ _mesa_NamedFramebufferTexture(GLuint framebuffer, GLenum attachment, GET_CURRENT_CONTEXT(ctx); struct gl_framebuffer *fb; struct gl_texture_object *texObj; - GLboolean layered; + GLboolean layered = GL_FALSE; const char *func = "glNamedFramebufferTexture"; @@ -3400,7 +3401,7 @@ _mesa_framebuffer_renderbuffer(struct gl_context *ctx, if (att == NULL) { _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid attachment %s)", func, - _mesa_lookup_enum_by_nr(attachment)); + _mesa_enum_to_string(attachment)); return; } @@ -3440,7 +3441,7 @@ _mesa_FramebufferRenderbuffer(GLenum target, GLenum attachment, if (!fb) { _mesa_error(ctx, GL_INVALID_ENUM, "glFramebufferRenderbuffer(invalid target %s)", - _mesa_lookup_enum_by_nr(target)); + _mesa_enum_to_string(target)); return; } @@ -3539,7 +3540,7 @@ _mesa_get_framebuffer_attachment_parameter(struct gl_context *ctx, attachment != GL_DEPTH && attachment != GL_STENCIL) { _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid attachment %s)", caller, - _mesa_lookup_enum_by_nr(attachment)); + _mesa_enum_to_string(attachment)); return; } /* the default / window-system FBO */ @@ -3552,7 +3553,7 @@ _mesa_get_framebuffer_attachment_parameter(struct gl_context *ctx, if (att == NULL) { _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid attachment %s)", caller, - _mesa_lookup_enum_by_nr(attachment)); + _mesa_enum_to_string(attachment)); return; } @@ -3609,7 +3610,7 @@ _mesa_get_framebuffer_attachment_parameter(struct gl_context *ctx, } else if (att->Type == GL_NONE) { _mesa_error(ctx, err, "%s(invalid pname %s)", caller, - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); } else { goto invalid_pname_enum; @@ -3626,7 +3627,7 @@ _mesa_get_framebuffer_attachment_parameter(struct gl_context *ctx, } else if (att->Type == GL_NONE) { _mesa_error(ctx, err, "%s(invalid pname %s)", caller, - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); } else { goto invalid_pname_enum; @@ -3637,7 +3638,7 @@ _mesa_get_framebuffer_attachment_parameter(struct gl_context *ctx, goto invalid_pname_enum; } else if (att->Type == GL_NONE) { _mesa_error(ctx, err, "%s(invalid pname %s)", caller, - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); } else if (att->Type == GL_TEXTURE) { if (att->Texture && (att->Texture->Target == GL_TEXTURE_3D || att->Texture->Target == GL_TEXTURE_2D_ARRAY)) { @@ -3659,7 +3660,7 @@ _mesa_get_framebuffer_attachment_parameter(struct gl_context *ctx, } else if (att->Type == GL_NONE) { _mesa_error(ctx, err, "%s(invalid pname %s)", caller, - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); } else { if (ctx->Extensions.EXT_framebuffer_sRGB) { @@ -3682,7 +3683,7 @@ _mesa_get_framebuffer_attachment_parameter(struct gl_context *ctx, } else if (att->Type == GL_NONE) { _mesa_error(ctx, err, "%s(invalid pname %s)", caller, - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); } else { mesa_format format = att->Renderbuffer->Format; @@ -3734,7 +3735,7 @@ _mesa_get_framebuffer_attachment_parameter(struct gl_context *ctx, } else if (att->Type == GL_NONE) { _mesa_error(ctx, err, "%s(invalid pname %s)", caller, - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); } else if (att->Texture) { const struct gl_texture_image *texImage = @@ -3763,7 +3764,7 @@ _mesa_get_framebuffer_attachment_parameter(struct gl_context *ctx, *params = att->Layered; } else if (att->Type == GL_NONE) { _mesa_error(ctx, err, "%s(invalid pname %s)", caller, - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); } else { goto invalid_pname_enum; } @@ -3776,7 +3777,7 @@ _mesa_get_framebuffer_attachment_parameter(struct gl_context *ctx, invalid_pname_enum: _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid pname %s)", caller, - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); return; } @@ -3792,7 +3793,7 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, if (!buffer) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetFramebufferAttachmentParameteriv(invalid target %s)", - _mesa_lookup_enum_by_nr(target)); + _mesa_enum_to_string(target)); return; } @@ -4009,7 +4010,7 @@ invalidate_framebuffer_storage(struct gl_context *ctx, invalid_enum: _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid attachment %s)", name, - _mesa_lookup_enum_by_nr(attachments[i])); + _mesa_enum_to_string(attachments[i])); return; } @@ -4026,7 +4027,7 @@ _mesa_InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, if (!fb) { _mesa_error(ctx, GL_INVALID_ENUM, "glInvalidateSubFramebuffer(invalid target %s)", - _mesa_lookup_enum_by_nr(target)); + _mesa_enum_to_string(target)); return; } @@ -4076,7 +4077,7 @@ _mesa_InvalidateFramebuffer(GLenum target, GLsizei numAttachments, if (!fb) { _mesa_error(ctx, GL_INVALID_ENUM, "glInvalidateFramebuffer(invalid target %s)", - _mesa_lookup_enum_by_nr(target)); + _mesa_enum_to_string(target)); return; } @@ -4152,7 +4153,7 @@ _mesa_DiscardFramebufferEXT(GLenum target, GLsizei numAttachments, if (!fb) { _mesa_error(ctx, GL_INVALID_ENUM, "glDiscardFramebufferEXT(target %s)", - _mesa_lookup_enum_by_nr(target)); + _mesa_enum_to_string(target)); return; } @@ -4189,5 +4190,5 @@ _mesa_DiscardFramebufferEXT(GLenum target, GLsizei numAttachments, invalid_enum: _mesa_error(ctx, GL_INVALID_ENUM, "glDiscardFramebufferEXT(attachment %s)", - _mesa_lookup_enum_by_nr(attachments[i])); + _mesa_enum_to_string(attachments[i])); } diff --git a/src/mesa/main/feedback.c b/src/mesa/main/feedback.c index 6bc4294f9c7..699e2a855a3 100644 --- a/src/mesa/main/feedback.c +++ b/src/mesa/main/feedback.c @@ -415,7 +415,7 @@ _mesa_RenderMode( GLenum mode ) ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0); if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glRenderMode %s\n", _mesa_lookup_enum_by_nr(mode)); + _mesa_debug(ctx, "glRenderMode %s\n", _mesa_enum_to_string(mode)); FLUSH_VERTICES(ctx, _NEW_RENDERMODE); diff --git a/src/mesa/main/ffvertex_prog.c b/src/mesa/main/ffvertex_prog.c index 70adaf88551..95b428dca3e 100644 --- a/src/mesa/main/ffvertex_prog.c +++ b/src/mesa/main/ffvertex_prog.c @@ -189,15 +189,15 @@ static void make_state_key( struct gl_context *ctx, struct state_key *key ) if (light->Enabled) { key->unit[i].light_enabled = 1; - if (light->EyePosition[3] == 0.0) + if (light->EyePosition[3] == 0.0F) key->unit[i].light_eyepos3_is_zero = 1; - if (light->SpotCutoff == 180.0) + if (light->SpotCutoff == 180.0F) key->unit[i].light_spotcutoff_is_180 = 1; - if (light->ConstantAttenuation != 1.0 || - light->LinearAttenuation != 0.0 || - light->QuadraticAttenuation != 0.0) + if (light->ConstantAttenuation != 1.0F || + light->LinearAttenuation != 0.0F || + light->QuadraticAttenuation != 0.0F) key->unit[i].light_attenuated = 1; } } diff --git a/src/mesa/main/fog.c b/src/mesa/main/fog.c index 3bce289e785..45f343d61c8 100644 --- a/src/mesa/main/fog.c +++ b/src/mesa/main/fog.c @@ -115,7 +115,7 @@ _mesa_Fogfv( GLenum pname, const GLfloat *params ) ctx->Fog.Mode = m; break; case GL_FOG_DENSITY: - if (*params<0.0) { + if (*params<0.0F) { _mesa_error( ctx, GL_INVALID_VALUE, "glFog" ); return; } diff --git a/src/mesa/main/format_parser.py b/src/mesa/main/format_parser.py index 11184f78e2c..799b14f0b1c 100755 --- a/src/mesa/main/format_parser.py +++ b/src/mesa/main/format_parser.py @@ -40,9 +40,6 @@ SRGB = 'srgb' YUV = 'yuv' ZS = 'zs' -def is_power_of_two(x): - return not bool(x & (x - 1)) - VERY_LARGE = 99999999999999999999999 class Channel: @@ -100,10 +97,6 @@ class Channel: else: return 1 - def is_power_of_two(self): - """Returns true if the size of this channel is a power of two.""" - return is_power_of_two(self.size) - def datatype(self): """Returns the datatype corresponding to a channel type and size""" return _get_datatype(self.type, self.size) diff --git a/src/mesa/main/format_utils.h b/src/mesa/main/format_utils.h index 7f500ec78da..618f43d0aaa 100644 --- a/src/mesa/main/format_utils.h +++ b/src/mesa/main/format_utils.h @@ -33,6 +33,7 @@ #include "imports.h" #include "macros.h" +#include "util/rounding.h" extern const mesa_array_format RGBA32_FLOAT; extern const mesa_array_format RGBA8_UBYTE; @@ -84,7 +85,7 @@ _mesa_float_to_unorm(float x, unsigned dst_bits) else if (x > 1.0f) return MAX_UINT(dst_bits); else - return F_TO_I(x * MAX_UINT(dst_bits)); + return _mesa_lroundevenf(x * MAX_UINT(dst_bits)); } static inline unsigned @@ -98,7 +99,7 @@ _mesa_unorm_to_unorm(unsigned x, unsigned src_bits, unsigned dst_bits) { if (src_bits < dst_bits) { return EXTEND_NORMALIZED_INT(x, src_bits, dst_bits); - } else { + } else if (src_bits > dst_bits) { unsigned src_half = (1 << (src_bits - 1)) - 1; if (src_bits + dst_bits > sizeof(x) * 8) { @@ -108,6 +109,8 @@ _mesa_unorm_to_unorm(unsigned x, unsigned src_bits, unsigned dst_bits) } else { return (x * MAX_UINT(dst_bits) + src_half) / MAX_UINT(src_bits); } + } else { + return x; } } @@ -128,7 +131,7 @@ _mesa_float_to_snorm(float x, unsigned dst_bits) else if (x > 1.0f) return MAX_INT(dst_bits); else - return F_TO_I(x * MAX_INT(dst_bits)); + return _mesa_lroundevenf(x * MAX_INT(dst_bits)); } static inline int diff --git a/src/mesa/main/formatquery.c b/src/mesa/main/formatquery.c index 7741cabada1..85f7b6b5664 100644 --- a/src/mesa/main/formatquery.c +++ b/src/mesa/main/formatquery.c @@ -74,13 +74,15 @@ _mesa_GetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, case GL_TEXTURE_2D_MULTISAMPLE: case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: /* These enums are only valid if ARB_texture_multisample is supported */ - if (_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_multisample) + if ((_mesa_is_desktop_gl(ctx) && + ctx->Extensions.ARB_texture_multisample) || + _mesa_is_gles31(ctx)) break; default: _mesa_error(ctx, GL_INVALID_ENUM, "glGetInternalformativ(target=%s)", - _mesa_lookup_enum_by_nr(target)); + _mesa_enum_to_string(target)); return; } @@ -107,7 +109,7 @@ _mesa_GetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, _mesa_base_fbo_format(ctx, internalformat) == 0) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetInternalformativ(internalformat=%s)", - _mesa_lookup_enum_by_nr(internalformat)); + _mesa_enum_to_string(internalformat)); return; } @@ -119,7 +121,7 @@ _mesa_GetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, if (bufSize < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetInternalformativ(target=%s)", - _mesa_lookup_enum_by_nr(target)); + _mesa_enum_to_string(target)); return; } @@ -168,7 +170,7 @@ _mesa_GetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, default: _mesa_error(ctx, GL_INVALID_ENUM, "glGetInternalformativ(pname=%s)", - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); return; } diff --git a/src/mesa/main/formats.c b/src/mesa/main/formats.c index baeb1bfe5de..d7b2bae59e7 100644 --- a/src/mesa/main/formats.c +++ b/src/mesa/main/formats.c @@ -354,14 +354,22 @@ _mesa_array_format_flip_channels(mesa_array_format format) return format; if (num_channels == 2) { - _mesa_array_format_set_swizzle(&format, swizzle[1], swizzle[0], - swizzle[2], swizzle[3]); + /* Assert that the swizzle makes sense for 2 channels */ + for (unsigned i = 0; i < 4; i++) + assert(swizzle[i] != 2 && swizzle[i] != 3); + + static const uint8_t flip_xy[6] = { 1, 0, 2, 3, 4, 5 }; + _mesa_array_format_set_swizzle(&format, + flip_xy[swizzle[0]], flip_xy[swizzle[1]], + flip_xy[swizzle[2]], flip_xy[swizzle[3]]); return format; } if (num_channels == 4) { - _mesa_array_format_set_swizzle(&format, swizzle[3], swizzle[2], - swizzle[1], swizzle[0]); + static const uint8_t flip[6] = { 3, 2, 1, 0, 4, 5 }; + _mesa_array_format_set_swizzle(&format, + flip[swizzle[0]], flip[swizzle[1]], + flip[swizzle[2]], flip[swizzle[3]]); return format; } @@ -372,10 +380,11 @@ uint32_t _mesa_format_to_array_format(mesa_format format) { const struct gl_format_info *info = _mesa_get_format_info(format); - if (_mesa_little_endian()) - return info->ArrayFormat; - else + if (info->ArrayFormat && !_mesa_little_endian() && + info->Layout == MESA_FORMAT_LAYOUT_PACKED) return _mesa_array_format_flip_channels(info->ArrayFormat); + else + return info->ArrayFormat; } static struct hash_table *format_array_format_table; diff --git a/src/mesa/main/formats.h b/src/mesa/main/formats.h index 7e451caf0ff..d938e6ad513 100644 --- a/src/mesa/main/formats.h +++ b/src/mesa/main/formats.h @@ -191,6 +191,11 @@ static inline void _mesa_array_format_set_swizzle(mesa_array_format *f, int32_t x, int32_t y, int32_t z, int32_t w) { + *f &= ~(MESA_ARRAY_FORMAT_SWIZZLE_X_MASK | + MESA_ARRAY_FORMAT_SWIZZLE_Y_MASK | + MESA_ARRAY_FORMAT_SWIZZLE_Z_MASK | + MESA_ARRAY_FORMAT_SWIZZLE_W_MASK); + *f |= ((x << 8 ) & MESA_ARRAY_FORMAT_SWIZZLE_X_MASK) | ((y << 11) & MESA_ARRAY_FORMAT_SWIZZLE_Y_MASK) | ((z << 14) & MESA_ARRAY_FORMAT_SWIZZLE_Z_MASK) | diff --git a/src/mesa/main/framebuffer.c b/src/mesa/main/framebuffer.c index 77c04b8dab8..37e2c29c89c 100644 --- a/src/mesa/main/framebuffer.c +++ b/src/mesa/main/framebuffer.c @@ -938,7 +938,7 @@ _mesa_print_framebuffer(const struct gl_framebuffer *fb) fprintf(stderr, "Mesa Framebuffer %u at %p\n", fb->Name, (void *) fb); fprintf(stderr, " Size: %u x %u Status: %s\n", fb->Width, fb->Height, - _mesa_lookup_enum_by_nr(fb->_Status)); + _mesa_enum_to_string(fb->_Status)); fprintf(stderr, " Attachments:\n"); for (i = 0; i < BUFFER_COUNT; i++) { diff --git a/src/mesa/main/genmipmap.c b/src/mesa/main/genmipmap.c index 9aef090194e..c18f9d5223f 100644 --- a/src/mesa/main/genmipmap.c +++ b/src/mesa/main/genmipmap.c @@ -83,7 +83,7 @@ _mesa_generate_texture_mipmap(struct gl_context *ctx, if (error) { _mesa_error(ctx, GL_INVALID_ENUM, "glGenerate%sMipmap(target=%s)", - suffix, _mesa_lookup_enum_by_nr(target)); + suffix, _mesa_enum_to_string(target)); return; } diff --git a/src/mesa/main/get.c b/src/mesa/main/get.c index 3d6d63916b3..307a5ffbd1c 100644 --- a/src/mesa/main/get.c +++ b/src/mesa/main/get.c @@ -149,6 +149,8 @@ enum value_extra { EXTRA_EXT_UBO_GS4, EXTRA_EXT_ATOMICS_GS4, EXTRA_EXT_SHADER_IMAGE_GS4, + EXTRA_EXT_ATOMICS_TESS, + EXTRA_EXT_SHADER_IMAGE_TESS, }; #define NO_EXTRA NULL @@ -349,12 +351,58 @@ static const int extra_ARB_shader_image_load_store_and_geometry_shader[] = { EXTRA_END }; +static const int extra_ARB_shader_atomic_counters_and_tessellation[] = { + EXTRA_EXT_ATOMICS_TESS, + EXTRA_END +}; + +static const int extra_ARB_shader_image_load_store_and_tessellation[] = { + EXTRA_EXT_SHADER_IMAGE_TESS, + EXTRA_END +}; + static const int extra_ARB_draw_indirect_es31[] = { EXT(ARB_draw_indirect), EXTRA_API_ES31, EXTRA_END }; +static const int extra_ARB_shader_image_load_store_es31[] = { + EXT(ARB_shader_image_load_store), + EXTRA_API_ES31, + EXTRA_END +}; + +static const int extra_ARB_shader_atomic_counters_es31[] = { + EXT(ARB_shader_atomic_counters), + EXTRA_API_ES31, + EXTRA_END +}; + +static const int extra_ARB_texture_multisample_es31[] = { + EXT(ARB_texture_multisample), + EXTRA_API_ES31, + EXTRA_END +}; + +static const int extra_ARB_texture_gather_es31[] = { + EXT(ARB_texture_gather), + EXTRA_API_ES31, + EXTRA_END +}; + +static const int extra_ARB_compute_shader_es31[] = { + EXT(ARB_compute_shader), + EXTRA_API_ES31, + EXTRA_END +}; + +static const int extra_ARB_explicit_uniform_location_es31[] = { + EXT(ARB_explicit_uniform_location), + EXTRA_API_ES31, + EXTRA_END +}; + EXTRA_EXT(ARB_texture_cube_map); EXTRA_EXT(EXT_texture_array); EXTRA_EXT(NV_fog_distance); @@ -401,6 +449,8 @@ EXTRA_EXT(ARB_explicit_uniform_location); EXTRA_EXT(ARB_clip_control); EXTRA_EXT(EXT_polygon_offset_clamp); EXTRA_EXT(ARB_framebuffer_no_attachments); +EXTRA_EXT(ARB_tessellation_shader); +EXTRA_EXT(ARB_shader_subroutine); static const int extra_ARB_color_buffer_float_or_glcore[] = { @@ -626,7 +676,7 @@ find_custom_value(struct gl_context *ctx, const struct value_desc *d, union valu break; case GL_EDGE_FLAG: - v->value_bool = ctx->Current.Attrib[VERT_ATTRIB_EDGEFLAG][0] == 1.0; + v->value_bool = ctx->Current.Attrib[VERT_ATTRIB_EDGEFLAG][0] == 1.0F; break; case GL_READ_BUFFER: @@ -1149,6 +1199,16 @@ check_extra(struct gl_context *ctx, const char *func, const struct value_desc *d api_found = (ctx->Extensions.ARB_shader_image_load_store && _mesa_has_geometry_shaders(ctx)); break; + case EXTRA_EXT_ATOMICS_TESS: + api_check = GL_TRUE; + api_found = ctx->Extensions.ARB_shader_atomic_counters && + _mesa_has_tessellation(ctx); + break; + case EXTRA_EXT_SHADER_IMAGE_TESS: + api_check = GL_TRUE; + api_found = ctx->Extensions.ARB_shader_image_load_store && + _mesa_has_tessellation(ctx); + break; case EXTRA_END: break; default: /* *e is a offset into the extension struct */ @@ -1161,7 +1221,7 @@ check_extra(struct gl_context *ctx, const char *func, const struct value_desc *d if (api_check && !api_found) { _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=%s)", func, - _mesa_lookup_enum_by_nr(d->pname)); + _mesa_enum_to_string(d->pname)); return GL_FALSE; } @@ -1208,10 +1268,13 @@ find_value(const char *func, GLenum pname, void **p, union value *v) * value since it's compatible with GLES2 its entry in table_set[] is at the * end. */ - STATIC_ASSERT(ARRAY_SIZE(table_set) == API_OPENGL_LAST + 2); + STATIC_ASSERT(ARRAY_SIZE(table_set) == API_OPENGL_LAST + 3); if (_mesa_is_gles3(ctx)) { api = API_OPENGL_LAST + 1; } + if (_mesa_is_gles31(ctx)) { + api = API_OPENGL_LAST + 2; + } mask = ARRAY_SIZE(table(api)) - 1; hash = (pname * prime_factor); while (1) { @@ -1222,7 +1285,7 @@ find_value(const char *func, GLenum pname, void **p, union value *v) * any valid enum. */ if (unlikely(idx == 0)) { _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=%s)", func, - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); return &error_value; } @@ -2004,11 +2067,11 @@ find_value_indexed(const char *func, GLenum pname, GLuint index, union value *v) invalid_enum: _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=%s)", func, - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); return TYPE_INVALID; invalid_value: _mesa_error(ctx, GL_INVALID_VALUE, "%s(pname=%s)", func, - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); return TYPE_INVALID; } diff --git a/src/mesa/main/get_hash_generator.py b/src/mesa/main/get_hash_generator.py index b200d197341..c777b782442 100644 --- a/src/mesa/main/get_hash_generator.py +++ b/src/mesa/main/get_hash_generator.py @@ -44,7 +44,7 @@ prime_factor = 89 prime_step = 281 hash_table_size = 1024 -gl_apis=set(["GL", "GL_CORE", "GLES", "GLES2", "GLES3"]) +gl_apis=set(["GL", "GL_CORE", "GLES", "GLES2", "GLES3", "GLES31"]) def print_header(): print "typedef const unsigned short table_t[%d];\n" % (hash_table_size) @@ -68,6 +68,7 @@ api_enum = [ 'GLES2', 'GL_CORE', 'GLES3', # Not in gl_api enum in mtypes.h + 'GLES31', # Not in gl_api enum in mtypes.h ] def api_index(api): @@ -167,10 +168,13 @@ def generate_hash_tables(enum_list, enabled_apis, param_descriptors): for api in valid_apis: add_to_hash_table(tables[api], hash_val, len(params)) - # Also add GLES2 items to the GLES3 hash table + # Also add GLES2 items to the GLES3 and GLES31 hash table if api == "GLES2": add_to_hash_table(tables["GLES3"], hash_val, len(params)) - + add_to_hash_table(tables["GLES31"], hash_val, len(params)) + # Also add GLES3 items to the GLES31 hash table + if api == "GLES3": + add_to_hash_table(tables["GLES31"], hash_val, len(params)) params.append(["GL_" + enum_name, param[1]]) sorted_tables={} @@ -206,7 +210,7 @@ if __name__ == '__main__': die("missing descriptor file (-f)\n") # generate the code for all APIs - enabled_apis = set(["GLES", "GLES2", "GLES3", "GL", "GL_CORE"]) + enabled_apis = set(["GLES", "GLES2", "GLES3", "GLES31", "GL", "GL_CORE"]) try: api_desc = gl_XML.parse_GL_API(api_desc_file) diff --git a/src/mesa/main/get_hash_params.py b/src/mesa/main/get_hash_params.py index 74ff3ba6619..7dc92f10100 100644 --- a/src/mesa/main/get_hash_params.py +++ b/src/mesa/main/get_hash_params.py @@ -351,6 +351,9 @@ descriptor=[ # GL_ARB_framebuffer_object [ "MAX_SAMPLES", "CONTEXT_INT(Const.MaxSamples), extra_ARB_framebuffer_object_EXT_framebuffer_multisample" ], +# GL_ARB_sampler_objects / GL 3.3 / GLES 3.0 + [ "SAMPLER_BINDING", "LOC_CUSTOM, TYPE_INT, GL_SAMPLER_BINDING, NO_EXTRA" ], + # GL_ARB_sync [ "MAX_SERVER_WAIT_TIMEOUT", "CONTEXT_INT64(Const.MaxServerWaitTimeout), extra_ARB_sync" ], @@ -404,9 +407,49 @@ descriptor=[ [ "TEXTURE_EXTERNAL_OES", "LOC_CUSTOM, TYPE_BOOLEAN, 0, extra_OES_EGL_image_external" ], ]}, -{ "apis": ["GL", "GL_CORE", "GLES3"], "params": [ -# GL_ARB_sampler_objects / GL 3.3 / GLES 3.0 - [ "SAMPLER_BINDING", "LOC_CUSTOM, TYPE_INT, GL_SAMPLER_BINDING, NO_EXTRA" ], +# Enums in OpenGL and ES 3.1 +{ "apis": ["GL", "GL_CORE", "GLES31"], "params": [ +# GL_ARB_shader_image_load_store / GLES 3.1 + [ "MAX_IMAGE_UNITS", "CONTEXT_INT(Const.MaxImageUnits), extra_ARB_shader_image_load_store_es31" ], + [ "MAX_VERTEX_IMAGE_UNIFORMS", "CONTEXT_INT(Const.Program[MESA_SHADER_VERTEX].MaxImageUniforms), extra_ARB_shader_image_load_store_es31" ], + [ "MAX_FRAGMENT_IMAGE_UNIFORMS", "CONTEXT_INT(Const.Program[MESA_SHADER_FRAGMENT].MaxImageUniforms), extra_ARB_shader_image_load_store_es31" ], + [ "MAX_COMBINED_IMAGE_UNIFORMS", "CONTEXT_INT(Const.MaxCombinedImageUniforms), extra_ARB_shader_image_load_store_es31" ], + +# GL_ARB_shader_atomic_counters / GLES 3.1 + [ "ATOMIC_COUNTER_BUFFER_BINDING", "LOC_CUSTOM, TYPE_INT, 0, extra_ARB_shader_atomic_counters_es31" ], + [ "MAX_ATOMIC_COUNTER_BUFFER_BINDINGS", "CONTEXT_INT(Const.MaxAtomicBufferBindings), extra_ARB_shader_atomic_counters_es31" ], + [ "MAX_ATOMIC_COUNTER_BUFFER_SIZE", "CONTEXT_INT(Const.MaxAtomicBufferSize), extra_ARB_shader_atomic_counters_es31" ], + [ "MAX_VERTEX_ATOMIC_COUNTER_BUFFERS", "CONTEXT_INT(Const.Program[MESA_SHADER_VERTEX].MaxAtomicBuffers), extra_ARB_shader_atomic_counters_es31" ], + [ "MAX_VERTEX_ATOMIC_COUNTERS", "CONTEXT_INT(Const.Program[MESA_SHADER_VERTEX].MaxAtomicCounters), extra_ARB_shader_atomic_counters_es31" ], + [ "MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS", "CONTEXT_INT(Const.Program[MESA_SHADER_FRAGMENT].MaxAtomicBuffers), extra_ARB_shader_atomic_counters_es31" ], + [ "MAX_FRAGMENT_ATOMIC_COUNTERS", "CONTEXT_INT(Const.Program[MESA_SHADER_FRAGMENT].MaxAtomicCounters), extra_ARB_shader_atomic_counters_es31" ], + [ "MAX_COMBINED_ATOMIC_COUNTER_BUFFERS", "CONTEXT_INT(Const.MaxCombinedAtomicBuffers), extra_ARB_shader_atomic_counters_es31" ], + [ "MAX_COMBINED_ATOMIC_COUNTERS", "CONTEXT_INT(Const.MaxCombinedAtomicCounters), extra_ARB_shader_atomic_counters_es31" ], + +# GL_ARB_texture_multisample / GLES 3.1 + [ "TEXTURE_BINDING_2D_MULTISAMPLE", "LOC_CUSTOM, TYPE_INT, TEXTURE_2D_MULTISAMPLE_INDEX, extra_ARB_texture_multisample_es31" ], + [ "MAX_COLOR_TEXTURE_SAMPLES", "CONTEXT_INT(Const.MaxColorTextureSamples), extra_ARB_texture_multisample_es31" ], + [ "MAX_DEPTH_TEXTURE_SAMPLES", "CONTEXT_INT(Const.MaxDepthTextureSamples), extra_ARB_texture_multisample_es31" ], + [ "MAX_INTEGER_SAMPLES", "CONTEXT_INT(Const.MaxIntegerSamples), extra_ARB_texture_multisample_es31" ], + [ "SAMPLE_MASK", "CONTEXT_BOOL(Multisample.SampleMask), extra_ARB_texture_multisample_es31" ], + [ "MAX_SAMPLE_MASK_WORDS", "CONST(1), extra_ARB_texture_multisample_es31" ], + +# GL_ARB_texture_gather / GLES 3.1 + [ "MIN_PROGRAM_TEXTURE_GATHER_OFFSET", "CONTEXT_INT(Const.MinProgramTextureGatherOffset), extra_ARB_texture_gather_es31"], + [ "MAX_PROGRAM_TEXTURE_GATHER_OFFSET", "CONTEXT_INT(Const.MaxProgramTextureGatherOffset), extra_ARB_texture_gather_es31"], + +# GL_ARB_compute_shader / GLES 3.1 + [ "MAX_COMPUTE_WORK_GROUP_INVOCATIONS", "CONTEXT_INT(Const.MaxComputeWorkGroupInvocations), extra_ARB_compute_shader_es31" ], + [ "MAX_COMPUTE_UNIFORM_BLOCKS", "CONST(MAX_COMPUTE_UNIFORM_BLOCKS), extra_ARB_compute_shader_es31" ], + [ "MAX_COMPUTE_TEXTURE_IMAGE_UNITS", "CONST(MAX_COMPUTE_TEXTURE_IMAGE_UNITS), extra_ARB_compute_shader_es31" ], + [ "MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS", "CONST(MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS), extra_ARB_compute_shader_es31" ], + [ "MAX_COMPUTE_ATOMIC_COUNTERS", "CONST(MAX_COMPUTE_ATOMIC_COUNTERS), extra_ARB_compute_shader_es31" ], + [ "MAX_COMPUTE_SHARED_MEMORY_SIZE", "CONST(MAX_COMPUTE_SHARED_MEMORY_SIZE), extra_ARB_compute_shader_es31" ], + [ "MAX_COMPUTE_UNIFORM_COMPONENTS", "CONST(MAX_COMPUTE_UNIFORM_COMPONENTS), extra_ARB_compute_shader_es31" ], + [ "MAX_COMPUTE_IMAGE_UNIFORMS", "CONST(MAX_COMPUTE_IMAGE_UNIFORMS), extra_ARB_compute_shader_es31" ], + +# GL_ARB_explicit_uniform_location / GLES 3.1 + [ "MAX_UNIFORM_LOCATIONS", "CONTEXT_INT(Const.MaxUserAssignableUniformLocations), extra_ARB_explicit_uniform_location_es31" ], ]}, # Enums in OpenGL Core profile and ES 3.1 @@ -498,7 +541,6 @@ descriptor=[ [ "MAX_LIST_NESTING", "CONST(MAX_LIST_NESTING), NO_EXTRA" ], [ "MAX_NAME_STACK_DEPTH", "CONST(MAX_NAME_STACK_DEPTH), NO_EXTRA" ], [ "MAX_PIXEL_MAP_TABLE", "CONST(MAX_PIXEL_MAP_TABLE), NO_EXTRA" ], - [ "MAX_UNIFORM_LOCATIONS", "CONTEXT_INT(Const.MaxUserAssignableUniformLocations), extra_ARB_explicit_uniform_location" ], [ "NAME_STACK_DEPTH", "CONTEXT_INT(Select.NameStackDepth), NO_EXTRA" ], [ "PACK_LSB_FIRST", "CONTEXT_BOOL(Pack.LsbFirst), NO_EXTRA" ], [ "PACK_SWAP_BYTES", "CONTEXT_BOOL(Pack.SwapBytes), NO_EXTRA" ], @@ -699,13 +741,7 @@ descriptor=[ [ "TEXTURE_BUFFER_ARB", "LOC_CUSTOM, TYPE_INT, 0, extra_texture_buffer_object" ], # GL_ARB_texture_multisample / GL 3.2 - [ "TEXTURE_BINDING_2D_MULTISAMPLE", "LOC_CUSTOM, TYPE_INT, TEXTURE_2D_MULTISAMPLE_INDEX, extra_ARB_texture_multisample" ], [ "TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY", "LOC_CUSTOM, TYPE_INT, TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX, extra_ARB_texture_multisample" ], - [ "MAX_COLOR_TEXTURE_SAMPLES", "CONTEXT_INT(Const.MaxColorTextureSamples), extra_ARB_texture_multisample" ], - [ "MAX_DEPTH_TEXTURE_SAMPLES", "CONTEXT_INT(Const.MaxDepthTextureSamples), extra_ARB_texture_multisample" ], - [ "MAX_INTEGER_SAMPLES", "CONTEXT_INT(Const.MaxIntegerSamples), extra_ARB_texture_multisample" ], - [ "SAMPLE_MASK", "CONTEXT_BOOL(Multisample.SampleMask), extra_ARB_texture_multisample" ], - [ "MAX_SAMPLE_MASK_WORDS", "CONST(1), extra_ARB_texture_multisample" ], # GL 3.0 [ "CONTEXT_FLAGS", "CONTEXT_INT(Const.ContextFlags), extra_version_30" ], @@ -756,48 +792,23 @@ descriptor=[ [ "TEXTURE_BINDING_CUBE_MAP_ARRAY_ARB", "LOC_CUSTOM, TYPE_INT, TEXTURE_CUBE_ARRAY_INDEX, extra_ARB_texture_cube_map_array" ], # GL_ARB_texture_gather - [ "MIN_PROGRAM_TEXTURE_GATHER_OFFSET", "CONTEXT_INT(Const.MinProgramTextureGatherOffset), extra_ARB_texture_gather"], - [ "MAX_PROGRAM_TEXTURE_GATHER_OFFSET", "CONTEXT_INT(Const.MaxProgramTextureGatherOffset), extra_ARB_texture_gather"], [ "MAX_PROGRAM_TEXTURE_GATHER_COMPONENTS_ARB", "CONTEXT_INT(Const.MaxProgramTextureGatherComponents), extra_ARB_texture_gather"], # GL_ARB_separate_shader_objects [ "PROGRAM_PIPELINE_BINDING", "LOC_CUSTOM, TYPE_INT, GL_PROGRAM_PIPELINE_BINDING, NO_EXTRA" ], # GL_ARB_shader_atomic_counters - [ "ATOMIC_COUNTER_BUFFER_BINDING", "LOC_CUSTOM, TYPE_INT, 0, extra_ARB_shader_atomic_counters" ], - [ "MAX_ATOMIC_COUNTER_BUFFER_BINDINGS", "CONTEXT_INT(Const.MaxAtomicBufferBindings), extra_ARB_shader_atomic_counters" ], - [ "MAX_ATOMIC_COUNTER_BUFFER_SIZE", "CONTEXT_INT(Const.MaxAtomicBufferSize), extra_ARB_shader_atomic_counters" ], - [ "MAX_VERTEX_ATOMIC_COUNTER_BUFFERS", "CONTEXT_INT(Const.Program[MESA_SHADER_VERTEX].MaxAtomicBuffers), extra_ARB_shader_atomic_counters" ], - [ "MAX_VERTEX_ATOMIC_COUNTERS", "CONTEXT_INT(Const.Program[MESA_SHADER_VERTEX].MaxAtomicCounters), extra_ARB_shader_atomic_counters" ], - [ "MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS", "CONTEXT_INT(Const.Program[MESA_SHADER_FRAGMENT].MaxAtomicBuffers), extra_ARB_shader_atomic_counters" ], - [ "MAX_FRAGMENT_ATOMIC_COUNTERS", "CONTEXT_INT(Const.Program[MESA_SHADER_FRAGMENT].MaxAtomicCounters), extra_ARB_shader_atomic_counters" ], [ "MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS", "CONTEXT_INT(Const.Program[MESA_SHADER_GEOMETRY].MaxAtomicBuffers), extra_ARB_shader_atomic_counters_and_geometry_shader" ], [ "MAX_GEOMETRY_ATOMIC_COUNTERS", "CONTEXT_INT(Const.Program[MESA_SHADER_GEOMETRY].MaxAtomicCounters), extra_ARB_shader_atomic_counters_and_geometry_shader" ], - [ "MAX_COMBINED_ATOMIC_COUNTER_BUFFERS", "CONTEXT_INT(Const.MaxCombinedAtomicBuffers), extra_ARB_shader_atomic_counters" ], - [ "MAX_COMBINED_ATOMIC_COUNTERS", "CONTEXT_INT(Const.MaxCombinedAtomicCounters), extra_ARB_shader_atomic_counters" ], # GL_ARB_vertex_attrib_binding [ "MAX_VERTEX_ATTRIB_RELATIVE_OFFSET", "CONTEXT_ENUM(Const.MaxVertexAttribRelativeOffset), NO_EXTRA" ], [ "MAX_VERTEX_ATTRIB_BINDINGS", "CONTEXT_ENUM(Const.MaxVertexAttribBindings), NO_EXTRA" ], # GL_ARB_shader_image_load_store - [ "MAX_IMAGE_UNITS", "CONTEXT_INT(Const.MaxImageUnits), extra_ARB_shader_image_load_store"], - [ "MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS", "CONTEXT_INT(Const.MaxCombinedImageUnitsAndFragmentOutputs), extra_ARB_shader_image_load_store"], - [ "MAX_IMAGE_SAMPLES", "CONTEXT_INT(Const.MaxImageSamples), extra_ARB_shader_image_load_store"], - [ "MAX_VERTEX_IMAGE_UNIFORMS", "CONTEXT_INT(Const.Program[MESA_SHADER_VERTEX].MaxImageUniforms), extra_ARB_shader_image_load_store"], + [ "MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS", "CONTEXT_INT(Const.MaxCombinedImageUnitsAndFragmentOutputs), extra_ARB_shader_image_load_store" ], + [ "MAX_IMAGE_SAMPLES", "CONTEXT_INT(Const.MaxImageSamples), extra_ARB_shader_image_load_store" ], [ "MAX_GEOMETRY_IMAGE_UNIFORMS", "CONTEXT_INT(Const.Program[MESA_SHADER_GEOMETRY].MaxImageUniforms), extra_ARB_shader_image_load_store_and_geometry_shader"], - [ "MAX_FRAGMENT_IMAGE_UNIFORMS", "CONTEXT_INT(Const.Program[MESA_SHADER_FRAGMENT].MaxImageUniforms), extra_ARB_shader_image_load_store"], - [ "MAX_COMBINED_IMAGE_UNIFORMS", "CONTEXT_INT(Const.MaxCombinedImageUniforms), extra_ARB_shader_image_load_store"], - -# GL_ARB_compute_shader - [ "MAX_COMPUTE_WORK_GROUP_INVOCATIONS", "CONTEXT_INT(Const.MaxComputeWorkGroupInvocations), extra_ARB_compute_shader" ], - [ "MAX_COMPUTE_UNIFORM_BLOCKS", "CONST(MAX_COMPUTE_UNIFORM_BLOCKS), extra_ARB_compute_shader" ], - [ "MAX_COMPUTE_TEXTURE_IMAGE_UNITS", "CONST(MAX_COMPUTE_TEXTURE_IMAGE_UNITS), extra_ARB_compute_shader" ], - [ "MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS", "CONST(MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS), extra_ARB_compute_shader" ], - [ "MAX_COMPUTE_ATOMIC_COUNTERS", "CONST(MAX_COMPUTE_ATOMIC_COUNTERS), extra_ARB_compute_shader" ], - [ "MAX_COMPUTE_SHARED_MEMORY_SIZE", "CONST(MAX_COMPUTE_SHARED_MEMORY_SIZE), extra_ARB_compute_shader" ], - [ "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_framebuffer_no_attachments ["MAX_FRAMEBUFFER_WIDTH", "CONTEXT_INT(Const.MaxFramebufferWidth), extra_ARB_framebuffer_no_attachments"], @@ -826,6 +837,38 @@ descriptor=[ [ "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_tessellation_shader + [ "PATCH_VERTICES", "CONTEXT_INT(TessCtrlProgram.patch_vertices), extra_ARB_tessellation_shader" ], + [ "PATCH_DEFAULT_OUTER_LEVEL", "CONTEXT_FLOAT4(TessCtrlProgram.patch_default_outer_level), extra_ARB_tessellation_shader" ], + [ "PATCH_DEFAULT_INNER_LEVEL", "CONTEXT_FLOAT2(TessCtrlProgram.patch_default_inner_level), extra_ARB_tessellation_shader" ], + [ "MAX_TESS_GEN_LEVEL", "CONTEXT_INT(Const.MaxTessGenLevel), extra_ARB_tessellation_shader" ], + [ "MAX_PATCH_VERTICES", "CONTEXT_INT(Const.MaxPatchVertices), extra_ARB_tessellation_shader" ], + [ "MAX_TESS_CONTROL_UNIFORM_COMPONENTS", "CONTEXT_INT(Const.Program[MESA_SHADER_TESS_CTRL].MaxUniformComponents), extra_ARB_tessellation_shader" ], + [ "MAX_TESS_EVALUATION_UNIFORM_COMPONENTS", "CONTEXT_INT(Const.Program[MESA_SHADER_TESS_EVAL].MaxUniformComponents), extra_ARB_tessellation_shader" ], + [ "MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS", "CONTEXT_INT(Const.Program[MESA_SHADER_TESS_CTRL].MaxTextureImageUnits), extra_ARB_tessellation_shader" ], + [ "MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS", "CONTEXT_INT(Const.Program[MESA_SHADER_TESS_EVAL].MaxTextureImageUnits), extra_ARB_tessellation_shader" ], + [ "MAX_TESS_CONTROL_OUTPUT_COMPONENTS", "CONTEXT_INT(Const.Program[MESA_SHADER_TESS_CTRL].MaxOutputComponents), extra_ARB_tessellation_shader" ], + [ "MAX_TESS_PATCH_COMPONENTS", "CONTEXT_INT(Const.MaxTessPatchComponents), extra_ARB_tessellation_shader" ], + [ "MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS", "CONTEXT_INT(Const.MaxTessControlTotalOutputComponents), extra_ARB_tessellation_shader" ], + [ "MAX_TESS_EVALUATION_OUTPUT_COMPONENTS", "CONTEXT_INT(Const.Program[MESA_SHADER_TESS_EVAL].MaxOutputComponents), extra_ARB_tessellation_shader" ], + [ "MAX_TESS_CONTROL_INPUT_COMPONENTS", "CONTEXT_INT(Const.Program[MESA_SHADER_TESS_CTRL].MaxInputComponents), extra_ARB_tessellation_shader" ], + [ "MAX_TESS_EVALUATION_INPUT_COMPONENTS", "CONTEXT_INT(Const.Program[MESA_SHADER_TESS_EVAL].MaxInputComponents), extra_ARB_tessellation_shader" ], + [ "MAX_TESS_CONTROL_UNIFORM_BLOCKS", "CONTEXT_INT(Const.Program[MESA_SHADER_TESS_CTRL].MaxUniformBlocks), extra_ARB_tessellation_shader" ], + [ "MAX_TESS_EVALUATION_UNIFORM_BLOCKS", "CONTEXT_INT(Const.Program[MESA_SHADER_TESS_EVAL].MaxUniformBlocks), extra_ARB_tessellation_shader" ], + [ "MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS", "CONTEXT_INT(Const.Program[MESA_SHADER_TESS_CTRL].MaxCombinedUniformComponents), extra_ARB_tessellation_shader" ], + [ "MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS", "CONTEXT_INT(Const.Program[MESA_SHADER_TESS_EVAL].MaxCombinedUniformComponents), extra_ARB_tessellation_shader" ], +# Dependencies on GL_ARB_tessellation_shader + [ "MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS", "CONTEXT_INT(Const.Program[MESA_SHADER_TESS_CTRL].MaxAtomicBuffers), extra_ARB_shader_atomic_counters_and_tessellation" ], + [ "MAX_TESS_CONTROL_ATOMIC_COUNTERS", "CONTEXT_INT(Const.Program[MESA_SHADER_TESS_CTRL].MaxAtomicCounters), extra_ARB_shader_atomic_counters_and_tessellation" ], + [ "MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS", "CONTEXT_INT(Const.Program[MESA_SHADER_TESS_EVAL].MaxAtomicBuffers), extra_ARB_shader_atomic_counters_and_tessellation" ], + [ "MAX_TESS_EVALUATION_ATOMIC_COUNTERS", "CONTEXT_INT(Const.Program[MESA_SHADER_TESS_EVAL].MaxAtomicCounters), extra_ARB_shader_atomic_counters_and_tessellation" ], + [ "MAX_TESS_CONTROL_IMAGE_UNIFORMS", "CONTEXT_INT(Const.Program[MESA_SHADER_TESS_CTRL].MaxImageUniforms), extra_ARB_shader_image_load_store_and_tessellation"], + [ "MAX_TESS_EVALUATION_IMAGE_UNIFORMS", "CONTEXT_INT(Const.Program[MESA_SHADER_TESS_EVAL].MaxImageUniforms), extra_ARB_shader_image_load_store_and_tessellation"], + +# GL_ARB_shader_subroutine + [ "MAX_SUBROUTINES", "CONST(MAX_SUBROUTINES), extra_ARB_shader_subroutine" ], + [ "MAX_SUBROUTINE_UNIFORM_LOCATIONS", "CONST(MAX_SUBROUTINE_UNIFORM_LOCATIONS), extra_ARB_shader_subroutine" ], ]} ] diff --git a/src/mesa/main/getstring.c b/src/mesa/main/getstring.c index 72d99ca4e22..9873fdbf1a4 100644 --- a/src/mesa/main/getstring.c +++ b/src/mesa/main/getstring.c @@ -208,7 +208,7 @@ _mesa_GetPointerv( GLenum pname, GLvoid **params ) return; if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glGetPointerv %s\n", _mesa_lookup_enum_by_nr(pname)); + _mesa_debug(ctx, "glGetPointerv %s\n", _mesa_enum_to_string(pname)); switch (pname) { case GL_VERTEX_ARRAY_POINTER: @@ -299,7 +299,7 @@ _mesa_GetError( void ) ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0); if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glGetError <-- %s\n", _mesa_lookup_enum_by_nr(e)); + _mesa_debug(ctx, "glGetError <-- %s\n", _mesa_enum_to_string(e)); ctx->ErrorValue = (GLenum) GL_NO_ERROR; ctx->ErrorDebugCount = 0; diff --git a/src/mesa/main/glformats.c b/src/mesa/main/glformats.c index ac69fabccaa..3eb66dab7f8 100644 --- a/src/mesa/main/glformats.c +++ b/src/mesa/main/glformats.c @@ -186,7 +186,7 @@ get_map_idx(GLenum value) return IDX_RG; default: _mesa_problem(NULL, "Unexpected inFormat %s", - _mesa_lookup_enum_by_nr(value)); + _mesa_enum_to_string(value)); return 0; } } @@ -216,8 +216,8 @@ _mesa_compute_component_mapping(GLenum inFormat, GLenum outFormat, GLubyte *map) #if 0 printf("from %x/%s to %x/%s map %d %d %d %d %d %d\n", - inFormat, _mesa_lookup_enum_by_nr(inFormat), - outFormat, _mesa_lookup_enum_by_nr(outFormat), + inFormat, _mesa_enum_to_string(inFormat), + outFormat, _mesa_enum_to_string(outFormat), map[0], map[1], map[2], @@ -1278,9 +1278,53 @@ _mesa_is_compressed_format(const struct gl_context *ctx, GLenum format) } } +/** + * Convert various unpack formats to the corresponding base format. + */ +GLenum +_mesa_unpack_format_to_base_format(GLenum format) +{ + switch(format) { + case GL_RED_INTEGER: + return GL_RED; + case GL_GREEN_INTEGER: + return GL_GREEN; + case GL_BLUE_INTEGER: + return GL_BLUE; + case GL_ALPHA_INTEGER: + return GL_ALPHA; + case GL_RG_INTEGER: + return GL_RG; + case GL_RGB_INTEGER: + return GL_RGB; + case GL_RGBA_INTEGER: + return GL_RGBA; + case GL_BGR_INTEGER: + return GL_BGR; + case GL_BGRA_INTEGER: + return GL_BGRA; + case GL_LUMINANCE_INTEGER_EXT: + return GL_LUMINANCE; + case GL_LUMINANCE_ALPHA_INTEGER_EXT: + return GL_LUMINANCE_ALPHA; + case GL_RED: + case GL_GREEN: + case GL_BLUE: + case GL_RG: + case GL_RGB: + case GL_RGBA: + case GL_BGR: + case GL_BGRA: + case GL_ALPHA: + case GL_LUMINANCE: + case GL_LUMINANCE_ALPHA: + default: + return format; + } +} /** - * Convert various base formats to the cooresponding integer format. + * Convert various base formats to the corresponding integer format. */ GLenum _mesa_base_format_to_integer_format(GLenum format) @@ -2605,8 +2649,6 @@ get_swizzle_from_gl_format(GLenum format, uint8_t *swizzle) uint32_t _mesa_format_from_format_and_type(GLenum format, GLenum type) { - mesa_array_format array_format; - bool is_array_format = true; uint8_t swizzle[4]; bool normalized = false, is_float = false, is_signed = false; @@ -2662,15 +2704,9 @@ _mesa_format_from_format_and_type(GLenum format, GLenum type) normalized = !_mesa_is_enum_format_integer(format); num_channels = _mesa_components_in_format(format); - array_format = - MESA_ARRAY_FORMAT(type_size, is_signed, is_float, - normalized, num_channels, - swizzle[0], swizzle[1], swizzle[2], swizzle[3]); - - if (!_mesa_little_endian()) - array_format = _mesa_array_format_flip_channels(array_format); - - return array_format; + return MESA_ARRAY_FORMAT(type_size, is_signed, is_float, + normalized, num_channels, + swizzle[0], swizzle[1], swizzle[2], swizzle[3]); } /* Otherwise this is not an array format, so return the mesa_format diff --git a/src/mesa/main/glformats.h b/src/mesa/main/glformats.h index 8881cb7d86b..419955a6033 100644 --- a/src/mesa/main/glformats.h +++ b/src/mesa/main/glformats.h @@ -101,6 +101,9 @@ _mesa_is_compressed_format(const struct gl_context *ctx, GLenum format); extern GLenum _mesa_base_format_to_integer_format(GLenum format); +extern GLenum +_mesa_unpack_format_to_base_format(GLenum format); + extern GLboolean _mesa_base_format_has_channel(GLenum base_format, GLenum pname); diff --git a/src/mesa/main/hint.c b/src/mesa/main/hint.c index 3e056ebaf13..984239a7276 100644 --- a/src/mesa/main/hint.c +++ b/src/mesa/main/hint.c @@ -40,8 +40,8 @@ _mesa_Hint( GLenum target, GLenum mode ) if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glHint %s %s\n", - _mesa_lookup_enum_by_nr(target), - _mesa_lookup_enum_by_nr(mode)); + _mesa_enum_to_string(target), + _mesa_enum_to_string(mode)); if (mode != GL_NICEST && mode != GL_FASTEST && mode != GL_DONT_CARE) { _mesa_error(ctx, GL_INVALID_ENUM, "glHint(mode)"); diff --git a/src/mesa/main/imports.c b/src/mesa/main/imports.c index 68c7316575c..350e6752c8b 100644 --- a/src/mesa/main/imports.c +++ b/src/mesa/main/imports.c @@ -369,7 +369,7 @@ _mesa_float_to_half(float val) * or normal. */ e = 0; - m = (int) _mesa_roundevenf((1 << 24) * fabsf(fi.f)); + m = _mesa_lroundevenf((1 << 24) * fabsf(fi.f)); } else if (new_exp > 15) { /* map this value to infinity */ @@ -383,7 +383,7 @@ _mesa_float_to_half(float val) * either normal or infinite. */ e = new_exp + 15; - m = (int) _mesa_roundevenf(flt_m / (float) (1 << 13)); + m = _mesa_lroundevenf(flt_m / (float) (1 << 13)); } } diff --git a/src/mesa/main/imports.h b/src/mesa/main/imports.h index 9ffe3decd0f..d61279ac4e5 100644 --- a/src/mesa/main/imports.h +++ b/src/mesa/main/imports.h @@ -170,34 +170,6 @@ static inline int IROUND_POS(float f) return (int) (f + 0.5F); } -#ifdef __x86_64__ -# include <xmmintrin.h> -#endif - -/** - * Convert float to int using a fast method. The rounding mode may vary. - */ -static inline int F_TO_I(float f) -{ -#if defined(USE_X86_ASM) && defined(__GNUC__) && defined(__i386__) - int r; - __asm__ ("fistpl %0" : "=m" (r) : "t" (f) : "st"); - return r; -#elif defined(USE_X86_ASM) && defined(_MSC_VER) - int r; - _asm { - fld f - fistp r - } - return r; -#elif defined(__x86_64__) - return _mm_cvt_ss2si(_mm_load_ss(&f)); -#else - return IROUND(f); -#endif -} - - /** Return (as an integer) floor of float */ static inline int IFLOOR(float f) { diff --git a/src/mesa/main/light.c b/src/mesa/main/light.c index 4021dbef922..14b4b04162b 100644 --- a/src/mesa/main/light.c +++ b/src/mesa/main/light.c @@ -42,16 +42,16 @@ _mesa_ShadeModel( GLenum mode ) GET_CURRENT_CONTEXT(ctx); if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glShadeModel %s\n", _mesa_lookup_enum_by_nr(mode)); + _mesa_debug(ctx, "glShadeModel %s\n", _mesa_enum_to_string(mode)); + + if (ctx->Light.ShadeModel == mode) + return; if (mode != GL_FLAT && mode != GL_SMOOTH) { _mesa_error(ctx, GL_INVALID_ENUM, "glShadeModel"); return; } - if (ctx->Light.ShadeModel == mode) - return; - FLUSH_VERTICES(ctx, _NEW_LIGHT); ctx->Light.ShadeModel = mode; @@ -143,7 +143,7 @@ _mesa_light(struct gl_context *ctx, GLuint lnum, GLenum pname, const GLfloat *pa COPY_3V(light->SpotDirection, params); break; case GL_SPOT_EXPONENT: - assert(params[0] >= 0.0); + assert(params[0] >= 0.0F); assert(params[0] <= ctx->Const.MaxSpotExponent); if (light->SpotExponent == params[0]) return; @@ -151,12 +151,12 @@ _mesa_light(struct gl_context *ctx, GLuint lnum, GLenum pname, const GLfloat *pa light->SpotExponent = params[0]; break; case GL_SPOT_CUTOFF: - assert(params[0] == 180.0 || (params[0] >= 0.0 && params[0] <= 90.0)); + assert(params[0] == 180.0F || (params[0] >= 0.0F && params[0] <= 90.0F)); if (light->SpotCutoff == params[0]) return; FLUSH_VERTICES(ctx, _NEW_LIGHT); light->SpotCutoff = params[0]; - light->_CosCutoff = (GLfloat) (cos(light->SpotCutoff * M_PI / 180.0)); + light->_CosCutoff = (cosf(light->SpotCutoff * M_PI / 180.0)); if (light->_CosCutoff < 0) light->_CosCutoff = 0; if (light->SpotCutoff != 180.0F) @@ -165,21 +165,21 @@ _mesa_light(struct gl_context *ctx, GLuint lnum, GLenum pname, const GLfloat *pa light->_Flags &= ~LIGHT_SPOT; break; case GL_CONSTANT_ATTENUATION: - assert(params[0] >= 0.0); + assert(params[0] >= 0.0F); if (light->ConstantAttenuation == params[0]) return; FLUSH_VERTICES(ctx, _NEW_LIGHT); light->ConstantAttenuation = params[0]; break; case GL_LINEAR_ATTENUATION: - assert(params[0] >= 0.0); + assert(params[0] >= 0.0F); if (light->LinearAttenuation == params[0]) return; FLUSH_VERTICES(ctx, _NEW_LIGHT); light->LinearAttenuation = params[0]; break; case GL_QUADRATIC_ATTENUATION: - assert(params[0] >= 0.0); + assert(params[0] >= 0.0F); if (light->QuadraticAttenuation == params[0]) return; FLUSH_VERTICES(ctx, _NEW_LIGHT); @@ -238,31 +238,31 @@ _mesa_Lightfv( GLenum light, GLenum pname, const GLfloat *params ) params = temp; break; case GL_SPOT_EXPONENT: - if (params[0] < 0.0 || params[0] > ctx->Const.MaxSpotExponent) { + if (params[0] < 0.0F || params[0] > ctx->Const.MaxSpotExponent) { _mesa_error(ctx, GL_INVALID_VALUE, "glLight"); return; } break; case GL_SPOT_CUTOFF: - if ((params[0] < 0.0 || params[0] > 90.0) && params[0] != 180.0) { + if ((params[0] < 0.0F || params[0] > 90.0F) && params[0] != 180.0F) { _mesa_error(ctx, GL_INVALID_VALUE, "glLight"); return; } break; case GL_CONSTANT_ATTENUATION: - if (params[0] < 0.0) { + if (params[0] < 0.0F) { _mesa_error(ctx, GL_INVALID_VALUE, "glLight"); return; } break; case GL_LINEAR_ATTENUATION: - if (params[0] < 0.0) { + if (params[0] < 0.0F) { _mesa_error(ctx, GL_INVALID_VALUE, "glLight"); return; } break; case GL_QUADRATIC_ATTENUATION: - if (params[0] < 0.0) { + if (params[0] < 0.0F) { _mesa_error(ctx, GL_INVALID_VALUE, "glLight"); return; } @@ -463,14 +463,14 @@ _mesa_LightModelfv( GLenum pname, const GLfloat *params ) case GL_LIGHT_MODEL_LOCAL_VIEWER: if (ctx->API != API_OPENGL_COMPAT) goto invalid_pname; - newbool = (params[0]!=0.0); + newbool = (params[0] != 0.0F); if (ctx->Light.Model.LocalViewer == newbool) return; FLUSH_VERTICES(ctx, _NEW_LIGHT); ctx->Light.Model.LocalViewer = newbool; break; case GL_LIGHT_MODEL_TWO_SIDE: - newbool = (params[0]!=0.0); + newbool = (params[0] != 0.0F); if (ctx->Light.Model.TwoSide == newbool) return; FLUSH_VERTICES(ctx, _NEW_LIGHT); @@ -723,8 +723,8 @@ _mesa_ColorMaterial( GLenum face, GLenum mode ) if (MESA_VERBOSE&VERBOSE_API) _mesa_debug(ctx, "glColorMaterial %s %s\n", - _mesa_lookup_enum_by_nr(face), - _mesa_lookup_enum_by_nr(mode)); + _mesa_enum_to_string(face), + _mesa_enum_to_string(mode)); bitmask = _mesa_material_bitmask(ctx, face, mode, legal, "glColorMaterial"); if (bitmask == 0) @@ -975,7 +975,7 @@ compute_light_positions( struct gl_context *ctx ) } else { /* positional light w/ homogeneous coordinate, divide by W */ - GLfloat wInv = (GLfloat)1.0 / light->_Position[3]; + GLfloat wInv = 1.0F / light->_Position[3]; light->_Position[0] *= wInv; light->_Position[1] *= wInv; light->_Position[2] *= wInv; @@ -1024,7 +1024,7 @@ update_modelview_scale( struct gl_context *ctx ) if (!_math_matrix_is_length_preserving(ctx->ModelviewMatrixStack.Top)) { const GLfloat *m = ctx->ModelviewMatrixStack.Top->inv; GLfloat f = m[2] * m[2] + m[6] * m[6] + m[10] * m[10]; - if (f < 1e-12) f = 1.0; + if (f < 1e-12f) f = 1.0f; if (ctx->_NeedEyeCoords) ctx->_ModelViewInvScale = 1.0f / sqrtf(f); else diff --git a/src/mesa/main/lines.c b/src/mesa/main/lines.c index 3c08ed2e713..c020fb3eb9e 100644 --- a/src/mesa/main/lines.c +++ b/src/mesa/main/lines.c @@ -45,7 +45,7 @@ _mesa_LineWidth( GLfloat width ) if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glLineWidth %f\n", width); - if (width<=0.0) { + if (width <= 0.0F) { _mesa_error( ctx, GL_INVALID_VALUE, "glLineWidth" ); return; } @@ -63,7 +63,7 @@ _mesa_LineWidth( GLfloat width ) if (ctx->API == API_OPENGL_CORE && ((ctx->Const.ContextFlags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT) != 0) - && width > 1.0) { + && width > 1.0F) { _mesa_error( ctx, GL_INVALID_VALUE, "glLineWidth" ); return; } diff --git a/src/mesa/main/macros.h b/src/mesa/main/macros.h index 0608650aeb4..54df50c9cfe 100644 --- a/src/mesa/main/macros.h +++ b/src/mesa/main/macros.h @@ -33,6 +33,7 @@ #include "util/macros.h" #include "util/u_math.h" +#include "util/rounding.h" #include "imports.h" @@ -131,12 +132,12 @@ extern GLfloat _mesa_ubyte_to_float_color_tab[256]; #define INT_TO_USHORT(i) ((i) < 0 ? 0 : ((GLushort) ((i) >> 15))) #define UINT_TO_USHORT(i) ((i) < 0 ? 0 : ((GLushort) ((i) >> 16))) #define UNCLAMPED_FLOAT_TO_USHORT(us, f) \ - us = ( (GLushort) F_TO_I( CLAMP((f), 0.0F, 1.0F) * 65535.0F) ) + us = ( (GLushort) _mesa_lroundevenf( CLAMP((f), 0.0F, 1.0F) * 65535.0F) ) #define CLAMPED_FLOAT_TO_USHORT(us, f) \ - us = ( (GLushort) F_TO_I( (f) * 65535.0F) ) + us = ( (GLushort) _mesa_lroundevenf( (f) * 65535.0F) ) #define UNCLAMPED_FLOAT_TO_SHORT(s, f) \ - s = ( (GLshort) F_TO_I( CLAMP((f), -1.0F, 1.0F) * 32767.0F) ) + s = ( (GLshort) _mesa_lroundevenf( CLAMP((f), -1.0F, 1.0F) * 32767.0F) ) /*** *** UNCLAMPED_FLOAT_TO_UBYTE: clamp float to [0,1] and map to ubyte in [0,255] @@ -167,9 +168,9 @@ extern GLfloat _mesa_ubyte_to_float_color_tab[256]; } while (0) #else #define UNCLAMPED_FLOAT_TO_UBYTE(ub, f) \ - ub = ((GLubyte) F_TO_I(CLAMP((f), 0.0F, 1.0F) * 255.0F)) + ub = ((GLubyte) _mesa_lroundevenf(CLAMP((f), 0.0F, 1.0F) * 255.0F)) #define CLAMPED_FLOAT_TO_UBYTE(ub, f) \ - ub = ((GLubyte) F_TO_I((f) * 255.0F)) + ub = ((GLubyte) _mesa_lroundevenf((f) * 255.0F)) #endif static fi_type UINT_AS_UNION(GLuint u) @@ -679,17 +680,6 @@ minify(unsigned value, unsigned levels) } /** - * Return true if the given value is a power of two. - * - * Note that this considers 0 a power of two. - */ -static inline bool -is_power_of_two(unsigned value) -{ - return (value & (value - 1)) == 0; -} - -/** * Align a value up to an alignment value * * If \c value is not already aligned to the requested alignment value, it diff --git a/src/mesa/main/matrix.c b/src/mesa/main/matrix.c index 80c8a248ce4..2b8016a4a72 100644 --- a/src/mesa/main/matrix.c +++ b/src/mesa/main/matrix.c @@ -229,7 +229,7 @@ _mesa_PushMatrix( void ) if (MESA_VERBOSE&VERBOSE_API) _mesa_debug(ctx, "glPushMatrix %s\n", - _mesa_lookup_enum_by_nr(ctx->Transform.MatrixMode)); + _mesa_enum_to_string(ctx->Transform.MatrixMode)); if (stack->Depth + 1 >= stack->MaxDepth) { if (ctx->Transform.MatrixMode == GL_TEXTURE) { @@ -239,7 +239,7 @@ _mesa_PushMatrix( void ) } else { _mesa_error(ctx, GL_STACK_OVERFLOW, "glPushMatrix(mode=%s)", - _mesa_lookup_enum_by_nr(ctx->Transform.MatrixMode)); + _mesa_enum_to_string(ctx->Transform.MatrixMode)); } return; } @@ -270,7 +270,7 @@ _mesa_PopMatrix( void ) if (MESA_VERBOSE&VERBOSE_API) _mesa_debug(ctx, "glPopMatrix %s\n", - _mesa_lookup_enum_by_nr(ctx->Transform.MatrixMode)); + _mesa_enum_to_string(ctx->Transform.MatrixMode)); if (stack->Depth == 0) { if (ctx->Transform.MatrixMode == GL_TEXTURE) { @@ -280,7 +280,7 @@ _mesa_PopMatrix( void ) } else { _mesa_error(ctx, GL_STACK_UNDERFLOW, "glPopMatrix(mode=%s)", - _mesa_lookup_enum_by_nr(ctx->Transform.MatrixMode)); + _mesa_enum_to_string(ctx->Transform.MatrixMode)); } return; } diff --git a/src/mesa/main/mipmap.c b/src/mesa/main/mipmap.c index 7732d09b2ec..1e22f930092 100644 --- a/src/mesa/main/mipmap.c +++ b/src/mesa/main/mipmap.c @@ -2077,9 +2077,12 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target, /* Get the uncompressed image */ assert(srcImage->Level == texObj->BaseLevel); - ctx->Driver.GetTexImage(ctx, - temp_base_format, temp_datatype, - temp_src, srcImage); + ctx->Driver.GetTexSubImage(ctx, + 0, 0, 0, + srcImage->Width, srcImage->Height, + srcImage->Depth, + temp_base_format, temp_datatype, + temp_src, srcImage); /* restore packing mode */ ctx->Pack = save; } diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 2d285b87a78..83f3717754d 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -90,7 +90,7 @@ struct vbo_context; /** Extra draw modes beyond GL_POINTS, GL_TRIANGLE_FAN, etc */ -#define PRIM_MAX GL_TRIANGLE_STRIP_ADJACENCY +#define PRIM_MAX GL_PATCHES #define PRIM_OUTSIDE_BEGIN_END (PRIM_MAX + 1) #define PRIM_UNKNOWN (PRIM_MAX + 2) @@ -109,6 +109,8 @@ _mesa_varying_slot_in_fs(gl_varying_slot slot) case VARYING_SLOT_EDGE: case VARYING_SLOT_CLIP_VERTEX: case VARYING_SLOT_LAYER: + case VARYING_SLOT_TESS_LEVEL_OUTER: + case VARYING_SLOT_TESS_LEVEL_INNER: return GL_FALSE; default: return GL_TRUE; @@ -1254,6 +1256,7 @@ typedef enum { USAGE_UNIFORM_BUFFER = 0x1, USAGE_TEXTURE_BUFFER = 0x2, USAGE_ATOMIC_COUNTER_BUFFER = 0x4, + USAGE_SHADER_STORAGE_BUFFER = 0x8, } gl_buffer_usage; @@ -1654,6 +1657,11 @@ struct gl_transform_feedback_info * multiple transform feedback outputs in the same buffer. */ unsigned BufferStride[MAX_FEEDBACK_BUFFERS]; + + /** + * Which transform feedback stream this buffer binding is associated with. + */ + unsigned BufferStream[MAX_FEEDBACK_BUFFERS]; }; @@ -1891,6 +1899,8 @@ struct gl_program GLbitfield64 InputsRead; /**< Bitmask of which input regs are read */ GLbitfield64 DoubleInputsRead; /**< Bitmask of which input regs are read and are doubles */ GLbitfield64 OutputsWritten; /**< Bitmask of which output regs are written */ + GLbitfield PatchInputsRead; /**< VAR[0..31] usage for patch inputs (user-defined only) */ + GLbitfield PatchOutputsWritten; /**< VAR[0..31] usage for patch outputs (user-defined only) */ GLbitfield SystemValuesRead; /**< Bitmask of SYSTEM_VALUE_x inputs used */ GLbitfield TexturesUsed[MAX_COMBINED_TEXTURE_IMAGE_UNITS]; /**< TEXTURE_x_BIT bitmask */ GLbitfield SamplersUsed; /**< Bitfield of which samplers are used */ @@ -1958,6 +1968,29 @@ struct gl_vertex_program }; +/** Tessellation control program object */ +struct gl_tess_ctrl_program +{ + struct gl_program Base; /**< base class */ + + /* output layout */ + GLint VerticesOut; +}; + + +/** Tessellation evaluation program object */ +struct gl_tess_eval_program +{ + struct gl_program Base; /**< base class */ + + /* input layout */ + GLenum PrimitiveMode; /* GL_TRIANGLES, GL_QUADS or GL_ISOLINES */ + GLenum Spacing; /* GL_EQUAL, GL_FRACTIONAL_EVEN, GL_FRACTIONAL_ODD */ + GLenum VertexOrder; /* GL_CW or GL_CCW */ + bool PointMode; +}; + + /** Geometry program object */ struct gl_geometry_program { @@ -2060,6 +2093,27 @@ struct gl_vertex_program_state GLboolean _Overriden; }; +/** + * Context state for tessellation control programs. + */ +struct gl_tess_ctrl_program_state +{ + /** Currently bound and valid shader. */ + struct gl_tess_ctrl_program *_Current; + + GLint patch_vertices; + GLfloat patch_default_outer_level[4]; + GLfloat patch_default_inner_level[2]; +}; + +/** + * Context state for tessellation evaluation programs. + */ +struct gl_tess_eval_program_state +{ + /** Currently bound and valid shader. */ + struct gl_tess_eval_program *_Current; +}; /** * Context state for geometry programs. @@ -2154,13 +2208,23 @@ struct gl_ati_fragment_shader_state struct ati_fragment_shader *Current; }; +/** + * Shader subroutine function definition + */ +struct gl_subroutine_function +{ + char *name; + int num_compat_types; + const struct glsl_type **types; +}; /** * A GLSL vertex or fragment shader object. */ struct gl_shader { - /** GL_FRAGMENT_SHADER || GL_VERTEX_SHADER || GL_GEOMETRY_SHADER_ARB. + /** GL_FRAGMENT_SHADER || GL_VERTEX_SHADER || GL_GEOMETRY_SHADER_ARB || + * GL_TESS_CONTROL_SHADER || GL_TESS_EVALUATION_SHADER. * Must be the first field. */ GLenum Type; @@ -2240,6 +2304,41 @@ struct gl_shader bool pixel_center_integer; /** + * Tessellation Control shader state from layout qualifiers. + */ + struct { + /** + * 0 - vertices not declared in shader, or + * 1 .. GL_MAX_PATCH_VERTICES + */ + GLint VerticesOut; + } TessCtrl; + + /** + * Tessellation Evaluation shader state from layout qualifiers. + */ + struct { + /** + * GL_TRIANGLES, GL_QUADS, GL_ISOLINES or PRIM_UNKNOWN if it's not set + * in this shader. + */ + GLenum PrimitiveMode; + /** + * GL_EQUAL, GL_FRACTIONAL_ODD, GL_FRACTIONAL_EVEN, or 0 if it's not set + * in this shader. + */ + GLenum Spacing; + /** + * GL_CW, GL_CCW, or 0 if it's not set in this shader. + */ + GLenum VertexOrder; + /** + * 1, 0, or -1 if it's not set in this shader. + */ + int PointMode; + } TessEval; + + /** * Geometry shader state from GLSL 1.50 layout qualifiers. */ struct { @@ -2304,6 +2403,25 @@ struct gl_shader */ unsigned LocalSize[3]; } Comp; + + /** + * Number of types for subroutine uniforms. + */ + GLuint NumSubroutineUniformTypes; + + /** + * Subroutine uniform remap table + * based on the program level uniform remap table. + */ + GLuint NumSubroutineUniformRemapTable; + struct gl_uniform_storage **SubroutineUniformRemapTable; + + /** + * Num of subroutine functions for this stage + * and storage for them. + */ + GLuint NumSubroutineFunctions; + struct gl_subroutine_function *SubroutineFunctions; }; @@ -2365,6 +2483,11 @@ struct gl_uniform_block GLuint UniformBufferSize; /** + * Is this actually an interface block for a shader storage buffer? + */ + bool IsShaderStorage; + + /** * Layout specified in the shader * * This isn't accessible through the API, but it is used while @@ -2468,6 +2591,37 @@ struct gl_shader_program enum gl_frag_depth_layout FragDepthLayout; /** + * Tessellation Control shader state from layout qualifiers. + */ + struct { + /** + * 0 - vertices not declared in shader, or + * 1 .. GL_MAX_PATCH_VERTICES + */ + GLint VerticesOut; + } TessCtrl; + + /** + * Tessellation Evaluation shader state from layout qualifiers. + */ + struct { + /** GL_TRIANGLES, GL_QUADS or GL_ISOLINES */ + GLenum PrimitiveMode; + /** GL_EQUAL, GL_FRACTIONAL_ODD or GL_FRACTIONAL_EVEN */ + GLenum Spacing; + /** GL_CW or GL_CCW */ + GLenum VertexOrder; + bool PointMode; + /** + * True if gl_ClipDistance is written to. Copied into + * gl_tess_eval_program by _mesa_copy_linked_program_data(). + */ + GLboolean UsesClipDistance; + GLuint ClipDistanceArraySize; /**< Size of the gl_ClipDistance array, or + 0 if not present. */ + } TessEval; + + /** * Geometry shader state - copied into gl_geometry_program by * _mesa_copy_linked_program_data(). */ @@ -2681,6 +2835,7 @@ struct gl_shader_compiler_options GLboolean EmitNoIndirectOutput; /**< No indirect addressing of outputs */ GLboolean EmitNoIndirectTemp; /**< No indirect addressing of temps */ GLboolean EmitNoIndirectUniform; /**< No indirect addressing of constants */ + GLboolean EmitNoIndirectSampler; /**< No indirect addressing of samplers */ /*@}*/ GLuint MaxIfDepth; /**< Maximum nested IF blocks */ @@ -3100,6 +3255,9 @@ struct gl_program_constants /* GL_ARB_shader_image_load_store */ GLuint MaxImageUniforms; + + /* GL_ARB_shader_storage_buffer_object */ + GLuint MaxShaderStorageBlocks; }; @@ -3197,6 +3355,15 @@ struct gl_constants GLuint UniformBufferOffsetAlignment; /** @} */ + /** @{ + * GL_ARB_shader_storage_buffer_object + */ + GLuint MaxCombinedShaderStorageBlocks; + GLuint MaxShaderStorageBufferBindings; + GLuint MaxShaderStorageBlockSize; + GLuint ShaderStorageBufferOffsetAlignment; + /** @} */ + /** * GL_ARB_explicit_uniform_location */ @@ -3423,6 +3590,13 @@ struct gl_constants GLenum ContextReleaseBehavior; struct gl_shader_compiler_options ShaderCompilerOptions[MESA_SHADER_STAGES]; + + /** GL_ARB_tessellation_shader */ + GLuint MaxPatchVertices; + GLuint MaxTessGenLevel; + GLuint MaxTessPatchComponents; + GLuint MaxTessControlTotalOutputComponents; + bool LowerTessLevel; /**< Lower gl_TessLevel* from float[n] to vecn? */ }; @@ -3484,6 +3658,8 @@ struct gl_extensions GLboolean ARB_shader_image_load_store; GLboolean ARB_shader_precision; GLboolean ARB_shader_stencil_export; + GLboolean ARB_shader_storage_buffer_object; + GLboolean ARB_shader_subroutine; GLboolean ARB_shader_texture_lod; GLboolean ARB_shading_language_packing; GLboolean ARB_shading_language_420pack; @@ -3815,6 +3991,12 @@ struct gl_driver_flags */ uint64_t NewUniformBuffer; + /** + * gl_context::ShaderStorageBufferBindings + * gl_shader_program::ShaderStorageBlocks + */ + uint64_t NewShaderStorageBuffer; + uint64_t NewTextureBuffer; /** @@ -3826,6 +4008,11 @@ struct gl_driver_flags * gl_context::ImageUnits */ uint64_t NewImageUnits; + + /** + * gl_context::TessCtrlProgram::patch_default_* + */ + uint64_t NewDefaultTessLevels; }; struct gl_uniform_buffer_binding @@ -3842,6 +4029,20 @@ struct gl_uniform_buffer_binding GLboolean AutomaticSize; }; +struct gl_shader_storage_buffer_binding +{ + struct gl_buffer_object *BufferObject; + /** Start of shader storage block data in the buffer */ + GLintptr Offset; + /** Size of data allowed to be referenced from the buffer (in bytes) */ + GLsizeiptr Size; + /** + * glBindBufferBase() indicates that the Size should be ignored and only + * limited by the current size of the BufferObject. + */ + GLboolean AutomaticSize; +}; + /** * ARB_shader_image_load_store image unit. */ @@ -4047,6 +4248,8 @@ struct gl_context struct gl_fragment_program_state FragmentProgram; struct gl_geometry_program_state GeometryProgram; struct gl_compute_program_state ComputeProgram; + struct gl_tess_ctrl_program_state TessCtrlProgram; + struct gl_tess_eval_program_state TessEvalProgram; struct gl_ati_fragment_shader_state ATIFragmentShader; struct gl_pipeline_shader_state Pipeline; /**< GLSL pipeline shader object state */ @@ -4089,6 +4292,12 @@ struct gl_context struct gl_buffer_object *UniformBuffer; /** + * Current GL_ARB_shader_storage_buffer_object binding referenced by + * GL_SHADER_STORAGE_BUFFER target for glBufferData, glMapBuffer, etc. + */ + struct gl_buffer_object *ShaderStorageBuffer; + + /** * Array of uniform buffers for GL_ARB_uniform_buffer_object and GL 3.1. * This is set up using glBindBufferRange() or glBindBufferBase(). They are * associated with uniform blocks by glUniformBlockBinding()'s state in the @@ -4098,6 +4307,15 @@ struct gl_context UniformBufferBindings[MAX_COMBINED_UNIFORM_BUFFERS]; /** + * Array of shader storage buffers for ARB_shader_storage_buffer_object + * and GL 4.3. This is set up using glBindBufferRange() or + * glBindBufferBase(). They are associated with shader storage blocks by + * glShaderStorageBlockBinding()'s state in the shader program. + */ + struct gl_shader_storage_buffer_binding + ShaderStorageBufferBindings[MAX_COMBINED_SHADER_STORAGE_BUFFERS]; + + /** * Object currently associated with the GL_ATOMIC_COUNTER_BUFFER * target. */ diff --git a/src/mesa/main/multisample.c b/src/mesa/main/multisample.c index 816837b95bd..09e6154f7ec 100644 --- a/src/mesa/main/multisample.c +++ b/src/mesa/main/multisample.c @@ -43,7 +43,7 @@ _mesa_SampleCoverage(GLclampf value, GLboolean invert) FLUSH_VERTICES(ctx, 0); - ctx->Multisample.SampleCoverageValue = (GLfloat) CLAMP(value, 0.0, 1.0); + ctx->Multisample.SampleCoverageValue = CLAMP(value, 0.0f, 1.0f); ctx->Multisample.SampleCoverageInvert = invert; ctx->NewState |= _NEW_MULTISAMPLE; } @@ -134,7 +134,7 @@ _mesa_MinSampleShading(GLclampf value) FLUSH_VERTICES(ctx, 0); - ctx->Multisample.MinSampleShadingValue = CLAMP(value, 0.0, 1.0); + ctx->Multisample.MinSampleShadingValue = CLAMP(value, 0.0f, 1.0f); ctx->NewState |= _NEW_MULTISAMPLE; } @@ -164,8 +164,11 @@ _mesa_check_sample_count(struct gl_context *ctx, GLenum target, * * "If internalformat is a signed or unsigned integer format and samples * is greater than zero, then the error INVALID_OPERATION is generated." + * + * This restriction is relaxed for OpenGL ES 3.1. */ - if (_mesa_is_gles3(ctx) && _mesa_is_enum_format_integer(internalFormat) + if ((ctx->API == API_OPENGLES2 && ctx->Version == 30) && + _mesa_is_enum_format_integer(internalFormat) && samples > 0) { return GL_INVALID_OPERATION; } diff --git a/src/mesa/main/objectlabel.c b/src/mesa/main/objectlabel.c index 5626054687b..1019f893ba8 100644 --- a/src/mesa/main/objectlabel.c +++ b/src/mesa/main/objectlabel.c @@ -234,7 +234,7 @@ get_label_pointer(struct gl_context *ctx, GLenum identifier, GLuint name, invalid_enum: _mesa_error(ctx, GL_INVALID_ENUM, "%s(identifier = %s)", - caller, _mesa_lookup_enum_by_nr(identifier)); + caller, _mesa_enum_to_string(identifier)); return NULL; } diff --git a/src/mesa/main/pack.c b/src/mesa/main/pack.c index f72360817e9..7147fd6e4fe 100644 --- a/src/mesa/main/pack.c +++ b/src/mesa/main/pack.c @@ -470,7 +470,7 @@ extract_uint_indexes(GLuint n, GLuint indexes[], static inline GLuint clamp_float_to_uint(GLfloat f) { - return f < 0.0F ? 0 : F_TO_I(f); + return f < 0.0F ? 0 : _mesa_lroundevenf(f); } @@ -478,7 +478,7 @@ static inline GLuint clamp_half_to_uint(GLhalfARB h) { GLfloat f = _mesa_half_to_float(h); - return f < 0.0F ? 0 : F_TO_I(f); + return f < 0.0F ? 0 : _mesa_lroundevenf(f); } @@ -796,7 +796,7 @@ _mesa_unpack_depth_span( struct gl_context *ctx, GLuint n, * back to an int type can introduce errors that will show up as * artifacts in things like depth peeling which uses glCopyTexImage. */ - if (ctx->Pixel.DepthScale == 1.0 && ctx->Pixel.DepthBias == 0.0) { + if (ctx->Pixel.DepthScale == 1.0F && ctx->Pixel.DepthBias == 0.0F) { if (srcType == GL_UNSIGNED_INT && dstType == GL_UNSIGNED_SHORT) { const GLuint *src = (const GLuint *) source; GLushort *dst = (GLushort *) dest; @@ -874,8 +874,8 @@ _mesa_unpack_depth_span( struct gl_context *ctx, GLuint n, case GL_UNSIGNED_INT_24_8_EXT: /* GL_EXT_packed_depth_stencil */ if (dstType == GL_UNSIGNED_INT_24_8_EXT && depthMax == 0xffffff && - ctx->Pixel.DepthScale == 1.0 && - ctx->Pixel.DepthBias == 0.0) { + ctx->Pixel.DepthScale == 1.0F && + ctx->Pixel.DepthBias == 0.0F) { const GLuint *src = (const GLuint *) source; GLuint *zValues = (GLuint *) dest; GLuint i; @@ -945,7 +945,7 @@ _mesa_unpack_depth_span( struct gl_context *ctx, GLuint n, { const GLfloat scale = ctx->Pixel.DepthScale; const GLfloat bias = ctx->Pixel.DepthBias; - if (scale != 1.0 || bias != 0.0) { + if (scale != 1.0F || bias != 0.0F) { GLuint i; for (i = 0; i < n; i++) { depthValues[i] = depthValues[i] * scale + bias; @@ -958,7 +958,7 @@ _mesa_unpack_depth_span( struct gl_context *ctx, GLuint n, if (needClamp) { GLuint i; for (i = 0; i < n; i++) { - depthValues[i] = (GLfloat)CLAMP(depthValues[i], 0.0, 1.0); + depthValues[i] = CLAMP(depthValues[i], 0.0F, 1.0F); } } @@ -1025,7 +1025,7 @@ _mesa_pack_depth_span( struct gl_context *ctx, GLuint n, GLvoid *dest, return; } - if (ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0) { + if (ctx->Pixel.DepthScale != 1.0F || ctx->Pixel.DepthBias != 0.0F) { memcpy(depthCopy, depthSpan, n * sizeof(GLfloat)); _mesa_scale_and_bias_depth(ctx, n, depthCopy); depthSpan = depthCopy; @@ -1153,7 +1153,7 @@ _mesa_pack_depth_stencil_span(struct gl_context *ctx,GLuint n, return; } - if (ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0) { + if (ctx->Pixel.DepthScale != 1.0F || ctx->Pixel.DepthBias != 0.0F) { memcpy(depthCopy, depthVals, n * sizeof(GLfloat)); _mesa_scale_and_bias_depth(ctx, n, depthCopy); depthVals = depthCopy; diff --git a/src/mesa/main/pipelineobj.c b/src/mesa/main/pipelineobj.c index 279ae2078fe..07acbf10c1d 100644 --- a/src/mesa/main/pipelineobj.c +++ b/src/mesa/main/pipelineobj.c @@ -244,14 +244,13 @@ _mesa_UseProgramStages(GLuint pipeline, GLbitfield stages, GLuint program) * * "If stages is not the special value ALL_SHADER_BITS, and has a bit * set that is not recognized, the error INVALID_VALUE is generated." - * - * NOT YET SUPPORTED: - * GL_TESS_CONTROL_SHADER_BIT - * GL_TESS_EVALUATION_SHADER_BIT */ any_valid_stages = GL_VERTEX_SHADER_BIT | GL_FRAGMENT_SHADER_BIT; if (_mesa_has_geometry_shaders(ctx)) any_valid_stages |= GL_GEOMETRY_SHADER_BIT; + if (_mesa_has_tessellation(ctx)) + any_valid_stages |= GL_TESS_CONTROL_SHADER_BIT | + GL_TESS_EVALUATION_SHADER_BIT; if (stages != GL_ALL_SHADER_BITS && (stages & ~any_valid_stages) != 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glUseProgramStages(Stages)"); @@ -327,6 +326,12 @@ _mesa_UseProgramStages(GLuint pipeline, GLbitfield stages, GLuint program) if ((stages & GL_GEOMETRY_SHADER_BIT) != 0) _mesa_use_shader_program(ctx, GL_GEOMETRY_SHADER, shProg, pipe); + + if ((stages & GL_TESS_CONTROL_SHADER_BIT) != 0) + _mesa_use_shader_program(ctx, GL_TESS_CONTROL_SHADER, shProg, pipe); + + if ((stages & GL_TESS_EVALUATION_SHADER_BIT) != 0) + _mesa_use_shader_program(ctx, GL_TESS_EVALUATION_SHADER, shProg, pipe); } /** @@ -588,6 +593,7 @@ _mesa_GetProgramPipelineiv(GLuint pipeline, GLenum pname, GLint *params) /* Are geometry shaders available in this context? */ const bool has_gs = _mesa_has_geometry_shaders(ctx); + const bool has_tess = _mesa_has_tessellation(ctx);; if (!pipe) { _mesa_error(ctx, GL_INVALID_OPERATION, @@ -615,11 +621,17 @@ _mesa_GetProgramPipelineiv(GLuint pipeline, GLenum pname, GLint *params) ? pipe->CurrentProgram[MESA_SHADER_VERTEX]->Name : 0; return; case GL_TESS_EVALUATION_SHADER: - /* NOT YET SUPPORTED */ - break; + if (!has_tess) + break; + *params = pipe->CurrentProgram[MESA_SHADER_TESS_EVAL] + ? pipe->CurrentProgram[MESA_SHADER_TESS_EVAL]->Name : 0; + return; case GL_TESS_CONTROL_SHADER: - /* NOT YET SUPPORTED */ - break; + if (!has_tess) + break; + *params = pipe->CurrentProgram[MESA_SHADER_TESS_CTRL] + ? pipe->CurrentProgram[MESA_SHADER_TESS_CTRL]->Name : 0; + return; case GL_GEOMETRY_SHADER: if (!has_gs) break; @@ -635,7 +647,7 @@ _mesa_GetProgramPipelineiv(GLuint pipeline, GLenum pname, GLint *params) } _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramPipelineiv(pname=%s)", - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); } /** @@ -777,7 +789,9 @@ _mesa_validate_program_pipeline(struct gl_context* ctx, * executable vertex shader." */ if (!pipe->CurrentProgram[MESA_SHADER_VERTEX] - && pipe->CurrentProgram[MESA_SHADER_GEOMETRY]) { + && (pipe->CurrentProgram[MESA_SHADER_GEOMETRY] || + pipe->CurrentProgram[MESA_SHADER_TESS_CTRL] || + pipe->CurrentProgram[MESA_SHADER_TESS_EVAL])) { pipe->InfoLog = ralloc_strdup(pipe, "Program lacks a vertex shader"); goto err; } diff --git a/src/mesa/main/pixel.c b/src/mesa/main/pixel.c index ecda2694fc8..608a5454702 100644 --- a/src/mesa/main/pixel.c +++ b/src/mesa/main/pixel.c @@ -455,12 +455,12 @@ _mesa_GetnPixelMapusvARB( GLenum map, GLsizei bufSize, GLushort *values ) /* special cases */ case GL_PIXEL_MAP_I_TO_I: for (i = 0; i < mapsize; i++) { - values[i] = (GLushort) CLAMP(ctx->PixelMaps.ItoI.Map[i], 0.0, 65535.); + values[i] = (GLushort) CLAMP(ctx->PixelMaps.ItoI.Map[i], 0.0F, 65535.0F); } break; case GL_PIXEL_MAP_S_TO_S: for (i = 0; i < mapsize; i++) { - values[i] = (GLushort) CLAMP(ctx->PixelMaps.StoS.Map[i], 0.0, 65535.); + values[i] = (GLushort) CLAMP(ctx->PixelMaps.StoS.Map[i], 0.0F, 65535.0F); } break; default: diff --git a/src/mesa/main/pixeltransfer.c b/src/mesa/main/pixeltransfer.c index 94464ea6709..22eac00a7df 100644 --- a/src/mesa/main/pixeltransfer.c +++ b/src/mesa/main/pixeltransfer.c @@ -35,6 +35,7 @@ #include "pixeltransfer.h" #include "imports.h" #include "mtypes.h" +#include "util/rounding.h" /* @@ -47,25 +48,25 @@ _mesa_scale_and_bias_rgba(GLuint n, GLfloat rgba[][4], GLfloat rBias, GLfloat gBias, GLfloat bBias, GLfloat aBias) { - if (rScale != 1.0 || rBias != 0.0) { + if (rScale != 1.0F || rBias != 0.0F) { GLuint i; for (i = 0; i < n; i++) { rgba[i][RCOMP] = rgba[i][RCOMP] * rScale + rBias; } } - if (gScale != 1.0 || gBias != 0.0) { + if (gScale != 1.0F || gBias != 0.0F) { GLuint i; for (i = 0; i < n; i++) { rgba[i][GCOMP] = rgba[i][GCOMP] * gScale + gBias; } } - if (bScale != 1.0 || bBias != 0.0) { + if (bScale != 1.0F || bBias != 0.0F) { GLuint i; for (i = 0; i < n; i++) { rgba[i][BCOMP] = rgba[i][BCOMP] * bScale + bBias; } } - if (aScale != 1.0 || aBias != 0.0) { + if (aScale != 1.0F || aBias != 0.0F) { GLuint i; for (i = 0; i < n; i++) { rgba[i][ACOMP] = rgba[i][ACOMP] * aScale + aBias; @@ -94,10 +95,10 @@ _mesa_map_rgba( const struct gl_context *ctx, GLuint n, GLfloat rgba[][4] ) GLfloat g = CLAMP(rgba[i][GCOMP], 0.0F, 1.0F); GLfloat b = CLAMP(rgba[i][BCOMP], 0.0F, 1.0F); GLfloat a = CLAMP(rgba[i][ACOMP], 0.0F, 1.0F); - rgba[i][RCOMP] = rMap[F_TO_I(r * rscale)]; - rgba[i][GCOMP] = gMap[F_TO_I(g * gscale)]; - rgba[i][BCOMP] = bMap[F_TO_I(b * bscale)]; - rgba[i][ACOMP] = aMap[F_TO_I(a * ascale)]; + rgba[i][RCOMP] = rMap[(int)_mesa_lroundevenf(r * rscale)]; + rgba[i][GCOMP] = gMap[(int)_mesa_lroundevenf(g * gscale)]; + rgba[i][BCOMP] = bMap[(int)_mesa_lroundevenf(b * bscale)]; + rgba[i][ACOMP] = aMap[(int)_mesa_lroundevenf(a * ascale)]; } } @@ -236,7 +237,7 @@ _mesa_apply_ci_transfer_ops(const struct gl_context *ctx, GLuint i; for (i = 0; i < n; i++) { const GLuint j = indexes[i] & mask; - indexes[i] = F_TO_I(ctx->PixelMaps.ItoI.Map[j]); + indexes[i] = _mesa_lroundevenf(ctx->PixelMaps.ItoI.Map[j]); } } } diff --git a/src/mesa/main/points.c b/src/mesa/main/points.c index 5ad1f38f366..863e3c1af32 100644 --- a/src/mesa/main/points.c +++ b/src/mesa/main/points.c @@ -45,7 +45,7 @@ _mesa_PointSize( GLfloat size ) { GET_CURRENT_CONTEXT(ctx); - if (size <= 0.0) { + if (size <= 0.0F) { _mesa_error( ctx, GL_INVALID_VALUE, "glPointSize" ); return; } @@ -119,9 +119,9 @@ _mesa_PointParameterfv( GLenum pname, const GLfloat *params) return; FLUSH_VERTICES(ctx, _NEW_POINT); COPY_3V(ctx->Point.Params, params); - ctx->Point._Attenuated = (ctx->Point.Params[0] != 1.0 || - ctx->Point.Params[1] != 0.0 || - ctx->Point.Params[2] != 0.0); + ctx->Point._Attenuated = (ctx->Point.Params[0] != 1.0F || + ctx->Point.Params[1] != 0.0F || + ctx->Point.Params[2] != 0.0F); break; case GL_POINT_SIZE_MIN_EXT: if (params[0] < 0.0F) { diff --git a/src/mesa/main/polygon.c b/src/mesa/main/polygon.c index a1f0aa02da1..60af88f9857 100644 --- a/src/mesa/main/polygon.c +++ b/src/mesa/main/polygon.c @@ -56,7 +56,7 @@ _mesa_CullFace( GLenum mode ) GET_CURRENT_CONTEXT(ctx); if (MESA_VERBOSE&VERBOSE_API) - _mesa_debug(ctx, "glCullFace %s\n", _mesa_lookup_enum_by_nr(mode)); + _mesa_debug(ctx, "glCullFace %s\n", _mesa_enum_to_string(mode)); if (mode!=GL_FRONT && mode!=GL_BACK && mode!=GL_FRONT_AND_BACK) { _mesa_error( ctx, GL_INVALID_ENUM, "glCullFace" ); @@ -91,16 +91,16 @@ _mesa_FrontFace( GLenum mode ) GET_CURRENT_CONTEXT(ctx); if (MESA_VERBOSE&VERBOSE_API) - _mesa_debug(ctx, "glFrontFace %s\n", _mesa_lookup_enum_by_nr(mode)); + _mesa_debug(ctx, "glFrontFace %s\n", _mesa_enum_to_string(mode)); + + if (ctx->Polygon.FrontFace == mode) + return; if (mode!=GL_CW && mode!=GL_CCW) { _mesa_error( ctx, GL_INVALID_ENUM, "glFrontFace" ); return; } - if (ctx->Polygon.FrontFace == mode) - return; - FLUSH_VERTICES(ctx, _NEW_POLYGON); ctx->Polygon.FrontFace = mode; @@ -128,8 +128,8 @@ _mesa_PolygonMode( GLenum face, GLenum mode ) if (MESA_VERBOSE&VERBOSE_API) _mesa_debug(ctx, "glPolygonMode %s %s\n", - _mesa_lookup_enum_by_nr(face), - _mesa_lookup_enum_by_nr(mode)); + _mesa_enum_to_string(face), + _mesa_enum_to_string(mode)); if (mode!=GL_POINT && mode!=GL_LINE && mode!=GL_FILL) { _mesa_error( ctx, GL_INVALID_ENUM, "glPolygonMode(mode)" ); diff --git a/src/mesa/main/program_resource.c b/src/mesa/main/program_resource.c index d857b84e60d..23d2b4d2da0 100644 --- a/src/mesa/main/program_resource.c +++ b/src/mesa/main/program_resource.c @@ -28,10 +28,11 @@ #include "main/mtypes.h" #include "main/shaderapi.h" #include "main/shaderobj.h" +#include "main/context.h" #include "program_resource.h" - +#include "ir_uniform.h" static bool -supported_interface_enum(GLenum iface) +supported_interface_enum(struct gl_context *ctx, GLenum iface) { switch (iface) { case GL_UNIFORM: @@ -42,17 +43,21 @@ supported_interface_enum(GLenum iface) case GL_ATOMIC_COUNTER_BUFFER: return true; case GL_VERTEX_SUBROUTINE: - case GL_TESS_CONTROL_SUBROUTINE: - case GL_TESS_EVALUATION_SUBROUTINE: - case GL_GEOMETRY_SUBROUTINE: case GL_FRAGMENT_SUBROUTINE: - case GL_COMPUTE_SUBROUTINE: case GL_VERTEX_SUBROUTINE_UNIFORM: - case GL_TESS_CONTROL_SUBROUTINE_UNIFORM: - case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM: - case GL_GEOMETRY_SUBROUTINE_UNIFORM: case GL_FRAGMENT_SUBROUTINE_UNIFORM: + return _mesa_has_shader_subroutine(ctx); + case GL_GEOMETRY_SUBROUTINE: + case GL_GEOMETRY_SUBROUTINE_UNIFORM: + return _mesa_has_geometry_shaders(ctx) && _mesa_has_shader_subroutine(ctx); + case GL_COMPUTE_SUBROUTINE: case GL_COMPUTE_SUBROUTINE_UNIFORM: + return _mesa_has_compute_shaders(ctx) && _mesa_has_shader_subroutine(ctx); + case GL_TESS_CONTROL_SUBROUTINE: + case GL_TESS_EVALUATION_SUBROUTINE: + case GL_TESS_CONTROL_SUBROUTINE_UNIFORM: + case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM: + return _mesa_has_tessellation(ctx) && _mesa_has_shader_subroutine(ctx); case GL_BUFFER_VARIABLE: case GL_SHADER_STORAGE_BLOCK: default: @@ -79,9 +84,9 @@ _mesa_GetProgramInterfaceiv(GLuint program, GLenum programInterface, } /* Validate interface. */ - if (!supported_interface_enum(programInterface)) { + if (!supported_interface_enum(ctx, programInterface)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramInterfaceiv(%s)", - _mesa_lookup_enum_by_nr(programInterface)); + _mesa_enum_to_string(programInterface)); return; } @@ -96,8 +101,8 @@ _mesa_GetProgramInterfaceiv(GLuint program, GLenum programInterface, if (programInterface == GL_ATOMIC_COUNTER_BUFFER) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramInterfaceiv(%s pname %s)", - _mesa_lookup_enum_by_nr(programInterface), - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(programInterface), + _mesa_enum_to_string(pname)); return; } /* Name length consists of base name, 3 additional chars '[0]' if @@ -138,15 +143,40 @@ _mesa_GetProgramInterfaceiv(GLuint program, GLenum programInterface, default: _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramInterfaceiv(%s pname %s)", - _mesa_lookup_enum_by_nr(programInterface), - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(programInterface), + _mesa_enum_to_string(pname)); }; break; case GL_MAX_NUM_COMPATIBLE_SUBROUTINES: + switch (programInterface) { + case GL_VERTEX_SUBROUTINE_UNIFORM: + case GL_FRAGMENT_SUBROUTINE_UNIFORM: + case GL_GEOMETRY_SUBROUTINE_UNIFORM: + case GL_COMPUTE_SUBROUTINE_UNIFORM: + case GL_TESS_CONTROL_SUBROUTINE_UNIFORM: + case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM: { + for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++) { + if (shProg->ProgramResourceList[i].Type == programInterface) { + struct gl_uniform_storage *uni = + (struct gl_uniform_storage *) + shProg->ProgramResourceList[i].Data; + *params = MAX2(*params, uni->num_compatible_subroutines); + } + } + break; + } + + default: + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetProgramInterfaceiv(%s pname %s)", + _mesa_enum_to_string(programInterface), + _mesa_enum_to_string(pname)); + } + break; default: _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramInterfaceiv(pname %s)", - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); } } @@ -173,32 +203,12 @@ is_xfb_marker(const char *str) return false; } -/** - * Checks if given name index is legal for GetProgramResourceIndex, - * check is written to be compatible with GL_ARB_array_of_arrays. - */ -static bool -valid_program_resource_index_name(const GLchar *name) -{ - const char *array = strstr(name, "["); - const char *close = strrchr(name, ']'); - - /* Not array, no need for the check. */ - if (!array) - return true; - - /* Last array index has to be zero. */ - if (!close || *--close != '0') - return false; - - return true; -} - GLuint GLAPIENTRY _mesa_GetProgramResourceIndex(GLuint program, GLenum programInterface, const GLchar *name) { GET_CURRENT_CONTEXT(ctx); + unsigned array_index = 0; struct gl_program_resource *res; struct gl_shader_program *shProg = _mesa_lookup_shader_program_err(ctx, program, @@ -206,6 +216,11 @@ _mesa_GetProgramResourceIndex(GLuint program, GLenum programInterface, if (!shProg || !name) return GL_INVALID_INDEX; + if (!supported_interface_enum(ctx, programInterface)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceIndex(%s)", + _mesa_enum_to_string(programInterface)); + return GL_INVALID_INDEX; + } /* * For the interface TRANSFORM_FEEDBACK_VARYING, the value INVALID_INDEX * should be returned when querying the index assigned to the special names @@ -217,24 +232,33 @@ _mesa_GetProgramResourceIndex(GLuint program, GLenum programInterface, return GL_INVALID_INDEX; switch (programInterface) { + case GL_TESS_CONTROL_SUBROUTINE: + case GL_TESS_CONTROL_SUBROUTINE_UNIFORM: + case GL_TESS_EVALUATION_SUBROUTINE: + case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM: + case GL_COMPUTE_SUBROUTINE: + case GL_COMPUTE_SUBROUTINE_UNIFORM: + case GL_GEOMETRY_SUBROUTINE: + case GL_GEOMETRY_SUBROUTINE_UNIFORM: + case GL_VERTEX_SUBROUTINE: + case GL_FRAGMENT_SUBROUTINE: + case GL_VERTEX_SUBROUTINE_UNIFORM: + case GL_FRAGMENT_SUBROUTINE_UNIFORM: case GL_PROGRAM_INPUT: case GL_PROGRAM_OUTPUT: case GL_UNIFORM: case GL_TRANSFORM_FEEDBACK_VARYING: - /* 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) + res = _mesa_program_resource_find_name(shProg, programInterface, name, + &array_index); + if (!res || array_index > 0) return GL_INVALID_INDEX; return _mesa_program_resource_index(shProg, res); case GL_ATOMIC_COUNTER_BUFFER: default: _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceIndex(%s)", - _mesa_lookup_enum_by_nr(programInterface)); + _mesa_enum_to_string(programInterface)); } return GL_INVALID_INDEX; @@ -250,19 +274,13 @@ _mesa_GetProgramResourceName(GLuint program, GLenum programInterface, _mesa_lookup_shader_program_err(ctx, program, "glGetProgramResourceName"); - /* Set user friendly return values in case of errors. */ - if (name) - *name = '\0'; - if (length) - *length = 0; - if (!shProg || !name) return; if (programInterface == GL_ATOMIC_COUNTER_BUFFER || - !supported_interface_enum(programInterface)) { + !supported_interface_enum(ctx, programInterface)) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceName(%s)", - _mesa_lookup_enum_by_nr(programInterface)); + _mesa_enum_to_string(programInterface)); return; } @@ -300,36 +318,6 @@ _mesa_GetProgramResourceiv(GLuint program, GLenum programInterface, propCount, props, bufSize, length, params); } -/** - * Function verifies syntax of given name for GetProgramResourceLocation - * and GetProgramResourceLocationIndex for the following cases: - * - * "array element portion of a string passed to GetProgramResourceLocation - * or GetProgramResourceLocationIndex must not have, a "+" sign, extra - * leading zeroes, or whitespace". - * - * Check is written to be compatible with GL_ARB_array_of_arrays. - */ -static bool -invalid_array_element_syntax(const GLchar *name) -{ - char *first = strchr(name, '['); - char *last = strrchr(name, '['); - - if (!first) - return false; - - /* No '+' or ' ' allowed anywhere. */ - if (strchr(first, '+') || strchr(first, ' ')) - return true; - - /* Check that last array index is 0. */ - if (last[1] == '0' && last[2] != ']') - return true; - - return false; -} - static struct gl_shader_program * lookup_linked_program(GLuint program, const char *caller) { @@ -356,7 +344,7 @@ _mesa_GetProgramResourceLocation(GLuint program, GLenum programInterface, struct gl_shader_program *shProg = lookup_linked_program(program, "glGetProgramResourceLocation"); - if (!shProg || !name || invalid_array_element_syntax(name)) + if (!shProg || !name) return -1; /* Validate programInterface. */ @@ -366,24 +354,33 @@ _mesa_GetProgramResourceLocation(GLuint program, GLenum programInterface, case GL_PROGRAM_OUTPUT: break; - /* For reference valid cases requiring additional extension support: - * GL_ARB_shader_subroutine - * GL_ARB_tessellation_shader - * GL_ARB_compute_shader - */ case GL_VERTEX_SUBROUTINE_UNIFORM: - case GL_TESS_CONTROL_SUBROUTINE_UNIFORM: - case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM: - case GL_GEOMETRY_SUBROUTINE_UNIFORM: case GL_FRAGMENT_SUBROUTINE_UNIFORM: + if (!_mesa_has_shader_subroutine(ctx)) + goto fail; + break; + case GL_GEOMETRY_SUBROUTINE_UNIFORM: + if (!_mesa_has_geometry_shaders(ctx) || !_mesa_has_shader_subroutine(ctx)) + goto fail; + break; case GL_COMPUTE_SUBROUTINE_UNIFORM: - + if (!_mesa_has_compute_shaders(ctx) || !_mesa_has_shader_subroutine(ctx)) + goto fail; + break; + case GL_TESS_CONTROL_SUBROUTINE_UNIFORM: + case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM: + if (!_mesa_has_tessellation(ctx) || !_mesa_has_shader_subroutine(ctx)) + goto fail; + break; default: - _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceLocation(%s %s)", - _mesa_lookup_enum_by_nr(programInterface), name); + goto fail; } return _mesa_program_resource_location(shProg, programInterface, name); +fail: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceLocation(%s %s)", + _mesa_enum_to_string(programInterface), name); + return -1; } /** @@ -397,7 +394,7 @@ _mesa_GetProgramResourceLocationIndex(GLuint program, GLenum programInterface, struct gl_shader_program *shProg = lookup_linked_program(program, "glGetProgramResourceLocationIndex"); - if (!shProg || !name || invalid_array_element_syntax(name)) + if (!shProg || !name) return -1; /* From the GL_ARB_program_interface_query spec: @@ -408,7 +405,7 @@ _mesa_GetProgramResourceLocationIndex(GLuint program, GLenum programInterface, if (programInterface != GL_PROGRAM_OUTPUT) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceLocationIndex(%s)", - _mesa_lookup_enum_by_nr(programInterface)); + _mesa_enum_to_string(programInterface)); return -1; } diff --git a/src/mesa/main/queryobj.c b/src/mesa/main/queryobj.c index 5ff1b953231..98366857f62 100644 --- a/src/mesa/main/queryobj.c +++ b/src/mesa/main/queryobj.c @@ -217,7 +217,7 @@ get_query_binding_point(struct gl_context *ctx, GLenum target, GLuint index) case GL_TESS_CONTROL_SHADER_PATCHES_ARB: case GL_TESS_EVALUATION_SHADER_INVOCATIONS_ARB: - if (ctx->Extensions.ARB_tessellation_shader) + if (_mesa_has_tessellation(ctx)) return get_pipe_stats_binding_point(ctx, target); else return NULL; @@ -295,7 +295,7 @@ _mesa_CreateQueries(GLenum target, GLsizei n, GLuint *ids) break; default: _mesa_error(ctx, GL_INVALID_ENUM, "glCreateQueries(invalid target = %s)", - _mesa_lookup_enum_by_nr(target)); + _mesa_enum_to_string(target)); return; } @@ -390,7 +390,7 @@ _mesa_BeginQueryIndexed(GLenum target, GLuint index, GLuint id) if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glBeginQueryIndexed(%s, %u, %u)\n", - _mesa_lookup_enum_by_nr(target), index, id); + _mesa_enum_to_string(target), index, id); if (!query_error_check_index(ctx, target, index)) return; @@ -412,7 +412,7 @@ _mesa_BeginQueryIndexed(GLenum target, GLuint index, GLuint id) if (*bindpt) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginQuery{Indexed}(target=%s is active)", - _mesa_lookup_enum_by_nr(target)); + _mesa_enum_to_string(target)); return; } @@ -496,7 +496,7 @@ _mesa_EndQueryIndexed(GLenum target, GLuint index) if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glEndQueryIndexed(%s, %u)\n", - _mesa_lookup_enum_by_nr(target), index); + _mesa_enum_to_string(target), index); if (!query_error_check_index(ctx, target, index)) return; @@ -516,8 +516,8 @@ _mesa_EndQueryIndexed(GLenum target, GLuint index) if (q && q->Target != target) { _mesa_error(ctx, GL_INVALID_OPERATION, "glEndQuery(target=%s with active query of target %s)", - _mesa_lookup_enum_by_nr(target), - _mesa_lookup_enum_by_nr(q->Target)); + _mesa_enum_to_string(target), + _mesa_enum_to_string(q->Target)); return; } @@ -553,7 +553,7 @@ _mesa_QueryCounter(GLuint id, GLenum target) if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glQueryCounter(%u, %s)\n", id, - _mesa_lookup_enum_by_nr(target)); + _mesa_enum_to_string(target)); /* error checking */ if (target != GL_TIMESTAMP) { @@ -628,9 +628,9 @@ _mesa_GetQueryIndexediv(GLenum target, GLuint index, GLenum pname, if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glGetQueryIndexediv(%s, %u, %s)\n", - _mesa_lookup_enum_by_nr(target), + _mesa_enum_to_string(target), index, - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); if (!query_error_check_index(ctx, target, index)) return; @@ -712,7 +712,7 @@ _mesa_GetQueryIndexediv(GLenum target, GLuint index, GLenum pname, default: _mesa_problem(ctx, "Unknown target in glGetQueryIndexediv(target = %s)", - _mesa_lookup_enum_by_nr(target)); + _mesa_enum_to_string(target)); *params = 0; break; } @@ -740,7 +740,7 @@ _mesa_GetQueryObjectiv(GLuint id, GLenum pname, GLint *params) if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glGetQueryObjectiv(%u, %s)\n", id, - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); if (id) q = _mesa_lookup_query_object(ctx, id); @@ -794,7 +794,7 @@ _mesa_GetQueryObjectuiv(GLuint id, GLenum pname, GLuint *params) if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glGetQueryObjectuiv(%u, %s)\n", id, - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); if (id) q = _mesa_lookup_query_object(ctx, id); @@ -851,7 +851,7 @@ _mesa_GetQueryObjecti64v(GLuint id, GLenum pname, GLint64EXT *params) if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glGetQueryObjecti64v(%u, %s)\n", id, - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); if (id) q = _mesa_lookup_query_object(ctx, id); @@ -894,7 +894,7 @@ _mesa_GetQueryObjectui64v(GLuint id, GLenum pname, GLuint64EXT *params) if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glGetQueryObjectui64v(%u, %s)\n", id, - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); if (id) q = _mesa_lookup_query_object(ctx, id); diff --git a/src/mesa/main/readpix.c b/src/mesa/main/readpix.c index a3357cd6419..d826ecfc3d5 100644 --- a/src/mesa/main/readpix.c +++ b/src/mesa/main/readpix.c @@ -47,28 +47,47 @@ * Return true if the conversion L=R+G+B is needed. */ GLboolean -_mesa_need_rgb_to_luminance_conversion(mesa_format texFormat, GLenum format) +_mesa_need_rgb_to_luminance_conversion(GLenum srcBaseFormat, + GLenum dstBaseFormat) { - 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_INTEGER_EXT || - format == GL_LUMINANCE_ALPHA_INTEGER_EXT); + return (srcBaseFormat == GL_RG || + srcBaseFormat == GL_RGB || + srcBaseFormat == GL_RGBA) && + (dstBaseFormat == GL_LUMINANCE || + dstBaseFormat == GL_LUMINANCE_ALPHA); } +/** + * Return true if the conversion L,I to RGB conversion is needed. + */ +GLboolean +_mesa_need_luminance_to_rgb_conversion(GLenum srcBaseFormat, + GLenum dstBaseFormat) +{ + return (srcBaseFormat == GL_LUMINANCE || + srcBaseFormat == GL_LUMINANCE_ALPHA || + srcBaseFormat == GL_INTENSITY) && + (dstBaseFormat == GL_GREEN || + dstBaseFormat == GL_BLUE || + dstBaseFormat == GL_RG || + dstBaseFormat == GL_RGB || + dstBaseFormat == GL_BGR || + dstBaseFormat == GL_RGBA || + dstBaseFormat == GL_BGRA); +} /** * Return transfer op flags for this ReadPixels operation. */ -static GLbitfield -get_readpixels_transfer_ops(const struct gl_context *ctx, mesa_format texFormat, - GLenum format, GLenum type, GLboolean uses_blit) +GLbitfield +_mesa_get_readpixels_transfer_ops(const struct gl_context *ctx, + mesa_format texFormat, + GLenum format, GLenum type, + GLboolean uses_blit) { GLbitfield transferOps = ctx->_ImageTransferState; + GLenum srcBaseFormat = _mesa_get_format_base_format(texFormat); + GLenum dstBaseFormat = _mesa_unpack_format_to_base_format(format); if (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL || @@ -105,7 +124,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 && - !_mesa_need_rgb_to_luminance_conversion(texFormat, format)) { + !_mesa_need_rgb_to_luminance_conversion(srcBaseFormat, dstBaseFormat)) { transferOps &= ~IMAGE_CLAMP_BIT; } @@ -128,7 +147,7 @@ _mesa_readpixels_needs_slow_path(const struct gl_context *ctx, GLenum format, { struct gl_renderbuffer *rb = _mesa_get_read_renderbuffer_for_format(ctx, format); - GLenum srcType; + GLenum dstBaseFormat = _mesa_unpack_format_to_base_format(format); assert(rb); @@ -149,28 +168,14 @@ _mesa_readpixels_needs_slow_path(const struct gl_context *ctx, GLenum format, default: /* Color formats. */ - if (_mesa_need_rgb_to_luminance_conversion(rb->Format, format)) { - return GL_TRUE; - } - - /* Conversion between signed and unsigned integers needs masking - * (it isn't just memcpy). */ - srcType = _mesa_get_format_datatype(rb->Format); - - if ((srcType == GL_INT && - (type == GL_UNSIGNED_INT || - type == GL_UNSIGNED_SHORT || - type == GL_UNSIGNED_BYTE)) || - (srcType == GL_UNSIGNED_INT && - (type == GL_INT || - type == GL_SHORT || - type == GL_BYTE))) { + if (_mesa_need_rgb_to_luminance_conversion(rb->_BaseFormat, + dstBaseFormat)) { return GL_TRUE; } /* And finally, see if there are any transfer ops. */ - return get_readpixels_transfer_ops(ctx, rb->Format, format, type, - uses_blit) != 0; + return _mesa_get_readpixels_transfer_ops(ctx, rb->Format, format, type, + uses_blit) != 0; } return GL_FALSE; } @@ -263,7 +268,7 @@ read_uint_depth_pixels( struct gl_context *ctx, GLubyte *map, *dst; int stride, dstStride, j; - if (ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0) + if (ctx->Pixel.DepthScale != 1.0F || ctx->Pixel.DepthBias != 0.0F) return GL_FALSE; if (packing->SwapBytes) @@ -432,18 +437,19 @@ read_rgba_pixels( struct gl_context *ctx, uint8_t rebase_swizzle[4]; struct gl_framebuffer *fb = ctx->ReadBuffer; struct gl_renderbuffer *rb = fb->_ColorReadBuffer; + GLenum dstBaseFormat = _mesa_unpack_format_to_base_format(format); if (!rb) return; - transferOps = get_readpixels_transfer_ops(ctx, rb->Format, format, type, - GL_FALSE); + transferOps = _mesa_get_readpixels_transfer_ops(ctx, rb->Format, format, + type, GL_FALSE); /* Describe the dst format */ 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); convert_rgb_to_lum = - _mesa_need_rgb_to_luminance_conversion(rb->Format, format); + _mesa_need_rgb_to_luminance_conversion(rb->_BaseFormat, dstBaseFormat); dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height, format, type, 0, 0); @@ -815,7 +821,7 @@ read_depth_stencil_pixels(struct gl_context *ctx, const struct gl_pixelstore_attrib *packing ) { const GLboolean scaleOrBias - = ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0; + = ctx->Pixel.DepthScale != 1.0F || ctx->Pixel.DepthBias != 0.0F; const GLboolean stencilTransfer = ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset || ctx->Pixel.MapStencilFlag; GLubyte *dst; @@ -910,10 +916,8 @@ read_pixels_es3_error_check(GLenum format, GLenum type, const GLenum data_type = _mesa_get_format_datatype(rb->Format); GLboolean is_unsigned_int = GL_FALSE; GLboolean is_signed_int = GL_FALSE; - - if (!_mesa_is_color_format(internalFormat)) { - return GL_INVALID_OPERATION; - } + GLboolean is_float_depth = (internalFormat == GL_DEPTH_COMPONENT32F) || + (internalFormat == GL_DEPTH32F_STENCIL8); is_unsigned_int = _mesa_is_enum_format_unsigned_int(internalFormat); if (!is_unsigned_int) { @@ -944,6 +948,43 @@ read_pixels_es3_error_check(GLenum format, GLenum type, (is_unsigned_int && type == GL_UNSIGNED_INT)) return GL_NO_ERROR; break; + case GL_DEPTH_STENCIL: + switch (type) { + case GL_FLOAT_32_UNSIGNED_INT_24_8_REV: + if (is_float_depth) + return GL_NO_ERROR; + break; + case GL_UNSIGNED_INT_24_8: + if (!is_float_depth) + return GL_NO_ERROR; + break; + default: + return GL_INVALID_ENUM; + } + break; + case GL_DEPTH_COMPONENT: + switch (type) { + case GL_FLOAT: + if (is_float_depth) + return GL_NO_ERROR; + break; + case GL_UNSIGNED_SHORT: + case GL_UNSIGNED_INT_24_8: + if (!is_float_depth) + return GL_NO_ERROR; + break; + default: + return GL_INVALID_ENUM; + } + break; + case GL_STENCIL_INDEX: + switch (type) { + case GL_UNSIGNED_BYTE: + return GL_NO_ERROR; + default: + return GL_INVALID_ENUM; + } + break; } return GL_INVALID_OPERATION; @@ -966,8 +1007,8 @@ _mesa_ReadnPixelsARB( GLint x, GLint y, GLsizei width, GLsizei height, if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glReadPixels(%d, %d, %s, %s, %p)\n", width, height, - _mesa_lookup_enum_by_nr(format), - _mesa_lookup_enum_by_nr(type), + _mesa_enum_to_string(format), + _mesa_enum_to_string(type), pixels); if (width < 0 || height < 0) { @@ -1017,15 +1058,10 @@ _mesa_ReadnPixelsARB( GLint x, GLint y, GLsizei width, GLsizei height, err = read_pixels_es3_error_check(format, type, rb); } - if (err == GL_NO_ERROR && (format == GL_DEPTH_COMPONENT - || format == GL_DEPTH_STENCIL)) { - err = GL_INVALID_ENUM; - } - if (err != GL_NO_ERROR) { _mesa_error(ctx, err, "glReadPixels(invalid format %s and/or type %s)", - _mesa_lookup_enum_by_nr(format), - _mesa_lookup_enum_by_nr(type)); + _mesa_enum_to_string(format), + _mesa_enum_to_string(type)); return; } } @@ -1033,8 +1069,8 @@ _mesa_ReadnPixelsARB( GLint x, GLint y, GLsizei width, GLsizei height, err = _mesa_error_check_format_and_type(ctx, format, type); if (err != GL_NO_ERROR) { _mesa_error(ctx, err, "glReadPixels(invalid format %s and/or type %s)", - _mesa_lookup_enum_by_nr(format), - _mesa_lookup_enum_by_nr(type)); + _mesa_enum_to_string(format), + _mesa_enum_to_string(type)); return; } diff --git a/src/mesa/main/readpix.h b/src/mesa/main/readpix.h index 1636dd9ce3e..481ad9d9c37 100644 --- a/src/mesa/main/readpix.h +++ b/src/mesa/main/readpix.h @@ -38,7 +38,18 @@ _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); +_mesa_need_rgb_to_luminance_conversion(GLenum srcBaseFormat, + GLenum dstBaseFormat); + +extern GLboolean +_mesa_need_luminance_to_rgb_conversion(GLenum srcBaseFormat, + GLenum dstBaseFormat); + +extern GLbitfield +_mesa_get_readpixels_transfer_ops(const struct gl_context *ctx, + mesa_format texFormat, + GLenum format, GLenum type, + GLboolean uses_blit); extern void _mesa_readpixels(struct gl_context *ctx, diff --git a/src/mesa/main/samplerobj.c b/src/mesa/main/samplerobj.c index a3aacc66aa3..32180fb1ba2 100644 --- a/src/mesa/main/samplerobj.c +++ b/src/mesa/main/samplerobj.c @@ -689,7 +689,7 @@ set_sampler_max_anisotropy(struct gl_context *ctx, if (samp->MaxAnisotropy == param) return GL_FALSE; - if (param < 1.0) + if (param < 1.0F) return INVALID_VALUE; flush(ctx); @@ -813,7 +813,7 @@ _mesa_SamplerParameteri(GLuint sampler, GLenum pname, GLint param) break; case INVALID_PNAME: _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteri(pname=%s)\n", - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); break; case INVALID_PARAM: _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteri(param=%d)\n", @@ -906,7 +906,7 @@ _mesa_SamplerParameterf(GLuint sampler, GLenum pname, GLfloat param) break; case INVALID_PNAME: _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterf(pname=%s)\n", - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); break; case INVALID_PARAM: _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterf(param=%f)\n", @@ -1006,7 +1006,7 @@ _mesa_SamplerParameteriv(GLuint sampler, GLenum pname, const GLint *params) break; case INVALID_PNAME: _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteriv(pname=%s)\n", - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); break; case INVALID_PARAM: _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteriv(param=%d)\n", @@ -1099,7 +1099,7 @@ _mesa_SamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat *params) break; case INVALID_PNAME: _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterfv(pname=%s)\n", - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); break; case INVALID_PARAM: _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterfv(param=%f)\n", @@ -1184,7 +1184,7 @@ _mesa_SamplerParameterIiv(GLuint sampler, GLenum pname, const GLint *params) break; case INVALID_PNAME: _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIiv(pname=%s)\n", - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); break; case INVALID_PARAM: _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIiv(param=%d)\n", @@ -1270,7 +1270,7 @@ _mesa_SamplerParameterIuiv(GLuint sampler, GLenum pname, const GLuint *params) break; case INVALID_PNAME: _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIuiv(pname=%s)\n", - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); break; case INVALID_PARAM: _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIuiv(param=%u)\n", @@ -1380,7 +1380,7 @@ _mesa_GetSamplerParameteriv(GLuint sampler, GLenum pname, GLint *params) invalid_pname: _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameteriv(pname=%s)", - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); } @@ -1466,7 +1466,7 @@ _mesa_GetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat *params) invalid_pname: _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameterfv(pname=%s)", - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); } @@ -1545,7 +1545,7 @@ _mesa_GetSamplerParameterIiv(GLuint sampler, GLenum pname, GLint *params) invalid_pname: _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameterIiv(pname=%s)", - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); } @@ -1624,7 +1624,7 @@ _mesa_GetSamplerParameterIuiv(GLuint sampler, GLenum pname, GLuint *params) invalid_pname: _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameterIuiv(pname=%s)", - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); } diff --git a/src/mesa/main/shader_query.cpp b/src/mesa/main/shader_query.cpp index a6246a39aad..ee7320221e2 100644 --- a/src/mesa/main/shader_query.cpp +++ b/src/mesa/main/shader_query.cpp @@ -44,7 +44,8 @@ extern "C" { static GLint program_resource_location(struct gl_shader_program *shProg, - struct gl_program_resource *res, const char *name); + struct gl_program_resource *res, const char *name, + unsigned array_index); /** * Declare convenience functions to return resource data in a given type. @@ -61,6 +62,7 @@ DECL_RESOURCE_FUNC(UBO, gl_uniform_block); DECL_RESOURCE_FUNC(UNI, gl_uniform_storage); DECL_RESOURCE_FUNC(ATC, gl_active_atomic_buffer); DECL_RESOURCE_FUNC(XFB, gl_transform_feedback_varying_info); +DECL_RESOURCE_FUNC(SUB, gl_subroutine_function); void GLAPIENTRY _mesa_BindAttribLocation(GLhandleARB program, GLuint index, @@ -189,63 +191,6 @@ _mesa_GetActiveAttrib(GLhandleARB program, GLuint desired_index, (GLint *) type, "glGetActiveAttrib"); } -/* Locations associated with shader variables (array or non-array) can be - * queried using its base name or using the base name appended with the - * valid array index. For example, in case of below vertex shader, valid - * queries can be made to know the location of "xyz", "array", "array[0]", - * "array[1]", "array[2]" and "array[3]". In this example index reurned - * will be 0, 0, 0, 1, 2, 3 respectively. - * - * [Vertex Shader] - * layout(location=0) in vec4 xyz; - * layout(location=1) in vec4[4] array; - * void main() - * { } - * - * This requirement came up with the addition of ARB_program_interface_query - * to OpenGL 4.3 specification. See page 101 (page 122 of the PDF) for details. - * - * This utility function is used by: - * _mesa_GetAttribLocation - * _mesa_GetFragDataLocation - * _mesa_GetFragDataIndex - * - * Returns 0: - * if the 'name' string matches var->name. - * Returns 'matched index': - * if the 'name' string matches var->name appended with valid array index. - */ -int static inline -get_matching_index(const ir_variable *const var, const char *name) { - unsigned idx = 0; - const char *const paren = strchr(name, '['); - const unsigned len = (paren != NULL) ? paren - name : strlen(name); - - if (paren != NULL) { - if (!var->type->is_array()) - return -1; - - char *endptr; - idx = (unsigned) strtol(paren + 1, &endptr, 10); - const unsigned idx_len = endptr != (paren + 1) ? endptr - paren - 1 : 0; - - /* Validate the sub string representing index in 'name' string */ - if ((idx > 0 && paren[1] == '0') /* leading zeroes */ - || (idx == 0 && idx_len > 1) /* all zeroes */ - || paren[1] == ' ' /* whitespace */ - || endptr[0] != ']' /* closing brace */ - || endptr[1] != '\0' /* null char */ - || idx_len == 0 /* missing index */ - || idx >= var->type->length) /* exceeding array bound */ - return -1; - } - - if (strncmp(var->name, name, len) == 0 && var->name[len] == '\0') - return idx; - - return -1; -} - GLint GLAPIENTRY _mesa_GetAttribLocation(GLhandleARB program, const GLcharARB * name) { @@ -271,13 +216,15 @@ _mesa_GetAttribLocation(GLhandleARB program, const GLcharARB * name) if (shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) return -1; + unsigned array_index = 0; struct gl_program_resource *res = - _mesa_program_resource_find_name(shProg, GL_PROGRAM_INPUT, name); + _mesa_program_resource_find_name(shProg, GL_PROGRAM_INPUT, name, + &array_index); if (!res) return -1; - GLint loc = program_resource_location(shProg, res, name); + GLint loc = program_resource_location(shProg, res, name, array_index); /* The extra check against against 0 is made because of builtin-attribute * locations that have offset applied. Function program_resource_location @@ -455,13 +402,15 @@ _mesa_GetFragDataLocation(GLuint program, const GLchar *name) if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL) return -1; + unsigned array_index = 0; struct gl_program_resource *res = - _mesa_program_resource_find_name(shProg, GL_PROGRAM_OUTPUT, name); + _mesa_program_resource_find_name(shProg, GL_PROGRAM_OUTPUT, name, + &array_index); if (!res) return -1; - GLint loc = program_resource_location(shProg, res, name); + GLint loc = program_resource_location(shProg, res, name, array_index); /* The extra check against against 0 is made because of builtin-attribute * locations that have offset applied. Function program_resource_location @@ -497,6 +446,20 @@ _mesa_program_resource_name(struct gl_program_resource *res) return RESOURCE_VAR(res)->name; case GL_UNIFORM: return RESOURCE_UNI(res)->name; + case GL_VERTEX_SUBROUTINE_UNIFORM: + case GL_GEOMETRY_SUBROUTINE_UNIFORM: + case GL_FRAGMENT_SUBROUTINE_UNIFORM: + case GL_COMPUTE_SUBROUTINE_UNIFORM: + case GL_TESS_CONTROL_SUBROUTINE_UNIFORM: + case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM: + return RESOURCE_UNI(res)->name + MESA_SUBROUTINE_PREFIX_LEN; + case GL_VERTEX_SUBROUTINE: + case GL_GEOMETRY_SUBROUTINE: + case GL_FRAGMENT_SUBROUTINE: + case GL_COMPUTE_SUBROUTINE: + case GL_TESS_CONTROL_SUBROUTINE: + case GL_TESS_EVALUATION_SUBROUTINE: + return RESOURCE_SUB(res)->name; default: assert(!"support for resource type not implemented"); } @@ -515,7 +478,19 @@ _mesa_program_resource_array_size(struct gl_program_resource *res) case GL_PROGRAM_OUTPUT: return RESOURCE_VAR(res)->data.max_array_access; case GL_UNIFORM: + case GL_VERTEX_SUBROUTINE_UNIFORM: + case GL_GEOMETRY_SUBROUTINE_UNIFORM: + case GL_FRAGMENT_SUBROUTINE_UNIFORM: + case GL_COMPUTE_SUBROUTINE_UNIFORM: + case GL_TESS_CONTROL_SUBROUTINE_UNIFORM: + case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM: return RESOURCE_UNI(res)->array_elements; + case GL_VERTEX_SUBROUTINE: + case GL_GEOMETRY_SUBROUTINE: + case GL_FRAGMENT_SUBROUTINE: + case GL_COMPUTE_SUBROUTINE: + case GL_TESS_CONTROL_SUBROUTINE: + case GL_TESS_EVALUATION_SUBROUTINE: case GL_ATOMIC_COUNTER_BUFFER: case GL_UNIFORM_BLOCK: return 0; @@ -525,39 +500,32 @@ _mesa_program_resource_array_size(struct gl_program_resource *res) return 0; } -static int -array_index_of_resource(struct gl_program_resource *res, - const char *name) +/** + * Checks if array subscript is valid and if so sets array_index. + */ +static bool +valid_array_index(const GLchar *name, unsigned *array_index) { - assert(res->Data); + long idx = 0; + const GLchar *out_base_name_end; - switch (res->Type) { - case GL_PROGRAM_INPUT: - case GL_PROGRAM_OUTPUT: - return get_matching_index(RESOURCE_VAR(res), name); - default: - assert(!"support for resource type not implemented"); - return -1; - } + idx = parse_program_resource_name(name, &out_base_name_end); + if (idx < 0) + return false; + + if (array_index) + *array_index = idx; + + return true; } /* Find a program resource with specific name in given interface. */ struct gl_program_resource * _mesa_program_resource_find_name(struct gl_shader_program *shProg, - GLenum programInterface, const char *name) + GLenum programInterface, const char *name, + unsigned *array_index) { - 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) @@ -567,26 +535,46 @@ _mesa_program_resource_find_name(struct gl_shader_program *shProg, const char *rname = _mesa_program_resource_name(res); unsigned baselen = strlen(rname); - switch (programInterface) { - case GL_TRANSFORM_FEEDBACK_VARYING: - case GL_UNIFORM_BLOCK: - case GL_UNIFORM: - if (strncmp(rname, name, baselen) == 0) { + if (strncmp(rname, name, baselen) == 0) { + switch (programInterface) { + case GL_UNIFORM_BLOCK: /* Basename match, check if array or struct. */ if (name[baselen] == '\0' || name[baselen] == '[' || name[baselen] == '.') { return res; } + break; + case GL_TRANSFORM_FEEDBACK_VARYING: + case GL_UNIFORM: + case GL_VERTEX_SUBROUTINE_UNIFORM: + case GL_GEOMETRY_SUBROUTINE_UNIFORM: + case GL_FRAGMENT_SUBROUTINE_UNIFORM: + case GL_COMPUTE_SUBROUTINE_UNIFORM: + case GL_TESS_CONTROL_SUBROUTINE_UNIFORM: + case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM: + case GL_VERTEX_SUBROUTINE: + case GL_GEOMETRY_SUBROUTINE: + case GL_FRAGMENT_SUBROUTINE: + case GL_COMPUTE_SUBROUTINE: + case GL_TESS_CONTROL_SUBROUTINE: + case GL_TESS_EVALUATION_SUBROUTINE: + if (name[baselen] == '.') { + return res; + } + /* fall-through */ + case GL_PROGRAM_INPUT: + case GL_PROGRAM_OUTPUT: + if (name[baselen] == '\0') { + return res; + } else if (name[baselen] == '[' && + valid_array_index(name, array_index)) { + return res; + } + break; + default: + assert(!"not implemented for given interface"); } - break; - case GL_PROGRAM_INPUT: - case GL_PROGRAM_OUTPUT: - if (array_index_of_resource(res, full_name) >= 0) - return res; - break; - default: - assert(!"not implemented for given interface"); } } return NULL; @@ -651,6 +639,18 @@ _mesa_program_resource_find_index(struct gl_shader_program *shProg, case GL_PROGRAM_INPUT: case GL_PROGRAM_OUTPUT: case GL_UNIFORM: + case GL_VERTEX_SUBROUTINE_UNIFORM: + case GL_GEOMETRY_SUBROUTINE_UNIFORM: + case GL_FRAGMENT_SUBROUTINE_UNIFORM: + case GL_COMPUTE_SUBROUTINE_UNIFORM: + case GL_TESS_CONTROL_SUBROUTINE_UNIFORM: + case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM: + case GL_VERTEX_SUBROUTINE: + case GL_GEOMETRY_SUBROUTINE: + case GL_FRAGMENT_SUBROUTINE: + case GL_COMPUTE_SUBROUTINE: + case GL_TESS_CONTROL_SUBROUTINE: + case GL_TESS_EVALUATION_SUBROUTINE: if (++idx == (int) index) return res; break; @@ -719,6 +719,12 @@ _mesa_get_program_resource_name(struct gl_shader_program *shProg, bool add_index = !(((programInterface == GL_PROGRAM_INPUT) && res->StageReferences & (1 << MESA_SHADER_GEOMETRY))); + /* Transform feedback varyings have array index already appended + * in their names. + */ + if (programInterface == GL_TRANSFORM_FEEDBACK_VARYING) + add_index = false; + if (add_index && _mesa_program_resource_array_size(res)) { int i; @@ -736,17 +742,9 @@ _mesa_get_program_resource_name(struct gl_shader_program *shProg, static GLint program_resource_location(struct gl_shader_program *shProg, - struct gl_program_resource *res, const char *name) + struct gl_program_resource *res, const char *name, + unsigned array_index) { - unsigned index, offset; - int array_index = -1; - - if (res->Type == GL_PROGRAM_INPUT || res->Type == GL_PROGRAM_OUTPUT) { - array_index = array_index_of_resource(res, name); - if (array_index < 0) - return -1; - } - /* Built-in locations should report GL_INVALID_INDEX. */ if (is_gl_identifier(name)) return GL_INVALID_INDEX; @@ -757,13 +755,22 @@ program_resource_location(struct gl_shader_program *shProg, */ switch (res->Type) { case GL_PROGRAM_INPUT: + /* If the input is an array, fail if the index is out of bounds. */ + if (array_index > 0 + && array_index >= RESOURCE_VAR(res)->type->length) { + return -1; + } return RESOURCE_VAR(res)->data.location + array_index - VERT_ATTRIB_GENERIC0; case GL_PROGRAM_OUTPUT: + /* If the output is an array, fail if the index is out of bounds. */ + if (array_index > 0 + && array_index >= RESOURCE_VAR(res)->type->length) { + return -1; + } return RESOURCE_VAR(res)->data.location + array_index - FRAG_RESULT_DATA0; case GL_UNIFORM: - index = _mesa_get_uniform_location(shProg, name, &offset); - - if (index == GL_INVALID_INDEX) + /* If the uniform is built-in, fail. */ + if (RESOURCE_UNI(res)->builtin) return -1; /* From the GL_ARB_uniform_buffer_object spec: @@ -777,9 +784,21 @@ program_resource_location(struct gl_shader_program *shProg, RESOURCE_UNI(res)->atomic_buffer_index != -1) return -1; - /* location in remap table + array element offset */ - return RESOURCE_UNI(res)->remap_location + offset; + /* fallthrough */ + case GL_VERTEX_SUBROUTINE_UNIFORM: + case GL_GEOMETRY_SUBROUTINE_UNIFORM: + case GL_FRAGMENT_SUBROUTINE_UNIFORM: + case GL_COMPUTE_SUBROUTINE_UNIFORM: + case GL_TESS_CONTROL_SUBROUTINE_UNIFORM: + case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM: + /* If the uniform is an array, fail if the index is out of bounds. */ + if (array_index > 0 + && array_index >= RESOURCE_UNI(res)->array_elements) { + return -1; + } + /* location in remap table + array element offset */ + return RESOURCE_UNI(res)->remap_location + array_index; default: return -1; } @@ -787,22 +806,22 @@ program_resource_location(struct gl_shader_program *shProg, /** * Function implements following location queries: - * glGetAttribLocation - * glGetFragDataLocation * glGetUniformLocation */ GLint _mesa_program_resource_location(struct gl_shader_program *shProg, GLenum programInterface, const char *name) { + unsigned array_index = 0; struct gl_program_resource *res = - _mesa_program_resource_find_name(shProg, programInterface, name); + _mesa_program_resource_find_name(shProg, programInterface, name, + &array_index); /* Resource not found. */ if (!res) return -1; - return program_resource_location(shProg, res, name); + return program_resource_location(shProg, res, name, array_index); } /** @@ -814,7 +833,7 @@ _mesa_program_resource_location_index(struct gl_shader_program *shProg, GLenum programInterface, const char *name) { struct gl_program_resource *res = - _mesa_program_resource_find_name(shProg, programInterface, name); + _mesa_program_resource_find_name(shProg, programInterface, name, NULL); /* Non-existent variable or resource is not referenced by fragment stage. */ if (!res || !(res->StageReferences & (1 << MESA_SHADER_FRAGMENT))) @@ -829,6 +848,10 @@ stage_from_enum(GLenum ref) switch (ref) { case GL_REFERENCED_BY_VERTEX_SHADER: return MESA_SHADER_VERTEX; + case GL_REFERENCED_BY_TESS_CONTROL_SHADER: + return MESA_SHADER_TESS_CTRL; + case GL_REFERENCED_BY_TESS_EVALUATION_SHADER: + return MESA_SHADER_TESS_EVAL; case GL_REFERENCED_BY_GEOMETRY_SHADER: return MESA_SHADER_GEOMETRY; case GL_REFERENCED_BY_FRAGMENT_SHADER: @@ -886,7 +909,8 @@ get_buffer_property(struct gl_shader_program *shProg, for (unsigned i = 0; i < RESOURCE_UBO(res)->NumUniforms; i++) { const char *iname = RESOURCE_UBO(res)->Uniforms[i].IndexName; struct gl_program_resource *uni = - _mesa_program_resource_find_name(shProg, GL_UNIFORM, iname); + _mesa_program_resource_find_name(shProg, GL_UNIFORM, iname, + NULL); if (!uni) continue; (*val)++; @@ -896,7 +920,8 @@ get_buffer_property(struct gl_shader_program *shProg, for (unsigned i = 0; i < RESOURCE_UBO(res)->NumUniforms; i++) { const char *iname = RESOURCE_UBO(res)->Uniforms[i].IndexName; struct gl_program_resource *uni = - _mesa_program_resource_find_name(shProg, GL_UNIFORM, iname); + _mesa_program_resource_find_name(shProg, GL_UNIFORM, iname, + NULL); if (!uni) continue; *val++ = @@ -925,8 +950,8 @@ get_buffer_property(struct gl_shader_program *shProg, invalid_operation: _mesa_error(ctx, GL_INVALID_OPERATION, "%s(%s prop %s)", caller, - _mesa_lookup_enum_by_nr(res->Type), - _mesa_lookup_enum_by_nr(prop)); + _mesa_enum_to_string(res->Type), + _mesa_enum_to_string(prop)); return 0; } @@ -944,11 +969,17 @@ _mesa_program_resource_prop(struct gl_shader_program *shProg, switch(prop) { case GL_NAME_LENGTH: - if (res->Type == GL_ATOMIC_COUNTER_BUFFER) + switch (res->Type) { + case GL_ATOMIC_COUNTER_BUFFER: goto invalid_operation; - /* Base name +3 if array '[0]' + terminator. */ - *val = strlen(_mesa_program_resource_name(res)) + - (_mesa_program_resource_array_size(res) > 0 ? 3 : 0) + 1; + case GL_TRANSFORM_FEEDBACK_VARYING: + *val = strlen(_mesa_program_resource_name(res)) + 1; + break; + default: + /* Base name +3 if array '[0]' + terminator. */ + *val = strlen(_mesa_program_resource_name(res)) + + (_mesa_program_resource_array_size(res) > 0 ? 3 : 0) + 1; + } return 1; case GL_TYPE: switch (res->Type) { @@ -1014,6 +1045,8 @@ _mesa_program_resource_prop(struct gl_shader_program *shProg, goto invalid_enum; /* fallthrough */ case GL_REFERENCED_BY_VERTEX_SHADER: + case GL_REFERENCED_BY_TESS_CONTROL_SHADER: + case GL_REFERENCED_BY_TESS_EVALUATION_SHADER: case GL_REFERENCED_BY_GEOMETRY_SHADER: case GL_REFERENCED_BY_FRAGMENT_SHADER: switch (res->Type) { @@ -1034,7 +1067,8 @@ _mesa_program_resource_prop(struct gl_shader_program *shProg, case GL_PROGRAM_INPUT: case GL_PROGRAM_OUTPUT: *val = program_resource_location(shProg, res, - _mesa_program_resource_name(res)); + _mesa_program_resource_name(res), + 0); return 1; default: goto invalid_operation; @@ -1045,10 +1079,54 @@ _mesa_program_resource_prop(struct gl_shader_program *shProg, *val = RESOURCE_VAR(res)->data.index; return 1; + case GL_NUM_COMPATIBLE_SUBROUTINES: + if (res->Type != GL_VERTEX_SUBROUTINE_UNIFORM && + res->Type != GL_FRAGMENT_SUBROUTINE_UNIFORM && + res->Type != GL_GEOMETRY_SUBROUTINE_UNIFORM && + res->Type != GL_COMPUTE_SUBROUTINE_UNIFORM && + res->Type != GL_TESS_CONTROL_SUBROUTINE_UNIFORM && + res->Type != GL_TESS_EVALUATION_SUBROUTINE_UNIFORM) + goto invalid_operation; + *val = RESOURCE_UNI(res)->num_compatible_subroutines; + return 1; + case GL_COMPATIBLE_SUBROUTINES: { + const struct gl_uniform_storage *uni; + struct gl_shader *sh; + unsigned count, i; + int j; + + if (res->Type != GL_VERTEX_SUBROUTINE_UNIFORM && + res->Type != GL_FRAGMENT_SUBROUTINE_UNIFORM && + res->Type != GL_GEOMETRY_SUBROUTINE_UNIFORM && + res->Type != GL_COMPUTE_SUBROUTINE_UNIFORM && + res->Type != GL_TESS_CONTROL_SUBROUTINE_UNIFORM && + res->Type != GL_TESS_EVALUATION_SUBROUTINE_UNIFORM) + goto invalid_operation; + uni = RESOURCE_UNI(res); + + sh = shProg->_LinkedShaders[_mesa_shader_stage_from_subroutine_uniform(res->Type)]; + count = 0; + for (i = 0; i < sh->NumSubroutineFunctions; i++) { + struct gl_subroutine_function *fn = &sh->SubroutineFunctions[i]; + for (j = 0; j < fn->num_compat_types; j++) { + if (fn->types[j] == uni->type) { + val[count++] = i; + break; + } + } + } + return count; + } /* GL_ARB_tessellation_shader */ case GL_IS_PER_PATCH: - case GL_REFERENCED_BY_TESS_CONTROL_SHADER: - case GL_REFERENCED_BY_TESS_EVALUATION_SHADER: + switch (res->Type) { + case GL_PROGRAM_INPUT: + case GL_PROGRAM_OUTPUT: + *val = RESOURCE_VAR(res)->data.patch; + return 1; + default: + goto invalid_operation; + } default: goto invalid_enum; } @@ -1057,14 +1135,14 @@ _mesa_program_resource_prop(struct gl_shader_program *shProg, invalid_enum: _mesa_error(ctx, GL_INVALID_ENUM, "%s(%s prop %s)", caller, - _mesa_lookup_enum_by_nr(res->Type), - _mesa_lookup_enum_by_nr(prop)); + _mesa_enum_to_string(res->Type), + _mesa_enum_to_string(prop)); return 0; invalid_operation: _mesa_error(ctx, GL_INVALID_OPERATION, "%s(%s prop %s)", caller, - _mesa_lookup_enum_by_nr(res->Type), - _mesa_lookup_enum_by_nr(prop)); + _mesa_enum_to_string(res->Type), + _mesa_enum_to_string(prop)); return 0; } @@ -1086,7 +1164,7 @@ _mesa_get_program_resourceiv(struct gl_shader_program *shProg, if (!res || bufSize < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramResourceiv(%s index %d bufSize %d)", - _mesa_lookup_enum_by_nr(programInterface), index, bufSize); + _mesa_enum_to_string(programInterface), index, bufSize); return; } diff --git a/src/mesa/main/shaderapi.c b/src/mesa/main/shaderapi.c index a4296adf799..f9a7d130f9c 100644 --- a/src/mesa/main/shaderapi.c +++ b/src/mesa/main/shaderapi.c @@ -110,6 +110,7 @@ _mesa_init_shader_state(struct gl_context *ctx) */ struct gl_shader_compiler_options options; gl_shader_stage sh; + int i; memset(&options, 0, sizeof(options)); options.MaxUnrollIterations = 32; @@ -126,6 +127,12 @@ _mesa_init_shader_state(struct gl_context *ctx) /* Extended for ARB_separate_shader_objects */ ctx->Shader.RefCount = 1; mtx_init(&ctx->Shader.Mutex, mtx_plain); + + ctx->TessCtrlProgram.patch_vertices = 3; + for (i = 0; i < 4; ++i) + ctx->TessCtrlProgram.patch_default_outer_level[i] = 1.0; + for (i = 0; i < 2; ++i) + ctx->TessCtrlProgram.patch_default_inner_level[i] = 1.0; } @@ -199,6 +206,9 @@ _mesa_validate_shader_target(const struct gl_context *ctx, GLenum type) return ctx == NULL || ctx->Extensions.ARB_vertex_shader; case GL_GEOMETRY_SHADER_ARB: return ctx == NULL || _mesa_has_geometry_shaders(ctx); + case GL_TESS_CONTROL_SHADER: + case GL_TESS_EVALUATION_SHADER: + return ctx == NULL || _mesa_has_tessellation(ctx); case GL_COMPUTE_SHADER: return ctx == NULL || ctx->Extensions.ARB_compute_shader; default: @@ -415,6 +425,8 @@ detach_shader(struct gl_context *ctx, GLuint program, GLuint shader) /* sanity check - make sure the new list's entries are sensible */ for (j = 0; j < shProg->NumShaders; j++) { assert(shProg->Shaders[j]->Type == GL_VERTEX_SHADER || + shProg->Shaders[j]->Type == GL_TESS_CONTROL_SHADER || + shProg->Shaders[j]->Type == GL_TESS_EVALUATION_SHADER || shProg->Shaders[j]->Type == GL_GEOMETRY_SHADER || shProg->Shaders[j]->Type == GL_FRAGMENT_SHADER); assert(shProg->Shaders[j]->RefCount > 0); @@ -511,6 +523,57 @@ check_gs_query(struct gl_context *ctx, const struct gl_shader_program *shProg) /** + * Check if a tessellation control shader query is valid at this time. + * If not, report an error and return false. + * + * From GL 4.0 section 6.1.12 (Shader and Program Queries): + * + * "If TESS_CONTROL_OUTPUT_VERTICES is queried for a program which has + * not been linked successfully, or which does not contain objects to + * form a tessellation control shader, then an INVALID_OPERATION error is + * generated." + */ +static bool +check_tcs_query(struct gl_context *ctx, const struct gl_shader_program *shProg) +{ + if (shProg->LinkStatus && + shProg->_LinkedShaders[MESA_SHADER_TESS_CTRL] != NULL) { + return true; + } + + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetProgramv(linked tessellation control shader required)"); + return false; +} + + +/** + * Check if a tessellation evaluation shader query is valid at this time. + * If not, report an error and return false. + * + * From GL 4.0 section 6.1.12 (Shader and Program Queries): + * + * "If any of the pname values in this paragraph are queried for a program + * which has not been linked successfully, or which does not contain + * objects to form a tessellation evaluation shader, then an + * INVALID_OPERATION error is generated." + * + */ +static bool +check_tes_query(struct gl_context *ctx, const struct gl_shader_program *shProg) +{ + if (shProg->LinkStatus && + shProg->_LinkedShaders[MESA_SHADER_TESS_EVAL] != NULL) { + return true; + } + + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramv(linked tessellation " + "evaluation shader required)"); + return false; +} + + +/** * glGetProgramiv() - get shader program state. * Note that this is for GLSL shader programs, not ARB vertex/fragment * programs (see glGetProgramivARB). @@ -533,6 +596,7 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname, * and GL 3.2) are available in this context */ const bool has_core_gs = _mesa_has_geometry_shaders(ctx); + const bool has_tess = _mesa_has_tessellation(ctx); /* Are uniform buffer objects available in this context? */ @@ -711,12 +775,44 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname, case GL_PROGRAM_SEPARABLE: *params = shProg->SeparateShader; return; + + /* ARB_tessellation_shader */ + case GL_TESS_CONTROL_OUTPUT_VERTICES: + if (!has_tess) + break; + if (check_tcs_query(ctx, shProg)) + *params = shProg->TessCtrl.VerticesOut; + return; + case GL_TESS_GEN_MODE: + if (!has_tess) + break; + if (check_tes_query(ctx, shProg)) + *params = shProg->TessEval.PrimitiveMode; + return; + case GL_TESS_GEN_SPACING: + if (!has_tess) + break; + if (check_tes_query(ctx, shProg)) + *params = shProg->TessEval.Spacing; + return; + case GL_TESS_GEN_VERTEX_ORDER: + if (!has_tess) + break; + if (check_tes_query(ctx, shProg)) + *params = shProg->TessEval.VertexOrder; + return; + case GL_TESS_GEN_POINT_MODE: + if (!has_tess) + break; + if (check_tes_query(ctx, shProg)) + *params = shProg->TessEval.PointMode; + return; default: break; } _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname=%s)", - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); } @@ -992,6 +1088,12 @@ print_shader_info(const struct gl_shader_program *shProg) if (shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]) printf(" geom prog %u\n", shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]->Program->Id); + if (shProg->_LinkedShaders[MESA_SHADER_TESS_CTRL]) + printf(" tesc prog %u\n", + shProg->_LinkedShaders[MESA_SHADER_TESS_CTRL]->Program->Id); + if (shProg->_LinkedShaders[MESA_SHADER_TESS_EVAL]) + printf(" tese prog %u\n", + shProg->_LinkedShaders[MESA_SHADER_TESS_EVAL]->Program->Id); } @@ -1037,11 +1139,9 @@ use_shader_program(struct gl_context *ctx, gl_shader_stage stage, */ switch (stage) { case MESA_SHADER_VERTEX: - /* Empty for now. */ - break; + case MESA_SHADER_TESS_CTRL: + case MESA_SHADER_TESS_EVAL: case MESA_SHADER_GEOMETRY: - /* Empty for now. */ - break; case MESA_SHADER_COMPUTE: /* Empty for now. */ break; @@ -1071,6 +1171,7 @@ _mesa_use_program(struct gl_context *ctx, struct gl_shader_program *shProg) use_shader_program(ctx, i, shProg, &ctx->Shader); _mesa_active_program(ctx, shProg, "glUseProgram"); + _mesa_shader_program_init_subroutine_defaults(shProg); if (ctx->Driver.UseProgram) ctx->Driver.UseProgram(ctx, shProg); } @@ -1172,7 +1273,7 @@ _mesa_CreateShader(GLenum type) { GET_CURRENT_CONTEXT(ctx); if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glCreateShader %s\n", _mesa_lookup_enum_by_nr(type)); + _mesa_debug(ctx, "glCreateShader %s\n", _mesa_enum_to_string(type)); return create_shader(ctx, type); } @@ -1331,7 +1432,7 @@ void GLAPIENTRY _mesa_GetObjectParameterfvARB(GLhandleARB object, GLenum pname, GLfloat *params) { - GLint iparams[1]; /* XXX is one element enough? */ + GLint iparams[1] = {0}; /* XXX is one element enough? */ _mesa_GetObjectParameterivARB(object, pname, iparams); params[0] = (GLfloat) iparams[0]; } @@ -1460,7 +1561,7 @@ read_shader(const char *fname) */ void GLAPIENTRY _mesa_ShaderSource(GLhandleARB shaderObj, GLsizei count, - const GLcharARB * const * string, const GLint * length) + const GLcharARB * const * string, const GLint * length) { GET_CURRENT_CONTEXT(ctx); GLint *offsets; @@ -1692,12 +1793,23 @@ _mesa_ShaderBinary(GLint n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLint length) { GET_CURRENT_CONTEXT(ctx); - (void) n; (void) shaders; (void) binaryformat; (void) binary; - (void) length; - _mesa_error(ctx, GL_INVALID_OPERATION, "glShaderBinary"); + + /* Page 68, section 7.2 'Shader Binaries" of the of the OpenGL ES 3.1, and + * page 88 of the OpenGL 4.5 specs state: + * + * "An INVALID_VALUE error is generated if count or length is negative. + * An INVALID_ENUM error is generated if binaryformat is not a supported + * format returned in SHADER_BINARY_FORMATS." + */ + if (n < 0 || length < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glShaderBinary(count or length < 0)"); + return; + } + + _mesa_error(ctx, GL_INVALID_ENUM, "glShaderBinary(format)"); } @@ -1857,7 +1969,7 @@ _mesa_ProgramParameteri(GLuint program, GLenum pname, GLint value) default: _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameteri(pname=%s)", - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); return; } @@ -1865,7 +1977,7 @@ invalid_value: _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameteri(pname=%s, value=%d): " "value must be 0 or 1.", - _mesa_lookup_enum_by_nr(pname), + _mesa_enum_to_string(pname), value); } @@ -1885,7 +1997,8 @@ _mesa_use_shader_program(struct gl_context *ctx, GLenum type, static GLuint _mesa_create_shader_program(struct gl_context* ctx, GLboolean separate, - GLenum type, GLsizei count, const GLchar* const *strings) + GLenum type, GLsizei count, + const GLchar* const *strings) { const GLuint shader = create_shader(ctx, type); GLuint program = 0; @@ -1920,8 +2033,8 @@ _mesa_create_shader_program(struct gl_context* ctx, GLboolean separate, } #endif } - - ralloc_strcat(&shProg->InfoLog, sh->InfoLog); + if (sh->InfoLog) + ralloc_strcat(&shProg->InfoLog, sh->InfoLog); } delete_shader(ctx, shader); @@ -1944,6 +2057,22 @@ _mesa_copy_linked_program_data(gl_shader_stage type, case MESA_SHADER_VERTEX: dst->UsesClipDistanceOut = src->Vert.UsesClipDistance; break; + case MESA_SHADER_TESS_CTRL: { + struct gl_tess_ctrl_program *dst_tcp = + (struct gl_tess_ctrl_program *) dst; + dst_tcp->VerticesOut = src->TessCtrl.VerticesOut; + break; + } + case MESA_SHADER_TESS_EVAL: { + struct gl_tess_eval_program *dst_tep = + (struct gl_tess_eval_program *) dst; + dst_tep->PrimitiveMode = src->TessEval.PrimitiveMode; + dst_tep->Spacing = src->TessEval.Spacing; + dst_tep->VertexOrder = src->TessEval.VertexOrder; + dst_tep->PointMode = src->TessEval.PointMode; + dst->UsesClipDistanceOut = src->TessEval.UsesClipDistance; + break; + } case MESA_SHADER_GEOMETRY: { struct gl_geometry_program *dst_gp = (struct gl_geometry_program *) dst; dst_gp->VerticesIn = src->Geom.VerticesIn; @@ -1954,20 +2083,20 @@ _mesa_copy_linked_program_data(gl_shader_stage type, dst->UsesClipDistanceOut = src->Geom.UsesClipDistance; dst_gp->UsesEndPrimitive = src->Geom.UsesEndPrimitive; dst_gp->UsesStreams = src->Geom.UsesStreams; - } break; + } case MESA_SHADER_FRAGMENT: { struct gl_fragment_program *dst_fp = (struct gl_fragment_program *) dst; dst_fp->FragDepthLayout = src->FragDepthLayout; - } break; + } case MESA_SHADER_COMPUTE: { struct gl_compute_program *dst_cp = (struct gl_compute_program *) dst; int i; for (i = 0; i < 3; i++) dst_cp->LocalSize[i] = src->Comp.LocalSize[i]; - } break; + } default: break; } @@ -1984,3 +2113,568 @@ _mesa_CreateShaderProgramv(GLenum type, GLsizei count, return _mesa_create_shader_program(ctx, GL_TRUE, type, count, strings); } + + +/** + * For GL_ARB_tessellation_shader + */ +extern void GLAPIENTRY +_mesa_PatchParameteri(GLenum pname, GLint value) +{ + GET_CURRENT_CONTEXT(ctx); + + if (!_mesa_has_tessellation(ctx)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glPatchParameteri"); + return; + } + + if (pname != GL_PATCH_VERTICES) { + _mesa_error(ctx, GL_INVALID_ENUM, "glPatchParameteri"); + return; + } + + if (value <= 0 || value > ctx->Const.MaxPatchVertices) { + _mesa_error(ctx, GL_INVALID_VALUE, "glPatchParameteri"); + return; + } + + ctx->TessCtrlProgram.patch_vertices = value; +} + + +extern void GLAPIENTRY +_mesa_PatchParameterfv(GLenum pname, const GLfloat *values) +{ + GET_CURRENT_CONTEXT(ctx); + + if (!_mesa_has_tessellation(ctx)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glPatchParameterfv"); + return; + } + + switch(pname) { + case GL_PATCH_DEFAULT_OUTER_LEVEL: + FLUSH_VERTICES(ctx, 0); + memcpy(ctx->TessCtrlProgram.patch_default_outer_level, values, + 4 * sizeof(GLfloat)); + ctx->NewDriverState |= ctx->DriverFlags.NewDefaultTessLevels; + return; + case GL_PATCH_DEFAULT_INNER_LEVEL: + FLUSH_VERTICES(ctx, 0); + memcpy(ctx->TessCtrlProgram.patch_default_inner_level, values, + 2 * sizeof(GLfloat)); + ctx->NewDriverState |= ctx->DriverFlags.NewDefaultTessLevels; + return; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glPatchParameterfv"); + return; + } +} + +/** + * ARB_shader_subroutine + */ +GLint GLAPIENTRY +_mesa_GetSubroutineUniformLocation(GLuint program, GLenum shadertype, + const GLchar *name) +{ + GET_CURRENT_CONTEXT(ctx); + const char *api_name = "glGetSubroutineUniformLocation"; + struct gl_shader_program *shProg; + GLenum resource_type; + gl_shader_stage stage; + + if (!_mesa_has_shader_subroutine(ctx)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); + return -1; + } + + if (!_mesa_validate_shader_target(ctx, shadertype)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); + return -1; + } + + shProg = _mesa_lookup_shader_program_err(ctx, program, api_name); + if (!shProg) + return -1; + + stage = _mesa_shader_enum_to_shader_stage(shadertype); + if (!shProg->_LinkedShaders[stage]) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); + return -1; + } + + resource_type = _mesa_shader_stage_to_subroutine_uniform(stage); + return _mesa_program_resource_location(shProg, resource_type, name); +} + +GLuint GLAPIENTRY +_mesa_GetSubroutineIndex(GLuint program, GLenum shadertype, + const GLchar *name) +{ + GET_CURRENT_CONTEXT(ctx); + const char *api_name = "glGetSubroutineIndex"; + struct gl_shader_program *shProg; + struct gl_program_resource *res; + GLenum resource_type; + gl_shader_stage stage; + + if (!_mesa_has_shader_subroutine(ctx)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); + return -1; + } + + if (!_mesa_validate_shader_target(ctx, shadertype)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); + return -1; + } + + shProg = _mesa_lookup_shader_program_err(ctx, program, api_name); + if (!shProg) + return -1; + + stage = _mesa_shader_enum_to_shader_stage(shadertype); + if (!shProg->_LinkedShaders[stage]) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); + return -1; + } + + resource_type = _mesa_shader_stage_to_subroutine(stage); + res = _mesa_program_resource_find_name(shProg, resource_type, name, NULL); + if (!res) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); + return -1; + } + + return _mesa_program_resource_index(shProg, res); +} + + +GLvoid GLAPIENTRY +_mesa_GetActiveSubroutineUniformiv(GLuint program, GLenum shadertype, + GLuint index, GLenum pname, GLint *values) +{ + GET_CURRENT_CONTEXT(ctx); + const char *api_name = "glGetActiveSubroutineUniformiv"; + struct gl_shader_program *shProg; + struct gl_shader *sh; + gl_shader_stage stage; + struct gl_program_resource *res; + const struct gl_uniform_storage *uni; + GLenum resource_type; + int count, i, j; + + if (!_mesa_has_shader_subroutine(ctx)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); + return; + } + + if (!_mesa_validate_shader_target(ctx, shadertype)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); + return; + } + + shProg = _mesa_lookup_shader_program_err(ctx, program, api_name); + if (!shProg) + return; + + stage = _mesa_shader_enum_to_shader_stage(shadertype); + resource_type = _mesa_shader_stage_to_subroutine_uniform(stage); + + sh = shProg->_LinkedShaders[stage]; + if (!sh) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); + return; + } + + switch (pname) { + case GL_NUM_COMPATIBLE_SUBROUTINES: { + res = _mesa_program_resource_find_index(shProg, resource_type, index); + if (res) { + uni = res->Data; + values[0] = uni->num_compatible_subroutines; + } + break; + } + case GL_COMPATIBLE_SUBROUTINES: { + res = _mesa_program_resource_find_index(shProg, resource_type, index); + if (res) { + uni = res->Data; + count = 0; + for (i = 0; i < sh->NumSubroutineFunctions; i++) { + struct gl_subroutine_function *fn = &sh->SubroutineFunctions[i]; + for (j = 0; j < fn->num_compat_types; j++) { + if (fn->types[j] == uni->type) { + values[count++] = i; + break; + } + } + } + } + break; + } + case GL_UNIFORM_SIZE: + res = _mesa_program_resource_find_index(shProg, resource_type, index); + if (res) { + uni = res->Data; + values[0] = uni->array_elements ? uni->array_elements : 1; + } + break; + case GL_UNIFORM_NAME_LENGTH: + res = _mesa_program_resource_find_index(shProg, resource_type, index); + if (res) { + values[0] = strlen(_mesa_program_resource_name(res)) + 1 + + ((_mesa_program_resource_array_size(res) != 0) ? 3 : 0);; + } + break; + default: + _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); + return; + } +} + + +GLvoid GLAPIENTRY +_mesa_GetActiveSubroutineUniformName(GLuint program, GLenum shadertype, + GLuint index, GLsizei bufsize, + GLsizei *length, GLchar *name) +{ + GET_CURRENT_CONTEXT(ctx); + const char *api_name = "glGetActiveSubroutineUniformName"; + struct gl_shader_program *shProg; + GLenum resource_type; + gl_shader_stage stage; + + if (!_mesa_has_shader_subroutine(ctx)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); + return; + } + + if (!_mesa_validate_shader_target(ctx, shadertype)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); + return; + } + + shProg = _mesa_lookup_shader_program_err(ctx, program, api_name); + if (!shProg) + return; + + stage = _mesa_shader_enum_to_shader_stage(shadertype); + if (!shProg->_LinkedShaders[stage]) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); + return; + } + + resource_type = _mesa_shader_stage_to_subroutine_uniform(stage); + /* get program resource name */ + _mesa_get_program_resource_name(shProg, resource_type, + index, bufsize, + length, name, api_name); +} + + +GLvoid GLAPIENTRY +_mesa_GetActiveSubroutineName(GLuint program, GLenum shadertype, + GLuint index, GLsizei bufsize, + GLsizei *length, GLchar *name) +{ + GET_CURRENT_CONTEXT(ctx); + const char *api_name = "glGetActiveSubroutineName"; + struct gl_shader_program *shProg; + GLenum resource_type; + gl_shader_stage stage; + + if (!_mesa_has_shader_subroutine(ctx)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); + return; + } + + if (!_mesa_validate_shader_target(ctx, shadertype)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); + return; + } + + shProg = _mesa_lookup_shader_program_err(ctx, program, api_name); + if (!shProg) + return; + + stage = _mesa_shader_enum_to_shader_stage(shadertype); + if (!shProg->_LinkedShaders[stage]) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); + return; + } + resource_type = _mesa_shader_stage_to_subroutine(stage); + _mesa_get_program_resource_name(shProg, resource_type, + index, bufsize, + length, name, api_name); +} + + +GLvoid GLAPIENTRY +_mesa_UniformSubroutinesuiv(GLenum shadertype, GLsizei count, + const GLuint *indices) +{ + GET_CURRENT_CONTEXT(ctx); + const char *api_name = "glUniformSubroutinesuiv"; + struct gl_shader_program *shProg; + struct gl_shader *sh; + gl_shader_stage stage; + int i; + + if (!_mesa_has_shader_subroutine(ctx)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); + return; + } + + if (!_mesa_validate_shader_target(ctx, shadertype)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); + return; + } + + stage = _mesa_shader_enum_to_shader_stage(shadertype); + shProg = ctx->_Shader->CurrentProgram[stage]; + if (!shProg) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); + return; + } + + sh = shProg->_LinkedShaders[stage]; + if (!sh) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); + return; + } + + if (count != sh->NumSubroutineUniformRemapTable) { + _mesa_error(ctx, GL_INVALID_VALUE, "%s", api_name); + return; + } + + i = 0; + do { + struct gl_uniform_storage *uni = sh->SubroutineUniformRemapTable[i]; + int uni_count = uni->array_elements ? uni->array_elements : 1; + int j, k; + + for (j = i; j < i + uni_count; j++) { + struct gl_subroutine_function *subfn; + if (indices[j] >= sh->NumSubroutineFunctions) { + _mesa_error(ctx, GL_INVALID_VALUE, "%s", api_name); + return; + } + + subfn = &sh->SubroutineFunctions[indices[j]]; + for (k = 0; k < subfn->num_compat_types; k++) { + if (subfn->types[k] == uni->type) + break; + } + if (k == subfn->num_compat_types) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); + return; + } + } + i += uni_count; + } while(i < count); + + FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS); + i = 0; + do { + struct gl_uniform_storage *uni = sh->SubroutineUniformRemapTable[i]; + int uni_count = uni->array_elements ? uni->array_elements : 1; + + memcpy(&uni->storage[0], &indices[i], + sizeof(GLuint) * uni_count); + + uni->initialized = true; + _mesa_propagate_uniforms_to_driver_storage(uni, 0, uni_count); + i += uni_count; + } while(i < count); +} + + +GLvoid GLAPIENTRY +_mesa_GetUniformSubroutineuiv(GLenum shadertype, GLint location, + GLuint *params) +{ + GET_CURRENT_CONTEXT(ctx); + const char *api_name = "glGetUniformSubroutineuiv"; + struct gl_shader_program *shProg; + struct gl_shader *sh; + gl_shader_stage stage; + + if (!_mesa_has_shader_subroutine(ctx)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); + return; + } + + if (!_mesa_validate_shader_target(ctx, shadertype)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); + return; + } + + stage = _mesa_shader_enum_to_shader_stage(shadertype); + shProg = ctx->_Shader->CurrentProgram[stage]; + if (!shProg) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); + return; + } + + sh = shProg->_LinkedShaders[stage]; + if (!sh) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); + return; + } + + if (location >= sh->NumSubroutineUniformRemapTable) { + _mesa_error(ctx, GL_INVALID_VALUE, "%s", api_name); + return; + } + + { + struct gl_uniform_storage *uni = sh->SubroutineUniformRemapTable[location]; + int offset = location - uni->subroutine[stage].index; + memcpy(params, &uni->storage[offset], + sizeof(GLuint)); + } +} + + +GLvoid GLAPIENTRY +_mesa_GetProgramStageiv(GLuint program, GLenum shadertype, + GLenum pname, GLint *values) +{ + GET_CURRENT_CONTEXT(ctx); + const char *api_name = "glGetProgramStageiv"; + struct gl_shader_program *shProg; + struct gl_shader *sh; + gl_shader_stage stage; + + if (!_mesa_has_shader_subroutine(ctx)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); + return; + } + + if (!_mesa_validate_shader_target(ctx, shadertype)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); + return; + } + + shProg = _mesa_lookup_shader_program_err(ctx, program, api_name); + if (!shProg) + return; + + stage = _mesa_shader_enum_to_shader_stage(shadertype); + sh = shProg->_LinkedShaders[stage]; + if (!sh) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); + return; + } + + switch (pname) { + case GL_ACTIVE_SUBROUTINES: + values[0] = sh->NumSubroutineFunctions; + break; + case GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS: + values[0] = sh->NumSubroutineUniformRemapTable; + break; + case GL_ACTIVE_SUBROUTINE_UNIFORMS: + values[0] = sh->NumSubroutineUniformTypes; + break; + case GL_ACTIVE_SUBROUTINE_MAX_LENGTH: + { + unsigned i; + GLint max_len = 0; + GLenum resource_type; + struct gl_program_resource *res; + + resource_type = _mesa_shader_stage_to_subroutine(stage); + for (i = 0; i < sh->NumSubroutineFunctions; i++) { + res = _mesa_program_resource_find_index(shProg, resource_type, i); + if (res) { + const GLint len = strlen(_mesa_program_resource_name(res)) + 1; + if (len > max_len) + max_len = len; + } + } + values[0] = max_len; + break; + } + case GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH: + { + unsigned i; + GLint max_len = 0; + GLenum resource_type; + struct gl_program_resource *res; + + resource_type = _mesa_shader_stage_to_subroutine_uniform(stage); + for (i = 0; i < sh->NumSubroutineUniformRemapTable; i++) { + res = _mesa_program_resource_find_index(shProg, resource_type, i); + if (res) { + const GLint len = strlen(_mesa_program_resource_name(res)) + 1 + + ((_mesa_program_resource_array_size(res) != 0) ? 3 : 0); + + if (len > max_len) + max_len = len; + } + } + values[0] = max_len; + break; + } + default: + _mesa_error(ctx, GL_INVALID_ENUM, "%s", api_name); + values[0] = -1; + break; + } +} + +static int +find_compat_subroutine(struct gl_shader *sh, const struct glsl_type *type) +{ + int i, j; + + for (i = 0; i < sh->NumSubroutineFunctions; i++) { + struct gl_subroutine_function *fn = &sh->SubroutineFunctions[i]; + for (j = 0; j < fn->num_compat_types; j++) { + if (fn->types[j] == type) + return i; + } + } + return 0; +} + +static void +_mesa_shader_init_subroutine_defaults(struct gl_shader *sh) +{ + int i, j; + + for (i = 0; i < sh->NumSubroutineUniformRemapTable; i++) { + struct gl_uniform_storage *uni = sh->SubroutineUniformRemapTable[i]; + int uni_count; + int val; + + if (!uni) + continue; + uni_count = uni->array_elements ? uni->array_elements : 1; + val = find_compat_subroutine(sh, uni->type); + + for (j = 0; j < uni_count; j++) + memcpy(&uni->storage[j], &val, sizeof(int)); + uni->initialized = true; + _mesa_propagate_uniforms_to_driver_storage(uni, 0, uni_count); + } +} + +void +_mesa_shader_program_init_subroutine_defaults(struct gl_shader_program *shProg) +{ + int i; + + if (!shProg) + return; + + for (i = 0; i < MESA_SHADER_STAGES; i++) { + if (!shProg->_LinkedShaders[i]) + continue; + + _mesa_shader_init_subroutine_defaults(shProg->_LinkedShaders[i]); + } +} diff --git a/src/mesa/main/shaderapi.h b/src/mesa/main/shaderapi.h index aba6d5d8306..0a10191684f 100644 --- a/src/mesa/main/shaderapi.h +++ b/src/mesa/main/shaderapi.h @@ -232,7 +232,8 @@ _mesa_program_resource_index(struct gl_shader_program *shProg, extern struct gl_program_resource * _mesa_program_resource_find_name(struct gl_shader_program *shProg, - GLenum programInterface, const char *name); + GLenum programInterface, const char *name, + unsigned *array_index); extern struct gl_program_resource * _mesa_program_resource_find_index(struct gl_shader_program *shProg, @@ -264,6 +265,51 @@ _mesa_get_program_resourceiv(struct gl_shader_program *shProg, GLsizei bufSize, GLsizei *length, GLint *params); +/* GL_ARB_tessellation_shader */ +extern void GLAPIENTRY +_mesa_PatchParameteri(GLenum pname, GLint value); + +extern void GLAPIENTRY +_mesa_PatchParameterfv(GLenum pname, const GLfloat *values); + +/* GL_ARB_shader_subroutine */ +void +_mesa_shader_program_init_subroutine_defaults(struct gl_shader_program *shProg); + +extern GLint GLAPIENTRY +_mesa_GetSubroutineUniformLocation(GLuint program, GLenum shadertype, + const GLchar *name); + +extern GLuint GLAPIENTRY +_mesa_GetSubroutineIndex(GLuint program, GLenum shadertype, + const GLchar *name); + +extern GLvoid GLAPIENTRY +_mesa_GetActiveSubroutineUniformiv(GLuint program, GLenum shadertype, + GLuint index, GLenum pname, GLint *values); + +extern GLvoid GLAPIENTRY +_mesa_GetActiveSubroutineUniformName(GLuint program, GLenum shadertype, + GLuint index, GLsizei bufsize, + GLsizei *length, GLchar *name); + +extern GLvoid GLAPIENTRY +_mesa_GetActiveSubroutineName(GLuint program, GLenum shadertype, + GLuint index, GLsizei bufsize, + GLsizei *length, GLchar *name); + +extern GLvoid GLAPIENTRY +_mesa_UniformSubroutinesuiv(GLenum shadertype, GLsizei count, + const GLuint *indices); + +extern GLvoid GLAPIENTRY +_mesa_GetUniformSubroutineuiv(GLenum shadertype, GLint location, + GLuint *params); + +extern GLvoid GLAPIENTRY +_mesa_GetProgramStageiv(GLuint program, GLenum shadertype, + GLenum pname, GLint *values); + #ifdef __cplusplus } #endif diff --git a/src/mesa/main/shaderimage.c b/src/mesa/main/shaderimage.c index 80b77275f93..a348cdb0405 100644 --- a/src/mesa/main/shaderimage.c +++ b/src/mesa/main/shaderimage.c @@ -610,7 +610,7 @@ _mesa_BindImageTextures(GLuint first, GLsizei count, const GLuint *textures) "glBindImageTextures(the internal format %s of " "the level zero texture image of textures[%d]=%u " "is not supported)", - _mesa_lookup_enum_by_nr(tex_format), + _mesa_enum_to_string(tex_format), i, texture); continue; } diff --git a/src/mesa/main/shaderobj.h b/src/mesa/main/shaderobj.h index 3d696a1887e..943044e37cd 100644 --- a/src/mesa/main/shaderobj.h +++ b/src/mesa/main/shaderobj.h @@ -111,6 +111,10 @@ _mesa_shader_enum_to_shader_stage(GLenum v) return MESA_SHADER_FRAGMENT; case GL_GEOMETRY_SHADER: return MESA_SHADER_GEOMETRY; + case GL_TESS_CONTROL_SHADER: + return MESA_SHADER_TESS_CTRL; + case GL_TESS_EVALUATION_SHADER: + return MESA_SHADER_TESS_EVAL; case GL_COMPUTE_SHADER: return MESA_SHADER_COMPUTE; default: @@ -119,6 +123,107 @@ _mesa_shader_enum_to_shader_stage(GLenum v) } } +/* 8 bytes + another underscore */ +#define MESA_SUBROUTINE_PREFIX_LEN 9 +static inline const char * +_mesa_shader_stage_to_subroutine_prefix(gl_shader_stage stage) +{ + switch (stage) { + case MESA_SHADER_VERTEX: + return "__subu_v"; + case MESA_SHADER_GEOMETRY: + return "__subu_g"; + case MESA_SHADER_FRAGMENT: + return "__subu_f"; + case MESA_SHADER_COMPUTE: + return "__subu_c"; + case MESA_SHADER_TESS_CTRL: + return "__subu_t"; + case MESA_SHADER_TESS_EVAL: + return "__subu_e"; + default: + return NULL; + } +} + +static inline gl_shader_stage +_mesa_shader_stage_from_subroutine_uniform(GLenum subuniform) +{ + switch (subuniform) { + default: + case GL_VERTEX_SUBROUTINE_UNIFORM: + return MESA_SHADER_VERTEX; + case GL_GEOMETRY_SUBROUTINE_UNIFORM: + return MESA_SHADER_GEOMETRY; + case GL_FRAGMENT_SUBROUTINE_UNIFORM: + return MESA_SHADER_FRAGMENT; + case GL_COMPUTE_SUBROUTINE_UNIFORM: + return MESA_SHADER_COMPUTE; + case GL_TESS_CONTROL_SUBROUTINE_UNIFORM: + return MESA_SHADER_TESS_CTRL; + case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM: + return MESA_SHADER_TESS_EVAL; + } +} + +static inline gl_shader_stage +_mesa_shader_stage_from_subroutine(GLenum subroutine) +{ + switch (subroutine) { + case GL_VERTEX_SUBROUTINE: + return MESA_SHADER_VERTEX; + case GL_GEOMETRY_SUBROUTINE: + return MESA_SHADER_GEOMETRY; + case GL_FRAGMENT_SUBROUTINE: + return MESA_SHADER_FRAGMENT; + case GL_COMPUTE_SUBROUTINE: + return MESA_SHADER_COMPUTE; + case GL_TESS_CONTROL_SUBROUTINE: + return MESA_SHADER_TESS_CTRL; + case GL_TESS_EVALUATION_SUBROUTINE: + return MESA_SHADER_TESS_EVAL; + } +} + +static inline GLenum +_mesa_shader_stage_to_subroutine(gl_shader_stage stage) +{ + switch (stage) { + default: + case MESA_SHADER_VERTEX: + return GL_VERTEX_SUBROUTINE; + case MESA_SHADER_GEOMETRY: + return GL_GEOMETRY_SUBROUTINE; + case MESA_SHADER_FRAGMENT: + return GL_FRAGMENT_SUBROUTINE; + case MESA_SHADER_COMPUTE: + return GL_COMPUTE_SUBROUTINE; + case MESA_SHADER_TESS_CTRL: + return GL_TESS_CONTROL_SUBROUTINE; + case MESA_SHADER_TESS_EVAL: + return GL_TESS_EVALUATION_SUBROUTINE; + } +} + +static inline GLenum +_mesa_shader_stage_to_subroutine_uniform(gl_shader_stage stage) +{ + switch (stage) { + default: + case MESA_SHADER_VERTEX: + return GL_VERTEX_SUBROUTINE_UNIFORM; + case MESA_SHADER_GEOMETRY: + return GL_GEOMETRY_SUBROUTINE_UNIFORM; + case MESA_SHADER_FRAGMENT: + return GL_FRAGMENT_SUBROUTINE_UNIFORM; + case MESA_SHADER_COMPUTE: + return GL_COMPUTE_SUBROUTINE_UNIFORM; + case MESA_SHADER_TESS_CTRL: + return GL_TESS_CONTROL_SUBROUTINE_UNIFORM; + case MESA_SHADER_TESS_EVAL: + return GL_TESS_EVALUATION_SUBROUTINE_UNIFORM; + } +} #ifdef __cplusplus } diff --git a/src/mesa/main/state.c b/src/mesa/main/state.c index bede7fe1d0e..d3b1c72b08d 100644 --- a/src/mesa/main/state.c +++ b/src/mesa/main/state.c @@ -79,8 +79,8 @@ update_program_enables(struct gl_context *ctx) /** - * Update the ctx->Vertex/Geometry/FragmentProgram._Current pointers to point - * to the current/active programs. Then call ctx->Driver.BindProgram() to + * Update the ctx->*Program._Current pointers to point to the + * current/active programs. Then call ctx->Driver.BindProgram() to * tell the driver which programs to use. * * Programs may come from 3 sources: GLSL shaders, ARB/NV_vertex/fragment @@ -97,6 +97,10 @@ update_program(struct gl_context *ctx) { const struct gl_shader_program *vsProg = ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX]; + const struct gl_shader_program *tcsProg = + ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_CTRL]; + const struct gl_shader_program *tesProg = + ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_EVAL]; const struct gl_shader_program *gsProg = ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY]; struct gl_shader_program *fsProg = @@ -106,6 +110,8 @@ update_program(struct gl_context *ctx) const struct gl_vertex_program *prevVP = ctx->VertexProgram._Current; const struct gl_fragment_program *prevFP = ctx->FragmentProgram._Current; const struct gl_geometry_program *prevGP = ctx->GeometryProgram._Current; + const struct gl_tess_ctrl_program *prevTCP = ctx->TessCtrlProgram._Current; + const struct gl_tess_eval_program *prevTEP = ctx->TessEvalProgram._Current; const struct gl_compute_program *prevCP = ctx->ComputeProgram._Current; GLbitfield new_state = 0x0; @@ -175,6 +181,30 @@ update_program(struct gl_context *ctx) _mesa_reference_geomprog(ctx, &ctx->GeometryProgram._Current, NULL); } + if (tesProg && tesProg->LinkStatus + && tesProg->_LinkedShaders[MESA_SHADER_TESS_EVAL]) { + /* Use GLSL tessellation evaluation shader */ + _mesa_reference_tesseprog(ctx, &ctx->TessEvalProgram._Current, + gl_tess_eval_program( + tesProg->_LinkedShaders[MESA_SHADER_TESS_EVAL]->Program)); + } + else { + /* No tessellation evaluation program */ + _mesa_reference_tesseprog(ctx, &ctx->TessEvalProgram._Current, NULL); + } + + if (tcsProg && tcsProg->LinkStatus + && tcsProg->_LinkedShaders[MESA_SHADER_TESS_CTRL]) { + /* Use GLSL tessellation control shader */ + _mesa_reference_tesscprog(ctx, &ctx->TessCtrlProgram._Current, + gl_tess_ctrl_program( + tcsProg->_LinkedShaders[MESA_SHADER_TESS_CTRL]->Program)); + } + else { + /* No tessellation control program */ + _mesa_reference_tesscprog(ctx, &ctx->TessCtrlProgram._Current, NULL); + } + /* Examine vertex program after fragment program as * _mesa_get_fixed_func_vertex_program() needs to know active * fragprog inputs. @@ -230,6 +260,22 @@ update_program(struct gl_context *ctx) } } + if (ctx->TessEvalProgram._Current != prevTEP) { + new_state |= _NEW_PROGRAM; + if (ctx->Driver.BindProgram) { + ctx->Driver.BindProgram(ctx, GL_TESS_EVALUATION_PROGRAM_NV, + (struct gl_program *) ctx->TessEvalProgram._Current); + } + } + + if (ctx->TessCtrlProgram._Current != prevTCP) { + new_state |= _NEW_PROGRAM; + if (ctx->Driver.BindProgram) { + ctx->Driver.BindProgram(ctx, GL_TESS_CONTROL_PROGRAM_NV, + (struct gl_program *) ctx->TessCtrlProgram._Current); + } + } + if (ctx->VertexProgram._Current != prevVP) { new_state |= _NEW_PROGRAM; if (ctx->Driver.BindProgram) { @@ -266,8 +312,8 @@ update_program_constants(struct gl_context *ctx) } } - /* Don't handle geometry shaders here. They don't use any state - * constants. + /* Don't handle tessellation and geometry shaders here. They don't use + * any state constants. */ if (ctx->VertexProgram._Current) { diff --git a/src/mesa/main/tests/dispatch_sanity.cpp b/src/mesa/main/tests/dispatch_sanity.cpp index 800720b798e..af89d2c1cfb 100644 --- a/src/mesa/main/tests/dispatch_sanity.cpp +++ b/src/mesa/main/tests/dispatch_sanity.cpp @@ -563,6 +563,8 @@ const struct function common_desktop_functions_possible[] = { /* GL 4.0 */ { "glMinSampleShading", 40, -1 }, + { "glPatchParameteri", 40, -1 }, + { "glPatchParameterfv", 40, -1 }, { "glBlendEquationi", 40, -1 }, { "glBlendEquationSeparatei", 40, -1 }, { "glBlendFunci", 40, -1 }, @@ -930,6 +932,11 @@ const struct function common_desktop_functions_possible[] = { /* GL_EXT_polygon_offset_clamp */ { "glPolygonOffsetClampEXT", 11, -1 }, + + /* GL_ARB_get_texture_sub_image */ + { "glGetTextureSubImage", 20, -1 }, + { "glGetCompressedTextureSubImage", 20, -1 }, + { NULL, 0, -1 } }; @@ -1424,6 +1431,16 @@ const struct function gl_core_functions_possible[] = { /* GL 3.2 */ { "glFramebufferTexture", 32, -1 }, + /* GL 4.0 */ + { "glGetSubroutineUniformLocation", 40, -1 }, + { "glGetSubroutineIndex", 40, -1 }, + { "glGetActiveSubroutineUniformiv", 40, -1 }, + { "glGetActiveSubroutineUniformName", 40, -1 }, + { "glGetActiveSubroutineName", 40, -1 }, + { "glUniformSubroutinesuiv", 40, -1 }, + { "glGetUniformSubroutineuiv", 40, -1 }, + { "glGetProgramStageiv", 40, -1 }, + /* GL 4.3 */ { "glIsRenderbuffer", 43, -1 }, { "glBindRenderbuffer", 43, -1 }, @@ -1562,16 +1579,6 @@ const struct function gl_core_functions_possible[] = { { "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 }, diff --git a/src/mesa/main/tests/enum_strings.cpp b/src/mesa/main/tests/enum_strings.cpp index dc5fe751a86..8218cc9a685 100644 --- a/src/mesa/main/tests/enum_strings.cpp +++ b/src/mesa/main/tests/enum_strings.cpp @@ -39,13 +39,13 @@ TEST(EnumStrings, LookUpByNumber) { for (unsigned i = 0; everything[i].name != NULL; i++) { EXPECT_STREQ(everything[i].name, - _mesa_lookup_enum_by_nr(everything[i].value)); + _mesa_enum_to_string(everything[i].value)); } } TEST(EnumStrings, LookUpUnknownNumber) { - EXPECT_STRCASEEQ("0xEEEE", _mesa_lookup_enum_by_nr(0xEEEE)); + EXPECT_STRCASEEQ("0xEEEE", _mesa_enum_to_string(0xEEEE)); } /* Please type the name and the value. This makes it easier to detect @@ -1731,6 +1731,10 @@ const struct enum_info everything[] = { { 0x8DDF, "GL_MAX_GEOMETRY_UNIFORM_COMPONENTS" }, { 0x8DE0, "GL_MAX_GEOMETRY_OUTPUT_VERTICES" }, { 0x8DE1, "GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS" }, + { 0x8DE5, "GL_ACTIVE_SUBROUTINES" }, + { 0x8DE6, "GL_ACTIVE_SUBROUTINE_UNIFORMS" }, + { 0x8DE7, "GL_MAX_SUBROUTINES" }, + { 0x8DE8, "GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS" }, { 0x8DF0, "GL_LOW_FLOAT" }, { 0x8DF1, "GL_MEDIUM_FLOAT" }, { 0x8DF2, "GL_HIGH_FLOAT" }, @@ -1759,6 +1763,11 @@ const struct enum_info everything[] = { { 0x8E44, "GL_TEXTURE_SWIZZLE_B" }, { 0x8E45, "GL_TEXTURE_SWIZZLE_A" }, { 0x8E46, "GL_TEXTURE_SWIZZLE_RGBA" }, + { 0x8E47, "GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS" }, + { 0x8E48, "GL_ACTIVE_SUBROUTINE_MAX_LENGTH" }, + { 0x8E49, "GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH" }, + { 0x8E4A, "GL_NUM_COMPATIBLE_SUBROUTINES" }, + { 0x8E4B, "GL_COMPATIBLE_SUBROUTINES" }, { 0x8E4C, "GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION" }, { 0x8E4D, "GL_FIRST_VERTEX_CONVENTION" }, { 0x8E4E, "GL_LAST_VERTEX_CONVENTION" }, diff --git a/src/mesa/main/texenv.c b/src/mesa/main/texenv.c index 3edafc0f776..091922161c5 100644 --- a/src/mesa/main/texenv.c +++ b/src/mesa/main/texenv.c @@ -42,7 +42,7 @@ #define TE_ERROR(errCode, msg, value) \ - _mesa_error(ctx, errCode, msg, _mesa_lookup_enum_by_nr(value)); + _mesa_error(ctx, errCode, msg, _mesa_enum_to_string(value)); /** Set texture env mode */ @@ -482,16 +482,16 @@ _mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param ) } else { _mesa_error(ctx, GL_INVALID_ENUM, "glTexEnv(target=%s)", - _mesa_lookup_enum_by_nr(target)); + _mesa_enum_to_string(target)); return; } if (MESA_VERBOSE&(VERBOSE_API|VERBOSE_TEXTURE)) _mesa_debug(ctx, "glTexEnv %s %s %.1f(%s) ...\n", - _mesa_lookup_enum_by_nr(target), - _mesa_lookup_enum_by_nr(pname), + _mesa_enum_to_string(target), + _mesa_enum_to_string(pname), *param, - _mesa_lookup_enum_by_nr((GLenum) iparam0)); + _mesa_enum_to_string((GLenum) iparam0)); /* Tell device driver about the new texture environment */ if (ctx->Driver.TexEnv) { diff --git a/src/mesa/main/texformat.c b/src/mesa/main/texformat.c index 3c4baca7026..f4d17e1bdb5 100644 --- a/src/mesa/main/texformat.c +++ b/src/mesa/main/texformat.c @@ -847,7 +847,7 @@ _mesa_choose_tex_format(struct gl_context *ctx, GLenum target, } _mesa_problem(ctx, "unexpected format %s in _mesa_choose_tex_format()", - _mesa_lookup_enum_by_nr(internalFormat)); + _mesa_enum_to_string(internalFormat)); return MESA_FORMAT_NONE; } diff --git a/src/mesa/main/texgen.c b/src/mesa/main/texgen.c index 41e428b69e7..24ba295746a 100644 --- a/src/mesa/main/texgen.c +++ b/src/mesa/main/texgen.c @@ -76,10 +76,10 @@ _mesa_TexGenfv( GLenum coord, GLenum pname, const GLfloat *params ) if (MESA_VERBOSE&(VERBOSE_API|VERBOSE_TEXTURE)) _mesa_debug(ctx, "glTexGen %s %s %.1f(%s)...\n", - _mesa_lookup_enum_by_nr(coord), - _mesa_lookup_enum_by_nr(pname), + _mesa_enum_to_string(coord), + _mesa_enum_to_string(pname), *params, - _mesa_lookup_enum_by_nr((GLenum) (GLint) *params)); + _mesa_enum_to_string((GLenum) (GLint) *params)); if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) { _mesa_error(ctx, GL_INVALID_OPERATION, "glTexGen(current unit)"); diff --git a/src/mesa/main/texgetimage.c b/src/mesa/main/texgetimage.c index 92b4d6795c6..c0ccce3d50e 100644 --- a/src/mesa/main/texgetimage.c +++ b/src/mesa/main/texgetimage.c @@ -75,12 +75,11 @@ type_needs_clamping(GLenum type) */ static void get_tex_depth(struct gl_context *ctx, GLuint dimensions, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLint depth, GLenum format, GLenum type, GLvoid *pixels, struct gl_texture_image *texImage) { - const GLint width = texImage->Width; - GLint height = texImage->Height; - GLint depth = texImage->Depth; GLint img, row; GLfloat *depthRow = malloc(width * sizeof(GLfloat)); @@ -94,14 +93,15 @@ get_tex_depth(struct gl_context *ctx, GLuint dimensions, height = 1; } + assert(zoffset + depth <= texImage->Depth); for (img = 0; img < depth; img++) { GLubyte *srcMap; GLint srcRowStride; /* map src texture buffer */ - ctx->Driver.MapTextureImage(ctx, texImage, img, - 0, 0, width, height, GL_MAP_READ_BIT, - &srcMap, &srcRowStride); + ctx->Driver.MapTextureImage(ctx, texImage, zoffset + img, + xoffset, yoffset, width, height, + GL_MAP_READ_BIT, &srcMap, &srcRowStride); if (srcMap) { for (row = 0; row < height; row++) { @@ -113,7 +113,7 @@ get_tex_depth(struct gl_context *ctx, GLuint dimensions, _mesa_pack_depth_span(ctx, width, dest, type, depthRow, &ctx->Pack); } - ctx->Driver.UnmapTextureImage(ctx, texImage, img); + ctx->Driver.UnmapTextureImage(ctx, texImage, zoffset + img); } else { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage"); @@ -130,26 +130,26 @@ get_tex_depth(struct gl_context *ctx, GLuint dimensions, */ static void get_tex_depth_stencil(struct gl_context *ctx, GLuint dimensions, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLint depth, GLenum format, GLenum type, GLvoid *pixels, struct gl_texture_image *texImage) { - const GLint width = texImage->Width; - const GLint height = texImage->Height; - const GLint depth = texImage->Depth; GLint img, row; assert(format == GL_DEPTH_STENCIL); assert(type == GL_UNSIGNED_INT_24_8 || type == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); + assert(zoffset + depth <= texImage->Depth); for (img = 0; img < depth; img++) { GLubyte *srcMap; GLint rowstride; /* map src texture buffer */ - ctx->Driver.MapTextureImage(ctx, texImage, img, - 0, 0, width, height, GL_MAP_READ_BIT, - &srcMap, &rowstride); + ctx->Driver.MapTextureImage(ctx, texImage, zoffset + img, + xoffset, yoffset, width, height, + GL_MAP_READ_BIT, &srcMap, &rowstride); if (srcMap) { for (row = 0; row < height; row++) { @@ -166,7 +166,7 @@ get_tex_depth_stencil(struct gl_context *ctx, GLuint dimensions, } } - ctx->Driver.UnmapTextureImage(ctx, texImage, img); + ctx->Driver.UnmapTextureImage(ctx, texImage, zoffset + img); } else { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage"); @@ -180,12 +180,11 @@ get_tex_depth_stencil(struct gl_context *ctx, GLuint dimensions, */ static void get_tex_stencil(struct gl_context *ctx, GLuint dimensions, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLint depth, GLenum format, GLenum type, GLvoid *pixels, struct gl_texture_image *texImage) { - const GLint width = texImage->Width; - const GLint height = texImage->Height; - const GLint depth = texImage->Depth; GLint img, row; assert(format == GL_STENCIL_INDEX); @@ -195,8 +194,9 @@ get_tex_stencil(struct gl_context *ctx, GLuint dimensions, GLint rowstride; /* map src texture buffer */ - ctx->Driver.MapTextureImage(ctx, texImage, img, - 0, 0, width, height, GL_MAP_READ_BIT, + ctx->Driver.MapTextureImage(ctx, texImage, zoffset + img, + xoffset, yoffset, width, height, + GL_MAP_READ_BIT, &srcMap, &rowstride); if (srcMap) { @@ -211,7 +211,7 @@ get_tex_stencil(struct gl_context *ctx, GLuint dimensions, dest); } - ctx->Driver.UnmapTextureImage(ctx, texImage, img); + ctx->Driver.UnmapTextureImage(ctx, texImage, zoffset + img); } else { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage"); @@ -226,22 +226,22 @@ get_tex_stencil(struct gl_context *ctx, GLuint dimensions, */ static void get_tex_ycbcr(struct gl_context *ctx, GLuint dimensions, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLint depth, GLenum format, GLenum type, GLvoid *pixels, struct gl_texture_image *texImage) { - const GLint width = texImage->Width; - const GLint height = texImage->Height; - const GLint depth = texImage->Depth; GLint img, row; + assert(zoffset + depth <= texImage->Depth); for (img = 0; img < depth; img++) { GLubyte *srcMap; GLint rowstride; /* map src texture buffer */ - ctx->Driver.MapTextureImage(ctx, texImage, img, - 0, 0, width, height, GL_MAP_READ_BIT, - &srcMap, &rowstride); + ctx->Driver.MapTextureImage(ctx, texImage, zoffset + img, + xoffset, yoffset, width, height, + GL_MAP_READ_BIT, &srcMap, &rowstride); if (srcMap) { for (row = 0; row < height; row++) { @@ -264,7 +264,7 @@ get_tex_ycbcr(struct gl_context *ctx, GLuint dimensions, } } - ctx->Driver.UnmapTextureImage(ctx, texImage, img); + ctx->Driver.UnmapTextureImage(ctx, texImage, zoffset + img); } else { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage"); @@ -279,6 +279,8 @@ get_tex_ycbcr(struct gl_context *ctx, GLuint dimensions, */ static void get_tex_rgba_compressed(struct gl_context *ctx, GLuint dimensions, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLint depth, GLenum format, GLenum type, GLvoid *pixels, struct gl_texture_image *texImage, GLbitfield transferOps) @@ -287,9 +289,6 @@ get_tex_rgba_compressed(struct gl_context *ctx, GLuint dimensions, const mesa_format texFormat = _mesa_get_srgb_format_linear(texImage->TexFormat); const GLenum baseFormat = _mesa_get_format_base_format(texFormat); - const GLuint width = texImage->Width; - const GLuint height = texImage->Height; - const GLuint depth = texImage->Depth; GLfloat *tempImage, *tempSlice; GLuint slice; int srcStride, dstStride; @@ -312,15 +311,15 @@ get_tex_rgba_compressed(struct gl_context *ctx, GLuint dimensions, tempSlice = tempImage + slice * 4 * width * height; - ctx->Driver.MapTextureImage(ctx, texImage, slice, - 0, 0, width, height, + ctx->Driver.MapTextureImage(ctx, texImage, zoffset + slice, + xoffset, yoffset, width, height, GL_MAP_READ_BIT, &srcMap, &srcRowStride); if (srcMap) { _mesa_decompress_image(texFormat, width, height, srcMap, srcRowStride, tempSlice); - ctx->Driver.UnmapTextureImage(ctx, texImage, slice); + ctx->Driver.UnmapTextureImage(ctx, texImage, zoffset + slice); } else { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage"); @@ -409,6 +408,8 @@ _mesa_base_pack_format(GLenum format) */ static void get_tex_rgba_uncompressed(struct gl_context *ctx, GLuint dimensions, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLint depth, GLenum format, GLenum type, GLvoid *pixels, struct gl_texture_image *texImage, GLbitfield transferOps) @@ -416,9 +417,6 @@ get_tex_rgba_uncompressed(struct gl_context *ctx, GLuint dimensions, /* don't want to apply sRGB -> RGB conversion here so override the format */ const mesa_format texFormat = _mesa_get_srgb_format_linear(texImage->TexFormat); - const GLuint width = texImage->Width; - GLuint height = texImage->Height; - GLuint depth = texImage->Depth; GLuint img; GLboolean dst_is_integer; uint32_t dst_format; @@ -430,6 +428,8 @@ get_tex_rgba_uncompressed(struct gl_context *ctx, GLuint dimensions, if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) { depth = height; height = 1; + zoffset = yoffset; + yoffset = 0; } /* Depending on the base format involved we may need to apply a rebase @@ -449,7 +449,8 @@ get_tex_rgba_uncompressed(struct gl_context *ctx, GLuint dimensions, rebaseSwizzle[1] = MESA_FORMAT_SWIZZLE_ZERO; rebaseSwizzle[2] = MESA_FORMAT_SWIZZLE_ZERO; rebaseSwizzle[3] = MESA_FORMAT_SWIZZLE_W; - } else if (texImage->_BaseFormat != _mesa_get_format_base_format(texFormat)) { + } else if (texImage->_BaseFormat != + _mesa_get_format_base_format(texFormat)) { needsRebase = _mesa_compute_rgba2base2rgba_component_mapping(texImage->_BaseFormat, rebaseSwizzle); @@ -480,8 +481,9 @@ get_tex_rgba_uncompressed(struct gl_context *ctx, GLuint dimensions, uint32_t src_format; /* map src texture buffer */ - ctx->Driver.MapTextureImage(ctx, texImage, img, - 0, 0, width, height, GL_MAP_READ_BIT, + ctx->Driver.MapTextureImage(ctx, texImage, zoffset + img, + xoffset, yoffset, width, height, + GL_MAP_READ_BIT, &srcMap, &rowstride); if (!srcMap) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage"); @@ -530,8 +532,8 @@ get_tex_rgba_uncompressed(struct gl_context *ctx, GLuint dimensions, /* If we had to rebase, we have already handled that */ needsRebase = false; - /* If we were lucky and our RGBA conversion matches the dst format, then - * we are done. + /* If we were lucky and our RGBA conversion matches the dst format, + * then we are done. */ if (!need_convert) goto do_swap; @@ -568,7 +570,7 @@ get_tex_rgba_uncompressed(struct gl_context *ctx, GLuint dimensions, } /* Unmap the src texture buffer */ - ctx->Driver.UnmapTextureImage(ctx, texImage, img); + ctx->Driver.UnmapTextureImage(ctx, texImage, zoffset + img); } done: @@ -583,6 +585,8 @@ done: */ static void get_tex_rgba(struct gl_context *ctx, GLuint dimensions, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLint depth, GLenum format, GLenum type, GLvoid *pixels, struct gl_texture_image *texImage) { @@ -604,11 +608,17 @@ get_tex_rgba(struct gl_context *ctx, GLuint dimensions, } if (_mesa_is_format_compressed(texImage->TexFormat)) { - get_tex_rgba_compressed(ctx, dimensions, format, type, + get_tex_rgba_compressed(ctx, dimensions, + xoffset, yoffset, zoffset, + width, height, depth, + format, type, pixels, texImage, transferOps); } else { - get_tex_rgba_uncompressed(ctx, dimensions, format, type, + get_tex_rgba_uncompressed(ctx, dimensions, + xoffset, yoffset, zoffset, + width, height, depth, + format, type, pixels, texImage, transferOps); } } @@ -619,8 +629,10 @@ get_tex_rgba(struct gl_context *ctx, GLuint dimensions, * \return GL_TRUE if done, GL_FALSE otherwise */ static GLboolean -get_tex_memcpy(struct gl_context *ctx, GLenum format, GLenum type, - GLvoid *pixels, +get_tex_memcpy(struct gl_context *ctx, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLint depth, + GLenum format, GLenum type, GLvoid *pixels, struct gl_texture_image *texImage) { const GLenum target = texImage->TexObject->Target; @@ -642,20 +654,25 @@ get_tex_memcpy(struct gl_context *ctx, GLenum format, GLenum type, ctx->Pack.SwapBytes); } + if (depth > 1) { + /* only a single slice is supported at this time */ + memCopy = FALSE; + } + if (memCopy) { const GLuint bpp = _mesa_get_format_bytes(texImage->TexFormat); - const GLint bytesPerRow = texImage->Width * bpp; + const GLint bytesPerRow = width * bpp; GLubyte *dst = - _mesa_image_address2d(&ctx->Pack, pixels, texImage->Width, - texImage->Height, format, type, 0, 0); + _mesa_image_address2d(&ctx->Pack, pixels, width, height, + format, type, 0, 0); const GLint dstRowStride = - _mesa_image_row_stride(&ctx->Pack, texImage->Width, format, type); + _mesa_image_row_stride(&ctx->Pack, width, format, type); GLubyte *src; GLint srcRowStride; /* map src texture buffer */ - ctx->Driver.MapTextureImage(ctx, texImage, 0, - 0, 0, texImage->Width, texImage->Height, + ctx->Driver.MapTextureImage(ctx, texImage, zoffset, + xoffset, yoffset, width, height, GL_MAP_READ_BIT, &src, &srcRowStride); if (src) { @@ -664,7 +681,7 @@ get_tex_memcpy(struct gl_context *ctx, GLenum format, GLenum type, } else { GLuint row; - for (row = 0; row < texImage->Height; row++) { + for (row = 0; row < height; row++) { memcpy(dst, src, bytesPerRow); dst += dstRowStride; src += srcRowStride; @@ -672,7 +689,7 @@ get_tex_memcpy(struct gl_context *ctx, GLenum format, GLenum type, } /* unmap src texture buffer */ - ctx->Driver.UnmapTextureImage(ctx, texImage, 0); + ctx->Driver.UnmapTextureImage(ctx, texImage, zoffset); } else { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage"); @@ -684,15 +701,17 @@ get_tex_memcpy(struct gl_context *ctx, GLenum format, GLenum type, /** - * This is the software fallback for Driver.GetTexImage(). + * This is the software fallback for Driver.GetTexSubImage(). * All error checking will have been done before this routine is called. * We'll call ctx->Driver.MapTextureImage() to access the data, then * unmap with ctx->Driver.UnmapTextureImage(). */ void -_mesa_GetTexImage_sw(struct gl_context *ctx, - GLenum format, GLenum type, GLvoid *pixels, - struct gl_texture_image *texImage) +_mesa_GetTexSubImage_sw(struct gl_context *ctx, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLint depth, + GLenum format, GLenum type, GLvoid *pixels, + struct gl_texture_image *texImage) { const GLuint dimensions = _mesa_get_texture_dimensions(texImage->TexObject->Target); @@ -720,23 +739,30 @@ _mesa_GetTexImage_sw(struct gl_context *ctx, pixels = ADD_POINTERS(buf, pixels); } - if (get_tex_memcpy(ctx, format, type, pixels, texImage)) { + if (get_tex_memcpy(ctx, xoffset, yoffset, zoffset, width, height, depth, + format, type, pixels, texImage)) { /* all done */ } else if (format == GL_DEPTH_COMPONENT) { - get_tex_depth(ctx, dimensions, format, type, pixels, texImage); + get_tex_depth(ctx, dimensions, xoffset, yoffset, zoffset, + width, height, depth, format, type, pixels, texImage); } else if (format == GL_DEPTH_STENCIL_EXT) { - get_tex_depth_stencil(ctx, dimensions, format, type, pixels, texImage); + get_tex_depth_stencil(ctx, dimensions, xoffset, yoffset, zoffset, + width, height, depth, format, type, pixels, + texImage); } else if (format == GL_STENCIL_INDEX) { - get_tex_stencil(ctx, dimensions, format, type, pixels, texImage); + get_tex_stencil(ctx, dimensions, xoffset, yoffset, zoffset, + width, height, depth, format, type, pixels, texImage); } else if (format == GL_YCBCR_MESA) { - get_tex_ycbcr(ctx, dimensions, format, type, pixels, texImage); + get_tex_ycbcr(ctx, dimensions, xoffset, yoffset, zoffset, + width, height, depth, format, type, pixels, texImage); } else { - get_tex_rgba(ctx, dimensions, format, type, pixels, texImage); + get_tex_rgba(ctx, dimensions, xoffset, yoffset, zoffset, + width, height, depth, format, type, pixels, texImage); } if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { @@ -747,13 +773,16 @@ _mesa_GetTexImage_sw(struct gl_context *ctx, /** - * This is the software fallback for Driver.GetCompressedTexImage(). + * This is the software fallback for Driver.GetCompressedTexSubImage(). * All error checking will have been done before this routine is called. */ void -_mesa_GetCompressedTexImage_sw(struct gl_context *ctx, - struct gl_texture_image *texImage, - GLvoid *img) +_mesa_GetCompressedTexSubImage_sw(struct gl_context *ctx, + struct gl_texture_image *texImage, + GLint xoffset, GLint yoffset, + GLint zoffset, GLsizei width, + GLint height, GLint depth, + GLvoid *img) { const GLuint dimensions = _mesa_get_texture_dimensions(texImage->TexObject->Target); @@ -762,10 +791,8 @@ _mesa_GetCompressedTexImage_sw(struct gl_context *ctx, GLubyte *dest; _mesa_compute_compressed_pixelstore(dimensions, texImage->TexFormat, - texImage->Width, texImage->Height, - texImage->Depth, - &ctx->Pack, - &store); + width, height, depth, + &ctx->Pack, &store); if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { /* pack texture image into a PBO */ @@ -791,8 +818,8 @@ _mesa_GetCompressedTexImage_sw(struct gl_context *ctx, GLubyte *src; /* map src texture buffer */ - ctx->Driver.MapTextureImage(ctx, texImage, slice, - 0, 0, texImage->Width, texImage->Height, + ctx->Driver.MapTextureImage(ctx, texImage, zoffset + slice, + xoffset, yoffset, width, height, GL_MAP_READ_BIT, &src, &srcRowStride); if (src) { @@ -803,10 +830,11 @@ _mesa_GetCompressedTexImage_sw(struct gl_context *ctx, src += srcRowStride; } - ctx->Driver.UnmapTextureImage(ctx, texImage, slice); + ctx->Driver.UnmapTextureImage(ctx, texImage, zoffset + slice); /* Advance to next slice */ - dest += store.TotalBytesPerRow * (store.TotalRowsPerSlice - store.CopyRowsPerSlice); + dest += store.TotalBytesPerRow * (store.TotalRowsPerSlice - + store.CopyRowsPerSlice); } else { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetCompresssedTexImage"); @@ -863,29 +891,299 @@ legal_getteximage_target(struct gl_context *ctx, GLenum target, bool dsa) /** - * Do error checking for a glGetTex(ture)Image() call. - * \return GL_TRUE if any error, GL_FALSE if no errors. + * Wrapper for _mesa_select_tex_image() which can handle target being + * GL_TEXTURE_CUBE_MAP_ARB in which case we use zoffset to select a cube face. + * This can happen for glGetTextureImage and glGetTextureSubImage (DSA + * functions). */ -static GLboolean +static struct gl_texture_image * +select_tex_image(const struct gl_texture_object *texObj, GLenum target, + GLint level, GLint zoffset) +{ + assert(level >= 0); + assert(level < MAX_TEXTURE_LEVELS); + if (target == GL_TEXTURE_CUBE_MAP) { + assert(zoffset >= 0); + assert(zoffset < 6); + target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + zoffset; + } + return _mesa_select_tex_image(texObj, target, level); +} + + +/** + * Error-check the offset and size arguments to + * glGet[Compressed]TextureSubImage(). Also checks if the specified + * texture image is missing. + * \return true if error, false if no error. + */ +static bool +dimensions_error_check(struct gl_context *ctx, + struct gl_texture_object *texObj, + GLenum target, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, + const char *caller) +{ + const struct gl_texture_image *texImage; + int i; + + if (xoffset < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "%s(xoffset = %d)", caller, xoffset); + return true; + } + + if (yoffset < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "%s(yoffset = %d)", caller, yoffset); + return true; + } + + if (zoffset < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "%s(zoffset = %d)", caller, zoffset); + return true; + } + + if (width < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "%s(width = %d)", caller, width); + return true; + } + + if (height < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "%s(height = %d)", caller, height); + return true; + } + + if (depth < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "%s(depth = %d)", caller, depth); + return true; + } + + /* do special per-target checks */ + switch (target) { + case GL_TEXTURE_1D: + if (yoffset != 0) { + _mesa_error(ctx, GL_INVALID_VALUE, + "%s(1D, yoffset = %d)", caller, yoffset); + return true; + } + if (height > 1) { + _mesa_error(ctx, GL_INVALID_VALUE, + "%s(1D, height = %d)", caller, height); + return true; + } + /* fall-through */ + case GL_TEXTURE_1D_ARRAY: + case GL_TEXTURE_2D: + case GL_TEXTURE_RECTANGLE: + if (zoffset != 0) { + _mesa_error(ctx, GL_INVALID_VALUE, + "%s(zoffset = %d)", caller, zoffset); + return true; + } + if (depth > 1) { + _mesa_error(ctx, GL_INVALID_VALUE, + "%s(depth = %d)", caller, depth); + return true; + } + break; + case GL_TEXTURE_CUBE_MAP: + /* Non-array cube maps are special because we have a gl_texture_image + * per face. + */ + if (zoffset + depth > 6) { + _mesa_error(ctx, GL_INVALID_VALUE, + "%s(zoffset + depth = %d)", caller, zoffset + depth); + return true; + } + /* check that the range of faces exist */ + for (i = 0; i < depth; i++) { + GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + zoffset + i; + if (!_mesa_select_tex_image(texObj, face, level)) { + /* non-existant face */ + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(missing cube face)", caller); + return true; + } + } + break; + default: + ; /* nothing */ + } + + texImage = select_tex_image(texObj, target, level, zoffset); + if (!texImage) { + /* missing texture image */ + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(missing image)", caller); + return true; + } + + if (xoffset + width > texImage->Width) { + _mesa_error(ctx, GL_INVALID_VALUE, + "%s(xoffset %d + width %d > %u)", + caller, xoffset, width, texImage->Width); + return true; + } + + if (yoffset + height > texImage->Height) { + _mesa_error(ctx, GL_INVALID_VALUE, + "%s(yoffset %d + height %d > %u)", + caller, yoffset, height, texImage->Height); + return true; + } + + if (target != GL_TEXTURE_CUBE_MAP) { + /* Cube map error checking was done above */ + if (zoffset + depth > texImage->Depth) { + _mesa_error(ctx, GL_INVALID_VALUE, + "%s(zoffset %d + depth %d > %u)", + caller, zoffset, depth, texImage->Depth); + return true; + } + } + + /* Extra checks for compressed textures */ + { + GLuint bw, bh; + _mesa_get_format_block_size(texImage->TexFormat, &bw, &bh); + if (bw > 1 || bh > 1) { + /* offset must be multiple of block size */ + if (xoffset % bw != 0) { + _mesa_error(ctx, GL_INVALID_VALUE, + "%s(xoffset = %d)", caller, xoffset); + return true; + } + if (target != GL_TEXTURE_1D && target != GL_TEXTURE_1D_ARRAY) { + if (yoffset % bh != 0) { + _mesa_error(ctx, GL_INVALID_VALUE, + "%s(yoffset = %d)", caller, yoffset); + return true; + } + } + + /* The size must be a multiple of bw x bh, or we must be using a + * offset+size that exactly hits the edge of the image. + */ + if ((width % bw != 0) && + (xoffset + width != (GLint) texImage->Width)) { + _mesa_error(ctx, GL_INVALID_VALUE, + "%s(width = %d)", caller, width); + return true; + } + + if ((height % bh != 0) && + (yoffset + height != (GLint) texImage->Height)) { + _mesa_error(ctx, GL_INVALID_VALUE, + "%s(height = %d)", caller, height); + return true; + } + } + } + + if (width == 0 || height == 0 || depth == 0) { + /* Not an error, but nothing to do. Return 'true' so that the + * caller simply returns. + */ + return true; + } + + return false; +} + + +/** + * Do PBO-related error checking for getting uncompressed images. + * \return true if there was an error (or the GetTexImage is to be a no-op) + */ +static bool +pbo_error_check(struct gl_context *ctx, GLenum target, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, GLsizei clientMemSize, + GLvoid *pixels, + const char *caller) +{ + const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2; + + if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, width, height, depth, + format, type, clientMemSize, pixels)) { + if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(out of bounds PBO access)", caller); + } else { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(out of bounds access: bufSize (%d) is too small)", + caller, clientMemSize); + } + return true; + } + + if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { + /* PBO should not be mapped */ + if (_mesa_check_disallowed_mapping(ctx->Pack.BufferObj)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(PBO is mapped)", caller); + return true; + } + } + + if (!_mesa_is_bufferobj(ctx->Pack.BufferObj) && !pixels) { + /* not an error, do nothing */ + return true; + } + + return false; +} + + +/** + * Do error checking for all (non-compressed) get-texture-image functions. + * \return true if any error, false if no errors. + */ +static bool getteximage_error_check(struct gl_context *ctx, - struct gl_texture_image *texImage, + struct gl_texture_object *texObj, GLenum target, GLint level, - GLenum format, GLenum type, GLsizei clientMemSize, - GLvoid *pixels, bool dsa) + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, GLsizei bufSize, + GLvoid *pixels, const char *caller) { - const GLint maxLevels = _mesa_max_texture_levels(ctx, target); - const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2; - GLenum baseFormat; - const char *suffix = dsa ? "ture" : ""; + struct gl_texture_image *texImage; + GLenum baseFormat, err; + GLint maxLevels; - assert(texImage); - assert(maxLevels != 0); + assert(texObj); + + if (texObj->Target == 0) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid texture)", caller); + return true; + } + + maxLevels = _mesa_max_texture_levels(ctx, target); if (level < 0 || level >= maxLevels) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glGetTex%sImage(level out of range)", suffix); - return GL_TRUE; + _mesa_error(ctx, GL_INVALID_VALUE, "%s(level = %d)", caller, level); + return true; } + err = _mesa_error_check_format_and_type(ctx, format, type); + if (err != GL_NO_ERROR) { + _mesa_error(ctx, err, "%s(format/type)", caller); + return true; + } + + if (dimensions_error_check(ctx, texObj, target, level, + xoffset, yoffset, zoffset, + width, height, depth, caller)) { + return true; + } + + if (pbo_error_check(ctx, target, width, height, depth, + format, type, bufSize, pixels, caller)) { + return true; + } + + texImage = select_tex_image(texObj, target, level, zoffset); + assert(texImage); + /* * Format and type checking has been moved up to GetnTexImage and * GetTextureImage so that it happens before getting the texImage object. @@ -899,494 +1197,579 @@ getteximage_error_check(struct gl_context *ctx, if (_mesa_is_color_format(format) && !_mesa_is_color_format(baseFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glGetTex%sImage(format mismatch)", suffix); - return GL_TRUE; + "%s(format mismatch)", caller); + return true; } else if (_mesa_is_depth_format(format) && !_mesa_is_depth_format(baseFormat) && !_mesa_is_depthstencil_format(baseFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glGetTex%sImage(format mismatch)", suffix); - return GL_TRUE; + "%s(format mismatch)", caller); + return true; } else if (_mesa_is_stencil_format(format) && !ctx->Extensions.ARB_texture_stencil8) { _mesa_error(ctx, GL_INVALID_ENUM, - "glGetTex%sImage(format=GL_STENCIL_INDEX)", suffix); - return GL_TRUE; + "%s(format=GL_STENCIL_INDEX)", caller); + return true; } else if (_mesa_is_ycbcr_format(format) && !_mesa_is_ycbcr_format(baseFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glGetTex%sImage(format mismatch)", suffix); - return GL_TRUE; + "%s(format mismatch)", caller); + return true; } else if (_mesa_is_depthstencil_format(format) && !_mesa_is_depthstencil_format(baseFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glGetTex%sImage(format mismatch)", suffix); - return GL_TRUE; + "%s(format mismatch)", caller); + return true; } - else if (!_mesa_is_stencil_format(format) && _mesa_is_enum_format_integer(format) != + else if (!_mesa_is_stencil_format(format) && + _mesa_is_enum_format_integer(format) != _mesa_is_format_integer(texImage->TexFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glGetTex%sImage(format mismatch)", suffix); - return GL_TRUE; + "%s(format mismatch)", caller); + return true; } - if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, texImage->Width, - texImage->Height, texImage->Depth, - format, type, clientMemSize, pixels)) { - if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glGetTex%sImage(out of bounds PBO access)", suffix); - } else { - _mesa_error(ctx, GL_INVALID_OPERATION, - "%s(out of bounds access:" - " bufSize (%d) is too small)", - dsa ? "glGetTextureImage" : "glGetnTexImageARB", - clientMemSize); - } - return GL_TRUE; + return false; +} + + +/** + * Return the width, height and depth of a texture image. + * This function must be resilient to bad parameter values since + * this is called before full error checking. + */ +static void +get_texture_image_dims(const struct gl_texture_object *texObj, + GLenum target, GLint level, + GLsizei *width, GLsizei *height, GLsizei *depth) +{ + const struct gl_texture_image *texImage = NULL; + + if (level >= 0 && level < MAX_TEXTURE_LEVELS) { + texImage = _mesa_select_tex_image(texObj, target, level); } - if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { - /* PBO should not be mapped */ - if (_mesa_check_disallowed_mapping(ctx->Pack.BufferObj)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glGetTex%sImage(PBO is mapped)", suffix); - return GL_TRUE; + if (texImage) { + *width = texImage->Width; + *height = texImage->Height; + if (target == GL_TEXTURE_CUBE_MAP) { + *depth = 6; + } + else { + *depth = texImage->Depth; } } - - return GL_FALSE; + else { + *width = *height = *depth = 0; + } } /** - * This is the implementation for glGetnTexImageARB, glGetTextureImage, - * and glGetTexImage. - * - * Requires caller to pass in texImage object because _mesa_GetTextureImage - * must handle the GL_TEXTURE_CUBE_MAP target. - * - * \param target texture target. + * Common code for all (uncompressed) get-texture-image functions. + * \param texObj the texture object (should not be null) + * \param target user-provided target, or 0 for DSA * \param level image level. * \param format pixel data format for returned image. * \param type pixel data type for returned image. * \param bufSize size of the pixels data buffer. * \param pixels returned pixel data. - * \param dsa True when the caller is an ARB_direct_state_access function, - * false otherwise + * \param caller name of calling function */ -void -_mesa_get_texture_image(struct gl_context *ctx, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage, GLenum target, - GLint level, GLenum format, GLenum type, - GLsizei bufSize, GLvoid *pixels, bool dsa) +static void +get_texture_image(struct gl_context *ctx, + struct gl_texture_object *texObj, + GLenum target, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLint depth, + GLenum format, GLenum type, + GLvoid *pixels, const char *caller) { - assert(texObj); - assert(texImage); + struct gl_texture_image *texImage; + unsigned firstFace, numFaces, i; + GLint imageStride; FLUSH_VERTICES(ctx, 0); - /* - * Legal target checking has been moved up to GetnTexImage and - * GetTextureImage so that it can be caught before receiving a NULL - * texImage object and exiting. - */ - - if (getteximage_error_check(ctx, texImage, target, level, format, - type, bufSize, pixels, dsa)) { - return; - } + texImage = select_tex_image(texObj, target, level, zoffset); + assert(texImage); /* should have been error checked already */ - if (!_mesa_is_bufferobj(ctx->Pack.BufferObj) && !pixels) { - /* not an error, do nothing */ + if (_mesa_is_zero_size_texture(texImage)) { + /* no image data to return */ return; } - if (_mesa_is_zero_size_texture(texImage)) - return; - if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE)) { - _mesa_debug(ctx, "glGetTex%sImage(tex %u) format = %s, w=%d, h=%d," + _mesa_debug(ctx, "%s(tex %u) format = %s, w=%d, h=%d," " dstFmt=0x%x, dstType=0x%x\n", - dsa ? "ture": "", - texObj->Name, + caller, texObj->Name, _mesa_get_format_name(texImage->TexFormat), texImage->Width, texImage->Height, format, type); } + if (target == GL_TEXTURE_CUBE_MAP) { + /* Compute stride between cube faces */ + imageStride = _mesa_image_image_stride(&ctx->Pack, width, height, + format, type); + firstFace = zoffset; + numFaces = depth; + zoffset = 0; + depth = 1; + } + else { + imageStride = 0; + firstFace = _mesa_tex_target_to_face(target); + numFaces = 1; + } + _mesa_lock_texture(ctx, texObj); - { - ctx->Driver.GetTexImage(ctx, format, type, pixels, texImage); + + for (i = 0; i < numFaces; i++) { + texImage = texObj->Image[firstFace + i][level]; + assert(texImage); + + ctx->Driver.GetTexSubImage(ctx, xoffset, yoffset, zoffset, + width, height, depth, + format, type, pixels, texImage); + + /* next cube face */ + pixels = (GLubyte *) pixels + imageStride; } + _mesa_unlock_texture(ctx, texObj); } -/** - * Get texture image. Called by glGetTexImage. - * - * \param target texture target. - * \param level image level. - * \param format pixel data format for returned image. - * \param type pixel data type for returned image. - * \param bufSize size of the pixels data buffer. - * \param pixels returned pixel data. - */ + void GLAPIENTRY -_mesa_GetnTexImageARB(GLenum target, GLint level, GLenum format, - GLenum type, GLsizei bufSize, GLvoid *pixels) +_mesa_GetnTexImageARB(GLenum target, GLint level, GLenum format, GLenum type, + GLsizei bufSize, GLvoid *pixels) { - struct gl_texture_object *texObj; - struct gl_texture_image *texImage; - GLenum err; GET_CURRENT_CONTEXT(ctx); + static const char *caller = "glGetnTexImageARB"; + GLsizei width, height, depth; + struct gl_texture_object *texObj; - /* - * This has been moved here because a format/type mismatch can cause a NULL - * texImage object, which in turn causes the mismatch error to be - * ignored. - */ - err = _mesa_error_check_format_and_type(ctx, format, type); - if (err != GL_NO_ERROR) { - _mesa_error(ctx, err, "glGetnTexImage(format/type)"); - return; - } - - /* - * Legal target checking has been moved here to prevent exiting with a NULL - * texImage object. - */ if (!legal_getteximage_target(ctx, target, false)) { - _mesa_error(ctx, GL_INVALID_ENUM, "glGetnTexImage(target=0x%x)", - target); + _mesa_error(ctx, GL_INVALID_ENUM, "%s", caller); return; } texObj = _mesa_get_current_tex_object(ctx, target); - if (!texObj) - return; + assert(texObj); + + get_texture_image_dims(texObj, target, level, &width, &height, &depth); - texImage = _mesa_select_tex_image(texObj, target, level); - if (!texImage) + if (getteximage_error_check(ctx, texObj, target, level, + 0, 0, 0, width, height, depth, + format, type, bufSize, pixels, caller)) { return; + } - _mesa_get_texture_image(ctx, texObj, texImage, target, level, format, type, - bufSize, pixels, false); + get_texture_image(ctx, texObj, target, level, + 0, 0, 0, width, height, depth, + format, type, pixels, caller); } void GLAPIENTRY -_mesa_GetTexImage( GLenum target, GLint level, GLenum format, - GLenum type, GLvoid *pixels ) +_mesa_GetTexImage(GLenum target, GLint level, GLenum format, GLenum type, + GLvoid *pixels ) { - _mesa_GetnTexImageARB(target, level, format, type, INT_MAX, pixels); + GET_CURRENT_CONTEXT(ctx); + static const char *caller = "glGetTexImage"; + GLsizei width, height, depth; + struct gl_texture_object *texObj; + + if (!legal_getteximage_target(ctx, target, false)) { + _mesa_error(ctx, GL_INVALID_ENUM, "%s", caller); + return; + } + + texObj = _mesa_get_current_tex_object(ctx, target); + assert(texObj); + + get_texture_image_dims(texObj, target, level, &width, &height, &depth); + + if (getteximage_error_check(ctx, texObj, target, level, + 0, 0, 0, width, height, depth, + format, type, INT_MAX, pixels, caller)) { + return; + } + + get_texture_image(ctx, texObj, target, level, + 0, 0, 0, width, height, depth, + format, type, pixels, caller); } -/** - * Get texture image. - * - * \param texture texture name. - * \param level image level. - * \param format pixel data format for returned image. - * \param type pixel data type for returned image. - * \param bufSize size of the pixels data buffer. - * \param pixels returned pixel data. - */ + void GLAPIENTRY -_mesa_GetTextureImage(GLuint texture, GLint level, GLenum format, - GLenum type, GLsizei bufSize, GLvoid *pixels) +_mesa_GetTextureImage(GLuint texture, GLint level, GLenum format, GLenum type, + GLsizei bufSize, GLvoid *pixels) { - struct gl_texture_object *texObj; - struct gl_texture_image *texImage; - int i; - GLint image_stride; - GLenum err; GET_CURRENT_CONTEXT(ctx); + GLsizei width, height, depth; + static const char *caller = "glGetTextureImage"; + struct gl_texture_object *texObj = + _mesa_lookup_texture_err(ctx, texture, caller); - /* - * This has been moved here because a format/type mismatch can cause a NULL - * texImage object, which in turn causes the mismatch error to be - * ignored. - */ - err = _mesa_error_check_format_and_type(ctx, format, type); - if (err != GL_NO_ERROR) { - _mesa_error(ctx, err, "glGetTextureImage(format/type)"); + if (!texObj) { return; } - texObj = _mesa_lookup_texture_err(ctx, texture, "glGetTextureImage"); - if (!texObj) - return; + get_texture_image_dims(texObj, texObj->Target, level, + &width, &height, &depth); - /* - * Legal target checking has been moved here to prevent exiting with a NULL - * texImage object. - */ - if (!legal_getteximage_target(ctx, texObj->Target, true)) { - _mesa_error(ctx, GL_INVALID_ENUM, "glGetTextureImage(target=%s)", - _mesa_lookup_enum_by_nr(texObj->Target)); + if (getteximage_error_check(ctx, texObj, texObj->Target, level, + 0, 0, 0, width, height, depth, + format, type, bufSize, pixels, caller)) { return; } - /* Must handle special case GL_TEXTURE_CUBE_MAP. */ - if (texObj->Target == GL_TEXTURE_CUBE_MAP) { - - /* Make sure the texture object is a proper cube. - * (See texturesubimage in teximage.c for details on why this check is - * performed.) - */ - if (!_mesa_cube_level_complete(texObj, level)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glGetTextureImage(cube map incomplete)"); - return; - } + get_texture_image(ctx, texObj, texObj->Target, level, + 0, 0, 0, width, height, depth, + format, type, pixels, caller); +} - /* Copy each face. */ - for (i = 0; i < 6; ++i) { - texImage = texObj->Image[i][level]; - assert(texImage); - _mesa_get_texture_image(ctx, texObj, texImage, texObj->Target, level, - format, type, bufSize, pixels, true); +void GLAPIENTRY +_mesa_GetTextureSubImage(GLuint texture, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, GLsizei bufSize, + void *pixels) +{ + GET_CURRENT_CONTEXT(ctx); + static const char *caller = "glGetTextureSubImage"; + struct gl_texture_object *texObj = + _mesa_lookup_texture_err(ctx, texture, caller); - image_stride = _mesa_image_image_stride(&ctx->Pack, texImage->Width, - texImage->Height, format, - type); - pixels = (GLubyte *) pixels + image_stride; - bufSize -= image_stride; - } + if (!texObj) { + return; } - else { - texImage = _mesa_select_tex_image(texObj, texObj->Target, level); - if (!texImage) - return; - _mesa_get_texture_image(ctx, texObj, texImage, texObj->Target, level, - format, type, bufSize, pixels, true); + if (getteximage_error_check(ctx, texObj, texObj->Target, level, + xoffset, yoffset, zoffset, width, height, depth, + format, type, bufSize, pixels, caller)) { + return; } + + get_texture_image(ctx, texObj, texObj->Target, level, + xoffset, yoffset, zoffset, width, height, depth, + format, type, pixels, caller); } + + /** - * Do error checking for a glGetCompressedTexImage() call. - * \return GL_TRUE if any error, GL_FALSE if no errors. + * Compute the number of bytes which will be written when retrieving + * a sub-region of a compressed texture. */ -static GLboolean +static GLsizei +packed_compressed_size(GLuint dimensions, mesa_format format, + GLsizei width, GLsizei height, GLsizei depth, + const struct gl_pixelstore_attrib *packing) +{ + struct compressed_pixelstore st; + GLsizei totalBytes; + + _mesa_compute_compressed_pixelstore(dimensions, format, + width, height, depth, + packing, &st); + totalBytes = + (st.CopySlices - 1) * st.TotalRowsPerSlice * st.TotalBytesPerRow + + st.SkipBytes + + (st.CopyRowsPerSlice - 1) * st.TotalBytesPerRow + + st.CopyBytesPerRow; + + return totalBytes; +} + + +/** + * Do error checking for getting compressed texture images. + * \return true if any error, false if no errors. + */ +static bool getcompressedteximage_error_check(struct gl_context *ctx, - struct gl_texture_image *texImage, - GLenum target, - GLint level, GLsizei clientMemSize, - GLvoid *img, bool dsa) + struct gl_texture_object *texObj, + GLenum target, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, + GLsizei bufSize, GLvoid *pixels, + const char *caller) { - const GLint maxLevels = _mesa_max_texture_levels(ctx, target); - GLuint compressedSize, dimensions; - const char *suffix = dsa ? "ture" : ""; + struct gl_texture_image *texImage; + GLint maxLevels; + GLsizei totalBytes; + GLuint dimensions; - assert(texImage); + assert(texObj); - if (!legal_getteximage_target(ctx, target, dsa)) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetCompressedTex%sImage(target=%s)", suffix, - _mesa_lookup_enum_by_nr(target)); - return GL_TRUE; + if (texObj->Target == 0) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid texture)", caller); + return true; } - assert(maxLevels != 0); + maxLevels = _mesa_max_texture_levels(ctx, target); if (level < 0 || level >= maxLevels) { _mesa_error(ctx, GL_INVALID_VALUE, - "glGetCompressedTex%sImage(bad level = %d)", suffix, level); - return GL_TRUE; + "%s(bad level = %d)", caller, level); + return true; + } + + if (dimensions_error_check(ctx, texObj, target, level, + xoffset, yoffset, zoffset, + width, height, depth, caller)) { + return true; } + texImage = select_tex_image(texObj, target, level, zoffset); + assert(texImage); + if (!_mesa_is_format_compressed(texImage->TexFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glGetCompressedTex%sImage(texture is not compressed)", - suffix); - return GL_TRUE; + "%s(texture is not compressed)", caller); + return true; } - compressedSize = _mesa_format_image_size(texImage->TexFormat, - texImage->Width, - texImage->Height, - texImage->Depth); - /* Check for invalid pixel storage modes */ - dimensions = _mesa_get_texture_dimensions(texImage->TexObject->Target); + dimensions = _mesa_get_texture_dimensions(texObj->Target); if (!_mesa_compressed_pixel_storage_error_check(ctx, dimensions, - &ctx->Pack, dsa ? - "glGetCompressedTextureImage": - "glGetCompressedTexImage")) { - return GL_TRUE; + &ctx->Pack, + caller)) { + return true; } - if (!_mesa_is_bufferobj(ctx->Pack.BufferObj)) { - /* do bounds checking on writing to client memory */ - if (clientMemSize < (GLsizei) compressedSize) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "%s(out of bounds access: bufSize (%d) is too small)", - dsa ? "glGetCompressedTextureImage" : - "glGetnCompressedTexImageARB", clientMemSize); - return GL_TRUE; - } - } else { + /* Compute number of bytes that may be touched in the dest buffer */ + totalBytes = packed_compressed_size(dimensions, texImage->TexFormat, + width, height, depth, + &ctx->Pack); + + /* Do dest buffer bounds checking */ + if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { /* do bounds checking on PBO write */ - if ((const GLubyte *) img + compressedSize > - (const GLubyte *) ctx->Pack.BufferObj->Size) { + if ((GLubyte *) pixels + totalBytes > + (GLubyte *) ctx->Pack.BufferObj->Size) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glGetCompressedTex%sImage(out of bounds PBO access)", - suffix); - return GL_TRUE; + "%s(out of bounds PBO access)", caller); + return true; } /* make sure PBO is not mapped */ if (_mesa_check_disallowed_mapping(ctx->Pack.BufferObj)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)", caller); + return true; + } + } + else { + /* do bounds checking on writing to client memory */ + if (totalBytes > bufSize) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glGetCompressedTex%sImage(PBO is mapped)", suffix); - return GL_TRUE; + "%s(out of bounds access: bufSize (%d) is too small)", + caller, bufSize); + return true; } } - return GL_FALSE; + if (!_mesa_is_bufferobj(ctx->Pack.BufferObj) && !pixels) { + /* not an error, but do nothing */ + return true; + } + + return false; } -/** Implements glGetnCompressedTexImageARB, glGetCompressedTexImage, and - * glGetCompressedTextureImage. - * - * texImage must be passed in because glGetCompressedTexImage must handle the - * target GL_TEXTURE_CUBE_MAP. + +/** + * Common helper for all glGetCompressed-teximage functions. */ -void -_mesa_get_compressed_texture_image(struct gl_context *ctx, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage, - GLenum target, GLint level, - GLsizei bufSize, GLvoid *pixels, - bool dsa) +static void +get_compressed_texture_image(struct gl_context *ctx, + struct gl_texture_object *texObj, + GLenum target, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLint depth, + GLvoid *pixels, + const char *caller) { - assert(texObj); - assert(texImage); + struct gl_texture_image *texImage; + unsigned firstFace, numFaces, i, imageStride; FLUSH_VERTICES(ctx, 0); - if (getcompressedteximage_error_check(ctx, texImage, target, level, - bufSize, pixels, dsa)) { - return; - } - - if (!_mesa_is_bufferobj(ctx->Pack.BufferObj) && !pixels) { - /* not an error, do nothing */ - return; - } + texImage = select_tex_image(texObj, target, level, zoffset); + assert(texImage); /* should have been error checked already */ if (_mesa_is_zero_size_texture(texImage)) return; if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE)) { _mesa_debug(ctx, - "glGetCompressedTex%sImage(tex %u) format = %s, w=%d, h=%d\n", - dsa ? "ture" : "", texObj->Name, + "%s(tex %u) format = %s, w=%d, h=%d\n", + caller, texObj->Name, _mesa_get_format_name(texImage->TexFormat), texImage->Width, texImage->Height); } + if (target == GL_TEXTURE_CUBE_MAP) { + struct compressed_pixelstore store; + + /* Compute image stride between cube faces */ + _mesa_compute_compressed_pixelstore(2, texImage->TexFormat, + width, height, depth, + &ctx->Pack, &store); + imageStride = store.TotalBytesPerRow * store.TotalRowsPerSlice; + + firstFace = zoffset; + numFaces = depth; + zoffset = 0; + depth = 1; + } + else { + imageStride = 0; + firstFace = _mesa_tex_target_to_face(target); + numFaces = 1; + } + _mesa_lock_texture(ctx, texObj); - { - ctx->Driver.GetCompressedTexImage(ctx, texImage, pixels); + + for (i = 0; i < numFaces; i++) { + texImage = texObj->Image[firstFace + i][level]; + assert(texImage); + + ctx->Driver.GetCompressedTexSubImage(ctx, texImage, + xoffset, yoffset, zoffset, + width, height, depth, pixels); + + /* next cube face */ + pixels = (GLubyte *) pixels + imageStride; } + _mesa_unlock_texture(ctx, texObj); } + void GLAPIENTRY _mesa_GetnCompressedTexImageARB(GLenum target, GLint level, GLsizei bufSize, - GLvoid *img) + GLvoid *pixels) { - struct gl_texture_object *texObj; - struct gl_texture_image *texImage; GET_CURRENT_CONTEXT(ctx); + static const char *caller = "glGetnCompressedTexImageARB"; + GLsizei width, height, depth; + struct gl_texture_object *texObj; - texObj = _mesa_get_current_tex_object(ctx, target); - if (!texObj) + if (!legal_getteximage_target(ctx, target, false)) { + _mesa_error(ctx, GL_INVALID_ENUM, "%s", caller); return; + } - texImage = _mesa_select_tex_image(texObj, target, level); - if (!texImage) + texObj = _mesa_get_current_tex_object(ctx, target); + assert(texObj); + + get_texture_image_dims(texObj, target, level, &width, &height, &depth); + + if (getcompressedteximage_error_check(ctx, texObj, target, level, + 0, 0, 0, width, height, depth, + INT_MAX, pixels, caller)) { return; + } - _mesa_get_compressed_texture_image(ctx, texObj, texImage, target, level, - bufSize, img, false); + get_compressed_texture_image(ctx, texObj, target, level, + 0, 0, 0, width, height, depth, + pixels, caller); } + void GLAPIENTRY -_mesa_GetCompressedTexImage(GLenum target, GLint level, GLvoid *img) +_mesa_GetCompressedTexImage(GLenum target, GLint level, GLvoid *pixels) { - _mesa_GetnCompressedTexImageARB(target, level, INT_MAX, img); + GET_CURRENT_CONTEXT(ctx); + static const char *caller = "glGetCompressedTexImage"; + GLsizei width, height, depth; + struct gl_texture_object *texObj; + + if (!legal_getteximage_target(ctx, target, false)) { + _mesa_error(ctx, GL_INVALID_ENUM, "%s", caller); + return; + } + + texObj = _mesa_get_current_tex_object(ctx, target); + assert(texObj); + + get_texture_image_dims(texObj, target, level, + &width, &height, &depth); + + if (getcompressedteximage_error_check(ctx, texObj, target, level, + 0, 0, 0, width, height, depth, + INT_MAX, pixels, caller)) { + return; + } + + get_compressed_texture_image(ctx, texObj, target, level, + 0, 0, 0, width, height, depth, + pixels, caller); } -/** - * Get compressed texture image. - * - * \param texture texture name. - * \param level image level. - * \param bufSize size of the pixels data buffer. - * \param pixels returned pixel data. - */ + void GLAPIENTRY _mesa_GetCompressedTextureImage(GLuint texture, GLint level, GLsizei bufSize, GLvoid *pixels) { - struct gl_texture_object *texObj; - struct gl_texture_image *texImage; - int i; - GLint image_stride; GET_CURRENT_CONTEXT(ctx); + static const char *caller = "glGetCompressedTextureImage"; + GLsizei width, height, depth; + struct gl_texture_object *texObj = + _mesa_lookup_texture_err(ctx, texture, caller); - texObj = _mesa_lookup_texture_err(ctx, texture, - "glGetCompressedTextureImage"); - if (!texObj) + if (!texObj) { return; + } - /* Must handle special case GL_TEXTURE_CUBE_MAP. */ - if (texObj->Target == GL_TEXTURE_CUBE_MAP) { + get_texture_image_dims(texObj, texObj->Target, level, + &width, &height, &depth); - /* Make sure the texture object is a proper cube. - * (See texturesubimage in teximage.c for details on why this check is - * performed.) - */ - if (!_mesa_cube_level_complete(texObj, level)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glGetCompressedTextureImage(cube map incomplete)"); - return; - } + if (getcompressedteximage_error_check(ctx, texObj, texObj->Target, level, + 0, 0, 0, width, height, depth, + bufSize, pixels, caller)) { + return; + } - /* Copy each face. */ - for (i = 0; i < 6; ++i) { - texImage = texObj->Image[i][level]; - assert(texImage); + get_compressed_texture_image(ctx, texObj, texObj->Target, level, + 0, 0, 0, width, height, depth, + pixels, caller); +} - _mesa_get_compressed_texture_image(ctx, texObj, texImage, - texObj->Target, level, - bufSize, pixels, true); - /* Compressed images don't have a client format */ - image_stride = _mesa_format_image_size(texImage->TexFormat, - texImage->Width, - texImage->Height, 1); +void APIENTRY +_mesa_GetCompressedTextureSubImage(GLuint texture, GLint level, + GLint xoffset, GLint yoffset, + GLint zoffset, GLsizei width, + GLsizei height, GLsizei depth, + GLsizei bufSize, void *pixels) +{ + GET_CURRENT_CONTEXT(ctx); + static const char *caller = "glGetCompressedTextureImage"; + struct gl_texture_object *texObj; - pixels = (GLubyte *) pixels + image_stride; - bufSize -= image_stride; - } + texObj = _mesa_lookup_texture_err(ctx, texture, caller); + if (!texObj) { + return; } - else { - texImage = _mesa_select_tex_image(texObj, texObj->Target, level); - if (!texImage) - return; - _mesa_get_compressed_texture_image(ctx, texObj, texImage, - texObj->Target, level, bufSize, - pixels, true); + if (getcompressedteximage_error_check(ctx, texObj, texObj->Target, level, + xoffset, yoffset, zoffset, + width, height, depth, + bufSize, pixels, caller)) { + return; } + + get_compressed_texture_image(ctx, texObj, texObj->Target, level, + xoffset, yoffset, zoffset, + width, height, depth, + pixels, caller); } diff --git a/src/mesa/main/texgetimage.h b/src/mesa/main/texgetimage.h index 1fa2f59dcdc..63c75eb931d 100644 --- a/src/mesa/main/texgetimage.h +++ b/src/mesa/main/texgetimage.h @@ -37,22 +37,19 @@ extern GLenum _mesa_base_pack_format(GLenum format); extern void -_mesa_GetTexImage_sw(struct gl_context *ctx, - GLenum format, GLenum type, GLvoid *pixels, - struct gl_texture_image *texImage); - - -extern void -_mesa_GetCompressedTexImage_sw(struct gl_context *ctx, - struct gl_texture_image *texImage, - GLvoid *data); +_mesa_GetTexSubImage_sw(struct gl_context *ctx, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLint depth, + GLenum format, GLenum type, GLvoid *pixels, + struct gl_texture_image *texImage); extern void -_mesa_get_texture_image(struct gl_context *ctx, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage, GLenum target, - GLint level, GLenum format, GLenum type, - GLsizei bufSize, GLvoid *pixels, bool dsa); +_mesa_GetCompressedTexSubImage_sw(struct gl_context *ctx, + struct gl_texture_image *texImage, + GLint xoffset, GLint yoffset, + GLint zoffset, GLsizei width, + GLint height, GLint depth, + GLvoid *data); extern void _mesa_get_compressed_texture_image( struct gl_context *ctx, @@ -74,6 +71,14 @@ _mesa_GetTextureImage(GLuint texture, GLint level, GLenum format, GLenum type, GLsizei bufSize, GLvoid *pixels); extern void GLAPIENTRY +_mesa_GetTextureSubImage(GLuint texture, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, GLsizei bufSize, + void *pixels); + + +extern void GLAPIENTRY _mesa_GetCompressedTexImage(GLenum target, GLint lod, GLvoid *img); extern void GLAPIENTRY @@ -84,4 +89,11 @@ extern void GLAPIENTRY _mesa_GetCompressedTextureImage(GLuint texture, GLint level, GLsizei bufSize, GLvoid *pixels); +extern void APIENTRY +_mesa_GetCompressedTextureSubImage(GLuint texture, GLint level, + GLint xoffset, GLint yoffset, + GLint zoffset, GLsizei width, + GLsizei height, GLsizei depth, + GLsizei bufSize, void *pixels); + #endif /* TEXGETIMAGE_H */ diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c index 3d85615fa45..3a556a6ad6e 100644 --- a/src/mesa/main/teximage.c +++ b/src/mesa/main/teximage.c @@ -1008,7 +1008,7 @@ _mesa_max_texture_levels(struct gl_context *ctx, GLenum target) case GL_PROXY_TEXTURE_2D_MULTISAMPLE: case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY: - return _mesa_is_desktop_gl(ctx) + return (_mesa_is_desktop_gl(ctx) || _mesa_is_gles31(ctx)) && ctx->Extensions.ARB_texture_multisample ? 1 : 0; case GL_TEXTURE_EXTERNAL_OES: @@ -1793,8 +1793,6 @@ GLboolean _mesa_target_can_be_compressed(const struct gl_context *ctx, GLenum target, GLenum intFormat) { - (void) intFormat; /* not used yet */ - switch (target) { case GL_TEXTURE_2D: case GL_PROXY_TEXTURE_2D: @@ -1814,6 +1812,16 @@ _mesa_target_can_be_compressed(const struct gl_context *ctx, GLenum target, case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY: case GL_TEXTURE_CUBE_MAP_ARRAY: return ctx->Extensions.ARB_texture_cube_map_array; + case GL_TEXTURE_3D: + switch (intFormat) { + case GL_COMPRESSED_RGBA_BPTC_UNORM: + case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM: + case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT: + case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT: + return ctx->Extensions.ARB_texture_compression_bptc; + default: + return GL_FALSE; + } default: return GL_FALSE; } @@ -2081,6 +2089,53 @@ texture_formats_agree(GLenum internalFormat, } /** + * Test the combination of format, type and internal format arguments of + * different texture operations on GLES. + * + * \param ctx GL context. + * \param format pixel data format given by the user. + * \param type pixel data type given by the user. + * \param internalFormat internal format given by the user. + * \param dimensions texture image dimensions (must be 1, 2 or 3). + * \param callerName name of the caller function to print in the error message + * + * \return true if a error is found, false otherwise + * + * Currently, it is used by texture_error_check() and texsubimage_error_check(). + */ +static bool +texture_format_error_check_gles(struct gl_context *ctx, GLenum format, + GLenum type, GLenum internalFormat, + GLuint dimensions, const char *callerName) +{ + GLenum err; + + if (_mesa_is_gles3(ctx)) { + err = _mesa_es3_error_check_format_and_type(ctx, format, type, + internalFormat); + if (err != GL_NO_ERROR) { + _mesa_error(ctx, err, + "%s(format = %s, type = %s, internalformat = %s)", + callerName, _mesa_enum_to_string(format), + _mesa_enum_to_string(type), + _mesa_enum_to_string(internalFormat)); + return true; + } + } + else { + err = _mesa_es_error_check_format_and_type(format, type, dimensions); + if (err != GL_NO_ERROR) { + _mesa_error(ctx, err, "%s(format = %s, type = %s)", + callerName, _mesa_enum_to_string(format), + _mesa_enum_to_string(type)); + return true; + } + } + + return false; +} + +/** * Test the glTexImage[123]D() parameters for errors. * * \param ctx GL context. @@ -2151,39 +2206,17 @@ texture_error_check( struct gl_context *ctx, * Formats and types that require additional extensions (e.g., GL_FLOAT * requires GL_OES_texture_float) are filtered elsewhere. */ - - if (_mesa_is_gles(ctx)) { - if (_mesa_is_gles3(ctx)) { - err = _mesa_es3_error_check_format_and_type(ctx, format, type, - internalFormat); - } else { - if (format != internalFormat) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glTexImage%dD(format = %s, internalFormat = %s)", - dimensions, - _mesa_lookup_enum_by_nr(format), - _mesa_lookup_enum_by_nr(internalFormat)); - return GL_TRUE; - } - - err = _mesa_es_error_check_format_and_type(format, type, dimensions); - } - if (err != GL_NO_ERROR) { - _mesa_error(ctx, err, - "glTexImage%dD(format = %s, type = %s, internalFormat = %s)", - dimensions, - _mesa_lookup_enum_by_nr(format), - _mesa_lookup_enum_by_nr(type), - _mesa_lookup_enum_by_nr(internalFormat)); - return GL_TRUE; - } + if (_mesa_is_gles(ctx) && + texture_format_error_check_gles(ctx, format, type, internalFormat, + dimensions, "glTexImage%dD")) { + return GL_TRUE; } /* Check internalFormat */ if (_mesa_base_tex_format(ctx, internalFormat) < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glTexImage%dD(internalFormat=%s)", - dimensions, _mesa_lookup_enum_by_nr(internalFormat)); + dimensions, _mesa_enum_to_string(internalFormat)); return GL_TRUE; } @@ -2192,8 +2225,8 @@ texture_error_check( struct gl_context *ctx, if (err != GL_NO_ERROR) { _mesa_error(ctx, err, "glTexImage%dD(incompatible format = %s, type = %s)", - dimensions, _mesa_lookup_enum_by_nr(format), - _mesa_lookup_enum_by_nr(type)); + dimensions, _mesa_enum_to_string(format), + _mesa_enum_to_string(type)); return GL_TRUE; } @@ -2208,8 +2241,8 @@ texture_error_check( struct gl_context *ctx, if (!texture_formats_agree(internalFormat, format)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glTexImage%dD(incompatible internalFormat = %s, format = %s)", - dimensions, _mesa_lookup_enum_by_nr(internalFormat), - _mesa_lookup_enum_by_nr(format)); + dimensions, _mesa_enum_to_string(internalFormat), + _mesa_enum_to_string(format)); return GL_TRUE; } @@ -2324,7 +2357,7 @@ compressed_texture_error_check(struct gl_context *ctx, GLint dimensions, if (!_mesa_is_compressed_format(ctx, internalFormat)) { _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage%dD(internalFormat=%s)", - dimensions, _mesa_lookup_enum_by_nr(internalFormat)); + dimensions, _mesa_enum_to_string(internalFormat)); return GL_TRUE; } @@ -2479,40 +2512,38 @@ texsubimage_error_check(struct gl_context *ctx, GLuint dimensions, return GL_TRUE; } - /* check target (proxies not allowed) */ - if (!legal_texsubimage_target(ctx, dimensions, target, dsa)) { - _mesa_error(ctx, GL_INVALID_ENUM, "%s(target=%s)", - callerName, _mesa_lookup_enum_by_nr(target)); - return GL_TRUE; - } - /* level check */ if (level < 0 || level >= _mesa_max_texture_levels(ctx, target)) { _mesa_error(ctx, GL_INVALID_VALUE, "%s(level=%d)", callerName, level); return GL_TRUE; } - /* OpenGL ES 1.x and OpenGL ES 2.0 impose additional restrictions on the - * combinations of format and type that can be used. Formats and types - * that require additional extensions (e.g., GL_FLOAT requires - * GL_OES_texture_float) are filtered elsewhere. - */ - if (_mesa_is_gles(ctx) && !_mesa_is_gles3(ctx)) { - err = _mesa_es_error_check_format_and_type(format, type, dimensions); - if (err != GL_NO_ERROR) { - _mesa_error(ctx, err, "%s(format = %s, type = %s)", - callerName, _mesa_lookup_enum_by_nr(format), - _mesa_lookup_enum_by_nr(type)); - return GL_TRUE; - } + texImage = _mesa_select_tex_image(texObj, target, level); + if (!texImage) { + /* non-existant texture level */ + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid texture image)", + callerName); + return GL_TRUE; } err = _mesa_error_check_format_and_type(ctx, format, type); if (err != GL_NO_ERROR) { _mesa_error(ctx, err, "%s(incompatible format = %s, type = %s)", - callerName, _mesa_lookup_enum_by_nr(format), - _mesa_lookup_enum_by_nr(type)); + callerName, _mesa_enum_to_string(format), + _mesa_enum_to_string(type)); + return GL_TRUE; + } + + /* OpenGL ES 1.x and OpenGL ES 2.0 impose additional restrictions on the + * combinations of format, internalFormat, and type that can be used. + * Formats and types that require additional extensions (e.g., GL_FLOAT + * requires GL_OES_texture_float) are filtered elsewhere. + */ + if (_mesa_is_gles(ctx) && + texture_format_error_check_gles(ctx, format, type, + texImage->InternalFormat, + dimensions, callerName)) { return GL_TRUE; } @@ -2523,14 +2554,6 @@ texsubimage_error_check(struct gl_context *ctx, GLuint dimensions, return GL_TRUE; } - texImage = _mesa_select_tex_image(texObj, target, level); - if (!texImage) { - /* non-existant texture level */ - _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid texture image)", - callerName); - return GL_TRUE; - } - if (error_check_subtexture_dimensions(ctx, dimensions, texImage, xoffset, yoffset, zoffset, width, height, depth, callerName)) { @@ -2590,7 +2613,7 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions, /* check target */ if (!legal_texsubimage_target(ctx, dimensions, target, false)) { _mesa_error(ctx, GL_INVALID_ENUM, "glCopyTexImage%uD(target=%s)", - dimensions, _mesa_lookup_enum_by_nr(target)); + dimensions, _mesa_enum_to_string(target)); return GL_TRUE; } @@ -2629,13 +2652,6 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions, return GL_TRUE; } - rb = _mesa_get_read_renderbuffer_for_format(ctx, internalFormat); - if (rb == NULL) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glCopyTexImage%dD(read buffer)", dimensions); - return GL_TRUE; - } - /* OpenGL ES 1.x and OpenGL ES 2.0 impose additional restrictions on the * internalFormat. */ @@ -2648,18 +2664,25 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions, case GL_LUMINANCE_ALPHA: break; default: - _mesa_error(ctx, GL_INVALID_VALUE, + _mesa_error(ctx, GL_INVALID_ENUM, "glCopyTexImage%dD(internalFormat=%s)", dimensions, - _mesa_lookup_enum_by_nr(internalFormat)); + _mesa_enum_to_string(internalFormat)); return GL_TRUE; } } baseFormat = _mesa_base_tex_format(ctx, internalFormat); if (baseFormat < 0) { - _mesa_error(ctx, GL_INVALID_OPERATION, + _mesa_error(ctx, GL_INVALID_ENUM, "glCopyTexImage%dD(internalFormat=%s)", dimensions, - _mesa_lookup_enum_by_nr(internalFormat)); + _mesa_enum_to_string(internalFormat)); + return GL_TRUE; + } + + rb = _mesa_get_read_renderbuffer_for_format(ctx, internalFormat); + if (rb == NULL) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glCopyTexImage%dD(read buffer)", dimensions); return GL_TRUE; } @@ -2669,7 +2692,7 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions, if (rb_base_format < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glCopyTexImage%dD(internalFormat=%s)", dimensions, - _mesa_lookup_enum_by_nr(internalFormat)); + _mesa_enum_to_string(internalFormat)); return GL_TRUE; } } @@ -2696,7 +2719,7 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions, if (!valid) { _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyTexImage%dD(internalFormat=%s)", dimensions, - _mesa_lookup_enum_by_nr(internalFormat)); + _mesa_enum_to_string(internalFormat)); return GL_TRUE; } } @@ -2735,10 +2758,10 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions, * types for SNORM formats. Also, conversion to SNORM formats is not * allowed by Table 3.2 on Page 110. */ - if(_mesa_is_enum_format_snorm(internalFormat)) { + if (_mesa_is_enum_format_snorm(internalFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyTexImage%dD(internalFormat=%s)", dimensions, - _mesa_lookup_enum_by_nr(internalFormat)); + _mesa_enum_to_string(internalFormat)); return GL_TRUE; } } @@ -3103,8 +3126,8 @@ _mesa_choose_texture_format(struct gl_context *ctx, "DXT compression requested (%s), " "but libtxc_dxtn library not installed. Using %s " "instead.", - _mesa_lookup_enum_by_nr(before), - _mesa_lookup_enum_by_nr(internalFormat)); + _mesa_enum_to_string(before), + _mesa_enum_to_string(internalFormat)); } } @@ -3191,18 +3214,18 @@ teximage(struct gl_context *ctx, GLboolean compressed, GLuint dims, _mesa_debug(ctx, "glCompressedTexImage%uD %s %d %s %d %d %d %d %p\n", dims, - _mesa_lookup_enum_by_nr(target), level, - _mesa_lookup_enum_by_nr(internalFormat), + _mesa_enum_to_string(target), level, + _mesa_enum_to_string(internalFormat), width, height, depth, border, pixels); else _mesa_debug(ctx, "glTexImage%uD %s %d %s %d %d %d %d %s %s %p\n", dims, - _mesa_lookup_enum_by_nr(target), level, - _mesa_lookup_enum_by_nr(internalFormat), + _mesa_enum_to_string(target), level, + _mesa_enum_to_string(internalFormat), width, height, depth, border, - _mesa_lookup_enum_by_nr(format), - _mesa_lookup_enum_by_nr(type), pixels); + _mesa_enum_to_string(format), + _mesa_enum_to_string(type), pixels); } internalFormat = override_internal_format(internalFormat, width, height); @@ -3210,7 +3233,7 @@ teximage(struct gl_context *ctx, GLboolean compressed, GLuint dims, /* target error checking */ if (!legal_teximage_target(ctx, dims, target)) { _mesa_error(ctx, GL_INVALID_ENUM, "%s%uD(target=%s)", - func, dims, _mesa_lookup_enum_by_nr(target)); + func, dims, _mesa_enum_to_string(target)); return; } @@ -3313,16 +3336,16 @@ teximage(struct gl_context *ctx, GLboolean compressed, GLuint dims, if (!dimensionsOK) { _mesa_error(ctx, GL_INVALID_VALUE, - "glTexImage%uD(invalid width or height or depth)", - dims); + "%s%uD(invalid width or height or depth)", + func, dims); return; } if (!sizeOK) { _mesa_error(ctx, GL_OUT_OF_MEMORY, - "glTexImage%uD(image too large: %d x %d x %d, %s format)", - dims, width, height, depth, - _mesa_lookup_enum_by_nr(internalFormat)); + "%s%uD(image too large: %d x %d x %d, %s format)", + func, dims, width, height, depth, + _mesa_enum_to_string(internalFormat)); return; } @@ -3495,7 +3518,6 @@ _mesa_EGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image) _mesa_dirty_texobj(ctx, texObj); } _mesa_unlock_texture(ctx, texObj); - } @@ -3515,14 +3537,6 @@ _mesa_texture_sub_image(struct gl_context *ctx, GLuint dims, { FLUSH_VERTICES(ctx, 0); - /* check target (proxies not allowed) */ - if (!legal_texsubimage_target(ctx, dims, target, dsa)) { - _mesa_error(ctx, GL_INVALID_ENUM, "glTex%sSubImage%uD(target=%s)", - dsa ? "ture" : "", - dims, _mesa_lookup_enum_by_nr(target)); - return; - } - if (ctx->NewState & _NEW_PIXEL) _mesa_update_state(ctx); @@ -3572,6 +3586,13 @@ texsubimage(struct gl_context *ctx, GLuint dims, GLenum target, GLint level, struct gl_texture_object *texObj; struct gl_texture_image *texImage; + /* check target (proxies not allowed) */ + if (!legal_texsubimage_target(ctx, dims, target, false)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glTexSubImage%uD(target=%s)", + dims, _mesa_enum_to_string(target)); + return; + } + texObj = _mesa_get_current_tex_object(ctx, target); if (!texObj) return; @@ -3589,10 +3610,10 @@ texsubimage(struct gl_context *ctx, GLuint dims, GLenum target, GLint level, if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) _mesa_debug(ctx, "glTexSubImage%uD %s %d %d %d %d %d %d %d %s %s %p\n", dims, - _mesa_lookup_enum_by_nr(target), level, + _mesa_enum_to_string(target), level, xoffset, yoffset, zoffset, width, height, depth, - _mesa_lookup_enum_by_nr(format), - _mesa_lookup_enum_by_nr(type), pixels); + _mesa_enum_to_string(format), + _mesa_enum_to_string(type), pixels); _mesa_texture_sub_image(ctx, dims, texObj, texImage, target, level, xoffset, yoffset, zoffset, width, height, depth, @@ -3621,8 +3642,8 @@ texturesubimage(struct gl_context *ctx, GLuint dims, "glTextureSubImage%uD %d %d %d %d %d %d %d %d %s %s %p\n", dims, texture, level, xoffset, yoffset, zoffset, width, height, depth, - _mesa_lookup_enum_by_nr(format), - _mesa_lookup_enum_by_nr(type), pixels); + _mesa_enum_to_string(format), + _mesa_enum_to_string(type), pixels); /* Get the texture object by Name. */ texObj = _mesa_lookup_texture(ctx, texture); @@ -3632,6 +3653,13 @@ texturesubimage(struct gl_context *ctx, GLuint dims, return; } + /* check target (proxies not allowed) */ + if (!legal_texsubimage_target(ctx, dims, texObj->Target, true)) { + _mesa_error(ctx, GL_INVALID_ENUM, "%s(target=%s)", + callerName, _mesa_enum_to_string(texObj->Target)); + return; + } + if (texsubimage_error_check(ctx, dims, texObj, texObj->Target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, @@ -3842,8 +3870,7 @@ copytexsubimage_by_slice(struct gl_context *ctx, } static GLboolean -formats_differ_in_component_sizes (mesa_format f1, - mesa_format f2) +formats_differ_in_component_sizes(mesa_format f1, mesa_format f2) { GLint f1_r_bits = _mesa_get_format_bits(f1, GL_RED_BITS); GLint f1_g_bits = _mesa_get_format_bits(f1, GL_GREEN_BITS); @@ -3883,8 +3910,8 @@ copyteximage(struct gl_context *ctx, GLuint dims, if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) _mesa_debug(ctx, "glCopyTexImage%uD %s %d %s %d %d %d %d %d\n", dims, - _mesa_lookup_enum_by_nr(target), level, - _mesa_lookup_enum_by_nr(internalFormat), + _mesa_enum_to_string(target), level, + _mesa_enum_to_string(internalFormat), x, y, width, height, border); if (ctx->NewState & NEW_COPY_TEX_STATE) @@ -3916,8 +3943,8 @@ copyteximage(struct gl_context *ctx, GLuint dims, */ if (rb->InternalFormat == GL_RGB10_A2) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glCopyTexImage%uD(Reading from GL_RGB10_A2 buffer and" - " writing to unsized internal format)", dims); + "glCopyTexImage%uD(Reading from GL_RGB10_A2 buffer" + " and writing to unsized internal format)", dims); return; } } @@ -4043,7 +4070,7 @@ _mesa_copy_texture_sub_image(struct gl_context *ctx, GLuint dims, if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) _mesa_debug(ctx, "%s %s %d %d %d %d %d %d %d %d\n", caller, - _mesa_lookup_enum_by_nr(target), + _mesa_enum_to_string(target), level, xoffset, yoffset, zoffset, x, y, width, height); if (ctx->NewState & NEW_COPY_TEX_STATE) @@ -4105,7 +4132,7 @@ _mesa_CopyTexSubImage1D( GLenum target, GLint level, */ if (!legal_texsubimage_target(ctx, 1, target, false)) { _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", self, - _mesa_lookup_enum_by_nr(target)); + _mesa_enum_to_string(target)); return; } @@ -4133,7 +4160,7 @@ _mesa_CopyTexSubImage2D( GLenum target, GLint level, */ if (!legal_texsubimage_target(ctx, 2, target, false)) { _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", self, - _mesa_lookup_enum_by_nr(target)); + _mesa_enum_to_string(target)); return; } @@ -4162,7 +4189,7 @@ _mesa_CopyTexSubImage3D( GLenum target, GLint level, */ if (!legal_texsubimage_target(ctx, 3, target, false)) { _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", self, - _mesa_lookup_enum_by_nr(target)); + _mesa_enum_to_string(target)); return; } @@ -4190,7 +4217,7 @@ _mesa_CopyTextureSubImage1D(GLuint texture, GLint level, /* Check target (proxies not allowed). */ if (!legal_texsubimage_target(ctx, 1, texObj->Target, true)) { _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", self, - _mesa_lookup_enum_by_nr(texObj->Target)); + _mesa_enum_to_string(texObj->Target)); return; } @@ -4214,7 +4241,7 @@ _mesa_CopyTextureSubImage2D(GLuint texture, GLint level, /* Check target (proxies not allowed). */ if (!legal_texsubimage_target(ctx, 2, texObj->Target, true)) { _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", self, - _mesa_lookup_enum_by_nr(texObj->Target)); + _mesa_enum_to_string(texObj->Target)); return; } @@ -4241,7 +4268,7 @@ _mesa_CopyTextureSubImage3D(GLuint texture, GLint level, /* Check target (proxies not allowed). */ if (!legal_texsubimage_target(ctx, 3, texObj->Target, true)) { _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", self, - _mesa_lookup_enum_by_nr(texObj->Target)); + _mesa_enum_to_string(texObj->Target)); return; } @@ -4288,8 +4315,8 @@ check_clear_tex_image(struct gl_context *ctx, _mesa_error(ctx, err, "%s(incompatible format = %s, type = %s)", function, - _mesa_lookup_enum_by_nr(format), - _mesa_lookup_enum_by_nr(type)); + _mesa_enum_to_string(format), + _mesa_enum_to_string(type)); return false; } @@ -4298,8 +4325,8 @@ check_clear_tex_image(struct gl_context *ctx, _mesa_error(ctx, GL_INVALID_OPERATION, "%s(incompatible internalFormat = %s, format = %s)", function, - _mesa_lookup_enum_by_nr(internalFormat), - _mesa_lookup_enum_by_nr(format)); + _mesa_enum_to_string(internalFormat), + _mesa_enum_to_string(format)); return false; } @@ -4541,7 +4568,7 @@ compressed_subtexture_target_check(struct gl_context *ctx, GLenum target, if (dsa && target == GL_TEXTURE_RECTANGLE) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid target %s)", caller, - _mesa_lookup_enum_by_nr(target)); + _mesa_enum_to_string(target)); return GL_TRUE; } @@ -4549,13 +4576,15 @@ compressed_subtexture_target_check(struct gl_context *ctx, GLenum target, case 2: switch (target) { case GL_TEXTURE_2D: + targetOK = GL_TRUE; + 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: - targetOK = GL_TRUE; + targetOK = ctx->Extensions.ARB_texture_cube_map; break; default: targetOK = GL_FALSE; @@ -4563,52 +4592,59 @@ compressed_subtexture_target_check(struct gl_context *ctx, GLenum target, } break; case 3: - targetOK = (target == GL_TEXTURE_3D) || - (target == GL_TEXTURE_2D_ARRAY) || - (target == GL_TEXTURE_CUBE_MAP_ARRAY) || - (target == GL_TEXTURE_CUBE_MAP && dsa); - - /* OpenGL 4.5 spec (30.10.2014) says in Section 8.7 Compressed Texture - * Images: - * "An INVALID_OPERATION error is generated by - * CompressedTex*SubImage3D if the internal format of the texture is - * one of the EAC, ETC2, or RGTC formats and either border is - * non-zero, or the effective target for the texture is not - * TEXTURE_2D_ARRAY." - */ - if (target != GL_TEXTURE_2D_ARRAY) { - bool invalidformat; + switch (target) { + case GL_TEXTURE_CUBE_MAP: + targetOK = dsa && ctx->Extensions.ARB_texture_cube_map; + break; + case GL_TEXTURE_2D_ARRAY: + targetOK = _mesa_is_gles3(ctx) || + (_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array); + break; + case GL_TEXTURE_CUBE_MAP_ARRAY: + targetOK = ctx->Extensions.ARB_texture_cube_map_array; + break; + case GL_TEXTURE_3D: + targetOK = GL_TRUE; + /* + * OpenGL 4.5 spec (30.10.2014) says in Section 8.7 Compressed Texture + * Images: + * "An INVALID_OPERATION error is generated by + * CompressedTex*SubImage3D if the internal format of the texture + * is one of the EAC, ETC2, or RGTC formats and either border is + * non-zero, or the effective target for the texture is not + * TEXTURE_2D_ARRAY." + * + * NOTE: that's probably a spec error. It should probably say + * "... or the effective target for the texture is not + * TEXTURE_2D_ARRAY, TEXTURE_CUBE_MAP, nor + * GL_TEXTURE_CUBE_MAP_ARRAY." + * since those targets are 2D images and they support all compression + * formats. + * + * Instead of listing all these, just list those which are allowed, + * which is (at this time) only bptc. Otherwise we'd say s3tc (and + * more) are valid here, which they are not, but of course not + * mentioned by core spec. + */ switch (format) { - /* These came from _mesa_is_compressed_format in glformats.c. */ - /* EAC formats */ - case GL_COMPRESSED_RGBA8_ETC2_EAC: - case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: - case GL_COMPRESSED_R11_EAC: - case GL_COMPRESSED_RG11_EAC: - case GL_COMPRESSED_SIGNED_R11_EAC: - case GL_COMPRESSED_SIGNED_RG11_EAC: - /* ETC2 formats */ - case GL_COMPRESSED_RGB8_ETC2: - case GL_COMPRESSED_SRGB8_ETC2: - case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: - case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: - /* RGTC formats */ - case GL_COMPRESSED_RED_RGTC1: - case GL_COMPRESSED_SIGNED_RED_RGTC1: - case GL_COMPRESSED_RG_RGTC2: - case GL_COMPRESSED_SIGNED_RG_RGTC2: - invalidformat = true; - break; - default: - invalidformat = false; - } - if (invalidformat) { + /* These are the only 3D compression formats supported at this time */ + case GL_COMPRESSED_RGBA_BPTC_UNORM: + case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM: + case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT: + case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT: + /* valid format */ + break; + default: + /* invalid format */ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid target %s for format %s)", caller, - _mesa_lookup_enum_by_nr(target), - _mesa_lookup_enum_by_nr(format)); + _mesa_enum_to_string(target), + _mesa_enum_to_string(format)); return GL_TRUE; } + break; + default: + targetOK = GL_FALSE; } break; @@ -4621,7 +4657,7 @@ compressed_subtexture_target_check(struct gl_context *ctx, GLenum target, if (!targetOK) { _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", caller, - _mesa_lookup_enum_by_nr(target)); + _mesa_enum_to_string(target)); return GL_TRUE; } @@ -4834,8 +4870,7 @@ _mesa_CompressedTextureSubImage1D(GLuint texture, GLint level, GLint xoffset, if (!texObj) return; - if (compressed_subtexture_target_check(ctx, texObj->Target, 1, format, - true, + if (compressed_subtexture_target_check(ctx, texObj->Target, 1, format, true, "glCompressedTextureSubImage1D")) { return; } @@ -4912,8 +4947,7 @@ _mesa_CompressedTextureSubImage2D(GLuint texture, GLint level, GLint xoffset, if (!texObj) return; - if (compressed_subtexture_target_check(ctx, texObj->Target, 2, format, - true, + if (compressed_subtexture_target_check(ctx, texObj->Target, 2, format, true, "glCompressedTextureSubImage2D")) { return; } @@ -4990,8 +5024,7 @@ _mesa_CompressedTextureSubImage3D(GLuint texture, GLint level, GLint xoffset, if (!texObj) return; - if (compressed_subtexture_target_check(ctx, texObj->Target, 3, format, - true, + if (compressed_subtexture_target_check(ctx, texObj->Target, 3, format, true, "glCompressedTextureSubImage3D")) { return; } @@ -5440,7 +5473,6 @@ _mesa_TexBufferRange(GLenum target, GLenum internalFormat, GLuint buffer, return; } else { - /* OpenGL 4.5 core spec (02.02.2015) says in Section 8.9 Buffer * Textures (PDF page 254): * "If buffer is zero, then any buffer object attached to the buffer @@ -5508,7 +5540,6 @@ _mesa_TextureBufferRange(GLuint texture, GLenum internalFormat, GLuint buffer, return; } else { - /* OpenGL 4.5 core spec (02.02.2015) says in Section 8.9 Buffer * Textures (PDF page 254): * "If buffer is zero, then any buffer object attached to the buffer @@ -5554,19 +5585,17 @@ check_multisample_target(GLuint dims, GLenum target, bool dsa) return dims == 2; case GL_PROXY_TEXTURE_2D_MULTISAMPLE: return dims == 2 && !dsa; - case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: return dims == 3; case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY: return dims == 3 && !dsa; - default: return GL_FALSE; } } -void +static void _mesa_texture_image_multisample(struct gl_context *ctx, GLuint dims, struct gl_texture_object *texObj, GLenum target, GLsizei samples, @@ -5581,8 +5610,8 @@ _mesa_texture_image_multisample(struct gl_context *ctx, GLuint dims, GLenum sample_count_error; bool dsa = strstr(func, "ture") ? true : false; - if (!(ctx->Extensions.ARB_texture_multisample - && _mesa_is_desktop_gl(ctx))) { + if (!((ctx->Extensions.ARB_texture_multisample + && _mesa_is_desktop_gl(ctx))) && !_mesa_is_gles31(ctx)) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func); return; } @@ -5605,14 +5634,21 @@ _mesa_texture_image_multisample(struct gl_context *ctx, GLuint dims, if (immutable && !_mesa_is_legal_tex_storage_format(ctx, internalformat)) { _mesa_error(ctx, GL_INVALID_ENUM, "%s(internalformat=%s not legal for immutable-format)", - func, _mesa_lookup_enum_by_nr(internalformat)); + func, _mesa_enum_to_string(internalformat)); return; } if (!is_renderable_texture_format(ctx, internalformat)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "%s(internalformat=%s)", - func, _mesa_lookup_enum_by_nr(internalformat)); + /* Page 172 of OpenGL ES 3.1 spec says: + * "An INVALID_ENUM error is generated if sizedinternalformat is not + * color-renderable, depth-renderable, or stencil-renderable (as + * defined in section 9.4). + * + * (Same error is also defined for desktop OpenGL for multisample + * teximage/texstorage functions.) + */ + _mesa_error(ctx, GL_INVALID_ENUM, "%s(internalformat=%s)", func, + _mesa_enum_to_string(internalformat)); return; } @@ -5671,13 +5707,12 @@ _mesa_texture_image_multisample(struct gl_context *ctx, GLuint dims, else { if (!dimensionsOK) { _mesa_error(ctx, GL_INVALID_VALUE, - "%s(invalid width or height)", func); + "%s(invalid width or height)", func); return; } if (!sizeOK) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, - "%s(texture too large)", func); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s(texture too large)", func); return; } @@ -5695,7 +5730,7 @@ _mesa_texture_image_multisample(struct gl_context *ctx, GLuint dims, if (width > 0 && height > 0 && depth > 0) { if (!ctx->Driver.AllocTextureStorage(ctx, texObj, 1, - width, height, depth)) { + width, height, depth)) { /* tidy up the texture image state. strictly speaking, * we're allowed to just leave this in whatever state we * like, but being tidy is good. diff --git a/src/mesa/main/teximage.h b/src/mesa/main/teximage.h index 1eebaa8b631..bf729daf534 100644 --- a/src/mesa/main/teximage.h +++ b/src/mesa/main/teximage.h @@ -200,15 +200,6 @@ _mesa_copy_texture_sub_image(struct gl_context *ctx, GLuint dims, const char *caller); extern void -_mesa_texture_image_multisample(struct gl_context *ctx, GLuint dims, - struct gl_texture_object *texObj, - GLenum target, GLsizei samples, - GLint internalformat, GLsizei width, - GLsizei height, GLsizei depth, - GLboolean fixedsamplelocations, - GLboolean immutable, const char *func); - -extern void _mesa_texture_buffer_range(struct gl_context *ctx, struct gl_texture_object *texObj, GLenum internalFormat, diff --git a/src/mesa/main/texobj.c b/src/mesa/main/texobj.c index c563f1e7434..cd7cfd6a4fb 100644 --- a/src/mesa/main/texobj.c +++ b/src/mesa/main/texobj.c @@ -1255,7 +1255,7 @@ create_textures(struct gl_context *ctx, GLenum target, if (targetIndex < 0) { /* Bad Target */ mtx_unlock(&ctx->Shared->Mutex); _mesa_error(ctx, GL_INVALID_ENUM, "gl%sTextures(target = %s)", - func, _mesa_lookup_enum_by_nr(texObj->Target)); + func, _mesa_enum_to_string(texObj->Target)); return; } assert(targetIndex < NUM_TEXTURE_TARGETS); @@ -1606,8 +1606,8 @@ _mesa_tex_target_to_index(const struct gl_context *ctx, GLenum target) return _mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_cube_map_array ? TEXTURE_CUBE_ARRAY_INDEX : -1; case GL_TEXTURE_2D_MULTISAMPLE: - return _mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_multisample - ? TEXTURE_2D_MULTISAMPLE_INDEX: -1; + return ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_multisample) || + _mesa_is_gles31(ctx)) ? TEXTURE_2D_MULTISAMPLE_INDEX: -1; case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: return _mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_multisample ? TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX: -1; @@ -1642,7 +1642,7 @@ _mesa_BindTexture( GLenum target, GLuint texName ) if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) _mesa_debug(ctx, "glBindTexture %s %d\n", - _mesa_lookup_enum_by_nr(target), (GLint) texName); + _mesa_enum_to_string(target), (GLint) texName); targetIndex = _mesa_tex_target_to_index(ctx, target); if (targetIndex < 0) { @@ -1806,7 +1806,7 @@ _mesa_BindTextureUnit(GLuint unit, GLuint texture) if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) _mesa_debug(ctx, "glBindTextureUnit %s %d\n", - _mesa_lookup_enum_by_nr(GL_TEXTURE0+unit), (GLint) texture); + _mesa_enum_to_string(GL_TEXTURE0+unit), (GLint) texture); /* Section 8.1 (Texture Objects) of the OpenGL 4.5 core profile spec * (20141030) says: diff --git a/src/mesa/main/texparam.c b/src/mesa/main/texparam.c index d74134f41b1..c0611c3e489 100644 --- a/src/mesa/main/texparam.c +++ b/src/mesa/main/texparam.c @@ -381,7 +381,7 @@ set_tex_parameteri(struct gl_context *ctx, if (texObj->Target == GL_TEXTURE_RECTANGLE_ARB && params[0] != 0) { _mesa_error(ctx, GL_INVALID_OPERATION, "glTex%sParameter(target=%s, param=%d)", suffix, - _mesa_lookup_enum_by_nr(texObj->Target), params[0]); + _mesa_enum_to_string(texObj->Target), params[0]); return GL_FALSE; } incomplete(ctx, texObj); @@ -500,7 +500,9 @@ set_tex_parameteri(struct gl_context *ctx, goto invalid_pname; case GL_DEPTH_STENCIL_TEXTURE_MODE: - if (_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_stencil_texturing) { + if ((_mesa_is_desktop_gl(ctx) && + ctx->Extensions.ARB_stencil_texturing) || + _mesa_is_gles31(ctx)) { bool stencil = params[0] == GL_STENCIL_INDEX; if (!stencil && params[0] != GL_DEPTH_COMPONENT) goto invalid_param; @@ -610,22 +612,22 @@ set_tex_parameteri(struct gl_context *ctx, invalid_pname: _mesa_error(ctx, GL_INVALID_ENUM, "glTex%sParameter(pname=%s)", - suffix, _mesa_lookup_enum_by_nr(pname)); + suffix, _mesa_enum_to_string(pname)); return GL_FALSE; invalid_param: _mesa_error(ctx, GL_INVALID_ENUM, "glTex%sParameter(param=%s)", - suffix, _mesa_lookup_enum_by_nr(params[0])); + suffix, _mesa_enum_to_string(params[0])); return GL_FALSE; invalid_operation: _mesa_error(ctx, GL_INVALID_OPERATION, "glTex%sParameter(pname=%s)", - suffix, _mesa_lookup_enum_by_nr(pname)); + suffix, _mesa_enum_to_string(pname)); return GL_FALSE; invalid_enum: _mesa_error(ctx, GL_INVALID_ENUM, "glTex%sParameter(pname=%s)", - suffix, _mesa_lookup_enum_by_nr(pname)); + suffix, _mesa_enum_to_string(pname)); return GL_FALSE; } @@ -683,7 +685,7 @@ set_tex_parameterf(struct gl_context *ctx, if (texObj->Sampler.MaxAnisotropy == params[0]) return GL_FALSE; - if (params[0] < 1.0) { + if (params[0] < 1.0F) { _mesa_error(ctx, GL_INVALID_VALUE, "glTex%sParameter(param)", suffix); return GL_FALSE; @@ -745,12 +747,12 @@ set_tex_parameterf(struct gl_context *ctx, invalid_pname: _mesa_error(ctx, GL_INVALID_ENUM, "glTex%sParameter(pname=%s)", - suffix, _mesa_lookup_enum_by_nr(pname)); + suffix, _mesa_enum_to_string(pname)); return GL_FALSE; invalid_enum: _mesa_error(ctx, GL_INVALID_ENUM, "glTex%sParameter(pname=%s)", - suffix, _mesa_lookup_enum_by_nr(pname)); + suffix, _mesa_enum_to_string(pname)); return GL_FALSE; } @@ -1395,7 +1397,7 @@ get_tex_level_parameter_image(struct gl_context *ctx, else { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTex%sLevelParameter[if]v(pname=%s)", suffix, - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); } break; case GL_TEXTURE_COMPRESSED: @@ -1444,7 +1446,7 @@ get_tex_level_parameter_image(struct gl_context *ctx, invalid_pname: _mesa_error(ctx, GL_INVALID_ENUM, "glGetTex%sLevelParameter[if]v(pname=%s)", suffix, - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); } @@ -1528,7 +1530,7 @@ get_tex_level_parameter_buffer(struct gl_context *ctx, /* Always illegal for GL_TEXTURE_BUFFER */ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTex%sLevelParameter[if]v(pname=%s)", suffix, - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); break; /* GL_ARB_texture_float */ @@ -1557,7 +1559,7 @@ get_tex_level_parameter_buffer(struct gl_context *ctx, invalid_pname: _mesa_error(ctx, GL_INVALID_ENUM, "glGetTex%sLevelParameter[if]v(pname=%s)", suffix, - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); } @@ -1586,7 +1588,7 @@ get_tex_level_parameteriv(struct gl_context *ctx, if (!legal_get_tex_level_parameter_target(ctx, target, dsa)) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetTex%sLevelParameter[if]v(target=%s)", suffix, - _mesa_lookup_enum_by_nr(target)); + _mesa_enum_to_string(target)); return; } diff --git a/src/mesa/main/texstate.c b/src/mesa/main/texstate.c index 1af9d47f030..9b5928c4306 100644 --- a/src/mesa/main/texstate.c +++ b/src/mesa/main/texstate.c @@ -123,21 +123,21 @@ _mesa_print_texunit_state( struct gl_context *ctx, GLuint unit ) { const struct gl_texture_unit *texUnit = ctx->Texture.Unit + unit; printf("Texture Unit %d\n", unit); - printf(" GL_TEXTURE_ENV_MODE = %s\n", _mesa_lookup_enum_by_nr(texUnit->EnvMode)); - printf(" GL_COMBINE_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.ModeRGB)); - printf(" GL_COMBINE_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.ModeA)); - printf(" GL_SOURCE0_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceRGB[0])); - printf(" GL_SOURCE1_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceRGB[1])); - printf(" GL_SOURCE2_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceRGB[2])); - printf(" GL_SOURCE0_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceA[0])); - printf(" GL_SOURCE1_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceA[1])); - printf(" GL_SOURCE2_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceA[2])); - printf(" GL_OPERAND0_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandRGB[0])); - printf(" GL_OPERAND1_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandRGB[1])); - printf(" GL_OPERAND2_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandRGB[2])); - printf(" GL_OPERAND0_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandA[0])); - printf(" GL_OPERAND1_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandA[1])); - printf(" GL_OPERAND2_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandA[2])); + printf(" GL_TEXTURE_ENV_MODE = %s\n", _mesa_enum_to_string(texUnit->EnvMode)); + printf(" GL_COMBINE_RGB = %s\n", _mesa_enum_to_string(texUnit->Combine.ModeRGB)); + printf(" GL_COMBINE_ALPHA = %s\n", _mesa_enum_to_string(texUnit->Combine.ModeA)); + printf(" GL_SOURCE0_RGB = %s\n", _mesa_enum_to_string(texUnit->Combine.SourceRGB[0])); + printf(" GL_SOURCE1_RGB = %s\n", _mesa_enum_to_string(texUnit->Combine.SourceRGB[1])); + printf(" GL_SOURCE2_RGB = %s\n", _mesa_enum_to_string(texUnit->Combine.SourceRGB[2])); + printf(" GL_SOURCE0_ALPHA = %s\n", _mesa_enum_to_string(texUnit->Combine.SourceA[0])); + printf(" GL_SOURCE1_ALPHA = %s\n", _mesa_enum_to_string(texUnit->Combine.SourceA[1])); + printf(" GL_SOURCE2_ALPHA = %s\n", _mesa_enum_to_string(texUnit->Combine.SourceA[2])); + printf(" GL_OPERAND0_RGB = %s\n", _mesa_enum_to_string(texUnit->Combine.OperandRGB[0])); + printf(" GL_OPERAND1_RGB = %s\n", _mesa_enum_to_string(texUnit->Combine.OperandRGB[1])); + printf(" GL_OPERAND2_RGB = %s\n", _mesa_enum_to_string(texUnit->Combine.OperandRGB[2])); + printf(" GL_OPERAND0_ALPHA = %s\n", _mesa_enum_to_string(texUnit->Combine.OperandA[0])); + printf(" GL_OPERAND1_ALPHA = %s\n", _mesa_enum_to_string(texUnit->Combine.OperandA[1])); + printf(" GL_OPERAND2_ALPHA = %s\n", _mesa_enum_to_string(texUnit->Combine.OperandA[2])); printf(" GL_RGB_SCALE = %d\n", 1 << texUnit->Combine.ScaleShiftRGB); printf(" GL_ALPHA_SCALE = %d\n", 1 << texUnit->Combine.ScaleShiftA); printf(" GL_TEXTURE_ENV_COLOR = (%f, %f, %f, %f)\n", texUnit->EnvColor[0], texUnit->EnvColor[1], texUnit->EnvColor[2], texUnit->EnvColor[3]); @@ -289,23 +289,23 @@ _mesa_ActiveTexture(GLenum texture) GLuint k; GET_CURRENT_CONTEXT(ctx); + if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) + _mesa_debug(ctx, "glActiveTexture %s\n", + _mesa_enum_to_string(texture)); + + if (ctx->Texture.CurrentUnit == texUnit) + return; + k = _mesa_max_tex_unit(ctx); assert(k <= ARRAY_SIZE(ctx->Texture.Unit)); - if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) - _mesa_debug(ctx, "glActiveTexture %s\n", - _mesa_lookup_enum_by_nr(texture)); - if (texUnit >= k) { _mesa_error(ctx, GL_INVALID_ENUM, "glActiveTexture(texture=%s)", - _mesa_lookup_enum_by_nr(texture)); + _mesa_enum_to_string(texture)); return; } - if (ctx->Texture.CurrentUnit == texUnit) - return; - FLUSH_VERTICES(ctx, _NEW_TEXTURE); ctx->Texture.CurrentUnit = texUnit; @@ -325,16 +325,16 @@ _mesa_ClientActiveTexture(GLenum texture) if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE)) _mesa_debug(ctx, "glClientActiveTexture %s\n", - _mesa_lookup_enum_by_nr(texture)); + _mesa_enum_to_string(texture)); + + if (ctx->Array.ActiveTexture == texUnit) + return; if (texUnit >= ctx->Const.MaxTextureCoordUnits) { _mesa_error(ctx, GL_INVALID_ENUM, "glClientActiveTexture(texture)"); return; } - if (ctx->Array.ActiveTexture == texUnit) - return; - FLUSH_VERTICES(ctx, _NEW_ARRAY); ctx->Array.ActiveTexture = texUnit; } diff --git a/src/mesa/main/texstate.h b/src/mesa/main/texstate.h index 662435b47cc..bee8c9c3316 100644 --- a/src/mesa/main/texstate.h +++ b/src/mesa/main/texstate.h @@ -77,7 +77,7 @@ _mesa_get_tex_unit_err(struct gl_context *ctx, GLuint unit, const char *func) * implementation." */ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unit=%s)", func, - _mesa_lookup_enum_by_nr(GL_TEXTURE0+unit)); + _mesa_enum_to_string(GL_TEXTURE0+unit)); return NULL; } diff --git a/src/mesa/main/texstorage.c b/src/mesa/main/texstorage.c index 53cb2c091f8..4a2cc6065df 100644 --- a/src/mesa/main/texstorage.c +++ b/src/mesa/main/texstorage.c @@ -308,7 +308,8 @@ tex_storage_error_check(struct gl_context *ctx, _mesa_error(ctx, _mesa_is_desktop_gl(ctx)? GL_INVALID_ENUM : GL_INVALID_OPERATION, "glTex%sStorage%dD(internalformat = %s)", suffix, dims, - _mesa_lookup_enum_by_nr(internalformat)); + _mesa_enum_to_string(internalformat)); + return GL_TRUE; } /* levels check */ @@ -464,21 +465,21 @@ texstorage(GLuint dims, GLenum target, GLsizei levels, GLenum internalformat, if (!legal_texobj_target(ctx, dims, target)) { _mesa_error(ctx, GL_INVALID_ENUM, "glTexStorage%uD(illegal target=%s)", - dims, _mesa_lookup_enum_by_nr(target)); + dims, _mesa_enum_to_string(target)); return; } if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) _mesa_debug(ctx, "glTexStorage%uD %s %d %s %d %d %d\n", dims, - _mesa_lookup_enum_by_nr(target), levels, - _mesa_lookup_enum_by_nr(internalformat), + _mesa_enum_to_string(target), levels, + _mesa_enum_to_string(internalformat), width, height, depth); /* Check the format to make sure it is sized. */ if (!_mesa_is_legal_tex_storage_format(ctx, internalformat)) { _mesa_error(ctx, GL_INVALID_ENUM, "glTexStorage%uD(internalformat = %s)", dims, - _mesa_lookup_enum_by_nr(internalformat)); + _mesa_enum_to_string(internalformat)); return; } @@ -504,14 +505,14 @@ texturestorage(GLuint dims, GLuint texture, GLsizei levels, if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) _mesa_debug(ctx, "glTextureStorage%uD %d %d %s %d %d %d\n", dims, texture, levels, - _mesa_lookup_enum_by_nr(internalformat), + _mesa_enum_to_string(internalformat), width, height, depth); /* Check the format to make sure it is sized. */ if (!_mesa_is_legal_tex_storage_format(ctx, internalformat)) { _mesa_error(ctx, GL_INVALID_ENUM, "glTextureStorage%uD(internalformat = %s)", dims, - _mesa_lookup_enum_by_nr(internalformat)); + _mesa_enum_to_string(internalformat)); return; } @@ -529,7 +530,7 @@ texturestorage(GLuint dims, GLuint texture, GLsizei levels, if (!legal_texobj_target(ctx, dims, texObj->Target)) { _mesa_error(ctx, GL_INVALID_ENUM, "glTextureStorage%uD(illegal target=%s)", - dims, _mesa_lookup_enum_by_nr(texObj->Target)); + dims, _mesa_enum_to_string(texObj->Target)); return; } diff --git a/src/mesa/main/texstore.c b/src/mesa/main/texstore.c index 1525205981b..37c05690091 100644 --- a/src/mesa/main/texstore.c +++ b/src/mesa/main/texstore.c @@ -787,6 +787,7 @@ texstore_rgba(TEXSTORE_PARAMS) srcType = GL_FLOAT; srcRowStride = srcWidth * 4 * sizeof(float); srcMesaFormat = RGBA32_FLOAT; + srcPacking = &ctx->DefaultPacking; } src = (GLubyte *) diff --git a/src/mesa/main/textureview.c b/src/mesa/main/textureview.c index 6b0aed4ea1a..5a3282a40c1 100644 --- a/src/mesa/main/textureview.c +++ b/src/mesa/main/textureview.c @@ -313,7 +313,7 @@ target_valid(struct gl_context *ctx, GLenum origTarget, GLenum newTarget) } _mesa_error(ctx, GL_INVALID_OPERATION, "glTextureView(illegal target=%s)", - _mesa_lookup_enum_by_nr(newTarget)); + _mesa_enum_to_string(newTarget)); return false; } #undef RETURN_IF_SUPPORTED @@ -435,8 +435,8 @@ _mesa_TextureView(GLuint texture, GLenum target, GLuint origtexture, if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE)) _mesa_debug(ctx, "glTextureView %d %s %d %s %d %d %d %d\n", - texture, _mesa_lookup_enum_by_nr(target), origtexture, - _mesa_lookup_enum_by_nr(internalformat), + texture, _mesa_enum_to_string(target), origtexture, + _mesa_enum_to_string(internalformat), minlevel, numlevels, minlayer, numlayers); if (origtexture == 0) { @@ -523,8 +523,8 @@ _mesa_TextureView(GLuint texture, GLenum target, GLuint origtexture, 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)); + _mesa_enum_to_string(internalformat), + _mesa_enum_to_string(origTexObj->Image[0][0]->InternalFormat)); return; } diff --git a/src/mesa/main/uniform_query.cpp b/src/mesa/main/uniform_query.cpp index cab5083e81b..036530e91b6 100644 --- a/src/mesa/main/uniform_query.cpp +++ b/src/mesa/main/uniform_query.cpp @@ -978,81 +978,6 @@ _mesa_uniform_matrix(struct gl_context *ctx, struct gl_shader_program *shProg, } -/** - * Called via glGetUniformLocation(). - * - * Returns the uniform index into UniformStorage (also the - * glGetActiveUniformsiv uniform index), and stores the referenced - * array offset in *offset, or GL_INVALID_INDEX (-1). - */ -extern "C" unsigned -_mesa_get_uniform_location(struct gl_shader_program *shProg, - const GLchar *name, - unsigned *out_offset) -{ - /* Page 80 (page 94 of the PDF) of the OpenGL 2.1 spec says: - * - * "The first element of a uniform array is identified using the - * name of the uniform array appended with "[0]". Except if the last - * part of the string name indicates a uniform array, then the - * location of the first element of that array can be retrieved by - * either using the name of the uniform array, or the name of the - * uniform array appended with "[0]"." - * - * Note: since uniform names are not allowed to use whitespace, and array - * indices within uniform names are not allowed to use "+", "-", or leading - * zeros, it follows that each uniform has a unique name up to the possible - * ambiguity with "[0]" noted above. Therefore we don't need to worry - * about mal-formed inputs--they will properly fail when we try to look up - * the uniform name in shProg->UniformHash. - */ - - const GLchar *base_name_end; - long offset = parse_program_resource_name(name, &base_name_end); - bool array_lookup = offset >= 0; - char *name_copy; - - if (array_lookup) { - name_copy = (char *) malloc(base_name_end - name + 1); - memcpy(name_copy, name, base_name_end - name); - name_copy[base_name_end - name] = '\0'; - } else { - name_copy = (char *) name; - offset = 0; - } - - unsigned location = 0; - const bool found = shProg->UniformHash->get(location, name_copy); - - assert(!found - || strcmp(name_copy, shProg->UniformStorage[location].name) == 0); - - /* Free the temporary buffer *before* possibly returning an error. - */ - if (name_copy != name) - free(name_copy); - - 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 - * array_elements is zero and offset >= 0. - */ - if (array_lookup - && offset >= (long) shProg->UniformStorage[location].array_elements) { - return GL_INVALID_INDEX; - } - - *out_offset = offset; - return location; -} - extern "C" bool _mesa_sampler_uniforms_are_valid(const struct gl_shader_program *shProg, char *errMsg, size_t errMsgLength) @@ -1101,18 +1026,23 @@ _mesa_sampler_uniforms_pipeline_are_valid(struct gl_pipeline_object *pipeline) 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()) - ? storage->type->fields.array : storage->type; - if (!t->is_sampler()) + if (!storage->type->is_sampler()) continue; active_samplers++; - const unsigned count = MAX2(1, storage->type->array_size()); + const unsigned count = MAX2(1, storage->array_elements); for (unsigned j = 0; j < count; j++) { const unsigned unit = storage->storage[j].i; + /* FIXME: Samplers are initialized to 0 and Mesa doesn't do a + * great job of eliminating unused uniforms currently so for now + * don't throw an error if two sampler types both point to 0. + */ + if (unit == 0) + continue; + /* The types of the samplers associated with a particular texture * unit must be an exact match. Page 74 (page 89 of the PDF) of * the OpenGL 3.3 core spec says: @@ -1122,13 +1052,14 @@ _mesa_sampler_uniforms_pipeline_are_valid(struct gl_pipeline_object *pipeline) * program object." */ if (unit_types[unit] == NULL) { - unit_types[unit] = t; - } else if (unit_types[unit] != t) { + unit_types[unit] = storage->type; + } else if (unit_types[unit] != storage->type) { pipeline->InfoLog = ralloc_asprintf(pipeline, "Texture unit %d is accessed both as %s " "and %s", - unit, unit_types[unit]->name, t->name); + unit, unit_types[unit]->name, + storage->type->name); return false; } } diff --git a/src/mesa/main/uniforms.c b/src/mesa/main/uniforms.c index 5548d1d026f..ff1df72e1d6 100644 --- a/src/mesa/main/uniforms.c +++ b/src/mesa/main/uniforms.c @@ -952,7 +952,7 @@ _mesa_GetUniformBlockIndex(GLuint program, struct gl_program_resource *res = _mesa_program_resource_find_name(shProg, GL_UNIFORM_BLOCK, - uniformBlockName); + uniformBlockName, NULL); if (!res) return GL_INVALID_INDEX; @@ -987,7 +987,8 @@ _mesa_GetUniformIndices(GLuint program, for (i = 0; i < uniformCount; i++) { struct gl_program_resource *res = - _mesa_program_resource_find_name(shProg, GL_UNIFORM, uniformNames[i]); + _mesa_program_resource_find_name(shProg, GL_UNIFORM, uniformNames[i], + NULL); uniformIndices[i] = _mesa_program_resource_index(shProg, res); } } @@ -1092,6 +1093,21 @@ mesa_bufferiv(struct gl_shader_program *shProg, GLenum type, GL_REFERENCED_BY_VERTEX_SHADER, params, caller); return; + + case GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_CONTROL_SHADER: + case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER: + _mesa_program_resource_prop(shProg, res, index, + GL_REFERENCED_BY_TESS_CONTROL_SHADER, params, + caller); + return; + + case GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_EVALUATION_SHADER: + case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER: + _mesa_program_resource_prop(shProg, res, index, + GL_REFERENCED_BY_TESS_EVALUATION_SHADER, params, + caller); + return; + case GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER: case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER: _mesa_program_resource_prop(shProg, res, index, @@ -1104,16 +1120,10 @@ mesa_bufferiv(struct gl_shader_program *shProg, GLenum type, GL_REFERENCED_BY_FRAGMENT_SHADER, params, caller); return; - case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER: - params[0] = GL_FALSE; - return; - case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER: - params[0] = GL_FALSE; - return; default: _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname 0x%x (%s))", caller, pname, - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); return; } } diff --git a/src/mesa/main/uniforms.h b/src/mesa/main/uniforms.h index bd7b05e207a..e62eaa53ccc 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); -unsigned -_mesa_get_uniform_location(struct gl_shader_program *shProg, - const GLchar *name, unsigned *offset); - void _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shader_program, GLint location, GLsizei count, diff --git a/src/mesa/main/varray.c b/src/mesa/main/varray.c index ebdd9eaf02e..3bab9850588 100644 --- a/src/mesa/main/varray.c +++ b/src/mesa/main/varray.c @@ -300,7 +300,7 @@ update_array_format(struct gl_context *ctx, typeBit = type_to_bit(ctx, type); if (typeBit == 0x0 || (typeBit & legalTypesMask) == 0x0) { _mesa_error(ctx, GL_INVALID_ENUM, "%s(type = %s)", - func, _mesa_lookup_enum_by_nr(type)); + func, _mesa_enum_to_string(type)); return false; } @@ -333,7 +333,7 @@ update_array_format(struct gl_context *ctx, if (bgra_error) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(size=GL_BGRA and type=%s)", - func, _mesa_lookup_enum_by_nr(type)); + func, _mesa_enum_to_string(type)); return false; } @@ -2310,7 +2310,7 @@ print_array(const char *name, GLint index, const struct gl_client_array *array) else fprintf(stderr, " %s: ", name); 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->Ptr, _mesa_enum_to_string(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 8bc00ace5c4..fd7ae53ccbd 100644 --- a/src/mesa/main/version.c +++ b/src/mesa/main/version.c @@ -309,7 +309,7 @@ compute_version(const struct gl_extensions *extensions, extensions->ARB_gpu_shader5 && extensions->ARB_gpu_shader_fp64 && extensions->ARB_sample_shading && - false /*extensions->ARB_shader_subroutine*/ && + extensions->ARB_shader_subroutine && extensions->ARB_tessellation_shader && extensions->ARB_texture_buffer_object_rgb32 && extensions->ARB_texture_cube_map_array && diff --git a/src/mesa/main/viewport.c b/src/mesa/main/viewport.c index b27063031c4..7d8914291c3 100644 --- a/src/mesa/main/viewport.c +++ b/src/mesa/main/viewport.c @@ -391,8 +391,8 @@ _mesa_ClipControl(GLenum origin, GLenum depth) if (MESA_VERBOSE&VERBOSE_API) _mesa_debug(ctx, "glClipControl(%s, %s)\n", - _mesa_lookup_enum_by_nr(origin), - _mesa_lookup_enum_by_nr(depth)); + _mesa_enum_to_string(origin), + _mesa_enum_to_string(depth)); ASSERT_OUTSIDE_BEGIN_END(ctx); @@ -443,12 +443,12 @@ _mesa_ClipControl(GLenum origin, GLenum depth) */ void _mesa_get_viewport_xform(struct gl_context *ctx, unsigned i, - double scale[3], double translate[3]) + float scale[3], float translate[3]) { - double x = ctx->ViewportArray[i].X; - double y = ctx->ViewportArray[i].Y; - double half_width = 0.5*ctx->ViewportArray[i].Width; - double half_height = 0.5*ctx->ViewportArray[i].Height; + float x = ctx->ViewportArray[i].X; + float y = ctx->ViewportArray[i].Y; + float half_width = 0.5f * ctx->ViewportArray[i].Width; + float half_height = 0.5f * ctx->ViewportArray[i].Height; double n = ctx->ViewportArray[i].Near; double f = ctx->ViewportArray[i].Far; @@ -462,8 +462,8 @@ _mesa_get_viewport_xform(struct gl_context *ctx, unsigned i, translate[1] = half_height + y; } if (ctx->Transform.ClipDepthMode == GL_NEGATIVE_ONE_TO_ONE) { - scale[2] = 0.5*(f - n); - translate[2] = 0.5*(n + f); + scale[2] = 0.5 * (f - n); + translate[2] = 0.5 * (n + f); } else { scale[2] = f - n; translate[2] = n; diff --git a/src/mesa/main/viewport.h b/src/mesa/main/viewport.h index 899dc2d0bcc..b0675db1096 100644 --- a/src/mesa/main/viewport.h +++ b/src/mesa/main/viewport.h @@ -73,6 +73,6 @@ _mesa_ClipControl(GLenum origin, GLenum depth); extern void _mesa_get_viewport_xform(struct gl_context *ctx, unsigned i, - double scale[3], double translate[3]); + float scale[3], float translate[3]); #endif |