soc-2008-mxcurioni: merged changes to revision 14798, compilation works for rendering...
[blender-staging.git] / source / blender / freestyle / intern / rendering / pbuffer.cpp
1 #include "pbuffer.h"
2
3 #include <memory.h>
4
5 #define MAX_PFORMATS 256
6 #define MAX_ATTRIBS  32
7 #define PBUFFER_AS_TEXTURE 2048
8
9 //************************************************************
10 // Implementation of PBuffer
11 //************************************************************
12 /*!
13  * Creates a PBuffer of size \p w by \p h, eith mode \p mode.
14  */
15 PBuffer::PBuffer(const unsigned int w,
16                  const unsigned int h,
17                  const int format) 
18   : format_(format),
19     sharedContext_(false),
20     sharedLists_(false),
21     display_(NULL),
22     glxPbuffer_(0),
23     glxContext_(0), 
24     width_(w),
25     height_(h)
26 {
27 }    
28 /*!
29  * Initialize the pbuffer. If \p shareContext is true, then the currently
30  * active context with be shared by the pbuffer, meaning for example that
31  * textures objects or display lists of the currently active GL context will
32  * be available to the pbuffer.  If you want it to be the case just for
33  * display lists, set \p sharedContext to false and \p shareLists to true.
34  * 
35  * This function is outside of the constructor for several reasons. First it
36  * might raise exceptions so it cannot be done in the constructor. Secondly,
37  * it is using the current context for sharing so you might want to create
38  * the pbuffer at a moment where this context is not yet active, and then
39  * initialise it once the context has been created and activated.
40  *
41  * Return false if creation failed.
42  */
43 bool
44 PBuffer::create(const bool shareContext, const bool shareLists)
45 {
46   // Set display and screen
47   Display *pDisplay     = glXGetCurrentDisplay();
48   if (pDisplay == NULL)
49   {
50     pDisplay = XOpenDisplay(NULL);
51   }
52   int iScreen           = DefaultScreen(pDisplay);
53   GLXContext glxContext = glXGetCurrentContext();
54   
55   GLXFBConfig *glxConfig;
56   int iConfigCount;   
57     
58   sharedContext_ = shareContext;
59   sharedLists_ = shareLists;
60
61   if (sharedContext_)
62   {
63     glxConfig = glXGetFBConfigs(pDisplay, iScreen, &iConfigCount);
64     if (!glxConfig)
65     {
66 //       "pbuffer creation error:  glXGetFBConfigs() failed"
67       return false;
68     }
69   }  
70   else
71   {
72     int iAttributes[2*MAX_ATTRIBS];
73     int curAttrib = 0;
74         
75     memset(iAttributes, 0, 2*MAX_ATTRIBS*sizeof(int));        
76             
77     iAttributes[2*curAttrib  ] = GLX_DRAWABLE_TYPE;
78     iAttributes[2*curAttrib+1] = GLX_PBUFFER_BIT;
79     curAttrib++;
80         
81     if (format_ & ColorIndex)
82     {
83       iAttributes[2*curAttrib  ] = GLX_RENDER_TYPE;
84       iAttributes[2*curAttrib+1] = GLX_COLOR_INDEX_BIT;
85       curAttrib++;
86     }
87     else
88     {
89       iAttributes[2*curAttrib  ] = GLX_RENDER_TYPE;
90       iAttributes[2*curAttrib+1] = GLX_RGBA_BIT;
91       iAttributes[2*curAttrib  ] = GLX_ALPHA_SIZE;
92       iAttributes[2*curAttrib+1] = 8;
93       curAttrib++;
94     }
95         
96     if (format_ & DoubleBuffer)
97     {
98       iAttributes[2*curAttrib  ] = GLX_DOUBLEBUFFER;
99       iAttributes[2*curAttrib+1] = true;
100       curAttrib++;
101     }
102     else
103     {
104       iAttributes[2*curAttrib  ] = GLX_DOUBLEBUFFER;
105       iAttributes[2*curAttrib+1] = false;
106       curAttrib++;
107     }  
108     if (format_ & DepthBuffer)
109     {
110       iAttributes[2*curAttrib  ] = GLX_DEPTH_SIZE;
111       iAttributes[2*curAttrib+1] = 1;
112       curAttrib++;
113     }
114     else
115     {
116       iAttributes[2*curAttrib  ] = GLX_DEPTH_SIZE;
117       iAttributes[2*curAttrib+1] = 0;
118       curAttrib++;
119     }    
120         
121     if (format_ & StencilBuffer)
122     {
123       iAttributes[2*curAttrib  ] = GLX_STENCIL_SIZE;
124       iAttributes[2*curAttrib+1] = 1;
125       curAttrib++;
126     }
127     else
128     {
129       iAttributes[2*curAttrib  ] = GLX_STENCIL_SIZE;
130       iAttributes[2*curAttrib+1] = 0;
131       curAttrib++;
132     }
133
134     iAttributes[2*curAttrib  ] = None;
135     
136     glxConfig = glXChooseFBConfigSGIX(pDisplay, iScreen, iAttributes, &iConfigCount);
137     if (!glxConfig)
138     {
139       // "pbuffer creation error:  glXChooseFBConfig() failed"
140       return false;
141     }
142   }
143    
144   int attributes[5];
145   int iCurAttrib = 0;
146     
147   memset(attributes, 0, 5*sizeof(int));
148
149   attributes[2*iCurAttrib  ] = GLX_LARGEST_PBUFFER;
150   attributes[2*iCurAttrib+1] = true;
151   iCurAttrib++;
152
153   attributes[2*iCurAttrib  ] = GLX_PRESERVED_CONTENTS;
154   attributes[2*iCurAttrib+1] = true;
155   iCurAttrib++;
156     
157   attributes[2*iCurAttrib  ] = None;
158
159   glxPbuffer_ = glXCreateGLXPbufferSGIX(pDisplay, glxConfig[0],
160                                         width_, height_, attributes);
161     
162   if (!glxPbuffer_)
163   {
164     // "pbuffer creation error:  glXCreatePbuffer() failed"
165     return false;
166   }
167     
168   if (sharedContext_)
169   {
170     glxContext_ = glxContext;
171   }
172   else
173   {
174     if (format_ & ColorIndex)
175     {
176       if (sharedLists_)
177         glxContext_ = glXCreateContextWithConfigSGIX(pDisplay,
178                                                      glxConfig[0],
179                                                      GLX_COLOR_INDEX_TYPE,
180                                                      glxContext, true);
181       else
182         glxContext_ = glXCreateContextWithConfigSGIX(pDisplay,
183                                                      glxConfig[0],
184                                                      GLX_COLOR_INDEX_TYPE,
185                                                      NULL, true);
186     }
187     else
188     {
189       if (sharedLists_)
190         glxContext_ = glXCreateContextWithConfigSGIX(pDisplay,
191                                                      glxConfig[0],
192                                                      GLX_RGBA_TYPE,
193                                                      glxContext, true);
194       else
195         glxContext_ = glXCreateContextWithConfigSGIX(pDisplay,
196                                                      glxConfig[0],
197                                                      GLX_RGBA_TYPE,
198                                                      NULL, true);
199     }
200
201     if (!glxConfig)
202     {
203       // "pbuffer creation error:  glXCreateNewContext() failed"
204       return false;
205     }
206   }
207
208   display_ = pDisplay;
209
210   glXQueryGLXPbufferSGIX(display_, glxPbuffer_, GLX_WIDTH, &width_);
211   glXQueryGLXPbufferSGIX(display_, glxPbuffer_, GLX_HEIGHT, &height_);
212
213   return true;
214 }
215 /*!
216  * Destroy the pbuffer
217  */
218 PBuffer::~PBuffer()
219 {
220   if (glxPbuffer_)
221   {
222     glXDestroyGLXPbufferSGIX(display_, glxPbuffer_);        
223   }
224 }
225 /*!
226  * Activate the pbuffer as the current GL context. All subsequents GL
227  * commands will now affect the pbuffer. If you want to push/pop the current
228  * OpenGL context use subclass PBufferEx instead.
229  *
230  * Return false if it failed.
231  */
232 bool
233 PBuffer::makeCurrent()
234 {
235   return glXMakeCurrent(display_, glxPbuffer_, glxContext_);
236 }
237 /*!
238  * Return the width of the pbuffer
239  */
240 unsigned int
241 PBuffer::width() const
242 {
243   return width_;
244 }
245 /*!
246  * Return the height of the pbuffer
247  */
248 unsigned int
249 PBuffer::height() const
250 {
251   return height_;
252 }
253 //************************************************************
254 // Implementation of PBufferEx
255 //************************************************************
256 PBufferEx::PBufferEx(const unsigned int width,
257                      const unsigned int height,
258                      const int mode)
259   : PBuffer(width, height, mode),
260     oldDisplay_(NULL),
261     glxOldDrawable_(0),
262     glxOldContext_(0)
263 {
264 }
265 /*!
266  * Activate the pbuffer as the current GL context. All subsequents GL
267  * commands will now affect the pbuffer. Once you are done with you GL
268  * commands, you can call endCurrent() to restore the context that was active
269  * when you call makeCurrent().
270  *
271  * Return false if it failed.
272  */
273 bool
274 PBufferEx::makeCurrent()
275 {
276   oldDisplay_ = glXGetCurrentDisplay();
277   glxOldDrawable_ = glXGetCurrentDrawable();
278   glxOldContext_ = glXGetCurrentContext();
279   
280   return PBuffer::makeCurrent();
281 }
282 /*!
283  * Restore the GL context that was active when makeCurrent() was called.
284  *
285  * Return false if it failed.
286  */
287 bool
288 PBufferEx::endCurrent()
289 {
290   return glXMakeCurrent(oldDisplay_, glxOldDrawable_, glxOldContext_);
291 }
292