VirtualBox

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

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

crOpenGL: more gl state fixes

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