1 /***********************************************************************
2     created:    Sun Feb 1 2009
3     author:     Paul D Turner
4 *************************************************************************/
5 /***************************************************************************
6  *   Copyright (C) 2004 - 2011 Paul D Turner & The CEGUI Development Team
7  *
8  *   Permission is hereby granted, free of charge, to any person obtaining
9  *   a copy of this software and associated documentation files (the
10  *   "Software"), to deal in the Software without restriction, including
11  *   without limitation the rights to use, copy, modify, merge, publish,
12  *   distribute, sublicense, and/or sell copies of the Software, and to
13  *   permit persons to whom the Software is furnished to do so, subject to
14  *   the following conditions:
15  *
16  *   The above copyright notice and this permission notice shall be
17  *   included in all copies or substantial portions of the Software.
18  *
19  *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20  *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21  *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22  *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23  *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24  *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25  *   OTHER DEALINGS IN THE SOFTWARE.
26  ***************************************************************************/
27 #include "CEGUI/RendererModules/OpenGL/GL.h"
28 #include "CEGUI/RendererModules/OpenGL/ApplePBTextureTarget.h"
29 #include "CEGUI/Exceptions.h"
30 #include "CEGUI/RenderQueue.h"
31 #include "CEGUI/GeometryBuffer.h"
32 
33 #include "CEGUI/RendererModules/OpenGL/RendererBase.h"
34 #include "CEGUI/RendererModules/OpenGL/Texture.h"
35 
36 // Start of CEGUI namespace section
37 namespace CEGUI
38 {
39 //----------------------------------------------------------------------------//
40 const float OpenGLApplePBTextureTarget::DEFAULT_SIZE = 128.0f;
41 
42 //----------------------------------------------------------------------------//
43 static CGLPixelFormatAttribute fmtAttrs[] =
44 {
45     kCGLPFAAccelerated,
46     kCGLPFAPBuffer,
47     kCGLPFAColorSize, static_cast<CGLPixelFormatAttribute>(24),
48     kCGLPFAAlphaSize, static_cast<CGLPixelFormatAttribute>(8),
49     static_cast<CGLPixelFormatAttribute>(0)
50 };
51 
52 //----------------------------------------------------------------------------//
OpenGLApplePBTextureTarget(OpenGLRendererBase & owner)53 OpenGLApplePBTextureTarget::OpenGLApplePBTextureTarget(OpenGLRendererBase& owner) :
54     OpenGLTextureTarget(owner),
55     d_pbuffer(0),
56     d_context(0)
57 {
58     if (!GLEW_APPLE_pixel_buffer)
59         CEGUI_THROW(RendererException("GL_APPLE_pixel_buffer extension is "
60             "needed to use OpenGLApplePBTextureTarget!"));
61 
62     initialiseTexture();
63 
64     CGLError err;
65     CGLContextObj cctx = CGLGetCurrentContext();
66     if (err = CGLGetVirtualScreen(cctx, &d_screen))
67         CEGUI_THROW(RendererException(
68             "CGLGetVirtualScreen failed: " + String(CGLErrorString(err))));
69 
70     GLint fmt_count;
71     CGLPixelFormatObj pix_fmt;
72     if (err = CGLChoosePixelFormat(fmtAttrs, &pix_fmt, &fmt_count))
73         CEGUI_THROW(RendererException(
74             "CGLChoosePixelFormat failed: " + String(CGLErrorString(err))));
75 
76     err = CGLCreateContext(pix_fmt, cctx, &d_context);
77     CGLDestroyPixelFormat(pix_fmt);
78 
79     if (err)
80         CEGUI_THROW(RendererException(
81             "CGLCreateContext failed: " + String(CGLErrorString(err))));
82 
83     // set default size (and cause initialisation of the pbuffer)
84     CEGUI_TRY
85     {
86         declareRenderSize(Sizef(DEFAULT_SIZE, DEFAULT_SIZE));
87     }
88     CEGUI_CATCH(...)
89     {
90         CGLDestroyContext(d_context);
91         CEGUI_RETHROW;
92     }
93 
94     // set these states one-time since we have our own context
95     enablePBuffer();
96     glEnable(GL_SCISSOR_TEST);
97     glEnable(GL_TEXTURE_2D);
98     glEnable(GL_BLEND);
99     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
100     glEnableClientState(GL_VERTEX_ARRAY);
101     glEnableClientState(GL_COLOR_ARRAY);
102     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
103     glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
104     glDisableClientState(GL_INDEX_ARRAY);
105     glDisableClientState(GL_NORMAL_ARRAY);
106     glDisableClientState(GL_FOG_COORDINATE_ARRAY);
107     glDisableClientState(GL_EDGE_FLAG_ARRAY);
108     glClearColor(0,0,0,0);
109     disablePBuffer();
110 }
111 
112 //----------------------------------------------------------------------------//
~OpenGLApplePBTextureTarget()113 OpenGLApplePBTextureTarget::~OpenGLApplePBTextureTarget()
114 {
115     if (d_context)
116         CGLDestroyContext(d_context);
117 
118     if (d_pbuffer)
119         CGLDestroyPBuffer(d_pbuffer);
120 }
121 
122 //----------------------------------------------------------------------------//
activate()123 void OpenGLApplePBTextureTarget::activate()
124 {
125     enablePBuffer();
126 
127     // we clear the blend mode here so the next setupRenderingBlendMode call
128     // is forced to update states for our local context.
129     d_owner.setupRenderingBlendMode(BM_INVALID);
130 
131     OpenGLTextureTarget::activate();
132 }
133 
134 //----------------------------------------------------------------------------//
deactivate()135 void OpenGLApplePBTextureTarget::deactivate()
136 {
137     glFlush();
138     OpenGLTextureTarget::deactivate();
139 
140     // Clear the blend mode again so the next setupRenderingBlendMode call
141     // is forced to update states for the main / previous context.
142     d_owner.setupRenderingBlendMode(BM_INVALID);
143 
144     disablePBuffer();
145 }
146 
147 //----------------------------------------------------------------------------//
clear()148 void OpenGLApplePBTextureTarget::clear()
149 {
150     enablePBuffer();
151     glDisable(GL_SCISSOR_TEST);
152     glClear(GL_COLOR_BUFFER_BIT);
153     glEnable(GL_SCISSOR_TEST);
154     disablePBuffer();
155 }
156 
157 //----------------------------------------------------------------------------//
declareRenderSize(const Sizef & sz)158 void OpenGLApplePBTextureTarget::declareRenderSize(const Sizef& sz)
159 {
160     // exit if current size is enough
161     if ((d_area.getWidth() >= sz.d_width) &&
162         (d_area.getHeight() >= sz.d_height))
163             return;
164 
165     setArea(Rectf(d_area.getPosition(), d_owner.getAdjustedTextureSize(sz)));
166 
167     // dump any previous pbuffer
168     if (d_pbuffer)
169     {
170         CGLDestroyPBuffer(d_pbuffer);
171         d_pbuffer = 0;
172     }
173 
174     CGLError err;
175     if (err = CGLCreatePBuffer(d_area.getWidth(), d_area.getHeight(),
176                                 GL_TEXTURE_2D, GL_RGBA, 0, &d_pbuffer))
177     {
178         CEGUI_THROW(RendererException(
179             "CGLCreatePBuffer failed: " + String(CGLErrorString(err))));
180     }
181 
182     if (err = CGLSetPBuffer(d_context, d_pbuffer, 0, 0, d_screen))
183         CEGUI_THROW(RendererException(
184             "CGLSetPBuffer failed: " + String(CGLErrorString(err))));
185 
186     clear();
187 
188     // make d_texture use the pbuffer as it's data source
189     // save old texture binding
190     GLuint old_tex;
191     glGetIntegerv(GL_TEXTURE_BINDING_2D, reinterpret_cast<GLint*>(&old_tex));
192 
193     glBindTexture(GL_TEXTURE_2D, d_texture);
194     err = CGLTexImagePBuffer(CGLGetCurrentContext(), d_pbuffer, GL_FRONT);
195 
196     // restore previous texture binding.
197     glBindTexture(GL_TEXTURE_2D, old_tex);
198 
199     if (err)
200         CEGUI_THROW(RendererException(
201             "CGLTexImagePBuffer failed: " + String(CGLErrorString(err))));
202 
203     // ensure CEGUI::Texture is wrapping real GL texture and has correct size
204     d_CEGUITexture->setOpenGLTexture(d_texture, d_area.getSize());
205 }
206 
207 //----------------------------------------------------------------------------//
initialiseTexture()208 void OpenGLApplePBTextureTarget::initialiseTexture()
209 {
210     // save old texture binding
211     GLuint old_tex;
212     glGetIntegerv(GL_TEXTURE_BINDING_2D, reinterpret_cast<GLint*>(&old_tex));
213 
214     // create and setup texture which pbuffer content will be loaded to
215     glGenTextures(1, &d_texture);
216     glBindTexture(GL_TEXTURE_2D, d_texture);
217     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
218     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
219 
220     // restore previous texture binding.
221     glBindTexture(GL_TEXTURE_2D, old_tex);
222 }
223 
224 //----------------------------------------------------------------------------//
enablePBuffer() const225 void OpenGLApplePBTextureTarget::enablePBuffer() const
226 {
227     if (CGLGetCurrentContext() != d_context)
228     {
229         d_prevContext = CGLGetCurrentContext();
230         CGLSetCurrentContext(d_context);
231     }
232 }
233 
234 //----------------------------------------------------------------------------//
disablePBuffer() const235 void OpenGLApplePBTextureTarget::disablePBuffer() const
236 {
237     if (CGLGetCurrentContext() == d_context)
238         CGLSetCurrentContext(d_prevContext);
239 }
240 
241 //----------------------------------------------------------------------------//
grabTexture()242 void OpenGLApplePBTextureTarget::grabTexture()
243 {
244     if (d_pbuffer)
245     {
246         CGLDestroyPBuffer(d_pbuffer);
247         d_pbuffer = 0;
248     }
249 
250     OpenGLTextureTarget::grabTexture();
251 }
252 
253 //----------------------------------------------------------------------------//
restoreTexture()254 void OpenGLApplePBTextureTarget::restoreTexture()
255 {
256     const Sizef sz(d_area.getSize());
257     d_area.setSize(Sizef(0.0f, 0.0f));
258 
259     OpenGLTextureTarget::restoreTexture();
260     initialiseTexture();
261     declareRenderSize(sz);
262 }
263 
264 //----------------------------------------------------------------------------//
265 
266 } // End of  CEGUI namespace section
267