VirtualBox

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

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

crOpenGL: more state fixes

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