VirtualBox

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

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

crOpenGL: saved state fixes & improvements

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