VirtualBox

source: vbox/trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_bufferobject.c@ 20961

Last change on this file since 20961 was 15532, checked in by vboxsync, 16 years ago

crOpenGL: export to OSE

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 24.2 KB
Line 
1/* Copyright (c) 2001, Stanford University
2 * All rights reserved
3 *
4 * See the file LICENSE.txt for information on redistributing this software.
5 */
6
7#include "state.h"
8#include "state/cr_statetypes.h"
9#include "state/cr_statefuncs.h"
10#include "state_internals.h"
11#include "cr_mem.h"
12#include "cr_string.h"
13
14
15static CRBufferObject *AllocBufferObject(GLuint name)
16{
17 CRBufferObject *b = crCalloc(sizeof(CRBufferObject));
18 if (b) {
19 b->refCount = 1;
20 b->name = name;
21 b->usage = GL_STATIC_DRAW_ARB;
22 b->access = GL_READ_WRITE_ARB;
23 }
24 return b;
25}
26
27
28void crStateBufferObjectInit (CRContext *ctx)
29{
30 CRStateBits *sb = GetCurrentBits();
31 CRBufferObjectBits *bb = &sb->bufferobject;
32 CRBufferObjectState *b = &ctx->bufferobject;
33
34 RESET(bb->dirty, ctx->bitid);
35 RESET(bb->arrayBinding, ctx->bitid);
36 RESET(bb->elementsBinding, ctx->bitid);
37
38#ifdef IN_GUEST
39 b->retainBufferData = GL_FALSE;
40#else
41 b->retainBufferData = GL_TRUE;
42#endif
43
44 b->nullBuffer = AllocBufferObject(0);
45 b->arrayBuffer = b->nullBuffer;
46 b->elementsBuffer = b->nullBuffer;
47 b->nullBuffer->refCount = 3;
48
49 b->buffers = crAllocHashtable();
50}
51
52
53void crStateBufferObjectDestroy (CRContext *ctx)
54{
55 CRBufferObjectState *b = &ctx->bufferobject;
56 crFreeHashtable(b->buffers, crFree);
57 crFree(b->nullBuffer);
58}
59
60
61void STATE_APIENTRY
62crStateBindBufferARB (GLenum target, GLuint buffer)
63{
64 CRContext *g = GetCurrentContext();
65 CRBufferObjectState *b = &(g->bufferobject);
66 CRStateBits *sb = GetCurrentBits();
67 CRBufferObjectBits *bb = &(sb->bufferobject);
68 CRBufferObject *oldObj, *newObj;
69
70 if (g->current.inBeginEnd) {
71 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
72 "glBindBufferARB called in begin/end");
73 return;
74 }
75
76 FLUSH();
77
78 if (target == GL_ARRAY_BUFFER_ARB) {
79 oldObj = b->arrayBuffer;
80 }
81 else if (target == GL_ELEMENT_ARRAY_BUFFER_ARB) {
82 oldObj = b->elementsBuffer;
83 }
84 else {
85 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
86 "glBindBufferARB(target)");
87 return;
88 }
89
90 if (buffer == 0) {
91 newObj = b->nullBuffer;
92 }
93 else {
94 newObj = (CRBufferObject *) crHashtableSearch(b->buffers, buffer);
95 if (!newObj) {
96 newObj = AllocBufferObject(buffer);
97 if (!newObj) {
98 crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY, "glBindBuffer");
99 return;
100 }
101 crHashtableAdd( b->buffers, buffer, newObj );
102 }
103 }
104
105 newObj->refCount++;
106 oldObj->refCount--;
107
108 if (target == GL_ARRAY_BUFFER_ARB) {
109 b->arrayBuffer = newObj;
110 DIRTY(bb->dirty, g->neg_bitid);
111 DIRTY(bb->arrayBinding, g->neg_bitid);
112 }
113 else {
114 CRASSERT(target == GL_ELEMENT_ARRAY_BUFFER_ARB);
115 b->elementsBuffer = newObj;
116 DIRTY(bb->dirty, g->neg_bitid);
117 DIRTY(bb->elementsBinding, g->neg_bitid);
118 }
119
120 if (oldObj->refCount <= 0) {
121 crHashtableDelete(b->buffers, (unsigned long) oldObj->name, crFree);
122 }
123}
124
125void STATE_APIENTRY
126crStateDeleteBuffersARB(GLsizei n, const GLuint *buffers)
127{
128 CRContext *g = GetCurrentContext();
129 CRBufferObjectState *b = &(g->bufferobject);
130 CRStateBits *sb = GetCurrentBits();
131 CRBufferObjectBits *bb = &(sb->bufferobject);
132 int i;
133
134 FLUSH();
135
136 if (g->current.inBeginEnd) {
137 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
138 "glDeleteBuffersARB called in Begin/End");
139 return;
140 }
141
142 if (n < 0) {
143 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
144 "glDeleteBuffersARB(n < 0)");
145 return;
146 }
147
148 for (i = 0; i < n; i++) {
149 if (buffers[i]) {
150 CRBufferObject *obj = (CRBufferObject *)
151 crHashtableSearch(b->buffers, buffers[i]);
152 if (obj) {
153 if (obj == b->arrayBuffer) {
154 b->arrayBuffer = b->nullBuffer;
155 b->arrayBuffer->refCount++;
156 DIRTY(bb->dirty, g->neg_bitid);
157 DIRTY(bb->arrayBinding, g->neg_bitid);
158 }
159 if (obj == b->elementsBuffer) {
160 b->elementsBuffer = b->nullBuffer;
161 b->elementsBuffer->refCount++;
162 DIRTY(bb->dirty, g->neg_bitid);
163 DIRTY(bb->elementsBinding, g->neg_bitid);
164 }
165 /* XXX check bindings with the vertex arrays */
166
167 crHashtableDelete(b->buffers, buffers[i], crFree);
168 }
169 }
170 }
171}
172
173
174void STATE_APIENTRY
175crStateGenBuffersARB(GLsizei n, GLuint * buffers)
176{
177 CRContext *g = GetCurrentContext();
178 CRBufferObjectState *b = &(g->bufferobject);
179 GLint start;
180
181 FLUSH();
182
183 if (g->current.inBeginEnd) {
184 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
185 "glGenBuffersARB called in Begin/End");
186 return;
187 }
188
189 if (n < 0) {
190 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
191 "glGenBuffersARB(n < 0)");
192 return;
193 }
194
195 start = crHashtableAllocKeys(b->buffers, n);
196 if (start) {
197 GLint i;
198 for (i = 0; i < n; i++)
199 buffers[i] = (GLuint) (start + i);
200 }
201 else {
202 crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY, "glGenBuffersARB");
203 }
204}
205
206
207GLboolean STATE_APIENTRY
208crStateIsBufferARB(GLuint buffer)
209{
210 CRContext *g = GetCurrentContext();
211 CRBufferObjectState *b = &g->bufferobject;
212
213 FLUSH();
214
215 if (g->current.inBeginEnd) {
216 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
217 "glIsBufferARB called in begin/end");
218 return GL_FALSE;
219 }
220
221 if (buffer && crHashtableSearch(b->buffers, buffer))
222 return GL_TRUE;
223 else
224 return GL_FALSE;
225}
226
227
228void STATE_APIENTRY
229crStateBufferDataARB(GLenum target, GLsizeiptrARB size, const GLvoid * data, GLenum usage)
230{
231 CRContext *g = GetCurrentContext();
232 CRBufferObjectState *b = &g->bufferobject;
233 CRBufferObject *obj;
234 CRStateBits *sb = GetCurrentBits();
235 CRBufferObjectBits *bb = &sb->bufferobject;
236
237 FLUSH();
238
239 if (g->current.inBeginEnd) {
240 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
241 "glBufferDataARB called in begin/end");
242 return;
243 }
244
245 if (size < 0) {
246 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
247 "glBufferDataARB(size < 0)");
248 return;
249 }
250
251 switch (usage) {
252 case GL_STREAM_DRAW_ARB:
253 case GL_STREAM_READ_ARB:
254 case GL_STREAM_COPY_ARB:
255 case GL_STATIC_DRAW_ARB:
256 case GL_STATIC_READ_ARB:
257 case GL_STATIC_COPY_ARB:
258 case GL_DYNAMIC_DRAW_ARB:
259 case GL_DYNAMIC_READ_ARB:
260 case GL_DYNAMIC_COPY_ARB:
261 /* OK */
262 break;
263 default:
264 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
265 "glBufferDataARB(usage)");
266 return;
267 }
268
269 if (target == GL_ARRAY_BUFFER_ARB) {
270 obj = b->arrayBuffer;
271 }
272 else if (target == GL_ELEMENT_ARRAY_BUFFER_ARB) {
273 obj = b->elementsBuffer;
274 }
275 else {
276 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
277 "glBufferDataARB(target)");
278 return;
279 }
280
281 if (obj->name == 0) {
282 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glBufferDataARB");
283 return;
284 }
285
286 if (obj->pointer) {
287 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
288 "glBufferDataARB(buffer is mapped)");
289 return;
290 }
291
292 obj->usage = usage;
293 obj->size = size;
294
295 /* The user of the state tracker should set the retainBufferData field
296 * during context initialization, if needed.
297 */
298 if (b->retainBufferData) {
299 if (obj->data) {
300 crFree(obj->data);
301 }
302
303 obj->data = crAlloc(size);
304 if (!obj->data) {
305 crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY, "glBufferDataARB");
306 return;
307 }
308 if (data)
309 crMemcpy(obj->data, data, size);
310 }
311
312 DIRTY(bb->dirty, g->neg_bitid);
313 DIRTY(obj->dirty, g->neg_bitid);
314 obj->dirtyStart = 0;
315 obj->dirtyLength = size;
316}
317
318
319void STATE_APIENTRY
320crStateBufferSubDataARB(GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid * data)
321{
322 CRContext *g = GetCurrentContext();
323 CRBufferObjectState *b = &g->bufferobject;
324 CRBufferObject *obj;
325 CRStateBits *sb = GetCurrentBits();
326 CRBufferObjectBits *bb = &sb->bufferobject;
327
328 FLUSH();
329
330 if (g->current.inBeginEnd) {
331 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
332 "glBufferSubDataARB called in begin/end");
333 return;
334 }
335
336 if (target == GL_ARRAY_BUFFER_ARB) {
337 obj = b->arrayBuffer;
338 }
339 else if (target == GL_ELEMENT_ARRAY_BUFFER_ARB) {
340 obj = b->elementsBuffer;
341 }
342 else {
343 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
344 "glBufferSubDataARB(target)");
345 return;
346 }
347
348 if (obj->name == 0) {
349 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
350 "glBufferSubDataARB");
351 return;
352 }
353
354 if (obj->pointer) {
355 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
356 "glBufferSubDataARB(buffer is mapped)");
357 return;
358 }
359
360 if (size < 0 || offset < 0 || (unsigned int)offset + size > obj->size) {
361 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
362 "glBufferSubDataARB(bad offset and/or size)");
363 return;
364 }
365
366 if (b->retainBufferData && obj->data) {
367 crMemcpy((char *) obj->data + offset, data, size);
368 }
369
370 DIRTY(bb->dirty, g->neg_bitid);
371 DIRTY(obj->dirty, g->neg_bitid);
372 /* grow dirty region */
373 if (offset + size > obj->dirtyStart + obj->dirtyLength)
374 obj->dirtyLength = offset + size;
375 if (offset < obj->dirtyStart)
376 obj->dirtyStart = offset;
377}
378
379
380void STATE_APIENTRY
381crStateGetBufferSubDataARB(GLenum target, GLintptrARB offset, GLsizeiptrARB size, void * data)
382{
383 CRContext *g = GetCurrentContext();
384 CRBufferObjectState *b = &g->bufferobject;
385 CRBufferObject *obj;
386
387 FLUSH();
388
389 if (g->current.inBeginEnd) {
390 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
391 "glGetBufferSubDataARB called in begin/end");
392 return;
393 }
394
395 if (target == GL_ARRAY_BUFFER_ARB) {
396 obj = b->arrayBuffer;
397 }
398 else if (target == GL_ELEMENT_ARRAY_BUFFER_ARB) {
399 obj = b->elementsBuffer;
400 }
401 else {
402 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
403 "glGetBufferSubDataARB(target)");
404 return;
405 }
406
407 if (obj->name == 0) {
408 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
409 "glGetBufferSubDataARB");
410 return;
411 }
412
413 if (obj->pointer) {
414 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
415 "glGetBufferSubDataARB(buffer is mapped)");
416 return;
417 }
418
419 if (size < 0 || offset < 0 || (unsigned int)offset + size > obj->size) {
420 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
421 "glGetBufferSubDataARB(bad offset and/or size)");
422 return;
423 }
424
425 if (b->retainBufferData && obj->data) {
426 crMemcpy(data, (char *) obj->data + offset, size);
427 }
428}
429
430
431void * STATE_APIENTRY
432crStateMapBufferARB(GLenum target, GLenum access)
433{
434 CRContext *g = GetCurrentContext();
435 CRBufferObjectState *b = &g->bufferobject;
436 CRBufferObject *obj;
437
438 FLUSH();
439
440 if (g->current.inBeginEnd) {
441 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
442 "glMapBufferARB called in begin/end");
443 return NULL;
444 }
445
446 if (target == GL_ARRAY_BUFFER_ARB) {
447 obj = b->arrayBuffer;
448 }
449 else if (target == GL_ELEMENT_ARRAY_BUFFER_ARB) {
450 obj = b->elementsBuffer;
451 }
452 else {
453 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
454 "glMapBufferARB(target)");
455 return NULL;
456 }
457
458 if (obj->name == 0) {
459 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glMapBufferARB");
460 return GL_FALSE;
461 }
462
463 switch (access) {
464 case GL_READ_ONLY_ARB:
465 case GL_WRITE_ONLY_ARB:
466 case GL_READ_WRITE_ARB:
467 obj->access = access;
468 break;
469 default:
470 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
471 "glMapBufferARB(access)");
472 return NULL;
473 }
474
475 if (b->retainBufferData && obj->data)
476 obj->pointer = obj->data;
477
478 return obj->pointer;
479}
480
481
482GLboolean STATE_APIENTRY
483crStateUnmapBufferARB(GLenum target)
484{
485 CRContext *g = GetCurrentContext();
486 CRBufferObjectState *b = &g->bufferobject;
487 CRBufferObject *obj;
488 CRStateBits *sb = GetCurrentBits();
489 CRBufferObjectBits *bb = &sb->bufferobject;
490
491 FLUSH();
492
493 if (g->current.inBeginEnd) {
494 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
495 "glUnmapBufferARB called in begin/end");
496 return GL_FALSE;
497 }
498
499 if (target == GL_ARRAY_BUFFER_ARB) {
500 obj = b->arrayBuffer;
501 }
502 else if (target == GL_ELEMENT_ARRAY_BUFFER_ARB) {
503 obj = b->elementsBuffer;
504 }
505 else {
506 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
507 "glUnmapBufferARB(target)");
508 return GL_FALSE;
509 }
510
511 if (obj->name == 0) {
512 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glUnmapBufferARB");
513 return GL_FALSE;
514 }
515
516 if (!obj->pointer) {
517 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glUnmapBufferARB");
518 return GL_FALSE;
519 }
520
521 obj->pointer = NULL;
522
523 if (obj->access != GL_READ_ONLY_ARB) {
524 /* the data was most likely modified */
525 DIRTY(bb->dirty, g->neg_bitid);
526 DIRTY(obj->dirty, g->neg_bitid);
527 obj->dirtyStart = 0;
528 obj->dirtyLength = obj->size;
529 }
530
531 return GL_TRUE;
532}
533
534
535void STATE_APIENTRY
536crStateGetBufferParameterivARB(GLenum target, GLenum pname, GLint *params)
537{
538 CRContext *g = GetCurrentContext();
539 CRBufferObjectState *b = &g->bufferobject;
540 CRBufferObject *obj;
541
542 FLUSH();
543
544 if (g->current.inBeginEnd) {
545 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
546 "glGetBufferParameterivARB called in begin/end");
547 return;
548 }
549
550 if (target == GL_ARRAY_BUFFER_ARB) {
551 obj = b->arrayBuffer;
552 }
553 else if (target == GL_ELEMENT_ARRAY_BUFFER_ARB) {
554 obj = b->elementsBuffer;
555 }
556 else {
557 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
558 "glGetBufferParameterivARB(target)");
559 return;
560 }
561
562 switch (pname) {
563 case GL_BUFFER_SIZE_ARB:
564 *params = obj->size;
565 break;
566 case GL_BUFFER_USAGE_ARB:
567 *params = obj->usage;
568 break;
569 case GL_BUFFER_ACCESS_ARB:
570 *params = obj->access;
571 break;
572 case GL_BUFFER_MAPPED_ARB:
573 *params = (obj->pointer != NULL);
574 break;
575 default:
576 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
577 "glGetBufferParameterivARB(pname)");
578 return;
579 }
580}
581
582
583void STATE_APIENTRY
584crStateGetBufferPointervARB(GLenum target, GLenum pname, GLvoid **params)
585{
586 CRContext *g = GetCurrentContext();
587 CRBufferObjectState *b = &g->bufferobject;
588 CRBufferObject *obj;
589
590 FLUSH();
591
592 if (g->current.inBeginEnd) {
593 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
594 "glGetBufferPointervARB called in begin/end");
595 return;
596 }
597
598 if (target == GL_ARRAY_BUFFER_ARB) {
599 obj = b->arrayBuffer;
600 }
601 else if (target == GL_ELEMENT_ARRAY_BUFFER_ARB) {
602 obj = b->elementsBuffer;
603 }
604 else {
605 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
606 "glGetBufferPointervARB(target)");
607 return;
608 }
609
610 if (pname != GL_BUFFER_MAP_POINTER_ARB) {
611 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
612 "glGetBufferPointervARB(pname)");
613 return;
614 }
615
616 *params = obj->pointer;
617}
618
619
620/**
621 * We need to check if the GL_EXT_vertex/pixel_buffer_object extensions
622 * are supported before calling any of the diff_api functions.
623 * This flag indidcates if the extensions is available (1), not available (0)
624 * or needs to be tested for (-1).
625 * If we don't do this, we can segfault inside OpenGL.
626 * Ideally, the render SPU should no-op unsupported GL functions, but
627 * that's a bit complicated.
628 */
629static GLboolean
630HaveBufferObjectExtension(void)
631{
632 static GLint haveBufferObjectExt = -1;
633
634 if (haveBufferObjectExt == -1) {
635 const char *ext;
636 /* XXX this check is temporary. We need to make the tilesort SPU plug
637 * GetString into the diff'ing table in order for this to really work.
638 */
639 if (!diff_api.GetString) {
640 haveBufferObjectExt = 0;
641 return 0;
642 }
643 CRASSERT(diff_api.GetString);
644 ext = (const char *) diff_api.GetString(GL_EXTENSIONS);
645 if (crStrstr(ext, "GL_ARB_vertex_buffer_object") ||
646 crStrstr(ext, "GL_ARB_pixel_buffer_object")) {
647 haveBufferObjectExt = 1;
648 }
649 else {
650 haveBufferObjectExt = 0;
651 }
652 }
653 return haveBufferObjectExt;
654}
655
656
657void crStateBufferObjectDiff(CRBufferObjectBits *bb, CRbitvalue *bitID,
658 CRContext *fromCtx, CRContext *toCtx)
659{
660 CRBufferObjectState *from = &(fromCtx->bufferobject);
661 const CRBufferObjectState *to = &(toCtx->bufferobject);
662
663 if (!HaveBufferObjectExtension())
664 return;
665
666 /* ARRAY_BUFFER binding */
667 if (CHECKDIRTY(bb->arrayBinding, bitID)) {
668 if (from->arrayBuffer != to->arrayBuffer) {
669 GLuint bufferID = to->arrayBuffer ? to->arrayBuffer->name : 0;
670 diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, bufferID);
671 CLEARDIRTY2(bb->arrayBinding, bitID);
672 from->arrayBuffer = to->arrayBuffer;
673 }
674 }
675
676 if (to->arrayBuffer && CHECKDIRTY(to->arrayBuffer->dirty, bitID)) {
677 /* update array buffer data */
678 CRBufferObject *bufObj = to->arrayBuffer;
679 CRASSERT(bufObj);
680 if (bufObj->dirtyStart == 0 && bufObj->dirtyLength == (int) bufObj->size) {
681 /* update whole buffer */
682 diff_api.BufferDataARB(GL_ARRAY_BUFFER_ARB, bufObj->size,
683 bufObj->data, bufObj->usage);
684 }
685 else {
686 /* update sub buffer */
687 diff_api.BufferSubDataARB(GL_ARRAY_BUFFER_ARB,
688 bufObj->dirtyStart,
689 bufObj->dirtyLength,
690 (char *) bufObj->data
691 + bufObj->dirtyStart);
692 }
693 CLEARDIRTY2(bufObj->dirty, bitID);
694#if 0
695 bufObj->dirtyStart = 0;
696 bufObj->dirtyLength = 0;
697#endif
698 }
699
700 /* ELEMENTS_BUFFER binding */
701 if (CHECKDIRTY(bb->elementsBinding, bitID)) {
702 if (from->elementsBuffer != to->elementsBuffer) {
703 GLuint bufferID = to->elementsBuffer ? to->elementsBuffer->name : 0;
704 diff_api.BindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, bufferID);
705 CLEARDIRTY2(bb->elementsBinding, bitID);
706 from->elementsBuffer = to->elementsBuffer;
707 }
708 }
709
710 if (to->elementsBuffer && CHECKDIRTY(to->elementsBuffer->dirty, bitID)) {
711 /* update element buffer data */
712 CRBufferObject *bufObj = to->elementsBuffer;
713 CRASSERT(bufObj);
714 if (bufObj->dirtyStart == 0 && bufObj->dirtyLength == (int) bufObj->size) {
715 /* update whole buffer */
716 diff_api.BufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, bufObj->size,
717 bufObj->data, bufObj->usage);
718 }
719 else {
720 /* update sub buffer */
721 diff_api.BufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB,
722 bufObj->dirtyStart,
723 bufObj->dirtyLength,
724 (char *) bufObj->data
725 + bufObj->dirtyStart);
726 }
727 CLEARDIRTY2(bufObj->dirty, bitID);
728#if 0
729 bufObj->dirtyStart = 0;
730 bufObj->dirtyLength = 0;
731#endif
732 }
733}
734
735
736/*
737 * XXX this function might need some testing/fixing.
738 */
739void crStateBufferObjectSwitch(CRBufferObjectBits *bb, CRbitvalue *bitID,
740 CRContext *fromCtx, CRContext *toCtx)
741{
742 const CRBufferObjectState *from = &(fromCtx->bufferobject);
743 const CRBufferObjectState *to = &(toCtx->bufferobject);
744
745 if (!HaveBufferObjectExtension())
746 return;
747
748 /* ARRAY_BUFFER binding */
749 if (CHECKDIRTY(bb->arrayBinding, bitID)) {
750 if (from->arrayBuffer != to->arrayBuffer) {
751 GLuint bufferID = to->arrayBuffer ? to->arrayBuffer->name : 0;
752 diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, bufferID);
753 FILLDIRTY(bb->arrayBinding);
754 }
755 CLEARDIRTY2(bb->arrayBinding, bitID);
756 }
757
758 if (to->arrayBuffer && CHECKDIRTY(to->arrayBuffer->dirty, bitID)) {
759 /* update array buffer data */
760 CRBufferObject *bufObj = to->arrayBuffer;
761 CRASSERT(bufObj);
762 if (bufObj->dirtyStart == 0 && bufObj->dirtyLength == (int) bufObj->size) {
763 /* update whole buffer */
764 diff_api.BufferDataARB(GL_ARRAY_BUFFER_ARB, bufObj->size,
765 bufObj->data, bufObj->usage);
766 }
767 else {
768 /* update sub buffer */
769 diff_api.BufferSubDataARB(GL_ARRAY_BUFFER_ARB,
770 bufObj->dirtyStart,
771 bufObj->dirtyLength,
772 (char *) bufObj->data
773 + bufObj->dirtyStart);
774 }
775 FILLDIRTY(bufObj->dirty);
776 CLEARDIRTY2(bufObj->dirty, bitID);
777#if 0
778 bufObj->dirtyStart = 0;
779 bufObj->dirtyLength = 0;
780#endif
781 }
782
783 /* ELEMENTS_BUFFER binding */
784 if (CHECKDIRTY(bb->elementsBinding, bitID)) {
785 if (from->elementsBuffer != to->elementsBuffer) {
786 GLuint bufferID = to->elementsBuffer ? to->elementsBuffer->name : 0;
787 diff_api.BindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, bufferID);
788 FILLDIRTY(bb->elementsBinding);
789 }
790 CLEARDIRTY2(bb->elementsBinding, bitID);
791 }
792
793 if (to->elementsBuffer && CHECKDIRTY(to->elementsBuffer->dirty, bitID)) {
794 /* update element buffer data */
795 CRBufferObject *bufObj = to->elementsBuffer;
796 CRASSERT(bufObj);
797 if (bufObj->dirtyStart == 0 && bufObj->dirtyLength == (int) bufObj->size) {
798 /* update whole buffer */
799 diff_api.BufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, bufObj->size,
800 bufObj->data, bufObj->usage);
801 }
802 else {
803 /* update sub buffer */
804 diff_api.BufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB,
805 bufObj->dirtyStart,
806 bufObj->dirtyLength,
807 (char *) bufObj->data
808 + bufObj->dirtyStart);
809 }
810 FILLDIRTY(bufObj->dirty);
811 CLEARDIRTY2(bufObj->dirty, bitID);
812#if 0
813 bufObj->dirtyStart = 0;
814 bufObj->dirtyLength = 0;
815#endif
816 }
817}
818
819
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette