1 /***********************************************************************
2     created:    Sun Jan 11 2009
3     author:     Paul D Turner
4 *************************************************************************/
5 /***************************************************************************
6  *   Copyright (C) 2004 - 2009 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/OpenGLES/Renderer.h"
28 #include "CEGUI/RendererModules/OpenGLES/Texture.h"
29 #include "CEGUI/Exceptions.h"
30 #include "CEGUI/EventArgs.h"
31 #include "CEGUI/ImageCodec.h"
32 #include "CEGUI/DynamicModule.h"
33 #include "CEGUI/RendererModules/OpenGLES/ViewportTarget.h"
34 #include "CEGUI/RendererModules/OpenGLES/GeometryBuffer.h"
35 #include "CEGUI/RendererModules/OpenGLES/FBOTextureTarget.h"
36 #include "CEGUI/Logger.h"
37 #include "CEGUI/System.h"
38 #include "CEGUI/DefaultResourceProvider.h"
39 
40 #include <sstream>
41 #include <algorithm>
42 
43 #include "CEGUI/RendererModules/OpenGLES/FBOTextureTarget.h"
44 
45 // Start of CEGUI namespace section
46 namespace CEGUI
47 {
48 //----------------------------------------------------------------------------//
49 // The following are some GL extension / version dependant related items.
50 // This is all done totally internally here; no need for external interface
51 // to show any of this.
52 //----------------------------------------------------------------------------//
53 // we only really need this with MSVC / Windows(?) and by now it should already
54 // be defined on that platform, so we just define it as empty macro so the
55 // compile does not break on other systems.
56 #ifndef APIENTRY
57 #   define APIENTRY
58 #endif
59 //! Dummy function for if real ones are not present (saves testing each render)
activeTextureDummy(GLenum)60 void APIENTRY activeTextureDummy(GLenum) {}
61 
62 //----------------------------------------------------------------------------//
63 //
64 // Here we have an internal class that allows us to implement a factory template
65 // for creating / destroying any type of TextureTarget.  The code that detects
66 // the computer's abilities will generate an appropriate factory for a
67 // TextureTarget based on what the host system can provide - or use the default
68 // 'null' factory if no suitable TextureTargets are available.
69 //
70 // base factory class - mainly used as a polymorphic interface
71 class OGLTextureTargetFactory
72 {
73 public:
OGLTextureTargetFactory()74     OGLTextureTargetFactory() {}
~OGLTextureTargetFactory()75     virtual ~OGLTextureTargetFactory() {}
create(OpenGLESRenderer &) const76     virtual TextureTarget* create(OpenGLESRenderer&) const
77         { return 0; }
destory(TextureTarget * target) const78     virtual void destory(TextureTarget* target) const
79         { delete target; }
80 };
81 
82 // template specialised class that does the real work for us
83 template<typename T>
84 class OGLTemplateTargetFactory : public OGLTextureTargetFactory
85 {
create(OpenGLESRenderer & r) const86     virtual TextureTarget* create(OpenGLESRenderer& r) const
87         { return new T(r); }
88 };
89 
90 //----------------------------------------------------------------------------//
91 String OpenGLESRenderer::d_rendererID(
92 "CEGUI::OpenGLESRenderer - Official OpenGLES based 2nd generation renderer module.");
93 
94 //----------------------------------------------------------------------------//
bootstrapSystem(const TextureTargetType tt_type,const int abi)95 OpenGLESRenderer& OpenGLESRenderer::bootstrapSystem(
96                                         const TextureTargetType tt_type,
97                                         const int abi)
98 {
99     System::performVersionTest(CEGUI_VERSION_ABI, abi, CEGUI_FUNCTION_NAME);
100 
101     if (System::getSingletonPtr())
102         CEGUI_THROW(InvalidRequestException(
103             "CEGUI::System object is already initialised."));
104 
105     OpenGLESRenderer& renderer(create(tt_type));
106     DefaultResourceProvider* rp = new CEGUI::DefaultResourceProvider();
107     System::create(renderer, rp);
108 
109     return renderer;
110 }
111 
112 //----------------------------------------------------------------------------//
bootstrapSystem(const Sizef & display_size,const TextureTargetType tt_type,const int abi)113 OpenGLESRenderer& OpenGLESRenderer::bootstrapSystem(
114                                         const Sizef& display_size,
115                                         const TextureTargetType tt_type,
116                                         const int abi)
117 {
118     System::performVersionTest(CEGUI_VERSION_ABI, abi, CEGUI_FUNCTION_NAME);
119 
120     if (System::getSingletonPtr())
121         CEGUI_THROW(InvalidRequestException(
122             "CEGUI::System object is already initialised."));
123 
124     OpenGLESRenderer& renderer(create(display_size, tt_type));
125     DefaultResourceProvider* rp = new CEGUI::DefaultResourceProvider();
126     System::create(renderer, rp);
127 
128     return renderer;
129 }
130 
131 //----------------------------------------------------------------------------//
destroySystem()132 void OpenGLESRenderer::destroySystem()
133 {
134     System* sys;
135     if (!(sys = System::getSingletonPtr()))
136         CEGUI_THROW(InvalidRequestException(
137             "CEGUI::System object is not created or was already destroyed."));
138 
139     OpenGLESRenderer* renderer =
140         static_cast<OpenGLESRenderer*>(sys->getRenderer());
141     DefaultResourceProvider* rp =
142         static_cast<DefaultResourceProvider*>(sys->getResourceProvider());
143 
144     System::destroy();
145     delete rp;
146     destroy(*renderer);
147 }
148 
149 //----------------------------------------------------------------------------//
create(const TextureTargetType tt_type,const int abi)150 OpenGLESRenderer& OpenGLESRenderer::create(const TextureTargetType tt_type,
151                                            const int abi)
152 {
153     System::performVersionTest(CEGUI_VERSION_ABI, abi, CEGUI_FUNCTION_NAME);
154 
155     return *new OpenGLESRenderer(tt_type);
156 }
157 
158 //----------------------------------------------------------------------------//
create(const Sizef & display_size,const TextureTargetType tt_type,const int abi)159 OpenGLESRenderer& OpenGLESRenderer::create(const Sizef& display_size,
160                                            const TextureTargetType tt_type,
161                                            const int abi)
162 {
163     System::performVersionTest(CEGUI_VERSION_ABI, abi, CEGUI_FUNCTION_NAME);
164 
165     return *new OpenGLESRenderer(display_size, tt_type);
166 }
167 
168 //----------------------------------------------------------------------------//
destroy(OpenGLESRenderer & renderer)169 void OpenGLESRenderer::destroy(OpenGLESRenderer& renderer)
170 {
171     delete &renderer;
172 }
173 
174 //----------------------------------------------------------------------------//
isGLExtensionSupported(const char * extension)175 bool OpenGLESRenderer::isGLExtensionSupported( const char* extension )
176 {
177 	const GLubyte *extensions = NULL;
178 	const GLubyte *start;
179 	GLubyte *where, *terminator;
180 
181 	/* Extension names should not have spaces. */
182 	where = (GLubyte *) strchr(extension, ' ');
183 	if (where || *extension == '\0')
184 		return 0;
185 
186 	extensions = glGetString(GL_EXTENSIONS);
187 
188 	start = extensions;
189 	for (;;)
190 	{
191 		where = (GLubyte *) strstr((const char *) start, extension);
192 		if (!where)
193 			break;
194 		terminator = where + strlen(extension);
195 		if (where == start || *(where - 1) == ' ')
196 			if (*terminator == ' ' || *terminator == '\0')
197 				return true;
198 		start = terminator;
199 	}
200 	return false;
201 }
202 
203 //----------------------------------------------------------------------------//
OpenGLESRenderer(const TextureTargetType tt_type)204 OpenGLESRenderer::OpenGLESRenderer(const TextureTargetType tt_type) :
205     d_displayDPI(96, 96),
206     d_initExtraStates(false)
207 {
208     // get rough max texture size
209     GLint max_tex_size;
210     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_tex_size);
211     d_maxTextureSize = max_tex_size;
212 
213     // initialise display size
214     GLint vp[4];
215     glGetIntegerv(GL_VIEWPORT, vp);
216     d_displaySize = Sizef(static_cast<float>(vp[2]), static_cast<float>(vp[3]));
217 
218     initialiseTextureTargetFactory(tt_type);
219 
220     d_defaultTarget = new OpenGLESViewportTarget(*this);
221 }
222 
223 //----------------------------------------------------------------------------//
OpenGLESRenderer(const Sizef & display_size,const TextureTargetType tt_type)224 OpenGLESRenderer::OpenGLESRenderer(const Sizef& display_size,
225                                    const TextureTargetType tt_type) :
226     d_displaySize(display_size),
227     d_displayDPI(96, 96),
228     d_initExtraStates(false)
229 {
230     // get rough max texture size
231     GLint max_tex_size;
232     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_tex_size);
233     d_maxTextureSize = max_tex_size;
234 
235     initialiseTextureTargetFactory(tt_type);
236 
237     d_defaultTarget = new OpenGLESViewportTarget(*this);
238 }
239 
240 //----------------------------------------------------------------------------//
~OpenGLESRenderer()241 OpenGLESRenderer::~OpenGLESRenderer()
242 {
243     destroyAllGeometryBuffers();
244     destroyAllTextureTargets();
245     destroyAllTextures();
246 
247     delete d_defaultTarget;
248     delete d_textureTargetFactory;
249 }
250 
251 //----------------------------------------------------------------------------//
getDefaultRenderTarget()252 RenderTarget& OpenGLESRenderer::getDefaultRenderTarget()
253 {
254     return *d_defaultTarget;
255 }
256 
257 //----------------------------------------------------------------------------//
createGeometryBuffer()258 GeometryBuffer& OpenGLESRenderer::createGeometryBuffer()
259 {
260     OpenGLESGeometryBuffer* b= new OpenGLESGeometryBuffer;
261     d_geometryBuffers.push_back(b);
262     return *b;
263 }
264 
265 //----------------------------------------------------------------------------//
destroyGeometryBuffer(const GeometryBuffer & buffer)266 void OpenGLESRenderer::destroyGeometryBuffer(const GeometryBuffer& buffer)
267 {
268     GeometryBufferList::iterator i = std::find(d_geometryBuffers.begin(),
269                                                d_geometryBuffers.end(),
270                                                &buffer);
271 
272     if (d_geometryBuffers.end() != i)
273     {
274         d_geometryBuffers.erase(i);
275         delete &buffer;
276     }
277 }
278 
279 //----------------------------------------------------------------------------//
destroyAllGeometryBuffers()280 void OpenGLESRenderer::destroyAllGeometryBuffers()
281 {
282     while (!d_geometryBuffers.empty())
283         destroyGeometryBuffer(**d_geometryBuffers.begin());
284 }
285 
286 //----------------------------------------------------------------------------//
createTextureTarget()287 TextureTarget* OpenGLESRenderer::createTextureTarget()
288 {
289     TextureTarget* t = d_textureTargetFactory->create(*this);
290     d_textureTargets.push_back(t);
291     return t;
292 }
293 
294 //----------------------------------------------------------------------------//
destroyTextureTarget(TextureTarget * target)295 void OpenGLESRenderer::destroyTextureTarget(TextureTarget* target)
296 {
297     TextureTargetList::iterator i = std::find(d_textureTargets.begin(),
298                                               d_textureTargets.end(),
299                                               target);
300 
301     if (d_textureTargets.end() != i)
302     {
303         d_textureTargets.erase(i);
304         d_textureTargetFactory->destory(target);
305     }
306 }
307 
308 //----------------------------------------------------------------------------//
destroyAllTextureTargets()309 void OpenGLESRenderer::destroyAllTextureTargets()
310 {
311     while (!d_textureTargets.empty())
312         destroyTextureTarget(*d_textureTargets.begin());
313 }
314 
315 //----------------------------------------------------------------------------//
createTexture(const String & name)316 Texture& OpenGLESRenderer::createTexture(const String& name)
317 {
318     OpenGLESTexture* tex = new OpenGLESTexture(*this, name);
319     d_textures[name] = tex;
320     return *tex;
321 }
322 
323 //----------------------------------------------------------------------------//
createTexture(const String & name,const String & filename,const String & resourceGroup)324 Texture& OpenGLESRenderer::createTexture(const String& name,
325                                          const String& filename,
326                                          const String& resourceGroup)
327 {
328     OpenGLESTexture* tex = new OpenGLESTexture(*this, name, filename,
329                                                resourceGroup);
330     d_textures[name] = tex;
331     return *tex;
332 }
333 
334 //----------------------------------------------------------------------------//
createTexture(const String & name,const Sizef & size)335 Texture& OpenGLESRenderer::createTexture(const String& name, const Sizef& size)
336 {
337     OpenGLESTexture* tex = new OpenGLESTexture(*this, name, size);
338     d_textures[name] = tex;
339     return *tex;
340 }
341 
342 //----------------------------------------------------------------------------//
destroyTexture(const String & name)343 void OpenGLESRenderer::destroyTexture(const String& name)
344 {
345     TextureMap::iterator i = d_textures.find(name);
346 
347     if (d_textures.end() != i)
348     {
349         logTextureDestruction(name);
350         delete i->second;
351         d_textures.erase(i);
352     }
353 }
354 
355 //----------------------------------------------------------------------------//
logTextureDestruction(const String & name)356 void OpenGLESRenderer::logTextureDestruction(const String& name)
357 {
358     Logger* logger = Logger::getSingletonPtr();
359     if (logger)
360         logger->logEvent("[OpenGLESRenderer] Destroyed texture: " + name);
361 }
362 
363 //----------------------------------------------------------------------------//
destroyTexture(Texture & texture)364 void OpenGLESRenderer::destroyTexture(Texture& texture)
365 {
366     destroyTexture(texture.getName());
367 }
368 
369 //----------------------------------------------------------------------------//
destroyAllTextures()370 void OpenGLESRenderer::destroyAllTextures()
371 {
372     while (!d_textures.empty())
373         destroyTexture(d_textures.begin()->first);
374 }
375 
376 //----------------------------------------------------------------------------//
getTexture(const String & name) const377 Texture& OpenGLESRenderer::getTexture(const String& name) const
378 {
379     TextureMap::const_iterator i = d_textures.find(name);
380 
381     if (i == d_textures.end())
382         CEGUI_THROW(UnknownObjectException(
383             "No texture named '" + name + "' is available."));
384 
385     return *i->second;
386 }
387 
388 //----------------------------------------------------------------------------//
isTextureDefined(const String & name) const389 bool OpenGLESRenderer::isTextureDefined(const String& name) const
390 {
391     return d_textures.find(name) != d_textures.end();
392 }
393 
394 //----------------------------------------------------------------------------//
beginRendering()395 void OpenGLESRenderer::beginRendering()
396 {
397     //save current attributes
398 
399 	// Unsupported by OpenGL ES
400 	//glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS);
401     //glPushAttrib(GL_ALL_ATTRIB_BITS);
402 
403     // save current matrices
404     //glMatrixMode(GL_PROJECTION);
405     //glPushMatrix();  -- causes gl stack overflow error
406 
407     glMatrixMode(GL_MODELVIEW);
408     glPushMatrix();
409 
410 	// Save at least something
411 	glPreRenderStates.glScissorTest = glIsEnabled(GL_SCISSOR_TEST);
412 	glPreRenderStates.texturing = glIsEnabled(GL_TEXTURE_2D);
413 	glPreRenderStates.blend = glIsEnabled(GL_BLEND);
414 	glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &glPreRenderStates.arrayBuffer);
415 	glGetIntegerv(GL_TEXTURE_BINDING_2D, &glPreRenderStates.texture);
416 	glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &glPreRenderStates.texEnvParam);
417 
418     // do required set-up.  yes, it really is this minimal ;)
419 	glEnable(GL_SCISSOR_TEST);
420     glEnable(GL_TEXTURE_2D);
421     glEnable(GL_BLEND);
422     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
423 
424 	glBindBuffer(GL_ARRAY_BUFFER, 0);
425 	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
426 
427     // enable arrays that we'll be using in the batches
428     glEnableClientState(GL_VERTEX_ARRAY);
429     glEnableClientState(GL_COLOR_ARRAY);
430     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
431     glDisableClientState(GL_NORMAL_ARRAY);
432 
433     // if enabled, restores a subset of the GL state back to default values.
434     if (d_initExtraStates)
435         setupExtraStates();
436 }
437 
438 //----------------------------------------------------------------------------//
endRendering()439 void OpenGLESRenderer::endRendering()
440 {
441     if (d_initExtraStates)
442         cleanupExtraStates();
443 
444     // restore former matrices
445     // FIXME: If the push ops failed, the following could mess things up!
446     //glMatrixMode(GL_PROJECTION);
447     //glPopMatrix();
448     glMatrixMode(GL_MODELVIEW);
449     glPopMatrix();
450 
451 	if (!glPreRenderStates.glScissorTest)
452 		glDisable(GL_SCISSOR_TEST);
453 	if (!glPreRenderStates.texturing)
454 		glDisable(GL_TEXTURE_2D);
455 	if (!glPreRenderStates.blend)
456 		glDisable(GL_BLEND);
457 
458 	if (glPreRenderStates.arrayBuffer)
459 		glBindBuffer(GL_ARRAY_BUFFER, glPreRenderStates.arrayBuffer);
460 	glBindTexture(GL_TEXTURE_2D, glPreRenderStates.texture);
461 	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, glPreRenderStates.texEnvParam);
462 
463 	glDisableClientState(GL_VERTEX_ARRAY);
464 	glDisableClientState(GL_COLOR_ARRAY);
465 	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
466 
467     //restore former attributes
468 	//still unsupported
469     //glPopAttrib();
470     //glPopClientAttrib();
471 }
472 
473 //----------------------------------------------------------------------------//
getDisplaySize() const474 const Sizef& OpenGLESRenderer::getDisplaySize() const
475 {
476     return d_displaySize;
477 }
478 
479 //----------------------------------------------------------------------------//
getDisplayDPI() const480 const Vector2f& OpenGLESRenderer::getDisplayDPI() const
481 {
482     return d_displayDPI;
483 }
484 
485 //----------------------------------------------------------------------------//
getMaxTextureSize() const486 uint OpenGLESRenderer::getMaxTextureSize() const
487 {
488     return d_maxTextureSize;
489 }
490 
491 //----------------------------------------------------------------------------//
getIdentifierString() const492 const String& OpenGLESRenderer::getIdentifierString() const
493 {
494     return d_rendererID;
495 }
496 
497 //----------------------------------------------------------------------------//
createTexture(const String & name,GLuint tex,const Sizef & sz)498 Texture& OpenGLESRenderer::createTexture(const String& name, GLuint tex,
499                                          const Sizef& sz)
500 {
501     OpenGLESTexture* t = new OpenGLESTexture(*this, name, tex, sz);
502     d_textures[name] = t;
503     return *t;
504 }
505 
506 //----------------------------------------------------------------------------//
setDisplaySize(const Sizef & sz)507 void OpenGLESRenderer::setDisplaySize(const Sizef& sz)
508 {
509     if (sz != d_displaySize)
510     {
511         d_displaySize = sz;
512 
513         // update the default target's area
514         Rectf area(d_defaultTarget->getArea());
515         area.setSize(sz);
516         d_defaultTarget->setArea(area);
517     }
518 }
519 
520 //----------------------------------------------------------------------------//
enableExtraStateSettings(bool setting)521 void OpenGLESRenderer::enableExtraStateSettings(bool setting)
522 {
523     d_initExtraStates = setting;
524 }
525 
526 //----------------------------------------------------------------------------//
setupExtraStates()527 void OpenGLESRenderer::setupExtraStates()
528 {
529     glMatrixMode(GL_TEXTURE);
530     glPushMatrix();
531     glLoadIdentity();
532 
533     glActiveTexture(GL_TEXTURE0);
534 	glClientActiveTexture(GL_TEXTURE0);
535 
536     //glPolygonMode(GL_FRONT, GL_FILL);
537     //glPolygonMode(GL_BACK, GL_FILL);
538 
539     glDisable(GL_LIGHTING);
540     glDisable(GL_FOG);
541     glDisable(GL_CULL_FACE);
542     glDisable(GL_DEPTH_TEST);
543 
544     //glDisable(GL_TEXTURE_GEN_S);
545     //glDisable(GL_TEXTURE_GEN_T);
546     //glDisable(GL_TEXTURE_GEN_R);
547 
548     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
549 }
550 
551 //----------------------------------------------------------------------------//
cleanupExtraStates()552 void OpenGLESRenderer::cleanupExtraStates()
553 {
554     glMatrixMode(GL_TEXTURE);
555     glPopMatrix();
556 }
557 
558 //----------------------------------------------------------------------------//
grabTextures()559 void OpenGLESRenderer::grabTextures()
560 {
561     for(TextureMap::iterator i = d_textures.begin();
562         i != d_textures.end();
563         ++i)
564         i->second->grabTexture();
565 }
566 
567 //----------------------------------------------------------------------------//
restoreTextures()568 void OpenGLESRenderer::restoreTextures()
569 {
570     for(TextureMap::iterator i = d_textures.begin();
571         i != d_textures.end();
572         ++i)
573         i->second->restoreTexture();
574 }
575 
576 //----------------------------------------------------------------------------//
initialiseTextureTargetFactory(const TextureTargetType tt_type)577 void OpenGLESRenderer::initialiseTextureTargetFactory(
578     const TextureTargetType tt_type)
579 {
580     if (isGLExtensionSupported("GL_OES_framebuffer_object"))
581     {
582         d_rendererID += "  TextureTarget support enabled via"
583 						"GL_OES_framebuffer_object extension.";
584 		OpenGLESFBOTextureTarget::initializedFBOExtension();
585 		d_textureTargetFactory =
586             new OGLTemplateTargetFactory<OpenGLESFBOTextureTarget>;
587     }
588     else
589     {
590         d_rendererID += "  TextureTarget support is not available :(";
591         d_textureTargetFactory = new OGLTextureTargetFactory;
592     }
593 }
594 
595 //----------------------------------------------------------------------------//
getAdjustedTextureSize(const Sizef & sz) const596 Sizef OpenGLESRenderer::getAdjustedTextureSize(const Sizef& sz) const
597 {
598     Sizef out(sz);
599     out.d_width = getNextPOTSize(out.d_width);
600     out.d_height = getNextPOTSize(out.d_height);
601     return out;
602 }
603 
604 //----------------------------------------------------------------------------//
getNextPOTSize(const float f)605 float OpenGLESRenderer::getNextPOTSize(const float f)
606 {
607     uint size = static_cast<uint>(f);
608 
609     // if not power of 2
610     if ((size & (size - 1)) || !size)
611     {
612         int log = 0;
613 
614         // get integer log of 'size' to base 2
615         while (size >>= 1)
616             ++log;
617 
618         // use log to calculate value to use as size.
619         size = (2 << log);
620     }
621 
622     return static_cast<float>(size);
623 }
624 
625 //----------------------------------------------------------------------------//
626 
627 } // End of  CEGUI namespace section
628 
629