00001
00002
00003
00004
00005
00006
00007
00008 #include <stdlib.h>
00009 #include <stdio.h>
00010 #include <string.h>
00011 #include <assert.h>
00012
00013 #if !defined(_WIN32)
00014 #include <X11/Xlib.h>
00015 #include <X11/Xutil.h>
00016 #include <X11/Xatom.h>
00017 #if defined (__vms)
00018 #include <Xmu/StdCmap.h>
00019 #else
00020 #include <X11/Xmu/StdCmap.h>
00021 #endif
00022 #endif
00023
00024 #include "glutint.h"
00025 #include "layerutil.h"
00026
00027 static Criterion requiredOverlayCriteria[] =
00028 {
00029 {LEVEL, EQ, 1},
00030
00031 {TRANSPARENT, EQ, 1},
00032 {XPSEUDOCOLOR, EQ, 1},
00033 {RGBA, EQ, 0},
00034 {BUFFER_SIZE, GTE, 1}
00035 };
00036 static int numRequiredOverlayCriteria = sizeof(requiredOverlayCriteria) / sizeof(Criterion);
00037 static int requiredOverlayCriteriaMask =
00038 (1 << LEVEL) | (1 << TRANSPARENT) | (1 << XSTATICGRAY) | (1 << RGBA) | (1 << CI_MODE);
00039
00040 #if !defined(_WIN32)
00041 static int
00042 checkOverlayAcceptability(XVisualInfo * vi, unsigned int mode)
00043 {
00044 int value;
00045
00046
00047 glXGetConfig(__glutDisplay, vi, GLX_USE_GL, &value);
00048 if (!value)
00049 return 1;
00050
00051
00052 glXGetConfig(__glutDisplay, vi, GLX_RGBA, &value);
00053 if (value)
00054 return 1;
00055
00056
00057 glXGetConfig(__glutDisplay, vi, GLX_DOUBLEBUFFER, &value);
00058 if (GLUT_WIND_IS_DOUBLE(mode) != (value != 0))
00059 return 1;
00060
00061
00062 glXGetConfig(__glutDisplay, vi, GLX_STEREO, &value);
00063 if (GLUT_WIND_IS_STEREO(mode) != (value != 0))
00064 return 1;
00065
00066
00067
00068 if (GLUT_WIND_HAS_ALPHA(mode) || GLUT_WIND_HAS_ACCUM(mode))
00069 return 1;
00070
00071
00072 glXGetConfig(__glutDisplay, vi, GLX_DEPTH_SIZE, &value);
00073 if (GLUT_WIND_HAS_DEPTH(mode) && (value <= 0))
00074 return 1;
00075
00076
00077 glXGetConfig(__glutDisplay, vi, GLX_STENCIL_SIZE, &value);
00078 if (GLUT_WIND_HAS_STENCIL(mode) && (value <= 0))
00079 return 1;
00080
00081 #if defined(GLX_VERSION_1_1) && defined(GLX_SGIS_multisample)
00082
00083
00084 if (__glutIsSupportedByGLX("GLX_SGIS_multisample"))
00085 glXGetConfig(__glutDisplay, vi, GLX_SAMPLES_SGIS, &value);
00086 else
00087 value = 0;
00088 if (GLUT_WIND_IS_MULTISAMPLE(mode) && (value <= 0))
00089 return 1;
00090 #endif
00091
00092 return 0;
00093 }
00094 #endif
00095
00096 static XVisualInfo *
00097 getOverlayVisualInfoCI(unsigned int mode)
00098 {
00099 #if !defined(_WIN32)
00100 XLayerVisualInfo *vi;
00101 XLayerVisualInfo template;
00102 XVisualInfo *goodVisual, *returnVisual;
00103 int nitems, i, j, bad;
00104
00105
00106
00107
00108
00109
00110
00111
00112 for (i = 1; i <= 3; i++) {
00113 template.vinfo.screen = __glutScreen;
00114 template.vinfo.class = PseudoColor;
00115 template.layer = i;
00116 template.type = TransparentPixel;
00117 vi = __glutXGetLayerVisualInfo(__glutDisplay,
00118 VisualTransparentType | VisualScreenMask | VisualClassMask | VisualLayerMask,
00119 &template, &nitems);
00120 if (vi) {
00121
00122
00123 for (j = 0; j < nitems; j++) {
00124 bad = checkOverlayAcceptability(&vi[j].vinfo, mode);
00125 if (bad) {
00126
00127 vi[j].vinfo.visual = NULL;
00128 }
00129 }
00130
00131
00132 goodVisual = NULL;
00133 for (j = 0; j < nitems; j++) {
00134 if (vi[j].vinfo.visual) {
00135 if (goodVisual == NULL) {
00136 goodVisual = &vi[j].vinfo;
00137 } else {
00138 if (goodVisual->depth < vi[j].vinfo.depth) {
00139 goodVisual = &vi[j].vinfo;
00140 }
00141 }
00142 }
00143 }
00144
00145
00146 if (goodVisual) {
00147 returnVisual = (XVisualInfo *) malloc(sizeof(XVisualInfo));
00148 if (returnVisual) {
00149 *returnVisual = *goodVisual;
00150 }
00151 XFree(vi);
00152 return returnVisual;
00153 }
00154 XFree(vi);
00155 }
00156 }
00157 #endif
00158 return NULL;
00159 }
00160
00161
00162 static XVisualInfo *
00163 getOverlayVisualInfoRGB(unsigned int mode)
00164 {
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250 __glutWarning("RGBA overlays are not supported by GLUT (for now).");
00251 return NULL;
00252 }
00253
00254 static XVisualInfo *
00255 getOverlayVisualInfo(unsigned int mode)
00256 {
00257
00258 if (GLUT_WIND_IS_LUMINANCE(mode))
00259 return NULL;
00260
00261 if (GLUT_WIND_IS_RGB(mode))
00262 return getOverlayVisualInfoRGB(mode);
00263 else
00264 return getOverlayVisualInfoCI(mode);
00265 }
00266
00267 #if !defined(_WIN32)
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283 static void
00284 addStaleWindow(GLUTwindow * window, Window win)
00285 {
00286 GLUTstale *entry;
00287
00288 entry = (GLUTstale *) malloc(sizeof(GLUTstale));
00289 if (!entry)
00290 __glutFatalError("out of memory");
00291 entry->window = window;
00292 entry->win = win;
00293 entry->next = __glutStaleWindowList;
00294 __glutStaleWindowList = entry;
00295 }
00296
00297 #endif
00298
00299 void
00300 __glutFreeOverlay(GLUToverlay * overlay)
00301 {
00302 if (overlay->visAlloced)
00303 XFree(overlay->vis);
00304 XDestroyWindow(__glutDisplay, overlay->win);
00305 glXDestroyContext(__glutDisplay, overlay->ctx);
00306 if (overlay->colormap) {
00307
00308 __glutFreeColormap(overlay->colormap);
00309 }
00310 free(overlay);
00311 }
00312
00313 static XVisualInfo *
00314 determineOverlayVisual(int *treatAsSingle, Bool * visAlloced, void **fbc)
00315 {
00316 if (__glutDisplayString) {
00317 XVisualInfo *vi;
00318 int i;
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331 assert(__glutDetermineVisualFromString);
00332
00333
00334 *visAlloced = False;
00335 *fbc = NULL;
00336 for (i = 1; i <= 3; i++) {
00337 requiredOverlayCriteria[0].value = i;
00338 vi = __glutDetermineVisualFromString(__glutDisplayString, treatAsSingle,
00339 requiredOverlayCriteria, numRequiredOverlayCriteria,
00340 requiredOverlayCriteriaMask, fbc);
00341 if (vi) {
00342 return vi;
00343 }
00344 }
00345 return NULL;
00346 } else {
00347 *visAlloced = True;
00348 *fbc = NULL;
00349 return __glutDetermineVisual(__glutDisplayMode,
00350 treatAsSingle, getOverlayVisualInfo);
00351 }
00352 }
00353
00354
00355 void APIENTRY
00356 glutEstablishOverlay(void)
00357 {
00358 GLUToverlay *overlay;
00359 GLUTwindow *window;
00360 XSetWindowAttributes wa;
00361 #if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_fbconfig)
00362 GLXFBConfigSGIX fbc;
00363 #else
00364 void *fbc;
00365 #endif
00366
00367
00368
00369
00370
00371 __glutFreeOverlayFunc = __glutFreeOverlay;
00372
00373 window = __glutCurrentWindow;
00374
00375
00376
00377 if (window->overlay) {
00378 #if !defined(_WIN32)
00379 addStaleWindow(window, window->overlay->win);
00380 #endif
00381 __glutFreeOverlay(window->overlay);
00382 }
00383 overlay = (GLUToverlay *) malloc(sizeof(GLUToverlay));
00384 if (!overlay)
00385 __glutFatalError("out of memory.");
00386
00387 overlay->vis = determineOverlayVisual(&overlay->treatAsSingle,
00388 &overlay->visAlloced, (void **) &fbc);
00389 if (!overlay->vis) {
00390 __glutFatalError("lacks overlay support.");
00391 }
00392 #if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_fbconfig) && defined(__sgi)
00393 if (fbc) {
00394 window->ctx = glXCreateContextWithConfigSGIX(__glutDisplay, fbc,
00395 GLX_RGBA_TYPE_SGIX, None, __glutTryDirect);
00396 } else
00397 #endif
00398 {
00399 overlay->ctx = glXCreateContext(__glutDisplay, overlay->vis,
00400 None, __glutTryDirect);
00401 }
00402 if (!overlay->ctx) {
00403 __glutFatalError(
00404 "failed to create overlay OpenGL rendering context.");
00405 }
00406 #if !defined(_WIN32)
00407 overlay->isDirect = glXIsDirect(__glutDisplay, overlay->ctx);
00408 if (__glutForceDirect) {
00409 if (!overlay->isDirect) {
00410 __glutFatalError("direct rendering not possible.");
00411 }
00412 }
00413 #endif
00414 __glutSetupColormap(overlay->vis, &overlay->colormap, &overlay->cmap);
00415 overlay->transparentPixel = __glutGetTransparentPixel(__glutDisplay,
00416 overlay->vis);
00417 wa.colormap = overlay->cmap;
00418 wa.background_pixel = overlay->transparentPixel;
00419 wa.event_mask = window->eventMask & GLUT_OVERLAY_EVENT_FILTER_MASK;
00420 wa.border_pixel = 0;
00421 #if defined(_WIN32)
00422
00423 #else
00424 overlay->win = XCreateWindow(__glutDisplay,
00425 window->win,
00426 window->x, window->y, window->width, window->height, 0,
00427 overlay->vis->depth, InputOutput, overlay->vis->visual,
00428 CWBackPixel | CWBorderPixel | CWEventMask | CWColormap,
00429 &wa);
00430 #endif
00431 if (window->children) {
00432
00433
00434 XLowerWindow(__glutDisplay, overlay->win);
00435 }
00436 XMapWindow(__glutDisplay, overlay->win);
00437 overlay->shownState = 1;
00438
00439 overlay->display = NULL;
00440
00441
00442 window->forceReshape = True;
00443
00444 #if !defined(_WIN32)
00445 __glutPutOnWorkList(__glutToplevelOf(window), GLUT_COLORMAP_WORK);
00446 #endif
00447
00448 window->overlay = overlay;
00449 glutUseLayer(GLUT_OVERLAY);
00450
00451 if (overlay->treatAsSingle) {
00452 glDrawBuffer(GL_FRONT);
00453 glReadBuffer(GL_FRONT);
00454 }
00455 }
00456
00457 void APIENTRY
00458 glutRemoveOverlay(void)
00459 {
00460 GLUTwindow *window = __glutCurrentWindow;
00461 GLUToverlay *overlay = __glutCurrentWindow->overlay;
00462
00463 if (!window->overlay)
00464 return;
00465
00466
00467 if (window->renderWin == overlay->win) {
00468 glutUseLayer(GLUT_NORMAL);
00469 }
00470 #if !defined(_WIN32)
00471 addStaleWindow(window, overlay->win);
00472 #endif
00473 __glutFreeOverlay(overlay);
00474 window->overlay = NULL;
00475 #if !defined(_WIN32)
00476 __glutPutOnWorkList(__glutToplevelOf(window), GLUT_COLORMAP_WORK);
00477 #endif
00478 }
00479
00480 void APIENTRY
00481 glutUseLayer(GLenum layer)
00482 {
00483 GLUTwindow *window = __glutCurrentWindow;
00484
00485 switch (layer) {
00486 case GLUT_NORMAL:
00487 #ifdef _WIN32
00488 window->renderDc = window->hdc;
00489 #endif
00490 window->renderWin = window->win;
00491 window->renderCtx = window->ctx;
00492 break;
00493 case GLUT_OVERLAY:
00494
00495
00496
00497 #ifdef _WIN32
00498 window->renderDc = window->overlay->hdc;
00499 #endif
00500 window->renderWin = window->overlay->win;
00501 window->renderCtx = window->overlay->ctx;
00502 break;
00503 default:
00504 __glutWarning("glutUseLayer: unknown layer, %d.", layer);
00505 break;
00506 }
00507 __glutSetWindow(window);
00508 }
00509
00510 void APIENTRY
00511 glutPostOverlayRedisplay(void)
00512 {
00513 __glutPostRedisplay(__glutCurrentWindow, GLUT_OVERLAY_REDISPLAY_WORK);
00514 }
00515
00516
00517
00518
00519
00520 void APIENTRY
00521 glutPostWindowOverlayRedisplay(int win)
00522 {
00523 __glutPostRedisplay(__glutWindowList[win - 1], GLUT_OVERLAY_REDISPLAY_WORK);
00524 }
00525
00526 void APIENTRY
00527 glutOverlayDisplayFunc(GLUTdisplayCB displayFunc)
00528 {
00529 if (!__glutCurrentWindow->overlay) {
00530 __glutWarning("glutOverlayDisplayFunc: window has no overlay established");
00531 return;
00532 }
00533 __glutCurrentWindow->overlay->display = displayFunc;
00534 }
00535
00536 void APIENTRY
00537 glutHideOverlay(void)
00538 {
00539 if (!__glutCurrentWindow->overlay) {
00540 __glutWarning("glutHideOverlay: window has no overlay established");
00541 return;
00542 }
00543 XUnmapWindow(__glutDisplay, __glutCurrentWindow->overlay->win);
00544 __glutCurrentWindow->overlay->shownState = 0;
00545 }
00546
00547 void APIENTRY
00548 glutShowOverlay(void)
00549 {
00550 if (!__glutCurrentWindow->overlay) {
00551 __glutWarning("glutShowOverlay: window has no overlay established");
00552 return;
00553 }
00554 XMapWindow(__glutDisplay, __glutCurrentWindow->overlay->win);
00555 __glutCurrentWindow->overlay->shownState = 1;
00556 }
00557
00558 int APIENTRY
00559 glutLayerGet(GLenum param)
00560 {
00561 switch (param) {
00562 case GLUT_OVERLAY_POSSIBLE:
00563 {
00564 XVisualInfo *vi;
00565 Bool dummy, visAlloced;
00566 void *fbc;
00567
00568 vi = determineOverlayVisual(&dummy, &visAlloced, &fbc);
00569 if (vi) {
00570 if (visAlloced)
00571 XFree(vi);
00572 return 1;
00573 }
00574 return 0;
00575 }
00576 case GLUT_LAYER_IN_USE:
00577 return __glutCurrentWindow->renderWin != __glutCurrentWindow->win;
00578 case GLUT_HAS_OVERLAY:
00579 return __glutCurrentWindow->overlay != NULL;
00580 case GLUT_TRANSPARENT_INDEX:
00581 if (__glutCurrentWindow->overlay) {
00582 return __glutCurrentWindow->overlay->transparentPixel;
00583 } else {
00584 return -1;
00585 }
00586 case GLUT_NORMAL_DAMAGED:
00587
00588
00589
00590
00591
00592
00593 return (__glutCurrentWindow->workMask & GLUT_REPAIR_WORK)
00594 || __glutWindowDamaged;
00595 case GLUT_OVERLAY_DAMAGED:
00596 if (__glutCurrentWindow->overlay) {
00597 return (__glutCurrentWindow->workMask & GLUT_OVERLAY_REPAIR_WORK)
00598 || __glutWindowDamaged;
00599 } else {
00600 return -1;
00601 }
00602 default:
00603 __glutWarning("invalid glutLayerGet param: %d", param);
00604 return -1;
00605 }
00606 }
00607