diff options
Diffstat (limited to 'mesalib/src/mesa')
-rw-r--r-- | mesalib/src/mesa/drivers/dri/common/xmlconfig.c | 20 | ||||
-rw-r--r-- | mesalib/src/mesa/main/arrayobj.c | 2 | ||||
-rw-r--r-- | mesalib/src/mesa/main/buffers.c | 2 | ||||
-rw-r--r-- | mesalib/src/mesa/main/texcompress_rgtc.c | 8 | ||||
-rw-r--r-- | mesalib/src/mesa/state_tracker/st_atom_sampler.c | 11 | ||||
-rw-r--r-- | mesalib/src/mesa/state_tracker/st_atom_texture.c | 650 | ||||
-rw-r--r-- | mesalib/src/mesa/state_tracker/st_context.c | 4 | ||||
-rw-r--r-- | mesalib/src/mesa/state_tracker/st_context.h | 13 | ||||
-rw-r--r-- | mesalib/src/mesa/state_tracker/st_draw.c | 78 | ||||
-rw-r--r-- | mesalib/src/mesa/state_tracker/st_draw.h | 2 | ||||
-rw-r--r-- | mesalib/src/mesa/state_tracker/st_draw_feedback.c | 15 | ||||
-rw-r--r-- | mesalib/src/mesa/vbo/vbo_context.c | 3 | ||||
-rw-r--r-- | mesalib/src/mesa/vbo/vbo_exec_api.c | 2 | ||||
-rw-r--r-- | mesalib/src/mesa/vbo/vbo_exec_array.c | 7 | ||||
-rw-r--r-- | mesalib/src/mesa/vbo/vbo_exec_draw.c | 1 | ||||
-rw-r--r-- | mesalib/src/mesa/vbo/vbo_save_draw.c | 3 | ||||
-rw-r--r-- | mesalib/src/mesa/vbo/vbo_split_copy.c | 1253 |
17 files changed, 1067 insertions, 1007 deletions
diff --git a/mesalib/src/mesa/drivers/dri/common/xmlconfig.c b/mesalib/src/mesa/drivers/dri/common/xmlconfig.c index eaba335a4..30075f253 100644 --- a/mesalib/src/mesa/drivers/dri/common/xmlconfig.c +++ b/mesalib/src/mesa/drivers/dri/common/xmlconfig.c @@ -64,7 +64,25 @@ extern char *program_invocation_name, *program_invocation_short_name; the basename to match BSD getprogname() */
# include <stdlib.h>
# include <libgen.h>
-# define GET_PROGRAM_NAME() basename(getexecname())
+
+static const char *__getProgramName () {
+ static const char *progname;
+
+ if (progname == NULL) {
+ const char *e = getexecname();
+ if (e != NULL) {
+ /* Have to make a copy since getexecname can return a readonly
+ string, but basename expects to be able to modify its arg. */
+ char *n = strdup(e);
+ if (n != NULL) {
+ progname = basename(n);
+ }
+ }
+ }
+ return progname;
+}
+
+# define GET_PROGRAM_NAME() __getProgramName()
#endif
#if !defined(GET_PROGRAM_NAME)
diff --git a/mesalib/src/mesa/main/arrayobj.c b/mesalib/src/mesa/main/arrayobj.c index 8fff3c0e2..ce1e277bd 100644 --- a/mesalib/src/mesa/main/arrayobj.c +++ b/mesalib/src/mesa/main/arrayobj.c @@ -41,6 +41,7 @@ #include "glheader.h"
#include "hash.h"
+#include "image.h"
#include "imports.h"
#include "context.h"
#include "mfeatures.h"
@@ -207,6 +208,7 @@ init_array(struct gl_context *ctx, array->Ptr = NULL;
array->Enabled = GL_FALSE;
array->Normalized = GL_FALSE;
+ array->_ElementSize = size * _mesa_sizeof_type(type);
#if FEATURE_ARB_vertex_buffer_object
/* Vertex array buffers */
_mesa_reference_buffer_object(ctx, &array->BufferObj,
diff --git a/mesalib/src/mesa/main/buffers.c b/mesalib/src/mesa/main/buffers.c index 1ddf5b2c8..928450f0f 100644 --- a/mesalib/src/mesa/main/buffers.c +++ b/mesalib/src/mesa/main/buffers.c @@ -407,7 +407,6 @@ _mesa_drawbuffers(struct gl_context *ctx, GLuint n, const GLenum *buffers, fb->_ColorDrawBufferIndexes[buf] = bufIndex;
newState = GL_TRUE;
}
- fb->ColorDrawBuffer[buf] = buffers[buf];
count = buf + 1;
}
else {
@@ -416,6 +415,7 @@ _mesa_drawbuffers(struct gl_context *ctx, GLuint n, const GLenum *buffers, newState = GL_TRUE;
}
}
+ fb->ColorDrawBuffer[buf] = buffers[buf];
}
/* set remaining outputs to -1 (GL_NONE) */
while (buf < ctx->Const.MaxDrawBuffers) {
diff --git a/mesalib/src/mesa/main/texcompress_rgtc.c b/mesalib/src/mesa/main/texcompress_rgtc.c index 60146d09b..d75546a92 100644 --- a/mesalib/src/mesa/main/texcompress_rgtc.c +++ b/mesalib/src/mesa/main/texcompress_rgtc.c @@ -121,7 +121,7 @@ _mesa_texstore_red_rgtc1(TEXSTORE_PARAMS) texWidth, (GLubyte *) dstAddr);
blkaddr = dst;
- dstRowDiff = dstRowStride >= (srcWidth * 4) ? dstRowStride - (((srcWidth + 3) & ~3) * 4) : 0;
+ dstRowDiff = dstRowStride >= (srcWidth * 2) ? dstRowStride - (((srcWidth + 3) & ~3) * 2) : 0;
for (j = 0; j < srcHeight; j+=4) {
if (srcHeight > j + 3) numypixels = 4;
else numypixels = srcHeight - j;
@@ -176,7 +176,7 @@ _mesa_texstore_signed_red_rgtc1(TEXSTORE_PARAMS) texWidth, (GLubyte *) dstAddr);
blkaddr = dst;
- dstRowDiff = dstRowStride >= (srcWidth * 4) ? dstRowStride - (((srcWidth + 3) & ~3) * 4) : 0;
+ dstRowDiff = dstRowStride >= (srcWidth * 2) ? dstRowStride - (((srcWidth + 3) & ~3) * 2) : 0;
for (j = 0; j < srcHeight; j+=4) {
if (srcHeight > j + 3) numypixels = 4;
else numypixels = srcHeight - j;
@@ -232,7 +232,7 @@ _mesa_texstore_rg_rgtc2(TEXSTORE_PARAMS) texWidth, (GLubyte *) dstAddr);
blkaddr = dst;
- dstRowDiff = dstRowStride >= (srcWidth * 8) ? dstRowStride - (((srcWidth + 7) & ~7) * 8) : 0;
+ dstRowDiff = dstRowStride >= (srcWidth * 4) ? dstRowStride - (((srcWidth + 3) & ~3) * 4) : 0;
for (j = 0; j < srcHeight; j+=4) {
if (srcHeight > j + 3) numypixels = 4;
else numypixels = srcHeight - j;
@@ -294,7 +294,7 @@ _mesa_texstore_signed_rg_rgtc2(TEXSTORE_PARAMS) texWidth, (GLubyte *) dstAddr);
blkaddr = dst;
- dstRowDiff = dstRowStride >= (srcWidth * 8) ? dstRowStride - (((srcWidth + 7) & ~7) * 8) : 0;
+ dstRowDiff = dstRowStride >= (srcWidth * 4) ? dstRowStride - (((srcWidth + 3) & ~3) * 4) : 0;
for (j = 0; j < srcHeight; j += 4) {
if (srcHeight > j + 3) numypixels = 4;
else numypixels = srcHeight - j;
diff --git a/mesalib/src/mesa/state_tracker/st_atom_sampler.c b/mesalib/src/mesa/state_tracker/st_atom_sampler.c index d1ab1ac3e..48b94500d 100644 --- a/mesalib/src/mesa/state_tracker/st_atom_sampler.c +++ b/mesalib/src/mesa/state_tracker/st_atom_sampler.c @@ -166,12 +166,11 @@ update_samplers(struct st_context *st) sampler->lod_bias = st->ctx->Texture.Unit[texUnit].LodBias +
texobj->LodBias;
- sampler->min_lod = texobj->BaseLevel + texobj->MinLod;
- if (sampler->min_lod < texobj->BaseLevel)
- sampler->min_lod = texobj->BaseLevel;
-
- sampler->max_lod = MIN2((GLfloat) texobj->MaxLevel,
- (texobj->MaxLod + texobj->BaseLevel));
+ sampler->min_lod = CLAMP(texobj->MinLod,
+ 0.0f,
+ (GLfloat) texobj->MaxLevel - texobj->BaseLevel);
+ sampler->max_lod = MIN2((GLfloat) texobj->MaxLevel - texobj->BaseLevel,
+ texobj->MaxLod);
if (sampler->max_lod < sampler->min_lod) {
/* The GL spec doesn't seem to specify what to do in this case.
* Swap the values.
diff --git a/mesalib/src/mesa/state_tracker/st_atom_texture.c b/mesalib/src/mesa/state_tracker/st_atom_texture.c index fd03669e6..04825ba4a 100644 --- a/mesalib/src/mesa/state_tracker/st_atom_texture.c +++ b/mesalib/src/mesa/state_tracker/st_atom_texture.c @@ -1,324 +1,326 @@ -/************************************************************************** - * - * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. - * 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"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * 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 NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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. - * - **************************************************************************/ - - /* - * Authors: - * Keith Whitwell <keith@tungstengraphics.com> - * Brian Paul - */ - - -#include "main/macros.h" -#include "program/prog_instruction.h" - -#include "st_context.h" -#include "st_atom.h" -#include "st_texture.h" -#include "st_format.h" -#include "st_cb_texture.h" -#include "pipe/p_context.h" -#include "util/u_format.h" -#include "util/u_inlines.h" -#include "cso_cache/cso_context.h" - - -/** - * Combine depth texture mode with "swizzle" so that depth mode swizzling - * takes place before texture swizzling, and return the resulting swizzle. - * If the format is not a depth format, return "swizzle" unchanged. - * - * \param format PIPE_FORMAT_*. - * \param swizzle Texture swizzle, a bitmask computed using MAKE_SWIZZLE4. - * \param depthmode One of GL_LUMINANCE, GL_INTENSITY, GL_ALPHA, GL_RED. - */ -static GLuint -apply_depthmode(enum pipe_format format, GLuint swizzle, GLenum depthmode) -{ - const struct util_format_description *desc = - util_format_description(format); - unsigned char swiz[4]; - unsigned i; - - if (desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS || - desc->swizzle[0] == UTIL_FORMAT_SWIZZLE_NONE) { - /* Not a depth format. */ - return swizzle; - } - - for (i = 0; i < 4; i++) - swiz[i] = GET_SWZ(swizzle, i); - - switch (depthmode) { - case GL_LUMINANCE: - /* Rewrite reads from W to ONE, and reads from XYZ to XXX. */ - for (i = 0; i < 4; i++) - if (swiz[i] == SWIZZLE_W) - swiz[i] = SWIZZLE_ONE; - else if (swiz[i] < SWIZZLE_W) - swiz[i] = SWIZZLE_X; - break; - - case GL_INTENSITY: - /* Rewrite reads from XYZW to XXXX. */ - for (i = 0; i < 4; i++) - if (swiz[i] <= SWIZZLE_W) - swiz[i] = SWIZZLE_X; - break; - - case GL_ALPHA: - /* Rewrite reads from W to X, and reads from XYZ to 000. */ - for (i = 0; i < 4; i++) - if (swiz[i] == SWIZZLE_W) - swiz[i] = SWIZZLE_X; - else if (swiz[i] < SWIZZLE_W) - swiz[i] = SWIZZLE_ZERO; - break; - case GL_RED: - /* Rewrite reads W to 1, XYZ to X00 */ - for (i = 0; i < 4; i++) - if (swiz[i] == SWIZZLE_W) - swiz[i] = SWIZZLE_ONE; - else if (swiz[i] == SWIZZLE_Y || swiz[i] == SWIZZLE_Z) - swiz[i] = SWIZZLE_ZERO; - break; - } - - return MAKE_SWIZZLE4(swiz[0], swiz[1], swiz[2], swiz[3]); -} - - -/** - * Return TRUE if the swizzling described by "swizzle" and - * "depthmode" (for depth textures only) is different from the swizzling - * set in the given sampler view. - * - * \param sv A sampler view. - * \param swizzle Texture swizzle, a bitmask computed using MAKE_SWIZZLE4. - * \param depthmode One of GL_LUMINANCE, GL_INTENSITY, GL_ALPHA. - */ -static boolean -check_sampler_swizzle(struct pipe_sampler_view *sv, - GLuint swizzle, GLenum depthmode) -{ - swizzle = apply_depthmode(sv->texture->format, swizzle, depthmode); - - if ((sv->swizzle_r != GET_SWZ(swizzle, 0)) || - (sv->swizzle_g != GET_SWZ(swizzle, 1)) || - (sv->swizzle_b != GET_SWZ(swizzle, 2)) || - (sv->swizzle_a != GET_SWZ(swizzle, 3))) - return TRUE; - return FALSE; -} - - -static INLINE struct pipe_sampler_view * -st_create_texture_sampler_view_from_stobj(struct pipe_context *pipe, - struct st_texture_object *stObj, - enum pipe_format format) -{ - struct pipe_sampler_view templ; - GLuint swizzle = apply_depthmode(stObj->pt->format, - stObj->base._Swizzle, - stObj->base.DepthMode); - - u_sampler_view_default_template(&templ, - stObj->pt, - format); - - if (swizzle != SWIZZLE_NOOP) { - templ.swizzle_r = GET_SWZ(swizzle, 0); - templ.swizzle_g = GET_SWZ(swizzle, 1); - templ.swizzle_b = GET_SWZ(swizzle, 2); - templ.swizzle_a = GET_SWZ(swizzle, 3); - } - - return pipe->create_sampler_view(pipe, stObj->pt, &templ); -} - - -static INLINE struct pipe_sampler_view * -st_get_texture_sampler_view_from_stobj(struct st_texture_object *stObj, - struct pipe_context *pipe, - enum pipe_format format) -{ - if (!stObj || !stObj->pt) { - return NULL; - } - - if (!stObj->sampler_view) { - stObj->sampler_view = - st_create_texture_sampler_view_from_stobj(pipe, stObj, format); - } - - return stObj->sampler_view; -} - - -static void -update_textures(struct st_context *st) -{ - struct pipe_context *pipe = st->pipe; - struct gl_vertex_program *vprog = st->ctx->VertexProgram._Current; - struct gl_fragment_program *fprog = st->ctx->FragmentProgram._Current; - const GLbitfield samplersUsed = (vprog->Base.SamplersUsed | - fprog->Base.SamplersUsed); - GLuint su; - - st->state.num_textures = 0; - - /* loop over sampler units (aka tex image units) */ - for (su = 0; su < st->ctx->Const.MaxTextureImageUnits; su++) { - struct pipe_sampler_view *sampler_view = NULL; - enum pipe_format st_view_format; - if (samplersUsed & (1 << su)) { - struct gl_texture_object *texObj; - struct st_texture_object *stObj; - GLboolean retval; - GLuint texUnit; - - if (fprog->Base.SamplersUsed & (1 << su)) - texUnit = fprog->Base.SamplerUnits[su]; - else - texUnit = vprog->Base.SamplerUnits[su]; - - texObj = st->ctx->Texture.Unit[texUnit]._Current; - - if (!texObj) { - texObj = st_get_default_texture(st); - } - stObj = st_texture_object(texObj); - - retval = st_finalize_texture(st->ctx, st->pipe, texObj); - if (!retval) { - /* out of mem */ - continue; - } - - /* Determine the format of the texture sampler view */ - st_view_format = stObj->pt->format; - { - const struct st_texture_image *firstImage = - st_texture_image(stObj->base.Image[0][stObj->base.BaseLevel]); - const gl_format texFormat = firstImage->base.TexFormat; - enum pipe_format firstImageFormat = - st_mesa_format_to_pipe_format(texFormat); - - if ((stObj->base.sRGBDecode == GL_SKIP_DECODE_EXT) && - (_mesa_get_format_color_encoding(texFormat) == GL_SRGB)) { - /* don't do sRGB->RGB conversion. Interpret the texture - * texture data as linear values. - */ - const gl_format linearFormat = - _mesa_get_srgb_format_linear(texFormat); - firstImageFormat = st_mesa_format_to_pipe_format(linearFormat); - } - - if (firstImageFormat != stObj->pt->format) - st_view_format = firstImageFormat; - } - - st->state.num_textures = su + 1; - - /* if sampler view has changed dereference it */ - if (stObj->sampler_view) - if (check_sampler_swizzle(stObj->sampler_view, - stObj->base._Swizzle, - stObj->base.DepthMode) || - (st_view_format != stObj->sampler_view->format)) - pipe_sampler_view_reference(&stObj->sampler_view, NULL); - - sampler_view = st_get_texture_sampler_view_from_stobj(stObj, pipe, st_view_format); - } - pipe_sampler_view_reference(&st->state.sampler_views[su], sampler_view); - } - - cso_set_fragment_sampler_views(st->cso_context, - st->state.num_textures, - st->state.sampler_views); - if (st->ctx->Const.MaxVertexTextureImageUnits > 0) { - cso_set_vertex_sampler_views(st->cso_context, - MIN2(st->state.num_textures, - st->ctx->Const.MaxVertexTextureImageUnits), - st->state.sampler_views); - } -} - - -const struct st_tracked_state st_update_texture = { - "st_update_texture", /* name */ - { /* dirty */ - _NEW_TEXTURE, /* mesa */ - ST_NEW_FRAGMENT_PROGRAM, /* st */ - }, - update_textures /* update */ -}; - - - - -static void -finalize_textures(struct st_context *st) -{ - struct gl_fragment_program *fprog = st->ctx->FragmentProgram._Current; - const GLboolean prev_missing_textures = st->missing_textures; - GLuint su; - - st->missing_textures = GL_FALSE; - - for (su = 0; su < st->ctx->Const.MaxTextureCoordUnits; su++) { - if (fprog->Base.SamplersUsed & (1 << su)) { - const GLuint texUnit = fprog->Base.SamplerUnits[su]; - struct gl_texture_object *texObj - = st->ctx->Texture.Unit[texUnit]._Current; - - if (texObj) { - GLboolean retval; - - retval = st_finalize_texture(st->ctx, st->pipe, texObj); - if (!retval) { - /* out of mem */ - st->missing_textures = GL_TRUE; - continue; - } - } - } - } - - if (prev_missing_textures != st->missing_textures) - st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM; -} - - - -const struct st_tracked_state st_finalize_textures = { - "st_finalize_textures", /* name */ - { /* dirty */ - _NEW_TEXTURE, /* mesa */ - 0, /* st */ - }, - finalize_textures /* update */ -}; +/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * 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"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * 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 NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * Brian Paul
+ */
+
+
+#include "main/macros.h"
+#include "program/prog_instruction.h"
+
+#include "st_context.h"
+#include "st_atom.h"
+#include "st_texture.h"
+#include "st_format.h"
+#include "st_cb_texture.h"
+#include "pipe/p_context.h"
+#include "util/u_format.h"
+#include "util/u_inlines.h"
+#include "cso_cache/cso_context.h"
+
+
+/**
+ * Combine depth texture mode with "swizzle" so that depth mode swizzling
+ * takes place before texture swizzling, and return the resulting swizzle.
+ * If the format is not a depth format, return "swizzle" unchanged.
+ *
+ * \param format PIPE_FORMAT_*.
+ * \param swizzle Texture swizzle, a bitmask computed using MAKE_SWIZZLE4.
+ * \param depthmode One of GL_LUMINANCE, GL_INTENSITY, GL_ALPHA, GL_RED.
+ */
+static GLuint
+apply_depthmode(enum pipe_format format, GLuint swizzle, GLenum depthmode)
+{
+ const struct util_format_description *desc =
+ util_format_description(format);
+ unsigned char swiz[4];
+ unsigned i;
+
+ if (desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS ||
+ desc->swizzle[0] == UTIL_FORMAT_SWIZZLE_NONE) {
+ /* Not a depth format. */
+ return swizzle;
+ }
+
+ for (i = 0; i < 4; i++)
+ swiz[i] = GET_SWZ(swizzle, i);
+
+ switch (depthmode) {
+ case GL_LUMINANCE:
+ /* Rewrite reads from W to ONE, and reads from XYZ to XXX. */
+ for (i = 0; i < 4; i++)
+ if (swiz[i] == SWIZZLE_W)
+ swiz[i] = SWIZZLE_ONE;
+ else if (swiz[i] < SWIZZLE_W)
+ swiz[i] = SWIZZLE_X;
+ break;
+
+ case GL_INTENSITY:
+ /* Rewrite reads from XYZW to XXXX. */
+ for (i = 0; i < 4; i++)
+ if (swiz[i] <= SWIZZLE_W)
+ swiz[i] = SWIZZLE_X;
+ break;
+
+ case GL_ALPHA:
+ /* Rewrite reads from W to X, and reads from XYZ to 000. */
+ for (i = 0; i < 4; i++)
+ if (swiz[i] == SWIZZLE_W)
+ swiz[i] = SWIZZLE_X;
+ else if (swiz[i] < SWIZZLE_W)
+ swiz[i] = SWIZZLE_ZERO;
+ break;
+ case GL_RED:
+ /* Rewrite reads W to 1, XYZ to X00 */
+ for (i = 0; i < 4; i++)
+ if (swiz[i] == SWIZZLE_W)
+ swiz[i] = SWIZZLE_ONE;
+ else if (swiz[i] == SWIZZLE_Y || swiz[i] == SWIZZLE_Z)
+ swiz[i] = SWIZZLE_ZERO;
+ break;
+ }
+
+ return MAKE_SWIZZLE4(swiz[0], swiz[1], swiz[2], swiz[3]);
+}
+
+
+/**
+ * Return TRUE if the swizzling described by "swizzle" and
+ * "depthmode" (for depth textures only) is different from the swizzling
+ * set in the given sampler view.
+ *
+ * \param sv A sampler view.
+ * \param swizzle Texture swizzle, a bitmask computed using MAKE_SWIZZLE4.
+ * \param depthmode One of GL_LUMINANCE, GL_INTENSITY, GL_ALPHA.
+ */
+static boolean
+check_sampler_swizzle(struct pipe_sampler_view *sv,
+ GLuint swizzle, GLenum depthmode)
+{
+ swizzle = apply_depthmode(sv->texture->format, swizzle, depthmode);
+
+ if ((sv->swizzle_r != GET_SWZ(swizzle, 0)) ||
+ (sv->swizzle_g != GET_SWZ(swizzle, 1)) ||
+ (sv->swizzle_b != GET_SWZ(swizzle, 2)) ||
+ (sv->swizzle_a != GET_SWZ(swizzle, 3)))
+ return TRUE;
+ return FALSE;
+}
+
+
+static INLINE struct pipe_sampler_view *
+st_create_texture_sampler_view_from_stobj(struct pipe_context *pipe,
+ struct st_texture_object *stObj,
+ enum pipe_format format)
+{
+ struct pipe_sampler_view templ;
+ GLuint swizzle = apply_depthmode(stObj->pt->format,
+ stObj->base._Swizzle,
+ stObj->base.DepthMode);
+
+ u_sampler_view_default_template(&templ,
+ stObj->pt,
+ format);
+ templ.u.tex.first_level = stObj->base.BaseLevel;
+
+ if (swizzle != SWIZZLE_NOOP) {
+ templ.swizzle_r = GET_SWZ(swizzle, 0);
+ templ.swizzle_g = GET_SWZ(swizzle, 1);
+ templ.swizzle_b = GET_SWZ(swizzle, 2);
+ templ.swizzle_a = GET_SWZ(swizzle, 3);
+ }
+
+ return pipe->create_sampler_view(pipe, stObj->pt, &templ);
+}
+
+
+static INLINE struct pipe_sampler_view *
+st_get_texture_sampler_view_from_stobj(struct st_texture_object *stObj,
+ struct pipe_context *pipe,
+ enum pipe_format format)
+{
+ if (!stObj || !stObj->pt) {
+ return NULL;
+ }
+
+ if (!stObj->sampler_view) {
+ stObj->sampler_view =
+ st_create_texture_sampler_view_from_stobj(pipe, stObj, format);
+ }
+
+ return stObj->sampler_view;
+}
+
+
+static void
+update_textures(struct st_context *st)
+{
+ struct pipe_context *pipe = st->pipe;
+ struct gl_vertex_program *vprog = st->ctx->VertexProgram._Current;
+ struct gl_fragment_program *fprog = st->ctx->FragmentProgram._Current;
+ const GLbitfield samplersUsed = (vprog->Base.SamplersUsed |
+ fprog->Base.SamplersUsed);
+ GLuint su;
+
+ st->state.num_textures = 0;
+
+ /* loop over sampler units (aka tex image units) */
+ for (su = 0; su < st->ctx->Const.MaxTextureImageUnits; su++) {
+ struct pipe_sampler_view *sampler_view = NULL;
+ enum pipe_format st_view_format;
+ if (samplersUsed & (1 << su)) {
+ struct gl_texture_object *texObj;
+ struct st_texture_object *stObj;
+ GLboolean retval;
+ GLuint texUnit;
+
+ if (fprog->Base.SamplersUsed & (1 << su))
+ texUnit = fprog->Base.SamplerUnits[su];
+ else
+ texUnit = vprog->Base.SamplerUnits[su];
+
+ texObj = st->ctx->Texture.Unit[texUnit]._Current;
+
+ if (!texObj) {
+ texObj = st_get_default_texture(st);
+ }
+ stObj = st_texture_object(texObj);
+
+ retval = st_finalize_texture(st->ctx, st->pipe, texObj);
+ if (!retval) {
+ /* out of mem */
+ continue;
+ }
+
+ /* Determine the format of the texture sampler view */
+ st_view_format = stObj->pt->format;
+ {
+ const struct st_texture_image *firstImage =
+ st_texture_image(stObj->base.Image[0][stObj->base.BaseLevel]);
+ const gl_format texFormat = firstImage->base.TexFormat;
+ enum pipe_format firstImageFormat =
+ st_mesa_format_to_pipe_format(texFormat);
+
+ if ((stObj->base.sRGBDecode == GL_SKIP_DECODE_EXT) &&
+ (_mesa_get_format_color_encoding(texFormat) == GL_SRGB)) {
+ /* don't do sRGB->RGB conversion. Interpret the texture
+ * texture data as linear values.
+ */
+ const gl_format linearFormat =
+ _mesa_get_srgb_format_linear(texFormat);
+ firstImageFormat = st_mesa_format_to_pipe_format(linearFormat);
+ }
+
+ if (firstImageFormat != stObj->pt->format)
+ st_view_format = firstImageFormat;
+ }
+
+ st->state.num_textures = su + 1;
+
+ /* if sampler view has changed dereference it */
+ if (stObj->sampler_view)
+ if (check_sampler_swizzle(stObj->sampler_view,
+ stObj->base._Swizzle,
+ stObj->base.DepthMode) ||
+ (st_view_format != stObj->sampler_view->format) ||
+ stObj->base.BaseLevel != stObj->sampler_view->u.tex.first_level)
+ pipe_sampler_view_reference(&stObj->sampler_view, NULL);
+
+ sampler_view = st_get_texture_sampler_view_from_stobj(stObj, pipe, st_view_format);
+ }
+ pipe_sampler_view_reference(&st->state.sampler_views[su], sampler_view);
+ }
+
+ cso_set_fragment_sampler_views(st->cso_context,
+ st->state.num_textures,
+ st->state.sampler_views);
+ if (st->ctx->Const.MaxVertexTextureImageUnits > 0) {
+ cso_set_vertex_sampler_views(st->cso_context,
+ MIN2(st->state.num_textures,
+ st->ctx->Const.MaxVertexTextureImageUnits),
+ st->state.sampler_views);
+ }
+}
+
+
+const struct st_tracked_state st_update_texture = {
+ "st_update_texture", /* name */
+ { /* dirty */
+ _NEW_TEXTURE, /* mesa */
+ ST_NEW_FRAGMENT_PROGRAM, /* st */
+ },
+ update_textures /* update */
+};
+
+
+
+
+static void
+finalize_textures(struct st_context *st)
+{
+ struct gl_fragment_program *fprog = st->ctx->FragmentProgram._Current;
+ const GLboolean prev_missing_textures = st->missing_textures;
+ GLuint su;
+
+ st->missing_textures = GL_FALSE;
+
+ for (su = 0; su < st->ctx->Const.MaxTextureCoordUnits; su++) {
+ if (fprog->Base.SamplersUsed & (1 << su)) {
+ const GLuint texUnit = fprog->Base.SamplerUnits[su];
+ struct gl_texture_object *texObj
+ = st->ctx->Texture.Unit[texUnit]._Current;
+
+ if (texObj) {
+ GLboolean retval;
+
+ retval = st_finalize_texture(st->ctx, st->pipe, texObj);
+ if (!retval) {
+ /* out of mem */
+ st->missing_textures = GL_TRUE;
+ continue;
+ }
+ }
+ }
+ }
+
+ if (prev_missing_textures != st->missing_textures)
+ st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM;
+}
+
+
+
+const struct st_tracked_state st_finalize_textures = {
+ "st_finalize_textures", /* name */
+ { /* dirty */
+ _NEW_TEXTURE, /* mesa */
+ 0, /* st */
+ },
+ finalize_textures /* update */
+};
diff --git a/mesalib/src/mesa/state_tracker/st_context.c b/mesalib/src/mesa/state_tracker/st_context.c index afd85f0de..458968486 100644 --- a/mesalib/src/mesa/state_tracker/st_context.c +++ b/mesalib/src/mesa/state_tracker/st_context.c @@ -206,8 +206,8 @@ static void st_destroy_context_priv( struct st_context *st ) st_destroy_drawtex(st);
/* Unreference any user vertex buffers. */
- for (i = 0; i < st->num_user_vbs; i++) {
- pipe_resource_reference(&st->user_vb[i], NULL);
+ for (i = 0; i < st->num_user_attribs; i++) {
+ pipe_resource_reference(&st->user_attrib[i].buffer, NULL);
}
for (i = 0; i < Elements(st->state.sampler_views); i++) {
diff --git a/mesalib/src/mesa/state_tracker/st_context.h b/mesalib/src/mesa/state_tracker/st_context.h index ef54fd7cd..a35439741 100644 --- a/mesalib/src/mesa/state_tracker/st_context.h +++ b/mesalib/src/mesa/state_tracker/st_context.h @@ -187,9 +187,16 @@ struct st_context void *winsys_drawable_handle;
/* User vertex buffers. */
- struct pipe_resource *user_vb[PIPE_MAX_ATTRIBS];
- unsigned user_vb_stride[PIPE_MAX_ATTRIBS];
- unsigned num_user_vbs;
+ struct {
+ struct pipe_resource *buffer;
+
+ /** Element size */
+ GLuint element_size;
+
+ /** Attribute stride */
+ GLsizei stride;
+ } user_attrib[PIPE_MAX_ATTRIBS];
+ unsigned num_user_attribs;
};
diff --git a/mesalib/src/mesa/state_tracker/st_draw.c b/mesalib/src/mesa/state_tracker/st_draw.c index 52e46d628..61e127776 100644 --- a/mesalib/src/mesa/state_tracker/st_draw.c +++ b/mesalib/src/mesa/state_tracker/st_draw.c @@ -329,8 +329,12 @@ setup_interleaved_attribs(struct gl_context *ctx, const struct gl_client_array *array = arrays[mesaAttr];
struct gl_buffer_object *bufobj = array->BufferObj;
struct st_buffer_object *stobj = st_buffer_object(bufobj);
+ unsigned src_offset = (unsigned) (array->Ptr - low_addr);
+ GLuint element_size = array->_ElementSize;
GLsizei stride = array->StrideB;
+ assert(element_size == array->Size * _mesa_sizeof_type(array->Type));
+
if (attr == 0) {
if (bufobj && bufobj->Name) {
vbuffer->buffer = NULL;
@@ -339,22 +343,25 @@ setup_interleaved_attribs(struct gl_context *ctx, }
else {
uint divisor = array->InstanceDivisor;
- uint length = (divisor ? num_instances / divisor : max_index) + 1;
+ uint last_index = divisor ? num_instances / divisor : max_index;
+ uint bytes = src_offset + stride * last_index + element_size;
+
vbuffer->buffer = pipe_user_buffer_create(pipe->screen,
(void*) low_addr,
- stride * length,
+ bytes,
PIPE_BIND_VERTEX_BUFFER);
vbuffer->buffer_offset = 0;
/* Track user vertex buffers. */
- pipe_resource_reference(&st->user_vb[0], vbuffer->buffer);
- st->user_vb_stride[0] = stride;
- st->num_user_vbs = 1;
+ pipe_resource_reference(&st->user_attrib[0].buffer, vbuffer->buffer);
+ st->user_attrib[0].element_size = element_size;
+ st->user_attrib[0].stride = stride;
+ st->num_user_attribs = 1;
}
vbuffer->stride = stride; /* in bytes */
}
- velements[attr].src_offset = (unsigned) (array->Ptr - low_addr);
+ velements[attr].src_offset = src_offset;
velements[attr].instance_divisor = array->InstanceDivisor;
velements[attr].vertex_buffer_index = 0;
velements[attr].src_format = st_pipe_vertex_format(array->Type,
@@ -390,8 +397,11 @@ setup_non_interleaved_attribs(struct gl_context *ctx, const GLuint mesaAttr = vp->index_to_input[attr];
const struct gl_client_array *array = arrays[mesaAttr];
struct gl_buffer_object *bufobj = array->BufferObj;
+ GLuint element_size = array->_ElementSize;
GLsizei stride = array->StrideB;
+ assert(element_size == array->Size * _mesa_sizeof_type(array->Type));
+
if (bufobj && bufobj->Name) {
/* Attribute data is in a VBO.
* Recall that for VBOs, the gl_client_array->Ptr field is
@@ -410,20 +420,16 @@ setup_non_interleaved_attribs(struct gl_context *ctx, void *ptr;
if (array->Ptr) {
- if (stride == 0) {
- bytes = _mesa_sizeof_type(array->Type) * array->Size;
- }
- else {
- uint divisor = array->InstanceDivisor;
- uint length = (divisor ? num_instances / divisor : max_index) + 1;
- bytes = stride * length;
- }
+ uint divisor = array->InstanceDivisor;
+ uint last_index = divisor ? num_instances / divisor : max_index;
+
+ bytes = stride * last_index + element_size;
ptr = (void *) array->Ptr;
}
else {
/* no array, use ctx->Current.Attrib[] value */
- bytes = sizeof(ctx->Current.Attrib[0]);
+ bytes = element_size = sizeof(ctx->Current.Attrib[0]);
ptr = (void *) ctx->Current.Attrib[mesaAttr];
stride = 0;
}
@@ -438,9 +444,10 @@ setup_non_interleaved_attribs(struct gl_context *ctx, vbuffer[attr].buffer_offset = 0;
/* Track user vertex buffers. */
- pipe_resource_reference(&st->user_vb[attr], vbuffer[attr].buffer);
- st->user_vb_stride[attr] = stride;
- st->num_user_vbs = MAX2(st->num_user_vbs, attr+1);
+ pipe_resource_reference(&st->user_attrib[attr].buffer, vbuffer[attr].buffer);
+ st->user_attrib[attr].element_size = element_size;
+ st->user_attrib[attr].stride = stride;
+ st->num_user_attribs = MAX2(st->num_user_attribs, attr + 1);
}
/* common-case setup */
@@ -583,10 +590,10 @@ st_validate_varrays(struct gl_context *ctx, memset(velements, 0, sizeof(struct pipe_vertex_element) * vpv->num_inputs);
/* Unreference any user vertex buffers. */
- for (i = 0; i < st->num_user_vbs; i++) {
- pipe_resource_reference(&st->user_vb[i], NULL);
+ for (i = 0; i < st->num_user_attribs; i++) {
+ pipe_resource_reference(&st->user_attrib[i].buffer, NULL);
}
- st->num_user_vbs = 0;
+ st->num_user_attribs = 0;
/*
* Setup the vbuffer[] and velements[] arrays.
@@ -700,21 +707,20 @@ st_draw_vbo(struct gl_context *ctx, /* Notify the driver that the content of user buffers may have been
* changed. */
- if (!new_array && st->num_user_vbs) {
- for (i = 0; i < st->num_user_vbs; i++) {
- if (st->user_vb[i]) {
- unsigned stride = st->user_vb_stride[i];
-
- if (stride) {
- pipe->redefine_user_buffer(pipe, st->user_vb[i],
- min_index * stride,
- (max_index + 1 - min_index) * stride);
- }
- else {
- /* stride == 0 */
- pipe->redefine_user_buffer(pipe, st->user_vb[i],
- 0, st->user_vb[i]->width0);
- }
+ assert(max_index >= min_index);
+ if (!new_array && st->num_user_attribs) {
+ for (i = 0; i < st->num_user_attribs; i++) {
+ if (st->user_attrib[i].buffer) {
+ unsigned element_size = st->user_attrib[i].element_size;
+ unsigned stride = st->user_attrib[i].stride;
+ unsigned min_offset = min_index * stride;
+ unsigned max_offset = max_index * stride + element_size;
+
+ assert(max_offset > min_offset);
+
+ pipe->redefine_user_buffer(pipe, st->user_attrib[i].buffer,
+ min_offset,
+ max_offset - min_offset);
}
}
}
diff --git a/mesalib/src/mesa/state_tracker/st_draw.h b/mesalib/src/mesa/state_tracker/st_draw.h index 6c8b78c76..23e1c7821 100644 --- a/mesalib/src/mesa/state_tracker/st_draw.h +++ b/mesalib/src/mesa/state_tracker/st_draw.h @@ -69,7 +69,7 @@ st_feedback_draw_vbo(struct gl_context *ctx, /* Internal function:
*/
-extern GLuint
+extern enum pipe_format
st_pipe_vertex_format(GLenum type, GLuint size, GLenum format,
GLboolean normalized);
diff --git a/mesalib/src/mesa/state_tracker/st_draw_feedback.c b/mesalib/src/mesa/state_tracker/st_draw_feedback.c index f0734eae0..bbf2ef67e 100644 --- a/mesalib/src/mesa/state_tracker/st_draw_feedback.c +++ b/mesalib/src/mesa/state_tracker/st_draw_feedback.c @@ -111,6 +111,7 @@ st_feedback_draw_vbo(struct gl_context *ctx, struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS];
struct pipe_transfer *ib_transfer = NULL;
GLuint attr, i;
+ const GLubyte *low_addr = NULL;
const void *mapped_indices = NULL;
assert(draw);
@@ -141,6 +142,16 @@ st_feedback_draw_vbo(struct gl_context *ctx, draw_bind_vertex_shader(draw, st->vp_variant->draw_shader);
set_feedback_vertex_format(ctx);
+ /* Find the lowest address of the arrays we're drawing */
+ if (vp->num_inputs) {
+ low_addr = arrays[vp->index_to_input[0]]->Ptr;
+
+ for (attr = 1; attr < vp->num_inputs; attr++) {
+ const GLubyte *start = arrays[vp->index_to_input[attr]]->Ptr;
+ low_addr = MIN2(low_addr, start);
+ }
+ }
+
/* loop over TGSI shader inputs to determine vertex buffer
* and attribute info
*/
@@ -159,8 +170,8 @@ st_feedback_draw_vbo(struct gl_context *ctx, vbuffers[attr].buffer = NULL;
pipe_resource_reference(&vbuffers[attr].buffer, stobj->buffer);
- vbuffers[attr].buffer_offset = pointer_to_offset(arrays[0]->Ptr);
- velements[attr].src_offset = arrays[mesaAttr]->Ptr - arrays[0]->Ptr;
+ vbuffers[attr].buffer_offset = pointer_to_offset(low_addr);
+ velements[attr].src_offset = arrays[mesaAttr]->Ptr - low_addr;
}
else {
/* attribute data is in user-space memory, not a VBO */
diff --git a/mesalib/src/mesa/vbo/vbo_context.c b/mesalib/src/mesa/vbo/vbo_context.c index bbf422f74..5f03ce547 100644 --- a/mesalib/src/mesa/vbo/vbo_context.c +++ b/mesalib/src/mesa/vbo/vbo_context.c @@ -72,6 +72,7 @@ static void init_legacy_currval(struct gl_context *ctx) cl->Type = GL_FLOAT;
cl->Format = GL_RGBA;
cl->Ptr = (const void *)ctx->Current.Attrib[i];
+ cl->_ElementSize = cl->Size * sizeof(GLfloat);
_mesa_reference_buffer_object(ctx, &cl->BufferObj,
ctx->Shared->NullBufferObj);
}
@@ -98,6 +99,7 @@ static void init_generic_currval(struct gl_context *ctx) cl->Stride = 0;
cl->StrideB = 0;
cl->Enabled = 1;
+ cl->_ElementSize = cl->Size * sizeof(GLfloat);
_mesa_reference_buffer_object(ctx, &cl->BufferObj,
ctx->Shared->NullBufferObj);
}
@@ -143,6 +145,7 @@ static void init_mat_currval(struct gl_context *ctx) cl->Stride = 0;
cl->StrideB = 0;
cl->Enabled = 1;
+ cl->_ElementSize = cl->Size * sizeof(GLfloat);
_mesa_reference_buffer_object(ctx, &cl->BufferObj,
ctx->Shared->NullBufferObj);
}
diff --git a/mesalib/src/mesa/vbo/vbo_exec_api.c b/mesalib/src/mesa/vbo/vbo_exec_api.c index 790310903..6b919e8b4 100644 --- a/mesalib/src/mesa/vbo/vbo_exec_api.c +++ b/mesalib/src/mesa/vbo/vbo_exec_api.c @@ -168,6 +168,8 @@ static void vbo_exec_copy_to_current( struct vbo_exec_context *exec ) * directly.
*/
vbo->currval[i].Size = exec->vtx.attrsz[i];
+ assert(vbo->currval[i].Type == GL_FLOAT);
+ vbo->currval[i]._ElementSize = vbo->currval[i].Size * sizeof(GLfloat);
/* This triggers rather too much recalculation of Mesa state
* that doesn't get used (eg light positions).
diff --git a/mesalib/src/mesa/vbo/vbo_exec_array.c b/mesalib/src/mesa/vbo/vbo_exec_array.c index 37656c23a..a189ab76b 100644 --- a/mesalib/src/mesa/vbo/vbo_exec_array.c +++ b/mesalib/src/mesa/vbo/vbo_exec_array.c @@ -943,8 +943,13 @@ vbo_exec_DrawRangeElementsBaseVertex(GLenum mode, /* Set 'end' to the max possible legal value */
assert(ctx->Array.ArrayObj->_MaxElement >= 1);
end = ctx->Array.ArrayObj->_MaxElement - 1;
+
+ if (end < start) {
+ return;
+ }
}
- else if (0) {
+
+ if (0) {
printf("glDraw[Range]Elements{,BaseVertex}"
"(start %u, end %u, type 0x%x, count %d) ElemBuf %u, "
"base %d\n",
diff --git a/mesalib/src/mesa/vbo/vbo_exec_draw.c b/mesalib/src/mesa/vbo/vbo_exec_draw.c index 7cc843779..98f585792 100644 --- a/mesalib/src/mesa/vbo/vbo_exec_draw.c +++ b/mesalib/src/mesa/vbo/vbo_exec_draw.c @@ -239,6 +239,7 @@ vbo_exec_bind_arrays( struct gl_context *ctx ) arrays[attr].Type = GL_FLOAT;
arrays[attr].Format = GL_RGBA;
arrays[attr].Enabled = 1;
+ arrays[attr]._ElementSize = arrays[attr].Size * sizeof(GLfloat);
_mesa_reference_buffer_object(ctx,
&arrays[attr].BufferObj,
exec->vtx.bufferobj);
diff --git a/mesalib/src/mesa/vbo/vbo_save_draw.c b/mesalib/src/mesa/vbo/vbo_save_draw.c index 5a19b0d62..d0f627a35 100644 --- a/mesalib/src/mesa/vbo/vbo_save_draw.c +++ b/mesalib/src/mesa/vbo/vbo_save_draw.c @@ -90,6 +90,8 @@ _playback_copy_to_current(struct gl_context *ctx, memcpy(current, tmp, 4 * sizeof(GLfloat));
vbo->currval[i].Size = node->attrsz[i];
+ assert(vbo->currval[i].Type == GL_FLOAT);
+ vbo->currval[i]._ElementSize = vbo->currval[i].Size * sizeof(GLfloat);
if (i >= VBO_ATTRIB_FIRST_MATERIAL &&
i <= VBO_ATTRIB_LAST_MATERIAL)
@@ -193,6 +195,7 @@ static void vbo_bind_vertex_list(struct gl_context *ctx, arrays[attr].Type = GL_FLOAT;
arrays[attr].Format = GL_RGBA;
arrays[attr].Enabled = 1;
+ arrays[attr]._ElementSize = arrays[attr].Size * sizeof(GLfloat);
_mesa_reference_buffer_object(ctx,
&arrays[attr].BufferObj,
node->vertex_store->bufferobj);
diff --git a/mesalib/src/mesa/vbo/vbo_split_copy.c b/mesalib/src/mesa/vbo/vbo_split_copy.c index 8c981f93e..3a869d712 100644 --- a/mesalib/src/mesa/vbo/vbo_split_copy.c +++ b/mesalib/src/mesa/vbo/vbo_split_copy.c @@ -1,626 +1,627 @@ - -/* - * Mesa 3-D graphics library - * Version: 6.5 - * - * 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"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * 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. - * - * Authors: - * Keith Whitwell <keith@tungstengraphics.com> - */ - -/* Split indexed primitives with per-vertex copying. - */ - -#include "main/glheader.h" -#include "main/bufferobj.h" -#include "main/imports.h" -#include "main/image.h" -#include "main/macros.h" -#include "main/mtypes.h" - -#include "vbo_split.h" -#include "vbo.h" - - -#define ELT_TABLE_SIZE 16 - -/** - * Used for vertex-level splitting of indexed buffers. Note that - * non-indexed primitives may be converted to indexed in some cases - * (eg loops, fans) in order to use this splitting path. - */ -struct copy_context { - - struct gl_context *ctx; - const struct gl_client_array **array; - const struct _mesa_prim *prim; - GLuint nr_prims; - const struct _mesa_index_buffer *ib; - vbo_draw_func draw; - - const struct split_limits *limits; - - struct { - GLuint attr; - GLuint size; - const struct gl_client_array *array; - const GLubyte *src_ptr; - - struct gl_client_array dstarray; - - } varying[VERT_ATTRIB_MAX]; - GLuint nr_varying; - - const struct gl_client_array *dstarray_ptr[VERT_ATTRIB_MAX]; - struct _mesa_index_buffer dstib; - - GLuint *translated_elt_buf; - const GLuint *srcelt; - - /** A baby hash table to avoid re-emitting (some) duplicate - * vertices when splitting indexed primitives. - */ - struct { - GLuint in; - GLuint out; - } vert_cache[ELT_TABLE_SIZE]; - - GLuint vertex_size; - GLubyte *dstbuf; - GLubyte *dstptr; /**< dstptr == dstbuf + dstelt_max * vertsize */ - GLuint dstbuf_size; /**< in vertices */ - GLuint dstbuf_nr; /**< count of emitted vertices, also the largest value - * in dstelt. Our MaxIndex. - */ - - GLuint *dstelt; - GLuint dstelt_nr; - GLuint dstelt_size; - -#define MAX_PRIM 32 - struct _mesa_prim dstprim[MAX_PRIM]; - GLuint dstprim_nr; - -}; - - -static GLuint attr_size( const struct gl_client_array *array ) -{ - return array->Size * _mesa_sizeof_type(array->Type); -} - - -/** - * Starts returning true slightly before the buffer fills, to ensure - * that there is sufficient room for any remaining vertices to finish - * off the prim: - */ -static GLboolean -check_flush( struct copy_context *copy ) -{ - GLenum mode = copy->dstprim[copy->dstprim_nr].mode; - - if (GL_TRIANGLE_STRIP == mode && - copy->dstelt_nr & 1) { /* see bug9962 */ - return GL_FALSE; - } - - if (copy->dstbuf_nr + 4 > copy->dstbuf_size) - return GL_TRUE; - - if (copy->dstelt_nr + 4 > copy->dstelt_size) - return GL_TRUE; - - return GL_FALSE; -} - - -/** - * Dump the parameters/info for a vbo->draw() call. - */ -static void -dump_draw_info(struct gl_context *ctx, - const struct gl_client_array **arrays, - const struct _mesa_prim *prims, - GLuint nr_prims, - const struct _mesa_index_buffer *ib, - GLuint min_index, - GLuint max_index) -{ - GLuint i, j; - - printf("VBO Draw:\n"); - for (i = 0; i < nr_prims; i++) { - printf("Prim %u of %u\n", i, nr_prims); - printf(" Prim mode 0x%x\n", prims[i].mode); - printf(" IB: %p\n", (void*) ib); - for (j = 0; j < VERT_ATTRIB_MAX; j++) { - printf(" array %d at %p:\n", j, (void*) arrays[j]); - printf(" enabled %d, ptr %p, size %d, type 0x%x, stride %d\n", - arrays[j]->Enabled, arrays[j]->Ptr, - arrays[j]->Size, arrays[j]->Type, arrays[j]->StrideB); - if (0) { - GLint k = prims[i].start + prims[i].count - 1; - GLfloat *last = (GLfloat *) (arrays[j]->Ptr + arrays[j]->Stride * k); - printf(" last: %f %f %f\n", - last[0], last[1], last[2]); - } - } - } -} - - -static void -flush( struct copy_context *copy ) -{ - GLuint i; - - /* Set some counters: - */ - copy->dstib.count = copy->dstelt_nr; - -#if 0 - dump_draw_info(copy->ctx, - copy->dstarray_ptr, - copy->dstprim, - copy->dstprim_nr, - ©->dstib, - 0, - copy->dstbuf_nr); -#else - (void) dump_draw_info; -#endif - - copy->draw( copy->ctx, - copy->dstarray_ptr, - copy->dstprim, - copy->dstprim_nr, - ©->dstib, - GL_TRUE, - 0, - copy->dstbuf_nr - 1 ); - - /* Reset all pointers: - */ - copy->dstprim_nr = 0; - copy->dstelt_nr = 0; - copy->dstbuf_nr = 0; - copy->dstptr = copy->dstbuf; - - /* Clear the vertex cache: - */ - for (i = 0; i < ELT_TABLE_SIZE; i++) - copy->vert_cache[i].in = ~0; -} - - -/** - * Called at begin of each primitive during replay. - */ -static void -begin( struct copy_context *copy, GLenum mode, GLboolean begin_flag ) -{ - struct _mesa_prim *prim = ©->dstprim[copy->dstprim_nr]; - - prim->mode = mode; - prim->begin = begin_flag; - prim->num_instances = 1; -} - - -/** - * Use a hashtable to attempt to identify recently-emitted vertices - * and avoid re-emitting them. - */ -static GLuint -elt(struct copy_context *copy, GLuint elt_idx) -{ - GLuint elt = copy->srcelt[elt_idx]; - GLuint slot = elt & (ELT_TABLE_SIZE-1); - -/* printf("elt %d\n", elt); */ - - /* Look up the incoming element in the vertex cache. Re-emit if - * necessary. - */ - if (copy->vert_cache[slot].in != elt) { - GLubyte *csr = copy->dstptr; - GLuint i; - -/* printf(" --> emit to dstelt %d\n", copy->dstbuf_nr); */ - - for (i = 0; i < copy->nr_varying; i++) { - const struct gl_client_array *srcarray = copy->varying[i].array; - const GLubyte *srcptr = copy->varying[i].src_ptr + elt * srcarray->StrideB; - - memcpy(csr, srcptr, copy->varying[i].size); - csr += copy->varying[i].size; - -#ifdef NAN_CHECK - if (srcarray->Type == GL_FLOAT) { - GLuint k; - GLfloat *f = (GLfloat *) srcptr; - for (k = 0; k < srcarray->Size; k++) { - assert(!IS_INF_OR_NAN(f[k])); - assert(f[k] <= 1.0e20 && f[k] >= -1.0e20); - } - } -#endif - - if (0) - { - const GLuint *f = (const GLuint *)srcptr; - GLuint j; - printf(" varying %d: ", i); - for(j = 0; j < copy->varying[i].size / 4; j++) - printf("%x ", f[j]); - printf("\n"); - } - } - - copy->vert_cache[slot].in = elt; - copy->vert_cache[slot].out = copy->dstbuf_nr++; - copy->dstptr += copy->vertex_size; - - assert(csr == copy->dstptr); - assert(copy->dstptr == (copy->dstbuf + - copy->dstbuf_nr * copy->vertex_size)); - } -/* else */ -/* printf(" --> reuse vertex\n"); */ - -/* printf(" --> emit %d\n", copy->vert_cache[slot].out); */ - copy->dstelt[copy->dstelt_nr++] = copy->vert_cache[slot].out; - return check_flush(copy); -} - - -/** - * Called at end of each primitive during replay. - */ -static void -end( struct copy_context *copy, GLboolean end_flag ) -{ - struct _mesa_prim *prim = ©->dstprim[copy->dstprim_nr]; - -/* printf("end (%d)\n", end_flag); */ - - prim->end = end_flag; - prim->count = copy->dstelt_nr - prim->start; - - if (++copy->dstprim_nr == MAX_PRIM || - check_flush(copy)) - flush(copy); -} - - -static void -replay_elts( struct copy_context *copy ) -{ - GLuint i, j, k; - GLboolean split; - - for (i = 0; i < copy->nr_prims; i++) { - const struct _mesa_prim *prim = ©->prim[i]; - const GLuint start = prim->start; - GLuint first, incr; - - switch (prim->mode) { - - case GL_LINE_LOOP: - /* Convert to linestrip and emit the final vertex explicitly, - * but only in the resultant strip that requires it. - */ - j = 0; - while (j != prim->count) { - begin(copy, GL_LINE_STRIP, prim->begin && j == 0); - - for (split = GL_FALSE; j != prim->count && !split; j++) - split = elt(copy, start + j); - - if (j == prim->count) { - /* Done, emit final line. Split doesn't matter as - * it is always raised a bit early so we can emit - * the last verts if necessary! - */ - if (prim->end) - (void)elt(copy, start + 0); - - end(copy, prim->end); - } - else { - /* Wrap - */ - assert(split); - end(copy, 0); - j--; - } - } - break; - - case GL_TRIANGLE_FAN: - case GL_POLYGON: - j = 2; - while (j != prim->count) { - begin(copy, prim->mode, prim->begin && j == 0); - - split = elt(copy, start+0); - assert(!split); - - split = elt(copy, start+j-1); - assert(!split); - - for (; j != prim->count && !split; j++) - split = elt(copy, start+j); - - end(copy, prim->end && j == prim->count); - - if (j != prim->count) { - /* Wrapped the primitive, need to repeat some vertices: - */ - j -= 1; - } - } - break; - - default: - (void)split_prim_inplace(prim->mode, &first, &incr); - - j = 0; - while (j != prim->count) { - - begin(copy, prim->mode, prim->begin && j == 0); - - split = 0; - for (k = 0; k < first; k++, j++) - split |= elt(copy, start+j); - - assert(!split); - - for (; j != prim->count && !split; ) - for (k = 0; k < incr; k++, j++) - split |= elt(copy, start+j); - - end(copy, prim->end && j == prim->count); - - if (j != prim->count) { - /* Wrapped the primitive, need to repeat some vertices: - */ - assert(j > first - incr); - j -= (first - incr); - } - } - break; - } - } - - if (copy->dstprim_nr) - flush(copy); -} - - -static void -replay_init( struct copy_context *copy ) -{ - struct gl_context *ctx = copy->ctx; - GLuint i; - GLuint offset; - const GLvoid *srcptr; - - /* Make a list of varying attributes and their vbo's. Also - * calculate vertex size. - */ - copy->vertex_size = 0; - for (i = 0; i < VERT_ATTRIB_MAX; i++) { - struct gl_buffer_object *vbo = copy->array[i]->BufferObj; - - if (copy->array[i]->StrideB == 0) { - copy->dstarray_ptr[i] = copy->array[i]; - } - else { - GLuint j = copy->nr_varying++; - - copy->varying[j].attr = i; - copy->varying[j].array = copy->array[i]; - copy->varying[j].size = attr_size(copy->array[i]); - copy->vertex_size += attr_size(copy->array[i]); - - if (_mesa_is_bufferobj(vbo) && !_mesa_bufferobj_mapped(vbo)) - ctx->Driver.MapBuffer(ctx, GL_ARRAY_BUFFER, GL_READ_ONLY, vbo); - - copy->varying[j].src_ptr = ADD_POINTERS(vbo->Pointer, - copy->array[i]->Ptr); - - copy->dstarray_ptr[i] = ©->varying[j].dstarray; - } - } - - /* There must always be an index buffer. Currently require the - * caller convert non-indexed prims to indexed. Could alternately - * do it internally. - */ - if (_mesa_is_bufferobj(copy->ib->obj) && - !_mesa_bufferobj_mapped(copy->ib->obj)) - ctx->Driver.MapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER, GL_READ_ONLY, - copy->ib->obj); - - srcptr = (const GLubyte *) ADD_POINTERS(copy->ib->obj->Pointer, - copy->ib->ptr); - - switch (copy->ib->type) { - case GL_UNSIGNED_BYTE: - copy->translated_elt_buf = malloc(sizeof(GLuint) * copy->ib->count); - copy->srcelt = copy->translated_elt_buf; - - for (i = 0; i < copy->ib->count; i++) - copy->translated_elt_buf[i] = ((const GLubyte *)srcptr)[i]; - break; - - case GL_UNSIGNED_SHORT: - copy->translated_elt_buf = malloc(sizeof(GLuint) * copy->ib->count); - copy->srcelt = copy->translated_elt_buf; - - for (i = 0; i < copy->ib->count; i++) - copy->translated_elt_buf[i] = ((const GLushort *)srcptr)[i]; - break; - - case GL_UNSIGNED_INT: - copy->translated_elt_buf = NULL; - copy->srcelt = (const GLuint *)srcptr; - break; - } - - /* Figure out the maximum allowed vertex buffer size: - */ - if (copy->vertex_size * copy->limits->max_verts <= copy->limits->max_vb_size) { - copy->dstbuf_size = copy->limits->max_verts; - } - else { - copy->dstbuf_size = copy->limits->max_vb_size / copy->vertex_size; - } - - /* Allocate an output vertex buffer: - * - * XXX: This should be a VBO! - */ - copy->dstbuf = malloc(copy->dstbuf_size * copy->vertex_size); - copy->dstptr = copy->dstbuf; - - /* Setup new vertex arrays to point into the output buffer: - */ - for (offset = 0, i = 0; i < copy->nr_varying; i++) { - const struct gl_client_array *src = copy->varying[i].array; - struct gl_client_array *dst = ©->varying[i].dstarray; - - dst->Size = src->Size; - dst->Type = src->Type; - dst->Format = GL_RGBA; - dst->Stride = copy->vertex_size; - dst->StrideB = copy->vertex_size; - dst->Ptr = copy->dstbuf + offset; - dst->Enabled = GL_TRUE; - dst->Normalized = src->Normalized; - dst->BufferObj = ctx->Shared->NullBufferObj; - dst->_MaxElement = copy->dstbuf_size; /* may be less! */ - - offset += copy->varying[i].size; - } - - /* Allocate an output element list: - */ - copy->dstelt_size = MIN2(65536, - copy->ib->count * 2 + 3); - copy->dstelt_size = MIN2(copy->dstelt_size, - copy->limits->max_indices); - copy->dstelt = malloc(sizeof(GLuint) * copy->dstelt_size); - copy->dstelt_nr = 0; - - /* Setup the new index buffer to point to the allocated element - * list: - */ - copy->dstib.count = 0; /* duplicates dstelt_nr */ - copy->dstib.type = GL_UNSIGNED_INT; - copy->dstib.obj = ctx->Shared->NullBufferObj; - copy->dstib.ptr = copy->dstelt; -} - - -/** - * Free up everything allocated during split/replay. - */ -static void -replay_finish( struct copy_context *copy ) -{ - struct gl_context *ctx = copy->ctx; - GLuint i; - - /* Free our vertex and index buffers: - */ - free(copy->translated_elt_buf); - free(copy->dstbuf); - free(copy->dstelt); - - /* Unmap VBO's - */ - for (i = 0; i < copy->nr_varying; i++) { - struct gl_buffer_object *vbo = copy->varying[i].array->BufferObj; - if (_mesa_is_bufferobj(vbo) && _mesa_bufferobj_mapped(vbo)) - ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER, vbo); - } - - /* Unmap index buffer: - */ - if (_mesa_is_bufferobj(copy->ib->obj) && - _mesa_bufferobj_mapped(copy->ib->obj)) { - ctx->Driver.UnmapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER, copy->ib->obj); - } -} - - -/** - * Split VBO into smaller pieces, draw the pieces. - */ -void vbo_split_copy( struct gl_context *ctx, - const struct gl_client_array *arrays[], - const struct _mesa_prim *prim, - GLuint nr_prims, - const struct _mesa_index_buffer *ib, - vbo_draw_func draw, - const struct split_limits *limits ) -{ - struct copy_context copy; - GLuint i, this_nr_prims; - - for (i = 0; i < nr_prims;) { - /* Our SW TNL pipeline doesn't handle basevertex yet, so bind_indices - * will rebase the elements to the basevertex, and we'll only - * emit strings of prims with the same basevertex in one draw call. - */ - for (this_nr_prims = 1; i + this_nr_prims < nr_prims; - this_nr_prims++) { - if (prim[i].basevertex != prim[i + this_nr_prims].basevertex) - break; - } - - memset(©, 0, sizeof(copy)); - - /* Require indexed primitives: - */ - assert(ib); - - copy.ctx = ctx; - copy.array = arrays; - copy.prim = &prim[i]; - copy.nr_prims = this_nr_prims; - copy.ib = ib; - copy.draw = draw; - copy.limits = limits; - - /* Clear the vertex cache: - */ - for (i = 0; i < ELT_TABLE_SIZE; i++) - copy.vert_cache[i].in = ~0; - - replay_init(©); - replay_elts(©); - replay_finish(©); - } -} +
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * 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"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * 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.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+/* Split indexed primitives with per-vertex copying.
+ */
+
+#include "main/glheader.h"
+#include "main/bufferobj.h"
+#include "main/imports.h"
+#include "main/image.h"
+#include "main/macros.h"
+#include "main/mtypes.h"
+
+#include "vbo_split.h"
+#include "vbo.h"
+
+
+#define ELT_TABLE_SIZE 16
+
+/**
+ * Used for vertex-level splitting of indexed buffers. Note that
+ * non-indexed primitives may be converted to indexed in some cases
+ * (eg loops, fans) in order to use this splitting path.
+ */
+struct copy_context {
+
+ struct gl_context *ctx;
+ const struct gl_client_array **array;
+ const struct _mesa_prim *prim;
+ GLuint nr_prims;
+ const struct _mesa_index_buffer *ib;
+ vbo_draw_func draw;
+
+ const struct split_limits *limits;
+
+ struct {
+ GLuint attr;
+ GLuint size;
+ const struct gl_client_array *array;
+ const GLubyte *src_ptr;
+
+ struct gl_client_array dstarray;
+
+ } varying[VERT_ATTRIB_MAX];
+ GLuint nr_varying;
+
+ const struct gl_client_array *dstarray_ptr[VERT_ATTRIB_MAX];
+ struct _mesa_index_buffer dstib;
+
+ GLuint *translated_elt_buf;
+ const GLuint *srcelt;
+
+ /** A baby hash table to avoid re-emitting (some) duplicate
+ * vertices when splitting indexed primitives.
+ */
+ struct {
+ GLuint in;
+ GLuint out;
+ } vert_cache[ELT_TABLE_SIZE];
+
+ GLuint vertex_size;
+ GLubyte *dstbuf;
+ GLubyte *dstptr; /**< dstptr == dstbuf + dstelt_max * vertsize */
+ GLuint dstbuf_size; /**< in vertices */
+ GLuint dstbuf_nr; /**< count of emitted vertices, also the largest value
+ * in dstelt. Our MaxIndex.
+ */
+
+ GLuint *dstelt;
+ GLuint dstelt_nr;
+ GLuint dstelt_size;
+
+#define MAX_PRIM 32
+ struct _mesa_prim dstprim[MAX_PRIM];
+ GLuint dstprim_nr;
+
+};
+
+
+static GLuint attr_size( const struct gl_client_array *array )
+{
+ return array->Size * _mesa_sizeof_type(array->Type);
+}
+
+
+/**
+ * Starts returning true slightly before the buffer fills, to ensure
+ * that there is sufficient room for any remaining vertices to finish
+ * off the prim:
+ */
+static GLboolean
+check_flush( struct copy_context *copy )
+{
+ GLenum mode = copy->dstprim[copy->dstprim_nr].mode;
+
+ if (GL_TRIANGLE_STRIP == mode &&
+ copy->dstelt_nr & 1) { /* see bug9962 */
+ return GL_FALSE;
+ }
+
+ if (copy->dstbuf_nr + 4 > copy->dstbuf_size)
+ return GL_TRUE;
+
+ if (copy->dstelt_nr + 4 > copy->dstelt_size)
+ return GL_TRUE;
+
+ return GL_FALSE;
+}
+
+
+/**
+ * Dump the parameters/info for a vbo->draw() call.
+ */
+static void
+dump_draw_info(struct gl_context *ctx,
+ const struct gl_client_array **arrays,
+ const struct _mesa_prim *prims,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ GLuint min_index,
+ GLuint max_index)
+{
+ GLuint i, j;
+
+ printf("VBO Draw:\n");
+ for (i = 0; i < nr_prims; i++) {
+ printf("Prim %u of %u\n", i, nr_prims);
+ printf(" Prim mode 0x%x\n", prims[i].mode);
+ printf(" IB: %p\n", (void*) ib);
+ for (j = 0; j < VERT_ATTRIB_MAX; j++) {
+ printf(" array %d at %p:\n", j, (void*) arrays[j]);
+ printf(" enabled %d, ptr %p, size %d, type 0x%x, stride %d\n",
+ arrays[j]->Enabled, arrays[j]->Ptr,
+ arrays[j]->Size, arrays[j]->Type, arrays[j]->StrideB);
+ if (0) {
+ GLint k = prims[i].start + prims[i].count - 1;
+ GLfloat *last = (GLfloat *) (arrays[j]->Ptr + arrays[j]->Stride * k);
+ printf(" last: %f %f %f\n",
+ last[0], last[1], last[2]);
+ }
+ }
+ }
+}
+
+
+static void
+flush( struct copy_context *copy )
+{
+ GLuint i;
+
+ /* Set some counters:
+ */
+ copy->dstib.count = copy->dstelt_nr;
+
+#if 0
+ dump_draw_info(copy->ctx,
+ copy->dstarray_ptr,
+ copy->dstprim,
+ copy->dstprim_nr,
+ ©->dstib,
+ 0,
+ copy->dstbuf_nr);
+#else
+ (void) dump_draw_info;
+#endif
+
+ copy->draw( copy->ctx,
+ copy->dstarray_ptr,
+ copy->dstprim,
+ copy->dstprim_nr,
+ ©->dstib,
+ GL_TRUE,
+ 0,
+ copy->dstbuf_nr - 1 );
+
+ /* Reset all pointers:
+ */
+ copy->dstprim_nr = 0;
+ copy->dstelt_nr = 0;
+ copy->dstbuf_nr = 0;
+ copy->dstptr = copy->dstbuf;
+
+ /* Clear the vertex cache:
+ */
+ for (i = 0; i < ELT_TABLE_SIZE; i++)
+ copy->vert_cache[i].in = ~0;
+}
+
+
+/**
+ * Called at begin of each primitive during replay.
+ */
+static void
+begin( struct copy_context *copy, GLenum mode, GLboolean begin_flag )
+{
+ struct _mesa_prim *prim = ©->dstprim[copy->dstprim_nr];
+
+ prim->mode = mode;
+ prim->begin = begin_flag;
+ prim->num_instances = 1;
+}
+
+
+/**
+ * Use a hashtable to attempt to identify recently-emitted vertices
+ * and avoid re-emitting them.
+ */
+static GLuint
+elt(struct copy_context *copy, GLuint elt_idx)
+{
+ GLuint elt = copy->srcelt[elt_idx];
+ GLuint slot = elt & (ELT_TABLE_SIZE-1);
+
+/* printf("elt %d\n", elt); */
+
+ /* Look up the incoming element in the vertex cache. Re-emit if
+ * necessary.
+ */
+ if (copy->vert_cache[slot].in != elt) {
+ GLubyte *csr = copy->dstptr;
+ GLuint i;
+
+/* printf(" --> emit to dstelt %d\n", copy->dstbuf_nr); */
+
+ for (i = 0; i < copy->nr_varying; i++) {
+ const struct gl_client_array *srcarray = copy->varying[i].array;
+ const GLubyte *srcptr = copy->varying[i].src_ptr + elt * srcarray->StrideB;
+
+ memcpy(csr, srcptr, copy->varying[i].size);
+ csr += copy->varying[i].size;
+
+#ifdef NAN_CHECK
+ if (srcarray->Type == GL_FLOAT) {
+ GLuint k;
+ GLfloat *f = (GLfloat *) srcptr;
+ for (k = 0; k < srcarray->Size; k++) {
+ assert(!IS_INF_OR_NAN(f[k]));
+ assert(f[k] <= 1.0e20 && f[k] >= -1.0e20);
+ }
+ }
+#endif
+
+ if (0)
+ {
+ const GLuint *f = (const GLuint *)srcptr;
+ GLuint j;
+ printf(" varying %d: ", i);
+ for(j = 0; j < copy->varying[i].size / 4; j++)
+ printf("%x ", f[j]);
+ printf("\n");
+ }
+ }
+
+ copy->vert_cache[slot].in = elt;
+ copy->vert_cache[slot].out = copy->dstbuf_nr++;
+ copy->dstptr += copy->vertex_size;
+
+ assert(csr == copy->dstptr);
+ assert(copy->dstptr == (copy->dstbuf +
+ copy->dstbuf_nr * copy->vertex_size));
+ }
+/* else */
+/* printf(" --> reuse vertex\n"); */
+
+/* printf(" --> emit %d\n", copy->vert_cache[slot].out); */
+ copy->dstelt[copy->dstelt_nr++] = copy->vert_cache[slot].out;
+ return check_flush(copy);
+}
+
+
+/**
+ * Called at end of each primitive during replay.
+ */
+static void
+end( struct copy_context *copy, GLboolean end_flag )
+{
+ struct _mesa_prim *prim = ©->dstprim[copy->dstprim_nr];
+
+/* printf("end (%d)\n", end_flag); */
+
+ prim->end = end_flag;
+ prim->count = copy->dstelt_nr - prim->start;
+
+ if (++copy->dstprim_nr == MAX_PRIM ||
+ check_flush(copy))
+ flush(copy);
+}
+
+
+static void
+replay_elts( struct copy_context *copy )
+{
+ GLuint i, j, k;
+ GLboolean split;
+
+ for (i = 0; i < copy->nr_prims; i++) {
+ const struct _mesa_prim *prim = ©->prim[i];
+ const GLuint start = prim->start;
+ GLuint first, incr;
+
+ switch (prim->mode) {
+
+ case GL_LINE_LOOP:
+ /* Convert to linestrip and emit the final vertex explicitly,
+ * but only in the resultant strip that requires it.
+ */
+ j = 0;
+ while (j != prim->count) {
+ begin(copy, GL_LINE_STRIP, prim->begin && j == 0);
+
+ for (split = GL_FALSE; j != prim->count && !split; j++)
+ split = elt(copy, start + j);
+
+ if (j == prim->count) {
+ /* Done, emit final line. Split doesn't matter as
+ * it is always raised a bit early so we can emit
+ * the last verts if necessary!
+ */
+ if (prim->end)
+ (void)elt(copy, start + 0);
+
+ end(copy, prim->end);
+ }
+ else {
+ /* Wrap
+ */
+ assert(split);
+ end(copy, 0);
+ j--;
+ }
+ }
+ break;
+
+ case GL_TRIANGLE_FAN:
+ case GL_POLYGON:
+ j = 2;
+ while (j != prim->count) {
+ begin(copy, prim->mode, prim->begin && j == 0);
+
+ split = elt(copy, start+0);
+ assert(!split);
+
+ split = elt(copy, start+j-1);
+ assert(!split);
+
+ for (; j != prim->count && !split; j++)
+ split = elt(copy, start+j);
+
+ end(copy, prim->end && j == prim->count);
+
+ if (j != prim->count) {
+ /* Wrapped the primitive, need to repeat some vertices:
+ */
+ j -= 1;
+ }
+ }
+ break;
+
+ default:
+ (void)split_prim_inplace(prim->mode, &first, &incr);
+
+ j = 0;
+ while (j != prim->count) {
+
+ begin(copy, prim->mode, prim->begin && j == 0);
+
+ split = 0;
+ for (k = 0; k < first; k++, j++)
+ split |= elt(copy, start+j);
+
+ assert(!split);
+
+ for (; j != prim->count && !split; )
+ for (k = 0; k < incr; k++, j++)
+ split |= elt(copy, start+j);
+
+ end(copy, prim->end && j == prim->count);
+
+ if (j != prim->count) {
+ /* Wrapped the primitive, need to repeat some vertices:
+ */
+ assert(j > first - incr);
+ j -= (first - incr);
+ }
+ }
+ break;
+ }
+ }
+
+ if (copy->dstprim_nr)
+ flush(copy);
+}
+
+
+static void
+replay_init( struct copy_context *copy )
+{
+ struct gl_context *ctx = copy->ctx;
+ GLuint i;
+ GLuint offset;
+ const GLvoid *srcptr;
+
+ /* Make a list of varying attributes and their vbo's. Also
+ * calculate vertex size.
+ */
+ copy->vertex_size = 0;
+ for (i = 0; i < VERT_ATTRIB_MAX; i++) {
+ struct gl_buffer_object *vbo = copy->array[i]->BufferObj;
+
+ if (copy->array[i]->StrideB == 0) {
+ copy->dstarray_ptr[i] = copy->array[i];
+ }
+ else {
+ GLuint j = copy->nr_varying++;
+
+ copy->varying[j].attr = i;
+ copy->varying[j].array = copy->array[i];
+ copy->varying[j].size = attr_size(copy->array[i]);
+ copy->vertex_size += attr_size(copy->array[i]);
+
+ if (_mesa_is_bufferobj(vbo) && !_mesa_bufferobj_mapped(vbo))
+ ctx->Driver.MapBuffer(ctx, GL_ARRAY_BUFFER, GL_READ_ONLY, vbo);
+
+ copy->varying[j].src_ptr = ADD_POINTERS(vbo->Pointer,
+ copy->array[i]->Ptr);
+
+ copy->dstarray_ptr[i] = ©->varying[j].dstarray;
+ }
+ }
+
+ /* There must always be an index buffer. Currently require the
+ * caller convert non-indexed prims to indexed. Could alternately
+ * do it internally.
+ */
+ if (_mesa_is_bufferobj(copy->ib->obj) &&
+ !_mesa_bufferobj_mapped(copy->ib->obj))
+ ctx->Driver.MapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER, GL_READ_ONLY,
+ copy->ib->obj);
+
+ srcptr = (const GLubyte *) ADD_POINTERS(copy->ib->obj->Pointer,
+ copy->ib->ptr);
+
+ switch (copy->ib->type) {
+ case GL_UNSIGNED_BYTE:
+ copy->translated_elt_buf = malloc(sizeof(GLuint) * copy->ib->count);
+ copy->srcelt = copy->translated_elt_buf;
+
+ for (i = 0; i < copy->ib->count; i++)
+ copy->translated_elt_buf[i] = ((const GLubyte *)srcptr)[i];
+ break;
+
+ case GL_UNSIGNED_SHORT:
+ copy->translated_elt_buf = malloc(sizeof(GLuint) * copy->ib->count);
+ copy->srcelt = copy->translated_elt_buf;
+
+ for (i = 0; i < copy->ib->count; i++)
+ copy->translated_elt_buf[i] = ((const GLushort *)srcptr)[i];
+ break;
+
+ case GL_UNSIGNED_INT:
+ copy->translated_elt_buf = NULL;
+ copy->srcelt = (const GLuint *)srcptr;
+ break;
+ }
+
+ /* Figure out the maximum allowed vertex buffer size:
+ */
+ if (copy->vertex_size * copy->limits->max_verts <= copy->limits->max_vb_size) {
+ copy->dstbuf_size = copy->limits->max_verts;
+ }
+ else {
+ copy->dstbuf_size = copy->limits->max_vb_size / copy->vertex_size;
+ }
+
+ /* Allocate an output vertex buffer:
+ *
+ * XXX: This should be a VBO!
+ */
+ copy->dstbuf = malloc(copy->dstbuf_size * copy->vertex_size);
+ copy->dstptr = copy->dstbuf;
+
+ /* Setup new vertex arrays to point into the output buffer:
+ */
+ for (offset = 0, i = 0; i < copy->nr_varying; i++) {
+ const struct gl_client_array *src = copy->varying[i].array;
+ struct gl_client_array *dst = ©->varying[i].dstarray;
+
+ dst->Size = src->Size;
+ dst->Type = src->Type;
+ dst->Format = GL_RGBA;
+ dst->Stride = copy->vertex_size;
+ dst->StrideB = copy->vertex_size;
+ dst->Ptr = copy->dstbuf + offset;
+ dst->Enabled = GL_TRUE;
+ dst->Normalized = src->Normalized;
+ dst->BufferObj = ctx->Shared->NullBufferObj;
+ dst->_ElementSize = src->_ElementSize;
+ dst->_MaxElement = copy->dstbuf_size; /* may be less! */
+
+ offset += copy->varying[i].size;
+ }
+
+ /* Allocate an output element list:
+ */
+ copy->dstelt_size = MIN2(65536,
+ copy->ib->count * 2 + 3);
+ copy->dstelt_size = MIN2(copy->dstelt_size,
+ copy->limits->max_indices);
+ copy->dstelt = malloc(sizeof(GLuint) * copy->dstelt_size);
+ copy->dstelt_nr = 0;
+
+ /* Setup the new index buffer to point to the allocated element
+ * list:
+ */
+ copy->dstib.count = 0; /* duplicates dstelt_nr */
+ copy->dstib.type = GL_UNSIGNED_INT;
+ copy->dstib.obj = ctx->Shared->NullBufferObj;
+ copy->dstib.ptr = copy->dstelt;
+}
+
+
+/**
+ * Free up everything allocated during split/replay.
+ */
+static void
+replay_finish( struct copy_context *copy )
+{
+ struct gl_context *ctx = copy->ctx;
+ GLuint i;
+
+ /* Free our vertex and index buffers:
+ */
+ free(copy->translated_elt_buf);
+ free(copy->dstbuf);
+ free(copy->dstelt);
+
+ /* Unmap VBO's
+ */
+ for (i = 0; i < copy->nr_varying; i++) {
+ struct gl_buffer_object *vbo = copy->varying[i].array->BufferObj;
+ if (_mesa_is_bufferobj(vbo) && _mesa_bufferobj_mapped(vbo))
+ ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER, vbo);
+ }
+
+ /* Unmap index buffer:
+ */
+ if (_mesa_is_bufferobj(copy->ib->obj) &&
+ _mesa_bufferobj_mapped(copy->ib->obj)) {
+ ctx->Driver.UnmapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER, copy->ib->obj);
+ }
+}
+
+
+/**
+ * Split VBO into smaller pieces, draw the pieces.
+ */
+void vbo_split_copy( struct gl_context *ctx,
+ const struct gl_client_array *arrays[],
+ const struct _mesa_prim *prim,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ vbo_draw_func draw,
+ const struct split_limits *limits )
+{
+ struct copy_context copy;
+ GLuint i, this_nr_prims;
+
+ for (i = 0; i < nr_prims;) {
+ /* Our SW TNL pipeline doesn't handle basevertex yet, so bind_indices
+ * will rebase the elements to the basevertex, and we'll only
+ * emit strings of prims with the same basevertex in one draw call.
+ */
+ for (this_nr_prims = 1; i + this_nr_prims < nr_prims;
+ this_nr_prims++) {
+ if (prim[i].basevertex != prim[i + this_nr_prims].basevertex)
+ break;
+ }
+
+ memset(©, 0, sizeof(copy));
+
+ /* Require indexed primitives:
+ */
+ assert(ib);
+
+ copy.ctx = ctx;
+ copy.array = arrays;
+ copy.prim = &prim[i];
+ copy.nr_prims = this_nr_prims;
+ copy.ib = ib;
+ copy.draw = draw;
+ copy.limits = limits;
+
+ /* Clear the vertex cache:
+ */
+ for (i = 0; i < ELT_TABLE_SIZE; i++)
+ copy.vert_cache[i].in = ~0;
+
+ replay_init(©);
+ replay_elts(©);
+ replay_finish(©);
+ }
+}
|