Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/RenderSystems/GL/src/GLX/OgreGLXUtils.cpp @ 1

Last change on this file since 1 was 1, checked in by landauf, 17 years ago
File size: 15.8 KB
RevLine 
[1]1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4(Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2006 Torus Knot Software Ltd
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23
24You may alternatively use this source under the terms of a specific version of
25the OGRE Unrestricted License provided you have obtained such a license from
26Torus Knot Software Ltd.
27-----------------------------------------------------------------------------
28*/
29#include "OgreStableHeaders.h"
30
31#include "OgreException.h"
32#include "OgreLogManager.h"
33#include "OgreRoot.h"
34#include "OgreStringConverter.h"
35
36#include "OgreGLRenderSystem.h"
37#include "OgreGLXUtils.h"
38
39#include "OgreNoMemoryMacros.h"
40#include <GL/glxext.h>
41
42namespace Ogre {
43    struct visual_attribs
44    {
45       /* X visual attribs */
46       int id;
47       int klass;
48       int depth;
49       int redMask, greenMask, blueMask;
50       int colormapSize;
51       int bitsPerRGB;
52
53       /* GL visual attribs */
54       int supportsGL;
55       int transparentType;
56       int transparentRedValue;
57       int transparentGreenValue;
58       int transparentBlueValue;
59       int transparentAlphaValue;
60       int transparentIndexValue;
61       int bufferSize;
62       int level;
63       int rgba;
64       int doubleBuffer;
65       int stereo;
66       int auxBuffers;
67       int redSize, greenSize, blueSize, alphaSize;
68       int depthSize;
69       int stencilSize;
70       int accumRedSize, accumGreenSize, accumBlueSize, accumAlphaSize;
71       int numSamples, numMultisample;
72       int visualCaveat;
73    };
74
75
76
77    FBConfigData::FBConfigData():
78        configID(0), visualID(0), bufferSize(0), level(0), doubleBuffer(0), stereo(0),
79        auxBuffers(0), renderType(0),
80        redSize(0), greenSize(0), blueSize(0), alphaSize(0),
81        depthSize(0), stencilSize(0),
82        accumRedSize(0), accumGreenSize(0), accumBlueSize(0), accumAlphaSize(0),
83        drawableType(0), caveat(0),
84        maxPBufferWidth(0), maxPBufferHeight(0), maxPBufferPixels(0)
85    {
86        memset(this, 0, sizeof(FBConfigData));
87    }
88    FBConfigData::FBConfigData(Display *dpy, GLXFBConfig config)
89    {
90        memset(this, 0, sizeof(FBConfigData));
91
92        glXGetFBConfigAttrib(dpy, config, GLX_FBCONFIG_ID, &configID);
93        glXGetFBConfigAttrib(dpy, config, GLX_VISUAL_ID, &visualID);
94        glXGetFBConfigAttrib(dpy, config, GLX_BUFFER_SIZE, &bufferSize);
95        glXGetFBConfigAttrib(dpy, config, GLX_LEVEL, &level);
96        glXGetFBConfigAttrib(dpy, config, GLX_DOUBLEBUFFER, &doubleBuffer);
97        glXGetFBConfigAttrib(dpy, config, GLX_STEREO, &stereo);
98        glXGetFBConfigAttrib(dpy, config, GLX_AUX_BUFFERS, &auxBuffers);
99        glXGetFBConfigAttrib(dpy, config, GLX_RENDER_TYPE, &renderType);
100        glXGetFBConfigAttrib(dpy, config, GLX_RED_SIZE, &redSize);
101        glXGetFBConfigAttrib(dpy, config, GLX_GREEN_SIZE, &greenSize);
102        glXGetFBConfigAttrib(dpy, config, GLX_BLUE_SIZE, &blueSize);
103        glXGetFBConfigAttrib(dpy, config, GLX_ALPHA_SIZE, &alphaSize);
104        glXGetFBConfigAttrib(dpy, config, GLX_DEPTH_SIZE, &depthSize);
105        glXGetFBConfigAttrib(dpy, config, GLX_STENCIL_SIZE, &stencilSize);
106        glXGetFBConfigAttrib(dpy, config, GLX_ACCUM_RED_SIZE, &accumRedSize);
107        glXGetFBConfigAttrib(dpy, config, GLX_ACCUM_GREEN_SIZE, &accumGreenSize);
108        glXGetFBConfigAttrib(dpy, config, GLX_ACCUM_BLUE_SIZE, &accumBlueSize);
109        glXGetFBConfigAttrib(dpy, config, GLX_ACCUM_ALPHA_SIZE, &accumAlphaSize);
110        glXGetFBConfigAttrib(dpy, config, GLX_DRAWABLE_TYPE, &drawableType);
111        glXGetFBConfigAttrib(dpy, config, GLX_CONFIG_CAVEAT, &caveat);
112        glXGetFBConfigAttrib(dpy, config, GLX_MAX_PBUFFER_WIDTH, &maxPBufferWidth);
113        glXGetFBConfigAttrib(dpy, config, GLX_MAX_PBUFFER_HEIGHT, &maxPBufferHeight);
114        glXGetFBConfigAttrib(dpy, config, GLX_MAX_PBUFFER_PIXELS, &maxPBufferPixels);
115    }
116    String FBConfigData::toString() const
117    {
118        std::stringstream ss;
119        ss << "configID=" << configID;
120        ss << " visualID=" << visualID;
121        ss << " bufferSize=" << bufferSize;
122        ss << " level=" << level;
123        ss << " doubleBuffer=" << doubleBuffer;
124        ss << " stereo=" << stereo;
125        ss << " auxBuffers=" << auxBuffers;
126        ss << " renderType=" << renderType;
127        ss << " redSize=" << redSize;
128        ss << " greenSize=" << greenSize;
129        ss << " blueSize=" << blueSize;
130        ss << " alphaSize=" << alphaSize;
131        ss << " depthSize=" << depthSize;
132        ss << " stencilSize=" << stencilSize;
133        ss << " accumRedSize=" << accumRedSize;
134        ss << " accumGreenSize=" << accumGreenSize;
135        ss << " accumBlueSize=" << accumBlueSize;
136        ss << " accumAlphaSize=" << accumAlphaSize;
137        ss << " drawableType=" << drawableType;
138        ss << " caveat=" << caveat;
139        ss << " maxPBufferWidth=" << maxPBufferWidth;
140        ss << " maxPBufferHeight=" << maxPBufferHeight;
141        ss << " maxPBufferPixels=" << maxPBufferPixels;
142        return ss.str();
143    }
144
145    bool GLXUtils::LoadIcon(Display *mDisplay, Window rootWindow, const std::string &name, Pixmap *pix, Pixmap *mask)
146    {
147     Image img;
148     int mWidth, mHeight;
149       char *data, *bitmap;
150       try {
151          // Try to load image
152           img.load(name, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
153         mWidth = img.getWidth();
154           mHeight = img.getHeight();
155         if(img.getFormat() != PF_A8R8G8B8)
156             // Image format must be RGBA
157               return 0;
158      } catch(Exception &e) {
159            // Could not find image; never mind
160            return false;
161      }
162
163     // Allocate space for image data
164       data = (char*)malloc(mWidth * mHeight * 4); // Must be allocated with malloc
165       // Allocate space for transparency bitmap
166      int wbits = (mWidth+7)/8;
167      bitmap = (char*)malloc(wbits * mHeight);
168
169      // Convert and copy image
170      const char *imgdata = (const char*)img.getData();
171      int sptr = 0, dptr = 0;
172        for(int y=0; y<mHeight; y++) {
173         for(int x=0; x<mWidth; x++) {
174              data[dptr + 0] = 0;
175                data[dptr + 1] = imgdata[sptr + 0];
176                data[dptr + 2] = imgdata[sptr + 1];
177                data[dptr + 3] = imgdata[sptr + 2];
178                // Alpha threshold
179             if(((unsigned char)imgdata[sptr + 3])<128) {
180                   bitmap[y*wbits+(x>>3)] &= ~(1<<(x&7));
181             } else {
182                   bitmap[y*wbits+(x>>3)] |= 1<<(x&7);
183                }
184              sptr += 4;
185             dptr += 4;
186         }
187      }
188
189     /* put my pixmap data into the client side X image data structure */
190       XImage *image = XCreateImage (mDisplay, NULL, 24, ZPixmap, 0,
191                                    data,
192                                      mWidth, mHeight, 8,
193                                    mWidth*4);
194       image->byte_order = MSBFirst; // 0RGB format
195
196      /* tell server to start managing my pixmap */
197      Pixmap retval = XCreatePixmap(mDisplay, rootWindow, mWidth,
198                                      mHeight, 24);
199
200       /* copy from client to server */
201       GC context = XCreateGC (mDisplay, rootWindow, 0, NULL);
202        XPutImage(mDisplay, retval, context, image, 0, 0, 0, 0,
203                  mWidth, mHeight);
204
205       /* free up the client side pixmap data area */
206     XDestroyImage(image); // also cleans data
207      XFreeGC(mDisplay, context);
208
209       *pix = retval;
210     *mask = XCreateBitmapFromData(mDisplay, rootWindow, bitmap, mWidth, mHeight);
211      free(bitmap);
212      return true;
213    }
214
215
216
217    static void
218    get_visual_attribs(Display *dpy, XVisualInfo *vInfo,
219                       struct visual_attribs *attribs)
220    {
221     const char *ext = glXQueryExtensionsString(dpy, vInfo->screen);
222
223       memset(attribs, 0, sizeof(struct visual_attribs));
224
225        attribs->id = vInfo->visualid;
226    #if defined(__cplusplus) || defined(c_plusplus)
227
228        attribs->klass = vInfo->c_class;
229    #else
230
231        attribs->klass = vInfo->class;
232    #endif
233
234     attribs->depth = vInfo->depth;
235     attribs->redMask = vInfo->red_mask;
236        attribs->greenMask = vInfo->green_mask;
237        attribs->blueMask = vInfo->blue_mask;
238      attribs->colormapSize = vInfo->colormap_size;
239      attribs->bitsPerRGB = vInfo->bits_per_rgb;
240
241        if (glXGetConfig(dpy, vInfo, GLX_USE_GL, &attribs->supportsGL) != 0)
242           return;
243        glXGetConfig(dpy, vInfo, GLX_BUFFER_SIZE, &attribs->bufferSize);
244       glXGetConfig(dpy, vInfo, GLX_LEVEL, &attribs->level);
245      glXGetConfig(dpy, vInfo, GLX_RGBA, &attribs->rgba);
246        glXGetConfig(dpy, vInfo, GLX_DOUBLEBUFFER, &attribs->doubleBuffer);
247        glXGetConfig(dpy, vInfo, GLX_STEREO, &attribs->stereo);
248        glXGetConfig(dpy, vInfo, GLX_AUX_BUFFERS, &attribs->auxBuffers);
249       glXGetConfig(dpy, vInfo, GLX_RED_SIZE, &attribs->redSize);
250     glXGetConfig(dpy, vInfo, GLX_GREEN_SIZE, &attribs->greenSize);
251     glXGetConfig(dpy, vInfo, GLX_BLUE_SIZE, &attribs->blueSize);
252       glXGetConfig(dpy, vInfo, GLX_ALPHA_SIZE, &attribs->alphaSize);
253     glXGetConfig(dpy, vInfo, GLX_DEPTH_SIZE, &attribs->depthSize);
254     glXGetConfig(dpy, vInfo, GLX_STENCIL_SIZE, &attribs->stencilSize);
255     glXGetConfig(dpy, vInfo, GLX_ACCUM_RED_SIZE, &attribs->accumRedSize);
256      glXGetConfig(dpy, vInfo, GLX_ACCUM_GREEN_SIZE, &attribs->accumGreenSize);
257      glXGetConfig(dpy, vInfo, GLX_ACCUM_BLUE_SIZE, &attribs->accumBlueSize);
258        glXGetConfig(dpy, vInfo, GLX_ACCUM_ALPHA_SIZE, &attribs->accumAlphaSize);
259
260     /* get transparent pixel stuff */
261      glXGetConfig(dpy, vInfo,GLX_TRANSPARENT_TYPE, &attribs->transparentType);
262      if (attribs->transparentType == GLX_TRANSPARENT_RGB) {
263         glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_RED_VALUE, &attribs->transparentRedValue);
264            glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_GREEN_VALUE, &attribs->transparentGreenValue);
265            glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_BLUE_VALUE, &attribs->transparentBlueValue);
266          glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_ALPHA_VALUE, &attribs->transparentAlphaValue);
267        } else if (attribs->transparentType == GLX_TRANSPARENT_INDEX) {
268            glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_INDEX_VALUE, &attribs->transparentIndexValue);
269        }
270
271     /* multisample attribs */
272       if (ext && strstr("GLX_ARB_multisample", ext) == 0) {
273                glXGetConfig(dpy, vInfo, GLX_SAMPLE_BUFFERS_ARB, &attribs->numMultisample);
274            glXGetConfig(dpy, vInfo, GLX_SAMPLES_ARB, &attribs->numSamples);
275       }
276       else {
277         attribs->numSamples = 0;
278           attribs->numMultisample = 0;
279       }
280
281      if (ext && strstr(ext, "GLX_EXT_visual_rating")) {
282         glXGetConfig(dpy, vInfo, GLX_VISUAL_CAVEAT_EXT, &attribs->visualCaveat);
283       } else {
284           attribs->visualCaveat = GLX_NONE_EXT;
285      }
286    }
287
288    /*
289     * Examine all visuals to find the so-called best one.
290     * We prefer deepest RGBA buffer with depth, stencil and accum
291     * that has no caveats.
292     * @author Brian Paul (from the glxinfo source)
293     */
294    int GLXUtils::findBestVisual(Display *dpy, int scrnum, int multiSample)
295    {
296        XVisualInfo theTemplate;
297       XVisualInfo *visuals;
298      int numVisuals;
299        long mask;
300     int i;
301     struct visual_attribs bestVis;
302         int msDiff;
303
304        /* get list of all visuals on this screen */
305       theTemplate.screen = scrnum;
306       mask = VisualScreenMask;
307       visuals = XGetVisualInfo(dpy, mask, &theTemplate, &numVisuals);
308        if(numVisuals == 0 || visuals == 0) {
309          /* something went wrong */
310         if(visuals)
311                XFree(visuals);
312            return -1;
313     }
314
315     /* init bestVis with first visual info */
316      get_visual_attribs(dpy, &visuals[0], &bestVis);
317
318       /* try to find a "better" visual */
319        for (i = 1; i < numVisuals; i++) {
320         struct visual_attribs vis;
321
322            get_visual_attribs(dpy, &visuals[i], &vis);
323
324                /* always skip visuals that are slow */
325                if (vis.visualCaveat == GLX_SLOW_VISUAL_EXT)
326                    continue;
327                        /* skip visual if it doesn't have the desired number of multisamples */
328                        if (multiSample != -1 && vis.numSamples != multiSample)
329                           continue;
330
331         /* see if this vis is better than bestVis */
332
333           if ((!bestVis.supportsGL && vis.supportsGL) ||
334                         (bestVis.visualCaveat != GLX_NONE_EXT) ||
335                          (!bestVis.rgba && vis.rgba) ||
336                         (!bestVis.doubleBuffer && vis.doubleBuffer) ||
337                         (bestVis.redSize < vis.redSize) ||
338                         (bestVis.greenSize < vis.greenSize) ||
339                         (bestVis.blueSize < vis.blueSize) ||
340                           (bestVis.alphaSize < vis.alphaSize) ||
341                         (bestVis.depthSize < vis.depthSize) ||
342                         (bestVis.stencilSize < vis.stencilSize) ||
343                         (bestVis.accumRedSize < vis.accumRedSize))
344                        {
345               /* found a better visual */
346                bestVis = vis;
347                        }
348
349      }
350
351     XFree(visuals);
352        if (multiSample != -1 && bestVis.numSamples != multiSample)
353                        // We found no visual with the desired FSAA
354                        return -1;
355       return bestVis.id;
356    }
357
358    /**
359     * Class to sort FBConfig records by best match
360     */
361    class FBConfigMatchSort
362    {
363    public:
364        FBConfigMatchSort(Display *dpy, const int *idealattribs): dpy(dpy), mIdeal(idealattribs) { }
365
366        Display *dpy;
367        const int *mIdeal;
368        bool operator()(const GLXFBConfig & a, const GLXFBConfig & b)
369        {
370            for(int idx = 0; mIdeal[idx] != None; idx += 2)
371            {
372                int valuea, valueb;
373                int valueideal = mIdeal[idx+1];
374                glXGetFBConfigAttrib(dpy, a, mIdeal[idx], &valuea);
375                glXGetFBConfigAttrib(dpy, b, mIdeal[idx], &valueb);
376                // Distance to a smaller than distance to b?
377                if(std::abs(valuea - valueideal) < std::abs(valueb - valueideal))
378                    return true;
379            }
380            return false;
381        }
382    };
383
384
385    GLXFBConfig GLXUtils::findBestMatch(Display *dpy, int scrnum, const int *attribs, const int *idealattribs)
386    {
387        // Create vector of existing config data formats
388        GLXFBConfig * fbConfigs;
389        int nConfigs;
390        fbConfigs = glXChooseFBConfig(dpy, scrnum, attribs, &nConfigs);
391        if (nConfigs == 0 || !fbConfigs)
392            OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED, "glXChooseFBConfig() failed: Couldn't find a suitable pixel format", "GLRenderTexture::createPBuffer");
393
394        // Sort by best match
395        std::sort(fbConfigs, fbConfigs+nConfigs, FBConfigMatchSort(dpy, idealattribs));
396
397        GLXFBConfig retval = fbConfigs[0];
398        XFree(fbConfigs);
399
400        return retval;
401    }
402
403};
Note: See TracBrowser for help on using the repository browser.