mesa: add support for memory object creation/import/delete
[mesa.git] / src / mesa / main / shaderapi.c
index e690e4731fa73f04ec2ac6cebca5298957a646d3..6dd617be7e5e727a1506a88f09aad7a642b8774f 100644 (file)
@@ -1039,7 +1039,7 @@ get_shader_source(struct gl_context *ctx, GLuint shader, GLsizei maxLength,
  * glShaderSource[ARB].
  */
 static void
-shader_source(struct gl_shader *sh, const GLchar *source)
+set_shader_source(struct gl_shader *sh, const GLchar *source)
 {
    assert(sh);
 
@@ -1130,21 +1130,24 @@ _mesa_compile_shader(struct gl_context *ctx, struct gl_shader *sh)
 /**
  * Link a program's shaders.
  */
-void
-_mesa_link_program(struct gl_context *ctx, struct gl_shader_program *shProg)
+static ALWAYS_INLINE void
+link_program(struct gl_context *ctx, struct gl_shader_program *shProg,
+             bool no_error)
 {
    if (!shProg)
       return;
 
-   /* From the ARB_transform_feedback2 specification:
-    * "The error INVALID_OPERATION is generated by LinkProgram if <program> is
-    *  the name of a program being used by one or more transform feedback
-    *  objects, even if the objects are not currently bound or are paused."
-    */
-   if (_mesa_transform_feedback_is_using_program(ctx, shProg)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glLinkProgram(transform feedback is using the program)");
-      return;
+   if (!no_error) {
+      /* From the ARB_transform_feedback2 specification:
+       * "The error INVALID_OPERATION is generated by LinkProgram if <program>
+       * is the name of a program being used by one or more transform feedback
+       * objects, even if the objects are not currently bound or are paused."
+       */
+      if (_mesa_transform_feedback_is_using_program(ctx, shProg)) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glLinkProgram(transform feedback is using the program)");
+         return;
+      }
    }
 
    unsigned programs_in_use = 0;
@@ -1232,6 +1235,27 @@ _mesa_link_program(struct gl_context *ctx, struct gl_shader_program *shProg)
 }
 
 
+static void
+link_program_error(struct gl_context *ctx, struct gl_shader_program *shProg)
+{
+   link_program(ctx, shProg, false);
+}
+
+
+static void
+link_program_no_error(struct gl_context *ctx, struct gl_shader_program *shProg)
+{
+   link_program(ctx, shProg, true);
+}
+
+
+void
+_mesa_link_program(struct gl_context *ctx, struct gl_shader_program *shProg)
+{
+   link_program_error(ctx, shProg);
+}
+
+
 /**
  * Print basic shader info (for debug).
  */
@@ -1685,14 +1709,28 @@ _mesa_IsShader(GLuint name)
 }
 
 
+void GLAPIENTRY
+_mesa_LinkProgram_no_error(GLuint programObj)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   struct gl_shader_program *shProg =
+      _mesa_lookup_shader_program(ctx, programObj);
+   link_program_no_error(ctx, shProg);
+}
+
+
 void GLAPIENTRY
 _mesa_LinkProgram(GLuint programObj)
 {
    GET_CURRENT_CONTEXT(ctx);
+
    if (MESA_VERBOSE & VERBOSE_API)
       _mesa_debug(ctx, "glLinkProgram %u\n", programObj);
-   _mesa_link_program(ctx, _mesa_lookup_shader_program_err(ctx, programObj,
-                                                           "glLinkProgram"));
+
+   struct gl_shader_program *shProg =
+      _mesa_lookup_shader_program_err(ctx, programObj, "glLinkProgram");
+   link_program_error(ctx, shProg);
 }
 
 #ifdef ENABLE_SHADER_CACHE
@@ -1814,23 +1852,26 @@ read_shader(const gl_shader_stage stage, const char *source)
  * Basically, concatenate the source code strings into one long string
  * and pass it to _mesa_shader_source().
  */
-void GLAPIENTRY
-_mesa_ShaderSource(GLuint shaderObj, GLsizei count,
-                   const GLchar * const * string, const GLint * length)
+static ALWAYS_INLINE void
+shader_source(struct gl_context *ctx, GLuint shaderObj, GLsizei count,
+              const GLchar *const *string, const GLint *length, bool no_error)
 {
-   GET_CURRENT_CONTEXT(ctx);
    GLint *offsets;
    GLsizei i, totalLength;
    GLcharARB *source;
    struct gl_shader *sh;
 
-   sh = _mesa_lookup_shader_err(ctx, shaderObj, "glShaderSourceARB");
-   if (!sh)
-      return;
+   if (!no_error) {
+      sh = _mesa_lookup_shader_err(ctx, shaderObj, "glShaderSourceARB");
+      if (!sh)
+         return;
 
-   if (string == NULL) {
-      _mesa_error(ctx, GL_INVALID_VALUE, "glShaderSourceARB");
-      return;
+      if (string == NULL) {
+         _mesa_error(ctx, GL_INVALID_VALUE, "glShaderSourceARB");
+         return;
+      }
+   } else {
+      sh = _mesa_lookup_shader(ctx, shaderObj);
    }
 
    /*
@@ -1844,7 +1885,7 @@ _mesa_ShaderSource(GLuint shaderObj, GLsizei count,
    }
 
    for (i = 0; i < count; i++) {
-      if (string[i] == NULL) {
+      if (!no_error && string[i] == NULL) {
          free((GLvoid *) offsets);
          _mesa_error(ctx, GL_INVALID_OPERATION,
                      "glShaderSourceARB(null string)");
@@ -1894,12 +1935,30 @@ _mesa_ShaderSource(GLuint shaderObj, GLsizei count,
    }
 #endif /* ENABLE_SHADER_CACHE */
 
-   shader_source(sh, source);
+   set_shader_source(sh, source);
 
    free(offsets);
 }
 
 
+void GLAPIENTRY
+_mesa_ShaderSource_no_error(GLuint shaderObj, GLsizei count,
+                            const GLchar *const *string, const GLint *length)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   shader_source(ctx, shaderObj, count, string, length, true);
+}
+
+
+void GLAPIENTRY
+_mesa_ShaderSource(GLuint shaderObj, GLsizei count,
+                   const GLchar *const *string, const GLint *length)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   shader_source(ctx, shaderObj, count, string, length, false);
+}
+
+
 static ALWAYS_INLINE void
 use_program(GLuint program, bool no_error)
 {