X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fmain%2Fcontext.c;h=4b5b694a7fb21c60574d882f399278d4159d50de;hb=60e3bfddaf6ab4f8385561654dfe4e0034d8bc9d;hp=abebd82874a288e91a07ebaad9a43501dfddef24;hpb=347dde82e65663562d6d2930bf861ec8c8079362;p=mesa.git diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c index abebd82874a..4b5b694a7fb 100644 --- a/src/mesa/main/context.c +++ b/src/mesa/main/context.c @@ -106,6 +106,7 @@ #include "matrix.h" #include "multisample.h" #include "performance_monitor.h" +#include "pipelineobj.h" #include "pixel.h" #include "pixelstore.h" #include "points.h" @@ -132,6 +133,7 @@ #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" @@ -363,7 +365,7 @@ dummy_enum_func(void) * * \sa Used by one_time_init(). */ -_glthread_DECLARE_STATIC_MUTEX(OneTimeLock); +mtx_t OneTimeLock = _MTX_INITIALIZER_NP; @@ -381,7 +383,7 @@ one_time_init( struct gl_context *ctx ) { static GLbitfield api_init_mask = 0x0; - _glthread_LOCK_MUTEX(OneTimeLock); + mtx_lock(&OneTimeLock); /* truly one-time init */ if (!api_init_mask) { @@ -395,6 +397,8 @@ one_time_init( struct gl_context *ctx ) assert( sizeof(GLint) == 4 ); assert( sizeof(GLuint) == 4 ); + _mesa_one_time_init_extension_overrides(); + _mesa_get_cpu_features(); for (i = 0; i < 256; i++) { @@ -422,7 +426,7 @@ one_time_init( struct gl_context *ctx ) 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. @@ -461,7 +465,7 @@ _mesa_init_current(struct gl_context *ctx) * Important: drivers should override these with actual limits. */ static void -init_program_limits(struct gl_context *ctx, gl_shader_stage stage, +init_program_limits(struct gl_constants *consts, gl_shader_stage stage, struct gl_program_constants *prog) { prog->MaxInstructions = MAX_PROGRAM_INSTRUCTIONS; @@ -543,7 +547,7 @@ init_program_limits(struct gl_context *ctx, gl_shader_stage stage, prog->MaxUniformBlocks = 12; prog->MaxCombinedUniformComponents = (prog->MaxUniformComponents + - ctx->Const.MaxUniformBlockSize / 4 * + consts->MaxUniformBlockSize / 4 * prog->MaxUniformBlocks); prog->MaxAtomicBuffers = 0; @@ -556,155 +560,168 @@ init_program_limits(struct gl_context *ctx, gl_shader_stage stage, * 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) { int i; - assert(ctx); + 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.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS; - ctx->Const.MaxTextureUnits = MIN2(ctx->Const.MaxTextureCoordUnits, - ctx->Const.Program[MESA_SHADER_FRAGMENT].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.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; - ctx->Const.MinMapBufferAlignment = 64; + 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. */ - ctx->Const.MaxViewports = 1; - ctx->Const.ViewportSubpixelBits = 0; - ctx->Const.ViewportBounds.Min = 0; - ctx->Const.ViewportBounds.Max = 0; - - /* Driver must override if it supports ARB_viewport_array */ - ctx->Const.MaxViewports = 1; + 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; + + /* GL_ARB_explicit_uniform_location, GL_MAX_UNIFORM_LOCATIONS */ + consts->MaxUserAssignableUniformLocations = + 4 * MESA_SHADER_STAGES * MAX_UNIFORMS; for (i = 0; i < MESA_SHADER_STAGES; i++) - init_program_limits(ctx, i, &ctx->Const.Program[i]); + init_program_limits(consts, i, &consts->Program[i]); - ctx->Const.MaxProgramMatrices = MAX_PROGRAM_MATRICES; - ctx->Const.MaxProgramMatrixStackDepth = MAX_PROGRAM_MATRIX_STACK_DEPTH; + consts->MaxProgramMatrices = MAX_PROGRAM_MATRICES; + consts->MaxProgramMatrixStackDepth = MAX_PROGRAM_MATRIX_STACK_DEPTH; - /* CheckArrayBounds is overriden by drivers/x11 for X server */ - ctx->Const.CheckArrayBounds = GL_FALSE; + /* 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.Program[MESA_SHADER_VERTEX].MaxTextureImageUnits = MAX_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.Program[MESA_SHADER_GEOMETRY].MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS; - 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 = 0x1fff7fffffffULL; + /* 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 */ - ctx->Const.ProfileMask = ctx->API == API_OPENGL_CORE + 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_texture_gather */ - ctx->Const.MinProgramTextureGatherOffset = -8; - ctx->Const.MaxProgramTextureGatherOffset = 7; + consts->MinProgramTextureGatherOffset = -8; + consts->MaxProgramTextureGatherOffset = 7; /* GL_ARB_robustness */ - ctx->Const.ResetStrategy = GL_NO_RESET_NOTIFICATION_ARB; - - /* PrimitiveRestart */ - ctx->Const.PrimitiveRestartInSoftware = GL_FALSE; + 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 */ - ctx->Const.MaxAtomicBufferBindings = MAX_COMBINED_ATOMIC_BUFFERS; - ctx->Const.MaxAtomicBufferSize = MAX_ATOMIC_COUNTERS * ATOMIC_COUNTER_SIZE; - ctx->Const.MaxCombinedAtomicBuffers = MAX_COMBINED_ATOMIC_BUFFERS; - ctx->Const.MaxCombinedAtomicCounters = MAX_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 */ - ctx->Const.MaxVertexAttribRelativeOffset = 2047; - ctx->Const.MaxVertexAttribBindings = MAX_VERTEX_GENERIC_ATTRIBS; + consts->MaxVertexAttribRelativeOffset = 2047; + consts->MaxVertexAttribBindings = MAX_VERTEX_GENERIC_ATTRIBS; /* GL_ARB_compute_shader */ - ctx->Const.MaxComputeWorkGroupSize[0] = 1024; - ctx->Const.MaxComputeWorkGroupSize[1] = 1024; - ctx->Const.MaxComputeWorkGroupSize[2] = 64; + 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; } @@ -715,6 +732,8 @@ _mesa_init_constants(struct gl_context *ctx) 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))); @@ -781,10 +800,10 @@ init_attrib_groups(struct gl_context *ctx) 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 ); @@ -806,6 +825,7 @@ init_attrib_groups(struct gl_context *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 ); @@ -877,10 +897,27 @@ _mesa_generic_nop(void) /** - * 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 @@ -895,8 +932,34 @@ _mesa_alloc_dispatch_table() _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; } @@ -1006,7 +1069,8 @@ _mesa_initialize_dispatch_tables(struct gl_context *ctx) * * \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 @@ -1026,12 +1090,20 @@ _mesa_initialize_context(struct gl_context *ctx, 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); } @@ -1070,10 +1142,10 @@ _mesa_initialize_context(struct gl_context *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; @@ -1125,7 +1197,7 @@ _mesa_initialize_context(struct gl_context *ctx, fail: _mesa_reference_shared_state(ctx, &ctx->Shared, NULL); free(ctx->BeginEnd); - free(ctx->Exec); + free(ctx->OutsideBeginEnd); free(ctx->Save); return GL_FALSE; } @@ -1138,7 +1210,8 @@ fail: * 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. @@ -1153,8 +1226,6 @@ _mesa_create_context(gl_api api, { struct gl_context *ctx; - ASSERT(visual); - ctx = calloc(1, sizeof(struct gl_context)); if (!ctx) return NULL; @@ -1197,6 +1268,9 @@ _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_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); @@ -1211,6 +1285,7 @@ _mesa_free_context_data( struct gl_context *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); @@ -1226,7 +1301,7 @@ _mesa_free_context_data( struct gl_context *ctx ) /* free dispatch tables */ free(ctx->BeginEnd); - free(ctx->Exec); + free(ctx->OutsideBeginEnd); free(ctx->Save); /* Shared context state (display lists, textures, etc) */ @@ -1467,6 +1542,57 @@ _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; + } + + 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 @@ -1510,9 +1636,11 @@ _mesa_make_current( struct gl_context *newCtx, } 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 */ @@ -1559,21 +1687,7 @@ _mesa_make_current( struct gl_context *newCtx, } 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(newCtx); - } - + handle_first_current(newCtx); newCtx->FirstTimeCurrent = GL_FALSE; } } @@ -1761,93 +1875,60 @@ _mesa_check_blend_func_error(struct gl_context *ctx) 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; - - /* This depends on having up to date derived state (shaders) */ - if (ctx->NewState) - _mesa_update_state(ctx); - - if (ctx->Shader.CurrentProgram[MESA_SHADER_VERTEX]) { - vert_from_glsl_shader = true; + if (shProg) { + *shader_present = true; - if (!ctx->Shader.CurrentProgram[MESA_SHADER_VERTEX]->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.CurrentProgram[MESA_SHADER_VERTEX], - errMsg)) { + if (!_mesa_validate_shader_program(ctx, shProg, errMsg)) { _mesa_warning(ctx, "Shader program %u is invalid: %s", - ctx->Shader.CurrentProgram[MESA_SHADER_VERTEX]->Name, errMsg); + shProg->Name, errMsg); } } #endif } - if (ctx->Shader.CurrentProgram[MESA_SHADER_GEOMETRY]) { - geom_from_glsl_shader = true; + return true; +} - if (!ctx->Shader.CurrentProgram[MESA_SHADER_GEOMETRY]->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[MESA_SHADER_GEOMETRY], - errMsg)) { - _mesa_warning(ctx, "Shader program %u is invalid: %s", - ctx->Shader.CurrentProgram[MESA_SHADER_GEOMETRY]->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.CurrentProgram[MESA_SHADER_FRAGMENT]) { - 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.CurrentProgram[MESA_SHADER_FRAGMENT]->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.CurrentProgram[MESA_SHADER_FRAGMENT], - errMsg)) { - _mesa_warning(ctx, "Shader program %u is invalid: %s", - ctx->Shader.CurrentProgram[MESA_SHADER_FRAGMENT]->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); @@ -1857,9 +1938,9 @@ _mesa_valid_to_render(struct gl_context *ctx, const char *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); @@ -1876,6 +1957,26 @@ _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)) { + 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); @@ -1887,8 +1988,8 @@ _mesa_valid_to_render(struct gl_context *ctx, const char *where) } #ifdef DEBUG - if (ctx->Shader.Flags & GLSL_LOG) { - struct gl_shader_program **shProg = ctx->Shader.CurrentProgram; + if (ctx->_Shader->Flags & GLSL_LOG) { + struct gl_shader_program **shProg = ctx->_Shader->CurrentProgram; gl_shader_stage i; for (i = 0; i < MESA_SHADER_STAGES; i++) {