VirtualBox

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

Last change on this file since 27159 was 27152, checked in by vboxsync, 15 years ago

GuestHost/OpenGL: warning

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