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