#include "main/mtypes.h"
#include "main/shaderapi.h"
#include "main/shaderobj.h"
+#include "main/transformfeedback.h"
#include "main/uniforms.h"
#include "program/program.h"
#include "program/prog_parameter.h"
memset(&options, 0, sizeof(options));
options.MaxUnrollIterations = 32;
+ options.MaxIfDepth = UINT_MAX;
/* Default pragma settings */
options.DefaultPragmas.Optimize = GL_TRUE;
}
-/**
- * Find the length of the longest transform feedback varying name
- * which was specified with glTransformFeedbackVaryings().
- */
-static GLint
-longest_feedback_varying_name(const struct gl_shader_program *shProg)
-{
- GLuint i;
- GLint max = 0;
- for (i = 0; i < shProg->TransformFeedback.NumVarying; i++) {
- GLint len = strlen(shProg->TransformFeedback.VaryingNames[i]);
- if (len > max)
- max = len;
- }
- return max;
-}
-
-
-
static GLboolean
is_program(struct gl_context *ctx, GLuint name)
{
struct gl_shader *sh;
GLuint i, n;
+ const bool same_type_disallowed = _mesa_is_gles(ctx);
+
shProg = _mesa_lookup_shader_program_err(ctx, program, "glAttachShader");
if (!shProg)
return;
*/
_mesa_error(ctx, GL_INVALID_OPERATION, "glAttachShader");
return;
+ } else if (same_type_disallowed &&
+ shProg->Shaders[i]->Type == sh->Type) {
+ /* Shader with the same type is already attached to this program,
+ * OpenGL ES 2.0 and 3.0 specs say:
+ *
+ * "Multiple shader objects of the same type may not be attached
+ * to a single program object. [...] The error INVALID_OPERATION
+ * is generated if [...] another shader object of the same type
+ * as shader is already attached to program."
+ */
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glAttachShader");
+ return;
}
}
/* Is transform feedback available in this context?
*/
const bool has_xfb =
- (ctx->API == API_OPENGL && ctx->Extensions.EXT_transform_feedback)
+ (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.EXT_transform_feedback)
|| ctx->API == API_OPENGL_CORE
|| _mesa_is_gles3(ctx);
/* Are uniform buffer objects available in this context?
*/
const bool has_ubo =
- (ctx->API == API_OPENGL && ctx->Extensions.ARB_uniform_buffer_object)
+ (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ARB_uniform_buffer_object)
|| ctx->API == API_OPENGL_CORE
|| _mesa_is_gles3(ctx);
break;
*params = shProg->TransformFeedback.NumVarying;
return;
- case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
+ case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH: {
+ unsigned i;
+ GLint max_len = 0;
if (!has_xfb)
break;
- *params = longest_feedback_varying_name(shProg) + 1;
+
+ for (i = 0; i < shProg->TransformFeedback.NumVarying; i++) {
+ /* Add one for the terminating NUL character.
+ */
+ const GLint len = strlen(shProg->TransformFeedback.VaryingNames[i]) + 1;
+
+ if (len > max_len)
+ max_len = len;
+ }
+
+ *params = max_len;
return;
+ }
case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
if (!has_xfb)
break;
*params = shProg->NumUniformBlocks;
return;
+ case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
+ /* This enum isn't part of the OES extension for OpenGL ES 2.0. It is
+ * only available with desktop OpenGL 3.0+ with the
+ * GL_ARB_get_program_binary extension or OpenGL ES 3.0.
+ *
+ * On desktop, we ignore the 3.0+ requirement because it is silly.
+ */
+ if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
+ break;
+
+ *params = shProg->BinaryRetreivableHint;
+ return;
+ case GL_PROGRAM_BINARY_LENGTH:
+ *params = 0;
+ return;
default:
break;
}
void GLAPIENTRY
-_mesa_CompileShaderARB(GLhandleARB shaderObj)
+_mesa_CompileShader(GLhandleARB shaderObj)
{
GET_CURRENT_CONTEXT(ctx);
if (MESA_VERBOSE & VERBOSE_API)
void GLAPIENTRY
-_mesa_GetShaderSourceARB(GLhandleARB shader, GLsizei maxLength,
+_mesa_GetShaderSource(GLhandleARB shader, GLsizei maxLength,
GLsizei *length, GLcharARB *sourceOut)
{
GET_CURRENT_CONTEXT(ctx);
void GLAPIENTRY
-_mesa_LinkProgramARB(GLhandleARB programObj)
+_mesa_LinkProgram(GLhandleARB programObj)
{
GET_CURRENT_CONTEXT(ctx);
link_program(ctx, programObj);
* and pass it to _mesa_shader_source().
*/
void GLAPIENTRY
-_mesa_ShaderSourceARB(GLhandleARB shaderObj, GLsizei count,
- const GLcharARB ** string, const GLint * length)
+_mesa_ShaderSource(GLhandleARB shaderObj, GLsizei count,
+ const GLcharARB * const * string, const GLint * length)
{
GET_CURRENT_CONTEXT(ctx);
GLint *offsets;
void GLAPIENTRY
-_mesa_UseProgramObjectARB(GLhandleARB program)
+_mesa_UseProgram(GLhandleARB program)
{
GET_CURRENT_CONTEXT(ctx);
struct gl_shader_program *shProg;
- struct gl_transform_feedback_object *obj =
- ctx->TransformFeedback.CurrentObject;
-
- ASSERT_OUTSIDE_BEGIN_END(ctx);
- if (obj->Active && !obj->Paused) {
+ if (_mesa_is_xfb_active_and_unpaused(ctx)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glUseProgram(transform feedback active)");
return;
void GLAPIENTRY
-_mesa_ValidateProgramARB(GLhandleARB program)
+_mesa_ValidateProgram(GLhandleARB program)
{
GET_CURRENT_CONTEXT(ctx);
validate_program(ctx, program);
#endif /* FEATURE_ES2 */
+void GLAPIENTRY
+_mesa_GetProgramBinary(GLuint program, GLsizei bufSize, GLsizei *length,
+ GLenum *binaryFormat, GLvoid *binary)
+{
+ struct gl_shader_program *shProg;
+ GET_CURRENT_CONTEXT(ctx);
+
+ shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetProgramBinary");
+ if (!shProg)
+ return;
+
+ if (!shProg->LinkStatus) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetProgramBinary(program %u not linked)",
+ shProg->Name);
+ return;
+ }
+
+ if (bufSize < 0){
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramBinary(bufSize < 0)");
+ return;
+ }
+
+ /* The ARB_get_program_binary spec says:
+ *
+ * "If <length> is NULL, then no length is returned."
+ */
+ if (length != NULL)
+ *length = 0;
+
+ (void) binaryFormat;
+ (void) binary;
+}
void GLAPIENTRY
-_mesa_ProgramParameteriARB(GLuint program, GLenum pname, GLint value)
+_mesa_ProgramBinary(GLuint program, GLenum binaryFormat,
+ const GLvoid *binary, GLsizei length)
{
struct gl_shader_program *shProg;
GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
+ shProg = _mesa_lookup_shader_program_err(ctx, program, "glProgramBinary");
+ if (!shProg)
+ return;
+
+ (void) binaryFormat;
+ (void) binary;
+ (void) length;
+ _mesa_error(ctx, GL_INVALID_OPERATION, __FUNCTION__);
+}
+
+
+void GLAPIENTRY
+_mesa_ProgramParameteri(GLuint program, GLenum pname, GLint value)
+{
+ struct gl_shader_program *shProg;
+ GET_CURRENT_CONTEXT(ctx);
shProg = _mesa_lookup_shader_program_err(ctx, program,
"glProgramParameteri");
switch (pname) {
case GL_GEOMETRY_VERTICES_OUT_ARB:
+ if (!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_geometry_shader4)
+ break;
+
if (value < 1 ||
(unsigned) value > ctx->Const.MaxGeometryOutputVertices) {
_mesa_error(ctx, GL_INVALID_VALUE,
return;
}
shProg->Geom.VerticesOut = value;
- break;
+ 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:
_mesa_lookup_enum_by_nr(value));
return;
}
- break;
+ 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:
_mesa_lookup_enum_by_nr(value));
return;
}
- break;
+ 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
+ * even be in the dispatch table, so we shouldn't need to expclicitly
+ * check here.
+ *
+ * On desktop, we ignore the 3.0+ requirement because it is silly.
+ */
+
+ /* The ARB_get_program_binary extension spec says:
+ *
+ * "An INVALID_VALUE error is generated if the <value> argument to
+ * ProgramParameteri is not TRUE or FALSE."
+ */
+ if (value != GL_TRUE && value != GL_FALSE) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glProgramParameteri(pname=%s, value=%d): "
+ "value must be 0 or 1.",
+ _mesa_lookup_enum_by_nr(pname),
+ value);
+ return;
+ }
+
+ /* No need to notify the driver. Any changes will actually take effect
+ * the next time the shader is linked.
+ *
+ * The ARB_get_program_binary extension spec says:
+ *
+ * "To indicate that a program binary is likely to be retrieved,
+ * ProgramParameteri should be called with <pname>
+ * PROGRAM_BINARY_RETRIEVABLE_HINT and <value> TRUE. This setting
+ * will not be in effect until the next time LinkProgram or
+ * ProgramBinary has been called successfully."
+ *
+ * The resloution of issue 9 in the extension spec also says:
+ *
+ * "The application may use the PROGRAM_BINARY_RETRIEVABLE_HINT hint
+ * to indicate to the GL implementation that this program will
+ * likely be saved with GetProgramBinary at some point. This will
+ * give the GL implementation the opportunity to track any state
+ * changes made to the program before being saved such that when it
+ * is loaded again a recompile can be avoided."
+ */
+ shProg->BinaryRetreivableHint = value;
+ return;
default:
- _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameteriARB(pname=%s)",
- _mesa_lookup_enum_by_nr(pname));
break;
}
+
+ _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameteri(pname=%s)",
+ _mesa_lookup_enum_by_nr(pname));
}
void
GET_CURRENT_CONTEXT(ctx);
struct gl_shader_program *shProg = NULL;
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
if (!validate_shader_target(ctx, type)) {
_mesa_error(ctx, GL_INVALID_ENUM, "glUseShaderProgramEXT(type)");
return;
}
- if (ctx->TransformFeedback.CurrentObject->Active &&
- !ctx->TransformFeedback.CurrentObject->Paused) {
+ if (_mesa_is_xfb_active_and_unpaused(ctx)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glUseShaderProgramEXT(transform feedback is active)");
return;
return program;
}
-
-/**
- * Plug in shader-related functions into API dispatch table.
- */
-void
-_mesa_init_shader_dispatch(struct _glapi_table *exec)
-{
-#if FEATURE_GL
- /* GL_ARB_vertex/fragment_shader */
- SET_DeleteObjectARB(exec, _mesa_DeleteObjectARB);
- SET_GetHandleARB(exec, _mesa_GetHandleARB);
- SET_DetachObjectARB(exec, _mesa_DetachObjectARB);
- SET_CreateShaderObjectARB(exec, _mesa_CreateShaderObjectARB);
- SET_ShaderSourceARB(exec, _mesa_ShaderSourceARB);
- SET_CompileShaderARB(exec, _mesa_CompileShaderARB);
- SET_CreateProgramObjectARB(exec, _mesa_CreateProgramObjectARB);
- SET_AttachObjectARB(exec, _mesa_AttachObjectARB);
- SET_LinkProgramARB(exec, _mesa_LinkProgramARB);
- SET_UseProgramObjectARB(exec, _mesa_UseProgramObjectARB);
- SET_ValidateProgramARB(exec, _mesa_ValidateProgramARB);
- SET_GetObjectParameterfvARB(exec, _mesa_GetObjectParameterfvARB);
- SET_GetObjectParameterivARB(exec, _mesa_GetObjectParameterivARB);
- SET_GetInfoLogARB(exec, _mesa_GetInfoLogARB);
- SET_GetAttachedObjectsARB(exec, _mesa_GetAttachedObjectsARB);
- SET_GetShaderSourceARB(exec, _mesa_GetShaderSourceARB);
-
- /* OpenGL 2.0 */
- SET_AttachShader(exec, _mesa_AttachShader);
- SET_CreateProgram(exec, _mesa_CreateProgram);
- SET_CreateShader(exec, _mesa_CreateShader);
- SET_DeleteProgram(exec, _mesa_DeleteProgram);
- SET_DeleteShader(exec, _mesa_DeleteShader);
- SET_DetachShader(exec, _mesa_DetachShader);
- SET_GetAttachedShaders(exec, _mesa_GetAttachedShaders);
- SET_GetProgramiv(exec, _mesa_GetProgramiv);
- SET_GetProgramInfoLog(exec, _mesa_GetProgramInfoLog);
- SET_GetShaderiv(exec, _mesa_GetShaderiv);
- SET_GetShaderInfoLog(exec, _mesa_GetShaderInfoLog);
- SET_IsProgram(exec, _mesa_IsProgram);
- SET_IsShader(exec, _mesa_IsShader);
-
- /* GL_ARB_vertex_shader */
- SET_BindAttribLocationARB(exec, _mesa_BindAttribLocationARB);
- SET_GetActiveAttribARB(exec, _mesa_GetActiveAttribARB);
- SET_GetAttribLocationARB(exec, _mesa_GetAttribLocationARB);
-
- SET_ProgramParameteriARB(exec, _mesa_ProgramParameteriARB);
-
- SET_UseShaderProgramEXT(exec, _mesa_UseShaderProgramEXT);
- SET_ActiveProgramEXT(exec, _mesa_ActiveProgramEXT);
- SET_CreateShaderProgramEXT(exec, _mesa_CreateShaderProgramEXT);
-
- /* GL_EXT_gpu_shader4 / GL 3.0 */
- SET_BindFragDataLocationEXT(exec, _mesa_BindFragDataLocation);
- SET_GetFragDataLocationEXT(exec, _mesa_GetFragDataLocation);
-
- /* GL_ARB_ES2_compatibility */
- SET_ReleaseShaderCompiler(exec, _mesa_ReleaseShaderCompiler);
- SET_GetShaderPrecisionFormat(exec, _mesa_GetShaderPrecisionFormat);
- SET_ShaderBinary(exec, _mesa_ShaderBinary);
-
- /* GL_ARB_blend_func_extended */
- SET_BindFragDataLocationIndexed(exec, _mesa_BindFragDataLocationIndexed);
- SET_GetFragDataIndex(exec, _mesa_GetFragDataIndex);
-#endif /* FEATURE_GL */
-}
-