/*
* Mesa 3-D graphics library
- * Version: 7.3
*
* Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
* Copyright (C) 2008 VMware, Inc. All Rights Reserved.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
*/
/**
#include "glheader.h"
-#include "mfeatures.h"
#include "imports.h"
#include "accum.h"
#include "api_exec.h"
+#include "api_loopback.h"
#include "arrayobj.h"
#include "attrib.h"
#include "blend.h"
#include "buffers.h"
#include "bufferobj.h"
-#include "colortab.h"
#include "context.h"
#include "cpuinfo.h"
#include "debug.h"
#include "fbobject.h"
#include "feedback.h"
#include "fog.h"
+#include "formats.h"
#include "framebuffer.h"
-#include "histogram.h"
#include "hint.h"
#include "hash.h"
#include "light.h"
#include "macros.h"
#include "matrix.h"
#include "multisample.h"
+#include "performance_monitor.h"
#include "pixel.h"
#include "pixelstore.h"
#include "points.h"
#include "polygon.h"
#include "queryobj.h"
-#if FEATURE_ARB_sync
#include "syncobj.h"
-#endif
#include "rastpos.h"
#include "remap.h"
#include "scissor.h"
#include "shared.h"
+#include "shaderobj.h"
#include "simple_list.h"
#include "state.h"
#include "stencil.h"
#include "version.h"
#include "viewport.h"
#include "vtxfmt.h"
-#include "shader/program.h"
-#include "shader/prog_print.h"
-#include "shader/shader_api.h"
-#if _HAVE_FULL_GL
+#include "program/program.h"
+#include "program/prog_print.h"
#include "math/m_matrix.h"
-#endif
+#include "main/dispatch.h" /* for _gloffset_COUNT */
#ifdef USE_SPARC_ASM
#include "sparc/sparc.h"
#endif
+#include "glsl_parser_extras.h"
+#include <stdbool.h>
+
+
#ifndef MESA_VERBOSE
int MESA_VERBOSE = 0;
#endif
* We have to finish any pending rendering.
*/
void
-_mesa_notifySwapBuffers(__GLcontext *ctx)
+_mesa_notifySwapBuffers(struct gl_context *ctx)
{
if (MESA_VERBOSE & VERBOSE_SWAPBUFFERS)
_mesa_debug(ctx, "SwapBuffers\n");
/*@{*/
/**
- * Allocates a GLvisual structure and initializes it via
+ * Allocates a struct gl_config structure and initializes it via
* _mesa_initialize_visual().
*
* \param dbFlag double buffering
* is acceptable but the actual depth type will be GLushort or GLuint as
* needed.
* \param stencilBits requested minimum bits per stencil buffer value
- * \param accumRedBits, accumGreenBits, accumBlueBits, accumAlphaBits number of bits per color component in accum buffer.
+ * \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 alphaBits same as above.
* \param numSamples not really used.
*
- * \return pointer to new GLvisual or NULL if requested parameters can't be
- * met.
+ * \return pointer to new struct gl_config or NULL if requested parameters
+ * can't be met.
*
* \note Need to add params for level and numAuxBuffers (at least)
*/
-GLvisual *
+struct gl_config *
_mesa_create_visual( GLboolean dbFlag,
GLboolean stereoFlag,
GLint redBits,
GLint accumAlphaBits,
GLint numSamples )
{
- GLvisual *vis = (GLvisual *) calloc(1, sizeof(GLvisual));
+ struct gl_config *vis = CALLOC_STRUCT(gl_config);
if (vis) {
if (!_mesa_initialize_visual(vis, dbFlag, stereoFlag,
redBits, greenBits, blueBits, alphaBits,
return vis;
}
+
/**
- * Makes some sanity checks and fills in the fields of the
- * GLvisual object with the given parameters. If the caller needs
- * to set additional fields, he should just probably init the whole GLvisual
- * 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.
*/
GLboolean
-_mesa_initialize_visual( GLvisual *vis,
+_mesa_initialize_visual( struct gl_config *vis,
GLboolean dbFlag,
GLboolean stereoFlag,
GLint redBits,
if (depthBits < 0 || depthBits > 32) {
return GL_FALSE;
}
- if (stencilBits < 0 || stencilBits > STENCIL_BITS) {
+ if (stencilBits < 0 || stencilBits > 8) {
return GL_FALSE;
}
assert(accumRedBits >= 0);
vis->numAuxBuffers = 0;
vis->level = 0;
- vis->pixmapMode = 0;
vis->sampleBuffers = numSamples > 0 ? 1 : 0;
vis->samples = numSamples;
* Frees the visual structure.
*/
void
-_mesa_destroy_visual( GLvisual *vis )
+_mesa_destroy_visual( struct gl_config *vis )
{
free(vis);
}
static void
dummy_enum_func(void)
{
- gl_buffer_index bi;
- gl_colortable_index ci;
- gl_face_index fi;
- gl_frag_attrib fa;
- gl_frag_result fr;
- gl_texture_index ti;
- gl_vert_attrib va;
- gl_vert_result vr;
+ 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) ci;
(void) fi;
- (void) fa;
(void) fr;
(void) ti;
(void) va;
- (void) vr;
+ (void) vs;
}
*/
_glthread_DECLARE_STATIC_MUTEX(OneTimeLock);
+
+
/**
* Calls all the various one-time-init functions in Mesa.
*
* \sa _math_init().
*/
static void
-one_time_init( GLcontext *ctx )
+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 */
_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();
-
for (i = 0; i < 256; i++) {
_mesa_ubyte_to_float_color_tab[i] = (float) i / 255.0F;
}
#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",
+ PACKAGE_VERSION, __DATE__, __TIME__);
+ }
#endif
- alreadyCalled = GL_TRUE;
+#ifdef DEBUG
+ _mesa_test_formats();
+#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();
}
* Initialize fields of gl_current_attrib (aka ctx->Current.*)
*/
static void
-_mesa_init_current(GLcontext *ctx)
+_mesa_init_current(struct gl_context *ctx)
{
GLuint i;
/**
- * Init vertex/fragment program limits.
+ * Init vertex/fragment/geometry program limits.
* Important: drivers should override these with actual limits.
*/
static void
-init_program_limits(GLenum type, struct gl_program_constants *prog)
+init_program_limits(struct gl_context *ctx, GLenum type,
+ struct gl_program_constants *prog)
{
prog->MaxInstructions = MAX_PROGRAM_INSTRUCTIONS;
prog->MaxAluInstructions = MAX_PROGRAM_INSTRUCTIONS;
prog->MaxTemps = MAX_PROGRAM_TEMPS;
prog->MaxEnvParams = MAX_PROGRAM_ENV_PARAMS;
prog->MaxLocalParams = MAX_PROGRAM_LOCAL_PARAMS;
- prog->MaxUniformComponents = 4 * MAX_UNIFORMS;
+ prog->MaxAddressOffset = MAX_PROGRAM_LOCAL_PARAMS;
- if (type == GL_VERTEX_PROGRAM_ARB) {
+ switch (type) {
+ case GL_VERTEX_PROGRAM_ARB:
prog->MaxParameters = MAX_VERTEX_PROGRAM_PARAMS;
- prog->MaxAttribs = MAX_NV_VERTEX_PROGRAM_INPUTS;
+ prog->MaxAttribs = MAX_VERTEX_GENERIC_ATTRIBS;
prog->MaxAddressRegs = MAX_VERTEX_PROGRAM_ADDRESS_REGS;
- }
- else {
+ 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;
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:
+ 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->MaxInputComponents = 16 * 4; /* old limit not to break tnl and swrast */
+ prog->MaxOutputComponents = 16 * 4; /* old limit not to break tnl and swrast */
+ break;
+ default:
+ assert(0 && "Bad program type in init_program_limits()");
}
/* Set the native limits to zero. This implies that there is no native
prog->MaxNativeTemps = 0;
prog->MaxNativeAddressRegs = 0;
prog->MaxNativeParameters = 0;
+
+ /* Set GLSL datatype range/precision info assuming IEEE float values.
+ * Drivers should override these defaults as needed.
+ */
+ prog->MediumFloat.RangeMin = 127;
+ prog->MediumFloat.RangeMax = 127;
+ prog->MediumFloat.Precision = 23;
+ prog->LowFloat = prog->HighFloat = prog->MediumFloat;
+
+ /* Assume ints are stored as floats for now, since this is the least-common
+ * denominator. The OpenGL ES spec implies (page 132) that the precision
+ * of integer types should be 0. Practically speaking, IEEE
+ * single-precision floating point values can only store integers in the
+ * range [-0x01000000, 0x01000000] without loss of precision.
+ */
+ prog->MediumInt.RangeMin = 24;
+ prog->MediumInt.RangeMax = 24;
+ prog->MediumInt.Precision = 0;
+ prog->LowInt = prog->HighInt = prog->MediumInt;
+
+ prog->MaxUniformBlocks = 12;
+ prog->MaxCombinedUniformComponents = (prog->MaxUniformComponents +
+ ctx->Const.MaxUniformBlockSize / 4 *
+ prog->MaxUniformBlocks);
}
* some of these values (such as number of texture units).
*/
static void
-_mesa_init_constants(GLcontext *ctx)
+_mesa_init_constants(struct gl_context *ctx)
{
assert(ctx);
/* 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.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
+ ctx->Const.FragmentProgram.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
ctx->Const.MaxTextureUnits = MIN2(ctx->Const.MaxTextureCoordUnits,
- ctx->Const.MaxTextureImageUnits);
+ ctx->Const.FragmentProgram.MaxTextureImageUnits);
ctx->Const.MaxTextureMaxAnisotropy = MAX_TEXTURE_MAX_ANISOTROPY;
ctx->Const.MaxTextureLodBias = MAX_TEXTURE_LOD_BIAS;
+ ctx->Const.MaxTextureBufferSize = 65536;
+ ctx->Const.TextureBufferOffsetAlignment = 1;
ctx->Const.MaxArrayLockSize = MAX_ARRAY_LOCK_SIZE;
ctx->Const.SubPixelBits = SUB_PIXEL_BITS;
ctx->Const.MinPointSize = MIN_POINT_SIZE;
ctx->Const.MinLineWidthAA = MIN_LINE_WIDTH;
ctx->Const.MaxLineWidthAA = MAX_LINE_WIDTH;
ctx->Const.LineWidthGranularity = (GLfloat) LINE_WIDTH_GRANULARITY;
- ctx->Const.MaxColorTableSize = MAX_COLOR_TABLE_SIZE;
- ctx->Const.MaxConvolutionWidth = MAX_CONVOLUTION_WIDTH;
- ctx->Const.MaxConvolutionHeight = MAX_CONVOLUTION_HEIGHT;
- ctx->Const.MaxClipPlanes = MAX_CLIP_PLANES;
+ ctx->Const.MaxClipPlanes = 6;
ctx->Const.MaxLights = MAX_LIGHTS;
ctx->Const.MaxShininess = 128.0;
ctx->Const.MaxSpotExponent = 128.0;
- ctx->Const.MaxViewportWidth = MAX_WIDTH;
- ctx->Const.MaxViewportHeight = MAX_HEIGHT;
-#if FEATURE_ARB_vertex_program
- init_program_limits(GL_VERTEX_PROGRAM_ARB, &ctx->Const.VertexProgram);
-#endif
-#if FEATURE_ARB_fragment_program
- init_program_limits(GL_FRAGMENT_PROGRAM_ARB, &ctx->Const.FragmentProgram);
-#endif
+ ctx->Const.MaxViewportWidth = MAX_VIEWPORT_WIDTH;
+ ctx->Const.MaxViewportHeight = MAX_VIEWPORT_HEIGHT;
+
+ /** GL_ARB_uniform_buffer_object */
+ ctx->Const.MaxCombinedUniformBlocks = 36;
+ ctx->Const.MaxUniformBufferBindings = 36;
+ ctx->Const.MaxUniformBlockSize = 16384;
+ ctx->Const.UniformBufferOffsetAlignment = 1;
+
+ init_program_limits(ctx, GL_VERTEX_PROGRAM_ARB, &ctx->Const.VertexProgram);
+ init_program_limits(ctx, GL_FRAGMENT_PROGRAM_ARB, &ctx->Const.FragmentProgram);
+ init_program_limits(ctx, MESA_GEOMETRY_PROGRAM, &ctx->Const.GeometryProgram);
+
ctx->Const.MaxProgramMatrices = MAX_PROGRAM_MATRICES;
ctx->Const.MaxProgramMatrixStackDepth = MAX_PROGRAM_MATRIX_STACK_DEPTH;
/* GL_ARB_draw_buffers */
ctx->Const.MaxDrawBuffers = MAX_DRAW_BUFFERS;
-#if FEATURE_EXT_framebuffer_object
ctx->Const.MaxColorAttachments = MAX_COLOR_ATTACHMENTS;
- ctx->Const.MaxRenderbufferSize = MAX_WIDTH;
-#endif
+ ctx->Const.MaxRenderbufferSize = MAX_RENDERBUFFER_SIZE;
-#if FEATURE_ARB_vertex_shader
- ctx->Const.MaxVertexTextureImageUnits = MAX_VERTEX_TEXTURE_IMAGE_UNITS;
+ ctx->Const.VertexProgram.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
ctx->Const.MaxCombinedTextureImageUnits = MAX_COMBINED_TEXTURE_IMAGE_UNITS;
- ctx->Const.MaxVarying = MAX_VARYING;
-#endif
+ 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;
+
+ /* 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 */
+ }
/* GL_ARB_framebuffer_object */
ctx->Const.MaxSamples = 0;
/* GL_ARB_sync */
- ctx->Const.MaxServerWaitTimeout = (GLuint64) ~0;
+ ctx->Const.MaxServerWaitTimeout = 0x1fff7fffffffULL;
/* GL_ATI_envmap_bumpmap */
ctx->Const.SupportedBumpUnits = SUPPORTED_ATI_BUMP_UNITS;
ctx->Const.QuadsFollowProvokingVertexConvention = GL_TRUE;
/* GL_EXT_transform_feedback */
- ctx->Const.MaxTransformFeedbackSeparateAttribs = MAX_FEEDBACK_ATTRIBS;
+ ctx->Const.MaxTransformFeedbackBuffers = MAX_FEEDBACK_BUFFERS;
ctx->Const.MaxTransformFeedbackSeparateComponents = 4 * MAX_FEEDBACK_ATTRIBS;
ctx->Const.MaxTransformFeedbackInterleavedComponents = 4 * MAX_FEEDBACK_ATTRIBS;
+ ctx->Const.MaxVertexStreams = 1;
+
+ /* GL 3.2 */
+ ctx->Const.ProfileMask = ctx->API == API_OPENGL_CORE
+ ? GL_CONTEXT_CORE_PROFILE_BIT
+ : GL_CONTEXT_COMPATIBILITY_PROFILE_BIT;
+
+ /** GL_EXT_gpu_shader4 */
+ ctx->Const.MinProgramTexelOffset = -8;
+ ctx->Const.MaxProgramTexelOffset = 7;
+
+ /* GL_ARB_texture_gather */
+ ctx->Const.MinProgramTextureGatherOffset = -8;
+ ctx->Const.MaxProgramTextureGatherOffset = 7;
+
+ /* GL_ARB_robustness */
+ ctx->Const.ResetStrategy = GL_NO_RESET_NOTIFICATION_ARB;
+
+ /* PrimitiveRestart */
+ ctx->Const.PrimitiveRestartInSoftware = GL_FALSE;
- /* GL 3.2: hard-coded for now: */
- ctx->Const.ProfileMask = GL_CONTEXT_COMPATIBILITY_PROFILE_BIT;
+ /* ES 3.0 or ARB_ES3_compatibility */
+ ctx->Const.MaxElementIndex = 0xffffffffu;
+
+ /* GL_ARB_texture_multisample */
+ ctx->Const.MaxColorTextureSamples = 1;
+ ctx->Const.MaxDepthTextureSamples = 1;
+ ctx->Const.MaxIntegerSamples = 1;
}
* Only called the first time a context is bound.
*/
static void
-check_context_limits(GLcontext *ctx)
+check_context_limits(struct gl_context *ctx)
{
/* check that we don't exceed the size of various bitfields */
- assert(VERT_RESULT_MAX <=
+ assert(VARYING_SLOT_MAX <=
(8 * sizeof(ctx->VertexProgram._Current->Base.OutputsWritten)));
- assert(FRAG_ATTRIB_MAX <=
+ assert(VARYING_SLOT_MAX <=
(8 * sizeof(ctx->FragmentProgram._Current->Base.InputsRead)));
- assert(MAX_COMBINED_TEXTURE_IMAGE_UNITS <= 8 * sizeof(GLbitfield));
-
/* shader-related checks */
assert(ctx->Const.FragmentProgram.MaxLocalParams <= MAX_PROGRAM_LOCAL_PARAMS);
assert(ctx->Const.VertexProgram.MaxLocalParams <= MAX_PROGRAM_LOCAL_PARAMS);
- assert(MAX_NV_FRAGMENT_PROGRAM_TEMPS <= MAX_PROGRAM_TEMPS);
- assert(MAX_NV_VERTEX_PROGRAM_TEMPS <= MAX_PROGRAM_TEMPS);
- assert(MAX_NV_VERTEX_PROGRAM_INPUTS <= VERT_ATTRIB_MAX);
- assert(MAX_NV_VERTEX_PROGRAM_OUTPUTS <= VERT_RESULT_MAX);
-
/* Texture unit checks */
- assert(ctx->Const.MaxTextureImageUnits > 0);
- assert(ctx->Const.MaxTextureImageUnits <= MAX_TEXTURE_IMAGE_UNITS);
+ assert(ctx->Const.FragmentProgram.MaxTextureImageUnits > 0);
+ assert(ctx->Const.FragmentProgram.MaxTextureImageUnits <= MAX_TEXTURE_IMAGE_UNITS);
assert(ctx->Const.MaxTextureCoordUnits > 0);
assert(ctx->Const.MaxTextureCoordUnits <= MAX_TEXTURE_COORD_UNITS);
assert(ctx->Const.MaxTextureUnits > 0);
assert(ctx->Const.MaxTextureUnits <= MAX_TEXTURE_IMAGE_UNITS);
assert(ctx->Const.MaxTextureUnits <= MAX_TEXTURE_COORD_UNITS);
- assert(ctx->Const.MaxTextureUnits == MIN2(ctx->Const.MaxTextureImageUnits,
+ assert(ctx->Const.MaxTextureUnits == MIN2(ctx->Const.FragmentProgram.MaxTextureImageUnits,
ctx->Const.MaxTextureCoordUnits));
assert(ctx->Const.MaxCombinedTextureImageUnits > 0);
assert(ctx->Const.MaxCombinedTextureImageUnits <= MAX_COMBINED_TEXTURE_IMAGE_UNITS);
assert(ctx->Const.MaxTextureCoordUnits <= MAX_COMBINED_TEXTURE_IMAGE_UNITS);
/* number of coord units cannot be greater than number of image units */
- assert(ctx->Const.MaxTextureCoordUnits <= ctx->Const.MaxTextureImageUnits);
+ assert(ctx->Const.MaxTextureCoordUnits <= ctx->Const.FragmentProgram.MaxTextureImageUnits);
/* Texture size checks */
assert(ctx->Const.MaxCubeTextureLevels <= MAX_CUBE_TEXTURE_LEVELS);
assert(ctx->Const.MaxTextureRectSize <= MAX_TEXTURE_RECT_SIZE);
- /* make sure largest texture image is <= MAX_WIDTH in size */
- assert((1 << (ctx->Const.MaxTextureLevels - 1)) <= MAX_WIDTH);
- assert((1 << (ctx->Const.MaxCubeTextureLevels - 1)) <= MAX_WIDTH);
- assert((1 << (ctx->Const.Max3DTextureLevels - 1)) <= MAX_WIDTH);
-
/* Texture level checks */
assert(MAX_TEXTURE_LEVELS >= MAX_3D_TEXTURE_LEVELS);
assert(MAX_TEXTURE_LEVELS >= MAX_CUBE_TEXTURE_LEVELS);
/* Max texture size should be <= max viewport size (render to texture) */
- assert((1 << (MAX_TEXTURE_LEVELS - 1)) <= MAX_WIDTH);
-
- assert(ctx->Const.MaxViewportWidth <= MAX_WIDTH);
- assert(ctx->Const.MaxViewportHeight <= MAX_WIDTH);
+ assert((1U << (ctx->Const.MaxTextureLevels - 1))
+ <= ctx->Const.MaxViewportWidth);
+ assert((1U << (ctx->Const.MaxTextureLevels - 1))
+ <= ctx->Const.MaxViewportHeight);
assert(ctx->Const.MaxDrawBuffers <= MAX_DRAW_BUFFERS);
* functions for the more complex data structures.
*/
static GLboolean
-init_attrib_groups(GLcontext *ctx)
+init_attrib_groups(struct gl_context *ctx)
{
assert(ctx);
_mesa_init_attrib( ctx );
_mesa_init_buffer_objects( ctx );
_mesa_init_color( ctx );
- _mesa_init_colortables( ctx );
_mesa_init_current( ctx );
_mesa_init_depth( ctx );
_mesa_init_debug( ctx );
_mesa_init_display_list( ctx );
+ _mesa_init_errors( ctx );
_mesa_init_eval( ctx );
_mesa_init_fbobjects( ctx );
_mesa_init_feedback( ctx );
_mesa_init_fog( ctx );
- _mesa_init_histogram( ctx );
_mesa_init_hint( ctx );
_mesa_init_line( ctx );
_mesa_init_lighting( ctx );
_mesa_init_matrix( ctx );
_mesa_init_multisample( ctx );
+ _mesa_init_performance_monitors( ctx );
_mesa_init_pixel( ctx );
_mesa_init_pixelstore( ctx );
_mesa_init_point( ctx );
_mesa_init_polygon( ctx );
_mesa_init_program( ctx );
_mesa_init_queryobj( ctx );
-#if FEATURE_ARB_sync
_mesa_init_sync( ctx );
-#endif
_mesa_init_rastpos( ctx );
_mesa_init_scissor( ctx );
_mesa_init_shader_state( ctx );
/* Miscellaneous */
ctx->NewState = _NEW_ALL;
- ctx->ErrorValue = (GLenum) GL_NO_ERROR;
- ctx->varying_vp_inputs = ~0;
+ ctx->NewDriverState = ~0;
+ ctx->ErrorValue = GL_NO_ERROR;
+ ctx->ResetStatus = GL_NO_ERROR;
+ ctx->varying_vp_inputs = VERT_BIT_ALL;
return GL_TRUE;
}
* state.
*/
static GLboolean
-update_default_objects(GLcontext *ctx)
+update_default_objects(struct gl_context *ctx)
{
assert(ctx);
* This helps prevents a segfault when someone calls a GL function without
* first checking if the extension's supported.
*/
-static int
-generic_nop(void)
+int
+_mesa_generic_nop(void)
{
- _mesa_warning(NULL, "User called no-op dispatch function (an unsupported extension function?)");
+ GET_CURRENT_CONTEXT(ctx);
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "unsupported function called "
+ "(unsupported extension or deprecated function?)");
return 0;
}
* Allocate and initialize a new dispatch table.
*/
struct _glapi_table *
-_mesa_alloc_dispatch_table(int size)
+_mesa_alloc_dispatch_table()
{
/* Find the larger of Mesa's dispatch table and libGL's dispatch table.
* In practice, this'll be the same for stand-alone Mesa. But for DRI
* 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;
+
+ table = malloc(numEntries * sizeof(_glapi_proc));
if (table) {
_glapi_proc *entry = (_glapi_proc *) table;
GLint i;
for (i = 0; i < numEntries; i++) {
- entry[i] = (_glapi_proc) generic_nop;
+ entry[i] = (_glapi_proc) _mesa_generic_nop;
}
}
return table;
}
+/**
+ * Creates a minimal dispatch table for use within glBegin()/glEnd().
+ *
+ * This ensures that we generate GL_INVALID_OPERATION errors from most
+ * functions, since the set of functions that are valid within Begin/End is
+ * very small.
+ *
+ * From the GL 1.0 specification section 2.6.3, "GL Commands within
+ * Begin/End"
+ *
+ * "The only GL commands that are allowed within any Begin/End pairs are
+ * the commands for specifying vertex coordinates, vertex color, normal
+ * coordinates, and texture coordinates (Vertex, Color, Index, Normal,
+ * TexCoord), EvalCoord and EvalPoint commands (see section 5.1),
+ * commands for specifying lighting material parameters (Material
+ * commands see section 2.12.2), display list invocation commands
+ * (CallList and CallLists see section 5.4), and the EdgeFlag
+ * command. Executing Begin after Begin has already been executed but
+ * before an End is issued generates the INVALID OPERATION error, as does
+ * executing End without a previous corresponding Begin. Executing any
+ * other GL command within Begin/End results in the error INVALID
+ * OPERATION."
+ *
+ * The table entries for specifying vertex attributes are set up by
+ * install_vtxfmt() and _mesa_loopback_init_api_table(), and End() and dlists
+ * are set by install_vtxfmt() as well.
+ */
+static struct _glapi_table *
+create_beginend_table(const struct gl_context *ctx)
+{
+ struct _glapi_table *table;
+
+ table = _mesa_alloc_dispatch_table();
+ if (!table)
+ return NULL;
+
+ /* Fill in functions which return a value, since they should return some
+ * specific value even if they emit a GL_INVALID_OPERATION error from them
+ * being called within glBegin()/glEnd().
+ */
+#define COPY_DISPATCH(func) SET_##func(table, GET_##func(ctx->Exec))
+
+ COPY_DISPATCH(GenLists);
+ COPY_DISPATCH(IsProgram);
+ COPY_DISPATCH(IsVertexArray);
+ COPY_DISPATCH(IsBuffer);
+ COPY_DISPATCH(IsEnabled);
+ COPY_DISPATCH(IsEnabledi);
+ COPY_DISPATCH(IsRenderbuffer);
+ COPY_DISPATCH(IsFramebuffer);
+ COPY_DISPATCH(CheckFramebufferStatus);
+ COPY_DISPATCH(RenderMode);
+ COPY_DISPATCH(GetString);
+ COPY_DISPATCH(GetStringi);
+ COPY_DISPATCH(GetPointerv);
+ COPY_DISPATCH(IsQuery);
+ COPY_DISPATCH(IsSampler);
+ COPY_DISPATCH(IsSync);
+ COPY_DISPATCH(IsTexture);
+ COPY_DISPATCH(IsTransformFeedback);
+ COPY_DISPATCH(DeleteQueries);
+ COPY_DISPATCH(AreTexturesResident);
+ COPY_DISPATCH(FenceSync);
+ COPY_DISPATCH(ClientWaitSync);
+ COPY_DISPATCH(MapBuffer);
+ COPY_DISPATCH(UnmapBuffer);
+ COPY_DISPATCH(MapBufferRange);
+ COPY_DISPATCH(ObjectPurgeableAPPLE);
+ COPY_DISPATCH(ObjectUnpurgeableAPPLE);
+
+ _mesa_loopback_init_api_table(ctx, table);
+
+ return table;
+}
+
+void
+_mesa_initialize_dispatch_tables(struct gl_context *ctx)
+{
+ /* Do the code-generated setup of the exec table in api_exec.c. */
+ _mesa_initialize_exec_table(ctx);
+
+ if (ctx->Save)
+ _mesa_initialize_save_table(ctx);
+}
/**
- * Initialize a GLcontext struct (rendering context).
+ * Initialize a struct gl_context struct (rendering context).
*
* This includes allocating all the other structs and arrays which hang off of
* the context by pointers.
* etc with, or NULL
* \param driverFunctions table of device driver functions for this context
* to use
- * \param driverContext pointer to driver-specific context data
*/
GLboolean
-_mesa_initialize_context_for_api(GLcontext *ctx,
- gl_api api,
- const GLvisual *visual,
- GLcontext *share_list,
- const struct dd_function_table *driverFunctions,
- void *driverContext)
+_mesa_initialize_context(struct gl_context *ctx,
+ gl_api api,
+ const struct gl_config *visual,
+ struct gl_context *share_list,
+ const struct dd_function_table *driverFunctions)
{
struct gl_shared_state *shared;
int i;
- /*ASSERT(driverContext);*/
assert(driverFunctions->NewTextureObject);
- assert(driverFunctions->FreeTexImageData);
+ assert(driverFunctions->FreeTextureImageBuffer);
ctx->API = api;
ctx->Visual = *visual;
ctx->WinSysDrawBuffer = NULL;
ctx->WinSysReadBuffer = NULL;
+ if (_mesa_is_desktop_gl(ctx)) {
+ _mesa_override_gl_version(ctx);
+ }
+
/* misc one-time initializations */
one_time_init(ctx);
* textures.
*/
ctx->Driver = *driverFunctions;
- ctx->DriverCtx = driverContext;
if (share_list) {
/* share state with another context */
return GL_FALSE;
}
- _glthread_LOCK_MUTEX(shared->Mutex);
- ctx->Shared = shared;
- shared->RefCount++;
- _glthread_UNLOCK_MUTEX(shared->Mutex);
+ _mesa_reference_shared_state(ctx, &ctx->Shared, shared);
- if (!init_attrib_groups( ctx )) {
- _mesa_release_shared_state(ctx, ctx->Shared);
- return GL_FALSE;
- }
-
-#if FEATURE_dispatch
- /* setup the API dispatch tables */
- switch (ctx->API) {
-#if FEATURE_GL
- case API_OPENGL:
- ctx->Exec = _mesa_create_exec_table();
- break;
-#endif
-#if FEATURE_ES1
- case API_OPENGLES:
- ctx->Exec = _mesa_create_exec_table_es1();
- break;
-#endif
-#if FEATURE_ES2
- case API_OPENGLES2:
- ctx->Exec = _mesa_create_exec_table_es2();
- break;
-#endif
- default:
- _mesa_problem(ctx, "unknown or unsupported API");
- break;
- }
+ if (!init_attrib_groups( ctx ))
+ goto fail;
- if (!ctx->Exec) {
- _mesa_release_shared_state(ctx, ctx->Shared);
- return GL_FALSE;
- }
-#endif
- ctx->CurrentDispatch = ctx->Exec;
+ /* setup the API dispatch tables with all nop functions */
+ ctx->OutsideBeginEnd = _mesa_alloc_dispatch_table();
+ if (!ctx->OutsideBeginEnd)
+ goto fail;
+ ctx->Exec = ctx->OutsideBeginEnd;
+ ctx->CurrentDispatch = ctx->OutsideBeginEnd;
ctx->FragmentProgram._MaintainTexEnvProgram
= (_mesa_getenv("MESA_TEX_PROG") != NULL);
ctx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE;
}
- switch (ctx->API) {
- case API_OPENGL:
- /* Neutral tnl module stuff */
- _mesa_init_exec_vtxfmt( ctx );
- ctx->TnlModule.Current = NULL;
- ctx->TnlModule.SwapCount = 0;
-
-#if FEATURE_dlist
- ctx->Save = _mesa_create_save_table();
- if (!ctx->Save) {
- _mesa_release_shared_state(ctx, ctx->Shared);
- free(ctx->Exec);
- return GL_FALSE;
- }
+ /* Mesa core handles all the formats that mesa core knows about.
+ * Drivers will want to override this list with just the formats
+ * they can handle, and confirm that appropriate fallbacks exist in
+ * _mesa_choose_tex_format().
+ */
+ memset(&ctx->TextureFormatSupported, GL_TRUE,
+ sizeof(ctx->TextureFormatSupported));
- _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt );
-#endif
+ switch (ctx->API) {
+ case API_OPENGL_COMPAT:
+ ctx->BeginEnd = create_beginend_table(ctx);
+ ctx->Save = _mesa_alloc_dispatch_table();
+ if (!ctx->BeginEnd || !ctx->Save)
+ goto fail;
+
+ /* fall-through */
+ case API_OPENGL_CORE:
break;
case API_OPENGLES:
/**
case API_OPENGLES2:
ctx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE;
ctx->VertexProgram._MaintainTnlProgram = GL_TRUE;
- ctx->Point.PointSprite = GL_TRUE; /* always on for ES 2.x */
break;
}
ctx->FirstTimeCurrent = GL_TRUE;
return GL_TRUE;
-}
-GLboolean
-_mesa_initialize_context(GLcontext *ctx,
- const GLvisual *visual,
- GLcontext *share_list,
- const struct dd_function_table *driverFunctions,
- void *driverContext)
-{
- return _mesa_initialize_context_for_api(ctx,
- API_OPENGL,
- visual,
- share_list,
- driverFunctions,
- driverContext);
+fail:
+ _mesa_reference_shared_state(ctx, &ctx->Shared, NULL);
+ free(ctx->BeginEnd);
+ free(ctx->Exec);
+ free(ctx->Save);
+ return GL_FALSE;
}
+
/**
- * Allocate and initialize a GLcontext structure.
+ * 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 GLvisual pointer (we copy the struct contents)
+ * \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.
- * \param driverContext points to the device driver's private context state
*
- * \return pointer to a new __GLcontextRec or NULL if error.
+ * \return pointer to a new __struct gl_contextRec or NULL if error.
*/
-GLcontext *
-_mesa_create_context_for_api(gl_api api,
- const GLvisual *visual,
- GLcontext *share_list,
- const struct dd_function_table *driverFunctions,
- void *driverContext)
+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)
{
- GLcontext *ctx;
+ struct gl_context *ctx;
ASSERT(visual);
- /*ASSERT(driverContext);*/
- ctx = (GLcontext *) calloc(1, sizeof(GLcontext));
+ ctx = calloc(1, sizeof(struct gl_context));
if (!ctx)
return NULL;
- if (_mesa_initialize_context_for_api(ctx, api, visual, share_list,
- driverFunctions, driverContext)) {
+ if (_mesa_initialize_context(ctx, api, visual, share_list,
+ driverFunctions)) {
return ctx;
}
else {
}
}
-GLcontext *
-_mesa_create_context(const GLvisual *visual,
- GLcontext *share_list,
- const struct dd_function_table *driverFunctions,
- void *driverContext)
-{
- return _mesa_create_context_for_api(API_OPENGL, visual,
- share_list,
- driverFunctions,
- driverContext);
-}
/**
* Free the data associated with the given context.
*
- * But doesn't free the GLcontext struct itself.
+ * But doesn't free the struct gl_context struct itself.
*
* \sa _mesa_initialize_context() and init_attrib_groups().
*/
void
-_mesa_free_context_data( GLcontext *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_fragprog(ctx, &ctx->FragmentProgram._Current, NULL);
_mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram, NULL);
+ _mesa_reference_array_object(ctx, &ctx->Array.ArrayObj, NULL);
+ _mesa_reference_array_object(ctx, &ctx->Array.DefaultArrayObj, NULL);
+
_mesa_free_attrib_data(ctx);
_mesa_free_buffer_objects(ctx);
_mesa_free_lighting_data( ctx );
_mesa_free_texture_data( ctx );
_mesa_free_matrix_data( ctx );
_mesa_free_viewport_data( ctx );
- _mesa_free_colortables_data( ctx );
_mesa_free_program_data(ctx);
_mesa_free_shader_state(ctx);
_mesa_free_queryobj_data(ctx);
-#if FEATURE_ARB_sync
_mesa_free_sync_data(ctx);
-#endif
_mesa_free_varray_data(ctx);
_mesa_free_transform_feedback(ctx);
- _mesa_delete_array_object(ctx, ctx->Array.DefaultArrayObj);
-
-#if FEATURE_ARB_pixel_buffer_object
_mesa_reference_buffer_object(ctx, &ctx->Pack.BufferObj, NULL);
_mesa_reference_buffer_object(ctx, &ctx->Unpack.BufferObj, NULL);
_mesa_reference_buffer_object(ctx, &ctx->DefaultPacking.BufferObj, NULL);
-#endif
-
-#if FEATURE_ARB_vertex_buffer_object
_mesa_reference_buffer_object(ctx, &ctx->Array.ArrayBufferObj, NULL);
- _mesa_reference_buffer_object(ctx, &ctx->Array.ElementArrayBufferObj, NULL);
-#endif
/* free dispatch tables */
+ free(ctx->BeginEnd);
free(ctx->Exec);
free(ctx->Save);
/* Shared context state (display lists, textures, etc) */
- _mesa_release_shared_state( ctx, ctx->Shared );
+ _mesa_reference_shared_state(ctx, &ctx->Shared, NULL);
/* needs to be after freeing shared state */
_mesa_free_display_list_data(ctx);
- if (ctx->Extensions.String)
- free((void *) ctx->Extensions.String);
+ _mesa_free_errors_data(ctx);
- if (ctx->VersionString)
- free(ctx->VersionString);
+ free((void *)ctx->Extensions.String);
+
+ free(ctx->VersionString);
/* unbind the context if it's currently bound */
if (ctx == _mesa_get_current_context()) {
/**
- * Destroy a GLcontext structure.
+ * Destroy a struct gl_context structure.
*
* \param ctx GL context.
*
- * Calls _mesa_free_context_data() and frees the GLcontext structure itself.
+ * Calls _mesa_free_context_data() and frees the gl_context object itself.
*/
void
-_mesa_destroy_context( GLcontext *ctx )
+_mesa_destroy_context( struct gl_context *ctx )
{
if (ctx) {
_mesa_free_context_data(ctx);
}
-#if _HAVE_FULL_GL
/**
* Copy attribute groups from one context to another.
*
* structures.
*/
void
-_mesa_copy_context( const GLcontext *src, GLcontext *dst, GLuint mask )
+_mesa_copy_context( const struct gl_context *src, struct gl_context *dst,
+ GLuint mask )
{
if (mask & GL_ACCUM_BUFFER_BIT) {
/* OK to memcpy */
/* XXX FIXME: Call callbacks?
*/
dst->NewState = _NEW_ALL;
+ dst->NewDriverState = ~0;
}
-#endif
/**
* \return GL_TRUE if compatible, GL_FALSE otherwise.
*/
static GLboolean
-check_compatible(const GLcontext *ctx, const GLframebuffer *buffer)
+check_compatible(const struct gl_context *ctx,
+ const struct gl_framebuffer *buffer)
{
- const GLvisual *ctxvis = &ctx->Visual;
- const GLvisual *bufvis = &buffer->Visual;
+ const struct gl_config *ctxvis = &ctx->Visual;
+ const struct gl_config *bufvis = &buffer->Visual;
- if (ctxvis == bufvis)
+ if (buffer == _mesa_get_incomplete_framebuffer())
return GL_TRUE;
#if 0
}
-/**
- * Do one-time initialization for the given framebuffer. Specifically,
- * ask the driver for the window's current size and update the framebuffer
- * object to match.
- * Really, the device driver should totally take care of this.
- */
-static void
-initialize_framebuffer_size(GLcontext *ctx, GLframebuffer *fb)
-{
- GLuint width, height;
- if (ctx->Driver.GetBufferSize) {
- ctx->Driver.GetBufferSize(fb, &width, &height);
- if (ctx->Driver.ResizeBuffers)
- ctx->Driver.ResizeBuffers(ctx, fb, width, height);
- fb->Initialized = GL_TRUE;
- }
-}
-
-
/**
* 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(GLcontext *ctx, GLuint width, GLuint height)
+_mesa_check_init_viewport(struct gl_context *ctx, GLuint width, GLuint height)
{
if (!ctx->ViewportInitialized && width > 0 && height > 0) {
/* Note: set flag here, before calling _mesa_set_viewport(), to prevent
* \param readBuffer the reading framebuffer
*/
GLboolean
-_mesa_make_current( GLcontext *newCtx, GLframebuffer *drawBuffer,
- GLframebuffer *readBuffer )
+_mesa_make_current( struct gl_context *newCtx,
+ struct gl_framebuffer *drawBuffer,
+ struct gl_framebuffer *readBuffer )
{
+ GET_CURRENT_CONTEXT(curCtx);
+
if (MESA_VERBOSE & VERBOSE_API)
_mesa_debug(newCtx, "_mesa_make_current()\n");
}
}
+ if (curCtx &&
+ (curCtx->WinSysDrawBuffer || curCtx->WinSysReadBuffer) &&
+ /* make sure this context is valid for flushing */
+ curCtx != newCtx)
+ _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);
_glapi_set_dispatch(newCtx->CurrentDispatch);
if (drawBuffer && readBuffer) {
- /* TODO: check if newCtx and buffer's visual match??? */
-
- ASSERT(drawBuffer->Name == 0);
- ASSERT(readBuffer->Name == 0);
+ ASSERT(_mesa_is_winsys_fbo(drawBuffer));
+ ASSERT(_mesa_is_winsys_fbo(readBuffer));
_mesa_reference_framebuffer(&newCtx->WinSysDrawBuffer, drawBuffer);
_mesa_reference_framebuffer(&newCtx->WinSysReadBuffer, readBuffer);
* Only set the context's Draw/ReadBuffer fields if they're NULL
* or not bound to a user-created FBO.
*/
- if (!newCtx->DrawBuffer || newCtx->DrawBuffer->Name == 0) {
- /* KW: merge conflict here, revisit.
- */
- /* fix up the fb fields - these will end up wrong otherwise
- * if the DRIdrawable changes, and everything relies on them.
- * This is a bit messy (same as needed in _mesa_BindFramebufferEXT)
- */
- unsigned int i;
- GLenum buffers[MAX_DRAW_BUFFERS];
-
+ if (!newCtx->DrawBuffer || _mesa_is_winsys_fbo(newCtx->DrawBuffer)) {
_mesa_reference_framebuffer(&newCtx->DrawBuffer, drawBuffer);
-
- for(i = 0; i < newCtx->Const.MaxDrawBuffers; i++) {
- buffers[i] = newCtx->Color.DrawBuffer[i];
- }
-
- _mesa_drawbuffers(newCtx, newCtx->Const.MaxDrawBuffers, buffers, NULL);
+ /* Update the FBO's list of drawbuffers/renderbuffers.
+ * For winsys FBOs this comes from the GL state (which may have
+ * changed since the last time this FBO was bound).
+ */
+ _mesa_update_draw_buffers(newCtx);
}
- if (!newCtx->ReadBuffer || newCtx->ReadBuffer->Name == 0) {
+ if (!newCtx->ReadBuffer || _mesa_is_winsys_fbo(newCtx->ReadBuffer)) {
_mesa_reference_framebuffer(&newCtx->ReadBuffer, readBuffer);
}
*/
newCtx->NewState |= _NEW_BUFFERS;
-#if 1
- /* We want to get rid of these lines: */
-
-#if _HAVE_FULL_GL
- if (!drawBuffer->Initialized) {
- initialize_framebuffer_size(newCtx, drawBuffer);
- }
- if (readBuffer != drawBuffer && !readBuffer->Initialized) {
- initialize_framebuffer_size(newCtx, readBuffer);
- }
-
- _mesa_resizebuffers(newCtx);
-#endif
-
-#else
- /* We want the drawBuffer and readBuffer to be initialized by
- * the driver.
- * This generally means the Width and Height match the actual
- * window size and the renderbuffers (both hardware and software
- * based) are allocated to match. The later can generally be
- * done with a call to _mesa_resize_framebuffer().
- *
- * It's theoretically possible for a buffer to have zero width
- * or height, but for now, assert check that the driver did what's
- * expected of it.
- */
- ASSERT(drawBuffer->Width > 0);
- ASSERT(drawBuffer->Height > 0);
-#endif
-
if (drawBuffer) {
_mesa_check_init_viewport(newCtx,
drawBuffer->Width, drawBuffer->Height);
}
if (newCtx->FirstTimeCurrent) {
- _mesa_compute_version(newCtx);
+ assert(newCtx->Version > 0);
+
+ newCtx->Extensions.String = _mesa_make_extension_string(newCtx);
check_context_limits(newCtx);
* be deleted if nobody else is sharing them.
*/
GLboolean
-_mesa_share_state(GLcontext *ctx, GLcontext *ctxToShare)
+_mesa_share_state(struct gl_context *ctx, struct gl_context *ctxToShare)
{
if (ctx && ctxToShare && ctx->Shared && ctxToShare->Shared) {
- struct gl_shared_state *oldSharedState = ctx->Shared;
+ struct gl_shared_state *oldShared = NULL;
+
+ /* save ref to old state to prevent it from being deleted immediately */
+ _mesa_reference_shared_state(ctx, &oldShared, ctx->Shared);
- ctx->Shared = ctxToShare->Shared;
-
- _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
- ctx->Shared->RefCount++;
- _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
+ /* update ctx's Shared pointer */
+ _mesa_reference_shared_state(ctx, &ctx->Shared, ctxToShare->Shared);
update_default_objects(ctx);
- _mesa_release_shared_state(ctx, oldSharedState);
+ /* release the old shared state */
+ _mesa_reference_shared_state(ctx, &oldShared, NULL);
return GL_TRUE;
}
* context. If you need speed, see the #GET_CURRENT_CONTEXT macro in
* context.h.
*/
-GLcontext *
+struct gl_context *
_mesa_get_current_context( void )
{
- return (GLcontext *) _glapi_get_context();
+ return (struct gl_context *) _glapi_get_context();
}
*
* \return pointer to dispatch_table.
*
- * Simply returns __GLcontextRec::CurrentDispatch.
+ * Simply returns __struct gl_contextRec::CurrentDispatch.
*/
struct _glapi_table *
-_mesa_get_dispatch(GLcontext *ctx)
+_mesa_get_dispatch(struct gl_context *ctx)
{
return ctx->CurrentDispatch;
}
* This is called via _mesa_error().
*/
void
-_mesa_record_error(GLcontext *ctx, GLenum error)
+_mesa_record_error(struct gl_context *ctx, GLenum error)
{
if (!ctx)
return;
if (ctx->ErrorValue == GL_NO_ERROR) {
ctx->ErrorValue = error;
}
-
- /* Call device driver's error handler, if any. This is used on the Mac. */
- if (ctx->Driver.Error) {
- ctx->Driver.Error(ctx);
- }
}
* Flush commands and wait for completion.
*/
void
-_mesa_finish(GLcontext *ctx)
+_mesa_finish(struct gl_context *ctx)
{
+ FLUSH_VERTICES( ctx, 0 );
FLUSH_CURRENT( ctx, 0 );
if (ctx->Driver.Finish) {
ctx->Driver.Finish(ctx);
* Flush commands.
*/
void
-_mesa_flush(GLcontext *ctx)
+_mesa_flush(struct gl_context *ctx)
{
+ FLUSH_VERTICES( ctx, 0 );
FLUSH_CURRENT( ctx, 0 );
if (ctx->Driver.Flush) {
ctx->Driver.Flush(ctx);
_mesa_Finish(void)
{
GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
_mesa_finish(ctx);
}
_mesa_Flush(void)
{
GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
_mesa_flush(ctx);
}
-/**
- * Set mvp_with_dp4 flag. If a driver has a preference for DP4 over
- * MUL/MAD, or vice versa, call this function to register that.
- * Otherwise we default to MUL/MAD.
+/*
+ * 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."
*/
-void
-_mesa_set_mvp_with_dp4( GLcontext *ctx,
- GLboolean flag )
+static GLboolean
+_mesa_check_blend_func_error(struct gl_context *ctx)
{
- ctx->mvp_with_dp4 = flag;
+ 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
* \return GL_TRUE if OK to render, GL_FALSE if not
*/
GLboolean
-_mesa_valid_to_render(GLcontext *ctx, const char *where)
+_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.CurrentProgram) {
- /* using shaders */
- if (!ctx->Shader.CurrentProgram->LinkStatus) {
+ 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");
+ "%s(shader not linked)", where);
return GL_FALSE;
}
#if 0 /* not normally enabled */
{
char errMsg[100];
- if (!_mesa_validate_shader_program(ctx, ctx->Shader.CurrentProgram,
+ if (!_mesa_validate_shader_program(ctx,
+ ctx->Shader.CurrentVertexProgram,
errMsg)) {
_mesa_warning(ctx, "Shader program %u is invalid: %s",
- ctx->Shader.CurrentProgram->Name, errMsg);
+ ctx->Shader.CurrentVertexProgram->Name, errMsg);
}
}
#endif
}
- else {
- if (ctx->VertexProgram.Enabled && !ctx->VertexProgram._Enabled) {
+
+ 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(vertex program not valid)", where);
+ "%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(fragment program not valid)", where);
+ "%s(integer format but no fragment shader)", where);
return GL_FALSE;
}
}
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;
- 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];
+ 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