vbo_exec_array.c revision 9881bf6e69b52efc1eb57a4027d9a8817ef8cbcb
14b562cf889bc59e1914dd2c5d9fbd7e7bfa1ad77Argyrios Kyrtzidis/**************************************************************************
24b562cf889bc59e1914dd2c5d9fbd7e7bfa1ad77Argyrios Kyrtzidis *
34b562cf889bc59e1914dd2c5d9fbd7e7bfa1ad77Argyrios Kyrtzidis * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
44b562cf889bc59e1914dd2c5d9fbd7e7bfa1ad77Argyrios Kyrtzidis * Copyright 2009 VMware, Inc.
54b562cf889bc59e1914dd2c5d9fbd7e7bfa1ad77Argyrios Kyrtzidis * All Rights Reserved.
64b562cf889bc59e1914dd2c5d9fbd7e7bfa1ad77Argyrios Kyrtzidis *
74b562cf889bc59e1914dd2c5d9fbd7e7bfa1ad77Argyrios Kyrtzidis * Permission is hereby granted, free of charge, to any person obtaining a
84b562cf889bc59e1914dd2c5d9fbd7e7bfa1ad77Argyrios Kyrtzidis * copy of this software and associated documentation files (the
94b562cf889bc59e1914dd2c5d9fbd7e7bfa1ad77Argyrios Kyrtzidis * "Software"), to deal in the Software without restriction, including
104b562cf889bc59e1914dd2c5d9fbd7e7bfa1ad77Argyrios Kyrtzidis * without limitation the rights to use, copy, modify, merge, publish,
114b562cf889bc59e1914dd2c5d9fbd7e7bfa1ad77Argyrios Kyrtzidis * distribute, sub license, and/or sell copies of the Software, and to
124b562cf889bc59e1914dd2c5d9fbd7e7bfa1ad77Argyrios Kyrtzidis * permit persons to whom the Software is furnished to do so, subject to
134b562cf889bc59e1914dd2c5d9fbd7e7bfa1ad77Argyrios Kyrtzidis * the following conditions:
140853a02c3b04d96a3c432b883e403175c954cd81Argyrios Kyrtzidis *
150853a02c3b04d96a3c432b883e403175c954cd81Argyrios Kyrtzidis * The above copyright notice and this permission notice (including the
160853a02c3b04d96a3c432b883e403175c954cd81Argyrios Kyrtzidis * next paragraph) shall be included in all copies or substantial portions
17eb8837b88c18631c69ac75f64ab1853762063180Douglas Gregor * of the Software.
1805a07605322dfef2b017781042043a261c5a89cdSebastian Redl *
19914ed9d30e9abf829a62aa996b083b1e47c19ff6Douglas Gregor * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
200a2c5e256abb4dc031c21fe4dc92c4f3afe9947cJohn McCall * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
214ae8f298b1ea51b4c2234f9148e2e4349c9bdd23Douglas Gregor * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
2231b87d8006d4863dd9b17e515ac720941efc38e3Daniel Dunbar * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
23eb8837b88c18631c69ac75f64ab1853762063180Douglas Gregor * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
2587c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2628019772db70d4547be05a042eb950bc910f134fDouglas Gregor *
270853a02c3b04d96a3c432b883e403175c954cd81Argyrios Kyrtzidis **************************************************************************/
28a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor
29cc5888d833caf90ebda37f24da40d2cd06b4d820Douglas Gregor#include "main/glheader.h"
3003013fa9a0bf1ef4b907f5fec006c8f4000fdd21Michael J. Spencer#include "main/context.h"
31788f5a1242c04762f91eaa7565c07b9865846d88Douglas Gregor#include "main/state.h"
320853a02c3b04d96a3c432b883e403175c954cd81Argyrios Kyrtzidis#include "main/api_validate.h"
33f772d1e2a5688572d07f42896a50ac57a4a41fe8Daniel Dunbar#include "main/varray.h"
34f772d1e2a5688572d07f42896a50ac57a4a41fe8Daniel Dunbar#include "main/bufferobj.h"
354db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor#include "main/enums.h"
36cc5888d833caf90ebda37f24da40d2cd06b4d820Douglas Gregor#include "main/macros.h"
374db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor#include "main/transformfeedback.h"
384db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor
394db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor#include "vbo_context.h"
404db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor
410853a02c3b04d96a3c432b883e403175c954cd81Argyrios Kyrtzidis
420853a02c3b04d96a3c432b883e403175c954cd81Argyrios Kyrtzidis/**
43521bf9c529e653ab28896d027352d3e16e2672d5Daniel Dunbar * All vertex buffers should be in an unmapped state when we're about
441abc6bca3d7fb0e7b1e40fbcad6cfb5e10594548Douglas Gregor * to draw.  This debug function checks that.
45521bf9c529e653ab28896d027352d3e16e2672d5Daniel Dunbar */
46521bf9c529e653ab28896d027352d3e16e2672d5Daniel Dunbarstatic void
47521bf9c529e653ab28896d027352d3e16e2672d5Daniel Dunbarcheck_buffers_are_unmapped(const struct gl_client_array **inputs)
48521bf9c529e653ab28896d027352d3e16e2672d5Daniel Dunbar{
49521bf9c529e653ab28896d027352d3e16e2672d5Daniel Dunbar#ifdef DEBUG
50521bf9c529e653ab28896d027352d3e16e2672d5Daniel Dunbar   GLuint i;
51521bf9c529e653ab28896d027352d3e16e2672d5Daniel Dunbar
52521bf9c529e653ab28896d027352d3e16e2672d5Daniel Dunbar   for (i = 0; i < VERT_ATTRIB_MAX; i++) {
53521bf9c529e653ab28896d027352d3e16e2672d5Daniel Dunbar      if (inputs[i]) {
540853a02c3b04d96a3c432b883e403175c954cd81Argyrios Kyrtzidis         struct gl_buffer_object *obj = inputs[i]->BufferObj;
55f96b524306ccfa623235d375deee79637bd38f29Steve Naroff         assert(!_mesa_bufferobj_mapped(obj));
5644c181aec37789f25f6c15543c164416f72e562aDouglas Gregor         (void) obj;
5748601b32321496b07a18fb6631f8563275d8c5fbDouglas Gregor      }
5848601b32321496b07a18fb6631f8563275d8c5fbDouglas Gregor   }
5948601b32321496b07a18fb6631f8563275d8c5fbDouglas Gregor#endif
6048601b32321496b07a18fb6631f8563275d8c5fbDouglas Gregor}
6148601b32321496b07a18fb6631f8563275d8c5fbDouglas Gregor
6248601b32321496b07a18fb6631f8563275d8c5fbDouglas Gregor
6348601b32321496b07a18fb6631f8563275d8c5fbDouglas Gregor/**
6448601b32321496b07a18fb6631f8563275d8c5fbDouglas Gregor * A debug function that may be called from other parts of Mesa as
653c7f4134603d04b44f997b43c0a9def270f25386Sebastian Redl * needed during debugging.
660853a02c3b04d96a3c432b883e403175c954cd81Argyrios Kyrtzidis */
670853a02c3b04d96a3c432b883e403175c954cd81Argyrios Kyrtzidisvoid
68788f5a1242c04762f91eaa7565c07b9865846d88Douglas Gregorvbo_check_buffers_are_unmapped(struct gl_context *ctx)
69788f5a1242c04762f91eaa7565c07b9865846d88Douglas Gregor{
70788f5a1242c04762f91eaa7565c07b9865846d88Douglas Gregor   struct vbo_context *vbo = vbo_context(ctx);
71bdbb004f38978da0c4a75af3294d1c7b5ff84af1Douglas Gregor   struct vbo_exec_context *exec = &vbo->exec;
72788f5a1242c04762f91eaa7565c07b9865846d88Douglas Gregor   /* check the current vertex arrays */
7328019772db70d4547be05a042eb950bc910f134fDouglas Gregor   check_buffers_are_unmapped(exec->array.inputs);
74405634b215f19eec7183bd8005e34aa5a02f64a1Douglas Gregor   /* check the current glBegin/glVertex/glEnd-style VBO */
75405634b215f19eec7183bd8005e34aa5a02f64a1Douglas Gregor   assert(!_mesa_bufferobj_mapped(exec->vtx.bufferobj));
760853a02c3b04d96a3c432b883e403175c954cd81Argyrios Kyrtzidis}
770853a02c3b04d96a3c432b883e403175c954cd81Argyrios Kyrtzidis
780853a02c3b04d96a3c432b883e403175c954cd81Argyrios Kyrtzidis
790853a02c3b04d96a3c432b883e403175c954cd81Argyrios Kyrtzidis
80389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis/**
81389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis * Compute min and max elements by scanning the index buffer for
82389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis * glDraw[Range]Elements() calls.
83914ed9d30e9abf829a62aa996b083b1e47c19ff6Douglas Gregor * If primitive restart is enabled, we need to ignore restart
84914ed9d30e9abf829a62aa996b083b1e47c19ff6Douglas Gregor * indexes when computing min/max.
85914ed9d30e9abf829a62aa996b083b1e47c19ff6Douglas Gregor */
86914ed9d30e9abf829a62aa996b083b1e47c19ff6Douglas Gregorstatic void
87914ed9d30e9abf829a62aa996b083b1e47c19ff6Douglas Gregorvbo_get_minmax_index(struct gl_context *ctx,
88914ed9d30e9abf829a62aa996b083b1e47c19ff6Douglas Gregor		     const struct _mesa_prim *prim,
89914ed9d30e9abf829a62aa996b083b1e47c19ff6Douglas Gregor		     const struct _mesa_index_buffer *ib,
90914ed9d30e9abf829a62aa996b083b1e47c19ff6Douglas Gregor		     GLuint *min_index, GLuint *max_index,
91807b06157a1a5c050520fc194d32f16d22d423a8Daniel Dunbar		     const GLuint count)
92807b06157a1a5c050520fc194d32f16d22d423a8Daniel Dunbar{
93807b06157a1a5c050520fc194d32f16d22d423a8Daniel Dunbar   const GLboolean restart = ctx->Array.PrimitiveRestart;
94914ed9d30e9abf829a62aa996b083b1e47c19ff6Douglas Gregor   const GLuint restartIndex = ctx->Array.RestartIndex;
951aa27307c462baaa9e5fda14ff6797dd39fe8b84Douglas Gregor   const int index_size = vbo_sizeof_ib_type(ib->type);
961aa27307c462baaa9e5fda14ff6797dd39fe8b84Douglas Gregor   const char *indices;
971aa27307c462baaa9e5fda14ff6797dd39fe8b84Douglas Gregor   GLuint i;
981aa27307c462baaa9e5fda14ff6797dd39fe8b84Douglas Gregor
991aa27307c462baaa9e5fda14ff6797dd39fe8b84Douglas Gregor   indices = (char *) ib->ptr + prim->start * index_size;
1001aa27307c462baaa9e5fda14ff6797dd39fe8b84Douglas Gregor   if (_mesa_is_bufferobj(ib->obj)) {
1011aa27307c462baaa9e5fda14ff6797dd39fe8b84Douglas Gregor      GLsizeiptr size = MIN2(count * index_size, ib->obj->Size);
1027d1d49d2971b20a97b3c2a301470b9eaaa130137Douglas Gregor      indices = ctx->Driver.MapBufferRange(ctx, (GLintptr) indices, size,
1037d1d49d2971b20a97b3c2a301470b9eaaa130137Douglas Gregor                                           GL_MAP_READ_BIT, ib->obj);
1047d1d49d2971b20a97b3c2a301470b9eaaa130137Douglas Gregor   }
1057d1d49d2971b20a97b3c2a301470b9eaaa130137Douglas Gregor
106c7822dbf3c01a2a5f837cff82ba7889ea755dacaDaniel Dunbar   switch (ib->type) {
107abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor   case GL_UNSIGNED_INT: {
108abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor      const GLuint *ui_indices = (const GLuint *)indices;
109e47be3e9682e82da15059006f43c7f3c021e4fffDouglas Gregor      GLuint max_ui = 0;
110df95a13ec73d2cdaea79555cb412d767f4963120Douglas Gregor      GLuint min_ui = ~0U;
111c7822dbf3c01a2a5f837cff82ba7889ea755dacaDaniel Dunbar      if (restart) {
112c7822dbf3c01a2a5f837cff82ba7889ea755dacaDaniel Dunbar         for (i = 0; i < count; i++) {
113df95a13ec73d2cdaea79555cb412d767f4963120Douglas Gregor            if (ui_indices[i] != restartIndex) {
114df95a13ec73d2cdaea79555cb412d767f4963120Douglas Gregor               if (ui_indices[i] > max_ui) max_ui = ui_indices[i];
115df95a13ec73d2cdaea79555cb412d767f4963120Douglas Gregor               if (ui_indices[i] < min_ui) min_ui = ui_indices[i];
116213f18b3d654de7d1c7cf4a329ea9d3db1c50b6aDouglas Gregor            }
117213f18b3d654de7d1c7cf4a329ea9d3db1c50b6aDouglas Gregor         }
11815727ddb11405c45372150b5bfb07dbfa4c9960bArgyrios Kyrtzidis      }
11915727ddb11405c45372150b5bfb07dbfa4c9960bArgyrios Kyrtzidis      else {
12015727ddb11405c45372150b5bfb07dbfa4c9960bArgyrios Kyrtzidis         for (i = 0; i < count; i++) {
121213f18b3d654de7d1c7cf4a329ea9d3db1c50b6aDouglas Gregor            if (ui_indices[i] > max_ui) max_ui = ui_indices[i];
122f772d1e2a5688572d07f42896a50ac57a4a41fe8Daniel Dunbar            if (ui_indices[i] < min_ui) min_ui = ui_indices[i];
123f772d1e2a5688572d07f42896a50ac57a4a41fe8Daniel Dunbar         }
124f772d1e2a5688572d07f42896a50ac57a4a41fe8Daniel Dunbar      }
125f772d1e2a5688572d07f42896a50ac57a4a41fe8Daniel Dunbar      *min_index = min_ui;
126f772d1e2a5688572d07f42896a50ac57a4a41fe8Daniel Dunbar      *max_index = max_ui;
127f772d1e2a5688572d07f42896a50ac57a4a41fe8Daniel Dunbar      break;
128f772d1e2a5688572d07f42896a50ac57a4a41fe8Daniel Dunbar   }
129f772d1e2a5688572d07f42896a50ac57a4a41fe8Daniel Dunbar   case GL_UNSIGNED_SHORT: {
130f772d1e2a5688572d07f42896a50ac57a4a41fe8Daniel Dunbar      const GLushort *us_indices = (const GLushort *)indices;
13189d9980bbc2e4a4ac86673e6ec16fb9f5babb63bDouglas Gregor      GLuint max_us = 0;
13289d9980bbc2e4a4ac86673e6ec16fb9f5babb63bDouglas Gregor      GLuint min_us = ~0U;
13389d9980bbc2e4a4ac86673e6ec16fb9f5babb63bDouglas Gregor      if (restart) {
13489d9980bbc2e4a4ac86673e6ec16fb9f5babb63bDouglas Gregor         for (i = 0; i < count; i++) {
13589d9980bbc2e4a4ac86673e6ec16fb9f5babb63bDouglas Gregor            if (us_indices[i] != restartIndex) {
13689d9980bbc2e4a4ac86673e6ec16fb9f5babb63bDouglas Gregor               if (us_indices[i] > max_us) max_us = us_indices[i];
13789d9980bbc2e4a4ac86673e6ec16fb9f5babb63bDouglas Gregor               if (us_indices[i] < min_us) min_us = us_indices[i];
13889d9980bbc2e4a4ac86673e6ec16fb9f5babb63bDouglas Gregor            }
13968d40e2d16b9fadba386853d6bbb60089291fdc5Daniel Dunbar         }
14068d40e2d16b9fadba386853d6bbb60089291fdc5Daniel Dunbar      }
14168d40e2d16b9fadba386853d6bbb60089291fdc5Daniel Dunbar      else {
142f96b524306ccfa623235d375deee79637bd38f29Steve Naroff         for (i = 0; i < count; i++) {
143f96b524306ccfa623235d375deee79637bd38f29Steve Naroff            if (us_indices[i] > max_us) max_us = us_indices[i];
144f772d1e2a5688572d07f42896a50ac57a4a41fe8Daniel Dunbar            if (us_indices[i] < min_us) min_us = us_indices[i];
145a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor         }
146a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor      }
147405634b215f19eec7183bd8005e34aa5a02f64a1Douglas Gregor      *min_index = min_us;
148a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor      *max_index = max_us;
1494cd912aa94656697a44c3ebb159f05060300524eDouglas Gregor      break;
1504cd912aa94656697a44c3ebb159f05060300524eDouglas Gregor   }
1514cd912aa94656697a44c3ebb159f05060300524eDouglas Gregor   case GL_UNSIGNED_BYTE: {
1524cd912aa94656697a44c3ebb159f05060300524eDouglas Gregor      const GLubyte *ub_indices = (const GLubyte *)indices;
1534cd912aa94656697a44c3ebb159f05060300524eDouglas Gregor      GLuint max_ub = 0;
1544cd912aa94656697a44c3ebb159f05060300524eDouglas Gregor      GLuint min_ub = ~0U;
1554cd912aa94656697a44c3ebb159f05060300524eDouglas Gregor      if (restart) {
156313e26c4e81f0e467490a530548450f4c824a6c4Douglas Gregor         for (i = 0; i < count; i++) {
157313e26c4e81f0e467490a530548450f4c824a6c4Douglas Gregor            if (ub_indices[i] != restartIndex) {
158313e26c4e81f0e467490a530548450f4c824a6c4Douglas Gregor               if (ub_indices[i] > max_ub) max_ub = ub_indices[i];
159bdf6062bc10aa3b73b16402b440b8073310acd06Douglas Gregor               if (ub_indices[i] < min_ub) min_ub = ub_indices[i];
160788f5a1242c04762f91eaa7565c07b9865846d88Douglas Gregor            }
161788f5a1242c04762f91eaa7565c07b9865846d88Douglas Gregor         }
162788f5a1242c04762f91eaa7565c07b9865846d88Douglas Gregor      }
163788f5a1242c04762f91eaa7565c07b9865846d88Douglas Gregor      else {
164788f5a1242c04762f91eaa7565c07b9865846d88Douglas Gregor         for (i = 0; i < count; i++) {
165788f5a1242c04762f91eaa7565c07b9865846d88Douglas Gregor            if (ub_indices[i] > max_ub) max_ub = ub_indices[i];
166788f5a1242c04762f91eaa7565c07b9865846d88Douglas Gregor            if (ub_indices[i] < min_ub) min_ub = ub_indices[i];
167788f5a1242c04762f91eaa7565c07b9865846d88Douglas Gregor         }
168788f5a1242c04762f91eaa7565c07b9865846d88Douglas Gregor      }
169bdf6062bc10aa3b73b16402b440b8073310acd06Douglas Gregor      *min_index = min_ub;
170bdf6062bc10aa3b73b16402b440b8073310acd06Douglas Gregor      *max_index = max_ub;
171bdf6062bc10aa3b73b16402b440b8073310acd06Douglas Gregor      break;
172bdf6062bc10aa3b73b16402b440b8073310acd06Douglas Gregor   }
173bdf6062bc10aa3b73b16402b440b8073310acd06Douglas Gregor   default:
174bdf6062bc10aa3b73b16402b440b8073310acd06Douglas Gregor      assert(0);
175bdf6062bc10aa3b73b16402b440b8073310acd06Douglas Gregor      break;
176bdf6062bc10aa3b73b16402b440b8073310acd06Douglas Gregor   }
177bdf6062bc10aa3b73b16402b440b8073310acd06Douglas Gregor
178175c4a9aa61f4449f27b729737e4438684ac6d92Douglas Gregor   if (_mesa_is_bufferobj(ib->obj)) {
179eababfbddb74d186f78783a9731a78ad371c9800Douglas Gregor      ctx->Driver.UnmapBuffer(ctx, ib->obj);
180eababfbddb74d186f78783a9731a78ad371c9800Douglas Gregor   }
181eababfbddb74d186f78783a9731a78ad371c9800Douglas Gregor}
182eababfbddb74d186f78783a9731a78ad371c9800Douglas Gregor
183eababfbddb74d186f78783a9731a78ad371c9800Douglas Gregor/**
184eababfbddb74d186f78783a9731a78ad371c9800Douglas Gregor * Compute min and max elements for nr_prims
185eababfbddb74d186f78783a9731a78ad371c9800Douglas Gregor */
186eababfbddb74d186f78783a9731a78ad371c9800Douglas Gregorvoid
187eababfbddb74d186f78783a9731a78ad371c9800Douglas Gregorvbo_get_minmax_indices(struct gl_context *ctx,
188eababfbddb74d186f78783a9731a78ad371c9800Douglas Gregor                       const struct _mesa_prim *prims,
189eababfbddb74d186f78783a9731a78ad371c9800Douglas Gregor                       const struct _mesa_index_buffer *ib,
190175c4a9aa61f4449f27b729737e4438684ac6d92Douglas Gregor                       GLuint *min_index,
191385103b79c5338a2be5da0ca70652400bc267371Douglas Gregor                       GLuint *max_index,
192175c4a9aa61f4449f27b729737e4438684ac6d92Douglas Gregor                       GLuint nr_prims)
193175c4a9aa61f4449f27b729737e4438684ac6d92Douglas Gregor{
194175c4a9aa61f4449f27b729737e4438684ac6d92Douglas Gregor   GLuint tmp_min, tmp_max;
195175c4a9aa61f4449f27b729737e4438684ac6d92Douglas Gregor   GLuint i;
196175c4a9aa61f4449f27b729737e4438684ac6d92Douglas Gregor   GLuint count;
197f4f6c9db68465b886ec2e596feaa6ecc782395a4Douglas Gregor
198f4f6c9db68465b886ec2e596feaa6ecc782395a4Douglas Gregor   *min_index = ~0;
199f4f6c9db68465b886ec2e596feaa6ecc782395a4Douglas Gregor   *max_index = 0;
200f4f6c9db68465b886ec2e596feaa6ecc782395a4Douglas Gregor
201f4f6c9db68465b886ec2e596feaa6ecc782395a4Douglas Gregor   for (i = 0; i < nr_prims; i++) {
202f4f6c9db68465b886ec2e596feaa6ecc782395a4Douglas Gregor      const struct _mesa_prim *start_prim;
203175c4a9aa61f4449f27b729737e4438684ac6d92Douglas Gregor
204175c4a9aa61f4449f27b729737e4438684ac6d92Douglas Gregor      start_prim = &prims[i];
205175c4a9aa61f4449f27b729737e4438684ac6d92Douglas Gregor      count = start_prim->count;
206cc5888d833caf90ebda37f24da40d2cd06b4d820Douglas Gregor      /* Do combination if possible to reduce map/unmap count */
207cc5888d833caf90ebda37f24da40d2cd06b4d820Douglas Gregor      while ((i + 1 < nr_prims) &&
208cc5888d833caf90ebda37f24da40d2cd06b4d820Douglas Gregor             (prims[i].start + prims[i].count == prims[i+1].start)) {
209cc5888d833caf90ebda37f24da40d2cd06b4d820Douglas Gregor         count += prims[i+1].count;
210cc5888d833caf90ebda37f24da40d2cd06b4d820Douglas Gregor         i++;
211cc5888d833caf90ebda37f24da40d2cd06b4d820Douglas Gregor      }
212cc5888d833caf90ebda37f24da40d2cd06b4d820Douglas Gregor      vbo_get_minmax_index(ctx, start_prim, ib, &tmp_min, &tmp_max, count);
213cc5888d833caf90ebda37f24da40d2cd06b4d820Douglas Gregor      *min_index = MIN2(*min_index, tmp_min);
21428233428da1ebec20c893d6297ae3191318940ddDouglas Gregor      *max_index = MAX2(*max_index, tmp_max);
21528233428da1ebec20c893d6297ae3191318940ddDouglas Gregor   }
21628233428da1ebec20c893d6297ae3191318940ddDouglas Gregor}
21728233428da1ebec20c893d6297ae3191318940ddDouglas Gregor
218c0659ec614c428c7d15746fcad15d50a2703751dDouglas Gregor
219671947b18dba342f9aba022ee992babef325a833Douglas Gregor/**
220671947b18dba342f9aba022ee992babef325a833Douglas Gregor * Check that element 'j' of the array has reasonable data.
221671947b18dba342f9aba022ee992babef325a833Douglas Gregor * Map VBO if needed.
222671947b18dba342f9aba022ee992babef325a833Douglas Gregor * For debugging purposes; not normally used.
223671947b18dba342f9aba022ee992babef325a833Douglas Gregor */
224c0659ec614c428c7d15746fcad15d50a2703751dDouglas Gregorstatic void
225c0659ec614c428c7d15746fcad15d50a2703751dDouglas Gregorcheck_array_data(struct gl_context *ctx, struct gl_client_array *array,
226c0659ec614c428c7d15746fcad15d50a2703751dDouglas Gregor                 GLuint attrib, GLuint j)
227c0659ec614c428c7d15746fcad15d50a2703751dDouglas Gregor{
228c0659ec614c428c7d15746fcad15d50a2703751dDouglas Gregor   if (array->Enabled) {
229c0659ec614c428c7d15746fcad15d50a2703751dDouglas Gregor      const void *data = array->Ptr;
230c0659ec614c428c7d15746fcad15d50a2703751dDouglas Gregor      if (_mesa_is_bufferobj(array->BufferObj)) {
231c0659ec614c428c7d15746fcad15d50a2703751dDouglas Gregor         if (!array->BufferObj->Pointer) {
232c0659ec614c428c7d15746fcad15d50a2703751dDouglas Gregor            /* need to map now */
233c0659ec614c428c7d15746fcad15d50a2703751dDouglas Gregor            array->BufferObj->Pointer =
234c0659ec614c428c7d15746fcad15d50a2703751dDouglas Gregor               ctx->Driver.MapBufferRange(ctx, 0, array->BufferObj->Size,
235c0659ec614c428c7d15746fcad15d50a2703751dDouglas Gregor					  GL_MAP_READ_BIT, array->BufferObj);
236c0659ec614c428c7d15746fcad15d50a2703751dDouglas Gregor         }
237c0659ec614c428c7d15746fcad15d50a2703751dDouglas Gregor         data = ADD_POINTERS(data, array->BufferObj->Pointer);
238c0659ec614c428c7d15746fcad15d50a2703751dDouglas Gregor      }
239c0659ec614c428c7d15746fcad15d50a2703751dDouglas Gregor      switch (array->Type) {
2403c7f4134603d04b44f997b43c0a9def270f25386Sebastian Redl      case GL_FLOAT:
241eb8837b88c18631c69ac75f64ab1853762063180Douglas Gregor         {
2428538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl            GLfloat *f = (GLfloat *) ((GLubyte *) data + array->StrideB * j);
243eb8837b88c18631c69ac75f64ab1853762063180Douglas Gregor            GLint k;
24489d9980bbc2e4a4ac86673e6ec16fb9f5babb63bDouglas Gregor            for (k = 0; k < array->Size; k++) {
24589d9980bbc2e4a4ac86673e6ec16fb9f5babb63bDouglas Gregor               if (IS_INF_OR_NAN(f[k]) ||
24689d9980bbc2e4a4ac86673e6ec16fb9f5babb63bDouglas Gregor                   f[k] >= 1.0e20 || f[k] <= -1.0e10) {
24789d9980bbc2e4a4ac86673e6ec16fb9f5babb63bDouglas Gregor                  printf("Bad array data:\n");
24887c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor                  printf("  Element[%u].%u = %f\n", j, k, f[k]);
24987c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor                  printf("  Array %u at %p\n", attrib, (void* ) array);
25087c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor                  printf("  Type 0x%x, Size %d, Stride %d\n",
251e47be3e9682e82da15059006f43c7f3c021e4fffDouglas Gregor			 array->Type, array->Size, array->Stride);
2520b53cf834346d78985aaa9e7300445a39c245614Douglas Gregor                  printf("  Address/offset %p in Buffer Object %u\n",
253e47be3e9682e82da15059006f43c7f3c021e4fffDouglas Gregor			 array->Ptr, array->BufferObj->Name);
254e47be3e9682e82da15059006f43c7f3c021e4fffDouglas Gregor                  f[k] = 1.0; /* XXX replace the bad value! */
25587c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor               }
25687c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor               /*assert(!IS_INF_OR_NAN(f[k]));*/
25787c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor            }
25887c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor         }
25987c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor         break;
26087c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor      default:
26187c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor         ;
26287c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor      }
26387c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor   }
26487c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor}
26587c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor
26687c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor
26787c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor/**
26887c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor * Unmap the buffer object referenced by given array, if mapped.
26987c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor */
27087c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregorstatic void
27187c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregorunmap_array_buffer(struct gl_context *ctx, struct gl_client_array *array)
27287c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor{
27387c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor   if (array->Enabled &&
27487c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor       _mesa_is_bufferobj(array->BufferObj) &&
27587c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor       _mesa_bufferobj_mapped(array->BufferObj)) {
27687c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor      ctx->Driver.UnmapBuffer(ctx, array->BufferObj);
27787c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor   }
27887c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor}
2791827e10051638770ad9ccf3e285caf95f995afd1Douglas Gregor
28058ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor
28158ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor/**
28258ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor * Examine the array's data for NaNs, etc.
2831827e10051638770ad9ccf3e285caf95f995afd1Douglas Gregor * For debug purposes; not normally used.
2841827e10051638770ad9ccf3e285caf95f995afd1Douglas Gregor */
285f5586f6b311c98e1022a8fe0609053849b70d323Douglas Gregorstatic void
286f5586f6b311c98e1022a8fe0609053849b70d323Douglas Gregorcheck_draw_elements_data(struct gl_context *ctx, GLsizei count, GLenum elemType,
287f5586f6b311c98e1022a8fe0609053849b70d323Douglas Gregor                         const void *elements, GLint basevertex)
288f5586f6b311c98e1022a8fe0609053849b70d323Douglas Gregor{
289f5586f6b311c98e1022a8fe0609053849b70d323Douglas Gregor   struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
290f5586f6b311c98e1022a8fe0609053849b70d323Douglas Gregor   const void *elemMap;
291f5586f6b311c98e1022a8fe0609053849b70d323Douglas Gregor   GLint i, k;
292f5586f6b311c98e1022a8fe0609053849b70d323Douglas Gregor
29387c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor   if (_mesa_is_bufferobj(ctx->Array.ArrayObj->ElementArrayBufferObj)) {
29487c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor      elemMap = ctx->Driver.MapBufferRange(ctx, 0,
295f5586f6b311c98e1022a8fe0609053849b70d323Douglas Gregor					   ctx->Array.ArrayObj->ElementArrayBufferObj->Size,
296f5586f6b311c98e1022a8fe0609053849b70d323Douglas Gregor					   GL_MAP_READ_BIT,
297f5586f6b311c98e1022a8fe0609053849b70d323Douglas Gregor					   ctx->Array.ArrayObj->ElementArrayBufferObj);
298f5586f6b311c98e1022a8fe0609053849b70d323Douglas Gregor      elements = ADD_POINTERS(elements, elemMap);
299f5586f6b311c98e1022a8fe0609053849b70d323Douglas Gregor   }
300f5586f6b311c98e1022a8fe0609053849b70d323Douglas Gregor
30148601b32321496b07a18fb6631f8563275d8c5fbDouglas Gregor   for (i = 0; i < count; i++) {
30248601b32321496b07a18fb6631f8563275d8c5fbDouglas Gregor      GLuint j;
30348601b32321496b07a18fb6631f8563275d8c5fbDouglas Gregor
30448601b32321496b07a18fb6631f8563275d8c5fbDouglas Gregor      /* j = element[i] */
30548601b32321496b07a18fb6631f8563275d8c5fbDouglas Gregor      switch (elemType) {
30648601b32321496b07a18fb6631f8563275d8c5fbDouglas Gregor      case GL_UNSIGNED_BYTE:
30787c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor         j = ((const GLubyte *) elements)[i];
308218937c13ef5b0625a70aad41ca7a92da9278bd2Douglas Gregor         break;
30948601b32321496b07a18fb6631f8563275d8c5fbDouglas Gregor      case GL_UNSIGNED_SHORT:
31048601b32321496b07a18fb6631f8563275d8c5fbDouglas Gregor         j = ((const GLushort *) elements)[i];
311218937c13ef5b0625a70aad41ca7a92da9278bd2Douglas Gregor         break;
31287c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor      case GL_UNSIGNED_INT:
31387c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor         j = ((const GLuint *) elements)[i];
31487c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor         break;
315f5586f6b311c98e1022a8fe0609053849b70d323Douglas Gregor      default:
316f5586f6b311c98e1022a8fe0609053849b70d323Douglas Gregor         assert(0);
317f5586f6b311c98e1022a8fe0609053849b70d323Douglas Gregor      }
318f5586f6b311c98e1022a8fe0609053849b70d323Douglas Gregor
3199b7db6200d366e4964d63ae1f33c7b9d7b9831cbDouglas Gregor      /* check element j of each enabled array */
3209b7db6200d366e4964d63ae1f33c7b9d7b9831cbDouglas Gregor      for (k = 0; k < Elements(arrayObj->VertexAttrib); k++) {
321727d93ef49e18147149354fadd10e86b13bc4ab0Douglas Gregor         check_array_data(ctx, &arrayObj->VertexAttrib[k], k, j);
3229b7db6200d366e4964d63ae1f33c7b9d7b9831cbDouglas Gregor      }
3239b7db6200d366e4964d63ae1f33c7b9d7b9831cbDouglas Gregor   }
3249b7db6200d366e4964d63ae1f33c7b9d7b9831cbDouglas Gregor
325727d93ef49e18147149354fadd10e86b13bc4ab0Douglas Gregor   if (_mesa_is_bufferobj(arrayObj->ElementArrayBufferObj)) {
3269b7db6200d366e4964d63ae1f33c7b9d7b9831cbDouglas Gregor      ctx->Driver.UnmapBuffer(ctx, ctx->Array.ArrayObj->ElementArrayBufferObj);
3279b7db6200d366e4964d63ae1f33c7b9d7b9831cbDouglas Gregor   }
328727d93ef49e18147149354fadd10e86b13bc4ab0Douglas Gregor
3299b7db6200d366e4964d63ae1f33c7b9d7b9831cbDouglas Gregor   for (k = 0; k < Elements(arrayObj->VertexAttrib); k++) {
3309b7db6200d366e4964d63ae1f33c7b9d7b9831cbDouglas Gregor      unmap_array_buffer(ctx, &arrayObj->VertexAttrib[k]);
3319b7db6200d366e4964d63ae1f33c7b9d7b9831cbDouglas Gregor   }
332ea94bbc4769697143e717df9b0310f874102b6c1Daniel Dunbar}
3339b7db6200d366e4964d63ae1f33c7b9d7b9831cbDouglas Gregor
3349b7db6200d366e4964d63ae1f33c7b9d7b9831cbDouglas Gregor
3359b7db6200d366e4964d63ae1f33c7b9d7b9831cbDouglas Gregor/**
3369b7db6200d366e4964d63ae1f33c7b9d7b9831cbDouglas Gregor * Check array data, looking for NaNs, etc.
337ea94bbc4769697143e717df9b0310f874102b6c1Daniel Dunbar */
338ea94bbc4769697143e717df9b0310f874102b6c1Daniel Dunbarstatic void
339ea94bbc4769697143e717df9b0310f874102b6c1Daniel Dunbarcheck_draw_arrays_data(struct gl_context *ctx, GLint start, GLsizei count)
340ea94bbc4769697143e717df9b0310f874102b6c1Daniel Dunbar{
341c4421e966d77a18f815284175b3fcbb46f36fa39Douglas Gregor   /* TO DO */
342c4421e966d77a18f815284175b3fcbb46f36fa39Douglas Gregor}
34387c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor
34487c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor
34587c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor/**
34687c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor * Print info/data for glDrawArrays(), for debugging.
34787c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor */
34831b87d8006d4863dd9b17e515ac720941efc38e3Daniel Dunbarstatic void
34931b87d8006d4863dd9b17e515ac720941efc38e3Daniel Dunbarprint_draw_arrays(struct gl_context *ctx,
350bdf6062bc10aa3b73b16402b440b8073310acd06Douglas Gregor                  GLenum mode, GLint start, GLsizei count)
3513687e9d3a5dbfa9963af02a49a2b139d91310813Douglas Gregor{
3528b96253907c47141af0b7b2a44a368748d006a87Douglas Gregor   struct vbo_context *vbo = vbo_context(ctx);
353abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor   struct vbo_exec_context *exec = &vbo->exec;
354754f3490c5b0f5d83361f001bc87944f23644abbDouglas Gregor   struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
355175c4a9aa61f4449f27b729737e4438684ac6d92Douglas Gregor   int i;
356f4f6c9db68465b886ec2e596feaa6ecc782395a4Douglas Gregor
357df95a13ec73d2cdaea79555cb412d767f4963120Douglas Gregor   printf("vbo_exec_DrawArrays(mode 0x%x, start %d, count %d):\n",
358df95a13ec73d2cdaea79555cb412d767f4963120Douglas Gregor	  mode, start, count);
359175c4a9aa61f4449f27b729737e4438684ac6d92Douglas Gregor
360df95a13ec73d2cdaea79555cb412d767f4963120Douglas Gregor   for (i = 0; i < 32; i++) {
3612283d79155a3e82442fce124ce5fd704ca138801Douglas Gregor      struct gl_buffer_object *bufObj = exec->array.inputs[i]->BufferObj;
362df95a13ec73d2cdaea79555cb412d767f4963120Douglas Gregor      GLuint bufName = bufObj->Name;
363df95a13ec73d2cdaea79555cb412d767f4963120Douglas Gregor      GLint stride = exec->array.inputs[i]->Stride;
364eb8837b88c18631c69ac75f64ab1853762063180Douglas Gregor      printf("attr %2d: size %d stride %d  enabled %d  "
36589d9980bbc2e4a4ac86673e6ec16fb9f5babb63bDouglas Gregor	     "ptr %p  Bufobj %u\n",
36689d9980bbc2e4a4ac86673e6ec16fb9f5babb63bDouglas Gregor	     i,
3670853a02c3b04d96a3c432b883e403175c954cd81Argyrios Kyrtzidis	     exec->array.inputs[i]->Size,
368bdf6062bc10aa3b73b16402b440b8073310acd06Douglas Gregor	     stride,
369bdf6062bc10aa3b73b16402b440b8073310acd06Douglas Gregor	     /*exec->array.inputs[i]->Enabled,*/
370bdf6062bc10aa3b73b16402b440b8073310acd06Douglas Gregor	     arrayObj->VertexAttrib[VERT_ATTRIB_FF(i)].Enabled,
371bdf6062bc10aa3b73b16402b440b8073310acd06Douglas Gregor	     exec->array.inputs[i]->Ptr,
372bdf6062bc10aa3b73b16402b440b8073310acd06Douglas Gregor	     bufName);
373bdf6062bc10aa3b73b16402b440b8073310acd06Douglas Gregor
374bdf6062bc10aa3b73b16402b440b8073310acd06Douglas Gregor      if (bufName) {
375bdf6062bc10aa3b73b16402b440b8073310acd06Douglas Gregor         GLubyte *p = ctx->Driver.MapBufferRange(ctx, 0, bufObj->Size,
376bdf6062bc10aa3b73b16402b440b8073310acd06Douglas Gregor						 GL_MAP_READ_BIT, bufObj);
377bdf6062bc10aa3b73b16402b440b8073310acd06Douglas Gregor         int offset = (int) (GLintptr) exec->array.inputs[i]->Ptr;
378bdf6062bc10aa3b73b16402b440b8073310acd06Douglas Gregor         float *f = (float *) (p + offset);
379bdf6062bc10aa3b73b16402b440b8073310acd06Douglas Gregor         int *k = (int *) f;
380bdf6062bc10aa3b73b16402b440b8073310acd06Douglas Gregor         int i;
381bdf6062bc10aa3b73b16402b440b8073310acd06Douglas Gregor         int n = (count * stride) / 4;
382bdf6062bc10aa3b73b16402b440b8073310acd06Douglas Gregor         if (n > 32)
383bdf6062bc10aa3b73b16402b440b8073310acd06Douglas Gregor            n = 32;
384bdf6062bc10aa3b73b16402b440b8073310acd06Douglas Gregor         printf("  Data at offset %d:\n", offset);
385bdf6062bc10aa3b73b16402b440b8073310acd06Douglas Gregor         for (i = 0; i < n; i++) {
3860853a02c3b04d96a3c432b883e403175c954cd81Argyrios Kyrtzidis            printf("    float[%d] = 0x%08x %f\n", i, k[i], f[i]);
3870853a02c3b04d96a3c432b883e403175c954cd81Argyrios Kyrtzidis         }
388c7822dbf3c01a2a5f837cff82ba7889ea755dacaDaniel Dunbar         ctx->Driver.UnmapBuffer(ctx, bufObj);
389c7822dbf3c01a2a5f837cff82ba7889ea755dacaDaniel Dunbar      }
390ea94bbc4769697143e717df9b0310f874102b6c1Daniel Dunbar   }
391ea94bbc4769697143e717df9b0310f874102b6c1Daniel Dunbar}
392ea94bbc4769697143e717df9b0310f874102b6c1Daniel Dunbar
3933687e9d3a5dbfa9963af02a49a2b139d91310813Douglas Gregor
3943687e9d3a5dbfa9963af02a49a2b139d91310813Douglas Gregor/**
3953687e9d3a5dbfa9963af02a49a2b139d91310813Douglas Gregor * Set the vbo->exec->inputs[] pointers to point to the enabled
396405634b215f19eec7183bd8005e34aa5a02f64a1Douglas Gregor * vertex arrays.  This depends on the current vertex program/shader
397405634b215f19eec7183bd8005e34aa5a02f64a1Douglas Gregor * being executed because of whether or not generic vertex arrays
3980853a02c3b04d96a3c432b883e403175c954cd81Argyrios Kyrtzidis * alias the conventional vertex arrays.
3990853a02c3b04d96a3c432b883e403175c954cd81Argyrios Kyrtzidis * For arrays that aren't enabled, we set the input[attrib] pointer
4000853a02c3b04d96a3c432b883e403175c954cd81Argyrios Kyrtzidis * to point at a zero-stride current value "array".
4011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump */
4020853a02c3b04d96a3c432b883e403175c954cd81Argyrios Kyrtzidisstatic void
4030853a02c3b04d96a3c432b883e403175c954cd81Argyrios Kyrtzidisrecalculate_input_bindings(struct gl_context *ctx)
4040853a02c3b04d96a3c432b883e403175c954cd81Argyrios Kyrtzidis{
405914ed9d30e9abf829a62aa996b083b1e47c19ff6Douglas Gregor   struct vbo_context *vbo = vbo_context(ctx);
406914ed9d30e9abf829a62aa996b083b1e47c19ff6Douglas Gregor   struct vbo_exec_context *exec = &vbo->exec;
407914ed9d30e9abf829a62aa996b083b1e47c19ff6Douglas Gregor   struct gl_client_array *vertexAttrib = ctx->Array.ArrayObj->VertexAttrib;
408914ed9d30e9abf829a62aa996b083b1e47c19ff6Douglas Gregor   const struct gl_client_array **inputs = &exec->array.inputs[0];
409914ed9d30e9abf829a62aa996b083b1e47c19ff6Douglas Gregor   GLbitfield64 const_inputs = 0x0;
410914ed9d30e9abf829a62aa996b083b1e47c19ff6Douglas Gregor   GLuint i;
411405634b215f19eec7183bd8005e34aa5a02f64a1Douglas Gregor
412405634b215f19eec7183bd8005e34aa5a02f64a1Douglas Gregor   switch (get_program_mode(ctx)) {
413f772d1e2a5688572d07f42896a50ac57a4a41fe8Daniel Dunbar   case VP_NONE:
414389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis      /* When no vertex program is active (or the vertex program is generated
415389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis       * from fixed-function state).  We put the material values into the
41677accc11f04ed4ff9afd4e27d430144d4714be56Steve Naroff       * generic slots.  This is the only situation where material values
4173c7f4134603d04b44f997b43c0a9def270f25386Sebastian Redl       * are available as per-vertex attributes.
418b85bca2676b433ae555db09de4dd2823ff13b856Zhongxing Xu       */
419313e26c4e81f0e467490a530548450f4c824a6c4Douglas Gregor      for (i = 0; i < VERT_ATTRIB_FF_MAX; i++) {
420313e26c4e81f0e467490a530548450f4c824a6c4Douglas Gregor	 if (vertexAttrib[VERT_ATTRIB_FF(i)].Enabled)
421313e26c4e81f0e467490a530548450f4c824a6c4Douglas Gregor	    inputs[i] = &vertexAttrib[VERT_ATTRIB_FF(i)];
422313e26c4e81f0e467490a530548450f4c824a6c4Douglas Gregor	 else {
423313e26c4e81f0e467490a530548450f4c824a6c4Douglas Gregor	    inputs[i] = &vbo->currval[VBO_ATTRIB_POS+i];
424313e26c4e81f0e467490a530548450f4c824a6c4Douglas Gregor            const_inputs |= VERT_BIT(i);
425313e26c4e81f0e467490a530548450f4c824a6c4Douglas Gregor         }
4267d1d49d2971b20a97b3c2a301470b9eaaa130137Douglas Gregor      }
427f772d1e2a5688572d07f42896a50ac57a4a41fe8Daniel Dunbar
42815727ddb11405c45372150b5bfb07dbfa4c9960bArgyrios Kyrtzidis      for (i = 0; i < MAT_ATTRIB_MAX; i++) {
42915727ddb11405c45372150b5bfb07dbfa4c9960bArgyrios Kyrtzidis	 inputs[VERT_ATTRIB_GENERIC(i)] =
43015727ddb11405c45372150b5bfb07dbfa4c9960bArgyrios Kyrtzidis	    &vbo->currval[VBO_ATTRIB_MAT_FRONT_AMBIENT+i];
431eb8837b88c18631c69ac75f64ab1853762063180Douglas Gregor         const_inputs |= VERT_BIT_GENERIC(i);
432eb8837b88c18631c69ac75f64ab1853762063180Douglas Gregor      }
433eb8837b88c18631c69ac75f64ab1853762063180Douglas Gregor
434eb8837b88c18631c69ac75f64ab1853762063180Douglas Gregor      /* Could use just about anything, just to fill in the empty
435f96b524306ccfa623235d375deee79637bd38f29Steve Naroff       * slots:
436f96b524306ccfa623235d375deee79637bd38f29Steve Naroff       */
437f772d1e2a5688572d07f42896a50ac57a4a41fe8Daniel Dunbar      for (i = MAT_ATTRIB_MAX; i < VERT_ATTRIB_GENERIC_MAX; i++) {
438213f18b3d654de7d1c7cf4a329ea9d3db1c50b6aDouglas Gregor	 inputs[VERT_ATTRIB_GENERIC(i)] = &vbo->currval[VBO_ATTRIB_GENERIC0+i];
439213f18b3d654de7d1c7cf4a329ea9d3db1c50b6aDouglas Gregor         const_inputs |= VERT_BIT_GENERIC(i);
440213f18b3d654de7d1c7cf4a329ea9d3db1c50b6aDouglas Gregor      }
441eb8837b88c18631c69ac75f64ab1853762063180Douglas Gregor      break;
442eb8837b88c18631c69ac75f64ab1853762063180Douglas Gregor
443eb8837b88c18631c69ac75f64ab1853762063180Douglas Gregor   case VP_NV:
444f772d1e2a5688572d07f42896a50ac57a4a41fe8Daniel Dunbar      /* NV_vertex_program - attribute arrays alias and override
445eb8837b88c18631c69ac75f64ab1853762063180Douglas Gregor       * conventional, legacy arrays.  No materials, and the generic
446eb8837b88c18631c69ac75f64ab1853762063180Douglas Gregor       * slots are vacant.
447eb8837b88c18631c69ac75f64ab1853762063180Douglas Gregor       */
448f772d1e2a5688572d07f42896a50ac57a4a41fe8Daniel Dunbar      for (i = 0; i < VERT_ATTRIB_FF_MAX; i++) {
449eb8837b88c18631c69ac75f64ab1853762063180Douglas Gregor	 if (i < VERT_ATTRIB_GENERIC_MAX
450eb8837b88c18631c69ac75f64ab1853762063180Douglas Gregor             && vertexAttrib[VERT_ATTRIB_GENERIC(i)].Enabled)
451f772d1e2a5688572d07f42896a50ac57a4a41fe8Daniel Dunbar	    inputs[i] = &vertexAttrib[VERT_ATTRIB_GENERIC(i)];
452eb8837b88c18631c69ac75f64ab1853762063180Douglas Gregor	 else if (vertexAttrib[VERT_ATTRIB_FF(i)].Enabled)
453eb8837b88c18631c69ac75f64ab1853762063180Douglas Gregor	    inputs[i] = &vertexAttrib[VERT_ATTRIB_FF(i)];
454eb8837b88c18631c69ac75f64ab1853762063180Douglas Gregor	 else {
455eb8837b88c18631c69ac75f64ab1853762063180Douglas Gregor	    inputs[i] = &vbo->currval[VBO_ATTRIB_POS+i];
456eb8837b88c18631c69ac75f64ab1853762063180Douglas Gregor            const_inputs |= VERT_BIT_FF(i);
457eb8837b88c18631c69ac75f64ab1853762063180Douglas Gregor         }
458eb8837b88c18631c69ac75f64ab1853762063180Douglas Gregor      }
459eb8837b88c18631c69ac75f64ab1853762063180Douglas Gregor
460eb8837b88c18631c69ac75f64ab1853762063180Douglas Gregor      /* Could use just about anything, just to fill in the empty
461eb8837b88c18631c69ac75f64ab1853762063180Douglas Gregor       * slots:
462eb8837b88c18631c69ac75f64ab1853762063180Douglas Gregor       */
463eb8837b88c18631c69ac75f64ab1853762063180Douglas Gregor      for (i = 0; i < VERT_ATTRIB_GENERIC_MAX; i++) {
464eb8837b88c18631c69ac75f64ab1853762063180Douglas Gregor	 inputs[VERT_ATTRIB_GENERIC(i)] = &vbo->currval[VBO_ATTRIB_GENERIC0+i];
465eb8837b88c18631c69ac75f64ab1853762063180Douglas Gregor         const_inputs |= VERT_BIT_GENERIC(i);
466eb8837b88c18631c69ac75f64ab1853762063180Douglas Gregor      }
467eb8837b88c18631c69ac75f64ab1853762063180Douglas Gregor      break;
468eb8837b88c18631c69ac75f64ab1853762063180Douglas Gregor
469eb8837b88c18631c69ac75f64ab1853762063180Douglas Gregor   case VP_ARB:
470eb8837b88c18631c69ac75f64ab1853762063180Douglas Gregor      /* GL_ARB_vertex_program or GLSL vertex shader - Only the generic[0]
471eb8837b88c18631c69ac75f64ab1853762063180Douglas Gregor       * attribute array aliases and overrides the legacy position array.
472eb8837b88c18631c69ac75f64ab1853762063180Douglas Gregor       *
473eb8837b88c18631c69ac75f64ab1853762063180Douglas Gregor       * Otherwise, legacy attributes available in the legacy slots,
4748538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl       * generic attributes in the generic slots and materials are not
475eb8837b88c18631c69ac75f64ab1853762063180Douglas Gregor       * available as per-vertex attributes.
476f772d1e2a5688572d07f42896a50ac57a4a41fe8Daniel Dunbar       */
477f772d1e2a5688572d07f42896a50ac57a4a41fe8Daniel Dunbar      if (vertexAttrib[VERT_ATTRIB_GENERIC0].Enabled)
4789b7db6200d366e4964d63ae1f33c7b9d7b9831cbDouglas Gregor	 inputs[0] = &vertexAttrib[VERT_ATTRIB_GENERIC0];
4799b7db6200d366e4964d63ae1f33c7b9d7b9831cbDouglas Gregor      else if (vertexAttrib[VERT_ATTRIB_POS].Enabled)
4809b7db6200d366e4964d63ae1f33c7b9d7b9831cbDouglas Gregor	 inputs[0] = &vertexAttrib[VERT_ATTRIB_POS];
4819b7db6200d366e4964d63ae1f33c7b9d7b9831cbDouglas Gregor      else {
4829b7db6200d366e4964d63ae1f33c7b9d7b9831cbDouglas Gregor	 inputs[0] = &vbo->currval[VBO_ATTRIB_POS];
48389d9980bbc2e4a4ac86673e6ec16fb9f5babb63bDouglas Gregor         const_inputs |= VERT_BIT_POS;
48489d9980bbc2e4a4ac86673e6ec16fb9f5babb63bDouglas Gregor      }
48589d9980bbc2e4a4ac86673e6ec16fb9f5babb63bDouglas Gregor
48689d9980bbc2e4a4ac86673e6ec16fb9f5babb63bDouglas Gregor      for (i = 1; i < VERT_ATTRIB_FF_MAX; i++) {
48789d9980bbc2e4a4ac86673e6ec16fb9f5babb63bDouglas Gregor	 if (vertexAttrib[VERT_ATTRIB_FF(i)].Enabled)
48889d9980bbc2e4a4ac86673e6ec16fb9f5babb63bDouglas Gregor	    inputs[i] = &vertexAttrib[VERT_ATTRIB_FF(i)];
48989d9980bbc2e4a4ac86673e6ec16fb9f5babb63bDouglas Gregor	 else {
49089d9980bbc2e4a4ac86673e6ec16fb9f5babb63bDouglas Gregor	    inputs[i] = &vbo->currval[VBO_ATTRIB_POS+i];
49189d9980bbc2e4a4ac86673e6ec16fb9f5babb63bDouglas Gregor            const_inputs |= VERT_BIT_FF(i);
49289d9980bbc2e4a4ac86673e6ec16fb9f5babb63bDouglas Gregor         }
49389d9980bbc2e4a4ac86673e6ec16fb9f5babb63bDouglas Gregor      }
494788f5a1242c04762f91eaa7565c07b9865846d88Douglas Gregor
495788f5a1242c04762f91eaa7565c07b9865846d88Douglas Gregor      for (i = 1; i < VERT_ATTRIB_GENERIC_MAX; i++) {
496788f5a1242c04762f91eaa7565c07b9865846d88Douglas Gregor	 if (vertexAttrib[VERT_ATTRIB_GENERIC(i)].Enabled)
497788f5a1242c04762f91eaa7565c07b9865846d88Douglas Gregor	    inputs[VERT_ATTRIB_GENERIC(i)] = &vertexAttrib[VERT_ATTRIB_GENERIC(i)];
498788f5a1242c04762f91eaa7565c07b9865846d88Douglas Gregor	 else {
499788f5a1242c04762f91eaa7565c07b9865846d88Douglas Gregor	    inputs[VERT_ATTRIB_GENERIC(i)] = &vbo->currval[VBO_ATTRIB_GENERIC0+i];
500a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor            const_inputs |= VERT_BIT_GENERIC(i);
501405634b215f19eec7183bd8005e34aa5a02f64a1Douglas Gregor         }
502405634b215f19eec7183bd8005e34aa5a02f64a1Douglas Gregor      }
503405634b215f19eec7183bd8005e34aa5a02f64a1Douglas Gregor
504405634b215f19eec7183bd8005e34aa5a02f64a1Douglas Gregor      inputs[VERT_ATTRIB_GENERIC0] = inputs[0];
505405634b215f19eec7183bd8005e34aa5a02f64a1Douglas Gregor      break;
506405634b215f19eec7183bd8005e34aa5a02f64a1Douglas Gregor   }
507405634b215f19eec7183bd8005e34aa5a02f64a1Douglas Gregor
508405634b215f19eec7183bd8005e34aa5a02f64a1Douglas Gregor   _mesa_set_varying_vp_inputs( ctx, VERT_BIT_ALL & (~const_inputs) );
509405634b215f19eec7183bd8005e34aa5a02f64a1Douglas Gregor   ctx->NewDriverState |= ctx->DriverFlags.NewArray;
510405634b215f19eec7183bd8005e34aa5a02f64a1Douglas Gregor}
511405634b215f19eec7183bd8005e34aa5a02f64a1Douglas Gregor
512a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor
513a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor/**
51487c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor * Examine the enabled vertex arrays to set the exec->array.inputs[] values.
51587c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor * These will point to the arrays to actually use for drawing.  Some will
51687c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor * be user-provided arrays, other will be zero-stride const-valued arrays.
51787c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor * Note that this might set the _NEW_VARYING_VP_INPUTS dirty flag so state
51887c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor * validation must be done after this call.
51987c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor */
52087c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregorvoid
52187c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregorvbo_bind_arrays(struct gl_context *ctx)
52287c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor{
52387c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor   struct vbo_context *vbo = vbo_context(ctx);
52487c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor   struct vbo_exec_context *exec = &vbo->exec;
52587c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor
52687c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor   vbo_draw_method(vbo, DRAW_ARRAYS);
52787c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor
528389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis   if (exec->array.recalculate_inputs) {
529389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis      recalculate_input_bindings(ctx);
53075dfb65c38d51772df9a00ce2d2feeefd55667adChris Lattner
531389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis      /* Again... because we may have changed the bitmask of per-vertex varying
532df95a13ec73d2cdaea79555cb412d767f4963120Douglas Gregor       * attributes.  If we regenerate the fixed-function vertex program now
533df95a13ec73d2cdaea79555cb412d767f4963120Douglas Gregor       * we may be able to prune down the number of vertex attributes which we
534df95a13ec73d2cdaea79555cb412d767f4963120Douglas Gregor       * need in the shader.
535df95a13ec73d2cdaea79555cb412d767f4963120Douglas Gregor       */
536df95a13ec73d2cdaea79555cb412d767f4963120Douglas Gregor      if (ctx->NewState) {
537df95a13ec73d2cdaea79555cb412d767f4963120Douglas Gregor         _mesa_update_state(ctx);
5384db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor      }
5394db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor
5404db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor      exec->array.recalculate_inputs = GL_FALSE;
5414db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor   }
5423c7f4134603d04b44f997b43c0a9def270f25386Sebastian Redl}
5430853a02c3b04d96a3c432b883e403175c954cd81Argyrios Kyrtzidis
5443c7f4134603d04b44f997b43c0a9def270f25386Sebastian Redl
5450853a02c3b04d96a3c432b883e403175c954cd81Argyrios Kyrtzidis/**
5465262fda30b876c8aae95f2eb92e349418d6b14bbDaniel Dunbar * Handle a draw case that potentially has primitive restart enabled.
5475262fda30b876c8aae95f2eb92e349418d6b14bbDaniel Dunbar *
54831b87d8006d4863dd9b17e515ac720941efc38e3Daniel Dunbar * If primitive restart is enabled, and PrimitiveRestartInSoftware is
5493c7f4134603d04b44f997b43c0a9def270f25386Sebastian Redl * set, then vbo_sw_primitive_restart is used to handle the primitive
5503c7f4134603d04b44f997b43c0a9def270f25386Sebastian Redl * restart case in software.
55128019772db70d4547be05a042eb950bc910f134fDouglas Gregor */
552389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidisstatic void
5535cf48766d626ff6b223acc9d4b7e415ca8480836Ted Kremenekvbo_handle_primitive_restart(struct gl_context *ctx,
5544db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor                             const struct _mesa_prim *prim,
555a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor                             GLuint nr_prims,
556a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor                             const struct _mesa_index_buffer *ib,
557521bf9c529e653ab28896d027352d3e16e2672d5Daniel Dunbar                             GLboolean index_bounds_valid,
5584cd912aa94656697a44c3ebb159f05060300524eDouglas Gregor                             GLuint min_index,
5594cd912aa94656697a44c3ebb159f05060300524eDouglas Gregor                             GLuint max_index)
5604cd912aa94656697a44c3ebb159f05060300524eDouglas Gregor{
5614cd912aa94656697a44c3ebb159f05060300524eDouglas Gregor   struct vbo_context *vbo = vbo_context(ctx);
5624cd912aa94656697a44c3ebb159f05060300524eDouglas Gregor
5634cd912aa94656697a44c3ebb159f05060300524eDouglas Gregor   if ((ib != NULL) &&
5644cd912aa94656697a44c3ebb159f05060300524eDouglas Gregor       ctx->Const.PrimitiveRestartInSoftware &&
5654cd912aa94656697a44c3ebb159f05060300524eDouglas Gregor       ctx->Array.PrimitiveRestart) {
5664cd912aa94656697a44c3ebb159f05060300524eDouglas Gregor      /* Handle primitive restart in software */
5674cd912aa94656697a44c3ebb159f05060300524eDouglas Gregor      vbo_sw_primitive_restart(ctx, prim, nr_prims, ib);
5684cd912aa94656697a44c3ebb159f05060300524eDouglas Gregor   } else {
5694cd912aa94656697a44c3ebb159f05060300524eDouglas Gregor      /* Call driver directly for draw_prims */
5704cd912aa94656697a44c3ebb159f05060300524eDouglas Gregor      vbo->draw_prims(ctx, prim, nr_prims, ib,
571521bf9c529e653ab28896d027352d3e16e2672d5Daniel Dunbar                      index_bounds_valid, min_index, max_index, NULL);
572521bf9c529e653ab28896d027352d3e16e2672d5Daniel Dunbar   }
573521bf9c529e653ab28896d027352d3e16e2672d5Daniel Dunbar}
574521bf9c529e653ab28896d027352d3e16e2672d5Daniel Dunbar
575f7acc37450d59ef751df73acb91de73850cc6517Daniel Dunbar
576521bf9c529e653ab28896d027352d3e16e2672d5Daniel Dunbar/**
5775262fda30b876c8aae95f2eb92e349418d6b14bbDaniel Dunbar * Helper function called by the other DrawArrays() functions below.
5785262fda30b876c8aae95f2eb92e349418d6b14bbDaniel Dunbar * This is where we handle primitive restart for drawing non-indexed
579521bf9c529e653ab28896d027352d3e16e2672d5Daniel Dunbar * arrays.  If primitive restart is enabled, it typically means
580521bf9c529e653ab28896d027352d3e16e2672d5Daniel Dunbar * splitting one DrawArrays() into two.
581521bf9c529e653ab28896d027352d3e16e2672d5Daniel Dunbar */
582f7acc37450d59ef751df73acb91de73850cc6517Daniel Dunbarstatic void
58328019772db70d4547be05a042eb950bc910f134fDouglas Gregorvbo_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start,
584a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor                GLsizei count, GLuint numInstances, GLuint baseInstance)
58544c181aec37789f25f6c15543c164416f72e562aDouglas Gregor{
586df95a13ec73d2cdaea79555cb412d767f4963120Douglas Gregor   struct vbo_context *vbo = vbo_context(ctx);
58787c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor   struct vbo_exec_context *exec = &vbo->exec;
58887c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor   struct _mesa_prim prim[2];
589521bf9c529e653ab28896d027352d3e16e2672d5Daniel Dunbar
5907b55668db7618334cc40011d3c1e128524d89462Daniel Dunbar   vbo_bind_arrays(ctx);
5917b55668db7618334cc40011d3c1e128524d89462Daniel Dunbar
5927b55668db7618334cc40011d3c1e128524d89462Daniel Dunbar   /* init most fields to zero */
5937b55668db7618334cc40011d3c1e128524d89462Daniel Dunbar   memset(prim, 0, sizeof(prim));
5947b55668db7618334cc40011d3c1e128524d89462Daniel Dunbar   prim[0].begin = 1;
5957b55668db7618334cc40011d3c1e128524d89462Daniel Dunbar   prim[0].end = 1;
5967b55668db7618334cc40011d3c1e128524d89462Daniel Dunbar   prim[0].mode = mode;
5975262fda30b876c8aae95f2eb92e349418d6b14bbDaniel Dunbar   prim[0].num_instances = numInstances;
5985262fda30b876c8aae95f2eb92e349418d6b14bbDaniel Dunbar   prim[0].base_instance = baseInstance;
5997b55668db7618334cc40011d3c1e128524d89462Daniel Dunbar
600869824e87940f97b87064db2df2861e82e08a8c6Daniel Dunbar   /* Implement the primitive restart index */
6017b55668db7618334cc40011d3c1e128524d89462Daniel Dunbar   if (ctx->Array.PrimitiveRestart && ctx->Array.RestartIndex < count) {
6027b55668db7618334cc40011d3c1e128524d89462Daniel Dunbar      GLuint primCount = 0;
6037b55668db7618334cc40011d3c1e128524d89462Daniel Dunbar
6047b55668db7618334cc40011d3c1e128524d89462Daniel Dunbar      if (ctx->Array.RestartIndex == start) {
6057b55668db7618334cc40011d3c1e128524d89462Daniel Dunbar         /* special case: RestartIndex at beginning */
60628019772db70d4547be05a042eb950bc910f134fDouglas Gregor         if (count > 1) {
607869824e87940f97b87064db2df2861e82e08a8c6Daniel Dunbar            prim[0].start = start + 1;
6087b55668db7618334cc40011d3c1e128524d89462Daniel Dunbar            prim[0].count = count - 1;
609e47be3e9682e82da15059006f43c7f3c021e4fffDouglas Gregor            primCount = 1;
6104db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor         }
611a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor      }
612df95a13ec73d2cdaea79555cb412d767f4963120Douglas Gregor      else if (ctx->Array.RestartIndex == start + count - 1) {
61387c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor         /* special case: RestartIndex at end */
61499ba202f659e1885fa5ee114f97c97cf6a857491Douglas Gregor         if (count > 1) {
61599ba202f659e1885fa5ee114f97c97cf6a857491Douglas Gregor            prim[0].start = start;
61699ba202f659e1885fa5ee114f97c97cf6a857491Douglas Gregor            prim[0].count = count - 1;
617abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor            primCount = 1;
618abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor         }
619abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor      }
620abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor      else {
621abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor         /* general case: RestartIndex in middle, split into two prims */
622abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor         prim[0].start = start;
623abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor         prim[0].count = ctx->Array.RestartIndex - start;
624abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor
6251abc6bca3d7fb0e7b1e40fbcad6cfb5e10594548Douglas Gregor         prim[1] = prim[0];
6261abc6bca3d7fb0e7b1e40fbcad6cfb5e10594548Douglas Gregor         prim[1].start = ctx->Array.RestartIndex + 1;
6271abc6bca3d7fb0e7b1e40fbcad6cfb5e10594548Douglas Gregor         prim[1].count = count - prim[1].start;
6281abc6bca3d7fb0e7b1e40fbcad6cfb5e10594548Douglas Gregor
629cee235cdf0b8047761ffac598c4c3a32ab7411a2Douglas Gregor         primCount = 2;
630cee235cdf0b8047761ffac598c4c3a32ab7411a2Douglas Gregor      }
631cee235cdf0b8047761ffac598c4c3a32ab7411a2Douglas Gregor
632cee235cdf0b8047761ffac598c4c3a32ab7411a2Douglas Gregor      if (primCount > 0) {
633cee235cdf0b8047761ffac598c4c3a32ab7411a2Douglas Gregor         /* draw one or two prims */
634cee235cdf0b8047761ffac598c4c3a32ab7411a2Douglas Gregor         check_buffers_are_unmapped(exec->array.inputs);
635cee235cdf0b8047761ffac598c4c3a32ab7411a2Douglas Gregor         vbo->draw_prims(ctx, prim, primCount, NULL,
636cee235cdf0b8047761ffac598c4c3a32ab7411a2Douglas Gregor                         GL_TRUE, start, start + count - 1, NULL);
637cee235cdf0b8047761ffac598c4c3a32ab7411a2Douglas Gregor      }
638cee235cdf0b8047761ffac598c4c3a32ab7411a2Douglas Gregor   }
639cee235cdf0b8047761ffac598c4c3a32ab7411a2Douglas Gregor   else {
6401abc6bca3d7fb0e7b1e40fbcad6cfb5e10594548Douglas Gregor      /* no prim restart */
6412283d79155a3e82442fce124ce5fd704ca138801Douglas Gregor      prim[0].start = start;
6422283d79155a3e82442fce124ce5fd704ca138801Douglas Gregor      prim[0].count = count;
6431abc6bca3d7fb0e7b1e40fbcad6cfb5e10594548Douglas Gregor
6441abc6bca3d7fb0e7b1e40fbcad6cfb5e10594548Douglas Gregor      check_buffers_are_unmapped(exec->array.inputs);
645cee235cdf0b8047761ffac598c4c3a32ab7411a2Douglas Gregor      vbo->draw_prims(ctx, prim, 1, NULL,
6461abc6bca3d7fb0e7b1e40fbcad6cfb5e10594548Douglas Gregor                      GL_TRUE, start, start + count - 1,
6471abc6bca3d7fb0e7b1e40fbcad6cfb5e10594548Douglas Gregor                      NULL);
6481abc6bca3d7fb0e7b1e40fbcad6cfb5e10594548Douglas Gregor   }
6492283d79155a3e82442fce124ce5fd704ca138801Douglas Gregor
6502283d79155a3e82442fce124ce5fd704ca138801Douglas Gregor   if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
6517ae2faafd30524ef5f863bb3b8701977888839bbDouglas Gregor      _mesa_flush(ctx);
6527ae2faafd30524ef5f863bb3b8701977888839bbDouglas Gregor   }
6537ae2faafd30524ef5f863bb3b8701977888839bbDouglas Gregor}
6547ae2faafd30524ef5f863bb3b8701977888839bbDouglas Gregor
6557ae2faafd30524ef5f863bb3b8701977888839bbDouglas Gregor
6560853a02c3b04d96a3c432b883e403175c954cd81Argyrios Kyrtzidis
6570853a02c3b04d96a3c432b883e403175c954cd81Argyrios Kyrtzidis/**
6580853a02c3b04d96a3c432b883e403175c954cd81Argyrios Kyrtzidis * Called from glDrawArrays when in immediate mode (not display list mode).
6590853a02c3b04d96a3c432b883e403175c954cd81Argyrios Kyrtzidis */
6600853a02c3b04d96a3c432b883e403175c954cd81Argyrios Kyrtzidisstatic void GLAPIENTRY
661vbo_exec_DrawArrays(GLenum mode, GLint start, GLsizei count)
662{
663   GET_CURRENT_CONTEXT(ctx);
664
665   if (MESA_VERBOSE & VERBOSE_DRAW)
666      _mesa_debug(ctx, "glDrawArrays(%s, %d, %d)\n",
667                  _mesa_lookup_enum_by_nr(mode), start, count);
668
669   FLUSH_CURRENT(ctx, 0);
670
671   if (!_mesa_validate_DrawArrays( ctx, mode, start, count ))
672      return;
673
674   if (0)
675      check_draw_arrays_data(ctx, start, count);
676
677   vbo_draw_arrays(ctx, mode, start, count, 1, 0);
678
679   if (0)
680      print_draw_arrays(ctx, mode, start, count);
681}
682
683
684/**
685 * Called from glDrawArraysInstanced when in immediate mode (not
686 * display list mode).
687 */
688static void GLAPIENTRY
689vbo_exec_DrawArraysInstanced(GLenum mode, GLint start, GLsizei count,
690                             GLsizei numInstances)
691{
692   GET_CURRENT_CONTEXT(ctx);
693
694   if (MESA_VERBOSE & VERBOSE_DRAW)
695      _mesa_debug(ctx, "glDrawArraysInstanced(%s, %d, %d, %d)\n",
696                  _mesa_lookup_enum_by_nr(mode), start, count, numInstances);
697
698   FLUSH_CURRENT(ctx, 0);
699
700   if (!_mesa_validate_DrawArraysInstanced(ctx, mode, start, count, numInstances))
701      return;
702
703   if (0)
704      check_draw_arrays_data(ctx, start, count);
705
706   vbo_draw_arrays(ctx, mode, start, count, numInstances, 0);
707
708   if (0)
709      print_draw_arrays(ctx, mode, start, count);
710}
711
712
713/**
714 * Called from glDrawArraysInstancedBaseInstance when in immediate mode.
715 */
716static void GLAPIENTRY
717vbo_exec_DrawArraysInstancedBaseInstance(GLenum mode, GLint first, GLsizei count,
718                                         GLsizei numInstances, GLuint baseInstance)
719{
720   GET_CURRENT_CONTEXT(ctx);
721
722   if (MESA_VERBOSE & VERBOSE_DRAW)
723      _mesa_debug(ctx, "glDrawArraysInstancedBaseInstance(%s, %d, %d, %d, %d)\n",
724                  _mesa_lookup_enum_by_nr(mode), first, count,
725                  numInstances, baseInstance);
726
727   if (!_mesa_validate_DrawArraysInstanced(ctx, mode, first, count,
728                                           numInstances))
729      return;
730
731   FLUSH_CURRENT(ctx, 0);
732
733   if (!_mesa_valid_to_render(ctx, "glDrawArraysInstancedBaseInstance"))
734      return;
735
736   if (0)
737      check_draw_arrays_data(ctx, first, count);
738
739   vbo_draw_arrays(ctx, mode, first, count, numInstances, baseInstance);
740
741   if (0)
742      print_draw_arrays(ctx, mode, first, count);
743}
744
745
746
747/**
748 * Map GL_ELEMENT_ARRAY_BUFFER and print contents.
749 * For debugging.
750 */
751#if 0
752static void
753dump_element_buffer(struct gl_context *ctx, GLenum type)
754{
755   const GLvoid *map =
756      ctx->Driver.MapBufferRange(ctx, 0,
757				 ctx->Array.ArrayObj->ElementArrayBufferObj->Size,
758				 GL_MAP_READ_BIT,
759				 ctx->Array.ArrayObj->ElementArrayBufferObj);
760   switch (type) {
761   case GL_UNSIGNED_BYTE:
762      {
763         const GLubyte *us = (const GLubyte *) map;
764         GLint i;
765         for (i = 0; i < ctx->Array.ArrayObj->ElementArrayBufferObj->Size; i++) {
766            printf("%02x ", us[i]);
767            if (i % 32 == 31)
768               printf("\n");
769         }
770         printf("\n");
771      }
772      break;
773   case GL_UNSIGNED_SHORT:
774      {
775         const GLushort *us = (const GLushort *) map;
776         GLint i;
777         for (i = 0; i < ctx->Array.ArrayObj->ElementArrayBufferObj->Size / 2; i++) {
778            printf("%04x ", us[i]);
779            if (i % 16 == 15)
780               printf("\n");
781         }
782         printf("\n");
783      }
784      break;
785   case GL_UNSIGNED_INT:
786      {
787         const GLuint *us = (const GLuint *) map;
788         GLint i;
789         for (i = 0; i < ctx->Array.ArrayObj->ElementArrayBufferObj->Size / 4; i++) {
790            printf("%08x ", us[i]);
791            if (i % 8 == 7)
792               printf("\n");
793         }
794         printf("\n");
795      }
796      break;
797   default:
798      ;
799   }
800
801   ctx->Driver.UnmapBuffer(ctx, ctx->Array.ArrayObj->ElementArrayBufferObj);
802}
803#endif
804
805
806/**
807 * Inner support for both _mesa_DrawElements and _mesa_DrawRangeElements.
808 * Do the rendering for a glDrawElements or glDrawRangeElements call after
809 * we've validated buffer bounds, etc.
810 */
811static void
812vbo_validated_drawrangeelements(struct gl_context *ctx, GLenum mode,
813				GLboolean index_bounds_valid,
814				GLuint start, GLuint end,
815				GLsizei count, GLenum type,
816				const GLvoid *indices,
817				GLint basevertex, GLint numInstances,
818				GLuint baseInstance)
819{
820   struct vbo_context *vbo = vbo_context(ctx);
821   struct vbo_exec_context *exec = &vbo->exec;
822   struct _mesa_index_buffer ib;
823   struct _mesa_prim prim[1];
824
825   vbo_bind_arrays(ctx);
826
827   ib.count = count;
828   ib.type = type;
829   ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj;
830   ib.ptr = indices;
831
832   prim[0].begin = 1;
833   prim[0].end = 1;
834   prim[0].weak = 0;
835   prim[0].pad = 0;
836   prim[0].mode = mode;
837   prim[0].start = 0;
838   prim[0].count = count;
839   prim[0].indexed = 1;
840   prim[0].basevertex = basevertex;
841   prim[0].num_instances = numInstances;
842   prim[0].base_instance = baseInstance;
843
844   /* Need to give special consideration to rendering a range of
845    * indices starting somewhere above zero.  Typically the
846    * application is issuing multiple DrawRangeElements() to draw
847    * successive primitives layed out linearly in the vertex arrays.
848    * Unless the vertex arrays are all in a VBO (or locked as with
849    * CVA), the OpenGL semantics imply that we need to re-read or
850    * re-upload the vertex data on each draw call.
851    *
852    * In the case of hardware tnl, we want to avoid starting the
853    * upload at zero, as it will mean every draw call uploads an
854    * increasing amount of not-used vertex data.  Worse - in the
855    * software tnl module, all those vertices might be transformed and
856    * lit but never rendered.
857    *
858    * If we just upload or transform the vertices in start..end,
859    * however, the indices will be incorrect.
860    *
861    * At this level, we don't know exactly what the requirements of
862    * the backend are going to be, though it will likely boil down to
863    * either:
864    *
865    * 1) Do nothing, everything is in a VBO and is processed once
866    *       only.
867    *
868    * 2) Adjust the indices and vertex arrays so that start becomes
869    *    zero.
870    *
871    * Rather than doing anything here, I'll provide a helper function
872    * for the latter case elsewhere.
873    */
874
875   check_buffers_are_unmapped(exec->array.inputs);
876   vbo_handle_primitive_restart(ctx, prim, 1, &ib,
877                                index_bounds_valid, start, end);
878
879   if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
880      _mesa_flush(ctx);
881   }
882}
883
884
885/**
886 * Called by glDrawRangeElementsBaseVertex() in immediate mode.
887 */
888static void GLAPIENTRY
889vbo_exec_DrawRangeElementsBaseVertex(GLenum mode,
890				     GLuint start, GLuint end,
891				     GLsizei count, GLenum type,
892				     const GLvoid *indices,
893				     GLint basevertex)
894{
895   static GLuint warnCount = 0;
896   GLboolean index_bounds_valid = GL_TRUE;
897   GET_CURRENT_CONTEXT(ctx);
898
899   if (MESA_VERBOSE & VERBOSE_DRAW)
900      _mesa_debug(ctx,
901                "glDrawRangeElementsBaseVertex(%s, %u, %u, %d, %s, %p, %d)\n",
902                _mesa_lookup_enum_by_nr(mode), start, end, count,
903                _mesa_lookup_enum_by_nr(type), indices, basevertex);
904
905   FLUSH_CURRENT(ctx, 0);
906
907   if (!_mesa_validate_DrawRangeElements( ctx, mode, start, end, count,
908                                          type, indices, basevertex ))
909      return;
910
911   if ((int) end + basevertex < 0 ||
912       start + basevertex >= ctx->Array.ArrayObj->_MaxElement) {
913      /* The application requested we draw using a range of indices that's
914       * outside the bounds of the current VBO.  This is invalid and appears
915       * to give undefined results.  The safest thing to do is to simply
916       * ignore the range, in case the application botched their range tracking
917       * but did provide valid indices.  Also issue a warning indicating that
918       * the application is broken.
919       */
920      if (warnCount++ < 10) {
921         _mesa_warning(ctx, "glDrawRangeElements(start %u, end %u, "
922                       "basevertex %d, count %d, type 0x%x, indices=%p):\n"
923                       "\trange is outside VBO bounds (max=%u); ignoring.\n"
924                       "\tThis should be fixed in the application.",
925                       start, end, basevertex, count, type, indices,
926                       ctx->Array.ArrayObj->_MaxElement - 1);
927      }
928      index_bounds_valid = GL_FALSE;
929   }
930
931   /* NOTE: It's important that 'end' is a reasonable value.
932    * in _tnl_draw_prims(), we use end to determine how many vertices
933    * to transform.  If it's too large, we can unnecessarily split prims
934    * or we can read/write out of memory in several different places!
935    */
936
937   /* Catch/fix some potential user errors */
938   if (type == GL_UNSIGNED_BYTE) {
939      start = MIN2(start, 0xff);
940      end = MIN2(end, 0xff);
941   }
942   else if (type == GL_UNSIGNED_SHORT) {
943      start = MIN2(start, 0xffff);
944      end = MIN2(end, 0xffff);
945   }
946
947   if (0) {
948      printf("glDraw[Range]Elements{,BaseVertex}"
949	     "(start %u, end %u, type 0x%x, count %d) ElemBuf %u, "
950	     "base %d\n",
951	     start, end, type, count,
952	     ctx->Array.ArrayObj->ElementArrayBufferObj->Name,
953	     basevertex);
954   }
955
956   if ((int) start + basevertex < 0 ||
957       end + basevertex >= ctx->Array.ArrayObj->_MaxElement)
958      index_bounds_valid = GL_FALSE;
959
960#if 0
961   check_draw_elements_data(ctx, count, type, indices);
962#else
963   (void) check_draw_elements_data;
964#endif
965
966   vbo_validated_drawrangeelements(ctx, mode, index_bounds_valid, start, end,
967				   count, type, indices, basevertex, 1, 0);
968}
969
970
971/**
972 * Called by glDrawRangeElements() in immediate mode.
973 */
974static void GLAPIENTRY
975vbo_exec_DrawRangeElements(GLenum mode, GLuint start, GLuint end,
976                           GLsizei count, GLenum type, const GLvoid *indices)
977{
978   if (MESA_VERBOSE & VERBOSE_DRAW) {
979      GET_CURRENT_CONTEXT(ctx);
980      _mesa_debug(ctx,
981                  "glDrawRangeElements(%s, %u, %u, %d, %s, %p)\n",
982                  _mesa_lookup_enum_by_nr(mode), start, end, count,
983                  _mesa_lookup_enum_by_nr(type), indices);
984   }
985
986   vbo_exec_DrawRangeElementsBaseVertex(mode, start, end, count, type,
987					indices, 0);
988}
989
990
991/**
992 * Called by glDrawElements() in immediate mode.
993 */
994static void GLAPIENTRY
995vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type,
996                      const GLvoid *indices)
997{
998   GET_CURRENT_CONTEXT(ctx);
999
1000   if (MESA_VERBOSE & VERBOSE_DRAW)
1001      _mesa_debug(ctx, "glDrawElements(%s, %u, %s, %p)\n",
1002                  _mesa_lookup_enum_by_nr(mode), count,
1003                  _mesa_lookup_enum_by_nr(type), indices);
1004
1005   FLUSH_CURRENT(ctx, 0);
1006
1007   if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices, 0 ))
1008      return;
1009
1010   vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
1011				   count, type, indices, 0, 1, 0);
1012}
1013
1014
1015/**
1016 * Called by glDrawElementsBaseVertex() in immediate mode.
1017 */
1018static void GLAPIENTRY
1019vbo_exec_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
1020				const GLvoid *indices, GLint basevertex)
1021{
1022   GET_CURRENT_CONTEXT(ctx);
1023
1024   if (MESA_VERBOSE & VERBOSE_DRAW)
1025      _mesa_debug(ctx, "glDrawElementsBaseVertex(%s, %d, %s, %p, %d)\n",
1026                  _mesa_lookup_enum_by_nr(mode), count,
1027                  _mesa_lookup_enum_by_nr(type), indices, basevertex);
1028
1029   FLUSH_CURRENT(ctx, 0);
1030
1031   if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices,
1032				     basevertex ))
1033      return;
1034
1035   vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
1036				   count, type, indices, basevertex, 1, 0);
1037}
1038
1039
1040/**
1041 * Called by glDrawElementsInstanced() in immediate mode.
1042 */
1043static void GLAPIENTRY
1044vbo_exec_DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type,
1045                               const GLvoid *indices, GLsizei numInstances)
1046{
1047   GET_CURRENT_CONTEXT(ctx);
1048
1049   if (MESA_VERBOSE & VERBOSE_DRAW)
1050      _mesa_debug(ctx, "glDrawElementsInstanced(%s, %d, %s, %p, %d)\n",
1051                  _mesa_lookup_enum_by_nr(mode), count,
1052                  _mesa_lookup_enum_by_nr(type), indices, numInstances);
1053
1054   FLUSH_CURRENT(ctx, 0);
1055
1056   if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices,
1057                                             numInstances, 0))
1058      return;
1059
1060   vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
1061				   count, type, indices, 0, numInstances, 0);
1062}
1063
1064
1065/**
1066 * Called by glDrawElementsInstancedBaseVertex() in immediate mode.
1067 */
1068static void GLAPIENTRY
1069vbo_exec_DrawElementsInstancedBaseVertex(GLenum mode, GLsizei count, GLenum type,
1070                               const GLvoid *indices, GLsizei numInstances,
1071                               GLint basevertex)
1072{
1073   GET_CURRENT_CONTEXT(ctx);
1074
1075   if (MESA_VERBOSE & VERBOSE_DRAW)
1076      _mesa_debug(ctx, "glDrawElementsInstancedBaseVertex(%s, %d, %s, %p, %d; %d)\n",
1077                  _mesa_lookup_enum_by_nr(mode), count,
1078                  _mesa_lookup_enum_by_nr(type), indices,
1079                  numInstances, basevertex);
1080
1081   FLUSH_CURRENT(ctx, 0);
1082
1083   if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices,
1084                                             numInstances, basevertex))
1085      return;
1086
1087   vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
1088				   count, type, indices, basevertex, numInstances, 0);
1089}
1090
1091
1092/**
1093 * Called by glDrawElementsInstancedBaseInstance() in immediate mode.
1094 */
1095static void GLAPIENTRY
1096vbo_exec_DrawElementsInstancedBaseInstance(GLenum mode, GLsizei count, GLenum type,
1097                                           const GLvoid *indices, GLsizei numInstances,
1098                                           GLuint baseInstance)
1099{
1100   GET_CURRENT_CONTEXT(ctx);
1101
1102   if (MESA_VERBOSE & VERBOSE_DRAW)
1103      _mesa_debug(ctx, "glDrawElementsInstancedBaseInstance(%s, %d, %s, %p, %d, %d)\n",
1104                  _mesa_lookup_enum_by_nr(mode), count,
1105                  _mesa_lookup_enum_by_nr(type), indices,
1106                  numInstances, baseInstance);
1107
1108   if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices,
1109                                             numInstances, 0))
1110      return;
1111
1112   vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
1113                                   count, type, indices, 0, numInstances,
1114                                   baseInstance);
1115}
1116
1117
1118/**
1119 * Called by glDrawElementsInstancedBaseVertexBaseInstance() in immediate mode.
1120 */
1121static void GLAPIENTRY
1122vbo_exec_DrawElementsInstancedBaseVertexBaseInstance(GLenum mode, GLsizei count, GLenum type,
1123                                                     const GLvoid *indices, GLsizei numInstances,
1124                                                     GLint basevertex, GLuint baseInstance)
1125{
1126   GET_CURRENT_CONTEXT(ctx);
1127
1128   if (MESA_VERBOSE & VERBOSE_DRAW)
1129      _mesa_debug(ctx, "glDrawElementsInstancedBaseVertexBaseInstance(%s, %d, %s, %p, %d, %d, %d)\n",
1130                  _mesa_lookup_enum_by_nr(mode), count,
1131                  _mesa_lookup_enum_by_nr(type), indices,
1132                  numInstances, basevertex, baseInstance);
1133
1134   if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices,
1135                                             numInstances, basevertex))
1136      return;
1137
1138   vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
1139                                   count, type, indices, basevertex, numInstances,
1140                                   baseInstance);
1141}
1142
1143
1144/**
1145 * Inner support for both _mesa_MultiDrawElements() and
1146 * _mesa_MultiDrawRangeElements().
1147 * This does the actual rendering after we've checked array indexes, etc.
1148 */
1149static void
1150vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode,
1151				const GLsizei *count, GLenum type,
1152				const GLvoid * const *indices,
1153				GLsizei primcount,
1154				const GLint *basevertex)
1155{
1156   struct vbo_context *vbo = vbo_context(ctx);
1157   struct vbo_exec_context *exec = &vbo->exec;
1158   struct _mesa_index_buffer ib;
1159   struct _mesa_prim *prim;
1160   unsigned int index_type_size = vbo_sizeof_ib_type(type);
1161   uintptr_t min_index_ptr, max_index_ptr;
1162   GLboolean fallback = GL_FALSE;
1163   int i;
1164
1165   if (primcount == 0)
1166      return;
1167
1168   prim = calloc(1, primcount * sizeof(*prim));
1169   if (prim == NULL) {
1170      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawElements");
1171      return;
1172   }
1173
1174   vbo_bind_arrays(ctx);
1175
1176   min_index_ptr = (uintptr_t)indices[0];
1177   max_index_ptr = 0;
1178   for (i = 0; i < primcount; i++) {
1179      min_index_ptr = MIN2(min_index_ptr, (uintptr_t)indices[i]);
1180      max_index_ptr = MAX2(max_index_ptr, (uintptr_t)indices[i] +
1181			   index_type_size * count[i]);
1182   }
1183
1184   /* Check if we can handle this thing as a bunch of index offsets from the
1185    * same index pointer.  If we can't, then we have to fall back to doing
1186    * a draw_prims per primitive.
1187    * Check that the difference between each prim's indexes is a multiple of
1188    * the index/element size.
1189    */
1190   if (index_type_size != 1) {
1191      for (i = 0; i < primcount; i++) {
1192	 if ((((uintptr_t)indices[i] - min_index_ptr) % index_type_size) != 0) {
1193	    fallback = GL_TRUE;
1194	    break;
1195	 }
1196      }
1197   }
1198
1199   /* If the index buffer isn't in a VBO, then treating the application's
1200    * subranges of the index buffer as one large index buffer may lead to
1201    * us reading unmapped memory.
1202    */
1203   if (!_mesa_is_bufferobj(ctx->Array.ArrayObj->ElementArrayBufferObj))
1204      fallback = GL_TRUE;
1205
1206   if (!fallback) {
1207      ib.count = (max_index_ptr - min_index_ptr) / index_type_size;
1208      ib.type = type;
1209      ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj;
1210      ib.ptr = (void *)min_index_ptr;
1211
1212      for (i = 0; i < primcount; i++) {
1213	 prim[i].begin = (i == 0);
1214	 prim[i].end = (i == primcount - 1);
1215	 prim[i].weak = 0;
1216	 prim[i].pad = 0;
1217	 prim[i].mode = mode;
1218	 prim[i].start = ((uintptr_t)indices[i] - min_index_ptr) / index_type_size;
1219	 prim[i].count = count[i];
1220	 prim[i].indexed = 1;
1221         prim[i].num_instances = 1;
1222         prim[i].base_instance = 0;
1223	 if (basevertex != NULL)
1224	    prim[i].basevertex = basevertex[i];
1225	 else
1226	    prim[i].basevertex = 0;
1227      }
1228
1229      check_buffers_are_unmapped(exec->array.inputs);
1230      vbo_handle_primitive_restart(ctx, prim, primcount, &ib,
1231                                   GL_FALSE, ~0, ~0);
1232   } else {
1233      /* render one prim at a time */
1234      for (i = 0; i < primcount; i++) {
1235	 ib.count = count[i];
1236	 ib.type = type;
1237	 ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj;
1238	 ib.ptr = indices[i];
1239
1240	 prim[0].begin = 1;
1241	 prim[0].end = 1;
1242	 prim[0].weak = 0;
1243	 prim[0].pad = 0;
1244	 prim[0].mode = mode;
1245	 prim[0].start = 0;
1246	 prim[0].count = count[i];
1247	 prim[0].indexed = 1;
1248         prim[0].num_instances = 1;
1249         prim[0].base_instance = 0;
1250	 if (basevertex != NULL)
1251	    prim[0].basevertex = basevertex[i];
1252	 else
1253	    prim[0].basevertex = 0;
1254
1255         check_buffers_are_unmapped(exec->array.inputs);
1256         vbo_handle_primitive_restart(ctx, prim, 1, &ib,
1257                                      GL_FALSE, ~0, ~0);
1258      }
1259   }
1260
1261   free(prim);
1262
1263   if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
1264      _mesa_flush(ctx);
1265   }
1266}
1267
1268
1269static void GLAPIENTRY
1270vbo_exec_MultiDrawElements(GLenum mode,
1271			   const GLsizei *count, GLenum type,
1272			   const GLvoid **indices,
1273			   GLsizei primcount)
1274{
1275   GET_CURRENT_CONTEXT(ctx);
1276   GLint i;
1277
1278   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1279
1280   for (i = 0; i < primcount; i++) {
1281      if (!_mesa_validate_DrawElements(ctx, mode, count[i], type, indices[i],
1282				       0))
1283	 return;
1284   }
1285
1286   vbo_validated_multidrawelements(ctx, mode, count, type, indices, primcount,
1287				   NULL);
1288}
1289
1290
1291static void GLAPIENTRY
1292vbo_exec_MultiDrawElementsBaseVertex(GLenum mode,
1293				     const GLsizei *count, GLenum type,
1294				     const GLvoid * const *indices,
1295				     GLsizei primcount,
1296				     const GLsizei *basevertex)
1297{
1298   GET_CURRENT_CONTEXT(ctx);
1299   GLint i;
1300
1301   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1302
1303   for (i = 0; i < primcount; i++) {
1304      if (!_mesa_validate_DrawElements(ctx, mode, count[i], type, indices[i],
1305				       basevertex[i]))
1306	 return;
1307   }
1308
1309   vbo_validated_multidrawelements(ctx, mode, count, type, indices, primcount,
1310				   basevertex);
1311}
1312
1313#if FEATURE_EXT_transform_feedback
1314
1315static void
1316vbo_draw_transform_feedback(struct gl_context *ctx, GLenum mode,
1317                            struct gl_transform_feedback_object *obj,
1318                            GLuint numInstances)
1319{
1320   struct vbo_context *vbo = vbo_context(ctx);
1321   struct vbo_exec_context *exec = &vbo->exec;
1322   struct _mesa_prim prim[2];
1323
1324   vbo_bind_arrays(ctx);
1325
1326   /* init most fields to zero */
1327   memset(prim, 0, sizeof(prim));
1328   prim[0].begin = 1;
1329   prim[0].end = 1;
1330   prim[0].mode = mode;
1331   prim[0].num_instances = numInstances;
1332   prim[0].base_instance = 0;
1333
1334   /* Maybe we should do some primitive splitting for primitive restart
1335    * (like in DrawArrays), but we have no way to know how many vertices
1336    * will be rendered. */
1337
1338   check_buffers_are_unmapped(exec->array.inputs);
1339   vbo->draw_prims(ctx, prim, 1, NULL,
1340                   GL_TRUE, 0, 0, obj);
1341
1342   if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
1343      _mesa_flush(ctx);
1344   }
1345}
1346
1347/**
1348 * Like DrawArrays, but take the count from a transform feedback object.
1349 * \param mode  GL_POINTS, GL_LINES, GL_TRIANGLE_STRIP, etc.
1350 * \param name  the transform feedback object
1351 * User still has to setup of the vertex attribute info with
1352 * glVertexPointer, glColorPointer, etc.
1353 * Part of GL_ARB_transform_feedback2.
1354 */
1355static void GLAPIENTRY
1356vbo_exec_DrawTransformFeedback(GLenum mode, GLuint name)
1357{
1358   GET_CURRENT_CONTEXT(ctx);
1359   struct gl_transform_feedback_object *obj =
1360      _mesa_lookup_transform_feedback_object(ctx, name);
1361
1362   if (MESA_VERBOSE & VERBOSE_DRAW)
1363      _mesa_debug(ctx, "glDrawTransformFeedback(%s, %d)\n",
1364                  _mesa_lookup_enum_by_nr(mode), name);
1365
1366   FLUSH_CURRENT(ctx, 0);
1367
1368   if (!_mesa_validate_DrawTransformFeedback(ctx, mode, obj)) {
1369      return;
1370   }
1371
1372   vbo_draw_transform_feedback(ctx, mode, obj, 1);
1373}
1374
1375#endif
1376
1377/**
1378 * Plug in the immediate-mode vertex array drawing commands into the
1379 * givven vbo_exec_context object.
1380 */
1381void
1382vbo_exec_array_init( struct vbo_exec_context *exec )
1383{
1384   exec->vtxfmt.DrawArrays = vbo_exec_DrawArrays;
1385   exec->vtxfmt.DrawElements = vbo_exec_DrawElements;
1386   exec->vtxfmt.DrawRangeElements = vbo_exec_DrawRangeElements;
1387   exec->vtxfmt.MultiDrawElementsEXT = vbo_exec_MultiDrawElements;
1388   exec->vtxfmt.DrawElementsBaseVertex = vbo_exec_DrawElementsBaseVertex;
1389   exec->vtxfmt.DrawRangeElementsBaseVertex = vbo_exec_DrawRangeElementsBaseVertex;
1390   exec->vtxfmt.MultiDrawElementsBaseVertex = vbo_exec_MultiDrawElementsBaseVertex;
1391   exec->vtxfmt.DrawArraysInstanced = vbo_exec_DrawArraysInstanced;
1392   exec->vtxfmt.DrawArraysInstancedBaseInstance = vbo_exec_DrawArraysInstancedBaseInstance;
1393   exec->vtxfmt.DrawElementsInstanced = vbo_exec_DrawElementsInstanced;
1394   exec->vtxfmt.DrawElementsInstancedBaseInstance = vbo_exec_DrawElementsInstancedBaseInstance;
1395   exec->vtxfmt.DrawElementsInstancedBaseVertex = vbo_exec_DrawElementsInstancedBaseVertex;
1396   exec->vtxfmt.DrawElementsInstancedBaseVertexBaseInstance = vbo_exec_DrawElementsInstancedBaseVertexBaseInstance;
1397#if FEATURE_EXT_transform_feedback
1398   exec->vtxfmt.DrawTransformFeedback = vbo_exec_DrawTransformFeedback;
1399#endif
1400}
1401
1402
1403void
1404vbo_exec_array_destroy( struct vbo_exec_context *exec )
1405{
1406   /* nothing to do */
1407}
1408
1409
1410
1411/**
1412 * The following functions are only used for OpenGL ES 1/2 support.
1413 * And some aren't even supported (yet) in ES 1/2.
1414 */
1415
1416
1417void GLAPIENTRY
1418_mesa_DrawArrays(GLenum mode, GLint first, GLsizei count)
1419{
1420   vbo_exec_DrawArrays(mode, first, count);
1421}
1422
1423
1424void GLAPIENTRY
1425_mesa_DrawElements(GLenum mode, GLsizei count, GLenum type,
1426                   const GLvoid *indices)
1427{
1428   vbo_exec_DrawElements(mode, count, type, indices);
1429}
1430
1431
1432void GLAPIENTRY
1433_mesa_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
1434			     const GLvoid *indices, GLint basevertex)
1435{
1436   vbo_exec_DrawElementsBaseVertex(mode, count, type, indices, basevertex);
1437}
1438
1439
1440void GLAPIENTRY
1441_mesa_DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count,
1442                        GLenum type, const GLvoid *indices)
1443{
1444   vbo_exec_DrawRangeElements(mode, start, end, count, type, indices);
1445}
1446
1447
1448void GLAPIENTRY
1449_mesa_DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end,
1450				  GLsizei count, GLenum type,
1451				  const GLvoid *indices, GLint basevertex)
1452{
1453   vbo_exec_DrawRangeElementsBaseVertex(mode, start, end, count, type,
1454					indices, basevertex);
1455}
1456
1457
1458void GLAPIENTRY
1459_mesa_MultiDrawElementsEXT(GLenum mode, const GLsizei *count, GLenum type,
1460			   const GLvoid **indices, GLsizei primcount)
1461{
1462   vbo_exec_MultiDrawElements(mode, count, type, indices, primcount);
1463}
1464
1465
1466void GLAPIENTRY
1467_mesa_MultiDrawElementsBaseVertex(GLenum mode,
1468				  const GLsizei *count, GLenum type,
1469				  const GLvoid **indices, GLsizei primcount,
1470				  const GLint *basevertex)
1471{
1472   vbo_exec_MultiDrawElementsBaseVertex(mode, count, type, indices,
1473					primcount, basevertex);
1474}
1475
1476#if FEATURE_EXT_transform_feedback
1477
1478void GLAPIENTRY
1479_mesa_DrawTransformFeedback(GLenum mode, GLuint name)
1480{
1481   vbo_exec_DrawTransformFeedback(mode, name);
1482}
1483
1484#endif
1485