VirtualBox

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

Last change on this file since 42932 was 41057, checked in by vboxsync, 13 years ago

crOpenGL: fix gl resource leaking (server part)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 32.3 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;
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 /* @todo check bindings with the vertex arrays */
305
306 crHashtableDelete(g->shared->buffersTable, buffers[i], crStateFreeBufferObject);
307 }
308 }
309 }
310}
311
312
313void STATE_APIENTRY
314crStateGenBuffersARB(GLsizei n, GLuint * buffers)
315{
316 CRContext *g = GetCurrentContext();
317 CRBufferObjectState *b = &(g->bufferobject);
318 GLint start;
319
320 FLUSH();
321
322 if (g->current.inBeginEnd) {
323 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
324 "glGenBuffersARB called in Begin/End");
325 return;
326 }
327
328 if (n < 0) {
329 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
330 "glGenBuffersARB(n < 0)");
331 return;
332 }
333
334 start = crHashtableAllocKeys(g->shared->buffersTable, n);
335 if (start) {
336 GLint i;
337 for (i = 0; i < n; i++)
338 buffers[i] = (GLuint) (start + i);
339 }
340 else {
341 crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY, "glGenBuffersARB");
342 }
343}
344
345
346GLboolean STATE_APIENTRY
347crStateIsBufferARB(GLuint buffer)
348{
349 CRContext *g = GetCurrentContext();
350 CRBufferObjectState *b = &g->bufferobject;
351
352 FLUSH();
353
354 if (g->current.inBeginEnd) {
355 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
356 "glIsBufferARB called in begin/end");
357 return GL_FALSE;
358 }
359
360 if (buffer && crHashtableSearch(g->shared->buffersTable, buffer))
361 return GL_TRUE;
362 else
363 return GL_FALSE;
364}
365
366
367void STATE_APIENTRY
368crStateBufferDataARB(GLenum target, GLsizeiptrARB size, const GLvoid * data, GLenum usage)
369{
370 CRContext *g = GetCurrentContext();
371 CRBufferObjectState *b = &g->bufferobject;
372 CRBufferObject *obj;
373 CRStateBits *sb = GetCurrentBits();
374 CRBufferObjectBits *bb = &sb->bufferobject;
375
376 FLUSH();
377
378 if (g->current.inBeginEnd) {
379 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
380 "glBufferDataARB called in begin/end");
381 return;
382 }
383
384 if (size < 0) {
385 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
386 "glBufferDataARB(size < 0)");
387 return;
388 }
389
390 switch (usage) {
391 case GL_STREAM_DRAW_ARB:
392 case GL_STREAM_READ_ARB:
393 case GL_STREAM_COPY_ARB:
394 case GL_STATIC_DRAW_ARB:
395 case GL_STATIC_READ_ARB:
396 case GL_STATIC_COPY_ARB:
397 case GL_DYNAMIC_DRAW_ARB:
398 case GL_DYNAMIC_READ_ARB:
399 case GL_DYNAMIC_COPY_ARB:
400 /* OK */
401 break;
402 default:
403 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
404 "glBufferDataARB(usage)");
405 return;
406 }
407
408 obj = crStateGetBoundBufferObject(target, b);
409 if (!obj)
410 {
411 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glBufferDataARB(target)");
412 return;
413 }
414
415 if (obj->id == 0) {
416 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glBufferDataARB");
417 return;
418 }
419
420 if (obj->pointer) {
421 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
422 "glBufferDataARB(buffer is mapped)");
423 return;
424 }
425
426 obj->usage = usage;
427 obj->size = size;
428
429 /* The user of the state tracker should set the retainBufferData field
430 * during context initialization, if needed.
431 */
432 if (b->retainBufferData) {
433 if (obj->data) {
434 crFree(obj->data);
435 }
436
437 obj->data = crAlloc(size);
438 if (!obj->data) {
439 crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY, "glBufferDataARB");
440 return;
441 }
442 if (data)
443 crMemcpy(obj->data, data, size);
444 }
445
446 DIRTY(bb->dirty, g->neg_bitid);
447 DIRTY(obj->dirty, g->neg_bitid);
448 obj->dirtyStart = 0;
449 obj->dirtyLength = size;
450}
451
452
453void STATE_APIENTRY
454crStateBufferSubDataARB(GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid * data)
455{
456 CRContext *g = GetCurrentContext();
457 CRBufferObjectState *b = &g->bufferobject;
458 CRBufferObject *obj;
459 CRStateBits *sb = GetCurrentBits();
460 CRBufferObjectBits *bb = &sb->bufferobject;
461
462 FLUSH();
463
464 if (g->current.inBeginEnd) {
465 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
466 "glBufferSubDataARB called in begin/end");
467 return;
468 }
469
470 obj = crStateGetBoundBufferObject(target, b);
471 if (!obj)
472 {
473 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glBufferSubDataARB(target)");
474 return;
475 }
476
477 if (obj->id == 0) {
478 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
479 "glBufferSubDataARB");
480 return;
481 }
482
483 if (obj->pointer) {
484 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
485 "glBufferSubDataARB(buffer is mapped)");
486 return;
487 }
488
489 if (size < 0 || offset < 0 || (unsigned int)offset + size > obj->size) {
490 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
491 "glBufferSubDataARB(bad offset and/or size)");
492 return;
493 }
494
495 if (b->retainBufferData && obj->data) {
496 crMemcpy((char *) obj->data + offset, data, size);
497 }
498
499 DIRTY(bb->dirty, g->neg_bitid);
500 DIRTY(obj->dirty, g->neg_bitid);
501 /* grow dirty region */
502 if (offset + size > obj->dirtyStart + obj->dirtyLength)
503 obj->dirtyLength = offset + size;
504 if (offset < obj->dirtyStart)
505 obj->dirtyStart = offset;
506}
507
508
509void STATE_APIENTRY
510crStateGetBufferSubDataARB(GLenum target, GLintptrARB offset, GLsizeiptrARB size, void * data)
511{
512 CRContext *g = GetCurrentContext();
513 CRBufferObjectState *b = &g->bufferobject;
514 CRBufferObject *obj;
515
516 FLUSH();
517
518 if (g->current.inBeginEnd) {
519 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
520 "glGetBufferSubDataARB called in begin/end");
521 return;
522 }
523
524 obj = crStateGetBoundBufferObject(target, b);
525 if (!obj)
526 {
527 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetBufferSubDataARB(target)");
528 return;
529 }
530
531 if (obj->id == 0) {
532 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
533 "glGetBufferSubDataARB");
534 return;
535 }
536
537 if (obj->pointer) {
538 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
539 "glGetBufferSubDataARB(buffer is mapped)");
540 return;
541 }
542
543 if (size < 0 || offset < 0 || (unsigned int)offset + size > obj->size) {
544 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
545 "glGetBufferSubDataARB(bad offset and/or size)");
546 return;
547 }
548
549 if (b->retainBufferData && obj->data) {
550 crMemcpy(data, (char *) obj->data + offset, size);
551 }
552}
553
554
555void * STATE_APIENTRY
556crStateMapBufferARB(GLenum target, GLenum access)
557{
558 CRContext *g = GetCurrentContext();
559 CRBufferObjectState *b = &g->bufferobject;
560 CRBufferObject *obj;
561
562 FLUSH();
563
564 if (g->current.inBeginEnd) {
565 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
566 "glMapBufferARB called in begin/end");
567 return NULL;
568 }
569
570 obj = crStateGetBoundBufferObject(target, b);
571 if (!obj)
572 {
573 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glMapBufferARB(target)");
574 return NULL;
575 }
576
577 if (obj->id == 0) {
578 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glMapBufferARB");
579 return GL_FALSE;
580 }
581
582 switch (access) {
583 case GL_READ_ONLY_ARB:
584 case GL_WRITE_ONLY_ARB:
585 case GL_READ_WRITE_ARB:
586 obj->access = access;
587 break;
588 default:
589 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
590 "glMapBufferARB(access)");
591 return NULL;
592 }
593
594 if (b->retainBufferData && obj->data)
595 obj->pointer = obj->data;
596
597 return obj->pointer;
598}
599
600
601GLboolean STATE_APIENTRY
602crStateUnmapBufferARB(GLenum target)
603{
604 CRContext *g = GetCurrentContext();
605 CRBufferObjectState *b = &g->bufferobject;
606 CRBufferObject *obj;
607 CRStateBits *sb = GetCurrentBits();
608 CRBufferObjectBits *bb = &sb->bufferobject;
609
610 FLUSH();
611
612 if (g->current.inBeginEnd) {
613 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
614 "glUnmapBufferARB called in begin/end");
615 return GL_FALSE;
616 }
617
618 obj = crStateGetBoundBufferObject(target, b);
619 if (!obj)
620 {
621 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glUnmapBufferARB(target)");
622 return GL_FALSE;
623 }
624
625 if (obj->id == 0) {
626 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glUnmapBufferARB");
627 return GL_FALSE;
628 }
629
630 if (!obj->pointer) {
631 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glUnmapBufferARB");
632 return GL_FALSE;
633 }
634
635 obj->pointer = NULL;
636
637 if (obj->access != GL_READ_ONLY_ARB) {
638 /* the data was most likely modified */
639 DIRTY(bb->dirty, g->neg_bitid);
640 DIRTY(obj->dirty, g->neg_bitid);
641 obj->dirtyStart = 0;
642 obj->dirtyLength = obj->size;
643 }
644
645 return GL_TRUE;
646}
647
648
649void STATE_APIENTRY
650crStateGetBufferParameterivARB(GLenum target, GLenum pname, GLint *params)
651{
652 CRContext *g = GetCurrentContext();
653 CRBufferObjectState *b = &g->bufferobject;
654 CRBufferObject *obj;
655
656 FLUSH();
657
658 if (g->current.inBeginEnd) {
659 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
660 "glGetBufferParameterivARB called in begin/end");
661 return;
662 }
663
664 obj = crStateGetBoundBufferObject(target, b);
665 if (!obj)
666 {
667 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetBufferParameterivARB(target)");
668 return;
669 }
670
671 switch (pname) {
672 case GL_BUFFER_SIZE_ARB:
673 *params = obj->size;
674 break;
675 case GL_BUFFER_USAGE_ARB:
676 *params = obj->usage;
677 break;
678 case GL_BUFFER_ACCESS_ARB:
679 *params = obj->access;
680 break;
681 case GL_BUFFER_MAPPED_ARB:
682 *params = (obj->pointer != NULL);
683 break;
684 default:
685 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
686 "glGetBufferParameterivARB(pname)");
687 return;
688 }
689}
690
691
692void STATE_APIENTRY
693crStateGetBufferPointervARB(GLenum target, GLenum pname, GLvoid **params)
694{
695 CRContext *g = GetCurrentContext();
696 CRBufferObjectState *b = &g->bufferobject;
697 CRBufferObject *obj;
698
699 FLUSH();
700
701 if (g->current.inBeginEnd) {
702 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
703 "glGetBufferPointervARB called in begin/end");
704 return;
705 }
706
707 obj = crStateGetBoundBufferObject(target, b);
708 if (!obj)
709 {
710 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetBufferPointervARB(target)");
711 return;
712 }
713
714 if (pname != GL_BUFFER_MAP_POINTER_ARB) {
715 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetBufferPointervARB(pname)");
716 return;
717 }
718
719 *params = obj->pointer;
720}
721
722
723/**
724 * We need to check if the GL_EXT_vertex/pixel_buffer_object extensions
725 * are supported before calling any of the diff_api functions.
726 * This flag indicates if the extensions is available (1), not available (0)
727 * or needs to be tested for (-1).
728 * If we don't do this, we can segfault inside OpenGL.
729 * Ideally, the render SPU should no-op unsupported GL functions, but
730 * that's a bit complicated.
731 */
732static GLboolean
733HaveBufferObjectExtension(void)
734{
735 static GLint haveBufferObjectExt = -1;
736
737 if (haveBufferObjectExt == -1) {
738 const char *ext;
739 /* XXX this check is temporary. We need to make the tilesort SPU plug
740 * GetString into the diff'ing table in order for this to really work.
741 */
742 if (!diff_api.GetString) {
743 haveBufferObjectExt = 0;
744 return 0;
745 }
746 CRASSERT(diff_api.GetString);
747 ext = (const char *) diff_api.GetString(GL_EXTENSIONS);
748 if (crStrstr(ext, "GL_ARB_vertex_buffer_object") ||
749 crStrstr(ext, "GL_ARB_pixel_buffer_object")) {
750 haveBufferObjectExt = 1;
751 }
752 else {
753 haveBufferObjectExt = 0;
754 }
755 }
756 return haveBufferObjectExt;
757}
758
759static void crStateBufferObjectIntCmp(CRBufferObjectBits *bb, CRbitvalue *bitID,
760 CRContext *fromCtx, CRContext *toCtx,
761 GLboolean bSwitch)
762{
763 CRBufferObjectState *from = &(fromCtx->bufferobject);
764 const CRBufferObjectState *to = &(toCtx->bufferobject);
765
766 /* ARRAY_BUFFER */
767 if (CHECKDIRTY(bb->arrayBinding, bitID))
768 {
769 if (from->arrayBuffer != to->arrayBuffer)
770 {
771 GLuint bufferID = to->arrayBuffer ? to->arrayBuffer->hwid : 0;
772 diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, bufferID);
773 if (bSwitch)
774 {
775 FILLDIRTY(bb->arrayBinding);
776 FILLDIRTY(bb->dirty);
777 }
778 else
779 {
780 CLEARDIRTY2(bb->arrayBinding, bitID);
781 from->arrayBuffer = to->arrayBuffer;
782 }
783 }
784 if (bSwitch) CLEARDIRTY2(bb->arrayBinding, bitID);
785 }
786
787 if (to->arrayBuffer && CHECKDIRTY(to->arrayBuffer->dirty, bitID))
788 {
789 /* update array buffer data */
790 CRBufferObject *bufObj = to->arrayBuffer;
791 CRASSERT(bufObj);
792 if (bufObj->dirtyStart == 0 && bufObj->dirtyLength == (int) bufObj->size)
793 {
794 /* update whole buffer */
795 diff_api.BufferDataARB(GL_ARRAY_BUFFER_ARB, bufObj->size,
796 bufObj->data, bufObj->usage);
797 }
798 else
799 {
800 /* update sub buffer */
801 diff_api.BufferSubDataARB(GL_ARRAY_BUFFER_ARB,
802 bufObj->dirtyStart, bufObj->dirtyLength,
803 (char *) bufObj->data + bufObj->dirtyStart);
804 }
805 if (bSwitch) FILLDIRTY(bufObj->dirty);
806 CLEARDIRTY2(bufObj->dirty, bitID);
807 }
808
809 /* ELEMENTS_BUFFER */
810 if (CHECKDIRTY(bb->elementsBinding, bitID))
811 {
812 if (from->elementsBuffer != to->elementsBuffer)
813 {
814 GLuint bufferID = to->elementsBuffer ? to->elementsBuffer->hwid : 0;
815 diff_api.BindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, bufferID);
816 if (bSwitch)
817 {
818 FILLDIRTY(bb->elementsBinding);
819 FILLDIRTY(bb->dirty);
820 }
821 else
822 {
823 CLEARDIRTY2(bb->elementsBinding, bitID);
824 from->elementsBuffer = to->elementsBuffer;
825 }
826 }
827 if (bSwitch) CLEARDIRTY2(bb->elementsBinding, bitID);
828 }
829
830 if (to->elementsBuffer && CHECKDIRTY(to->elementsBuffer->dirty, bitID))
831 {
832 /* update array buffer data */
833 CRBufferObject *bufObj = to->elementsBuffer;
834 CRASSERT(bufObj);
835 if (bufObj->dirtyStart == 0 && bufObj->dirtyLength == (int) bufObj->size)
836 {
837 /* update whole buffer */
838 diff_api.BufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, bufObj->size,
839 bufObj->data, bufObj->usage);
840 }
841 else
842 {
843 /* update sub buffer */
844 diff_api.BufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB,
845 bufObj->dirtyStart, bufObj->dirtyLength,
846 (char *) bufObj->data + bufObj->dirtyStart);
847 }
848 if (bSwitch) FILLDIRTY(bufObj->dirty);
849 CLEARDIRTY2(bufObj->dirty, bitID);
850 }
851
852#ifdef CR_ARB_pixel_buffer_object
853 /* PIXEL_PACK_BUFFER */
854 if (CHECKDIRTY(bb->packBinding, bitID))
855 {
856 if (from->packBuffer != to->packBuffer)
857 {
858 GLuint bufferID = to->packBuffer ? to->packBuffer->hwid : 0;
859 diff_api.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, bufferID);
860 if (bSwitch)
861 {
862 FILLDIRTY(bb->packBinding);
863 FILLDIRTY(bb->dirty);
864 }
865 else
866 {
867 CLEARDIRTY2(bb->packBinding, bitID);
868 from->packBuffer = to->packBuffer;
869 }
870 }
871 if (bSwitch) CLEARDIRTY2(bb->packBinding, bitID);
872 }
873
874 if (to->packBuffer && CHECKDIRTY(to->packBuffer->dirty, bitID))
875 {
876 /* update array buffer data */
877 CRBufferObject *bufObj = to->packBuffer;
878 CRASSERT(bufObj);
879 if (bufObj->dirtyStart == 0 && bufObj->dirtyLength == (int) bufObj->size)
880 {
881 /* update whole buffer */
882 diff_api.BufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, bufObj->size,
883 bufObj->data, bufObj->usage);
884 }
885 else
886 {
887 /* update sub buffer */
888 diff_api.BufferSubDataARB(GL_PIXEL_PACK_BUFFER_ARB,
889 bufObj->dirtyStart, bufObj->dirtyLength,
890 (char *) bufObj->data + bufObj->dirtyStart);
891 }
892 if (bSwitch) FILLDIRTY(bufObj->dirty);
893 CLEARDIRTY2(bufObj->dirty, bitID);
894 }
895
896 /* PIXEL_UNPACK_BUFFER */
897 if (CHECKDIRTY(bb->unpackBinding, bitID))
898 {
899 if (from->unpackBuffer != to->unpackBuffer)
900 {
901 GLuint bufferID = to->unpackBuffer ? to->unpackBuffer->hwid : 0;
902 diff_api.BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, bufferID);
903 if (bSwitch)
904 {
905 FILLDIRTY(bb->unpackBinding);
906 FILLDIRTY(bb->dirty);
907 }
908 else
909 {
910 CLEARDIRTY2(bb->unpackBinding, bitID);
911 from->unpackBuffer = to->unpackBuffer;
912 }
913 }
914 if (bSwitch) CLEARDIRTY2(bb->unpackBinding, bitID);
915 }
916
917 if (to->unpackBuffer && CHECKDIRTY(to->unpackBuffer->dirty, bitID))
918 {
919 /* update array buffer data */
920 CRBufferObject *bufObj = to->unpackBuffer;
921 CRASSERT(bufObj);
922 if (bufObj->dirtyStart == 0 && bufObj->dirtyLength == (int) bufObj->size)
923 {
924 /* update whole buffer */
925 diff_api.BufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, bufObj->size,
926 bufObj->data, bufObj->usage);
927 }
928 else
929 {
930 /* update sub buffer */
931 diff_api.BufferSubDataARB(GL_PIXEL_UNPACK_BUFFER_ARB,
932 bufObj->dirtyStart, bufObj->dirtyLength,
933 (char *) bufObj->data + bufObj->dirtyStart);
934 }
935 if (bSwitch) FILLDIRTY(bufObj->dirty);
936 CLEARDIRTY2(bufObj->dirty, bitID);
937 }
938#endif /*ifdef CR_ARB_pixel_buffer_object*/
939}
940
941void crStateBufferObjectDiff(CRBufferObjectBits *bb, CRbitvalue *bitID,
942 CRContext *fromCtx, CRContext *toCtx)
943{
944 CRBufferObjectState *from = &(fromCtx->bufferobject);
945 const CRBufferObjectState *to = &(toCtx->bufferobject);
946
947 if (!HaveBufferObjectExtension())
948 return;
949
950 crStateBufferObjectIntCmp(bb, bitID, fromCtx, toCtx, GL_FALSE);
951}
952
953static void crStateBufferObjectSyncCB(unsigned long key, void *data1, void *data2)
954{
955 CRBufferObject *pBufferObj = (CRBufferObject *) data1;
956 CRBufferObjectState *pState = (CRBufferObjectState *) data2;
957
958 if (pBufferObj->id && !pBufferObj->hwid)
959 {
960 diff_api.GenBuffersARB(1, &pBufferObj->hwid);
961 CRASSERT(pBufferObj->hwid);
962 }
963
964 if (pBufferObj->data)
965 {
966 /*@todo http://www.opengl.org/registry/specs/ARB/pixel_buffer_object.txt
967 "While it is entirely legal to create a buffer object by binding
968 it to GL_ARRAY_BUFFER and loading it with data, then using it
969 with the GL_PIXEL_UNPACK_BUFFER_ARB or GL_PIXEL_PACK_BUFFER_ARB
970 binding, such behavior is liable to confuse the driver and may
971 hurt performance."
972 */
973 diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, pBufferObj->hwid);
974 diff_api.BufferDataARB(GL_ARRAY_BUFFER_ARB, pBufferObj->size, pBufferObj->data, pBufferObj->usage);
975
976 if (!pState->retainBufferData)
977 {
978 crFree(pBufferObj->data);
979 pBufferObj->data = NULL;
980 }
981 }
982}
983
984/*
985 * XXX this function might need some testing/fixing.
986 */
987void crStateBufferObjectSwitch(CRBufferObjectBits *bb, CRbitvalue *bitID,
988 CRContext *fromCtx, CRContext *toCtx)
989{
990 const CRBufferObjectState *from = &(fromCtx->bufferobject);
991 CRBufferObjectState *to = &(toCtx->bufferobject);
992 int i;
993
994 if (!HaveBufferObjectExtension())
995 return;
996
997 if (toCtx->shared->bVBOResyncNeeded)
998 {
999 CRClientPointer *cp;
1000 GLboolean locked = toCtx->client.array.locked;
1001
1002 crHashtableWalk(toCtx->shared->buffersTable, crStateBufferObjectSyncCB, to);
1003 toCtx->shared->bVBOResyncNeeded = GL_FALSE;
1004
1005 /*@todo, move to state_client.c*/
1006 cp = &toCtx->client.array.v;
1007 if (cp->buffer && (cp->buffer->id || locked))
1008 {
1009 diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, cp->buffer->hwid);
1010 diff_api.VertexPointer(cp->size, cp->type, cp->stride, cp->p);
1011 }
1012
1013 cp = &toCtx->client.array.c;
1014 if (cp->buffer && (cp->buffer->id || locked))
1015 {
1016 diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, cp->buffer->hwid);
1017 diff_api.ColorPointer(cp->size, cp->type, cp->stride, cp->p);
1018 }
1019
1020 cp = &toCtx->client.array.f;
1021 if (cp->buffer && (cp->buffer->id || locked))
1022 {
1023 diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, cp->buffer->hwid);
1024 diff_api.FogCoordPointerEXT(cp->type, cp->stride, cp->p);
1025 }
1026
1027 cp = &toCtx->client.array.s;
1028 if (cp->buffer && (cp->buffer->id || locked))
1029 {
1030 diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, cp->buffer->hwid);
1031 diff_api.SecondaryColorPointerEXT(cp->size, cp->type, cp->stride, cp->p);
1032 }
1033
1034 cp = &toCtx->client.array.e;
1035 if (cp->buffer && (cp->buffer->id || locked))
1036 {
1037 diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, cp->buffer->hwid);
1038 diff_api.EdgeFlagPointer(cp->stride, cp->p);
1039 }
1040
1041 cp = &toCtx->client.array.i;
1042 if (cp->buffer && (cp->buffer->id || locked))
1043 {
1044 diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, cp->buffer->hwid);
1045 diff_api.IndexPointer(cp->type, cp->stride, cp->p);
1046 }
1047
1048 cp = &toCtx->client.array.n;
1049 if (cp->buffer && (cp->buffer->id || locked))
1050 {
1051 diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, cp->buffer->hwid);
1052 diff_api.NormalPointer(cp->type, cp->stride, cp->p);
1053 }
1054
1055 for (i = 0; i < CR_MAX_TEXTURE_UNITS; i++)
1056 {
1057 cp = &toCtx->client.array.t[i];
1058 if (cp->buffer && (cp->buffer->id || locked))
1059 {
1060 if (diff_api.ActiveTextureARB)
1061 diff_api.ActiveTextureARB(i+GL_TEXTURE0_ARB);
1062 diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, cp->buffer->hwid);
1063 diff_api.TexCoordPointer(cp->size, cp->type, cp->stride, cp->p);
1064 }
1065 }
1066
1067 if (diff_api.ActiveTextureARB)
1068 diff_api.ActiveTextureARB(toCtx->client.curClientTextureUnit+GL_TEXTURE0_ARB);
1069
1070#ifdef CR_NV_vertex_program
1071 for (i = 0; i < CR_MAX_VERTEX_ATTRIBS; i++)
1072 {
1073 cp = &toCtx->client.array.a[i];
1074 if (cp->buffer && (cp->buffer->id || locked))
1075 {
1076 diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, cp->buffer->hwid);
1077 diff_api.VertexAttribPointerARB(i, cp->size, cp->type, cp->normalized, cp->stride, cp->p);
1078 }
1079 }
1080#endif
1081 diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, to->arrayBuffer->hwid);
1082 diff_api.BindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, to->elementsBuffer->hwid);
1083#ifdef CR_ARB_pixel_buffer_object
1084 diff_api.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, to->packBuffer->hwid);
1085 diff_api.BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, to->unpackBuffer->hwid);
1086#endif
1087 }
1088 else
1089 {
1090 crStateBufferObjectIntCmp(bb, bitID, fromCtx, toCtx, GL_TRUE);
1091 }
1092}
1093
1094
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