Max 5 API Reference
00001 /* 00002 * Copyright 2001-2005 - Cycling '74 00003 * Derek Gerstmann - derek@cycling74.com 00004 * 00005 * Struct and associated methods for maintaining an offscreen OpenGL 00006 * framebuffer object (fbo) with multiple attached image buffers 00007 * (either textures or renderbuffers). 00008 * 00009 */ 00010 00011 /****************************************************************************/ 00012 00013 #include "jit.gl.fbo.h" 00014 #include "jit.gl.texture.h" 00015 00016 /****************************************************************************/ 00017 00018 t_jit_gl_fbo_attachment *jit_gl_fbo_attachment_new() 00019 { 00020 t_jit_gl_fbo_attachment *x = NULL; 00021 00022 if(x = jit_getbytes(sizeof(t_jit_gl_fbo_attachment))) 00023 { 00024 x->id = 0; 00025 jit_gl_fbo_attachment_reset(x); 00026 } 00027 00028 return x; 00029 } 00030 00031 void jit_gl_fbo_attachment_free(t_jit_gl_fbo_attachment *x) 00032 { 00033 if(x) 00034 { 00035 jit_gl_fbo_attachment_destroy(x); 00036 jit_freebytes(x, sizeof(t_jit_gl_fbo_attachment)); 00037 } 00038 } 00039 00040 t_jit_err jit_gl_fbo_attachment_reset(t_jit_gl_fbo_attachment *x) 00041 { 00042 t_jit_err err = JIT_ERR_NONE; 00043 00044 if(x) 00045 { 00046 x->type = 0; 00047 x->target = 0; 00048 x->miplevel = 0; 00049 x->zslice = 0; 00050 x->id = 0; 00051 } 00052 00053 return err; 00054 } 00055 00056 t_jit_err jit_gl_fbo_attachment_destroy(t_jit_gl_fbo_attachment *x) 00057 { 00058 t_jit_err err = JIT_ERR_NONE; 00059 00060 if(x) 00061 { 00062 err = jit_gl_fbo_attachment_reset(x); 00063 } 00064 00065 return err; 00066 } 00067 00068 /****************************************************************************/ 00069 00070 void *_jit_gl_fbo_class; 00071 00072 00073 t_jit_err jit_gl_fbo_init(void) 00074 { 00075 long attrflags=0; 00076 long ob3d_flags=0; 00077 void *attr; 00078 void *ob3d; 00079 00080 // create class 00081 _jit_gl_fbo_class = jit_class_new("jit_gl_fbo",(method)jit_gl_fbo_new,(method)jit_gl_fbo_free, 00082 sizeof(t_jit_gl_fbo), A_DEFSYM, 0L); 00083 00084 // set up object extension for 3d object, customized with flags 00085 ob3d_flags = JIT_OB3D_HAS_LIGHTS | JIT_OB3D_HAS_CAMERA | JIT_OB3D_IS_RENDERER; 00086 ob3d = jit_ob3d_setup(_jit_gl_fbo_class, calcoffset(t_jit_gl_fbo, ob3d), ob3d_flags); 00087 00088 // add ob3d methods 00089 jit_class_addmethod(_jit_gl_fbo_class, (method)jit_object_register, "register", A_CANT, 0L); 00090 jit_class_addmethod(_jit_gl_fbo_class, (method)jit_gl_fbo_draw, "ob3d_draw", A_CANT, 0L); 00091 jit_class_addmethod(_jit_gl_fbo_class, (method)jit_gl_fbo_dest_changed, "dest_changed", A_CANT, 0L); 00092 jit_class_addmethod(_jit_gl_fbo_class, (method)jit_gl_fbo_dest_closing, "dest_closing", A_CANT, 0L); 00093 00094 //add attributes 00095 attrflags = JIT_ATTR_GET_DEFER_LOW | JIT_ATTR_SET_USURP_LOW; 00096 attr = jit_object_new(_jit_sym_jit_attr_offset_array,"color_attachment",_jit_sym_symbol,JIT_GL_FBO_MAX_COLOR_ATTACHMENTS,attrflags, 00097 (method)0L,(method)jit_gl_fbo_setattr_color_attachment,NULL,calcoffset(t_jit_gl_fbo,color_attachment)); 00098 jit_class_addattr(_jit_gl_fbo_class,attr); 00099 00100 attr = jit_object_new(_jit_sym_jit_attr_offset, "depthtex", _jit_sym_symbol, attrflags, 00101 (method)0L, (method)jit_gl_fbo_attach_depthtex, calcoffset(t_jit_gl_fbo, depthtex)); 00102 jit_class_addattr(_jit_gl_fbo_class, attr); 00103 00104 attr = jit_object_new(_jit_sym_jit_attr_offset, "depth", _jit_sym_long, attrflags, 00105 (method)0L, (method)jit_gl_fbo_attach_depth_image, calcoffset(t_jit_gl_fbo, depth)); 00106 jit_class_addattr(_jit_gl_fbo_class, attr); 00107 00108 attr = jit_object_new(_jit_sym_jit_attr_offset, "stencil", _jit_sym_long, attrflags, 00109 (method)0L, (method)jit_gl_fbo_attach_stencil_image, calcoffset(t_jit_gl_fbo, stencil)); 00110 jit_class_addattr(_jit_gl_fbo_class, attr); 00111 00112 attr = jit_object_new(_jit_sym_jit_attr_offset, "stencil", _jit_sym_long, attrflags, 00113 (method)0L, (method)jit_gl_fbo_attach_stencil_image, calcoffset(t_jit_gl_fbo, stencil)); 00114 jit_class_addattr(_jit_gl_fbo_class, attr); 00115 00116 attrflags = JIT_ATTR_SET_OPAQUE_USER; 00117 00118 attr = jit_object_new(_jit_sym_jit_attr_offset, "attachedcount", _jit_sym_long, attrflags, 00119 (method)0L, (method)0L, calcoffset(t_jit_gl_fbo, attachedcount)); 00120 jit_class_addattr(_jit_gl_fbo_class, attr); 00121 00122 jit_class_register(_jit_gl_fbo_class); 00123 00124 return JIT_ERR_NONE; 00125 } 00126 00127 t_jit_err jit_gl_fbo_setattr_color_attachment(t_jit_gl_fbo *x, void *attr, long argc, t_atom *argv) 00128 { 00129 long i; 00130 t_symbol *name; 00131 t_jit_err err=JIT_ERR_NONE; 00132 00133 if(argc) { 00134 name = jit_atom_getsym(argv); 00135 err = jit_gl_fbo_attach_tex_image(x, name, GL_COLOR_ATTACHMENT0_EXT, x->color_attachment); 00136 } 00137 00138 return err; 00139 } 00140 00141 t_jit_err jit_gl_fbo_attach_depthtex(t_jit_gl_fbo *x, void *attr, long argc, t_atom *argv) 00142 { 00143 t_symbol *name; 00144 t_jit_err err=JIT_ERR_NONE; 00145 00146 if(argc) { 00147 name = jit_atom_getsym(argv); 00148 err = jit_gl_fbo_attach_tex_image(x, name, GL_DEPTH_ATTACHMENT_EXT, &(x->depthtex)); 00149 } 00150 00151 return err; 00152 } 00153 00154 t_jit_gl_fbo * jit_gl_fbo_new(t_symbol * dest_name) 00155 { 00156 GLuint i; 00157 t_jit_gl_fbo *x = NULL; 00158 00159 if (x=(t_jit_gl_fbo *)jit_object_alloc(_jit_gl_fbo_class)) 00160 { 00161 // create and attach ob3d 00162 jit_ob3d_new(x, dest_name); 00163 00164 x->depthtex = _jit_sym_nothing; 00165 x->id = 0; 00166 x->attachedcount = 0; 00167 00168 for(i = 0; i < JIT_GL_FBO_MAX_ATTACHMENTS; i++) { 00169 x->attached[i] = NULL; 00170 x->renderbuffers[i] = NULL; 00171 } 00172 00173 jit_gl_fbo_reset(x); 00174 } 00175 00176 return x; 00177 } 00178 00179 void jit_gl_fbo_free(t_jit_gl_fbo *x) 00180 { 00181 if(x) 00182 { 00183 jit_gl_fbo_destroy(x); 00184 jit_ob3d_free(x); 00185 } 00186 } 00187 00188 t_jit_err jit_gl_fbo_create(t_jit_gl_fbo *x) 00189 { 00190 t_jit_gl_context ctx = NULL; 00191 t_jit_err err; 00192 00193 if(!x) 00194 return JIT_ERR_GENERIC; 00195 00196 // destroy the existing fbo 00197 jit_gl_fbo_destroy(x); 00198 00199 // verify hw support for fbo 00200 err = jit_gl_fbo_verify_support(x); 00201 if(err) return err; 00202 00203 // generate a new fbo 00204 x->id = 0; 00205 glGenFramebuffersEXT(1, &x->id); 00206 00207 // report errors 00208 err = jit_gl_report_error("jit.gl.fbo: error generating framebuffer object!"); 00209 if(err) return err; 00210 00211 return err; 00212 } 00213 00214 t_jit_err jit_gl_fbo_bind(t_jit_gl_fbo *x) 00215 { 00216 long i; 00217 GLuint id; 00218 GLint previous; 00219 t_jit_err err; 00220 00221 if(!x) 00222 return JIT_ERR_INVALID_PTR; 00223 00224 // verify hw support for fbo 00225 err = jit_gl_fbo_verify_support(x); 00226 if(err) return err; 00227 00228 // only bind if current id is different than previous bound framebuffer 00229 glGetIntegerv( GL_FRAMEBUFFER_BINDING_EXT, &previous ); 00230 x->previous = previous; 00231 if (x->id != x->previous) 00232 { 00233 glDisable(GL_TEXTURE_2D); 00234 glDisable(GL_TEXTURE_RECTANGLE_ARB); 00235 00236 // perform bind 00237 id = x->id; 00238 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, id); 00239 00240 // report errors 00241 err = jit_gl_fbo_report_error(x, "jit.gl.fbo: error binding framebuffer to current!"); 00242 if(err) return err; 00243 } 00244 return JIT_ERR_NONE; 00245 } 00246 00247 t_jit_err jit_gl_fbo_unbind(t_jit_gl_fbo *x) 00248 { 00249 t_jit_err err; 00250 t_jit_gl_context ctx = NULL; 00251 00252 if(!x) 00253 return JIT_ERR_INVALID_PTR; 00254 00255 // verify hw support for fbo 00256 err = jit_gl_fbo_verify_support(x); 00257 if(err) return err; 00258 00259 // restore previous framebuffer 00260 if (x->previous != x->id) 00261 { 00262 // perform restore 00263 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, x->previous); 00264 00265 // report errors 00266 err = jit_gl_fbo_report_error(x, "jit.gl.fbo: error restoring framebuffer to previous buffer!"); 00267 if(err) return err; 00268 } 00269 return JIT_ERR_NONE; 00270 } 00271 00272 t_jit_err jit_gl_fbo_disable(t_jit_gl_fbo *x) 00273 { 00274 t_jit_err err; 00275 t_jit_gl_context ctx = NULL; 00276 00277 if(!x) 00278 return JIT_ERR_INVALID_PTR; 00279 00280 // verify hw support for fbo 00281 err = jit_gl_fbo_verify_support(x); 00282 if(err) return err; 00283 00284 // disable all framebuffer usage 00285 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); 00286 00287 // report errors 00288 err = jit_gl_fbo_report_error(x, "jit.gl.fbo: error disabling all framebuffer usage!"); 00289 return err; 00290 } 00291 00292 t_jit_err jit_gl_fbo_draw(t_jit_gl_fbo *x) 00293 { 00294 //nothing yet 00295 return JIT_ERR_NONE; 00296 } 00297 00298 t_jit_err jit_gl_fbo_dest_changed(t_jit_gl_fbo *x) 00299 { 00300 //nothing yet 00301 return JIT_ERR_NONE; 00302 } 00303 00304 t_jit_err jit_gl_fbo_dest_closing(t_jit_gl_fbo *x) 00305 { 00306 //nothing yet 00307 return JIT_ERR_NONE; 00308 } 00309 00310 t_jit_err jit_gl_fbo_attach_tex_image(t_jit_gl_fbo *x, t_symbol *texname, GLenum attachment, t_symbol **attachment_name) 00311 { 00312 long dim[3]; 00313 GLuint id; 00314 long target; 00315 t_jit_err err=JIT_ERR_NONE; 00316 void *o; 00317 long adapt=1; 00318 t_jit_gl_texture *tex = NULL; 00319 00320 if(x && texname) { 00321 o = jit_object_findregistered( texname ); 00322 00323 if(jit_object_classname(o) == gensym("jit_gl_texture")) { 00324 tex = (t_jit_gl_texture *)o; 00325 tex->fbocontext = x; 00326 tex->fboattachment = (unsigned long *)attachment; 00327 adapt = tex->adapt; 00328 tex->adapt = 0; 00329 *attachment_name = texname; 00330 00331 if(x->id <= 0 ) { 00332 err = jit_gl_fbo_create(x); 00333 if(err) goto cleanup; 00334 } 00335 00336 err = jit_gl_fbo_bind(x); 00337 if(err) goto cleanup; 00338 00339 err = (t_jit_err)jit_object_method(o, gensym("begin_capture"), 1 /*JIT_GL_READBACK_MODE_FBO*/); 00340 if(err) goto cleanup; 00341 00342 /* 00343 jit_object_post((t_object *)x,"dim: %d %d %d", tex->dim[0], tex->dim[1], tex->dim[2]); 00344 jit_object_post((t_object *)x,"target: %d", tex->target); 00345 jit_object_post((t_object *)x,"id: %d", tex->bindid); 00346 jit_object_post((t_object *)x,"attachmentname: %s", (*attachment_name)->s_name); 00347 */ 00348 00349 err = jit_gl_fbo_unbind(x); 00350 if(err) goto cleanup; 00351 } 00352 } 00353 00354 cleanup: 00355 00356 if(err) { 00357 *attachment_name = _jit_sym_nothing; 00358 00359 //maybe reset fbo_attachment at location? 00360 //if tex exists and there's an error, clean tha mutha up 00361 if(tex) { 00362 tex->fbocontext = NULL; 00363 tex->fboattachment = GL_NONE; 00364 jit_object_free(tex->readback); 00365 tex->readback = NULL; 00366 tex->adapt = adapt; 00367 } 00368 } 00369 else { 00370 tex->adapt = adapt; 00371 } 00372 00373 return err; 00374 } 00375 00376 t_jit_err jit_gl_fbo_attach_depth_image(t_jit_gl_fbo *x, void *attr, long argc, t_atom *argv) 00377 { 00378 GLint index; 00379 GLint depth; 00380 GLenum depthtype; 00381 long dim[3]; 00382 t_jit_err err; 00383 void *o; 00384 00385 if(argc) { 00386 // get attachment index 00387 index = GL_DEPTH_ATTACHMENT_EXT - GL_COLOR_ATTACHMENT0_EXT; 00388 00389 if(x->attached[index]) { 00390 jit_gl_fbo_detach(x, GL_DEPTH_ATTACHMENT_EXT); 00391 } 00392 00393 depth = jit_atom_getlong(argv); 00394 00395 // create an optional depth buffer 00396 if(depth > 0) 00397 { 00398 if(!x->renderbuffers[index]) 00399 { 00400 // create a new renderbuffer object 00401 x->renderbuffers[index] = jit_gl_renderbuffer_new(); 00402 if(!x->renderbuffers[index]) 00403 return JIT_ERR_INVALID_PTR; 00404 } 00405 00406 switch(depth) 00407 { 00408 case(16): 00409 depthtype = GL_DEPTH_COMPONENT16; 00410 break; 00411 case(24): 00412 depthtype = GL_DEPTH_COMPONENT24; 00413 break; 00414 case(32): 00415 depthtype = GL_DEPTH_COMPONENT32; 00416 break; 00417 default: 00418 depthtype = GL_DEPTH_COMPONENT24; 00419 break; 00420 } 00421 00422 if( o=jit_object_findregistered(x->color_attachment[0]) ) { 00423 jit_attr_getlong_array(o, gensym("dim"), 3, dim); 00424 } 00425 else { 00426 dim[0] = 256; 00427 dim[1] = 256; 00428 dim[2] = 1; 00429 } 00430 00431 // jit_object_post((t_object *)x,"dim: %d %d %d", dim[0], dim[1], dim[2]); 00432 00433 // create the renderbuffer 00434 err = jit_gl_renderbuffer_create(x->renderbuffers[index], depthtype, dim[0], dim[1]); 00435 if(err) return err; 00436 00437 // attach renderbuffer to fbo 00438 err = jit_gl_fbo_attach_renderbuffer(x, GL_DEPTH_ATTACHMENT_EXT, x->renderbuffers[index]->id); 00439 if(err) return err; 00440 } 00441 } 00442 00443 return JIT_ERR_NONE; 00444 } 00445 00446 t_jit_err jit_gl_fbo_attach_stencil_image(t_jit_gl_fbo *x, void *attr, long argc, t_atom *argv) 00447 { 00448 GLint index; 00449 GLint stencil; 00450 00451 if(argc) { 00452 // get attachment index 00453 index = GL_STENCIL_ATTACHMENT_EXT - GL_COLOR_ATTACHMENT0_EXT; 00454 00455 if(x->attached[index]) { 00456 jit_gl_fbo_detach(x, GL_STENCIL_ATTACHMENT_EXT); 00457 } 00458 00459 stencil = jit_atom_getlong(argv); 00460 00461 //have to crete a renderbuffer and attach it 00462 } 00463 00464 return JIT_ERR_NONE; 00465 } 00466 00467 t_jit_err jit_gl_fbo_attach_texture( 00468 t_jit_gl_fbo *x, GLenum attachment, GLenum target, 00469 GLuint id, GLint miplevel, GLint zslice) 00470 { 00471 GLuint attached = 0; 00472 GLuint fboid; 00473 t_jit_err err = JIT_ERR_NONE; 00474 00475 // bind the fbo 00476 //err = jit_gl_fbo_bind(x); 00477 //if(err) return err; 00478 glDisable(GL_TEXTURE_2D); 00479 glDisable(GL_TEXTURE_RECTANGLE_ARB); 00480 00481 // perform bind 00482 fboid = x->id; 00483 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboid); 00484 00485 // check for current attached id via opengl (might be associated with another instance!) 00486 //err = jit_gl_fbo_query_attached_id(x, attachment, &attached); 00487 //if(err) return err; 00488 00489 { 00490 GLint id = 0; 00491 GLint type = 0; 00492 t_jit_err err = JIT_ERR_NONE; 00493 // perform type query 00494 glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER_EXT, attachment, 00495 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT, &type); 00496 00497 if(type != GL_NONE) 00498 { 00499 // perform name query 00500 glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER_EXT, attachment, 00501 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT, &id); 00502 } 00503 00504 attached = id; 00505 } 00506 00507 // attach the texture (right now doesn't check type...could be a renderbuffer 00508 // in which case this test isn't enough)...also need to read spec as it might 00509 // be beneficial to detach previously attached item anyway...in fact, we should notify any other texture 00510 // as it could cause problems 00511 // if( attached != id ) 00512 // { 00513 switch(target) 00514 { 00515 case GL_TEXTURE_1D: 00516 { 00517 glFramebufferTexture1DEXT( GL_FRAMEBUFFER_EXT, attachment, target, id, miplevel ); 00518 break; 00519 } 00520 case GL_TEXTURE_2D: 00521 case GL_TEXTURE_RECTANGLE_ARB: 00522 { 00523 glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, attachment, target, id, miplevel ); 00524 break; 00525 } 00526 case GL_TEXTURE_3D: 00527 { 00528 glFramebufferTexture3DEXT( GL_FRAMEBUFFER_EXT, attachment, target, id, miplevel, zslice ); 00529 break; 00530 } 00531 default: 00532 { 00533 jit_object_error((t_object *)x,"jit.gl.fbo: invalid texture target for framebuffer attachment!"); 00534 err = JIT_ERR_GENERIC; 00535 } 00536 }; 00537 00538 // report fbo errors 00539 err = jit_gl_fbo_report_error(x, "jit.gl.fbo: error attaching texture to framebuffer!"); 00540 00541 // save attachment if successful 00542 if(!err) 00543 { 00544 // get attachment index 00545 GLint index = attachment - GL_COLOR_ATTACHMENT0_EXT; 00546 00547 // create attachment if necessary 00548 if(!x->attached[index]) 00549 x->attached[index] = jit_gl_fbo_attachment_new(); 00550 00551 // reset current attachment 00552 jit_gl_fbo_attachment_reset(x->attached[index]); 00553 00554 // save attachment data 00555 x->attached[index]->id = id; 00556 x->attached[index]->target = target; 00557 x->attached[index]->miplevel = miplevel; 00558 x->attached[index]->zslice = zslice; 00559 x->attached[index]->type = attachment; 00560 x->attachedcount++; 00561 } 00562 // } 00563 00564 // unbind the fbo 00565 jit_gl_fbo_unbind(x); 00566 return err; 00567 } 00568 00569 t_jit_err jit_gl_fbo_attach_renderbuffer(t_jit_gl_fbo *x, GLenum attachment, GLuint id) 00570 { 00571 GLuint attached = 0; 00572 t_jit_err err = JIT_ERR_NONE; 00573 00574 // bind the fbo 00575 err = jit_gl_fbo_bind(x); 00576 if(err) return err; 00577 00578 // check for current attached id via opengl (might be associated with another instance!) 00579 err = jit_gl_fbo_query_attached_id(x, attachment, &attached); 00580 if(err) return err; 00581 00582 // attach the renderbuffer object 00583 if( attached != id ) 00584 { 00585 // perform attachment 00586 glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, attachment, GL_RENDERBUFFER_EXT, id); 00587 00588 // report errors 00589 err = jit_gl_report_error("jit.gl.fbo: error attaching renderbuffer to framebuffer!"); 00590 00591 // save attachment if successful 00592 if(!err) 00593 { 00594 // get attachment index 00595 GLint index = attachment - GL_COLOR_ATTACHMENT0_EXT; 00596 00597 // create attachment if necessary 00598 if(!x->attached[index]) 00599 x->attached[index] = jit_gl_fbo_attachment_new(); 00600 00601 // reset current attachment 00602 jit_gl_fbo_attachment_reset(x->attached[index]); 00603 00604 // save attachment data 00605 x->attached[index]->id = id; 00606 x->attached[index]->type = attachment; 00607 x->attachedcount++; 00608 } 00609 } 00610 00611 // unbind the fbo 00612 jit_gl_fbo_unbind(x); 00613 return err; 00614 } 00615 00616 00617 t_jit_err jit_gl_fbo_detach(t_jit_gl_fbo *x, GLenum attachment) 00618 { 00619 GLuint id; 00620 GLenum type; 00621 GLint index; 00622 t_jit_err err = JIT_ERR_NONE; 00623 00624 // get attachment index 00625 index = attachment - GL_COLOR_ATTACHMENT0_EXT; 00626 00627 // bind the fbo 00628 err = jit_gl_fbo_bind(x); 00629 if(err) return err; 00630 00631 // get attached type 00632 err = jit_gl_fbo_query_attached_type(x, attachment, &type); 00633 if(err) return err; 00634 00635 // detach 00636 switch(type) 00637 { 00638 case GL_NONE: 00639 { 00640 err = JIT_ERR_NONE; 00641 break; 00642 } 00643 case GL_RENDERBUFFER_EXT: 00644 { 00645 // reset renderbuffer attachment using invalid id (zero) 00646 err = jit_gl_fbo_attach_renderbuffer( x, attachment, 0 /* invalid id */); 00647 jit_gl_report_error("jit.gl.fbo: error detaching renderbuffer!"); 00648 break; 00649 } 00650 case GL_TEXTURE: 00651 { 00652 // reset texture attachment using invalid id (zero) 00653 err = jit_gl_fbo_attach_texture( x, attachment, GL_TEXTURE_2D, 0 /* invalid id */, 0, 0 ); 00654 jit_gl_report_error("jit.gl.fbo: error detaching texture!"); 00655 break; 00656 } 00657 default: 00658 { 00659 jit_object_error((t_object *)x,"jit.gl.fbo: invalid resource type for detaching from framebuffer!"); 00660 err = JIT_ERR_GENERIC; 00661 break; 00662 } 00663 }; 00664 00665 // destroy attachment if necessary 00666 if(x->attached[index]) 00667 jit_gl_fbo_attachment_free(x->attached[index]); 00668 x->attached[index] = NULL; 00669 x->attachedcount--; 00670 00671 // unbind the fbo 00672 jit_gl_fbo_unbind(x); 00673 return err; 00674 } 00675 00676 t_jit_err jit_gl_fbo_update_attached(t_jit_gl_fbo *x) 00677 { 00678 GLuint i; 00679 GLenum type; 00680 GLenum attachment; 00681 GLint index; 00682 t_jit_err err = JIT_ERR_NONE; 00683 00684 // verify hw support for fbo 00685 err = jit_gl_fbo_verify_support(x); 00686 if(err) return err; 00687 00688 // free all attachments 00689 for(i = 0; i < JIT_GL_FBO_MAX_ATTACHMENTS; i++) 00690 { 00691 if(x->attached[i]) 00692 { 00693 attachment = x->attached[i]->type; 00694 00695 // get attached type 00696 err = jit_gl_fbo_query_attached_type(x, attachment, &type); 00697 if(err) return err; 00698 00699 switch(type) 00700 { 00701 case GL_RENDERBUFFER_EXT: 00702 { 00703 // reset renderbuffer attachment using invalid id (zero) 00704 err = jit_gl_fbo_attach_renderbuffer( x, attachment, x->attached[i]->id); 00705 jit_gl_report_error("jit.gl.fbo: error updating renderbuffer!"); 00706 break; 00707 } 00708 case GL_TEXTURE: 00709 { 00710 // reset texture attachment using invalid id (zero) 00711 err = jit_gl_fbo_attach_texture( x, attachment, x->attached[i]->target, x->attached[i]->id, x->attached[i]->miplevel, x->attached[i]->zslice ); 00712 jit_gl_report_error("jit.gl.fbo: error updating texture!"); 00713 break; 00714 } 00715 }; 00716 } 00717 00718 // report fbo errors 00719 err = jit_gl_fbo_report_error(x, "jit.gl.fbo: error updating framebuffer attachment!"); 00720 } 00721 00722 return err; 00723 } 00724 00725 t_jit_err jit_gl_fbo_update_attachment(t_jit_gl_fbo *x, GLenum attachment) 00726 { 00727 GLint index; 00728 t_jit_err err = JIT_ERR_NONE; 00729 00730 // verify hw support for fbo 00731 err = jit_gl_fbo_verify_support(x); 00732 if(err) return err; 00733 00734 // get attachment index 00735 index = attachment - GL_COLOR_ATTACHMENT0_EXT; 00736 00737 // draw to attached buffer 00738 if(x->attached[index]) 00739 { 00740 // draw to attached buffer 00741 // glDrawBuffer(x->attached[index]->type); 00742 00743 // report fbo errors 00744 err = jit_gl_fbo_report_error(x, "jit.gl.fbo: error updating framebuffer attachment!"); 00745 if(err) return err; 00746 00747 // report errors 00748 err = jit_gl_report_error("jit.gl.fbo: error updating framebuffer attachment!"); 00749 if(err) return err; 00750 } 00751 00752 return err; 00753 } 00754 00755 t_jit_err jit_gl_fbo_destroy(t_jit_gl_fbo *x) 00756 { 00757 GLuint i; 00758 t_jit_err err = JIT_ERR_NONE; 00759 00760 if(!x) 00761 return JIT_ERR_INVALID_PTR; 00762 00763 // verify hw support for fbo 00764 err = jit_gl_fbo_verify_support(x); 00765 if(err) return err; 00766 00767 // disable fbo 00768 err = jit_gl_fbo_unbind(x); 00769 if(err) return err; 00770 00771 // free all attachments 00772 for(i = 0; i < JIT_GL_FBO_MAX_ATTACHMENTS; i++) 00773 { 00774 if(x->attached[i]) 00775 { 00776 // jit_gl_fbo_detach(x, x->attached[i]->type); 00777 jit_gl_renderbuffer_free(x->renderbuffers[i]); 00778 jit_gl_fbo_attachment_free(x->attached[i]); 00779 } 00780 00781 x->attached[i] = NULL; 00782 } 00783 x->attachedcount = 0; 00784 00785 // destroy the frambuffer object 00786 if(x->id) 00787 { 00788 glDeleteFramebuffersEXT(1, &x->id); 00789 x->id = 0; 00790 00791 // report errors 00792 jit_gl_report_error("jit.gl.fbo: error deleting framebuffer object!"); 00793 } 00794 00795 jit_gl_fbo_reset(x); 00796 return JIT_ERR_NONE; 00797 } 00798 00799 t_jit_err jit_gl_fbo_reset(t_jit_gl_fbo *x) 00800 { 00801 GLint i; 00802 00803 if(!x) 00804 return JIT_ERR_INVALID_PTR; 00805 00806 x->id = 0; 00807 x->previous = 0; 00808 x->attachedcount = 0; 00809 00810 for(i = 0; i < JIT_GL_FBO_MAX_ATTACHMENTS; i++) 00811 { 00812 jit_gl_fbo_attachment_free(x->attached[i]); 00813 x->attached[i] = NULL; 00814 } 00815 00816 return JIT_ERR_NONE; 00817 } 00818 00819 /****************************************************************************/ 00820 00821 t_jit_err jit_gl_fbo_verify_support(t_jit_gl_fbo *x) 00822 { 00823 t_jit_gl_support *support = NULL; 00824 00825 // get opengl support capabilities 00826 support = jit_gl_get_support(); 00827 if(!support || !support->initialized || !support->fbo) 00828 { 00829 jit_object_error((t_object *)x,"jit.gl.fbo: unable to verify hardware support for framebuffer objects!"); 00830 return JIT_ERR_GENERIC; 00831 } 00832 return JIT_ERR_NONE; 00833 } 00834 00835 t_jit_err jit_gl_fbo_report_error(t_jit_gl_fbo *x, const char *prefix) 00836 { 00837 t_jit_err err = JIT_ERR_NONE; 00838 GLenum status; 00839 00840 // verify hw support for fbo 00841 err = jit_gl_fbo_verify_support(x); 00842 if(err) return err; 00843 00844 // perform query 00845 status = (GLenum) glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); 00846 switch(status) 00847 { 00848 case GL_FRAMEBUFFER_COMPLETE_EXT: 00849 { 00850 // no error! 00851 err = JIT_ERR_NONE; 00852 break; 00853 } 00854 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: 00855 { 00856 // no error! 00857 err = JIT_ERR_NONE; 00858 break; 00859 } 00860 case GL_FRAMEBUFFER_UNSUPPORTED_EXT: 00861 { 00862 jit_object_error((t_object *)x,"jit.gl.fbo: unsupported framebuffer format!"); 00863 err = JIT_ERR_GENERIC; 00864 break; 00865 } 00866 case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: 00867 { 00868 jit_object_error((t_object *)x,"jit.gl.fbo: framebuffer incomplete, missing attachments!"); 00869 err = JIT_ERR_GENERIC; 00870 break; 00871 } 00872 case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: 00873 { 00874 jit_object_error((t_object *)x,"jit.gl.fbo: framebuffer incomplete, attachments must have same dimensions!"); 00875 err = JIT_ERR_GENERIC; 00876 break; 00877 } 00878 case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: 00879 { 00880 jit_object_error((t_object *)x,"jit.gl.fbo: framebuffer incomplete, attachments must be the same format!"); 00881 err = JIT_ERR_GENERIC; 00882 break; 00883 } 00884 case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: 00885 { 00886 jit_object_error((t_object *)x,"jit.gl.fbo: framebuffer incomplete, missing draw buffer!"); 00887 err = JIT_ERR_GENERIC; 00888 break; 00889 } 00890 case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: 00891 { 00892 jit_object_error((t_object *)x,"jit.gl.fbo: framebuffer incomplete, missing read buffer!"); 00893 err = JIT_ERR_GENERIC; 00894 break; 00895 } 00896 } 00897 if (err&&prefix) 00898 jit_object_error((t_object *)x,(char *)prefix); 00899 return err; 00900 } 00901 00902 t_jit_err jit_gl_fbo_query_max_color_attachments(t_jit_gl_fbo *x, GLint *value) 00903 { 00904 GLint max = 0; 00905 t_jit_err err = JIT_ERR_NONE; 00906 00907 // verify hw support for fbo 00908 err = jit_gl_fbo_verify_support(x); 00909 if(err) return err; 00910 00911 // perform query 00912 glGetIntegerv( GL_MAX_COLOR_ATTACHMENTS_EXT, &max ); 00913 00914 // report errors 00915 jit_gl_report_error("jit.gl.fbo: error querying framebuffer max color attachments!"); 00916 00917 // save value 00918 *value = max; 00919 return JIT_ERR_NONE; 00920 } 00921 00922 t_jit_err jit_gl_fbo_query_attached_type(t_jit_gl_fbo *x, GLenum attachment, GLenum *value ) 00923 { 00924 GLint type = 0; 00925 t_jit_err err = JIT_ERR_NONE; 00926 00927 // bind fbo 00928 err = jit_gl_fbo_bind(x); 00929 if(err) return err; 00930 00931 // perform query 00932 glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER_EXT, attachment, 00933 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT, &type); 00934 // unbind fbo 00935 err = jit_gl_fbo_unbind(x); 00936 if(err) return err; 00937 00938 // save value 00939 *value = (GLenum)type; 00940 return err; 00941 } 00942 00943 t_jit_err jit_gl_fbo_query_attached_id(t_jit_gl_fbo *x, GLenum attachment, GLuint *value ) 00944 { 00945 GLint id = 0; 00946 GLint type = 0; 00947 t_jit_err err = JIT_ERR_NONE; 00948 00949 // bind fbo 00950 err = jit_gl_fbo_bind(x); 00951 if(err) return err; 00952 00953 // perform type query 00954 glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER_EXT, attachment, 00955 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT, &type); 00956 00957 if(type != GL_NONE) 00958 { 00959 // perform name query 00960 glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER_EXT, attachment, 00961 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT, &id); 00962 } 00963 00964 // report errors 00965 err = jit_gl_report_error("jit.gl.fbo: error querying framebuffer attachment id!"); 00966 00967 // unbind fbo 00968 err = jit_gl_fbo_unbind(x); 00969 if(err) return err; 00970 00971 // save value 00972 *value = (GLuint)id; 00973 return err; 00974 } 00975 00976 t_jit_err jit_gl_fbo_query_attached_miplevel(t_jit_gl_fbo *x, GLenum attachment, GLint *value ) 00977 { 00978 GLint level = 0; 00979 t_jit_err err = JIT_ERR_NONE; 00980 00981 // bind fbo 00982 err = jit_gl_fbo_bind(x); 00983 if(err) return err; 00984 00985 // perform query 00986 glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER_EXT, attachment, 00987 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT, &level); 00988 // report errors 00989 jit_gl_report_error("jit.gl.fbo: error querying framebuffer attachment mipmap level!"); 00990 00991 // unbind fbo 00992 err = jit_gl_fbo_unbind(x); 00993 if(err) return err; 00994 00995 // save value 00996 *value = level; 00997 return err; 00998 } 00999 01000 t_jit_err jit_gl_fbo_query_attached_zslice(t_jit_gl_fbo *x, GLenum attachment, GLint *value ) 01001 { 01002 GLint slice = 0; 01003 t_jit_err err = JIT_ERR_NONE; 01004 01005 // bind fbo 01006 err = jit_gl_fbo_bind(x); 01007 if(err) return err; 01008 01009 // perfom query 01010 glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER_EXT, attachment, 01011 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT, &slice); 01012 01013 // report errors 01014 jit_gl_report_error("jit.gl.fbo: error querying framebuffer attachment z-slice!"); 01015 01016 // unbind fbo 01017 err = jit_gl_fbo_unbind(x); 01018 if(err) return err; 01019 01020 // save value 01021 *value = slice; 01022 return err; 01023 }
Copyright © 2008, Cycling '74