#include "api_arrayelt.h"
#include "api_exec.h"
#include "api_loopback.h"
-#include "api_validate.h"
+#include "draw_validate.h"
#include "atifragshader.h"
#include "config.h"
#include "bufferobj.h"
#include "vbo/vbo.h"
+#define USE_BITMAP_ATLAS 1
+
+
/**
* Other parts of Mesa (such as the VBO module) can plug into the display
* Checks if dd_function_table::SaveNeedFlush is marked to flush
* stored (save) vertices, and calls vbo_save_SaveFlushVertices if so.
*/
-#define SAVE_FLUSH_VERTICES(ctx) \
-do { \
- if (ctx->Driver.SaveNeedFlush) \
- vbo_save_SaveFlushVertices(ctx); \
-} while (0)
+#define SAVE_FLUSH_VERTICES(ctx) \
+ do { \
+ if (ctx->Driver.SaveNeedFlush) \
+ vbo_save_SaveFlushVertices(ctx); \
+ } while (0)
/**
* Macro to assert that the API call was made outside the
* glBegin()/glEnd() pair, with return value.
- *
+ *
* \param ctx GL context.
* \param retval value to return value in case the assertion fails.
*/
-#define ASSERT_OUTSIDE_SAVE_BEGIN_END_WITH_RETVAL(ctx, retval) \
-do { \
- if (ctx->Driver.CurrentSavePrimitive <= PRIM_MAX) { \
- _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glBegin/End" ); \
- return retval; \
- } \
-} while (0)
+#define ASSERT_OUTSIDE_SAVE_BEGIN_END_WITH_RETVAL(ctx, retval) \
+ do { \
+ if (ctx->Driver.CurrentSavePrimitive <= PRIM_MAX) { \
+ _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glBegin/End" ); \
+ return retval; \
+ } \
+ } while (0)
/**
* Macro to assert that the API call was made outside the
* glBegin()/glEnd() pair.
- *
+ *
* \param ctx GL context.
*/
-#define ASSERT_OUTSIDE_SAVE_BEGIN_END(ctx) \
-do { \
- if (ctx->Driver.CurrentSavePrimitive <= PRIM_MAX) { \
- _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glBegin/End" ); \
- return; \
- } \
-} while (0)
+#define ASSERT_OUTSIDE_SAVE_BEGIN_END(ctx) \
+ do { \
+ if (ctx->Driver.CurrentSavePrimitive <= PRIM_MAX) { \
+ _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glBegin/End" ); \
+ return; \
+ } \
+ } while (0)
/**
* Macro to assert that the API call was made outside the
* glBegin()/glEnd() pair and flush the vertices.
- *
+ *
* \param ctx GL context.
*/
-#define ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx) \
-do { \
- ASSERT_OUTSIDE_SAVE_BEGIN_END(ctx); \
- SAVE_FLUSH_VERTICES(ctx); \
-} while (0)
+#define ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx) \
+ do { \
+ ASSERT_OUTSIDE_SAVE_BEGIN_END(ctx); \
+ SAVE_FLUSH_VERTICES(ctx); \
+ } while (0)
/**
* Macro to assert that the API call was made outside the
* glBegin()/glEnd() pair and flush the vertices, with return value.
- *
+ *
* \param ctx GL context.
* \param retval value to return value in case the assertion fails.
*/
-#define ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH_WITH_RETVAL(ctx, retval)\
-do { \
- ASSERT_OUTSIDE_SAVE_BEGIN_END_WITH_RETVAL(ctx, retval); \
- SAVE_FLUSH_VERTICES(ctx); \
-} while (0)
-
+#define ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH_WITH_RETVAL(ctx, retval) \
+ do { \
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_WITH_RETVAL(ctx, retval); \
+ SAVE_FLUSH_VERTICES(ctx); \
+ } while (0)
/**
OPCODE_SAMPLE_COVERAGE,
/* GL_ARB_window_pos */
OPCODE_WINDOW_POS_ARB,
- /* GL_NV_fragment_program */
- OPCODE_BIND_PROGRAM_NV,
+ /* GL_ARB_vertex_program */
+ OPCODE_BIND_PROGRAM_ARB,
OPCODE_PROGRAM_LOCAL_PARAMETER_ARB,
/* GL_EXT_stencil_two_side */
OPCODE_ACTIVE_STENCIL_FACE_EXT,
OPCODE_STENCIL_FUNC_SEPARATE,
OPCODE_STENCIL_OP_SEPARATE,
OPCODE_STENCIL_MASK_SEPARATE,
-
+ /* GL_NV_primitive_restart */
+ OPCODE_PRIMITIVE_RESTART_NV,
/* GL_ARB_shader_objects */
OPCODE_USE_PROGRAM,
OPCODE_UNIFORM_1F,
/* EXT_polygon_offset_clamp */
OPCODE_POLYGON_OFFSET_CLAMP,
+ /* EXT_window_rectangles */
+ OPCODE_WINDOW_RECTANGLES,
+
+ /* NV_conservative_raster */
+ OPCODE_SUBPIXEL_PRECISION_BIAS,
+
+ /* NV_conservative_raster_dilate */
+ OPCODE_CONSERVATIVE_RASTER_PARAMETER_F,
+
+ /* NV_conservative_raster_pre_snap_triangles */
+ OPCODE_CONSERVATIVE_RASTER_PARAMETER_I,
+
/* The following three are meta instructions */
OPCODE_ERROR, /* raise compiled-in error */
OPCODE_CONTINUE,
void mesa_print_display_list(GLuint list);
+/**
+ * Does the given display list only contain a single glBitmap call?
+ */
+static bool
+is_bitmap_list(const struct gl_display_list *dlist)
+{
+ const Node *n = dlist->Head;
+ if (n[0].opcode == OPCODE_BITMAP) {
+ n += InstSize[OPCODE_BITMAP];
+ if (n[0].opcode == OPCODE_END_OF_LIST)
+ return true;
+ }
+ return false;
+}
+
+
+/**
+ * Is the given display list an empty list?
+ */
+static bool
+is_empty_list(const struct gl_display_list *dlist)
+{
+ const Node *n = dlist->Head;
+ return n[0].opcode == OPCODE_END_OF_LIST;
+}
+
+
+/**
+ * Delete/free a gl_bitmap_atlas. Called during context tear-down.
+ */
+void
+_mesa_delete_bitmap_atlas(struct gl_context *ctx, struct gl_bitmap_atlas *atlas)
+{
+ if (atlas->texObj) {
+ ctx->Driver.DeleteTexture(ctx, atlas->texObj);
+ }
+ free(atlas->glyphs);
+}
+
+
+/**
+ * Lookup a gl_bitmap_atlas by listBase ID.
+ */
+static struct gl_bitmap_atlas *
+lookup_bitmap_atlas(struct gl_context *ctx, GLuint listBase)
+{
+ struct gl_bitmap_atlas *atlas;
+
+ assert(listBase > 0);
+ atlas = _mesa_HashLookup(ctx->Shared->BitmapAtlas, listBase);
+ return atlas;
+}
+
+
+/**
+ * Create new bitmap atlas and insert into hash table.
+ */
+static struct gl_bitmap_atlas *
+alloc_bitmap_atlas(struct gl_context *ctx, GLuint listBase)
+{
+ struct gl_bitmap_atlas *atlas;
+
+ assert(listBase > 0);
+ assert(_mesa_HashLookup(ctx->Shared->BitmapAtlas, listBase) == NULL);
+
+ atlas = calloc(1, sizeof(*atlas));
+ if (atlas) {
+ _mesa_HashInsert(ctx->Shared->BitmapAtlas, listBase, atlas);
+ }
+
+ return atlas;
+}
+
+
+/**
+ * Try to build a bitmap atlas. This involves examining a sequence of
+ * display lists which contain glBitmap commands and putting the bitmap
+ * images into a texture map (the atlas).
+ * If we succeed, gl_bitmap_atlas::complete will be set to true.
+ * If we fail, gl_bitmap_atlas::incomplete will be set to true.
+ */
+static void
+build_bitmap_atlas(struct gl_context *ctx, struct gl_bitmap_atlas *atlas,
+ GLuint listBase)
+{
+ unsigned i, row_height = 0, xpos = 0, ypos = 0;
+ GLubyte *map;
+ GLint map_stride;
+
+ assert(atlas);
+ assert(!atlas->complete);
+ assert(atlas->numBitmaps > 0);
+
+ /* We use a rectangle texture (non-normalized coords) for the atlas */
+ assert(ctx->Extensions.NV_texture_rectangle);
+ assert(ctx->Const.MaxTextureRectSize >= 1024);
+
+ atlas->texWidth = 1024;
+ atlas->texHeight = 0; /* determined below */
+
+ atlas->glyphs = malloc(atlas->numBitmaps * sizeof(atlas->glyphs[0]));
+ if (!atlas->glyphs) {
+ /* give up */
+ atlas->incomplete = true;
+ return;
+ }
+
+ /* Loop over the display lists. They should all contain a single glBitmap
+ * call. If not, bail out. Also, compute the position and sizes of each
+ * bitmap in the atlas to determine the texture atlas size.
+ */
+ for (i = 0; i < atlas->numBitmaps; i++) {
+ const struct gl_display_list *list = _mesa_lookup_list(ctx, listBase + i);
+ const Node *n;
+ struct gl_bitmap_glyph *g = &atlas->glyphs[i];
+ unsigned bitmap_width, bitmap_height;
+ float bitmap_xmove, bitmap_ymove, bitmap_xorig, bitmap_yorig;
+
+ if (!list || is_empty_list(list)) {
+ /* stop here */
+ atlas->numBitmaps = i;
+ break;
+ }
+
+ if (!is_bitmap_list(list)) {
+ /* This list does not contain exactly one glBitmap command. Give up. */
+ atlas->incomplete = true;
+ return;
+ }
+
+ /* get bitmap info from the display list command */
+ n = list->Head;
+ assert(n[0].opcode == OPCODE_BITMAP);
+ bitmap_width = n[1].i;
+ bitmap_height = n[2].i;
+ bitmap_xorig = n[3].f;
+ bitmap_yorig = n[4].f;
+ bitmap_xmove = n[5].f;
+ bitmap_ymove = n[6].f;
+
+ if (xpos + bitmap_width > atlas->texWidth) {
+ /* advance to the next row of the texture */
+ xpos = 0;
+ ypos += row_height;
+ row_height = 0;
+ }
+
+ /* save the bitmap's position in the atlas */
+ g->x = xpos;
+ g->y = ypos;
+ g->w = bitmap_width;
+ g->h = bitmap_height;
+ g->xorig = bitmap_xorig;
+ g->yorig = bitmap_yorig;
+ g->xmove = bitmap_xmove;
+ g->ymove = bitmap_ymove;
+
+ xpos += bitmap_width;
+
+ /* keep track of tallest bitmap in the row */
+ row_height = MAX2(row_height, bitmap_height);
+ }
+
+ /* Now we know the texture height */
+ atlas->texHeight = ypos + row_height;
+
+ if (atlas->texHeight == 0) {
+ /* no glyphs found, give up */
+ goto fail;
+ }
+ else if (atlas->texHeight > ctx->Const.MaxTextureRectSize) {
+ /* too large, give up */
+ goto fail;
+ }
+
+ /* Create atlas texture (texture ID is irrelevant) */
+ atlas->texObj = ctx->Driver.NewTextureObject(ctx, 999, GL_TEXTURE_RECTANGLE);
+ if (!atlas->texObj) {
+ goto out_of_memory;
+ }
+
+ atlas->texObj->Sampler.MinFilter = GL_NEAREST;
+ atlas->texObj->Sampler.MagFilter = GL_NEAREST;
+ atlas->texObj->MaxLevel = 0;
+ atlas->texObj->Immutable = GL_TRUE;
+
+ atlas->texImage = _mesa_get_tex_image(ctx, atlas->texObj,
+ GL_TEXTURE_RECTANGLE, 0);
+ if (!atlas->texImage) {
+ goto out_of_memory;
+ }
+
+ _mesa_init_teximage_fields(ctx, atlas->texImage,
+ atlas->texWidth, atlas->texHeight, 1, 0,
+ GL_ALPHA, MESA_FORMAT_A_UNORM8);
+
+ /* alloc image storage */
+ if (!ctx->Driver.AllocTextureImageBuffer(ctx, atlas->texImage)) {
+ goto out_of_memory;
+ }
+
+ /* map teximage, load with bitmap glyphs */
+ ctx->Driver.MapTextureImage(ctx, atlas->texImage, 0,
+ 0, 0, atlas->texWidth, atlas->texHeight,
+ GL_MAP_WRITE_BIT, &map, &map_stride);
+ if (!map) {
+ goto out_of_memory;
+ }
+
+ /* Background/clear pixels are 0xff, foreground/set pixels are 0x0 */
+ memset(map, 0xff, map_stride * atlas->texHeight);
+
+ for (i = 0; i < atlas->numBitmaps; i++) {
+ const struct gl_display_list *list = _mesa_lookup_list(ctx, listBase + i);
+ const Node *n = list->Head;
+
+ assert(n[0].opcode == OPCODE_BITMAP ||
+ n[0].opcode == OPCODE_END_OF_LIST);
+
+ if (n[0].opcode == OPCODE_BITMAP) {
+ unsigned bitmap_width = n[1].i;
+ unsigned bitmap_height = n[2].i;
+ unsigned xpos = atlas->glyphs[i].x;
+ unsigned ypos = atlas->glyphs[i].y;
+ const void *bitmap_image = get_pointer(&n[7]);
+
+ assert(atlas->glyphs[i].w == bitmap_width);
+ assert(atlas->glyphs[i].h == bitmap_height);
+
+ /* put the bitmap image into the texture image */
+ _mesa_expand_bitmap(bitmap_width, bitmap_height,
+ &ctx->DefaultPacking, bitmap_image,
+ map + map_stride * ypos + xpos, /* dest addr */
+ map_stride, 0x0);
+ }
+ }
+
+ ctx->Driver.UnmapTextureImage(ctx, atlas->texImage, 0);
+
+ atlas->complete = true;
+
+ return;
+
+out_of_memory:
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "Display list bitmap atlas");
+fail:
+ if (atlas->texObj) {
+ ctx->Driver.DeleteTexture(ctx, atlas->texObj);
+ }
+ free(atlas->glyphs);
+ atlas->glyphs = NULL;
+ atlas->incomplete = true;
+}
+
+
/**
* Allocate a gl_display_list object with an initial block of storage.
- * \param count how many display list nodes/tokes to allocate
+ * \param count how many display list nodes/tokens to allocate
*/
static struct gl_display_list *
make_list(GLuint name, GLuint count)
/* for some commands, we need to free malloc'd memory */
case OPCODE_MAP1:
free(get_pointer(&n[6]));
- n += InstSize[n[0].opcode];
break;
case OPCODE_MAP2:
free(get_pointer(&n[10]));
- n += InstSize[n[0].opcode];
break;
case OPCODE_CALL_LISTS:
free(get_pointer(&n[3]));
- n += InstSize[n[0].opcode];
break;
case OPCODE_DRAW_PIXELS:
free(get_pointer(&n[5]));
- n += InstSize[n[0].opcode];
break;
case OPCODE_BITMAP:
free(get_pointer(&n[7]));
- n += InstSize[n[0].opcode];
break;
case OPCODE_POLYGON_STIPPLE:
free(get_pointer(&n[1]));
- n += InstSize[n[0].opcode];
break;
case OPCODE_TEX_IMAGE1D:
free(get_pointer(&n[8]));
- n += InstSize[n[0].opcode];
break;
case OPCODE_TEX_IMAGE2D:
free(get_pointer(&n[9]));
- n += InstSize[n[0].opcode];
break;
case OPCODE_TEX_IMAGE3D:
free(get_pointer(&n[10]));
- n += InstSize[n[0].opcode];
break;
case OPCODE_TEX_SUB_IMAGE1D:
free(get_pointer(&n[7]));
- n += InstSize[n[0].opcode];
break;
case OPCODE_TEX_SUB_IMAGE2D:
free(get_pointer(&n[9]));
- n += InstSize[n[0].opcode];
break;
case OPCODE_TEX_SUB_IMAGE3D:
free(get_pointer(&n[11]));
- n += InstSize[n[0].opcode];
break;
case OPCODE_COMPRESSED_TEX_IMAGE_1D:
free(get_pointer(&n[7]));
- n += InstSize[n[0].opcode];
break;
case OPCODE_COMPRESSED_TEX_IMAGE_2D:
free(get_pointer(&n[8]));
- n += InstSize[n[0].opcode];
break;
case OPCODE_COMPRESSED_TEX_IMAGE_3D:
free(get_pointer(&n[9]));
- n += InstSize[n[0].opcode];
break;
case OPCODE_COMPRESSED_TEX_SUB_IMAGE_1D:
free(get_pointer(&n[7]));
- n += InstSize[n[0].opcode];
break;
case OPCODE_COMPRESSED_TEX_SUB_IMAGE_2D:
free(get_pointer(&n[9]));
- n += InstSize[n[0].opcode];
break;
case OPCODE_COMPRESSED_TEX_SUB_IMAGE_3D:
free(get_pointer(&n[11]));
- n += InstSize[n[0].opcode];
break;
case OPCODE_PROGRAM_STRING_ARB:
free(get_pointer(&n[4])); /* program string */
- n += InstSize[n[0].opcode];
break;
case OPCODE_UNIFORM_1FV:
case OPCODE_UNIFORM_2FV:
case OPCODE_UNIFORM_3UIV:
case OPCODE_UNIFORM_4UIV:
free(get_pointer(&n[3]));
- n += InstSize[n[0].opcode];
break;
case OPCODE_UNIFORM_MATRIX22:
case OPCODE_UNIFORM_MATRIX33:
case OPCODE_UNIFORM_MATRIX34:
case OPCODE_UNIFORM_MATRIX43:
free(get_pointer(&n[4]));
- n += InstSize[n[0].opcode];
break;
case OPCODE_PROGRAM_UNIFORM_1FV:
case OPCODE_PROGRAM_UNIFORM_2FV:
case OPCODE_PROGRAM_UNIFORM_3UIV:
case OPCODE_PROGRAM_UNIFORM_4UIV:
free(get_pointer(&n[4]));
- n += InstSize[n[0].opcode];
break;
case OPCODE_PROGRAM_UNIFORM_MATRIX22F:
case OPCODE_PROGRAM_UNIFORM_MATRIX33F:
case OPCODE_PROGRAM_UNIFORM_MATRIX34F:
case OPCODE_PROGRAM_UNIFORM_MATRIX43F:
free(get_pointer(&n[5]));
- n += InstSize[n[0].opcode];
break;
case OPCODE_PIXEL_MAP:
free(get_pointer(&n[3]));
- n += InstSize[n[0].opcode];
break;
-
+ case OPCODE_WINDOW_RECTANGLES:
+ free(get_pointer(&n[3]));
+ break;
case OPCODE_CONTINUE:
n = (Node *) get_pointer(&n[1]);
free(block);
done = GL_TRUE;
break;
default:
- /* Most frequent case */
- n += InstSize[n[0].opcode];
- break;
+ /* just increment 'n' pointer, below */
+ ;
+ }
+
+ if (opcode != OPCODE_CONTINUE) {
+ assert(InstSize[opcode] > 0);
+ n += InstSize[opcode];
}
}
}
}
+/**
+ * Called by _mesa_HashWalk() to check if a display list which is being
+ * deleted belongs to a bitmap texture atlas.
+ */
+static void
+check_atlas_for_deleted_list(GLuint atlas_id, void *data, void *userData)
+{
+ struct gl_bitmap_atlas *atlas = (struct gl_bitmap_atlas *) data;
+ GLuint list_id = *((GLuint *) userData); /* the list being deleted */
+
+ /* See if the list_id falls in the range contained in this texture atlas */
+ if (atlas->complete &&
+ list_id >= atlas_id &&
+ list_id < atlas_id + atlas->numBitmaps) {
+ /* Mark the atlas as incomplete so it doesn't get used. But don't
+ * delete it yet since we don't want to try to recreate it in the next
+ * glCallLists.
+ */
+ atlas->complete = false;
+ atlas->incomplete = true;
+ }
+}
+
+
/**
* Destroy a display list and remove from hash table.
* \param list - display list number
if (!dlist)
return;
+ if (is_bitmap_list(dlist)) {
+ /* If we're destroying a simple glBitmap display list, there's a
+ * chance that we're destroying a bitmap image that's in a texture
+ * atlas. Examine all atlases to see if that's the case. There's
+ * usually few (if any) atlases so this isn't expensive.
+ */
+ _mesa_HashWalk(ctx->Shared->BitmapAtlas,
+ check_atlas_for_deleted_list, &list);
+ }
+
_mesa_delete_list(ctx, dlist);
_mesa_HashRemove(ctx->Shared->DisplayList, list);
}
map = (GLubyte *)
ctx->Driver.MapBufferRange(ctx, 0, unpack->BufferObj->Size,
- GL_MAP_READ_BIT, unpack->BufferObj,
+ GL_MAP_READ_BIT, unpack->BufferObj,
MAP_INTERNAL);
if (!map) {
/* unable to map src buffer! */
GLuint nopNode;
Node *n;
+ assert(bytes <= BLOCK_SIZE * sizeof(Node));
+
if (opcode < OPCODE_EXT_0) {
if (InstSize[opcode] == 0) {
/* save instruction size now */
/* GL_ARB_draw_instanced. */
static void GLAPIENTRY
-save_DrawArraysInstancedARB(GLenum mode,
- GLint first,
- GLsizei count,
- GLsizei primcount)
+save_DrawArraysInstancedARB(UNUSED GLenum mode,
+ UNUSED GLint first,
+ UNUSED GLsizei count,
+ UNUSED GLsizei primcount)
{
GET_CURRENT_CONTEXT(ctx);
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glDrawArraysInstanced() during display list compile");
+ "glDrawArraysInstanced() during display list compile");
}
static void GLAPIENTRY
-save_DrawElementsInstancedARB(GLenum mode,
- GLsizei count,
- GLenum type,
- const GLvoid *indices,
- GLsizei primcount)
+save_DrawElementsInstancedARB(UNUSED GLenum mode,
+ UNUSED GLsizei count,
+ UNUSED GLenum type,
+ UNUSED const GLvoid *indices,
+ UNUSED GLsizei primcount)
{
GET_CURRENT_CONTEXT(ctx);
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glDrawElementsInstanced() during display list compile");
+ "glDrawElementsInstanced() during display list compile");
}
static void GLAPIENTRY
-save_DrawElementsInstancedBaseVertexARB(GLenum mode,
- GLsizei count,
- GLenum type,
- const GLvoid *indices,
- GLsizei primcount,
- GLint basevertex)
+save_DrawElementsInstancedBaseVertexARB(UNUSED GLenum mode,
+ UNUSED GLsizei count,
+ UNUSED GLenum type,
+ UNUSED const GLvoid *indices,
+ UNUSED GLsizei primcount,
+ UNUSED GLint basevertex)
{
GET_CURRENT_CONTEXT(ctx);
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glDrawElementsInstancedBaseVertex() during display list compile");
+ "glDrawElementsInstancedBaseVertex() during display list compile");
}
/* GL_ARB_base_instance. */
static void GLAPIENTRY
-save_DrawArraysInstancedBaseInstance(GLenum mode,
- GLint first,
- GLsizei count,
- GLsizei primcount,
- GLuint baseinstance)
+save_DrawArraysInstancedBaseInstance(UNUSED GLenum mode,
+ UNUSED GLint first,
+ UNUSED GLsizei count,
+ UNUSED GLsizei primcount,
+ UNUSED GLuint baseinstance)
{
GET_CURRENT_CONTEXT(ctx);
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glDrawArraysInstancedBaseInstance() during display list compile");
+ "glDrawArraysInstancedBaseInstance() during display list compile");
}
static void APIENTRY
-save_DrawElementsInstancedBaseInstance(GLenum mode,
- GLsizei count,
- GLenum type,
- const void *indices,
- GLsizei primcount,
- GLuint baseinstance)
+save_DrawElementsInstancedBaseInstance(UNUSED GLenum mode,
+ UNUSED GLsizei count,
+ UNUSED GLenum type,
+ UNUSED const void *indices,
+ UNUSED GLsizei primcount,
+ UNUSED GLuint baseinstance)
{
GET_CURRENT_CONTEXT(ctx);
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glDrawElementsInstancedBaseInstance() during display list compile");
+ "glDrawElementsInstancedBaseInstance() during display list compile");
}
static void APIENTRY
-save_DrawElementsInstancedBaseVertexBaseInstance(GLenum mode,
- GLsizei count,
- GLenum type,
- const void *indices,
- GLsizei primcount,
- GLint basevertex,
- GLuint baseinstance)
+save_DrawElementsInstancedBaseVertexBaseInstance(UNUSED GLenum mode,
+ UNUSED GLsizei count,
+ UNUSED GLenum type,
+ UNUSED const void *indices,
+ UNUSED GLsizei primcount,
+ UNUSED GLint basevertex,
+ UNUSED GLuint baseinstance)
{
GET_CURRENT_CONTEXT(ctx);
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glDrawElementsInstancedBaseVertexBaseInstance() during display list compile");
+ "glDrawElementsInstancedBaseVertexBaseInstance() during display list compile");
}
n[1].i = num;
n[2].e = type;
save_pointer(&n[3], lists_copy);
- };
+ }
/* After this, we don't know what state we're in. Invalidate all
* cached information previously gathered:
}
-static void GLAPIENTRY
-save_PolygonOffsetEXT(GLfloat factor, GLfloat bias)
-{
- GET_CURRENT_CONTEXT(ctx);
- /* XXX mult by DepthMaxF here??? */
- save_PolygonOffset(factor, ctx->DrawBuffer->_DepthMaxF * bias);
-}
-
static void GLAPIENTRY
save_PolygonOffsetClampEXT(GLfloat factor, GLfloat units, GLfloat clamp)
{
/*
- * GL_NV_fragment_program
+ * GL_ARB_vertex_program
*/
static void GLAPIENTRY
-save_BindProgramNV(GLenum target, GLuint id)
+save_BindProgramARB(GLenum target, GLuint id)
{
GET_CURRENT_CONTEXT(ctx);
Node *n;
ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
- n = alloc_instruction(ctx, OPCODE_BIND_PROGRAM_NV, 2);
+ n = alloc_instruction(ctx, OPCODE_BIND_PROGRAM_ARB, 2);
if (n) {
n[1].e = target;
n[2].ui = id;
static void GLAPIENTRY
save_ProgramEnvParameters4fvEXT(GLenum target, GLuint index, GLsizei count,
- const GLfloat * params)
+ const GLfloat * params)
{
GET_CURRENT_CONTEXT(ctx);
Node *n;
const GLfloat * p = params;
for (i = 0 ; i < count ; i++) {
- n = alloc_instruction(ctx, OPCODE_PROGRAM_ENV_PARAMETER_ARB, 6);
- if (n) {
- n[1].e = target;
- n[2].ui = index;
- n[3].f = p[0];
- n[4].f = p[1];
- n[5].f = p[2];
- n[6].f = p[3];
- p += 4;
- }
+ n = alloc_instruction(ctx, OPCODE_PROGRAM_ENV_PARAMETER_ARB, 6);
+ if (n) {
+ n[1].e = target;
+ n[2].ui = index;
+ n[3].f = p[0];
+ n[4].f = p[1];
+ n[5].f = p[2];
+ n[6].f = p[3];
+ p += 4;
+ }
}
}
static void GLAPIENTRY
save_ProgramLocalParameters4fvEXT(GLenum target, GLuint index, GLsizei count,
- const GLfloat *params)
+ const GLfloat *params)
{
GET_CURRENT_CONTEXT(ctx);
Node *n;
const GLfloat * p = params;
for (i = 0 ; i < count ; i++) {
- n = alloc_instruction(ctx, OPCODE_PROGRAM_LOCAL_PARAMETER_ARB, 6);
- if (n) {
- n[1].e = target;
- n[2].ui = index;
- n[3].f = p[0];
- n[4].f = p[1];
- n[5].f = p[2];
- n[6].f = p[3];
- p += 4;
- }
+ n = alloc_instruction(ctx, OPCODE_PROGRAM_LOCAL_PARAMETER_ARB, 6);
+ if (n) {
+ n[1].e = target;
+ n[2].ui = index;
+ n[3].f = p[0];
+ n[4].f = p[1];
+ n[5].f = p[2];
+ n[6].f = p[3];
+ p += 4;
+ }
}
}
_mesa_compile_error(ctx, GL_INVALID_ENUM, "glMaterial(pname)");
return;
}
-
+
if (ctx->ExecuteFlag) {
CALL_Materialfv(ctx->Exec, (face, pname, param));
}
_mesa_compile_error(ctx, GL_INVALID_OPERATION, "recursive glBegin");
}
else {
- Node *n;
-
ctx->Driver.CurrentSavePrimitive = mode;
- /* Give the driver an opportunity to hook in an optimized
- * display list compiler.
- */
- if (vbo_save_NotifyBegin(ctx, mode))
- return;
-
- SAVE_FLUSH_VERTICES(ctx);
- n = alloc_instruction(ctx, OPCODE_BEGIN, 1);
- if (n) {
- n[1].e = mode;
- }
-
- if (ctx->ExecuteFlag) {
- CALL_Begin(ctx->Exec, (mode));
- }
+ vbo_save_NotifyBegin(ctx, mode);
}
}
/**
- * Record a GL_INVALID_VALUE error when a invalid vertex attribute
+ * Record a GL_INVALID_VALUE error when an invalid vertex attribute
* index is found.
*/
static void
index_error();
}
+static void GLAPIENTRY
+save_PrimitiveRestartNV(void)
+{
+ /* Note: this is used when outside a glBegin/End pair in a display list */
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ (void) alloc_instruction(ctx, OPCODE_PRIMITIVE_RESTART_NV, 0);
+ if (ctx->ExecuteFlag) {
+ CALL_PrimitiveRestartNV(ctx->Exec, ());
+ }
+}
+
+
static void GLAPIENTRY
save_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
n[2].i = x;
}
if (ctx->ExecuteFlag) {
- /*CALL_Uniform1ui(ctx->Exec, (location, x));*/
+ CALL_Uniform1ui(ctx->Exec, (location, x));
}
}
n[3].i = y;
}
if (ctx->ExecuteFlag) {
- /*CALL_Uniform2ui(ctx->Exec, (location, x, y));*/
+ CALL_Uniform2ui(ctx->Exec, (location, x, y));
}
}
n[4].i = z;
}
if (ctx->ExecuteFlag) {
- /*CALL_Uniform3ui(ctx->Exec, (location, x, y, z));*/
+ CALL_Uniform3ui(ctx->Exec, (location, x, y, z));
}
}
n[5].i = w;
}
if (ctx->ExecuteFlag) {
- /*CALL_Uniform4ui(ctx->Exec, (location, x, y, z, w));*/
+ CALL_Uniform4ui(ctx->Exec, (location, x, y, z, w));
}
}
save_pointer(&n[3], memdup(v, count * 1 * sizeof(*v)));
}
if (ctx->ExecuteFlag) {
- /*CALL_Uniform1uiv(ctx->Exec, (location, count, v));*/
+ CALL_Uniform1uiv(ctx->Exec, (location, count, v));
}
}
save_pointer(&n[3], memdup(v, count * 2 * sizeof(*v)));
}
if (ctx->ExecuteFlag) {
- /*CALL_Uniform2uiv(ctx->Exec, (location, count, v));*/
+ CALL_Uniform2uiv(ctx->Exec, (location, count, v));
}
}
save_pointer(&n[3], memdup(v, count * 3 * sizeof(*v)));
}
if (ctx->ExecuteFlag) {
- /*CALL_Uniform3uiv(ctx->Exec, (location, count, v));*/
+ CALL_Uniform3uiv(ctx->Exec, (location, count, v));
}
}
save_pointer(&n[3], memdup(v, count * 4 * sizeof(*v)));
}
if (ctx->ExecuteFlag) {
- /*CALL_Uniform4uiv(ctx->Exec, (location, count, v));*/
+ CALL_Uniform4uiv(ctx->Exec, (location, count, v));
}
}
}
}
+/** GL_EXT_window_rectangles */
+static void GLAPIENTRY
+save_WindowRectanglesEXT(GLenum mode, GLsizei count, const GLint *box)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = alloc_instruction(ctx, OPCODE_WINDOW_RECTANGLES, 2 + POINTER_DWORDS);
+ if (n) {
+ GLint *box_copy = NULL;
+
+ if (count > 0)
+ box_copy = memdup(box, sizeof(GLint) * 4 * count);
+ n[1].e = mode;
+ n[2].si = count;
+ save_pointer(&n[3], box_copy);
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_WindowRectanglesEXT(ctx->Exec, (mode, count, box));
+ }
+}
+
+
+/** GL_NV_conservative_raster */
+static void GLAPIENTRY
+save_SubpixelPrecisionBiasNV(GLuint xbits, GLuint ybits)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = alloc_instruction(ctx, OPCODE_SUBPIXEL_PRECISION_BIAS, 2);
+ if (n) {
+ n[1].ui = xbits;
+ n[2].ui = ybits;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_SubpixelPrecisionBiasNV(ctx->Exec, (xbits, ybits));
+ }
+}
+
+/** GL_NV_conservative_raster_dilate */
+static void GLAPIENTRY
+save_ConservativeRasterParameterfNV(GLenum pname, GLfloat param)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = alloc_instruction(ctx, OPCODE_CONSERVATIVE_RASTER_PARAMETER_F, 2);
+ if (n) {
+ n[1].e = pname;
+ n[2].f = param;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_ConservativeRasterParameterfNV(ctx->Exec, (pname, param));
+ }
+}
+
+/** GL_NV_conservative_raster_pre_snap_triangles */
+static void GLAPIENTRY
+save_ConservativeRasterParameteriNV(GLenum pname, GLint param)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = alloc_instruction(ctx, OPCODE_CONSERVATIVE_RASTER_PARAMETER_I, 2);
+ if (n) {
+ n[1].e = pname;
+ n[2].i = param;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_ConservativeRasterParameteriNV(ctx->Exec, (pname, param));
+ }
+}
+
/**
* Save an error-generating command into display list.
case OPCODE_WINDOW_POS_ARB: /* GL_ARB_window_pos */
CALL_WindowPos3f(ctx->Exec, (n[1].f, n[2].f, n[3].f));
break;
- case OPCODE_BIND_PROGRAM_NV: /* GL_ARB_vertex_program */
+ case OPCODE_BIND_PROGRAM_ARB: /* GL_ARB_vertex_program */
CALL_BindProgramARB(ctx->Exec, (n[1].e, n[2].ui));
break;
case OPCODE_PROGRAM_LOCAL_PARAMETER_ARB:
CALL_DrawBuffers(ctx->Exec, (n[1].i, buffers));
}
break;
- case OPCODE_BLIT_FRAMEBUFFER:
- CALL_BlitFramebuffer(ctx->Exec, (n[1].i, n[2].i, n[3].i, n[4].i,
+ case OPCODE_BLIT_FRAMEBUFFER:
+ CALL_BlitFramebuffer(ctx->Exec, (n[1].i, n[2].i, n[3].i, n[4].i,
n[5].i, n[6].i, n[7].i, n[8].i,
n[9].i, n[10].e));
- break;
- case OPCODE_USE_PROGRAM:
- CALL_UseProgram(ctx->Exec, (n[1].ui));
- break;
- case OPCODE_UNIFORM_1F:
- CALL_Uniform1f(ctx->Exec, (n[1].i, n[2].f));
- break;
- case OPCODE_UNIFORM_2F:
- CALL_Uniform2f(ctx->Exec, (n[1].i, n[2].f, n[3].f));
- break;
- case OPCODE_UNIFORM_3F:
- CALL_Uniform3f(ctx->Exec, (n[1].i, n[2].f, n[3].f, n[4].f));
- break;
- case OPCODE_UNIFORM_4F:
- CALL_Uniform4f(ctx->Exec,
+ break;
+ case OPCODE_PRIMITIVE_RESTART_NV:
+ CALL_PrimitiveRestartNV(ctx->Exec, ());
+ break;
+
+ case OPCODE_USE_PROGRAM:
+ CALL_UseProgram(ctx->Exec, (n[1].ui));
+ break;
+ case OPCODE_UNIFORM_1F:
+ CALL_Uniform1f(ctx->Exec, (n[1].i, n[2].f));
+ break;
+ case OPCODE_UNIFORM_2F:
+ CALL_Uniform2f(ctx->Exec, (n[1].i, n[2].f, n[3].f));
+ break;
+ case OPCODE_UNIFORM_3F:
+ CALL_Uniform3f(ctx->Exec, (n[1].i, n[2].f, n[3].f, n[4].f));
+ break;
+ case OPCODE_UNIFORM_4F:
+ CALL_Uniform4f(ctx->Exec,
(n[1].i, n[2].f, n[3].f, n[4].f, n[5].f));
- break;
- case OPCODE_UNIFORM_1FV:
- CALL_Uniform1fv(ctx->Exec, (n[1].i, n[2].i, get_pointer(&n[3])));
- break;
- case OPCODE_UNIFORM_2FV:
- CALL_Uniform2fv(ctx->Exec, (n[1].i, n[2].i, get_pointer(&n[3])));
- break;
- case OPCODE_UNIFORM_3FV:
- CALL_Uniform3fv(ctx->Exec, (n[1].i, n[2].i, get_pointer(&n[3])));
- break;
- case OPCODE_UNIFORM_4FV:
- CALL_Uniform4fv(ctx->Exec, (n[1].i, n[2].i, get_pointer(&n[3])));
- break;
- case OPCODE_UNIFORM_1I:
- CALL_Uniform1i(ctx->Exec, (n[1].i, n[2].i));
- break;
- case OPCODE_UNIFORM_2I:
- CALL_Uniform2i(ctx->Exec, (n[1].i, n[2].i, n[3].i));
- break;
- case OPCODE_UNIFORM_3I:
- CALL_Uniform3i(ctx->Exec, (n[1].i, n[2].i, n[3].i, n[4].i));
- break;
- case OPCODE_UNIFORM_4I:
- CALL_Uniform4i(ctx->Exec,
- (n[1].i, n[2].i, n[3].i, n[4].i, n[5].i));
- break;
- case OPCODE_UNIFORM_1IV:
- CALL_Uniform1iv(ctx->Exec, (n[1].i, n[2].i, get_pointer(&n[3])));
- break;
- case OPCODE_UNIFORM_2IV:
- CALL_Uniform2iv(ctx->Exec, (n[1].i, n[2].i, get_pointer(&n[3])));
- break;
- case OPCODE_UNIFORM_3IV:
- CALL_Uniform3iv(ctx->Exec, (n[1].i, n[2].i, get_pointer(&n[3])));
- break;
- case OPCODE_UNIFORM_4IV:
- CALL_Uniform4iv(ctx->Exec, (n[1].i, n[2].i, get_pointer(&n[3])));
- break;
- case OPCODE_UNIFORM_1UI:
- /*CALL_Uniform1uiARB(ctx->Exec, (n[1].i, n[2].i));*/
- break;
- case OPCODE_UNIFORM_2UI:
- /*CALL_Uniform2uiARB(ctx->Exec, (n[1].i, n[2].i, n[3].i));*/
- break;
- case OPCODE_UNIFORM_3UI:
- /*CALL_Uniform3uiARB(ctx->Exec, (n[1].i, n[2].i, n[3].i, n[4].i));*/
- break;
- case OPCODE_UNIFORM_4UI:
- /*CALL_Uniform4uiARB(ctx->Exec,
+ break;
+ case OPCODE_UNIFORM_1FV:
+ CALL_Uniform1fv(ctx->Exec, (n[1].i, n[2].i, get_pointer(&n[3])));
+ break;
+ case OPCODE_UNIFORM_2FV:
+ CALL_Uniform2fv(ctx->Exec, (n[1].i, n[2].i, get_pointer(&n[3])));
+ break;
+ case OPCODE_UNIFORM_3FV:
+ CALL_Uniform3fv(ctx->Exec, (n[1].i, n[2].i, get_pointer(&n[3])));
+ break;
+ case OPCODE_UNIFORM_4FV:
+ CALL_Uniform4fv(ctx->Exec, (n[1].i, n[2].i, get_pointer(&n[3])));
+ break;
+ case OPCODE_UNIFORM_1I:
+ CALL_Uniform1i(ctx->Exec, (n[1].i, n[2].i));
+ break;
+ case OPCODE_UNIFORM_2I:
+ CALL_Uniform2i(ctx->Exec, (n[1].i, n[2].i, n[3].i));
+ break;
+ case OPCODE_UNIFORM_3I:
+ CALL_Uniform3i(ctx->Exec, (n[1].i, n[2].i, n[3].i, n[4].i));
+ break;
+ case OPCODE_UNIFORM_4I:
+ CALL_Uniform4i(ctx->Exec,
(n[1].i, n[2].i, n[3].i, n[4].i, n[5].i));
- */
- break;
- case OPCODE_UNIFORM_1UIV:
- /*CALL_Uniform1uivARB(ctx->Exec, (n[1].i, n[2].i,
- get_pointer(&n[3])));*/
- break;
- case OPCODE_UNIFORM_2UIV:
- /*CALL_Uniform2uivARB(ctx->Exec, (n[1].i, n[2].i,
- get_pointer(&n[3])));*/
- break;
- case OPCODE_UNIFORM_3UIV:
- /*CALL_Uniform3uivARB(ctx->Exec, (n[1].i, n[2].i,
- get_pointer(&n[3])));*/
- break;
- case OPCODE_UNIFORM_4UIV:
- /*CALL_Uniform4uivARB(ctx->Exec, (n[1].i, n[2].i,
- get_pointer(&n[3])));*/
- break;
- case OPCODE_UNIFORM_MATRIX22:
- CALL_UniformMatrix2fv(ctx->Exec,
+ break;
+ case OPCODE_UNIFORM_1IV:
+ CALL_Uniform1iv(ctx->Exec, (n[1].i, n[2].i, get_pointer(&n[3])));
+ break;
+ case OPCODE_UNIFORM_2IV:
+ CALL_Uniform2iv(ctx->Exec, (n[1].i, n[2].i, get_pointer(&n[3])));
+ break;
+ case OPCODE_UNIFORM_3IV:
+ CALL_Uniform3iv(ctx->Exec, (n[1].i, n[2].i, get_pointer(&n[3])));
+ break;
+ case OPCODE_UNIFORM_4IV:
+ CALL_Uniform4iv(ctx->Exec, (n[1].i, n[2].i, get_pointer(&n[3])));
+ break;
+ case OPCODE_UNIFORM_1UI:
+ CALL_Uniform1ui(ctx->Exec, (n[1].i, n[2].i));
+ break;
+ case OPCODE_UNIFORM_2UI:
+ CALL_Uniform2ui(ctx->Exec, (n[1].i, n[2].i, n[3].i));
+ break;
+ case OPCODE_UNIFORM_3UI:
+ CALL_Uniform3ui(ctx->Exec, (n[1].i, n[2].i, n[3].i, n[4].i));
+ break;
+ case OPCODE_UNIFORM_4UI:
+ CALL_Uniform4ui(ctx->Exec,
+ (n[1].i, n[2].i, n[3].i, n[4].i, n[5].i));
+ break;
+ case OPCODE_UNIFORM_1UIV:
+ CALL_Uniform1uiv(ctx->Exec, (n[1].i, n[2].i, get_pointer(&n[3])));
+ break;
+ case OPCODE_UNIFORM_2UIV:
+ CALL_Uniform2uiv(ctx->Exec, (n[1].i, n[2].i, get_pointer(&n[3])));
+ break;
+ case OPCODE_UNIFORM_3UIV:
+ CALL_Uniform3uiv(ctx->Exec, (n[1].i, n[2].i, get_pointer(&n[3])));
+ break;
+ case OPCODE_UNIFORM_4UIV:
+ CALL_Uniform4uiv(ctx->Exec, (n[1].i, n[2].i, get_pointer(&n[3])));
+ break;
+ case OPCODE_UNIFORM_MATRIX22:
+ CALL_UniformMatrix2fv(ctx->Exec,
(n[1].i, n[2].i, n[3].b, get_pointer(&n[4])));
- break;
- case OPCODE_UNIFORM_MATRIX33:
- CALL_UniformMatrix3fv(ctx->Exec,
+ break;
+ case OPCODE_UNIFORM_MATRIX33:
+ CALL_UniformMatrix3fv(ctx->Exec,
(n[1].i, n[2].i, n[3].b, get_pointer(&n[4])));
- break;
- case OPCODE_UNIFORM_MATRIX44:
- CALL_UniformMatrix4fv(ctx->Exec,
+ break;
+ case OPCODE_UNIFORM_MATRIX44:
+ CALL_UniformMatrix4fv(ctx->Exec,
(n[1].i, n[2].i, n[3].b, get_pointer(&n[4])));
- break;
- case OPCODE_UNIFORM_MATRIX23:
- CALL_UniformMatrix2x3fv(ctx->Exec,
+ break;
+ case OPCODE_UNIFORM_MATRIX23:
+ CALL_UniformMatrix2x3fv(ctx->Exec,
(n[1].i, n[2].i, n[3].b, get_pointer(&n[4])));
- break;
- case OPCODE_UNIFORM_MATRIX32:
- CALL_UniformMatrix3x2fv(ctx->Exec,
+ break;
+ case OPCODE_UNIFORM_MATRIX32:
+ CALL_UniformMatrix3x2fv(ctx->Exec,
(n[1].i, n[2].i, n[3].b, get_pointer(&n[4])));
- break;
- case OPCODE_UNIFORM_MATRIX24:
- CALL_UniformMatrix2x4fv(ctx->Exec,
+ break;
+ case OPCODE_UNIFORM_MATRIX24:
+ CALL_UniformMatrix2x4fv(ctx->Exec,
(n[1].i, n[2].i, n[3].b, get_pointer(&n[4])));
- break;
- case OPCODE_UNIFORM_MATRIX42:
- CALL_UniformMatrix4x2fv(ctx->Exec,
+ break;
+ case OPCODE_UNIFORM_MATRIX42:
+ CALL_UniformMatrix4x2fv(ctx->Exec,
(n[1].i, n[2].i, n[3].b, get_pointer(&n[4])));
- break;
- case OPCODE_UNIFORM_MATRIX34:
- CALL_UniformMatrix3x4fv(ctx->Exec,
+ break;
+ case OPCODE_UNIFORM_MATRIX34:
+ CALL_UniformMatrix3x4fv(ctx->Exec,
(n[1].i, n[2].i, n[3].b, get_pointer(&n[4])));
- break;
- case OPCODE_UNIFORM_MATRIX43:
- CALL_UniformMatrix4x3fv(ctx->Exec,
+ break;
+ case OPCODE_UNIFORM_MATRIX43:
+ CALL_UniformMatrix4x3fv(ctx->Exec,
(n[1].i, n[2].i, n[3].b, get_pointer(&n[4])));
- break;
+ break;
- case OPCODE_USE_PROGRAM_STAGES:
- CALL_UseProgramStages(ctx->Exec, (n[1].ui, n[2].ui, n[3].ui));
- break;
+ case OPCODE_USE_PROGRAM_STAGES:
+ CALL_UseProgramStages(ctx->Exec, (n[1].ui, n[2].ui, n[3].ui));
+ break;
case OPCODE_PROGRAM_UNIFORM_1F:
CALL_ProgramUniform1f(ctx->Exec, (n[1].ui, n[2].i, n[3].f));
break;
CALL_UniformBlockBinding(ctx->Exec, (n[1].ui, n[2].ui, n[3].ui));
break;
+ /* GL_EXT_window_rectangles */
+ case OPCODE_WINDOW_RECTANGLES:
+ CALL_WindowRectanglesEXT(
+ ctx->Exec, (n[1].e, n[2].si, get_pointer(&n[3])));
+ break;
+
+ /* GL_NV_conservative_raster */
+ case OPCODE_SUBPIXEL_PRECISION_BIAS:
+ CALL_SubpixelPrecisionBiasNV(ctx->Exec, (n[1].ui, n[2].ui));
+ break;
+
+ /* GL_NV_conservative_raster_dilate */
+ case OPCODE_CONSERVATIVE_RASTER_PARAMETER_F:
+ CALL_ConservativeRasterParameterfNV(ctx->Exec, (n[1].e, n[2].f));
+ break;
+
+ /* GL_NV_conservative_raster_pre_snap_triangles */
+ case OPCODE_CONSERVATIVE_RASTER_PARAMETER_I:
+ CALL_ConservativeRasterParameteriNV(ctx->Exec, (n[1].e, n[2].i));
+ break;
+
case OPCODE_CONTINUE:
n = (Node *) get_pointer(&n[1]);
break;
/* increment n to point to next compiled command */
if (opcode != OPCODE_CONTINUE) {
+ assert(InstSize[opcode] > 0);
n += InstSize[opcode];
}
}
_mesa_error(ctx, GL_INVALID_VALUE, "glDeleteLists");
return;
}
+
+ if (range > 1) {
+ /* We may be deleting a set of bitmap lists. See if there's a
+ * bitmap atlas to free.
+ */
+ struct gl_bitmap_atlas *atlas = lookup_bitmap_atlas(ctx, list);
+ if (atlas) {
+ _mesa_delete_bitmap_atlas(ctx, atlas);
+ _mesa_HashRemove(ctx->Shared->BitmapAtlas, list);
+ }
+ }
+
for (i = list; i < list + range; i++) {
destroy_list(ctx, i);
}
/*
* Make this an atomic operation
*/
- mtx_lock(&ctx->Shared->Mutex);
+ _mesa_HashLockMutex(ctx->Shared->DisplayList);
base = _mesa_HashFindFreeKeyBlock(ctx->Shared->DisplayList, range);
if (base) {
/* reserve the list IDs by with empty/dummy lists */
GLint i;
for (i = 0; i < range; i++) {
- _mesa_HashInsert(ctx->Shared->DisplayList, base + i,
- make_list(base + i, 1));
+ _mesa_HashInsertLocked(ctx->Shared->DisplayList, base + i,
+ make_list(base + i, 1));
+ }
+ }
+
+ if (USE_BITMAP_ATLAS &&
+ range > 16 &&
+ ctx->Driver.DrawAtlasBitmaps) {
+ /* "range > 16" is a rough heuristic to guess when glGenLists might be
+ * used to allocate display lists for glXUseXFont or wglUseFontBitmaps.
+ * Create the empty atlas now.
+ */
+ struct gl_bitmap_atlas *atlas = lookup_bitmap_atlas(ctx, base);
+ if (!atlas) {
+ atlas = alloc_bitmap_atlas(ctx, base);
+ }
+ if (atlas) {
+ /* Atlas _should_ be new/empty now, but clobbering is OK */
+ assert(atlas->numBitmaps == 0);
+ atlas->numBitmaps = range;
}
}
- mtx_unlock(&ctx->Shared->Mutex);
+ _mesa_HashUnlockMutex(ctx->Shared->DisplayList);
return base;
}
vbo_save_NewList(ctx, name, mode);
- ctx->CurrentDispatch = ctx->Save;
- _glapi_set_dispatch(ctx->CurrentDispatch);
+ ctx->CurrentServerDispatch = ctx->Save;
+ _glapi_set_dispatch(ctx->CurrentServerDispatch);
+ if (ctx->MarshalExec == NULL) {
+ ctx->CurrentClientDispatch = ctx->CurrentServerDispatch;
+ }
}
/**
- * End definition of current display list.
+ * End definition of current display list.
*/
void GLAPIENTRY
_mesa_EndList(void)
_mesa_error(ctx, GL_INVALID_OPERATION, "glEndList");
return;
}
-
+
/* Call before emitting END_OF_LIST, in case the driver wants to
* emit opcodes itself.
*/
ctx->ExecuteFlag = GL_TRUE;
ctx->CompileFlag = GL_FALSE;
- ctx->CurrentDispatch = ctx->Exec;
- _glapi_set_dispatch(ctx->CurrentDispatch);
+ ctx->CurrentServerDispatch = ctx->Exec;
+ _glapi_set_dispatch(ctx->CurrentServerDispatch);
+ if (ctx->MarshalExec == NULL) {
+ ctx->CurrentClientDispatch = ctx->CurrentServerDispatch;
+ }
}
/* also restore API function pointers to point to "save" versions */
if (save_compile_flag) {
- ctx->CurrentDispatch = ctx->Save;
- _glapi_set_dispatch(ctx->CurrentDispatch);
+ ctx->CurrentServerDispatch = ctx->Save;
+ _glapi_set_dispatch(ctx->CurrentServerDispatch);
+ if (ctx->MarshalExec == NULL) {
+ ctx->CurrentClientDispatch = ctx->CurrentServerDispatch;
+ }
}
}
+/**
+ * Try to execute a glCallLists() command where the display lists contain
+ * glBitmap commands with a texture atlas.
+ * \return true for success, false otherwise
+ */
+static bool
+render_bitmap_atlas(struct gl_context *ctx, GLsizei n, GLenum type,
+ const void *lists)
+{
+ struct gl_bitmap_atlas *atlas;
+ int i;
+
+ if (!USE_BITMAP_ATLAS ||
+ !ctx->Current.RasterPosValid ||
+ ctx->List.ListBase == 0 ||
+ type != GL_UNSIGNED_BYTE ||
+ !ctx->Driver.DrawAtlasBitmaps) {
+ /* unsupported */
+ return false;
+ }
+
+ atlas = lookup_bitmap_atlas(ctx, ctx->List.ListBase);
+
+ if (!atlas) {
+ /* Even if glGenLists wasn't called, we can still try to create
+ * the atlas now.
+ */
+ atlas = alloc_bitmap_atlas(ctx, ctx->List.ListBase);
+ }
+
+ if (atlas && !atlas->complete && !atlas->incomplete) {
+ /* Try to build the bitmap atlas now.
+ * If the atlas was created in glGenLists, we'll have recorded the
+ * number of lists (bitmaps). Otherwise, take a guess at 256.
+ */
+ if (atlas->numBitmaps == 0)
+ atlas->numBitmaps = 256;
+ build_bitmap_atlas(ctx, atlas, ctx->List.ListBase);
+ }
+
+ if (!atlas || !atlas->complete) {
+ return false;
+ }
+
+ /* check that all display list IDs are in the atlas */
+ for (i = 0; i < n; i++) {
+ const GLubyte *ids = (const GLubyte *) lists;
+
+ if (ids[i] >= atlas->numBitmaps) {
+ return false;
+ }
+ }
+
+ ctx->Driver.DrawAtlasBitmaps(ctx, atlas, n, (const GLubyte *) lists);
+
+ return true;
+}
+
+
/**
* Execute glCallLists: call multiple display lists.
*/
return;
}
+ if (render_bitmap_atlas(ctx, n, type, lists)) {
+ return;
+ }
+
/* Save the CompileFlag status, turn it off, execute display list,
* and restore the CompileFlag.
*/
/* also restore API function pointers to point to "save" versions */
if (save_compile_flag) {
- ctx->CurrentDispatch = ctx->Save;
- _glapi_set_dispatch(ctx->CurrentDispatch);
+ ctx->CurrentServerDispatch = ctx->Save;
+ _glapi_set_dispatch(ctx->CurrentServerDispatch);
+ if (ctx->MarshalExec == NULL) {
+ ctx->CurrentClientDispatch = ctx->CurrentServerDispatch;
+ }
}
}
SET_StencilMaskSeparate(table, save_StencilMaskSeparate);
SET_StencilOpSeparate(table, save_StencilOpSeparate);
- /* ATI_separate_stencil */
+ /* ATI_separate_stencil */
SET_StencilFuncSeparateATI(table, save_StencilFuncSeparateATI);
/* GL_ARB_imaging */
SET_BlendColorEXT(table, save_BlendColorEXT);
#endif
- /* 3. GL_EXT_polygon_offset */
- SET_PolygonOffsetEXT(table, save_PolygonOffsetEXT);
-
/* 6. GL_EXT_texture3d */
#if 0
SET_CopyTexSubImage3DEXT(table, save_CopyTexSubImage3D);
SET_WindowPos4sMESA(table, save_WindowPos4sMESA);
SET_WindowPos4svMESA(table, save_WindowPos4svMESA);
- /* 233. GL_NV_vertex_program */
- /* The following commands DO NOT go into display lists:
- * AreProgramsResidentNV, IsProgramNV, GenProgramsNV, DeleteProgramsNV,
- * VertexAttribPointerNV, GetProgram*, GetVertexAttrib*
- */
- SET_BindProgramARB(table, save_BindProgramNV);
-
/* 245. GL_ATI_fragment_shader */
SET_BindFragmentShaderATI(table, save_BindFragmentShaderATI);
SET_SetFragmentShaderConstantATI(table, save_SetFragmentShaderConstantATI);
/* ARB 27. GL_ARB_fragment_program */
/* glVertexAttrib* functions alias the NV ones, handled elsewhere */
SET_ProgramStringARB(table, save_ProgramStringARB);
- SET_BindProgramARB(table, save_BindProgramNV);
+ SET_BindProgramARB(table, save_BindProgramARB);
SET_ProgramEnvParameter4dARB(table, save_ProgramEnvParameter4dARB);
SET_ProgramEnvParameter4dvARB(table, save_ProgramEnvParameter4dvARB);
SET_ProgramEnvParameter4fARB(table, save_ProgramEnvParameter4fARB);
SET_ClearBufferuiv(table, save_ClearBufferuiv);
SET_ClearBufferfv(table, save_ClearBufferfv);
SET_ClearBufferfi(table, save_ClearBufferfi);
-#if 0
SET_Uniform1ui(table, save_Uniform1ui);
SET_Uniform2ui(table, save_Uniform2ui);
SET_Uniform3ui(table, save_Uniform3ui);
SET_Uniform2uiv(table, save_Uniform2uiv);
SET_Uniform3uiv(table, save_Uniform3uiv);
SET_Uniform4uiv(table, save_Uniform4uiv);
-#else
- (void) save_Uniform1ui;
- (void) save_Uniform2ui;
- (void) save_Uniform3ui;
- (void) save_Uniform4ui;
- (void) save_Uniform1uiv;
- (void) save_Uniform2uiv;
- (void) save_Uniform3uiv;
- (void) save_Uniform4uiv;
-#endif
/* These are: */
SET_BeginTransformFeedback(table, save_BeginTransformFeedback);
SET_ProgramUniformMatrix3x4fv(table, save_ProgramUniformMatrix3x4fv);
SET_ProgramUniformMatrix4x3fv(table, save_ProgramUniformMatrix4x3fv);
- /* GL_EXT_polygon_offset_clamp */
+ /* GL_{ARB,EXT}_polygon_offset_clamp */
SET_PolygonOffsetClampEXT(table, save_PolygonOffsetClampEXT);
+
+ /* GL_EXT_window_rectangles */
+ SET_WindowRectanglesEXT(table, save_WindowRectanglesEXT);
+
+ /* GL_NV_conservative_raster */
+ SET_SubpixelPrecisionBiasNV(table, save_SubpixelPrecisionBiasNV);
+
+ /* GL_NV_conservative_raster_dilate */
+ SET_ConservativeRasterParameterfNV(table, save_ConservativeRasterParameterfNV);
+
+ /* GL_NV_conservative_raster_pre_snap_triangles */
+ SET_ConservativeRasterParameteriNV(table, save_ConservativeRasterParameteriNV);
}
if (!islist(ctx, list)) {
fprintf(f, "%u is not a display list ID\n", list);
- return;
+ goto out;
}
dlist = _mesa_lookup_list(ctx, list);
- if (!dlist)
- return;
+ if (!dlist) {
+ goto out;
+ }
n = dlist->Head;
printf
("ERROR IN DISPLAY LIST: opcode = %d, address = %p\n",
opcode, (void *) n);
- return;
+ goto out;
}
else {
fprintf(f, "command %d, %u operands\n", opcode,
}
/* increment n to point to next compiled command */
if (opcode != OPCODE_CONTINUE) {
+ assert(InstSize[opcode] > 0);
n += InstSize[opcode];
}
}
}
+ out:
fflush(f);
if (fname)
fclose(f);
vfmt->VertexAttrib3fvARB = save_VertexAttrib3fvARB;
vfmt->VertexAttrib4fARB = save_VertexAttrib4fARB;
vfmt->VertexAttrib4fvARB = save_VertexAttrib4fvARB;
+
+ vfmt->PrimitiveRestartNV = save_PrimitiveRestartNV;
}