VirtualBox

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

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

crOpenGL: fix GPU memory leak for apps not clearing VBOs/FBOs and incorrect FBO tracking

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 18.5 KB
Line 
1/* $Id: state_framebuffer.c 22831 2009-09-08 11:13:06Z vboxsync $ */
2
3/** @file
4 * VBox OpenGL: EXT_framebuffer_object state tracking
5 */
6
7/*
8 * Copyright (C) 2009 Sun Microsystems, Inc.
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 *
18 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
19 * Clara, CA 95054 USA or visit http://www.sun.com if you need
20 * additional information or have any questions.
21 */
22
23#include "state.h"
24#include "state/cr_statetypes.h"
25#include "state/cr_statefuncs.h"
26#include "state_internals.h"
27#include "cr_mem.h"
28
29#define CRSTATE_FBO_CHECKERR(expr, result, message) \
30 if (expr) { \
31 crStateError(__LINE__, __FILE__, result, message); \
32 return; \
33 }
34
35DECLEXPORT(void) STATE_APIENTRY
36crStateFramebufferObjectInit(CRContext *ctx)
37{
38 CRFramebufferObjectState *fbo = &ctx->framebufferobject;
39
40 fbo->framebuffer = NULL;
41 fbo->renderbuffer = NULL;
42 fbo->framebuffers = crAllocHashtable();
43 fbo->renderbuffers = crAllocHashtable();
44}
45
46static void crStateFreeFBO(void *data)
47{
48 CRFramebufferObject *pObj = (CRFramebufferObject *)data;
49
50 if (diff_api.AlphaFunc)
51 {
52 diff_api.DeleteFramebuffersEXT(1, &pObj->id);
53 }
54
55 crFree(pObj);
56}
57
58static void crStateFreeRBO(void *data)
59{
60 CRRenderbufferObject *pObj = (CRRenderbufferObject *)data;
61
62 if (diff_api.AlphaFunc)
63 {
64 diff_api.DeleteRenderbuffersEXT(1, &pObj->id);
65 }
66
67 crFree(pObj);
68}
69
70DECLEXPORT(void) STATE_APIENTRY
71crStateFramebufferObjectDestroy(CRContext *ctx)
72{
73 CRFramebufferObjectState *fbo = &ctx->framebufferobject;
74
75 fbo->framebuffer = NULL;
76 fbo->renderbuffer = NULL;
77
78 crFreeHashtable(fbo->framebuffers, crStateFreeFBO);
79 crFreeHashtable(fbo->renderbuffers, crStateFreeRBO);
80}
81
82DECLEXPORT(void) STATE_APIENTRY
83crStateBindRenderbufferEXT(GLenum target, GLuint renderbuffer)
84{
85 CRContext *g = GetCurrentContext();
86 CRFramebufferObjectState *fbo = &g->framebufferobject;
87
88 CRSTATE_FBO_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
89 CRSTATE_FBO_CHECKERR(target!=GL_RENDERBUFFER_EXT, GL_INVALID_ENUM, "invalid target");
90
91 if (renderbuffer)
92 {
93 fbo->renderbuffer = (CRRenderbufferObject*) crHashtableSearch(fbo->renderbuffers, renderbuffer);
94 if (!fbo->renderbuffer)
95 {
96 fbo->renderbuffer = (CRRenderbufferObject*) crCalloc(sizeof(CRRenderbufferObject));
97 CRSTATE_FBO_CHECKERR(!fbo->renderbuffer, GL_OUT_OF_MEMORY, "glBindRenderbufferEXT");
98 fbo->renderbuffer->id = renderbuffer;
99 fbo->renderbuffer->internalformat = GL_RGBA;
100 crHashtableAdd(fbo->renderbuffers, renderbuffer, fbo->renderbuffer);
101 }
102 }
103 else fbo->renderbuffer = NULL;
104}
105
106DECLEXPORT(void) STATE_APIENTRY
107crStateDeleteRenderbuffersEXT(GLsizei n, const GLuint *renderbuffers)
108{
109 CRContext *g = GetCurrentContext();
110 CRFramebufferObjectState *fbo = &g->framebufferobject;
111 int i;
112
113 CRSTATE_FBO_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
114 CRSTATE_FBO_CHECKERR(n<0, GL_INVALID_OPERATION, "n<0");
115
116 for (i = 0; i < n; i++)
117 {
118 if (renderbuffers[i])
119 {
120 CRRenderbufferObject *rbo;
121 rbo = (CRRenderbufferObject*) crHashtableSearch(fbo->renderbuffers, renderbuffers[i]);
122 if (rbo)
123 {
124 if (fbo->renderbuffer==rbo)
125 {
126 fbo->renderbuffer = NULL;
127 }
128
129 /* check the attachments of current framebuffer */
130 if (fbo->framebuffer)
131 {
132 CRFBOAttachmentPoint *ap;
133 int u;
134
135 for (u=0; u<CR_MAX_COLOR_ATTACHMENTS; ++u)
136 {
137 ap = &fbo->framebuffer->color[u];
138 if (ap->type==GL_RENDERBUFFER_EXT && ap->name==renderbuffers[i])
139 {
140 crStateFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, u+GL_COLOR_ATTACHMENT0_EXT, 0, 0);
141 }
142 }
143
144 ap = &fbo->framebuffer->depth;
145 if (ap->type==GL_RENDERBUFFER_EXT && ap->name==renderbuffers[i])
146 {
147 crStateFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, 0, 0);
148 }
149 ap = &g->framebufferobject.framebuffer->stencil;
150 if (ap->type==GL_RENDERBUFFER_EXT && ap->name==renderbuffers[i])
151 {
152 crStateFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, 0, 0);
153 }
154 }
155
156 crHashtableDelete(fbo->renderbuffers, renderbuffers[i], crFree);
157 }
158 }
159 }
160}
161
162DECLEXPORT(void) STATE_APIENTRY
163crStateRenderbufferStorageEXT(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
164{
165 CRContext *g = GetCurrentContext();
166 CRFramebufferObjectState *fbo = &g->framebufferobject;
167 CRRenderbufferObject *rb = fbo->renderbuffer;
168
169 CRSTATE_FBO_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
170 CRSTATE_FBO_CHECKERR(target!=GL_RENDERBUFFER_EXT, GL_INVALID_ENUM, "invalid target");
171 CRSTATE_FBO_CHECKERR(rb, GL_INVALID_OPERATION, "no bound renderbuffer");
172
173 rb->width = width;
174 rb->height = height;
175 rb->internalformat = internalformat;
176}
177
178DECLEXPORT(void) STATE_APIENTRY
179crStateGetRenderbufferParameterivEXT(GLenum target, GLenum pname, GLint *params)
180{
181 CRContext *g = GetCurrentContext();
182 CRFramebufferObjectState *fbo = &g->framebufferobject;
183 CRRenderbufferObject *rb = fbo->renderbuffer;
184
185 CRSTATE_FBO_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
186 CRSTATE_FBO_CHECKERR(target!=GL_RENDERBUFFER_EXT, GL_INVALID_ENUM, "invalid target");
187 CRSTATE_FBO_CHECKERR(rb, GL_INVALID_OPERATION, "no bound renderbuffer");
188
189 switch (pname)
190 {
191 case GL_RENDERBUFFER_WIDTH_EXT:
192 *params = rb->width;
193 break;
194 case GL_RENDERBUFFER_HEIGHT_EXT:
195 *params = rb->height;
196 break;
197 case GL_RENDERBUFFER_INTERNAL_FORMAT_EXT:
198 *params = rb->internalformat;
199 break;
200 case GL_RENDERBUFFER_RED_SIZE_EXT:
201 case GL_RENDERBUFFER_GREEN_SIZE_EXT:
202 case GL_RENDERBUFFER_BLUE_SIZE_EXT:
203 case GL_RENDERBUFFER_ALPHA_SIZE_EXT:
204 case GL_RENDERBUFFER_DEPTH_SIZE_EXT:
205 case GL_RENDERBUFFER_STENCIL_SIZE_EXT:
206 CRSTATE_FBO_CHECKERR(GL_TRUE, GL_INVALID_OPERATION, "unimplemented");
207 break;
208 default:
209 CRSTATE_FBO_CHECKERR(GL_TRUE, GL_INVALID_ENUM, "invalid pname");
210 }
211}
212
213static void crStateInitFBOAttachmentPoint(CRFBOAttachmentPoint *fboap)
214{
215 fboap->type = GL_NONE;
216 fboap->name = 0;
217 fboap->level = 0;
218 fboap->face = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
219 fboap->zoffset = 0;
220}
221
222static void crStateInitFrameBuffer(CRFramebufferObject *fbo)
223{
224 int i;
225
226 for (i=0; i<CR_MAX_COLOR_ATTACHMENTS; ++i)
227 crStateInitFBOAttachmentPoint(&fbo->color[i]);
228
229 crStateInitFBOAttachmentPoint(&fbo->depth);
230 crStateInitFBOAttachmentPoint(&fbo->stencil);
231
232 fbo->readbuffer = GL_COLOR_ATTACHMENT0_EXT;
233 fbo->drawbuffer[0] = GL_COLOR_ATTACHMENT0_EXT;
234}
235
236static GLboolean crStateGetFBOAttachmentPoint(CRFramebufferObject *fb, GLenum attachment, CRFBOAttachmentPoint **ap)
237{
238 switch (attachment)
239 {
240 case GL_DEPTH_ATTACHMENT_EXT:
241 *ap = &fb->depth;
242 break;
243 case GL_STENCIL_ATTACHMENT_EXT:
244 *ap = &fb->stencil;
245 break;
246 default:
247 if (attachment>=GL_COLOR_ATTACHMENT0_EXT && attachment<=GL_COLOR_ATTACHMENT15_EXT)
248 {
249 *ap = &fb->color[attachment-GL_COLOR_ATTACHMENT0_EXT];
250 }
251 else return GL_FALSE;
252 }
253
254 return GL_TRUE;
255}
256
257DECLEXPORT(void) STATE_APIENTRY
258crStateBindFramebufferEXT(GLenum target, GLuint framebuffer)
259{
260 CRContext *g = GetCurrentContext();
261 CRFramebufferObjectState *fbo = &g->framebufferobject;
262
263 CRSTATE_FBO_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
264 CRSTATE_FBO_CHECKERR(target!=GL_FRAMEBUFFER_EXT, GL_INVALID_ENUM, "invalid target");
265
266 if (framebuffer)
267 {
268 fbo->framebuffer = (CRFramebufferObject*) crHashtableSearch(fbo->framebuffers, framebuffer);
269 if (!fbo->framebuffer)
270 {
271 fbo->framebuffer = (CRFramebufferObject*) crCalloc(sizeof(CRFramebufferObject));
272 CRSTATE_FBO_CHECKERR(!fbo->framebuffer, GL_OUT_OF_MEMORY, "glBindFramebufferEXT");
273 fbo->framebuffer->id = framebuffer;
274 crStateInitFrameBuffer(fbo->framebuffer);
275 crHashtableAdd(fbo->framebuffers, framebuffer, fbo->framebuffer);
276 }
277 }
278 else fbo->framebuffer = NULL;
279}
280
281DECLEXPORT(void) STATE_APIENTRY
282crStateDeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers)
283{
284 CRContext *g = GetCurrentContext();
285 CRFramebufferObjectState *fbo = &g->framebufferobject;
286 int i;
287
288 CRSTATE_FBO_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
289 CRSTATE_FBO_CHECKERR(n<0, GL_INVALID_OPERATION, "n<0");
290
291 for (i = 0; i < n; i++)
292 {
293 if (framebuffers[i])
294 {
295 CRFramebufferObject *fb;
296 fb = (CRFramebufferObject*) crHashtableSearch(fbo->framebuffers, framebuffers[i]);
297 if (fb)
298 {
299 if (fbo->framebuffer==fb)
300 {
301 fbo->framebuffer = NULL;
302 }
303 crHashtableDelete(fbo->framebuffers, framebuffers[i], crFree);
304 }
305 }
306 }
307}
308
309/*@todo: move this function somewhere else*/
310/*return floor of base 2 log of x. log(0)==0*/
311unsigned int crLog2Floor(unsigned int x)
312{
313 x |= (x >> 1);
314 x |= (x >> 2);
315 x |= (x >> 4);
316 x |= (x >> 8);
317 x |= (x >> 16);
318 x -= ((x >> 1) & 0x55555555);
319 x = (((x >> 2) & 0x33333333) + (x & 0x33333333));
320 x = (((x >> 4) + x) & 0x0f0f0f0f);
321 x += (x >> 8);
322 x += (x >> 16);
323 return (x & 0x0000003f) - 1;
324}
325
326static void crStateFramebufferTextureCheck(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level,
327 GLboolean *failed, CRFBOAttachmentPoint **ap, CRTextureObj **tobj)
328{
329 CRContext *g = GetCurrentContext();
330 CRFramebufferObjectState *fbo = &g->framebufferobject;
331 GLuint maxtexsizelog2;
332
333 *failed = GL_TRUE;
334
335 CRSTATE_FBO_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
336 CRSTATE_FBO_CHECKERR(target!=GL_FRAMEBUFFER_EXT, GL_INVALID_ENUM, "invalid target");
337 CRSTATE_FBO_CHECKERR(!fbo->framebuffer, GL_INVALID_OPERATION, "no fbo bound");
338 CRSTATE_FBO_CHECKERR(!crStateGetFBOAttachmentPoint(fbo->framebuffer, attachment, ap), GL_INVALID_ENUM, "invalid attachment");
339
340 if (!texture)
341 {
342 *failed = GL_FALSE;
343 return;
344 }
345
346 switch (textarget)
347 {
348 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
349 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
350 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
351 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
352 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
353 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
354 maxtexsizelog2 = crLog2Floor(g->limits.maxCubeMapTextureSize);
355 *tobj = crStateTextureGet(GL_TEXTURE_CUBE_MAP_ARB, texture);
356 break;
357 case GL_TEXTURE_RECTANGLE_ARB:
358 maxtexsizelog2 = 0;
359 *tobj = crStateTextureGet(textarget, texture);
360 break;
361 case GL_TEXTURE_3D:
362 maxtexsizelog2 = crLog2Floor(g->limits.max3DTextureSize);
363 *tobj = crStateTextureGet(textarget, texture);
364 break;
365 case GL_TEXTURE_2D:
366 case GL_TEXTURE_1D:
367 maxtexsizelog2 = crLog2Floor(g->limits.maxTextureSize);
368 *tobj = crStateTextureGet(textarget, texture);
369 break;
370 default:
371 CRSTATE_FBO_CHECKERR(GL_TRUE, GL_INVALID_OPERATION, "invalid textarget");
372 }
373
374 CRSTATE_FBO_CHECKERR(!*tobj, GL_INVALID_OPERATION, "invalid textarget/texture combo");
375
376 if (GL_TEXTURE_RECTANGLE_ARB==textarget)
377 {
378 CRSTATE_FBO_CHECKERR(level!=0, GL_INVALID_VALUE, "non zero mipmap level");
379 }
380
381 CRSTATE_FBO_CHECKERR(level<0, GL_INVALID_VALUE, "level<0");
382 CRSTATE_FBO_CHECKERR(level>maxtexsizelog2, GL_INVALID_VALUE, "level too big");
383
384 *failed = GL_FALSE;
385}
386
387DECLEXPORT(void) STATE_APIENTRY
388crStateFramebufferTexture1DEXT(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
389{
390 CRContext *g = GetCurrentContext();
391 CRFramebufferObjectState *fbo = &g->framebufferobject;
392 CRFBOAttachmentPoint *ap;
393 CRTextureObj *tobj;
394 GLboolean failed;
395
396 crStateFramebufferTextureCheck(target, attachment, textarget, texture, level, &failed, &ap, &tobj);
397 if (failed) return;
398
399 if (!texture)
400 {
401 crStateInitFBOAttachmentPoint(ap);
402 return;
403 }
404
405 CRSTATE_FBO_CHECKERR(textarget!=GL_TEXTURE_1D, GL_INVALID_OPERATION, "textarget");
406
407 crStateInitFBOAttachmentPoint(ap);
408 ap->type = GL_TEXTURE;
409 ap->name = texture;
410 ap->level = level;
411}
412
413DECLEXPORT(void) STATE_APIENTRY
414crStateFramebufferTexture2DEXT(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
415{
416 CRContext *g = GetCurrentContext();
417 CRFramebufferObjectState *fbo = &g->framebufferobject;
418 CRFBOAttachmentPoint *ap;
419 CRTextureObj *tobj;
420 GLboolean failed;
421
422 crStateFramebufferTextureCheck(target, attachment, textarget, texture, level, &failed, &ap, &tobj);
423 if (failed) return;
424
425 if (!texture)
426 {
427 crStateInitFBOAttachmentPoint(ap);
428 return;
429 }
430
431 CRSTATE_FBO_CHECKERR(GL_TEXTURE_1D==textarget || GL_TEXTURE_3D==textarget, GL_INVALID_OPERATION, "textarget");
432
433 crStateInitFBOAttachmentPoint(ap);
434 ap->type = GL_TEXTURE;
435 ap->name = texture;
436 ap->level = level;
437 if (textarget!=GL_TEXTURE_2D && textarget!=GL_TEXTURE_RECTANGLE_ARB)
438 {
439 ap->face = textarget;
440 }
441}
442
443DECLEXPORT(void) STATE_APIENTRY
444crStateFramebufferTexture3DEXT(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset)
445{
446 CRContext *g = GetCurrentContext();
447 CRFramebufferObjectState *fbo = &g->framebufferobject;
448 CRFBOAttachmentPoint *ap;
449 CRTextureObj *tobj;
450 GLboolean failed;
451
452 crStateFramebufferTextureCheck(target, attachment, textarget, texture, level, &failed, &ap, &tobj);
453 if (failed) return;
454
455 if (!texture)
456 {
457 crStateInitFBOAttachmentPoint(ap);
458 return;
459 }
460
461 CRSTATE_FBO_CHECKERR(zoffset>(g->limits.max3DTextureSize-1), GL_INVALID_VALUE, "zoffset too big");
462 CRSTATE_FBO_CHECKERR(textarget!=GL_TEXTURE_3D, GL_INVALID_OPERATION, "textarget");
463
464 crStateInitFBOAttachmentPoint(ap);
465 ap->type = GL_TEXTURE;
466 ap->name = texture;
467 ap->level = level;
468 ap->zoffset = zoffset;
469}
470
471DECLEXPORT(void) STATE_APIENTRY
472crStateFramebufferRenderbufferEXT(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
473{
474 CRContext *g = GetCurrentContext();
475 CRFramebufferObjectState *fbo = &g->framebufferobject;
476 CRFBOAttachmentPoint *ap;
477 CRRenderbufferObject *rb;
478
479 CRSTATE_FBO_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
480 CRSTATE_FBO_CHECKERR(target!=GL_FRAMEBUFFER_EXT, GL_INVALID_ENUM, "invalid target");
481 CRSTATE_FBO_CHECKERR(!fbo->framebuffer, GL_INVALID_OPERATION, "no fbo bound");
482 CRSTATE_FBO_CHECKERR(!crStateGetFBOAttachmentPoint(fbo->framebuffer, attachment, &ap), GL_INVALID_ENUM, "invalid attachment");
483
484 if (!renderbuffer)
485 {
486 crStateInitFBOAttachmentPoint(ap);
487 return;
488 }
489
490 rb = (CRRenderbufferObject*) crHashtableSearch(fbo->renderbuffers, renderbuffer);
491 CRSTATE_FBO_CHECKERR(!rb, GL_INVALID_OPERATION, "rb doesn't exist");
492
493 crStateInitFBOAttachmentPoint(ap);
494 ap->type = GL_RENDERBUFFER_EXT;
495 ap->name = renderbuffer;
496}
497
498DECLEXPORT(void) STATE_APIENTRY
499crStateGetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, GLenum pname, GLint *params)
500{
501 CRContext *g = GetCurrentContext();
502 CRFramebufferObjectState *fbo = &g->framebufferobject;
503 CRFBOAttachmentPoint *ap;
504
505 CRSTATE_FBO_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
506 CRSTATE_FBO_CHECKERR(target!=GL_FRAMEBUFFER_EXT, GL_INVALID_ENUM, "invalid target");
507 CRSTATE_FBO_CHECKERR(!fbo->framebuffer, GL_INVALID_OPERATION, "no fbo bound");
508 CRSTATE_FBO_CHECKERR(!crStateGetFBOAttachmentPoint(fbo->framebuffer, attachment, &ap), GL_INVALID_ENUM, "invalid attachment");
509
510 switch (pname)
511 {
512 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT:
513 *params = ap->type;
514 break;
515 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT:
516 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")
517 *params = ap->name;
518 break;
519 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT:
520 CRSTATE_FBO_CHECKERR(ap->type!=GL_TEXTURE, GL_INVALID_ENUM, "not a texture");
521 *params = ap->level;
522 break;
523 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT:
524 CRSTATE_FBO_CHECKERR(ap->type!=GL_TEXTURE, GL_INVALID_ENUM, "not a texture");
525 *params = ap->face;
526 break;
527 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT:
528 CRSTATE_FBO_CHECKERR(ap->type!=GL_TEXTURE, GL_INVALID_ENUM, "not a texture");
529 *params = ap->zoffset;
530 break;
531 default:
532 CRSTATE_FBO_CHECKERR(GL_TRUE, GL_INVALID_ENUM, "invalid pname");
533 }
534}
535
536DECLEXPORT(void) STATE_APIENTRY
537crStateGenerateMipmapEXT(GLenum target)
538{
539 /*@todo*/
540}
541
542DECLEXPORT(void) STATE_APIENTRY
543crStateFramebufferObjectSwitch(CRContext *from, CRContext *to)
544{
545 if (to->framebufferobject.framebuffer!=from->framebufferobject.framebuffer)
546 {
547 diff_api.BindFramebufferEXT(GL_FRAMEBUFFER_EXT, to->framebufferobject.framebuffer?
548 to->framebufferobject.framebuffer->id:0);
549 }
550}
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