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 OpenGL 00006 * pbuffer (offscreen drawable). 00007 * 00008 */ 00009 00010 /****************************************************************************/ 00011 00012 #include "jit.gl.pbuffer.h" 00013 #include "jit.gl.texture.h" 00014 #include "jit.gl.pixelformat.h" 00015 00016 #ifdef MAC_VERSION 00017 GDHandle jit_gl_context_getdevice(t_jit_gl_context ctx); 00018 #endif 00019 00020 /****************************************************************************/ 00021 00022 t_jit_err jit_gl_pbuffer_create_attributes( 00023 t_jit_gl_pbuffer *x, t_jit_gl_pixelformat *pixelformat, 00024 GLint **attributes, GLuint *acount); 00025 00026 /****************************************************************************/ 00027 00028 t_jit_gl_pbuffer *jit_gl_pbuffer_new() 00029 { 00030 t_jit_gl_pbuffer *x = NULL; 00031 00032 if(x = jit_getbytes(sizeof(t_jit_gl_pbuffer))) 00033 { 00034 jit_gl_pbuffer_reset(x); 00035 } 00036 00037 return x; 00038 } 00039 00040 void jit_gl_pbuffer_free(t_jit_gl_pbuffer *x) 00041 { 00042 if(x) 00043 { 00044 jit_gl_pbuffer_destroy(x); 00045 jit_freebytes(x, sizeof(t_jit_gl_pbuffer)); 00046 } 00047 } 00048 00049 t_jit_err jit_gl_pbuffer_create( 00050 t_jit_gl_pbuffer *x, t_symbol *colormode, t_symbol *datatype, long mode, long width, long height, 00051 long target, long internal, long mipmap, long buffer, 00052 long share_lists, long copy_context, t_jit_gl_pixelformat *pixelformat) 00053 { 00054 t_jit_gl_native_pixelformat pfnative = NULL; 00055 t_jit_gl_native_drawable device = NULL; 00056 t_jit_gl_native_context context = NULL; 00057 t_jit_gl_native_pbuffer pbuffer = NULL; 00058 t_jit_gl_context ctx = NULL; 00059 GLenum glinternal, glformat, gltype; 00060 GLuint pfcount = 0; 00061 GLint *attributes = NULL; 00062 GLuint acount = 0; 00063 GLint pf = 0; 00064 GLint w = 0; 00065 GLint h = 0; 00066 t_jit_err err; 00067 00068 if(!x) 00069 return JIT_ERR_GENERIC; 00070 00071 // destroy the existing pbuffer 00072 jit_gl_pbuffer_destroy(x); 00073 00074 // get the current opengl rendering context 00075 ctx = jit_gl_get_context(); 00076 if (!ctx) 00077 { 00078 jit_object_error((t_object *)x,"jit.gl.pbuffer: unable to get current render context!"); 00079 return JIT_ERR_GENERIC; 00080 } 00081 00082 // verify system support of pbuffers 00083 if(!ctx->support->pbuffer) 00084 { 00085 jit_object_error((t_object *)x,"jit.gl.pbuffer: hardware does not support pbuffers!"); 00086 return JIT_ERR_GENERIC; 00087 } 00088 00089 if(mode == JIT_GL_PBUFFER_MODE_CTT) 00090 { 00091 err = jit_gl_texture_choose_internal_format( 00092 colormode, datatype, gensym("static"), 00093 &glinternal, &glformat, &gltype, 0); 00094 if(err) 00095 { 00096 jit_object_error((t_object *)x,"jit.gl.pbuffer: unable to find suitable internal format for copy to texture!"); 00097 return JIT_ERR_GENERIC; 00098 } 00099 } 00100 00101 // allocate context 00102 x->current = (t_jit_gl_context) jit_getbytes(sizeof(t_jit_gl_context_struct)); 00103 if (!x->current) 00104 { 00105 jit_object_error((t_object *)x,"jit.gl.pbuffer: unable to create current render context: out of memory!"); 00106 return JIT_ERR_GENERIC; 00107 } 00108 00109 // allocate 00110 x->previous = (t_jit_gl_context) jit_getbytes(sizeof(t_jit_gl_context_struct)); 00111 if (!x->previous) 00112 { 00113 jit_object_error((t_object *)x,"jit.gl.pbuffer: unable to create copy of current render context: out of memory!"); 00114 return JIT_ERR_GENERIC; 00115 } 00116 00117 // make a local copy of current context 00118 *(x->previous) = *(ctx); 00119 *(x->current) = *(ctx); 00120 00121 #ifdef WIN_VERSION 00122 { 00123 // default pixel format attributes 00124 static GLint s_jit_gl_pbuffer_default_attrib[] = 00125 { 00126 WGL_SUPPORT_OPENGL_ARB, TRUE, 00127 WGL_DRAW_TO_PBUFFER_ARB, TRUE, 00128 WGL_BIND_TO_TEXTURE_RGBA_ARB, TRUE, 00129 WGL_RED_BITS_ARB, 8, 00130 WGL_GREEN_BITS_ARB, 8, 00131 WGL_BLUE_BITS_ARB, 8, 00132 WGL_ALPHA_BITS_ARB, 8, 00133 WGL_DEPTH_BITS_ARB, 16, 00134 WGL_DOUBLE_BUFFER_ARB, FALSE, 00135 0, 0 00136 }; 00137 00138 // create a new pixel format 00139 if(pixelformat) 00140 { 00141 // create the native pixelformat 00142 pfnative = jit_gl_pixelformat_create_native(pixelformat, x->previous->drawable); 00143 if(!pfnative) 00144 { 00145 if(pixelformat) 00146 jit_gl_pixelformat_free(pixelformat); 00147 pixelformat = NULL; 00148 00149 jit_gl_report_error("jit.gl.pbuffer: error creating native pixel format"); 00150 jit_object_error((t_object *)x,"jit.gl.pbuffer: unable to get a valid pixel format!"); 00151 return JIT_ERR_GENERIC; 00152 } 00153 } 00154 else 00155 { 00156 // create the native pixelformat 00157 pfnative = jit_gl_pixelformat_create_native_from_attributes(s_jit_gl_pbuffer_default_attrib, x->previous->drawable); 00158 if(!pfnative) 00159 { 00160 jit_gl_report_error("jit.gl.pbuffer: error creating default pixel format"); 00161 jit_object_error((t_object *)x,"jit.gl.pbuffer: unable to get a valid pixel format!"); 00162 return JIT_ERR_GENERIC; 00163 } 00164 } 00165 00166 // create pbuffer attributes 00167 x->mode = mode; 00168 x->target = target; 00169 err = jit_gl_pbuffer_create_attributes(x, pixelformat, &attributes, &acount); 00170 if(err || !attributes || !acount) 00171 { 00172 jit_object_error((t_object *)x,"jit.gl.pbuffer: unable to create pbuffer attributes!"); 00173 return JIT_ERR_GENERIC; 00174 } 00175 00176 // create the pbuffer 00177 x->native = wglCreatePbufferARB(x->previous->drawable, *pfnative, width, height, attributes); 00178 jit_freebytes(attributes, acount * sizeof(GLint)); 00179 attributes = NULL; acount = 0; 00180 00181 // keep trying different float targets until one is found 00182 while(!x->native && pixelformat->pixel_float) 00183 { 00184 if(pixelformat->pixel_float_target == JIT_GL_PF_PIXEL_FLOAT_ARB) 00185 { 00186 pixelformat->pixel_float_target = JIT_GL_PF_PIXEL_FLOAT_NV; 00187 } 00188 else if(pixelformat->pixel_float_target == JIT_GL_PF_PIXEL_FLOAT_NV) 00189 { 00190 pixelformat->pixel_float_target = JIT_GL_PF_PIXEL_FLOAT_ATI; 00191 } 00192 else 00193 { 00194 pixelformat->pixel_float = 0; 00195 pixelformat->pixel_float_target = 0; 00196 break; 00197 } 00198 00199 // try again 00200 x->native = wglCreatePbufferARB(x->previous->drawable, *pfnative, width, height, attributes); 00201 jit_freebytes(attributes, acount * sizeof(GLint)); 00202 attributes = NULL; acount = 0; 00203 } 00204 00205 if (!x->native) 00206 { 00207 jit_gl_report_error("jit.gl.pbuffer: error creating pbuffer"); 00208 jit_object_error((t_object *)x,"jit.gl.pbuffer: unable to create pbuffer!"); 00209 return JIT_ERR_GENERIC; 00210 } 00211 00212 // replace drawable with the pbuffer device context. 00213 x->current->drawable = wglGetPbufferDCARB(x->native); 00214 if ( !x->current->drawable ) 00215 { 00216 jit_gl_report_error("jit.gl.pbuffer: error creating pbuffer device context"); 00217 jit_object_error((t_object *)x,"jit.gl.pbuffer: unable to create pbuffer device context!"); 00218 return JIT_ERR_GENERIC; 00219 } 00220 00221 // copy or create a new gl rendering context for the pbuffer. 00222 if (copy_context && x->previous->context) 00223 { 00224 // use existing 00225 wglCopyContext(x->previous->context, x->current->context, 0); 00226 // x->current->context = x->previous->context; 00227 } 00228 else 00229 { 00230 // create a new context 00231 x->current->context = wglCreateContext( x->current->drawable ); 00232 if ( !x->current->context ) 00233 { 00234 jit_gl_report_error("jit.gl.pbuffer: error creating pbuffer rendering context"); 00235 jit_object_error((t_object *)x,"jit.gl.pbuffer: unable to create pbuffer rendering context!"); 00236 return JIT_ERR_GENERIC; 00237 } 00238 } 00239 00240 // share lists, texture objects, and program objects. 00241 if( share_lists && x->previous->context && x->current->context) 00242 { 00243 if(x->previous->context != x->current->context) 00244 { 00245 if( !wglShareLists(x->previous->context, x->current->context) ) 00246 { 00247 jit_gl_report_error("jit.gl.pbuffer: error sharing existing objects"); 00248 jit_object_error((t_object *)x,"jit.gl.pbuffer: unable to share existing objects!"); 00249 return JIT_ERR_GENERIC; 00250 } 00251 } 00252 } 00253 00254 // determine the actual width and height we were able to create. 00255 wglQueryPbufferARB( x->native, WGL_PBUFFER_WIDTH_ARB, &w ); 00256 wglQueryPbufferARB( x->native, WGL_PBUFFER_HEIGHT_ARB, &h ); 00257 00258 // save info 00259 x->width = w; 00260 x->height = h; 00261 x->type = datatype; 00262 x->mode = mode; 00263 x->target = target; 00264 x->internal = internal; 00265 x->mipmap = mipmap; 00266 x->buffer = buffer; 00267 x->buffertexid = -1; 00268 x->copy_context = copy_context; 00269 x->share_lists = share_lists; 00270 x->pixelformat = x->current->pixelformat = pfnative; 00271 x->bound = FALSE; 00272 00273 // toggle the initialized flag 00274 x->initialized = FALSE; 00275 00276 // enable the previous rendering context 00277 if(!jit_gl_set_context(x->previous)) 00278 { 00279 jit_gl_report_error("jit.gl.pbuffer: error restoring previous context"); 00280 return JIT_ERR_GENERIC; 00281 } 00282 00283 // create a local texture for ctt/rtt 00284 //if(x->mode == JIT_GL_PBUFFER_MODE_CTT) 00285 { 00286 GLuint id; 00287 glGenTextures(1,&id); 00288 x->buffertexid = id; 00289 glBindTexture(x->target, id); 00290 00291 switch(x->target) 00292 { 00293 case GL_TEXTURE_1D: 00294 { 00295 glTexImage1D(x->target, 0, glinternal, x->width, 0, glformat, gltype, NULL); 00296 break; 00297 } 00298 case GL_TEXTURE_2D: 00299 case GL_TEXTURE_RECTANGLE_ARB: // same as EXT 00300 { 00301 glTexImage2D(x->target, 0, glinternal, x->width, x->height, 0, glformat, gltype, NULL); 00302 break; 00303 } 00304 }; 00305 } 00306 00307 return JIT_ERR_NONE; 00308 } 00309 #endif // WIN_VERSION 00310 00311 #ifdef MAC_VERSION 00312 { 00313 // default attributes 00314 static GLint s_jit_gl_pbuffer_default_attrib[] = { AGL_RGBA, AGL_DEPTH_SIZE, 16, AGL_NONE }; 00315 00316 if(copy_context) 00317 { 00318 // use existing pixelformat 00319 pfnative = x->previous->pixelformat; 00320 } 00321 else if(pixelformat) 00322 { 00323 GDHandle dev; 00324 GDHandle *pdev=NULL; 00325 00326 // create a new native pixelformat 00327 if ((share_lists)&&(dev=jit_gl_context_getdevice(x->previous))) 00328 pdev = &dev; 00329 00330 pfnative = jit_gl_pixelformat_create_native(pixelformat,pdev); 00331 } 00332 else 00333 { 00334 // create a default pixelformat 00335 pfnative = aglChoosePixelFormat(NULL, 0, s_jit_gl_pbuffer_default_attrib); 00336 } 00337 00338 if(!pfnative) 00339 { 00340 jit_gl_report_error("jit.gl.pbuffer: error creating pixel format"); 00341 jit_object_error((t_object *)x,"jit.gl.pbuffer: unable to get a valid pixel format!"); 00342 return JIT_ERR_GENERIC; 00343 } 00344 00345 // copy context state 00346 if(share_lists) 00347 { 00348 // create a new clean context 00349 x->current->context = aglCreateContext(pfnative, x->previous->context); 00350 if (!x->current->context) 00351 { 00352 // attempt to fall back on said format (can probably remove this case now, but leaving in for safety's sake) 00353 x->current->context = aglCreateContext(x->previous->pixelformat, x->previous->context); 00354 if (!x->current->context) { 00355 jit_gl_report_error("jit.gl.pbuffer: error creating pbuffer context"); 00356 jit_object_error((t_object *)x,"jit.gl.pbuffer: unable to create pbuffer context!"); 00357 jit_object_error((t_object *)x,"jit.gl.pbuffer: may have more success using jitter glreadback fbo."); 00358 return JIT_ERR_GENERIC; 00359 } else { 00360 pfnative = x->previous->pixelformat; 00361 copy_context = 1; 00362 if((datatype!=_jit_sym_char)&&(datatype!=gensym("auto"))) { 00363 jit_object_post((t_object *)x,"jit.gl.pbuffer: falling back on master context pixelformat with datatype=%s",datatype->s_name); 00364 jit_object_post((t_object *)x,"jit.gl.pbuffer: may have more success using jitter glreadback fbo."); 00365 } 00366 } 00367 } 00368 } 00369 else 00370 { 00371 // create a new clean context 00372 x->current->context = aglCreateContext(pfnative, NULL); 00373 if (!x->current->context) 00374 { 00375 jit_gl_report_error("jit.gl.pbuffer: error creating pbuffer context"); 00376 jit_object_error((t_object *)x,"jit.gl.pbuffer: unable to create pbuffer context!"); 00377 return JIT_ERR_GENERIC; 00378 } 00379 } 00380 00381 // create the pbuffer 00382 if (!aglCreatePBuffer(width, height, target, internal, mipmap, &(x->native))) 00383 { 00384 jit_gl_report_error("jit.gl.pbuffer: error creating pbuffer"); 00385 jit_object_error((t_object *)x,"jit.gl.pbuffer: unable to create pbuffer!"); 00386 return JIT_ERR_GENERIC; 00387 } 00388 jit_gl_report_error("jit.gl.pbuffer: error after creating pbuffer"); 00389 00390 // save info 00391 x->width = width; 00392 x->height = height; 00393 x->mode = mode; 00394 x->type = datatype; 00395 x->target = target; 00396 x->internal = internal; 00397 x->mipmap = mipmap; 00398 x->buffer = buffer; 00399 x->buffertexid = -1; 00400 x->copy_context = copy_context; 00401 x->share_lists = share_lists; 00402 x->pixelformat = pfnative; 00403 x->bound = FALSE; 00404 00405 // toggle the initialized flag 00406 x->initialized = FALSE; 00407 00408 // create a local texture for ctt/rtt 00409 { 00410 GLuint id; 00411 glGenTextures(1,&id); 00412 x->buffertexid = id; 00413 glBindTexture(x->target, id); 00414 00415 if(x->mode == JIT_GL_PBUFFER_MODE_CTT) 00416 { 00417 switch(x->target) 00418 { 00419 case GL_TEXTURE_1D: 00420 { 00421 glTexImage1D(x->target, 0, glinternal, x->width, 0, glformat, gltype, NULL); 00422 break; 00423 } 00424 case GL_TEXTURE_2D: 00425 case GL_TEXTURE_RECTANGLE_ARB: // same as EXT 00426 { 00427 glTexImage2D(x->target, 0, glinternal, x->width, x->height, 0, glformat, gltype, NULL); 00428 break; 00429 } 00430 }; 00431 } 00432 } 00433 00434 jit_gl_report_error("jit.gl.pbuffer: attaching texture"); 00435 00436 return JIT_ERR_NONE; 00437 } 00438 #endif // MAC_VERSION 00439 00440 } 00441 00442 t_jit_err jit_gl_pbuffer_bind(t_jit_gl_pbuffer *x, t_symbol *s, int argc, t_atom *argv) 00443 { 00444 GLint src = -1; 00445 t_jit_err err; 00446 t_jit_gl_context ctx = NULL; 00447 00448 if(!x) 00449 return JIT_ERR_INVALID_PTR; 00450 00451 if(!x->native || !x->current || !x->previous) 00452 { 00453 jit_object_error((t_object *)x,"jit.gl.pbuffer: error binding invalid pbuffer!"); 00454 return JIT_ERR_GENERIC; 00455 } 00456 00457 // make the pbuffers rendering context current. 00458 if(!jit_gl_set_context(x->current)) 00459 { 00460 jit_gl_report_error("jit.gl.pbuffer: error setting pbuffer context"); 00461 jit_object_error((t_object *)x,"jit.gl.pbuffer: unable to set current pbuffer context!"); 00462 } 00463 00464 #ifdef MAC_VERSION 00465 00466 // get the active screen (0 on a single-monitor system) 00467 src = aglGetVirtualScreen(x->previous->context); 00468 err = jit_gl_report_error("jit.gl.pbuffer: error setting target context"); 00469 if(src < 0) 00470 { 00471 jit_object_error((t_object *)x,"jit.gl.pbuffer: unable to set the target context!"); 00472 return JIT_ERR_GENERIC; 00473 } 00474 00475 // set the source 00476 if (x->source != src) 00477 { 00478 // set the pbuffer and source 00479 x->source = src; 00480 if (!aglSetPBuffer(x->current->context, x->native, 0, 0, x->source)) 00481 { 00482 // handle error 00483 x->source = -1; 00484 jit_gl_report_error("jit.gl.pbuffer: error setting active pbuffer"); 00485 jit_object_error((t_object *)x,"jit.gl.pbuffer: unable to activate the pbuffer!"); 00486 return JIT_ERR_GENERIC; 00487 } 00488 jit_gl_report_error("jit.gl.pbuffer: error after setting active pbuffer"); 00489 } 00490 00491 #endif // MAC_VERSION 00492 00493 if (!x->initialized) 00494 { 00495 x->initialized = TRUE; 00496 } 00497 00498 return JIT_ERR_NONE; 00499 } 00500 00501 t_jit_err jit_gl_pbuffer_unbind(t_jit_gl_pbuffer *x, t_symbol *s, int argc, t_atom *argv) 00502 { 00503 t_jit_err err = JIT_ERR_NONE; 00504 t_jit_gl_context ctx = NULL; 00505 00506 if(!x) 00507 return JIT_ERR_INVALID_PTR; 00508 00509 if(!x->native || !x->current || !x->previous) 00510 { 00511 jit_object_error((t_object *)x,"jit.gl.pbuffer: error unbinding invalid pbuffer!"); 00512 return JIT_ERR_GENERIC; 00513 } 00514 00515 if(x->mode == JIT_GL_PBUFFER_MODE_CTT) 00516 { 00517 // texture should be bound and active prior to this call 00518 GLuint id = x->buffertexid; 00519 glBindTexture(x->target, id); 00520 00521 switch(x->target) 00522 { 00523 case GL_TEXTURE_1D: 00524 { 00525 glCopyTexSubImage1D(x->target, 0, 0, 0, 0, x->width); 00526 break; 00527 } 00528 case GL_TEXTURE_2D: 00529 case GL_TEXTURE_RECTANGLE_ARB: // same as EXT 00530 { 00531 glCopyTexSubImage2D(x->target, 0, 0, 0, 0, 0, x->width, x->height); 00532 break; 00533 } 00534 }; 00535 00536 jit_gl_report_error("jit.gl.pbuffer: error updating bound texture"); 00537 } 00538 00539 // debug copy to matrix in patcher 00540 // jit_gl_pbuffer_readpixels(x,gensym("slurp")); 00541 00542 #ifdef MAC_VERSION 00543 00544 // disable drawing to the pbuffer context 00545 if(!aglSetCurrentContext(NULL)) 00546 { 00547 jit_gl_report_error("jit.gl.pbuffer: error clearing context"); 00548 return JIT_ERR_GENERIC; 00549 } 00550 00551 #endif 00552 00553 // enable the previous rendering context 00554 if(!jit_gl_set_context(x->previous)) 00555 { 00556 jit_gl_report_error("jit.gl.pbuffer: error restoring previous context"); 00557 return JIT_ERR_GENERIC; 00558 } 00559 00560 #ifdef MAC_VERSION 00561 // enable the previous render target 00562 if(!jit_gl_set_target(x->previous, x->previous->target, x->previous->targettype)) 00563 { 00564 jit_gl_report_error("jit.gl.pbuffer: error restoring previous target"); 00565 return JIT_ERR_GENERIC; 00566 } 00567 #endif 00568 00569 return JIT_ERR_NONE; 00570 } 00571 00572 t_jit_err jit_gl_pbuffer_bind_texture(t_jit_gl_pbuffer *x) 00573 { 00574 if(!x) 00575 return JIT_ERR_INVALID_PTR; 00576 00577 if(!x->native || !x->current || !x->previous) 00578 { 00579 jit_object_error((t_object *)x,"jit.gl.pbuffer: error binding texture for invalid pbuffer!"); 00580 return JIT_ERR_GENERIC; 00581 } 00582 00583 // render to the binded texture 00584 if (x->mode == JIT_GL_PBUFFER_MODE_RTT && !x->bound) 00585 { 00586 00587 #ifdef WIN_VERSION 00588 if (!wglBindTexImageARB(x->native, x->buffer)) 00589 { 00590 jit_gl_report_error("jit.gl.pbuffer: error binding texture"); 00591 return JIT_ERR_GENERIC; 00592 } 00593 jit_gl_report_error("jit.gl.pbuffer: error after binding texture"); 00594 #endif 00595 #ifdef MAC_VERSION 00596 00597 // grab the current context in which the texture should be used, not necessarily the same as x->previous->context 00598 AGLContext current = aglGetCurrentContext(); 00599 if (!aglTexImagePBuffer(current, x->native, x->buffer)) 00600 { 00601 jit_gl_report_error("jit.gl.pbuffer: error binding texture"); 00602 return JIT_ERR_GENERIC; 00603 } 00604 jit_gl_report_error("jit.gl.pbuffer: error after binding texture"); 00605 #endif 00606 x->bound = TRUE; 00607 } 00608 else if(x->mode == JIT_GL_PBUFFER_MODE_CTT) 00609 { 00610 GLuint id; 00611 id = x->buffertexid; 00612 glEnable(x->target); 00613 // glBindTexture(x->target, id); 00614 } 00615 00616 return JIT_ERR_NONE; 00617 } 00618 00619 t_jit_err jit_gl_pbuffer_unbind_texture(t_jit_gl_pbuffer *x) 00620 { 00621 if(!x) 00622 return JIT_ERR_INVALID_PTR; 00623 00624 if(!x->native || !x->current || !x->previous) 00625 { 00626 jit_object_error((t_object *)x,"jit.gl.pbuffer: error unbinding texture for invalid pbuffer!"); 00627 return JIT_ERR_GENERIC; 00628 } 00629 00630 // release render to texture related resources 00631 if (x->mode == JIT_GL_PBUFFER_MODE_RTT) 00632 { 00633 // release the pbuffer from the render texture object 00634 if (x->bound) 00635 { 00636 #ifdef WIN_VERSION 00637 if (!wglReleaseTexImageARB(x->native, x->buffer)) 00638 { 00639 jit_gl_report_error("jit.gl.pbuffer: error releasing bound texture"); 00640 return JIT_ERR_GENERIC; 00641 } 00642 #endif 00643 x->bound = FALSE; 00644 } 00645 } 00646 else if(x->mode == JIT_GL_PBUFFER_MODE_CTT) 00647 { 00648 // glDisable(x->target); 00649 } 00650 00651 return JIT_ERR_NONE; 00652 } 00653 00654 t_jit_err jit_gl_pbuffer_destroy_native(t_jit_gl_native_pbuffer x, t_jit_gl_native_drawable device) 00655 { 00656 #ifdef WIN_VERSION 00657 00658 // release the native device 00659 if(x && device) 00660 wglReleasePbufferDCARB(x, device); 00661 00662 // destroy the native pbuffer 00663 if(x) 00664 wglDestroyPbufferARB(x); 00665 00666 #endif 00667 00668 #ifdef MAC_VERSION 00669 if(x) 00670 aglDestroyPBuffer(x); 00671 #endif 00672 00673 return JIT_ERR_NONE; 00674 } 00675 00676 t_jit_err jit_gl_pbuffer_destroy(t_jit_gl_pbuffer *x) 00677 { 00678 if(!x) 00679 return JIT_ERR_INVALID_PTR; 00680 00681 if(/*x->mode == JIT_GL_PBUFFER_MODE_CTT &&*/ x->buffertexid > 0) 00682 { 00683 GLuint id = x->buffertexid; 00684 glDeleteTextures(1, &id); 00685 x->buffertexid = -1; 00686 } 00687 00688 #ifdef WIN_VERSION 00689 // destroy the native context 00690 if(x->current) 00691 jit_gl_destroy_native_context(x->current->context); 00692 00693 // destroy the pbuffer 00694 if(x->native && x->current) 00695 jit_gl_pbuffer_destroy_native(x->native, x->current->drawable); 00696 x->native = NULL; 00697 00698 // destroy the native pixelformat 00699 if(x->pixelformat) 00700 jit_gl_pixelformat_destroy_native(x->pixelformat); 00701 x->pixelformat = NULL; 00702 00703 #endif 00704 00705 #ifdef MAC_VERSION 00706 00707 // destroy the pbuffer 00708 if(x->native) 00709 jit_gl_pbuffer_destroy_native(x->native, NULL); 00710 x->native = NULL; 00711 00712 // destroy the native context 00713 if(x->current) 00714 jit_gl_destroy_native_context(x->current->context); 00715 00716 // destroy the native pixelformat 00717 if(!x->copy_context && x->pixelformat) 00718 jit_gl_pixelformat_destroy_native(x->pixelformat); 00719 x->pixelformat = NULL; 00720 00721 #endif 00722 00723 // free existing previous copy 00724 if(x->current) 00725 { 00726 jit_freebytes(x->current, sizeof(t_jit_gl_context_struct)); 00727 x->current = NULL; 00728 } 00729 00730 // free existing previous copy 00731 if(x->previous) 00732 { 00733 jit_freebytes(x->previous, sizeof(t_jit_gl_context_struct)); 00734 x->previous = NULL; 00735 } 00736 00737 x->bound = FALSE; 00738 jit_gl_pbuffer_reset(x); 00739 return JIT_ERR_NONE; 00740 } 00741 00742 t_jit_err jit_gl_pbuffer_reset(t_jit_gl_pbuffer *x) 00743 { 00744 x->initialized = FALSE; 00745 x->mode = JIT_GL_PBUFFER_MODE_DRAW; 00746 x->bound = FALSE; 00747 x->source = -1; 00748 x->type = NULL; 00749 x->native = NULL; 00750 x->previous = NULL; 00751 x->current = NULL; 00752 x->width = 0; 00753 x->height = 0; 00754 x->target = -1; 00755 x->internal = -1; 00756 x->mipmap = FALSE; 00757 x->share_lists = FALSE; 00758 x->copy_context = FALSE; 00759 x->buffer = GL_FRONT; 00760 x->pixelformat = NULL; 00761 return JIT_ERR_NONE; 00762 } 00763 00764 t_jit_err jit_gl_pbuffer_create_attributes( 00765 t_jit_gl_pbuffer *x, t_jit_gl_pixelformat *pixelformat, GLint **attributes, GLuint *acount) 00766 { 00767 GLint attrib[JIT_GL_PF_MAX_ATTRIBCOUNT]; 00768 GLuint ac = 0; 00769 long i = 0; 00770 t_jit_gl_context ctx = NULL; 00771 00772 if(!x || !attributes || !acount) 00773 return JIT_ERR_GENERIC; 00774 00775 // only needed for win 00776 #ifdef WIN_VERSION 00777 00778 // get current render context 00779 ctx = jit_gl_get_context(); 00780 if(!ctx) return JIT_ERR_INVALID_PTR; 00781 00782 // allocate largest available pbuffer upto width + height 00783 attrib[ac++] = WGL_PBUFFER_LARGEST_ARB; 00784 attrib[ac++] = GL_TRUE; 00785 00786 // setup pixel buffer attributes 00787 if(x->mode == JIT_GL_PBUFFER_MODE_RTT) 00788 { 00789 if(ctx->support->pbuffer_rtt) 00790 { 00791 // choose texture target (ARB enum value same as NV, EXT) 00792 if (x->target == GL_TEXTURE_RECTANGLE_ARB && ctx->support->pbuffer_rtt_rect) 00793 { 00794 attrib[ac++] = WGL_TEXTURE_TARGET_ARB; 00795 attrib[ac++] = ctx->support->pbuffer_rtt_rect_target; 00796 } 00797 else 00798 { 00799 attrib[ac++] = WGL_TEXTURE_TARGET_ARB; 00800 attrib[ac++] = WGL_TEXTURE_2D_ARB; 00801 00802 // choose mipmaps for non-rect targets 00803 if (x->mipmap) 00804 { 00805 attrib[ac++] = WGL_MIPMAP_TEXTURE_ARB; 00806 attrib[ac++] = TRUE; 00807 } 00808 } 00809 00810 // choose special float texture format 00811 if (pixelformat && pixelformat->pixel_float && 00812 pixelformat->pixel_float_target == JIT_GL_PF_PIXEL_FLOAT_NV && 00813 ctx->support->pbuffer_float) 00814 { 00815 if(pixelformat->pixel_type == JIT_GL_PF_PIXELTYPE_R) 00816 { 00817 attrib[ac++] = WGL_TEXTURE_FORMAT_ARB; 00818 attrib[ac++] = WGL_TEXTURE_FLOAT_R_NV; 00819 } 00820 else if(pixelformat->pixel_type == JIT_GL_PF_PIXELTYPE_RG) 00821 { 00822 attrib[ac++] = WGL_TEXTURE_FORMAT_ARB; 00823 attrib[ac++] = WGL_TEXTURE_FLOAT_RG_NV; 00824 } 00825 else if(pixelformat->pixel_type == JIT_GL_PF_PIXELTYPE_RGB) 00826 { 00827 attrib[ac++] = WGL_TEXTURE_FORMAT_ARB; 00828 attrib[ac++] = WGL_TEXTURE_FLOAT_RGB_NV; 00829 } 00830 else if(pixelformat->pixel_type == JIT_GL_PF_PIXELTYPE_RGBA) 00831 { 00832 attrib[ac++] = WGL_TEXTURE_FORMAT_ARB; 00833 attrib[ac++] = WGL_TEXTURE_FLOAT_RGBA_NV; 00834 } 00835 } 00836 else if (pixelformat) 00837 { 00838 if(pixelformat->pixel_type == JIT_GL_PF_PIXELTYPE_RGBA) 00839 { 00840 attrib[ac++] = WGL_TEXTURE_FORMAT_ARB; 00841 attrib[ac++] = WGL_TEXTURE_RGBA_ARB; 00842 } 00843 else 00844 { 00845 attrib[ac++] = WGL_TEXTURE_FORMAT_ARB; 00846 attrib[ac++] = WGL_TEXTURE_RGB_ARB; 00847 } 00848 } 00849 } 00850 00851 // choose special depth texture format 00852 if (pixelformat && GET_FLAG(pixelformat->flags, JIT_GL_PF_FLAG_TEXTURE_DEPTH) && 00853 ctx->support->pbuffer_rtt_depth) 00854 { 00855 if (x->target == GL_TEXTURE_RECTANGLE_ARB && ctx->support->pbuffer_rtt_rect) 00856 { 00857 attrib[ac++] = WGL_DEPTH_TEXTURE_FORMAT_NV; 00858 attrib[ac++] = WGL_TEXTURE_DEPTH_COMPONENT_NV; 00859 } 00860 else 00861 { 00862 attrib[ac++] = WGL_DEPTH_TEXTURE_FORMAT_NV; 00863 attrib[ac++] = WGL_TEXTURE_DEPTH_COMPONENT_NV; 00864 } 00865 } 00866 00867 // choose default format 00868 if(!pixelformat) 00869 { 00870 attrib[ac++] = WGL_TEXTURE_FORMAT_ARB; 00871 attrib[ac++] = WGL_TEXTURE_RGBA_ARB; 00872 } 00873 } 00874 00875 // terminate 00876 attrib[ac++] = 0; 00877 attrib[ac++] = 0; 00878 00879 // allocate attribute array 00880 *attributes = NULL; 00881 *attributes = jit_getbytes(ac * sizeof(GLint)); 00882 if(!(*attributes)) 00883 { 00884 jit_object_error((t_object *)x,"jit.gl.pbuffer: error creating pbuffer attributes: out of memory!"); 00885 return JIT_ERR_INVALID_PTR; 00886 } 00887 00888 // copy to attribute array 00889 *acount = ac; 00890 for(i = 0; i < (long)ac; i++) 00891 (*attributes)[i] = attrib[i]; 00892 00893 #endif // WIN_VERSION 00894 00895 return JIT_ERR_NONE; 00896 } 00897 00898 /****************************************************************************/ 00899
Copyright © 2008, Cycling '74