VirtualBox

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

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

Additions/common/crOpengl,GuestHost/OpenGL,HostServices/SharedOpenGL: Eliminate all global variables from the state tracker library (state_tracker) in preparation of the SPU DLL merging, bugref:9435

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