Max 5 API Reference
00001 /* 00002 * Copyright 2001-2005 - Cycling '74 00003 * Derek Gerstmann - derek@cycling74.com 00004 * 00005 * Struct and associated methods for an offscreen framebuffer object 00006 * capable of writing raster information into another buffer object, 00007 * either textures or renderbuffers. 00008 */ 00009 00010 #include "jit.gl.readback.h" 00011 #include "jit.gl.readback.fbo.h" 00012 #include "jit.gl.readback.pbuffer.h" 00013 #include "jit.gl.texture.h" 00014 #include "jit.gl.pixelformat.h" 00015 #include "jit.gl.fbo.h" 00016 00017 //****************************************************************************** 00018 00019 void *_jit_gl_readback_class; 00020 00021 t_symbol *ps_jit_gl_readback_fbo; 00022 t_symbol *ps_jit_gl_readback_rtt; 00023 t_symbol *ps_jit_gl_readback_ctt; 00024 00025 //****************************************************************************** 00026 00027 void jit_gl_readback_init() 00028 { 00029 long attrflags=0; 00030 void *attr; 00031 00032 jit_gl_fbo_init(); //should eventually move to kernel initialization 00033 00034 // create class 00035 _jit_gl_readback_class = jit_class_new("jit_gl_readback",(method)jit_gl_readback_new,(method)jit_gl_readback_free, 00036 sizeof(t_jit_gl_readback), A_DEFSYM, 0L); 00037 00038 ps_jit_gl_readback_fbo = gensym("fbo"); 00039 ps_jit_gl_readback_rtt = gensym("rtt"); 00040 ps_jit_gl_readback_ctt = gensym("ctt"); 00041 00042 jit_class_register(_jit_gl_readback_class); 00043 } 00044 00045 t_jit_gl_readback *jit_gl_readback_new() 00046 { 00047 t_jit_gl_readback *x = NULL; 00048 00049 if(x=(t_jit_gl_readback *)jit_object_alloc(_jit_gl_readback_class)) 00050 { 00051 x->mode = -1; 00052 x->fbo = NULL; 00053 x->matrix = NULL; 00054 x->pbuffer = NULL; 00055 x->depthbuffer = NULL; 00056 x->stencilbuffer = NULL; 00057 jit_gl_readback_reset(x); 00058 x->ownsfbo = 0; 00059 x->attachment = GL_NONE; 00060 } 00061 00062 return x; 00063 } 00064 00065 void jit_gl_readback_free(t_jit_gl_readback *x) 00066 { 00067 if(x) 00068 { 00069 jit_gl_readback_destroy(x); 00070 } 00071 } 00072 00073 //****************************************************************************** 00074 00075 t_jit_err jit_gl_readback_create( 00076 t_jit_gl_readback *x, long mode, GLint width, GLint height, GLint depth, GLint stencil) 00077 { 00078 t_jit_err err = JIT_ERR_NONE; 00079 00080 if(!x) 00081 return JIT_ERR_INVALID_PTR; 00082 00083 // handle vendor specific limitations 00084 if(mode == JIT_GL_READBACK_MODE_FBO) 00085 { 00086 /*char *vendor = (char *) glGetString(GL_VENDOR); 00087 char *version = (char *) glGetString(GL_VERSION); 00088 00089 if (strstr(vendor, "ATI Technologies")) 00090 { 00091 // ATI only seems to support 16bit depth 00092 if(depth) 00093 depth = 16; 00094 } 00095 00096 if (strstr(vendor, "NVIDIA")) 00097 { 00098 // NVIDIA only seems to support 24bit depth 00099 if(depth) 00100 depth = 24; 00101 }*/ 00102 } 00103 00104 if( x->mode == mode && 00105 x->width == width && 00106 x->height == height && 00107 x->depth == depth && 00108 x->stencil == stencil ) 00109 { 00110 // nothing todo! 00111 return JIT_ERR_NONE; 00112 } 00113 00114 // destroy current readback 00115 jit_gl_readback_destroy(x); 00116 00117 // use either fbo or pbuffer as destination 00118 switch(mode) 00119 { 00120 case(JIT_GL_READBACK_MODE_FBO): 00121 { 00122 err = jit_gl_readback_create_fbo(x, mode, width, height, depth, stencil); 00123 break; 00124 } 00125 case(JIT_GL_READBACK_MODE_PBUFFER_CTT): 00126 case(JIT_GL_READBACK_MODE_PBUFFER_RTT): 00127 { 00128 err = jit_gl_readback_create_pbuffer(x, mode, width, height, depth, stencil); 00129 break; 00130 } 00131 default: 00132 { 00133 jit_object_error((t_object *)x,"jit.gl.readback: unable to create readback object: mode invalid!"); 00134 err = JIT_ERR_GENERIC; 00135 break; 00136 } 00137 }; 00138 00139 if(!err) 00140 { 00141 x->mode = mode; 00142 x->width = width; 00143 x->height = height; 00144 x->depth = depth; 00145 x->stencil = stencil; 00146 } 00147 00148 return err; 00149 } 00150 00151 t_jit_err jit_gl_readback_create_with_fbo(t_jit_gl_readback *x, long mode, GLint width, GLint height, void *fbocontext, GLenum attachment) 00152 { 00153 GLenum type; 00154 t_jit_gl_support *support = NULL; 00155 00156 //reinit readback mechanism 00157 jit_gl_readback_destroy(x); 00158 00159 //verify fbocontext is valid 00160 if(jit_object_classname(fbocontext) != gensym("jit_gl_fbo")) { 00161 jit_object_error((t_object *)x,"jit.gl.readback: texture's fbocontext is invalid!"); 00162 return JIT_ERR_INVALID_OBJECT; 00163 } 00164 00165 //setup readback struct to sync with FBO attachment point 00166 x->mode = mode; 00167 x->width = width; 00168 x->height = height; 00169 x->fbo = (t_jit_gl_fbo *)fbocontext; 00170 x->ownsfbo = 0; 00171 x->attachment = attachment; 00172 00173 if(attachment == GL_DEPTH_ATTACHMENT_EXT) { 00174 // get opengl support capabilities 00175 support = jit_gl_get_support(); 00176 if(!support || !support->initialized) 00177 { 00178 jit_object_error((t_object *)x,"jit.gl.texture: unable to setup readback mechanism: opengl support uninitialized!"); 00179 return JIT_ERR_GENERIC; 00180 } 00181 00182 x->depth = support->depth_bits; 00183 } 00184 else if(attachment == GL_STENCIL_ATTACHMENT_EXT){ 00185 jit_object_error((t_object *)x,"jit.gl.readback: stencil is invalid FBO attachment point for textures!"); 00186 return JIT_ERR_GENERIC; 00187 } 00188 else if(attachment > GL_STENCIL_ATTACHMENT_EXT) { 00189 jit_object_error((t_object *)x,"jit.gl.readback: invalid FBO attachment point!"); 00190 return JIT_ERR_GENERIC; 00191 } 00192 00193 return JIT_ERR_NONE; 00194 } 00195 00196 t_jit_err jit_gl_readback_attach_texture( 00197 t_jit_gl_readback *x, GLenum attachment, t_jit_gl_texture *texture, GLint miplevel, GLint zslice) 00198 { 00199 t_jit_err err = JIT_ERR_NONE; 00200 GLuint id; 00201 00202 // use either fbo or pbuffer as destination 00203 switch(x->mode) 00204 { 00205 case(JIT_GL_READBACK_MODE_FBO): 00206 { 00207 jit_gl_texture_destroy_data(texture); 00208 err = jit_gl_texture_bind(texture, 0, 0, 0); 00209 if(err) return err; 00210 00211 err = jit_gl_texture_unbind(texture, 0, 0, 0); 00212 if(err) return err; 00213 00214 err = jit_gl_readback_attach_texture_fbo(x, attachment, texture, miplevel, zslice); 00215 break; 00216 } 00217 case(JIT_GL_READBACK_MODE_PBUFFER_CTT): 00218 case(JIT_GL_READBACK_MODE_PBUFFER_RTT): 00219 { 00220 err = jit_gl_readback_attach_texture_pbuffer(x, attachment, texture, miplevel, zslice); 00221 break; 00222 } 00223 }; 00224 00225 return err; 00226 } 00227 00228 t_jit_err jit_gl_readback_detach_texture(t_jit_gl_readback *x, GLenum attachment) 00229 { 00230 t_jit_err err = JIT_ERR_NONE; 00231 00232 // use either fbo or pbuffer as destination 00233 switch(x->mode) 00234 { 00235 case(JIT_GL_READBACK_MODE_FBO): 00236 { 00237 err = jit_gl_readback_detach_texture_fbo(x, attachment); 00238 break; 00239 } 00240 case(JIT_GL_READBACK_MODE_PBUFFER_CTT): 00241 case(JIT_GL_READBACK_MODE_PBUFFER_RTT): 00242 { 00243 err = jit_gl_readback_detach_texture_pbuffer(x, attachment); 00244 break; 00245 } 00246 }; 00247 00248 return err; 00249 } 00250 00251 t_jit_err jit_gl_readback_bind(t_jit_gl_readback *x) 00252 { 00253 t_jit_err err = JIT_ERR_NONE; 00254 00255 // use either fbo or pbuffer as destination 00256 switch(x->mode) 00257 { 00258 case(JIT_GL_READBACK_MODE_FBO): 00259 { 00260 err = jit_gl_readback_bind_fbo(x); 00261 jit_gl_fbo_report_error(x->fbo, "jit.gl.readback: error binding framebuffer object!"); 00262 jit_gl_report_error("jit.gl.readback: error binding framebuffer object!"); 00263 break; 00264 } 00265 case(JIT_GL_READBACK_MODE_PBUFFER_CTT): 00266 case(JIT_GL_READBACK_MODE_PBUFFER_RTT): 00267 { 00268 err = jit_gl_readback_bind_pbuffer(x); 00269 jit_gl_report_error("jit.gl.readback: error binding pbuffer!"); 00270 break; 00271 } 00272 default: 00273 { 00274 jit_object_error((t_object *)x,"jit.gl.readback: invalid readback mode!"); 00275 break; 00276 } 00277 }; 00278 return err; 00279 } 00280 00281 t_jit_err jit_gl_readback_unbind(t_jit_gl_readback *x) 00282 { 00283 t_jit_err err = JIT_ERR_NONE; 00284 00285 // use either fbo or pbuffer as destination 00286 switch(x->mode) 00287 { 00288 case(JIT_GL_READBACK_MODE_FBO): 00289 { 00290 err = jit_gl_readback_unbind_fbo(x); 00291 break; 00292 } 00293 case(JIT_GL_READBACK_MODE_PBUFFER_CTT): 00294 case(JIT_GL_READBACK_MODE_PBUFFER_RTT): 00295 { 00296 err = jit_gl_readback_unbind_pbuffer(x); 00297 break; 00298 } 00299 default: 00300 { 00301 jit_object_error((t_object *)x,"jit.gl.readback: unable to create readback object: mode invalid!"); 00302 err = JIT_ERR_GENERIC; 00303 break; 00304 } 00305 }; 00306 00307 return err; 00308 } 00309 00310 t_jit_err jit_gl_readback_bind_attachment(t_jit_gl_readback *x, long attachment) 00311 { 00312 t_jit_err err = JIT_ERR_NONE; 00313 00314 // use either fbo or pbuffer as destination 00315 switch(x->mode) 00316 { 00317 case(JIT_GL_READBACK_MODE_FBO): 00318 { 00319 // nothing to do for FBO 00320 return JIT_ERR_NONE; 00321 } 00322 case(JIT_GL_READBACK_MODE_PBUFFER_CTT): 00323 case(JIT_GL_READBACK_MODE_PBUFFER_RTT): 00324 { 00325 return jit_gl_pbuffer_bind_texture(x->pbuffer); 00326 } 00327 default: 00328 { 00329 jit_object_error((t_object *)x,"jit.gl.readback: unable to unbind attachment: mode invalid!"); 00330 err = JIT_ERR_GENERIC; 00331 break; 00332 } 00333 }; 00334 00335 return err; 00336 } 00337 00338 t_jit_err jit_gl_readback_unbind_attachment(t_jit_gl_readback *x, long attachment) 00339 { 00340 t_jit_err err = JIT_ERR_NONE; 00341 00342 // use either fbo or pbuffer as destination 00343 switch(x->mode) 00344 { 00345 case(JIT_GL_READBACK_MODE_FBO): 00346 { 00347 // nothing to do for FBO 00348 return JIT_ERR_NONE; 00349 } 00350 case(JIT_GL_READBACK_MODE_PBUFFER_CTT): 00351 case(JIT_GL_READBACK_MODE_PBUFFER_RTT): 00352 { 00353 return jit_gl_pbuffer_unbind_texture(x->pbuffer); 00354 } 00355 default: 00356 { 00357 jit_object_error((t_object *)x,"jit.gl.readback: unable to unbind attachment: mode invalid!"); 00358 err = JIT_ERR_GENERIC; 00359 break; 00360 } 00361 }; 00362 00363 return err; 00364 } 00365 00366 t_jit_err jit_gl_readback_update(t_jit_gl_readback *x) 00367 { 00368 t_jit_err err = JIT_ERR_NONE; 00369 00370 // use either fbo or pbuffer as destination 00371 switch(x->mode) 00372 { 00373 case(JIT_GL_READBACK_MODE_FBO): 00374 { 00375 err = jit_gl_readback_update_fbo(x); 00376 break; 00377 } 00378 case(JIT_GL_READBACK_MODE_PBUFFER_CTT): 00379 case(JIT_GL_READBACK_MODE_PBUFFER_RTT): 00380 { 00381 err = jit_gl_readback_update_pbuffer(x); 00382 break; 00383 } 00384 }; 00385 return err; 00386 } 00387 00388 t_jit_err jit_gl_readback_destroy(t_jit_gl_readback *x) 00389 { 00390 t_jit_err err = JIT_ERR_NONE; 00391 00392 // use either fbo or pbuffer as destination 00393 switch(x->mode) 00394 { 00395 case(JIT_GL_READBACK_MODE_FBO): 00396 { 00397 if(x->ownsfbo) 00398 err = jit_gl_readback_destroy_fbo(x); 00399 break; 00400 } 00401 case(JIT_GL_READBACK_MODE_PBUFFER_CTT): 00402 case(JIT_GL_READBACK_MODE_PBUFFER_RTT): 00403 { 00404 err = jit_gl_readback_destroy_pbuffer(x); 00405 break; 00406 } 00407 }; 00408 00409 //delete FBO if owns it, otherwise detach from FBO context 00410 if(x->ownsfbo) { 00411 if(x->fbo) 00412 jit_gl_fbo_free(x->fbo); 00413 } 00414 else { 00415 jit_gl_fbo_detach(x->fbo, x->attachment); 00416 } 00417 x->fbo = NULL; 00418 00419 if(x->pbuffer) 00420 jit_gl_pbuffer_free(x->pbuffer); 00421 x->pbuffer = NULL; 00422 00423 if (x->matrix) 00424 jit_object_free(x->matrix); 00425 x->matrix = NULL; 00426 00427 if(x->depthbuffer) 00428 jit_gl_renderbuffer_free(x->depthbuffer); 00429 x->depthbuffer = NULL; 00430 00431 if(x->stencilbuffer) 00432 jit_gl_renderbuffer_free(x->stencilbuffer); 00433 x->stencilbuffer = NULL; 00434 00435 return err; 00436 } 00437 00438 t_jit_err jit_gl_readback_reset(t_jit_gl_readback *x) 00439 { 00440 t_jit_err err = JIT_ERR_NONE; 00441 00442 // use either fbo or pbuffer as destination 00443 switch(x->mode) 00444 { 00445 case(JIT_GL_READBACK_MODE_FBO): 00446 { 00447 err = jit_gl_readback_reset_fbo(x); 00448 break; 00449 } 00450 case(JIT_GL_READBACK_MODE_PBUFFER_CTT): 00451 case(JIT_GL_READBACK_MODE_PBUFFER_RTT): 00452 { 00453 err = jit_gl_readback_reset_pbuffer(x); 00454 break; 00455 } 00456 }; 00457 00458 x->mode = -1; 00459 x->width = 0; 00460 x->height = 0; 00461 x->depth = 0; 00462 x->stencil = 0; 00463 return err; 00464 } 00465 00466 t_jit_err jit_gl_readback_readpixels(t_jit_gl_readback *x, t_symbol *matrix) 00467 { 00468 char *bp; 00469 GLint drawbuffer; 00470 GLint readbuffer; 00471 GLboolean enabled; 00472 long i = 0; 00473 long ix = 0, iy = 0; 00474 long width = 0, height = 0; 00475 long usefloat = 0; 00476 00477 GLenum internal, format, type; 00478 t_symbol *colormode; 00479 t_jit_object *m; 00480 t_jit_matrix_info info; 00481 t_jit_gl_context ctx = NULL; 00482 t_jit_err err; 00483 00484 if(!x) 00485 return JIT_ERR_INVALID_PTR; 00486 00487 ctx = jit_gl_get_context(); 00488 if(!ctx) 00489 return JIT_ERR_GENERIC; 00490 00491 // find the registered matrix object 00492 if (m = jit_object_findregistered(matrix)) 00493 { 00494 if (!jit_object_method(m, _jit_sym_class_jit_matrix)) 00495 { 00496 jit_object_error((t_object *)x,"jit.gl.readback:: unable to find matrix %s", matrix); 00497 return JIT_ERR_GENERIC; 00498 } 00499 } 00500 else 00501 { 00502 return JIT_ERR_GENERIC; 00503 } 00504 00505 // get the matrix info and data pointer 00506 jit_object_method(m,_jit_sym_getinfo,&info); 00507 jit_object_method(m,_jit_sym_getdata,&bp); 00508 00509 // skip invalid data 00510 if(!bp) 00511 return JIT_ERR_INVALID_PTR; 00512 00513 // get the dimensions and datatype 00514 width = info.dim[0]; 00515 height = info.dim[1]; 00516 usefloat = (info.type == _jit_sym_float32); 00517 00518 // hack for 16 byte aligned data, not a valid byte alignment for gl 00519 if (width == info.dim[0]) 00520 width = info.dimstride[1] / info.dimstride[0]; 00521 00522 // detemine colormode from planecount 00523 switch(info.planecount) 00524 { 00525 case 1: 00526 colormode = ps_jit_gl_colormode_luminance; 00527 break; 00528 case 2: 00529 colormode = ps_jit_gl_colormode_lumalpha; 00530 break; 00531 case 3: 00532 colormode = ps_jit_gl_colormode_rgb; 00533 break; 00534 case 4: 00535 colormode = ps_jit_gl_colormode_argb; 00536 default: 00537 break; 00538 }; 00539 00540 // choose the internal format 00541 err = jit_gl_texture_choose_internal_format(colormode, info.type, gensym("static"), &internal, &format, &type, 0); 00542 if(err) return err; 00543 00544 glGetIntegerv(GL_DRAW_BUFFER, &drawbuffer); 00545 glGetIntegerv(GL_READ_BUFFER, &readbuffer); 00546 00547 if(x->mode == JIT_GL_READBACK_MODE_FBO) 00548 { 00549 glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); 00550 } 00551 else 00552 { 00553 glReadBuffer(drawbuffer); 00554 } 00555 00556 glPixelStorei(GL_PACK_ROW_LENGTH, (info.dimstride[1] / info.dimstride[0])); 00557 glPixelStorei(GL_PACK_ALIGNMENT, 8); 00558 00559 // perform the readback 00560 glReadPixels(ix, iy, width, height, format, type, bp); 00561 00562 // restore pixel store 00563 glPixelStorei(GL_PACK_ROW_LENGTH, 0); 00564 glPixelStorei(GL_PACK_ALIGNMENT, 1); 00565 glReadBuffer(readbuffer); 00566 00567 return JIT_ERR_NONE; 00568 }
Copyright © 2008, Cycling '74