VirtualBox

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

Last change on this file since 36140 was 34107, checked in by vboxsync, 14 years ago

crOpenGL/wddm: resync shared data only once

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