VirtualBox

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

Last change on this file since 30045 was 30028, checked in by vboxsync, 15 years ago

crOpenGL: fix host nvidia driver crashes on guest wddm startup

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 31.1 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 b->bResyncOnRead = GL_FALSE;
24 }
25 return b;
26}
27
28GLboolean crStateIsBufferBound(GLenum target)
29{
30 CRContext *g = GetCurrentContext();
31 CRBufferObjectState *b = &(g->bufferobject);
32
33 switch (target)
34 {
35 case GL_ARRAY_BUFFER_ARB:
36 return b->arrayBuffer->name!=0;
37 case GL_ELEMENT_ARRAY_BUFFER_ARB:
38 return b->elementsBuffer->name!=0;
39#ifdef CR_ARB_pixel_buffer_object
40 case GL_PIXEL_PACK_BUFFER_ARB:
41 return b->packBuffer->name!=0;
42 case GL_PIXEL_UNPACK_BUFFER_ARB:
43 return b->unpackBuffer->name!=0;
44#endif
45 default:
46 return GL_FALSE;
47 }
48}
49
50CRBufferObject *crStateGetBoundBufferObject(GLenum target, CRBufferObjectState *b)
51{
52 switch (target)
53 {
54 case GL_ARRAY_BUFFER_ARB:
55 return b->arrayBuffer;
56 case GL_ELEMENT_ARRAY_BUFFER_ARB:
57 return b->elementsBuffer;
58#ifdef CR_ARB_pixel_buffer_object
59 case GL_PIXEL_PACK_BUFFER_ARB:
60 return b->packBuffer;
61 case GL_PIXEL_UNPACK_BUFFER_ARB:
62 return b->unpackBuffer;
63#endif
64 default:
65 return NULL;
66 }
67}
68
69void crStateBufferObjectInit (CRContext *ctx)
70{
71 CRStateBits *sb = GetCurrentBits();
72 CRBufferObjectBits *bb = &sb->bufferobject;
73 CRBufferObjectState *b = &ctx->bufferobject;
74
75 RESET(bb->dirty, ctx->bitid);
76 RESET(bb->arrayBinding, ctx->bitid);
77 RESET(bb->elementsBinding, ctx->bitid);
78#ifdef CR_ARB_pixel_buffer_object
79 RESET(bb->unpackBinding, ctx->bitid);
80 RESET(bb->packBinding, ctx->bitid);
81#endif
82
83#ifdef IN_GUEST
84 b->retainBufferData = GL_TRUE;
85#else
86 b->retainBufferData = GL_FALSE;
87#endif
88
89 b->nullBuffer = AllocBufferObject(0);
90 b->arrayBuffer = b->nullBuffer;
91 b->elementsBuffer = b->nullBuffer;
92 b->nullBuffer->refCount = 3;
93#ifdef CR_ARB_pixel_buffer_object
94 b->packBuffer = b->nullBuffer;
95 b->unpackBuffer = b->nullBuffer;
96 b->nullBuffer->refCount += 2;
97#endif
98
99 b->buffers = crAllocHashtable();
100
101 b->bResyncNeeded = GL_FALSE;
102}
103
104
105static void crStateFreeBufferObject(void *data)
106{
107 CRBufferObject *pObj = (CRBufferObject *)data;
108 if (pObj->data) crFree(pObj->data);
109
110#ifndef IN_GUEST
111 if (diff_api.DeleteBuffersARB)
112 {
113 diff_api.DeleteBuffersARB(1, &pObj->name);
114 }
115#endif
116
117 crFree(pObj);
118}
119
120void crStateBufferObjectDestroy (CRContext *ctx)
121{
122 CRBufferObjectState *b = &ctx->bufferobject;
123 crFreeHashtable(b->buffers, crStateFreeBufferObject);
124 crFree(b->nullBuffer);
125}
126
127void STATE_APIENTRY
128crStateBindBufferARB (GLenum target, GLuint buffer)
129{
130 CRContext *g = GetCurrentContext();
131 CRBufferObjectState *b = &(g->bufferobject);
132 CRStateBits *sb = GetCurrentBits();
133 CRBufferObjectBits *bb = &(sb->bufferobject);
134 CRBufferObject *oldObj, *newObj;
135
136 if (g->current.inBeginEnd) {
137 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
138 "glBindBufferARB called in begin/end");
139 return;
140 }
141
142 FLUSH();
143
144 oldObj = crStateGetBoundBufferObject(target, b);
145 if (!oldObj)
146 {
147 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glBindBufferARB(target)");
148 return;
149 }
150
151 if (buffer == 0) {
152 newObj = b->nullBuffer;
153 }
154 else {
155 newObj = (CRBufferObject *) crHashtableSearch(b->buffers, buffer);
156 if (!newObj) {
157 newObj = AllocBufferObject(buffer);
158 if (!newObj) {
159 crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY, "glBindBuffer");
160 return;
161 }
162 crHashtableAdd( b->buffers, buffer, newObj );
163 }
164 }
165
166 newObj->refCount++;
167 oldObj->refCount--;
168
169 switch (target)
170 {
171 case GL_ARRAY_BUFFER_ARB:
172 b->arrayBuffer = newObj;
173 DIRTY(bb->dirty, g->neg_bitid);
174 DIRTY(bb->arrayBinding, g->neg_bitid);
175 break;
176 case GL_ELEMENT_ARRAY_BUFFER_ARB:
177 b->elementsBuffer = newObj;
178 DIRTY(bb->dirty, g->neg_bitid);
179 DIRTY(bb->elementsBinding, g->neg_bitid);
180 break;
181#ifdef CR_ARB_pixel_buffer_object
182 case GL_PIXEL_PACK_BUFFER_ARB:
183 b->packBuffer = newObj;
184 DIRTY(bb->dirty, g->neg_bitid);
185 DIRTY(bb->packBinding, g->neg_bitid);
186 break;
187 case GL_PIXEL_UNPACK_BUFFER_ARB:
188 b->unpackBuffer = newObj;
189 DIRTY(bb->dirty, g->neg_bitid);
190 DIRTY(bb->unpackBinding, g->neg_bitid);
191 break;
192#endif
193 default: /*can't get here*/
194 CRASSERT(false);
195 return;
196 }
197
198 if (oldObj->refCount <= 0) {
199 /*we shouldn't reach this point*/
200 CRASSERT(false);
201 crHashtableDelete(b->buffers, (unsigned long) oldObj->name, crStateFreeBufferObject);
202 }
203
204#ifdef IN_GUEST
205 if (target == GL_PIXEL_PACK_BUFFER_ARB)
206 {
207 newObj->bResyncOnRead = GL_TRUE;
208 }
209#endif
210}
211
212void STATE_APIENTRY
213crStateDeleteBuffersARB(GLsizei n, const GLuint *buffers)
214{
215 CRContext *g = GetCurrentContext();
216 CRBufferObjectState *b = &(g->bufferobject);
217 CRStateBits *sb = GetCurrentBits();
218 CRBufferObjectBits *bb = &(sb->bufferobject);
219 int i;
220
221 FLUSH();
222
223 if (g->current.inBeginEnd) {
224 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
225 "glDeleteBuffersARB called in Begin/End");
226 return;
227 }
228
229 if (n < 0) {
230 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
231 "glDeleteBuffersARB(n < 0)");
232 return;
233 }
234
235 for (i = 0; i < n; i++) {
236 if (buffers[i]) {
237 CRBufferObject *obj = (CRBufferObject *)
238 crHashtableSearch(b->buffers, buffers[i]);
239 if (obj) {
240 if (obj == b->arrayBuffer)
241 {
242 b->arrayBuffer = b->nullBuffer;
243 b->arrayBuffer->refCount++;
244 DIRTY(bb->dirty, g->neg_bitid);
245 DIRTY(bb->arrayBinding, g->neg_bitid);
246 }
247 else if (obj == b->elementsBuffer)
248 {
249 b->elementsBuffer = b->nullBuffer;
250 b->elementsBuffer->refCount++;
251 DIRTY(bb->dirty, g->neg_bitid);
252 DIRTY(bb->elementsBinding, g->neg_bitid);
253 }
254#ifdef CR_ARB_pixel_buffer_object
255 else if (obj == b->packBuffer)
256 {
257 b->packBuffer = b->nullBuffer;
258 b->packBuffer->refCount++;
259 DIRTY(bb->dirty, g->neg_bitid);
260 DIRTY(bb->packBinding, g->neg_bitid);
261 }
262 else if (obj == b->unpackBuffer)
263 {
264 b->unpackBuffer = b->nullBuffer;
265 b->unpackBuffer->refCount++;
266 DIRTY(bb->dirty, g->neg_bitid);
267 DIRTY(bb->unpackBinding, g->neg_bitid);
268 }
269#endif
270 /* @todo check bindings with the vertex arrays */
271
272 crHashtableDelete(b->buffers, buffers[i], crStateFreeBufferObject);
273 }
274 }
275 }
276}
277
278
279void STATE_APIENTRY
280crStateGenBuffersARB(GLsizei n, GLuint * buffers)
281{
282 CRContext *g = GetCurrentContext();
283 CRBufferObjectState *b = &(g->bufferobject);
284 GLint start;
285
286 FLUSH();
287
288 if (g->current.inBeginEnd) {
289 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
290 "glGenBuffersARB called in Begin/End");
291 return;
292 }
293
294 if (n < 0) {
295 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
296 "glGenBuffersARB(n < 0)");
297 return;
298 }
299
300 start = crHashtableAllocKeys(b->buffers, n);
301 if (start) {
302 GLint i;
303 for (i = 0; i < n; i++)
304 buffers[i] = (GLuint) (start + i);
305 }
306 else {
307 crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY, "glGenBuffersARB");
308 }
309}
310
311
312GLboolean STATE_APIENTRY
313crStateIsBufferARB(GLuint buffer)
314{
315 CRContext *g = GetCurrentContext();
316 CRBufferObjectState *b = &g->bufferobject;
317
318 FLUSH();
319
320 if (g->current.inBeginEnd) {
321 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
322 "glIsBufferARB called in begin/end");
323 return GL_FALSE;
324 }
325
326 if (buffer && crHashtableSearch(b->buffers, buffer))
327 return GL_TRUE;
328 else
329 return GL_FALSE;
330}
331
332
333void STATE_APIENTRY
334crStateBufferDataARB(GLenum target, GLsizeiptrARB size, const GLvoid * data, GLenum usage)
335{
336 CRContext *g = GetCurrentContext();
337 CRBufferObjectState *b = &g->bufferobject;
338 CRBufferObject *obj;
339 CRStateBits *sb = GetCurrentBits();
340 CRBufferObjectBits *bb = &sb->bufferobject;
341
342 FLUSH();
343
344 if (g->current.inBeginEnd) {
345 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
346 "glBufferDataARB called in begin/end");
347 return;
348 }
349
350 if (size < 0) {
351 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
352 "glBufferDataARB(size < 0)");
353 return;
354 }
355
356 switch (usage) {
357 case GL_STREAM_DRAW_ARB:
358 case GL_STREAM_READ_ARB:
359 case GL_STREAM_COPY_ARB:
360 case GL_STATIC_DRAW_ARB:
361 case GL_STATIC_READ_ARB:
362 case GL_STATIC_COPY_ARB:
363 case GL_DYNAMIC_DRAW_ARB:
364 case GL_DYNAMIC_READ_ARB:
365 case GL_DYNAMIC_COPY_ARB:
366 /* OK */
367 break;
368 default:
369 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
370 "glBufferDataARB(usage)");
371 return;
372 }
373
374 obj = crStateGetBoundBufferObject(target, b);
375 if (!obj)
376 {
377 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glBufferDataARB(target)");
378 return;
379 }
380
381 if (obj->name == 0) {
382 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glBufferDataARB");
383 return;
384 }
385
386 if (obj->pointer) {
387 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
388 "glBufferDataARB(buffer is mapped)");
389 return;
390 }
391
392 obj->usage = usage;
393 obj->size = size;
394
395 /* The user of the state tracker should set the retainBufferData field
396 * during context initialization, if needed.
397 */
398 if (b->retainBufferData) {
399 if (obj->data) {
400 crFree(obj->data);
401 }
402
403 obj->data = crAlloc(size);
404 if (!obj->data) {
405 crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY, "glBufferDataARB");
406 return;
407 }
408 if (data)
409 crMemcpy(obj->data, data, size);
410 }
411
412 DIRTY(bb->dirty, g->neg_bitid);
413 DIRTY(obj->dirty, g->neg_bitid);
414 obj->dirtyStart = 0;
415 obj->dirtyLength = size;
416}
417
418
419void STATE_APIENTRY
420crStateBufferSubDataARB(GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid * data)
421{
422 CRContext *g = GetCurrentContext();
423 CRBufferObjectState *b = &g->bufferobject;
424 CRBufferObject *obj;
425 CRStateBits *sb = GetCurrentBits();
426 CRBufferObjectBits *bb = &sb->bufferobject;
427
428 FLUSH();
429
430 if (g->current.inBeginEnd) {
431 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
432 "glBufferSubDataARB called in begin/end");
433 return;
434 }
435
436 obj = crStateGetBoundBufferObject(target, b);
437 if (!obj)
438 {
439 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glBufferSubDataARB(target)");
440 return;
441 }
442
443 if (obj->name == 0) {
444 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
445 "glBufferSubDataARB");
446 return;
447 }
448
449 if (obj->pointer) {
450 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
451 "glBufferSubDataARB(buffer is mapped)");
452 return;
453 }
454
455 if (size < 0 || offset < 0 || (unsigned int)offset + size > obj->size) {
456 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
457 "glBufferSubDataARB(bad offset and/or size)");
458 return;
459 }
460
461 if (b->retainBufferData && obj->data) {
462 crMemcpy((char *) obj->data + offset, data, size);
463 }
464
465 DIRTY(bb->dirty, g->neg_bitid);
466 DIRTY(obj->dirty, g->neg_bitid);
467 /* grow dirty region */
468 if (offset + size > obj->dirtyStart + obj->dirtyLength)
469 obj->dirtyLength = offset + size;
470 if (offset < obj->dirtyStart)
471 obj->dirtyStart = offset;
472}
473
474
475void STATE_APIENTRY
476crStateGetBufferSubDataARB(GLenum target, GLintptrARB offset, GLsizeiptrARB size, void * data)
477{
478 CRContext *g = GetCurrentContext();
479 CRBufferObjectState *b = &g->bufferobject;
480 CRBufferObject *obj;
481
482 FLUSH();
483
484 if (g->current.inBeginEnd) {
485 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
486 "glGetBufferSubDataARB called in begin/end");
487 return;
488 }
489
490 obj = crStateGetBoundBufferObject(target, b);
491 if (!obj)
492 {
493 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetBufferSubDataARB(target)");
494 return;
495 }
496
497 if (obj->name == 0) {
498 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
499 "glGetBufferSubDataARB");
500 return;
501 }
502
503 if (obj->pointer) {
504 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
505 "glGetBufferSubDataARB(buffer is mapped)");
506 return;
507 }
508
509 if (size < 0 || offset < 0 || (unsigned int)offset + size > obj->size) {
510 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
511 "glGetBufferSubDataARB(bad offset and/or size)");
512 return;
513 }
514
515 if (b->retainBufferData && obj->data) {
516 crMemcpy(data, (char *) obj->data + offset, size);
517 }
518}
519
520
521void * STATE_APIENTRY
522crStateMapBufferARB(GLenum target, GLenum access)
523{
524 CRContext *g = GetCurrentContext();
525 CRBufferObjectState *b = &g->bufferobject;
526 CRBufferObject *obj;
527
528 FLUSH();
529
530 if (g->current.inBeginEnd) {
531 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
532 "glMapBufferARB called in begin/end");
533 return NULL;
534 }
535
536 obj = crStateGetBoundBufferObject(target, b);
537 if (!obj)
538 {
539 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glMapBufferARB(target)");
540 return NULL;
541 }
542
543 if (obj->name == 0) {
544 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glMapBufferARB");
545 return GL_FALSE;
546 }
547
548 switch (access) {
549 case GL_READ_ONLY_ARB:
550 case GL_WRITE_ONLY_ARB:
551 case GL_READ_WRITE_ARB:
552 obj->access = access;
553 break;
554 default:
555 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
556 "glMapBufferARB(access)");
557 return NULL;
558 }
559
560 if (b->retainBufferData && obj->data)
561 obj->pointer = obj->data;
562
563 return obj->pointer;
564}
565
566
567GLboolean STATE_APIENTRY
568crStateUnmapBufferARB(GLenum target)
569{
570 CRContext *g = GetCurrentContext();
571 CRBufferObjectState *b = &g->bufferobject;
572 CRBufferObject *obj;
573 CRStateBits *sb = GetCurrentBits();
574 CRBufferObjectBits *bb = &sb->bufferobject;
575
576 FLUSH();
577
578 if (g->current.inBeginEnd) {
579 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
580 "glUnmapBufferARB called in begin/end");
581 return GL_FALSE;
582 }
583
584 obj = crStateGetBoundBufferObject(target, b);
585 if (!obj)
586 {
587 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glUnmapBufferARB(target)");
588 return GL_FALSE;
589 }
590
591 if (obj->name == 0) {
592 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glUnmapBufferARB");
593 return GL_FALSE;
594 }
595
596 if (!obj->pointer) {
597 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glUnmapBufferARB");
598 return GL_FALSE;
599 }
600
601 obj->pointer = NULL;
602
603 if (obj->access != GL_READ_ONLY_ARB) {
604 /* the data was most likely modified */
605 DIRTY(bb->dirty, g->neg_bitid);
606 DIRTY(obj->dirty, g->neg_bitid);
607 obj->dirtyStart = 0;
608 obj->dirtyLength = obj->size;
609 }
610
611 return GL_TRUE;
612}
613
614
615void STATE_APIENTRY
616crStateGetBufferParameterivARB(GLenum target, GLenum pname, GLint *params)
617{
618 CRContext *g = GetCurrentContext();
619 CRBufferObjectState *b = &g->bufferobject;
620 CRBufferObject *obj;
621
622 FLUSH();
623
624 if (g->current.inBeginEnd) {
625 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
626 "glGetBufferParameterivARB called in begin/end");
627 return;
628 }
629
630 obj = crStateGetBoundBufferObject(target, b);
631 if (!obj)
632 {
633 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetBufferParameterivARB(target)");
634 return;
635 }
636
637 switch (pname) {
638 case GL_BUFFER_SIZE_ARB:
639 *params = obj->size;
640 break;
641 case GL_BUFFER_USAGE_ARB:
642 *params = obj->usage;
643 break;
644 case GL_BUFFER_ACCESS_ARB:
645 *params = obj->access;
646 break;
647 case GL_BUFFER_MAPPED_ARB:
648 *params = (obj->pointer != NULL);
649 break;
650 default:
651 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
652 "glGetBufferParameterivARB(pname)");
653 return;
654 }
655}
656
657
658void STATE_APIENTRY
659crStateGetBufferPointervARB(GLenum target, GLenum pname, GLvoid **params)
660{
661 CRContext *g = GetCurrentContext();
662 CRBufferObjectState *b = &g->bufferobject;
663 CRBufferObject *obj;
664
665 FLUSH();
666
667 if (g->current.inBeginEnd) {
668 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
669 "glGetBufferPointervARB called in begin/end");
670 return;
671 }
672
673 obj = crStateGetBoundBufferObject(target, b);
674 if (!obj)
675 {
676 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetBufferPointervARB(target)");
677 return;
678 }
679
680 if (pname != GL_BUFFER_MAP_POINTER_ARB) {
681 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetBufferPointervARB(pname)");
682 return;
683 }
684
685 *params = obj->pointer;
686}
687
688
689/**
690 * We need to check if the GL_EXT_vertex/pixel_buffer_object extensions
691 * are supported before calling any of the diff_api functions.
692 * This flag indidcates if the extensions is available (1), not available (0)
693 * or needs to be tested for (-1).
694 * If we don't do this, we can segfault inside OpenGL.
695 * Ideally, the render SPU should no-op unsupported GL functions, but
696 * that's a bit complicated.
697 */
698static GLboolean
699HaveBufferObjectExtension(void)
700{
701 static GLint haveBufferObjectExt = -1;
702
703 if (haveBufferObjectExt == -1) {
704 const char *ext;
705 /* XXX this check is temporary. We need to make the tilesort SPU plug
706 * GetString into the diff'ing table in order for this to really work.
707 */
708 if (!diff_api.GetString) {
709 haveBufferObjectExt = 0;
710 return 0;
711 }
712 CRASSERT(diff_api.GetString);
713 ext = (const char *) diff_api.GetString(GL_EXTENSIONS);
714 if (crStrstr(ext, "GL_ARB_vertex_buffer_object") ||
715 crStrstr(ext, "GL_ARB_pixel_buffer_object")) {
716 haveBufferObjectExt = 1;
717 }
718 else {
719 haveBufferObjectExt = 0;
720 }
721 }
722 return haveBufferObjectExt;
723}
724
725static void crStateBufferObjectIntCmp(CRBufferObjectBits *bb, CRbitvalue *bitID,
726 CRContext *fromCtx, CRContext *toCtx,
727 GLboolean bSwitch)
728{
729 CRBufferObjectState *from = &(fromCtx->bufferobject);
730 const CRBufferObjectState *to = &(toCtx->bufferobject);
731
732 /* ARRAY_BUFFER */
733 if (CHECKDIRTY(bb->arrayBinding, bitID))
734 {
735 if (from->arrayBuffer != to->arrayBuffer)
736 {
737 GLuint bufferID = to->arrayBuffer ? to->arrayBuffer->name : 0;
738 diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, bufferID);
739 if (bSwitch)
740 {
741 FILLDIRTY(bb->arrayBinding);
742 FILLDIRTY(bb->dirty);
743 }
744 else
745 {
746 CLEARDIRTY2(bb->arrayBinding, bitID);
747 from->arrayBuffer = to->arrayBuffer;
748 }
749 }
750 if (bSwitch) CLEARDIRTY2(bb->arrayBinding, bitID);
751 }
752
753 if (to->arrayBuffer && CHECKDIRTY(to->arrayBuffer->dirty, bitID))
754 {
755 /* update array buffer data */
756 CRBufferObject *bufObj = to->arrayBuffer;
757 CRASSERT(bufObj);
758 if (bufObj->dirtyStart == 0 && bufObj->dirtyLength == (int) bufObj->size)
759 {
760 /* update whole buffer */
761 diff_api.BufferDataARB(GL_ARRAY_BUFFER_ARB, bufObj->size,
762 bufObj->data, bufObj->usage);
763 }
764 else
765 {
766 /* update sub buffer */
767 diff_api.BufferSubDataARB(GL_ARRAY_BUFFER_ARB,
768 bufObj->dirtyStart, bufObj->dirtyLength,
769 (char *) bufObj->data + bufObj->dirtyStart);
770 }
771 if (bSwitch) FILLDIRTY(bufObj->dirty);
772 CLEARDIRTY2(bufObj->dirty, bitID);
773 }
774
775 /* ELEMENTS_BUFFER */
776 if (CHECKDIRTY(bb->elementsBinding, bitID))
777 {
778 if (from->elementsBuffer != to->elementsBuffer)
779 {
780 GLuint bufferID = to->elementsBuffer ? to->elementsBuffer->name : 0;
781 diff_api.BindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, bufferID);
782 if (bSwitch)
783 {
784 FILLDIRTY(bb->elementsBinding);
785 FILLDIRTY(bb->dirty);
786 }
787 else
788 {
789 CLEARDIRTY2(bb->elementsBinding, bitID);
790 from->elementsBuffer = to->elementsBuffer;
791 }
792 }
793 if (bSwitch) CLEARDIRTY2(bb->elementsBinding, bitID);
794 }
795
796 if (to->elementsBuffer && CHECKDIRTY(to->elementsBuffer->dirty, bitID))
797 {
798 /* update array buffer data */
799 CRBufferObject *bufObj = to->elementsBuffer;
800 CRASSERT(bufObj);
801 if (bufObj->dirtyStart == 0 && bufObj->dirtyLength == (int) bufObj->size)
802 {
803 /* update whole buffer */
804 diff_api.BufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, bufObj->size,
805 bufObj->data, bufObj->usage);
806 }
807 else
808 {
809 /* update sub buffer */
810 diff_api.BufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB,
811 bufObj->dirtyStart, bufObj->dirtyLength,
812 (char *) bufObj->data + bufObj->dirtyStart);
813 }
814 if (bSwitch) FILLDIRTY(bufObj->dirty);
815 CLEARDIRTY2(bufObj->dirty, bitID);
816 }
817
818#ifdef CR_ARB_pixel_buffer_object
819 /* PIXEL_PACK_BUFFER */
820 if (CHECKDIRTY(bb->packBinding, bitID))
821 {
822 if (from->packBuffer != to->packBuffer)
823 {
824 GLuint bufferID = to->packBuffer ? to->packBuffer->name : 0;
825 diff_api.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, bufferID);
826 if (bSwitch)
827 {
828 FILLDIRTY(bb->packBinding);
829 FILLDIRTY(bb->dirty);
830 }
831 else
832 {
833 CLEARDIRTY2(bb->packBinding, bitID);
834 from->packBuffer = to->packBuffer;
835 }
836 }
837 if (bSwitch) CLEARDIRTY2(bb->packBinding, bitID);
838 }
839
840 if (to->packBuffer && CHECKDIRTY(to->packBuffer->dirty, bitID))
841 {
842 /* update array buffer data */
843 CRBufferObject *bufObj = to->packBuffer;
844 CRASSERT(bufObj);
845 if (bufObj->dirtyStart == 0 && bufObj->dirtyLength == (int) bufObj->size)
846 {
847 /* update whole buffer */
848 diff_api.BufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, bufObj->size,
849 bufObj->data, bufObj->usage);
850 }
851 else
852 {
853 /* update sub buffer */
854 diff_api.BufferSubDataARB(GL_PIXEL_PACK_BUFFER_ARB,
855 bufObj->dirtyStart, bufObj->dirtyLength,
856 (char *) bufObj->data + bufObj->dirtyStart);
857 }
858 if (bSwitch) FILLDIRTY(bufObj->dirty);
859 CLEARDIRTY2(bufObj->dirty, bitID);
860 }
861
862 /* PIXEL_UNPACK_BUFFER */
863 if (CHECKDIRTY(bb->unpackBinding, bitID))
864 {
865 if (from->unpackBuffer != to->unpackBuffer)
866 {
867 GLuint bufferID = to->unpackBuffer ? to->unpackBuffer->name : 0;
868 diff_api.BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, bufferID);
869 if (bSwitch)
870 {
871 FILLDIRTY(bb->unpackBinding);
872 FILLDIRTY(bb->dirty);
873 }
874 else
875 {
876 CLEARDIRTY2(bb->unpackBinding, bitID);
877 from->unpackBuffer = to->unpackBuffer;
878 }
879 }
880 if (bSwitch) CLEARDIRTY2(bb->unpackBinding, bitID);
881 }
882
883 if (to->unpackBuffer && CHECKDIRTY(to->unpackBuffer->dirty, bitID))
884 {
885 /* update array buffer data */
886 CRBufferObject *bufObj = to->unpackBuffer;
887 CRASSERT(bufObj);
888 if (bufObj->dirtyStart == 0 && bufObj->dirtyLength == (int) bufObj->size)
889 {
890 /* update whole buffer */
891 diff_api.BufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, bufObj->size,
892 bufObj->data, bufObj->usage);
893 }
894 else
895 {
896 /* update sub buffer */
897 diff_api.BufferSubDataARB(GL_PIXEL_UNPACK_BUFFER_ARB,
898 bufObj->dirtyStart, bufObj->dirtyLength,
899 (char *) bufObj->data + bufObj->dirtyStart);
900 }
901 if (bSwitch) FILLDIRTY(bufObj->dirty);
902 CLEARDIRTY2(bufObj->dirty, bitID);
903 }
904#endif /*ifdef CR_ARB_pixel_buffer_object*/
905}
906
907void crStateBufferObjectDiff(CRBufferObjectBits *bb, CRbitvalue *bitID,
908 CRContext *fromCtx, CRContext *toCtx)
909{
910 CRBufferObjectState *from = &(fromCtx->bufferobject);
911 const CRBufferObjectState *to = &(toCtx->bufferobject);
912
913 if (!HaveBufferObjectExtension())
914 return;
915
916 crStateBufferObjectIntCmp(bb, bitID, fromCtx, toCtx, GL_FALSE);
917}
918
919static void crStateBufferObjectSyncCB(unsigned long key, void *data1, void *data2)
920{
921 CRBufferObject *pBufferObj = (CRBufferObject *) data1;
922 CRBufferObjectState *pState = (CRBufferObjectState *) data2;
923
924 if (pBufferObj->data)
925 {
926 /*@todo http://www.opengl.org/registry/specs/ARB/pixel_buffer_object.txt
927 "While it is entirely legal to create a buffer object by binding
928 it to GL_ARRAY_BUFFER and loading it with data, then using it
929 with the GL_PIXEL_UNPACK_BUFFER_ARB or GL_PIXEL_PACK_BUFFER_ARB
930 binding, such behavior is liable to confuse the driver and may
931 hurt performance."
932 */
933 diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, pBufferObj->name);
934 diff_api.BufferDataARB(GL_ARRAY_BUFFER_ARB, pBufferObj->size, pBufferObj->data, pBufferObj->usage);
935
936 if (!pState->retainBufferData)
937 {
938 crFree(pBufferObj->data);
939 pBufferObj->data = NULL;
940 }
941 }
942}
943
944/*
945 * XXX this function might need some testing/fixing.
946 */
947void crStateBufferObjectSwitch(CRBufferObjectBits *bb, CRbitvalue *bitID,
948 CRContext *fromCtx, CRContext *toCtx)
949{
950 const CRBufferObjectState *from = &(fromCtx->bufferobject);
951 CRBufferObjectState *to = &(toCtx->bufferobject);
952 int i;
953
954 if (!HaveBufferObjectExtension())
955 return;
956
957 if (to->bResyncNeeded)
958 {
959 CRClientPointer *cp;
960 GLboolean locked = toCtx->client.array.locked;
961
962 crHashtableWalk(to->buffers, crStateBufferObjectSyncCB, to);
963 to->bResyncNeeded = GL_FALSE;
964
965 /*@todo, move to state_client.c*/
966 cp = &toCtx->client.array.v;
967 if (cp->buffer->name || locked)
968 {
969 diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, cp->buffer->name);
970 diff_api.VertexPointer(cp->size, cp->type, cp->stride, cp->p);
971 }
972
973 cp = &toCtx->client.array.c;
974 if (cp->buffer->name || locked)
975 {
976 diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, cp->buffer->name);
977 diff_api.ColorPointer(cp->size, cp->type, cp->stride, cp->p);
978 }
979
980 cp = &toCtx->client.array.f;
981 if (cp->buffer->name || locked)
982 {
983 diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, cp->buffer->name);
984 diff_api.FogCoordPointerEXT(cp->type, cp->stride, cp->p);
985 }
986
987 cp = &toCtx->client.array.s;
988 if (cp->buffer->name || locked)
989 {
990 diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, cp->buffer->name);
991 diff_api.SecondaryColorPointerEXT(cp->size, cp->type, cp->stride, cp->p);
992 }
993
994 cp = &toCtx->client.array.e;
995 if (cp->buffer->name || locked)
996 {
997 diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, cp->buffer->name);
998 diff_api.EdgeFlagPointer(cp->stride, cp->p);
999 }
1000
1001 cp = &toCtx->client.array.i;
1002 if (cp->buffer->name || locked)
1003 {
1004 diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, cp->buffer->name);
1005 diff_api.IndexPointer(cp->type, cp->stride, cp->p);
1006 }
1007
1008 cp = &toCtx->client.array.n;
1009 if (cp->buffer->name || locked)
1010 {
1011 diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, cp->buffer->name);
1012 diff_api.NormalPointer(cp->type, cp->stride, cp->p);
1013 }
1014
1015 for (i = 0; i < CR_MAX_TEXTURE_UNITS; i++)
1016 {
1017 cp = &toCtx->client.array.t[i];
1018 if (cp->buffer->name || locked)
1019 {
1020 if (diff_api.ActiveTextureARB)
1021 diff_api.ActiveTextureARB(i+GL_TEXTURE0_ARB);
1022 diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, cp->buffer->name);
1023 diff_api.TexCoordPointer(cp->size, cp->type, cp->stride, cp->p);
1024 }
1025 }
1026
1027 if (diff_api.ActiveTextureARB)
1028 diff_api.ActiveTextureARB(toCtx->client.curClientTextureUnit+GL_TEXTURE0_ARB);
1029
1030#ifdef CR_NV_vertex_program
1031 for (i = 0; i < CR_MAX_VERTEX_ATTRIBS; i++)
1032 {
1033 cp = &toCtx->client.array.a[i];
1034 if (cp->buffer->name || locked)
1035 {
1036 diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, cp->buffer->name);
1037 diff_api.VertexAttribPointerARB(i, cp->size, cp->type, cp->normalized, cp->stride, cp->p);
1038 }
1039 }
1040#endif
1041 diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, to->arrayBuffer->name);
1042 diff_api.BindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, to->elementsBuffer->name);
1043#ifdef CR_ARB_pixel_buffer_object
1044 diff_api.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, to->packBuffer->name);
1045 diff_api.BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, to->unpackBuffer->name);
1046#endif
1047 }
1048 else
1049 {
1050 crStateBufferObjectIntCmp(bb, bitID, fromCtx, toCtx, GL_TRUE);
1051 }
1052}
1053
1054
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