VirtualBox

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

Last change on this file since 71930 was 69500, checked in by vboxsync, 7 years ago

*: scm --update-copyright-year

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