/*
* Mesa 3-D graphics library
- * Version: 7.3
*
* Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
* Copyright (C) 2008 VMware, Inc. All Rights Reserved.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
*/
/**
#include "macros.h"
#include "matrix.h"
#include "multisample.h"
+#include "performance_monitor.h"
+#include "pipelineobj.h"
#include "pixel.h"
#include "pixelstore.h"
#include "points.h"
#include "program/prog_print.h"
#include "math/m_matrix.h"
#include "main/dispatch.h" /* for _gloffset_COUNT */
+#include "uniforms.h"
#ifdef USE_SPARC_ASM
#include "sparc/sparc.h"
*
* \sa Used by one_time_init().
*/
-_glthread_DECLARE_STATIC_MUTEX(OneTimeLock);
+mtx_t OneTimeLock = _MTX_INITIALIZER_NP;
{
static GLbitfield api_init_mask = 0x0;
- _glthread_LOCK_MUTEX(OneTimeLock);
+ mtx_lock(&OneTimeLock);
/* truly one-time init */
if (!api_init_mask) {
assert( sizeof(GLint) == 4 );
assert( sizeof(GLuint) == 4 );
+ _mesa_one_time_init_extension_overrides();
+
_mesa_get_cpu_features();
for (i = 0; i < 256; i++) {
api_init_mask |= 1 << ctx->API;
- _glthread_UNLOCK_MUTEX(OneTimeLock);
+ mtx_unlock(&OneTimeLock);
/* Hopefully atexit() is widely available. If not, we may need some
* #ifdef tests here.
* Important: drivers should override these with actual limits.
*/
static void
-init_program_limits(struct gl_context *ctx, GLenum type,
+init_program_limits(struct gl_constants *consts, gl_shader_stage stage,
struct gl_program_constants *prog)
{
prog->MaxInstructions = MAX_PROGRAM_INSTRUCTIONS;
prog->MaxLocalParams = MAX_PROGRAM_LOCAL_PARAMS;
prog->MaxAddressOffset = MAX_PROGRAM_LOCAL_PARAMS;
- switch (type) {
- case GL_VERTEX_PROGRAM_ARB:
+ switch (stage) {
+ case MESA_SHADER_VERTEX:
prog->MaxParameters = MAX_VERTEX_PROGRAM_PARAMS;
prog->MaxAttribs = MAX_VERTEX_GENERIC_ATTRIBS;
prog->MaxAddressRegs = MAX_VERTEX_PROGRAM_ADDRESS_REGS;
prog->MaxUniformComponents = 4 * MAX_UNIFORMS;
+ prog->MaxInputComponents = 0; /* value not used */
+ prog->MaxOutputComponents = 16 * 4; /* old limit not to break tnl and swrast */
break;
- case GL_FRAGMENT_PROGRAM_ARB:
+ case MESA_SHADER_FRAGMENT:
prog->MaxParameters = MAX_NV_FRAGMENT_PROGRAM_PARAMS;
prog->MaxAttribs = MAX_NV_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_GEOMETRY_PROGRAM:
+ case MESA_SHADER_GEOMETRY:
prog->MaxParameters = MAX_VERTEX_PROGRAM_PARAMS;
prog->MaxAttribs = MAX_VERTEX_GENERIC_ATTRIBS;
prog->MaxAddressRegs = MAX_VERTEX_PROGRAM_ADDRESS_REGS;
- prog->MaxUniformComponents = MAX_GEOMETRY_UNIFORM_COMPONENTS;
+ prog->MaxUniformComponents = 4 * MAX_UNIFORMS;
+ prog->MaxInputComponents = 16 * 4; /* old limit not to break tnl and swrast */
+ prog->MaxOutputComponents = 16 * 4; /* old limit not to break tnl and swrast */
+ break;
+ case MESA_SHADER_COMPUTE:
+ prog->MaxParameters = 0; /* not meaningful for compute shaders */
+ prog->MaxAttribs = 0; /* not meaningful for compute shaders */
+ prog->MaxAddressRegs = 0; /* not meaningful for compute shaders */
+ prog->MaxUniformComponents = 4 * MAX_UNIFORMS;
+ prog->MaxInputComponents = 0; /* not meaningful for compute shaders */
+ prog->MaxOutputComponents = 0; /* not meaningful for compute shaders */
break;
default:
- assert(0 && "Bad program type in init_program_limits()");
+ assert(0 && "Bad shader stage in init_program_limits()");
}
/* Set the native limits to zero. This implies that there is no native
prog->MaxUniformBlocks = 12;
prog->MaxCombinedUniformComponents = (prog->MaxUniformComponents +
- ctx->Const.MaxUniformBlockSize / 4 *
+ consts->MaxUniformBlockSize / 4 *
prog->MaxUniformBlocks);
+
+ prog->MaxAtomicBuffers = 0;
+ prog->MaxAtomicCounters = 0;
}
* Use defaults from config.h. The device drivers will often override
* some of these values (such as number of texture units).
*/
-static void
-_mesa_init_constants(struct gl_context *ctx)
+void
+_mesa_init_constants(struct gl_constants *consts, gl_api api)
{
- assert(ctx);
+ int i;
+ assert(consts);
/* Constants, may be overriden (usually only reduced) by device drivers */
- ctx->Const.MaxTextureMbytes = MAX_TEXTURE_MBYTES;
- ctx->Const.MaxTextureLevels = MAX_TEXTURE_LEVELS;
- ctx->Const.Max3DTextureLevels = MAX_3D_TEXTURE_LEVELS;
- ctx->Const.MaxCubeTextureLevels = MAX_CUBE_TEXTURE_LEVELS;
- ctx->Const.MaxTextureRectSize = MAX_TEXTURE_RECT_SIZE;
- ctx->Const.MaxArrayTextureLayers = MAX_ARRAY_TEXTURE_LAYERS;
- ctx->Const.MaxTextureCoordUnits = MAX_TEXTURE_COORD_UNITS;
- ctx->Const.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
- ctx->Const.MaxTextureUnits = MIN2(ctx->Const.MaxTextureCoordUnits,
- ctx->Const.MaxTextureImageUnits);
- ctx->Const.MaxTextureMaxAnisotropy = MAX_TEXTURE_MAX_ANISOTROPY;
- ctx->Const.MaxTextureLodBias = MAX_TEXTURE_LOD_BIAS;
- ctx->Const.MaxTextureBufferSize = 65536;
- ctx->Const.TextureBufferOffsetAlignment = 1;
- ctx->Const.MaxArrayLockSize = MAX_ARRAY_LOCK_SIZE;
- ctx->Const.SubPixelBits = SUB_PIXEL_BITS;
- ctx->Const.MinPointSize = MIN_POINT_SIZE;
- ctx->Const.MaxPointSize = MAX_POINT_SIZE;
- ctx->Const.MinPointSizeAA = MIN_POINT_SIZE;
- ctx->Const.MaxPointSizeAA = MAX_POINT_SIZE;
- ctx->Const.PointSizeGranularity = (GLfloat) POINT_SIZE_GRANULARITY;
- ctx->Const.MinLineWidth = MIN_LINE_WIDTH;
- ctx->Const.MaxLineWidth = MAX_LINE_WIDTH;
- ctx->Const.MinLineWidthAA = MIN_LINE_WIDTH;
- ctx->Const.MaxLineWidthAA = MAX_LINE_WIDTH;
- ctx->Const.LineWidthGranularity = (GLfloat) LINE_WIDTH_GRANULARITY;
- ctx->Const.MaxColorTableSize = MAX_COLOR_TABLE_SIZE;
- ctx->Const.MaxClipPlanes = 6;
- ctx->Const.MaxLights = MAX_LIGHTS;
- ctx->Const.MaxShininess = 128.0;
- ctx->Const.MaxSpotExponent = 128.0;
- ctx->Const.MaxViewportWidth = MAX_VIEWPORT_WIDTH;
- ctx->Const.MaxViewportHeight = MAX_VIEWPORT_HEIGHT;
+ consts->MaxTextureMbytes = MAX_TEXTURE_MBYTES;
+ consts->MaxTextureLevels = MAX_TEXTURE_LEVELS;
+ consts->Max3DTextureLevels = MAX_3D_TEXTURE_LEVELS;
+ consts->MaxCubeTextureLevels = MAX_CUBE_TEXTURE_LEVELS;
+ consts->MaxTextureRectSize = MAX_TEXTURE_RECT_SIZE;
+ consts->MaxArrayTextureLayers = MAX_ARRAY_TEXTURE_LAYERS;
+ consts->MaxTextureCoordUnits = MAX_TEXTURE_COORD_UNITS;
+ consts->Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
+ consts->MaxTextureUnits = MIN2(consts->MaxTextureCoordUnits,
+ consts->Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits);
+ consts->MaxTextureMaxAnisotropy = MAX_TEXTURE_MAX_ANISOTROPY;
+ consts->MaxTextureLodBias = MAX_TEXTURE_LOD_BIAS;
+ consts->MaxTextureBufferSize = 65536;
+ consts->TextureBufferOffsetAlignment = 1;
+ consts->MaxArrayLockSize = MAX_ARRAY_LOCK_SIZE;
+ consts->SubPixelBits = SUB_PIXEL_BITS;
+ consts->MinPointSize = MIN_POINT_SIZE;
+ consts->MaxPointSize = MAX_POINT_SIZE;
+ consts->MinPointSizeAA = MIN_POINT_SIZE;
+ consts->MaxPointSizeAA = MAX_POINT_SIZE;
+ consts->PointSizeGranularity = (GLfloat) POINT_SIZE_GRANULARITY;
+ consts->MinLineWidth = MIN_LINE_WIDTH;
+ consts->MaxLineWidth = MAX_LINE_WIDTH;
+ consts->MinLineWidthAA = MIN_LINE_WIDTH;
+ consts->MaxLineWidthAA = MAX_LINE_WIDTH;
+ consts->LineWidthGranularity = (GLfloat) LINE_WIDTH_GRANULARITY;
+ consts->MaxClipPlanes = 6;
+ consts->MaxLights = MAX_LIGHTS;
+ consts->MaxShininess = 128.0;
+ consts->MaxSpotExponent = 128.0;
+ consts->MaxViewportWidth = MAX_VIEWPORT_WIDTH;
+ consts->MaxViewportHeight = MAX_VIEWPORT_HEIGHT;
+ consts->MinMapBufferAlignment = 64;
+
+ /* Driver must override these values if ARB_viewport_array is supported. */
+ consts->MaxViewports = 1;
+ consts->ViewportSubpixelBits = 0;
+ consts->ViewportBounds.Min = 0;
+ consts->ViewportBounds.Max = 0;
/** GL_ARB_uniform_buffer_object */
- ctx->Const.MaxCombinedUniformBlocks = 36;
- ctx->Const.MaxUniformBufferBindings = 36;
- ctx->Const.MaxUniformBlockSize = 16384;
- ctx->Const.UniformBufferOffsetAlignment = 1;
+ consts->MaxCombinedUniformBlocks = 36;
+ consts->MaxUniformBufferBindings = 36;
+ consts->MaxUniformBlockSize = 16384;
+ consts->UniformBufferOffsetAlignment = 1;
- init_program_limits(ctx, GL_VERTEX_PROGRAM_ARB, &ctx->Const.VertexProgram);
- init_program_limits(ctx, GL_FRAGMENT_PROGRAM_ARB, &ctx->Const.FragmentProgram);
- init_program_limits(ctx, MESA_GEOMETRY_PROGRAM, &ctx->Const.GeometryProgram);
+ /* GL_ARB_explicit_uniform_location, GL_MAX_UNIFORM_LOCATIONS */
+ consts->MaxUserAssignableUniformLocations =
+ 4 * MESA_SHADER_STAGES * MAX_UNIFORMS;
- ctx->Const.MaxProgramMatrices = MAX_PROGRAM_MATRICES;
- ctx->Const.MaxProgramMatrixStackDepth = MAX_PROGRAM_MATRIX_STACK_DEPTH;
+ for (i = 0; i < MESA_SHADER_STAGES; i++)
+ init_program_limits(consts, i, &consts->Program[i]);
- /* CheckArrayBounds is overriden by drivers/x11 for X server */
- ctx->Const.CheckArrayBounds = GL_FALSE;
+ consts->MaxProgramMatrices = MAX_PROGRAM_MATRICES;
+ consts->MaxProgramMatrixStackDepth = MAX_PROGRAM_MATRIX_STACK_DEPTH;
+
+ /* Assume that if GLSL 1.30+ (or GLSL ES 3.00+) is supported that
+ * gl_VertexID is implemented using a native hardware register with OpenGL
+ * semantics.
+ */
+ consts->VertexID_is_zero_based = false;
/* GL_ARB_draw_buffers */
- ctx->Const.MaxDrawBuffers = MAX_DRAW_BUFFERS;
+ consts->MaxDrawBuffers = MAX_DRAW_BUFFERS;
- ctx->Const.MaxColorAttachments = MAX_COLOR_ATTACHMENTS;
- ctx->Const.MaxRenderbufferSize = MAX_RENDERBUFFER_SIZE;
+ consts->MaxColorAttachments = MAX_COLOR_ATTACHMENTS;
+ consts->MaxRenderbufferSize = MAX_RENDERBUFFER_SIZE;
- ctx->Const.MaxVertexTextureImageUnits = MAX_VERTEX_TEXTURE_IMAGE_UNITS;
- ctx->Const.MaxCombinedTextureImageUnits = MAX_COMBINED_TEXTURE_IMAGE_UNITS;
- ctx->Const.MaxVarying = 16; /* old limit not to break tnl and swrast */
- ctx->Const.MaxGeometryTextureImageUnits = MAX_GEOMETRY_TEXTURE_IMAGE_UNITS;
- ctx->Const.MaxVertexVaryingComponents = MAX_VERTEX_VARYING_COMPONENTS;
- ctx->Const.MaxGeometryVaryingComponents = MAX_GEOMETRY_VARYING_COMPONENTS;
- ctx->Const.MaxGeometryOutputVertices = MAX_GEOMETRY_OUTPUT_VERTICES;
- ctx->Const.MaxGeometryTotalOutputComponents = MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS;
+ consts->Program[MESA_SHADER_VERTEX].MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
+ consts->MaxCombinedTextureImageUnits = MAX_COMBINED_TEXTURE_IMAGE_UNITS;
+ consts->MaxVarying = 16; /* old limit not to break tnl and swrast */
+ consts->Program[MESA_SHADER_GEOMETRY].MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
+ consts->MaxGeometryOutputVertices = MAX_GEOMETRY_OUTPUT_VERTICES;
+ consts->MaxGeometryTotalOutputComponents = MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS;
/* Shading language version */
- if (_mesa_is_desktop_gl(ctx)) {
- ctx->Const.GLSLVersion = 120;
- _mesa_override_glsl_version(ctx);
- }
- else if (ctx->API == API_OPENGLES2) {
- ctx->Const.GLSLVersion = 100;
- }
- else if (ctx->API == API_OPENGLES) {
- ctx->Const.GLSLVersion = 0; /* GLSL not supported */
- }
+ consts->GLSLVersion = 120;
+ _mesa_override_glsl_version(consts);
+
+#ifdef DEBUG
+ consts->GenerateTemporaryNames = true;
+#else
+ consts->GenerateTemporaryNames = false;
+#endif
/* GL_ARB_framebuffer_object */
- ctx->Const.MaxSamples = 0;
+ consts->MaxSamples = 0;
- /* GL_ARB_sync */
- ctx->Const.MaxServerWaitTimeout = (GLuint64) ~0;
+ /* GLSL default if NativeIntegers == FALSE */
+ consts->UniformBooleanTrue = FLT_AS_UINT(1.0f);
- /* GL_ATI_envmap_bumpmap */
- ctx->Const.SupportedBumpUnits = SUPPORTED_ATI_BUMP_UNITS;
+ /* GL_ARB_sync */
+ consts->MaxServerWaitTimeout = 0x1fff7fffffffULL;
/* GL_EXT_provoking_vertex */
- ctx->Const.QuadsFollowProvokingVertexConvention = GL_TRUE;
+ consts->QuadsFollowProvokingVertexConvention = GL_TRUE;
/* GL_EXT_transform_feedback */
- ctx->Const.MaxTransformFeedbackBuffers = MAX_FEEDBACK_BUFFERS;
- ctx->Const.MaxTransformFeedbackSeparateComponents = 4 * MAX_FEEDBACK_ATTRIBS;
- ctx->Const.MaxTransformFeedbackInterleavedComponents = 4 * MAX_FEEDBACK_ATTRIBS;
- ctx->Const.MaxVertexStreams = 1;
+ consts->MaxTransformFeedbackBuffers = MAX_FEEDBACK_BUFFERS;
+ consts->MaxTransformFeedbackSeparateComponents = 4 * MAX_FEEDBACK_ATTRIBS;
+ consts->MaxTransformFeedbackInterleavedComponents = 4 * MAX_FEEDBACK_ATTRIBS;
+ consts->MaxVertexStreams = 1;
- /* GL 3.2: hard-coded for now: */
- ctx->Const.ProfileMask = GL_CONTEXT_COMPATIBILITY_PROFILE_BIT;
+ /* GL 3.2 */
+ consts->ProfileMask = api == API_OPENGL_CORE
+ ? GL_CONTEXT_CORE_PROFILE_BIT
+ : GL_CONTEXT_COMPATIBILITY_PROFILE_BIT;
+
+ /* GL 4.4 */
+ consts->MaxVertexAttribStride = 2048;
/** GL_EXT_gpu_shader4 */
- ctx->Const.MinProgramTexelOffset = -8;
- ctx->Const.MaxProgramTexelOffset = 7;
+ consts->MinProgramTexelOffset = -8;
+ consts->MaxProgramTexelOffset = 7;
- /* GL_ARB_robustness */
- ctx->Const.ResetStrategy = GL_NO_RESET_NOTIFICATION_ARB;
+ /* GL_ARB_texture_gather */
+ consts->MinProgramTextureGatherOffset = -8;
+ consts->MaxProgramTextureGatherOffset = 7;
- /* PrimitiveRestart */
- ctx->Const.PrimitiveRestartInSoftware = GL_FALSE;
+ /* GL_ARB_robustness */
+ consts->ResetStrategy = GL_NO_RESET_NOTIFICATION_ARB;
/* ES 3.0 or ARB_ES3_compatibility */
- ctx->Const.MaxElementIndex = 0xffffffffu;
+ consts->MaxElementIndex = 0xffffffffu;
/* GL_ARB_texture_multisample */
- ctx->Const.MaxColorTextureSamples = 1;
- ctx->Const.MaxDepthTextureSamples = 1;
- ctx->Const.MaxIntegerSamples = 1;
+ consts->MaxColorTextureSamples = 1;
+ consts->MaxDepthTextureSamples = 1;
+ consts->MaxIntegerSamples = 1;
+
+ /* GL_ARB_shader_atomic_counters */
+ consts->MaxAtomicBufferBindings = MAX_COMBINED_ATOMIC_BUFFERS;
+ consts->MaxAtomicBufferSize = MAX_ATOMIC_COUNTERS * ATOMIC_COUNTER_SIZE;
+ consts->MaxCombinedAtomicBuffers = MAX_COMBINED_ATOMIC_BUFFERS;
+ consts->MaxCombinedAtomicCounters = MAX_ATOMIC_COUNTERS;
+
+ /* GL_ARB_vertex_attrib_binding */
+ consts->MaxVertexAttribRelativeOffset = 2047;
+ consts->MaxVertexAttribBindings = MAX_VERTEX_GENERIC_ATTRIBS;
+
+ /* GL_ARB_compute_shader */
+ consts->MaxComputeWorkGroupCount[0] = 65535;
+ consts->MaxComputeWorkGroupCount[1] = 65535;
+ consts->MaxComputeWorkGroupCount[2] = 65535;
+ consts->MaxComputeWorkGroupSize[0] = 1024;
+ consts->MaxComputeWorkGroupSize[1] = 1024;
+ consts->MaxComputeWorkGroupSize[2] = 64;
+ consts->MaxComputeWorkGroupInvocations = 1024;
+
+ /** GL_ARB_gpu_shader5 */
+ consts->MinFragmentInterpolationOffset = MIN_FRAGMENT_INTERPOLATION_OFFSET;
+ consts->MaxFragmentInterpolationOffset = MAX_FRAGMENT_INTERPOLATION_OFFSET;
+
+ /** GL_KHR_context_flush_control */
+ consts->ContextReleaseBehavior = GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH;
}
static void
check_context_limits(struct gl_context *ctx)
{
+ (void) ctx;
+
/* check that we don't exceed the size of various bitfields */
assert(VARYING_SLOT_MAX <=
(8 * sizeof(ctx->VertexProgram._Current->Base.OutputsWritten)));
assert(VARYING_SLOT_MAX <=
(8 * sizeof(ctx->FragmentProgram._Current->Base.InputsRead)));
- assert(MAX_COMBINED_TEXTURE_IMAGE_UNITS <= 8 * sizeof(GLbitfield));
-
/* shader-related checks */
- assert(ctx->Const.FragmentProgram.MaxLocalParams <= MAX_PROGRAM_LOCAL_PARAMS);
- assert(ctx->Const.VertexProgram.MaxLocalParams <= MAX_PROGRAM_LOCAL_PARAMS);
+ assert(ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxLocalParams <= MAX_PROGRAM_LOCAL_PARAMS);
+ assert(ctx->Const.Program[MESA_SHADER_VERTEX].MaxLocalParams <= MAX_PROGRAM_LOCAL_PARAMS);
/* Texture unit checks */
- assert(ctx->Const.MaxTextureImageUnits > 0);
- assert(ctx->Const.MaxTextureImageUnits <= MAX_TEXTURE_IMAGE_UNITS);
+ assert(ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits > 0);
+ assert(ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits <= MAX_TEXTURE_IMAGE_UNITS);
assert(ctx->Const.MaxTextureCoordUnits > 0);
assert(ctx->Const.MaxTextureCoordUnits <= MAX_TEXTURE_COORD_UNITS);
assert(ctx->Const.MaxTextureUnits > 0);
assert(ctx->Const.MaxTextureUnits <= MAX_TEXTURE_IMAGE_UNITS);
assert(ctx->Const.MaxTextureUnits <= MAX_TEXTURE_COORD_UNITS);
- assert(ctx->Const.MaxTextureUnits == MIN2(ctx->Const.MaxTextureImageUnits,
+ assert(ctx->Const.MaxTextureUnits == MIN2(ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits,
ctx->Const.MaxTextureCoordUnits));
assert(ctx->Const.MaxCombinedTextureImageUnits > 0);
assert(ctx->Const.MaxCombinedTextureImageUnits <= MAX_COMBINED_TEXTURE_IMAGE_UNITS);
assert(ctx->Const.MaxTextureCoordUnits <= MAX_COMBINED_TEXTURE_IMAGE_UNITS);
/* number of coord units cannot be greater than number of image units */
- assert(ctx->Const.MaxTextureCoordUnits <= ctx->Const.MaxTextureImageUnits);
+ assert(ctx->Const.MaxTextureCoordUnits <= ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits);
/* Texture size checks */
assert(ctx);
/* Constants */
- _mesa_init_constants( ctx );
+ _mesa_init_constants(&ctx->Const, ctx->API);
/* Extensions */
- _mesa_init_extensions( ctx );
+ _mesa_init_extensions(&ctx->Extensions);
/* Attribute Groups */
_mesa_init_accum( ctx );
_mesa_init_lighting( ctx );
_mesa_init_matrix( ctx );
_mesa_init_multisample( ctx );
+ _mesa_init_performance_monitors( ctx );
+ _mesa_init_pipeline( ctx );
_mesa_init_pixel( ctx );
_mesa_init_pixelstore( ctx );
_mesa_init_point( ctx );
ctx->NewState = _NEW_ALL;
ctx->NewDriverState = ~0;
ctx->ErrorValue = GL_NO_ERROR;
- ctx->ResetStatus = GL_NO_ERROR;
+ ctx->ShareGroupReset = false;
ctx->varying_vp_inputs = VERT_BIT_ALL;
return GL_TRUE;
/**
- * Allocate and initialize a new dispatch table.
+ * Special no-op glFlush, see below.
+ */
+#if defined(_WIN32)
+static void GLAPIENTRY
+nop_glFlush(void)
+{
+ /* don't record an error like we do in _mesa_generic_nop() */
+}
+#endif
+
+
+extern void (*__glapi_noop_table[])(void);
+
+
+/**
+ * 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.
*/
struct _glapi_table *
-_mesa_alloc_dispatch_table()
+_mesa_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
_glapi_proc *entry = (_glapi_proc *) table;
GLint 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];
+#else
entry[i] = (_glapi_proc) _mesa_generic_nop;
+#endif
}
+
+#if defined(_WIN32)
+ /* This is a special case for Windows in the event that
+ * wglGetProcAddress is called between glBegin/End().
+ *
+ * The MS opengl32.dll library apparently calls glFlush from
+ * wglGetProcAddress(). If we're inside glBegin/End(), glFlush
+ * will dispatch to _mesa_generic_nop() and we'll generate a
+ * GL_INVALID_OPERATION error.
+ *
+ * The specific case which hits this is piglit's primitive-restart
+ * test which calls glPrimitiveRestartNV() inside glBegin/End. The
+ * first time we call glPrimitiveRestartNV() Piglit's API dispatch
+ * code will try to resolve the function by calling wglGetProcAddress.
+ * This raises GL_INVALID_OPERATION and an assert(glGetError()==0)
+ * will fail causing the test to fail. By suppressing the error, the
+ * assertion passes and the test continues.
+ */
+ SET_Flush(table, nop_glFlush);
+#endif
}
return table;
}
*
* \param ctx the context to initialize
* \param api the GL API type to create the context for
- * \param visual describes the visual attributes for this context
+ * \param visual describes the visual attributes for this context or NULL to
+ * create a configless context
* \param share_list points to context to share textures, display lists,
* etc with, or NULL
* \param driverFunctions table of device driver functions for this context
assert(driverFunctions->FreeTextureImageBuffer);
ctx->API = api;
- ctx->Visual = *visual;
ctx->DrawBuffer = NULL;
ctx->ReadBuffer = NULL;
ctx->WinSysDrawBuffer = NULL;
ctx->WinSysReadBuffer = NULL;
+ if (visual) {
+ ctx->Visual = *visual;
+ ctx->HasConfig = GL_TRUE;
+ }
+ else {
+ memset(&ctx->Visual, 0, sizeof ctx->Visual);
+ ctx->HasConfig = GL_FALSE;
+ }
+
if (_mesa_is_desktop_gl(ctx)) {
_mesa_override_gl_version(ctx);
}
ctx->CurrentDispatch = ctx->OutsideBeginEnd;
ctx->FragmentProgram._MaintainTexEnvProgram
- = (_mesa_getenv("MESA_TEX_PROG") != NULL);
+ = (getenv("MESA_TEX_PROG") != NULL);
ctx->VertexProgram._MaintainTnlProgram
- = (_mesa_getenv("MESA_TNL_PROG") != NULL);
+ = (getenv("MESA_TNL_PROG") != NULL);
if (ctx->VertexProgram._MaintainTnlProgram) {
/* this is required... */
ctx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE;
fail:
_mesa_reference_shared_state(ctx, &ctx->Shared, NULL);
free(ctx->BeginEnd);
- free(ctx->Exec);
+ free(ctx->OutsideBeginEnd);
free(ctx->Save);
return GL_FALSE;
}
* 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)
+ * \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.
{
struct gl_context *ctx;
- ASSERT(visual);
-
ctx = calloc(1, sizeof(struct gl_context));
if (!ctx)
return NULL;
_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_geomprog(ctx, &ctx->GeometryProgram._Current, NULL);
+
_mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, NULL);
_mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, NULL);
_mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram, NULL);
- _mesa_reference_array_object(ctx, &ctx->Array.ArrayObj, NULL);
- _mesa_reference_array_object(ctx, &ctx->Array.DefaultArrayObj, NULL);
+ _mesa_reference_vao(ctx, &ctx->Array.VAO, NULL);
+ _mesa_reference_vao(ctx, &ctx->Array.DefaultVAO, NULL);
_mesa_free_attrib_data(ctx);
_mesa_free_buffer_objects(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);
_mesa_free_queryobj_data(ctx);
_mesa_free_sync_data(ctx);
_mesa_free_varray_data(ctx);
_mesa_free_transform_feedback(ctx);
+ _mesa_free_performance_monitors(ctx);
_mesa_reference_buffer_object(ctx, &ctx->Pack.BufferObj, NULL);
_mesa_reference_buffer_object(ctx, &ctx->Unpack.BufferObj, NULL);
/* free dispatch tables */
free(ctx->BeginEnd);
- free(ctx->Exec);
+ free(ctx->OutsideBeginEnd);
free(ctx->Save);
/* Shared context state (display lists, textures, etc) */
}
if (mask & GL_VIEWPORT_BIT) {
/* Cannot use memcpy, because of pointers in GLmatrix _WindowMap */
- dst->Viewport.X = src->Viewport.X;
- dst->Viewport.Y = src->Viewport.Y;
- dst->Viewport.Width = src->Viewport.Width;
- dst->Viewport.Height = src->Viewport.Height;
- dst->Viewport.Near = src->Viewport.Near;
- dst->Viewport.Far = src->Viewport.Far;
- _math_matrix_copy(&dst->Viewport._WindowMap, &src->Viewport._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);
+ }
}
/* XXX FIXME: Call callbacks?
}
-/**
- * Do one-time initialization for the given framebuffer. Specifically,
- * ask the driver for the window's current size and update the framebuffer
- * object to match.
- * Really, the device driver should totally take care of this.
- */
-static void
-initialize_framebuffer_size(struct gl_context *ctx, struct gl_framebuffer *fb)
-{
- GLuint width, height;
- if (ctx->Driver.GetBufferSize) {
- ctx->Driver.GetBufferSize(fb, &width, &height);
- if (ctx->Driver.ResizeBuffers)
- ctx->Driver.ResizeBuffers(ctx, fb, width, height);
- fb->Initialized = GL_TRUE;
- }
-}
-
-
/**
* Check if the viewport/scissor size has not yet been initialized.
* Initialize the size if the given width and height are non-zero.
_mesa_check_init_viewport(struct gl_context *ctx, GLuint width, GLuint height)
{
if (!ctx->ViewportInitialized && width > 0 && height > 0) {
+ unsigned i;
+
/* 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);
+
+ /* Note: ctx->Const.MaxViewports may not have been set by the driver
+ * yet, so just initialize all of them.
+ */
+ for (i = 0; i < MAX_VIEWPORTS; i++) {
+ _mesa_set_viewport(ctx, i, 0, 0, width, height);
+ _mesa_set_scissor(ctx, i, 0, 0, width, 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;
+ }
+
+ ctx->Extensions.String = _mesa_make_extension_string(ctx);
+
+ check_context_limits(ctx);
+
+ /* According to GL_MESA_configless_context the default value of
+ * glDrawBuffers depends on the config of the first surface it is bound to.
+ * 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()) {
+ if (ctx->DrawBuffer->Visual.doubleBufferMode)
+ buffer = GL_BACK;
+ else
+ buffer = GL_FRONT;
+
+ _mesa_drawbuffers(ctx, 1, &buffer, NULL /* destMask */);
+ }
+
+ if (ctx->ReadBuffer != _mesa_get_incomplete_framebuffer()) {
+ if (ctx->ReadBuffer->Visual.doubleBufferMode) {
+ buffer = GL_BACK;
+ bufferIndex = BUFFER_BACK_LEFT;
+ }
+ else {
+ buffer = GL_FRONT;
+ bufferIndex = BUFFER_FRONT_LEFT;
+ }
+
+ _mesa_readbuffer(ctx, buffer, bufferIndex);
+ }
+ }
+
+ /* 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 (getenv("MESA_INFO")) {
+ _mesa_print_info(ctx);
+ }
+}
/**
* Bind the given context to the given drawBuffer and readBuffer and
}
if (curCtx &&
- (curCtx->WinSysDrawBuffer || curCtx->WinSysReadBuffer) &&
+ (curCtx->WinSysDrawBuffer || curCtx->WinSysReadBuffer) &&
/* make sure this context is valid for flushing */
- curCtx != newCtx)
+ curCtx != newCtx &&
+ curCtx->Const.ContextReleaseBehavior ==
+ GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH)
_mesa_flush(curCtx);
/* We used to call _glapi_check_multithread() here. Now do it in drivers */
*/
newCtx->NewState |= _NEW_BUFFERS;
-#if 1
- /* We want to get rid of these lines: */
- if (!drawBuffer->Initialized) {
- initialize_framebuffer_size(newCtx, drawBuffer);
- }
- if (readBuffer != drawBuffer && !readBuffer->Initialized) {
- initialize_framebuffer_size(newCtx, readBuffer);
- }
-
- _mesa_resizebuffers(newCtx);
-#else
- /* We want the drawBuffer and readBuffer to be initialized by
- * the driver.
- * This generally means the Width and Height match the actual
- * window size and the renderbuffers (both hardware and software
- * based) are allocated to match. The later can generally be
- * done with a call to _mesa_resize_framebuffer().
- *
- * It's theoretically possible for a buffer to have zero width
- * or height, but for now, assert check that the driver did what's
- * expected of it.
- */
- ASSERT(drawBuffer->Width > 0);
- ASSERT(drawBuffer->Height > 0);
-#endif
-
if (drawBuffer) {
_mesa_check_init_viewport(newCtx,
drawBuffer->Width, drawBuffer->Height);
}
if (newCtx->FirstTimeCurrent) {
- assert(newCtx->Version > 0);
-
- newCtx->Extensions.String = _mesa_make_extension_string(newCtx);
-
- 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();
- }
-
+ handle_first_current(newCtx);
newCtx->FirstTimeCurrent = GL_FALSE;
}
}
}
-/**
- * Set mvp_with_dp4 flag. If a driver has a preference for DP4 over
- * MUL/MAD, or vice versa, call this function to register that.
- * Otherwise we default to MUL/MAD.
- */
-void
-_mesa_set_mvp_with_dp4( struct gl_context *ctx,
- GLboolean flag )
-{
- ctx->mvp_with_dp4 = flag;
-}
-
/*
* ARB_blend_func_extended - ERRORS section
* "The error INVALID_OPERATION is generated by Begin or any procedure that
return GL_TRUE;
}
-/**
- * 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(struct gl_context *ctx, const char *where)
+static bool
+shader_linked_or_absent(struct gl_context *ctx,
+ const struct gl_shader_program *shProg,
+ bool *shader_present, const char *where)
{
- bool vert_from_glsl_shader = false;
- bool geom_from_glsl_shader = false;
- bool frag_from_glsl_shader = false;
+ if (shProg) {
+ *shader_present = true;
- /* This depends on having up to date derived state (shaders) */
- if (ctx->NewState)
- _mesa_update_state(ctx);
-
- if (ctx->Shader.CurrentVertexProgram) {
- vert_from_glsl_shader = true;
-
- if (!ctx->Shader.CurrentVertexProgram->LinkStatus) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "%s(shader not linked)", where);
- return GL_FALSE;
+ 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,
- ctx->Shader.CurrentVertexProgram,
- errMsg)) {
+ if (!_mesa_validate_shader_program(ctx, shProg, errMsg)) {
_mesa_warning(ctx, "Shader program %u is invalid: %s",
- ctx->Shader.CurrentVertexProgram->Name, errMsg);
+ shProg->Name, errMsg);
}
}
#endif
}
- if (ctx->Shader.CurrentGeometryProgram) {
- geom_from_glsl_shader = true;
+ return true;
+}
- if (!ctx->Shader.CurrentGeometryProgram->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.CurrentGeometryProgram,
- errMsg)) {
- _mesa_warning(ctx, "Shader program %u is invalid: %s",
- ctx->Shader.CurrentGeometryProgram->Name, errMsg);
- }
- }
-#endif
- }
+/**
+ * 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.
+ * It also check the current pipeline object is valid if any.
+ * 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(struct gl_context *ctx, const char *where)
+{
+ bool from_glsl_shader[MESA_SHADER_COMPUTE] = { false };
+ unsigned i;
- if (ctx->Shader.CurrentFragmentProgram) {
- frag_from_glsl_shader = true;
+ /* This depends on having up to date derived state (shaders) */
+ if (ctx->NewState)
+ _mesa_update_state(ctx);
- if (!ctx->Shader.CurrentFragmentProgram->LinkStatus) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "%s(shader not linked)", where);
+ 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;
- }
-#if 0 /* not normally enabled */
- {
- char errMsg[100];
- if (!_mesa_validate_shader_program(ctx,
- ctx->Shader.CurrentFragmentProgram,
- errMsg)) {
- _mesa_warning(ctx, "Shader program %u is invalid: %s",
- ctx->Shader.CurrentFragmentProgram->Name, errMsg);
- }
- }
-#endif
}
/* Any shader stages that are not supplied by the GLSL shader and have
* assembly shaders enabled must now be validated.
*/
- if (!vert_from_glsl_shader
+ if (!from_glsl_shader[MESA_SHADER_VERTEX]
&& ctx->VertexProgram.Enabled && !ctx->VertexProgram._Enabled) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"%s(vertex program not valid)", where);
/* FINISHME: If GL_NV_geometry_program4 is ever supported, the current
* FINISHME: geometry program should validated here.
*/
- (void) geom_from_glsl_shader;
+ (void) from_glsl_shader[MESA_SHADER_GEOMETRY];
- if (!frag_from_glsl_shader) {
+ if (!from_glsl_shader[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)) {
+ return GL_FALSE;
+ }
+ }
+
+ /* If a program is active and SSO not in use, check if validation of
+ * samplers succeeded for the active program. */
+ if (ctx->_Shader->ActiveProgram && ctx->_Shader != ctx->Pipeline.Current) {
+ char errMsg[100];
+ if (!_mesa_sampler_uniforms_are_valid(ctx->_Shader->ActiveProgram,
+ errMsg, 100)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s", errMsg);
+ return GL_FALSE;
+ }
+ }
+
if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
_mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
"%s(incomplete framebuffer)", where);
}
#ifdef DEBUG
- if (ctx->Shader.Flags & GLSL_LOG) {
- struct gl_shader_program *shProg[MESA_SHADER_TYPES];
- gl_shader_type i;
-
- shProg[MESA_SHADER_VERTEX] = ctx->Shader.CurrentVertexProgram;
- shProg[MESA_SHADER_GEOMETRY] = ctx->Shader.CurrentGeometryProgram;
- shProg[MESA_SHADER_FRAGMENT] = ctx->Shader.CurrentFragmentProgram;
+ if (ctx->_Shader->Flags & GLSL_LOG) {
+ struct gl_shader_program **shProg = ctx->_Shader->CurrentProgram;
+ gl_shader_stage i;
- for (i = 0; i < MESA_SHADER_TYPES; i++) {
+ for (i = 0; i < MESA_SHADER_STAGES; i++) {
if (shProg[i] == NULL || shProg[i]->_Used
|| shProg[i]->_LinkedShaders[i] == NULL)
continue;
_mesa_append_uniforms_to_file(shProg[i]->_LinkedShaders[i]);
}
- for (i = 0; i < MESA_SHADER_TYPES; i++) {
+ for (i = 0; i < MESA_SHADER_STAGES; i++) {
if (shProg[i] != NULL)
shProg[i]->_Used = GL_TRUE;
}