X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fmain%2Fcontext.c;h=38906ca5781720d9bb9749b14ad7f51baf920648;hb=43abaf2ad0c1c42e56e47732395cc98912a050e8;hp=5ad04cc9988e19b141cfac1311518ced89518b63;hpb=bab755ad1b8cc5560c7d92e21b1fb1c3bebd43ae;p=mesa.git diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c index 5ad04cc9988..3fa9f69f883 100644 --- a/src/mesa/main/context.c +++ b/src/mesa/main/context.c @@ -83,12 +83,14 @@ #include "api_loopback.h" #include "arrayobj.h" #include "attrib.h" +#include "bbox.h" #include "blend.h" #include "buffers.h" #include "bufferobj.h" #include "context.h" #include "cpuinfo.h" #include "debug.h" +#include "debug_output.h" #include "depth.h" #include "dlist.h" #include "eval.h" @@ -98,6 +100,7 @@ #include "fog.h" #include "formats.h" #include "framebuffer.h" +#include "glthread.h" #include "hint.h" #include "hash.h" #include "light.h" @@ -105,6 +108,9 @@ #include "macros.h" #include "matrix.h" #include "multisample.h" +#include "performance_monitor.h" +#include "performance_query.h" +#include "pipelineobj.h" #include "pixel.h" #include "pixelstore.h" #include "points.h" @@ -116,8 +122,10 @@ #include "scissor.h" #include "shared.h" #include "shaderobj.h" -#include "simple_list.h" -#include "state.h" +#include "shaderimage.h" +#include "util/debug.h" +#include "util/disk_cache.h" +#include "util/strtod.h" #include "stencil.h" #include "texcompress_s3tc.h" #include "texstate.h" @@ -126,17 +134,19 @@ #include "varray.h" #include "version.h" #include "viewport.h" -#include "vtxfmt.h" +#include "texturebindless.h" #include "program/program.h" -#include "program/prog_print.h" #include "math/m_matrix.h" #include "main/dispatch.h" /* for _gloffset_COUNT */ +#include "macros.h" +#include "git_sha1.h" #ifdef USE_SPARC_ASM #include "sparc/sparc.h" #endif -#include "glsl_parser_extras.h" +#include "compiler/glsl_types.h" +#include "compiler/glsl/glsl_parser_extras.h" #include @@ -156,7 +166,7 @@ GLfloat _mesa_ubyte_to_float_color_tab[256]; /** * Swap buffers notification callback. - * + * * \param ctx GL context. * * Called by window system just before swapping buffers. @@ -182,7 +192,7 @@ _mesa_notifySwapBuffers(struct gl_context *ctx) /** * Allocates a struct gl_config structure and initializes it via * _mesa_initialize_visual(). - * + * * \param dbFlag double buffering * \param stereoFlag stereo buffer * \param depthBits requested bits per depth buffer value. Any value in [0, 32] @@ -198,7 +208,7 @@ _mesa_notifySwapBuffers(struct gl_context *ctx) * \param blueBits same as above. * \param alphaBits same as above. * \param numSamples not really used. - * + * * \return pointer to new struct gl_config or NULL if requested parameters * can't be met. * @@ -310,7 +320,7 @@ _mesa_initialize_visual( struct gl_config *vis, * Destroy a visual and free its memory. * * \param vis visual. - * + * * Frees the visual structure. */ void @@ -332,39 +342,24 @@ _mesa_destroy_visual( struct gl_config *vis ) /*@{*/ -/** - * This is lame. gdb only seems to recognize enum types that are - * actually used somewhere. We want to be able to print/use enum - * values such as TEXTURE_2D_INDEX in gdb. But we don't actually use - * the gl_texture_index type anywhere. Thus, this lame function. - */ -static void -dummy_enum_func(void) -{ - gl_buffer_index bi = BUFFER_FRONT_LEFT; - gl_face_index fi = FACE_POS_X; - gl_frag_result fr = FRAG_RESULT_DEPTH; - gl_texture_index ti = TEXTURE_2D_ARRAY_INDEX; - gl_vert_attrib va = VERT_ATTRIB_POS; - gl_varying_slot vs = VARYING_SLOT_POS; - - (void) bi; - (void) fi; - (void) fr; - (void) ti; - (void) va; - (void) vs; -} - - /** * One-time initialization mutex lock. * * \sa Used by one_time_init(). */ -_glthread_DECLARE_STATIC_MUTEX(OneTimeLock); +mtx_t OneTimeLock = _MTX_INITIALIZER_NP; +/** + * Calls all the various one-time-fini functions in Mesa + */ + +static void +one_time_fini(void) +{ + _mesa_destroy_shader_compiler(); + _mesa_locale_fini(); +} /** * Calls all the various one-time-init functions in Mesa. @@ -380,19 +375,22 @@ 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) { GLuint i; - /* do some implementation tests */ - assert( sizeof(GLbyte) == 1 ); - assert( sizeof(GLubyte) == 1 ); - assert( sizeof(GLshort) == 2 ); - assert( sizeof(GLushort) == 2 ); - assert( sizeof(GLint) == 4 ); - assert( sizeof(GLuint) == 4 ); + STATIC_ASSERT(sizeof(GLbyte) == 1); + STATIC_ASSERT(sizeof(GLubyte) == 1); + STATIC_ASSERT(sizeof(GLshort) == 2); + STATIC_ASSERT(sizeof(GLushort) == 2); + STATIC_ASSERT(sizeof(GLint) == 4); + STATIC_ASSERT(sizeof(GLuint) == 4); + + _mesa_locale_init(); + + _mesa_one_time_init_extension_overrides(ctx); _mesa_get_cpu_features(); @@ -400,35 +398,27 @@ one_time_init( struct gl_context *ctx ) _mesa_ubyte_to_float_color_tab[i] = (float) i / 255.0F; } -#if defined(DEBUG) && defined(__DATE__) && defined(__TIME__) + atexit(one_time_fini); + +#if defined(DEBUG) if (MESA_VERBOSE != 0) { - _mesa_debug(ctx, "Mesa %s DEBUG build %s %s\n", - PACKAGE_VERSION, __DATE__, __TIME__); - } + _mesa_debug(ctx, "Mesa " PACKAGE_VERSION " DEBUG build" +#ifdef MESA_GIT_SHA1 + " (" MESA_GIT_SHA1 ")" #endif - -#ifdef DEBUG - _mesa_test_formats(); + "\n"); + } #endif } /* per-API one-time init */ if (!(api_init_mask & (1 << ctx->API))) { - _mesa_init_get_hash(ctx); - _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 - * #ifdef tests here. - */ - atexit(_mesa_destroy_shader_compiler); - - dummy_enum_func(); + mtx_unlock(&OneTimeLock); } @@ -441,12 +431,11 @@ _mesa_init_current(struct gl_context *ctx) GLuint i; /* Init all to (0,0,0,1) */ - for (i = 0; i < Elements(ctx->Current.Attrib); i++) { + for (i = 0; i < ARRAY_SIZE(ctx->Current.Attrib); i++) { ASSIGN_4V( ctx->Current.Attrib[i], 0.0, 0.0, 0.0, 1.0 ); } /* redo special cases: */ - 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 ); @@ -460,7 +449,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, GLenum type, +init_program_limits(struct gl_constants *consts, gl_shader_stage stage, struct gl_program_constants *prog) { prog->MaxInstructions = MAX_PROGRAM_INSTRUCTIONS; @@ -472,27 +461,43 @@ init_program_limits(struct gl_context *ctx, GLenum type, prog->MaxLocalParams = MAX_PROGRAM_LOCAL_PARAMS; prog->MaxAddressOffset = MAX_PROGRAM_LOCAL_PARAMS; - switch (type) { - case GL_VERTEX_PROGRAM_ARB: + switch (stage) { + case MESA_SHADER_VERTEX: prog->MaxParameters = MAX_VERTEX_PROGRAM_PARAMS; prog->MaxAttribs = MAX_VERTEX_GENERIC_ATTRIBS; prog->MaxAddressRegs = MAX_VERTEX_PROGRAM_ADDRESS_REGS; prog->MaxUniformComponents = 4 * MAX_UNIFORMS; + prog->MaxInputComponents = 0; /* value not used */ + prog->MaxOutputComponents = 16 * 4; /* old limit not to break tnl and swrast */ break; - case GL_FRAGMENT_PROGRAM_ARB: - prog->MaxParameters = MAX_NV_FRAGMENT_PROGRAM_PARAMS; - prog->MaxAttribs = MAX_NV_FRAGMENT_PROGRAM_INPUTS; + case MESA_SHADER_FRAGMENT: + prog->MaxParameters = MAX_FRAGMENT_PROGRAM_PARAMS; + prog->MaxAttribs = MAX_FRAGMENT_PROGRAM_INPUTS; prog->MaxAddressRegs = MAX_FRAGMENT_PROGRAM_ADDRESS_REGS; prog->MaxUniformComponents = 4 * MAX_UNIFORMS; + prog->MaxInputComponents = 16 * 4; /* old limit not to break tnl and swrast */ + prog->MaxOutputComponents = 0; /* value not used */ break; - case MESA_GEOMETRY_PROGRAM: + case MESA_SHADER_TESS_CTRL: + case MESA_SHADER_TESS_EVAL: + case MESA_SHADER_GEOMETRY: prog->MaxParameters = MAX_VERTEX_PROGRAM_PARAMS; prog->MaxAttribs = MAX_VERTEX_GENERIC_ATTRIBS; prog->MaxAddressRegs = MAX_VERTEX_PROGRAM_ADDRESS_REGS; - prog->MaxUniformComponents = MAX_GEOMETRY_UNIFORM_COMPONENTS; + prog->MaxUniformComponents = 4 * MAX_UNIFORMS; + prog->MaxInputComponents = 16 * 4; /* old limit not to break tnl and swrast */ + prog->MaxOutputComponents = 16 * 4; /* old limit not to break tnl and swrast */ + break; + case MESA_SHADER_COMPUTE: + prog->MaxParameters = 0; /* not meaningful for compute shaders */ + prog->MaxAttribs = 0; /* not meaningful for compute shaders */ + prog->MaxAddressRegs = 0; /* not meaningful for compute shaders */ + prog->MaxUniformComponents = 4 * MAX_UNIFORMS; + prog->MaxInputComponents = 0; /* not meaningful for compute shaders */ + prog->MaxOutputComponents = 0; /* not meaningful for compute shaders */ break; default: - assert(0 && "Bad program type in init_program_limits()"); + assert(0 && "Bad shader stage in init_program_limits()"); } /* Set the native limits to zero. This implies that there is no native @@ -528,8 +533,13 @@ init_program_limits(struct gl_context *ctx, GLenum type, prog->MaxUniformBlocks = 12; prog->MaxCombinedUniformComponents = (prog->MaxUniformComponents + - ctx->Const.MaxUniformBlockSize / 4 * + consts->MaxUniformBlockSize / 4 * prog->MaxUniformBlocks); + + prog->MaxAtomicBuffers = 0; + prog->MaxAtomicCounters = 0; + + prog->MaxShaderStorageBlocks = 8; } @@ -538,124 +548,196 @@ init_program_limits(struct gl_context *ctx, GLenum type, * Use defaults from config.h. The device drivers will often override * some of these values (such as number of texture units). */ -static void -_mesa_init_constants(struct gl_context *ctx) +void +_mesa_init_constants(struct gl_constants *consts, gl_api api) { - assert(ctx); + int i; + assert(consts); /* Constants, may be overriden (usually only reduced) by device drivers */ - ctx->Const.MaxTextureMbytes = MAX_TEXTURE_MBYTES; - ctx->Const.MaxTextureLevels = MAX_TEXTURE_LEVELS; - ctx->Const.Max3DTextureLevels = MAX_3D_TEXTURE_LEVELS; - ctx->Const.MaxCubeTextureLevels = MAX_CUBE_TEXTURE_LEVELS; - ctx->Const.MaxTextureRectSize = MAX_TEXTURE_RECT_SIZE; - ctx->Const.MaxArrayTextureLayers = MAX_ARRAY_TEXTURE_LAYERS; - ctx->Const.MaxTextureCoordUnits = MAX_TEXTURE_COORD_UNITS; - ctx->Const.FragmentProgram.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS; - ctx->Const.MaxTextureUnits = MIN2(ctx->Const.MaxTextureCoordUnits, - 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; - 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; + 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 = 16384; + consts->MaxViewportHeight = 16384; + consts->MinMapBufferAlignment = 64; + + /* Driver must override these values if ARB_viewport_array is supported. */ + consts->MaxViewports = 1; + consts->ViewportSubpixelBits = 0; + consts->ViewportBounds.Min = 0; + consts->ViewportBounds.Max = 0; /** GL_ARB_uniform_buffer_object */ - ctx->Const.MaxCombinedUniformBlocks = 36; - ctx->Const.MaxUniformBufferBindings = 36; - ctx->Const.MaxUniformBlockSize = 16384; - ctx->Const.UniformBufferOffsetAlignment = 1; - - 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; - - /* CheckArrayBounds is overriden by drivers/x11 for X server */ - ctx->Const.CheckArrayBounds = GL_FALSE; + consts->MaxCombinedUniformBlocks = 36; + consts->MaxUniformBufferBindings = 36; + consts->MaxUniformBlockSize = 16384; + consts->UniformBufferOffsetAlignment = 1; + + /** GL_ARB_shader_storage_buffer_object */ + consts->MaxCombinedShaderStorageBlocks = 8; + consts->MaxShaderStorageBufferBindings = 8; + consts->MaxShaderStorageBlockSize = 128 * 1024 * 1024; /* 2^27 */ + consts->ShaderStorageBufferOffsetAlignment = 256; + + /* 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(consts, i, &consts->Program[i]); + + consts->MaxProgramMatrices = MAX_PROGRAM_MATRICES; + consts->MaxProgramMatrixStackDepth = MAX_PROGRAM_MATRIX_STACK_DEPTH; + + /* Assume that if GLSL 1.30+ (or GLSL ES 3.00+) is supported that + * gl_VertexID is implemented using a native hardware register with OpenGL + * semantics. + */ + consts->VertexID_is_zero_based = false; /* GL_ARB_draw_buffers */ - ctx->Const.MaxDrawBuffers = MAX_DRAW_BUFFERS; + consts->MaxDrawBuffers = MAX_DRAW_BUFFERS; - ctx->Const.MaxColorAttachments = MAX_COLOR_ATTACHMENTS; - ctx->Const.MaxRenderbufferSize = MAX_RENDERBUFFER_SIZE; + consts->MaxColorAttachments = MAX_COLOR_ATTACHMENTS; + consts->MaxRenderbufferSize = MAX_RENDERBUFFER_SIZE; - ctx->Const.VertexProgram.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.GeometryProgram.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 = (GLuint64) ~0; + /* GLSL default if NativeIntegers == FALSE */ + consts->UniformBooleanTrue = FLOAT_AS_UNION(1.0f).u; - /* GL_ATI_envmap_bumpmap */ - ctx->Const.SupportedBumpUnits = SUPPORTED_ATI_BUMP_UNITS; + /* GL_ARB_sync */ + consts->MaxServerWaitTimeout = 0x7fffffff7fffffffULL; /* GL_EXT_provoking_vertex */ - ctx->Const.QuadsFollowProvokingVertexConvention = GL_TRUE; + consts->QuadsFollowProvokingVertexConvention = GL_TRUE; + + /** GL_ARB_viewport_array */ + consts->LayerAndVPIndexProvokingVertex = GL_UNDEFINED_VERTEX; /* GL_EXT_transform_feedback */ - ctx->Const.MaxTransformFeedbackBuffers = MAX_FEEDBACK_BUFFERS; - ctx->Const.MaxTransformFeedbackSeparateComponents = 4 * MAX_FEEDBACK_ATTRIBS; - ctx->Const.MaxTransformFeedbackInterleavedComponents = 4 * MAX_FEEDBACK_ATTRIBS; - ctx->Const.MaxVertexStreams = 1; + consts->MaxTransformFeedbackBuffers = MAX_FEEDBACK_BUFFERS; + consts->MaxTransformFeedbackSeparateComponents = 4 * MAX_FEEDBACK_ATTRIBS; + consts->MaxTransformFeedbackInterleavedComponents = 4 * MAX_FEEDBACK_ATTRIBS; + consts->MaxVertexStreams = 1; - /* GL 3.2: hard-coded for now: */ - ctx->Const.ProfileMask = GL_CONTEXT_COMPATIBILITY_PROFILE_BIT; + /* GL 3.2 */ + consts->ProfileMask = api == API_OPENGL_CORE + ? GL_CONTEXT_CORE_PROFILE_BIT + : GL_CONTEXT_COMPATIBILITY_PROFILE_BIT; + + /* GL 4.4 */ + consts->MaxVertexAttribStride = 2048; /** GL_EXT_gpu_shader4 */ - ctx->Const.MinProgramTexelOffset = -8; - ctx->Const.MaxProgramTexelOffset = 7; + consts->MinProgramTexelOffset = -8; + consts->MaxProgramTexelOffset = 7; + + /* GL_ARB_texture_gather */ + consts->MinProgramTextureGatherOffset = -8; + consts->MaxProgramTextureGatherOffset = 7; /* GL_ARB_robustness */ - ctx->Const.ResetStrategy = GL_NO_RESET_NOTIFICATION_ARB; + consts->ResetStrategy = GL_NO_RESET_NOTIFICATION_ARB; - /* PrimitiveRestart */ - ctx->Const.PrimitiveRestartInSoftware = GL_FALSE; + /* GL_KHR_robustness */ + consts->RobustAccess = GL_FALSE; /* ES 3.0 or ARB_ES3_compatibility */ - ctx->Const.MaxElementIndex = 0xffffffffu; + consts->MaxElementIndex = 0xffffffffu; /* GL_ARB_texture_multisample */ - ctx->Const.MaxColorTextureSamples = 1; - ctx->Const.MaxDepthTextureSamples = 1; - ctx->Const.MaxIntegerSamples = 1; + consts->MaxColorTextureSamples = 1; + consts->MaxDepthTextureSamples = 1; + consts->MaxIntegerSamples = 1; + + /* GL_ARB_shader_atomic_counters */ + consts->MaxAtomicBufferBindings = MAX_COMBINED_ATOMIC_BUFFERS; + consts->MaxAtomicBufferSize = MAX_ATOMIC_COUNTERS * ATOMIC_COUNTER_SIZE; + consts->MaxCombinedAtomicBuffers = MAX_COMBINED_ATOMIC_BUFFERS; + consts->MaxCombinedAtomicCounters = MAX_ATOMIC_COUNTERS; + + /* GL_ARB_vertex_attrib_binding */ + consts->MaxVertexAttribRelativeOffset = 2047; + consts->MaxVertexAttribBindings = MAX_VERTEX_GENERIC_ATTRIBS; + + /* GL_ARB_compute_shader */ + consts->MaxComputeWorkGroupCount[0] = 65535; + consts->MaxComputeWorkGroupCount[1] = 65535; + consts->MaxComputeWorkGroupCount[2] = 65535; + consts->MaxComputeWorkGroupSize[0] = 1024; + consts->MaxComputeWorkGroupSize[1] = 1024; + consts->MaxComputeWorkGroupSize[2] = 64; + /* Enables compute support for GLES 3.1 if >= 128 */ + consts->MaxComputeWorkGroupInvocations = 0; + + /** 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; + + /** GL_ARB_tessellation_shader */ + consts->MaxTessGenLevel = MAX_TESS_GEN_LEVEL; + consts->MaxPatchVertices = MAX_PATCH_VERTICES; + consts->Program[MESA_SHADER_TESS_CTRL].MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS; + consts->Program[MESA_SHADER_TESS_EVAL].MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS; + consts->MaxTessPatchComponents = MAX_TESS_PATCH_COMPONENTS; + consts->MaxTessControlTotalOutputComponents = MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS; + consts->PrimitiveRestartForPatches = false; + + /** GL_ARB_compute_variable_group_size */ + consts->MaxComputeVariableGroupSize[0] = 512; + consts->MaxComputeVariableGroupSize[1] = 512; + consts->MaxComputeVariableGroupSize[2] = 64; + consts->MaxComputeVariableGroupInvocations = 512; } @@ -666,31 +748,33 @@ _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))); + (8 * sizeof(ctx->VertexProgram._Current->info.outputs_written))); assert(VARYING_SLOT_MAX <= - (8 * sizeof(ctx->FragmentProgram._Current->Base.InputsRead))); + (8 * sizeof(ctx->FragmentProgram._Current->info.inputs_read))); /* shader-related checks */ - assert(ctx->Const.FragmentProgram.MaxLocalParams <= MAX_PROGRAM_LOCAL_PARAMS); - assert(ctx->Const.VertexProgram.MaxLocalParams <= MAX_PROGRAM_LOCAL_PARAMS); + assert(ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxLocalParams <= MAX_PROGRAM_LOCAL_PARAMS); + assert(ctx->Const.Program[MESA_SHADER_VERTEX].MaxLocalParams <= MAX_PROGRAM_LOCAL_PARAMS); /* Texture unit checks */ - assert(ctx->Const.FragmentProgram.MaxTextureImageUnits > 0); - assert(ctx->Const.FragmentProgram.MaxTextureImageUnits <= MAX_TEXTURE_IMAGE_UNITS); + assert(ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits > 0); + assert(ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits <= MAX_TEXTURE_IMAGE_UNITS); assert(ctx->Const.MaxTextureCoordUnits > 0); assert(ctx->Const.MaxTextureCoordUnits <= MAX_TEXTURE_COORD_UNITS); assert(ctx->Const.MaxTextureUnits > 0); assert(ctx->Const.MaxTextureUnits <= MAX_TEXTURE_IMAGE_UNITS); assert(ctx->Const.MaxTextureUnits <= MAX_TEXTURE_COORD_UNITS); - assert(ctx->Const.MaxTextureUnits == MIN2(ctx->Const.FragmentProgram.MaxTextureImageUnits, + assert(ctx->Const.MaxTextureUnits == MIN2(ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits, ctx->Const.MaxTextureCoordUnits)); assert(ctx->Const.MaxCombinedTextureImageUnits > 0); assert(ctx->Const.MaxCombinedTextureImageUnits <= MAX_COMBINED_TEXTURE_IMAGE_UNITS); assert(ctx->Const.MaxTextureCoordUnits <= MAX_COMBINED_TEXTURE_IMAGE_UNITS); /* number of coord units cannot be greater than number of image units */ - assert(ctx->Const.MaxTextureCoordUnits <= ctx->Const.FragmentProgram.MaxTextureImageUnits); + assert(ctx->Const.MaxTextureCoordUnits <= ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits); /* Texture size checks */ @@ -732,30 +816,35 @@ 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 ); _mesa_init_attrib( ctx ); + _mesa_init_bbox( ctx ); _mesa_init_buffer_objects( ctx ); _mesa_init_color( ctx ); _mesa_init_current( ctx ); _mesa_init_depth( ctx ); _mesa_init_debug( ctx ); + _mesa_init_debug_output( ctx ); _mesa_init_display_list( ctx ); - _mesa_init_errors( ctx ); _mesa_init_eval( ctx ); _mesa_init_fbobjects( ctx ); _mesa_init_feedback( ctx ); _mesa_init_fog( ctx ); _mesa_init_hint( ctx ); + _mesa_init_image_units( ctx ); _mesa_init_line( ctx ); _mesa_init_lighting( ctx ); _mesa_init_matrix( ctx ); _mesa_init_multisample( ctx ); + _mesa_init_performance_monitors( ctx ); + _mesa_init_performance_queries( ctx ); + _mesa_init_pipeline( ctx ); _mesa_init_pixel( ctx ); _mesa_init_pixelstore( ctx ); _mesa_init_point( ctx ); @@ -771,17 +860,18 @@ init_attrib_groups(struct gl_context *ctx) _mesa_init_transform_feedback( ctx ); _mesa_init_varray( ctx ); _mesa_init_viewport( ctx ); + _mesa_init_resident_handles( ctx ); if (!_mesa_init_texture( ctx )) return GL_FALSE; - _mesa_init_texture_s3tc( ctx ); - /* Miscellaneous */ + ctx->TileRasterOrderIncreasingX = GL_TRUE; + ctx->TileRasterOrderIncreasingY = GL_TRUE; ctx->NewState = _NEW_ALL; ctx->NewDriverState = ~0; ctx->ErrorValue = GL_NO_ERROR; - ctx->ResetStatus = GL_NO_ERROR; + ctx->ShareGroupReset = false; ctx->varying_vp_inputs = VERT_BIT_ALL; return GL_TRUE; @@ -810,13 +900,69 @@ update_default_objects(struct gl_context *ctx) } +/* XXX this is temporary and should be removed at some point in the + * future when there's a reasonable expectation that the libGL library + * contains the _glapi_new_nop_table() and _glapi_set_nop_handler() + * functions which were added in Mesa 10.6. + */ +#if !defined(_WIN32) +/* Avoid libGL / driver ABI break */ +#define USE_GLAPI_NOP_FEATURES 0 +#else +#define USE_GLAPI_NOP_FEATURES 1 +#endif + + /** - * This is the default function we plug into all dispatch table slots - * This helps prevents a segfault when someone calls a GL function without - * first checking if the extension's supported. + * This function is called by the glapi no-op functions. For each OpenGL + * function/entrypoint there's a simple no-op function. These "no-op" + * functions call this function. + * + * If there's a current OpenGL context for the calling thread, we record a + * GL_INVALID_OPERATION error. This can happen either because the app's + * calling an unsupported extension function, or calling an illegal function + * (such as glClear between glBegin/glEnd). + * + * If there's no current OpenGL context for the calling thread, we can + * print a message to stderr. + * + * \param name the name of the OpenGL function */ -int -_mesa_generic_nop(void) +#if USE_GLAPI_NOP_FEATURES +static void +nop_handler(const char *name) +{ + GET_CURRENT_CONTEXT(ctx); + if (ctx) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid call)", name); + } +#if defined(DEBUG) + else if (getenv("MESA_DEBUG") || getenv("LIBGL_DEBUG")) { + fprintf(stderr, + "GL User Error: gl%s called without a rendering context\n", + name); + fflush(stderr); + } +#endif +} +#endif + + +/** + * Special no-op glFlush, see below. + */ +#if defined(_WIN32) +static void GLAPIENTRY +nop_glFlush(void) +{ + /* don't record an error like we do in nop_handler() */ +} +#endif + + +#if !USE_GLAPI_NOP_FEATURES +static int +generic_nop(void) { GET_CURRENT_CONTEXT(ctx); _mesa_error(ctx, GL_INVALID_OPERATION, @@ -824,30 +970,79 @@ _mesa_generic_nop(void) "(unsupported extension or deprecated function?)"); return 0; } +#endif /** - * Allocate and initialize a new dispatch table. + * Create a new API dispatch table in which all entries point to the + * generic_nop() function. This will not work on Windows because of + * the __stdcall convention which requires the callee to clean up the + * call stack. That's impossible with one generic no-op function. */ struct _glapi_table * -_mesa_alloc_dispatch_table() +_mesa_new_nop_table(unsigned numEntries) { - /* 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 - * Mesa we do this to accomodate different versions of libGL and various - * DRI drivers. - */ - GLint numEntries = MAX2(_glapi_get_dispatch_table_size(), _gloffset_COUNT); struct _glapi_table *table; +#if !USE_GLAPI_NOP_FEATURES table = malloc(numEntries * sizeof(_glapi_proc)); if (table) { _glapi_proc *entry = (_glapi_proc *) table; - GLint i; + unsigned i; for (i = 0; i < numEntries; i++) { - entry[i] = (_glapi_proc) _mesa_generic_nop; + entry[i] = (_glapi_proc) generic_nop; } } +#else + table = _glapi_new_nop_table(numEntries); +#endif + return table; +} + + +/** + * Allocate and initialize a new dispatch table. The table will be + * populated with pointers to "no-op" functions. In turn, the no-op + * functions will call nop_handler() above. + */ +struct _glapi_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 + * Mesa we do this to accommodate different versions of libGL and various + * DRI drivers. + */ + int numEntries = MAX2(_glapi_get_dispatch_table_size(), _gloffset_COUNT); + + struct _glapi_table *table = _mesa_new_nop_table(numEntries); + +#if defined(_WIN32) + if (table) { + /* 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 + +#if USE_GLAPI_NOP_FEATURES + _glapi_set_nop_handler(nop_handler); +#endif + return table; } @@ -944,7 +1139,7 @@ _mesa_initialize_dispatch_tables(struct gl_context *ctx) * Note that the driver needs to pass in its dd_function_table here since * we need to at least call driverFunctions->NewTextureObject to create the * default texture objects. - * + * * Called by _mesa_create_context(). * * Performs the imports and exports callback tables initialization, and @@ -956,7 +1151,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 @@ -976,16 +1172,22 @@ _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 (_mesa_is_desktop_gl(ctx)) { - _mesa_override_gl_version(ctx); + if (visual) { + ctx->Visual = *visual; + ctx->HasConfig = GL_TRUE; + } + else { + memset(&ctx->Visual, 0, sizeof ctx->Visual); + ctx->HasConfig = GL_FALSE; } + _mesa_override_gl_version(ctx); + /* misc one-time initializations */ one_time_init(ctx); @@ -1012,18 +1214,28 @@ _mesa_initialize_context(struct gl_context *ctx, if (!init_attrib_groups( ctx )) goto fail; + /* KHR_no_error is likely to crash, overflow memory, etc if an application + * has errors so don't enable it for setuid processes. + */ + if (env_var_as_boolean("MESA_NO_ERROR", false)) { +#if !defined(_WIN32) + if (geteuid() == getuid()) +#endif + ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR; + } + /* 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->CurrentClientDispatch = ctx->CurrentServerDispatch = 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; @@ -1035,7 +1247,7 @@ _mesa_initialize_context(struct gl_context *ctx, * _mesa_choose_tex_format(). */ memset(&ctx->TextureFormatSupported, GL_TRUE, - sizeof(ctx->TextureFormatSupported)); + sizeof(ctx->TextureFormatSupported)); switch (ctx->API) { case API_OPENGL_COMPAT: @@ -1053,13 +1265,13 @@ _mesa_initialize_context(struct gl_context *ctx, * "Initially all texture generation modes are set to REFLECTION_MAP_OES" */ for (i = 0; i < MAX_TEXTURE_UNITS; i++) { - struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i]; - texUnit->GenS.Mode = GL_REFLECTION_MAP_NV; - texUnit->GenT.Mode = GL_REFLECTION_MAP_NV; - texUnit->GenR.Mode = GL_REFLECTION_MAP_NV; - texUnit->GenS._ModeBit = TEXGEN_REFLECTION_MAP_NV; - texUnit->GenT._ModeBit = TEXGEN_REFLECTION_MAP_NV; - texUnit->GenR._ModeBit = TEXGEN_REFLECTION_MAP_NV; + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i]; + texUnit->GenS.Mode = GL_REFLECTION_MAP_NV; + texUnit->GenT.Mode = GL_REFLECTION_MAP_NV; + texUnit->GenR.Mode = GL_REFLECTION_MAP_NV; + texUnit->GenS._ModeBit = TEXGEN_REFLECTION_MAP_NV; + texUnit->GenT._ModeBit = TEXGEN_REFLECTION_MAP_NV; + texUnit->GenR._ModeBit = TEXGEN_REFLECTION_MAP_NV; } break; case API_OPENGLES2: @@ -1075,54 +1287,15 @@ _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; } -/** - * Allocate and initialize a struct gl_context structure. - * Note that the driver needs to pass in its dd_function_table here since - * we need to at least call driverFunctions->NewTextureObject to initialize - * 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 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. - * - * \return pointer to a new __struct gl_contextRec or NULL if error. - */ -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) -{ - struct gl_context *ctx; - - ASSERT(visual); - - ctx = calloc(1, sizeof(struct gl_context)); - if (!ctx) - return NULL; - - if (_mesa_initialize_context(ctx, api, visual, share_list, - driverFunctions)) { - return ctx; - } - else { - free(ctx); - return NULL; - } -} - - /** * Free the data associated with the given context. - * + * * But doesn't free the struct gl_context struct itself. * * \sa _mesa_initialize_context() and init_attrib_groups(). @@ -1143,30 +1316,38 @@ _mesa_free_context_data( struct gl_context *ctx ) _mesa_reference_framebuffer(&ctx->DrawBuffer, NULL); _mesa_reference_framebuffer(&ctx->ReadBuffer, NULL); - _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_program(ctx, &ctx->VertexProgram.Current, NULL); + _mesa_reference_program(ctx, &ctx->VertexProgram._Current, NULL); + _mesa_reference_program(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_reference_program(ctx, &ctx->TessCtrlProgram._Current, NULL); + _mesa_reference_program(ctx, &ctx->TessEvalProgram._Current, NULL); + _mesa_reference_program(ctx, &ctx->GeometryProgram._Current, NULL); - _mesa_reference_array_object(ctx, &ctx->Array.ArrayObj, NULL); - _mesa_reference_array_object(ctx, &ctx->Array.DefaultArrayObj, NULL); + _mesa_reference_program(ctx, &ctx->FragmentProgram.Current, NULL); + _mesa_reference_program(ctx, &ctx->FragmentProgram._Current, NULL); + _mesa_reference_program(ctx, &ctx->FragmentProgram._TexEnvProgram, NULL); + + _mesa_reference_program(ctx, &ctx->ComputeProgram._Current, NULL); + + _mesa_reference_vao(ctx, &ctx->Array.VAO, NULL); + _mesa_reference_vao(ctx, &ctx->Array.DefaultVAO, NULL); _mesa_free_attrib_data(ctx); _mesa_free_buffer_objects(ctx); - _mesa_free_lighting_data( ctx ); _mesa_free_eval_data( ctx ); _mesa_free_texture_data( ctx ); _mesa_free_matrix_data( ctx ); - _mesa_free_viewport_data( ctx ); + _mesa_free_pipeline_data(ctx); _mesa_free_program_data(ctx); _mesa_free_shader_state(ctx); _mesa_free_queryobj_data(ctx); _mesa_free_sync_data(ctx); _mesa_free_varray_data(ctx); _mesa_free_transform_feedback(ctx); + _mesa_free_performance_monitors(ctx); + _mesa_free_performance_queries(ctx); + _mesa_free_resident_handles(ctx); _mesa_reference_buffer_object(ctx, &ctx->Pack.BufferObj, NULL); _mesa_reference_buffer_object(ctx, &ctx->Unpack.BufferObj, NULL); @@ -1175,8 +1356,10 @@ _mesa_free_context_data( struct gl_context *ctx ) /* free dispatch tables */ free(ctx->BeginEnd); - free(ctx->Exec); + free(ctx->OutsideBeginEnd); free(ctx->Save); + free(ctx->ContextLost); + free(ctx->MarshalExec); /* Shared context state (display lists, textures, etc) */ _mesa_reference_shared_state(ctx, &ctx->Shared, NULL); @@ -1201,7 +1384,7 @@ _mesa_free_context_data( struct gl_context *ctx ) * Destroy a struct gl_context structure. * * \param ctx GL context. - * + * * Calls _mesa_free_context_data() and frees the gl_context object itself. */ void @@ -1216,7 +1399,7 @@ _mesa_destroy_context( struct gl_context *ctx ) /** * Copy attribute groups from one context to another. - * + * * \param src source context * \param dst destination context * \param mask bitwise OR of GL_*_BIT flags @@ -1262,16 +1445,8 @@ _mesa_copy_context( const struct gl_context *src, struct gl_context *dst, dst->Hint = src->Hint; } if (mask & GL_LIGHTING_BIT) { - GLuint i; - /* begin with memcpy */ + /* OK to memcpy */ dst->Light = src->Light; - /* fixup linked lists to prevent pointer insanity */ - make_empty_list( &(dst->Light.EnabledList) ); - for (i = 0; i < MAX_LIGHTS; i++) { - if (dst->Light.Light[i].Enabled) { - insert_at_tail(&(dst->Light.EnabledList), &(dst->Light.Light[i])); - } - } } if (mask & GL_LINE_BIT) { /* OK to memcpy */ @@ -1319,14 +1494,11 @@ _mesa_copy_context( const struct gl_context *src, struct gl_context *dst, dst->Transform = src->Transform; } if (mask & GL_VIEWPORT_BIT) { - /* Cannot use memcpy, because of pointers in GLmatrix _WindowMap */ - dst->Viewport.X = src->Viewport.X; - dst->Viewport.Y = src->Viewport.Y; - dst->Viewport.Width = src->Viewport.Width; - dst->Viewport.Height = src->Viewport.Height; - dst->Viewport.Near = src->Viewport.Near; - dst->Viewport.Far = src->Viewport.Far; - _math_matrix_copy(&dst->Viewport._WindowMap, &src->Viewport._WindowMap); + unsigned i; + for (i = 0; i < src->Const.MaxViewports; i++) { + /* OK to memcpy */ + dst->ViewportArray[i] = src->ViewportArray[i]; + } } /* XXX FIXME: Call callbacks? @@ -1340,13 +1512,9 @@ _mesa_copy_context( const struct gl_context *src, struct gl_context *dst, * Check if the given context can render into the given framebuffer * by checking visual attributes. * - * 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. */ -static GLboolean +static GLboolean check_compatible(const struct gl_context *ctx, const struct gl_framebuffer *buffer) { @@ -1356,32 +1524,18 @@ check_compatible(const struct gl_context *ctx, if (buffer == _mesa_get_incomplete_framebuffer()) return GL_TRUE; -#if 0 - /* disabling this fixes the fgl_glxgears pbuffer demo */ - if (ctxvis->doubleBufferMode && !bufvis->doubleBufferMode) - return GL_FALSE; -#endif - if (ctxvis->stereoMode && !bufvis->stereoMode) - return GL_FALSE; - if (ctxvis->haveAccumBuffer && !bufvis->haveAccumBuffer) - return GL_FALSE; - if (ctxvis->haveDepthBuffer && !bufvis->haveDepthBuffer) - return GL_FALSE; - if (ctxvis->haveStencilBuffer && !bufvis->haveStencilBuffer) - return GL_FALSE; - if (ctxvis->redMask && ctxvis->redMask != bufvis->redMask) - return GL_FALSE; - if (ctxvis->greenMask && ctxvis->greenMask != bufvis->greenMask) - 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; +#define check_component(foo) \ + if (ctxvis->foo && bufvis->foo && \ + ctxvis->foo != bufvis->foo) \ + return GL_FALSE + + check_component(redMask); + check_component(greenMask); + check_component(blueMask); + check_component(depthBits); + check_component(stencilBits); + +#undef check_component return GL_TRUE; } @@ -1391,20 +1545,99 @@ check_compatible(const struct gl_context *ctx, * Check if the viewport/scissor size has not yet been initialized. * Initialize the size if the given width and height are non-zero. */ -void -_mesa_check_init_viewport(struct gl_context *ctx, GLuint width, GLuint height) +static void +check_init_viewport(struct gl_context *ctx, GLuint width, GLuint height) { if (!ctx->ViewportInitialized && width > 0 && height > 0) { + unsigned i; + /* Note: set flag here, before calling _mesa_set_viewport(), to prevent * potential infinite recursion. */ ctx->ViewportInitialized = GL_TRUE; - _mesa_set_viewport(ctx, 0, 0, width, height); - _mesa_set_scissor(ctx, 0, 0, width, height); + + /* Note: ctx->Const.MaxViewports may not have been set by the driver + * yet, so just initialize all of them. + */ + for (i = 0; i < MAX_VIEWPORTS; i++) { + _mesa_set_viewport(ctx, i, 0, 0, width, height); + _mesa_set_scissor(ctx, i, 0, 0, width, height); + } } } +static void +handle_first_current(struct gl_context *ctx) +{ + if (ctx->Version == 0 || !ctx->DrawBuffer) { + /* probably in the process of tearing down the context */ + return; + } + + 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()) { + GLenum buffer; + + if (ctx->DrawBuffer->Visual.doubleBufferMode) + buffer = GL_BACK; + else + buffer = GL_FRONT; + + _mesa_drawbuffers(ctx, ctx->DrawBuffer, 1, &buffer, + NULL /* destMask */); + } + + if (ctx->ReadBuffer != _mesa_get_incomplete_framebuffer()) { + gl_buffer_index bufferIndex; + GLenum buffer; + + if (ctx->ReadBuffer->Visual.doubleBufferMode) { + buffer = GL_BACK; + bufferIndex = BUFFER_BACK_LEFT; + } + else { + buffer = GL_FRONT; + bufferIndex = BUFFER_FRONT_LEFT; + } + + _mesa_readbuffer(ctx, ctx->ReadBuffer, buffer, bufferIndex); + } + } + + /* Determine if generic vertex attribute 0 aliases the conventional + * glVertex position. + */ + { + const bool is_forward_compatible_context = + ctx->Const.ContextFlags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT; + + /* In OpenGL 3.1 attribute 0 becomes non-magic, just like in OpenGL ES + * 2.0. Note that we cannot just check for API_OPENGL_COMPAT here because + * that will erroneously allow this usage in a 3.0 forward-compatible + * context too. + */ + ctx->_AttribZeroAliasesVertex = (ctx->API == API_OPENGLES + || (ctx->API == API_OPENGL_COMPAT + && !is_forward_compatible_context)); + } + + /* 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 * make it the current context for the calling thread. @@ -1446,25 +1679,38 @@ _mesa_make_current( struct gl_context *newCtx, } } - if (curCtx && - (curCtx->WinSysDrawBuffer || curCtx->WinSysReadBuffer) && + if (curCtx && + (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 */ - _glapi_set_context((void *) newCtx); - ASSERT(_mesa_get_current_context() == newCtx); if (!newCtx) { _glapi_set_dispatch(NULL); /* none current */ + /* We need old ctx to correctly release Draw/ReadBuffer + * and avoid a surface leak in st_renderbuffer_delete. + * Therefore, first drop buffers then set new ctx to NULL. + */ + if (curCtx) { + _mesa_reference_framebuffer(&curCtx->WinSysDrawBuffer, NULL); + _mesa_reference_framebuffer(&curCtx->WinSysReadBuffer, NULL); + } + _glapi_set_context(NULL); + assert(_mesa_get_current_context() == NULL); } else { - _glapi_set_dispatch(newCtx->CurrentDispatch); + _glapi_set_context((void *) newCtx); + assert(_mesa_get_current_context() == newCtx); + _glapi_set_dispatch(newCtx->CurrentClientDispatch); if (drawBuffer && readBuffer) { - ASSERT(_mesa_is_winsys_fbo(drawBuffer)); - ASSERT(_mesa_is_winsys_fbo(readBuffer)); + assert(_mesa_is_winsys_fbo(drawBuffer)); + assert(_mesa_is_winsys_fbo(readBuffer)); _mesa_reference_framebuffer(&newCtx->WinSysDrawBuffer, drawBuffer); _mesa_reference_framebuffer(&newCtx->WinSysReadBuffer, readBuffer); @@ -1482,39 +1728,32 @@ _mesa_make_current( struct gl_context *newCtx, } if (!newCtx->ReadBuffer || _mesa_is_winsys_fbo(newCtx->ReadBuffer)) { _mesa_reference_framebuffer(&newCtx->ReadBuffer, readBuffer); + /* In _mesa_initialize_window_framebuffer, for single-buffered + * visuals, the ColorReadBuffer is set to be GL_FRONT, even with + * GLES contexts. When calling read_buffer, we verify we are reading + * from GL_BACK in is_legal_es3_readbuffer_enum. But the default is + * incorrect, and certain dEQP tests check this. So fix it here. + */ + if (_mesa_is_gles(newCtx) && + !newCtx->ReadBuffer->Visual.doubleBufferMode) + if (newCtx->ReadBuffer->ColorReadBuffer == GL_FRONT) + newCtx->ReadBuffer->ColorReadBuffer = GL_BACK; } /* XXX only set this flag if we're really changing the draw/read * framebuffer bindings. */ - newCtx->NewState |= _NEW_BUFFERS; + newCtx->NewState |= _NEW_BUFFERS; - if (drawBuffer) { - _mesa_check_init_viewport(newCtx, - drawBuffer->Width, drawBuffer->Height); - } + check_init_viewport(newCtx, drawBuffer->Width, drawBuffer->Height); } if (newCtx->FirstTimeCurrent) { - assert(newCtx->Version > 0); - - newCtx->Extensions.String = _mesa_make_extension_string(newCtx); - - check_context_limits(newCtx); - - /* We can use this to help debug user's problems. Tell them to set - * the MESA_INFO env variable before running their app. Then the - * first time each context is made current we'll print some useful - * information. - */ - if (_mesa_getenv("MESA_INFO")) { - _mesa_print_info(); - } - - newCtx->FirstTimeCurrent = GL_FALSE; + handle_first_current(newCtx); + newCtx->FirstTimeCurrent = GL_FALSE; } } - + return GL_TRUE; } @@ -1553,7 +1792,7 @@ _mesa_share_state(struct gl_context *ctx, struct gl_context *ctxToShare) /** * \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. @@ -1568,19 +1807,19 @@ _mesa_get_current_context( void ) /** * Get context's current API dispatch table. * - * It'll either be the immediate-mode execute dispatcher or the display list - * compile dispatcher. - * + * It'll either be the immediate-mode execute dispatcher, the display list + * compile dispatcher, or the thread marshalling dispatcher. + * * \param ctx GL context. * * \return pointer to dispatch_table. * - * Simply returns __struct gl_contextRec::CurrentDispatch. + * Simply returns __struct gl_contextRec::CurrentClientDispatch. */ struct _glapi_table * _mesa_get_dispatch(struct gl_context *ctx) { - return ctx->CurrentDispatch; + return ctx->CurrentClientDispatch; } /*@}*/ @@ -1596,7 +1835,7 @@ _mesa_get_dispatch(struct gl_context *ctx) * * \param ctx GL context. * \param error error code. - * + * * Records the given error code and call the driver's dd_function_table::Error * function if defined. * @@ -1615,20 +1854,6 @@ _mesa_record_error(struct gl_context *ctx, GLenum error) } -/** - * Flush commands and wait for completion. - */ -void -_mesa_finish(struct gl_context *ctx) -{ - FLUSH_VERTICES( ctx, 0 ); - FLUSH_CURRENT( ctx, 0 ); - if (ctx->Driver.Finish) { - ctx->Driver.Finish(ctx); - } -} - - /** * Flush commands. */ @@ -1645,7 +1870,7 @@ _mesa_flush(struct gl_context *ctx) /** - * Execute glFinish(). + * Flush commands and wait for completion. * * Calls the #ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH macro and the * dd_function_table::Finish driver callback, if not NULL. @@ -1655,7 +1880,13 @@ _mesa_Finish(void) { GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); - _mesa_finish(ctx); + + FLUSH_VERTICES(ctx, 0); + FLUSH_CURRENT(ctx, 0); + + if (ctx->Driver.Finish) { + ctx->Driver.Finish(ctx); + } } @@ -1674,188 +1905,4 @@ _mesa_Flush(void) } -/* - * 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 - * 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) -{ - 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.CurrentVertexProgram) { - vert_from_glsl_shader = true; - - if (!ctx->Shader.CurrentVertexProgram->LinkStatus) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "%s(shader not linked)", where); - return GL_FALSE; - } -#if 0 /* not normally enabled */ - { - char errMsg[100]; - if (!_mesa_validate_shader_program(ctx, - ctx->Shader.CurrentVertexProgram, - errMsg)) { - _mesa_warning(ctx, "Shader program %u is invalid: %s", - ctx->Shader.CurrentVertexProgram->Name, errMsg); - } - } -#endif - } - - 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. - */ - if (!vert_from_glsl_shader - && ctx->VertexProgram.Enabled && !ctx->VertexProgram._Enabled) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "%s(vertex program not valid)", where); - return GL_FALSE; - } - - /* FINISHME: If GL_NV_geometry_program4 is ever supported, the current - * FINISHME: geometry program should validated here. - */ - (void) geom_from_glsl_shader; - - 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) { - _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, - "%s(incomplete framebuffer)", 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]; - gl_shader_type i; - - shProg[MESA_SHADER_VERTEX] = ctx->Shader.CurrentVertexProgram; - shProg[MESA_SHADER_GEOMETRY] = ctx->Shader.CurrentGeometryProgram; - shProg[MESA_SHADER_FRAGMENT] = ctx->Shader.CurrentFragmentProgram; - - for (i = 0; i < MESA_SHADER_TYPES; i++) { - 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. - * - * 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. - */ - _mesa_append_uniforms_to_file(shProg[i]->_LinkedShaders[i]); - } - - for (i = 0; i < MESA_SHADER_TYPES; i++) { - if (shProg[i] != NULL) - shProg[i]->_Used = GL_TRUE; - } - } -#endif - - return GL_TRUE; -} - - /*@}*/