VirtualBox

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

Last change on this file since 78375 was 78375, checked in by vboxsync, 6 years ago

Additions/common/crOpengl,GuestHost/OpenGL,HostServices/SharedOpenGL: Eliminate all global variables from the state tracker library (state_tracker) in preparation of the SPU DLL merging, bugref:9435

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