X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fmain%2Fcontext.c;h=e94509ad773b872d8bbb2be82e8647e9ba396b0e;hb=5e78433eec94fcaa87bdcb2526ec0910a69ed347;hp=b20063c33b283d41366faf2f061cf72a59b7f627;hpb=2dfa33a5e9325bfe9adb3a15aba466e3f15eb2c5;p=mesa.git diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c index b20063c33b2..e94509ad773 100644 --- a/src/mesa/main/context.c +++ b/src/mesa/main/context.c @@ -18,9 +18,10 @@ * 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. */ /** @@ -77,10 +78,10 @@ #include "glheader.h" -#include "mfeatures.h" #include "imports.h" #include "accum.h" #include "api_exec.h" +#include "api_loopback.h" #include "arrayobj.h" #include "attrib.h" #include "blend.h" @@ -129,9 +130,7 @@ #include "vtxfmt.h" #include "program/program.h" #include "program/prog_print.h" -#if _HAVE_FULL_GL #include "math/m_matrix.h" -#endif #include "main/dispatch.h" /* for _gloffset_COUNT */ #ifdef USE_SPARC_ASM @@ -268,7 +267,7 @@ _mesa_initialize_visual( struct gl_config *vis, if (depthBits < 0 || depthBits > 32) { return GL_FALSE; } - if (stencilBits < 0 || stencilBits > STENCIL_BITS) { + if (stencilBits < 0 || stencilBits > 8) { return GL_FALSE; } assert(accumRedBits >= 0); @@ -345,23 +344,17 @@ dummy_enum_func(void) { gl_buffer_index bi = BUFFER_FRONT_LEFT; gl_face_index fi = FACE_POS_X; - gl_frag_attrib fa = FRAG_ATTRIB_WPOS; gl_frag_result fr = FRAG_RESULT_DEPTH; gl_texture_index ti = TEXTURE_2D_ARRAY_INDEX; gl_vert_attrib va = VERT_ATTRIB_POS; - gl_vert_result vr = VERT_RESULT_HPOS; - gl_geom_attrib ga = GEOM_ATTRIB_POSITION; - gl_geom_result gr = GEOM_RESULT_POS; + gl_varying_slot vs = VARYING_SLOT_POS; (void) bi; (void) fi; - (void) fa; (void) fr; (void) ti; (void) va; - (void) vr; - (void) ga; - (void) gr; + (void) vs; } @@ -404,11 +397,6 @@ one_time_init( struct gl_context *ctx ) _mesa_get_cpu_features(); - _mesa_init_sqrt_table(); - - /* context dependence is never a one-time thing... */ - _mesa_init_get_hash(ctx); - for (i = 0; i < 256; i++) { _mesa_ubyte_to_float_color_tab[i] = (float) i / 255.0F; } @@ -416,7 +404,7 @@ one_time_init( struct gl_context *ctx ) #if defined(DEBUG) && defined(__DATE__) && defined(__TIME__) if (MESA_VERBOSE != 0) { _mesa_debug(ctx, "Mesa %s DEBUG build %s %s\n", - MESA_VERSION_STRING, __DATE__, __TIME__); + PACKAGE_VERSION, __DATE__, __TIME__); } #endif @@ -427,14 +415,9 @@ one_time_init( struct gl_context *ctx ) /* per-API one-time init */ if (!(api_init_mask & (1 << ctx->API))) { - /* - * This is fine as ES does not use the remap table, but it may not be - * future-proof. We cannot always initialize the remap table because - * when an app is linked to libGLES*, there are not enough dynamic - * entries. - */ - if (ctx->API == API_OPENGL) - _mesa_init_remap_table(); + _mesa_init_get_hash(ctx); + + _mesa_init_remap_table(); } api_init_mask |= 1 << ctx->API; @@ -478,7 +461,8 @@ _mesa_init_current(struct gl_context *ctx) * Important: drivers should override these with actual limits. */ static void -init_program_limits(GLenum type, struct gl_program_constants *prog) +init_program_limits(struct gl_context *ctx, GLenum type, + struct gl_program_constants *prog) { prog->MaxInstructions = MAX_PROGRAM_INSTRUCTIONS; prog->MaxAluInstructions = MAX_PROGRAM_INSTRUCTIONS; @@ -492,7 +476,7 @@ init_program_limits(GLenum type, struct gl_program_constants *prog) switch (type) { case GL_VERTEX_PROGRAM_ARB: prog->MaxParameters = MAX_VERTEX_PROGRAM_PARAMS; - prog->MaxAttribs = MAX_NV_VERTEX_PROGRAM_INPUTS; + prog->MaxAttribs = MAX_VERTEX_GENERIC_ATTRIBS; prog->MaxAddressRegs = MAX_VERTEX_PROGRAM_ADDRESS_REGS; prog->MaxUniformComponents = 4 * MAX_UNIFORMS; break; @@ -503,8 +487,8 @@ init_program_limits(GLenum type, struct gl_program_constants *prog) prog->MaxUniformComponents = 4 * MAX_UNIFORMS; break; case MESA_GEOMETRY_PROGRAM: - prog->MaxParameters = MAX_NV_VERTEX_PROGRAM_PARAMS; - prog->MaxAttribs = MAX_NV_VERTEX_PROGRAM_INPUTS; + 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; break; @@ -542,6 +526,11 @@ init_program_limits(GLenum type, struct gl_program_constants *prog) prog->MediumInt.RangeMax = 24; prog->MediumInt.Precision = 0; prog->LowInt = prog->HighInt = prog->MediumInt; + + prog->MaxUniformBlocks = 12; + prog->MaxCombinedUniformComponents = (prog->MaxUniformComponents + + ctx->Const.MaxUniformBlockSize / 4 * + prog->MaxUniformBlocks); } @@ -563,12 +552,13 @@ _mesa_init_constants(struct gl_context *ctx) 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.FragmentProgram.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS; ctx->Const.MaxTextureUnits = MIN2(ctx->Const.MaxTextureCoordUnits, - ctx->Const.MaxTextureImageUnits); + ctx->Const.FragmentProgram.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; @@ -586,17 +576,19 @@ _mesa_init_constants(struct gl_context *ctx) ctx->Const.MaxLights = MAX_LIGHTS; ctx->Const.MaxShininess = 128.0; ctx->Const.MaxSpotExponent = 128.0; - ctx->Const.MaxViewportWidth = MAX_WIDTH; - ctx->Const.MaxViewportHeight = MAX_HEIGHT; -#if FEATURE_ARB_vertex_program - init_program_limits(GL_VERTEX_PROGRAM_ARB, &ctx->Const.VertexProgram); -#endif -#if FEATURE_ARB_fragment_program - init_program_limits(GL_FRAGMENT_PROGRAM_ARB, &ctx->Const.FragmentProgram); -#endif -#if FEATURE_ARB_geometry_shader4 - init_program_limits(MESA_GEOMETRY_PROGRAM, &ctx->Const.GeometryProgram); -#endif + ctx->Const.MaxViewportWidth = MAX_VIEWPORT_WIDTH; + ctx->Const.MaxViewportHeight = MAX_VIEWPORT_HEIGHT; + + /** GL_ARB_uniform_buffer_object */ + ctx->Const.MaxCombinedUniformBlocks = 36; + ctx->Const.MaxUniformBufferBindings = 36; + ctx->Const.MaxUniformBlockSize = 16384; + ctx->Const.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); + ctx->Const.MaxProgramMatrices = MAX_PROGRAM_MATRICES; ctx->Const.MaxProgramMatrixStackDepth = MAX_PROGRAM_MATRIX_STACK_DEPTH; @@ -606,27 +598,22 @@ _mesa_init_constants(struct gl_context *ctx) /* GL_ARB_draw_buffers */ ctx->Const.MaxDrawBuffers = MAX_DRAW_BUFFERS; -#if FEATURE_EXT_framebuffer_object ctx->Const.MaxColorAttachments = MAX_COLOR_ATTACHMENTS; - ctx->Const.MaxRenderbufferSize = MAX_WIDTH; -#endif + ctx->Const.MaxRenderbufferSize = MAX_RENDERBUFFER_SIZE; -#if FEATURE_ARB_vertex_shader - ctx->Const.MaxVertexTextureImageUnits = MAX_VERTEX_TEXTURE_IMAGE_UNITS; + ctx->Const.VertexProgram.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS; ctx->Const.MaxCombinedTextureImageUnits = MAX_COMBINED_TEXTURE_IMAGE_UNITS; - ctx->Const.MaxVarying = MAX_VARYING; -#endif -#if FEATURE_ARB_geometry_shader4 - ctx->Const.MaxGeometryTextureImageUnits = MAX_GEOMETRY_TEXTURE_IMAGE_UNITS; + ctx->Const.MaxVarying = 16; /* old limit not to break tnl and swrast */ + ctx->Const.GeometryProgram.MaxTextureImageUnits = MAX_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; -#endif /* Shading language version */ - if (ctx->API == API_OPENGL) { + 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; @@ -648,9 +635,10 @@ _mesa_init_constants(struct gl_context *ctx) ctx->Const.QuadsFollowProvokingVertexConvention = GL_TRUE; /* GL_EXT_transform_feedback */ - ctx->Const.MaxTransformFeedbackSeparateAttribs = MAX_FEEDBACK_ATTRIBS; + ctx->Const.MaxTransformFeedbackBuffers = MAX_FEEDBACK_BUFFERS; ctx->Const.MaxTransformFeedbackSeparateComponents = 4 * MAX_FEEDBACK_ATTRIBS; ctx->Const.MaxTransformFeedbackInterleavedComponents = 4 * MAX_FEEDBACK_ATTRIBS; + ctx->Const.MaxVertexStreams = 1; /* GL 3.2: hard-coded for now: */ ctx->Const.ProfileMask = GL_CONTEXT_COMPATIBILITY_PROFILE_BIT; @@ -661,6 +649,17 @@ _mesa_init_constants(struct gl_context *ctx) /* GL_ARB_robustness */ ctx->Const.ResetStrategy = GL_NO_RESET_NOTIFICATION_ARB; + + /* PrimitiveRestart */ + ctx->Const.PrimitiveRestartInSoftware = GL_FALSE; + + /* ES 3.0 or ARB_ES3_compatibility */ + ctx->Const.MaxElementIndex = 0xffffffffu; + + /* GL_ARB_texture_multisample */ + ctx->Const.MaxColorTextureSamples = 1; + ctx->Const.MaxDepthTextureSamples = 1; + ctx->Const.MaxIntegerSamples = 1; } @@ -672,37 +671,30 @@ static void check_context_limits(struct gl_context *ctx) { /* check that we don't exceed the size of various bitfields */ - assert(VERT_RESULT_MAX <= + assert(VARYING_SLOT_MAX <= (8 * sizeof(ctx->VertexProgram._Current->Base.OutputsWritten))); - assert(FRAG_ATTRIB_MAX <= + 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(MAX_NV_FRAGMENT_PROGRAM_TEMPS <= MAX_PROGRAM_TEMPS); - assert(MAX_NV_VERTEX_PROGRAM_TEMPS <= MAX_PROGRAM_TEMPS); - assert(MAX_NV_VERTEX_PROGRAM_INPUTS <= VERT_ATTRIB_MAX); - assert(MAX_NV_VERTEX_PROGRAM_OUTPUTS <= VERT_RESULT_MAX); - /* Texture unit checks */ - assert(ctx->Const.MaxTextureImageUnits > 0); - assert(ctx->Const.MaxTextureImageUnits <= MAX_TEXTURE_IMAGE_UNITS); + assert(ctx->Const.FragmentProgram.MaxTextureImageUnits > 0); + assert(ctx->Const.FragmentProgram.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.FragmentProgram.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.FragmentProgram.MaxTextureImageUnits); /* Texture size checks */ @@ -711,20 +703,15 @@ check_context_limits(struct gl_context *ctx) assert(ctx->Const.MaxCubeTextureLevels <= MAX_CUBE_TEXTURE_LEVELS); assert(ctx->Const.MaxTextureRectSize <= MAX_TEXTURE_RECT_SIZE); - /* make sure largest texture image is <= MAX_WIDTH in size */ - assert((1 << (ctx->Const.MaxTextureLevels - 1)) <= MAX_WIDTH); - assert((1 << (ctx->Const.MaxCubeTextureLevels - 1)) <= MAX_WIDTH); - assert((1 << (ctx->Const.Max3DTextureLevels - 1)) <= MAX_WIDTH); - /* Texture level checks */ assert(MAX_TEXTURE_LEVELS >= MAX_3D_TEXTURE_LEVELS); assert(MAX_TEXTURE_LEVELS >= MAX_CUBE_TEXTURE_LEVELS); /* Max texture size should be <= max viewport size (render to texture) */ - assert((1 << (MAX_TEXTURE_LEVELS - 1)) <= MAX_WIDTH); - - assert(ctx->Const.MaxViewportWidth <= MAX_WIDTH); - assert(ctx->Const.MaxViewportHeight <= MAX_WIDTH); + assert((1U << (ctx->Const.MaxTextureLevels - 1)) + <= ctx->Const.MaxViewportWidth); + assert((1U << (ctx->Const.MaxTextureLevels - 1)) + <= ctx->Const.MaxViewportHeight); assert(ctx->Const.MaxDrawBuffers <= MAX_DRAW_BUFFERS); @@ -763,6 +750,7 @@ init_attrib_groups(struct gl_context *ctx) _mesa_init_depth( ctx ); _mesa_init_debug( ctx ); _mesa_init_display_list( ctx ); + _mesa_init_errors( ctx ); _mesa_init_eval( ctx ); _mesa_init_fbobjects( ctx ); _mesa_init_feedback( ctx ); @@ -795,9 +783,10 @@ init_attrib_groups(struct gl_context *ctx) /* Miscellaneous */ ctx->NewState = _NEW_ALL; - ctx->ErrorValue = (GLenum) GL_NO_ERROR; - ctx->ResetStatus = (GLenum) GL_NO_ERROR; - ctx->varying_vp_inputs = ~0; + ctx->NewDriverState = ~0; + ctx->ErrorValue = GL_NO_ERROR; + ctx->ResetStatus = GL_NO_ERROR; + ctx->varying_vp_inputs = VERT_BIT_ALL; return GL_TRUE; } @@ -830,10 +819,13 @@ update_default_objects(struct gl_context *ctx) * This helps prevents a segfault when someone calls a GL function without * first checking if the extension's supported. */ -static int -generic_nop(void) +int +_mesa_generic_nop(void) { - _mesa_warning(NULL, "User called no-op dispatch function (an unsupported extension function?)"); + GET_CURRENT_CONTEXT(ctx); + _mesa_error(ctx, GL_INVALID_OPERATION, + "unsupported function called " + "(unsupported extension or deprecated function?)"); return 0; } @@ -842,7 +834,7 @@ generic_nop(void) * Allocate and initialize a new dispatch table. */ struct _glapi_table * -_mesa_alloc_dispatch_table(int size) +_mesa_alloc_dispatch_table() { /* 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 @@ -852,20 +844,101 @@ _mesa_alloc_dispatch_table(int size) GLint numEntries = MAX2(_glapi_get_dispatch_table_size(), _gloffset_COUNT); struct _glapi_table *table; - /* should never happen, but just in case */ - numEntries = MAX2(numEntries, size); - - table = (struct _glapi_table *) malloc(numEntries * sizeof(_glapi_proc)); + table = malloc(numEntries * sizeof(_glapi_proc)); if (table) { _glapi_proc *entry = (_glapi_proc *) table; GLint i; for (i = 0; i < numEntries; i++) { - entry[i] = (_glapi_proc) generic_nop; + entry[i] = (_glapi_proc) _mesa_generic_nop; } } return table; } +/** + * Creates a minimal dispatch table for use within glBegin()/glEnd(). + * + * This ensures that we generate GL_INVALID_OPERATION errors from most + * functions, since the set of functions that are valid within Begin/End is + * very small. + * + * From the GL 1.0 specification section 2.6.3, "GL Commands within + * Begin/End" + * + * "The only GL commands that are allowed within any Begin/End pairs are + * the commands for specifying vertex coordinates, vertex color, normal + * coordinates, and texture coordinates (Vertex, Color, Index, Normal, + * TexCoord), EvalCoord and EvalPoint commands (see section 5.1), + * commands for specifying lighting material parameters (Material + * commands see section 2.12.2), display list invocation commands + * (CallList and CallLists see section 5.4), and the EdgeFlag + * command. Executing Begin after Begin has already been executed but + * before an End is issued generates the INVALID OPERATION error, as does + * executing End without a previous corresponding Begin. Executing any + * other GL command within Begin/End results in the error INVALID + * OPERATION." + * + * The table entries for specifying vertex attributes are set up by + * install_vtxfmt() and _mesa_loopback_init_api_table(), and End() and dlists + * are set by install_vtxfmt() as well. + */ +static struct _glapi_table * +create_beginend_table(const struct gl_context *ctx) +{ + struct _glapi_table *table; + + table = _mesa_alloc_dispatch_table(); + if (!table) + return NULL; + + /* Fill in functions which return a value, since they should return some + * specific value even if they emit a GL_INVALID_OPERATION error from them + * being called within glBegin()/glEnd(). + */ +#define COPY_DISPATCH(func) SET_##func(table, GET_##func(ctx->Exec)) + + COPY_DISPATCH(GenLists); + COPY_DISPATCH(IsProgram); + COPY_DISPATCH(IsVertexArray); + COPY_DISPATCH(IsBuffer); + COPY_DISPATCH(IsEnabled); + COPY_DISPATCH(IsEnabledi); + COPY_DISPATCH(IsRenderbuffer); + COPY_DISPATCH(IsFramebuffer); + COPY_DISPATCH(CheckFramebufferStatus); + COPY_DISPATCH(RenderMode); + COPY_DISPATCH(GetString); + COPY_DISPATCH(GetStringi); + COPY_DISPATCH(GetPointerv); + COPY_DISPATCH(IsQuery); + COPY_DISPATCH(IsSampler); + COPY_DISPATCH(IsSync); + COPY_DISPATCH(IsTexture); + COPY_DISPATCH(IsTransformFeedback); + COPY_DISPATCH(DeleteQueries); + COPY_DISPATCH(AreTexturesResident); + COPY_DISPATCH(FenceSync); + COPY_DISPATCH(ClientWaitSync); + COPY_DISPATCH(MapBuffer); + COPY_DISPATCH(UnmapBuffer); + COPY_DISPATCH(MapBufferRange); + COPY_DISPATCH(ObjectPurgeableAPPLE); + COPY_DISPATCH(ObjectUnpurgeableAPPLE); + + _mesa_loopback_init_api_table(ctx, table); + + return table; +} + +void +_mesa_initialize_dispatch_tables(struct gl_context *ctx) +{ + /* Do the code-generated setup of the exec table in api_exec.c. */ + _mesa_initialize_exec_table(ctx); + + if (ctx->Save) + _mesa_initialize_save_table(ctx); +} /** * Initialize a struct gl_context struct (rendering context). @@ -892,20 +965,17 @@ _mesa_alloc_dispatch_table(int size) * etc with, or NULL * \param driverFunctions table of device driver functions for this context * to use - * \param driverContext pointer to driver-specific context data */ GLboolean _mesa_initialize_context(struct gl_context *ctx, gl_api api, const struct gl_config *visual, struct gl_context *share_list, - const struct dd_function_table *driverFunctions, - void *driverContext) + const struct dd_function_table *driverFunctions) { struct gl_shared_state *shared; int i; - /*ASSERT(driverContext);*/ assert(driverFunctions->NewTextureObject); assert(driverFunctions->FreeTextureImageBuffer); @@ -916,6 +986,10 @@ _mesa_initialize_context(struct gl_context *ctx, ctx->WinSysDrawBuffer = NULL; ctx->WinSysReadBuffer = NULL; + if (_mesa_is_desktop_gl(ctx)) { + _mesa_override_gl_version(ctx); + } + /* misc one-time initializations */ one_time_init(ctx); @@ -925,7 +999,6 @@ _mesa_initialize_context(struct gl_context *ctx, * textures. */ ctx->Driver = *driverFunctions; - ctx->DriverCtx = driverContext; if (share_list) { /* share state with another context */ @@ -938,45 +1011,17 @@ _mesa_initialize_context(struct gl_context *ctx, return GL_FALSE; } - _glthread_LOCK_MUTEX(shared->Mutex); - ctx->Shared = shared; - shared->RefCount++; - _glthread_UNLOCK_MUTEX(shared->Mutex); - - if (!init_attrib_groups( ctx )) { - _mesa_release_shared_state(ctx, ctx->Shared); - return GL_FALSE; - } + _mesa_reference_shared_state(ctx, &ctx->Shared, shared); -#if FEATURE_dispatch - /* setup the API dispatch tables */ - switch (ctx->API) { -#if FEATURE_GL - case API_OPENGL: - ctx->Exec = _mesa_create_exec_table(); - break; -#endif -#if FEATURE_ES1 - case API_OPENGLES: - ctx->Exec = _mesa_create_exec_table_es1(); - break; -#endif -#if FEATURE_ES2 - case API_OPENGLES2: - ctx->Exec = _mesa_create_exec_table_es2(); - break; -#endif - default: - _mesa_problem(ctx, "unknown or unsupported API"); - break; - } + if (!init_attrib_groups( ctx )) + goto fail; - if (!ctx->Exec) { - _mesa_release_shared_state(ctx, ctx->Shared); - return GL_FALSE; - } -#endif - ctx->CurrentDispatch = ctx->Exec; + /* setup the API dispatch tables with all nop functions */ + ctx->OutsideBeginEnd = _mesa_alloc_dispatch_table(); + if (!ctx->OutsideBeginEnd) + goto fail; + ctx->Exec = ctx->OutsideBeginEnd; + ctx->CurrentDispatch = ctx->OutsideBeginEnd; ctx->FragmentProgram._MaintainTexEnvProgram = (_mesa_getenv("MESA_TEX_PROG") != NULL); @@ -997,17 +1042,14 @@ _mesa_initialize_context(struct gl_context *ctx, sizeof(ctx->TextureFormatSupported)); switch (ctx->API) { - case API_OPENGL: -#if FEATURE_dlist - ctx->Save = _mesa_create_save_table(); - if (!ctx->Save) { - _mesa_release_shared_state(ctx, ctx->Shared); - free(ctx->Exec); - return GL_FALSE; - } - - _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt ); -#endif + case API_OPENGL_COMPAT: + ctx->BeginEnd = create_beginend_table(ctx); + ctx->Save = _mesa_alloc_dispatch_table(); + if (!ctx->BeginEnd || !ctx->Save) + goto fail; + + /* fall-through */ + case API_OPENGL_CORE: break; case API_OPENGLES: /** @@ -1027,13 +1069,19 @@ _mesa_initialize_context(struct gl_context *ctx, case API_OPENGLES2: ctx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE; ctx->VertexProgram._MaintainTnlProgram = GL_TRUE; - ctx->Point.PointSprite = GL_TRUE; /* always on for ES 2.x */ break; } ctx->FirstTimeCurrent = GL_TRUE; return GL_TRUE; + +fail: + _mesa_reference_shared_state(ctx, &ctx->Shared, NULL); + free(ctx->BeginEnd); + free(ctx->Exec); + free(ctx->Save); + return GL_FALSE; } @@ -1048,7 +1096,6 @@ _mesa_initialize_context(struct gl_context *ctx, * \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. - * \param driverContext points to the device driver's private context state * * \return pointer to a new __struct gl_contextRec or NULL if error. */ @@ -1056,20 +1103,18 @@ 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, - void *driverContext) + const struct dd_function_table *driverFunctions) { struct gl_context *ctx; ASSERT(visual); - /*ASSERT(driverContext);*/ - ctx = (struct gl_context *) calloc(1, sizeof(struct gl_context)); + ctx = calloc(1, sizeof(struct gl_context)); if (!ctx) return NULL; if (_mesa_initialize_context(ctx, api, visual, share_list, - driverFunctions, driverContext)) { + driverFunctions)) { return ctx; } else { @@ -1110,6 +1155,9 @@ _mesa_free_context_data( struct gl_context *ctx ) _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_free_attrib_data(ctx); _mesa_free_buffer_objects(ctx); _mesa_free_lighting_data( ctx ); @@ -1124,34 +1172,27 @@ _mesa_free_context_data( struct gl_context *ctx ) _mesa_free_varray_data(ctx); _mesa_free_transform_feedback(ctx); - _mesa_delete_array_object(ctx, ctx->Array.DefaultArrayObj); - -#if FEATURE_ARB_pixel_buffer_object _mesa_reference_buffer_object(ctx, &ctx->Pack.BufferObj, NULL); _mesa_reference_buffer_object(ctx, &ctx->Unpack.BufferObj, NULL); _mesa_reference_buffer_object(ctx, &ctx->DefaultPacking.BufferObj, NULL); -#endif - -#if FEATURE_ARB_vertex_buffer_object _mesa_reference_buffer_object(ctx, &ctx->Array.ArrayBufferObj, NULL); - _mesa_reference_buffer_object(ctx, &ctx->Array.ElementArrayBufferObj, NULL); -#endif /* free dispatch tables */ + free(ctx->BeginEnd); free(ctx->Exec); free(ctx->Save); /* Shared context state (display lists, textures, etc) */ - _mesa_release_shared_state( ctx, ctx->Shared ); + _mesa_reference_shared_state(ctx, &ctx->Shared, NULL); /* needs to be after freeing shared state */ _mesa_free_display_list_data(ctx); - if (ctx->Extensions.String) - free((void *) ctx->Extensions.String); + _mesa_free_errors_data(ctx); + + free((void *)ctx->Extensions.String); - if (ctx->VersionString) - free(ctx->VersionString); + free(ctx->VersionString); /* unbind the context if it's currently bound */ if (ctx == _mesa_get_current_context()) { @@ -1177,7 +1218,6 @@ _mesa_destroy_context( struct gl_context *ctx ) } -#if _HAVE_FULL_GL /** * Copy attribute groups from one context to another. * @@ -1296,8 +1336,8 @@ _mesa_copy_context( const struct gl_context *src, struct gl_context *dst, /* XXX FIXME: Call callbacks? */ dst->NewState = _NEW_ALL; + dst->NewDriverState = ~0; } -#endif /** @@ -1446,8 +1486,8 @@ _mesa_make_current( struct gl_context *newCtx, _glapi_set_dispatch(newCtx->CurrentDispatch); if (drawBuffer && readBuffer) { - ASSERT(drawBuffer->Name == 0); - ASSERT(readBuffer->Name == 0); + ASSERT(_mesa_is_winsys_fbo(drawBuffer)); + ASSERT(_mesa_is_winsys_fbo(readBuffer)); _mesa_reference_framebuffer(&newCtx->WinSysDrawBuffer, drawBuffer); _mesa_reference_framebuffer(&newCtx->WinSysReadBuffer, readBuffer); @@ -1455,7 +1495,7 @@ _mesa_make_current( struct gl_context *newCtx, * Only set the context's Draw/ReadBuffer fields if they're NULL * or not bound to a user-created FBO. */ - if (!newCtx->DrawBuffer || newCtx->DrawBuffer->Name == 0) { + if (!newCtx->DrawBuffer || _mesa_is_winsys_fbo(newCtx->DrawBuffer)) { _mesa_reference_framebuffer(&newCtx->DrawBuffer, drawBuffer); /* Update the FBO's list of drawbuffers/renderbuffers. * For winsys FBOs this comes from the GL state (which may have @@ -1463,7 +1503,7 @@ _mesa_make_current( struct gl_context *newCtx, */ _mesa_update_draw_buffers(newCtx); } - if (!newCtx->ReadBuffer || newCtx->ReadBuffer->Name == 0) { + if (!newCtx->ReadBuffer || _mesa_is_winsys_fbo(newCtx->ReadBuffer)) { _mesa_reference_framebuffer(&newCtx->ReadBuffer, readBuffer); } @@ -1474,8 +1514,6 @@ _mesa_make_current( struct gl_context *newCtx, #if 1 /* We want to get rid of these lines: */ - -#if _HAVE_FULL_GL if (!drawBuffer->Initialized) { initialize_framebuffer_size(newCtx, drawBuffer); } @@ -1484,8 +1522,6 @@ _mesa_make_current( struct gl_context *newCtx, } _mesa_resizebuffers(newCtx); -#endif - #else /* We want the drawBuffer and readBuffer to be initialized by * the driver. @@ -1509,7 +1545,7 @@ _mesa_make_current( struct gl_context *newCtx, } if (newCtx->FirstTimeCurrent) { - _mesa_compute_version(newCtx); + assert(newCtx->Version > 0); newCtx->Extensions.String = _mesa_make_extension_string(newCtx); @@ -1542,17 +1578,18 @@ GLboolean _mesa_share_state(struct gl_context *ctx, struct gl_context *ctxToShare) { if (ctx && ctxToShare && ctx->Shared && ctxToShare->Shared) { - struct gl_shared_state *oldSharedState = ctx->Shared; + struct gl_shared_state *oldShared = NULL; + + /* save ref to old state to prevent it from being deleted immediately */ + _mesa_reference_shared_state(ctx, &oldShared, ctx->Shared); - ctx->Shared = ctxToShare->Shared; - - _glthread_LOCK_MUTEX(ctx->Shared->Mutex); - ctx->Shared->RefCount++; - _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + /* update ctx's Shared pointer */ + _mesa_reference_shared_state(ctx, &ctx->Shared, ctxToShare->Shared); update_default_objects(ctx); - _mesa_release_shared_state(ctx, oldSharedState); + /* release the old shared state */ + _mesa_reference_shared_state(ctx, &oldShared, NULL); return GL_TRUE; } @@ -1624,11 +1661,6 @@ _mesa_record_error(struct gl_context *ctx, GLenum error) if (ctx->ErrorValue == GL_NO_ERROR) { ctx->ErrorValue = error; } - - /* Call device driver's error handler, if any. This is used on the Mac. */ - if (ctx->Driver.Error) { - ctx->Driver.Error(ctx); - } } @@ -1638,6 +1670,7 @@ _mesa_record_error(struct gl_context *ctx, GLenum error) void _mesa_finish(struct gl_context *ctx) { + FLUSH_VERTICES( ctx, 0 ); FLUSH_CURRENT( ctx, 0 ); if (ctx->Driver.Finish) { ctx->Driver.Finish(ctx); @@ -1651,6 +1684,7 @@ _mesa_finish(struct gl_context *ctx) void _mesa_flush(struct gl_context *ctx) { + FLUSH_VERTICES( ctx, 0 ); FLUSH_CURRENT( ctx, 0 ); if (ctx->Driver.Flush) { ctx->Driver.Flush(ctx); @@ -1669,7 +1703,7 @@ void GLAPIENTRY _mesa_Finish(void) { GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); _mesa_finish(ctx); } @@ -1684,7 +1718,7 @@ void GLAPIENTRY _mesa_Flush(void) { GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); _mesa_flush(ctx); } @@ -1701,7 +1735,29 @@ _mesa_set_mvp_with_dp4( struct gl_context *ctx, ctx->mvp_with_dp4 = flag; } - +/* + * ARB_blend_func_extended - ERRORS section + * "The error INVALID_OPERATION is generated by Begin or any procedure that + * implicitly calls Begin if any draw buffer has a blend function requiring the + * second color input (SRC1_COLOR, ONE_MINUS_SRC1_COLOR, SRC1_ALPHA or + * ONE_MINUS_SRC1_ALPHA), and a framebuffer is bound that has more than + * the value of MAX_DUAL_SOURCE_DRAW_BUFFERS-1 active color attachements." + */ +static GLboolean +_mesa_check_blend_func_error(struct gl_context *ctx) +{ + GLuint i; + for (i = ctx->Const.MaxDualSourceDrawBuffers; + i < ctx->DrawBuffer->_NumColorDrawBuffers; + i++) { + if (ctx->Color.Blend[i]._UsesDualSrc) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "dual source blend on illegal attachment"); + return GL_FALSE; + } + } + return GL_TRUE; +} /** * Prior to drawing anything with glBegin, glDrawArrays, etc. this function @@ -1822,6 +1878,10 @@ _mesa_valid_to_render(struct gl_context *ctx, const char *where) return GL_FALSE; } + if (_mesa_check_blend_func_error(ctx) == GL_FALSE) { + return GL_FALSE; + } + #ifdef DEBUG if (ctx->Shader.Flags & GLSL_LOG) { struct gl_shader_program *shProg[MESA_SHADER_TYPES]; @@ -1832,8 +1892,6 @@ _mesa_valid_to_render(struct gl_context *ctx, const char *where) shProg[MESA_SHADER_FRAGMENT] = ctx->Shader.CurrentFragmentProgram; for (i = 0; i < MESA_SHADER_TYPES; i++) { - struct gl_shader *sh; - if (shProg[i] == NULL || shProg[i]->_Used || shProg[i]->_LinkedShaders[i] == NULL) continue; @@ -1841,29 +1899,13 @@ _mesa_valid_to_render(struct gl_context *ctx, const char *where) /* This is the first time this shader is being used. * Append shader's constants/uniforms to log file. * - * The logic is a little odd here. We only want to log data for each - * shader target that will actually be used, and we only want to log - * it once. It's possible to have a program bound to the vertex + * Only log data for the program target that matches the shader + * target. It's possible to have a program bound to the vertex * shader target that also supplied a fragment shader. If that * program isn't also bound to the fragment shader target we don't * want to log its fragment data. */ - sh = shProg[i]->_LinkedShaders[i]; - switch (sh->Type) { - case GL_VERTEX_SHADER: - _mesa_append_uniforms_to_file(sh, &shProg[i]->VertexProgram->Base); - break; - - case GL_GEOMETRY_SHADER_ARB: - _mesa_append_uniforms_to_file(sh, - &shProg[i]->GeometryProgram->Base); - break; - - case GL_FRAGMENT_SHADER: - _mesa_append_uniforms_to_file(sh, - &shProg[i]->FragmentProgram->Base); - break; - } + _mesa_append_uniforms_to_file(shProg[i]->_LinkedShaders[i]); } for (i = 0; i < MESA_SHADER_TYPES; i++) {