VirtualBox

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

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

crOpenGL: more code for multiscreen support

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