ARB sync: Add infrastructure for glGetInteger64v
[mesa.git] / src / mesa / main / context.c
index 5e0f2d7b1bdc29b8150227e480ebe2f454d97efb..4651760d7846aa7702eaebc194116852f041771d 100644 (file)
 #include "glapi/glapioffsets.h"
 #include "glapi/glapitable.h"
 #include "shader/program.h"
+#include "shader/prog_print.h"
 #include "shader/shader_api.h"
 #if FEATURE_ATI_fragment_shader
 #include "shader/atifragshader.h"
@@ -455,7 +456,7 @@ _mesa_init_current(GLcontext *ctx)
    GLuint i;
 
    /* Init all to (0,0,0,1) */
-   for (i = 0; i < VERT_ATTRIB_MAX; i++) {
+   for (i = 0; i < Elements(ctx->Current.Attrib); i++) {
       ASSIGN_4V( ctx->Current.Attrib[i], 0.0, 0.0, 0.0, 1.0 );
    }
 
@@ -486,7 +487,7 @@ init_program_limits(GLenum type, struct gl_program_constants *prog)
    prog->MaxUniformComponents = 4 * MAX_UNIFORMS;
 
    if (type == GL_VERTEX_PROGRAM_ARB) {
-      prog->MaxParameters = MAX_NV_VERTEX_PROGRAM_PARAMS;
+      prog->MaxParameters = MAX_VERTEX_PROGRAM_PARAMS;
       prog->MaxAttribs = MAX_NV_VERTEX_PROGRAM_INPUTS;
       prog->MaxAddressRegs = MAX_VERTEX_PROGRAM_ADDRESS_REGS;
    }
@@ -496,15 +497,17 @@ init_program_limits(GLenum type, struct gl_program_constants *prog)
       prog->MaxAddressRegs = MAX_FRAGMENT_PROGRAM_ADDRESS_REGS;
    }
 
-   /* copy the above limits to init native limits */
-   prog->MaxNativeInstructions = prog->MaxInstructions;
-   prog->MaxNativeAluInstructions = prog->MaxAluInstructions;
-   prog->MaxNativeTexInstructions = prog->MaxTexInstructions;
-   prog->MaxNativeTexIndirections = prog->MaxTexIndirections;
-   prog->MaxNativeAttribs = prog->MaxAttribs;
-   prog->MaxNativeTemps = prog->MaxTemps;
-   prog->MaxNativeAddressRegs = prog->MaxAddressRegs;
-   prog->MaxNativeParameters = prog->MaxParameters;
+   /* Set the native limits to zero.  This implies that there is no native
+    * support for shaders.  Let the drivers fill in the actual values.
+    */
+   prog->MaxNativeInstructions = 0;
+   prog->MaxNativeAluInstructions = 0;
+   prog->MaxNativeTexInstructions = 0;
+   prog->MaxNativeTexIndirections = 0;
+   prog->MaxNativeAttribs = 0;
+   prog->MaxNativeTemps = 0;
+   prog->MaxNativeAddressRegs = 0;
+   prog->MaxNativeParameters = 0;
 }
 
 
@@ -592,6 +595,9 @@ _mesa_init_constants(GLcontext *ctx)
    /* GL_ATI_envmap_bumpmap */
    ctx->Const.SupportedBumpUnits = SUPPORTED_ATI_BUMP_UNITS;
 
+   /* GL_EXT_provoking_vertex */
+   ctx->Const.QuadsFollowProvokingVertexConvention = GL_TRUE;
+
    /* sanity checks */
    ASSERT(ctx->Const.MaxTextureUnits == MIN2(ctx->Const.MaxTextureImageUnits,
                                              ctx->Const.MaxTextureCoordUnits));
@@ -1008,9 +1014,20 @@ _mesa_free_context_data( GLcontext *ctx )
 #if FEATURE_ARB_occlusion_query
    _mesa_free_query_data(ctx);
 #endif
+   _mesa_free_varray_data(ctx);
 
    _mesa_delete_array_object(ctx, ctx->Array.DefaultArrayObj);
 
+#if FEATURE_ARB_pixel_buffer_object
+   _mesa_reference_buffer_object(ctx, &ctx->Pack.BufferObj, NULL);
+   _mesa_reference_buffer_object(ctx, &ctx->Unpack.BufferObj, NULL);
+#endif
+
+#if FEATURE_ARB_vertex_buffer_object
+   _mesa_reference_buffer_object(ctx, &ctx->Array.ArrayBufferObj, NULL);
+   _mesa_reference_buffer_object(ctx, &ctx->Array.ElementArrayBufferObj, NULL);
+#endif
+
    /* free dispatch tables */
    _mesa_free(ctx->Exec);
    _mesa_free(ctx->Save);
@@ -1245,6 +1262,24 @@ initialize_framebuffer_size(GLcontext *ctx, GLframebuffer *fb)
 }
 
 
+/**
+ * Check if the viewport/scissor size has not yet been initialized.
+ * Initialize the size if the given width and height are non-zero.
+ */
+void
+_mesa_check_init_viewport(GLcontext *ctx, GLuint width, GLuint height)
+{
+   if (!ctx->ViewportInitialized && width > 0 && height > 0) {
+      /* Note: set flag here, before calling _mesa_set_viewport(), to prevent
+       * potential infinite recursion.
+       */
+      ctx->ViewportInitialized = GL_TRUE;
+      _mesa_set_viewport(ctx, 0, 0, width, height);
+      _mesa_set_scissor(ctx, 0, 0, width, height);
+   }
+}
+
+
 /**
  * Bind the given context to the given drawBuffer and readBuffer and
  * make it the current context for the calling thread.
@@ -1259,7 +1294,7 @@ initialize_framebuffer_size(GLcontext *ctx, GLframebuffer *fb)
  * \param drawBuffer  the drawing framebuffer
  * \param readBuffer  the reading framebuffer
  */
-void
+GLboolean
 _mesa_make_current( GLcontext *newCtx, GLframebuffer *drawBuffer,
                     GLframebuffer *readBuffer )
 {
@@ -1272,14 +1307,14 @@ _mesa_make_current( GLcontext *newCtx, GLframebuffer *drawBuffer,
       if (!check_compatible(newCtx, drawBuffer)) {
          _mesa_warning(newCtx,
               "MakeCurrent: incompatible visuals for context and drawbuffer");
-         return;
+         return GL_FALSE;
       }
    }
    if (newCtx && readBuffer && newCtx->WinSysReadBuffer != readBuffer) {
       if (!check_compatible(newCtx, readBuffer)) {
          _mesa_warning(newCtx,
               "MakeCurrent: incompatible visuals for context and readbuffer");
-         return;
+         return GL_FALSE;
       }
    }
 
@@ -1362,28 +1397,29 @@ _mesa_make_current( GLcontext *newCtx, GLframebuffer *drawBuffer,
          ASSERT(drawBuffer->Height > 0);
 #endif
 
-         if (newCtx->FirstTimeCurrent) {
-            /* set initial viewport and scissor size now */
-            _mesa_set_viewport(newCtx, 0, 0,
-                               drawBuffer->Width, drawBuffer->Height);
-           _mesa_set_scissor(newCtx, 0, 0,
-                             drawBuffer->Width, drawBuffer->Height );
-            check_context_limits(newCtx);
+         if (drawBuffer) {
+            _mesa_check_init_viewport(newCtx,
+                                      drawBuffer->Width, drawBuffer->Height);
          }
       }
 
-      /* We can use this to help debug user's problems.  Tell them to set
-       * the MESA_INFO env variable before running their app.  Then the
-       * first time each context is made current we'll print some useful
-       * information.
-       */
       if (newCtx->FirstTimeCurrent) {
+         check_context_limits(newCtx);
+
+         /* We can use this to help debug user's problems.  Tell them to set
+          * the MESA_INFO env variable before running their app.  Then the
+          * first time each context is made current we'll print some useful
+          * information.
+          */
         if (_mesa_getenv("MESA_INFO")) {
            _mesa_print_info();
         }
+
         newCtx->FirstTimeCurrent = GL_FALSE;
       }
    }
+   
+   return GL_TRUE;
 }
 
 
@@ -1543,4 +1579,82 @@ _mesa_set_mvp_with_dp4( GLcontext *ctx,
 }
 
 
+
+/**
+ * Prior to drawing anything with glBegin, glDrawArrays, etc. this function
+ * is called to see if it's valid to render.  This involves checking that
+ * the current shader is valid and the framebuffer is complete.
+ * If an error is detected it'll be recorded here.
+ * \return GL_TRUE if OK to render, GL_FALSE if not
+ */
+GLboolean
+_mesa_valid_to_render(GLcontext *ctx, const char *where)
+{
+   if (ctx->Shader.CurrentProgram) {
+      /* using shaders */
+      if (!ctx->Shader.CurrentProgram->LinkStatus) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "%s(shader not linked), where");
+         return GL_FALSE;
+      }
+#if 0 /* not normally enabled */
+      {
+         char errMsg[100];
+         if (!_mesa_validate_shader_program(ctx, ctx->Shader.CurrentProgram,
+                                            errMsg)) {
+            _mesa_warning(ctx, "Shader program %u is invalid: %s",
+                          ctx->Shader.CurrentProgram->Name, errMsg);
+         }
+      }
+#endif
+   }
+   else {
+      if (ctx->VertexProgram.Enabled && !ctx->VertexProgram._Enabled) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "%s(vertex program not valid)", where);
+         return GL_FALSE;
+      }
+      if (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "%s(fragment program not valid)", where);
+         return GL_FALSE;
+      }
+   }
+
+   if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+      _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
+                  "%s(incomplete framebuffer)", where);
+      return GL_FALSE;
+   }
+
+#ifdef DEBUG
+   if (ctx->Shader.Flags & GLSL_LOG) {
+      struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
+      if (shProg) {
+         if (!shProg->_Used) {
+            /* This is the first time this shader is being used.
+             * Append shader's constants/uniforms to log file.
+             */
+            GLuint i;
+            for (i = 0; i < shProg->NumShaders; i++) {
+               struct gl_shader *sh = shProg->Shaders[i];
+               if (sh->Type == GL_VERTEX_SHADER) {
+                  _mesa_append_uniforms_to_file(sh,
+                                                &shProg->VertexProgram->Base);
+               }
+               else if (sh->Type == GL_FRAGMENT_SHADER) {
+                  _mesa_append_uniforms_to_file(sh,
+                                                &shProg->FragmentProgram->Base);
+               }
+            }
+            shProg->_Used = GL_TRUE;
+         }
+      }
+   }
+#endif
+
+   return GL_TRUE;
+}
+
+
 /*@}*/