1 2/* Copyright (c) Mark J. Kilgard, 1996. */ 3 4/* This program is freely distributable without licensing fees 5 and is provided without guarantee or warrantee expressed or 6 implied. This program is -not- in the public domain. */ 7 8#include <stdlib.h> 9 10#ifdef __sgi 11#include <dlfcn.h> 12#endif 13 14#include "glutint.h" 15 16/* Grumble. The IRIX 6.3 and early IRIX 6.4 OpenGL headers 17 support the video resize extension, but failed to define 18 GLX_SGIX_video_resize. */ 19#if 0 20#ifdef GLX_SYNC_FRAME_SGIX 21#define GLX_SGIX_video_resize 1 22#endif 23#endif 24 25#if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_video_resize) 26static int canVideoResize = -1; 27static int videoResizeChannel; 28#else 29static int canVideoResize = 0; 30#endif 31static int videoResizeInUse = 0; 32static int dx = -1, dy = -1, dw = -1, dh = -1; 33 34/* XXX Note that IRIX 6.2, 6.3, and some 6.4 versions have a 35 bug where programs seg-fault when they attempt video 36 resizing from an indirect OpenGL context (either local or 37 over a network). */ 38 39#if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_video_resize) 40 41static volatile int errorCaught; 42 43/* ARGSUSED */ 44static int 45catchXSGIvcErrors(Display * dpy, XErrorEvent * event) 46{ 47 errorCaught = 1; 48 return 0; 49} 50#endif 51 52/* CENTRY */ 53int GLUTAPIENTRY 54glutVideoResizeGet(GLenum param) 55{ 56#if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_video_resize) 57 if (canVideoResize < 0) { 58 canVideoResize = __glutIsSupportedByGLX("GLX_SGIX_video_resize"); 59 if (canVideoResize) { 60#if defined(__sgi) && __sgi 61 /* This is a hack because IRIX 6.2, 6.3, and some 6.4 62 versions were released with GLX_SGIX_video_resize 63 being advertised by the X server though the video 64 resize extension is not actually supported. We try to 65 determine if the libGL.so we are using actually has a 66 video resize entrypoint before we try to use the 67 feature. */ 68 void (*func) (void); 69 void *glxDso = dlopen("libGL.so", RTLD_LAZY); 70 71 func = (void (*)(void)) dlsym(glxDso, "glXQueryChannelDeltasSGIX"); 72 if (!func) { 73 canVideoResize = 0; 74 } else 75#endif 76 { 77 char *channelString; 78 int (*handler) (Display *, XErrorEvent *); 79 80 channelString = getenv("GLUT_VIDEO_RESIZE_CHANNEL"); 81 videoResizeChannel = channelString ? atoi(channelString) : 0; 82 83 /* Work around another annoying problem with SGI's 84 GLX_SGIX_video_resize implementation. Early IRIX 85 6.4 OpenGL's advertise the extension and have the 86 video resize API, but an XSGIvc X protocol errors 87 result trying to use the API. Set up an error 88 handler to intercept what would otherwise be a fatal 89 error. If an error was recieved, do not report that 90 video resize is possible. */ 91 handler = XSetErrorHandler(catchXSGIvcErrors); 92 93 errorCaught = 0; 94 95#if defined(GLX_GLXEXT_PROTOTYPES) 96#endif 97 98 __glut_glXQueryChannelDeltasSGIX(__glutDisplay, __glutScreen, 99 videoResizeChannel, &dx, &dy, &dw, &dh); 100 101 /* glXQueryChannelDeltasSGIX is an inherent X server 102 round-trip so we know we will have gotten either the 103 correct reply or and error by this time. */ 104 XSetErrorHandler(handler); 105 106 /* Still yet another work around. In IRIX 6.4 betas, 107 glXQueryChannelDeltasSGIX will return as if it 108 succeeded, but the values are filled with junk. 109 Watch to make sure the delta variables really make 110 sense. */ 111 if (errorCaught || 112 dx < 0 || dy < 0 || dw < 0 || dh < 0 || 113 dx > 2048 || dy > 2048 || dw > 2048 || dh > 2048) { 114 canVideoResize = 0; 115 } 116 } 117 } 118 } 119#endif /* GLX_SGIX_video_resize */ 120 121 switch (param) { 122 case GLUT_VIDEO_RESIZE_POSSIBLE: 123 return canVideoResize; 124 case GLUT_VIDEO_RESIZE_IN_USE: 125 return videoResizeInUse; 126 case GLUT_VIDEO_RESIZE_X_DELTA: 127 return dx; 128 case GLUT_VIDEO_RESIZE_Y_DELTA: 129 return dy; 130 case GLUT_VIDEO_RESIZE_WIDTH_DELTA: 131 return dw; 132 case GLUT_VIDEO_RESIZE_HEIGHT_DELTA: 133 return dh; 134 case GLUT_VIDEO_RESIZE_X: 135 case GLUT_VIDEO_RESIZE_Y: 136 case GLUT_VIDEO_RESIZE_WIDTH: 137 case GLUT_VIDEO_RESIZE_HEIGHT: 138#if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_video_resize) 139 if (videoResizeInUse) { 140 int x, y, width, height; 141 142 __glut_glXQueryChannelRectSGIX(__glutDisplay, __glutScreen, 143 videoResizeChannel, &x, &y, &width, &height); 144 switch (param) { 145 case GLUT_VIDEO_RESIZE_X: 146 return x; 147 case GLUT_VIDEO_RESIZE_Y: 148 return y; 149 case GLUT_VIDEO_RESIZE_WIDTH: 150 return width; 151 case GLUT_VIDEO_RESIZE_HEIGHT: 152 return height; 153 } 154 } 155#endif 156 return -1; 157 default: 158 __glutWarning("invalid glutVideoResizeGet parameter: %d", param); 159 return -1; 160 } 161} 162 163void GLUTAPIENTRY 164glutSetupVideoResizing(void) 165{ 166#if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_video_resize) 167 if (glutVideoResizeGet(GLUT_VIDEO_RESIZE_POSSIBLE)) { 168 __glut_glXBindChannelToWindowSGIX(__glutDisplay, __glutScreen, 169 videoResizeChannel, __glutCurrentWindow->win); 170 videoResizeInUse = 1; 171 } else 172#endif 173 __glutFatalError("glutEstablishVideoResizing: video resizing not possible.\n"); 174} 175 176void GLUTAPIENTRY 177glutStopVideoResizing(void) 178{ 179#if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_video_resize) 180 if (glutVideoResizeGet(GLUT_VIDEO_RESIZE_POSSIBLE)) { 181 if (videoResizeInUse) { 182 __glut_glXBindChannelToWindowSGIX(__glutDisplay, __glutScreen, 183 videoResizeChannel, None); 184 videoResizeInUse = 0; 185 } 186 } 187#endif 188} 189 190/* ARGSUSED */ 191void GLUTAPIENTRY 192glutVideoResize(int x, int y, int width, int height) 193{ 194#if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_video_resize) 195 if (videoResizeInUse) { 196#ifdef GLX_SYNC_SWAP_SGIX 197 /* glXChannelRectSyncSGIX introduced in a patch to IRIX 198 6.2; the original unpatched IRIX 6.2 behavior is always 199 GLX_SYNC_SWAP_SGIX. */ 200 __glut_glXChannelRectSyncSGIX(__glutDisplay, __glutScreen, 201 videoResizeChannel, GLX_SYNC_SWAP_SGIX); 202#endif 203 __glut_glXChannelRectSGIX(__glutDisplay, __glutScreen, 204 videoResizeChannel, x, y, width, height); 205 } 206#endif 207} 208 209/* ARGSUSED */ 210void GLUTAPIENTRY 211glutVideoPan(int x, int y, int width, int height) 212{ 213#if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_video_resize) 214 if (videoResizeInUse) { 215#ifdef GLX_SYNC_FRAME_SGIX 216 /* glXChannelRectSyncSGIX introduced in a patch to IRIX 217 6.2; the original unpatched IRIX 6.2 behavior is always 218 GLX_SYNC_SWAP_SGIX. We just ignore that we cannot 219 accomplish GLX_SYNC_FRAME_SGIX on IRIX unpatched 6.2; 220 this means you'd need a glutSwapBuffers to actually 221 realize the video resize. */ 222 __glut_glXChannelRectSyncSGIX(__glutDisplay, __glutScreen, 223 videoResizeChannel, GLX_SYNC_FRAME_SGIX); 224#endif 225 __glut_glXChannelRectSGIX(__glutDisplay, __glutScreen, 226 videoResizeChannel, x, y, width, height); 227 } 228#endif 229} 230 231/* ENDCENTRY */ 232