Skip to content

AFNI/NIfTI Server

Sections
Personal tools
You are here: Home » AFNI » Documentation

Doxygen Source Code Documentation


Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Search  

glut_overlay.c

Go to the documentation of this file.
00001 
00002 /* Copyright (c) Mark J. Kilgard, 1996.  */
00003 
00004 /* This program is freely distributable without licensing fees
00005    and is provided without guarantee or warrantee expressed or
00006    implied. This program is -not- in the public domain. */
00007 
00008 #include <stdlib.h>
00009 #include <stdio.h>
00010 #include <string.h>
00011 #include <assert.h>
00012 #include <X11/Xlib.h>
00013 #include <X11/Xutil.h>
00014 #include <X11/Xatom.h>  /* for XA_RGB_DEFAULT_MAP atom */
00015 #if defined (__vms)
00016 #include <X11/StdCmap.h>  /* for XmuLookupStandardColormap */
00017 #else
00018 #include <X11/Xmu/StdCmap.h>  /* for XmuLookupStandardColormap */
00019 #endif
00020 
00021 #include <GL/glut.h>
00022 #include "glutint.h"
00023 #include "layerutil.h"
00024 
00025 static int
00026 checkOverlayAcceptability(XVisualInfo * vi, unsigned int mode)
00027 {
00028   int value;
00029 
00030   /* Must support OpenGL. */
00031   glXGetConfig(__glutDisplay, vi, GLX_USE_GL, &value);
00032   if (!value)
00033     return 1;
00034 
00035   /* Must be color index. */
00036   glXGetConfig(__glutDisplay, vi, GLX_RGBA, &value);
00037   if (value)
00038     return 1;
00039 
00040   /* Must match single/double buffering request. */
00041   glXGetConfig(__glutDisplay, vi, GLX_DOUBLEBUFFER, &value);
00042   if (GLUT_WIND_IS_DOUBLE(mode) != (value != 0))
00043     return 1;
00044 
00045   /* Must match mono/stereo request. */
00046   glXGetConfig(__glutDisplay, vi, GLX_STEREO, &value);
00047   if (GLUT_WIND_IS_STEREO(mode) != (value != 0))
00048     return 1;
00049 
00050   /* Alpha and accumulation buffers incompatible with color
00051      index. */
00052   if (GLUT_WIND_HAS_ALPHA(mode) || GLUT_WIND_HAS_ACCUM(mode))
00053     return 1;
00054 
00055   /* Look for depth buffer if requested. */
00056   glXGetConfig(__glutDisplay, vi, GLX_DEPTH_SIZE, &value);
00057   if (GLUT_WIND_HAS_DEPTH(mode) && (value <= 0))
00058     return 1;
00059 
00060   /* Look for stencil buffer if requested. */
00061   glXGetConfig(__glutDisplay, vi, GLX_STENCIL_SIZE, &value);
00062   if (GLUT_WIND_HAS_STENCIL(mode) && (value <= 0))
00063     return 1;
00064 
00065 #if defined(GLX_VERSION_1_1) && defined(GLX_SGIS_multisample)
00066   /* XXX Multisampled overlay color index??  Pretty unlikely. */
00067   /* Look for multisampling if requested. */
00068   if (__glutIsSupportedByGLX("GLX_SGIS_multisample"))
00069     glXGetConfig(__glutDisplay, vi, GLX_SAMPLES_SGIS, &value);
00070   else
00071     value = 0;
00072   if (GLUT_WIND_IS_MULTISAMPLE(mode) && (value <= 0))
00073     return 1;
00074 #endif
00075 
00076   return 0;
00077 }
00078 
00079 static XVisualInfo *
00080 getOverlayVisualInfoCI(unsigned int mode)
00081 {
00082   XLayerVisualInfo *vi;
00083   XLayerVisualInfo template;
00084   XVisualInfo *goodVisual, *returnVisual;
00085   int nitems, i, j, bad;
00086 
00087   /* The GLX 1.0 glXChooseVisual is does not permit queries
00088      based on pixel transparency (and GLX_BUFFER_SIZE uses
00089      "smallest that meets" its requirement instead of "largest
00090      that meets" that GLUT wants. So, GLUT implements its own
00091      visual selection routine for color index overlays. */
00092 
00093   /* Try three overlay layers. */
00094   for (i = 1; i <= 3; i++) {
00095     template.vinfo.screen = __glutScreen;
00096     template.vinfo.class = PseudoColor;
00097     template.layer = i;
00098     template.type = TransparentPixel;
00099     vi = __glutXGetLayerVisualInfo(__glutDisplay,
00100       VisualTransparentType | VisualScreenMask | VisualClassMask | VisualLayerMask,
00101       &template, &nitems);
00102     if (vi) {
00103       /* Check list for acceptable visual meeting requirements
00104          of requested display mode. */
00105       for (j = 0; j < nitems; j++) {
00106         bad = checkOverlayAcceptability(&vi[j].vinfo, mode);
00107         if (bad) {
00108           /* Set vi[j].vinfo.visual to mark it unacceptable. */
00109           vi[j].vinfo.visual = NULL;
00110         }
00111       }
00112 
00113       /* Look through list to find deepest acceptable visual. */
00114       goodVisual = NULL;
00115       for (j = 0; j < nitems; j++) {
00116         if (vi[j].vinfo.visual) {
00117           if (goodVisual == NULL) {
00118             goodVisual = &vi[j].vinfo;
00119           } else {
00120             if (goodVisual->depth < vi[j].vinfo.depth) {
00121               goodVisual = &vi[j].vinfo;
00122             }
00123           }
00124         }
00125       }
00126 
00127       /* If a visual is found, clean up and return the visual. */
00128       if (goodVisual) {
00129         returnVisual = (XVisualInfo *) malloc(sizeof(XVisualInfo));
00130         if (returnVisual) {
00131           *returnVisual = *goodVisual;
00132         }
00133         XFree(vi);
00134         return returnVisual;
00135       }
00136       XFree(vi);
00137     }
00138   }
00139   return NULL;
00140 }
00141 
00142 static XVisualInfo *
00143 getOverlayVisualInfoRGB(unsigned int mode)
00144 {
00145 
00146   /* XXX For now, transparent RGBA overlays are not supported
00147      by GLUT.  RGBA overlays raise difficult questions about
00148      what the transparent pixel (really color) value should be.
00149 
00150      Color index overlay transparency is "easy" because the
00151      transparent pixel value does not affect displayable colors
00152      (except for stealing one color cell) since colors are
00153      determined by indirection through a colormap, and because
00154      it is uncommon for arbitrary pixel values in color index to
00155      be "calculated" (as can occur with a host of RGBA operations
00156      like lighting, blending, etc) so it is easy to avoid the
00157      transparent pixel value.
00158 
00159      Since it is typically easy to avoid the transparent pixel
00160      value in color index mode, if GLUT tells the programmer what
00161      pixel is transparent, then most program can easily avoid
00162      generating that pixel value except when they intend
00163      transparency.  GLUT returns whatever transparent pixel value
00164      is provided by the system through glutGet(
00165      GLUT_TRANSPARENT_INDEX).
00166 
00167      Theory versus practice for RGBA overlay transparency: In
00168      theory, the reasonable thing is enabling overlay transparency 
00169 
00170      when an overlay pixel's destination alpha is 0 because this
00171      allows overlay transparency to be controlled via alpha and
00172      all visibile colors are permited, but no hardware I am aware
00173      of supports this practice (and it requires destination alpha
00174      which is typically optional and quite uncommon for overlay
00175      windows!).  In practice, the choice of  transparent pixel
00176      value is typically "hardwired" into most graphics hardware to 
00177 
00178      a single pixel value.  SGI hardware uses true black (0,0,0)
00179      without regard for the destination alpha.  This is far from
00180      ideal because true black (a common color that is easy to
00181      accidently generate) can not be generated in an RGBA overlay. 
00182 
00183      I am not sure what other vendors do.
00184 
00185      Pragmatically, most of the typical things you want to do in
00186      the overlays can be done in color index (rubber banding,
00187      pop-up menus, etc.).  One solution for GLUT would be to
00188      simply "advertise" what RGB triple (or possibly RGBA
00189      quadruple or simply A alone) generates transparency.  The
00190      problem with this approach is that it forces programmers to
00191      avoid whatever arbitrary color various systems decide is
00192      transparent.  This is a difficult burden to place on
00193      programmers that want to portably make use of overlays.
00194 
00195      To actually support transparent RGBA overlays, there are
00196      really two reaonsable options.  ONE: Simply mandate that true 
00197 
00198      black is the RGBA overlay transparent color (what IRIS GL
00199      did).  This is nice for programmers since only one option,
00200      nice for existing SGI hardware, bad for anyone (including
00201      SGI) who wants to improve upon "true black" RGB transparency. 
00202 
00203      Or TWO: Provide a set of queriable "transparency types" (like 
00204 
00205      "true black" or "alpha == 0" or "true white" or even a
00206      queriable transparent color).  This is harder for
00207      programmers, OK for existing SGI hardware, and it leaves open 
00208 
00209      the issue of what other modes are reasonable.
00210 
00211      Option TWO seems the more general approach, but since
00212      hardware designers will likely only implement a single mode
00213      (this is a scan out issue where bandwidth is pressing issue),
00214      codifying multiple speculative approaches nobody may ever
00215      implement seems silly.  And option ONE fiats a suboptimal
00216      solution.
00217 
00218      Therefore, I defer any decision of how GLUT should support
00219      RGBA overlay transparency and leave support for it
00220      unimplemented. Nobody has been pressing me for RGBA overlay
00221      transparency (though people have requested color index overlay 
00222 
00223      transparency repeatedly).  Geez, if you read this far you are
00224      either really bored or maybe actually  interested in this
00225      topic.  Anyway, if you have ideas (particularly if you plan on 
00226 
00227      implementing a hardware scheme for RGBA overlay transparency), 
00228 
00229      I'd be interested.
00230 
00231      For the record, SGI's expiremental Framebufer Configuration
00232      experimental GLX extension uses option TWO.  Transparency
00233      modes for "none" and "RGB" are defined (others could be
00234      defined later).  What RGB value is the transparent one must be 
00235 
00236      queried. I was hoping GLUT could have something that required
00237      less work from the programmer to use portably. -mjk */
00238 
00239   __glutWarning("RGBA overlays are not supported by GLUT (for now).");
00240   return NULL;
00241 }
00242 
00243 static XVisualInfo *
00244 getOverlayVisualInfo(unsigned int mode)
00245 {
00246   /* XXX GLUT_LUMINANCE not implemented for GLUT 3.0. */
00247   if (GLUT_WIND_IS_LUMINANCE(mode))
00248     return NULL;
00249 
00250   if (GLUT_WIND_IS_RGB(mode))
00251     return getOverlayVisualInfoRGB(mode);
00252   else
00253     return getOverlayVisualInfoCI(mode);
00254 }
00255 
00256 static void
00257 addStaleWindow(GLUTwindow * window, Window win)
00258 {
00259   GLUTstale *entry;
00260 
00261   entry = (GLUTstale *) malloc(sizeof(GLUTstale));
00262   if (!entry)
00263     __glutFatalError("out of memory");
00264   entry->window = window;
00265   entry->win = win;
00266   entry->next = __glutStaleWindowList;
00267   __glutStaleWindowList = entry;
00268 }
00269 
00270 void
00271 __glutFreeOverlay(GLUToverlay * overlay)
00272 {
00273   XFree(overlay->vis);
00274   XDestroyWindow(__glutDisplay, overlay->win);
00275   glXDestroyContext(__glutDisplay, overlay->ctx);
00276   if (overlay->colormap) {
00277     /* Only color index overlays have colormap data structure. */
00278     __glutFreeColormap(overlay->colormap);
00279   }
00280   free(overlay);
00281 }
00282 
00283 void
00284 glutEstablishOverlay(void)
00285 {
00286   GLUToverlay *overlay;
00287   GLUTwindow *window;
00288   XSetWindowAttributes wa;
00289 
00290   /* Register a routine to free an overlay with glut_win.c;
00291      this keeps glut_win.c from pulling in all of
00292      glut_overlay.c when no overlay functionality is used by
00293      the application. */
00294   __glutFreeOverlayFunc = __glutFreeOverlay;
00295 
00296   window = __glutCurrentWindow;
00297 
00298   /* Allow for an existant overlay to be re-established perhaps
00299      if you wanted a different display mode. */
00300   if (window->overlay) {
00301     addStaleWindow(window, window->overlay->win);
00302     __glutFreeOverlay(window->overlay);
00303   }
00304   overlay = (GLUToverlay *) malloc(sizeof(GLUToverlay));
00305   if (!overlay)
00306     __glutFatalError("out of memory.");
00307 
00308   overlay->vis = __glutDetermineVisual(__glutDisplayMode,
00309     &overlay->fakeSingle, getOverlayVisualInfo);
00310   if (!overlay->vis) {
00311     __glutFatalError("lacks overlay support.");
00312   }
00313   overlay->ctx = glXCreateContext(__glutDisplay, overlay->vis,
00314     None, __glutTryDirect);
00315   overlay->isDirect = glXIsDirect(__glutDisplay, overlay->ctx);
00316   if (__glutForceDirect) {
00317     if (!overlay->isDirect) {
00318       __glutFatalError("direct rendering not possible.");
00319     }
00320   }
00321   __glutSetupColormap(overlay->vis, &(overlay->colormap), &(overlay->cmap));
00322   overlay->transparentPixel = __glutGetTransparentPixel(__glutDisplay,
00323     overlay->vis);
00324 
00325   wa.colormap = overlay->cmap;
00326   wa.background_pixel = overlay->transparentPixel;
00327   wa.event_mask = window->eventMask & GLUT_OVERLAY_EVENT_FILTER_MASK;
00328   wa.border_pixel = 0;
00329   overlay->win = XCreateWindow(__glutDisplay,
00330     window->win,
00331     0, 0, window->width, window->height, 0,
00332     overlay->vis->depth, InputOutput, overlay->vis->visual,
00333     CWBackPixel | CWBorderPixel | CWEventMask | CWColormap,
00334     &wa);
00335   if (window->children) {
00336     /* Overlay window must be lowered below any GLUT
00337        subwindows. */
00338     XLowerWindow(__glutDisplay, overlay->win);
00339   }
00340   XMapWindow(__glutDisplay, overlay->win);
00341   overlay->shownState = 1;
00342 
00343   overlay->damaged = 0;
00344   overlay->display = NULL;
00345 
00346   /* Make sure a reshape gets delivered. */
00347   window->forceReshape = True;
00348 
00349   __glutPutOnWorkList(__glutToplevelOf(window), GLUT_COLORMAP_WORK);
00350 
00351   window->overlay = overlay;
00352   glutUseLayer(GLUT_OVERLAY);
00353 }
00354 
00355 void
00356 glutRemoveOverlay(void)
00357 {
00358   GLUTwindow *window = __glutCurrentWindow;
00359   GLUToverlay *overlay = __glutCurrentWindow->overlay;
00360 
00361   if (!window->overlay)
00362     return;
00363 
00364   /* If using overlay, switch to the normal layer. */
00365   if (window->renderWin == overlay->win) {
00366     glutUseLayer(GLUT_NORMAL);
00367   }
00368   addStaleWindow(window, overlay->win);
00369   __glutFreeOverlay(overlay);
00370   window->overlay = NULL;
00371   __glutPutOnWorkList(__glutToplevelOf(window), GLUT_COLORMAP_WORK);
00372 }
00373 
00374 void
00375 glutUseLayer(GLenum layer)
00376 {
00377   GLUTwindow *window = __glutCurrentWindow;
00378 
00379   switch (layer) {
00380   case GLUT_NORMAL:
00381     window->renderWin = window->win;
00382     window->renderCtx = window->ctx;
00383     break;
00384   case GLUT_OVERLAY:
00385     window->renderWin = window->overlay->win;
00386     window->renderCtx = window->overlay->ctx;
00387     break;
00388   default:
00389     __glutWarning("glutUseLayer: unknown layer, %d.", layer);
00390     break;
00391   }
00392   __glutSetWindow(window);
00393 }
00394 
00395 void
00396 glutPostOverlayRedisplay(void)
00397 {
00398   __glutPostRedisplay(__glutCurrentWindow, GLUT_OVERLAY_REDISPLAY_WORK);
00399 }
00400 
00401 void
00402 glutOverlayDisplayFunc(GLUTdisplayCB displayFunc)
00403 {
00404   if (!__glutCurrentWindow->overlay) {
00405     __glutWarning("glutOverlayDisplayFunc: window has no overlay established");
00406     return;
00407   }
00408   __glutCurrentWindow->overlay->display = displayFunc;
00409 }
00410 
00411 void
00412 glutHideOverlay(void)
00413 {
00414   if (!__glutCurrentWindow->overlay) {
00415     __glutWarning("glutHideOverlay: window has no overlay established");
00416     return;
00417   }
00418   XUnmapWindow(__glutDisplay, __glutCurrentWindow->overlay->win);
00419   __glutCurrentWindow->overlay->shownState = 0;
00420 }
00421 
00422 void
00423 glutShowOverlay(void)
00424 {
00425   if (!__glutCurrentWindow->overlay) {
00426     __glutWarning("glutShowOverlay: window has no overlay established");
00427     return;
00428   }
00429   XMapWindow(__glutDisplay, __glutCurrentWindow->overlay->win);
00430   __glutCurrentWindow->overlay->shownState = 1;
00431 }
00432 
00433 int
00434 glutLayerGet(GLenum param)
00435 {
00436   switch (param) {
00437   case GLUT_OVERLAY_POSSIBLE:
00438     {
00439       XVisualInfo *vi;
00440       Bool dummy;
00441 
00442       vi = __glutDetermineVisual(__glutDisplayMode, &dummy, getOverlayVisualInfo);
00443       if (vi) {
00444         XFree(vi);
00445         return 1;
00446       }
00447       return 0;
00448     }
00449   case GLUT_LAYER_IN_USE:
00450     return __glutCurrentWindow->renderWin != __glutCurrentWindow->win;
00451   case GLUT_HAS_OVERLAY:
00452     return __glutCurrentWindow->overlay != NULL;
00453   case GLUT_TRANSPARENT_INDEX:
00454     if (__glutCurrentWindow->overlay) {
00455       return __glutCurrentWindow->overlay->transparentPixel;
00456     } else {
00457       return -1;
00458     }
00459   case GLUT_NORMAL_DAMAGED:
00460     /* __glutWindowDamaged is used so the damage state within
00461        the window (or overlay belwo) can be cleared before
00462        calling a display callback so on return, the state does
00463        not have to be cleared (since upon return from the
00464        callback the window could be destroyed (or layer
00465        removed). */
00466     return __glutCurrentWindow->damaged || __glutWindowDamaged;
00467   case GLUT_OVERLAY_DAMAGED:
00468     if (__glutCurrentWindow->overlay) {
00469       return __glutCurrentWindow->overlay->damaged || __glutWindowDamaged;
00470     } else {
00471       return -1;
00472     }
00473   default:
00474     __glutWarning("invalid glutLayerGet param: %d", param);
00475     return -1;
00476   }
00477 }
 

Powered by Plone

This site conforms to the following standards: