mesa: Implement glGet*(GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED).
[mesa.git] / src / mesa / main / context.c
index c1acda980b53257eeb987d249d890774476a09e0..7c0a6ef340a4648f3afc99afe761735ba1b6ced0 100644 (file)
@@ -89,6 +89,7 @@
 #include "context.h"
 #include "cpuinfo.h"
 #include "debug.h"
+#include "debug_output.h"
 #include "depth.h"
 #include "dlist.h"
 #include "eval.h"
 #include "scissor.h"
 #include "shared.h"
 #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"
 #include "sparc/sparc.h"
 #endif
 
-#include "glsl_parser_extras.h"
+#include "compiler/glsl/glsl_parser_extras.h"
 #include <stdbool.h>
 
 
@@ -336,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.
  *
@@ -369,6 +347,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.
@@ -390,13 +378,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();
 
@@ -406,16 +395,14 @@ 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",
                     PACKAGE_VERSION, __DATE__, __TIME__);
       }
 #endif
-
-#ifdef DEBUG
-      _mesa_test_formats();
-#endif
    }
 
    /* per-API one-time init */
@@ -428,13 +415,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();
 }
 
 
@@ -488,13 +468,15 @@ init_program_limits(struct gl_constants *consts, gl_shader_stage stage,
       prog->MaxOutputComponents = 16 * 4; /* old limit not to break tnl and swrast */
       break;
    case MESA_SHADER_FRAGMENT:
-      prog->MaxParameters = MAX_NV_FRAGMENT_PROGRAM_PARAMS;
-      prog->MaxAttribs = MAX_NV_FRAGMENT_PROGRAM_INPUTS;
+      prog->MaxParameters = MAX_FRAGMENT_PROGRAM_PARAMS;
+      prog->MaxAttribs = MAX_FRAGMENT_PROGRAM_INPUTS;
       prog->MaxAddressRegs = MAX_FRAGMENT_PROGRAM_ADDRESS_REGS;
       prog->MaxUniformComponents = 4 * MAX_UNIFORMS;
       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;
@@ -553,6 +535,8 @@ init_program_limits(struct gl_constants *consts, gl_shader_stage stage,
 
    prog->MaxAtomicBuffers = 0;
    prog->MaxAtomicCounters = 0;
+
+   prog->MaxShaderStorageBlocks = 8;
 }
 
 
@@ -598,8 +582,8 @@ _mesa_init_constants(struct gl_constants *consts, gl_api api)
    consts->MaxLights = MAX_LIGHTS;
    consts->MaxShininess = 128.0;
    consts->MaxSpotExponent = 128.0;
-   consts->MaxViewportWidth = MAX_VIEWPORT_WIDTH;
-   consts->MaxViewportHeight = MAX_VIEWPORT_HEIGHT;
+   consts->MaxViewportWidth = 16384;
+   consts->MaxViewportHeight = 16384;
    consts->MinMapBufferAlignment = 64;
 
    /* Driver must override these values if ARB_viewport_array is supported. */
@@ -614,6 +598,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;
@@ -665,6 +655,9 @@ _mesa_init_constants(struct gl_constants *consts, gl_api api)
    /* GL_EXT_provoking_vertex */
    consts->QuadsFollowProvokingVertexConvention = GL_TRUE;
 
+   /** GL_ARB_viewport_array */
+   consts->LayerAndVPIndexProvokingVertex = GL_UNDEFINED_VERTEX;
+
    /* GL_EXT_transform_feedback */
    consts->MaxTransformFeedbackBuffers = MAX_FEEDBACK_BUFFERS;
    consts->MaxTransformFeedbackSeparateComponents = 4 * MAX_FEEDBACK_ATTRIBS;
@@ -715,7 +708,8 @@ _mesa_init_constants(struct gl_constants *consts, gl_api api)
    consts->MaxComputeWorkGroupSize[0] = 1024;
    consts->MaxComputeWorkGroupSize[1] = 1024;
    consts->MaxComputeWorkGroupSize[2] = 64;
-   consts->MaxComputeWorkGroupInvocations = 1024;
+   /* Enables compute support for GLES 3.1 if >= 128 */
+   consts->MaxComputeWorkGroupInvocations = 0;
 
    /** GL_ARB_gpu_shader5 */
    consts->MinFragmentInterpolationOffset = MIN_FRAGMENT_INTERPOLATION_OFFSET;
@@ -723,6 +717,15 @@ _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;
+   consts->PrimitiveRestartForPatches = false;
 }
 
 
@@ -814,13 +817,14 @@ init_attrib_groups(struct gl_context *ctx)
    _mesa_init_current( ctx );
    _mesa_init_depth( ctx );
    _mesa_init_debug( ctx );
+   _mesa_init_debug_output( ctx );
    _mesa_init_display_list( ctx );
-   _mesa_init_errors( ctx );
    _mesa_init_eval( ctx );
    _mesa_init_fbobjects( ctx );
    _mesa_init_feedback( ctx );
    _mesa_init_fog( ctx );
    _mesa_init_hint( ctx );
+   _mesa_init_image_units( ctx );
    _mesa_init_line( ctx );
    _mesa_init_lighting( ctx );
    _mesa_init_matrix( ctx );
@@ -881,6 +885,19 @@ update_default_objects(struct gl_context *ctx)
 }
 
 
+/* XXX this is temporary and should be removed at some point in the
+ * future when there's a reasonable expectation that the libGL library
+ * contains the _glapi_new_nop_table() and _glapi_set_nop_handler()
+ * functions which were added in Mesa 10.6.
+ */
+#if !defined(_WIN32)
+/* Avoid libGL / driver ABI break */
+#define USE_GLAPI_NOP_FEATURES 0
+#else
+#define USE_GLAPI_NOP_FEATURES 1
+#endif
+
+
 /**
  * This function is called by the glapi no-op functions.  For each OpenGL
  * function/entrypoint there's a simple no-op function.  These "no-op"
@@ -894,14 +911,15 @@ update_default_objects(struct gl_context *ctx)
  * If there's no current OpenGL context for the calling thread, we can
  * print a message to stderr.
  *
- * \param name  the name of the OpenGL function, without the "gl" prefix
+ * \param name  the name of the OpenGL function
  */
+#if USE_GLAPI_NOP_FEATURES
 static void
 nop_handler(const char *name)
 {
    GET_CURRENT_CONTEXT(ctx);
    if (ctx) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "gl%s(invalid call)", name);
+      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid call)", name);
    }
 #if defined(DEBUG)
    else if (getenv("MESA_DEBUG") || getenv("LIBGL_DEBUG")) {
@@ -912,6 +930,7 @@ nop_handler(const char *name)
    }
 #endif
 }
+#endif
 
 
 /**
@@ -921,11 +940,51 @@ nop_handler(const char *name)
 static void GLAPIENTRY
 nop_glFlush(void)
 {
-   /* don't record an error like we do in _mesa_generic_nop() */
+   /* don't record an error like we do in nop_handler() */
+}
+#endif
+
+
+#if !USE_GLAPI_NOP_FEATURES
+static int
+generic_nop(void)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   _mesa_error(ctx, GL_INVALID_OPERATION,
+               "unsupported function called "
+               "(unsupported extension or deprecated function?)");
+   return 0;
 }
 #endif
 
 
+/**
+ * Create a new API dispatch table in which all entries point to the
+ * generic_nop() function.  This will not work on Windows because of
+ * the __stdcall convention which requires the callee to clean up the
+ * call stack.  That's impossible with one generic no-op function.
+ */
+struct _glapi_table *
+_mesa_new_nop_table(unsigned numEntries)
+{
+   struct _glapi_table *table;
+
+#if !USE_GLAPI_NOP_FEATURES
+   table = malloc(numEntries * sizeof(_glapi_proc));
+   if (table) {
+      _glapi_proc *entry = (_glapi_proc *) table;
+      unsigned i;
+      for (i = 0; i < numEntries; i++) {
+         entry[i] = (_glapi_proc) generic_nop;
+      }
+   }
+#else
+   table = _glapi_new_nop_table(numEntries);
+#endif
+   return table;
+}
+
+
 /**
  * Allocate and initialize a new dispatch table.  The table will be
  * populated with pointers to "no-op" functions.  In turn, the no-op
@@ -936,11 +995,12 @@ alloc_dispatch_table(void)
 {
    /* Find the larger of Mesa's dispatch table and libGL's dispatch table.
     * In practice, this'll be the same for stand-alone Mesa.  But for DRI
-    * Mesa we do this to accomodate different versions of libGL and various
+    * Mesa we do this to accommodate different versions of libGL and various
     * DRI drivers.
     */
-   GLint numEntries = MAX2(_glapi_get_dispatch_table_size(), _gloffset_COUNT);
-   struct _glapi_table *table = _glapi_new_nop_table(numEntries);
+   int numEntries = MAX2(_glapi_get_dispatch_table_size(), _gloffset_COUNT);
+
+   struct _glapi_table *table = _mesa_new_nop_table(numEntries);
 
 #if defined(_WIN32)
    if (table) {
@@ -964,7 +1024,9 @@ alloc_dispatch_table(void)
    }
 #endif
 
+#if USE_GLAPI_NOP_FEATURES
    _glapi_set_nop_handler(nop_handler);
+#endif
 
    return table;
 }
@@ -1109,9 +1171,7 @@ _mesa_initialize_context(struct gl_context *ctx,
       ctx->HasConfig = GL_FALSE;
    }
 
-   if (_mesa_is_desktop_gl(ctx)) {
-      _mesa_override_gl_version(ctx);
-   }
+   _mesa_override_gl_version(ctx);
 
    /* misc one-time initializations */
    one_time_init(ctx);
@@ -1273,7 +1333,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_geomprog(ctx, &ctx->GeometryProgram.Current, 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);
@@ -1288,7 +1349,6 @@ _mesa_free_context_data( struct gl_context *ctx )
    _mesa_free_eval_data( ctx );
    _mesa_free_texture_data( ctx );
    _mesa_free_matrix_data( ctx );
-   _mesa_free_viewport_data( ctx );
    _mesa_free_pipeline_data(ctx);
    _mesa_free_program_data(ctx);
    _mesa_free_shader_state(ctx);
@@ -1449,17 +1509,10 @@ _mesa_copy_context( const struct gl_context *src, struct gl_context *dst,
       dst->Transform = src->Transform;
    }
    if (mask & GL_VIEWPORT_BIT) {
-      /* Cannot use memcpy, because of pointers in GLmatrix _WindowMap */
       unsigned i;
       for (i = 0; i < src->Const.MaxViewports; i++) {
-         dst->ViewportArray[i].X = src->ViewportArray[i].X;
-         dst->ViewportArray[i].Y = src->ViewportArray[i].Y;
-         dst->ViewportArray[i].Width = src->ViewportArray[i].Width;
-         dst->ViewportArray[i].Height = src->ViewportArray[i].Height;
-         dst->ViewportArray[i].Near = src->ViewportArray[i].Near;
-         dst->ViewportArray[i].Far = src->ViewportArray[i].Far;
-         _math_matrix_copy(&dst->ViewportArray[i]._WindowMap,
-                           &src->ViewportArray[i]._WindowMap);
+         /* OK to memcpy */
+         dst->ViewportArray[i] = src->ViewportArray[i];
       }
    }
 
@@ -1474,10 +1527,6 @@ _mesa_copy_context( const struct gl_context *src, struct gl_context *dst,
  * Check if the given context can render into the given framebuffer
  * by checking visual attributes.
  *
- * Most of these tests could go away because Mesa is now pretty flexible
- * in terms of mixing rendering contexts with framebuffers.  As long
- * as RGB vs. CI mode agree, we're probably good.
- *
  * \return GL_TRUE if compatible, GL_FALSE otherwise.
  */
 static GLboolean 
@@ -1490,32 +1539,18 @@ check_compatible(const struct gl_context *ctx,
    if (buffer == _mesa_get_incomplete_framebuffer())
       return GL_TRUE;
 
-#if 0
-   /* disabling this fixes the fgl_glxgears pbuffer demo */
-   if (ctxvis->doubleBufferMode && !bufvis->doubleBufferMode)
-      return GL_FALSE;
-#endif
-   if (ctxvis->stereoMode && !bufvis->stereoMode)
-      return GL_FALSE;
-   if (ctxvis->haveAccumBuffer && !bufvis->haveAccumBuffer)
-      return GL_FALSE;
-   if (ctxvis->haveDepthBuffer && !bufvis->haveDepthBuffer)
-      return GL_FALSE;
-   if (ctxvis->haveStencilBuffer && !bufvis->haveStencilBuffer)
-      return GL_FALSE;
-   if (ctxvis->redMask && ctxvis->redMask != bufvis->redMask)
-      return GL_FALSE;
-   if (ctxvis->greenMask && ctxvis->greenMask != bufvis->greenMask)
-      return GL_FALSE;
-   if (ctxvis->blueMask && ctxvis->blueMask != bufvis->blueMask)
-      return GL_FALSE;
-#if 0
-   /* disabled (see bug 11161) */
-   if (ctxvis->depthBits && ctxvis->depthBits != bufvis->depthBits)
-      return GL_FALSE;
-#endif
-   if (ctxvis->stencilBits && ctxvis->stencilBits != bufvis->stencilBits)
-      return GL_FALSE;
+#define check_component(foo)           \
+   if (ctxvis->foo && bufvis->foo &&   \
+       ctxvis->foo != bufvis->foo)     \
+      return GL_FALSE
+
+   check_component(redMask);
+   check_component(greenMask);
+   check_component(blueMask);
+   check_component(depthBits);
+   check_component(stencilBits);
+
+#undef check_component
 
    return GL_TRUE;
 }
@@ -1549,9 +1584,6 @@ _mesa_check_init_viewport(struct gl_context *ctx, GLuint width, GLuint height)
 static void
 handle_first_current(struct gl_context *ctx)
 {
-   GLenum buffer;
-   GLint bufferIndex;
-
    if (ctx->Version == 0) {
       /* probably in the process of tearing down the context */
       return;
@@ -1566,15 +1598,21 @@ handle_first_current(struct gl_context *ctx)
     * For GLES it is always GL_BACK which has a magic interpretation */
    if (!ctx->HasConfig && _mesa_is_desktop_gl(ctx)) {
       if (ctx->DrawBuffer != _mesa_get_incomplete_framebuffer()) {
+         GLenum buffer;
+
          if (ctx->DrawBuffer->Visual.doubleBufferMode)
             buffer = GL_BACK;
          else
             buffer = GL_FRONT;
 
-         _mesa_drawbuffers(ctx, 1, &buffer, NULL /* destMask */);
+         _mesa_drawbuffers(ctx, ctx->DrawBuffer, 1, &buffer,
+                           NULL /* destMask */);
       }
 
       if (ctx->ReadBuffer != _mesa_get_incomplete_framebuffer()) {
+         gl_buffer_index bufferIndex;
+         GLenum buffer;
+
          if (ctx->ReadBuffer->Visual.doubleBufferMode) {
             buffer = GL_BACK;
             bufferIndex = BUFFER_BACK_LEFT;
@@ -1584,7 +1622,7 @@ handle_first_current(struct gl_context *ctx)
             bufferIndex = BUFFER_FRONT_LEFT;
          }
 
-         _mesa_readbuffer(ctx, buffer, bufferIndex);
+         _mesa_readbuffer(ctx, ctx->ReadBuffer, buffer, bufferIndex);
       }
    }
 
@@ -1879,31 +1917,6 @@ _mesa_check_blend_func_error(struct gl_context *ctx)
    return GL_TRUE;
 }
 
-static bool
-shader_linked_or_absent(struct gl_context *ctx,
-                        const struct gl_shader_program *shProg,
-                        bool *shader_present, const char *where)
-{
-   if (shProg) {
-      *shader_present = true;
-
-      if (!shProg->LinkStatus) {
-         _mesa_error(ctx, GL_INVALID_OPERATION, "%s(shader not linked)", where);
-         return false;
-      }
-#if 0 /* not normally enabled */
-      {
-         char errMsg[100];
-         if (!_mesa_validate_shader_program(ctx, shProg, errMsg)) {
-            _mesa_warning(ctx, "Shader program %u is invalid: %s",
-                          shProg->Name, errMsg);
-         }
-      }
-#endif
-   }
-
-   return true;
-}
 
 /**
  * Prior to drawing anything with glBegin, glDrawArrays, etc. this function
@@ -1916,54 +1929,22 @@ shader_linked_or_absent(struct gl_context *ctx,
 GLboolean
 _mesa_valid_to_render(struct gl_context *ctx, const char *where)
 {
-   unsigned i;
-
    /* This depends on having up to date derived state (shaders) */
    if (ctx->NewState)
       _mesa_update_state(ctx);
 
-   if (ctx->API == API_OPENGL_CORE || ctx->API == API_OPENGLES2) {
-      bool from_glsl_shader[MESA_SHADER_COMPUTE] = { false };
-
-      for (i = 0; i < MESA_SHADER_COMPUTE; i++) {
-         if (!shader_linked_or_absent(ctx, ctx->_Shader->CurrentProgram[i],
-                                      &from_glsl_shader[i], where))
-            return GL_FALSE;
-      }
-
-      /* In OpenGL Core Profile and OpenGL ES 2.0 / 3.0, there are no assembly
-       * shaders.  Don't check state related to those.
-       */
-   } else {
-      bool has_vertex_shader = false;
-      bool has_fragment_shader = false;
-
-      /* In OpenGL Compatibility Profile, there is only vertex shader and
-       * fragment shader.  We take this path also for API_OPENGLES because
-       * optimizing that path would make the other (more common) paths
-       * slightly slower.
-       */
-      if (!shader_linked_or_absent(ctx,
-                                   ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX],
-                                   &has_vertex_shader, where))
-         return GL_FALSE;
-
-      if (!shader_linked_or_absent(ctx,
-                                   ctx->_Shader->CurrentProgram[MESA_SHADER_FRAGMENT],
-                                   &has_fragment_shader, where))
-         return GL_FALSE;
-
+   if (ctx->API == API_OPENGL_COMPAT) {
       /* Any shader stages that are not supplied by the GLSL shader and have
        * assembly shaders enabled must now be validated.
        */
-      if (!has_vertex_shader
+      if (!ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX]
           && ctx->VertexProgram.Enabled && !ctx->VertexProgram._Enabled) {
          _mesa_error(ctx, GL_INVALID_OPERATION,
                      "%s(vertex program not valid)", where);
          return GL_FALSE;
       }
 
-      if (!has_fragment_shader) {
+      if (!ctx->_Shader->CurrentProgram[MESA_SHADER_FRAGMENT]) {
          if (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) {
             _mesa_error(ctx, GL_INVALID_OPERATION,
                         "%s(fragment program not valid)", where);
@@ -1983,9 +1964,10 @@ _mesa_valid_to_render(struct gl_context *ctx, const char *where)
 
    /* A pipeline object is bound */
    if (ctx->_Shader->Name && !ctx->_Shader->Validated) {
-      /* Error message will be printed inside _mesa_validate_program_pipeline.
-       */
-      if (!_mesa_validate_program_pipeline(ctx, ctx->_Shader, GL_TRUE)) {
+      if (!_mesa_validate_program_pipeline(ctx, ctx->_Shader)) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glValidateProgramPipeline failed to validate the "
+                     "pipeline");
          return GL_FALSE;
       }
    }