Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1901 serge 1
/**************************************************************************
2
 
3
Copyright 2002-2008 Tungsten Graphics Inc., Cedar Park, Texas.
4
 
5
All Rights Reserved.
6
 
7
Permission is hereby granted, free of charge, to any person obtaining a
8
copy of this software and associated documentation files (the "Software"),
9
to deal in the Software without restriction, including without limitation
10
on the rights to use, copy, modify, merge, publish, distribute, sub
11
license, and/or sell copies of the Software, and to permit persons to whom
12
the Software is furnished to do so, subject to the following conditions:
13
 
14
The above copyright notice and this permission notice (including the next
15
paragraph) shall be included in all copies or substantial portions of the
16
Software.
17
 
18
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21
TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
22
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24
USE OR OTHER DEALINGS IN THE SOFTWARE.
25
 
26
**************************************************************************/
27
 
28
/*
29
 * Authors:
30
 *   Keith Whitwell 
31
 */
32
 
33
#include "main/glheader.h"
34
#include "main/bufferobj.h"
35
#include "main/context.h"
36
#include "main/macros.h"
37
#include "main/vtxfmt.h"
38
#include "main/dlist.h"
39
#include "main/eval.h"
40
#include "main/state.h"
41
#include "main/light.h"
42
#include "main/api_arrayelt.h"
43
#include "main/api_noop.h"
44
#include "main/dispatch.h"
45
 
46
#include "vbo_context.h"
47
 
48
#ifdef ERROR
49
#undef ERROR
50
#endif
51
 
52
 
53
/** ID/name for immediate-mode VBO */
54
#define IMM_BUFFER_NAME 0xaabbccdd
55
 
56
 
57
static void reset_attrfv( struct vbo_exec_context *exec );
58
 
59
 
60
/**
61
 * Close off the last primitive, execute the buffer, restart the
62
 * primitive.
63
 */
64
static void vbo_exec_wrap_buffers( struct vbo_exec_context *exec )
65
{
66
   if (exec->vtx.prim_count == 0) {
67
      exec->vtx.copied.nr = 0;
68
      exec->vtx.vert_count = 0;
69
      exec->vtx.buffer_ptr = exec->vtx.buffer_map;
70
   }
71
   else {
72
      GLuint last_begin = exec->vtx.prim[exec->vtx.prim_count-1].begin;
73
      GLuint last_count;
74
 
75
      if (exec->ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) {
76
	 GLint i = exec->vtx.prim_count - 1;
77
	 assert(i >= 0);
78
	 exec->vtx.prim[i].count = (exec->vtx.vert_count -
79
				    exec->vtx.prim[i].start);
80
      }
81
 
82
      last_count = exec->vtx.prim[exec->vtx.prim_count-1].count;
83
 
84
      /* Execute the buffer and save copied vertices.
85
       */
86
      if (exec->vtx.vert_count)
87
	 vbo_exec_vtx_flush( exec, GL_FALSE );
88
      else {
89
	 exec->vtx.prim_count = 0;
90
	 exec->vtx.copied.nr = 0;
91
      }
92
 
93
      /* Emit a glBegin to start the new list.
94
       */
95
      assert(exec->vtx.prim_count == 0);
96
 
97
      if (exec->ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) {
98
	 exec->vtx.prim[0].mode = exec->ctx->Driver.CurrentExecPrimitive;
99
	 exec->vtx.prim[0].start = 0;
100
	 exec->vtx.prim[0].count = 0;
101
	 exec->vtx.prim_count++;
102
 
103
	 if (exec->vtx.copied.nr == last_count)
104
	    exec->vtx.prim[0].begin = last_begin;
105
      }
106
   }
107
}
108
 
109
 
110
/**
111
 * Deal with buffer wrapping where provoked by the vertex buffer
112
 * filling up, as opposed to upgrade_vertex().
113
 */
114
void vbo_exec_vtx_wrap( struct vbo_exec_context *exec )
115
{
116
   GLfloat *data = exec->vtx.copied.buffer;
117
   GLuint i;
118
 
119
   /* Run pipeline on current vertices, copy wrapped vertices
120
    * to exec->vtx.copied.
121
    */
122
   vbo_exec_wrap_buffers( exec );
123
 
124
   /* Copy stored stored vertices to start of new list.
125
    */
126
   assert(exec->vtx.max_vert - exec->vtx.vert_count > exec->vtx.copied.nr);
127
 
128
   for (i = 0 ; i < exec->vtx.copied.nr ; i++) {
129
      memcpy( exec->vtx.buffer_ptr, data,
130
	      exec->vtx.vertex_size * sizeof(GLfloat));
131
      exec->vtx.buffer_ptr += exec->vtx.vertex_size;
132
      data += exec->vtx.vertex_size;
133
      exec->vtx.vert_count++;
134
   }
135
 
136
   exec->vtx.copied.nr = 0;
137
}
138
 
139
 
140
/**
141
 * Copy the active vertex's values to the ctx->Current fields.
142
 */
143
static void vbo_exec_copy_to_current( struct vbo_exec_context *exec )
144
{
145
   struct gl_context *ctx = exec->ctx;
146
   struct vbo_context *vbo = vbo_context(ctx);
147
   GLuint i;
148
 
149
   for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) {
150
      if (exec->vtx.attrsz[i]) {
151
         /* Note: the exec->vtx.current[i] pointers point into the
152
          * ctx->Current.Attrib and ctx->Light.Material.Attrib arrays.
153
          */
154
	 GLfloat *current = (GLfloat *)vbo->currval[i].Ptr;
155
         GLfloat tmp[4];
156
 
157
         COPY_CLEAN_4V(tmp,
158
                       exec->vtx.attrsz[i],
159
                       exec->vtx.attrptr[i]);
160
 
161
         if (memcmp(current, tmp, sizeof(tmp)) != 0)
162
         {
163
            memcpy(current, tmp, sizeof(tmp));
164
 
165
            /* Given that we explicitly state size here, there is no need
166
             * for the COPY_CLEAN above, could just copy 16 bytes and be
167
             * done.  The only problem is when Mesa accesses ctx->Current
168
             * directly.
169
             */
170
            vbo->currval[i].Size = exec->vtx.attrsz[i];
171
 
172
            /* This triggers rather too much recalculation of Mesa state
173
             * that doesn't get used (eg light positions).
174
             */
175
            if (i >= VBO_ATTRIB_MAT_FRONT_AMBIENT &&
176
                i <= VBO_ATTRIB_MAT_BACK_INDEXES)
177
               ctx->NewState |= _NEW_LIGHT;
178
 
179
            ctx->NewState |= _NEW_CURRENT_ATTRIB;
180
         }
181
      }
182
   }
183
 
184
   /* Colormaterial -- this kindof sucks.
185
    */
186
   if (ctx->Light.ColorMaterialEnabled &&
187
       exec->vtx.attrsz[VBO_ATTRIB_COLOR0]) {
188
      _mesa_update_color_material(ctx,
189
				  ctx->Current.Attrib[VBO_ATTRIB_COLOR0]);
190
   }
191
}
192
 
193
 
194
static void vbo_exec_copy_from_current( struct vbo_exec_context *exec )
195
{
196
   struct gl_context *ctx = exec->ctx;
197
   struct vbo_context *vbo = vbo_context(ctx);
198
   GLint i;
199
 
200
   for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) {
201
      const GLfloat *current = (GLfloat *)vbo->currval[i].Ptr;
202
      switch (exec->vtx.attrsz[i]) {
203
      case 4: exec->vtx.attrptr[i][3] = current[3];
204
      case 3: exec->vtx.attrptr[i][2] = current[2];
205
      case 2: exec->vtx.attrptr[i][1] = current[1];
206
      case 1: exec->vtx.attrptr[i][0] = current[0];
207
	 break;
208
      }
209
   }
210
}
211
 
212
 
213
/**
214
 * Flush existing data, set new attrib size, replay copied vertices.
215
 */
216
static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context *exec,
217
					  GLuint attr,
218
					  GLuint newsz )
219
{
220
   struct gl_context *ctx = exec->ctx;
221
   struct vbo_context *vbo = vbo_context(ctx);
222
   GLint lastcount = exec->vtx.vert_count;
223
   GLfloat *old_attrptr[VBO_ATTRIB_MAX];
224
   GLuint old_vtx_size = exec->vtx.vertex_size;
225
   GLuint oldsz = exec->vtx.attrsz[attr];
226
   GLuint i;
227
 
228
   /* Run pipeline on current vertices, copy wrapped vertices
229
    * to exec->vtx.copied.
230
    */
231
   vbo_exec_wrap_buffers( exec );
232
 
233
   if (unlikely(exec->vtx.copied.nr)) {
234
      /* We're in the middle of a primitive, keep the old vertex
235
       * format around to be able to translate the copied vertices to
236
       * the new format.
237
       */
238
      memcpy(old_attrptr, exec->vtx.attrptr, sizeof(old_attrptr));
239
   }
240
 
241
   if (unlikely(oldsz)) {
242
      /* Do a COPY_TO_CURRENT to ensure back-copying works for the
243
       * case when the attribute already exists in the vertex and is
244
       * having its size increased.
245
       */
246
      vbo_exec_copy_to_current( exec );
247
   }
248
 
249
   /* Heuristic: Attempt to isolate attributes received outside
250
    * begin/end so that they don't bloat the vertices.
251
    */
252
   if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END &&
253
       !oldsz && lastcount > 8 && exec->vtx.vertex_size) {
254
      vbo_exec_copy_to_current( exec );
255
      reset_attrfv( exec );
256
   }
257
 
258
   /* Fix up sizes:
259
    */
260
   exec->vtx.attrsz[attr] = newsz;
261
   exec->vtx.vertex_size += newsz - oldsz;
262
   exec->vtx.max_vert = ((VBO_VERT_BUFFER_SIZE - exec->vtx.buffer_used) /
263
                         (exec->vtx.vertex_size * sizeof(GLfloat)));
264
   exec->vtx.vert_count = 0;
265
   exec->vtx.buffer_ptr = exec->vtx.buffer_map;
266
 
267
   if (unlikely(oldsz)) {
268
      /* Size changed, recalculate all the attrptr[] values
269
       */
270
      GLfloat *tmp = exec->vtx.vertex;
271
 
272
      for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
273
	 if (exec->vtx.attrsz[i]) {
274
	    exec->vtx.attrptr[i] = tmp;
275
	    tmp += exec->vtx.attrsz[i];
276
	 }
277
	 else
278
	    exec->vtx.attrptr[i] = NULL; /* will not be dereferenced */
279
      }
280
 
281
      /* Copy from current to repopulate the vertex with correct
282
       * values.
283
       */
284
      vbo_exec_copy_from_current( exec );
285
 
286
   } else {
287
      /* Just have to append the new attribute at the end */
288
      exec->vtx.attrptr[attr] = exec->vtx.vertex +
289
	 exec->vtx.vertex_size - newsz;
290
   }
291
 
292
   /* Replay stored vertices to translate them
293
    * to new format here.
294
    *
295
    * -- No need to replay - just copy piecewise
296
    */
297
   if (unlikely(exec->vtx.copied.nr)) {
298
      GLfloat *data = exec->vtx.copied.buffer;
299
      GLfloat *dest = exec->vtx.buffer_ptr;
300
      GLuint j;
301
 
302
      assert(exec->vtx.buffer_ptr == exec->vtx.buffer_map);
303
 
304
      for (i = 0 ; i < exec->vtx.copied.nr ; i++) {
305
	 for (j = 0 ; j < VBO_ATTRIB_MAX ; j++) {
306
	    GLuint sz = exec->vtx.attrsz[j];
307
 
308
	    if (sz) {
309
	       GLint old_offset = old_attrptr[j] - exec->vtx.vertex;
310
	       GLint new_offset = exec->vtx.attrptr[j] - exec->vtx.vertex;
311
 
312
	       if (j == attr) {
313
		  if (oldsz) {
314
		     GLfloat tmp[4];
315
		     COPY_CLEAN_4V(tmp, oldsz, data + old_offset);
316
		     COPY_SZ_4V(dest + new_offset, newsz, tmp);
317
		  } else {
318
		     GLfloat *current = (GLfloat *)vbo->currval[j].Ptr;
319
		     COPY_SZ_4V(dest + new_offset, sz, current);
320
		  }
321
	       }
322
	       else {
323
		  COPY_SZ_4V(dest + new_offset, sz, data + old_offset);
324
	       }
325
	    }
326
	 }
327
 
328
	 data += old_vtx_size;
329
	 dest += exec->vtx.vertex_size;
330
      }
331
 
332
      exec->vtx.buffer_ptr = dest;
333
      exec->vtx.vert_count += exec->vtx.copied.nr;
334
      exec->vtx.copied.nr = 0;
335
   }
336
}
337
 
338
 
339
static void vbo_exec_fixup_vertex( struct gl_context *ctx,
340
				   GLuint attr, GLuint sz )
341
{
342
   struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
343
   int i;
344
 
345
   if (sz > exec->vtx.attrsz[attr]) {
346
      /* New size is larger.  Need to flush existing vertices and get
347
       * an enlarged vertex format.
348
       */
349
      vbo_exec_wrap_upgrade_vertex( exec, attr, sz );
350
   }
351
   else if (sz < exec->vtx.active_sz[attr]) {
352
      static const GLfloat id[4] = { 0, 0, 0, 1 };
353
 
354
      /* New size is smaller - just need to fill in some
355
       * zeros.  Don't need to flush or wrap.
356
       */
357
      for (i = sz ; i <= exec->vtx.attrsz[attr] ; i++)
358
	 exec->vtx.attrptr[attr][i-1] = id[i-1];
359
   }
360
 
361
   exec->vtx.active_sz[attr] = sz;
362
 
363
   /* Does setting NeedFlush belong here?  Necessitates resetting
364
    * vtxfmt on each flush (otherwise flags won't get reset
365
    * afterwards).
366
    */
367
   if (attr == 0)
368
      exec->ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
369
}
370
 
371
 
372
/*
373
 */
374
#define ATTR( A, N, V0, V1, V2, V3 )				\
375
do {								\
376
   struct vbo_exec_context *exec = &vbo_context(ctx)->exec;	\
377
									\
378
   if (unlikely(!(exec->ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT))) \
379
      ctx->Driver.BeginVertices( ctx );                                 \
380
   if (unlikely(exec->vtx.active_sz[A] != N))				\
381
      vbo_exec_fixup_vertex(ctx, A, N);					\
382
   									\
383
   {								\
384
      GLfloat *dest = exec->vtx.attrptr[A];			\
385
      if (N>0) dest[0] = V0;					\
386
      if (N>1) dest[1] = V1;					\
387
      if (N>2) dest[2] = V2;					\
388
      if (N>3) dest[3] = V3;					\
389
   }								\
390
								\
391
   if ((A) == 0) {						\
392
      GLuint i;							\
393
								\
394
      for (i = 0; i < exec->vtx.vertex_size; i++)		\
395
	 exec->vtx.buffer_ptr[i] = exec->vtx.vertex[i];		\
396
								\
397
      exec->vtx.buffer_ptr += exec->vtx.vertex_size;			\
398
      exec->ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;	\
399
								\
400
      if (++exec->vtx.vert_count >= exec->vtx.max_vert)		\
401
	 vbo_exec_vtx_wrap( exec );				\
402
   }								\
403
} while (0)
404
 
405
 
406
#define ERROR() _mesa_error( ctx, GL_INVALID_ENUM, __FUNCTION__ )
407
#define TAG(x) vbo_##x
408
 
409
#include "vbo_attrib_tmp.h"
410
 
411
 
412
#if FEATURE_beginend
413
 
414
 
415
#if FEATURE_evaluators
416
 
417
static void GLAPIENTRY vbo_exec_EvalCoord1f( GLfloat u )
418
{
419
   GET_CURRENT_CONTEXT( ctx );
420
   struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
421
 
422
   {
423
      GLint i;
424
      if (exec->eval.recalculate_maps)
425
	 vbo_exec_eval_update( exec );
426
 
427
      for (i = 0; i <= VBO_ATTRIB_TEX7; i++) {
428
	 if (exec->eval.map1[i].map)
429
	    if (exec->vtx.active_sz[i] != exec->eval.map1[i].sz)
430
	       vbo_exec_fixup_vertex( ctx, i, exec->eval.map1[i].sz );
431
      }
432
   }
433
 
434
 
435
   memcpy( exec->vtx.copied.buffer, exec->vtx.vertex,
436
           exec->vtx.vertex_size * sizeof(GLfloat));
437
 
438
   vbo_exec_do_EvalCoord1f( exec, u );
439
 
440
   memcpy( exec->vtx.vertex, exec->vtx.copied.buffer,
441
           exec->vtx.vertex_size * sizeof(GLfloat));
442
}
443
 
444
static void GLAPIENTRY vbo_exec_EvalCoord2f( GLfloat u, GLfloat v )
445
{
446
   GET_CURRENT_CONTEXT( ctx );
447
   struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
448
 
449
   {
450
      GLint i;
451
      if (exec->eval.recalculate_maps)
452
	 vbo_exec_eval_update( exec );
453
 
454
      for (i = 0; i <= VBO_ATTRIB_TEX7; i++) {
455
	 if (exec->eval.map2[i].map)
456
	    if (exec->vtx.active_sz[i] != exec->eval.map2[i].sz)
457
	       vbo_exec_fixup_vertex( ctx, i, exec->eval.map2[i].sz );
458
      }
459
 
460
      if (ctx->Eval.AutoNormal)
461
	 if (exec->vtx.active_sz[VBO_ATTRIB_NORMAL] != 3)
462
	    vbo_exec_fixup_vertex( ctx, VBO_ATTRIB_NORMAL, 3 );
463
   }
464
 
465
   memcpy( exec->vtx.copied.buffer, exec->vtx.vertex,
466
           exec->vtx.vertex_size * sizeof(GLfloat));
467
 
468
   vbo_exec_do_EvalCoord2f( exec, u, v );
469
 
470
   memcpy( exec->vtx.vertex, exec->vtx.copied.buffer,
471
           exec->vtx.vertex_size * sizeof(GLfloat));
472
}
473
 
474
static void GLAPIENTRY vbo_exec_EvalCoord1fv( const GLfloat *u )
475
{
476
   vbo_exec_EvalCoord1f( u[0] );
477
}
478
 
479
static void GLAPIENTRY vbo_exec_EvalCoord2fv( const GLfloat *u )
480
{
481
   vbo_exec_EvalCoord2f( u[0], u[1] );
482
}
483
 
484
static void GLAPIENTRY vbo_exec_EvalPoint1( GLint i )
485
{
486
   GET_CURRENT_CONTEXT( ctx );
487
   GLfloat du = ((ctx->Eval.MapGrid1u2 - ctx->Eval.MapGrid1u1) /
488
		 (GLfloat) ctx->Eval.MapGrid1un);
489
   GLfloat u = i * du + ctx->Eval.MapGrid1u1;
490
 
491
   vbo_exec_EvalCoord1f( u );
492
}
493
 
494
 
495
static void GLAPIENTRY vbo_exec_EvalPoint2( GLint i, GLint j )
496
{
497
   GET_CURRENT_CONTEXT( ctx );
498
   GLfloat du = ((ctx->Eval.MapGrid2u2 - ctx->Eval.MapGrid2u1) /
499
		 (GLfloat) ctx->Eval.MapGrid2un);
500
   GLfloat dv = ((ctx->Eval.MapGrid2v2 - ctx->Eval.MapGrid2v1) /
501
		 (GLfloat) ctx->Eval.MapGrid2vn);
502
   GLfloat u = i * du + ctx->Eval.MapGrid2u1;
503
   GLfloat v = j * dv + ctx->Eval.MapGrid2v1;
504
 
505
   vbo_exec_EvalCoord2f( u, v );
506
}
507
 
508
/* use noop eval mesh */
509
#define vbo_exec_EvalMesh1 _mesa_noop_EvalMesh1
510
#define vbo_exec_EvalMesh2 _mesa_noop_EvalMesh2
511
 
512
#endif /* FEATURE_evaluators */
513
 
514
 
515
/**
516
 * Called via glBegin.
517
 */
518
static void GLAPIENTRY vbo_exec_Begin( GLenum mode )
519
{
520
   GET_CURRENT_CONTEXT( ctx );
521
 
522
   if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END) {
523
      struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
524
      int i;
525
 
526
      if (ctx->NewState) {
527
	 _mesa_update_state( ctx );
528
 
529
	 CALL_Begin(ctx->Exec, (mode));
530
	 return;
531
      }
532
 
533
      if (!_mesa_valid_to_render(ctx, "glBegin")) {
534
         return;
535
      }
536
 
537
      /* Heuristic: attempt to isolate attributes occuring outside
538
       * begin/end pairs.
539
       */
540
      if (exec->vtx.vertex_size && !exec->vtx.attrsz[0])
541
	 vbo_exec_FlushVertices_internal( ctx, GL_FALSE );
542
 
543
      i = exec->vtx.prim_count++;
544
      exec->vtx.prim[i].mode = mode;
545
      exec->vtx.prim[i].begin = 1;
546
      exec->vtx.prim[i].end = 0;
547
      exec->vtx.prim[i].indexed = 0;
548
      exec->vtx.prim[i].weak = 0;
549
      exec->vtx.prim[i].pad = 0;
550
      exec->vtx.prim[i].start = exec->vtx.vert_count;
551
      exec->vtx.prim[i].count = 0;
552
      exec->vtx.prim[i].num_instances = 1;
553
 
554
      ctx->Driver.CurrentExecPrimitive = mode;
555
   }
556
   else
557
      _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" );
558
 
559
}
560
 
561
 
562
/**
563
 * Called via glEnd.
564
 */
565
static void GLAPIENTRY vbo_exec_End( void )
566
{
567
   GET_CURRENT_CONTEXT( ctx );
568
 
569
   if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) {
570
      struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
571
      int idx = exec->vtx.vert_count;
572
      int i = exec->vtx.prim_count - 1;
573
 
574
      exec->vtx.prim[i].end = 1;
575
      exec->vtx.prim[i].count = idx - exec->vtx.prim[i].start;
576
 
577
      ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END;
578
 
579
      if (exec->vtx.prim_count == VBO_MAX_PRIM)
580
	 vbo_exec_vtx_flush( exec, GL_FALSE );
581
   }
582
   else
583
      _mesa_error( ctx, GL_INVALID_OPERATION, "glEnd" );
584
}
585
 
586
 
587
/**
588
 * Called via glPrimitiveRestartNV()
589
 */
590
static void GLAPIENTRY
591
vbo_exec_PrimitiveRestartNV(void)
592
{
593
   GLenum curPrim;
594
   GET_CURRENT_CONTEXT( ctx );
595
 
596
   curPrim = ctx->Driver.CurrentExecPrimitive;
597
 
598
   if (curPrim == PRIM_OUTSIDE_BEGIN_END) {
599
      _mesa_error( ctx, GL_INVALID_OPERATION, "glPrimitiveRestartNV" );
600
   }
601
   else {
602
      vbo_exec_End();
603
      vbo_exec_Begin(curPrim);
604
   }
605
}
606
 
607
 
608
 
609
static void vbo_exec_vtxfmt_init( struct vbo_exec_context *exec )
610
{
611
   GLvertexformat *vfmt = &exec->vtxfmt;
612
 
613
   _MESA_INIT_ARRAYELT_VTXFMT(vfmt, _ae_);
614
 
615
   vfmt->Begin = vbo_exec_Begin;
616
   vfmt->End = vbo_exec_End;
617
   vfmt->PrimitiveRestartNV = vbo_exec_PrimitiveRestartNV;
618
 
619
   _MESA_INIT_DLIST_VTXFMT(vfmt, _mesa_);
620
   _MESA_INIT_EVAL_VTXFMT(vfmt, vbo_exec_);
621
 
622
   vfmt->Rectf = _mesa_noop_Rectf;
623
 
624
   /* from attrib_tmp.h:
625
    */
626
   vfmt->Color3f = vbo_Color3f;
627
   vfmt->Color3fv = vbo_Color3fv;
628
   vfmt->Color4f = vbo_Color4f;
629
   vfmt->Color4fv = vbo_Color4fv;
630
   vfmt->FogCoordfEXT = vbo_FogCoordfEXT;
631
   vfmt->FogCoordfvEXT = vbo_FogCoordfvEXT;
632
   vfmt->MultiTexCoord1fARB = vbo_MultiTexCoord1f;
633
   vfmt->MultiTexCoord1fvARB = vbo_MultiTexCoord1fv;
634
   vfmt->MultiTexCoord2fARB = vbo_MultiTexCoord2f;
635
   vfmt->MultiTexCoord2fvARB = vbo_MultiTexCoord2fv;
636
   vfmt->MultiTexCoord3fARB = vbo_MultiTexCoord3f;
637
   vfmt->MultiTexCoord3fvARB = vbo_MultiTexCoord3fv;
638
   vfmt->MultiTexCoord4fARB = vbo_MultiTexCoord4f;
639
   vfmt->MultiTexCoord4fvARB = vbo_MultiTexCoord4fv;
640
   vfmt->Normal3f = vbo_Normal3f;
641
   vfmt->Normal3fv = vbo_Normal3fv;
642
   vfmt->SecondaryColor3fEXT = vbo_SecondaryColor3fEXT;
643
   vfmt->SecondaryColor3fvEXT = vbo_SecondaryColor3fvEXT;
644
   vfmt->TexCoord1f = vbo_TexCoord1f;
645
   vfmt->TexCoord1fv = vbo_TexCoord1fv;
646
   vfmt->TexCoord2f = vbo_TexCoord2f;
647
   vfmt->TexCoord2fv = vbo_TexCoord2fv;
648
   vfmt->TexCoord3f = vbo_TexCoord3f;
649
   vfmt->TexCoord3fv = vbo_TexCoord3fv;
650
   vfmt->TexCoord4f = vbo_TexCoord4f;
651
   vfmt->TexCoord4fv = vbo_TexCoord4fv;
652
   vfmt->Vertex2f = vbo_Vertex2f;
653
   vfmt->Vertex2fv = vbo_Vertex2fv;
654
   vfmt->Vertex3f = vbo_Vertex3f;
655
   vfmt->Vertex3fv = vbo_Vertex3fv;
656
   vfmt->Vertex4f = vbo_Vertex4f;
657
   vfmt->Vertex4fv = vbo_Vertex4fv;
658
 
659
   vfmt->VertexAttrib1fARB = vbo_VertexAttrib1fARB;
660
   vfmt->VertexAttrib1fvARB = vbo_VertexAttrib1fvARB;
661
   vfmt->VertexAttrib2fARB = vbo_VertexAttrib2fARB;
662
   vfmt->VertexAttrib2fvARB = vbo_VertexAttrib2fvARB;
663
   vfmt->VertexAttrib3fARB = vbo_VertexAttrib3fARB;
664
   vfmt->VertexAttrib3fvARB = vbo_VertexAttrib3fvARB;
665
   vfmt->VertexAttrib4fARB = vbo_VertexAttrib4fARB;
666
   vfmt->VertexAttrib4fvARB = vbo_VertexAttrib4fvARB;
667
 
668
   vfmt->VertexAttrib1fNV = vbo_VertexAttrib1fNV;
669
   vfmt->VertexAttrib1fvNV = vbo_VertexAttrib1fvNV;
670
   vfmt->VertexAttrib2fNV = vbo_VertexAttrib2fNV;
671
   vfmt->VertexAttrib2fvNV = vbo_VertexAttrib2fvNV;
672
   vfmt->VertexAttrib3fNV = vbo_VertexAttrib3fNV;
673
   vfmt->VertexAttrib3fvNV = vbo_VertexAttrib3fvNV;
674
   vfmt->VertexAttrib4fNV = vbo_VertexAttrib4fNV;
675
   vfmt->VertexAttrib4fvNV = vbo_VertexAttrib4fvNV;
676
 
677
   /* integer-valued */
678
   vfmt->VertexAttribI1i = vbo_VertexAttribI1i;
679
   vfmt->VertexAttribI2i = vbo_VertexAttribI2i;
680
   vfmt->VertexAttribI3i = vbo_VertexAttribI3i;
681
   vfmt->VertexAttribI4i = vbo_VertexAttribI4i;
682
   vfmt->VertexAttribI2iv = vbo_VertexAttribI2iv;
683
   vfmt->VertexAttribI3iv = vbo_VertexAttribI3iv;
684
   vfmt->VertexAttribI4iv = vbo_VertexAttribI4iv;
685
 
686
   /* unsigned integer-valued */
687
   vfmt->VertexAttribI1ui = vbo_VertexAttribI1ui;
688
   vfmt->VertexAttribI2ui = vbo_VertexAttribI2ui;
689
   vfmt->VertexAttribI3ui = vbo_VertexAttribI3ui;
690
   vfmt->VertexAttribI4ui = vbo_VertexAttribI4ui;
691
   vfmt->VertexAttribI2uiv = vbo_VertexAttribI2uiv;
692
   vfmt->VertexAttribI3uiv = vbo_VertexAttribI3uiv;
693
   vfmt->VertexAttribI4uiv = vbo_VertexAttribI4uiv;
694
 
695
   vfmt->Materialfv = vbo_Materialfv;
696
 
697
   vfmt->EdgeFlag = vbo_EdgeFlag;
698
   vfmt->Indexf = vbo_Indexf;
699
   vfmt->Indexfv = vbo_Indexfv;
700
 
701
}
702
 
703
 
704
#else /* FEATURE_beginend */
705
 
706
 
707
static void vbo_exec_vtxfmt_init( struct vbo_exec_context *exec )
708
{
709
   /* silence warnings */
710
   (void) vbo_Color3f;
711
   (void) vbo_Color3fv;
712
   (void) vbo_Color4f;
713
   (void) vbo_Color4fv;
714
   (void) vbo_FogCoordfEXT;
715
   (void) vbo_FogCoordfvEXT;
716
   (void) vbo_MultiTexCoord1f;
717
   (void) vbo_MultiTexCoord1fv;
718
   (void) vbo_MultiTexCoord2f;
719
   (void) vbo_MultiTexCoord2fv;
720
   (void) vbo_MultiTexCoord3f;
721
   (void) vbo_MultiTexCoord3fv;
722
   (void) vbo_MultiTexCoord4f;
723
   (void) vbo_MultiTexCoord4fv;
724
   (void) vbo_Normal3f;
725
   (void) vbo_Normal3fv;
726
   (void) vbo_SecondaryColor3fEXT;
727
   (void) vbo_SecondaryColor3fvEXT;
728
   (void) vbo_TexCoord1f;
729
   (void) vbo_TexCoord1fv;
730
   (void) vbo_TexCoord2f;
731
   (void) vbo_TexCoord2fv;
732
   (void) vbo_TexCoord3f;
733
   (void) vbo_TexCoord3fv;
734
   (void) vbo_TexCoord4f;
735
   (void) vbo_TexCoord4fv;
736
   (void) vbo_Vertex2f;
737
   (void) vbo_Vertex2fv;
738
   (void) vbo_Vertex3f;
739
   (void) vbo_Vertex3fv;
740
   (void) vbo_Vertex4f;
741
   (void) vbo_Vertex4fv;
742
 
743
   (void) vbo_VertexAttrib1fARB;
744
   (void) vbo_VertexAttrib1fvARB;
745
   (void) vbo_VertexAttrib2fARB;
746
   (void) vbo_VertexAttrib2fvARB;
747
   (void) vbo_VertexAttrib3fARB;
748
   (void) vbo_VertexAttrib3fvARB;
749
   (void) vbo_VertexAttrib4fARB;
750
   (void) vbo_VertexAttrib4fvARB;
751
 
752
   (void) vbo_VertexAttrib1fNV;
753
   (void) vbo_VertexAttrib1fvNV;
754
   (void) vbo_VertexAttrib2fNV;
755
   (void) vbo_VertexAttrib2fvNV;
756
   (void) vbo_VertexAttrib3fNV;
757
   (void) vbo_VertexAttrib3fvNV;
758
   (void) vbo_VertexAttrib4fNV;
759
   (void) vbo_VertexAttrib4fvNV;
760
 
761
   (void) vbo_Materialfv;
762
 
763
   (void) vbo_EdgeFlag;
764
   (void) vbo_Indexf;
765
   (void) vbo_Indexfv;
766
}
767
 
768
 
769
#endif /* FEATURE_beginend */
770
 
771
 
772
/**
773
 * Tell the VBO module to use a real OpenGL vertex buffer object to
774
 * store accumulated immediate-mode vertex data.
775
 * This replaces the malloced buffer which was created in
776
 * vb_exec_vtx_init() below.
777
 */
778
void vbo_use_buffer_objects(struct gl_context *ctx)
779
{
780
   struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
781
   /* Any buffer name but 0 can be used here since this bufferobj won't
782
    * go into the bufferobj hashtable.
783
    */
784
   GLuint bufName = IMM_BUFFER_NAME;
785
   GLenum target = GL_ARRAY_BUFFER_ARB;
786
   GLenum usage = GL_STREAM_DRAW_ARB;
787
   GLsizei size = VBO_VERT_BUFFER_SIZE;
788
 
789
   /* Make sure this func is only used once */
790
   assert(exec->vtx.bufferobj == ctx->Shared->NullBufferObj);
791
   if (exec->vtx.buffer_map) {
792
      _mesa_align_free(exec->vtx.buffer_map);
793
      exec->vtx.buffer_map = NULL;
794
      exec->vtx.buffer_ptr = NULL;
795
   }
796
 
797
   /* Allocate a real buffer object now */
798
   _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL);
799
   exec->vtx.bufferobj = ctx->Driver.NewBufferObject(ctx, bufName, target);
800
   ctx->Driver.BufferData(ctx, target, size, NULL, usage, exec->vtx.bufferobj);
801
}
802
 
803
 
804
 
805
void vbo_exec_vtx_init( struct vbo_exec_context *exec )
806
{
807
   struct gl_context *ctx = exec->ctx;
808
   struct vbo_context *vbo = vbo_context(ctx);
809
   GLuint i;
810
 
811
   /* Allocate a buffer object.  Will just reuse this object
812
    * continuously, unless vbo_use_buffer_objects() is called to enable
813
    * use of real VBOs.
814
    */
815
   _mesa_reference_buffer_object(ctx,
816
                                 &exec->vtx.bufferobj,
817
                                 ctx->Shared->NullBufferObj);
818
 
819
   ASSERT(!exec->vtx.buffer_map);
820
   exec->vtx.buffer_map = (GLfloat *)_mesa_align_malloc(VBO_VERT_BUFFER_SIZE, 64);
821
   exec->vtx.buffer_ptr = exec->vtx.buffer_map;
822
 
823
   vbo_exec_vtxfmt_init( exec );
824
 
825
   /* Hook our functions into the dispatch table.
826
    */
827
   _mesa_install_exec_vtxfmt( exec->ctx, &exec->vtxfmt );
828
 
829
   for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
830
      ASSERT(i < Elements(exec->vtx.attrsz));
831
      exec->vtx.attrsz[i] = 0;
832
      ASSERT(i < Elements(exec->vtx.active_sz));
833
      exec->vtx.active_sz[i] = 0;
834
   }
835
   for (i = 0 ; i < VERT_ATTRIB_MAX; i++) {
836
      ASSERT(i < Elements(exec->vtx.inputs));
837
      ASSERT(i < Elements(exec->vtx.arrays));
838
      exec->vtx.inputs[i] = &exec->vtx.arrays[i];
839
   }
840
 
841
   {
842
      struct gl_client_array *arrays = exec->vtx.arrays;
843
      unsigned i;
844
 
845
      memcpy(arrays,      vbo->legacy_currval,  16 * sizeof(arrays[0]));
846
      memcpy(arrays + 16, vbo->generic_currval, 16 * sizeof(arrays[0]));
847
 
848
      for (i = 0; i < 16; ++i) {
849
         arrays[i     ].BufferObj = NULL;
850
         arrays[i + 16].BufferObj = NULL;
851
         _mesa_reference_buffer_object(ctx, &arrays[i     ].BufferObj,
852
                                       vbo->legacy_currval[i].BufferObj);
853
         _mesa_reference_buffer_object(ctx, &arrays[i + 16].BufferObj,
854
                                       vbo->generic_currval[i].BufferObj);
855
      }
856
   }
857
 
858
   exec->vtx.vertex_size = 0;
859
}
860
 
861
 
862
void vbo_exec_vtx_destroy( struct vbo_exec_context *exec )
863
{
864
   /* using a real VBO for vertex data */
865
   struct gl_context *ctx = exec->ctx;
866
   unsigned i;
867
 
868
   /* True VBOs should already be unmapped
869
    */
870
   if (exec->vtx.buffer_map) {
871
      ASSERT(exec->vtx.bufferobj->Name == 0 ||
872
             exec->vtx.bufferobj->Name == IMM_BUFFER_NAME);
873
      if (exec->vtx.bufferobj->Name == 0) {
874
         _mesa_align_free(exec->vtx.buffer_map);
875
         exec->vtx.buffer_map = NULL;
876
         exec->vtx.buffer_ptr = NULL;
877
      }
878
   }
879
 
880
   /* Drop any outstanding reference to the vertex buffer
881
    */
882
   for (i = 0; i < Elements(exec->vtx.arrays); i++) {
883
      _mesa_reference_buffer_object(ctx,
884
                                    &exec->vtx.arrays[i].BufferObj,
885
                                    NULL);
886
   }
887
 
888
   /* Free the vertex buffer.  Unmap first if needed.
889
    */
890
   if (_mesa_bufferobj_mapped(exec->vtx.bufferobj)) {
891
      ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER, exec->vtx.bufferobj);
892
   }
893
   _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL);
894
}
895
 
896
void vbo_exec_BeginVertices( struct gl_context *ctx )
897
{
898
   struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
899
   if (0) printf("%s\n", __FUNCTION__);
900
   vbo_exec_vtx_map( exec );
901
 
902
   assert((exec->ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) == 0);
903
   exec->ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT;
904
}
905
 
906
void vbo_exec_FlushVertices_internal( struct gl_context *ctx, GLboolean unmap )
907
{
908
   struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
909
 
910
   if (exec->vtx.vert_count || unmap) {
911
      vbo_exec_vtx_flush( exec, unmap );
912
   }
913
 
914
   if (exec->vtx.vertex_size) {
915
      vbo_exec_copy_to_current( exec );
916
      reset_attrfv( exec );
917
   }
918
}
919
 
920
 
921
/**
922
 * \param flags  bitmask of FLUSH_STORED_VERTICES, FLUSH_UPDATE_CURRENT
923
 */
924
void vbo_exec_FlushVertices( struct gl_context *ctx, GLuint flags )
925
{
926
   struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
927
 
928
#ifdef DEBUG
929
   /* debug check: make sure we don't get called recursively */
930
   exec->flush_call_depth++;
931
   assert(exec->flush_call_depth == 1);
932
#endif
933
 
934
   if (0) printf("%s\n", __FUNCTION__);
935
 
936
   if (exec->ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) {
937
      if (0) printf("%s - inside begin/end\n", __FUNCTION__);
938
#ifdef DEBUG
939
      exec->flush_call_depth--;
940
      assert(exec->flush_call_depth == 0);
941
#endif
942
      return;
943
   }
944
 
945
   vbo_exec_FlushVertices_internal( ctx, GL_TRUE );
946
 
947
   /* Need to do this to ensure BeginVertices gets called again:
948
    */
949
   if (exec->ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT)
950
      exec->ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT;
951
 
952
   exec->ctx->Driver.NeedFlush &= ~flags;
953
 
954
#ifdef DEBUG
955
   exec->flush_call_depth--;
956
   assert(exec->flush_call_depth == 0);
957
#endif
958
}
959
 
960
 
961
static void reset_attrfv( struct vbo_exec_context *exec )
962
{
963
   GLuint i;
964
 
965
   for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
966
      exec->vtx.attrsz[i] = 0;
967
      exec->vtx.active_sz[i] = 0;
968
   }
969
 
970
   exec->vtx.vertex_size = 0;
971
}
972
 
973
 
974
void GLAPIENTRY
975
_es_Color4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a)
976
{
977
   vbo_Color4f(r, g, b, a);
978
}
979
 
980
 
981
void GLAPIENTRY
982
_es_Normal3f(GLfloat x, GLfloat y, GLfloat z)
983
{
984
   vbo_Normal3f(x, y, z);
985
}
986
 
987
 
988
void GLAPIENTRY
989
_es_MultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q)
990
{
991
   vbo_MultiTexCoord4f(target, s, t, r, q);
992
}
993
 
994
 
995
void GLAPIENTRY
996
_es_Materialfv(GLenum face, GLenum pname, const GLfloat *params)
997
{
998
   vbo_Materialfv(face, pname, params);
999
}
1000
 
1001
 
1002
void GLAPIENTRY
1003
_es_Materialf(GLenum face, GLenum pname, GLfloat param)
1004
{
1005
   GLfloat p[4];
1006
   p[0] = param;
1007
   p[1] = p[2] = p[3] = 0.0F;
1008
   vbo_Materialfv(face, pname, p);
1009
}
1010
 
1011
 
1012
/**
1013
 * A special version of glVertexAttrib4f that does not treat index 0 as
1014
 * VBO_ATTRIB_POS.
1015
 */
1016
static void
1017
VertexAttrib4f_nopos(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
1018
{
1019
   GET_CURRENT_CONTEXT(ctx);
1020
   if (index < MAX_VERTEX_GENERIC_ATTRIBS)
1021
      ATTR(VBO_ATTRIB_GENERIC0 + index, 4, x, y, z, w);
1022
   else
1023
      ERROR();
1024
}
1025
 
1026
void GLAPIENTRY
1027
_es_VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
1028
{
1029
   VertexAttrib4f_nopos(index, x, y, z, w);
1030
}
1031
 
1032
 
1033
void GLAPIENTRY
1034
_es_VertexAttrib1f(GLuint indx, GLfloat x)
1035
{
1036
   VertexAttrib4f_nopos(indx, x, 0.0f, 0.0f, 1.0f);
1037
}
1038
 
1039
 
1040
void GLAPIENTRY
1041
_es_VertexAttrib1fv(GLuint indx, const GLfloat* values)
1042
{
1043
   VertexAttrib4f_nopos(indx, values[0], 0.0f, 0.0f, 1.0f);
1044
}
1045
 
1046
 
1047
void GLAPIENTRY
1048
_es_VertexAttrib2f(GLuint indx, GLfloat x, GLfloat y)
1049
{
1050
   VertexAttrib4f_nopos(indx, x, y, 0.0f, 1.0f);
1051
}
1052
 
1053
 
1054
void GLAPIENTRY
1055
_es_VertexAttrib2fv(GLuint indx, const GLfloat* values)
1056
{
1057
   VertexAttrib4f_nopos(indx, values[0], values[1], 0.0f, 1.0f);
1058
}
1059
 
1060
 
1061
void GLAPIENTRY
1062
_es_VertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z)
1063
{
1064
   VertexAttrib4f_nopos(indx, x, y, z, 1.0f);
1065
}
1066
 
1067
 
1068
void GLAPIENTRY
1069
_es_VertexAttrib3fv(GLuint indx, const GLfloat* values)
1070
{
1071
   VertexAttrib4f_nopos(indx, values[0], values[1], values[2], 1.0f);
1072
}
1073
 
1074
 
1075
void GLAPIENTRY
1076
_es_VertexAttrib4fv(GLuint indx, const GLfloat* values)
1077
{
1078
   VertexAttrib4f_nopos(indx, values[0], values[1], values[2], values[3]);
1079
}