Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

GLXPBufferStreams.cpp

00001 // Sh: A GPU metaprogramming language.
00002 //
00003 // Copyright (c) 2003 University of Waterloo Computer Graphics Laboratory
00004 // Project administrator: Michael D. McCool
00005 // Authors: Zheng Qin, Stefanus Du Toit, Kevin Moule, Tiberiu S. Popa,
00006 //          Michael D. McCool
00007 // 
00008 // This software is provided 'as-is', without any express or implied
00009 // warranty. In no event will the authors be held liable for any damages
00010 // arising from the use of this software.
00011 // 
00012 // Permission is granted to anyone to use this software for any purpose,
00013 // including commercial applications, and to alter it and redistribute it
00014 // freely, subject to the following restrictions:
00015 // 
00016 // 1. The origin of this software must not be misrepresented; you must
00017 // not claim that you wrote the original software. If you use this
00018 // software in a product, an acknowledgment in the product documentation
00019 // would be appreciated but is not required.
00020 // 
00021 // 2. Altered source versions must be plainly marked as such, and must
00022 // not be misrepresented as being the original software.
00023 // 
00024 // 3. This notice may not be removed or altered from any source
00025 // distribution.
00027 #include <iostream>
00028 #include <sstream>
00029 
00030 #include "ShError.hpp"
00031 #include "ShEnvironment.hpp"
00032 #include "GLXPBufferStreams.hpp"
00033 
00034 // Extensions for ATI and Nvidia
00035 
00036 #ifndef GLX_RGBA_FLOAT_ATI_BIT
00037 #define GLX_RGBA_FLOAT_ATI_BIT          0x00000100
00038 #endif /* GLX_RGBA_FLOAT_ATI_BIT */
00039 
00040 #ifndef GLX_FLOAT_COMPONENTS_NV
00041 #define GLX_FLOAT_COMPONENTS_NV         0x20B0
00042 #endif /* GLX_FLOAT_COMPONENTS_NV */
00043 
00044 namespace shgl {
00045 
00046   using namespace SH;
00047 
00048   class GLXPBufferStreamException : public ShException
00049     {
00050     public:
00051       GLXPBufferStreamException(const std::string& message) :
00052         ShException("GLX PBuffer Stream Execution: " + message)
00053         {
00054         }
00055     };
00056 
00057   GLXPBufferStreams::GLXPBufferStreams(void) :
00058     m_display(NULL),
00059     m_orig_drawable(0),
00060     m_orig_context(0)
00061     {
00062     }
00063 
00064   GLXPBufferStreams::~GLXPBufferStreams()
00065     {
00066     }
00067 
00068   StreamStrategy* GLXPBufferStreams::create(void)
00069     {
00070     return new GLXPBufferStreams;
00071     }
00072 
00073   FloatExtension GLXPBufferStreams::setupContext(int width, int height)
00074     {
00075     // initialize m_display if it hasn't already been done 
00076     if (!m_display)
00077       {
00078       m_display = glXGetCurrentDisplay();
00079       if (!m_display)
00080         {
00081         m_display = XOpenDisplay(0);
00082         if (!m_display)
00083           {
00084           shError(GLXPBufferStreamException("Could not open X display"));
00085           }
00086         }
00087       }
00088 
00089     // grab the current GLX context/drawable, they will
00090     // be restore after the stream execution is finished
00091     m_orig_context = glXGetCurrentContext();
00092     m_orig_drawable = glXGetCurrentDrawable();
00093     
00094     // search the crrent list of pbuffers for an applicable one
00095     ShGLXPBufferInfo match;
00096     for(std::list<ShGLXPBufferInfo>::iterator itr = m_infos.begin();
00097         itr != m_infos.end();
00098         itr++)
00099       {
00100       if ((*itr).valid() && (*itr).width == width && (*itr).height == height)
00101         {
00102         match = (*itr);
00103         break;
00104         }
00105       }
00106 
00107     // if a valid match wasn't found then create a new
00108     // context and add it to the list of infos
00109     if (!match.valid())
00110       {
00111       match = createContext(width, height);
00112       m_infos.push_back(match);
00113       }
00114 
00115     // Activate the pbuffer/context 
00116     if (!glXMakeCurrent(m_display, match.pbuffer, match.context))
00117       {
00118       std::stringstream msg;
00119       msg << "glXMakeCurrent failed";
00120       shError(GLXPBufferStreamException(msg.str()));
00121       }
00122 
00123     return match.extension;
00124     }
00125 
00126   void GLXPBufferStreams::restoreContext(void)
00127     {
00128     if (m_display && m_orig_drawable && m_orig_context)
00129       {
00130       if (!glXMakeCurrent(m_display, m_orig_drawable, m_orig_context))
00131         {
00132         std::stringstream msg;
00133         msg << "glXMakeCurrent failed";
00134         shError(GLXPBufferStreamException(msg.str()));
00135         }
00136       else
00137         {
00138         m_orig_context = 0;
00139         m_orig_drawable = 0;
00140         }
00141       }
00142     }
00143 
00144   ShGLXPBufferInfo GLXPBufferStreams::createContext(int width, int height)
00145     {
00146     ShGLXPBufferInfo ret;
00147     ret.width = width;
00148     ret.height = height;
00149 
00150     // Figure out what extension we're using
00151     int scrnum = DefaultScreen(m_display);
00152     
00153     std::vector<int> fb_base_attribs;
00154     fb_base_attribs.push_back(GLX_DOUBLEBUFFER); fb_base_attribs.push_back(False);
00155     fb_base_attribs.push_back(GLX_RED_SIZE); fb_base_attribs.push_back(32);
00156     fb_base_attribs.push_back(GLX_GREEN_SIZE); fb_base_attribs.push_back(32);
00157     fb_base_attribs.push_back(GLX_BLUE_SIZE); fb_base_attribs.push_back(32);
00158     fb_base_attribs.push_back(GLX_DRAWABLE_TYPE); fb_base_attribs.push_back(GLX_PBUFFER_BIT);
00159   
00160     GLXFBConfig* fb_config = 0;
00161 
00162     // Try NVIDIA
00163     if (!fb_config)
00164       {
00165       std::vector<int> fb_attribs(fb_base_attribs);
00166       fb_attribs.push_back(GLX_RENDER_TYPE); fb_attribs.push_back(GLX_RGBA_BIT);
00167       fb_attribs.push_back(GLX_FLOAT_COMPONENTS_NV); fb_attribs.push_back(True);
00168       fb_attribs.push_back(None);
00169     
00170       int items = 0;
00171       fb_config = glXChooseFBConfig(m_display, scrnum, &fb_attribs.front(), &items);
00172       if (fb_config)
00173         {
00174         ret.extension = SH_ARB_NV_FLOAT_BUFFER;
00175         }
00176       }
00177 
00178     // Try ATI
00179     if (!fb_config)
00180       {
00181       std::vector<int> fb_attribs(fb_base_attribs);
00182       fb_attribs.push_back(GLX_RENDER_TYPE); fb_attribs.push_back(GLX_RGBA_FLOAT_ATI_BIT);
00183       fb_attribs.push_back(None);
00184     
00185       int items = 0;
00186       fb_config = glXChooseFBConfig(m_display, scrnum, &fb_attribs.front(), &items);
00187       if (fb_config)
00188         {
00189         ret.extension = SH_ARB_ATI_PIXEL_FORMAT_FLOAT;
00190         }
00191       }
00192 
00193     if (!fb_config)
00194       {
00195       shError(GLXPBufferStreamException("Could not get GLX FB Config!\n"
00196                                         "Your card may not support the appropriate extensions."));
00197       }
00198 
00199     if (ret.extension == SH_ARB_NO_FLOAT_EXT)
00200       {
00201       shError(GLXPBufferStreamException("Could not choose a floating-point extension!\n"
00202                                         "Your card may not support the appropriate extensions."));
00203       }
00204 
00205     // Set up the pbuffer
00206     int pbuffer_attribs[] = {
00207       GLX_PBUFFER_WIDTH, width,
00208       GLX_PBUFFER_HEIGHT, height,
00209       GLX_LARGEST_PBUFFER, False,
00210       None
00211     };
00212 
00213     ret.pbuffer = glXCreatePbuffer(m_display, fb_config[0], pbuffer_attribs);
00214     if (!ret.pbuffer)
00215       {
00216       shError(GLXPBufferStreamException("Could not make pbuffer!"));
00217       }
00218   
00219     ret.context = glXCreateNewContext(m_display, fb_config[0], GLX_RGBA_TYPE, 0, True);
00220     if (!ret.context)
00221       {
00222       // TODO: delete pbuffer
00223       shError(GLXPBufferStreamException("Could not create PBuffer context"));
00224       }
00225 
00226     return ret;
00227     }
00228 
00229 }

Generated on Mon Jan 24 18:36:29 2005 for Sh by  doxygen 1.4.1