VirtualBox

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

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

Automated rebranding to Oracle copyright/license strings via filemuncher

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