Exemple #1
0
/**
 * Flush existing data, set new attrib size, replay copied vertices.
 * This is called when we transition from a small vertex attribute size
 * to a larger one.  Ex: glTexCoord2f -> glTexCoord4f.
 * We need to go back over the previous 2-component texcoords and insert
 * zero and one values.
 */
static void
vbo_exec_wrap_upgrade_vertex(struct vbo_exec_context *exec,
                             GLuint attr, GLuint newSize )
{
    struct gl_context *ctx = exec->ctx;
    struct vbo_context *vbo = vbo_context(ctx);
    const GLint lastcount = exec->vtx.vert_count;
    fi_type *old_attrptr[VBO_ATTRIB_MAX];
    const GLuint old_vtx_size = exec->vtx.vertex_size; /* floats per vertex */
    const GLuint oldSize = exec->vtx.attrsz[attr];
    GLuint i;

    /* Run pipeline on current vertices, copy wrapped vertices
     * to exec->vtx.copied.
     */
    vbo_exec_wrap_buffers( exec );

    if (unlikely(exec->vtx.copied.nr)) {
        /* We're in the middle of a primitive, keep the old vertex
         * format around to be able to translate the copied vertices to
         * the new format.
         */
        memcpy(old_attrptr, exec->vtx.attrptr, sizeof(old_attrptr));
    }

    if (unlikely(oldSize)) {
        /* Do a COPY_TO_CURRENT to ensure back-copying works for the
         * case when the attribute already exists in the vertex and is
         * having its size increased.
         */
        vbo_exec_copy_to_current( exec );
    }

    /* Heuristic: Attempt to isolate attributes received outside
     * begin/end so that they don't bloat the vertices.
     */
    if (!_mesa_inside_begin_end(ctx) &&
            !oldSize && lastcount > 8 && exec->vtx.vertex_size) {
        vbo_exec_copy_to_current( exec );
        vbo_reset_all_attr(exec);
    }

    /* Fix up sizes:
     */
    exec->vtx.attrsz[attr] = newSize;
    exec->vtx.vertex_size += newSize - oldSize;
    exec->vtx.max_vert = vbo_compute_max_verts(exec);
    exec->vtx.vert_count = 0;
    exec->vtx.buffer_ptr = exec->vtx.buffer_map;
    exec->vtx.enabled |= BITFIELD64_BIT(attr);

    if (unlikely(oldSize)) {
        /* Size changed, recalculate all the attrptr[] values
         */
        fi_type *tmp = exec->vtx.vertex;

        for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
            if (exec->vtx.attrsz[i]) {
                exec->vtx.attrptr[i] = tmp;
                tmp += exec->vtx.attrsz[i];
            }
            else
                exec->vtx.attrptr[i] = NULL; /* will not be dereferenced */
        }

        /* Copy from current to repopulate the vertex with correct
         * values.
         */
        vbo_exec_copy_from_current( exec );
    }
    else {
        /* Just have to append the new attribute at the end */
        exec->vtx.attrptr[attr] = exec->vtx.vertex +
                                  exec->vtx.vertex_size - newSize;
    }

    /* Replay stored vertices to translate them
     * to new format here.
     *
     * -- No need to replay - just copy piecewise
     */
    if (unlikely(exec->vtx.copied.nr)) {
        fi_type *data = exec->vtx.copied.buffer;
        fi_type *dest = exec->vtx.buffer_ptr;

        assert(exec->vtx.buffer_ptr == exec->vtx.buffer_map);

        for (i = 0 ; i < exec->vtx.copied.nr ; i++) {
            GLbitfield64 enabled = exec->vtx.enabled;
            while (enabled) {
                const int j = u_bit_scan64(&enabled);
                GLuint sz = exec->vtx.attrsz[j];
                GLint old_offset = old_attrptr[j] - exec->vtx.vertex;
                GLint new_offset = exec->vtx.attrptr[j] - exec->vtx.vertex;

                assert(sz);

                if (j == attr) {
                    if (oldSize) {
                        fi_type tmp[4];
                        COPY_CLEAN_4V_TYPE_AS_UNION(tmp, oldSize,
                                                    data + old_offset,
                                                    exec->vtx.attrtype[j]);
                        COPY_SZ_4V(dest + new_offset, newSize, tmp);
                    } else {
                        fi_type *current = (fi_type *)vbo->currval[j].Ptr;
                        COPY_SZ_4V(dest + new_offset, sz, current);
                    }
                }
                else {
                    COPY_SZ_4V(dest + new_offset, sz, data + old_offset);
                }
            }

            data += old_vtx_size;
            dest += exec->vtx.vertex_size;
        }

        exec->vtx.buffer_ptr = dest;
        exec->vtx.vert_count += exec->vtx.copied.nr;
        exec->vtx.copied.nr = 0;
    }
}
/**
 * After playback, copy everything but the position from the
 * last vertex to the saved state
 */
static void
_playback_copy_to_current(struct gl_context *ctx,
                          const struct vbo_save_vertex_list *node)
{
   struct vbo_context *vbo = vbo_context(ctx);
   fi_type vertex[VBO_ATTRIB_MAX * 4];
   fi_type *data;
   GLuint i, offset;

   if (node->current_size == 0)
      return;

   if (node->current_data) {
      data = node->current_data;
   }
   else {
      data = vertex;

      if (node->count)
         offset = (node->buffer_offset + 
                   (node->count-1) * node->vertex_size * sizeof(GLfloat));
      else
         offset = node->buffer_offset;

      ctx->Driver.GetBufferSubData( ctx, offset,
                                    node->vertex_size * sizeof(GLfloat), 
                                    data, node->vertex_store->bufferobj );

      data += node->attrsz[0]; /* skip vertex position */
   }

   for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) {
      if (node->attrsz[i]) {
	 fi_type *current = (fi_type *)vbo->currval[i].Ptr;
         fi_type tmp[4];

         COPY_CLEAN_4V_TYPE_AS_UNION(tmp,
                                     node->attrsz[i],
                                     data,
                                     node->attrtype[i]);
         
         if (node->attrtype[i] != vbo->currval[i].Type ||
             memcmp(current, tmp, 4 * sizeof(GLfloat)) != 0) {
            memcpy(current, tmp, 4 * sizeof(GLfloat));

            vbo->currval[i].Size = node->attrsz[i];
            vbo->currval[i]._ElementSize = vbo->currval[i].Size * sizeof(GLfloat);
            vbo->currval[i].Type = node->attrtype[i];
            vbo->currval[i].Integer =
                  vbo_attrtype_to_integer_flag(node->attrtype[i]);

            if (i >= VBO_ATTRIB_FIRST_MATERIAL &&
                i <= VBO_ATTRIB_LAST_MATERIAL)
               ctx->NewState |= _NEW_LIGHT;

            ctx->NewState |= _NEW_CURRENT_ATTRIB;
         }

	 data += node->attrsz[i];
      }
   }

   /* Colormaterial -- this kindof sucks.
    */
   if (ctx->Light.ColorMaterialEnabled) {
      _mesa_update_color_material(ctx, ctx->Current.Attrib[VBO_ATTRIB_COLOR0]);
   }

   /* CurrentExecPrimitive
    */
   if (node->prim_count) {
      const struct _mesa_prim *prim = &node->prim[node->prim_count - 1];
      if (prim->end)
	 ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END;
      else
	 ctx->Driver.CurrentExecPrimitive = prim->mode;
   }
}
Exemple #3
0
/**
 * Copy the active vertex's values to the ctx->Current fields.
 */
static void
vbo_exec_copy_to_current(struct vbo_exec_context *exec)
{
    struct gl_context *ctx = exec->ctx;
    struct vbo_context *vbo = vbo_context(ctx);
    GLbitfield64 enabled = exec->vtx.enabled & (~BITFIELD64_BIT(VBO_ATTRIB_POS));

    while (enabled) {
        const int i = u_bit_scan64(&enabled);

        /* Note: the exec->vtx.current[i] pointers point into the
         * ctx->Current.Attrib and ctx->Light.Material.Attrib arrays.
         */
        GLfloat *current = (GLfloat *)vbo->currval[i].Ptr;
        fi_type tmp[8]; /* space for doubles */
        int dmul = exec->vtx.attrtype[i] == GL_DOUBLE ? 2 : 1;

        assert(exec->vtx.attrsz[i]);

        if (exec->vtx.attrtype[i] == GL_DOUBLE) {
            memset(tmp, 0, sizeof(tmp));
            memcpy(tmp, exec->vtx.attrptr[i], exec->vtx.attrsz[i] * sizeof(GLfloat));
        } else {
            COPY_CLEAN_4V_TYPE_AS_UNION(tmp,
                                        exec->vtx.attrsz[i],
                                        exec->vtx.attrptr[i],
                                        exec->vtx.attrtype[i]);
        }

        if (exec->vtx.attrtype[i] != vbo->currval[i].Type ||
                memcmp(current, tmp, 4 * sizeof(GLfloat) * dmul) != 0) {
            memcpy(current, tmp, 4 * sizeof(GLfloat) * dmul);

            /* Given that we explicitly state size here, there is no need
             * for the COPY_CLEAN above, could just copy 16 bytes and be
             * done.  The only problem is when Mesa accesses ctx->Current
             * directly.
             */
            /* Size here is in components - not bytes */
            vbo->currval[i].Size = exec->vtx.attrsz[i] / dmul;
            vbo->currval[i]._ElementSize =
                vbo->currval[i].Size * sizeof(GLfloat) * dmul;
            vbo->currval[i].Type = exec->vtx.attrtype[i];
            vbo->currval[i].Integer =
                vbo_attrtype_to_integer_flag(exec->vtx.attrtype[i]);
            vbo->currval[i].Doubles =
                vbo_attrtype_to_double_flag(exec->vtx.attrtype[i]);

            /* This triggers rather too much recalculation of Mesa state
             * that doesn't get used (eg light positions).
             */
            if (i >= VBO_ATTRIB_MAT_FRONT_AMBIENT &&
                    i <= VBO_ATTRIB_MAT_BACK_INDEXES)
                ctx->NewState |= _NEW_LIGHT;

            ctx->NewState |= _NEW_CURRENT_ATTRIB;
        }
    }

    /* Colormaterial -- this kindof sucks.
     */
    if (ctx->Light.ColorMaterialEnabled &&
            exec->vtx.attrsz[VBO_ATTRIB_COLOR0]) {
        _mesa_update_color_material(ctx,
                                    ctx->Current.Attrib[VBO_ATTRIB_COLOR0]);
    }
}