2006-10-29 09:46:11 +00:00
|
|
|
/**************************************************************************
|
|
|
|
|
s/Tungsten Graphics/VMware/
Tungsten Graphics Inc. was acquired by VMware Inc. in 2008. Leaving the
old copyright name is creating unnecessary confusion, hence this change.
This was the sed script I used:
$ cat tg2vmw.sed
# Run as:
#
# git reset --hard HEAD && find include scons src -type f -not -name 'sed*' -print0 | xargs -0 sed -i -f tg2vmw.sed
#
# Rename copyrights
s/Tungsten Gra\(ph\|hp\)ics,\? [iI]nc\.\?\(, Cedar Park\)\?\(, Austin\)\?\(, \(Texas\|TX\)\)\?\.\?/VMware, Inc./g
/Copyright/s/Tungsten Graphics\(,\? [iI]nc\.\)\?\(, Cedar Park\)\?\(, Austin\)\?\(, \(Texas\|TX\)\)\?\.\?/VMware, Inc./
s/TUNGSTEN GRAPHICS/VMWARE/g
# Rename emails
s/alanh@tungstengraphics.com/alanh@vmware.com/
s/jens@tungstengraphics.com/jowen@vmware.com/g
s/jrfonseca-at-tungstengraphics-dot-com/jfonseca-at-vmware-dot-com/
s/jrfonseca\?@tungstengraphics.com/jfonseca@vmware.com/g
s/keithw\?@tungstengraphics.com/keithw@vmware.com/g
s/michel@tungstengraphics.com/daenzer@vmware.com/g
s/thomas-at-tungstengraphics-dot-com/thellstom-at-vmware-dot-com/
s/zack@tungstengraphics.com/zackr@vmware.com/
# Remove dead links
s@Tungsten Graphics (http://www.tungstengraphics.com)@Tungsten Graphics@g
# C string src/gallium/state_trackers/vega/api_misc.c
s/"Tungsten Graphics, Inc"/"VMware, Inc"/
Reviewed-by: Brian Paul <brianp@vmware.com>
2014-01-17 16:27:50 +00:00
|
|
|
Copyright 2002-2008 VMware, Inc.
|
2006-10-29 09:46:11 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
on 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
|
s/Tungsten Graphics/VMware/
Tungsten Graphics Inc. was acquired by VMware Inc. in 2008. Leaving the
old copyright name is creating unnecessary confusion, hence this change.
This was the sed script I used:
$ cat tg2vmw.sed
# Run as:
#
# git reset --hard HEAD && find include scons src -type f -not -name 'sed*' -print0 | xargs -0 sed -i -f tg2vmw.sed
#
# Rename copyrights
s/Tungsten Gra\(ph\|hp\)ics,\? [iI]nc\.\?\(, Cedar Park\)\?\(, Austin\)\?\(, \(Texas\|TX\)\)\?\.\?/VMware, Inc./g
/Copyright/s/Tungsten Graphics\(,\? [iI]nc\.\)\?\(, Cedar Park\)\?\(, Austin\)\?\(, \(Texas\|TX\)\)\?\.\?/VMware, Inc./
s/TUNGSTEN GRAPHICS/VMWARE/g
# Rename emails
s/alanh@tungstengraphics.com/alanh@vmware.com/
s/jens@tungstengraphics.com/jowen@vmware.com/g
s/jrfonseca-at-tungstengraphics-dot-com/jfonseca-at-vmware-dot-com/
s/jrfonseca\?@tungstengraphics.com/jfonseca@vmware.com/g
s/keithw\?@tungstengraphics.com/keithw@vmware.com/g
s/michel@tungstengraphics.com/daenzer@vmware.com/g
s/thomas-at-tungstengraphics-dot-com/thellstom-at-vmware-dot-com/
s/zack@tungstengraphics.com/zackr@vmware.com/
# Remove dead links
s@Tungsten Graphics (http://www.tungstengraphics.com)@Tungsten Graphics@g
# C string src/gallium/state_trackers/vega/api_misc.c
s/"Tungsten Graphics, Inc"/"VMware, Inc"/
Reviewed-by: Brian Paul <brianp@vmware.com>
2014-01-17 16:27:50 +00:00
|
|
|
VMWARE AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
2006-10-29 09:46:11 +00:00
|
|
|
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:
|
s/Tungsten Graphics/VMware/
Tungsten Graphics Inc. was acquired by VMware Inc. in 2008. Leaving the
old copyright name is creating unnecessary confusion, hence this change.
This was the sed script I used:
$ cat tg2vmw.sed
# Run as:
#
# git reset --hard HEAD && find include scons src -type f -not -name 'sed*' -print0 | xargs -0 sed -i -f tg2vmw.sed
#
# Rename copyrights
s/Tungsten Gra\(ph\|hp\)ics,\? [iI]nc\.\?\(, Cedar Park\)\?\(, Austin\)\?\(, \(Texas\|TX\)\)\?\.\?/VMware, Inc./g
/Copyright/s/Tungsten Graphics\(,\? [iI]nc\.\)\?\(, Cedar Park\)\?\(, Austin\)\?\(, \(Texas\|TX\)\)\?\.\?/VMware, Inc./
s/TUNGSTEN GRAPHICS/VMWARE/g
# Rename emails
s/alanh@tungstengraphics.com/alanh@vmware.com/
s/jens@tungstengraphics.com/jowen@vmware.com/g
s/jrfonseca-at-tungstengraphics-dot-com/jfonseca-at-vmware-dot-com/
s/jrfonseca\?@tungstengraphics.com/jfonseca@vmware.com/g
s/keithw\?@tungstengraphics.com/keithw@vmware.com/g
s/michel@tungstengraphics.com/daenzer@vmware.com/g
s/thomas-at-tungstengraphics-dot-com/thellstom-at-vmware-dot-com/
s/zack@tungstengraphics.com/zackr@vmware.com/
# Remove dead links
s@Tungsten Graphics (http://www.tungstengraphics.com)@Tungsten Graphics@g
# C string src/gallium/state_trackers/vega/api_misc.c
s/"Tungsten Graphics, Inc"/"VMware, Inc"/
Reviewed-by: Brian Paul <brianp@vmware.com>
2014-01-17 16:27:50 +00:00
|
|
|
* Keith Whitwell <keithw@vmware.com>
|
2006-10-29 09:46:11 +00:00
|
|
|
*/
|
|
|
|
|
2007-07-04 13:15:20 -06:00
|
|
|
#include "main/glheader.h"
|
2008-09-04 14:58:02 -06:00
|
|
|
#include "main/bufferobj.h"
|
2007-07-04 13:15:20 -06:00
|
|
|
#include "main/context.h"
|
|
|
|
#include "main/macros.h"
|
|
|
|
#include "main/vtxfmt.h"
|
|
|
|
#include "main/dlist.h"
|
2009-09-08 10:25:22 +08:00
|
|
|
#include "main/eval.h"
|
2007-07-04 13:15:20 -06:00
|
|
|
#include "main/state.h"
|
|
|
|
#include "main/light.h"
|
|
|
|
#include "main/api_arrayelt.h"
|
2011-09-21 08:22:07 -06:00
|
|
|
#include "main/api_validate.h"
|
2010-02-24 12:01:14 +08:00
|
|
|
#include "main/dispatch.h"
|
2006-10-29 09:46:11 +00:00
|
|
|
|
|
|
|
#include "vbo_context.h"
|
2011-11-10 09:47:37 -07:00
|
|
|
#include "vbo_noop.h"
|
|
|
|
|
2006-10-29 09:46:11 +00:00
|
|
|
|
2007-06-28 08:12:52 -06:00
|
|
|
#ifdef ERROR
|
|
|
|
#undef ERROR
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2009-06-10 13:00:35 -06:00
|
|
|
/** ID/name for immediate-mode VBO */
|
|
|
|
#define IMM_BUFFER_NAME 0xaabbccdd
|
|
|
|
|
|
|
|
|
2006-10-29 09:46:11 +00:00
|
|
|
static void reset_attrfv( struct vbo_exec_context *exec );
|
|
|
|
|
|
|
|
|
2009-10-22 09:37:56 -06:00
|
|
|
/**
|
|
|
|
* Close off the last primitive, execute the buffer, restart the
|
2015-10-15 22:31:50 -06:00
|
|
|
* primitive. This is called when we fill a vertex buffer before
|
|
|
|
* hitting glEnd.
|
2006-10-29 09:46:11 +00:00
|
|
|
*/
|
|
|
|
static void vbo_exec_wrap_buffers( struct vbo_exec_context *exec )
|
|
|
|
{
|
|
|
|
if (exec->vtx.prim_count == 0) {
|
|
|
|
exec->vtx.copied.nr = 0;
|
|
|
|
exec->vtx.vert_count = 0;
|
2009-03-03 10:46:12 +00:00
|
|
|
exec->vtx.buffer_ptr = exec->vtx.buffer_map;
|
2006-10-29 09:46:11 +00:00
|
|
|
}
|
|
|
|
else {
|
2015-10-15 20:18:32 -06:00
|
|
|
struct _mesa_prim *last_prim = &exec->vtx.prim[exec->vtx.prim_count - 1];
|
|
|
|
const GLuint last_begin = last_prim->begin;
|
2006-10-29 09:46:11 +00:00
|
|
|
GLuint last_count;
|
|
|
|
|
2013-04-23 10:53:00 -06:00
|
|
|
if (_mesa_inside_begin_end(exec->ctx)) {
|
2015-10-15 20:18:32 -06:00
|
|
|
last_prim->count = exec->vtx.vert_count - last_prim->start;
|
2006-10-29 09:46:11 +00:00
|
|
|
}
|
|
|
|
|
2015-10-15 20:18:32 -06:00
|
|
|
last_count = last_prim->count;
|
2006-10-29 09:46:11 +00:00
|
|
|
|
2015-10-15 22:31:50 -06:00
|
|
|
/* Special handling for wrapping GL_LINE_LOOP */
|
|
|
|
if (last_prim->mode == GL_LINE_LOOP &&
|
|
|
|
last_count > 0 &&
|
|
|
|
!last_prim->end) {
|
|
|
|
/* draw this section of the incomplete line loop as a line strip */
|
|
|
|
last_prim->mode = GL_LINE_STRIP;
|
|
|
|
if (!last_prim->begin) {
|
|
|
|
/* This is not the first section of the line loop, so don't
|
|
|
|
* draw the 0th vertex. We're saving it until we draw the
|
|
|
|
* very last section of the loop.
|
|
|
|
*/
|
|
|
|
last_prim->start++;
|
|
|
|
last_prim->count--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-10-29 09:46:11 +00:00
|
|
|
/* Execute the buffer and save copied vertices.
|
|
|
|
*/
|
|
|
|
if (exec->vtx.vert_count)
|
2009-03-03 10:46:12 +00:00
|
|
|
vbo_exec_vtx_flush( exec, GL_FALSE );
|
2006-10-29 09:46:11 +00:00
|
|
|
else {
|
|
|
|
exec->vtx.prim_count = 0;
|
|
|
|
exec->vtx.copied.nr = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Emit a glBegin to start the new list.
|
|
|
|
*/
|
|
|
|
assert(exec->vtx.prim_count == 0);
|
|
|
|
|
2013-04-23 10:53:00 -06:00
|
|
|
if (_mesa_inside_begin_end(exec->ctx)) {
|
2006-10-29 09:46:11 +00:00
|
|
|
exec->vtx.prim[0].mode = exec->ctx->Driver.CurrentExecPrimitive;
|
2015-10-15 22:31:50 -06:00
|
|
|
exec->vtx.prim[0].begin = 0;
|
2006-10-29 09:46:11 +00:00
|
|
|
exec->vtx.prim[0].start = 0;
|
|
|
|
exec->vtx.prim[0].count = 0;
|
|
|
|
exec->vtx.prim_count++;
|
|
|
|
|
|
|
|
if (exec->vtx.copied.nr == last_count)
|
|
|
|
exec->vtx.prim[0].begin = last_begin;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-10-22 09:37:56 -06:00
|
|
|
/**
|
|
|
|
* Deal with buffer wrapping where provoked by the vertex buffer
|
2006-10-29 09:46:11 +00:00
|
|
|
* filling up, as opposed to upgrade_vertex().
|
|
|
|
*/
|
2015-10-15 20:22:25 -06:00
|
|
|
static void
|
|
|
|
vbo_exec_vtx_wrap(struct vbo_exec_context *exec)
|
2006-10-29 09:46:11 +00:00
|
|
|
{
|
2015-02-25 09:49:45 -07:00
|
|
|
fi_type *data = exec->vtx.copied.buffer;
|
2006-10-29 09:46:11 +00:00
|
|
|
GLuint i;
|
|
|
|
|
|
|
|
/* Run pipeline on current vertices, copy wrapped vertices
|
|
|
|
* to exec->vtx.copied.
|
|
|
|
*/
|
|
|
|
vbo_exec_wrap_buffers( exec );
|
|
|
|
|
2013-01-24 16:32:42 -07:00
|
|
|
if (!exec->vtx.buffer_ptr) {
|
|
|
|
/* probably ran out of memory earlier when allocating the VBO */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2006-10-29 09:46:11 +00:00
|
|
|
/* Copy stored stored vertices to start of new list.
|
|
|
|
*/
|
|
|
|
assert(exec->vtx.max_vert - exec->vtx.vert_count > exec->vtx.copied.nr);
|
|
|
|
|
|
|
|
for (i = 0 ; i < exec->vtx.copied.nr ; i++) {
|
2010-02-18 23:50:59 -08:00
|
|
|
memcpy( exec->vtx.buffer_ptr, data,
|
|
|
|
exec->vtx.vertex_size * sizeof(GLfloat));
|
2009-03-03 10:46:12 +00:00
|
|
|
exec->vtx.buffer_ptr += exec->vtx.vertex_size;
|
2006-10-29 09:46:11 +00:00
|
|
|
data += exec->vtx.vertex_size;
|
|
|
|
exec->vtx.vert_count++;
|
|
|
|
}
|
|
|
|
|
|
|
|
exec->vtx.copied.nr = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-10-22 09:37:56 -06:00
|
|
|
/**
|
2006-10-29 09:46:11 +00:00
|
|
|
* Copy the active vertex's values to the ctx->Current fields.
|
|
|
|
*/
|
|
|
|
static void vbo_exec_copy_to_current( struct vbo_exec_context *exec )
|
|
|
|
{
|
2010-10-12 12:26:10 -04:00
|
|
|
struct gl_context *ctx = exec->ctx;
|
2006-10-30 20:16:35 +00:00
|
|
|
struct vbo_context *vbo = vbo_context(ctx);
|
2006-10-29 09:46:11 +00:00
|
|
|
GLuint i;
|
|
|
|
|
|
|
|
for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) {
|
|
|
|
if (exec->vtx.attrsz[i]) {
|
|
|
|
/* Note: the exec->vtx.current[i] pointers point into the
|
|
|
|
* ctx->Current.Attrib and ctx->Light.Material.Attrib arrays.
|
|
|
|
*/
|
2008-10-03 13:55:40 +01:00
|
|
|
GLfloat *current = (GLfloat *)vbo->currval[i].Ptr;
|
2015-02-20 11:41:01 +10:00
|
|
|
fi_type tmp[8]; /* space for doubles */
|
|
|
|
int dmul = exec->vtx.attrtype[i] == GL_DOUBLE ? 2 : 1;
|
|
|
|
|
|
|
|
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]);
|
|
|
|
}
|
2008-10-03 13:55:40 +01:00
|
|
|
|
2012-10-30 14:44:22 +01:00
|
|
|
if (exec->vtx.attrtype[i] != vbo->currval[i].Type ||
|
2015-02-20 11:41:01 +10:00
|
|
|
memcmp(current, tmp, 4 * sizeof(GLfloat) * dmul) != 0) {
|
|
|
|
memcpy(current, tmp, 4 * sizeof(GLfloat) * dmul);
|
2006-10-30 20:16:35 +00:00
|
|
|
|
2008-10-03 13:55:40 +01:00
|
|
|
/* 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.
|
|
|
|
*/
|
2015-02-20 11:41:01 +10:00
|
|
|
/* 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;
|
2012-10-30 14:44:22 +01:00
|
|
|
vbo->currval[i].Type = exec->vtx.attrtype[i];
|
|
|
|
vbo->currval[i].Integer =
|
|
|
|
vbo_attrtype_to_integer_flag(exec->vtx.attrtype[i]);
|
2015-02-20 11:41:01 +10:00
|
|
|
vbo->currval[i].Doubles =
|
|
|
|
vbo_attrtype_to_double_flag(exec->vtx.attrtype[i]);
|
2008-10-03 13:55:40 +01:00
|
|
|
|
|
|
|
/* 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;
|
|
|
|
}
|
2006-10-29 09:46:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 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]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-02-21 15:11:44 -07:00
|
|
|
/**
|
|
|
|
* Copy current vertex attribute values into the current vertex.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
vbo_exec_copy_from_current(struct vbo_exec_context *exec)
|
2006-10-29 09:46:11 +00:00
|
|
|
{
|
2010-10-12 12:26:10 -04:00
|
|
|
struct gl_context *ctx = exec->ctx;
|
2006-10-30 20:16:35 +00:00
|
|
|
struct vbo_context *vbo = vbo_context(ctx);
|
2006-10-29 09:46:11 +00:00
|
|
|
GLint i;
|
|
|
|
|
2011-02-21 15:11:44 -07:00
|
|
|
for (i = VBO_ATTRIB_POS + 1; i < VBO_ATTRIB_MAX; i++) {
|
2015-02-20 11:41:01 +10:00
|
|
|
if (exec->vtx.attrtype[i] == GL_DOUBLE) {
|
|
|
|
memcpy(exec->vtx.attrptr[i], vbo->currval[i].Ptr, exec->vtx.attrsz[i] * sizeof(GLfloat));
|
|
|
|
} else {
|
|
|
|
const fi_type *current = (fi_type *) vbo->currval[i].Ptr;
|
|
|
|
switch (exec->vtx.attrsz[i]) {
|
|
|
|
case 4: exec->vtx.attrptr[i][3] = current[3];
|
|
|
|
case 3: exec->vtx.attrptr[i][2] = current[2];
|
|
|
|
case 2: exec->vtx.attrptr[i][1] = current[1];
|
|
|
|
case 1: exec->vtx.attrptr[i][0] = current[0];
|
|
|
|
break;
|
|
|
|
}
|
2006-10-29 09:46:11 +00:00
|
|
|
}
|
2006-10-30 20:16:35 +00:00
|
|
|
}
|
2006-10-29 09:46:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-10-22 09:37:56 -06:00
|
|
|
/**
|
|
|
|
* Flush existing data, set new attrib size, replay copied vertices.
|
2011-02-21 15:11:44 -07:00
|
|
|
* 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.
|
2006-10-29 09:46:11 +00:00
|
|
|
*/
|
2011-02-21 15:11:44 -07:00
|
|
|
static void
|
|
|
|
vbo_exec_wrap_upgrade_vertex(struct vbo_exec_context *exec,
|
|
|
|
GLuint attr, GLuint newSize )
|
2006-10-29 09:46:11 +00:00
|
|
|
{
|
2010-10-12 12:26:10 -04:00
|
|
|
struct gl_context *ctx = exec->ctx;
|
2006-10-30 20:16:35 +00:00
|
|
|
struct vbo_context *vbo = vbo_context(ctx);
|
2011-02-21 15:11:44 -07:00
|
|
|
const GLint lastcount = exec->vtx.vert_count;
|
2015-02-25 09:49:45 -07:00
|
|
|
fi_type *old_attrptr[VBO_ATTRIB_MAX];
|
2011-02-21 15:11:44 -07:00
|
|
|
const GLuint old_vtx_size = exec->vtx.vertex_size; /* floats per vertex */
|
|
|
|
const GLuint oldSize = exec->vtx.attrsz[attr];
|
2006-10-29 09:46:11 +00:00
|
|
|
GLuint i;
|
|
|
|
|
|
|
|
/* Run pipeline on current vertices, copy wrapped vertices
|
|
|
|
* to exec->vtx.copied.
|
|
|
|
*/
|
|
|
|
vbo_exec_wrap_buffers( exec );
|
|
|
|
|
2010-10-31 23:51:30 +01:00
|
|
|
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));
|
|
|
|
}
|
2006-10-29 09:46:11 +00:00
|
|
|
|
2011-02-21 15:11:44 -07:00
|
|
|
if (unlikely(oldSize)) {
|
2010-10-31 23:51:30 +01:00
|
|
|
/* 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 );
|
|
|
|
}
|
2006-10-29 09:46:11 +00:00
|
|
|
|
|
|
|
/* Heuristic: Attempt to isolate attributes received outside
|
|
|
|
* begin/end so that they don't bloat the vertices.
|
|
|
|
*/
|
2013-04-23 10:53:00 -06:00
|
|
|
if (!_mesa_inside_begin_end(ctx) &&
|
2011-02-21 15:11:44 -07:00
|
|
|
!oldSize && lastcount > 8 && exec->vtx.vertex_size) {
|
2010-10-31 23:51:30 +01:00
|
|
|
vbo_exec_copy_to_current( exec );
|
2006-10-29 09:46:11 +00:00
|
|
|
reset_attrfv( exec );
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Fix up sizes:
|
|
|
|
*/
|
2011-02-21 15:11:44 -07:00
|
|
|
exec->vtx.attrsz[attr] = newSize;
|
|
|
|
exec->vtx.vertex_size += newSize - oldSize;
|
2015-10-16 11:19:40 -06:00
|
|
|
exec->vtx.max_vert = vbo_compute_max_verts(exec);
|
2006-10-29 09:46:11 +00:00
|
|
|
exec->vtx.vert_count = 0;
|
2009-03-03 10:46:12 +00:00
|
|
|
exec->vtx.buffer_ptr = exec->vtx.buffer_map;
|
2006-10-29 09:46:11 +00:00
|
|
|
|
2011-02-21 15:11:44 -07:00
|
|
|
if (unlikely(oldSize)) {
|
2010-10-31 23:51:30 +01:00
|
|
|
/* Size changed, recalculate all the attrptr[] values
|
|
|
|
*/
|
2015-02-25 09:49:45 -07:00
|
|
|
fi_type *tmp = exec->vtx.vertex;
|
2010-10-31 23:51:30 +01:00
|
|
|
|
|
|
|
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 */
|
2006-10-29 09:46:11 +00:00
|
|
|
}
|
|
|
|
|
2010-10-31 23:51:30 +01:00
|
|
|
/* Copy from current to repopulate the vertex with correct
|
|
|
|
* values.
|
|
|
|
*/
|
|
|
|
vbo_exec_copy_from_current( exec );
|
2011-02-21 15:11:44 -07:00
|
|
|
}
|
|
|
|
else {
|
2010-10-31 23:51:30 +01:00
|
|
|
/* Just have to append the new attribute at the end */
|
|
|
|
exec->vtx.attrptr[attr] = exec->vtx.vertex +
|
2015-02-25 09:49:45 -07:00
|
|
|
exec->vtx.vertex_size - newSize;
|
2010-10-31 23:51:30 +01:00
|
|
|
}
|
2006-10-29 09:46:11 +00:00
|
|
|
|
|
|
|
/* Replay stored vertices to translate them
|
|
|
|
* to new format here.
|
|
|
|
*
|
|
|
|
* -- No need to replay - just copy piecewise
|
|
|
|
*/
|
2010-10-31 23:51:30 +01:00
|
|
|
if (unlikely(exec->vtx.copied.nr)) {
|
2015-02-25 09:49:45 -07:00
|
|
|
fi_type *data = exec->vtx.copied.buffer;
|
|
|
|
fi_type *dest = exec->vtx.buffer_ptr;
|
2006-10-29 09:46:11 +00:00
|
|
|
GLuint j;
|
|
|
|
|
2009-03-03 10:46:12 +00:00
|
|
|
assert(exec->vtx.buffer_ptr == exec->vtx.buffer_map);
|
2010-10-31 23:51:30 +01:00
|
|
|
|
2006-10-29 09:46:11 +00:00
|
|
|
for (i = 0 ; i < exec->vtx.copied.nr ; i++) {
|
|
|
|
for (j = 0 ; j < VBO_ATTRIB_MAX ; j++) {
|
2010-10-31 23:51:30 +01:00
|
|
|
GLuint sz = exec->vtx.attrsz[j];
|
|
|
|
|
|
|
|
if (sz) {
|
|
|
|
GLint old_offset = old_attrptr[j] - exec->vtx.vertex;
|
|
|
|
GLint new_offset = exec->vtx.attrptr[j] - exec->vtx.vertex;
|
|
|
|
|
2006-10-29 09:46:11 +00:00
|
|
|
if (j == attr) {
|
2011-02-21 15:11:44 -07:00
|
|
|
if (oldSize) {
|
2015-02-25 09:49:45 -07:00
|
|
|
fi_type tmp[4];
|
|
|
|
COPY_CLEAN_4V_TYPE_AS_UNION(tmp, oldSize,
|
2012-10-30 14:44:22 +01:00
|
|
|
data + old_offset,
|
|
|
|
exec->vtx.attrtype[j]);
|
2011-02-21 15:11:44 -07:00
|
|
|
COPY_SZ_4V(dest + new_offset, newSize, tmp);
|
2006-10-29 09:46:11 +00:00
|
|
|
} else {
|
2015-02-25 09:49:45 -07:00
|
|
|
fi_type *current = (fi_type *)vbo->currval[j].Ptr;
|
2010-10-31 23:51:30 +01:00
|
|
|
COPY_SZ_4V(dest + new_offset, sz, current);
|
2006-10-29 09:46:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2010-10-31 23:51:30 +01:00
|
|
|
COPY_SZ_4V(dest + new_offset, sz, data + old_offset);
|
2006-10-29 09:46:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-10-31 23:51:30 +01:00
|
|
|
|
|
|
|
data += old_vtx_size;
|
|
|
|
dest += exec->vtx.vertex_size;
|
2006-10-29 09:46:11 +00:00
|
|
|
}
|
|
|
|
|
2009-03-03 10:46:12 +00:00
|
|
|
exec->vtx.buffer_ptr = dest;
|
2006-10-29 09:46:11 +00:00
|
|
|
exec->vtx.vert_count += exec->vtx.copied.nr;
|
|
|
|
exec->vtx.copied.nr = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-02-21 15:11:44 -07:00
|
|
|
/**
|
|
|
|
* This is when a vertex attribute transitions to a different size.
|
|
|
|
* For example, we saw a bunch of glTexCoord2f() calls and now we got a
|
|
|
|
* glTexCoord4f() call. We promote the array from size=2 to size=4.
|
2015-10-12 10:58:49 -06:00
|
|
|
* \param newSize size of new vertex (number of 32-bit words).
|
2011-02-21 15:11:44 -07:00
|
|
|
*/
|
|
|
|
static void
|
2015-10-12 10:58:49 -06:00
|
|
|
vbo_exec_fixup_vertex(struct gl_context *ctx, GLuint attr,
|
|
|
|
GLuint newSize, GLenum newType)
|
2006-10-29 09:46:11 +00:00
|
|
|
{
|
|
|
|
struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
|
|
|
|
|
2015-10-12 10:58:49 -06:00
|
|
|
if (newSize > exec->vtx.attrsz[attr] ||
|
|
|
|
newType != exec->vtx.attrtype[attr]) {
|
2006-10-29 09:46:11 +00:00
|
|
|
/* New size is larger. Need to flush existing vertices and get
|
|
|
|
* an enlarged vertex format.
|
|
|
|
*/
|
2011-02-21 15:11:44 -07:00
|
|
|
vbo_exec_wrap_upgrade_vertex( exec, attr, newSize );
|
2006-10-29 09:46:11 +00:00
|
|
|
}
|
2011-02-21 15:11:44 -07:00
|
|
|
else if (newSize < exec->vtx.active_sz[attr]) {
|
|
|
|
GLuint i;
|
2015-02-25 09:49:45 -07:00
|
|
|
const fi_type *id =
|
|
|
|
vbo_get_default_vals_as_union(exec->vtx.attrtype[attr]);
|
2006-10-29 09:46:11 +00:00
|
|
|
|
|
|
|
/* New size is smaller - just need to fill in some
|
|
|
|
* zeros. Don't need to flush or wrap.
|
|
|
|
*/
|
2011-02-21 15:11:44 -07:00
|
|
|
for (i = newSize; i <= exec->vtx.attrsz[attr]; i++)
|
2015-02-25 09:49:45 -07:00
|
|
|
exec->vtx.attrptr[attr][i-1] = id[i-1];
|
2006-10-29 09:46:11 +00:00
|
|
|
}
|
|
|
|
|
2011-02-21 15:11:44 -07:00
|
|
|
exec->vtx.active_sz[attr] = newSize;
|
2006-10-29 09:46:11 +00:00
|
|
|
|
|
|
|
/* Does setting NeedFlush belong here? Necessitates resetting
|
|
|
|
* vtxfmt on each flush (otherwise flags won't get reset
|
|
|
|
* afterwards).
|
|
|
|
*/
|
|
|
|
if (attr == 0)
|
2011-02-22 13:24:56 -07:00
|
|
|
ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
|
2006-10-29 09:46:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-10-12 14:16:37 -06:00
|
|
|
/**
|
|
|
|
* Called upon first glVertex, glColor, glTexCoord, etc.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
vbo_exec_begin_vertices(struct gl_context *ctx)
|
|
|
|
{
|
|
|
|
struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
|
|
|
|
|
|
|
|
vbo_exec_vtx_map( exec );
|
|
|
|
|
|
|
|
assert((ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) == 0);
|
|
|
|
assert(exec->begin_vertices_flags);
|
|
|
|
|
|
|
|
ctx->Driver.NeedFlush |= exec->begin_vertices_flags;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-02-21 15:11:44 -07:00
|
|
|
/**
|
|
|
|
* This macro is used to implement all the glVertex, glColor, glTexCoord,
|
|
|
|
* glVertexAttrib, etc functions.
|
2015-10-12 10:52:58 -06:00
|
|
|
* \param A attribute index
|
|
|
|
* \param N attribute size (1..4)
|
|
|
|
* \param T type (GL_FLOAT, GL_DOUBLE, GL_INT, GL_UNSIGNED_INT)
|
|
|
|
* \param C cast type (fi_type or double)
|
|
|
|
* \param V0, V1, v2, V3 attribute value
|
2006-10-29 09:46:11 +00:00
|
|
|
*/
|
2015-02-20 11:41:01 +10:00
|
|
|
#define ATTR_UNION( A, N, T, C, V0, V1, V2, V3 ) \
|
2011-02-21 15:11:44 -07:00
|
|
|
do { \
|
|
|
|
struct vbo_exec_context *exec = &vbo_context(ctx)->exec; \
|
2015-02-20 11:41:01 +10:00
|
|
|
int sz = (sizeof(C) / sizeof(GLfloat)); \
|
2015-10-12 10:53:59 -06:00
|
|
|
\
|
|
|
|
assert(sz == 1 || sz == 2); \
|
|
|
|
\
|
2015-10-12 10:52:58 -06:00
|
|
|
/* check if attribute size or type is changing */ \
|
2015-02-20 11:41:01 +10:00
|
|
|
if (unlikely(exec->vtx.active_sz[A] != N * sz) || \
|
2015-10-12 10:52:58 -06:00
|
|
|
unlikely(exec->vtx.attrtype[A] != T)) { \
|
2015-02-20 11:41:01 +10:00
|
|
|
vbo_exec_fixup_vertex(ctx, A, N * sz, T); \
|
2015-10-12 10:52:58 -06:00
|
|
|
} \
|
2015-02-20 11:41:01 +10:00
|
|
|
\
|
2015-10-12 10:52:58 -06:00
|
|
|
/* store vertex attribute in vertex buffer */ \
|
2011-02-21 15:11:44 -07:00
|
|
|
{ \
|
2015-02-20 11:41:01 +10:00
|
|
|
C *dest = (C *)exec->vtx.attrptr[A]; \
|
2011-02-21 15:11:44 -07:00
|
|
|
if (N>0) dest[0] = V0; \
|
|
|
|
if (N>1) dest[1] = V1; \
|
|
|
|
if (N>2) dest[2] = V2; \
|
|
|
|
if (N>3) dest[3] = V3; \
|
2015-02-25 09:49:45 -07:00
|
|
|
exec->vtx.attrtype[A] = T; \
|
2011-02-21 15:11:44 -07:00
|
|
|
} \
|
|
|
|
\
|
|
|
|
if ((A) == 0) { \
|
|
|
|
/* This is a glVertex call */ \
|
|
|
|
GLuint i; \
|
|
|
|
\
|
vbo: reduce number of vertex buffer mappings for vertex attributes
Whenever we got a glColor, glNormal, glTexCoord, etc. call outside a
glBegin/End pair, we'd immediately map a vertex buffer to begin
accumulating vertex data. In some cases, such as with display lists,
this led to excessive vertex buffer mapping. For example, if we have
a display list such as:
glNewList(42, GL_COMPILE);
glBegin(prim);
glVertex2f();
...
glVertex2f();
glEnd();
glEndList();
Then did:
glColor3f();
glCallList(42);
We'd map a vertex buffer as soon as we saw glColor3f but we'd never
actually write anything to it. Note that the vertex position data
was put into a vertex buffer during display list compilation.
With this change, we delay mapping the vertex buffer until we actually
have a vertex to write to it (triggered by a glVertex() call). In the
above case, we no longer map a vertex buffer when setting the color and
calling the list.
For drivers such as VMware's, reducing buffer mappings gives improved
performance.
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
2015-10-15 12:33:00 -06:00
|
|
|
if (unlikely((ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) == 0)) { \
|
|
|
|
vbo_exec_begin_vertices(ctx); \
|
|
|
|
} \
|
|
|
|
\
|
|
|
|
if (unlikely(!exec->vtx.buffer_ptr)) { \
|
|
|
|
vbo_exec_vtx_map(exec); \
|
|
|
|
} \
|
|
|
|
assert(exec->vtx.buffer_ptr); \
|
|
|
|
\
|
2015-10-12 10:52:58 -06:00
|
|
|
/* copy 32-bit words */ \
|
2011-02-21 15:11:44 -07:00
|
|
|
for (i = 0; i < exec->vtx.vertex_size; i++) \
|
|
|
|
exec->vtx.buffer_ptr[i] = exec->vtx.vertex[i]; \
|
|
|
|
\
|
|
|
|
exec->vtx.buffer_ptr += exec->vtx.vertex_size; \
|
|
|
|
\
|
|
|
|
/* Set FLUSH_STORED_VERTICES to indicate that there's now */ \
|
|
|
|
/* something to draw (not just updating a color or texcoord).*/ \
|
|
|
|
ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; \
|
|
|
|
\
|
|
|
|
if (++exec->vtx.vert_count >= exec->vtx.max_vert) \
|
|
|
|
vbo_exec_vtx_wrap( exec ); \
|
vbo: reduce number of vertex buffer mappings for vertex attributes
Whenever we got a glColor, glNormal, glTexCoord, etc. call outside a
glBegin/End pair, we'd immediately map a vertex buffer to begin
accumulating vertex data. In some cases, such as with display lists,
this led to excessive vertex buffer mapping. For example, if we have
a display list such as:
glNewList(42, GL_COMPILE);
glBegin(prim);
glVertex2f();
...
glVertex2f();
glEnd();
glEndList();
Then did:
glColor3f();
glCallList(42);
We'd map a vertex buffer as soon as we saw glColor3f but we'd never
actually write anything to it. Note that the vertex position data
was put into a vertex buffer during display list compilation.
With this change, we delay mapping the vertex buffer until we actually
have a vertex to write to it (triggered by a glVertex() call). In the
above case, we no longer map a vertex buffer when setting the color and
calling the list.
For drivers such as VMware's, reducing buffer mappings gives improved
performance.
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
2015-10-15 12:33:00 -06:00
|
|
|
} else { \
|
|
|
|
/* we now have accumulated per-vertex attributes */ \
|
|
|
|
ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; \
|
|
|
|
} \
|
2006-10-29 09:46:11 +00:00
|
|
|
} while (0)
|
|
|
|
|
2015-04-03 15:02:33 +03:00
|
|
|
#define ERROR(err) _mesa_error( ctx, err, __func__ )
|
2006-10-29 09:46:11 +00:00
|
|
|
#define TAG(x) vbo_##x
|
|
|
|
|
|
|
|
#include "vbo_attrib_tmp.h"
|
|
|
|
|
|
|
|
|
2012-05-08 11:41:03 -06:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Execute a glMaterial call. Note that if GL_COLOR_MATERIAL is enabled,
|
|
|
|
* this may be a (partial) no-op.
|
|
|
|
*/
|
|
|
|
static void GLAPIENTRY
|
|
|
|
vbo_Materialfv(GLenum face, GLenum pname, const GLfloat *params)
|
|
|
|
{
|
|
|
|
GLbitfield updateMats;
|
|
|
|
GET_CURRENT_CONTEXT(ctx);
|
|
|
|
|
|
|
|
/* This function should be a no-op when it tries to update material
|
|
|
|
* attributes which are currently tracking glColor via glColorMaterial.
|
|
|
|
* The updateMats var will be a mask of the MAT_BIT_FRONT/BACK_x bits
|
|
|
|
* indicating which material attributes can actually be updated below.
|
|
|
|
*/
|
|
|
|
if (ctx->Light.ColorMaterialEnabled) {
|
2012-06-26 14:47:19 -06:00
|
|
|
updateMats = ~ctx->Light._ColorMaterialBitmask;
|
2012-05-08 11:41:03 -06:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* GL_COLOR_MATERIAL is disabled so don't skip any material updates */
|
|
|
|
updateMats = ALL_MATERIAL_BITS;
|
|
|
|
}
|
|
|
|
|
2012-11-27 12:26:51 -08:00
|
|
|
if (ctx->API == API_OPENGL_COMPAT && face == GL_FRONT) {
|
2012-05-08 11:41:03 -06:00
|
|
|
updateMats &= FRONT_MATERIAL_BITS;
|
|
|
|
}
|
2012-11-27 12:26:51 -08:00
|
|
|
else if (ctx->API == API_OPENGL_COMPAT && face == GL_BACK) {
|
2012-05-08 11:41:03 -06:00
|
|
|
updateMats &= BACK_MATERIAL_BITS;
|
|
|
|
}
|
|
|
|
else if (face != GL_FRONT_AND_BACK) {
|
|
|
|
_mesa_error(ctx, GL_INVALID_ENUM, "glMaterial(invalid face)");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (pname) {
|
|
|
|
case GL_EMISSION:
|
|
|
|
if (updateMats & MAT_BIT_FRONT_EMISSION)
|
|
|
|
MAT_ATTR(VBO_ATTRIB_MAT_FRONT_EMISSION, 4, params);
|
|
|
|
if (updateMats & MAT_BIT_BACK_EMISSION)
|
|
|
|
MAT_ATTR(VBO_ATTRIB_MAT_BACK_EMISSION, 4, params);
|
|
|
|
break;
|
|
|
|
case GL_AMBIENT:
|
|
|
|
if (updateMats & MAT_BIT_FRONT_AMBIENT)
|
|
|
|
MAT_ATTR(VBO_ATTRIB_MAT_FRONT_AMBIENT, 4, params);
|
|
|
|
if (updateMats & MAT_BIT_BACK_AMBIENT)
|
|
|
|
MAT_ATTR(VBO_ATTRIB_MAT_BACK_AMBIENT, 4, params);
|
|
|
|
break;
|
|
|
|
case GL_DIFFUSE:
|
|
|
|
if (updateMats & MAT_BIT_FRONT_DIFFUSE)
|
|
|
|
MAT_ATTR(VBO_ATTRIB_MAT_FRONT_DIFFUSE, 4, params);
|
|
|
|
if (updateMats & MAT_BIT_BACK_DIFFUSE)
|
|
|
|
MAT_ATTR(VBO_ATTRIB_MAT_BACK_DIFFUSE, 4, params);
|
|
|
|
break;
|
|
|
|
case GL_SPECULAR:
|
|
|
|
if (updateMats & MAT_BIT_FRONT_SPECULAR)
|
|
|
|
MAT_ATTR(VBO_ATTRIB_MAT_FRONT_SPECULAR, 4, params);
|
|
|
|
if (updateMats & MAT_BIT_BACK_SPECULAR)
|
|
|
|
MAT_ATTR(VBO_ATTRIB_MAT_BACK_SPECULAR, 4, params);
|
|
|
|
break;
|
|
|
|
case GL_SHININESS:
|
|
|
|
if (*params < 0 || *params > ctx->Const.MaxShininess) {
|
|
|
|
_mesa_error(ctx, GL_INVALID_VALUE,
|
|
|
|
"glMaterial(invalid shininess: %f out range [0, %f])",
|
|
|
|
*params, ctx->Const.MaxShininess);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (updateMats & MAT_BIT_FRONT_SHININESS)
|
|
|
|
MAT_ATTR(VBO_ATTRIB_MAT_FRONT_SHININESS, 1, params);
|
|
|
|
if (updateMats & MAT_BIT_BACK_SHININESS)
|
|
|
|
MAT_ATTR(VBO_ATTRIB_MAT_BACK_SHININESS, 1, params);
|
|
|
|
break;
|
|
|
|
case GL_COLOR_INDEXES:
|
2012-11-27 12:26:51 -08:00
|
|
|
if (ctx->API != API_OPENGL_COMPAT) {
|
2012-07-27 16:07:19 -07:00
|
|
|
_mesa_error(ctx, GL_INVALID_ENUM, "glMaterialfv(pname)");
|
|
|
|
return;
|
|
|
|
}
|
2012-05-08 11:41:03 -06:00
|
|
|
if (updateMats & MAT_BIT_FRONT_INDEXES)
|
|
|
|
MAT_ATTR(VBO_ATTRIB_MAT_FRONT_INDEXES, 3, params);
|
|
|
|
if (updateMats & MAT_BIT_BACK_INDEXES)
|
|
|
|
MAT_ATTR(VBO_ATTRIB_MAT_BACK_INDEXES, 3, params);
|
|
|
|
break;
|
|
|
|
case GL_AMBIENT_AND_DIFFUSE:
|
|
|
|
if (updateMats & MAT_BIT_FRONT_AMBIENT)
|
|
|
|
MAT_ATTR(VBO_ATTRIB_MAT_FRONT_AMBIENT, 4, params);
|
|
|
|
if (updateMats & MAT_BIT_FRONT_DIFFUSE)
|
|
|
|
MAT_ATTR(VBO_ATTRIB_MAT_FRONT_DIFFUSE, 4, params);
|
|
|
|
if (updateMats & MAT_BIT_BACK_AMBIENT)
|
|
|
|
MAT_ATTR(VBO_ATTRIB_MAT_BACK_AMBIENT, 4, params);
|
|
|
|
if (updateMats & MAT_BIT_BACK_DIFFUSE)
|
|
|
|
MAT_ATTR(VBO_ATTRIB_MAT_BACK_DIFFUSE, 4, params);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
_mesa_error(ctx, GL_INVALID_ENUM, "glMaterialfv(pname)");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-04-08 22:50:43 +08:00
|
|
|
/**
|
|
|
|
* Flush (draw) vertices.
|
|
|
|
* \param unmap - leave VBO unmapped after flushing?
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
vbo_exec_FlushVertices_internal(struct vbo_exec_context *exec, GLboolean unmap)
|
|
|
|
{
|
|
|
|
if (exec->vtx.vert_count || unmap) {
|
|
|
|
vbo_exec_vtx_flush( exec, unmap );
|
|
|
|
}
|
|
|
|
|
|
|
|
if (exec->vtx.vertex_size) {
|
|
|
|
vbo_exec_copy_to_current( exec );
|
|
|
|
reset_attrfv( exec );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-10-29 09:46:11 +00:00
|
|
|
static void GLAPIENTRY vbo_exec_EvalCoord1f( GLfloat u )
|
|
|
|
{
|
|
|
|
GET_CURRENT_CONTEXT( ctx );
|
|
|
|
struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
|
|
|
|
|
|
|
|
{
|
|
|
|
GLint i;
|
|
|
|
if (exec->eval.recalculate_maps)
|
|
|
|
vbo_exec_eval_update( exec );
|
|
|
|
|
2007-04-06 15:45:11 -06:00
|
|
|
for (i = 0; i <= VBO_ATTRIB_TEX7; i++) {
|
2006-10-29 09:46:11 +00:00
|
|
|
if (exec->eval.map1[i].map)
|
|
|
|
if (exec->vtx.active_sz[i] != exec->eval.map1[i].sz)
|
2015-02-20 11:41:01 +10:00
|
|
|
vbo_exec_fixup_vertex( ctx, i, exec->eval.map1[i].sz, GL_FLOAT );
|
2006-10-29 09:46:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-02-18 23:50:59 -08:00
|
|
|
memcpy( exec->vtx.copied.buffer, exec->vtx.vertex,
|
|
|
|
exec->vtx.vertex_size * sizeof(GLfloat));
|
2006-10-29 09:46:11 +00:00
|
|
|
|
|
|
|
vbo_exec_do_EvalCoord1f( exec, u );
|
|
|
|
|
2010-02-18 23:50:59 -08:00
|
|
|
memcpy( exec->vtx.vertex, exec->vtx.copied.buffer,
|
|
|
|
exec->vtx.vertex_size * sizeof(GLfloat));
|
2006-10-29 09:46:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void GLAPIENTRY vbo_exec_EvalCoord2f( GLfloat u, GLfloat v )
|
|
|
|
{
|
|
|
|
GET_CURRENT_CONTEXT( ctx );
|
|
|
|
struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
|
|
|
|
|
|
|
|
{
|
|
|
|
GLint i;
|
|
|
|
if (exec->eval.recalculate_maps)
|
|
|
|
vbo_exec_eval_update( exec );
|
|
|
|
|
2007-04-06 15:45:11 -06:00
|
|
|
for (i = 0; i <= VBO_ATTRIB_TEX7; i++) {
|
2006-10-29 09:46:11 +00:00
|
|
|
if (exec->eval.map2[i].map)
|
|
|
|
if (exec->vtx.active_sz[i] != exec->eval.map2[i].sz)
|
2015-02-20 11:41:01 +10:00
|
|
|
vbo_exec_fixup_vertex( ctx, i, exec->eval.map2[i].sz, GL_FLOAT );
|
2006-10-29 09:46:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (ctx->Eval.AutoNormal)
|
|
|
|
if (exec->vtx.active_sz[VBO_ATTRIB_NORMAL] != 3)
|
2015-02-20 11:41:01 +10:00
|
|
|
vbo_exec_fixup_vertex( ctx, VBO_ATTRIB_NORMAL, 3, GL_FLOAT );
|
2006-10-29 09:46:11 +00:00
|
|
|
}
|
|
|
|
|
2010-02-18 23:50:59 -08:00
|
|
|
memcpy( exec->vtx.copied.buffer, exec->vtx.vertex,
|
|
|
|
exec->vtx.vertex_size * sizeof(GLfloat));
|
2006-10-29 09:46:11 +00:00
|
|
|
|
|
|
|
vbo_exec_do_EvalCoord2f( exec, u, v );
|
|
|
|
|
2010-02-18 23:50:59 -08:00
|
|
|
memcpy( exec->vtx.vertex, exec->vtx.copied.buffer,
|
|
|
|
exec->vtx.vertex_size * sizeof(GLfloat));
|
2006-10-29 09:46:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void GLAPIENTRY vbo_exec_EvalCoord1fv( const GLfloat *u )
|
|
|
|
{
|
|
|
|
vbo_exec_EvalCoord1f( u[0] );
|
|
|
|
}
|
|
|
|
|
|
|
|
static void GLAPIENTRY vbo_exec_EvalCoord2fv( const GLfloat *u )
|
|
|
|
{
|
|
|
|
vbo_exec_EvalCoord2f( u[0], u[1] );
|
|
|
|
}
|
|
|
|
|
|
|
|
static void GLAPIENTRY vbo_exec_EvalPoint1( GLint i )
|
|
|
|
{
|
|
|
|
GET_CURRENT_CONTEXT( ctx );
|
|
|
|
GLfloat du = ((ctx->Eval.MapGrid1u2 - ctx->Eval.MapGrid1u1) /
|
|
|
|
(GLfloat) ctx->Eval.MapGrid1un);
|
|
|
|
GLfloat u = i * du + ctx->Eval.MapGrid1u1;
|
|
|
|
|
|
|
|
vbo_exec_EvalCoord1f( u );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void GLAPIENTRY vbo_exec_EvalPoint2( GLint i, GLint j )
|
|
|
|
{
|
|
|
|
GET_CURRENT_CONTEXT( ctx );
|
|
|
|
GLfloat du = ((ctx->Eval.MapGrid2u2 - ctx->Eval.MapGrid2u1) /
|
|
|
|
(GLfloat) ctx->Eval.MapGrid2un);
|
|
|
|
GLfloat dv = ((ctx->Eval.MapGrid2v2 - ctx->Eval.MapGrid2v1) /
|
|
|
|
(GLfloat) ctx->Eval.MapGrid2vn);
|
|
|
|
GLfloat u = i * du + ctx->Eval.MapGrid2u1;
|
|
|
|
GLfloat v = j * dv + ctx->Eval.MapGrid2v1;
|
|
|
|
|
|
|
|
vbo_exec_EvalCoord2f( u, v );
|
|
|
|
}
|
|
|
|
|
2011-11-09 17:35:57 -07:00
|
|
|
|
2009-10-22 09:37:56 -06:00
|
|
|
/**
|
|
|
|
* Called via glBegin.
|
2006-10-29 09:46:11 +00:00
|
|
|
*/
|
|
|
|
static void GLAPIENTRY vbo_exec_Begin( GLenum mode )
|
|
|
|
{
|
|
|
|
GET_CURRENT_CONTEXT( ctx );
|
2013-01-16 15:01:10 -08:00
|
|
|
struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
|
|
|
|
int i;
|
2006-10-29 09:46:11 +00:00
|
|
|
|
2013-04-23 10:53:00 -06:00
|
|
|
if (_mesa_inside_begin_end(ctx)) {
|
2013-01-16 15:01:10 -08:00
|
|
|
_mesa_error(ctx, GL_INVALID_OPERATION, "glBegin");
|
|
|
|
return;
|
|
|
|
}
|
2006-10-29 09:46:11 +00:00
|
|
|
|
2013-01-16 15:01:10 -08:00
|
|
|
if (!_mesa_valid_prim_mode(ctx, mode, "glBegin")) {
|
|
|
|
return;
|
|
|
|
}
|
2011-09-21 08:22:07 -06:00
|
|
|
|
2013-01-16 15:01:10 -08:00
|
|
|
vbo_draw_method(vbo_context(ctx), DRAW_BEGIN_END);
|
2011-12-26 14:43:07 -07:00
|
|
|
|
2013-01-16 15:01:10 -08:00
|
|
|
if (ctx->NewState) {
|
|
|
|
_mesa_update_state( ctx );
|
2006-10-29 09:46:11 +00:00
|
|
|
|
2013-01-16 15:01:10 -08:00
|
|
|
CALL_Begin(ctx->Exec, (mode));
|
|
|
|
return;
|
|
|
|
}
|
2006-10-29 09:46:11 +00:00
|
|
|
|
2013-01-16 15:01:10 -08:00
|
|
|
if (!_mesa_valid_to_render(ctx, "glBegin")) {
|
|
|
|
return;
|
|
|
|
}
|
2008-02-20 08:54:15 -07:00
|
|
|
|
2015-04-22 11:33:17 +01:00
|
|
|
/* Heuristic: attempt to isolate attributes occurring outside
|
2013-01-16 15:01:10 -08:00
|
|
|
* begin/end pairs.
|
|
|
|
*/
|
|
|
|
if (exec->vtx.vertex_size && !exec->vtx.attrsz[0])
|
|
|
|
vbo_exec_FlushVertices_internal(exec, GL_FALSE);
|
|
|
|
|
|
|
|
i = exec->vtx.prim_count++;
|
|
|
|
exec->vtx.prim[i].mode = mode;
|
|
|
|
exec->vtx.prim[i].begin = 1;
|
|
|
|
exec->vtx.prim[i].end = 0;
|
|
|
|
exec->vtx.prim[i].indexed = 0;
|
|
|
|
exec->vtx.prim[i].weak = 0;
|
|
|
|
exec->vtx.prim[i].pad = 0;
|
|
|
|
exec->vtx.prim[i].start = exec->vtx.vert_count;
|
|
|
|
exec->vtx.prim[i].count = 0;
|
|
|
|
exec->vtx.prim[i].num_instances = 1;
|
|
|
|
exec->vtx.prim[i].base_instance = 0;
|
2013-11-16 16:38:57 +13:00
|
|
|
exec->vtx.prim[i].is_indirect = 0;
|
2013-01-16 15:01:10 -08:00
|
|
|
|
|
|
|
ctx->Driver.CurrentExecPrimitive = mode;
|
2013-01-16 15:20:45 -08:00
|
|
|
|
|
|
|
ctx->Exec = ctx->BeginEnd;
|
|
|
|
/* We may have been called from a display list, in which case we should
|
|
|
|
* leave dlist.c's dispatch table in place.
|
|
|
|
*/
|
|
|
|
if (ctx->CurrentDispatch == ctx->OutsideBeginEnd) {
|
|
|
|
ctx->CurrentDispatch = ctx->BeginEnd;
|
|
|
|
_glapi_set_dispatch(ctx->CurrentDispatch);
|
|
|
|
} else {
|
|
|
|
assert(ctx->CurrentDispatch == ctx->Save);
|
|
|
|
}
|
2006-10-29 09:46:11 +00:00
|
|
|
}
|
|
|
|
|
2009-10-22 09:37:56 -06:00
|
|
|
|
2013-05-03 19:00:07 -06:00
|
|
|
/**
|
|
|
|
* Try to merge / concatenate the two most recent VBO primitives.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
try_vbo_merge(struct vbo_exec_context *exec)
|
|
|
|
{
|
|
|
|
struct _mesa_prim *cur = &exec->vtx.prim[exec->vtx.prim_count - 1];
|
|
|
|
|
|
|
|
assert(exec->vtx.prim_count >= 1);
|
|
|
|
|
|
|
|
vbo_try_prim_conversion(cur);
|
|
|
|
|
|
|
|
if (exec->vtx.prim_count >= 2) {
|
|
|
|
struct _mesa_prim *prev = &exec->vtx.prim[exec->vtx.prim_count - 2];
|
|
|
|
assert(prev == cur - 1);
|
|
|
|
|
|
|
|
if (vbo_can_merge_prims(prev, cur)) {
|
|
|
|
assert(cur->begin);
|
|
|
|
assert(cur->end);
|
|
|
|
assert(prev->begin);
|
|
|
|
assert(prev->end);
|
|
|
|
vbo_merge_prims(prev, cur);
|
|
|
|
exec->vtx.prim_count--; /* drop the last primitive */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-10-22 09:37:56 -06:00
|
|
|
/**
|
|
|
|
* Called via glEnd.
|
|
|
|
*/
|
2006-10-29 09:46:11 +00:00
|
|
|
static void GLAPIENTRY vbo_exec_End( void )
|
|
|
|
{
|
|
|
|
GET_CURRENT_CONTEXT( ctx );
|
2013-01-16 15:01:10 -08:00
|
|
|
struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
|
2006-10-29 09:46:11 +00:00
|
|
|
|
2013-04-23 10:53:00 -06:00
|
|
|
if (!_mesa_inside_begin_end(ctx)) {
|
2013-01-16 15:01:10 -08:00
|
|
|
_mesa_error(ctx, GL_INVALID_OPERATION, "glEnd");
|
|
|
|
return;
|
|
|
|
}
|
2006-10-29 09:46:11 +00:00
|
|
|
|
2013-01-16 15:20:45 -08:00
|
|
|
ctx->Exec = ctx->OutsideBeginEnd;
|
|
|
|
if (ctx->CurrentDispatch == ctx->BeginEnd) {
|
|
|
|
ctx->CurrentDispatch = ctx->OutsideBeginEnd;
|
|
|
|
_glapi_set_dispatch(ctx->CurrentDispatch);
|
|
|
|
}
|
|
|
|
|
2013-01-16 15:01:10 -08:00
|
|
|
if (exec->vtx.prim_count > 0) {
|
|
|
|
/* close off current primitive */
|
2015-10-15 20:33:52 -06:00
|
|
|
struct _mesa_prim *last_prim = &exec->vtx.prim[exec->vtx.prim_count - 1];
|
2011-06-08 08:05:41 -06:00
|
|
|
|
2015-10-15 20:33:52 -06:00
|
|
|
last_prim->end = 1;
|
|
|
|
last_prim->count = exec->vtx.vert_count - last_prim->start;
|
2013-05-03 19:00:07 -06:00
|
|
|
|
2015-10-15 22:31:50 -06:00
|
|
|
/* Special handling for GL_LINE_LOOP */
|
|
|
|
if (last_prim->mode == GL_LINE_LOOP && last_prim->begin == 0) {
|
|
|
|
/* We're finishing drawing a line loop. Append 0th vertex onto
|
|
|
|
* end of vertex buffer so we can draw it as a line strip.
|
|
|
|
*/
|
|
|
|
const fi_type *src = exec->vtx.buffer_map;
|
|
|
|
fi_type *dst = exec->vtx.buffer_map +
|
|
|
|
exec->vtx.vert_count * exec->vtx.vertex_size;
|
|
|
|
|
|
|
|
/* copy 0th vertex to end of buffer */
|
|
|
|
memcpy(dst, src, exec->vtx.vertex_size * sizeof(fi_type));
|
|
|
|
|
|
|
|
assert(last_prim->start == 0);
|
|
|
|
last_prim->start++; /* skip vertex0 */
|
|
|
|
/* note that last_prim->count stays unchanged */
|
|
|
|
last_prim->mode = GL_LINE_STRIP;
|
|
|
|
}
|
|
|
|
|
2013-05-03 19:00:07 -06:00
|
|
|
try_vbo_merge(exec);
|
2013-01-16 15:01:10 -08:00
|
|
|
}
|
2006-10-29 09:46:11 +00:00
|
|
|
|
2013-01-16 15:01:10 -08:00
|
|
|
ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END;
|
2006-10-29 09:46:11 +00:00
|
|
|
|
2013-01-16 15:01:10 -08:00
|
|
|
if (exec->vtx.prim_count == VBO_MAX_PRIM)
|
|
|
|
vbo_exec_vtx_flush( exec, GL_FALSE );
|
2012-05-09 12:08:47 -06:00
|
|
|
|
|
|
|
if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
|
|
|
|
_mesa_flush(ctx);
|
|
|
|
}
|
2006-10-29 09:46:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-10-21 19:03:38 -06:00
|
|
|
/**
|
|
|
|
* Called via glPrimitiveRestartNV()
|
|
|
|
*/
|
|
|
|
static void GLAPIENTRY
|
|
|
|
vbo_exec_PrimitiveRestartNV(void)
|
|
|
|
{
|
|
|
|
GLenum curPrim;
|
|
|
|
GET_CURRENT_CONTEXT( ctx );
|
|
|
|
|
|
|
|
curPrim = ctx->Driver.CurrentExecPrimitive;
|
|
|
|
|
|
|
|
if (curPrim == PRIM_OUTSIDE_BEGIN_END) {
|
|
|
|
_mesa_error( ctx, GL_INVALID_OPERATION, "glPrimitiveRestartNV" );
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
vbo_exec_End();
|
|
|
|
vbo_exec_Begin(curPrim);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2006-10-29 09:46:11 +00:00
|
|
|
static void vbo_exec_vtxfmt_init( struct vbo_exec_context *exec )
|
|
|
|
{
|
2012-07-28 15:20:48 -07:00
|
|
|
struct gl_context *ctx = exec->ctx;
|
2006-10-29 09:46:11 +00:00
|
|
|
GLvertexformat *vfmt = &exec->vtxfmt;
|
|
|
|
|
2013-05-01 19:15:32 -06:00
|
|
|
vfmt->ArrayElement = _ae_ArrayElement;
|
2009-09-08 14:32:08 +08:00
|
|
|
|
2006-10-29 09:46:11 +00:00
|
|
|
vfmt->Begin = vbo_exec_Begin;
|
|
|
|
vfmt->End = vbo_exec_End;
|
2010-10-21 19:03:38 -06:00
|
|
|
vfmt->PrimitiveRestartNV = vbo_exec_PrimitiveRestartNV;
|
2006-10-29 09:46:11 +00:00
|
|
|
|
2013-05-01 19:15:32 -06:00
|
|
|
vfmt->CallList = _mesa_CallList;
|
|
|
|
vfmt->CallLists = _mesa_CallLists;
|
|
|
|
|
2013-05-01 19:15:33 -06:00
|
|
|
vfmt->EvalCoord1f = vbo_exec_EvalCoord1f;
|
|
|
|
vfmt->EvalCoord1fv = vbo_exec_EvalCoord1fv;
|
|
|
|
vfmt->EvalCoord2f = vbo_exec_EvalCoord2f;
|
|
|
|
vfmt->EvalCoord2fv = vbo_exec_EvalCoord2fv;
|
|
|
|
vfmt->EvalPoint1 = vbo_exec_EvalPoint1;
|
|
|
|
vfmt->EvalPoint2 = vbo_exec_EvalPoint2;
|
2006-10-29 09:46:11 +00:00
|
|
|
|
|
|
|
/* from attrib_tmp.h:
|
|
|
|
*/
|
|
|
|
vfmt->Color3f = vbo_Color3f;
|
|
|
|
vfmt->Color3fv = vbo_Color3fv;
|
|
|
|
vfmt->Color4f = vbo_Color4f;
|
|
|
|
vfmt->Color4fv = vbo_Color4fv;
|
|
|
|
vfmt->FogCoordfEXT = vbo_FogCoordfEXT;
|
|
|
|
vfmt->FogCoordfvEXT = vbo_FogCoordfvEXT;
|
|
|
|
vfmt->MultiTexCoord1fARB = vbo_MultiTexCoord1f;
|
|
|
|
vfmt->MultiTexCoord1fvARB = vbo_MultiTexCoord1fv;
|
|
|
|
vfmt->MultiTexCoord2fARB = vbo_MultiTexCoord2f;
|
|
|
|
vfmt->MultiTexCoord2fvARB = vbo_MultiTexCoord2fv;
|
|
|
|
vfmt->MultiTexCoord3fARB = vbo_MultiTexCoord3f;
|
|
|
|
vfmt->MultiTexCoord3fvARB = vbo_MultiTexCoord3fv;
|
|
|
|
vfmt->MultiTexCoord4fARB = vbo_MultiTexCoord4f;
|
|
|
|
vfmt->MultiTexCoord4fvARB = vbo_MultiTexCoord4fv;
|
|
|
|
vfmt->Normal3f = vbo_Normal3f;
|
|
|
|
vfmt->Normal3fv = vbo_Normal3fv;
|
|
|
|
vfmt->SecondaryColor3fEXT = vbo_SecondaryColor3fEXT;
|
|
|
|
vfmt->SecondaryColor3fvEXT = vbo_SecondaryColor3fvEXT;
|
|
|
|
vfmt->TexCoord1f = vbo_TexCoord1f;
|
|
|
|
vfmt->TexCoord1fv = vbo_TexCoord1fv;
|
|
|
|
vfmt->TexCoord2f = vbo_TexCoord2f;
|
|
|
|
vfmt->TexCoord2fv = vbo_TexCoord2fv;
|
|
|
|
vfmt->TexCoord3f = vbo_TexCoord3f;
|
|
|
|
vfmt->TexCoord3fv = vbo_TexCoord3fv;
|
|
|
|
vfmt->TexCoord4f = vbo_TexCoord4f;
|
|
|
|
vfmt->TexCoord4fv = vbo_TexCoord4fv;
|
|
|
|
vfmt->Vertex2f = vbo_Vertex2f;
|
|
|
|
vfmt->Vertex2fv = vbo_Vertex2fv;
|
|
|
|
vfmt->Vertex3f = vbo_Vertex3f;
|
|
|
|
vfmt->Vertex3fv = vbo_Vertex3fv;
|
|
|
|
vfmt->Vertex4f = vbo_Vertex4f;
|
|
|
|
vfmt->Vertex4fv = vbo_Vertex4fv;
|
|
|
|
|
2012-07-28 15:20:48 -07:00
|
|
|
if (ctx->API == API_OPENGLES2) {
|
|
|
|
vfmt->VertexAttrib1fARB = _es_VertexAttrib1f;
|
|
|
|
vfmt->VertexAttrib1fvARB = _es_VertexAttrib1fv;
|
|
|
|
vfmt->VertexAttrib2fARB = _es_VertexAttrib2f;
|
|
|
|
vfmt->VertexAttrib2fvARB = _es_VertexAttrib2fv;
|
|
|
|
vfmt->VertexAttrib3fARB = _es_VertexAttrib3f;
|
|
|
|
vfmt->VertexAttrib3fvARB = _es_VertexAttrib3fv;
|
|
|
|
vfmt->VertexAttrib4fARB = _es_VertexAttrib4f;
|
|
|
|
vfmt->VertexAttrib4fvARB = _es_VertexAttrib4fv;
|
|
|
|
} else {
|
|
|
|
vfmt->VertexAttrib1fARB = vbo_VertexAttrib1fARB;
|
|
|
|
vfmt->VertexAttrib1fvARB = vbo_VertexAttrib1fvARB;
|
|
|
|
vfmt->VertexAttrib2fARB = vbo_VertexAttrib2fARB;
|
|
|
|
vfmt->VertexAttrib2fvARB = vbo_VertexAttrib2fvARB;
|
|
|
|
vfmt->VertexAttrib3fARB = vbo_VertexAttrib3fARB;
|
|
|
|
vfmt->VertexAttrib3fvARB = vbo_VertexAttrib3fvARB;
|
|
|
|
vfmt->VertexAttrib4fARB = vbo_VertexAttrib4fARB;
|
|
|
|
vfmt->VertexAttrib4fvARB = vbo_VertexAttrib4fvARB;
|
|
|
|
}
|
2006-10-29 09:46:11 +00:00
|
|
|
|
2012-10-09 16:38:56 -07:00
|
|
|
/* Note that VertexAttrib4fNV is used from dlist.c and api_arrayelt.c so
|
|
|
|
* they can have a single entrypoint for updating any of the legacy
|
|
|
|
* attribs.
|
|
|
|
*/
|
2006-10-29 09:46:11 +00:00
|
|
|
vfmt->VertexAttrib1fNV = vbo_VertexAttrib1fNV;
|
|
|
|
vfmt->VertexAttrib1fvNV = vbo_VertexAttrib1fvNV;
|
|
|
|
vfmt->VertexAttrib2fNV = vbo_VertexAttrib2fNV;
|
|
|
|
vfmt->VertexAttrib2fvNV = vbo_VertexAttrib2fvNV;
|
|
|
|
vfmt->VertexAttrib3fNV = vbo_VertexAttrib3fNV;
|
|
|
|
vfmt->VertexAttrib3fvNV = vbo_VertexAttrib3fvNV;
|
|
|
|
vfmt->VertexAttrib4fNV = vbo_VertexAttrib4fNV;
|
|
|
|
vfmt->VertexAttrib4fvNV = vbo_VertexAttrib4fvNV;
|
|
|
|
|
2010-10-28 21:17:41 -06:00
|
|
|
/* integer-valued */
|
|
|
|
vfmt->VertexAttribI1i = vbo_VertexAttribI1i;
|
|
|
|
vfmt->VertexAttribI2i = vbo_VertexAttribI2i;
|
|
|
|
vfmt->VertexAttribI3i = vbo_VertexAttribI3i;
|
|
|
|
vfmt->VertexAttribI4i = vbo_VertexAttribI4i;
|
|
|
|
vfmt->VertexAttribI2iv = vbo_VertexAttribI2iv;
|
|
|
|
vfmt->VertexAttribI3iv = vbo_VertexAttribI3iv;
|
|
|
|
vfmt->VertexAttribI4iv = vbo_VertexAttribI4iv;
|
|
|
|
|
|
|
|
/* unsigned integer-valued */
|
|
|
|
vfmt->VertexAttribI1ui = vbo_VertexAttribI1ui;
|
|
|
|
vfmt->VertexAttribI2ui = vbo_VertexAttribI2ui;
|
|
|
|
vfmt->VertexAttribI3ui = vbo_VertexAttribI3ui;
|
|
|
|
vfmt->VertexAttribI4ui = vbo_VertexAttribI4ui;
|
|
|
|
vfmt->VertexAttribI2uiv = vbo_VertexAttribI2uiv;
|
|
|
|
vfmt->VertexAttribI3uiv = vbo_VertexAttribI3uiv;
|
|
|
|
vfmt->VertexAttribI4uiv = vbo_VertexAttribI4uiv;
|
|
|
|
|
2006-10-29 09:46:11 +00:00
|
|
|
vfmt->Materialfv = vbo_Materialfv;
|
|
|
|
|
|
|
|
vfmt->EdgeFlag = vbo_EdgeFlag;
|
|
|
|
vfmt->Indexf = vbo_Indexf;
|
|
|
|
vfmt->Indexfv = vbo_Indexfv;
|
|
|
|
|
2011-09-04 09:04:13 +01:00
|
|
|
/* ARB_vertex_type_2_10_10_10_rev */
|
|
|
|
vfmt->VertexP2ui = vbo_VertexP2ui;
|
|
|
|
vfmt->VertexP2uiv = vbo_VertexP2uiv;
|
|
|
|
vfmt->VertexP3ui = vbo_VertexP3ui;
|
|
|
|
vfmt->VertexP3uiv = vbo_VertexP3uiv;
|
|
|
|
vfmt->VertexP4ui = vbo_VertexP4ui;
|
|
|
|
vfmt->VertexP4uiv = vbo_VertexP4uiv;
|
|
|
|
|
|
|
|
vfmt->TexCoordP1ui = vbo_TexCoordP1ui;
|
|
|
|
vfmt->TexCoordP1uiv = vbo_TexCoordP1uiv;
|
|
|
|
vfmt->TexCoordP2ui = vbo_TexCoordP2ui;
|
|
|
|
vfmt->TexCoordP2uiv = vbo_TexCoordP2uiv;
|
|
|
|
vfmt->TexCoordP3ui = vbo_TexCoordP3ui;
|
|
|
|
vfmt->TexCoordP3uiv = vbo_TexCoordP3uiv;
|
|
|
|
vfmt->TexCoordP4ui = vbo_TexCoordP4ui;
|
|
|
|
vfmt->TexCoordP4uiv = vbo_TexCoordP4uiv;
|
|
|
|
|
|
|
|
vfmt->MultiTexCoordP1ui = vbo_MultiTexCoordP1ui;
|
|
|
|
vfmt->MultiTexCoordP1uiv = vbo_MultiTexCoordP1uiv;
|
|
|
|
vfmt->MultiTexCoordP2ui = vbo_MultiTexCoordP2ui;
|
|
|
|
vfmt->MultiTexCoordP2uiv = vbo_MultiTexCoordP2uiv;
|
|
|
|
vfmt->MultiTexCoordP3ui = vbo_MultiTexCoordP3ui;
|
|
|
|
vfmt->MultiTexCoordP3uiv = vbo_MultiTexCoordP3uiv;
|
|
|
|
vfmt->MultiTexCoordP4ui = vbo_MultiTexCoordP4ui;
|
|
|
|
vfmt->MultiTexCoordP4uiv = vbo_MultiTexCoordP4uiv;
|
|
|
|
|
|
|
|
vfmt->NormalP3ui = vbo_NormalP3ui;
|
|
|
|
vfmt->NormalP3uiv = vbo_NormalP3uiv;
|
|
|
|
|
|
|
|
vfmt->ColorP3ui = vbo_ColorP3ui;
|
|
|
|
vfmt->ColorP3uiv = vbo_ColorP3uiv;
|
|
|
|
vfmt->ColorP4ui = vbo_ColorP4ui;
|
|
|
|
vfmt->ColorP4uiv = vbo_ColorP4uiv;
|
|
|
|
|
|
|
|
vfmt->SecondaryColorP3ui = vbo_SecondaryColorP3ui;
|
|
|
|
vfmt->SecondaryColorP3uiv = vbo_SecondaryColorP3uiv;
|
|
|
|
|
|
|
|
vfmt->VertexAttribP1ui = vbo_VertexAttribP1ui;
|
|
|
|
vfmt->VertexAttribP1uiv = vbo_VertexAttribP1uiv;
|
|
|
|
vfmt->VertexAttribP2ui = vbo_VertexAttribP2ui;
|
|
|
|
vfmt->VertexAttribP2uiv = vbo_VertexAttribP2uiv;
|
|
|
|
vfmt->VertexAttribP3ui = vbo_VertexAttribP3ui;
|
|
|
|
vfmt->VertexAttribP3uiv = vbo_VertexAttribP3uiv;
|
|
|
|
vfmt->VertexAttribP4ui = vbo_VertexAttribP4ui;
|
|
|
|
vfmt->VertexAttribP4uiv = vbo_VertexAttribP4uiv;
|
2015-02-20 11:41:01 +10:00
|
|
|
|
|
|
|
vfmt->VertexAttribL1d = vbo_VertexAttribL1d;
|
|
|
|
vfmt->VertexAttribL2d = vbo_VertexAttribL2d;
|
|
|
|
vfmt->VertexAttribL3d = vbo_VertexAttribL3d;
|
|
|
|
vfmt->VertexAttribL4d = vbo_VertexAttribL4d;
|
|
|
|
|
|
|
|
vfmt->VertexAttribL1dv = vbo_VertexAttribL1dv;
|
|
|
|
vfmt->VertexAttribL2dv = vbo_VertexAttribL2dv;
|
|
|
|
vfmt->VertexAttribL3dv = vbo_VertexAttribL3dv;
|
|
|
|
vfmt->VertexAttribL4dv = vbo_VertexAttribL4dv;
|
2006-10-29 09:46:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-08-17 15:26:33 +01:00
|
|
|
/**
|
|
|
|
* Tell the VBO module to use a real OpenGL vertex buffer object to
|
|
|
|
* store accumulated immediate-mode vertex data.
|
|
|
|
* This replaces the malloced buffer which was created in
|
|
|
|
* vb_exec_vtx_init() below.
|
|
|
|
*/
|
2010-10-12 12:26:10 -04:00
|
|
|
void vbo_use_buffer_objects(struct gl_context *ctx)
|
2007-08-17 15:26:33 +01:00
|
|
|
{
|
|
|
|
struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
|
|
|
|
/* Any buffer name but 0 can be used here since this bufferobj won't
|
|
|
|
* go into the bufferobj hashtable.
|
|
|
|
*/
|
2009-06-10 13:00:35 -06:00
|
|
|
GLuint bufName = IMM_BUFFER_NAME;
|
2007-08-17 15:26:33 +01:00
|
|
|
GLenum target = GL_ARRAY_BUFFER_ARB;
|
|
|
|
GLenum usage = GL_STREAM_DRAW_ARB;
|
2009-03-03 10:46:12 +00:00
|
|
|
GLsizei size = VBO_VERT_BUFFER_SIZE;
|
2007-08-17 15:26:33 +01:00
|
|
|
|
|
|
|
/* Make sure this func is only used once */
|
2009-05-07 13:30:39 -06:00
|
|
|
assert(exec->vtx.bufferobj == ctx->Shared->NullBufferObj);
|
2013-12-03 21:50:00 -07:00
|
|
|
|
|
|
|
_mesa_align_free(exec->vtx.buffer_map);
|
|
|
|
exec->vtx.buffer_map = NULL;
|
|
|
|
exec->vtx.buffer_ptr = NULL;
|
2007-08-17 15:26:33 +01:00
|
|
|
|
|
|
|
/* Allocate a real buffer object now */
|
2010-02-09 14:25:41 +01:00
|
|
|
_mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL);
|
2014-10-15 13:00:39 -07:00
|
|
|
exec->vtx.bufferobj = ctx->Driver.NewBufferObject(ctx, bufName);
|
2014-01-27 21:15:19 +01:00
|
|
|
if (!ctx->Driver.BufferData(ctx, target, size, NULL, usage,
|
|
|
|
GL_MAP_WRITE_BIT |
|
|
|
|
GL_DYNAMIC_STORAGE_BIT |
|
|
|
|
GL_CLIENT_STORAGE_BIT,
|
|
|
|
exec->vtx.bufferobj)) {
|
2011-11-10 09:47:37 -07:00
|
|
|
_mesa_error(ctx, GL_OUT_OF_MEMORY, "VBO allocation");
|
|
|
|
}
|
2007-08-17 15:26:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-03-01 17:16:53 -07:00
|
|
|
/**
|
|
|
|
* If this function is called, all VBO buffers will be unmapped when
|
|
|
|
* we flush.
|
|
|
|
* Otherwise, if a simple command like glColor3f() is called and we flush,
|
|
|
|
* the current VBO may be left mapped.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
vbo_always_unmap_buffers(struct gl_context *ctx)
|
|
|
|
{
|
|
|
|
struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
|
|
|
|
exec->begin_vertices_flags |= FLUSH_STORED_VERTICES;
|
|
|
|
}
|
|
|
|
|
2007-08-17 15:26:33 +01:00
|
|
|
|
2006-10-29 09:46:11 +00:00
|
|
|
void vbo_exec_vtx_init( struct vbo_exec_context *exec )
|
|
|
|
{
|
2010-10-12 12:26:10 -04:00
|
|
|
struct gl_context *ctx = exec->ctx;
|
2006-10-30 20:16:35 +00:00
|
|
|
struct vbo_context *vbo = vbo_context(ctx);
|
2006-10-29 09:46:11 +00:00
|
|
|
GLuint i;
|
|
|
|
|
|
|
|
/* Allocate a buffer object. Will just reuse this object
|
2007-08-20 11:05:35 -06:00
|
|
|
* continuously, unless vbo_use_buffer_objects() is called to enable
|
|
|
|
* use of real VBOs.
|
2006-10-29 09:46:11 +00:00
|
|
|
*/
|
2008-09-04 14:58:02 -06:00
|
|
|
_mesa_reference_buffer_object(ctx,
|
|
|
|
&exec->vtx.bufferobj,
|
2009-05-07 13:30:39 -06:00
|
|
|
ctx->Shared->NullBufferObj);
|
2008-09-04 14:58:02 -06:00
|
|
|
|
2015-02-20 20:18:47 -08:00
|
|
|
assert(!exec->vtx.buffer_map);
|
2012-09-03 19:44:00 -07:00
|
|
|
exec->vtx.buffer_map = _mesa_align_malloc(VBO_VERT_BUFFER_SIZE, 64);
|
2009-03-04 17:01:47 +00:00
|
|
|
exec->vtx.buffer_ptr = exec->vtx.buffer_map;
|
2006-10-29 09:46:11 +00:00
|
|
|
|
|
|
|
vbo_exec_vtxfmt_init( exec );
|
2011-11-10 09:47:37 -07:00
|
|
|
_mesa_noop_vtxfmt_init(&exec->vtxfmt_noop);
|
2006-10-29 09:46:11 +00:00
|
|
|
|
|
|
|
for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
|
2015-02-28 08:57:15 -07:00
|
|
|
assert(i < ARRAY_SIZE(exec->vtx.attrsz));
|
2006-10-29 09:46:11 +00:00
|
|
|
exec->vtx.attrsz[i] = 0;
|
2015-02-28 08:57:15 -07:00
|
|
|
assert(i < ARRAY_SIZE(exec->vtx.attrtype));
|
2012-10-30 14:44:22 +01:00
|
|
|
exec->vtx.attrtype[i] = GL_FLOAT;
|
2015-02-28 08:57:15 -07:00
|
|
|
assert(i < ARRAY_SIZE(exec->vtx.active_sz));
|
2006-10-29 09:46:11 +00:00
|
|
|
exec->vtx.active_sz[i] = 0;
|
2009-11-04 17:51:21 -07:00
|
|
|
}
|
|
|
|
for (i = 0 ; i < VERT_ATTRIB_MAX; i++) {
|
2015-02-28 08:57:15 -07:00
|
|
|
assert(i < ARRAY_SIZE(exec->vtx.inputs));
|
|
|
|
assert(i < ARRAY_SIZE(exec->vtx.arrays));
|
2006-10-29 09:46:11 +00:00
|
|
|
exec->vtx.inputs[i] = &exec->vtx.arrays[i];
|
|
|
|
}
|
2006-10-30 20:16:35 +00:00
|
|
|
|
|
|
|
{
|
|
|
|
struct gl_client_array *arrays = exec->vtx.arrays;
|
2010-02-09 14:25:41 +01:00
|
|
|
unsigned i;
|
|
|
|
|
2012-04-16 16:24:39 +02:00
|
|
|
memcpy(arrays, &vbo->currval[VBO_ATTRIB_POS],
|
2011-10-31 16:23:40 +01:00
|
|
|
VERT_ATTRIB_FF_MAX * sizeof(arrays[0]));
|
|
|
|
for (i = 0; i < VERT_ATTRIB_FF_MAX; ++i) {
|
|
|
|
struct gl_client_array *array;
|
|
|
|
array = &arrays[VERT_ATTRIB_FF(i)];
|
|
|
|
array->BufferObj = NULL;
|
2014-09-14 23:45:38 -07:00
|
|
|
_mesa_reference_buffer_object(ctx, &array->BufferObj,
|
2012-04-16 16:24:39 +02:00
|
|
|
vbo->currval[VBO_ATTRIB_POS+i].BufferObj);
|
2011-10-31 16:23:40 +01:00
|
|
|
}
|
|
|
|
|
2012-04-16 16:35:58 +02:00
|
|
|
memcpy(arrays + VERT_ATTRIB_GENERIC(0),
|
|
|
|
&vbo->currval[VBO_ATTRIB_GENERIC0],
|
2011-10-31 16:23:40 +01:00
|
|
|
VERT_ATTRIB_GENERIC_MAX * sizeof(arrays[0]));
|
2012-04-16 16:35:58 +02:00
|
|
|
|
2011-10-31 16:23:40 +01:00
|
|
|
for (i = 0; i < VERT_ATTRIB_GENERIC_MAX; ++i) {
|
|
|
|
struct gl_client_array *array;
|
|
|
|
array = &arrays[VERT_ATTRIB_GENERIC(i)];
|
|
|
|
array->BufferObj = NULL;
|
|
|
|
_mesa_reference_buffer_object(ctx, &array->BufferObj,
|
2012-04-16 16:35:58 +02:00
|
|
|
vbo->currval[VBO_ATTRIB_GENERIC0+i].BufferObj);
|
2010-02-09 14:25:41 +01:00
|
|
|
}
|
2006-10-30 20:16:35 +00:00
|
|
|
}
|
|
|
|
|
2006-10-29 09:46:11 +00:00
|
|
|
exec->vtx.vertex_size = 0;
|
2011-03-01 17:16:53 -07:00
|
|
|
|
|
|
|
exec->begin_vertices_flags = FLUSH_UPDATE_CURRENT;
|
2006-10-29 09:46:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void vbo_exec_vtx_destroy( struct vbo_exec_context *exec )
|
|
|
|
{
|
2009-06-08 16:11:29 +01:00
|
|
|
/* using a real VBO for vertex data */
|
2010-10-12 12:26:10 -04:00
|
|
|
struct gl_context *ctx = exec->ctx;
|
2009-06-08 16:11:29 +01:00
|
|
|
unsigned i;
|
|
|
|
|
|
|
|
/* True VBOs should already be unmapped
|
|
|
|
*/
|
|
|
|
if (exec->vtx.buffer_map) {
|
2015-02-20 20:18:47 -08:00
|
|
|
assert(exec->vtx.bufferobj->Name == 0 ||
|
2009-06-10 13:00:35 -06:00
|
|
|
exec->vtx.bufferobj->Name == IMM_BUFFER_NAME);
|
2009-06-08 16:11:29 +01:00
|
|
|
if (exec->vtx.bufferobj->Name == 0) {
|
2010-02-19 13:16:57 -05:00
|
|
|
_mesa_align_free(exec->vtx.buffer_map);
|
2008-09-25 11:03:46 -06:00
|
|
|
exec->vtx.buffer_map = NULL;
|
2009-03-04 17:01:47 +00:00
|
|
|
exec->vtx.buffer_ptr = NULL;
|
2008-09-25 11:03:46 -06:00
|
|
|
}
|
2006-10-29 09:46:11 +00:00
|
|
|
}
|
2009-06-08 16:11:29 +01:00
|
|
|
|
|
|
|
/* Drop any outstanding reference to the vertex buffer
|
|
|
|
*/
|
2015-02-28 08:57:15 -07:00
|
|
|
for (i = 0; i < ARRAY_SIZE(exec->vtx.arrays); i++) {
|
2009-06-08 16:11:29 +01:00
|
|
|
_mesa_reference_buffer_object(ctx,
|
|
|
|
&exec->vtx.arrays[i].BufferObj,
|
|
|
|
NULL);
|
|
|
|
}
|
|
|
|
|
2010-04-19 10:27:55 -06:00
|
|
|
/* Free the vertex buffer. Unmap first if needed.
|
2009-06-08 16:11:29 +01:00
|
|
|
*/
|
2014-02-06 19:24:23 +01:00
|
|
|
if (_mesa_bufferobj_mapped(exec->vtx.bufferobj, MAP_INTERNAL)) {
|
|
|
|
ctx->Driver.UnmapBuffer(ctx, exec->vtx.bufferobj, MAP_INTERNAL);
|
2010-04-19 10:27:55 -06:00
|
|
|
}
|
2009-06-08 16:11:29 +01:00
|
|
|
_mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL);
|
2006-10-29 09:46:11 +00:00
|
|
|
}
|
|
|
|
|
2011-02-21 15:11:44 -07:00
|
|
|
|
2009-11-19 15:17:56 -07:00
|
|
|
/**
|
2015-09-27 21:28:22 +02:00
|
|
|
* If inside glBegin()/glEnd(), it should assert(0). Otherwise, if
|
|
|
|
* FLUSH_STORED_VERTICES bit in \p flags is set flushes any buffered
|
|
|
|
* vertices, if FLUSH_UPDATE_CURRENT bit is set updates
|
|
|
|
* __struct gl_contextRec::Current and gl_light_attrib::Material
|
|
|
|
*
|
|
|
|
* Note that the default T&L engine never clears the
|
|
|
|
* FLUSH_UPDATE_CURRENT bit, even after performing the update.
|
|
|
|
*
|
2009-11-19 15:17:56 -07:00
|
|
|
* \param flags bitmask of FLUSH_STORED_VERTICES, FLUSH_UPDATE_CURRENT
|
|
|
|
*/
|
2010-10-12 12:26:10 -04:00
|
|
|
void vbo_exec_FlushVertices( struct gl_context *ctx, GLuint flags )
|
2009-03-03 10:46:12 +00:00
|
|
|
{
|
|
|
|
struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
|
|
|
|
|
2009-11-19 15:17:56 -07:00
|
|
|
#ifdef DEBUG
|
|
|
|
/* debug check: make sure we don't get called recursively */
|
2009-12-01 13:26:15 -07:00
|
|
|
exec->flush_call_depth++;
|
|
|
|
assert(exec->flush_call_depth == 1);
|
2009-11-19 15:17:56 -07:00
|
|
|
#endif
|
|
|
|
|
2013-04-23 10:53:00 -06:00
|
|
|
if (_mesa_inside_begin_end(ctx)) {
|
2011-02-21 15:11:44 -07:00
|
|
|
/* We've had glBegin but not glEnd! */
|
2009-11-19 15:17:56 -07:00
|
|
|
#ifdef DEBUG
|
2009-12-01 13:26:15 -07:00
|
|
|
exec->flush_call_depth--;
|
|
|
|
assert(exec->flush_call_depth == 0);
|
2009-11-19 15:17:56 -07:00
|
|
|
#endif
|
2009-03-03 10:46:12 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-02-21 15:11:44 -07:00
|
|
|
/* Flush (draw), and make sure VBO is left unmapped when done */
|
2011-02-21 15:11:44 -07:00
|
|
|
vbo_exec_FlushVertices_internal(exec, GL_TRUE);
|
2006-10-29 09:46:11 +00:00
|
|
|
|
2015-10-12 14:16:37 -06:00
|
|
|
/* Need to do this to ensure vbo_exec_begin_vertices gets called again:
|
2009-03-03 10:41:57 +00:00
|
|
|
*/
|
2011-02-22 13:31:09 -07:00
|
|
|
ctx->Driver.NeedFlush &= ~(FLUSH_UPDATE_CURRENT | flags);
|
2009-11-19 15:17:56 -07:00
|
|
|
|
|
|
|
#ifdef DEBUG
|
2009-12-01 13:26:15 -07:00
|
|
|
exec->flush_call_depth--;
|
|
|
|
assert(exec->flush_call_depth == 0);
|
2009-11-19 15:17:56 -07:00
|
|
|
#endif
|
2006-10-29 09:46:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void reset_attrfv( struct vbo_exec_context *exec )
|
|
|
|
{
|
|
|
|
GLuint i;
|
|
|
|
|
|
|
|
for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
|
|
|
|
exec->vtx.attrsz[i] = 0;
|
2012-10-30 14:44:22 +01:00
|
|
|
exec->vtx.attrtype[i] = GL_FLOAT;
|
2006-10-29 09:46:11 +00:00
|
|
|
exec->vtx.active_sz[i] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
exec->vtx.vertex_size = 0;
|
|
|
|
}
|
|
|
|
|
2008-06-20 10:48:14 -06:00
|
|
|
|
2008-07-07 17:56:29 -06:00
|
|
|
void GLAPIENTRY
|
2010-12-07 21:33:53 +08:00
|
|
|
_es_Color4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a)
|
2008-06-20 10:48:14 -06:00
|
|
|
{
|
|
|
|
vbo_Color4f(r, g, b, a);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-07-07 17:56:29 -06:00
|
|
|
void GLAPIENTRY
|
2010-12-07 21:33:53 +08:00
|
|
|
_es_Normal3f(GLfloat x, GLfloat y, GLfloat z)
|
2008-06-20 10:48:14 -06:00
|
|
|
{
|
|
|
|
vbo_Normal3f(x, y, z);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-07-07 17:56:29 -06:00
|
|
|
void GLAPIENTRY
|
2010-12-07 21:33:53 +08:00
|
|
|
_es_MultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q)
|
2008-06-20 10:48:14 -06:00
|
|
|
{
|
|
|
|
vbo_MultiTexCoord4f(target, s, t, r, q);
|
|
|
|
}
|
|
|
|
|
2010-04-22 20:52:21 -04:00
|
|
|
|
2008-07-07 17:56:29 -06:00
|
|
|
void GLAPIENTRY
|
2010-12-07 21:33:53 +08:00
|
|
|
_es_Materialfv(GLenum face, GLenum pname, const GLfloat *params)
|
2008-06-20 11:04:37 -06:00
|
|
|
{
|
|
|
|
vbo_Materialfv(face, pname, params);
|
|
|
|
}
|
2008-07-03 16:59:24 -06:00
|
|
|
|
|
|
|
|
2010-04-22 20:52:21 -04:00
|
|
|
void GLAPIENTRY
|
2010-12-07 21:33:53 +08:00
|
|
|
_es_Materialf(GLenum face, GLenum pname, GLfloat param)
|
2010-04-22 20:52:21 -04:00
|
|
|
{
|
2010-07-15 00:53:07 -07:00
|
|
|
GLfloat p[4];
|
|
|
|
p[0] = param;
|
|
|
|
p[1] = p[2] = p[3] = 0.0F;
|
|
|
|
vbo_Materialfv(face, pname, p);
|
2010-04-22 20:52:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-12-07 21:33:53 +08:00
|
|
|
/**
|
|
|
|
* A special version of glVertexAttrib4f that does not treat index 0 as
|
|
|
|
* VBO_ATTRIB_POS.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
VertexAttrib4f_nopos(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
|
|
|
|
{
|
|
|
|
GET_CURRENT_CONTEXT(ctx);
|
|
|
|
if (index < MAX_VERTEX_GENERIC_ATTRIBS)
|
2015-03-11 03:25:00 -06:00
|
|
|
ATTRF(VBO_ATTRIB_GENERIC0 + index, 4, x, y, z, w);
|
2010-12-07 21:33:53 +08:00
|
|
|
else
|
2011-03-01 17:16:00 -07:00
|
|
|
ERROR(GL_INVALID_VALUE);
|
2010-12-07 21:33:53 +08:00
|
|
|
}
|
|
|
|
|
2008-07-07 17:56:29 -06:00
|
|
|
void GLAPIENTRY
|
2010-12-07 21:33:53 +08:00
|
|
|
_es_VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
|
2008-07-03 16:59:24 -06:00
|
|
|
{
|
2010-12-07 21:33:53 +08:00
|
|
|
VertexAttrib4f_nopos(index, x, y, z, w);
|
2008-07-03 16:59:24 -06:00
|
|
|
}
|
2010-04-22 20:52:21 -04:00
|
|
|
|
|
|
|
|
|
|
|
void GLAPIENTRY
|
2010-12-07 21:33:53 +08:00
|
|
|
_es_VertexAttrib1f(GLuint indx, GLfloat x)
|
2010-04-22 20:52:21 -04:00
|
|
|
{
|
2010-12-07 21:33:53 +08:00
|
|
|
VertexAttrib4f_nopos(indx, x, 0.0f, 0.0f, 1.0f);
|
2010-04-22 20:52:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GLAPIENTRY
|
2010-12-07 21:33:53 +08:00
|
|
|
_es_VertexAttrib1fv(GLuint indx, const GLfloat* values)
|
2010-04-22 20:52:21 -04:00
|
|
|
{
|
2010-12-07 21:33:53 +08:00
|
|
|
VertexAttrib4f_nopos(indx, values[0], 0.0f, 0.0f, 1.0f);
|
2010-04-22 20:52:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GLAPIENTRY
|
2010-12-07 21:33:53 +08:00
|
|
|
_es_VertexAttrib2f(GLuint indx, GLfloat x, GLfloat y)
|
2010-04-22 20:52:21 -04:00
|
|
|
{
|
2010-12-07 21:33:53 +08:00
|
|
|
VertexAttrib4f_nopos(indx, x, y, 0.0f, 1.0f);
|
2010-04-22 20:52:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GLAPIENTRY
|
2010-12-07 21:33:53 +08:00
|
|
|
_es_VertexAttrib2fv(GLuint indx, const GLfloat* values)
|
2010-04-22 20:52:21 -04:00
|
|
|
{
|
2010-12-07 21:33:53 +08:00
|
|
|
VertexAttrib4f_nopos(indx, values[0], values[1], 0.0f, 1.0f);
|
2010-04-22 20:52:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GLAPIENTRY
|
2010-12-07 21:33:53 +08:00
|
|
|
_es_VertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z)
|
2010-04-22 20:52:21 -04:00
|
|
|
{
|
2010-12-07 21:33:53 +08:00
|
|
|
VertexAttrib4f_nopos(indx, x, y, z, 1.0f);
|
2010-04-22 20:52:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GLAPIENTRY
|
2010-12-07 21:33:53 +08:00
|
|
|
_es_VertexAttrib3fv(GLuint indx, const GLfloat* values)
|
2010-04-22 20:52:21 -04:00
|
|
|
{
|
2010-12-07 21:33:53 +08:00
|
|
|
VertexAttrib4f_nopos(indx, values[0], values[1], values[2], 1.0f);
|
2010-04-22 20:52:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GLAPIENTRY
|
2010-12-07 21:33:53 +08:00
|
|
|
_es_VertexAttrib4fv(GLuint indx, const GLfloat* values)
|
2010-04-22 20:52:21 -04:00
|
|
|
{
|
2010-12-07 21:33:53 +08:00
|
|
|
VertexAttrib4f_nopos(indx, values[0], values[1], values[2], values[3]);
|
2010-04-22 20:52:21 -04:00
|
|
|
}
|