VirtualBox

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

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

crOpenGL: fix memory leak when using VBOs

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