X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fmain%2Fcontext.c;h=aa9d11299961a1c31f73d40b2365974e1c92867d;hb=28876dd511ec2c9d5f5500499201df2588e8c7f1;hp=7ff45cffe8b9458a987f1e7c6e8190a8894ffb00;hpb=3e6ef125f06cf036831063e46ee08bd17c4c4417;p=mesa.git diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c index 7ff45cffe8b..aa9d1129996 100644 --- a/src/mesa/main/context.c +++ b/src/mesa/main/context.c @@ -6,9 +6,9 @@ /* * Mesa 3-D graphics library - * Version: 6.5 + * Version: 7.1 * - * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -95,24 +95,19 @@ #include "fbobject.h" #include "feedback.h" #include "fog.h" +#include "framebuffer.h" #include "get.h" -#include "glthread.h" -#include "glapioffsets.h" #include "histogram.h" #include "hint.h" #include "hash.h" -#include "atifragshader.h" #include "light.h" #include "lines.h" #include "macros.h" #include "matrix.h" -#include "occlude.h" #include "pixel.h" #include "points.h" #include "polygon.h" -#if FEATURE_NV_vertex_program || FEATURE_NV_fragment_program -#include "program.h" -#endif +#include "queryobj.h" #include "rastpos.h" #include "simple_list.h" #include "state.h" @@ -125,13 +120,18 @@ #include "varray.h" #include "version.h" #include "vtxfmt.h" +#include "glapi/glthread.h" +#if FEATURE_NV_vertex_program || FEATURE_NV_fragment_program +#include "shader/program.h" +#endif +#include "shader/shader_api.h" +#include "shader/atifragshader.h" #if _HAVE_FULL_GL #include "math/m_translate.h" #include "math/m_matrix.h" #include "math/m_xform.h" #include "math/mathmod.h" #endif -#include "shaderobjects.h" #ifdef USE_SPARC_ASM #include "sparc/sparc.h" @@ -149,174 +149,7 @@ int MESA_DEBUG_FLAGS = 0; /* ubyte -> float conversion */ GLfloat _mesa_ubyte_to_float_color_tab[256]; -static void -free_shared_state( GLcontext *ctx, struct gl_shared_state *ss ); - - -/**********************************************************************/ -/** \name OpenGL SI-style interface (new in Mesa 3.5) - * - * \if subset - * \note Most of these functions are never called in the Mesa subset. - * \endif - */ -/*@{*/ - -/** - * Destroy context callback. - * - * \param gc context. - * \return GL_TRUE on success, or GL_FALSE on failure. - * - * \ifnot subset - * Called by window system/device driver (via __GLexports::destroyCurrent) when - * the rendering context is to be destroyed. - * \endif - * - * Frees the context data and the context structure. - */ -GLboolean -_mesa_destroyContext(__GLcontext *gc) -{ - if (gc) { - _mesa_free_context_data(gc); - _mesa_free(gc); - } - return GL_TRUE; -} - -/** - * Unbind context callback. - * - * \param gc context. - * \return GL_TRUE on success, or GL_FALSE on failure. - * - * \ifnot subset - * Called by window system/device driver (via __GLexports::loseCurrent) - * when the rendering context is made non-current. - * \endif - * - * No-op - */ -GLboolean -_mesa_loseCurrent(__GLcontext *gc) -{ - /* XXX unbind context from thread */ - (void) gc; - return GL_TRUE; -} - -/** - * Bind context callback. - * - * \param gc context. - * \return GL_TRUE on success, or GL_FALSE on failure. - * - * \ifnot subset - * Called by window system/device driver (via __GLexports::makeCurrent) - * when the rendering context is made current. - * \endif - * - * No-op - */ -GLboolean -_mesa_makeCurrent(__GLcontext *gc) -{ - /* XXX bind context to thread */ - (void) gc; - return GL_TRUE; -} -/** - * Share context callback. - * - * \param gc context. - * \param gcShare shared context. - * \return GL_TRUE on success, or GL_FALSE on failure. - * - * \ifnot subset - * Called by window system/device driver (via __GLexports::shareContext) - * \endif - * - * Update the shared context reference count, gl_shared_state::RefCount. - */ -GLboolean -_mesa_shareContext(__GLcontext *gc, __GLcontext *gcShare) -{ - if (gc && gcShare && gc->Shared && gcShare->Shared) { - gc->Shared->RefCount--; - if (gc->Shared->RefCount == 0) { - free_shared_state(gc, gc->Shared); - } - gc->Shared = gcShare->Shared; - gc->Shared->RefCount++; - return GL_TRUE; - } - else { - return GL_FALSE; - } -} - - -#if _HAVE_FULL_GL -/** - * Copy context callback. - */ -GLboolean -_mesa_copyContext(__GLcontext *dst, const __GLcontext *src, GLuint mask) -{ - if (dst && src) { - _mesa_copy_context( src, dst, mask ); - return GL_TRUE; - } - else { - return GL_FALSE; - } -} -#endif - -/** No-op */ -GLboolean -_mesa_forceCurrent(__GLcontext *gc) -{ - (void) gc; - return GL_TRUE; -} - -/** - * Windows/buffer resizing notification callback. - * - * \param gc GL context. - * \return GL_TRUE on success, or GL_FALSE on failure. - */ -GLboolean -_mesa_notifyResize(__GLcontext *gc) -{ - GLint x, y; - GLuint width, height; - __GLdrawablePrivate *d = gc->imports.getDrawablePrivate(gc); - if (!d || !d->getDrawableSize) - return GL_FALSE; - d->getDrawableSize( d, &x, &y, &width, &height ); - /* update viewport, resize software buffers, etc. */ - return GL_TRUE; -} - -/** - * Window/buffer destruction notification callback. - * - * \param gc GL context. - * - * Called when the context's window/buffer is going to be destroyed. - * - * No-op - */ -void -_mesa_notifyDestroy(__GLcontext *gc) -{ - /* Unbind from it. */ - (void) gc; -} /** * Swap buffers notification callback. @@ -332,105 +165,6 @@ _mesa_notifySwapBuffers(__GLcontext *gc) FLUSH_VERTICES( gc, 0 ); } -/** No-op */ -struct __GLdispatchStateRec * -_mesa_dispatchExec(__GLcontext *gc) -{ - (void) gc; - return NULL; -} - -/** No-op */ -void -_mesa_beginDispatchOverride(__GLcontext *gc) -{ - (void) gc; -} - -/** No-op */ -void -_mesa_endDispatchOverride(__GLcontext *gc) -{ - (void) gc; -} - -/** - * \ifnot subset - * Setup the exports. - * - * The window system will call these functions when it needs Mesa to do - * something. - * - * \note Device drivers should override these functions! For example, - * the Xlib driver should plug in the XMesa*-style functions into this - * structure. The XMesa-style functions should then call the _mesa_* - * version of these functions. This is an approximation to OO design - * (inheritance and virtual functions). - * \endif - * - * \if subset - * No-op. - * - * \endif - */ -static void -_mesa_init_default_exports(__GLexports *exports) -{ -#if _HAVE_FULL_GL - exports->destroyContext = _mesa_destroyContext; - exports->loseCurrent = _mesa_loseCurrent; - exports->makeCurrent = _mesa_makeCurrent; - exports->shareContext = _mesa_shareContext; - exports->copyContext = _mesa_copyContext; - exports->forceCurrent = _mesa_forceCurrent; - exports->notifyResize = _mesa_notifyResize; - exports->notifyDestroy = _mesa_notifyDestroy; - exports->notifySwapBuffers = _mesa_notifySwapBuffers; - exports->dispatchExec = _mesa_dispatchExec; - exports->beginDispatchOverride = _mesa_beginDispatchOverride; - exports->endDispatchOverride = _mesa_endDispatchOverride; -#else - (void) exports; -#endif -} - -/** - * Exported OpenGL SI interface. - */ -__GLcontext * -__glCoreCreateContext(__GLimports *imports, __GLcontextModes *modes) -{ - GLcontext *ctx; - - ctx = (GLcontext *) (*imports->calloc)(NULL, 1, sizeof(GLcontext)); - if (ctx == NULL) { - return NULL; - } - - /* XXX doesn't work at this time */ - _mesa_initialize_context(ctx, modes, NULL, NULL, NULL); - ctx->imports = *imports; - - return ctx; -} - -/** - * Exported OpenGL SI interface. - */ -void -__glCoreNopDispatch(void) -{ -#if 0 - /* SI */ - __gl_dispatch = __glNopDispatchState; -#else - /* Mesa */ - _glapi_set_dispatch(NULL); -#endif -} - -/*@}*/ - /**********************************************************************/ /** \name GL Visual allocation/destruction */ @@ -625,6 +359,8 @@ one_time_init( GLcontext *ctx ) assert( sizeof(GLint) == 4 ); assert( sizeof(GLuint) == 4 ); + _mesa_init_sqrt_table(); + #if _HAVE_FULL_GL _math_init(); @@ -682,12 +418,14 @@ alloc_shared_state( GLcontext *ctx ) #endif #if FEATURE_ARB_vertex_program - ss->DefaultVertexProgram = ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0); + ss->DefaultVertexProgram = (struct gl_vertex_program *) + ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0); if (!ss->DefaultVertexProgram) goto cleanup; #endif #if FEATURE_ARB_fragment_program - ss->DefaultFragmentProgram = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0); + ss->DefaultFragmentProgram = (struct gl_fragment_program *) + ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0); if (!ss->DefaultFragmentProgram) goto cleanup; #endif @@ -705,7 +443,7 @@ alloc_shared_state( GLcontext *ctx ) ss->ArrayObjects = _mesa_NewHashTable(); #if FEATURE_ARB_shader_objects - ss->GL2Objects = _mesa_NewHashTable (); + ss->ShaderObjects = _mesa_NewHashTable(); #endif ss->Default1D = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_1D); @@ -728,17 +466,20 @@ alloc_shared_state( GLcontext *ctx ) if (!ss->DefaultRect) goto cleanup; - /* Effectively bind the default textures to all texture units */ - ss->Default1D->RefCount += MAX_TEXTURE_IMAGE_UNITS; - ss->Default2D->RefCount += MAX_TEXTURE_IMAGE_UNITS; - ss->Default3D->RefCount += MAX_TEXTURE_IMAGE_UNITS; - ss->DefaultCubeMap->RefCount += MAX_TEXTURE_IMAGE_UNITS; - ss->DefaultRect->RefCount += MAX_TEXTURE_IMAGE_UNITS; + ss->Default1DArray = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_1D_ARRAY_EXT); + if (!ss->Default1DArray) + goto cleanup; + + ss->Default2DArray = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_2D_ARRAY_EXT); + if (!ss->Default2DArray) + goto cleanup; + + /* sanity check */ + assert(ss->Default1D->RefCount == 1); _glthread_INIT_MUTEX(ss->TexMutex); ss->TextureStateStamp = 0; - #if FEATURE_EXT_framebuffer_object ss->FrameBuffers = _mesa_NewHashTable(); if (!ss->FrameBuffers) @@ -748,10 +489,9 @@ alloc_shared_state( GLcontext *ctx ) goto cleanup; #endif - return GL_TRUE; - cleanup: +cleanup: /* Ran out of memory at some point. Free everything and return NULL */ if (ss->DisplayList) _mesa_DeleteHashTable(ss->DisplayList); @@ -762,12 +502,10 @@ alloc_shared_state( GLcontext *ctx ) _mesa_DeleteHashTable(ss->Programs); #endif #if FEATURE_ARB_vertex_program - if (ss->DefaultVertexProgram) - ctx->Driver.DeleteProgram(ctx, ss->DefaultVertexProgram); + _mesa_reference_vertprog(ctx, &ss->DefaultVertexProgram, NULL); #endif #if FEATURE_ARB_fragment_program - if (ss->DefaultFragmentProgram) - ctx->Driver.DeleteProgram(ctx, ss->DefaultFragmentProgram); + _mesa_reference_fragprog(ctx, &ss->DefaultFragmentProgram, NULL); #endif #if FEATURE_ATI_fragment_shader if (ss->DefaultFragmentShader) @@ -782,8 +520,8 @@ alloc_shared_state( GLcontext *ctx ) _mesa_DeleteHashTable (ss->ArrayObjects); #if FEATURE_ARB_shader_objects - if (ss->GL2Objects) - _mesa_DeleteHashTable (ss->GL2Objects); + if (ss->ShaderObjects) + _mesa_DeleteHashTable (ss->ShaderObjects); #endif #if FEATURE_EXT_framebuffer_object @@ -803,8 +541,13 @@ alloc_shared_state( GLcontext *ctx ) (*ctx->Driver.DeleteTexture)(ctx, ss->DefaultCubeMap); if (ss->DefaultRect) (*ctx->Driver.DeleteTexture)(ctx, ss->DefaultRect); - if (ss) - _mesa_free(ss); + if (ss->Default1DArray) + (*ctx->Driver.DeleteTexture)(ctx, ss->Default1DArray); + if (ss->Default2DArray) + (*ctx->Driver.DeleteTexture)(ctx, ss->Default2DArray); + + _mesa_free(ss); + return GL_FALSE; } @@ -839,6 +582,8 @@ delete_program_cb(GLuint id, void *data, void *userData) { struct gl_program *prog = (struct gl_program *) data; GLcontext *ctx = (GLcontext *) userData; + ASSERT(prog->RefCount == 1); /* should only be referenced by hash table */ + prog->RefCount = 0; /* now going away */ ctx->Driver.DeleteProgram(ctx, prog); } @@ -877,15 +622,72 @@ delete_arrayobj_cb(GLuint id, void *data, void *userData) } /** - * Callback for deleting an shader object. Called by _mesa_HashDeleteAll(). + * Callback for freeing shader program data. Call it before delete_shader_cb + * to avoid memory access error. */ static void -delete_shaderobj_cb(GLuint id, void *data, void *userData) +free_shader_program_data_cb(GLuint id, void *data, void *userData) { - /* XXX probably need to fix this */ - _mesa_free(data); + GLcontext *ctx = (GLcontext *) userData; + struct gl_shader_program *shProg = (struct gl_shader_program *) data; + + if (shProg->Type == GL_SHADER_PROGRAM_MESA) { + _mesa_free_shader_program_data(ctx, shProg); + } } +/** + * Callback for deleting shader and shader programs objects. + * Called by _mesa_HashDeleteAll(). + */ +static void +delete_shader_cb(GLuint id, void *data, void *userData) +{ + GLcontext *ctx = (GLcontext *) userData; + struct gl_shader *sh = (struct gl_shader *) data; + if (sh->Type == GL_FRAGMENT_SHADER || sh->Type == GL_VERTEX_SHADER) { + _mesa_free_shader(ctx, sh); + } + else { + struct gl_shader_program *shProg = (struct gl_shader_program *) data; + ASSERT(shProg->Type == GL_SHADER_PROGRAM_MESA); + _mesa_free_shader_program(ctx, shProg); + } +} + +/** + * Callback for deleting a framebuffer object. Called by _mesa_HashDeleteAll() + */ +static void +delete_framebuffer_cb(GLuint id, void *data, void *userData) +{ + struct gl_framebuffer *fb = (struct gl_framebuffer *) data; + /* The fact that the framebuffer is in the hashtable means its refcount + * is one, but we're removing from the hashtable now. So clear refcount. + */ + /*assert(fb->RefCount == 1);*/ + fb->RefCount = 0; + + /* NOTE: Delete should always be defined but there are two reports + * of it being NULL (bugs 13507, 14293). Work-around for now. + */ + if (fb->Delete) + fb->Delete(fb); +} + +/** + * Callback for deleting a renderbuffer object. Called by _mesa_HashDeleteAll() + */ +static void +delete_renderbuffer_cb(GLuint id, void *data, void *userData) +{ + struct gl_renderbuffer *rb = (struct gl_renderbuffer *) data; + rb->RefCount = 0; /* see comment for FBOs above */ + if (rb->Delete) + rb->Delete(rb); +} + + /** * Deallocate a shared state object and all children structures. @@ -908,29 +710,21 @@ free_shared_state( GLcontext *ctx, struct gl_shared_state *ss ) _mesa_HashDeleteAll(ss->DisplayList, delete_displaylist_cb, ctx); _mesa_DeleteHashTable(ss->DisplayList); - /* - * Free texture objects - */ - ASSERT(ctx->Driver.DeleteTexture); - /* the default textures */ - ctx->Driver.DeleteTexture(ctx, ss->Default1D); - ctx->Driver.DeleteTexture(ctx, ss->Default2D); - ctx->Driver.DeleteTexture(ctx, ss->Default3D); - ctx->Driver.DeleteTexture(ctx, ss->DefaultCubeMap); - ctx->Driver.DeleteTexture(ctx, ss->DefaultRect); - /* all other textures */ - _mesa_HashDeleteAll(ss->TexObjects, delete_texture_cb, ctx); - _mesa_DeleteHashTable(ss->TexObjects); +#if FEATURE_ARB_shader_objects + _mesa_HashWalk(ss->ShaderObjects, free_shader_program_data_cb, ctx); + _mesa_HashDeleteAll(ss->ShaderObjects, delete_shader_cb, ctx); + _mesa_DeleteHashTable(ss->ShaderObjects); +#endif #if defined(FEATURE_NV_vertex_program) || defined(FEATURE_NV_fragment_program) _mesa_HashDeleteAll(ss->Programs, delete_program_cb, ctx); _mesa_DeleteHashTable(ss->Programs); #endif #if FEATURE_ARB_vertex_program - _mesa_delete_program(ctx, ss->DefaultVertexProgram); + _mesa_reference_vertprog(ctx, &ss->DefaultVertexProgram, NULL); #endif #if FEATURE_ARB_fragment_program - _mesa_delete_program(ctx, ss->DefaultFragmentProgram); + _mesa_reference_fragprog(ctx, &ss->DefaultFragmentProgram, NULL); #endif #if FEATURE_ATI_fragment_shader @@ -947,16 +741,30 @@ free_shared_state( GLcontext *ctx, struct gl_shared_state *ss ) _mesa_HashDeleteAll(ss->ArrayObjects, delete_arrayobj_cb, ctx); _mesa_DeleteHashTable(ss->ArrayObjects); -#if FEATURE_ARB_shader_objects - _mesa_HashDeleteAll(ss->GL2Objects, delete_shaderobj_cb, ctx); - _mesa_DeleteHashTable(ss->GL2Objects); -#endif - #if FEATURE_EXT_framebuffer_object + _mesa_HashDeleteAll(ss->FrameBuffers, delete_framebuffer_cb, ctx); _mesa_DeleteHashTable(ss->FrameBuffers); + _mesa_HashDeleteAll(ss->RenderBuffers, delete_renderbuffer_cb, ctx); _mesa_DeleteHashTable(ss->RenderBuffers); #endif + /* + * Free texture objects (after FBOs since some textures might have + * been bound to FBOs). + */ + ASSERT(ctx->Driver.DeleteTexture); + /* the default textures */ + ctx->Driver.DeleteTexture(ctx, ss->Default1D); + ctx->Driver.DeleteTexture(ctx, ss->Default2D); + ctx->Driver.DeleteTexture(ctx, ss->Default3D); + ctx->Driver.DeleteTexture(ctx, ss->DefaultCubeMap); + ctx->Driver.DeleteTexture(ctx, ss->DefaultRect); + ctx->Driver.DeleteTexture(ctx, ss->Default1DArray); + ctx->Driver.DeleteTexture(ctx, ss->Default2DArray); + /* all other textures */ + _mesa_HashDeleteAll(ss->TexObjects, delete_texture_cb, ctx); + _mesa_DeleteHashTable(ss->TexObjects); + _glthread_DESTROY_MUTEX(ss->Mutex); _mesa_free(ss); @@ -967,7 +775,7 @@ free_shared_state( GLcontext *ctx, struct gl_shared_state *ss ) * Initialize fields of gl_current_attrib (aka ctx->Current.*) */ static void -_mesa_init_current( GLcontext *ctx ) +_mesa_init_current(GLcontext *ctx) { GLuint i; @@ -977,13 +785,12 @@ _mesa_init_current( GLcontext *ctx ) } /* redo special cases: */ - ASSIGN_4V( ctx->Current.Attrib[VERT_ATTRIB_WEIGHT], 1.0, 0.0, 0.0, 1.0 ); + ASSIGN_4V( ctx->Current.Attrib[VERT_ATTRIB_WEIGHT], 1.0, 0.0, 0.0, 0.0 ); ASSIGN_4V( ctx->Current.Attrib[VERT_ATTRIB_NORMAL], 0.0, 0.0, 1.0, 1.0 ); ASSIGN_4V( ctx->Current.Attrib[VERT_ATTRIB_COLOR0], 1.0, 1.0, 1.0, 1.0 ); ASSIGN_4V( ctx->Current.Attrib[VERT_ATTRIB_COLOR1], 0.0, 0.0, 0.0, 1.0 ); - ASSIGN_4V( ctx->Current.Attrib[VERT_ATTRIB_FOG], 0.0, 0.0, 0.0, 0.0 ); - ctx->Current.Attrib[VERT_ATTRIB_COLOR_INDEX][0] = 1.0; - ctx->Current.EdgeFlag = GL_TRUE; + ASSIGN_4V( ctx->Current.Attrib[VERT_ATTRIB_COLOR_INDEX], 1.0, 0.0, 0.0, 1.0 ); + ASSIGN_4V( ctx->Current.Attrib[VERT_ATTRIB_EDGEFLAG], 1.0, 0.0, 0.0, 1.0 ); } @@ -1010,7 +817,7 @@ init_natives(struct gl_program_constants *prog) * some of these values (such as number of texture units). */ static void -_mesa_init_constants( GLcontext *ctx ) +_mesa_init_constants(GLcontext *ctx) { assert(ctx); @@ -1025,6 +832,7 @@ _mesa_init_constants( GLcontext *ctx ) 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, @@ -1058,39 +866,34 @@ _mesa_init_constants( GLcontext *ctx ) ctx->Const.VertexProgram.MaxTexInstructions = 0; ctx->Const.VertexProgram.MaxTexIndirections = 0; ctx->Const.VertexProgram.MaxAttribs = MAX_NV_VERTEX_PROGRAM_INPUTS; - ctx->Const.VertexProgram.MaxTemps = MAX_NV_VERTEX_PROGRAM_TEMPS; + ctx->Const.VertexProgram.MaxTemps = MAX_PROGRAM_TEMPS; ctx->Const.VertexProgram.MaxParameters = MAX_NV_VERTEX_PROGRAM_PARAMS; ctx->Const.VertexProgram.MaxLocalParams = MAX_PROGRAM_LOCAL_PARAMS; - ctx->Const.VertexProgram.MaxEnvParams = MAX_NV_VERTEX_PROGRAM_PARAMS; + ctx->Const.VertexProgram.MaxEnvParams = MAX_PROGRAM_ENV_PARAMS; ctx->Const.VertexProgram.MaxAddressRegs = MAX_VERTEX_PROGRAM_ADDRESS_REGS; - ctx->Const.VertexProgram.MaxUniformComponents = MAX_VERTEX_UNIFORM_COMPONENTS; + ctx->Const.VertexProgram.MaxUniformComponents = 4 * MAX_UNIFORMS; init_natives(&ctx->Const.VertexProgram); #endif + #if FEATURE_ARB_fragment_program ctx->Const.FragmentProgram.MaxInstructions = MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS; ctx->Const.FragmentProgram.MaxAluInstructions = MAX_FRAGMENT_PROGRAM_ALU_INSTRUCTIONS; ctx->Const.FragmentProgram.MaxTexInstructions = MAX_FRAGMENT_PROGRAM_TEX_INSTRUCTIONS; ctx->Const.FragmentProgram.MaxTexIndirections = MAX_FRAGMENT_PROGRAM_TEX_INDIRECTIONS; ctx->Const.FragmentProgram.MaxAttribs = MAX_NV_FRAGMENT_PROGRAM_INPUTS; - ctx->Const.FragmentProgram.MaxTemps = MAX_NV_FRAGMENT_PROGRAM_TEMPS; + ctx->Const.FragmentProgram.MaxTemps = MAX_PROGRAM_TEMPS; ctx->Const.FragmentProgram.MaxParameters = MAX_NV_FRAGMENT_PROGRAM_PARAMS; ctx->Const.FragmentProgram.MaxLocalParams = MAX_PROGRAM_LOCAL_PARAMS; - ctx->Const.FragmentProgram.MaxEnvParams = MAX_NV_FRAGMENT_PROGRAM_PARAMS; + ctx->Const.FragmentProgram.MaxEnvParams = MAX_PROGRAM_ENV_PARAMS; ctx->Const.FragmentProgram.MaxAddressRegs = MAX_FRAGMENT_PROGRAM_ADDRESS_REGS; - ctx->Const.FragmentProgram.MaxUniformComponents = MAX_FRAGMENT_UNIFORM_COMPONENTS; + ctx->Const.FragmentProgram.MaxUniformComponents = 4 * MAX_UNIFORMS; init_natives(&ctx->Const.FragmentProgram); #endif ctx->Const.MaxProgramMatrices = MAX_PROGRAM_MATRICES; ctx->Const.MaxProgramMatrixStackDepth = MAX_PROGRAM_MATRIX_STACK_DEPTH; - /* If we're running in the X server, do bounds checking to prevent - * segfaults and server crashes! - */ -#if defined(XFree86Server) - ctx->Const.CheckArrayBounds = GL_TRUE; -#else + /* CheckArrayBounds is overriden by drivers/x11 for X server */ ctx->Const.CheckArrayBounds = GL_FALSE; -#endif /* GL_ARB_draw_buffers */ ctx->Const.MaxDrawBuffers = MAX_DRAW_BUFFERS; @@ -1106,7 +909,7 @@ _mesa_init_constants( GLcontext *ctx ) #if FEATURE_ARB_vertex_shader ctx->Const.MaxVertexTextureImageUnits = MAX_VERTEX_TEXTURE_IMAGE_UNITS; - ctx->Const.MaxVaryingFloats = MAX_VARYING_FLOATS; + ctx->Const.MaxVarying = MAX_VARYING; #endif /* sanity checks */ @@ -1114,6 +917,11 @@ _mesa_init_constants( GLcontext *ctx ) ctx->Const.MaxTextureCoordUnits)); 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); } @@ -1155,7 +963,7 @@ check_context_limits(GLcontext *ctx) * functions for the more complex data structures. */ static GLboolean -init_attrib_groups( GLcontext *ctx ) +init_attrib_groups(GLcontext *ctx) { assert(ctx); @@ -1176,6 +984,7 @@ init_attrib_groups( GLcontext *ctx ) _mesa_init_debug( ctx ); _mesa_init_display_list( ctx ); _mesa_init_eval( ctx ); + _mesa_init_fbobjects( ctx ); _mesa_init_feedback( ctx ); _mesa_init_fog( ctx ); _mesa_init_histogram( ctx ); @@ -1191,7 +1000,7 @@ init_attrib_groups( GLcontext *ctx ) _mesa_init_query( ctx ); _mesa_init_rastpos( ctx ); _mesa_init_scissor( ctx ); - _mesa_init_shaderobjects (ctx); + _mesa_init_shader_state( ctx ); _mesa_init_stencil( ctx ); _mesa_init_transform( ctx ); _mesa_init_varray( ctx ); @@ -1206,7 +1015,28 @@ init_attrib_groups( GLcontext *ctx ) /* Miscellaneous */ ctx->NewState = _NEW_ALL; ctx->ErrorValue = (GLenum) GL_NO_ERROR; - ctx->_Facing = 0; + + return GL_TRUE; +} + + +/** + * Update default objects in a GL context with respect to shared state. + * + * \param ctx GL context. + * + * Removes references to old default objects, (texture objects, program + * objects, etc.) and changes to reference those from the current shared + * state. + */ +static GLboolean +update_default_objects(GLcontext *ctx) +{ + assert(ctx); + + _mesa_update_default_objects_program(ctx); + _mesa_update_default_objects_texture(ctx); + _mesa_update_default_objects_buffer_objects(ctx); return GL_TRUE; } @@ -1220,7 +1050,7 @@ init_attrib_groups( GLcontext *ctx ) static int generic_nop(void) { - _mesa_problem(NULL, "User called no-op dispatch function (an unsupported extension function?)"); + _mesa_warning(NULL, "User called no-op dispatch function (an unsupported extension function?)"); return 0; } @@ -1278,24 +1108,16 @@ alloc_dispatch_table(void) * \param driverContext pointer to driver-specific context data */ GLboolean -_mesa_initialize_context( GLcontext *ctx, - const GLvisual *visual, - GLcontext *share_list, - const struct dd_function_table *driverFunctions, - void *driverContext ) +_mesa_initialize_context(GLcontext *ctx, + const GLvisual *visual, + GLcontext *share_list, + const struct dd_function_table *driverFunctions, + void *driverContext) { ASSERT(driverContext); assert(driverFunctions->NewTextureObject); assert(driverFunctions->FreeTexImageData); - /* If the driver wants core Mesa to use special imports, it'll have to - * override these defaults. - */ - _mesa_init_default_imports( &(ctx->imports), driverContext ); - - /* initialize the exports (Mesa functions called by the window system) */ - _mesa_init_default_exports( &(ctx->exports) ); - /* misc one-time initializations */ one_time_init(ctx); @@ -1351,12 +1173,16 @@ _mesa_initialize_context( GLcontext *ctx, ctx->TnlModule.SwapCount = 0; #endif - ctx->_MaintainTexEnvProgram = (_mesa_getenv("MESA_TEX_PROG") != NULL); - ctx->_UseTexEnvProgram = ctx->_MaintainTexEnvProgram; + ctx->FragmentProgram._MaintainTexEnvProgram + = (_mesa_getenv("MESA_TEX_PROG") != NULL); + ctx->FragmentProgram._UseTexEnvProgram = ctx->FragmentProgram._MaintainTexEnvProgram; - ctx->_MaintainTnlProgram = (_mesa_getenv("MESA_TNL_PROG") != NULL); - if (ctx->_MaintainTnlProgram) - ctx->_MaintainTexEnvProgram = 1; /* this is required... */ + ctx->VertexProgram._MaintainTnlProgram + = (_mesa_getenv("MESA_TNL_PROG") != NULL); + if (ctx->VertexProgram._MaintainTnlProgram) { + /* this is required... */ + ctx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE; + } ctx->FirstTimeCurrent = GL_TRUE; @@ -1379,11 +1205,10 @@ _mesa_initialize_context( GLcontext *ctx, * \return pointer to a new __GLcontextRec or NULL if error. */ GLcontext * -_mesa_create_context( const GLvisual *visual, - GLcontext *share_list, - const struct dd_function_table *driverFunctions, - void *driverContext ) - +_mesa_create_context(const GLvisual *visual, + GLcontext *share_list, + const struct dd_function_table *driverFunctions, + void *driverContext) { GLcontext *ctx; @@ -1415,11 +1240,28 @@ _mesa_create_context( const GLvisual *visual, void _mesa_free_context_data( GLcontext *ctx ) { - /* if we're destroying the current context, unbind it first */ - if (ctx == _mesa_get_current_context()) { - _mesa_make_current(NULL, NULL, NULL); + if (!_mesa_get_current_context()){ + /* No current context, but we may need one in order to delete + * texture objs, etc. So temporarily bind the context now. + */ + _mesa_make_current(ctx, NULL, NULL); } + /* unreference WinSysDraw/Read buffers */ + _mesa_unreference_framebuffer(&ctx->WinSysDrawBuffer); + _mesa_unreference_framebuffer(&ctx->WinSysReadBuffer); + _mesa_unreference_framebuffer(&ctx->DrawBuffer); + _mesa_unreference_framebuffer(&ctx->ReadBuffer); + + _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, NULL); + _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, NULL); + _mesa_reference_vertprog(ctx, &ctx->VertexProgram._TnlProgram, 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_free_attrib_data(ctx); _mesa_free_lighting_data( ctx ); _mesa_free_eval_data( ctx ); _mesa_free_texture_data( ctx ); @@ -1427,6 +1269,7 @@ _mesa_free_context_data( GLcontext *ctx ) _mesa_free_viewport_data( ctx ); _mesa_free_colortables_data( ctx ); _mesa_free_program_data(ctx); + _mesa_free_shader_state(ctx); _mesa_free_query_data(ctx); #if FEATURE_ARB_vertex_buffer_object @@ -1450,6 +1293,11 @@ _mesa_free_context_data( GLcontext *ctx ) if (ctx->Extensions.String) _mesa_free((void *) ctx->Extensions.String); + + /* unbind the context if it's currently bound */ + if (ctx == _mesa_get_current_context()) { + _mesa_make_current(NULL, NULL, NULL); + } } @@ -1596,9 +1444,9 @@ _mesa_copy_context( const GLcontext *src, GLcontext *dst, GLuint mask ) * Check if the given context can render into the given framebuffer * by checking visual attributes. * - * XXX this may go away someday because we're moving toward more freedom - * in binding contexts to drawables with different visual attributes. - * The GL_EXT_f_b_o extension is prompting some of that. + * Most of these tests could go away because Mesa is now pretty flexible + * in terms of mixing rendering contexts with framebuffers. As long + * as RGB vs. CI mode agree, we're probably good. * * \return GL_TRUE if compatible, GL_FALSE otherwise. */ @@ -1632,8 +1480,11 @@ check_compatible(const GLcontext *ctx, const GLframebuffer *buffer) return GL_FALSE; if (ctxvis->blueMask && ctxvis->blueMask != bufvis->blueMask) return GL_FALSE; +#if 0 + /* disabled (see bug 11161) */ if (ctxvis->depthBits && ctxvis->depthBits != bufvis->depthBits) return GL_FALSE; +#endif if (ctxvis->stencilBits && ctxvis->stencilBits != bufvis->stencilBits) return GL_FALSE; @@ -1713,20 +1564,23 @@ _mesa_make_current( GLcontext *newCtx, GLframebuffer *drawBuffer, ASSERT(drawBuffer->Name == 0); ASSERT(readBuffer->Name == 0); - newCtx->WinSysDrawBuffer = drawBuffer; - newCtx->WinSysReadBuffer = readBuffer; + _mesa_reference_framebuffer(&newCtx->WinSysDrawBuffer, drawBuffer); + _mesa_reference_framebuffer(&newCtx->WinSysReadBuffer, readBuffer); /* * 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) { - newCtx->DrawBuffer = drawBuffer; + _mesa_reference_framebuffer(&newCtx->DrawBuffer, drawBuffer); } if (!newCtx->ReadBuffer || newCtx->ReadBuffer->Name == 0) { - newCtx->ReadBuffer = readBuffer; + _mesa_reference_framebuffer(&newCtx->ReadBuffer, readBuffer); } + /* XXX only set this flag if we're really changing the draw/read + * framebuffer bindings. + */ newCtx->NewState |= _NEW_BUFFERS; #if 1 @@ -1794,12 +1648,18 @@ GLboolean _mesa_share_state(GLcontext *ctx, GLcontext *ctxToShare) { if (ctx && ctxToShare && ctx->Shared && ctxToShare->Shared) { - ctx->Shared->RefCount--; - if (ctx->Shared->RefCount == 0) { - free_shared_state(ctx, ctx->Shared); - } + struct gl_shared_state *oldSharedState = ctx->Shared; + ctx->Shared = ctxToShare->Shared; ctx->Shared->RefCount++; + + update_default_objects(ctx); + + oldSharedState->RefCount--; + if (oldSharedState->RefCount == 0) { + free_shared_state(ctx, oldSharedState); + } + return GL_TRUE; } else { @@ -1810,12 +1670,11 @@ _mesa_share_state(GLcontext *ctx, GLcontext *ctxToShare) /** - * Get current context for the calling thread. - * - * \return pointer to the current GL context. + * \return pointer to the current GL context for this thread. * * Calls _glapi_get_context(). This isn't the fastest way to get the current - * context. If you need speed, see the #GET_CURRENT_CONTEXT macro in context.h. + * context. If you need speed, see the #GET_CURRENT_CONTEXT macro in + * context.h. */ GLcontext * _mesa_get_current_context( void ) @@ -1823,6 +1682,7 @@ _mesa_get_current_context( void ) return (GLcontext *) _glapi_get_context(); } + /** * Get context's current API dispatch table. * @@ -1862,7 +1722,7 @@ _mesa_get_dispatch(GLcontext *ctx) * This is called via _mesa_error(). */ void -_mesa_record_error( GLcontext *ctx, GLenum error ) +_mesa_record_error(GLcontext *ctx, GLenum error) { if (!ctx) return; @@ -1873,10 +1733,11 @@ _mesa_record_error( GLcontext *ctx, GLenum error ) /* Call device driver's error handler, if any. This is used on the Mac. */ if (ctx->Driver.Error) { - (*ctx->Driver.Error)( ctx ); + ctx->Driver.Error(ctx); } } + /** * Execute glFinish(). * @@ -1884,15 +1745,16 @@ _mesa_record_error( GLcontext *ctx, GLenum error ) * dd_function_table::Finish driver callback, if not NULL. */ void GLAPIENTRY -_mesa_Finish( void ) +_mesa_Finish(void) { GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); if (ctx->Driver.Finish) { - (*ctx->Driver.Finish)( ctx ); + ctx->Driver.Finish(ctx); } } + /** * Execute glFlush(). * @@ -1900,12 +1762,12 @@ _mesa_Finish( void ) * dd_function_table::Flush driver callback, if not NULL. */ void GLAPIENTRY -_mesa_Flush( void ) +_mesa_Flush(void) { GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); if (ctx->Driver.Flush) { - (*ctx->Driver.Flush)( ctx ); + ctx->Driver.Flush(ctx); } }