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 
00003 
00004 
00005 
00006 
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>  
00015 #if defined (__vms)
00016 #include <X11/StdCmap.h>  
00017 #else
00018 #include <X11/Xmu/StdCmap.h>  
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   
00031   glXGetConfig(__glutDisplay, vi, GLX_USE_GL, &value);
00032   if (!value)
00033     return 1;
00034 
00035   
00036   glXGetConfig(__glutDisplay, vi, GLX_RGBA, &value);
00037   if (value)
00038     return 1;
00039 
00040   
00041   glXGetConfig(__glutDisplay, vi, GLX_DOUBLEBUFFER, &value);
00042   if (GLUT_WIND_IS_DOUBLE(mode) != (value != 0))
00043     return 1;
00044 
00045   
00046   glXGetConfig(__glutDisplay, vi, GLX_STEREO, &value);
00047   if (GLUT_WIND_IS_STEREO(mode) != (value != 0))
00048     return 1;
00049 
00050   
00051 
00052   if (GLUT_WIND_HAS_ALPHA(mode) || GLUT_WIND_HAS_ACCUM(mode))
00053     return 1;
00054 
00055   
00056   glXGetConfig(__glutDisplay, vi, GLX_DEPTH_SIZE, &value);
00057   if (GLUT_WIND_HAS_DEPTH(mode) && (value <= 0))
00058     return 1;
00059 
00060   
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   
00067   
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   
00088 
00089 
00090 
00091 
00092 
00093   
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       
00104 
00105       for (j = 0; j < nitems; j++) {
00106         bad = checkOverlayAcceptability(&vi[j].vinfo, mode);
00107         if (bad) {
00108           
00109           vi[j].vinfo.visual = NULL;
00110         }
00111       }
00112 
00113       
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       
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   
00147 
00148 
00149 
00150 
00151 
00152 
00153 
00154 
00155 
00156 
00157 
00158 
00159 
00160 
00161 
00162 
00163 
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   __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   
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     
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   
00291 
00292 
00293 
00294   __glutFreeOverlayFunc = __glutFreeOverlay;
00295 
00296   window = __glutCurrentWindow;
00297 
00298   
00299 
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     
00337 
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   
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   
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     
00461 
00462 
00463 
00464 
00465 
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 }