Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/RenderSystems/GL/src/OgreGLRenderSystem.cpp @ 5

Last change on this file since 5 was 5, checked in by anonymous, 17 years ago

=hoffentlich gehts jetzt

File size: 97.2 KB
Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org
6
7Copyright (c) 2000-2006 Torus Knot Software Ltd
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23
24You may alternatively use this source under the terms of a specific version of
25the OGRE Unrestricted License provided you have obtained such a license from
26Torus Knot Software Ltd.s
27-----------------------------------------------------------------------------
28*/
29
30
31#include "OgreGLRenderSystem.h"
32#include "OgreRenderSystem.h"
33#include "OgreLogManager.h"
34#include "OgreStringConverter.h"
35#include "OgreLight.h"
36#include "OgreCamera.h"
37#include "OgreGLTextureManager.h"
38#include "OgreGLHardwareVertexBuffer.h"
39#include "OgreGLHardwareIndexBuffer.h"
40#include "OgreGLDefaultHardwareBufferManager.h"
41#include "OgreGLUtil.h"
42#include "OgreGLGpuProgram.h"
43#include "OgreGLGpuNvparseProgram.h"
44#include "ATI_FS_GLGpuProgram.h"
45#include "OgreGLGpuProgramManager.h"
46#include "OgreException.h"
47#include "OgreGLSLExtSupport.h"
48#include "OgreGLHardwareOcclusionQuery.h"
49#include "OgreGLContext.h"
50
51#include "OgreGLFBORenderTexture.h"
52#include "OgreGLPBRenderTexture.h"
53#include "OgreConfig.h"
54
55// Convenience macro from ARB_vertex_buffer_object spec
56#define VBO_BUFFER_OFFSET(i) ((char *)NULL + (i))
57GLenum glewContextInit (Ogre::GLSupport *glSupport);
58
59namespace Ogre {
60
61    // Callback function used when registering GLGpuPrograms
62    GpuProgram* createGLArbGpuProgram(ResourceManager* creator, 
63        const String& name, ResourceHandle handle, 
64        const String& group, bool isManual, ManualResourceLoader* loader,
65        GpuProgramType gptype, const String& syntaxCode)
66    {
67        GLArbGpuProgram* ret = new GLArbGpuProgram(
68            creator, name, handle, group, isManual, loader);
69        ret->setType(gptype);
70        ret->setSyntaxCode(syntaxCode);
71        return ret;
72    }
73
74    GpuProgram* createGLGpuNvparseProgram(ResourceManager* creator, 
75        const String& name, ResourceHandle handle, 
76        const String& group, bool isManual, ManualResourceLoader* loader,
77        GpuProgramType gptype, const String& syntaxCode)
78    {
79        GLGpuNvparseProgram* ret = new GLGpuNvparseProgram(
80            creator, name, handle, group, isManual, loader);
81        ret->setType(gptype);
82        ret->setSyntaxCode(syntaxCode);
83        return ret;
84    }
85
86    GpuProgram* createGL_ATI_FS_GpuProgram(ResourceManager* creator, 
87        const String& name, ResourceHandle handle, 
88        const String& group, bool isManual, ManualResourceLoader* loader,
89        GpuProgramType gptype, const String& syntaxCode)
90        {
91
92        ATI_FS_GLGpuProgram* ret = new ATI_FS_GLGpuProgram(
93            creator, name, handle, group, isManual, loader);
94        ret->setType(gptype);
95        ret->setSyntaxCode(syntaxCode);
96        return ret;
97        }
98
99    GLRenderSystem::GLRenderSystem()
100      : mDepthWrite(true), mStencilMask(0xFFFFFFFF), mHardwareBufferManager(0),
101        mGpuProgramManager(0),
102        mGLSLProgramFactory(0),
103        mRTTManager(0)
104    {
105        size_t i;
106
107        LogManager::getSingleton().logMessage(getName() + " created.");
108
109        // Get our GLSupport
110        mGLSupport = getGLSupport();
111
112        for( i=0; i<MAX_LIGHTS; i++ )
113            mLights[i] = NULL;
114
115        mWorldMatrix = Matrix4::IDENTITY;
116        mViewMatrix = Matrix4::IDENTITY;
117       
118        initConfigOptions();
119
120        mColourWrite[0] = mColourWrite[1] = mColourWrite[2] = mColourWrite[3] = true;
121
122        for (i = 0; i < OGRE_MAX_TEXTURE_LAYERS; i++)
123        {
124                        // Dummy value
125            mTextureCoordIndex[i] = 99;
126        }
127
128        for (i = 0; i < OGRE_MAX_TEXTURE_LAYERS; i++)
129        {
130            mTextureTypes[i] = 0;
131        }
132
133        mActiveRenderTarget = 0;
134        mCurrentContext = 0;
135        mMainContext = 0;
136
137        mGLInitialized = false;
138
139        mCurrentLights = 0;
140        mMinFilter = FO_LINEAR;
141        mMipFilter = FO_POINT;
142        mCurrentVertexProgram = 0;
143        mCurrentFragmentProgram = 0;
144
145        mClipPlanes.reserve(6);
146
147    }
148
149    GLRenderSystem::~GLRenderSystem()
150    {
151        shutdown();
152
153        // Destroy render windows
154        RenderTargetMap::iterator i;
155        for (i = mRenderTargets.begin(); i != mRenderTargets.end(); ++i)
156        {
157            delete i->second;
158        }
159        mRenderTargets.clear();
160
161        delete mGLSupport;
162    }
163
164    const String& GLRenderSystem::getName(void) const
165    {
166        static String strName("OpenGL Rendering Subsystem");
167        return strName;
168    }
169
170    void GLRenderSystem::initConfigOptions(void)
171    {
172        mGLSupport->addConfig();
173    }
174   
175    ConfigOptionMap& GLRenderSystem::getConfigOptions(void)
176    {
177        return mGLSupport->getConfigOptions();
178    }
179
180    void GLRenderSystem::setConfigOption(const String &name, const String &value)
181    {
182        mGLSupport->setConfigOption(name, value);
183    }
184
185    String GLRenderSystem::validateConfigOptions(void)
186    {
187        // XXX Return an error string if something is invalid
188        return mGLSupport->validateConfig();
189    }
190
191    RenderWindow* GLRenderSystem::initialise(bool autoCreateWindow, const String& windowTitle)
192    {
193        mGLSupport->start();
194       
195                RenderWindow* autoWindow = mGLSupport->createWindow(autoCreateWindow, this, windowTitle);
196
197
198        _setCullingMode( mCullingMode );
199       
200        return autoWindow;
201    }
202
203    void GLRenderSystem::initGL(RenderTarget *primary)
204    {
205        // Set main and current context
206        mMainContext = 0;
207        primary->getCustomAttribute("GLCONTEXT", &mMainContext);
208        mCurrentContext = mMainContext;
209       
210        // Set primary context as active
211        if(mCurrentContext)
212            mCurrentContext->setCurrent();
213           
214        // Setup GLSupport
215        mGLSupport->initialiseExtensions();
216
217        LogManager::getSingleton().logMessage("***************************");
218                LogManager::getSingleton().logMessage("*** GL Renderer Started ***");
219                LogManager::getSingleton().logMessage("***************************");
220
221                // Get extension function pointers
222        glewContextInit(mGLSupport);
223
224        // Check for hardware mipmapping support.
225        if(GLEW_VERSION_1_4 || GLEW_SGIS_generate_mipmap)
226        {
227            mCapabilities->setCapability(RSC_AUTOMIPMAP);
228        }
229
230        // Check for blending support
231        if(GLEW_VERSION_1_3 || 
232            GLEW_ARB_texture_env_combine || 
233            GLEW_EXT_texture_env_combine)
234        {
235            mCapabilities->setCapability(RSC_BLENDING);
236        }
237
238        // Check for Multitexturing support and set number of texture units
239        if(GLEW_VERSION_1_3 || 
240           GLEW_ARB_multitexture)
241        {
242            GLint units;
243            glGetIntegerv( GL_MAX_TEXTURE_UNITS, &units );
244                        mFixedFunctionTextureUnits = units;
245
246                        if (GLEW_ARB_fragment_program)
247                        {
248                                // Also check GL_MAX_TEXTURE_IMAGE_UNITS_ARB since NV at least
249                                // only increased this on the FX/6x00 series
250                                GLint arbUnits;
251                                glGetIntegerv( GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &arbUnits );
252                                if (arbUnits > units)
253                                        units = arbUnits;
254                        }
255           
256            mCapabilities->setNumTextureUnits(units);
257
258        }
259        else
260        {
261            // If no multitexture support then set one texture unit
262            mCapabilities->setNumTextureUnits(1);
263        }
264           
265        // Check for Anisotropy support
266        if(GLEW_EXT_texture_filter_anisotropic)
267        {
268            mCapabilities->setCapability(RSC_ANISOTROPY);
269        }
270
271        // Check for DOT3 support
272        if(GLEW_VERSION_1_3 ||
273           GLEW_ARB_texture_env_dot3 ||
274           GLEW_EXT_texture_env_dot3)
275        {
276            mCapabilities->setCapability(RSC_DOT3);
277        }
278
279        // Check for cube mapping
280        if(GLEW_VERSION_1_3 || 
281           GLEW_ARB_texture_cube_map ||
282           GLEW_EXT_texture_cube_map)
283        {
284            mCapabilities->setCapability(RSC_CUBEMAPPING);
285        }
286       
287
288                // Point sprites
289                if (GLEW_VERSION_2_0 ||
290                        GLEW_ARB_point_sprite)
291                {
292                        mCapabilities->setCapability(RSC_POINT_SPRITES);
293                }
294        // Check for point parameters
295        if(GLEW_VERSION_1_4 ||
296                        GLEW_ARB_point_parameters ||
297                        GLEW_EXT_point_parameters)
298        {
299            mCapabilities->setCapability(RSC_POINT_EXTENDED_PARAMETERS);
300        }
301               
302        // Check for hardware stencil support and set bit depth
303        GLint stencil;
304        glGetIntegerv(GL_STENCIL_BITS,&stencil);
305
306        if(stencil)
307        {
308            mCapabilities->setCapability(RSC_HWSTENCIL);
309            mCapabilities->setStencilBufferBitDepth(stencil);
310        }
311
312        // Check for VBO support
313        if(GLEW_VERSION_1_5 || GLEW_ARB_vertex_buffer_object)
314        {
315            // Some buggy driver claim that it is GL 1.5 compliant and
316            // not support ARB_vertex_buffer_object
317            if (!GLEW_ARB_vertex_buffer_object)
318            {
319                // Assign ARB functions same to GL 1.5 version since
320                // interface identical
321                glBindBufferARB = glBindBuffer;
322                glBufferDataARB = glBufferData;
323                glBufferSubDataARB = glBufferSubData;
324                glDeleteBuffersARB = glDeleteBuffers;
325                glGenBuffersARB = glGenBuffers;
326                glGetBufferParameterivARB = glGetBufferParameteriv;
327                glGetBufferPointervARB = glGetBufferPointerv;
328                glGetBufferSubDataARB = glGetBufferSubData;
329                glIsBufferARB = glIsBuffer;
330                glMapBufferARB = glMapBuffer;
331                glUnmapBufferARB = glUnmapBuffer;
332            }
333
334            mCapabilities->setCapability(RSC_VBO);
335
336            mHardwareBufferManager = new GLHardwareBufferManager;
337        }
338        else
339        {
340            mHardwareBufferManager = new GLDefaultHardwareBufferManager;
341        }
342
343        // XXX Need to check for nv2 support and make a program manager for it
344        // XXX Probably nv1 as well for older cards
345        // GPU Program Manager setup
346        mGpuProgramManager = new GLGpuProgramManager();
347
348                if(GLEW_ARB_vertex_program)
349        {
350            mCapabilities->setCapability(RSC_VERTEX_PROGRAM);
351
352            // Vertex Program Properties
353            mCapabilities->setMaxVertexProgramVersion("arbvp1");
354            mCapabilities->setVertexProgramConstantBoolCount(0);
355            mCapabilities->setVertexProgramConstantIntCount(0);
356
357            GLint floatConstantCount;
358            glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB, &floatConstantCount);
359            mCapabilities->setVertexProgramConstantFloatCount(floatConstantCount);
360
361            mGpuProgramManager->_pushSyntaxCode("arbvp1");
362            mGpuProgramManager->registerProgramFactory("arbvp1", createGLArbGpuProgram);
363                        if (GLEW_NV_vertex_program2_option)
364                        {
365                                mCapabilities->setMaxVertexProgramVersion("vp30");
366                                mGpuProgramManager->_pushSyntaxCode("vp30");
367                                mGpuProgramManager->registerProgramFactory("vp30", createGLArbGpuProgram);
368                        }
369
370                        if (GLEW_NV_vertex_program3)
371                        {
372                                mCapabilities->setMaxVertexProgramVersion("vp40");
373                                mGpuProgramManager->_pushSyntaxCode("vp40");
374                                mGpuProgramManager->registerProgramFactory("vp40", createGLArbGpuProgram);
375                        }
376                }
377
378        if (GLEW_NV_register_combiners2 &&
379            GLEW_NV_texture_shader)
380        {
381            mCapabilities->setCapability(RSC_FRAGMENT_PROGRAM);
382            mCapabilities->setMaxFragmentProgramVersion("fp20");
383
384            mGpuProgramManager->_pushSyntaxCode("fp20");
385            mGpuProgramManager->registerProgramFactory("fp20", createGLGpuNvparseProgram);
386        }
387
388                // NFZ - check for ATI fragment shader support
389                if (GLEW_ATI_fragment_shader)
390                {
391            mCapabilities->setCapability(RSC_FRAGMENT_PROGRAM);
392            mCapabilities->setMaxFragmentProgramVersion("ps_1_4");
393            // no boolean params allowed
394            mCapabilities->setFragmentProgramConstantBoolCount(0);
395            // no integer params allowed
396            mCapabilities->setFragmentProgramConstantIntCount(0);
397
398                        // only 8 Vector4 constant floats supported
399            mCapabilities->setFragmentProgramConstantFloatCount(8);
400
401            mGpuProgramManager->_pushSyntaxCode("ps_1_4");
402            mGpuProgramManager->_pushSyntaxCode("ps_1_3");
403            mGpuProgramManager->_pushSyntaxCode("ps_1_2");
404            mGpuProgramManager->_pushSyntaxCode("ps_1_1");
405
406            mGpuProgramManager->registerProgramFactory("ps_1_4", createGL_ATI_FS_GpuProgram);
407            mGpuProgramManager->registerProgramFactory("ps_1_3", createGL_ATI_FS_GpuProgram);
408            mGpuProgramManager->registerProgramFactory("ps_1_2", createGL_ATI_FS_GpuProgram);
409            mGpuProgramManager->registerProgramFactory("ps_1_1", createGL_ATI_FS_GpuProgram);
410                }
411
412        if (GLEW_ARB_fragment_program)
413        {
414            mCapabilities->setCapability(RSC_FRAGMENT_PROGRAM);
415
416            // Fragment Program Properties
417            mCapabilities->setMaxFragmentProgramVersion("arbfp1");
418            mCapabilities->setFragmentProgramConstantBoolCount(0);
419            mCapabilities->setFragmentProgramConstantIntCount(0);
420
421            GLint floatConstantCount;
422            glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB, &floatConstantCount);
423            mCapabilities->setFragmentProgramConstantFloatCount(floatConstantCount);
424
425            mGpuProgramManager->_pushSyntaxCode("arbfp1");
426            mGpuProgramManager->registerProgramFactory("arbfp1", createGLArbGpuProgram);
427                        if (GLEW_NV_fragment_program_option)
428                        {
429                                mCapabilities->setMaxFragmentProgramVersion("fp30");
430                                mGpuProgramManager->_pushSyntaxCode("fp30");
431                                mGpuProgramManager->registerProgramFactory("fp30", createGLArbGpuProgram);
432                        }
433
434                        if (GLEW_NV_fragment_program2)
435                        {
436                                mCapabilities->setMaxFragmentProgramVersion("fp40");
437                                mGpuProgramManager->_pushSyntaxCode("fp40");
438                                mGpuProgramManager->registerProgramFactory("fp40", createGLArbGpuProgram);
439                        }       
440                }
441
442                // NFZ - Check if GLSL is supported
443                if ( GLEW_VERSION_2_0 || 
444                        (GLEW_ARB_shading_language_100 &&
445                         GLEW_ARB_shader_objects &&
446                         GLEW_ARB_fragment_shader &&
447                         GLEW_ARB_vertex_shader) )
448                {
449                        // NFZ - check for GLSL vertex and fragment shader support successful
450            mGLSLProgramFactory = new GLSLProgramFactory();
451            HighLevelGpuProgramManager::getSingleton().addFactory(mGLSLProgramFactory);
452            mGpuProgramManager->_pushSyntaxCode("glsl");
453                        LogManager::getSingleton().logMessage("GLSL support detected");
454                }
455
456                // Check for texture compression
457        if(GLEW_VERSION_1_3 || GLEW_ARB_texture_compression)
458        {   
459            mCapabilities->setCapability(RSC_TEXTURE_COMPRESSION);
460         
461            // Check for dxt compression
462            if(GLEW_EXT_texture_compression_s3tc)
463            {
464                mCapabilities->setCapability(RSC_TEXTURE_COMPRESSION_DXT);
465            }
466            // Check for vtc compression
467            if(GLEW_NV_texture_compression_vtc)
468            {
469                mCapabilities->setCapability(RSC_TEXTURE_COMPRESSION_VTC);
470            }
471        }
472
473        // Scissor test is standard in GL 1.2 (is it emulated on some cards though?)
474        mCapabilities->setCapability(RSC_SCISSOR_TEST);
475                // As are user clipping planes
476                mCapabilities->setCapability(RSC_USER_CLIP_PLANES);
477
478        // 2-sided stencil?
479        if (GLEW_VERSION_2_0 || GLEW_EXT_stencil_two_side)
480        {
481            mCapabilities->setCapability(RSC_TWO_SIDED_STENCIL);
482        }
483        // stencil wrapping?
484        if (GLEW_VERSION_1_4 || GLEW_EXT_stencil_wrap)
485        {
486            mCapabilities->setCapability(RSC_STENCIL_WRAP);
487        }
488
489        // Check for hardware occlusion support
490        if(GLEW_VERSION_1_5 || GLEW_ARB_occlusion_query)
491        {
492            // Some buggy driver claim that it is GL 1.5 compliant and
493            // not support ARB_occlusion_query
494            if (!GLEW_ARB_occlusion_query)
495            {
496                // Assign ARB functions same to GL 1.5 version since
497                // interface identical
498                glBeginQueryARB = glBeginQuery;
499                glDeleteQueriesARB = glDeleteQueries;
500                glEndQueryARB = glEndQuery;
501                glGenQueriesARB = glGenQueries;
502                glGetQueryObjectivARB = glGetQueryObjectiv;
503                glGetQueryObjectuivARB = glGetQueryObjectuiv;
504                glGetQueryivARB = glGetQueryiv;
505                glIsQueryARB = glIsQuery;
506            }
507
508            mCapabilities->setCapability(RSC_HWOCCLUSION);             
509        }
510                else if (GLEW_NV_occlusion_query)
511                {
512                        // Support NV extension too for old hardware
513            mCapabilities->setCapability(RSC_HWOCCLUSION);             
514                }
515
516                // UBYTE4 always supported
517                mCapabilities->setCapability(RSC_VERTEX_FORMAT_UBYTE4);
518
519        // Inifinite far plane always supported
520        mCapabilities->setCapability(RSC_INFINITE_FAR_PLANE);
521
522        // Check for non-power-of-2 texture support
523                if(GLEW_ARB_texture_non_power_of_two)
524        {
525            mCapabilities->setCapability(RSC_NON_POWER_OF_2_TEXTURES);
526        }
527
528        // Check for Float textures
529        if(GLEW_ATI_texture_float || GLEW_ARB_texture_float)
530        {
531            mCapabilities->setCapability(RSC_TEXTURE_FLOAT);
532        }
533       
534                // 3D textures should be supported by GL 1.2, which is our minimum version
535        mCapabilities->setCapability(RSC_TEXTURE_3D);
536       
537        /// Do this after extension function pointers are initialised as the extension
538        /// is used to probe further capabilities.
539                ConfigOptionMap::iterator cfi = getConfigOptions().find("RTT Preferred Mode");
540                // RTT Mode: 0 use whatever available, 1 use PBuffers, 2 force use copying
541                int rttMode = 0;
542                if (cfi != getConfigOptions().end())
543                {
544                        if (cfi->second.currentValue == "PBuffer")
545                        {
546                                rttMode = 1;
547                        }
548                        else if (cfi->second.currentValue == "Copy")
549                        {
550                                rttMode = 2;
551                        }
552                }
553         // Check for framebuffer object extension
554        if(GLEW_EXT_framebuffer_object && rttMode < 1)
555        {
556                        // Probe number of draw buffers
557                        // Only makes sense with FBO support, so probe here
558                        if(GLEW_VERSION_2_0 || 
559                                GLEW_ARB_draw_buffers ||
560                                GLEW_ATI_draw_buffers)
561                        {
562                                GLint buffers;
563                                glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &buffers);
564                                mCapabilities->setNumMultiRenderTargets(std::min(buffers, OGRE_MAX_MULTIPLE_RENDER_TARGETS));
565                                if(!GLEW_VERSION_2_0)
566                                {
567                                        // Before GL version 2.0, we need to get one of the extensions
568                                        if(GLEW_ARB_draw_buffers)
569                                                __glewDrawBuffers = glDrawBuffersARB;
570                                        else if(GLEW_ATI_draw_buffers)
571                                                __glewDrawBuffers = glDrawBuffersATI;
572                                }
573                        }
574                        // Create FBO manager
575            LogManager::getSingleton().logMessage("GL: Using GL_EXT_framebuffer_object for rendering to textures (best)");
576            //mRTTManager = new GLFBOManager(mGLSupport->getGLVendor() == "ATI");
577            mRTTManager = new GLFBOManager(false);
578            mCapabilities->setCapability(RSC_HWRENDER_TO_TEXTURE);
579        }
580        else
581        {
582            // Check GLSupport for PBuffer support
583            if(mGLSupport->supportsPBuffers() && rttMode < 2)
584            {
585                // Use PBuffers
586                mRTTManager = new GLPBRTTManager(mGLSupport, primary);
587                LogManager::getSingleton().logMessage("GL: Using PBuffers for rendering to textures");
588                mCapabilities->setCapability(RSC_HWRENDER_TO_TEXTURE);
589            }
590            else
591            {
592                // No pbuffer support either -- fallback to simplest copying from framebuffer
593                mRTTManager = new GLCopyingRTTManager();
594                LogManager::getSingleton().logMessage("GL: Using framebuffer copy for rendering to textures (worst)");
595                LogManager::getSingleton().logMessage("GL: Warning: RenderTexture size is restricted to size of framebuffer. If you are on Linux, consider using GLX instead of SDL.");
596            }
597        }
598
599                // Point size
600                float ps;
601                glGetFloatv(GL_POINT_SIZE_MAX, &ps);
602                mCapabilities->setMaxPointSize(ps);
603
604                // Vertex texture fetching
605                GLint vUnits;
606                glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &vUnits);
607                mCapabilities->setNumVertexTextureUnits(static_cast<ushort>(vUnits));
608                if (vUnits > 0)
609                {
610                        mCapabilities->setCapability(RSC_VERTEX_TEXTURE_FETCH);
611                }
612                // GL always shares vertex and fragment texture units (for now?)
613                mCapabilities->setVertexTextureUnitsShared(true);
614
615                // Mipmap LOD biasing?
616                if (GLEW_VERSION_1_4 || GLEW_EXT_texture_lod_bias)
617                {
618                        mCapabilities->setCapability(RSC_MIPMAP_LOD_BIAS);
619                }
620
621       
622                Log* defaultLog = LogManager::getSingleton().getDefaultLog();
623                if (defaultLog)
624                {
625                        mCapabilities->log(defaultLog);
626                }
627
628        /// Create the texture manager       
629        mTextureManager = new GLTextureManager(*mGLSupport); 
630
631        mGLInitialized = true;
632    }
633
634    void GLRenderSystem::reinitialise(void)
635    {
636        this->shutdown();
637        this->initialise(true);
638    }
639
640    void GLRenderSystem::shutdown(void)
641    {
642        RenderSystem::shutdown();
643
644        // Deleting the GLSL program factory
645        if (mGLSLProgramFactory)
646        {
647            // Remove from manager safely
648            if (HighLevelGpuProgramManager::getSingletonPtr())
649                HighLevelGpuProgramManager::getSingleton().removeFactory(mGLSLProgramFactory);
650                    delete mGLSLProgramFactory;
651                    mGLSLProgramFactory = 0;
652        }
653
654        // Deleting the GPU program manager and hardware buffer manager.  Has to be done before the mGLSupport->stop().
655        delete mGpuProgramManager;
656        mGpuProgramManager = 0;
657       
658        delete mHardwareBufferManager;
659        mHardwareBufferManager = 0;
660       
661        delete mRTTManager;
662        mRTTManager = 0;
663
664                // Delete extra threads contexts
665                for (GLContextList::iterator i = mBackgroundContextList.begin(); 
666                        i != mBackgroundContextList.end(); ++i)
667                {
668                        delete *i;
669                }
670                mBackgroundContextList.clear();
671
672        mGLSupport->stop();
673        mStopRendering = true;
674
675                delete mTextureManager;
676                mTextureManager = 0;
677
678                // There will be a new initial window and so forth, thus any call to test
679                //  some params will access an invalid pointer, so it is best to reset
680                //  the whole state.
681                mGLInitialized = 0;
682    }
683
684    void GLRenderSystem::setAmbientLight(float r, float g, float b)
685    {
686        GLfloat lmodel_ambient[] = {r, g, b, 1.0};
687        glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
688    }
689
690    void GLRenderSystem::setShadingType(ShadeOptions so)
691    {
692        switch(so)
693        {
694        case SO_FLAT:
695            glShadeModel(GL_FLAT);
696            break;
697        default:
698            glShadeModel(GL_SMOOTH);
699            break;
700        }
701    }
702
703        RenderWindow* GLRenderSystem::createRenderWindow(const String &name, 
704                unsigned int width, unsigned int height, bool fullScreen,
705                const NameValuePairList *miscParams)
706    {
707        if (mRenderTargets.find(name) != mRenderTargets.end())
708        {
709            OGRE_EXCEPT(
710                Exception::ERR_INVALIDPARAMS, 
711                "Window with name '" + name + "' already exists",
712                "GLRenderSystem::createRenderWindow" );
713        }
714                // Log a message
715                std::stringstream ss;
716                ss << "GLRenderSystem::createRenderWindow \"" << name << "\", " <<
717                        width << "x" << height << " ";
718                if(fullScreen)
719                        ss << "fullscreen ";
720                else
721                        ss << "windowed ";
722                if(miscParams)
723                {
724                        ss << " miscParams: ";
725                        NameValuePairList::const_iterator it;
726                        for(it=miscParams->begin(); it!=miscParams->end(); ++it)
727                        {
728                                ss << it->first << "=" << it->second << " ";
729                        }
730                        LogManager::getSingleton().logMessage(ss.str());
731                }
732
733        // Create the window
734        RenderWindow* win = mGLSupport->newWindow(name, width, height, 
735            fullScreen, miscParams);
736
737        attachRenderTarget( *win );
738
739        if (!mGLInitialized) 
740        {               
741            // Initialise GL after the first window has been created
742            initGL(win);
743           
744            // Initialise the main context
745            _oneTimeContextInitialization();
746            if(mCurrentContext)
747                mCurrentContext->setInitialized();
748        }
749
750        return win;
751    }
752
753        //-----------------------------------------------------------------------
754        MultiRenderTarget * GLRenderSystem::createMultiRenderTarget(const String & name)
755        {
756                MultiRenderTarget *retval = mRTTManager->createMultiRenderTarget(name);
757                attachRenderTarget( *retval );
758                return retval;
759        }
760
761        //-----------------------------------------------------------------------
762    void GLRenderSystem::destroyRenderWindow(RenderWindow* pWin)
763    {
764        // Find it to remove from list
765        RenderTargetMap::iterator i = mRenderTargets.begin();
766
767        while (i != mRenderTargets.end())
768        {
769            if (i->second == pWin)
770            {
771                mRenderTargets.erase(i);
772                delete pWin;
773                break;
774            }
775        }
776    }
777
778        //---------------------------------------------------------------------
779    void GLRenderSystem::_useLights(const LightList& lights, unsigned short limit)
780    {
781        // Save previous modelview
782        glMatrixMode(GL_MODELVIEW);
783        glPushMatrix();
784        // just load view matrix (identity world)
785        GLfloat mat[16];
786        makeGLMatrix(mat, mViewMatrix);
787        glLoadMatrixf(mat);
788
789        LightList::const_iterator i, iend;
790        iend = lights.end();
791        unsigned short num = 0;
792        for (i = lights.begin(); i != iend && num < limit; ++i, ++num)
793        {
794            setGLLight(num, *i);
795            mLights[num] = *i;
796        }
797        // Disable extra lights
798        for (; num < mCurrentLights; ++num)
799        {
800            setGLLight(num, NULL);
801            mLights[num] = NULL;
802        }
803        mCurrentLights = std::min(limit, static_cast<unsigned short>(lights.size()));
804
805        setLights();
806
807        // restore previous
808        glPopMatrix();
809
810    }
811
812    void GLRenderSystem::setGLLight(size_t index, Light* lt)
813    {
814        GLenum gl_index = GL_LIGHT0 + index;
815
816        if (!lt)
817        {
818            // Disable in the scene
819            glDisable(gl_index);
820        }
821        else
822        {
823            switch (lt->getType())
824            {
825            case Light::LT_SPOTLIGHT:
826                glLightf( gl_index, GL_SPOT_CUTOFF, 0.5f * lt->getSpotlightOuterAngle().valueDegrees() );
827                glLightf(gl_index, GL_SPOT_EXPONENT, lt->getSpotlightFalloff());
828                break;
829            default:
830                glLightf( gl_index, GL_SPOT_CUTOFF, 180.0 );
831                break;
832            }
833
834            // Color
835            ColourValue col;
836            col = lt->getDiffuseColour();
837
838
839            GLfloat f4vals[4] = {col.r, col.g, col.b, col.a};
840            glLightfv(gl_index, GL_DIFFUSE, f4vals);
841           
842            col = lt->getSpecularColour();
843            f4vals[0] = col.r;
844            f4vals[1] = col.g;
845            f4vals[2] = col.b;
846            f4vals[3] = col.a;
847            glLightfv(gl_index, GL_SPECULAR, f4vals);
848
849
850            // Disable ambient light for movables;
851            f4vals[0] = 0;
852            f4vals[1] = 0;
853            f4vals[2] = 0;
854            f4vals[3] = 1;
855            glLightfv(gl_index, GL_AMBIENT, f4vals);
856
857            setGLLightPositionDirection(lt, gl_index);
858
859
860            // Attenuation
861            glLightf(gl_index, GL_CONSTANT_ATTENUATION, lt->getAttenuationConstant());
862            glLightf(gl_index, GL_LINEAR_ATTENUATION, lt->getAttenuationLinear());
863            glLightf(gl_index, GL_QUADRATIC_ATTENUATION, lt->getAttenuationQuadric());
864            // Enable in the scene
865            glEnable(gl_index);
866
867        }
868
869    }
870
871    //-----------------------------------------------------------------------------
872    void GLRenderSystem::makeGLMatrix(GLfloat gl_matrix[16], const Matrix4& m)
873    {
874        size_t x = 0;
875        for (size_t i = 0; i < 4; i++)
876        {
877            for (size_t j = 0; j < 4; j++)
878            {
879                gl_matrix[x] = m[j][i];
880                x++;
881            }
882        }
883    }
884    //-----------------------------------------------------------------------------
885    void GLRenderSystem::_setWorldMatrix( const Matrix4 &m )
886    {
887        GLfloat mat[16];
888        mWorldMatrix = m;
889        makeGLMatrix( mat, mViewMatrix * mWorldMatrix );
890        glMatrixMode(GL_MODELVIEW);
891        glLoadMatrixf(mat);
892    }
893
894    //-----------------------------------------------------------------------------
895    void GLRenderSystem::_setViewMatrix( const Matrix4 &m )
896    {
897        mViewMatrix = m;
898
899        GLfloat mat[16];
900                makeGLMatrix( mat, mViewMatrix * mWorldMatrix );
901        glMatrixMode(GL_MODELVIEW);
902        glLoadMatrixf(mat);
903
904        setGLClipPlanes();
905    }
906    //-----------------------------------------------------------------------------
907    void GLRenderSystem::_setProjectionMatrix(const Matrix4 &m)
908    {
909        GLfloat mat[16];
910        makeGLMatrix(mat, m);
911        if (mActiveRenderTarget->requiresTextureFlipping())
912        {
913            // Invert transformed y
914            mat[1] = -mat[1];
915            mat[5] = -mat[5];
916            mat[9] = -mat[9];
917            mat[13] = -mat[13];
918        }
919        glMatrixMode(GL_PROJECTION);
920        glLoadMatrixf(mat);
921        glMatrixMode(GL_MODELVIEW);
922    }
923    //-----------------------------------------------------------------------------
924    void GLRenderSystem::_setSurfaceParams(const ColourValue &ambient,
925        const ColourValue &diffuse, const ColourValue &specular,
926        const ColourValue &emissive, Real shininess,
927        TrackVertexColourType tracking)
928    {
929       
930        // Track vertex colour
931        if(tracking != TVC_NONE) 
932        {
933            GLenum gt = GL_DIFFUSE;
934            // There are actually 15 different combinations for tracking, of which
935            // GL only supports the most used 5. This means that we have to do some
936            // magic to find the best match. NOTE:
937            //  GL_AMBIENT_AND_DIFFUSE != GL_AMBIENT | GL__DIFFUSE
938            if(tracking & TVC_AMBIENT) 
939            {
940                if(tracking & TVC_DIFFUSE)
941                {
942                    gt = GL_AMBIENT_AND_DIFFUSE;
943                } 
944                else 
945                {
946                    gt = GL_AMBIENT;
947                }
948            }
949            else if(tracking & TVC_DIFFUSE) 
950            {
951                gt = GL_DIFFUSE;
952            }
953            else if(tracking & TVC_SPECULAR) 
954            {
955                gt = GL_SPECULAR;             
956            }
957            else if(tracking & TVC_EMISSIVE) 
958            {
959                gt = GL_EMISSION;
960            }
961            glColorMaterial(GL_FRONT_AND_BACK, gt);
962           
963            glEnable(GL_COLOR_MATERIAL);
964        } 
965        else 
966        {
967            glDisable(GL_COLOR_MATERIAL);         
968        }
969
970                // XXX Cache previous values?
971                // XXX Front or Front and Back?
972
973                GLfloat f4val[4] = {diffuse.r, diffuse.g, diffuse.b, diffuse.a};
974                glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, f4val);
975                f4val[0] = ambient.r;
976                f4val[1] = ambient.g;
977                f4val[2] = ambient.b;
978                f4val[3] = ambient.a;
979                glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, f4val);
980                f4val[0] = specular.r;
981                f4val[1] = specular.g;
982                f4val[2] = specular.b;
983                f4val[3] = specular.a;
984                glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, f4val);
985                f4val[0] = emissive.r;
986                f4val[1] = emissive.g;
987                f4val[2] = emissive.b;
988                f4val[3] = emissive.a;
989                glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, f4val);
990                glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess);
991    }
992    //-----------------------------------------------------------------------------
993        void GLRenderSystem::_setPointParameters(Real size, 
994                bool attenuationEnabled, Real constant, Real linear, Real quadratic,
995                Real minSize, Real maxSize)
996    {
997
998                if(attenuationEnabled && 
999                        mCapabilities->hasCapability(RSC_POINT_EXTENDED_PARAMETERS))
1000                {
1001                        // Point size is still calculated in pixels even when attenuation is
1002                        // enabled, which is pretty awkward, since you typically want a viewport
1003                        // independent size if you're looking for attenuation.
1004                        // So, scale the point size up by viewport size (this is equivalent to
1005                        // what D3D does as standard)
1006                        Real adjSize = size * mActiveViewport->getActualHeight();
1007                        Real adjMinSize = minSize * mActiveViewport->getActualHeight();
1008                        Real adjMaxSize;
1009                        if (maxSize == 0.0f)
1010                                adjMaxSize = mCapabilities->getMaxPointSize(); // pixels
1011                        else
1012                                adjMaxSize = maxSize * mActiveViewport->getActualHeight();
1013                        glPointSize(adjSize);
1014
1015                        // XXX: why do I need this for results to be consistent with D3D?
1016                        // Equations are supposedly the same once you factor in vp height
1017                        Real correction = 0.005;
1018                        // scaling required
1019                        float val[4] = {constant, linear*correction, quadratic*correction, 1};
1020                        glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION, val);
1021                        glPointParameterf(GL_POINT_SIZE_MIN, adjMinSize);
1022                        glPointParameterf(GL_POINT_SIZE_MAX, adjMaxSize);
1023                }
1024                else
1025                {
1026                        // no scaling required
1027                        // GL has no disabled flag for this so just set to constant
1028                        glPointSize(size);
1029
1030                        if (mCapabilities->hasCapability(RSC_POINT_EXTENDED_PARAMETERS))
1031                        {
1032                                float val[4] = {1, 0, 0, 1};
1033                                glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION, val);
1034                                glPointParameterf(GL_POINT_SIZE_MIN, minSize);
1035                                if (maxSize == 0.0f)
1036                                        maxSize = mCapabilities->getMaxPointSize();
1037                                glPointParameterf(GL_POINT_SIZE_MAX, maxSize);
1038                        }
1039                }
1040
1041
1042
1043    }
1044        //---------------------------------------------------------------------
1045        void GLRenderSystem::_setPointSpritesEnabled(bool enabled)
1046        {
1047                if (enabled)
1048                {
1049                        glEnable(GL_POINT_SPRITE);
1050                }
1051                else
1052                {
1053                        glDisable(GL_POINT_SPRITE);
1054                }
1055
1056                // Set sprite texture coord generation
1057                // Don't offer this as an option since D3D links it to sprite enabled
1058                for (ushort i = 0; i < mFixedFunctionTextureUnits; ++i)
1059                {
1060                        glActiveTextureARB(GL_TEXTURE0 + i);
1061                        glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, 
1062                                enabled ? GL_TRUE : GL_FALSE);
1063                }
1064                glActiveTextureARB(GL_TEXTURE0);
1065
1066        }
1067    //-----------------------------------------------------------------------------
1068    void GLRenderSystem::_setTexture(size_t stage, bool enabled, const TexturePtr &texPtr)
1069    {
1070        GLTexturePtr tex = texPtr;
1071
1072        GLenum lastTextureType = mTextureTypes[stage];
1073
1074                glActiveTextureARB( GL_TEXTURE0 + stage );
1075                if (enabled)
1076        {
1077            if (!tex.isNull())
1078            {
1079                // note used
1080                tex->touch();
1081                mTextureTypes[stage] = tex->getGLTextureTarget();
1082            }
1083            else
1084                // assume 2D
1085                mTextureTypes[stage] = GL_TEXTURE_2D;
1086
1087            if(lastTextureType != mTextureTypes[stage] && lastTextureType != 0)
1088            {
1089                                if (stage < mFixedFunctionTextureUnits)
1090                                {
1091                        glDisable( lastTextureType );
1092                                }
1093            }
1094
1095                        if (stage < mFixedFunctionTextureUnits)
1096                        {
1097                                glEnable( mTextureTypes[stage] );
1098                        }
1099
1100                        if(!tex.isNull())
1101                                glBindTexture( mTextureTypes[stage], tex->getGLID() );
1102                        else
1103                                glBindTexture( mTextureTypes[stage], static_cast<GLTextureManager*>(mTextureManager)->getWarningTextureID() );
1104        }
1105        else
1106        {
1107                        if (stage < mFixedFunctionTextureUnits)
1108                        {
1109                                if (lastTextureType != 0)
1110                                {
1111                                        glDisable( mTextureTypes[stage] );
1112                                }
1113                                glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1114                        }
1115                        // bind zero texture
1116                        glBindTexture (GL_TEXTURE_2D, 0); 
1117        }
1118
1119        glActiveTextureARB( GL_TEXTURE0 );
1120    }
1121
1122    //-----------------------------------------------------------------------------
1123    void GLRenderSystem::_setTextureCoordSet(size_t stage, size_t index)
1124    {
1125        mTextureCoordIndex[stage] = index;
1126    }
1127    //-----------------------------------------------------------------------------
1128    void GLRenderSystem::_setTextureCoordCalculation(size_t stage, TexCoordCalcMethod m, 
1129        const Frustum* frustum)
1130    {
1131                if (stage >= mFixedFunctionTextureUnits)
1132                {
1133                        // Can't do this
1134                        return;
1135                }
1136
1137               
1138                GLfloat M[16];
1139        Matrix4 projectionBias;
1140
1141        // Default to no extra auto texture matrix
1142        mUseAutoTextureMatrix = false;
1143
1144        GLfloat eyePlaneS[] = {1.0, 0.0, 0.0, 0.0};
1145        GLfloat eyePlaneT[] = {0.0, 1.0, 0.0, 0.0};
1146        GLfloat eyePlaneR[] = {0.0, 0.0, 1.0, 0.0};
1147        GLfloat eyePlaneQ[] = {0.0, 0.0, 0.0, 1.0};
1148
1149        glActiveTextureARB( GL_TEXTURE0 + stage );
1150
1151                switch( m )
1152        {
1153        case TEXCALC_NONE:
1154            glDisable( GL_TEXTURE_GEN_S );
1155            glDisable( GL_TEXTURE_GEN_T );
1156            glDisable( GL_TEXTURE_GEN_R );
1157            glDisable( GL_TEXTURE_GEN_Q );
1158            break;
1159
1160        case TEXCALC_ENVIRONMENT_MAP:
1161            glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP );
1162            glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP );
1163
1164            glEnable( GL_TEXTURE_GEN_S );
1165            glEnable( GL_TEXTURE_GEN_T );
1166            glDisable( GL_TEXTURE_GEN_R );
1167            glDisable( GL_TEXTURE_GEN_Q );
1168
1169            // Need to use a texture matrix to flip the spheremap
1170            mUseAutoTextureMatrix = true;
1171            memset(mAutoTextureMatrix, 0, sizeof(GLfloat)*16);
1172            mAutoTextureMatrix[0] = mAutoTextureMatrix[10] = mAutoTextureMatrix[15] = 1.0f;
1173            mAutoTextureMatrix[5] = -1.0f;
1174
1175            break;
1176
1177        case TEXCALC_ENVIRONMENT_MAP_PLANAR:           
1178            // XXX This doesn't seem right?!
1179#ifdef GL_VERSION_1_3
1180            glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP );
1181            glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP );
1182            glTexGeni( GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP );
1183
1184            glEnable( GL_TEXTURE_GEN_S );
1185            glEnable( GL_TEXTURE_GEN_T );
1186            glEnable( GL_TEXTURE_GEN_R );
1187            glDisable( GL_TEXTURE_GEN_Q );
1188#else
1189            glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP );
1190            glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP );
1191
1192            glEnable( GL_TEXTURE_GEN_S );
1193            glEnable( GL_TEXTURE_GEN_T );
1194            glDisable( GL_TEXTURE_GEN_R );
1195            glDisable( GL_TEXTURE_GEN_Q );
1196#endif
1197            break;
1198        case TEXCALC_ENVIRONMENT_MAP_REFLECTION:
1199           
1200            glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP );
1201            glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP );
1202            glTexGeni( GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP );
1203
1204            glEnable( GL_TEXTURE_GEN_S );
1205            glEnable( GL_TEXTURE_GEN_T );
1206            glEnable( GL_TEXTURE_GEN_R );
1207            glDisable( GL_TEXTURE_GEN_Q );
1208
1209            // We need an extra texture matrix here
1210            // This sets the texture matrix to be the inverse of the view matrix
1211            mUseAutoTextureMatrix = true;
1212                        makeGLMatrix( M, mViewMatrix);
1213
1214            // Transpose 3x3 in order to invert matrix (rotation)
1215            // Note that we need to invert the Z _before_ the rotation
1216            // No idea why we have to invert the Z at all, but reflection is wrong without it
1217            mAutoTextureMatrix[0] = M[0]; mAutoTextureMatrix[1] = M[4]; mAutoTextureMatrix[2] = -M[8];
1218            mAutoTextureMatrix[4] = M[1]; mAutoTextureMatrix[5] = M[5]; mAutoTextureMatrix[6] = -M[9];
1219            mAutoTextureMatrix[8] = M[2]; mAutoTextureMatrix[9] = M[6]; mAutoTextureMatrix[10] = -M[10];
1220            mAutoTextureMatrix[3] = mAutoTextureMatrix[7] = mAutoTextureMatrix[11] = 0.0f;
1221            mAutoTextureMatrix[12] = mAutoTextureMatrix[13] = mAutoTextureMatrix[14] = 0.0f;
1222            mAutoTextureMatrix[15] = 1.0f;
1223
1224            break;
1225        case TEXCALC_ENVIRONMENT_MAP_NORMAL:
1226            glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP );
1227            glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP );
1228            glTexGeni( GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP );
1229
1230            glEnable( GL_TEXTURE_GEN_S );
1231            glEnable( GL_TEXTURE_GEN_T );
1232            glEnable( GL_TEXTURE_GEN_R );
1233            glDisable( GL_TEXTURE_GEN_Q );
1234            break;
1235        case TEXCALC_PROJECTIVE_TEXTURE:
1236            glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
1237            glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
1238            glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
1239            glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
1240            glTexGenfv(GL_S, GL_EYE_PLANE, eyePlaneS);
1241            glTexGenfv(GL_T, GL_EYE_PLANE, eyePlaneT);
1242            glTexGenfv(GL_R, GL_EYE_PLANE, eyePlaneR);
1243            glTexGenfv(GL_Q, GL_EYE_PLANE, eyePlaneQ);
1244            glEnable(GL_TEXTURE_GEN_S);
1245            glEnable(GL_TEXTURE_GEN_T);
1246            glEnable(GL_TEXTURE_GEN_R);
1247            glEnable(GL_TEXTURE_GEN_Q);
1248
1249            mUseAutoTextureMatrix = true;
1250
1251            // Set scale and translation matrix for projective textures
1252            projectionBias = Matrix4::CLIPSPACE2DTOIMAGESPACE;
1253
1254            projectionBias = projectionBias * frustum->getProjectionMatrix();
1255            projectionBias = projectionBias * frustum->getViewMatrix();
1256            projectionBias = projectionBias * mWorldMatrix;
1257
1258            makeGLMatrix(mAutoTextureMatrix, projectionBias);
1259            break;
1260        default:
1261            break;
1262        }
1263        glActiveTextureARB( GL_TEXTURE0 );
1264    }
1265    //-----------------------------------------------------------------------------
1266        GLint GLRenderSystem::getTextureAddressingMode(
1267                TextureUnitState::TextureAddressingMode tam) const
1268        {
1269        switch(tam)
1270        {
1271        default:
1272        case TextureUnitState::TAM_WRAP:
1273            return GL_REPEAT;
1274        case TextureUnitState::TAM_MIRROR:
1275            return GL_MIRRORED_REPEAT;
1276        case TextureUnitState::TAM_CLAMP:
1277            return GL_CLAMP_TO_EDGE;
1278        case TextureUnitState::TAM_BORDER:
1279            return GL_CLAMP_TO_BORDER;
1280        }
1281               
1282        }
1283    //-----------------------------------------------------------------------------
1284    void GLRenderSystem::_setTextureAddressingMode(size_t stage, const TextureUnitState::UVWAddressingMode& uvw)
1285    {
1286        glActiveTextureARB( GL_TEXTURE0 + stage );
1287        glTexParameteri( mTextureTypes[stage], GL_TEXTURE_WRAP_S, 
1288                        getTextureAddressingMode(uvw.u));
1289        glTexParameteri( mTextureTypes[stage], GL_TEXTURE_WRAP_T, 
1290                        getTextureAddressingMode(uvw.v));
1291        glTexParameteri( mTextureTypes[stage], GL_TEXTURE_WRAP_R, 
1292                                getTextureAddressingMode(uvw.w));
1293        glActiveTextureARB( GL_TEXTURE0 );
1294    }
1295    //-----------------------------------------------------------------------------
1296    void GLRenderSystem::_setTextureBorderColour(size_t stage, const ColourValue& colour)
1297    {
1298        GLfloat border[4] = { colour.r, colour.g, colour.b, colour.a };
1299        glActiveTextureARB( GL_TEXTURE0 + stage );
1300        glTexParameterfv( mTextureTypes[stage], GL_TEXTURE_BORDER_COLOR, border);
1301        glActiveTextureARB( GL_TEXTURE0 );
1302    }
1303        //-----------------------------------------------------------------------------
1304        void GLRenderSystem::_setTextureMipmapBias(size_t stage, float bias)
1305        {
1306                if (mCapabilities->hasCapability(RSC_MIPMAP_LOD_BIAS))
1307                {
1308                        glActiveTextureARB( GL_TEXTURE0 + stage );
1309                        glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, bias);
1310                        glActiveTextureARB( GL_TEXTURE0 );
1311                }
1312
1313        }
1314        //-----------------------------------------------------------------------------
1315    void GLRenderSystem::_setTextureMatrix(size_t stage, const Matrix4& xform)
1316    {
1317                if (stage >= mFixedFunctionTextureUnits)
1318                {
1319                        // Can't do this
1320                        return;
1321                }
1322
1323                GLfloat mat[16];
1324        makeGLMatrix(mat, xform);
1325
1326        glActiveTextureARB(GL_TEXTURE0 + stage);
1327        glMatrixMode(GL_TEXTURE);
1328
1329        // Load this matrix in
1330        glLoadMatrixf(mat);
1331
1332        if (mUseAutoTextureMatrix)
1333        {
1334            // Concat auto matrix
1335            glMultMatrixf(mAutoTextureMatrix);
1336        }
1337
1338        glMatrixMode(GL_MODELVIEW);
1339        glActiveTextureARB(GL_TEXTURE0);
1340    }
1341    //-----------------------------------------------------------------------------
1342    GLint GLRenderSystem::getBlendMode(SceneBlendFactor ogreBlend) const
1343    {
1344        switch(ogreBlend)
1345        {
1346        case SBF_ONE:
1347            return GL_ONE;
1348        case SBF_ZERO:
1349            return GL_ZERO;
1350        case SBF_DEST_COLOUR:
1351            return GL_DST_COLOR;
1352        case SBF_SOURCE_COLOUR:
1353            return GL_SRC_COLOR;
1354        case SBF_ONE_MINUS_DEST_COLOUR:
1355            return GL_ONE_MINUS_DST_COLOR;
1356        case SBF_ONE_MINUS_SOURCE_COLOUR:
1357            return GL_ONE_MINUS_SRC_COLOR;
1358        case SBF_DEST_ALPHA:
1359            return GL_DST_ALPHA;
1360        case SBF_SOURCE_ALPHA:
1361            return GL_SRC_ALPHA;
1362        case SBF_ONE_MINUS_DEST_ALPHA:
1363            return GL_ONE_MINUS_DST_ALPHA;
1364        case SBF_ONE_MINUS_SOURCE_ALPHA:
1365            return GL_ONE_MINUS_SRC_ALPHA;
1366        };
1367                // to keep compiler happy
1368                return GL_ONE;
1369    }
1370
1371    void GLRenderSystem::_setSceneBlending(SceneBlendFactor sourceFactor, SceneBlendFactor destFactor)
1372    {
1373        GLint sourceBlend = getBlendMode(sourceFactor);
1374        GLint destBlend = getBlendMode(destFactor);
1375        if(sourceFactor == SBF_ONE && destFactor == SBF_ZERO)
1376        {
1377            glDisable(GL_BLEND);
1378        }
1379        else
1380        {
1381            glEnable(GL_BLEND);
1382            glBlendFunc(sourceBlend, destBlend);
1383        }
1384    }
1385    //-----------------------------------------------------------------------------
1386    void GLRenderSystem::_setAlphaRejectSettings(CompareFunction func, unsigned char value)
1387    {
1388        if(func == CMPF_ALWAYS_PASS)
1389        {
1390            glDisable(GL_ALPHA_TEST);
1391        }
1392        else
1393        {
1394            glEnable(GL_ALPHA_TEST);
1395            glAlphaFunc(convertCompareFunction(func), value / 255.0f);
1396        }
1397    }
1398    //-----------------------------------------------------------------------------
1399    void GLRenderSystem::_setViewport(Viewport *vp)
1400    {
1401        // Check if viewport is different
1402        if (vp != mActiveViewport || vp->_isUpdated())
1403        {
1404            RenderTarget* target;
1405            target = vp->getTarget();
1406            _setRenderTarget(target);
1407            mActiveViewport = vp;
1408             
1409              GLsizei x, y, w, h;
1410 
1411              // Calculate the "lower-left" corner of the viewport
1412              w = vp->getActualWidth();
1413              h = vp->getActualHeight();
1414              x = vp->getActualLeft();
1415              y = vp->getActualTop();
1416              if (!target->requiresTextureFlipping())
1417              {
1418                  // Convert "upper-left" corner to "lower-left"
1419                  y = target->getHeight() - h - y;
1420              }
1421              glViewport(x, y, w, h);
1422 
1423              // Configure the viewport clipping
1424              glScissor(x, y, w, h);
1425 
1426              vp->_clearUpdatedFlag();
1427        }
1428    }
1429
1430        void GLRenderSystem::setLights()
1431        {
1432        for (size_t i = 0; i < MAX_LIGHTS; ++i)
1433        {
1434            if (mLights[i] != NULL)
1435            {
1436                Light* lt = mLights[i];
1437                setGLLightPositionDirection(lt, GL_LIGHT0 + i);
1438            }
1439        }
1440        }
1441
1442    //-----------------------------------------------------------------------------
1443    void GLRenderSystem::_beginFrame(void)
1444    {
1445        if (!mActiveViewport)
1446            OGRE_EXCEPT(Exception::ERR_INVALID_STATE, 
1447                                "Cannot begin frame - no viewport selected.",
1448                "GLRenderSystem::_beginFrame");
1449
1450        // Activate the viewport clipping
1451        glEnable(GL_SCISSOR_TEST);
1452    }
1453   
1454    //-----------------------------------------------------------------------------
1455    void GLRenderSystem::_endFrame(void)
1456    {
1457        // Deactivate the viewport clipping.
1458        glDisable(GL_SCISSOR_TEST);
1459    }
1460
1461    //-----------------------------------------------------------------------------
1462    void GLRenderSystem::_setCullingMode(CullingMode mode)
1463    {
1464        // NB: Because two-sided stencil API dependence of the front face, we must
1465        // use the same 'winding' for the front face everywhere. As the OGRE default
1466        // culling mode is clockwise, we also treat anticlockwise winding as front
1467        // face for consistently. On the assumption that, we can't change the front
1468        // face by glFrontFace anywhere.
1469
1470        GLenum cullMode;
1471
1472        switch( mode )
1473        {
1474        case CULL_NONE:
1475            glDisable( GL_CULL_FACE );
1476            return;
1477                default:
1478        case CULL_CLOCKWISE:
1479            if (mActiveRenderTarget && 
1480                ((mActiveRenderTarget->requiresTextureFlipping() && !mInvertVertexWinding) ||
1481                (!mActiveRenderTarget->requiresTextureFlipping() && mInvertVertexWinding)))
1482            {
1483                cullMode = GL_FRONT;
1484            }
1485            else
1486            {
1487                cullMode = GL_BACK;
1488            }
1489            break;
1490        case CULL_ANTICLOCKWISE:
1491            if (mActiveRenderTarget && 
1492                ((mActiveRenderTarget->requiresTextureFlipping() && !mInvertVertexWinding) ||
1493                (!mActiveRenderTarget->requiresTextureFlipping() && mInvertVertexWinding)))
1494            {
1495                cullMode = GL_BACK;
1496            }
1497            else
1498            {
1499                cullMode = GL_FRONT;
1500            }
1501            break;
1502        }
1503
1504        glEnable( GL_CULL_FACE );
1505        glCullFace( cullMode );
1506    }
1507    //-----------------------------------------------------------------------------
1508    void GLRenderSystem::_setDepthBufferParams(bool depthTest, bool depthWrite, CompareFunction depthFunction)
1509    {
1510        _setDepthBufferCheckEnabled(depthTest);
1511        _setDepthBufferWriteEnabled(depthWrite);
1512        _setDepthBufferFunction(depthFunction);
1513    }
1514    //-----------------------------------------------------------------------------
1515    void GLRenderSystem::_setDepthBufferCheckEnabled(bool enabled)
1516    {
1517        if (enabled)
1518        {
1519            glClearDepth(1.0f);
1520            glEnable(GL_DEPTH_TEST);
1521        }
1522        else
1523        {
1524            glDisable(GL_DEPTH_TEST);
1525        }
1526    }
1527    //-----------------------------------------------------------------------------
1528    void GLRenderSystem::_setDepthBufferWriteEnabled(bool enabled)
1529    {
1530        GLboolean flag = enabled ? GL_TRUE : GL_FALSE;
1531        glDepthMask( flag ); 
1532        // Store for reference in _beginFrame
1533        mDepthWrite = enabled;
1534    }
1535    //-----------------------------------------------------------------------------
1536    void GLRenderSystem::_setDepthBufferFunction(CompareFunction func)
1537    {
1538        glDepthFunc(convertCompareFunction(func));
1539    }
1540    //-----------------------------------------------------------------------------
1541    void GLRenderSystem::_setDepthBias(float constantBias, float slopeScaleBias)
1542    {
1543        if (constantBias != 0 || slopeScaleBias != 0)
1544        {
1545            glEnable(GL_POLYGON_OFFSET_FILL);
1546            glEnable(GL_POLYGON_OFFSET_POINT);
1547            glEnable(GL_POLYGON_OFFSET_LINE);
1548            glPolygonOffset(-slopeScaleBias, -constantBias);
1549        }
1550        else
1551        {
1552            glDisable(GL_POLYGON_OFFSET_FILL);
1553            glDisable(GL_POLYGON_OFFSET_POINT);
1554            glDisable(GL_POLYGON_OFFSET_LINE);
1555        }
1556    }
1557        //-----------------------------------------------------------------------------
1558        void GLRenderSystem::_setColourBufferWriteEnabled(bool red, bool green, bool blue, bool alpha)
1559        {
1560                glColorMask(red, green, blue, alpha);
1561                // record this
1562                mColourWrite[0] = red;
1563                mColourWrite[1] = blue;
1564                mColourWrite[2] = green;
1565                mColourWrite[3] = alpha;
1566        }
1567        //-----------------------------------------------------------------------------
1568    String GLRenderSystem::getErrorDescription(long errCode) const
1569    {
1570        const GLubyte *errString = gluErrorString (errCode);
1571        return String((const char*) errString);
1572    }
1573    //-----------------------------------------------------------------------------
1574    void GLRenderSystem::setLightingEnabled(bool enabled)
1575    {
1576        if (enabled) 
1577        {     
1578            glEnable(GL_LIGHTING);
1579        } 
1580        else 
1581        {
1582            glDisable(GL_LIGHTING);
1583        }
1584    }
1585    //-----------------------------------------------------------------------------
1586    void GLRenderSystem::_setFog(FogMode mode, const ColourValue& colour, Real density, Real start, Real end)
1587    {
1588
1589        GLint fogMode;
1590        switch (mode)
1591        {
1592        case FOG_EXP:
1593            fogMode = GL_EXP;
1594            break;
1595        case FOG_EXP2:
1596            fogMode = GL_EXP2;
1597            break;
1598        case FOG_LINEAR:
1599            fogMode = GL_LINEAR;
1600            break;
1601        default:
1602            // Give up on it
1603            glDisable(GL_FOG);
1604            return;
1605        }
1606
1607        glEnable(GL_FOG);
1608        glFogi(GL_FOG_MODE, fogMode);
1609        GLfloat fogColor[4] = {colour.r, colour.g, colour.b, colour.a};
1610        glFogfv(GL_FOG_COLOR, fogColor);
1611        glFogf(GL_FOG_DENSITY, density);
1612        glFogf(GL_FOG_START, start);
1613        glFogf(GL_FOG_END, end);
1614        // XXX Hint here?
1615    }
1616
1617        VertexElementType GLRenderSystem::getColourVertexElementType(void) const
1618    {
1619        return VET_COLOUR_ABGR;
1620    }
1621   
1622    void GLRenderSystem::_convertProjectionMatrix(const Matrix4& matrix,
1623        Matrix4& dest, bool forGpuProgram)
1624    {
1625        // no any convertion request for OpenGL
1626        dest = matrix;
1627    }
1628
1629    void GLRenderSystem::_makeProjectionMatrix(const Radian& fovy, Real aspect, Real nearPlane, 
1630        Real farPlane, Matrix4& dest, bool forGpuProgram)
1631    {
1632        Radian thetaY ( fovy / 2.0f );
1633        Real tanThetaY = Math::Tan(thetaY);
1634        //Real thetaX = thetaY * aspect;
1635        //Real tanThetaX = Math::Tan(thetaX);
1636
1637        // Calc matrix elements
1638        Real w = (1.0f / tanThetaY) / aspect;
1639        Real h = 1.0f / tanThetaY;
1640        Real q, qn;
1641        if (farPlane == 0)
1642        {
1643            // Infinite far plane
1644            q = Frustum::INFINITE_FAR_PLANE_ADJUST - 1;
1645            qn = nearPlane * (Frustum::INFINITE_FAR_PLANE_ADJUST - 2);
1646        }
1647        else
1648        {
1649            q = -(farPlane + nearPlane) / (farPlane - nearPlane);
1650            qn = -2 * (farPlane * nearPlane) / (farPlane - nearPlane);
1651        }
1652
1653        // NB This creates Z in range [-1,1]
1654        //
1655        // [ w   0   0   0  ]
1656        // [ 0   h   0   0  ]
1657        // [ 0   0   q   qn ]
1658        // [ 0   0   -1  0  ]
1659
1660        dest = Matrix4::ZERO;
1661        dest[0][0] = w;
1662        dest[1][1] = h;
1663        dest[2][2] = q;
1664        dest[2][3] = qn;
1665        dest[3][2] = -1;
1666
1667    }
1668   
1669    void GLRenderSystem::_makeOrthoMatrix(const Radian& fovy, Real aspect, Real nearPlane, 
1670        Real farPlane, Matrix4& dest, bool forGpuProgram)
1671    {
1672        Radian thetaY (fovy / 2.0f);
1673        Real tanThetaY = Math::Tan(thetaY);
1674
1675        //Real thetaX = thetaY * aspect;
1676        Real tanThetaX = tanThetaY * aspect; //Math::Tan(thetaX);
1677        Real half_w = tanThetaX * nearPlane;
1678        Real half_h = tanThetaY * nearPlane;
1679        Real iw = 1.0 / half_w;
1680        Real ih = 1.0 / half_h;
1681        Real q;
1682        if (farPlane == 0)
1683        {
1684            q = 0;
1685        }
1686        else
1687        {
1688            q = 2.0 / (farPlane - nearPlane);
1689        }
1690        dest = Matrix4::ZERO;
1691        dest[0][0] = iw;
1692        dest[1][1] = ih;
1693        dest[2][2] = -q;
1694        dest[2][3] = - (farPlane + nearPlane)/(farPlane - nearPlane);
1695        dest[3][3] = 1;
1696        }
1697
1698    void GLRenderSystem::_setPolygonMode(PolygonMode level)
1699    {
1700        GLenum glmode;
1701        switch(level)
1702        {
1703        case PM_POINTS:
1704            glmode = GL_POINT;
1705            break;
1706        case PM_WIREFRAME:
1707            glmode = GL_LINE;
1708            break;
1709                default:
1710        case PM_SOLID:
1711            glmode = GL_FILL;
1712            break;
1713        }
1714        glPolygonMode(GL_FRONT_AND_BACK, glmode);
1715    }
1716    //---------------------------------------------------------------------
1717    void GLRenderSystem::setStencilCheckEnabled(bool enabled)
1718    {
1719        if (enabled)
1720        {
1721            glEnable(GL_STENCIL_TEST);
1722        }
1723        else
1724        {
1725            glDisable(GL_STENCIL_TEST);
1726        }
1727    }
1728    //---------------------------------------------------------------------
1729    void GLRenderSystem::setStencilBufferParams(CompareFunction func, 
1730        uint32 refValue, uint32 mask, StencilOperation stencilFailOp, 
1731        StencilOperation depthFailOp, StencilOperation passOp, 
1732        bool twoSidedOperation)
1733    {
1734        bool flip;
1735                mStencilMask = mask;
1736
1737        if (twoSidedOperation)
1738        {
1739            if (!mCapabilities->hasCapability(RSC_TWO_SIDED_STENCIL))
1740                OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "2-sided stencils are not supported",
1741                    "GLRenderSystem::setStencilBufferParams");
1742           
1743            // NB: We should always treat CCW as front face for consistent with default
1744            // culling mode. Therefore, we must take care with two-sided stencil settings.
1745            flip = (mInvertVertexWinding && !mActiveRenderTarget->requiresTextureFlipping()) ||
1746                   (!mInvertVertexWinding && mActiveRenderTarget->requiresTextureFlipping());
1747                        if(GLEW_VERSION_2_0) // New GL2 commands
1748                        {
1749                                // Back
1750                                glStencilMaskSeparate(GL_BACK, mask);
1751                                glStencilFuncSeparate(GL_BACK, convertCompareFunction(func), refValue, mask);
1752                                glStencilOpSeparate(GL_BACK, 
1753                                        convertStencilOp(stencilFailOp, !flip), 
1754                                        convertStencilOp(depthFailOp, !flip), 
1755                                        convertStencilOp(passOp, !flip));
1756                                // Front
1757                                glStencilMaskSeparate(GL_FRONT, mask);
1758                                glStencilFuncSeparate(GL_FRONT, convertCompareFunction(func), refValue, mask);
1759                                glStencilOpSeparate(GL_FRONT, 
1760                                        convertStencilOp(stencilFailOp, flip),
1761                                        convertStencilOp(depthFailOp, flip), 
1762                                        convertStencilOp(passOp, flip));
1763                        }
1764                        else // EXT_stencil_two_side
1765                        {
1766                                glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
1767                                // Back
1768                                glActiveStencilFaceEXT(GL_BACK);
1769                                glStencilMask(mask);
1770                                glStencilFunc(convertCompareFunction(func), refValue, mask);
1771                                glStencilOp(
1772                                        convertStencilOp(stencilFailOp, !flip), 
1773                                        convertStencilOp(depthFailOp, !flip), 
1774                                        convertStencilOp(passOp, !flip));
1775                                // Front
1776                                glActiveStencilFaceEXT(GL_FRONT);
1777                                glStencilMask(mask);
1778                                glStencilFunc(convertCompareFunction(func), refValue, mask);
1779                                glStencilOp(
1780                                        convertStencilOp(stencilFailOp, flip),
1781                                        convertStencilOp(depthFailOp, flip), 
1782                                        convertStencilOp(passOp, flip));
1783                        }
1784        }
1785        else
1786        {
1787            glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);
1788            flip = false;
1789                        glStencilMask(mask);
1790                        glStencilFunc(convertCompareFunction(func), refValue, mask);
1791                        glStencilOp(
1792                                convertStencilOp(stencilFailOp, flip),
1793                                convertStencilOp(depthFailOp, flip), 
1794                                convertStencilOp(passOp, flip));
1795        }
1796    }
1797    //---------------------------------------------------------------------
1798    GLint GLRenderSystem::convertCompareFunction(CompareFunction func) const
1799    {
1800        switch(func)
1801        {
1802        case CMPF_ALWAYS_FAIL:
1803            return GL_NEVER;
1804        case CMPF_ALWAYS_PASS:
1805            return GL_ALWAYS;
1806        case CMPF_LESS:
1807            return GL_LESS;
1808        case CMPF_LESS_EQUAL:
1809            return GL_LEQUAL;
1810        case CMPF_EQUAL:
1811            return GL_EQUAL;
1812        case CMPF_NOT_EQUAL:
1813            return GL_NOTEQUAL;
1814        case CMPF_GREATER_EQUAL:
1815            return GL_GEQUAL;
1816        case CMPF_GREATER:
1817            return GL_GREATER;
1818        };
1819        // to keep compiler happy
1820        return GL_ALWAYS;
1821    }
1822    //---------------------------------------------------------------------
1823    GLint GLRenderSystem::convertStencilOp(StencilOperation op, bool invert) const
1824    {
1825        switch(op)
1826        {
1827        case SOP_KEEP:
1828            return GL_KEEP;
1829        case SOP_ZERO:
1830            return GL_ZERO;
1831        case SOP_REPLACE:
1832            return GL_REPLACE;
1833        case SOP_INCREMENT:
1834            return invert ? GL_DECR : GL_INCR;
1835        case SOP_DECREMENT:
1836            return invert ? GL_INCR : GL_DECR;
1837        case SOP_INCREMENT_WRAP:
1838            return invert ? GL_DECR_WRAP_EXT : GL_INCR_WRAP_EXT;
1839        case SOP_DECREMENT_WRAP:
1840            return invert ? GL_INCR_WRAP_EXT : GL_DECR_WRAP_EXT;
1841        case SOP_INVERT:
1842            return GL_INVERT;
1843        };
1844        // to keep compiler happy
1845        return SOP_KEEP;
1846    }
1847        //---------------------------------------------------------------------
1848    GLuint GLRenderSystem::getCombinedMinMipFilter(void) const
1849    {
1850        switch(mMinFilter)
1851        {
1852        case FO_ANISOTROPIC:
1853        case FO_LINEAR:
1854            switch(mMipFilter)
1855            {
1856            case FO_ANISOTROPIC:
1857            case FO_LINEAR:
1858                // linear min, linear mip
1859                return GL_LINEAR_MIPMAP_LINEAR;
1860            case FO_POINT:
1861                // linear min, point mip
1862                return GL_LINEAR_MIPMAP_NEAREST;
1863            case FO_NONE:
1864                // linear min, no mip
1865                return GL_LINEAR;
1866            }
1867            break;
1868        case FO_POINT:
1869        case FO_NONE:
1870            switch(mMipFilter)
1871            {
1872            case FO_ANISOTROPIC:
1873            case FO_LINEAR:
1874                // nearest min, linear mip
1875                return GL_NEAREST_MIPMAP_LINEAR;
1876            case FO_POINT:
1877                // nearest min, point mip
1878                return GL_NEAREST_MIPMAP_NEAREST;
1879            case FO_NONE:
1880                // nearest min, no mip
1881                return GL_NEAREST;
1882            }
1883            break;
1884        }
1885
1886        // should never get here
1887        return 0;
1888
1889    }
1890        //---------------------------------------------------------------------
1891    void GLRenderSystem::_setTextureUnitFiltering(size_t unit, 
1892        FilterType ftype, FilterOptions fo)
1893        {
1894                glActiveTextureARB( GL_TEXTURE0 + unit );
1895        switch(ftype)
1896        {
1897        case FT_MIN:
1898            mMinFilter = fo;
1899            // Combine with existing mip filter
1900                        glTexParameteri(
1901                mTextureTypes[unit],
1902                                GL_TEXTURE_MIN_FILTER, 
1903                                getCombinedMinMipFilter());
1904            break;
1905        case FT_MAG:
1906            switch (fo)
1907            {
1908            case FO_ANISOTROPIC: // GL treats linear and aniso the same
1909            case FO_LINEAR:
1910                            glTexParameteri(
1911                    mTextureTypes[unit],
1912                                    GL_TEXTURE_MAG_FILTER, 
1913                                    GL_LINEAR);
1914                break;
1915            case FO_POINT:
1916            case FO_NONE:
1917                            glTexParameteri(
1918                    mTextureTypes[unit],
1919                                    GL_TEXTURE_MAG_FILTER, 
1920                                    GL_NEAREST);
1921                break;
1922            }
1923            break;
1924        case FT_MIP:
1925            mMipFilter = fo;
1926            // Combine with existing min filter
1927                        glTexParameteri(
1928                mTextureTypes[unit],
1929                                GL_TEXTURE_MIN_FILTER, 
1930                                getCombinedMinMipFilter());
1931            break;
1932                }
1933
1934        glActiveTextureARB( GL_TEXTURE0 );
1935        }
1936        //---------------------------------------------------------------------
1937        GLfloat GLRenderSystem::_getCurrentAnisotropy(size_t unit)
1938        {
1939                GLfloat curAniso = 0;
1940                glGetTexParameterfv(mTextureTypes[unit], 
1941            GL_TEXTURE_MAX_ANISOTROPY_EXT, &curAniso);
1942                return curAniso ? curAniso : 1;
1943        }
1944        //---------------------------------------------------------------------
1945        void GLRenderSystem::_setTextureLayerAnisotropy(size_t unit, unsigned int maxAnisotropy)
1946        {
1947       if (!mCapabilities->hasCapability(RSC_ANISOTROPY))
1948                        return;
1949
1950                GLfloat largest_supported_anisotropy = 0;
1951                glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &largest_supported_anisotropy);
1952                if (maxAnisotropy > largest_supported_anisotropy)
1953                        maxAnisotropy = largest_supported_anisotropy ? 
1954                                static_cast<uint>(largest_supported_anisotropy) : 1;
1955                if (_getCurrentAnisotropy(unit) != maxAnisotropy)
1956                        glTexParameterf(mTextureTypes[unit], GL_TEXTURE_MAX_ANISOTROPY_EXT, maxAnisotropy);
1957        }
1958        //-----------------------------------------------------------------------------
1959    void GLRenderSystem::_setTextureBlendMode(size_t stage, const LayerBlendModeEx& bm)
1960    {       
1961                if (stage >= mFixedFunctionTextureUnits)
1962                {
1963                        // Can't do this
1964                        return;
1965                }
1966
1967                // Check to see if blending is supported
1968        if(!mCapabilities->hasCapability(RSC_BLENDING))
1969            return;
1970
1971        GLenum src1op, src2op, cmd;
1972        GLfloat cv1[4], cv2[4];
1973
1974                if (bm.blendType == LBT_COLOUR)
1975        {
1976                    cv1[0] = bm.colourArg1.r;
1977                    cv1[1] = bm.colourArg1.g;
1978                    cv1[2] = bm.colourArg1.b;
1979                    cv1[3] = bm.colourArg1.a;
1980                        mManualBlendColours[stage][0] = bm.colourArg1;
1981
1982
1983                    cv2[0] = bm.colourArg2.r;
1984                    cv2[1] = bm.colourArg2.g;
1985                    cv2[2] = bm.colourArg2.b;
1986                    cv2[3] = bm.colourArg2.a;
1987                        mManualBlendColours[stage][1] = bm.colourArg2;
1988        }
1989
1990                if (bm.blendType == LBT_ALPHA)
1991        {
1992                    cv1[0] = mManualBlendColours[stage][0].r;
1993                    cv1[1] = mManualBlendColours[stage][0].g;
1994                    cv1[2] = mManualBlendColours[stage][0].b;
1995                    cv1[3] = bm.alphaArg1;
1996
1997                    cv2[0] = mManualBlendColours[stage][1].r;
1998                    cv2[1] = mManualBlendColours[stage][1].g;
1999                    cv2[2] = mManualBlendColours[stage][1].b;
2000                    cv2[3] = bm.alphaArg2;
2001        }
2002
2003        switch (bm.source1)
2004        {
2005        case LBS_CURRENT:
2006            src1op = GL_PREVIOUS;
2007            break;
2008        case LBS_TEXTURE:
2009            src1op = GL_TEXTURE;
2010            break;
2011        case LBS_MANUAL:
2012            src1op = GL_CONSTANT;
2013                        break;
2014        case LBS_DIFFUSE:
2015            src1op = GL_PRIMARY_COLOR;
2016                        break;
2017        // XXX
2018        case LBS_SPECULAR:
2019            src1op = GL_PRIMARY_COLOR;
2020            break;
2021                default:
2022            src1op = 0;
2023        }
2024
2025        switch (bm.source2)
2026        {
2027        case LBS_CURRENT:
2028            src2op = GL_PREVIOUS;
2029            break;
2030        case LBS_TEXTURE:
2031            src2op = GL_TEXTURE;
2032            break;
2033        case LBS_MANUAL:
2034                        src2op = GL_CONSTANT;
2035                        break;
2036                case LBS_DIFFUSE:
2037            src2op = GL_PRIMARY_COLOR;
2038                        break;
2039        // XXX
2040        case LBS_SPECULAR:
2041            src2op = GL_PRIMARY_COLOR;
2042            break;
2043                default:
2044            src2op = 0;
2045        }
2046
2047        switch (bm.operation)
2048        {
2049        case LBX_SOURCE1:
2050            cmd = GL_REPLACE;
2051            break;
2052        case LBX_SOURCE2:
2053            cmd = GL_REPLACE;
2054            break;
2055        case LBX_MODULATE:
2056            cmd = GL_MODULATE;
2057            break;
2058        case LBX_MODULATE_X2:
2059            cmd = GL_MODULATE;
2060            break;
2061        case LBX_MODULATE_X4:
2062            cmd = GL_MODULATE;
2063            break;
2064        case LBX_ADD:
2065            cmd = GL_ADD;
2066            break;
2067        case LBX_ADD_SIGNED:
2068            cmd = GL_ADD_SIGNED;
2069            break;
2070                case LBX_ADD_SMOOTH:
2071                        cmd = GL_INTERPOLATE;
2072                        break;
2073        case LBX_SUBTRACT:
2074            cmd = GL_SUBTRACT;
2075            break;
2076                case LBX_BLEND_DIFFUSE_COLOUR:
2077                        cmd = GL_INTERPOLATE;
2078                        break; 
2079        case LBX_BLEND_DIFFUSE_ALPHA:
2080            cmd = GL_INTERPOLATE;
2081            break;
2082        case LBX_BLEND_TEXTURE_ALPHA:
2083            cmd = GL_INTERPOLATE;
2084            break;
2085        case LBX_BLEND_CURRENT_ALPHA:
2086            cmd = GL_INTERPOLATE;
2087            break;
2088        case LBX_BLEND_MANUAL:
2089            cmd = GL_INTERPOLATE;
2090            break;
2091        case LBX_DOTPRODUCT:
2092            cmd = mCapabilities->hasCapability(RSC_DOT3) 
2093                ? GL_DOT3_RGB : GL_MODULATE;
2094            break;
2095                default:
2096            cmd = 0;
2097        }
2098
2099                glActiveTextureARB(GL_TEXTURE0 + stage);
2100                glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
2101
2102            if (bm.blendType == LBT_COLOUR)
2103            {
2104                    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, cmd);
2105                    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, src1op);
2106                    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, src2op);
2107                    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_CONSTANT);
2108            }
2109            else
2110            {
2111                    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, cmd);
2112                    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, src1op);
2113                    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, src2op);
2114                    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA, GL_CONSTANT);
2115            }
2116
2117        float blendValue[4] = {0, 0, 0, bm.factor};
2118        switch (bm.operation)
2119        {
2120                case LBX_BLEND_DIFFUSE_COLOUR:
2121                        glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_PRIMARY_COLOR);
2122            glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA, GL_PRIMARY_COLOR);
2123            break;
2124        case LBX_BLEND_DIFFUSE_ALPHA:
2125            glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_PRIMARY_COLOR);
2126            glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA, GL_PRIMARY_COLOR);
2127            break;
2128        case LBX_BLEND_TEXTURE_ALPHA:
2129                        glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_TEXTURE);
2130                        glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA, GL_TEXTURE);
2131            break;
2132        case LBX_BLEND_CURRENT_ALPHA:
2133                        glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_PREVIOUS);
2134                        glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA, GL_PREVIOUS);
2135            break;
2136        case LBX_BLEND_MANUAL:
2137            glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, blendValue);
2138            break;
2139        default:
2140            break;
2141        };
2142
2143        switch (bm.operation)
2144        {
2145        case LBX_MODULATE_X2:
2146                        glTexEnvi(GL_TEXTURE_ENV, bm.blendType == LBT_COLOUR ? 
2147                GL_RGB_SCALE : GL_ALPHA_SCALE, 2);
2148            break;
2149        case LBX_MODULATE_X4:
2150                        glTexEnvi(GL_TEXTURE_ENV, bm.blendType == LBT_COLOUR ? 
2151                GL_RGB_SCALE : GL_ALPHA_SCALE, 4);
2152            break;
2153        default:
2154                        glTexEnvi(GL_TEXTURE_ENV, bm.blendType == LBT_COLOUR ? 
2155                GL_RGB_SCALE : GL_ALPHA_SCALE, 1);
2156            break;
2157                }
2158
2159                if (bm.blendType == LBT_COLOUR){
2160                        glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
2161                        glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
2162                        if (bm.operation == LBX_BLEND_DIFFUSE_COLOUR){
2163                                glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR);
2164                        } else {
2165                                glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA);
2166                        }
2167                } 
2168
2169                glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
2170                glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
2171                glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA, GL_SRC_ALPHA);
2172        if(bm.source1 == LBS_MANUAL)
2173            glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, cv1);
2174        if (bm.source2 == LBS_MANUAL)
2175            glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, cv2);
2176
2177        glActiveTextureARB(GL_TEXTURE0);
2178        }
2179    //---------------------------------------------------------------------
2180    void GLRenderSystem::setGLLightPositionDirection(Light* lt, GLenum lightindex)
2181    {
2182        // Set position / direction
2183        Vector4 vec;
2184                // Use general 4D vector which is the same as GL's approach
2185                vec = lt->getAs4DVector();
2186
2187#if OGRE_DOUBLE_PRECISION
2188                // Must convert to float*
2189                float tmp[4] = {vec.x, vec.y, vec.z, vec.w};
2190                glLightfv(lightindex, GL_POSITION, tmp);
2191#else
2192                glLightfv(lightindex, GL_POSITION, vec.ptr());
2193#endif
2194                // Set spotlight direction
2195        if (lt->getType() == Light::LT_SPOTLIGHT)
2196        {
2197            vec = lt->getDerivedDirection();
2198            vec.w = 0.0; 
2199#if OGRE_DOUBLE_PRECISION
2200                        // Must convert to float*
2201                        float tmp2[4] = {vec.x, vec.y, vec.z, vec.w};
2202                        glLightfv(lightindex, GL_SPOT_DIRECTION, tmp2);
2203#else
2204            glLightfv(lightindex, GL_SPOT_DIRECTION, vec.ptr());
2205#endif
2206        }
2207    }
2208    //---------------------------------------------------------------------
2209        void GLRenderSystem::setVertexDeclaration(VertexDeclaration* decl)
2210        {
2211        }
2212    //---------------------------------------------------------------------
2213        void GLRenderSystem::setVertexBufferBinding(VertexBufferBinding* binding)
2214        {
2215        }
2216    //---------------------------------------------------------------------
2217    void GLRenderSystem::_render(const RenderOperation& op)
2218        {
2219        // Call super class
2220        RenderSystem::_render(op);
2221
2222        void* pBufferData = 0;
2223       
2224        const VertexDeclaration::VertexElementList& decl = 
2225            op.vertexData->vertexDeclaration->getElements();
2226        VertexDeclaration::VertexElementList::const_iterator elem, elemEnd;
2227        elemEnd = decl.end();
2228
2229        for (elem = decl.begin(); elem != elemEnd; ++elem)
2230        {
2231                        if (!op.vertexData->vertexBufferBinding->isBufferBound(elem->getSource()))
2232                                continue; // skip unbound elements
2233
2234            HardwareVertexBufferSharedPtr vertexBuffer = 
2235                op.vertexData->vertexBufferBinding->getBuffer(elem->getSource());
2236            if(mCapabilities->hasCapability(RSC_VBO))
2237            {
2238                glBindBufferARB(GL_ARRAY_BUFFER_ARB, 
2239                    static_cast<const GLHardwareVertexBuffer*>(vertexBuffer.get())->getGLBufferId());
2240                pBufferData = VBO_BUFFER_OFFSET(elem->getOffset());
2241            }
2242            else
2243            {
2244                pBufferData = static_cast<const GLDefaultHardwareVertexBuffer*>(vertexBuffer.get())->getDataPtr(elem->getOffset());
2245            }
2246            if (op.vertexData->vertexStart)
2247            {
2248                pBufferData = static_cast<char*>(pBufferData) + op.vertexData->vertexStart * vertexBuffer->getVertexSize();
2249            }
2250
2251            unsigned int i = 0;
2252                        VertexElementSemantic sem = elem->getSemantic();
2253            switch(sem)
2254            {
2255            case VES_POSITION:
2256                glVertexPointer(VertexElement::getTypeCount(
2257                    elem->getType()), 
2258                    GLHardwareBufferManager::getGLType(elem->getType()), 
2259                    static_cast<GLsizei>(vertexBuffer->getVertexSize()), 
2260                    pBufferData);
2261                glEnableClientState( GL_VERTEX_ARRAY );
2262                break;
2263            case VES_NORMAL:
2264                glNormalPointer(
2265                    GLHardwareBufferManager::getGLType(elem->getType()), 
2266                    static_cast<GLsizei>(vertexBuffer->getVertexSize()), 
2267                    pBufferData);
2268                glEnableClientState( GL_NORMAL_ARRAY );
2269                break;
2270            case VES_DIFFUSE:
2271                glColorPointer(4, 
2272                    GLHardwareBufferManager::getGLType(elem->getType()), 
2273                    static_cast<GLsizei>(vertexBuffer->getVertexSize()), 
2274                    pBufferData);
2275                glEnableClientState( GL_COLOR_ARRAY );
2276                break;
2277            case VES_SPECULAR:
2278                                if (GLEW_EXT_secondary_color)
2279                                {
2280                                        glSecondaryColorPointerEXT(4, 
2281                                                GLHardwareBufferManager::getGLType(elem->getType()), 
2282                                                static_cast<GLsizei>(vertexBuffer->getVertexSize()), 
2283                                                pBufferData);
2284                                        glEnableClientState( GL_SECONDARY_COLOR_ARRAY );
2285                                }
2286                break;
2287            case VES_TEXTURE_COORDINATES:
2288
2289                                if (mCurrentVertexProgram)
2290                                {
2291                                        // Programmable pipeline - direct UV assignment
2292                                        glClientActiveTextureARB(GL_TEXTURE0 + elem->getIndex());
2293                                        glTexCoordPointer(
2294                                                VertexElement::getTypeCount(elem->getType()), 
2295                                                GLHardwareBufferManager::getGLType(elem->getType()),
2296                                                static_cast<GLsizei>(vertexBuffer->getVertexSize()), 
2297                                                pBufferData);
2298                                        glEnableClientState( GL_TEXTURE_COORD_ARRAY );
2299                                }
2300                                else
2301                                {
2302                                        // fixed function matching to units based on tex_coord_set
2303                                        for (i = 0; i < mDisabledTexUnitsFrom; i++)
2304                                        {
2305                                                // Only set this texture unit's texcoord pointer if it
2306                                                // is supposed to be using this element's index
2307                                                if (mTextureCoordIndex[i] == elem->getIndex())
2308                                                {
2309                                                        glClientActiveTextureARB(GL_TEXTURE0 + i);
2310                                                        glTexCoordPointer(
2311                                                                VertexElement::getTypeCount(elem->getType()), 
2312                                                                GLHardwareBufferManager::getGLType(elem->getType()),
2313                                                                static_cast<GLsizei>(vertexBuffer->getVertexSize()), 
2314                                                                        pBufferData);
2315                                                        glEnableClientState( GL_TEXTURE_COORD_ARRAY );
2316                                                }
2317                                        }
2318                                }
2319                break;
2320            case VES_BLEND_INDICES:
2321            case VES_BLEND_WEIGHTS:
2322                        case VES_TANGENT:
2323                        case VES_BINORMAL:
2324                                if (mCurrentVertexProgram)
2325                                {
2326                                        GLuint attrib = mCurrentVertexProgram->getAttributeIndex(sem);
2327                        glVertexAttribPointerARB(
2328                        attrib,
2329                            VertexElement::getTypeCount(elem->getType()), 
2330                        GLHardwareBufferManager::getGLType(elem->getType()), 
2331                            GL_FALSE, // normalisation disabled
2332                        static_cast<GLsizei>(vertexBuffer->getVertexSize()), 
2333                            pBufferData);
2334                    glEnableVertexAttribArrayARB(attrib);
2335                                       
2336                                }
2337                break;
2338            default:
2339                break;
2340            };
2341
2342        }
2343
2344        glClientActiveTextureARB(GL_TEXTURE0);
2345
2346        // Find the correct type to render
2347        GLint primType;
2348        switch (op.operationType)
2349        {
2350        case RenderOperation::OT_POINT_LIST:
2351            primType = GL_POINTS;
2352            break;
2353        case RenderOperation::OT_LINE_LIST:
2354            primType = GL_LINES;
2355            break;
2356        case RenderOperation::OT_LINE_STRIP:
2357            primType = GL_LINE_STRIP;
2358            break;
2359                default:
2360        case RenderOperation::OT_TRIANGLE_LIST:
2361            primType = GL_TRIANGLES;
2362            break;
2363        case RenderOperation::OT_TRIANGLE_STRIP:
2364            primType = GL_TRIANGLE_STRIP;
2365            break;
2366        case RenderOperation::OT_TRIANGLE_FAN:
2367            primType = GL_TRIANGLE_FAN;
2368            break;
2369        }
2370
2371        if (op.useIndexes)
2372        {
2373            if(mCapabilities->hasCapability(RSC_VBO))
2374            {
2375                glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 
2376                    static_cast<GLHardwareIndexBuffer*>(
2377                        op.indexData->indexBuffer.get())->getGLBufferId());
2378
2379                pBufferData = VBO_BUFFER_OFFSET(
2380                    op.indexData->indexStart * op.indexData->indexBuffer->getIndexSize());
2381            }
2382            else
2383            {
2384                pBufferData = static_cast<GLDefaultHardwareIndexBuffer*>(
2385                    op.indexData->indexBuffer.get())->getDataPtr(
2386                        op.indexData->indexStart * op.indexData->indexBuffer->getIndexSize());
2387            }
2388
2389            GLenum indexType = (op.indexData->indexBuffer->getType() == HardwareIndexBuffer::IT_16BIT) ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
2390
2391                        do
2392                        {
2393                                glDrawElements(primType, op.indexData->indexCount, indexType, pBufferData);
2394                        } while (updatePassIterationRenderState());
2395
2396        }
2397        else
2398        {
2399                        do
2400                        {
2401                                glDrawArrays(primType, 0, op.vertexData->vertexCount);
2402                        } while (updatePassIterationRenderState());
2403        }
2404
2405        glDisableClientState( GL_VERTEX_ARRAY );
2406        for (int i = 0; i < OGRE_MAX_TEXTURE_COORD_SETS; i++)
2407        {
2408            glClientActiveTextureARB(GL_TEXTURE0 + i);
2409            glDisableClientState( GL_TEXTURE_COORD_ARRAY );
2410        }
2411        glClientActiveTextureARB(GL_TEXTURE0);
2412        glDisableClientState( GL_NORMAL_ARRAY );
2413        glDisableClientState( GL_COLOR_ARRAY );
2414                if (GLEW_EXT_secondary_color)
2415                {
2416                        glDisableClientState( GL_SECONDARY_COLOR_ARRAY );
2417                }
2418        if (mCurrentVertexProgram)
2419        {
2420                        // unbind any custom attributes
2421                        if (mCurrentVertexProgram->isAttributeValid(VES_BLEND_INDICES))
2422                        {
2423                                glDisableVertexAttribArrayARB(
2424                                        mCurrentVertexProgram->getAttributeIndex(
2425                                                VES_BLEND_INDICES)); 
2426                        }
2427                        if (mCurrentVertexProgram->isAttributeValid(VES_BLEND_WEIGHTS))
2428                        {
2429                                glDisableVertexAttribArrayARB(
2430                                        mCurrentVertexProgram->getAttributeIndex(
2431                                                VES_BLEND_WEIGHTS)); 
2432                        }
2433                        if (mCurrentVertexProgram->isAttributeValid(VES_TANGENT))
2434                        {
2435                                glDisableVertexAttribArrayARB(
2436                                        mCurrentVertexProgram->getAttributeIndex(
2437                                                VES_TANGENT)); 
2438                        }
2439                        if (mCurrentVertexProgram->isAttributeValid(VES_BINORMAL))
2440                        {
2441                                glDisableVertexAttribArrayARB(
2442                                        mCurrentVertexProgram->getAttributeIndex(
2443                                                VES_BINORMAL)); 
2444                        }
2445        }
2446        glColor4f(1,1,1,1);
2447                if (GLEW_EXT_secondary_color)
2448                {
2449                        glSecondaryColor3fEXT(0.0f, 0.0f, 0.0f);
2450                }
2451
2452        }
2453    //---------------------------------------------------------------------
2454    void GLRenderSystem::setNormaliseNormals(bool normalise)
2455    {
2456        if (normalise)
2457            glEnable(GL_NORMALIZE);
2458        else
2459            glDisable(GL_NORMALIZE);
2460
2461    }
2462        //---------------------------------------------------------------------
2463    void GLRenderSystem::bindGpuProgram(GpuProgram* prg)
2464    {
2465        GLGpuProgram* glprg = static_cast<GLGpuProgram*>(prg);
2466
2467        // Unbind previous gpu program first.
2468        //
2469        // Note:
2470        //  1. Even if both previous and current are the same object, we can't
2471        //     bypass re-bind completely since the object itself maybe modified.
2472        //     But we can bypass unbind based on the assumption that object
2473        //     internally GL program type shouldn't be changed after it has
2474        //     been created. The behavior of bind to a GL program type twice
2475        //     should be same as unbind and rebind that GL program type, even
2476        //     for difference objects.
2477        //  2. We also assumed that the program's type (vertex or fragment) should
2478        //     not be changed during it's in using. If not, the following switch
2479        //     statement will confuse GL state completely, and we can't fix it
2480        //     here. To fix this case, we must coding the program implementation
2481        //     itself, if type is changing (during load/unload, etc), and it's inuse,
2482        //     unbind and notify render system to correct for its state.
2483        //
2484        switch (glprg->getType())
2485        {
2486        case GPT_VERTEX_PROGRAM:
2487            if (mCurrentVertexProgram != glprg)
2488            {
2489                if (mCurrentVertexProgram)
2490                    mCurrentVertexProgram->unbindProgram();
2491                mCurrentVertexProgram = glprg;
2492            }
2493            break;
2494
2495        case GPT_FRAGMENT_PROGRAM:
2496            if (mCurrentFragmentProgram != glprg)
2497            {
2498                if (mCurrentFragmentProgram)
2499                    mCurrentFragmentProgram->unbindProgram();
2500                mCurrentFragmentProgram = glprg;
2501            }
2502            break;
2503        }
2504
2505        // Bind the program
2506        glprg->bindProgram();
2507
2508        RenderSystem::bindGpuProgram(prg);
2509    }
2510        //---------------------------------------------------------------------
2511    void GLRenderSystem::unbindGpuProgram(GpuProgramType gptype)
2512    {
2513
2514        if (gptype == GPT_VERTEX_PROGRAM && mCurrentVertexProgram)
2515        {
2516            mActiveVertexGpuProgramParameters.setNull();
2517            mCurrentVertexProgram->unbindProgram();
2518            mCurrentVertexProgram = 0;
2519        }
2520        else if (gptype == GPT_FRAGMENT_PROGRAM && mCurrentFragmentProgram)
2521        {
2522            mActiveFragmentGpuProgramParameters.setNull();
2523            mCurrentFragmentProgram->unbindProgram();
2524            mCurrentFragmentProgram = 0;
2525        }
2526        RenderSystem::unbindGpuProgram(gptype);
2527
2528    }
2529        //---------------------------------------------------------------------
2530    void GLRenderSystem::bindGpuProgramParameters(GpuProgramType gptype, GpuProgramParametersSharedPtr params)
2531    {
2532        if (gptype == GPT_VERTEX_PROGRAM)
2533        {
2534            mActiveVertexGpuProgramParameters = params;
2535            mCurrentVertexProgram->bindProgramParameters(params);
2536        }
2537        else
2538        {
2539            mActiveFragmentGpuProgramParameters = params;
2540            mCurrentFragmentProgram->bindProgramParameters(params);
2541        }
2542    }
2543        //---------------------------------------------------------------------
2544    void GLRenderSystem::bindGpuProgramPassIterationParameters(GpuProgramType gptype)
2545    {
2546        if (gptype == GPT_VERTEX_PROGRAM)
2547        {
2548            mCurrentVertexProgram->bindProgramPassIterationParameters(mActiveVertexGpuProgramParameters);
2549        }
2550        else
2551        {
2552            mCurrentFragmentProgram->bindProgramPassIterationParameters(mActiveFragmentGpuProgramParameters);
2553        }
2554    }
2555        //---------------------------------------------------------------------
2556    void GLRenderSystem::setClipPlanes(const PlaneList& clipPlanes)
2557    {
2558        size_t i;
2559        size_t numClipPlanes;
2560        GLdouble clipPlane[4];
2561
2562        numClipPlanes = clipPlanes.size();
2563        for (i = 0; i < numClipPlanes; ++i)
2564        {
2565            GLenum clipPlaneId = static_cast<GLenum>(GL_CLIP_PLANE0 + i);
2566            const Plane& plane = clipPlanes[i];
2567
2568            if (i >= 6/*GL_MAX_CLIP_PLANES*/)
2569            {
2570                OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Unable to set clip plane", 
2571                    "GLRenderSystem::setClipPlanes");
2572            }
2573
2574            clipPlane[0] = plane.normal.x;
2575            clipPlane[1] = plane.normal.y;
2576            clipPlane[2] = plane.normal.z;
2577            clipPlane[3] = plane.d;
2578
2579            glClipPlane(clipPlaneId, clipPlane);
2580            glEnable(clipPlaneId);
2581        }
2582
2583            // disable remaining clip planes
2584        for ( ; i < 6/*GL_MAX_CLIP_PLANES*/; ++i)
2585        {
2586            glDisable(static_cast<GLenum>(GL_CLIP_PLANE0 + i));
2587        }
2588    }
2589        //---------------------------------------------------------------------
2590    void GLRenderSystem::setScissorTest(bool enabled, size_t left, 
2591        size_t top, size_t right, size_t bottom)
2592    {
2593        // If request texture flipping, use "upper-left", otherwise use "lower-left"
2594        bool flipping = mActiveRenderTarget->requiresTextureFlipping();
2595        //  GL measures from the bottom, not the top
2596        size_t targetHeight = mActiveRenderTarget->getHeight();
2597        // Calculate the "lower-left" corner of the viewport
2598        GLsizei w, h, x, y;
2599
2600        if (enabled)
2601        {
2602            glEnable(GL_SCISSOR_TEST);
2603            // NB GL uses width / height rather than right / bottom
2604            x = left;
2605            if (flipping)
2606                y = top;
2607            else
2608                y = targetHeight - bottom;
2609            w = right - left;
2610            h = bottom - top;
2611            glScissor(x, y, w, h);
2612        }
2613        else
2614        {
2615            glDisable(GL_SCISSOR_TEST);
2616            // GL requires you to reset the scissor when disabling
2617            w = mActiveViewport->getActualWidth();
2618            h = mActiveViewport->getActualHeight();
2619            x = mActiveViewport->getActualLeft();
2620            if (flipping)
2621                y = mActiveViewport->getActualTop();
2622            else
2623                y = targetHeight - mActiveViewport->getActualTop() - h;
2624            glScissor(x, y, w, h);
2625        }
2626    }
2627    //---------------------------------------------------------------------
2628    void GLRenderSystem::clearFrameBuffer(unsigned int buffers, 
2629        const ColourValue& colour, Real depth, unsigned short stencil)
2630    {
2631
2632                bool colourMask = !mColourWrite[0] || !mColourWrite[1] 
2633                        || !mColourWrite[2] || !mColourWrite[3]; 
2634
2635                GLbitfield flags = 0;
2636        if (buffers & FBT_COLOUR)
2637        {
2638            flags |= GL_COLOR_BUFFER_BIT;
2639                        // Enable buffer for writing if it isn't
2640                        if (colourMask)
2641                        {
2642                                glColorMask(true, true, true, true);
2643                        }
2644                        glClearColor(colour.r, colour.g, colour.b, colour.a);
2645        }
2646        if (buffers & FBT_DEPTH)
2647        {
2648            flags |= GL_DEPTH_BUFFER_BIT;
2649                        // Enable buffer for writing if it isn't
2650                        if (!mDepthWrite)
2651                        {
2652                                glDepthMask( GL_TRUE );
2653                        }
2654                        glClearDepth(depth);
2655        }
2656        if (buffers & FBT_STENCIL)
2657        {
2658            flags |= GL_STENCIL_BUFFER_BIT;
2659                        // Enable buffer for writing if it isn't
2660                        glStencilMask(0xFFFFFFFF);
2661
2662                        glClearStencil(stencil);
2663        }
2664
2665        // Should be enable scissor test due the clear region is
2666        // relied on scissor box bounds.
2667        GLboolean scissorTestEnabled = glIsEnabled(GL_SCISSOR_TEST);
2668        if (!scissorTestEnabled)
2669        {
2670            glEnable(GL_SCISSOR_TEST);
2671        }
2672
2673        // Sets the scissor box as same as viewport
2674        GLint viewport[4], scissor[4];
2675        glGetIntegerv(GL_VIEWPORT, viewport);
2676        glGetIntegerv(GL_SCISSOR_BOX, scissor);
2677        bool scissorBoxDifference =
2678            viewport[0] != scissor[0] || viewport[1] != scissor[1] ||
2679            viewport[2] != scissor[2] || viewport[3] != scissor[3];
2680        if (scissorBoxDifference)
2681        {
2682            glScissor(viewport[0], viewport[1], viewport[2], viewport[3]);
2683        }
2684
2685        // Clear buffers
2686        glClear(flags);
2687
2688        // Restore scissor box
2689        if (scissorBoxDifference)
2690        {
2691            glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
2692        }
2693        // Restore scissor test
2694        if (!scissorTestEnabled)
2695        {
2696            glDisable(GL_SCISSOR_TEST);
2697        }
2698
2699        // Reset buffer write state
2700        if (!mDepthWrite && (buffers & FBT_DEPTH))
2701        {
2702            glDepthMask( GL_FALSE );
2703        }
2704        if (colourMask && (buffers & FBT_COLOUR))
2705        {
2706            glColorMask(mColourWrite[0], mColourWrite[1], mColourWrite[2], mColourWrite[3]);
2707        }
2708                if (buffers & FBT_STENCIL)
2709                {
2710                        glStencilMask(mStencilMask);
2711                }
2712
2713    }
2714    // ------------------------------------------------------------------
2715    void GLRenderSystem::_makeProjectionMatrix(Real left, Real right, 
2716        Real bottom, Real top, Real nearPlane, Real farPlane, Matrix4& dest, 
2717        bool forGpuProgram)
2718    {
2719        Real width = right - left;
2720        Real height = top - bottom;
2721        Real q, qn;
2722        if (farPlane == 0)
2723        {
2724            // Infinite far plane
2725            q = Frustum::INFINITE_FAR_PLANE_ADJUST - 1;
2726            qn = nearPlane * (Frustum::INFINITE_FAR_PLANE_ADJUST - 2);
2727        }
2728        else
2729        {
2730            q = -(farPlane + nearPlane) / (farPlane - nearPlane);
2731            qn = -2 * (farPlane * nearPlane) / (farPlane - nearPlane);
2732        }
2733        dest = Matrix4::ZERO;
2734        dest[0][0] = 2 * nearPlane / width;
2735        dest[0][2] = (right+left) / width;
2736        dest[1][1] = 2 * nearPlane / height;
2737        dest[1][2] = (top+bottom) / height;
2738        dest[2][2] = q;
2739        dest[2][3] = qn;
2740        dest[3][2] = -1;
2741    }
2742
2743    // ------------------------------------------------------------------
2744    void GLRenderSystem::setClipPlane (ushort index, Real A, Real B, Real C, Real D)
2745    {
2746        if (ushort(mClipPlanes.size()) < index+1)
2747            mClipPlanes.resize(index+1);
2748        mClipPlanes[index] = Vector4 (A, B, C, D);
2749        GLdouble plane[4] = { A, B, C, D };
2750        glClipPlane (GL_CLIP_PLANE0 + index, plane);
2751    }
2752
2753    // ------------------------------------------------------------------
2754    void GLRenderSystem::setGLClipPlanes() const
2755    {
2756        size_t size = mClipPlanes.size();
2757        for (size_t i=0; i<size; i++)
2758        {
2759            const Vector4 &p = mClipPlanes[i];
2760            GLdouble plane[4] = { p.x, p.y, p.z, p.w };
2761            glClipPlane (GL_CLIP_PLANE0 + i, plane);
2762        }
2763    }
2764
2765    // ------------------------------------------------------------------
2766    void GLRenderSystem::enableClipPlane (ushort index, bool enable)
2767    {
2768        glEnable (GL_CLIP_PLANE0 + index);
2769    }
2770    //---------------------------------------------------------------------
2771    HardwareOcclusionQuery* GLRenderSystem::createHardwareOcclusionQuery(void)
2772    {
2773        GLHardwareOcclusionQuery* ret = new GLHardwareOcclusionQuery(); 
2774                mHwOcclusionQueries.push_back(ret);
2775                return ret;
2776    }
2777    //---------------------------------------------------------------------
2778    Real GLRenderSystem::getHorizontalTexelOffset(void)
2779    {
2780        // No offset in GL
2781        return 0.0f;
2782    }
2783    //---------------------------------------------------------------------
2784    Real GLRenderSystem::getVerticalTexelOffset(void)
2785    {
2786        // No offset in GL
2787        return 0.0f;
2788    }
2789        //---------------------------------------------------------------------
2790    void GLRenderSystem::_applyObliqueDepthProjection(Matrix4& matrix, const Plane& plane, 
2791        bool forGpuProgram)
2792    {
2793        // Thanks to Eric Lenyel for posting this calculation at www.terathon.com
2794
2795        // Calculate the clip-space corner point opposite the clipping plane
2796        // as (sgn(clipPlane.x), sgn(clipPlane.y), 1, 1) and
2797        // transform it into camera space by multiplying it
2798        // by the inverse of the projection matrix
2799
2800        Vector4 q;
2801        q.x = (Math::Sign(plane.normal.x) + matrix[0][2]) / matrix[0][0];
2802        q.y = (Math::Sign(plane.normal.y) + matrix[1][2]) / matrix[1][1];
2803        q.z = -1.0F;
2804        q.w = (1.0F + matrix[2][2]) / matrix[2][3];
2805
2806        // Calculate the scaled plane vector
2807        Vector4 clipPlane4d(plane.normal.x, plane.normal.y, plane.normal.z, plane.d);
2808        Vector4 c = clipPlane4d * (2.0F / (clipPlane4d.dotProduct(q)));
2809
2810        // Replace the third row of the projection matrix
2811        matrix[2][0] = c.x;
2812        matrix[2][1] = c.y;
2813        matrix[2][2] = c.z + 1.0F;
2814        matrix[2][3] = c.w; 
2815    }
2816    //---------------------------------------------------------------------
2817    void GLRenderSystem::_oneTimeContextInitialization()
2818    {
2819        // Set nicer lighting model -- d3d9 has this by default
2820        glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
2821        glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);       
2822        glEnable(GL_COLOR_SUM);
2823        glDisable(GL_DITHER);
2824
2825        // Check for FSAA
2826        // Enable the extension if it was enabled by the GLSupport
2827        if (mGLSupport->checkExtension("GL_ARB_multisample"))
2828        {
2829            int fsaa_active = false;
2830            glGetIntegerv(GL_SAMPLE_BUFFERS_ARB,(GLint*)&fsaa_active);
2831            if(fsaa_active)
2832            {
2833                glEnable(GL_MULTISAMPLE_ARB);
2834                LogManager::getSingleton().logMessage("Using FSAA from GL_ARB_multisample extension.");
2835            }           
2836        }
2837    }
2838    //---------------------------------------------------------------------
2839    void GLRenderSystem::_switchContext(GLContext *context)
2840    {
2841        // Unbind GPU programs and rebind to new context later, because
2842        // scene manager treat render system as ONE 'context' ONLY, and it
2843        // cached the GPU programs using state.
2844        if (mCurrentVertexProgram)
2845            mCurrentVertexProgram->unbindProgram();
2846        if (mCurrentFragmentProgram)
2847            mCurrentFragmentProgram->unbindProgram();
2848
2849        // It's ready to switching
2850        mCurrentContext->endCurrent();
2851        mCurrentContext = context;
2852        mCurrentContext->setCurrent();
2853       
2854        // Check if the context has already done one-time initialisation
2855        if(!mCurrentContext->getInitialized()) 
2856        {
2857            _oneTimeContextInitialization();
2858            mCurrentContext->setInitialized();
2859        }
2860
2861        // Rebind GPU programs to new context
2862        if (mCurrentVertexProgram)
2863            mCurrentVertexProgram->bindProgram();
2864        if (mCurrentFragmentProgram)
2865            mCurrentFragmentProgram->bindProgram();
2866
2867        // Must reset depth/colour write mask to according with user desired, otherwise,
2868        // clearFrameBuffer would be wrong because the value we are recorded may be
2869        // difference with the really state stored in GL context.
2870        glDepthMask(mDepthWrite);
2871        glColorMask(mColourWrite[0], mColourWrite[1], mColourWrite[2], mColourWrite[3]);
2872                glStencilMask(mStencilMask);
2873
2874    }
2875    //---------------------------------------------------------------------
2876    void GLRenderSystem::_setRenderTarget(RenderTarget *target)
2877    {
2878        // Unbind frame buffer object
2879        if(mActiveRenderTarget)
2880            mRTTManager->unbind(mActiveRenderTarget);
2881       
2882        mActiveRenderTarget = target;
2883       
2884        // Switch context if different from current one
2885        GLContext *newContext = 0;
2886        target->getCustomAttribute("GLCONTEXT", &newContext);
2887        if(newContext && mCurrentContext != newContext) 
2888        {
2889            _switchContext(newContext);
2890        }
2891       
2892        // Bind frame buffer object
2893        mRTTManager->bind(target);
2894    }
2895    //---------------------------------------------------------------------
2896    void GLRenderSystem::_unregisterContext(GLContext *context)
2897    {
2898        if(mCurrentContext == context) {
2899            // Change the context to something else so that a valid context
2900            // remains active. When this is the main context being unregistered,
2901            // we set the main context to 0.
2902            if(mCurrentContext != mMainContext) {
2903                _switchContext(mMainContext);
2904            } else {
2905                /// No contexts remain
2906                mCurrentContext->endCurrent();
2907                mCurrentContext = 0;
2908                mMainContext = 0;
2909            }
2910        }
2911    }
2912    //---------------------------------------------------------------------
2913    Real GLRenderSystem::getMinimumDepthInputValue(void)
2914    {
2915        // Range [-1.0f, 1.0f]
2916        return -1.0f;
2917    }
2918    //---------------------------------------------------------------------
2919    Real GLRenderSystem::getMaximumDepthInputValue(void)
2920    {
2921        // Range [-1.0f, 1.0f]
2922        return 1.0f;
2923    }
2924    //---------------------------------------------------------------------
2925        void GLRenderSystem::registerThread()
2926        {
2927                // This is only valid once we've created the main context
2928                if (!mMainContext)
2929                {
2930                        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, 
2931                                "Cannot register a background thread before the main context "
2932                                "has been created.", 
2933                                "GLRenderSystem::registerThread");
2934                }
2935
2936                // Create a new context for this thread. Cloning from the main context
2937                // will ensure that resources are shared with the main context
2938                // We want a separate context so that we can safely create GL
2939                // objects in parallel with the main thread
2940                GLContext* newContext = mMainContext->clone();
2941                mBackgroundContextList.push_back(newContext);
2942
2943                // Bind this new context to this thread.
2944                newContext->setCurrent();
2945
2946                _oneTimeContextInitialization();
2947                newContext->setInitialized();
2948
2949
2950        }
2951    //---------------------------------------------------------------------
2952        void GLRenderSystem::unregisterThread()
2953        {
2954                // nothing to do here?
2955                // Don't need to worry about active context, just make sure we delete
2956                // on shutdown.
2957
2958        }
2959        //---------------------------------------------------------------------
2960        void GLRenderSystem::preExtraThreadsStarted()
2961        {
2962                // free context, we'll need this to share lists
2963                mCurrentContext->endCurrent();
2964        }
2965        //---------------------------------------------------------------------
2966        void GLRenderSystem::postExtraThreadsStarted()
2967        {
2968                // reacquire context
2969                mCurrentContext->setCurrent();
2970        }
2971
2972
2973}
Note: See TracBrowser for help on using the repository browser.