#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 "util/simple_list.h"
+#include "shaderimage.h"
+#include "util/strtod.h"
#include "state.h"
#include "stencil.h"
#include "texcompress_s3tc.h"
#include "math/m_matrix.h"
#include "main/dispatch.h" /* for _gloffset_COUNT */
#include "uniforms.h"
+#include "macros.h"
#ifdef USE_SPARC_ASM
#include "sparc/sparc.h"
#endif
-#include "glsl_parser_extras.h"
+#include "compiler/glsl/glsl_parser_extras.h"
#include <stdbool.h>
/*@{*/
-/**
- * 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.
*
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.
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();
_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 */
if (!(api_init_mask & (1 << ctx->API))) {
- _mesa_init_get_hash(ctx);
-
_mesa_init_remap_table();
}
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();
}
GLuint i;
/* Init all to (0,0,0,1) */
- for (i = 0; i < Elements(ctx->Current.Attrib); i++) {
+ for (i = 0; i < ARRAY_SIZE(ctx->Current.Attrib); i++) {
ASSIGN_4V( ctx->Current.Attrib[i], 0.0, 0.0, 0.0, 1.0 );
}
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;
prog->MaxAtomicBuffers = 0;
prog->MaxAtomicCounters = 0;
+
+ prog->MaxShaderStorageBlocks = 8;
}
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. */
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;
consts->MaxSamples = 0;
/* GLSL default if NativeIntegers == FALSE */
- consts->UniformBooleanTrue = FLT_AS_UINT(1.0f);
+ consts->UniformBooleanTrue = FLOAT_AS_UNION(1.0f).u;
/* GL_ARB_sync */
consts->MaxServerWaitTimeout = 0x1fff7fffffffULL;
/* 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;
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;
/** 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;
}
_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 );
}
+/* 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 is the default function we plug into all dispatch table slots
- * This helps prevents a segfault when someone calls a GL function without
- * first checking if the extension's supported.
+ * 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"
+ * functions call this function.
+ *
+ * If there's a current OpenGL context for the calling thread, we record a
+ * GL_INVALID_OPERATION error. This can happen either because the app's
+ * calling an unsupported extension function, or calling an illegal function
+ * (such as glClear between glBegin/glEnd).
+ *
+ * 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
*/
-int
-_mesa_generic_nop(void)
+#if USE_GLAPI_NOP_FEATURES
+static void
+nop_handler(const char *name)
{
GET_CURRENT_CONTEXT(ctx);
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "unsupported function called "
- "(unsupported extension or deprecated function?)");
- return 0;
+ if (ctx) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid call)", name);
+ }
+#if defined(DEBUG)
+ else if (getenv("MESA_DEBUG") || getenv("LIBGL_DEBUG")) {
+ fprintf(stderr,
+ "GL User Error: gl%s called without a rendering context\n",
+ name);
+ fflush(stderr);
+ }
+#endif
}
+#endif
/**
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
-extern void (*__glapi_noop_table[])(void);
+#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
/**
- * Allocate and initialize a new dispatch table. All the dispatch
- * function pointers will point at the _mesa_generic_nop() function
- * which raises GL_INVALID_OPERATION.
+ * 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_alloc_dispatch_table(void)
+_mesa_new_nop_table(unsigned numEntries)
{
- /* 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
- * DRI drivers.
- */
- GLint numEntries = MAX2(_glapi_get_dispatch_table_size(), _gloffset_COUNT);
struct _glapi_table *table;
+#if !USE_GLAPI_NOP_FEATURES
table = malloc(numEntries * sizeof(_glapi_proc));
if (table) {
_glapi_proc *entry = (_glapi_proc *) table;
- GLint i;
+ unsigned i;
for (i = 0; i < numEntries; i++) {
-#if defined(_WIN32)
- /* FIXME: This will not generate an error, but at least it won't
- * corrupt the stack like _mesa_generic_nop does. */
- entry[i] = __glapi_noop_table[i];
+ entry[i] = (_glapi_proc) generic_nop;
+ }
+ }
#else
- entry[i] = (_glapi_proc) _mesa_generic_nop;
+ 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
+ * functions will call nop_handler() above.
+ */
+static struct _glapi_table *
+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 accommodate different versions of libGL and various
+ * DRI drivers.
+ */
+ int numEntries = MAX2(_glapi_get_dispatch_table_size(), _gloffset_COUNT);
+
+ struct _glapi_table *table = _mesa_new_nop_table(numEntries);
#if defined(_WIN32)
+ if (table) {
/* This is a special case for Windows in the event that
* wglGetProcAddress is called between glBegin/End().
*
* assertion passes and the test continues.
*/
SET_Flush(table, nop_glFlush);
-#endif
}
+#endif
+
+#if USE_GLAPI_NOP_FEATURES
+ _glapi_set_nop_handler(nop_handler);
+#endif
+
return table;
}
{
struct _glapi_table *table;
- table = _mesa_alloc_dispatch_table();
+ table = alloc_dispatch_table();
if (!table)
return NULL;
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);
goto fail;
/* setup the API dispatch tables with all nop functions */
- ctx->OutsideBeginEnd = _mesa_alloc_dispatch_table();
+ ctx->OutsideBeginEnd = alloc_dispatch_table();
if (!ctx->OutsideBeginEnd)
goto fail;
ctx->Exec = ctx->OutsideBeginEnd;
switch (ctx->API) {
case API_OPENGL_COMPAT:
ctx->BeginEnd = create_beginend_table(ctx);
- ctx->Save = _mesa_alloc_dispatch_table();
+ ctx->Save = alloc_dispatch_table();
if (!ctx->BeginEnd || !ctx->Save)
goto fail;
}
-/**
- * Allocate and initialize a struct gl_context structure.
- * Note that the driver needs to pass in its dd_function_table here since
- * we need to at least call driverFunctions->NewTextureObject to initialize
- * the rendering context.
- *
- * \param api the GL API type to create the context for
- * \param visual a struct gl_config pointer (we copy the struct contents) or
- * NULL to create a configless context
- * \param share_list another context to share display lists with or NULL
- * \param driverFunctions points to the dd_function_table into which the
- * driver has plugged in all its special functions.
- *
- * \return pointer to a new __struct gl_contextRec or NULL if error.
- */
-struct gl_context *
-_mesa_create_context(gl_api api,
- const struct gl_config *visual,
- struct gl_context *share_list,
- const struct dd_function_table *driverFunctions)
-{
- struct gl_context *ctx;
-
- ctx = calloc(1, sizeof(struct gl_context));
- if (!ctx)
- return NULL;
-
- if (_mesa_initialize_context(ctx, api, visual, share_list,
- driverFunctions)) {
- return ctx;
- }
- else {
- free(ctx);
- return NULL;
- }
-}
-
-
/**
* Free the data associated with the given context.
*
_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);
_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);
free(ctx->BeginEnd);
free(ctx->OutsideBeginEnd);
free(ctx->Save);
+ free(ctx->ContextLost);
/* Shared context state (display lists, textures, etc) */
_mesa_reference_shared_state(ctx, &ctx->Shared, NULL);
dst->Hint = src->Hint;
}
if (mask & GL_LIGHTING_BIT) {
- GLuint i;
- /* begin with memcpy */
+ /* OK to memcpy */
dst->Light = src->Light;
- /* fixup linked lists to prevent pointer insanity */
- make_empty_list( &(dst->Light.EnabledList) );
- for (i = 0; i < MAX_LIGHTS; i++) {
- if (dst->Light.Light[i].Enabled) {
- insert_at_tail(&(dst->Light.EnabledList), &(dst->Light.Light[i]));
- }
- }
}
if (mask & GL_LINE_BIT) {
/* OK to memcpy */
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];
}
}
* 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
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;
}
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;
* 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;
bufferIndex = BUFFER_FRONT_LEFT;
}
- _mesa_readbuffer(ctx, buffer, bufferIndex);
+ _mesa_readbuffer(ctx, ctx->ReadBuffer, buffer, bufferIndex);
}
}
}
if (!newCtx->ReadBuffer || _mesa_is_winsys_fbo(newCtx->ReadBuffer)) {
_mesa_reference_framebuffer(&newCtx->ReadBuffer, readBuffer);
+ /* In _mesa_initialize_window_framebuffer, for single-buffered
+ * visuals, the ColorReadBuffer is set to be GL_FRONT, even with
+ * GLES contexts. When calling read_buffer, we verify we are reading
+ * from GL_BACK in is_legal_es3_readbuffer_enum. But the default is
+ * incorrect, and certain dEQP tests check this. So fix it here.
+ */
+ if (_mesa_is_gles(newCtx) &&
+ !newCtx->ReadBuffer->Visual.doubleBufferMode)
+ if (newCtx->ReadBuffer->ColorReadBuffer == GL_FRONT)
+ newCtx->ReadBuffer->ColorReadBuffer = GL_BACK;
}
/* XXX only set this flag if we're really changing the draw/read
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
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);
/* 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;
}
}