* are generated by the GLSL compiler.
*/
struct gl_shader_compiler_options options;
- gl_shader_type sh;
+ gl_shader_stage sh;
memset(&options, 0, sizeof(options));
options.MaxUnrollIterations = 32;
/* Default pragma settings */
options.DefaultPragmas.Optimize = GL_TRUE;
- for (sh = 0; sh < MESA_SHADER_TYPES; ++sh)
+ for (sh = 0; sh < MESA_SHADER_STAGES; ++sh)
memcpy(&ctx->ShaderCompilerOptions[sh], &options, sizeof(options));
ctx->Shader.Flags = get_shader_flags();
void
_mesa_free_shader_state(struct gl_context *ctx)
{
- _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentVertexProgram, NULL);
- _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentGeometryProgram,
- NULL);
- _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentFragmentProgram,
- NULL);
+ int i;
+ for (i = 0; i < MESA_SHADER_STAGES; i++) {
+ _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram[i],
+ NULL);
+ }
_mesa_reference_shader_program(ctx, &ctx->Shader._CurrentFragmentProgram,
NULL);
_mesa_reference_shader_program(ctx, &ctx->Shader.ActiveProgram, NULL);
* \param type Shader target
*
*/
-static bool
-validate_shader_target(const struct gl_context *ctx, GLenum type)
-{
+bool
+_mesa_validate_shader_target(const struct gl_context *ctx, GLenum type)
+{
+ /* Note: when building built-in GLSL functions, this function may be
+ * invoked with ctx == NULL. In that case, we can only validate that it's
+ * a shader target we recognize, not that it's supported in the current
+ * context. But that's fine--we don't need any further validation than
+ * that when building built-in GLSL functions.
+ */
+
switch (type) {
case GL_FRAGMENT_SHADER:
- return ctx->Extensions.ARB_fragment_shader;
+ return ctx == NULL || ctx->Extensions.ARB_fragment_shader;
case GL_VERTEX_SHADER:
- return ctx->Extensions.ARB_vertex_shader;
+ return ctx == NULL || ctx->Extensions.ARB_vertex_shader;
case GL_GEOMETRY_SHADER_ARB:
- return _mesa_has_geometry_shaders(ctx);
+ return ctx == NULL || _mesa_has_geometry_shaders(ctx);
+ case GL_COMPUTE_SHADER:
+ return ctx == NULL || ctx->Extensions.ARB_compute_shader;
default:
return false;
}
struct gl_shader *sh;
GLuint name;
- if (!validate_shader_target(ctx, type)) {
+ if (!_mesa_validate_shader_target(ctx, type)) {
_mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(type)");
return 0;
}
_mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
/* alloc new, smaller array */
- newList =
- malloc((n - 1) * sizeof(struct gl_shader *));
+ newList = malloc((n - 1) * sizeof(struct gl_shader *));
if (!newList) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader");
return;
}
+ /* Copy old list entries to new list, skipping removed entry at [i] */
for (j = 0; j < i; j++) {
newList[j] = shProg->Shaders[j];
}
- while (++i < n)
+ while (++i < n) {
newList[j++] = shProg->Shaders[i];
- free(shProg->Shaders);
+ }
+ /* Free old list and install new one */
+ free(shProg->Shaders);
shProg->Shaders = newList;
shProg->NumShaders = n - 1;
#ifdef DEBUG
- /* sanity check */
- {
- for (j = 0; j < shProg->NumShaders; j++) {
- assert(shProg->Shaders[j]->Type == GL_VERTEX_SHADER ||
- shProg->Shaders[j]->Type == GL_FRAGMENT_SHADER);
- assert(shProg->Shaders[j]->RefCount > 0);
- }
+ /* 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_GEOMETRY_SHADER ||
+ shProg->Shaders[j]->Type == GL_FRAGMENT_SHADER);
+ assert(shProg->Shaders[j]->RefCount > 0);
}
#endif
err = GL_INVALID_OPERATION;
else
err = GL_INVALID_VALUE;
- _mesa_error(ctx, err, "glDetachProgram(shader)");
+ _mesa_error(ctx, err, "glDetachShader(shader)");
return;
}
}
}
+/**
+ * Check if a geometry shader query is valid at this time. If not, report an
+ * error and return false.
+ *
+ * From GL 3.2 section 6.1.16 (Shader and Program Queries):
+ *
+ * "If GEOMETRY_VERTICES_OUT, GEOMETRY_INPUT_TYPE, or GEOMETRY_OUTPUT_TYPE
+ * are queried for a program which has not been linked successfully, or
+ * which does not contain objects to form a geometry shader, then an
+ * INVALID_OPERATION error is generated."
+ */
+static bool
+check_gs_query(struct gl_context *ctx, const struct gl_shader_program *shProg)
+{
+ if (shProg->LinkStatus &&
+ shProg->_LinkedShaders[MESA_SHADER_GEOMETRY] != NULL) {
+ return true;
+ }
+
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetProgramv(linked geometry shader required)");
+ return false;
+}
+
+
/**
* glGetProgramiv() - get shader program state.
* Note that this is for GLSL shader programs, not ARB vertex/fragment
|| ctx->API == API_OPENGL_CORE
|| _mesa_is_gles3(ctx);
- /* Are geometry shaders available in this context?
+ /* True if geometry shaders (of the form that was adopted into GLSL 1.50
+ * and GL 3.2) are available in this context
*/
- const bool has_gs = _mesa_has_geometry_shaders(ctx);
+ const bool has_core_gs = _mesa_is_desktop_gl(ctx) && ctx->Version >= 32;
/* Are uniform buffer objects available in this context?
*/
break;
*params = shProg->TransformFeedback.BufferMode;
return;
- case GL_GEOMETRY_VERTICES_OUT_ARB:
- if (!has_gs)
+ case GL_GEOMETRY_VERTICES_OUT:
+ if (!has_core_gs)
+ break;
+ if (check_gs_query(ctx, shProg))
+ *params = shProg->Geom.VerticesOut;
+ return;
+ case GL_GEOMETRY_SHADER_INVOCATIONS:
+ if (!has_core_gs || !ctx->Extensions.ARB_gpu_shader5)
break;
- *params = shProg->Geom.VerticesOut;
+ if (check_gs_query(ctx, shProg))
+ *params = shProg->Geom.Invocations;
return;
- case GL_GEOMETRY_INPUT_TYPE_ARB:
- if (!has_gs)
+ case GL_GEOMETRY_INPUT_TYPE:
+ if (!has_core_gs)
break;
- *params = shProg->Geom.InputType;
+ if (check_gs_query(ctx, shProg))
+ *params = shProg->Geom.InputType;
return;
- case GL_GEOMETRY_OUTPUT_TYPE_ARB:
- if (!has_gs)
+ case GL_GEOMETRY_OUTPUT_TYPE:
+ if (!has_core_gs)
break;
- *params = shProg->Geom.OutputType;
+ if (check_gs_query(ctx, shProg))
+ *params = shProg->Geom.OutputType;
return;
case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH: {
unsigned i;
case GL_PROGRAM_BINARY_LENGTH:
*params = 0;
return;
+ case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
+ if (!ctx->Extensions.ARB_shader_atomic_counters)
+ break;
+
+ *params = shProg->NumAtomicBuffers;
+ return;
+ case GL_COMPUTE_WORK_GROUP_SIZE: {
+ int i;
+ if (!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_compute_shader)
+ break;
+ if (!shProg->LinkStatus) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramiv(program not "
+ "linked)");
+ return;
+ }
+ if (shProg->_LinkedShaders[MESA_SHADER_COMPUTE] == NULL) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramiv(no compute "
+ "shaders)");
+ return;
+ }
+ for (i = 0; i < 3; i++)
+ params[i] = shProg->Comp.LocalSize[i];
+ return;
+ }
default:
break;
}
if (!sh)
return;
- /* Geometry shaders are not yet fully supported, so issue a warning message
- * if we're compiling one.
- */
- if (sh->Type == GL_GEOMETRY_SHADER)
- printf("WARNING: Geometry shader support is currently experimental.\n");
-
- options = &ctx->ShaderCompilerOptions[_mesa_shader_type_to_index(sh->Type)];
+ options = &ctx->ShaderCompilerOptions[sh->Stage];
/* set default pragma state for shader */
sh->Pragmas = options->DefaultPragmas;
} else {
if (ctx->Shader.Flags & GLSL_DUMP) {
printf("GLSL source for %s shader %d:\n",
- _mesa_glsl_shader_target_name(sh->Type), sh->Name);
+ _mesa_shader_stage_to_string(sh->Stage), sh->Name);
printf("%s\n", sh->Source);
}
if (!sh->CompileStatus) {
if (ctx->Shader.Flags & GLSL_DUMP_ON_ERROR) {
fprintf(stderr, "GLSL source for %s shader %d:\n",
- _mesa_glsl_shader_target_name(sh->Type), sh->Name);
+ _mesa_shader_stage_to_string(sh->Stage), sh->Name);
fprintf(stderr, "%s\n", sh->Source);
+ fprintf(stderr, "Info Log:\n%s\n", sh->InfoLog);
+ fflush(stderr);
}
if (ctx->Shader.Flags & GLSL_REPORT_ERRORS) {
printf("Mesa: glUseProgram(%u)\n", shProg->Name);
for (i = 0; i < shProg->NumShaders; i++) {
printf(" %s shader %u, checksum %u\n",
- _mesa_glsl_shader_target_name(shProg->Shaders[i]->Type),
+ _mesa_shader_stage_to_string(shProg->Shaders[i]->Stage),
shProg->Shaders[i]->Name,
shProg->Shaders[i]->SourceChecksum);
}
/**
*/
-static bool
+static void
use_shader_program(struct gl_context *ctx, GLenum type,
struct gl_shader_program *shProg)
{
struct gl_shader_program **target;
+ gl_shader_stage stage = _mesa_shader_enum_to_shader_stage(type);
- switch (type) {
- case GL_VERTEX_SHADER:
- target = &ctx->Shader.CurrentVertexProgram;
- if ((shProg == NULL)
- || (shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL)) {
- shProg = NULL;
- }
- break;
- case GL_GEOMETRY_SHADER_ARB:
- target = &ctx->Shader.CurrentGeometryProgram;
- if ((shProg == NULL)
- || (shProg->_LinkedShaders[MESA_SHADER_GEOMETRY] == NULL)) {
- shProg = NULL;
- }
- break;
- case GL_FRAGMENT_SHADER:
- target = &ctx->Shader.CurrentFragmentProgram;
- if ((shProg == NULL)
- || (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL)) {
- shProg = NULL;
- }
- break;
- default:
- return false;
- }
+ target = &ctx->Shader.CurrentProgram[stage];
+ if ((shProg == NULL) || (shProg->_LinkedShaders[stage] == NULL))
+ shProg = NULL;
if (*target != shProg) {
FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
case GL_GEOMETRY_SHADER_ARB:
/* Empty for now. */
break;
+ case GL_COMPUTE_SHADER:
+ /* Empty for now. */
+ break;
case GL_FRAGMENT_SHADER:
if (*target == ctx->Shader._CurrentFragmentProgram) {
_mesa_reference_shader_program(ctx,
}
_mesa_reference_shader_program(ctx, target, shProg);
- return true;
+ return;
}
-
- return false;
}
/**
use_shader_program(ctx, GL_VERTEX_SHADER, shProg);
use_shader_program(ctx, GL_GEOMETRY_SHADER_ARB, shProg);
use_shader_program(ctx, GL_FRAGMENT_SHADER, shProg);
+ use_shader_program(ctx, GL_COMPUTE_SHADER, shProg);
_mesa_active_program(ctx, shProg, "glUseProgram");
if (ctx->Driver.UseProgram)
switch (shadertype) {
case GL_VERTEX_SHADER:
- limits = &ctx->Const.VertexProgram;
+ limits = &ctx->Const.Program[MESA_SHADER_VERTEX];
break;
case GL_FRAGMENT_SHADER:
- limits = &ctx->Const.FragmentProgram;
+ limits = &ctx->Const.Program[MESA_SHADER_FRAGMENT];
break;
default:
_mesa_error(ctx, GL_INVALID_ENUM,
return;
switch (pname) {
- case GL_GEOMETRY_VERTICES_OUT_ARB:
- if (!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_geometry_shader4)
- break;
-
- if (value < 0 ||
- (unsigned) value > ctx->Const.MaxGeometryOutputVertices) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glProgramParameteri(GL_GEOMETRY_VERTICES_OUT_ARB=%d)",
- value);
- return;
- }
- shProg->Geom.VerticesOut = value;
- return;
- case GL_GEOMETRY_INPUT_TYPE_ARB:
- if (!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_geometry_shader4)
- break;
-
- switch (value) {
- case GL_POINTS:
- case GL_LINES:
- case GL_LINES_ADJACENCY_ARB:
- case GL_TRIANGLES:
- case GL_TRIANGLES_ADJACENCY_ARB:
- shProg->Geom.InputType = value;
- break;
- default:
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glProgramParameteri(geometry input type = %s)",
- _mesa_lookup_enum_by_nr(value));
- return;
- }
- return;
- case GL_GEOMETRY_OUTPUT_TYPE_ARB:
- if (!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_geometry_shader4)
- break;
-
- switch (value) {
- case GL_POINTS:
- case GL_LINE_STRIP:
- case GL_TRIANGLE_STRIP:
- shProg->Geom.OutputType = value;
- break;
- default:
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glProgramParameteri(geometry output type = %s)",
- _mesa_lookup_enum_by_nr(value));
- return;
- }
- return;
case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
/* This enum isn't part of the OES extension for OpenGL ES 2.0, but it
* is part of OpenGL ES 3.0. For the ES2 case, this function shouldn't
GET_CURRENT_CONTEXT(ctx);
struct gl_shader_program *shProg = NULL;
- if (!validate_shader_target(ctx, type)) {
+ if (!_mesa_validate_shader_target(ctx, type)) {
_mesa_error(ctx, GL_INVALID_ENUM, "glUseShaderProgramEXT(type)");
return;
}
* object to a specific gl_program object.
*/
void
-_mesa_copy_linked_program_data(gl_shader_type type,
+_mesa_copy_linked_program_data(gl_shader_stage type,
const struct gl_shader_program *src,
struct gl_program *dst)
{
switch (type) {
- case MESA_SHADER_VERTEX: {
- struct gl_vertex_program *dst_vp = (struct gl_vertex_program *) dst;
- dst_vp->UsesClipDistance = src->Vert.UsesClipDistance;
- }
+ case MESA_SHADER_VERTEX:
+ dst->UsesClipDistanceOut = src->Vert.UsesClipDistance;
break;
case MESA_SHADER_GEOMETRY: {
struct gl_geometry_program *dst_gp = (struct gl_geometry_program *) dst;
dst_gp->VerticesIn = src->Geom.VerticesIn;
dst_gp->VerticesOut = src->Geom.VerticesOut;
+ dst_gp->Invocations = src->Geom.Invocations;
dst_gp->InputType = src->Geom.InputType;
dst_gp->OutputType = src->Geom.OutputType;
- dst_gp->UsesClipDistance = src->Geom.UsesClipDistance;
+ dst->UsesClipDistanceOut = src->Geom.UsesClipDistance;
dst_gp->UsesEndPrimitive = src->Geom.UsesEndPrimitive;
}
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;
}