VirtualBox

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

Last change on this file since 78116 was 78116, checked in by vboxsync, 6 years ago

GuestHost/OpenGL,HostServices/SharedOpenGL: Updates bugref:9407

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