VirtualBox

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

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

crOpenGL: fix black screen after snapshots loading for apps using compiled vertex arrays

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