root/OpenSceneGraph/trunk/src/osgViewer/PixelBufferX11.cpp @ 13130

Revision 13130, 14.1 kB (checked in by robert, 13 days ago)

Moved widgets from VolumeEditorWidget? to TransferFunctionWidget?, and widget utilities into WidgetUtils?.

  • Property svn:eol-style set to native
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
13
14/* Note, elements of PixelBufferX11 have used Prodcer/RenderSurface_X11.cpp as both
15 * a guide to use of X11/GLX and copiying directly in the case of setBorder().
16 * These elements are license under OSGPL as above, with Copyright (C) 2001-2004  Don Burns.
17 */
18
19#include <osgViewer/api/X11/PixelBufferX11>
20#include <osgViewer/api/X11/GraphicsWindowX11>
21#include <osg/GLExtensions>
22
23#include <X11/Xlib.h>
24
25#include <unistd.h>
26
27using namespace osgViewer;
28
29PixelBufferX11::PixelBufferX11(osg::GraphicsContext::Traits* traits)
30  : _valid(false),
31    _pbuffer(0),
32    _visualInfo(0),
33    _initialized(false),
34    _realized(false),
35    _useGLX1_3(false)
36{
37    _traits = traits;
38
39    init();
40
41    if (valid())
42    {
43        setState( new osg::State );
44        getState()->setGraphicsContext(this);
45
46        if (_traits.valid() && _traits->sharedContext.valid())
47        {
48            getState()->setContextID( _traits->sharedContext->getState()->getContextID() );
49            incrementContextIDUsageCount( getState()->getContextID() );
50        }
51        else
52        {
53            getState()->setContextID( osg::GraphicsContext::createNewContextID() );
54        }
55
56    }
57}
58
59PixelBufferX11::~PixelBufferX11()
60{
61    close(true);
62}
63
64#if defined(GLX_VERSION_1_3) || defined(GLX_SGIX_pbuffer)
65bool PixelBufferX11::createVisualInfo()
66{
67    typedef std::vector<int> Attributes;
68    Attributes attributes;
69
70    attributes.push_back(GLX_USE_GL);
71
72    attributes.push_back(GLX_RGBA);
73
74    if (_traits->doubleBuffer) attributes.push_back(GLX_DOUBLEBUFFER);
75
76    attributes.push_back(GLX_RED_SIZE); attributes.push_back(_traits->red);
77    attributes.push_back(GLX_GREEN_SIZE); attributes.push_back(_traits->green);
78    attributes.push_back(GLX_BLUE_SIZE); attributes.push_back(_traits->blue);
79    attributes.push_back(GLX_DEPTH_SIZE); attributes.push_back(_traits->depth);
80
81    if (_traits->alpha) { attributes.push_back(GLX_ALPHA_SIZE); attributes.push_back(_traits->alpha); }
82
83    if (_traits->stencil) { attributes.push_back(GLX_STENCIL_SIZE); attributes.push_back(_traits->stencil); }
84
85#if defined(GLX_SAMPLE_BUFFERS) && defined (GLX_SAMPLES)
86
87    if (_traits->sampleBuffers) { attributes.push_back(GLX_SAMPLE_BUFFERS); attributes.push_back(_traits->sampleBuffers); }
88    if (_traits->sampleBuffers) { attributes.push_back(GLX_SAMPLES); attributes.push_back(_traits->samples); }
89
90#endif
91    // TODO
92    //  GLX_AUX_BUFFERS
93    //  GLX_ACCUM_RED_SIZE
94    //  GLX_ACCUM_GREEN_SIZE
95
96    attributes.push_back(None);
97
98    _visualInfo = glXChooseVisual( _display, _traits->screenNum, &(attributes.front()) );
99
100    return _visualInfo != 0;
101}
102
103void PixelBufferX11::init()
104{
105    if (_initialized) return;
106
107    if (!_traits)
108    {
109        _valid = false;
110        return;
111    }
112
113    if (_traits->target != 0)
114    {
115        // we don't support Pbuffer render to texture under GLX.
116        _valid = false;
117        return;
118    }
119
120
121    _display = XOpenDisplay(_traits->displayName().c_str());
122
123    unsigned int screen = _traits->screenNum;
124
125    if (!_display)
126    {
127        OSG_NOTICE<<"Error: Unable to open display \"" << XDisplayName(_traits->displayName().c_str()) << "\"."<<std::endl;
128        _valid = false;
129        return;
130    }
131
132    // Query for GLX extension
133    int errorBase, eventBase;
134    if( glXQueryExtension( _display, &errorBase, &eventBase)  == False )
135    {
136        OSG_NOTICE<<"Error: " << XDisplayName(_traits->displayName().c_str()) <<" has no GLX extension." << std::endl;
137
138        XCloseDisplay( _display );
139        _display = 0;
140        _valid = false;
141        return;
142    }
143
144    // OSG_NOTICE<<"GLX extension, errorBase="<<errorBase<<" eventBase="<<eventBase<<std::endl;
145
146    int major, minor;
147    if (glXQueryVersion(_display, &major, &minor) == False)
148    {
149        OSG_NOTICE << "Error: " << XDisplayName(_traits->displayName().c_str())
150                                 << " can not query GLX version." << std::endl;
151        XCloseDisplay( _display );
152        _display = 0;
153        _valid = false;
154        return;
155    }
156
157    // Just be paranoid, if we are older than 1.1, we cannot even call glxQueryExtensionString
158    if (major < 1 || (1 == major && minor < 1))
159    {
160        OSG_NOTICE << "Error: " << XDisplayName(_traits->displayName().c_str())
161                                 << " GLX version " << major << "." << minor << " is too old." << std::endl;
162        XCloseDisplay( _display );
163        _display = 0;
164        _valid = false;
165        return;
166    }
167
168    bool haveGLX1_3 = false;
169    bool haveSGIX_pbuffer = false;
170
171    // We need to have at least GLX 1.3 to use getFBConfigFromVisual and glXCreatePbuffer
172    if (1 < major || (1 == major && 3 <= minor))
173    {
174        haveGLX1_3 = true;
175    }
176
177#if defined(GLX_VERSION_1_1)
178    // We need at least GLX 1.1 for glXQueryExtensionsString
179    if (!haveGLX1_3 && 1 <= minor)
180    {
181        const char *extensions = glXQueryExtensionsString(_display, screen);
182        haveSGIX_pbuffer = osg::isExtensionInExtensionString("GLX_SGIX_pbuffer", extensions)
183           && osg::isExtensionInExtensionString("GLX_SGIX_fbconfig", extensions);
184    }
185#endif
186
187    if (!haveGLX1_3 && !haveSGIX_pbuffer)
188    {
189        OSG_NOTICE << "Error: " << XDisplayName(_traits->displayName().c_str())
190                                 << " no Pbuffer support in GLX available." << std::endl;
191        XCloseDisplay( _display );
192        _display = 0;
193        _valid = false;
194        return;
195    }
196
197
198    if (!createVisualInfo())
199    {
200        _traits->red /= 2;
201        _traits->green /= 2;
202        _traits->blue /= 2;
203        _traits->alpha /= 2;
204        _traits->depth /= 2;
205
206        OSG_INFO<<"Relaxing traits"<<std::endl;
207
208        if (!createVisualInfo())
209        {
210            OSG_NOTICE<<"Error: Not able to create requested visual." << std::endl;
211            XCloseDisplay( _display );
212            _display = 0;
213            _valid = false;
214            return;
215        }
216    }
217
218    // get any shared GLX contexts
219    GraphicsHandleX11* graphicsHandleX11 = dynamic_cast<GraphicsHandleX11*>(_traits->sharedContext.get());
220    Context sharedContext = graphicsHandleX11 ? graphicsHandleX11->getContext() : 0;
221
222    _context = glXCreateContext( _display, _visualInfo, sharedContext, True );
223
224    if (!_context)
225    {
226        OSG_NOTICE<<"Error: Unable to create OpenGL graphics context."<<std::endl;
227        XCloseDisplay( _display );
228        _display = 0;
229        _valid = false;
230        return;
231    }
232
233#ifdef GLX_VERSION_1_3
234    // First try the regular glx extension if we have a new enough version available.
235    if (haveGLX1_3)
236    {
237        int nelements;
238        GLXFBConfig *fbconfigs = glXGetFBConfigs( _display, screen, &nelements );
239        for ( int i = 0; i < nelements; ++i )
240        {
241            int visual_id;
242            if ( glXGetFBConfigAttrib( _display, fbconfigs[i], GLX_VISUAL_ID, &visual_id ) == 0 )
243            {
244                if ( !_pbuffer && (unsigned int)visual_id == _visualInfo->visualid )
245                {
246                    typedef std::vector <int> AttributeList;
247
248                    AttributeList attributes;
249                    attributes.push_back( GLX_PBUFFER_WIDTH );
250                    attributes.push_back( _traits->width );
251                    attributes.push_back( GLX_PBUFFER_HEIGHT );
252                    attributes.push_back( _traits->height );
253                    attributes.push_back( GLX_LARGEST_PBUFFER );
254                    attributes.push_back( GL_TRUE );
255                    attributes.push_back( 0L );
256
257                    _pbuffer = glXCreatePbuffer(_display, fbconfigs[i], &attributes.front() );
258                    _useGLX1_3 = true;
259                }
260            }
261        }
262        if (_pbuffer)
263        {
264            int iWidth = 0;
265            int iHeight = 0;
266            glXQueryDrawable(_display, _pbuffer, GLX_WIDTH  , (unsigned int *)&iWidth);
267            glXQueryDrawable(_display, _pbuffer, GLX_HEIGHT , (unsigned int *)&iHeight);
268
269            if (_traits->width != iWidth || _traits->height != iHeight)
270            {
271                OSG_NOTICE << "PixelBufferX11::init(), pbuffer created with different size then requsted" << std::endl;
272                OSG_NOTICE << "\tRequested size (" << _traits->width << "," << _traits->height << ")" << std::endl;
273                OSG_NOTICE << "\tPbuffer size (" << iWidth << "," << iHeight << ")" << std::endl;
274                _traits->width  = iWidth;
275                _traits->height = iHeight;
276            }
277        }
278        XFree( fbconfigs );
279    }
280#endif
281
282#ifdef GLX_SGIX_pbuffer
283    // If we still have no pbuffer but a capable display with the SGIX extension, try to use that
284    if (!_pbuffer && haveSGIX_pbuffer)
285    {
286        GLXFBConfigSGIX fbconfig = glXGetFBConfigFromVisualSGIX( _display, _visualInfo );
287        typedef std::vector <int> AttributeList;
288
289        AttributeList attributes;
290        attributes.push_back( GLX_LARGEST_PBUFFER_SGIX );
291        attributes.push_back( GL_TRUE );
292        attributes.push_back( 0L );
293
294        _pbuffer = glXCreateGLXPbufferSGIX(_display, fbconfig, _traits->width, _traits->height,  &attributes.front() );
295        if (_pbuffer)
296        {
297            int iWidth = 0;
298            int iHeight = 0;
299            glXQueryGLXPbufferSGIX(_display, _pbuffer, GLX_WIDTH_SGIX , (unsigned int *)&iWidth);
300            glXQueryGLXPbufferSGIX(_display, _pbuffer, GLX_HEIGHT_SGIX, (unsigned int *)&iHeight);
301
302            if (_traits->width != iWidth || _traits->height != iHeight)
303            {
304                OSG_NOTICE << "PixelBufferX11::init(), SGIX_pbuffer created with different size then requsted" << std::endl;
305                OSG_NOTICE << "\tRequested size (" << _traits->width << "," << _traits->height << ")" << std::endl;
306                OSG_NOTICE << "\tPbuffer size (" << iWidth << "," << iHeight << ")" << std::endl;
307                _traits->width =  iWidth;
308                _traits->height = iHeight;
309            }
310        }
311        XFree( fbconfig );
312    }
313#endif
314
315    if (!_pbuffer)
316    {
317        OSG_NOTICE<<"Error: Unable to create pbuffer."<<std::endl;
318        XCloseDisplay( _display );
319        _display = 0;
320        _context = 0;
321        _valid = false;
322        return;
323    }
324
325
326    XFlush( _display );
327    XSync( _display, 0 );
328
329    _valid = true;
330    _initialized = true;
331}
332
333void PixelBufferX11::closeImplementation()
334{
335    // OSG_NOTICE<<"Closing PixelBufferX11"<<std::endl;
336    if (_display)
337    {
338        if (_context)
339        {
340            glXDestroyContext(_display, _context );
341        }
342
343        if (_pbuffer)
344        {
345            if (_useGLX1_3)
346            {
347#ifdef GLX_VERSION_1_3
348                glXDestroyPbuffer(_display, _pbuffer);
349#endif
350            }
351            else
352            {
353#ifdef GLX_SGIX_pbuffer
354                glXDestroyGLXPbufferSGIX(_display, _pbuffer);
355#endif
356            }
357        }
358
359        XFlush( _display );
360        XSync( _display,0 );
361    }
362
363    _pbuffer = 0;
364    _context = 0;
365
366    if (_visualInfo)
367    {
368        XFree(_visualInfo);
369        _visualInfo = 0;
370    }
371
372    if (_display)
373    {
374        XCloseDisplay( _display );
375        _display = 0;
376    }
377
378    _initialized = false;
379    _realized = false;
380    _valid = false;
381}
382
383#else
384
385// fallback for non GLX1.3 versions where pbuffers are not supported.
386// note, this makes the rest of the pbuffer code a non op as init is false;
387bool PixelBufferX11::createVisualInfo()
388{
389    return false;
390}
391
392void PixelBufferX11::init()
393{
394}
395
396void PixelBufferX11::closeImplementation()
397{
398    // OSG_NOTICE<<"Closing PixelBufferX11"<<std::endl;
399    _pbuffer = 0;
400    _context = 0;
401    _initialized = false;
402    _realized = false;
403    _valid = false;
404}
405
406#endif
407
408bool PixelBufferX11::realizeImplementation()
409{
410    if (_realized)
411    {
412        OSG_NOTICE<<"PixelBufferX11::realizeImplementation() Already realized"<<std::endl;
413        return true;
414    }
415
416    if (!_initialized) init();
417
418    if (!_initialized) return false;
419
420    _realized = true;
421
422    return true;
423}
424
425bool PixelBufferX11::makeCurrentImplementation()
426{
427    if (!_realized)
428    {
429        OSG_NOTICE<<"Warning: GraphicsWindow not realized, cannot do makeCurrent."<<std::endl;
430        return false;
431    }
432
433    // OSG_NOTICE<<"PixelBufferX11::makeCurrentImplementation "<<this<<" "<<OpenThreads::Thread::CurrentThread()<<std::endl;
434
435    #ifdef OSG_USE_EGL
436        return eglMakeCurrent(_display, _pbuffer, _pbuffer, _context)==EGL_TRUE;
437    #else
438        return glXMakeCurrent( _display, _pbuffer, _context )==True;
439    #endif
440}
441
442bool PixelBufferX11::makeContextCurrentImplementation(osg::GraphicsContext* readContext)
443{
444    // OSG_NOTICE<<"PixelBufferX11::makeContextCurrentImplementation() not implementation yet."<<std::endl;
445    return makeCurrentImplementation();
446}
447
448
449bool PixelBufferX11::releaseContextImplementation()
450{
451    if (!_realized)
452    {
453        OSG_NOTICE<<"Warning: GraphicsWindow not realized, cannot do makeCurrent."<<std::endl;
454        return false;
455    }
456
457    // OSG_NOTICE<<"PixelBufferX11::releaseContextImplementation() "<<this<<" "<<OpenThreads::Thread::CurrentThread()<<std::endl;
458
459    #ifdef OSG_USE_EGL
460        return eglMakeCurrent( _display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT )==EGL_TRUE;
461    #else
462        return glXMakeCurrent( _display, None, NULL )==True;
463    #endif
464}
465
466
467void PixelBufferX11::bindPBufferToTextureImplementation(GLenum buffer)
468{
469    OSG_NOTICE<<"PixelBufferX11::bindPBufferToTextureImplementation() not implementation yet."<<std::endl;
470}
471
472void PixelBufferX11::swapBuffersImplementation()
473{
474    if (!_realized) return;
475
476    // OSG_NOTICE<<"PixelBufferX11::swapBuffersImplementation "<<this<<" "<<OpenThreads::Thread::CurrentThread()<<std::endl;
477
478    #ifdef OSG_USE_EGL
479        eglSwapBuffers( _display, _pbuffer );
480    #else
481        glXSwapBuffers( _display, _pbuffer );
482    #endif
483}
Note: See TracBrowser for help on using the browser.