VirtualBox

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

Last change on this file since 36140 was 34107, checked in by vboxsync, 14 years ago

crOpenGL/wddm: resync shared data only once

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