00001 #include <gra/framebuffer/FrameBufferGLX.h>
00002
00003 using namespace gra;
00004
00005 void FrameBufferGLX::_init(const char * name)
00006 {
00007 int visualAttr[11] = { GLX_RED_SIZE, 1,
00008 GLX_GREEN_SIZE, 1,
00009 GLX_BLUE_SIZE, 1,
00010 GLX_RGBA, None, None, None, None };
00011 int i = 7;
00012 if (!(_fbMode & FB_RGBA))
00013 cerr << "FrameBufferGLX: Switching to RGBA mode" << endl;
00014 if (_fbMode & FB_DOUBLE) visualAttr[i++] = GLX_DOUBLEBUFFER;
00015 if (_fbMode & FB_DEPTH) {
00016 visualAttr[i++] = GLX_DEPTH_SIZE;
00017 visualAttr[i++] = 1;
00018 } else {
00019 visualAttr[i++] = GLX_DEPTH_SIZE;
00020 visualAttr[i++] = 0;
00021 }
00022
00023 _pDisplay = NULL;
00024 _pVisualInfo = NULL;
00025 _pImage = NULL;
00026
00027
00028 if (!(_pDisplay = XOpenDisplay(name))) {
00029 cerr << "FrameBufferGLX: Unable to open X display" << endl;
00030 return;
00031 }
00032
00033 if (! glXQueryExtension(_pDisplay, NULL, NULL)) {
00034 cerr << "FrameBufferGLX: GLX extension is not supported by X server" << endl;
00035 return;
00036 }
00037
00038
00039 if (!(_pVisualInfo = glXChooseVisual(_pDisplay,
00040 DefaultScreen(_pDisplay),
00041 visualAttr)))
00042 {
00043 cerr << "FrameBufferGLX: Unable to get X visual" << endl;
00044 return;
00045 }
00046
00047
00048
00049 _shiftRed = ffs(_pVisualInfo->red_mask) - 1;
00050 _shiftGreen = ffs(_pVisualInfo->green_mask) - 1;
00051 _shiftBlue = ffs(_pVisualInfo->blue_mask) - 1;
00052
00053 #if BYTE_ORDER == BIG_ENDIAN
00054 _byteRev = (ImageByteOrder(_pDisplay) != MSBFirst);
00055 #else
00056 _byteRev = (ImageByteOrder(_pDisplay) != LSBFirst);
00057 #endif
00058
00059
00060
00061 _context = glXCreateContext(_pDisplay, _pVisualInfo, 0, GL_TRUE);
00062
00063
00064 _winAttr.colormap = XCreateColormap(_pDisplay,
00065 RootWindow(_pDisplay,
00066 _pVisualInfo->screen),
00067 _pVisualInfo->visual,
00068 AllocNone);
00069 _winAttr.border_pixel = 0;
00070 _winAttr.event_mask = StructureNotifyMask;
00071 _win = XCreateWindow(_pDisplay,
00072 RootWindow(_pDisplay, _pVisualInfo->screen),
00073 0, 0, _width, _height, 0,
00074 _pVisualInfo->depth, InputOutput,
00075 _pVisualInfo->visual,
00076 CWBorderPixel|CWColormap|CWEventMask,
00077 &_winAttr);
00078 XMapWindow(_pDisplay, _win);
00079
00080
00081
00082 _gcValues.function = GXcopy;
00083 _gc = XCreateGC(_pDisplay, _win, GCFunction, &_gcValues);
00084
00085
00086
00087 if (!(_pImage = XCreateImage(_pDisplay,
00088 _pVisualInfo->visual,
00089 _pVisualInfo->depth,
00090 ZPixmap,
00091 0,
00092 NULL,
00093 _width,
00094 _height,
00095 BitmapPad(_pDisplay),
00096 0)))
00097 {
00098 cerr << "FrameBufferGLX: Unable to create X image" << endl;
00099 return;
00100 }
00101
00102 if (!(_pImage->data=(char *)calloc(1, _pImage->bytes_per_line*_height))) {
00103 cerr << "FrameBufferGLX: Unable to allocate data in the X image" << endl;
00104 return;
00105 }
00106
00107
00108 glXMakeCurrent(_pDisplay, _win, _context);
00109 }
00110
00111 void FrameBufferGLX::_destroy()
00112 {
00113 if (_pImage) {
00114 if (_pImage->data) {
00115 free(_pImage->data);
00116 _pImage->data = NULL;
00117 }
00118 XDestroyImage(_pImage);
00119 _pImage = NULL;
00120 }
00121 if (_winAttr.colormap != None) {
00122 XFreeColormap(_pDisplay, _winAttr.colormap);
00123 _winAttr.colormap = None;
00124 }
00125 if (_pVisualInfo) {
00126 XFree(_pVisualInfo);
00127 _pVisualInfo = NULL;
00128 }
00129 if (_pDisplay) {
00130 XDestroyWindow(_pDisplay, _win);
00131 glXDestroyContext(_pDisplay, _context);
00132 XCloseDisplay(_pDisplay);
00133 _pDisplay = NULL;
00134 }
00135 }
00136
00137 void FrameBufferGLX::setWidth(unsigned w)
00138 {
00139 _width = w;
00140
00141 if (_pDisplay) return;
00142
00143 XResizeWindow(_pDisplay, _win, _width, _height);
00144
00145 if (_pImage) {
00146 if (_pImage->data) {
00147 free(_pImage->data);
00148 _pImage->data = NULL;
00149 }
00150 XDestroyImage(_pImage);
00151 _pImage = NULL;
00152 }
00153
00154
00155 if (!(_pImage = XCreateImage(_pDisplay,
00156 _pVisualInfo->visual,
00157 _pVisualInfo->depth,
00158 ZPixmap,
00159 0,
00160 NULL,
00161 _width,
00162 _height,
00163 BitmapPad(_pDisplay),
00164 0)))
00165 {
00166 cerr << "FrameBufferGLX::setWidth(): Unable to create X image" << endl;
00167 return;
00168 }
00169
00170 if (!(_pImage->data=(char *)calloc(1, _pImage->bytes_per_line*_height))) {
00171 cerr << "FrameBufferGLX::setWidth(): Unable to allocate data in the X image" << endl;
00172 return;
00173 }
00174 }
00175
00176 void FrameBufferGLX::setHeight(unsigned h)
00177 {
00178 _height = h;
00179
00180 if (_pDisplay) return;
00181
00182 XResizeWindow(_pDisplay, _win, _width, _height);
00183
00184 if (_pImage) {
00185 if (_pImage->data) {
00186 free(_pImage->data);
00187 _pImage->data = NULL;
00188 }
00189 XDestroyImage(_pImage);
00190 _pImage = NULL;
00191 }
00192
00193
00194 if (!(_pImage = XCreateImage(_pDisplay,
00195 _pVisualInfo->visual,
00196 _pVisualInfo->depth,
00197 ZPixmap,
00198 0,
00199 NULL,
00200 _width,
00201 _height,
00202 BitmapPad(_pDisplay),
00203 0)))
00204 {
00205 cerr << "FrameBufferGLX::setHeight(): Unable to create X image" << endl;
00206 return;
00207 }
00208
00209 if (!(_pImage->data=(char *)calloc(1, _pImage->bytes_per_line*_height))) {
00210 cerr << "FrameBufferGLX::setHeight(): Unable to allocate data in the X image" << endl;
00211 return;
00212 }
00213 }
00214
00215 void FrameBufferGLX::showContent()
00216 {
00217 if (!_pDisplay || !_pImage) return;
00218 if (_fbMode & FB_DOUBLE) glXSwapBuffers(_pDisplay, _win);
00219 XPutImage(_pDisplay, _win, _gc, _pImage, 0, 0, 0, 0,
00220 _pImage->width, _pImage->height);
00221
00222 }
00223
00224 void FrameBufferGLX::setColor(const Camera& camera,
00225 unsigned x,
00226 unsigned y,
00227 float ,
00228 const Color3f& color)
00229 {
00230
00231 cerr << "FrameBufferGLX::setColor(): Depth of pixels is not supported" << endl;
00232 setColor(camera, x, y, color);
00233 }
00234
00235 void FrameBufferGLX::setColor(const Camera& ,
00236 unsigned x,
00237 unsigned y,
00238 const Color3f& color)
00239 {
00240 if (!_pVisualInfo || !_pDisplay) return;
00241
00242 unsigned long r = (unsigned long)(color.x * 255.0);
00243 unsigned long g = (unsigned long)(color.y * 255.0);
00244 unsigned long b = (unsigned long)(color.z * 255.0);
00245
00246
00247 if (r > 255) r = 255;
00248 if (g > 255) g = 255;
00249 if (b > 255) b = 255;
00250
00251 unsigned long pixel =
00252 ((_byteRev) ?
00253 (b << _shiftRed) | (g << _shiftGreen) | (r << _shiftBlue) :
00254 (r << _shiftRed) | (g << _shiftGreen) | (b << _shiftBlue));
00255
00256 unsigned posy = _height - 1 - y;
00257
00258 XPutPixel(_pImage, x, posy, pixel);
00259 XPutImage(_pDisplay, _win, _gc, _pImage, x, posy, x, posy, 1, 1);
00260 }
00261
00262 void FrameBufferGLX::setColors(const Camera& camera,
00263 unsigned x,
00264 unsigned y,
00265 float depth,
00266 const Color3f colors[],
00267 unsigned size)
00268 {
00269 fprintf(stderr,"FrameBufferGL::setColors(): To do");
00270
00271 }
00272
00273 void FrameBufferGLX::setColors(const Camera& camera,
00274 unsigned x,
00275 unsigned y,
00276 const Color3f colors[],
00277 unsigned size)
00278 {
00279 unsigned long xpos = x;
00280 unsigned long ypos = y;
00281
00282 for (unsigned i = 0; i < size; i++) {
00283 if (xpos >= _width) { xpos = 0; ypos--; }
00284 setColor(camera, xpos++, ypos, colors[i]);
00285 }
00286
00287 XPutImage(_pDisplay, _win, _gc, _pImage, 0, 0, 0, 0,
00288 _pImage->width, _pImage->height);
00289 }
00290
00291 Color3f FrameBufferGLX::getColor(unsigned x, unsigned y) const
00292 {
00293 Color3f c;
00294 if (!_pImage || !_pVisualInfo) return c;
00295
00296 unsigned long pixel = XGetPixel(_pImage, x, _height-y);
00297
00298 float r = ((float)((pixel & _pVisualInfo->red_mask) >> _shiftRed) /
00299 (float)(_pVisualInfo->red_mask >> _shiftRed));
00300 float g = ((float)((pixel & _pVisualInfo->green_mask) >> _shiftGreen) /
00301 (float)(_pVisualInfo->green_mask >> _shiftGreen));
00302 float b = ((float)((pixel & _pVisualInfo->blue_mask) >> _shiftBlue) /
00303 (float)(_pVisualInfo->blue_mask >> _shiftBlue));
00304
00305 (_byteRev) ? c.set(b,g,r) : c.set(r,g,b);
00306 return c;
00307 }
00308
00309 void FrameBufferGLX::clearColor(const Color3f& color)
00310 {
00311 glClearColor(color.x, color.y, color.z, 1.0);
00312 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00313 if (_fbMode & FB_DOUBLE) glXSwapBuffers(_pDisplay, _win);
00314 }