* Mesa 3-D graphics library
* Version: 6.5
*
- * Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
+ * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
#include "glheader.h"
#include "imports.h"
#include "accum.h"
+#include "arrayobj.h"
#include "attrib.h"
#include "blend.h"
#include "buffers.h"
GLint accumAlphaBits,
GLint numSamples )
{
- GLvisual *vis = (GLvisual *) CALLOC( sizeof(GLvisual) );
+ GLvisual *vis = (GLvisual *) _mesa_calloc(sizeof(GLvisual));
if (vis) {
if (!_mesa_initialize_visual(vis, rgbFlag, dbFlag, stereoFlag,
redBits, greenBits, blueBits, alphaBits,
accumRedBits, accumGreenBits,
accumBlueBits, accumAlphaBits,
numSamples)) {
- FREE(vis);
+ _mesa_free(vis);
return NULL;
}
}
void
_mesa_destroy_visual( GLvisual *vis )
{
- FREE(vis);
+ _mesa_free(vis);
}
/*@}*/
* and sets the glapi callbacks if the \c MESA_DEBUG environment variable is
* defined.
*
- * \sa _mesa_init_lists(), _math_init().
+ * \sa _math_init().
*/
static void
one_time_init( GLcontext *ctx )
assert( sizeof(GLint) == 4 );
assert( sizeof(GLuint) == 4 );
- _mesa_init_lists();
-
#if _HAVE_FULL_GL
_math_init();
goto cleanup;
#endif
+#if FEATURE_ARB_vertex_buffer_object || FEATURE_ARB_pixel_buffer_object
ss->BufferObjects = _mesa_NewHashTable();
+#endif
+
+ ss->ArrayObjects = _mesa_NewHashTable();
+#if FEATURE_ARB_shader_objects
ss->GL2Objects = _mesa_NewHashTable ();
+#endif
ss->Default1D = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_1D);
if (!ss->Default1D)
if (ss->DefaultFragmentShader)
_mesa_delete_ati_fragment_shader(ctx, ss->DefaultFragmentShader);
#endif
-#if FEATURE_ARB_vertex_buffer_object
+#if FEATURE_ARB_vertex_buffer_object || FEATURE_ARB_pixel_buffer_object
if (ss->BufferObjects)
_mesa_DeleteHashTable(ss->BufferObjects);
#endif
+ if (ss->ArrayObjects)
+ _mesa_DeleteHashTable (ss->ArrayObjects);
+
+#if FEATURE_ARB_shader_objects
if (ss->GL2Objects)
_mesa_DeleteHashTable (ss->GL2Objects);
+#endif
#if FEATURE_EXT_framebuffer_object
if (ss->FrameBuffers)
return GL_FALSE;
}
+
+/**
+ * Callback for deleting a display list. Called by _mesa_HashDeleteAll().
+ */
+static void
+delete_displaylist_cb(GLuint id, void *data, void *userData)
+{
+ struct mesa_display_list *list = (struct mesa_display_list *) data;
+ GLcontext *ctx = (GLcontext *) userData;
+ _mesa_delete_list(ctx, list);
+}
+
+/**
+ * Callback for deleting a texture object. Called by _mesa_HashDeleteAll().
+ */
+static void
+delete_texture_cb(GLuint id, void *data, void *userData)
+{
+ struct gl_texture_object *texObj = (struct gl_texture_object *) data;
+ GLcontext *ctx = (GLcontext *) userData;
+ ctx->Driver.DeleteTexture(ctx, texObj);
+}
+
+/**
+ * Callback for deleting a program object. Called by _mesa_HashDeleteAll().
+ */
+static void
+delete_program_cb(GLuint id, void *data, void *userData)
+{
+ struct gl_program *prog = (struct gl_program *) data;
+ GLcontext *ctx = (GLcontext *) userData;
+ ctx->Driver.DeleteProgram(ctx, prog);
+}
+
+/**
+ * Callback for deleting an ATI fragment shader object.
+ * Called by _mesa_HashDeleteAll().
+ */
+static void
+delete_fragshader_cb(GLuint id, void *data, void *userData)
+{
+ struct ati_fragment_shader *shader = (struct ati_fragment_shader *) data;
+ GLcontext *ctx = (GLcontext *) userData;
+ _mesa_delete_ati_fragment_shader(ctx, shader);
+}
+
+/**
+ * Callback for deleting a buffer object. Called by _mesa_HashDeleteAll().
+ */
+static void
+delete_bufferobj_cb(GLuint id, void *data, void *userData)
+{
+ struct gl_buffer_object *bufObj = (struct gl_buffer_object *) data;
+ GLcontext *ctx = (GLcontext *) userData;
+ ctx->Driver.DeleteBuffer(ctx, bufObj);
+}
+
+/**
+ * Callback for deleting an array object. Called by _mesa_HashDeleteAll().
+ */
+static void
+delete_arrayobj_cb(GLuint id, void *data, void *userData)
+{
+ struct gl_array_object *arrayObj = (struct gl_array_object *) data;
+ GLcontext *ctx = (GLcontext *) userData;
+ _mesa_delete_array_object(ctx, arrayObj);
+}
+
+
/**
- * Deallocate a shared state context and all children structures.
+ * Deallocate a shared state object and all children structures.
*
* \param ctx GL context.
* \param ss shared state pointer.
static void
free_shared_state( GLcontext *ctx, struct gl_shared_state *ss )
{
- /* Free display lists */
- while (1) {
- GLuint list = _mesa_HashFirstEntry(ss->DisplayList);
- if (list) {
- _mesa_destroy_list(ctx, list);
- }
- else {
- break;
- }
- }
+ /*
+ * Free display lists
+ */
+ _mesa_HashDeleteAll(ss->DisplayList, delete_displaylist_cb, ctx);
_mesa_DeleteHashTable(ss->DisplayList);
- /* Free texture objects */
+ /*
+ * Free texture objects
+ */
ASSERT(ctx->Driver.DeleteTexture);
/* the default textures */
- (*ctx->Driver.DeleteTexture)(ctx, ss->Default1D);
- (*ctx->Driver.DeleteTexture)(ctx, ss->Default2D);
- (*ctx->Driver.DeleteTexture)(ctx, ss->Default3D);
- (*ctx->Driver.DeleteTexture)(ctx, ss->DefaultCubeMap);
- (*ctx->Driver.DeleteTexture)(ctx, ss->DefaultRect);
+ ctx->Driver.DeleteTexture(ctx, ss->Default1D);
+ ctx->Driver.DeleteTexture(ctx, ss->Default2D);
+ ctx->Driver.DeleteTexture(ctx, ss->Default3D);
+ ctx->Driver.DeleteTexture(ctx, ss->DefaultCubeMap);
+ ctx->Driver.DeleteTexture(ctx, ss->DefaultRect);
/* all other textures */
- while (1) {
- GLuint texName = _mesa_HashFirstEntry(ss->TexObjects);
- if (texName) {
- struct gl_texture_object *texObj = (struct gl_texture_object *)
- _mesa_HashLookup(ss->TexObjects, texName);
- ASSERT(texObj);
- (*ctx->Driver.DeleteTexture)(ctx, texObj);
- _mesa_HashRemove(ss->TexObjects, texName);
- }
- else {
- break;
- }
- }
+ _mesa_HashDeleteAll(ss->TexObjects, delete_texture_cb, ctx);
_mesa_DeleteHashTable(ss->TexObjects);
-#if FEATURE_NV_vertex_program
- /* Free vertex programs */
- while (1) {
- GLuint prog = _mesa_HashFirstEntry(ss->Programs);
- if (prog) {
- struct program *p = (struct program *) _mesa_HashLookup(ss->Programs,
- prog);
- ASSERT(p);
- ctx->Driver.DeleteProgram(ctx, p);
- _mesa_HashRemove(ss->Programs, prog);
- }
- else {
- break;
- }
- }
+#if defined(FEATURE_NV_vertex_program) || defined(FEATURE_NV_fragment_program)
+ _mesa_HashDeleteAll(ss->Programs, delete_program_cb, ctx);
_mesa_DeleteHashTable(ss->Programs);
#endif
#if FEATURE_ARB_vertex_program
#if FEATURE_ARB_fragment_program
_mesa_delete_program(ctx, ss->DefaultFragmentProgram);
#endif
+
#if FEATURE_ATI_fragment_shader
- _mesa_free(ss->DefaultFragmentShader);
+ _mesa_HashDeleteAll(ss->ATIShaders, delete_fragshader_cb, ctx);
+ _mesa_DeleteHashTable(ss->ATIShaders);
+ _mesa_delete_ati_fragment_shader(ctx, ss->DefaultFragmentShader);
#endif
-#if FEATURE_ARB_vertex_buffer_object
+#if FEATURE_ARB_vertex_buffer_object || FEATURE_ARB_pixel_buffer_object
+ _mesa_HashDeleteAll(ss->BufferObjects, delete_bufferobj_cb, ctx);
_mesa_DeleteHashTable(ss->BufferObjects);
#endif
- _mesa_DeleteHashTable (ss->GL2Objects);
+ _mesa_HashDeleteAll(ss->ArrayObjects, delete_arrayobj_cb, ctx);
+ _mesa_DeleteHashTable(ss->ArrayObjects);
+
+#if FEATURE_ARB_shader_objects
+ _mesa_DeleteHashTable(ss->GL2Objects);
+#endif
#if FEATURE_EXT_framebuffer_object
_mesa_DeleteHashTable(ss->FrameBuffers);
_glthread_DESTROY_MUTEX(ss->Mutex);
- FREE(ss);
+ _mesa_free(ss);
}
{
GLuint i;
- /* Current group */
+ /* Init all to (0,0,0,1) */
for (i = 0; i < VERT_ATTRIB_MAX; i++) {
ASSIGN_4V( ctx->Current.Attrib[i], 0.0, 0.0, 0.0, 1.0 );
}
- /* special cases: */
+
+ /* redo special cases: */
ASSIGN_4V( ctx->Current.Attrib[VERT_ATTRIB_WEIGHT], 1.0, 0.0, 0.0, 1.0 );
ASSIGN_4V( ctx->Current.Attrib[VERT_ATTRIB_NORMAL], 0.0, 0.0, 1.0, 1.0 );
ASSIGN_4V( ctx->Current.Attrib[VERT_ATTRIB_COLOR0], 1.0, 1.0, 1.0, 1.0 );
ASSIGN_4V( ctx->Current.Attrib[VERT_ATTRIB_COLOR1], 0.0, 0.0, 0.0, 1.0 );
ASSIGN_4V( ctx->Current.Attrib[VERT_ATTRIB_FOG], 0.0, 0.0, 0.0, 0.0 );
-
- ctx->Current.Index = 1;
+ ctx->Current.Attrib[VERT_ATTRIB_COLOR_INDEX][0] = 1.0;
ctx->Current.EdgeFlag = GL_TRUE;
}
assert(MAX_TEXTURE_LEVELS >= MAX_3D_TEXTURE_LEVELS);
assert(MAX_TEXTURE_LEVELS >= MAX_CUBE_TEXTURE_LEVELS);
+ assert(MAX_TEXTURE_UNITS >= MAX_TEXTURE_COORD_UNITS);
+ assert(MAX_TEXTURE_UNITS >= MAX_TEXTURE_IMAGE_UNITS);
+
/* Constants, may be overriden (usually only reduced) by device drivers */
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.MaxTextureUnits = MAX_TEXTURE_UNITS;
ctx->Const.MaxTextureCoordUnits = MAX_TEXTURE_COORD_UNITS;
ctx->Const.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
+ ctx->Const.MaxTextureUnits = MIN2(ctx->Const.MaxTextureCoordUnits,
+ ctx->Const.MaxTextureImageUnits);
ctx->Const.MaxTextureMaxAnisotropy = MAX_TEXTURE_MAX_ANISOTROPY;
ctx->Const.MaxTextureLodBias = MAX_TEXTURE_LOD_BIAS;
ctx->Const.MaxArrayLockSize = MAX_ARRAY_LOCK_SIZE;
#endif
/* sanity checks */
- ASSERT(ctx->Const.MaxTextureUnits == MAX2(ctx->Const.MaxTextureImageUnits, ctx->Const.MaxTextureCoordUnits));
+ ASSERT(ctx->Const.MaxTextureUnits == MIN2(ctx->Const.MaxTextureImageUnits,
+ ctx->Const.MaxTextureCoordUnits));
ASSERT(ctx->Const.FragmentProgram.MaxLocalParams <= MAX_PROGRAM_LOCAL_PARAMS);
ASSERT(ctx->Const.VertexProgram.MaxLocalParams <= MAX_PROGRAM_LOCAL_PARAMS);
}
+/**
+ * Do some sanity checks on the limits/constants for the given context.
+ * Only called the first time a context is bound.
+ */
+static void
+check_context_limits(GLcontext *ctx)
+{
+ /* Many context limits/constants are limited by the size of
+ * internal arrays.
+ */
+ assert(ctx->Const.MaxTextureImageUnits <= MAX_TEXTURE_IMAGE_UNITS);
+ assert(ctx->Const.MaxTextureCoordUnits <= MAX_TEXTURE_COORD_UNITS);
+ assert(ctx->Const.MaxTextureUnits <= MAX_TEXTURE_IMAGE_UNITS);
+ assert(ctx->Const.MaxTextureUnits <= MAX_TEXTURE_COORD_UNITS);
+
+ assert(ctx->Const.MaxViewportWidth <= MAX_WIDTH);
+ assert(ctx->Const.MaxViewportHeight <= MAX_WIDTH);
+
+ /* 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);
+
+ assert(ctx->Const.MaxDrawBuffers <= MAX_DRAW_BUFFERS);
+
+ /* XXX probably add more tests */
+}
+
+
/**
* Initialize the attribute groups in a GL context.
*
#if FEATURE_ARB_vertex_buffer_object
_mesa_delete_buffer_object(ctx, ctx->Array.NullBufferObj);
#endif
+ _mesa_delete_array_object(ctx, ctx->Array.DefaultArrayObj);
/* free dispatch tables */
_mesa_free(ctx->Exec);
}
if (ctx->Extensions.String)
- FREE((void *) ctx->Extensions.String);
+ _mesa_free((void *) ctx->Extensions.String);
}
{
if (ctx) {
_mesa_free_context_data(ctx);
- FREE( (void *) ctx );
+ _mesa_free( (void *) ctx );
}
}
if (mask & GL_LIGHTING_BIT) {
GLuint i;
/* begin with memcpy */
- MEMCPY( &dst->Light, &src->Light, sizeof(struct gl_light) );
+ dst->Light = src->Light;
/* fixup linked lists to prevent pointer insanity */
make_empty_list( &(dst->Light.EnabledList) );
for (i = 0; i < MAX_LIGHTS; i++) {
/**
* Check if the given context can render into the given framebuffer
* by checking visual attributes.
+ *
+ * XXX this may go away someday because we're moving toward more freedom
+ * in binding contexts to drawables with different visual attributes.
+ * The GL_EXT_f_b_o extension is prompting some of that.
+ *
* \return GL_TRUE if compatible, GL_FALSE otherwise.
*/
static GLboolean
if (ctxvis->rgbMode != bufvis->rgbMode)
return GL_FALSE;
+#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)
initialize_framebuffer_size(GLcontext *ctx, GLframebuffer *fb)
{
GLuint width, height;
- ASSERT(ctx->Driver.GetBufferSize);
- ctx->Driver.GetBufferSize(fb, &width, &height);
- if (ctx->Driver.ResizeBuffers)
- ctx->Driver.ResizeBuffers(ctx, fb, width, height);
- fb->Initialized = GL_TRUE;
+ 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 that the context's and framebuffer's visuals are compatible.
*/
- if (newCtx && drawBuffer && newCtx->DrawBuffer != drawBuffer) {
- if (!check_compatible(newCtx, drawBuffer))
+ if (newCtx && drawBuffer && newCtx->WinSysDrawBuffer != drawBuffer) {
+ if (!check_compatible(newCtx, drawBuffer)) {
+ _mesa_warning(newCtx,
+ "MakeCurrent: incompatible visuals for context and drawbuffer");
return;
+ }
}
- if (newCtx && readBuffer && newCtx->ReadBuffer != readBuffer) {
- if (!check_compatible(newCtx, readBuffer))
+ if (newCtx && readBuffer && newCtx->WinSysReadBuffer != readBuffer) {
+ if (!check_compatible(newCtx, readBuffer)) {
+ _mesa_warning(newCtx,
+ "MakeCurrent: incompatible visuals for context and readbuffer");
return;
+ }
}
-#if !defined(IN_DRI_DRIVER)
- /* We call this function periodically (just here for now) in
- * order to detect when multithreading has begun. In a DRI driver, this
- * step is done by the driver loader (e.g., libGL).
- */
- _glapi_check_multithread();
-#endif /* !defined(IN_DRI_DRIVER) */
-
+ /* We used to call _glapi_check_multithread() here. Now do it in drivers */
_glapi_set_context((void *) newCtx);
ASSERT(_mesa_get_current_context() == newCtx);
ASSERT(readBuffer->Name == 0);
newCtx->WinSysDrawBuffer = drawBuffer;
newCtx->WinSysReadBuffer = readBuffer;
- /* don't replace user-buffer bindings with window system buffer */
+
+ /*
+ * Only set the context's Draw/ReadBuffer fields if they're NULL
+ * or not bound to a user-created FBO.
+ */
if (!newCtx->DrawBuffer || newCtx->DrawBuffer->Name == 0) {
newCtx->DrawBuffer = drawBuffer;
+ }
+ if (!newCtx->ReadBuffer || newCtx->ReadBuffer->Name == 0) {
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 (newCtx->FirstTimeCurrent) {
/* set initial viewport and scissor size now */
_mesa_set_viewport(newCtx, 0, 0,
drawBuffer->Width, drawBuffer->Height);
- newCtx->Scissor.Width = drawBuffer->Width;
- newCtx->Scissor.Height = drawBuffer->Height;
+ _mesa_set_scissor(newCtx, 0, 0,
+ drawBuffer->Width, drawBuffer->Height );
+ check_context_limits(newCtx);
}
}