VirtualBox

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

Last change on this file since 44052 was 44052, checked in by vboxsync, 12 years ago

crOpenGL: fix buffer object refferencing

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

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