source: OGRE/trunk/ogrenew/RenderSystems/GL/src/GLX/OgreGLXUtils.cpp @ 657

Revision 657, 15.8 KB checked in by mattausch, 18 years ago (diff)

added ogre dependencies and patched ogre sources

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