source: OGRE/trunk/ogre_changes/RenderSystems/GL/src/OgreGLRenderSystem.cpp @ 657

Revision 657, 96.7 KB checked in by mattausch, 18 years ago (diff)

added ogre dependencies and patched ogre sources

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