#include "glheader.h"
-#include "imports.h"
+
#include "accum.h"
#include "api_exec.h"
#include "api_loopback.h"
#include "arrayobj.h"
#include "attrib.h"
+#include "bbox.h"
#include "blend.h"
#include "buffers.h"
#include "bufferobj.h"
+#include "conservativeraster.h"
#include "context.h"
#include "cpuinfo.h"
#include "debug.h"
#include "fog.h"
#include "formats.h"
#include "framebuffer.h"
+#include "glthread.h"
#include "hint.h"
#include "hash.h"
#include "light.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 "shared.h"
#include "shaderobj.h"
#include "shaderimage.h"
-#include "util/simple_list.h"
-#include "util/strtod.h"
#include "state.h"
+#include "util/debug.h"
+#include "util/disk_cache.h"
+#include "util/strtod.h"
#include "stencil.h"
+#include "shaderimage.h"
#include "texcompress_s3tc.h"
#include "texstate.h"
#include "transformfeedback.h"
#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 "uniforms.h"
#include "macros.h"
+#include "git_sha1.h"
#ifdef USE_SPARC_ASM
#include "sparc/sparc.h"
#endif
+#include "compiler/glsl_types.h"
+#include "compiler/glsl/builtin_functions.h"
#include "compiler/glsl/glsl_parser_extras.h"
#include <stdbool.h>
+#include "util/u_memory.h"
#ifndef MESA_VERBOSE
/**
* Swap buffers notification callback.
- *
+ *
* \param ctx GL context.
*
* Called by window system just before swapping buffers.
{
if (MESA_VERBOSE & VERBOSE_SWAPBUFFERS)
_mesa_debug(ctx, "SwapBuffers\n");
- FLUSH_CURRENT( ctx, 0 );
+ FLUSH_VERTICES(ctx, 0);
if (ctx->Driver.Flush) {
ctx->Driver.Flush(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]
* \param stencilBits requested minimum bits per stencil buffer value
* \param accumRedBits, accumGreenBits, accumBlueBits, accumAlphaBits number
* of bits per color component in accum buffer.
- * \param indexBits number of bits per pixel if \p rgbFlag is GL_FALSE
* \param redBits number of bits per color component in frame buffer for RGB(A)
* mode. We always use 8 in core Mesa though.
* \param greenBits same as above.
* \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.
*
GLint accumGreenBits,
GLint accumBlueBits,
GLint accumAlphaBits,
- GLint numSamples )
+ GLuint numSamples )
{
struct gl_config *vis = CALLOC_STRUCT(gl_config);
if (vis) {
GLint accumGreenBits,
GLint accumBlueBits,
GLint accumAlphaBits,
- GLint numSamples )
+ GLuint numSamples )
{
assert(vis);
assert(accumBlueBits >= 0);
assert(accumAlphaBits >= 0);
- vis->rgbMode = GL_TRUE;
vis->doubleBufferMode = dbFlag;
vis->stereoMode = stereoFlag;
vis->alphaBits = alphaBits;
vis->rgbBits = redBits + greenBits + blueBits;
- vis->indexBits = 0;
vis->depthBits = depthBits;
vis->stencilBits = stencilBits;
vis->accumBlueBits = accumBlueBits;
vis->accumAlphaBits = accumAlphaBits;
- vis->haveAccumBuffer = accumRedBits > 0;
- vis->haveDepthBuffer = depthBits > 0;
- vis->haveStencilBuffer = stencilBits > 0;
-
vis->numAuxBuffers = 0;
vis->level = 0;
vis->sampleBuffers = numSamples > 0 ? 1 : 0;
* Destroy a visual and free its memory.
*
* \param vis visual.
- *
+ *
* Frees the visual structure.
*/
void
static void
one_time_fini(void)
{
- _mesa_destroy_shader_compiler();
+ glsl_type_singleton_decref();
_mesa_locale_fini();
}
*
* \sa _math_init().
*/
-static void
-one_time_init( struct gl_context *ctx )
+void
+_mesa_initialize(void)
{
- static GLbitfield api_init_mask = 0x0;
+ static bool initialized;
mtx_lock(&OneTimeLock);
/* truly one-time init */
- if (!api_init_mask) {
+ if (!initialized) {
GLuint i;
STATIC_ASSERT(sizeof(GLbyte) == 1);
atexit(one_time_fini);
-#if defined(DEBUG) && defined(__DATE__) && defined(__TIME__)
+#if defined(DEBUG)
if (MESA_VERBOSE != 0) {
- _mesa_debug(ctx, "Mesa %s DEBUG build %s %s\n",
- PACKAGE_VERSION, __DATE__, __TIME__);
+ _mesa_debug(NULL, "Mesa " PACKAGE_VERSION " DEBUG build" MESA_GIT_SHA1 "\n");
}
#endif
- }
- /* per-API one-time init */
- if (!(api_init_mask & (1 << ctx->API))) {
- _mesa_init_get_hash(ctx);
+ /* Take a glsl type reference for the duration of libGL's life to avoid
+ * unecessary creation/destruction of glsl types.
+ */
+ glsl_type_singleton_init_or_ref();
_mesa_init_remap_table();
}
- api_init_mask |= 1 << ctx->API;
+ initialized = true;
mtx_unlock(&OneTimeLock);
}
}
/* 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 );
/* Constants, may be overriden (usually only reduced) by device drivers */
consts->MaxTextureMbytes = MAX_TEXTURE_MBYTES;
- consts->MaxTextureLevels = MAX_TEXTURE_LEVELS;
+ consts->MaxTextureSize = 1 << (MAX_TEXTURE_LEVELS - 1);
consts->Max3DTextureLevels = MAX_3D_TEXTURE_LEVELS;
consts->MaxCubeTextureLevels = MAX_CUBE_TEXTURE_LEVELS;
consts->MaxTextureRectSize = MAX_TEXTURE_RECT_SIZE;
consts->MaxProgramMatrices = MAX_PROGRAM_MATRICES;
consts->MaxProgramMatrixStackDepth = MAX_PROGRAM_MATRIX_STACK_DEPTH;
+ /* Set the absolute minimum possible GLSL version. API_OPENGL_CORE can
+ * mean an OpenGL 3.0 forward-compatible context, so that implies a minimum
+ * possible version of 1.30. Otherwise, the minimum possible version 1.20.
+ * Since Mesa unconditionally advertises GL_ARB_shading_language_100 and
+ * GL_ARB_shader_objects, every driver has GLSL 1.20... even if they don't
+ * advertise any extensions to enable any shader stages (e.g.,
+ * GL_ARB_vertex_shader).
+ */
+ consts->GLSLVersion = api == API_OPENGL_CORE ? 130 : 120;
+ consts->GLSLVersionCompat = consts->GLSLVersion;
+
+ consts->GLSLLowerConstArrays = true;
+
/* 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->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 */
- consts->GLSLVersion = 120;
- _mesa_override_glsl_version(consts);
+ consts->MaxGeometryShaderInvocations = MAX_GEOMETRY_SHADER_INVOCATIONS;
#ifdef DEBUG
consts->GenerateTemporaryNames = true;
consts->UniformBooleanTrue = FLOAT_AS_UNION(1.0f).u;
/* GL_ARB_sync */
- consts->MaxServerWaitTimeout = 0x1fff7fffffffULL;
+ consts->MaxServerWaitTimeout = 0x7fffffff7fffffffULL;
/* GL_EXT_provoking_vertex */
consts->QuadsFollowProvokingVertexConvention = GL_TRUE;
/* GL_ARB_robustness */
consts->ResetStrategy = GL_NO_RESET_NOTIFICATION_ARB;
+ /* GL_KHR_robustness */
+ consts->RobustAccess = GL_FALSE;
+
/* ES 3.0 or ARB_ES3_compatibility */
consts->MaxElementIndex = 0xffffffffu;
consts->MaxComputeWorkGroupSize[0] = 1024;
consts->MaxComputeWorkGroupSize[1] = 1024;
consts->MaxComputeWorkGroupSize[2] = 64;
- consts->MaxComputeWorkGroupInvocations = 1024;
+ /* Enables compute support for GLES 3.1 if >= 128 */
+ consts->MaxComputeWorkGroupInvocations = 0;
/** GL_ARB_gpu_shader5 */
consts->MinFragmentInterpolationOffset = MIN_FRAGMENT_INTERPOLATION_OFFSET;
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;
+
+ /** GL_NV_conservative_raster */
+ consts->MaxSubpixelPrecisionBiasBits = 0;
+
+ /** GL_NV_conservative_raster_dilate */
+ consts->ConservativeRasterDilateRange[0] = 0.0;
+ consts->ConservativeRasterDilateRange[1] = 0.0;
+ consts->ConservativeRasterDilateGranularity = 0.0;
+
+ consts->glBeginEndBufferSize = 512 * 1024;
}
/* 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.Program[MESA_SHADER_FRAGMENT].MaxLocalParams <= MAX_PROGRAM_LOCAL_PARAMS);
/* Texture size checks */
- assert(ctx->Const.MaxTextureLevels <= MAX_TEXTURE_LEVELS);
+ assert(ctx->Const.MaxTextureSize <= (1 << (MAX_TEXTURE_LEVELS - 1)));
assert(ctx->Const.Max3DTextureLevels <= MAX_3D_TEXTURE_LEVELS);
assert(ctx->Const.MaxCubeTextureLevels <= MAX_CUBE_TEXTURE_LEVELS);
assert(ctx->Const.MaxTextureRectSize <= MAX_TEXTURE_RECT_SIZE);
assert(MAX_TEXTURE_LEVELS >= MAX_CUBE_TEXTURE_LEVELS);
/* Max texture size should be <= max viewport size (render to texture) */
- assert((1U << (ctx->Const.MaxTextureLevels - 1))
- <= ctx->Const.MaxViewportWidth);
- assert((1U << (ctx->Const.MaxTextureLevels - 1))
- <= ctx->Const.MaxViewportHeight);
+ assert(ctx->Const.MaxTextureSize <= ctx->Const.MaxViewportWidth);
+ assert(ctx->Const.MaxTextureSize <= ctx->Const.MaxViewportHeight);
assert(ctx->Const.MaxDrawBuffers <= MAX_DRAW_BUFFERS);
/* 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_conservative_raster( ctx );
_mesa_init_current( ctx );
_mesa_init_depth( ctx );
_mesa_init_debug( 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_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;
if (ctx) {
_mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid call)", name);
}
-#if defined(DEBUG)
+#ifndef NDEBUG
else if (getenv("MESA_DEBUG") || getenv("LIBGL_DEBUG")) {
fprintf(stderr,
"GL User Error: gl%s called without a rendering context\n",
* populated with pointers to "no-op" functions. In turn, the no-op
* functions will call nop_handler() above.
*/
-static struct _glapi_table *
-alloc_dispatch_table(void)
+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
{
struct _glapi_table *table;
- table = alloc_dispatch_table();
+ table = _mesa_alloc_dispatch_table();
if (!table)
return NULL;
* 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
_mesa_override_gl_version(ctx);
/* misc one-time initializations */
- one_time_init(ctx);
+ _mesa_initialize();
/* Plug in driver functions and context pointer here.
* This is important because when we call alloc_shared_state() below
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 = alloc_dispatch_table();
+ 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
= (getenv("MESA_TEX_PROG") != NULL);
* _mesa_choose_tex_format().
*/
memset(&ctx->TextureFormatSupported, GL_TRUE,
- sizeof(ctx->TextureFormatSupported));
+ sizeof(ctx->TextureFormatSupported));
switch (ctx->API) {
case API_OPENGL_COMPAT:
ctx->BeginEnd = create_beginend_table(ctx);
- ctx->Save = alloc_dispatch_table();
+ ctx->Save = _mesa_alloc_dispatch_table();
if (!ctx->BeginEnd || !ctx->Save)
goto fail;
* GL_OES_texture_cube_map says
* "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;
+ for (i = 0; i < ARRAY_SIZE(ctx->Texture.FixedFuncUnit); i++) {
+ struct gl_fixedfunc_texture_unit *texUnit =
+ &ctx->Texture.FixedFuncUnit[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:
}
-/**
- * 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) or
- * NULL to create a configless context
- * \param share_list another context to share display lists with or NULL
- * \param driverFunctions points to the dd_function_table into which the
- * driver has plugged in all its special functions.
- *
- * \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;
-
- 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().
*/
void
-_mesa_free_context_data( struct gl_context *ctx )
+_mesa_free_context_data(struct gl_context *ctx)
{
if (!_mesa_get_current_context()){
/* No current context, but we may need one in order to delete
_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_tesscprog(ctx, &ctx->TessCtrlProgram._Current, NULL);
- _mesa_reference_tesseprog(ctx, &ctx->TessEvalProgram._Current, NULL);
- _mesa_reference_geomprog(ctx, &ctx->GeometryProgram._Current, 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_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->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_reference_vao(ctx, &ctx->Array._EmptyVAO, NULL);
+ _mesa_reference_vao(ctx, &ctx->Array._DrawVAO, NULL);
_mesa_free_attrib_data(ctx);
_mesa_free_buffer_objects(ctx);
_mesa_free_eval_data( ctx );
_mesa_free_texture_data( ctx );
+ _mesa_free_image_textures(ctx);
_mesa_free_matrix_data( ctx );
_mesa_free_pipeline_data(ctx);
_mesa_free_program_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);
free(ctx->BeginEnd);
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);
free(ctx->VersionString);
+ ralloc_free(ctx->SoftFP64);
+
/* unbind the context if it's currently bound */
if (ctx == _mesa_get_current_context()) {
_mesa_make_current(NULL, NULL, NULL);
}
+
+ /* Do this after unbinding context to ensure any thread is finished. */
+ if (ctx->shader_builtin_ref) {
+ _mesa_glsl_builtin_functions_decref();
+ ctx->shader_builtin_ref = false;
+ }
+
+ free(ctx->Const.SpirVExtensions);
}
* Destroy a struct gl_context structure.
*
* \param ctx GL context.
- *
+ *
* Calls _mesa_free_context_data() and frees the gl_context object itself.
*/
void
/**
* Copy attribute groups from one context to another.
- *
+ *
* \param src source context
* \param dst destination context
* \param mask bitwise OR of GL_*_BIT flags
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 */
*
* \return GL_TRUE if compatible, GL_FALSE otherwise.
*/
-static GLboolean
+static GLboolean
check_compatible(const struct gl_context *ctx,
const struct gl_framebuffer *buffer)
{
ctxvis->foo != bufvis->foo) \
return GL_FALSE
- check_component(redMask);
- check_component(greenMask);
- check_component(blueMask);
+ check_component(redShift);
+ check_component(greenShift);
+ check_component(blueShift);
+ check_component(redBits);
+ check_component(greenBits);
+ check_component(blueBits);
check_component(depthBits);
check_component(stencilBits);
* 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;
}
}
+
static void
handle_first_current(struct gl_context *ctx)
{
- if (ctx->Version == 0) {
+ if (ctx->Version == 0 || !ctx->DrawBuffer) {
/* probably in the process of tearing down the context */
return;
}
- ctx->Extensions.String = _mesa_make_extension_string(ctx);
-
check_context_limits(ctx);
+ _mesa_update_vertex_processing_mode(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 */
+ * 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;
+ GLenum16 buffer;
if (ctx->DrawBuffer->Visual.doubleBufferMode)
buffer = GL_BACK;
}
}
+ /* 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
}
}
- if (curCtx &&
+ if (curCtx &&
(curCtx->WinSysDrawBuffer || curCtx->WinSysReadBuffer) &&
/* make sure this context is valid for flushing */
curCtx != newCtx &&
curCtx->Const.ContextReleaseBehavior ==
- GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH)
+ 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);
+ /* Call this periodically to detect when the user has begun using
+ * GL rendering from multiple threads.
+ */
+ _glapi_check_multithread();
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));
* changed since the last time this FBO was bound).
*/
_mesa_update_draw_buffers(newCtx);
+ _mesa_update_allow_draw_out_of_order(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) {
handle_first_current(newCtx);
- newCtx->FirstTimeCurrent = GL_FALSE;
+ newCtx->FirstTimeCurrent = GL_FALSE;
}
}
-
+
return GL_TRUE;
}
/**
* \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.
/**
* 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;
}
/*@}*/
/** \name Miscellaneous functions */
/**********************************************************************/
/*@{*/
-
-/**
- * Record an error.
- *
- * \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.
- *
- * \sa
- * This is called via _mesa_error().
- */
-void
-_mesa_record_error(struct gl_context *ctx, GLenum error)
-{
- if (!ctx)
- return;
-
- if (ctx->ErrorValue == GL_NO_ERROR) {
- ctx->ErrorValue = 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.
*/
_mesa_flush(struct gl_context *ctx)
{
FLUSH_VERTICES( ctx, 0 );
- FLUSH_CURRENT( ctx, 0 );
if (ctx->Driver.Flush) {
ctx->Driver.Flush(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.
{
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
- _mesa_finish(ctx);
+
+ FLUSH_VERTICES(ctx, 0);
+
+ if (ctx->Driver.Finish) {
+ ctx->Driver.Finish(ctx);
+ }
}
}
-/*
- * 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.
- * It also check the current pipeline object is valid if any.
- * If an error is detected it'll be recorded here.
- * \return GL_TRUE if OK to render, GL_FALSE if not
- */
-GLboolean
-_mesa_valid_to_render(struct gl_context *ctx, const char *where)
-{
- /* This depends on having up to date derived state (shaders) */
- if (ctx->NewState)
- _mesa_update_state(ctx);
-
- if (ctx->API == API_OPENGL_COMPAT) {
- /* Any shader stages that are not supplied by the GLSL shader and have
- * assembly shaders enabled must now be validated.
- */
- if (!ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX]
- && ctx->VertexProgram.Enabled && !ctx->VertexProgram._Enabled) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "%s(vertex program not valid)", where);
- return GL_FALSE;
- }
-
- if (!ctx->_Shader->CurrentProgram[MESA_SHADER_FRAGMENT]) {
- 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;
- }
- }
- }
-
- /* A pipeline object is bound */
- if (ctx->_Shader->Name && !ctx->_Shader->Validated) {
- if (!_mesa_validate_program_pipeline(ctx, ctx->_Shader)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glValidateProgramPipeline failed to validate the "
- "pipeline");
- return GL_FALSE;
- }
- }
-
- /* If a program is active and SSO not in use, check if validation of
- * samplers succeeded for the active program. */
- if (ctx->_Shader->ActiveProgram && ctx->_Shader != ctx->Pipeline.Current) {
- char errMsg[100];
- if (!_mesa_sampler_uniforms_are_valid(ctx->_Shader->ActiveProgram,
- errMsg, 100)) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "%s", errMsg);
- return GL_FALSE;
- }
- }
-
- if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
- _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
- "%s(incomplete framebuffer)", where);
- 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 = ctx->_Shader->CurrentProgram;
- gl_shader_stage i;
-
- for (i = 0; i < MESA_SHADER_STAGES; 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_STAGES; i++) {
- if (shProg[i] != NULL)
- shProg[i]->_Used = GL_TRUE;
- }
- }
-#endif
-
- return GL_TRUE;
-}
-
-
/*@}*/