diff options
Diffstat (limited to 'src/mesa/main/context.c')
-rw-r--r-- | src/mesa/main/context.c | 253 |
1 files changed, 170 insertions, 83 deletions
diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c index 9401e3dcc2..b132030b9b 100644 --- a/src/mesa/main/context.c +++ b/src/mesa/main/context.c @@ -131,6 +131,7 @@ #if _HAVE_FULL_GL #include "math/m_matrix.h" #endif +#include "main/dispatch.h" /* for _gloffset_COUNT */ #ifdef USE_SPARC_ASM #include "sparc/sparc.h" @@ -218,7 +219,7 @@ _mesa_create_visual( GLboolean dbFlag, GLint accumAlphaBits, GLint numSamples ) { - struct gl_config *vis = (struct gl_config *) calloc(1, sizeof(struct gl_config)); + struct gl_config *vis = CALLOC_STRUCT(gl_config); if (vis) { if (!_mesa_initialize_visual(vis, dbFlag, stereoFlag, redBits, greenBits, blueBits, alphaBits, @@ -233,11 +234,13 @@ _mesa_create_visual( GLboolean dbFlag, return vis; } + /** - * Makes some sanity checks and fills in the fields of the - * struct gl_config object with the given parameters. If the caller needs - * to set additional fields, he should just probably init the whole struct gl_config - * object himself. + * Makes some sanity checks and fills in the fields of the struct + * gl_config object with the given parameters. If the caller needs to + * set additional fields, he should just probably init the whole + * gl_config object himself. + * * \return GL_TRUE on success, or GL_FALSE on failure. * * \sa _mesa_create_visual() above for the parameter description. @@ -367,6 +370,8 @@ dummy_enum_func(void) */ _glthread_DECLARE_STATIC_MUTEX(OneTimeLock); + + /** * Calls all the various one-time-init functions in Mesa. * @@ -379,10 +384,12 @@ _glthread_DECLARE_STATIC_MUTEX(OneTimeLock); static void one_time_init( struct gl_context *ctx ) { - static GLboolean alreadyCalled = GL_FALSE; - (void) ctx; + static GLbitfield api_init_mask = 0x0; + _glthread_LOCK_MUTEX(OneTimeLock); - if (!alreadyCalled) { + + /* truly one-time init */ + if (!api_init_mask) { GLuint i; /* do some implementation tests */ @@ -395,27 +402,9 @@ one_time_init( struct gl_context *ctx ) _mesa_get_cpu_features(); - switch (ctx->API) { -#if FEATURE_GL - case API_OPENGL: - _mesa_init_remap_table(); - break; -#endif -#if FEATURE_ES1 - case API_OPENGLES: - _mesa_init_remap_table_es1(); - break; -#endif -#if FEATURE_ES2 - case API_OPENGLES2: - _mesa_init_remap_table_es2(); - break; -#endif - default: - break; - } - _mesa_init_sqrt_table(); + + /* context dependence is never a one-time thing... */ _mesa_init_get_hash(ctx); for (i = 0; i < 256; i++) { @@ -423,12 +412,27 @@ one_time_init( struct gl_context *ctx ) } #if defined(DEBUG) && defined(__DATE__) && defined(__TIME__) - _mesa_debug(ctx, "Mesa %s DEBUG build %s %s\n", - MESA_VERSION_STRING, __DATE__, __TIME__); + if (MESA_VERBOSE != 0) { + _mesa_debug(ctx, "Mesa %s DEBUG build %s %s\n", + MESA_VERSION_STRING, __DATE__, __TIME__); + } #endif + } - alreadyCalled = GL_TRUE; + /* 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(); } + + api_init_mask |= 1 << ctx->API; + _glthread_UNLOCK_MUTEX(OneTimeLock); /* Hopefully atexit() is widely available. If not, we may need some @@ -620,6 +624,10 @@ _mesa_init_constants(struct gl_context *ctx) /* GL 3.2: hard-coded for now: */ ctx->Const.ProfileMask = GL_CONTEXT_COMPATIBILITY_PROFILE_BIT; + + /** GL_EXT_gpu_shader4 */ + ctx->Const.MinProgramTexelOffset = -8; + ctx->Const.MaxProgramTexelOffset = 7; } @@ -807,10 +815,13 @@ _mesa_alloc_dispatch_table(int size) * Mesa we do this to accomodate different versions of libGL and various * DRI drivers. */ - GLint numEntries = MAX2(_glapi_get_dispatch_table_size(), - size / sizeof(_glapi_proc)); - struct _glapi_table *table = - (struct _glapi_table *) malloc(numEntries * sizeof(_glapi_proc)); + 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)); if (table) { _glapi_proc *entry = (_glapi_proc *) table; GLint i; @@ -983,6 +994,10 @@ _mesa_initialize_context_for_api(struct gl_context *ctx, return GL_TRUE; } + +/** + * Initialize an OpenGL context. + */ GLboolean _mesa_initialize_context(struct gl_context *ctx, const struct gl_config *visual, @@ -998,6 +1013,7 @@ _mesa_initialize_context(struct gl_context *ctx, driverContext); } + /** * Allocate and initialize a struct gl_context structure. * Note that the driver needs to pass in its dd_function_table here since @@ -1039,6 +1055,10 @@ _mesa_create_context_for_api(gl_api api, } } + +/** + * Create an OpenGL context. + */ struct gl_context * _mesa_create_context(const struct gl_config *visual, struct gl_context *share_list, @@ -1051,6 +1071,7 @@ _mesa_create_context(const struct gl_config *visual, driverContext); } + /** * Free the data associated with the given context. * @@ -1137,7 +1158,7 @@ _mesa_free_context_data( struct gl_context *ctx ) * * \param ctx GL context. * - * Calls _mesa_free_context_data() and frees the struct gl_context structure itself. + * Calls _mesa_free_context_data() and frees the gl_context object itself. */ void _mesa_destroy_context( struct gl_context *ctx ) @@ -1282,14 +1303,12 @@ _mesa_copy_context( const struct gl_context *src, struct gl_context *dst, GLuint * \return GL_TRUE if compatible, GL_FALSE otherwise. */ static GLboolean -check_compatible(const struct gl_context *ctx, const struct gl_framebuffer *buffer) +check_compatible(const struct gl_context *ctx, + const struct gl_framebuffer *buffer) { const struct gl_config *ctxvis = &ctx->Visual; const struct gl_config *bufvis = &buffer->Visual; - if (ctxvis == bufvis) - return GL_TRUE; - if (buffer == _mesa_get_incomplete_framebuffer()) return GL_TRUE; @@ -1376,7 +1395,8 @@ _mesa_check_init_viewport(struct gl_context *ctx, GLuint width, GLuint height) * \param readBuffer the reading framebuffer */ GLboolean -_mesa_make_current( struct gl_context *newCtx, struct gl_framebuffer *drawBuffer, +_mesa_make_current( struct gl_context *newCtx, + struct gl_framebuffer *drawBuffer, struct gl_framebuffer *readBuffer ) { if (MESA_VERBOSE & VERBOSE_API) @@ -1437,7 +1457,8 @@ _mesa_make_current( struct gl_context *newCtx, struct gl_framebuffer *drawBuffer buffers[i] = newCtx->Color.DrawBuffer[i]; } - _mesa_drawbuffers(newCtx, newCtx->Const.MaxDrawBuffers, buffers, NULL); + _mesa_drawbuffers(newCtx, newCtx->Const.MaxDrawBuffers, + buffers, NULL); } if (!newCtx->ReadBuffer || newCtx->ReadBuffer->Name == 0) { _mesa_reference_framebuffer(&newCtx->ReadBuffer, readBuffer); @@ -1697,11 +1718,10 @@ _mesa_valid_to_render(struct gl_context *ctx, const char *where) if (ctx->NewState) _mesa_update_state(ctx); - if (ctx->Shader.CurrentProgram) { - struct gl_shader_program *const prog = ctx->Shader.CurrentProgram; + if (ctx->Shader.CurrentVertexProgram) { + vert_from_glsl_shader = true; - /* using shaders */ - if (!prog->LinkStatus) { + if (!ctx->Shader.CurrentVertexProgram->LinkStatus) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(shader not linked)", where); return GL_FALSE; @@ -1709,25 +1729,57 @@ _mesa_valid_to_render(struct gl_context *ctx, const char *where) #if 0 /* not normally enabled */ { char errMsg[100]; - if (!_mesa_validate_shader_program(ctx, prog, errMsg)) { + if (!_mesa_validate_shader_program(ctx, + ctx->Shader.CurrentVertexProgram, + errMsg)) { _mesa_warning(ctx, "Shader program %u is invalid: %s", - prog->Name, errMsg); + ctx->Shader.CurrentVertexProgram->Name, errMsg); } } #endif + } - /* Figure out which shader stages are provided by the GLSL program. For - * any stages that are not provided, the corresponding assembly shader - * target will be validated below. - */ - vert_from_glsl_shader = - prog->_LinkedShaders[MESA_SHADER_VERTEX] != NULL; - geom_from_glsl_shader = - prog->_LinkedShaders[MESA_SHADER_GEOMETRY] != NULL; - frag_from_glsl_shader = - prog->_LinkedShaders[MESA_SHADER_FRAGMENT] != NULL; + if (ctx->Shader.CurrentGeometryProgram) { + geom_from_glsl_shader = 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 } + if (ctx->Shader.CurrentFragmentProgram) { + frag_from_glsl_shader = true; + + if (!ctx->Shader.CurrentFragmentProgram->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.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. @@ -1744,11 +1796,21 @@ _mesa_valid_to_render(struct gl_context *ctx, const char *where) */ (void) geom_from_glsl_shader; - if (!frag_from_glsl_shader - && ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "%s(fragment program not valid)", where); - return GL_FALSE; + if (!frag_from_glsl_shader) { + if (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(fragment program not valid)", where); + return GL_FALSE; + } + + /* If drawing to integer-valued color buffers, there must be an + * active fragment shader (GL_EXT_texture_integer). + */ + if (ctx->DrawBuffer && ctx->DrawBuffer->_IntegerColor) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(integer format but no fragment shader)", where); + return GL_FALSE; + } } if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { @@ -1759,26 +1821,51 @@ _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 (shProg) { - if (!shProg->_Used) { - /* This is the first time this shader is being used. - * Append shader's constants/uniforms to log file. - */ - GLuint i; - for (i = 0; i < shProg->NumShaders; i++) { - struct gl_shader *sh = shProg->Shaders[i]; - if (sh->Type == GL_VERTEX_SHADER) { - _mesa_append_uniforms_to_file(sh, - &shProg->VertexProgram->Base); - } - else if (sh->Type == GL_FRAGMENT_SHADER) { - _mesa_append_uniforms_to_file(sh, - &shProg->FragmentProgram->Base); - } - } - shProg->_Used = GL_TRUE; - } + struct gl_shader_program *shProg[MESA_SHADER_TYPES]; + unsigned i; + + shProg[MESA_SHADER_VERTEX] = ctx->Shader.CurrentVertexProgram; + shProg[MESA_SHADER_GEOMETRY] = ctx->Shader.CurrentGeometryProgram; + 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; + + /* 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 + * 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; + } + } + + for (i = 0; i < MESA_SHADER_TYPES; i++) { + if (shProg[i] != NULL) + shProg[i]->_Used = GL_TRUE; } } #endif |