00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "osxGraphicsStateGuardian.h"
00013 #include "osxGraphicsBuffer.h"
00014 #include "string_utils.h"
00015 #include "config_osxdisplay.h"
00016 #include "depthWriteAttrib.h"
00017 #include "depthTestAttrib.h"
00018 #include "textureAttrib.h"
00019 #include "pnmImage.h"
00020
00021 #include <OpenGL/gl.h>
00022 #import <mach-o/dyld.h>
00023
00024
00025
00026 #include "resize_box.rgb.c"
00027
00028 TypeHandle osxGraphicsStateGuardian::_type_handle;
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 void *osxGraphicsStateGuardian::
00041 do_get_extension_func(const char *prefix, const char *name) {
00042 string fullname = "_" + string(prefix) + string(name);
00043 NSSymbol symbol = NULL;
00044
00045 if (NSIsSymbolNameDefined (fullname.c_str())) {
00046 symbol = NSLookupAndBindSymbol (fullname.c_str());
00047 }
00048
00049 return symbol ? NSAddressOfSymbol(symbol) : NULL;
00050 }
00051
00052
00053
00054
00055
00056
00057 osxGraphicsStateGuardian::
00058 osxGraphicsStateGuardian(GraphicsEngine *engine, GraphicsPipe *pipe,
00059 osxGraphicsStateGuardian *share_with) :
00060 GLGraphicsStateGuardian(engine, pipe),
00061 _share_with(share_with),
00062 _aglPixFmt(NULL),
00063 _aglcontext(NULL)
00064 {
00065 _shared_buffer = 1011;
00066 get_gamma_table();
00067 }
00068
00069
00070
00071
00072
00073
00074 osxGraphicsStateGuardian::
00075 ~osxGraphicsStateGuardian() {
00076 if (_aglcontext != (AGLContext)NULL) {
00077 aglSetCurrentContext(NULL);
00078 aglDestroyContext(_aglcontext);
00079 report_agl_error("aglDestroyContext");
00080 _aglcontext = (AGLContext)NULL;
00081 }
00082 }
00083
00084
00085
00086
00087
00088
00089
00090 void osxGraphicsStateGuardian::reset()
00091 {
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101 GLGraphicsStateGuardian::reset();
00102
00103 if (_aglcontext != (AGLContext)NULL) {
00104
00105 GLint value = sync_video ? 1 : 0;
00106 aglSetInteger(_aglcontext, AGL_SWAP_INTERVAL, &value);
00107 }
00108 }
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120 void osxGraphicsStateGuardian::
00121 draw_resize_box() {
00122
00123 static CPT(RenderState) state;
00124 if (state == (RenderState *)NULL) {
00125 state = RenderState::make(TransparencyAttrib::make(TransparencyAttrib::M_alpha),
00126 DepthWriteAttrib::make(DepthWriteAttrib::M_off),
00127 DepthTestAttrib::make(DepthTestAttrib::M_none));
00128
00129
00130
00131 string resize_box_string((const char *)resize_box, resize_box_len);
00132 istringstream resize_box_strm(resize_box_string);
00133 PNMImage resize_box_pnm;
00134 if (resize_box_pnm.read(resize_box_strm, "resize_box.rgb")) {
00135 PT(Texture) tex = new Texture;
00136 tex->set_name("resize_box.rgb");
00137 tex->load(resize_box_pnm);
00138 tex->set_minfilter(Texture::FT_linear);
00139 tex->set_magfilter(Texture::FT_linear);
00140 state = state->add_attrib(TextureAttrib::make(tex));
00141 }
00142 }
00143
00144
00145 _projection_mat_inv = _projection_mat = TransformState::make_identity();
00146 prepare_lens();
00147
00148
00149 set_state_and_transform(state, TransformState::make_identity());
00150
00151
00152
00153
00154 PN_stdfloat inner_x = 1.0f - (15.0f * 2.0f / _viewport_width);
00155 PN_stdfloat inner_y = (15.0f * 2.0f / _viewport_height) - 1.0f;
00156
00157
00158
00159 glBegin(GL_QUADS);
00160
00161 glColor4f(1.0, 1.0, 1.0, 1.0);
00162 glTexCoord2f(0.0, 0.0);
00163 glVertex2f(inner_x, -1.0);
00164
00165 glTexCoord2f(0.9375, 0.0);
00166 glVertex2f(1.0, -1.0);
00167
00168 glTexCoord2f(0.9375, 0.9375);
00169 glVertex2f(1.0, inner_y);
00170
00171 glTexCoord2f(0.0, 0.9375);
00172 glVertex2f(inner_x, inner_y);
00173
00174 glEnd();
00175 }
00176
00177
00178
00179
00180
00181
00182 OSStatus osxGraphicsStateGuardian::
00183 build_gl(bool full_screen, bool pbuffer, FrameBufferProperties &fb_props) {
00184 if (_aglcontext) {
00185 describe_pixel_format(fb_props);
00186 return noErr;
00187 }
00188
00189 OSStatus err = noErr;
00190
00191 GDHandle display = GetMainDevice();
00192
00193 pvector<GLint> attrib;
00194 if (!fb_props.get_indexed_color()) {
00195 attrib.push_back(AGL_RGBA);
00196 int color_bits = fb_props.get_color_bits();
00197 int alpha_bits = fb_props.get_alpha_bits();
00198 attrib.push_back(AGL_BUFFER_SIZE);
00199 attrib.push_back(color_bits + alpha_bits);
00200 attrib.push_back(AGL_PIXEL_SIZE);
00201 attrib.push_back(color_bits);
00202 attrib.push_back(AGL_RED_SIZE);
00203 attrib.push_back(color_bits / 3);
00204 attrib.push_back(AGL_GREEN_SIZE);
00205 attrib.push_back(color_bits / 3);
00206 attrib.push_back(AGL_BLUE_SIZE);
00207 attrib.push_back(color_bits / 3);
00208 attrib.push_back(AGL_ALPHA_SIZE);
00209 attrib.push_back(alpha_bits);
00210 }
00211 attrib.push_back(AGL_DEPTH_SIZE);
00212 attrib.push_back(fb_props.get_depth_bits());
00213 attrib.push_back(AGL_STENCIL_SIZE);
00214 attrib.push_back(fb_props.get_stencil_bits());
00215 if (fb_props.get_multisamples() != 0) {
00216 attrib.push_back(AGL_MULTISAMPLE);
00217 attrib.push_back(AGL_SAMPLE_BUFFERS_ARB);
00218 attrib.push_back(1);
00219 attrib.push_back(AGL_SAMPLES_ARB);
00220 attrib.push_back(fb_props.get_multisamples());
00221 }
00222
00223 if (fb_props.is_stereo()) {
00224 attrib.push_back(AGL_STEREO);
00225 }
00226
00227 if (!fb_props.is_single_buffered()) {
00228 attrib.push_back(AGL_DOUBLEBUFFER);
00229 }
00230 if (full_screen) {
00231 attrib.push_back(AGL_FULLSCREEN);
00232 }
00233 if (pbuffer) {
00234 attrib.push_back(AGL_PBUFFER);
00235 }
00236
00237 if (fb_props.get_force_hardware()) {
00238 attrib.push_back(AGL_ACCELERATED);
00239 attrib.push_back(AGL_NO_RECOVERY);
00240 }
00241
00242
00243
00244 attrib.push_back(AGL_MAXIMUM_POLICY);
00245
00246
00247 attrib.push_back(AGL_NONE);
00248
00249
00250 _aglcontext = NULL;
00251 _aglPixFmt = aglChoosePixelFormat(&display, 1, &attrib[0]);
00252 err = report_agl_error("aglChoosePixelFormat");
00253 if (_aglPixFmt) {
00254 if(_share_with == NULL) {
00255 _aglcontext = aglCreateContext(_aglPixFmt, NULL);
00256 } else {
00257 _aglcontext = aglCreateContext(_aglPixFmt, ((osxGraphicsStateGuardian *)_share_with)->_aglcontext);
00258 }
00259 err = report_agl_error("aglCreateContext");
00260
00261 if (_aglcontext == NULL) {
00262 osxdisplay_cat.error()
00263 << "osxGraphicsStateGuardian::build_gl Error Getting GL Context \n" ;
00264 if(err == noErr) {
00265 err = -1;
00266 }
00267 } else {
00268 aglSetInteger(_aglcontext, AGL_BUFFER_NAME, &_shared_buffer);
00269 err = report_agl_error("aglSetInteger AGL_BUFFER_NAME");
00270 }
00271
00272 } else {
00273 osxdisplay_cat.error()
00274 << "osxGraphicsStateGuardian::build_gl Error Getting Pixel Format\n" ;
00275 osxdisplay_cat.error()
00276 << fb_props << "\n";
00277 if(err == noErr) {
00278 err = -1;
00279 }
00280 }
00281
00282 if (err == noErr) {
00283 describe_pixel_format(fb_props);
00284 }
00285
00286 if (osxdisplay_cat.is_debug()) {
00287 osxdisplay_cat.debug()
00288 << "osxGraphicsStateGuardian::build_gl Returning :" << err << "\n";
00289 osxdisplay_cat.debug()
00290 << fb_props << "\n";
00291 }
00292
00293 return err;
00294 }
00295
00296
00297
00298
00299
00300
00301
00302
00303 void osxGraphicsStateGuardian::
00304 describe_pixel_format(FrameBufferProperties &fb_props) {
00305 fb_props.clear();
00306 GLint value;
00307
00308 if (aglDescribePixelFormat(_aglPixFmt, AGL_RGBA, &value)) {
00309 fb_props.set_indexed_color(!value);
00310 fb_props.set_rgb_color(value);
00311 }
00312 if (aglDescribePixelFormat(_aglPixFmt, AGL_DEPTH_SIZE, &value)) {
00313 fb_props.set_depth_bits(value);
00314 }
00315 int color_bits = 0;
00316 if (aglDescribePixelFormat(_aglPixFmt, AGL_RED_SIZE, &value)) {
00317 color_bits += value;
00318 }
00319 if (aglDescribePixelFormat(_aglPixFmt, AGL_GREEN_SIZE, &value)) {
00320 color_bits += value;
00321 }
00322 if (aglDescribePixelFormat(_aglPixFmt, AGL_BLUE_SIZE, &value)) {
00323 color_bits += value;
00324 }
00325 fb_props.set_color_bits(color_bits);
00326 if (aglDescribePixelFormat(_aglPixFmt, AGL_ALPHA_SIZE, &value)) {
00327 fb_props.set_alpha_bits(value);
00328 }
00329
00330 if (aglDescribePixelFormat(_aglPixFmt, AGL_STENCIL_SIZE, &value)) {
00331 fb_props.set_stencil_bits(value);
00332 }
00333
00334 int accum_bits = 0;
00335 if (aglDescribePixelFormat(_aglPixFmt, AGL_ACCUM_RED_SIZE, &value)) {
00336 accum_bits += value;
00337 }
00338 if (aglDescribePixelFormat(_aglPixFmt, AGL_ACCUM_GREEN_SIZE, &value)) {
00339 accum_bits += value;
00340 }
00341 if (aglDescribePixelFormat(_aglPixFmt, AGL_ACCUM_BLUE_SIZE, &value)) {
00342 accum_bits += value;
00343 }
00344
00345 if (aglDescribePixelFormat(_aglPixFmt, AGL_SAMPLES_ARB, &value)) {
00346 fb_props.set_multisamples(value);
00347 }
00348
00349 if (aglDescribePixelFormat(_aglPixFmt, AGL_DOUBLEBUFFER, &value)) {
00350 if (value) {
00351 fb_props.set_back_buffers(1);
00352 } else {
00353 fb_props.set_back_buffers(0);
00354 }
00355 }
00356
00357 if (aglDescribePixelFormat(_aglPixFmt, AGL_STEREO, &value)) {
00358 fb_props.set_stereo(value);
00359 }
00360
00361
00362
00363 fb_props.set_force_hardware(true);
00364 fb_props.set_force_software(true);
00365
00366 GLint ndevs;
00367 AGLDevice *gdevs = aglDevicesOfPixelFormat(_aglPixFmt, &ndevs);
00368 if (gdevs != (AGLDevice *)NULL) {
00369 AGLRendererInfo rinfo = aglQueryRendererInfo(gdevs, ndevs);
00370 if (rinfo != NULL) {
00371 if (aglDescribeRenderer(rinfo, AGL_ACCELERATED, &value)) {
00372
00373 fb_props.set_force_hardware(value);
00374 fb_props.set_force_software(!value);
00375 }
00376 if (aglDescribeRenderer(rinfo, AGL_VIDEO_MEMORY, &value)) {
00377 osxdisplay_cat.debug()
00378 << "Reported video memory is " << value << "\n";
00379 }
00380 if (aglDescribeRenderer(rinfo, AGL_TEXTURE_MEMORY, &value)) {
00381 osxdisplay_cat.debug()
00382 << "Reported texture memory is " << value << "\n";
00383 }
00384 }
00385 }
00386 }
00387
00388
00389
00390
00391
00392
00393 bool osxGraphicsStateGuardian::
00394 get_gamma_table() {
00395 CGDisplayRestoreColorSyncSettings();
00396 _cgErr = CGGetDisplayTransferByTable( 0, 256, _gOriginalRedTable, _gOriginalGreenTable, _gOriginalBlueTable, &_sampleCount);
00397 }
00398
00399
00400
00401
00402
00403
00404
00405 bool osxGraphicsStateGuardian::
00406 static_set_gamma(bool restore, PN_stdfloat gamma) {
00407 bool set;
00408
00409 set = false;
00410
00411 if (restore) {
00412 CGDisplayRestoreColorSyncSettings();
00413 set = true;
00414 return set;
00415 }
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427 CGGammaValue redTable[ 256 ];
00428 CGGammaValue greenTable[ 256 ];
00429 CGGammaValue blueTable[ 256 ];
00430
00431 short j, i;
00432 short y[3];
00433
00434 for (j = 0; j < 3; j++) {
00435 y[j] = 255;
00436 }
00437
00438 y[0] = 256 * gamma;
00439 y[1] = 256 * gamma;
00440 y[2] = 256 * gamma;
00441
00442 for (i = 0; i < 256; i++) {
00443 redTable[i] = _gOriginalRedTable[ i ] * (y[ 0 ] ) / 256;
00444 greenTable[ i ] = _gOriginalGreenTable[ i ] * (y[ 1 ] ) / 256;
00445 blueTable[ i ] = _gOriginalBlueTable[ i ] * (y[ 2 ] ) / 256;
00446 }
00447 _cgErr = CGSetDisplayTransferByTable( 0, 256, redTable, greenTable, blueTable);
00448
00449 if (_cgErr == 0) {
00450 set = true;
00451 }
00452
00453 return set;
00454 }
00455
00456
00457
00458
00459
00460
00461
00462 bool osxGraphicsStateGuardian::
00463 set_gamma(PN_stdfloat gamma) {
00464 bool set;
00465
00466 set = static_set_gamma(false, gamma);
00467
00468 return set;
00469 }
00470
00471
00472
00473
00474
00475
00476 void osxGraphicsStateGuardian::
00477 restore_gamma() {
00478 static_set_gamma(true, 1.0f);
00479 }
00480
00481
00482
00483
00484
00485
00486 void osxGraphicsStateGuardian::
00487 atexit_function() {
00488 static_set_gamma(true, 1.0);
00489 }
00490
00491