VirtualBox

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

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

crOpenGL: more gl state fixes

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette