VirtualBox

source: vbox/trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_framebuffer.c@ 43980

Last change on this file since 43980 was 43980, checked in by vboxsync, 12 years ago

crOpenGL: double-buffering for offscreen rendering, bugxifes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 31.1 KB
Line 
1/* $Id: state_framebuffer.c 43980 2012-11-28 07:10:56Z vboxsync $ */
2
3/** @file
4 * VBox OpenGL: EXT_framebuffer_object state tracking
5 */
6
7/*
8 * Copyright (C) 2009 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18
19#include "state.h"
20#include "state/cr_statetypes.h"
21#include "state/cr_statefuncs.h"
22#include "state_internals.h"
23#include "cr_mem.h"
24
25#define CRSTATE_FBO_CHECKERR(expr, result, message) \
26 if (expr) { \
27 crStateError(__LINE__, __FILE__, result, message); \
28 return; \
29 }
30
31DECLEXPORT(void) STATE_APIENTRY
32crStateFramebufferObjectInit(CRContext *ctx)
33{
34 CRFramebufferObjectState *fbo = &ctx->framebufferobject;
35
36 fbo->readFB = NULL;
37 fbo->drawFB = NULL;
38 fbo->renderbuffer = NULL;
39 ctx->shared->bFBOResyncNeeded = GL_FALSE;
40}
41
42void crStateFreeFBO(void *data)
43{
44 CRFramebufferObject *pObj = (CRFramebufferObject *)data;
45
46#ifndef IN_GUEST
47 if (diff_api.DeleteFramebuffersEXT)
48 {
49 diff_api.DeleteFramebuffersEXT(1, &pObj->hwid);
50 }
51#endif
52
53 crFree(pObj);
54}
55
56void crStateFreeRBO(void *data)
57{
58 CRRenderbufferObject *pObj = (CRRenderbufferObject *)data;
59
60#ifndef IN_GUEST
61 if (diff_api.DeleteRenderbuffersEXT)
62 {
63 diff_api.DeleteRenderbuffersEXT(1, &pObj->hwid);
64 }
65#endif
66
67 crFree(pObj);
68}
69
70DECLEXPORT(void) STATE_APIENTRY
71crStateFramebufferObjectDestroy(CRContext *ctx)
72{
73 CRFramebufferObjectState *fbo = &ctx->framebufferobject;
74
75 fbo->readFB = NULL;
76 fbo->drawFB = NULL;
77 fbo->renderbuffer = NULL;
78}
79
80DECLEXPORT(void) STATE_APIENTRY
81crStateBindRenderbufferEXT(GLenum target, GLuint renderbuffer)
82{
83 CRContext *g = GetCurrentContext();
84 CRFramebufferObjectState *fbo = &g->framebufferobject;
85
86 CRSTATE_FBO_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
87 CRSTATE_FBO_CHECKERR(target!=GL_RENDERBUFFER_EXT, GL_INVALID_ENUM, "invalid target");
88
89 if (renderbuffer)
90 {
91 fbo->renderbuffer = (CRRenderbufferObject*) crHashtableSearch(g->shared->rbTable, renderbuffer);
92 if (!fbo->renderbuffer)
93 {
94 fbo->renderbuffer = (CRRenderbufferObject*) crCalloc(sizeof(CRRenderbufferObject));
95 CRSTATE_FBO_CHECKERR(!fbo->renderbuffer, GL_OUT_OF_MEMORY, "glBindRenderbufferEXT");
96 fbo->renderbuffer->id = renderbuffer;
97 fbo->renderbuffer->hwid = renderbuffer;
98 fbo->renderbuffer->internalformat = GL_RGBA;
99 crHashtableAdd(g->shared->rbTable, renderbuffer, fbo->renderbuffer);
100#ifndef IN_GUEST
101 CR_STATE_SHAREDOBJ_USAGE_INIT(fbo->renderbuffer);
102#endif
103 }
104#ifndef IN_GUEST
105 CR_STATE_SHAREDOBJ_USAGE_SET(fbo->renderbuffer, g);
106#endif
107
108 }
109 else fbo->renderbuffer = NULL;
110}
111
112static void crStateCheckFBOAttachments(CRFramebufferObject *pFBO, GLuint rbo, GLenum target)
113{
114 CRFBOAttachmentPoint *ap;
115 int u;
116
117 if (!pFBO)
118 return;
119
120 for (u=0; u<CR_MAX_COLOR_ATTACHMENTS; ++u)
121 {
122 ap = &pFBO->color[u];
123 if (ap->type==GL_RENDERBUFFER_EXT && ap->name==rbo)
124 {
125 crStateFramebufferRenderbufferEXT(target, u+GL_COLOR_ATTACHMENT0_EXT, 0, 0);
126#ifdef IN_GUEST
127 pFBO->status = GL_FRAMEBUFFER_UNDEFINED;
128#endif
129 }
130 }
131
132 ap = &pFBO->depth;
133 if (ap->type==GL_RENDERBUFFER_EXT && ap->name==rbo)
134 {
135 crStateFramebufferRenderbufferEXT(target, GL_DEPTH_ATTACHMENT_EXT, 0, 0);
136#ifdef IN_GUEST
137 pFBO->status = GL_FRAMEBUFFER_UNDEFINED;
138#endif
139 }
140 ap = &pFBO->stencil;
141 if (ap->type==GL_RENDERBUFFER_EXT && ap->name==rbo)
142 {
143 crStateFramebufferRenderbufferEXT(target, GL_STENCIL_ATTACHMENT_EXT, 0, 0);
144#ifdef IN_GUEST
145 pFBO->status = GL_FRAMEBUFFER_UNDEFINED;
146#endif
147 }
148}
149
150DECLEXPORT(void) STATE_APIENTRY
151crStateDeleteRenderbuffersEXT(GLsizei n, const GLuint *renderbuffers)
152{
153 CRContext *g = GetCurrentContext();
154 CRFramebufferObjectState *fbo = &g->framebufferobject;
155 int i;
156
157 CRSTATE_FBO_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
158 CRSTATE_FBO_CHECKERR(n<0, GL_INVALID_OPERATION, "n<0");
159
160 for (i = 0; i < n; i++)
161 {
162 if (renderbuffers[i])
163 {
164 CRRenderbufferObject *rbo;
165 rbo = (CRRenderbufferObject*) crHashtableSearch(g->shared->rbTable, renderbuffers[i]);
166 if (rbo)
167 {
168 if (fbo->renderbuffer==rbo)
169 {
170 fbo->renderbuffer = NULL;
171 }
172
173 /* check the attachments of current framebuffers */
174 crStateCheckFBOAttachments(fbo->readFB, renderbuffers[i], GL_READ_FRAMEBUFFER);
175 crStateCheckFBOAttachments(fbo->drawFB, renderbuffers[i], GL_DRAW_FRAMEBUFFER);
176
177 crHashtableDelete(g->shared->rbTable, renderbuffers[i], crStateFreeRBO);
178 }
179 }
180 }
181}
182
183DECLEXPORT(void) STATE_APIENTRY
184crStateRenderbufferStorageEXT(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
185{
186 CRContext *g = GetCurrentContext();
187 CRFramebufferObjectState *fbo = &g->framebufferobject;
188 CRRenderbufferObject *rb = fbo->renderbuffer;
189
190 CRSTATE_FBO_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
191 CRSTATE_FBO_CHECKERR(target!=GL_RENDERBUFFER_EXT, GL_INVALID_ENUM, "invalid target");
192 CRSTATE_FBO_CHECKERR(!rb, GL_INVALID_OPERATION, "no bound renderbuffer");
193
194 rb->width = width;
195 rb->height = height;
196 rb->internalformat = internalformat;
197}
198
199DECLEXPORT(void) STATE_APIENTRY
200crStateGetRenderbufferParameterivEXT(GLenum target, GLenum pname, GLint *params)
201{
202 CRContext *g = GetCurrentContext();
203 CRFramebufferObjectState *fbo = &g->framebufferobject;
204 CRRenderbufferObject *rb = fbo->renderbuffer;
205
206 CRSTATE_FBO_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
207 CRSTATE_FBO_CHECKERR(target!=GL_RENDERBUFFER_EXT, GL_INVALID_ENUM, "invalid target");
208 CRSTATE_FBO_CHECKERR(!rb, GL_INVALID_OPERATION, "no bound renderbuffer");
209
210 switch (pname)
211 {
212 case GL_RENDERBUFFER_WIDTH_EXT:
213 *params = rb->width;
214 break;
215 case GL_RENDERBUFFER_HEIGHT_EXT:
216 *params = rb->height;
217 break;
218 case GL_RENDERBUFFER_INTERNAL_FORMAT_EXT:
219 *params = rb->internalformat;
220 break;
221 case GL_RENDERBUFFER_RED_SIZE_EXT:
222 case GL_RENDERBUFFER_GREEN_SIZE_EXT:
223 case GL_RENDERBUFFER_BLUE_SIZE_EXT:
224 case GL_RENDERBUFFER_ALPHA_SIZE_EXT:
225 case GL_RENDERBUFFER_DEPTH_SIZE_EXT:
226 case GL_RENDERBUFFER_STENCIL_SIZE_EXT:
227 CRSTATE_FBO_CHECKERR(GL_TRUE, GL_INVALID_OPERATION, "unimplemented");
228 break;
229 default:
230 CRSTATE_FBO_CHECKERR(GL_TRUE, GL_INVALID_ENUM, "invalid pname");
231 }
232}
233
234static void crStateInitFBOAttachmentPoint(CRFBOAttachmentPoint *fboap)
235{
236 fboap->type = GL_NONE;
237 fboap->name = 0;
238 fboap->level = 0;
239 fboap->face = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
240 fboap->zoffset = 0;
241}
242
243static void crStateInitFrameBuffer(CRFramebufferObject *fbo)
244{
245 int i;
246
247 for (i=0; i<CR_MAX_COLOR_ATTACHMENTS; ++i)
248 crStateInitFBOAttachmentPoint(&fbo->color[i]);
249
250 crStateInitFBOAttachmentPoint(&fbo->depth);
251 crStateInitFBOAttachmentPoint(&fbo->stencil);
252
253 fbo->readbuffer = GL_COLOR_ATTACHMENT0_EXT;
254 fbo->drawbuffer[0] = GL_COLOR_ATTACHMENT0_EXT;
255
256#ifdef IN_GUEST
257 fbo->status = GL_FRAMEBUFFER_UNDEFINED;
258#endif
259}
260
261static GLboolean crStateGetFBOAttachmentPoint(CRFramebufferObject *fb, GLenum attachment, CRFBOAttachmentPoint **ap)
262{
263 switch (attachment)
264 {
265 case GL_DEPTH_ATTACHMENT_EXT:
266 *ap = &fb->depth;
267 break;
268 case GL_STENCIL_ATTACHMENT_EXT:
269 *ap = &fb->stencil;
270 break;
271 default:
272 if (attachment>=GL_COLOR_ATTACHMENT0_EXT && attachment<=GL_COLOR_ATTACHMENT15_EXT)
273 {
274 *ap = &fb->color[attachment-GL_COLOR_ATTACHMENT0_EXT];
275 }
276 else return GL_FALSE;
277 }
278
279 return GL_TRUE;
280}
281
282DECLEXPORT(void) STATE_APIENTRY
283crStateBindFramebufferEXT(GLenum target, GLuint framebuffer)
284{
285 CRContext *g = GetCurrentContext();
286 CRFramebufferObjectState *fbo = &g->framebufferobject;
287 CRFramebufferObject *pFBO=NULL;
288
289 CRSTATE_FBO_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
290 CRSTATE_FBO_CHECKERR(((target!=GL_FRAMEBUFFER_EXT) && (target!=GL_READ_FRAMEBUFFER) && (target!=GL_DRAW_FRAMEBUFFER)),
291 GL_INVALID_ENUM, "invalid target");
292
293 if (framebuffer)
294 {
295 pFBO = (CRFramebufferObject*) crHashtableSearch(g->shared->fbTable, framebuffer);
296 if (!pFBO)
297 {
298 pFBO = (CRFramebufferObject*) crCalloc(sizeof(CRFramebufferObject));
299 CRSTATE_FBO_CHECKERR(!pFBO, GL_OUT_OF_MEMORY, "glBindFramebufferEXT");
300 pFBO->id = framebuffer;
301 pFBO->hwid = framebuffer;
302 crStateInitFrameBuffer(pFBO);
303 crHashtableAdd(g->shared->fbTable, framebuffer, pFBO);
304#ifndef IN_GUEST
305 CR_STATE_SHAREDOBJ_USAGE_INIT(pFBO);
306#endif
307 }
308
309#ifndef IN_GUEST
310 CR_STATE_SHAREDOBJ_USAGE_SET(pFBO, g);
311#endif
312 }
313
314 /* @todo: http://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
315 * FBO status might change when binding a different FBO here...but I doubt it happens.
316 * So no status reset here until a proper check.
317 */
318
319 switch (target)
320 {
321 case GL_FRAMEBUFFER_EXT:
322 fbo->readFB = pFBO;
323 fbo->drawFB = pFBO;
324 break;
325 case GL_READ_FRAMEBUFFER:
326 fbo->readFB = pFBO;
327 break;
328 case GL_DRAW_FRAMEBUFFER:
329 fbo->drawFB = pFBO;
330 break;
331 }
332}
333
334DECLEXPORT(void) STATE_APIENTRY
335crStateDeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers)
336{
337 CRContext *g = GetCurrentContext();
338 CRFramebufferObjectState *fbo = &g->framebufferobject;
339 int i;
340
341 CRSTATE_FBO_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
342 CRSTATE_FBO_CHECKERR(n<0, GL_INVALID_OPERATION, "n<0");
343
344 for (i = 0; i < n; i++)
345 {
346 if (framebuffers[i])
347 {
348 CRFramebufferObject *fb;
349 fb = (CRFramebufferObject*) crHashtableSearch(g->shared->fbTable, framebuffers[i]);
350 if (fb)
351 {
352 if (fbo->readFB==fb)
353 {
354 fbo->readFB = NULL;
355 }
356 if (fbo->drawFB==fb)
357 {
358 fbo->drawFB = NULL;
359 }
360 crHashtableDelete(g->shared->fbTable, framebuffers[i], crStateFreeFBO);
361 }
362 }
363 }
364}
365
366/*@todo: move this function somewhere else*/
367/*return floor of base 2 log of x. log(0)==0*/
368unsigned int crLog2Floor(unsigned int x)
369{
370 x |= (x >> 1);
371 x |= (x >> 2);
372 x |= (x >> 4);
373 x |= (x >> 8);
374 x |= (x >> 16);
375 x -= ((x >> 1) & 0x55555555);
376 x = (((x >> 2) & 0x33333333) + (x & 0x33333333));
377 x = (((x >> 4) + x) & 0x0f0f0f0f);
378 x += (x >> 8);
379 x += (x >> 16);
380 return (x & 0x0000003f) - 1;
381}
382
383static void crStateFramebufferTextureCheck(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level,
384 GLboolean *failed, CRFBOAttachmentPoint **ap, CRTextureObj **tobj)
385{
386 CRContext *g = GetCurrentContext();
387 CRFramebufferObjectState *fbo = &g->framebufferobject;
388 CRFramebufferObject *pFBO;
389 GLuint maxtexsizelog2;
390
391 *failed = GL_TRUE;
392
393 CRSTATE_FBO_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
394 CRSTATE_FBO_CHECKERR(((target!=GL_FRAMEBUFFER_EXT) && (target!=GL_READ_FRAMEBUFFER) && (target!=GL_DRAW_FRAMEBUFFER)),
395 GL_INVALID_ENUM, "invalid target");
396 pFBO = GL_READ_FRAMEBUFFER==target ? fbo->readFB : fbo->drawFB;
397 CRSTATE_FBO_CHECKERR(!pFBO, GL_INVALID_OPERATION, "no fbo bound");
398 CRSTATE_FBO_CHECKERR(!crStateGetFBOAttachmentPoint(pFBO, attachment, ap), GL_INVALID_ENUM, "invalid attachment");
399
400 if (!texture)
401 {
402 *failed = GL_FALSE;
403 return;
404 }
405
406 switch (textarget)
407 {
408 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
409 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
410 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
411 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
412 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
413 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
414 maxtexsizelog2 = crLog2Floor(g->limits.maxCubeMapTextureSize);
415 *tobj = crStateTextureGet(GL_TEXTURE_CUBE_MAP_ARB, texture);
416 break;
417 case GL_TEXTURE_RECTANGLE_ARB:
418 maxtexsizelog2 = 0;
419 *tobj = crStateTextureGet(textarget, texture);
420 break;
421 case GL_TEXTURE_3D:
422 maxtexsizelog2 = crLog2Floor(g->limits.max3DTextureSize);
423 *tobj = crStateTextureGet(textarget, texture);
424 break;
425 case GL_TEXTURE_2D:
426 case GL_TEXTURE_1D:
427 maxtexsizelog2 = crLog2Floor(g->limits.maxTextureSize);
428 *tobj = crStateTextureGet(textarget, texture);
429 break;
430 default:
431 CRSTATE_FBO_CHECKERR(GL_TRUE, GL_INVALID_OPERATION, "invalid textarget");
432 }
433
434 CRSTATE_FBO_CHECKERR(!*tobj, GL_INVALID_OPERATION, "invalid textarget/texture combo");
435
436 if (GL_TEXTURE_RECTANGLE_ARB==textarget)
437 {
438 CRSTATE_FBO_CHECKERR(level!=0, GL_INVALID_VALUE, "non zero mipmap level");
439 }
440
441 CRSTATE_FBO_CHECKERR(level<0, GL_INVALID_VALUE, "level<0");
442 CRSTATE_FBO_CHECKERR(level>maxtexsizelog2, GL_INVALID_VALUE, "level too big");
443
444 *failed = GL_FALSE;
445
446#ifdef IN_GUEST
447 if ((*ap)->type!=GL_TEXTURE || (*ap)->name!=texture || (*ap)->level!=level)
448 {
449 pFBO->status = GL_FRAMEBUFFER_UNDEFINED;
450 }
451#endif
452}
453
454DECLEXPORT(void) STATE_APIENTRY
455crStateFramebufferTexture1DEXT(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
456{
457 CRContext *g = GetCurrentContext();
458 CRFramebufferObjectState *fbo = &g->framebufferobject;
459 CRFBOAttachmentPoint *ap;
460 CRTextureObj *tobj;
461 GLboolean failed;
462
463 crStateFramebufferTextureCheck(target, attachment, textarget, texture, level, &failed, &ap, &tobj);
464 if (failed) return;
465
466 if (!texture)
467 {
468 crStateInitFBOAttachmentPoint(ap);
469 return;
470 }
471
472 CRSTATE_FBO_CHECKERR(textarget!=GL_TEXTURE_1D, GL_INVALID_OPERATION, "textarget");
473
474#ifndef IN_GUEST
475 CR_STATE_SHAREDOBJ_USAGE_SET(tobj, g);
476#endif
477
478 crStateInitFBOAttachmentPoint(ap);
479 ap->type = GL_TEXTURE;
480 ap->name = texture;
481 ap->level = level;
482}
483
484DECLEXPORT(void) STATE_APIENTRY
485crStateFramebufferTexture2DEXT(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
486{
487 CRContext *g = GetCurrentContext();
488 CRFramebufferObjectState *fbo = &g->framebufferobject;
489 CRFBOAttachmentPoint *ap;
490 CRTextureObj *tobj;
491 GLboolean failed;
492
493 crStateFramebufferTextureCheck(target, attachment, textarget, texture, level, &failed, &ap, &tobj);
494 if (failed) return;
495
496 if (!texture)
497 {
498 crStateInitFBOAttachmentPoint(ap);
499 return;
500 }
501
502 CRSTATE_FBO_CHECKERR(GL_TEXTURE_1D==textarget || GL_TEXTURE_3D==textarget, GL_INVALID_OPERATION, "textarget");
503
504#ifndef IN_GUEST
505 CR_STATE_SHAREDOBJ_USAGE_SET(tobj, g);
506#endif
507
508 crStateInitFBOAttachmentPoint(ap);
509 ap->type = GL_TEXTURE;
510 ap->name = texture;
511 ap->level = level;
512 if (textarget!=GL_TEXTURE_2D && textarget!=GL_TEXTURE_RECTANGLE_ARB)
513 {
514 ap->face = textarget;
515 }
516}
517
518DECLEXPORT(void) STATE_APIENTRY
519crStateFramebufferTexture3DEXT(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset)
520{
521 CRContext *g = GetCurrentContext();
522 CRFramebufferObjectState *fbo = &g->framebufferobject;
523 CRFBOAttachmentPoint *ap;
524 CRTextureObj *tobj;
525 GLboolean failed;
526
527 crStateFramebufferTextureCheck(target, attachment, textarget, texture, level, &failed, &ap, &tobj);
528 if (failed) return;
529
530 if (!texture)
531 {
532 crStateInitFBOAttachmentPoint(ap);
533 return;
534 }
535
536 CRSTATE_FBO_CHECKERR(zoffset>(g->limits.max3DTextureSize-1), GL_INVALID_VALUE, "zoffset too big");
537 CRSTATE_FBO_CHECKERR(textarget!=GL_TEXTURE_3D, GL_INVALID_OPERATION, "textarget");
538
539#ifndef IN_GUEST
540 CR_STATE_SHAREDOBJ_USAGE_SET(tobj, g);
541#endif
542
543 crStateInitFBOAttachmentPoint(ap);
544 ap->type = GL_TEXTURE;
545 ap->name = texture;
546 ap->level = level;
547 ap->zoffset = zoffset;
548}
549
550DECLEXPORT(void) STATE_APIENTRY
551crStateFramebufferRenderbufferEXT(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
552{
553 CRContext *g = GetCurrentContext();
554 CRFramebufferObjectState *fbo = &g->framebufferobject;
555 CRFramebufferObject *pFBO;
556 CRFBOAttachmentPoint *ap;
557 CRRenderbufferObject *rb;
558
559 CRSTATE_FBO_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
560 CRSTATE_FBO_CHECKERR(((target!=GL_FRAMEBUFFER_EXT) && (target!=GL_READ_FRAMEBUFFER) && (target!=GL_DRAW_FRAMEBUFFER)),
561 GL_INVALID_ENUM, "invalid target");
562 pFBO = GL_READ_FRAMEBUFFER==target ? fbo->readFB : fbo->drawFB;
563 CRSTATE_FBO_CHECKERR(!pFBO, GL_INVALID_OPERATION, "no fbo bound");
564 CRSTATE_FBO_CHECKERR(!crStateGetFBOAttachmentPoint(pFBO, attachment, &ap), GL_INVALID_ENUM, "invalid attachment");
565
566 if (!renderbuffer)
567 {
568#ifdef IN_GUEST
569 if (ap->type!=GL_NONE)
570 {
571 pFBO->status = GL_FRAMEBUFFER_UNDEFINED;
572 }
573#endif
574 crStateInitFBOAttachmentPoint(ap);
575 return;
576 }
577
578 rb = (CRRenderbufferObject*) crHashtableSearch(g->shared->rbTable, renderbuffer);
579 CRSTATE_FBO_CHECKERR(!rb, GL_INVALID_OPERATION, "rb doesn't exist");
580
581#ifdef IN_GUEST
582 if (ap->type!=GL_RENDERBUFFER_EXT || ap->name!=renderbuffer)
583 {
584 pFBO->status = GL_FRAMEBUFFER_UNDEFINED;
585 }
586#endif
587 crStateInitFBOAttachmentPoint(ap);
588 ap->type = GL_RENDERBUFFER_EXT;
589 ap->name = renderbuffer;
590}
591
592DECLEXPORT(void) STATE_APIENTRY
593crStateGetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, GLenum pname, GLint *params)
594{
595 CRContext *g = GetCurrentContext();
596 CRFramebufferObjectState *fbo = &g->framebufferobject;
597 CRFramebufferObject *pFBO;
598 CRFBOAttachmentPoint *ap;
599
600 CRSTATE_FBO_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
601 CRSTATE_FBO_CHECKERR(((target!=GL_FRAMEBUFFER_EXT) && (target!=GL_READ_FRAMEBUFFER) && (target!=GL_DRAW_FRAMEBUFFER)),
602 GL_INVALID_ENUM, "invalid target");
603 pFBO = GL_READ_FRAMEBUFFER==target ? fbo->readFB : fbo->drawFB;
604 CRSTATE_FBO_CHECKERR(!pFBO, GL_INVALID_OPERATION, "no fbo bound");
605 CRSTATE_FBO_CHECKERR(!crStateGetFBOAttachmentPoint(pFBO, attachment, &ap), GL_INVALID_ENUM, "invalid attachment");
606
607 switch (pname)
608 {
609 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT:
610 *params = ap->type;
611 break;
612 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT:
613 CRSTATE_FBO_CHECKERR(ap->type!=GL_RENDERBUFFER_EXT && ap->type!=GL_TEXTURE, GL_INVALID_ENUM, "can't query object name when it's not bound")
614 *params = ap->name;
615 break;
616 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT:
617 CRSTATE_FBO_CHECKERR(ap->type!=GL_TEXTURE, GL_INVALID_ENUM, "not a texture");
618 *params = ap->level;
619 break;
620 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT:
621 CRSTATE_FBO_CHECKERR(ap->type!=GL_TEXTURE, GL_INVALID_ENUM, "not a texture");
622 *params = ap->face;
623 break;
624 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT:
625 CRSTATE_FBO_CHECKERR(ap->type!=GL_TEXTURE, GL_INVALID_ENUM, "not a texture");
626 *params = ap->zoffset;
627 break;
628 default:
629 CRSTATE_FBO_CHECKERR(GL_TRUE, GL_INVALID_ENUM, "invalid pname");
630 }
631}
632
633DECLEXPORT(void) STATE_APIENTRY
634crStateGenerateMipmapEXT(GLenum target)
635{
636 /*@todo*/
637}
638
639static void crStateSyncRenderbuffersCB(unsigned long key, void *data1, void *data2)
640{
641 CRRenderbufferObject *pRBO = (CRRenderbufferObject*) data1;
642
643 diff_api.GenRenderbuffersEXT(1, &pRBO->hwid);
644
645 diff_api.BindRenderbufferEXT(GL_RENDERBUFFER_EXT, pRBO->hwid);
646 diff_api.RenderbufferStorageEXT(GL_RENDERBUFFER_EXT, pRBO->internalformat, pRBO->width, pRBO->height);
647}
648
649static void crStateSyncAP(CRFBOAttachmentPoint *pAP, GLenum ap, CRContext *ctx)
650{
651 CRRenderbufferObject *pRBO;
652 CRTextureObj *tobj;
653
654 switch (pAP->type)
655 {
656 case GL_TEXTURE:
657 CRASSERT(pAP->name!=0);
658
659 tobj = (CRTextureObj *) crHashtableSearch(ctx->shared->textureTable, pAP->name);
660 if (tobj)
661 {
662 CRASSERT(!tobj->id || tobj->hwid);
663
664 switch (tobj->target)
665 {
666 case GL_TEXTURE_1D:
667 diff_api.FramebufferTexture1DEXT(GL_FRAMEBUFFER_EXT, ap, tobj->target, crStateGetTextureObjHWID(tobj), pAP->level);
668 break;
669 case GL_TEXTURE_2D:
670 case GL_TEXTURE_RECTANGLE_ARB:
671 diff_api.FramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, ap, tobj->target, crStateGetTextureObjHWID(tobj), pAP->level);
672 break;
673 case GL_TEXTURE_CUBE_MAP_ARB:
674 diff_api.FramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, ap, pAP->face, crStateGetTextureObjHWID(tobj), pAP->level);
675 break;
676 case GL_TEXTURE_3D:
677 diff_api.FramebufferTexture3DEXT(GL_FRAMEBUFFER_EXT, ap, tobj->target, crStateGetTextureObjHWID(tobj), pAP->level, pAP->zoffset);
678 break;
679 default:
680 crWarning("Unexpected textarget %d", tobj->target);
681 }
682 }
683 else
684 {
685 crWarning("Unknown texture id %d", pAP->name);
686 }
687 break;
688 case GL_RENDERBUFFER_EXT:
689 pRBO = (CRRenderbufferObject*) crHashtableSearch(ctx->shared->rbTable, pAP->name);
690 diff_api.FramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, ap, GL_RENDERBUFFER_EXT, pRBO->hwid);
691 break;
692 case GL_NONE:
693 /* Intentionally left blank */
694 break;
695 default: crWarning("Invalid attachment point type %d (ap: %i)", pAP->type, ap);
696 }
697}
698
699static void crStateSyncFramebuffersCB(unsigned long key, void *data1, void *data2)
700{
701 CRFramebufferObject *pFBO = (CRFramebufferObject*) data1;
702 CRContext *ctx = (CRContext*) data2;
703 GLint i;
704
705 diff_api.GenFramebuffersEXT(1, &pFBO->hwid);
706
707 diff_api.BindFramebufferEXT(GL_FRAMEBUFFER_EXT, pFBO->hwid);
708
709 for (i=0; i<CR_MAX_COLOR_ATTACHMENTS; ++i)
710 {
711 crStateSyncAP(&pFBO->color[i], GL_COLOR_ATTACHMENT0_EXT+i, ctx);
712 }
713
714 crStateSyncAP(&pFBO->depth, GL_DEPTH_ATTACHMENT_EXT, ctx);
715 crStateSyncAP(&pFBO->stencil, GL_STENCIL_ATTACHMENT_EXT, ctx);
716}
717
718DECLEXPORT(void) STATE_APIENTRY
719crStateFramebufferObjectSwitch(CRContext *from, CRContext *to)
720{
721 if (to->shared->bFBOResyncNeeded)
722 {
723 to->shared->bFBOResyncNeeded = GL_FALSE;
724
725 crHashtableWalk(to->shared->rbTable, crStateSyncRenderbuffersCB, NULL);
726 crHashtableWalk(to->shared->fbTable, crStateSyncFramebuffersCB, to);
727
728 if (to->framebufferobject.drawFB==to->framebufferobject.readFB)
729 {
730 diff_api.BindFramebufferEXT(GL_FRAMEBUFFER_EXT, to->framebufferobject.drawFB?
731 to->framebufferobject.drawFB->hwid:0);
732 }
733 else
734 {
735 diff_api.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, to->framebufferobject.drawFB?
736 to->framebufferobject.drawFB->hwid:0);
737
738 diff_api.BindFramebufferEXT(GL_READ_FRAMEBUFFER, to->framebufferobject.readFB?
739 to->framebufferobject.readFB->hwid:0);
740 }
741
742 diff_api.BindRenderbufferEXT(GL_RENDERBUFFER_EXT, to->framebufferobject.renderbuffer?
743 to->framebufferobject.renderbuffer->hwid:0);
744 }
745 else
746 {
747 if (to->framebufferobject.drawFB!=from->framebufferobject.drawFB
748 || to->framebufferobject.readFB!=from->framebufferobject.readFB)
749 {
750 if (to->framebufferobject.drawFB==to->framebufferobject.readFB)
751 {
752 diff_api.BindFramebufferEXT(GL_FRAMEBUFFER_EXT, to->framebufferobject.drawFB?
753 to->framebufferobject.drawFB->hwid:0);
754 }
755 else
756 {
757 diff_api.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, to->framebufferobject.drawFB?
758 to->framebufferobject.drawFB->hwid:0);
759
760 diff_api.BindFramebufferEXT(GL_READ_FRAMEBUFFER, to->framebufferobject.readFB?
761 to->framebufferobject.readFB->hwid:0);
762 }
763
764 diff_api.DrawBuffer(to->framebufferobject.drawFB?to->framebufferobject.drawFB->drawbuffer[0]:to->buffer.drawBuffer);
765 diff_api.ReadBuffer(to->framebufferobject.readFB?to->framebufferobject.readFB->readbuffer:to->buffer.readBuffer);
766 }
767
768 if (to->framebufferobject.renderbuffer!=from->framebufferobject.renderbuffer)
769 {
770 diff_api.BindRenderbufferEXT(GL_RENDERBUFFER_EXT, to->framebufferobject.renderbuffer?
771 to->framebufferobject.renderbuffer->hwid:0);
772 }
773 }
774}
775
776DECLEXPORT(void) STATE_APIENTRY
777crStateFramebufferObjectDisableHW(CRContext *ctx, GLuint idDrawFBO, GLuint idReadFBO)
778{
779 GLboolean fAdjustDrawReadBuffers = GL_FALSE;
780
781 if (ctx->framebufferobject.drawFB || idDrawFBO)
782 {
783 diff_api.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, 0);
784 fAdjustDrawReadBuffers = GL_TRUE;
785 }
786
787 if (ctx->framebufferobject.readFB || idReadFBO)
788 {
789 diff_api.BindFramebufferEXT(GL_READ_FRAMEBUFFER, 0);
790 fAdjustDrawReadBuffers = GL_TRUE;
791 }
792
793 if (fAdjustDrawReadBuffers)
794 {
795 diff_api.DrawBuffer(GL_BACK);
796 diff_api.ReadBuffer(GL_BACK);
797 }
798
799 if (ctx->framebufferobject.renderbuffer)
800 diff_api.BindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
801}
802
803DECLEXPORT(void) STATE_APIENTRY
804crStateFramebufferObjectReenableHW(CRContext *fromCtx, CRContext *toCtx, GLuint idDrawFBO, GLuint idReadFBO)
805{
806 GLuint idReadBuffer = 0, idDrawBuffer = 0;
807
808 if ((fromCtx->framebufferobject.drawFB) /* <- the FBO state was reset in crStateFramebufferObjectDisableHW */
809 && fromCtx->framebufferobject.drawFB == toCtx->framebufferobject.drawFB) /* .. and it was NOT restored properly in crStateFramebufferObjectSwitch */
810 {
811 diff_api.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, toCtx->framebufferobject.drawFB->hwid);
812 idDrawBuffer = toCtx->framebufferobject.drawFB->drawbuffer[0];
813 }
814 else if (idDrawFBO && !toCtx->framebufferobject.drawFB)
815 {
816 diff_api.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, idDrawFBO);
817 idDrawBuffer = GL_COLOR_ATTACHMENT0;
818 }
819
820 if ((fromCtx->framebufferobject.readFB) /* <- the FBO state was reset in crStateFramebufferObjectDisableHW */
821 && fromCtx->framebufferobject.readFB == toCtx->framebufferobject.readFB) /* .. and it was NOT restored properly in crStateFramebufferObjectSwitch */
822 {
823 diff_api.BindFramebufferEXT(GL_READ_FRAMEBUFFER, toCtx->framebufferobject.readFB->hwid);
824 idReadBuffer = toCtx->framebufferobject.readFB->readbuffer;
825 }
826 else if (idReadFBO && !toCtx->framebufferobject.readFB)
827 {
828 diff_api.BindFramebufferEXT(GL_READ_FRAMEBUFFER, idReadFBO);
829 idReadBuffer = GL_COLOR_ATTACHMENT0;
830 }
831
832 if (idDrawBuffer)
833 diff_api.DrawBuffer(idDrawBuffer);
834 if (idReadBuffer)
835 diff_api.ReadBuffer(idReadBuffer);
836
837 if (fromCtx->framebufferobject.renderbuffer /* <- the FBO state was reset in crStateFramebufferObjectDisableHW */
838 && fromCtx->framebufferobject.renderbuffer==toCtx->framebufferobject.renderbuffer) /* .. and it was NOT restored properly in crStateFramebufferObjectSwitch */
839 {
840 diff_api.BindRenderbufferEXT(GL_RENDERBUFFER_EXT, toCtx->framebufferobject.renderbuffer->hwid);
841 }
842}
843
844
845DECLEXPORT(GLuint) STATE_APIENTRY crStateGetFramebufferHWID(GLuint id)
846{
847 CRContext *g = GetCurrentContext();
848 CRFramebufferObject *pFBO = (CRFramebufferObject*) crHashtableSearch(g->shared->fbTable, id);
849#ifdef DEBUG_misha
850 crDebug("FB id(%d) hw(%d)", id, pFBO ? pFBO->hwid : 0);
851#endif
852 return pFBO ? pFBO->hwid : 0;
853}
854
855DECLEXPORT(GLuint) STATE_APIENTRY crStateGetRenderbufferHWID(GLuint id)
856{
857 CRContext *g = GetCurrentContext();
858 CRRenderbufferObject *pRBO = (CRRenderbufferObject*) crHashtableSearch(g->shared->rbTable, id);
859
860 return pRBO ? pRBO->hwid : 0;
861}
862
863static void crStateCheckFBOHWIDCB(unsigned long key, void *data1, void *data2)
864{
865 CRFramebufferObject *pFBO = (CRFramebufferObject *) data1;
866 crCheckIDHWID_t *pParms = (crCheckIDHWID_t*) data2;
867 (void) key;
868
869 if (pFBO->hwid==pParms->hwid)
870 pParms->id = pFBO->id;
871}
872
873static void crStateCheckRBOHWIDCB(unsigned long key, void *data1, void *data2)
874{
875 CRRenderbufferObject *pRBO = (CRRenderbufferObject *) data1;
876 crCheckIDHWID_t *pParms = (crCheckIDHWID_t*) data2;
877 (void) key;
878
879 if (pRBO->hwid==pParms->hwid)
880 pParms->id = pRBO->id;
881}
882
883DECLEXPORT(GLuint) STATE_APIENTRY crStateFBOHWIDtoID(GLuint hwid)
884{
885 CRContext *g = GetCurrentContext();
886 crCheckIDHWID_t parms;
887
888 parms.id = hwid;
889 parms.hwid = hwid;
890
891 crHashtableWalk(g->shared->fbTable, crStateCheckFBOHWIDCB, &parms);
892 return parms.id;
893}
894
895DECLEXPORT(GLuint) STATE_APIENTRY crStateRBOHWIDtoID(GLuint hwid)
896{
897 CRContext *g = GetCurrentContext();
898 crCheckIDHWID_t parms;
899
900 parms.id = hwid;
901 parms.hwid = hwid;
902
903 crHashtableWalk(g->shared->rbTable, crStateCheckRBOHWIDCB, &parms);
904 return parms.id;
905}
906
907#ifdef IN_GUEST
908DECLEXPORT(GLenum) STATE_APIENTRY crStateCheckFramebufferStatusEXT(GLenum target)
909{
910 GLenum status = GL_FRAMEBUFFER_UNDEFINED;
911 CRContext *g = GetCurrentContext();
912 CRFramebufferObjectState *fbo = &g->framebufferobject;
913 CRFramebufferObject *pFBO=NULL;
914
915 switch (target)
916 {
917 case GL_FRAMEBUFFER_EXT:
918 pFBO = fbo->drawFB;
919 break;
920 case GL_READ_FRAMEBUFFER:
921 pFBO = fbo->readFB;
922 break;
923 case GL_DRAW_FRAMEBUFFER:
924 pFBO = fbo->drawFB;
925 break;
926 }
927
928 if (pFBO) status = pFBO->status;
929
930 return status;
931}
932
933DECLEXPORT(GLenum) STATE_APIENTRY crStateSetFramebufferStatus(GLenum target, GLenum status)
934{
935 CRContext *g = GetCurrentContext();
936 CRFramebufferObjectState *fbo = &g->framebufferobject;
937 CRFramebufferObject *pFBO=NULL;
938
939 switch (target)
940 {
941 case GL_FRAMEBUFFER_EXT:
942 pFBO = fbo->drawFB;
943 break;
944 case GL_READ_FRAMEBUFFER:
945 pFBO = fbo->readFB;
946 break;
947 case GL_DRAW_FRAMEBUFFER:
948 pFBO = fbo->drawFB;
949 break;
950 }
951
952 if (pFBO) pFBO->status = status;
953
954 return status;
955}
956#endif
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