00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00027 #include <iostream>
00028 #include <sstream>
00029
00030 #include "ShError.hpp"
00031 #include "ShEnvironment.hpp"
00032 #include "GLXPBufferStreams.hpp"
00033
00034
00035
00036 #ifndef GLX_RGBA_FLOAT_ATI_BIT
00037 #define GLX_RGBA_FLOAT_ATI_BIT 0x00000100
00038 #endif
00039
00040 #ifndef GLX_FLOAT_COMPONENTS_NV
00041 #define GLX_FLOAT_COMPONENTS_NV 0x20B0
00042 #endif
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
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
00090
00091 m_orig_context = glXGetCurrentContext();
00092 m_orig_drawable = glXGetCurrentDrawable();
00093
00094
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
00108
00109 if (!match.valid())
00110 {
00111 match = createContext(width, height);
00112 m_infos.push_back(match);
00113 }
00114
00115
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
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
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
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
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
00223 shError(GLXPBufferStreamException("Could not create PBuffer context"));
00224 }
00225
00226 return ret;
00227 }
00228
00229 }