1 /*
2   -----------------------------------------------------------------------------
3   This source file is part of OGRE
4   (Object-oriented Graphics Rendering Engine)
5   For the latest info, see http://www.ogre3d.org
6 
7 Copyright (c) 2000-2014 Torus Knot Software Ltd
8 
9   Permission is hereby granted, free of charge, to any person obtaining a copy
10   of this software and associated documentation files (the "Software"), to deal
11   in the Software without restriction, including without limitation the rights
12   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13   copies of the Software, and to permit persons to whom the Software is
14   furnished to do so, subject to the following conditions:
15 
16   The above copyright notice and this permission notice shall be included in
17   all copies or substantial portions of the Software.
18 
19   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25   THE SOFTWARE.
26   -----------------------------------------------------------------------------
27 */
28 
29 #include "OgreGL3PlusRenderSystem.h"
30 
31 #include "OgreGLUtil.h"
32 #include "OgreRenderSystem.h"
33 #include "OgreLogManager.h"
34 #include "OgreStringConverter.h"
35 #include "OgreLight.h"
36 #include "OgreCamera.h"
37 #include "OgreGL3PlusTextureManager.h"
38 #include "OgreGL3PlusHardwareCounterBuffer.h"
39 #include "OgreGL3PlusHardwareUniformBuffer.h"
40 #include "OgreGL3PlusHardwareShaderStorageBuffer.h"
41 #include "OgreGL3PlusHardwareVertexBuffer.h"
42 #include "OgreGL3PlusHardwareIndexBuffer.h"
43 #include "OgreGLSLShader.h"
44 #include "OgreGLSLShaderManager.h"
45 #include "OgreException.h"
46 #include "OgreGLSLExtSupport.h"
47 #include "OgreGL3PlusHardwareOcclusionQuery.h"
48 #include "OgreGL3PlusDepthBuffer.h"
49 #include "OgreGL3PlusHardwarePixelBuffer.h"
50 #include "OgreGLContext.h"
51 #include "OgreGLSLShaderFactory.h"
52 #include "OgreGL3PlusFBORenderTexture.h"
53 #include "OgreGL3PlusHardwareBufferManager.h"
54 #include "OgreGLSLProgramManager.h"
55 #include "OgreGLSLSeparableProgram.h"
56 #include "OgreGLVertexArrayObject.h"
57 #include "OgreRoot.h"
58 #include "OgreConfig.h"
59 #include "OgreViewport.h"
60 #include "OgreGL3PlusPixelFormat.h"
61 #include "OgreGL3PlusStateCacheManager.h"
62 #include "OgreGLSLProgramCommon.h"
63 
64 #if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
65 extern "C" void glFlushRenderAPPLE();
66 #endif
67 
68 #ifndef GL_EXT_texture_filter_anisotropic
69 #define GL_TEXTURE_MAX_ANISOTROPY_EXT     0x84FE
70 #define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
71 #endif
72 
73 #if ENABLE_GL_DEBUG_OUTPUT
GLDebugCallback(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar * message,const GLvoid * userParam)74 static void APIENTRY GLDebugCallback(GLenum source,
75                                      GLenum type,
76                                      GLuint id,
77                                      GLenum severity,
78                                      GLsizei length,
79                                      const GLchar* message,
80                                      const GLvoid* userParam)
81 {
82     char debSource[32] = {0}, debType[32] = {0}, debSev[32] = {0};
83 
84     if (source == GL_DEBUG_SOURCE_API)
85         strcpy(debSource, "OpenGL");
86     else if (source == GL_DEBUG_SOURCE_WINDOW_SYSTEM)
87         strcpy(debSource, "Windows");
88     else if (source == GL_DEBUG_SOURCE_SHADER_COMPILER)
89         strcpy(debSource, "Shader Compiler");
90     else if (source == GL_DEBUG_SOURCE_THIRD_PARTY)
91         strcpy(debSource, "Third Party");
92     else if (source == GL_DEBUG_SOURCE_APPLICATION)
93         strcpy(debSource, "Application");
94     else if (source == GL_DEBUG_SOURCE_OTHER)
95         strcpy(debSource, "Other");
96 
97     if (type == GL_DEBUG_TYPE_ERROR)
98         strcpy(debType, "error");
99     else if (type == GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR)
100         strcpy(debType, "deprecated behavior");
101     else if (type == GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR)
102         strcpy(debType, "undefined behavior");
103     else if (type == GL_DEBUG_TYPE_PORTABILITY)
104         strcpy(debType, "portability");
105     else if (type == GL_DEBUG_TYPE_PERFORMANCE)
106         strcpy(debType, "performance");
107     else if (type == GL_DEBUG_TYPE_OTHER)
108         strcpy(debType, "message");
109 
110     if (severity == GL_DEBUG_SEVERITY_HIGH)
111     {
112         strcpy(debSev, "high");
113     }
114     else if (severity == GL_DEBUG_SEVERITY_MEDIUM)
115         strcpy(debSev, "medium");
116     else if (severity == GL_DEBUG_SEVERITY_LOW)
117         strcpy(debSev, "low");
118 
119     Ogre::LogManager::getSingleton().stream() << debSource << ":" << debType << "(" << debSev << ") " << id << ": " << message;
120 }
121 #endif
122 
123 namespace Ogre {
124 
125     static GLNativeSupport* glsupport;
get_proc(const char * proc)126     static GL3WglProc get_proc(const char* proc) {
127         return (GL3WglProc)glsupport->getProcAddress(proc);
128     }
129 
GL3PlusRenderSystem()130     GL3PlusRenderSystem::GL3PlusRenderSystem()
131         : mDepthWrite(true),
132           mScissorsEnabled(false),
133           mStencilWriteMask(0xFFFFFFFF),
134           mStateCacheManager(0),
135           mShaderManager(0),
136           mGLSLShaderFactory(0),
137           mHardwareBufferManager(0),
138           mRTTManager(0),
139           mActiveTextureUnit(0)
140     {
141         size_t i;
142 
143         LogManager::getSingleton().logMessage(getName() + " created.");
144 
145         // Get our GLSupport
146         mGLSupport = getGLSupport();
147         glsupport = mGLSupport;
148 
149         initConfigOptions();
150 
151         mColourWrite[0] = mColourWrite[1] = mColourWrite[2] = mColourWrite[3] = true;
152 
153         for (i = 0; i < OGRE_MAX_TEXTURE_LAYERS; i++)
154         {
155             // Dummy value
156             mTextureTypes[i] = 0;
157         }
158 
159         mActiveRenderTarget = 0;
160         mCurrentContext = 0;
161         mMainContext = 0;
162         mGLInitialised = false;
163         mMinFilter = FO_LINEAR;
164         mMipFilter = FO_POINT;
165         mCurrentVertexShader = 0;
166         mCurrentGeometryShader = 0;
167         mCurrentFragmentShader = 0;
168         mCurrentHullShader = 0;
169         mCurrentDomainShader = 0;
170         mCurrentComputeShader = 0;
171         mLargestSupportedAnisotropy = 1;
172     }
173 
~GL3PlusRenderSystem()174     GL3PlusRenderSystem::~GL3PlusRenderSystem()
175     {
176         shutdown();
177 
178         if (mGLSupport)
179             OGRE_DELETE mGLSupport;
180     }
181 
getName(void) const182     const String& GL3PlusRenderSystem::getName(void) const
183     {
184         static String strName("OpenGL 3+ Rendering Subsystem");
185         return strName;
186     }
187 
_initialise(bool autoCreateWindow,const String & windowTitle)188     RenderWindow* GL3PlusRenderSystem::_initialise(bool autoCreateWindow,
189                                                    const String& windowTitle)
190     {
191         mGLSupport->start();
192 
193         RenderWindow* autoWindow = NULL;
194         if(autoCreateWindow) {
195             uint w, h;
196             bool fullscreen;
197             NameValuePairList misc = parseOptions(w, h, fullscreen);
198             autoWindow = _createRenderWindow(windowTitle, w, h, fullscreen, &misc);
199         }
200         RenderSystem::_initialise(autoCreateWindow, windowTitle);
201         return autoWindow;
202     }
203 
createRenderSystemCapabilities() const204     RenderSystemCapabilities* GL3PlusRenderSystem::createRenderSystemCapabilities() const
205     {
206         RenderSystemCapabilities* rsc = OGRE_NEW RenderSystemCapabilities();
207 
208         rsc->setCategoryRelevant(CAPS_CATEGORY_GL, true);
209         rsc->setDriverVersion(mDriverVersion);
210 
211         const char* deviceName = (const char*)glGetString(GL_RENDERER);
212         if (deviceName)
213         {
214             rsc->setDeviceName(deviceName);
215         }
216 
217         rsc->setRenderSystemName(getName());
218         rsc->parseVendorFromString(mVendor);
219 
220         // Check for hardware mipmapping support.
221         rsc->setCapability(RSC_AUTOMIPMAP_COMPRESSED);
222 
223         // Multitexturing support and set number of texture units
224         GLint units;
225         OGRE_CHECK_GL_ERROR(glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &units));
226         rsc->setNumTextureUnits(std::min(OGRE_MAX_TEXTURE_LAYERS, units));
227 
228         glGetIntegerv( GL_MAX_VERTEX_ATTRIBS , &units);
229         rsc->setNumVertexAttributes(units);
230 
231         // Check for Anisotropy support
232         if (checkExtension("GL_EXT_texture_filter_anisotropic"))
233         {
234             GLfloat maxAnisotropy = 0;
235             OGRE_CHECK_GL_ERROR(glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropy));
236             rsc->setMaxSupportedAnisotropy(maxAnisotropy);
237             rsc->setCapability(RSC_ANISOTROPY);
238         }
239 
240         // DOT3 support is standard
241         rsc->setCapability(RSC_DOT3);
242 
243         // Cube map
244         rsc->setCapability(RSC_CUBEMAPPING);
245 
246         // Point sprites
247         rsc->setCapability(RSC_POINT_SPRITES);
248         rsc->setCapability(RSC_POINT_EXTENDED_PARAMETERS);
249 
250         // Check for hardware stencil support and set bit depth
251         rsc->setCapability(RSC_HWSTENCIL);
252         rsc->setCapability(RSC_TWO_SIDED_STENCIL);
253         rsc->setStencilBufferBitDepth(8);
254 
255         rsc->setCapability(RSC_HW_GAMMA);
256 
257         // Vertex Buffer Objects are always supported
258         rsc->setCapability(RSC_MAPBUFFER);
259         rsc->setCapability(RSC_32BIT_INDEX);
260 
261         // Vertex Array Objects are supported in 3.0
262         rsc->setCapability(RSC_VAO);
263 
264         // Check for texture compression
265         rsc->setCapability(RSC_TEXTURE_COMPRESSION);
266 
267         // Check for dxt compression
268         if (checkExtension("GL_EXT_texture_compression_s3tc"))
269         {
270             rsc->setCapability(RSC_TEXTURE_COMPRESSION_DXT);
271         }
272 
273         // Check for etc compression
274         if (hasMinGLVersion(4, 3) || checkExtension("GL_ARB_ES3_compatibility"))
275         {
276             rsc->setCapability(RSC_TEXTURE_COMPRESSION_ETC2);
277         }
278 
279         // Check for vtc compression
280         if (checkExtension("GL_NV_texture_compression_vtc"))
281         {
282             rsc->setCapability(RSC_TEXTURE_COMPRESSION_VTC);
283         }
284 
285         // RGTC(BC4/BC5) is supported by the 3.0 spec
286         rsc->setCapability(RSC_TEXTURE_COMPRESSION_BC4_BC5);
287 
288         // BPTC(BC6H/BC7) is supported by the extension or OpenGL 4.2 or higher
289         if (hasMinGLVersion(4, 2) || checkExtension("GL_ARB_texture_compression_bptc"))
290         {
291             rsc->setCapability(RSC_TEXTURE_COMPRESSION_BC6H_BC7);
292         }
293 
294         if (checkExtension("WEBGL_compressed_texture_astc") ||
295             checkExtension("GL_KHR_texture_compression_astc_ldr"))
296             rsc->setCapability(RSC_TEXTURE_COMPRESSION_ASTC);
297 
298         rsc->setCapability(RSC_HWRENDER_TO_TEXTURE);
299         // Probe number of draw buffers
300         // Only makes sense with FBO support, so probe here
301         GLint buffers;
302         OGRE_CHECK_GL_ERROR(glGetIntegerv(GL_MAX_DRAW_BUFFERS, &buffers));
303         rsc->setNumMultiRenderTargets(std::min<int>(buffers, (GLint)OGRE_MAX_MULTIPLE_RENDER_TARGETS));
304         rsc->setCapability(RSC_MRT_DIFFERENT_BIT_DEPTHS);
305 
306         // Stencil wrapping
307         rsc->setCapability(RSC_STENCIL_WRAP);
308 
309         // GL always shares vertex and fragment texture units (for now?)
310         rsc->setVertexTextureUnitsShared(true);
311 
312         // Blending support
313         rsc->setCapability(RSC_ADVANCED_BLEND_OPERATIONS);
314 
315         // Check for non-power-of-2 texture support
316         if (hasMinGLVersion(3, 1) || checkExtension("GL_ARB_texture_rectangle") || checkExtension("GL_ARB_texture_non_power_of_two"))
317             rsc->setCapability(RSC_NON_POWER_OF_2_TEXTURES);
318 
319         // Check for atomic counter support
320         if (hasMinGLVersion(4, 2) || checkExtension("GL_ARB_shader_atomic_counters"))
321             rsc->setCapability(RSC_ATOMIC_COUNTERS);
322 
323         // Scissor test is standard
324         rsc->setCapability(RSC_SCISSOR_TEST);
325 
326         // As are user clipping planes
327         rsc->setCapability(RSC_USER_CLIP_PLANES);
328 
329         // So are 1D & 3D textures
330         rsc->setCapability(RSC_TEXTURE_1D);
331         rsc->setCapability(RSC_TEXTURE_3D);
332 
333         // UBYTE4 always supported
334         rsc->setCapability(RSC_VERTEX_FORMAT_UBYTE4);
335 
336         // Infinite far plane always supported
337         rsc->setCapability(RSC_INFINITE_FAR_PLANE);
338 
339         // Check for hardware occlusion support
340         rsc->setCapability(RSC_HWOCCLUSION);
341 
342         // Point size
343         GLfloat psRange[2] = {0.0, 0.0};
344         OGRE_CHECK_GL_ERROR(glGetFloatv(GL_POINT_SIZE_RANGE, psRange));
345         rsc->setMaxPointSize(psRange[1]);
346 
347         // GLSL is always supported in GL
348         // TODO: Deprecate this profile name in favor of versioned names
349         rsc->addShaderProfile("glsl");
350 
351         // Support for specific shader profiles
352         bool limitedOSXCoreProfile = OGRE_PLATFORM == OGRE_PLATFORM_APPLE && hasMinGLVersion(3, 2);
353 
354         for (uint16 ver = getNativeShadingLanguageVersion(); ver >= 400; ver -= 10)
355             rsc->addShaderProfile("glsl" + StringConverter::toString(ver));
356 
357         if (getNativeShadingLanguageVersion() >= 330)
358             rsc->addShaderProfile("glsl330");
359         if (getNativeShadingLanguageVersion() >= 150)
360             rsc->addShaderProfile("glsl150");
361         if (getNativeShadingLanguageVersion() >= 140 && !limitedOSXCoreProfile)
362             rsc->addShaderProfile("glsl140");
363         if (getNativeShadingLanguageVersion() >= 130 && !limitedOSXCoreProfile)
364             rsc->addShaderProfile("glsl130");
365 
366         // FIXME: This isn't working right yet in some rarer cases
367         if (hasMinGLVersion(4, 1) || checkExtension("GL_ARB_separate_shader_objects")) {
368             rsc->setCapability(RSC_SEPARATE_SHADER_OBJECTS);
369             rsc->setCapability(RSC_GLSL_SSO_REDECLARE);
370         }
371 
372         // Mesa 11.2 does not behave according to spec and throws a "gl_Position redefined"
373         if(rsc->getDeviceName().find("Mesa") != String::npos) {
374             rsc->unsetCapability(RSC_GLSL_SSO_REDECLARE);
375         }
376 
377         // Vertex/Fragment Programs
378         rsc->setCapability(RSC_VERTEX_PROGRAM);
379         rsc->setCapability(RSC_FRAGMENT_PROGRAM);
380 
381         GLint constantCount = 0;
382         OGRE_CHECK_GL_ERROR(glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, &constantCount));
383         rsc->setVertexProgramConstantFloatCount((Ogre::ushort)constantCount);
384         rsc->setVertexProgramConstantBoolCount((Ogre::ushort)constantCount);
385         rsc->setVertexProgramConstantIntCount((Ogre::ushort)constantCount);
386 
387         // Fragment Program Properties
388         constantCount = 0;
389         OGRE_CHECK_GL_ERROR(glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &constantCount));
390         rsc->setFragmentProgramConstantFloatCount((Ogre::ushort)constantCount);
391         rsc->setFragmentProgramConstantBoolCount((Ogre::ushort)constantCount);
392         rsc->setFragmentProgramConstantIntCount((Ogre::ushort)constantCount);
393 
394         // Geometry Program Properties
395         if (hasMinGLVersion(3, 2) || checkExtension("ARB_geometry_shader4")) {
396             rsc->setCapability(RSC_GEOMETRY_PROGRAM);
397 
398             OGRE_CHECK_GL_ERROR(glGetIntegerv(GL_MAX_GEOMETRY_UNIFORM_COMPONENTS, &constantCount));
399             rsc->setGeometryProgramConstantFloatCount(constantCount);
400 
401             OGRE_CHECK_GL_ERROR(glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES, &constantCount));
402             rsc->setGeometryProgramNumOutputVertices(constantCount);
403 
404             //FIXME Is this correct?
405             OGRE_CHECK_GL_ERROR(glGetIntegerv(GL_MAX_GEOMETRY_UNIFORM_COMPONENTS, &constantCount));
406             rsc->setGeometryProgramConstantFloatCount(constantCount);
407             rsc->setGeometryProgramConstantBoolCount(constantCount);
408             rsc->setGeometryProgramConstantIntCount(constantCount);
409         }
410 
411         // Tessellation Program Properties
412         if (hasMinGLVersion(4, 0) || checkExtension("GL_ARB_tessellation_shader"))
413         {
414             rsc->setCapability(RSC_TESSELLATION_HULL_PROGRAM);
415             rsc->setCapability(RSC_TESSELLATION_DOMAIN_PROGRAM);
416 
417             OGRE_CHECK_GL_ERROR(glGetIntegerv(GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS, &constantCount));
418             // 16 boolean params allowed
419             rsc->setTessellationHullProgramConstantBoolCount(constantCount);
420             // 16 integer params allowed, 4D
421             rsc->setTessellationHullProgramConstantIntCount(constantCount);
422             // float params, always 4D
423             rsc->setTessellationHullProgramConstantFloatCount(constantCount);
424 
425             OGRE_CHECK_GL_ERROR(glGetIntegerv(GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS, &constantCount));
426             // 16 boolean params allowed
427             rsc->setTessellationDomainProgramConstantBoolCount(constantCount);
428             // 16 integer params allowed, 4D
429             rsc->setTessellationDomainProgramConstantIntCount(constantCount);
430             // float params, always 4D
431             rsc->setTessellationDomainProgramConstantFloatCount(constantCount);
432         }
433 
434         // Compute Program Properties
435         if (hasMinGLVersion(4, 3) || checkExtension("GL_ARB_compute_shader"))
436         {
437             rsc->setCapability(RSC_COMPUTE_PROGRAM);
438 
439             //FIXME Is this correct?
440             OGRE_CHECK_GL_ERROR(glGetIntegerv(GL_MAX_COMPUTE_UNIFORM_COMPONENTS, &constantCount));
441             rsc->setComputeProgramConstantFloatCount(constantCount);
442             rsc->setComputeProgramConstantBoolCount(constantCount);
443             rsc->setComputeProgramConstantIntCount(constantCount);
444 
445             //TODO we should also check max workgroup count & size
446             // OGRE_CHECK_GL_ERROR(glGetIntegerv(GL_MAX_COMPUTE_WORK_GROUP_SIZE, &workgroupCount));
447             // OGRE_CHECK_GL_ERROR(glGetIntegerv(GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS, &workgroupInvocations));
448         }
449 
450         if (hasMinGLVersion(4, 1) || checkExtension("GL_ARB_get_program_binary"))
451         {
452             GLint formats = 0;
453             OGRE_CHECK_GL_ERROR(glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &formats));
454 
455             if (formats > 0)
456                 rsc->setCapability(RSC_CAN_GET_COMPILED_SHADER_BUFFER);
457         }
458 
459         if (hasMinGLVersion(3, 3) || checkExtension("GL_ARB_instanced_arrays"))
460         {
461             rsc->setCapability(RSC_VERTEX_BUFFER_INSTANCE_DATA);
462         }
463 
464         // Check for Float textures
465         rsc->setCapability(RSC_TEXTURE_FLOAT);
466 
467         // OpenGL 3.0 requires a minimum of 16 texture image units
468         units = std::max<GLint>(16, units);
469 
470         rsc->setNumVertexTextureUnits(static_cast<ushort>(units));
471         rsc->setCapability(RSC_VERTEX_TEXTURE_FETCH);
472 
473         // Mipmap LOD biasing?
474         rsc->setCapability(RSC_MIPMAP_LOD_BIAS);
475 
476         // Alpha to coverage always 'supported' when MSAA is available
477         // although card may ignore it if it doesn't specifically support A2C
478         rsc->setCapability(RSC_ALPHA_TO_COVERAGE);
479 
480         // Check if render to vertex buffer (transform feedback in OpenGL)
481         rsc->setCapability(RSC_HWRENDER_TO_VERTEX_BUFFER);
482 
483         if (hasMinGLVersion(4, 3) || checkExtension("GL_KHR_debug"))
484             rsc->setCapability(RSC_DEBUG);
485 
486         if( hasMinGLVersion(4, 3) || checkExtension("GL_ARB_ES3_compatibility"))
487             rsc->setCapability(RSC_PRIMITIVE_RESTART);
488 
489         GLfloat lineWidth[2] = {1, 1};
490         glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, lineWidth);
491         if(lineWidth[1] != 1 && lineWidth[1] != lineWidth[0])
492             rsc->setCapability(RSC_WIDE_LINES);
493 
494         return rsc;
495     }
496 
initialiseFromRenderSystemCapabilities(RenderSystemCapabilities * caps,RenderTarget * primary)497     void GL3PlusRenderSystem::initialiseFromRenderSystemCapabilities(RenderSystemCapabilities* caps, RenderTarget* primary)
498     {
499         if (caps->getRenderSystemName() != getName())
500         {
501             OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
502                         "Trying to initialize GL3PlusRenderSystem from RenderSystemCapabilities that do not support OpenGL 3+",
503                         "GL3PlusRenderSystem::initialiseFromRenderSystemCapabilities");
504         }
505 
506         mShaderManager = OGRE_NEW GLSLShaderManager();
507 
508         // Create GLSL shader factory
509         mGLSLShaderFactory = new GLSLShaderFactory(this);
510         HighLevelGpuProgramManager::getSingleton().addFactory(mGLSLShaderFactory);
511 
512         // Use VBO's by default
513         mHardwareBufferManager = new GL3PlusHardwareBufferManager();
514 
515         // Use FBO's for RTT, PBuffers and Copy are no longer supported
516         // Create FBO manager
517         LogManager::getSingleton().logMessage("GL3+: Using FBOs for rendering to textures");
518         mRTTManager = new GL3PlusFBOManager(this);
519         caps->setCapability(RSC_RTT_DEPTHBUFFER_RESOLUTION_LESSEQUAL);
520 
521         Log* defaultLog = LogManager::getSingleton().getDefaultLog();
522         if (defaultLog)
523         {
524             caps->log(defaultLog);
525         }
526 
527         // Create the texture manager
528         mTextureManager = new GL3PlusTextureManager(this);
529 
530         mGLInitialised = true;
531     }
532 
shutdown(void)533     void GL3PlusRenderSystem::shutdown(void)
534     {
535         RenderSystem::shutdown();
536 
537         // Deleting the GLSL program factory
538         if (mGLSLShaderFactory)
539         {
540             // Remove from manager safely
541             if (HighLevelGpuProgramManager::getSingletonPtr())
542                 HighLevelGpuProgramManager::getSingleton().removeFactory(mGLSLShaderFactory);
543             OGRE_DELETE mGLSLShaderFactory;
544             mGLSLShaderFactory = 0;
545         }
546 
547         // Deleting the GPU program manager and hardware buffer manager.  Has to be done before the mGLSupport->stop().
548         OGRE_DELETE mShaderManager;
549         mShaderManager = 0;
550 
551         OGRE_DELETE mHardwareBufferManager;
552         mHardwareBufferManager = 0;
553 
554         OGRE_DELETE mRTTManager;
555         mRTTManager = 0;
556 
557         OGRE_DELETE mTextureManager;
558         mTextureManager = 0;
559 
560         // Delete extra threads contexts
561         for (GL3PlusContextList::iterator i = mBackgroundContextList.begin();
562              i != mBackgroundContextList.end(); ++i)
563         {
564             GL3PlusContext* pCurContext = *i;
565 
566             pCurContext->releaseContext();
567 
568             OGRE_DELETE pCurContext;
569         }
570         mBackgroundContextList.clear();
571 
572         mGLSupport->stop();
573         mStopRendering = true;
574 
575         // delete mTextureManager;
576         // mTextureManager = 0;
577 
578         mGLInitialised = 0;
579 
580         // RenderSystem::shutdown();
581     }
582 
_createRenderWindows(const RenderWindowDescriptionList & renderWindowDescriptions,RenderWindowList & createdWindows)583     bool GL3PlusRenderSystem::_createRenderWindows(const RenderWindowDescriptionList& renderWindowDescriptions,
584                                                    RenderWindowList& createdWindows)
585     {
586         // Call base render system method.
587         if (false == RenderSystem::_createRenderWindows(renderWindowDescriptions, createdWindows))
588             return false;
589 
590         // Simply call _createRenderWindow in a loop.
591         for (size_t i = 0; i < renderWindowDescriptions.size(); ++i)
592         {
593             const RenderWindowDescription& curRenderWindowDescription = renderWindowDescriptions[i];
594             RenderWindow* curWindow = NULL;
595 
596             curWindow = _createRenderWindow(curRenderWindowDescription.name,
597                                             curRenderWindowDescription.width,
598                                             curRenderWindowDescription.height,
599                                             curRenderWindowDescription.useFullScreen,
600                                             &curRenderWindowDescription.miscParams);
601 
602             createdWindows.push_back(curWindow);
603         }
604 
605         return true;
606     }
607 
_createRenderWindow(const String & name,unsigned int width,unsigned int height,bool fullScreen,const NameValuePairList * miscParams)608     RenderWindow* GL3PlusRenderSystem::_createRenderWindow(const String &name, unsigned int width, unsigned int height,
609                                                            bool fullScreen, const NameValuePairList *miscParams)
610     {
611         if (mRenderTargets.find(name) != mRenderTargets.end())
612         {
613             OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
614                         "Window with name '" + name + "' already exists",
615                         "GL3PlusRenderSystem::_createRenderWindow");
616         }
617 
618         // Log a message
619         StringStream ss;
620         ss << "GL3PlusRenderSystem::_createRenderWindow \"" << name << "\", " <<
621             width << "x" << height << " ";
622         if (fullScreen)
623             ss << "fullscreen ";
624         else
625             ss << "windowed ";
626 
627         if (miscParams)
628         {
629             ss << " miscParams: ";
630             NameValuePairList::const_iterator it;
631             for (it = miscParams->begin(); it != miscParams->end(); ++it)
632             {
633                 ss << it->first << "=" << it->second << " ";
634             }
635 
636             LogManager::getSingleton().logMessage(ss.str());
637         }
638 
639         // Create the window
640         RenderWindow* win = mGLSupport->newWindow(name, width, height, fullScreen, miscParams);
641         attachRenderTarget((Ogre::RenderTarget&) *win);
642 
643         if (!mGLInitialised)
644         {
645             initialiseContext(win);
646 
647             if (mDriverVersion.major < 3)
648                 OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
649                             "Driver does not support at least OpenGL 3.0.",
650                             "GL3PlusRenderSystem::_createRenderWindow");
651 
652             const char* shadingLangVersion = (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION);
653             StringVector tokens = StringUtil::split(shadingLangVersion, ". ");
654             mNativeShadingLanguageVersion = (StringConverter::parseUnsignedInt(tokens[0]) * 100) + StringConverter::parseUnsignedInt(tokens[1]);
655 
656             // Initialise GL after the first window has been created
657             // TODO: fire this from emulation options, and don't duplicate Real and Current capabilities
658             mRealCapabilities = createRenderSystemCapabilities();
659 
660             // use real capabilities if custom capabilities are not available
661             if (!mUseCustomCapabilities)
662                 mCurrentCapabilities = mRealCapabilities;
663 
664             fireEvent("RenderSystemCapabilitiesCreated");
665 
666             initialiseFromRenderSystemCapabilities(mCurrentCapabilities, (RenderTarget *) win);
667 
668             // Initialise the main context
669             _oneTimeContextInitialization();
670             if (mCurrentContext)
671                 mCurrentContext->setInitialized();
672         }
673 
674         if ( win->getDepthBufferPool() != DepthBuffer::POOL_NO_DEPTH )
675         {
676             // Unlike D3D9, OGL doesn't allow sharing the main depth buffer, so keep them separate.
677             // Only Copy does, but Copy means only one depth buffer...
678             GL3PlusContext *windowContext = dynamic_cast<GLRenderTarget*>(win)->getContext();
679             GL3PlusDepthBuffer *depthBuffer = new GL3PlusDepthBuffer( DepthBuffer::POOL_DEFAULT, this,
680                                                                       windowContext, 0, 0,
681                                                                       win->getWidth(), win->getHeight(),
682                                                                       win->getFSAA(), 0, true );
683 
684             mDepthBufferPool[depthBuffer->getPoolId()].push_back( depthBuffer );
685 
686             win->attachDepthBuffer( depthBuffer );
687         }
688 
689         return win;
690     }
691 
692 
_createDepthBufferFor(RenderTarget * renderTarget)693     DepthBuffer* GL3PlusRenderSystem::_createDepthBufferFor( RenderTarget *renderTarget )
694     {
695         GL3PlusDepthBuffer *retVal = 0;
696 
697         // Only FBOs support different depth buffers, so everything
698         // else creates dummy (empty) containers
699         // retVal = mRTTManager->_createDepthBufferFor( renderTarget );
700 
701         if ( auto fbo = dynamic_cast<GLRenderTarget*>(renderTarget)->getFBO() )
702         {
703             // Presence of an FBO means the manager is an FBO Manager, that's why it's safe to downcast.
704             // Find best depth & stencil format suited for the RT's format.
705             GLuint depthFormat, stencilFormat;
706             static_cast<GL3PlusFBOManager*>(mRTTManager)->getBestDepthStencil( fbo->getFormat(),
707                                                                                &depthFormat, &stencilFormat );
708 
709             GL3PlusRenderBuffer *depthBuffer = new GL3PlusRenderBuffer( depthFormat, fbo->getWidth(),
710                                                                         fbo->getHeight(), fbo->getFSAA() );
711 
712             GL3PlusRenderBuffer *stencilBuffer = NULL;
713             if ( depthFormat == GL_DEPTH24_STENCIL8 || depthFormat == GL_DEPTH32F_STENCIL8)
714             {
715                 // If we have a packed format, the stencilBuffer is the same as the depthBuffer
716                 stencilBuffer = depthBuffer;
717             }
718             else if(stencilFormat)
719             {
720                 stencilBuffer = new GL3PlusRenderBuffer( stencilFormat, fbo->getWidth(),
721                                                          fbo->getHeight(), fbo->getFSAA() );
722             }
723 
724             // No "custom-quality" multisample for now in GL
725             retVal = new GL3PlusDepthBuffer( 0, this, mCurrentContext, depthBuffer, stencilBuffer,
726                                              fbo->getWidth(), fbo->getHeight(), fbo->getFSAA(), 0, false );
727         }
728 
729         return retVal;
730     }
731 
_getDepthStencilFormatFor(PixelFormat internalColourFormat,GLenum * depthFormat,GLenum * stencilFormat)732     void GL3PlusRenderSystem::_getDepthStencilFormatFor( PixelFormat internalColourFormat, GLenum *depthFormat,
733                                                          GLenum *stencilFormat )
734     {
735         mRTTManager->getBestDepthStencil( internalColourFormat, depthFormat, stencilFormat );
736     }
737 
createMultiRenderTarget(const String & name)738     MultiRenderTarget* GL3PlusRenderSystem::createMultiRenderTarget(const String & name)
739     {
740         MultiRenderTarget *retval = mRTTManager->createMultiRenderTarget(name);
741         attachRenderTarget(*retval);
742         return retval;
743     }
744 
destroyRenderWindow(const String & name)745     void GL3PlusRenderSystem::destroyRenderWindow(const String& name)
746     {
747         // Find it to remove from list.
748         RenderTarget* pWin = detachRenderTarget(name);
749         OgreAssert(pWin, "unknown RenderWindow name");
750 
751         GL3PlusContext *windowContext = dynamic_cast<GLRenderTarget*>(pWin)->getContext();
752 
753         // 1 Window <-> 1 Context, should be always true.
754         assert( windowContext );
755 
756         bool bFound = false;
757         // Find the depth buffer from this window and remove it.
758         DepthBufferMap::iterator itMap = mDepthBufferPool.begin();
759         DepthBufferMap::iterator enMap = mDepthBufferPool.end();
760 
761         while( itMap != enMap && !bFound )
762         {
763             DepthBufferVec::iterator itor = itMap->second.begin();
764             DepthBufferVec::iterator end  = itMap->second.end();
765 
766             while( itor != end )
767             {
768                 // A DepthBuffer with no depth & stencil pointers is a dummy one,
769                 // look for the one that matches the same GL context.
770                 GL3PlusDepthBuffer *depthBuffer = static_cast<GL3PlusDepthBuffer*>(*itor);
771                 GL3PlusContext *glContext = depthBuffer->getGLContext();
772 
773                 if ( glContext == windowContext &&
774                      (depthBuffer->getDepthBuffer() || depthBuffer->getStencilBuffer()) )
775                 {
776                     bFound = true;
777 
778                     delete *itor;
779                     itMap->second.erase( itor );
780                     break;
781                 }
782                 ++itor;
783             }
784 
785             ++itMap;
786         }
787 
788         delete pWin;
789     }
790 
_setTexture(size_t stage,bool enabled,const TexturePtr & texPtr)791     void GL3PlusRenderSystem::_setTexture(size_t stage, bool enabled, const TexturePtr &texPtr)
792     {
793         if (!mStateCacheManager->activateGLTextureUnit(stage))
794             return;
795 
796         if (enabled)
797         {
798             GL3PlusTexturePtr tex = static_pointer_cast<GL3PlusTexture>(texPtr);
799 
800             // Note used
801             tex->touch();
802             mTextureTypes[stage] = tex->getGL3PlusTextureTarget();
803 
804             mStateCacheManager->bindGLTexture( mTextureTypes[stage], tex->getGLID() );
805         }
806         else
807         {
808             // Bind zero texture.
809             mStateCacheManager->bindGLTexture(GL_TEXTURE_2D, 0);
810         }
811     }
812 
_setSampler(size_t unit,Sampler & sampler)813     void GL3PlusRenderSystem::_setSampler(size_t unit, Sampler& sampler)
814     {
815         if(hasMinGLVersion(3, 3))
816         {
817             static_cast<GL3PlusSampler&>(sampler).bind(unit);
818             return;
819         }
820 
821         if (!mStateCacheManager->activateGLTextureUnit(unit))
822             return;
823 
824         GLenum target = mTextureTypes[unit];
825 
826         const Sampler::UVWAddressingMode& uvw = sampler.getAddressingMode();
827         mStateCacheManager->setTexParameteri(target, GL_TEXTURE_WRAP_S,
828                                              GL3PlusSampler::getTextureAddressingMode(uvw.u));
829         mStateCacheManager->setTexParameteri(target, GL_TEXTURE_WRAP_T,
830                                              GL3PlusSampler::getTextureAddressingMode(uvw.v));
831         mStateCacheManager->setTexParameteri(target, GL_TEXTURE_WRAP_R,
832                                              GL3PlusSampler::getTextureAddressingMode(uvw.w));
833 
834         if (uvw.u == TAM_BORDER || uvw.v == TAM_BORDER || uvw.w == TAM_BORDER)
835             OGRE_CHECK_GL_ERROR(glTexParameterfv( target, GL_TEXTURE_BORDER_COLOR, sampler.getBorderColour().ptr()));
836         OGRE_CHECK_GL_ERROR(glTexParameterf(target, GL_TEXTURE_LOD_BIAS, sampler.getMipmapBias()));
837 
838         if (mCurrentCapabilities->hasCapability(RSC_ANISOTROPY))
839             mStateCacheManager->setTexParameteri(
840                 target, GL_TEXTURE_MAX_ANISOTROPY_EXT,
841                 std::min<uint>(mLargestSupportedAnisotropy, sampler.getAnisotropy()));
842 
843         mStateCacheManager->setTexParameteri(target, GL_TEXTURE_COMPARE_MODE,
844                                              sampler.getCompareEnabled() ? GL_COMPARE_REF_TO_TEXTURE
845                                                                          : GL_NONE);
846         if (sampler.getCompareEnabled())
847             mStateCacheManager->setTexParameteri(target, GL_TEXTURE_COMPARE_FUNC,
848                                                  convertCompareFunction(sampler.getCompareFunction()));
849 
850         // Combine with existing mip filter
851         mStateCacheManager->setTexParameteri(
852             target, GL_TEXTURE_MIN_FILTER,
853             GL3PlusSampler::getCombinedMinMipFilter(sampler.getFiltering(FT_MIN),
854                                                     sampler.getFiltering(FT_MIP)));
855 
856         switch (sampler.getFiltering(FT_MAG))
857         {
858         case FO_ANISOTROPIC: // GL treats linear and aniso the same
859         case FO_LINEAR:
860             mStateCacheManager->setTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
861             break;
862         case FO_POINT:
863         case FO_NONE:
864             mStateCacheManager->setTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
865             break;
866         }
867     }
868 
_setTextureAddressingMode(size_t stage,const Sampler::UVWAddressingMode & uvw)869     void GL3PlusRenderSystem::_setTextureAddressingMode(size_t stage, const Sampler::UVWAddressingMode& uvw)
870     {
871         if (!mStateCacheManager->activateGLTextureUnit(stage))
872             return;
873         mStateCacheManager->setTexParameteri(mTextureTypes[stage], GL_TEXTURE_WRAP_S,
874                                              GL3PlusSampler::getTextureAddressingMode(uvw.u));
875         mStateCacheManager->setTexParameteri(mTextureTypes[stage], GL_TEXTURE_WRAP_T,
876                                              GL3PlusSampler::getTextureAddressingMode(uvw.v));
877         mStateCacheManager->setTexParameteri(mTextureTypes[stage], GL_TEXTURE_WRAP_R,
878                                              GL3PlusSampler::getTextureAddressingMode(uvw.w));
879     }
880 
_setTextureBorderColour(size_t stage,const ColourValue & colour)881     void GL3PlusRenderSystem::_setTextureBorderColour(size_t stage, const ColourValue& colour)
882     {
883         if (mStateCacheManager->activateGLTextureUnit(stage))
884         {
885             OGRE_CHECK_GL_ERROR(glTexParameterfv( mTextureTypes[stage], GL_TEXTURE_BORDER_COLOR, colour.ptr()));
886         }
887     }
888 
_setTextureMipmapBias(size_t stage,float bias)889     void GL3PlusRenderSystem::_setTextureMipmapBias(size_t stage, float bias)
890     {
891         if (mStateCacheManager->activateGLTextureUnit(stage))
892         {
893             OGRE_CHECK_GL_ERROR(glTexParameterf(mTextureTypes[stage], GL_TEXTURE_LOD_BIAS, bias));
894         }
895     }
896 
_setLineWidth(float width)897     void GL3PlusRenderSystem::_setLineWidth(float width)
898     {
899         OGRE_CHECK_GL_ERROR(glLineWidth(width));
900     }
901 
getBlendMode(SceneBlendFactor ogreBlend) const902     GLenum GL3PlusRenderSystem::getBlendMode(SceneBlendFactor ogreBlend) const
903     {
904         switch (ogreBlend)
905         {
906         case SBF_ONE:
907             return GL_ONE;
908         case SBF_ZERO:
909             return GL_ZERO;
910         case SBF_DEST_COLOUR:
911             return GL_DST_COLOR;
912         case SBF_SOURCE_COLOUR:
913             return GL_SRC_COLOR;
914         case SBF_ONE_MINUS_DEST_COLOUR:
915             return GL_ONE_MINUS_DST_COLOR;
916         case SBF_ONE_MINUS_SOURCE_COLOUR:
917             return GL_ONE_MINUS_SRC_COLOR;
918         case SBF_DEST_ALPHA:
919             return GL_DST_ALPHA;
920         case SBF_SOURCE_ALPHA:
921             return GL_SRC_ALPHA;
922         case SBF_ONE_MINUS_DEST_ALPHA:
923             return GL_ONE_MINUS_DST_ALPHA;
924         case SBF_ONE_MINUS_SOURCE_ALPHA:
925             return GL_ONE_MINUS_SRC_ALPHA;
926         };
927 
928         // To keep compiler happy.
929         return GL_ONE;
930     }
931 
_setSeparateSceneBlending(SceneBlendFactor sourceFactor,SceneBlendFactor destFactor,SceneBlendFactor sourceFactorAlpha,SceneBlendFactor destFactorAlpha,SceneBlendOperation op,SceneBlendOperation alphaOp)932     void GL3PlusRenderSystem::_setSeparateSceneBlending(
933         SceneBlendFactor sourceFactor, SceneBlendFactor destFactor,
934         SceneBlendFactor sourceFactorAlpha, SceneBlendFactor destFactorAlpha,
935         SceneBlendOperation op, SceneBlendOperation alphaOp )
936     {
937         GLenum sourceBlend = getBlendMode(sourceFactor);
938         GLenum destBlend = getBlendMode(destFactor);
939         GLenum sourceBlendAlpha = getBlendMode(sourceFactorAlpha);
940         GLenum destBlendAlpha = getBlendMode(destFactorAlpha);
941 
942         if (sourceFactor == SBF_ONE && destFactor == SBF_ZERO &&
943             sourceFactorAlpha == SBF_ONE && destFactorAlpha == SBF_ZERO)
944         {
945             mStateCacheManager->setEnabled(GL_BLEND, false);
946         }
947         else
948         {
949             mStateCacheManager->setEnabled(GL_BLEND, true);
950             mStateCacheManager->setBlendFunc(sourceBlend, destBlend, sourceBlendAlpha, destBlendAlpha);
951         }
952 
953         GLint func = GL_FUNC_ADD, alphaFunc = GL_FUNC_ADD;
954 
955         switch(op)
956         {
957         case SBO_ADD:
958             func = GL_FUNC_ADD;
959             break;
960         case SBO_SUBTRACT:
961             func = GL_FUNC_SUBTRACT;
962             break;
963         case SBO_REVERSE_SUBTRACT:
964             func = GL_FUNC_REVERSE_SUBTRACT;
965             break;
966         case SBO_MIN:
967             func = GL_MIN;
968             break;
969         case SBO_MAX:
970             func = GL_MAX;
971             break;
972         }
973 
974         switch(alphaOp)
975         {
976         case SBO_ADD:
977             alphaFunc = GL_FUNC_ADD;
978             break;
979         case SBO_SUBTRACT:
980             alphaFunc = GL_FUNC_SUBTRACT;
981             break;
982         case SBO_REVERSE_SUBTRACT:
983             alphaFunc = GL_FUNC_REVERSE_SUBTRACT;
984             break;
985         case SBO_MIN:
986             alphaFunc = GL_MIN;
987             break;
988         case SBO_MAX:
989             alphaFunc = GL_MAX;
990             break;
991         }
992 
993         mStateCacheManager->setBlendEquation(func, alphaFunc);
994     }
995 
_setAlphaRejectSettings(CompareFunction func,unsigned char value,bool alphaToCoverage)996     void GL3PlusRenderSystem::_setAlphaRejectSettings(CompareFunction func, unsigned char value, bool alphaToCoverage)
997     {
998         mStateCacheManager->setEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE, (func != CMPF_ALWAYS_PASS) && alphaToCoverage);
999     }
1000 
_setViewport(Viewport * vp)1001     void GL3PlusRenderSystem::_setViewport(Viewport *vp)
1002     {
1003         // Check if viewport is different
1004         if (!vp)
1005         {
1006             mActiveViewport = NULL;
1007             _setRenderTarget(NULL);
1008         }
1009 
1010         else if (vp != mActiveViewport || vp->_isUpdated())
1011         {
1012             RenderTarget* target;
1013 
1014             target = vp->getTarget();
1015             _setRenderTarget(target);
1016             mActiveViewport = vp;
1017 
1018             GLsizei x, y, w, h;
1019 
1020             // Calculate the "lower-left" corner of the viewport
1021             w = vp->getActualWidth();
1022             h = vp->getActualHeight();
1023             x = vp->getActualLeft();
1024             y = vp->getActualTop();
1025 
1026             if (target && !target->requiresTextureFlipping())
1027             {
1028                 // Convert "upper-left" corner to "lower-left"
1029                 y = target->getHeight() - h - y;
1030             }
1031 
1032             mStateCacheManager->setViewport(x, y, w, h);
1033 
1034             // Configure the viewport clipping
1035             glScissor(x, y, w, h);
1036             mScissorBox[0] = x;
1037             mScissorBox[1] = y;
1038             mScissorBox[2] = w;
1039             mScissorBox[3] = h;
1040 
1041             vp->_clearUpdatedFlag();
1042         }
1043     }
1044 
_beginFrame(void)1045     void GL3PlusRenderSystem::_beginFrame(void)
1046     {
1047         if (!mActiveViewport)
1048             OGRE_EXCEPT(Exception::ERR_INVALID_STATE,
1049                         "Cannot begin frame - no viewport selected.",
1050                         "GL3PlusRenderSystem::_beginFrame");
1051 
1052         mScissorsEnabled = true;
1053         mStateCacheManager->setEnabled(GL_SCISSOR_TEST, true);
1054     }
1055 
_endFrame(void)1056     void GL3PlusRenderSystem::_endFrame(void)
1057     {
1058         // Deactivate the viewport clipping.
1059         mScissorsEnabled = false;
1060         mStateCacheManager->setEnabled(GL_SCISSOR_TEST, false);
1061 
1062         // unbind GPU programs at end of frame
1063         // this is mostly to avoid holding bound programs that might get deleted
1064         // outside via the resource manager
1065         unbindGpuProgram(GPT_VERTEX_PROGRAM);
1066         unbindGpuProgram(GPT_FRAGMENT_PROGRAM);
1067         unbindGpuProgram(GPT_GEOMETRY_PROGRAM);
1068 
1069         if (mDriverVersion.major >= 4)
1070         {
1071             unbindGpuProgram(GPT_HULL_PROGRAM);
1072             unbindGpuProgram(GPT_DOMAIN_PROGRAM);
1073             if (mDriverVersion.minor >= 3)
1074                 unbindGpuProgram(GPT_COMPUTE_PROGRAM);
1075         }
1076     }
1077 
_setCullingMode(CullingMode mode)1078     void GL3PlusRenderSystem::_setCullingMode(CullingMode mode)
1079     {
1080         mCullingMode = mode;
1081         // NB: Because two-sided stencil API dependence of the front face, we must
1082         // use the same 'winding' for the front face everywhere. As the OGRE default
1083         // culling mode is clockwise, we also treat anticlockwise winding as front
1084         // face for consistently. On the assumption that, we can't change the front
1085         // face by glFrontFace anywhere.
1086 
1087         GLenum cullMode;
1088 
1089         switch( mode )
1090         {
1091         case CULL_NONE:
1092             mStateCacheManager->setEnabled( GL_CULL_FACE, false );
1093             return;
1094 
1095         default:
1096         case CULL_CLOCKWISE:
1097             if (mActiveRenderTarget &&
1098                 ((mActiveRenderTarget->requiresTextureFlipping() && !mInvertVertexWinding) ||
1099                  (!mActiveRenderTarget->requiresTextureFlipping() && mInvertVertexWinding)))
1100             {
1101                 cullMode = GL_FRONT;
1102             }
1103             else
1104             {
1105                 cullMode = GL_BACK;
1106             }
1107             break;
1108         case CULL_ANTICLOCKWISE:
1109             if (mActiveRenderTarget &&
1110                 ((mActiveRenderTarget->requiresTextureFlipping() && !mInvertVertexWinding) ||
1111                  (!mActiveRenderTarget->requiresTextureFlipping() && mInvertVertexWinding)))
1112             {
1113                 cullMode = GL_BACK;
1114             }
1115             else
1116             {
1117                 cullMode = GL_FRONT;
1118             }
1119             break;
1120         }
1121 
1122         mStateCacheManager->setEnabled( GL_CULL_FACE, true );
1123         mStateCacheManager->setCullFace( cullMode );
1124     }
1125 
_setDepthBufferParams(bool depthTest,bool depthWrite,CompareFunction depthFunction)1126     void GL3PlusRenderSystem::_setDepthBufferParams(bool depthTest, bool depthWrite, CompareFunction depthFunction)
1127     {
1128         _setDepthBufferCheckEnabled(depthTest);
1129         _setDepthBufferWriteEnabled(depthWrite);
1130         _setDepthBufferFunction(depthFunction);
1131     }
1132 
_setDepthBufferCheckEnabled(bool enabled)1133     void GL3PlusRenderSystem::_setDepthBufferCheckEnabled(bool enabled)
1134     {
1135         if (enabled)
1136         {
1137             mStateCacheManager->setClearDepth(1.0f);
1138         }
1139         mStateCacheManager->setEnabled(GL_DEPTH_TEST, enabled);
1140     }
1141 
_setDepthBufferWriteEnabled(bool enabled)1142     void GL3PlusRenderSystem::_setDepthBufferWriteEnabled(bool enabled)
1143     {
1144         GLboolean flag = enabled ? GL_TRUE : GL_FALSE;
1145         mStateCacheManager->setDepthMask( flag );
1146 
1147         // Store for reference in _beginFrame
1148         mDepthWrite = enabled;
1149     }
1150 
_setDepthBufferFunction(CompareFunction func)1151     void GL3PlusRenderSystem::_setDepthBufferFunction(CompareFunction func)
1152     {
1153         mStateCacheManager->setDepthFunc(convertCompareFunction(func));
1154     }
1155 
_setDepthBias(float constantBias,float slopeScaleBias)1156     void GL3PlusRenderSystem::_setDepthBias(float constantBias, float slopeScaleBias)
1157     {
1158         //FIXME glPolygonOffset currently is buggy in GL3+ RS but not GL RS.
1159         bool enable = constantBias != 0 || slopeScaleBias != 0;
1160         mStateCacheManager->setEnabled(GL_POLYGON_OFFSET_FILL, enable);
1161         mStateCacheManager->setEnabled(GL_POLYGON_OFFSET_POINT, enable);
1162         mStateCacheManager->setEnabled(GL_POLYGON_OFFSET_LINE, enable);
1163 
1164         if (enable)
1165         {
1166             glPolygonOffset(-slopeScaleBias, -constantBias);
1167         }
1168     }
1169 
_setColourBufferWriteEnabled(bool red,bool green,bool blue,bool alpha)1170     void GL3PlusRenderSystem::_setColourBufferWriteEnabled(bool red, bool green, bool blue, bool alpha)
1171     {
1172         mStateCacheManager->setColourMask(red, green, blue, alpha);
1173 
1174         // record this
1175         mColourWrite[0] = red;
1176         mColourWrite[1] = green;
1177         mColourWrite[2] = blue;
1178         mColourWrite[3] = alpha;
1179     }
1180 
createHardwareOcclusionQuery(void)1181     HardwareOcclusionQuery* GL3PlusRenderSystem::createHardwareOcclusionQuery(void)
1182     {
1183         GL3PlusHardwareOcclusionQuery* ret = new GL3PlusHardwareOcclusionQuery();
1184         mHwOcclusionQueries.push_back(ret);
1185         return ret;
1186     }
1187 
_setPolygonMode(PolygonMode level)1188     void GL3PlusRenderSystem::_setPolygonMode(PolygonMode level)
1189     {
1190         switch(level)
1191         {
1192         case PM_POINTS:
1193             mStateCacheManager->setPolygonMode(GL_POINT);
1194             break;
1195         case PM_WIREFRAME:
1196             mStateCacheManager->setPolygonMode(GL_LINE);
1197             break;
1198         case PM_SOLID:
1199             mStateCacheManager->setPolygonMode(GL_FILL);
1200             break;
1201         }
1202     }
1203 
setStencilCheckEnabled(bool enabled)1204     void GL3PlusRenderSystem::setStencilCheckEnabled(bool enabled)
1205     {
1206         mStateCacheManager->setEnabled(GL_STENCIL_TEST, enabled);
1207     }
1208 
setStencilBufferParams(CompareFunction func,uint32 refValue,uint32 compareMask,uint32 writeMask,StencilOperation stencilFailOp,StencilOperation depthFailOp,StencilOperation passOp,bool twoSidedOperation,bool readBackAsTexture)1209     void GL3PlusRenderSystem::setStencilBufferParams(CompareFunction func,
1210                                                      uint32 refValue, uint32 compareMask, uint32 writeMask,
1211                                                      StencilOperation stencilFailOp,
1212                                                      StencilOperation depthFailOp,
1213                                                      StencilOperation passOp,
1214                                                      bool twoSidedOperation,
1215                                                      bool readBackAsTexture)
1216     {
1217         bool flip;
1218         mStencilWriteMask = writeMask;
1219 
1220         if (twoSidedOperation)
1221         {
1222             if (!mCurrentCapabilities->hasCapability(RSC_TWO_SIDED_STENCIL))
1223                 OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "2-sided stencils are not supported",
1224                             "GL3PlusRenderSystem::setStencilBufferParams");
1225 
1226             // NB: We should always treat CCW as front face for consistent with default
1227             // culling mode. Therefore, we must take care with two-sided stencil settings.
1228             flip = (mInvertVertexWinding && !mActiveRenderTarget->requiresTextureFlipping()) ||
1229                 (!mInvertVertexWinding && mActiveRenderTarget->requiresTextureFlipping());
1230             // Back
1231             OGRE_CHECK_GL_ERROR(glStencilMaskSeparate(GL_BACK, writeMask));
1232             OGRE_CHECK_GL_ERROR(glStencilFuncSeparate(GL_BACK, convertCompareFunction(func), refValue, compareMask));
1233             OGRE_CHECK_GL_ERROR(glStencilOpSeparate(GL_BACK,
1234                                                     convertStencilOp(stencilFailOp, !flip),
1235                                                     convertStencilOp(depthFailOp, !flip),
1236                                                     convertStencilOp(passOp, !flip)));
1237 
1238             // Front
1239             OGRE_CHECK_GL_ERROR(glStencilMaskSeparate(GL_FRONT, writeMask));
1240             OGRE_CHECK_GL_ERROR(glStencilFuncSeparate(GL_FRONT, convertCompareFunction(func), refValue, compareMask));
1241             OGRE_CHECK_GL_ERROR(glStencilOpSeparate(GL_FRONT,
1242                                                     convertStencilOp(stencilFailOp, flip),
1243                                                     convertStencilOp(depthFailOp, flip),
1244                                                     convertStencilOp(passOp, flip)));
1245         }
1246         else
1247         {
1248             flip = false;
1249             mStateCacheManager->setStencilMask(writeMask);
1250             OGRE_CHECK_GL_ERROR(glStencilFunc(convertCompareFunction(func), refValue, compareMask));
1251             OGRE_CHECK_GL_ERROR(glStencilOp(
1252                 convertStencilOp(stencilFailOp, flip),
1253                 convertStencilOp(depthFailOp, flip),
1254                 convertStencilOp(passOp, flip)));
1255         }
1256     }
1257 
_setTextureUnitFiltering(size_t unit,FilterType ftype,FilterOptions fo)1258     void GL3PlusRenderSystem::_setTextureUnitFiltering(size_t unit, FilterType ftype, FilterOptions fo)
1259     {
1260         if (!mStateCacheManager->activateGLTextureUnit(unit))
1261             return;
1262 
1263         switch (ftype)
1264         {
1265         case FT_MIN:
1266             mMinFilter = fo;
1267 
1268             // Combine with existing mip filter
1269             mStateCacheManager->setTexParameteri(
1270                 mTextureTypes[unit], GL_TEXTURE_MIN_FILTER,
1271                 GL3PlusSampler::getCombinedMinMipFilter(mMinFilter, mMipFilter));
1272             break;
1273 
1274         case FT_MAG:
1275             switch (fo)
1276             {
1277             case FO_ANISOTROPIC: // GL treats linear and aniso the same
1278             case FO_LINEAR:
1279                 mStateCacheManager->setTexParameteri(mTextureTypes[unit],
1280                                                     GL_TEXTURE_MAG_FILTER,
1281                                                     GL_LINEAR);
1282                 break;
1283             case FO_POINT:
1284             case FO_NONE:
1285                 mStateCacheManager->setTexParameteri(mTextureTypes[unit],
1286                                                     GL_TEXTURE_MAG_FILTER,
1287                                                     GL_NEAREST);
1288                 break;
1289             }
1290             break;
1291         case FT_MIP:
1292             mMipFilter = fo;
1293 
1294             // Combine with existing min filter
1295             mStateCacheManager->setTexParameteri(
1296                 mTextureTypes[unit], GL_TEXTURE_MIN_FILTER,
1297                 GL3PlusSampler::getCombinedMinMipFilter(mMinFilter, mMipFilter));
1298             break;
1299         }
1300     }
1301 
_setTextureUnitCompareFunction(size_t unit,CompareFunction function)1302     void GL3PlusRenderSystem::_setTextureUnitCompareFunction(size_t unit, CompareFunction function)
1303     {
1304         if (!mStateCacheManager->activateGLTextureUnit(unit))
1305             return;
1306 
1307         mStateCacheManager->setTexParameteri(mTextureTypes[unit],
1308                                             GL_TEXTURE_COMPARE_FUNC,
1309                                             convertCompareFunction(function));
1310     }
1311 
_setTextureUnitCompareEnabled(size_t unit,bool compare)1312     void GL3PlusRenderSystem::_setTextureUnitCompareEnabled(size_t unit, bool compare)
1313     {
1314         if (!mStateCacheManager->activateGLTextureUnit(unit))
1315             return;
1316 
1317         mStateCacheManager->setTexParameteri(mTextureTypes[unit],
1318                                             GL_TEXTURE_COMPARE_MODE,
1319                                             compare ? GL_COMPARE_REF_TO_TEXTURE : GL_NONE);
1320     }
1321 
_setTextureLayerAnisotropy(size_t unit,unsigned int maxAnisotropy)1322     void GL3PlusRenderSystem::_setTextureLayerAnisotropy(size_t unit, unsigned int maxAnisotropy)
1323     {
1324         if (!mCurrentCapabilities->hasCapability(RSC_ANISOTROPY))
1325             return;
1326 
1327         if (!mStateCacheManager->activateGLTextureUnit(unit))
1328             return;
1329 
1330         maxAnisotropy = std::min<uint>(mLargestSupportedAnisotropy, maxAnisotropy);
1331         mStateCacheManager->setTexParameteri(mTextureTypes[unit], GL_TEXTURE_MAX_ANISOTROPY_EXT, maxAnisotropy);
1332     }
1333 
_dispatchCompute(const Vector3i & workgroupDim)1334     void GL3PlusRenderSystem::_dispatchCompute(const Vector3i& workgroupDim)
1335     {
1336         // if(mComputeProgramExecutions <= compute_execution_cap)
1337 
1338         //FIXME give user control over when and what memory barriers are created
1339         // if (mPreComputeMemoryBarrier)
1340         OGRE_CHECK_GL_ERROR(glMemoryBarrier(GL_ALL_BARRIER_BITS));
1341         OGRE_CHECK_GL_ERROR(glDispatchCompute(workgroupDim[0], workgroupDim[1], workgroupDim[2]));
1342         // if (mPostComputeMemoryBarrier)
1343         //     OGRE_CHECK_GL_ERROR(glMemoryBarrier(toGL(MB_TEXTURE)));
1344         // if (compute_execution_cap > 0)
1345         //     mComputeProgramExecutions++;
1346     }
1347 
_render(const RenderOperation & op)1348     void GL3PlusRenderSystem::_render(const RenderOperation& op)
1349     {
1350         // Call super class.
1351         RenderSystem::_render(op);
1352 
1353         // Create variables related to instancing.
1354         HardwareVertexBufferSharedPtr globalInstanceVertexBuffer = getGlobalInstanceVertexBuffer();
1355         VertexDeclaration* globalVertexDeclaration = getGlobalInstanceVertexBufferVertexDeclaration();
1356         bool hasInstanceData = (op.useGlobalInstancingVertexBufferIsAvailable &&
1357                                 globalInstanceVertexBuffer && globalVertexDeclaration) ||
1358                                op.vertexData->vertexBufferBinding->hasInstanceData();
1359 
1360         size_t numberOfInstances = op.numberOfInstances;
1361 
1362         if (op.useGlobalInstancingVertexBufferIsAvailable)
1363         {
1364             numberOfInstances *= getGlobalNumberOfInstances();
1365         }
1366 
1367         GLSLProgram* program = GLSLProgramManager::getSingleton().getActiveProgram();
1368 
1369         if (!program)
1370         {
1371             LogManager::getSingleton().logError("Failed to create shader program.");
1372         }
1373 
1374         GLVertexArrayObject* vao =
1375             static_cast<GLVertexArrayObject*>(op.vertexData->vertexDeclaration);
1376         // Bind VAO (set of per-vertex attributes: position, normal, etc.).
1377         vao->bind(this);
1378         bool updateVAO = vao->needsUpdate(op.vertexData->vertexBufferBinding,
1379                                           op.vertexData->vertexStart);
1380 
1381         if (updateVAO)
1382             vao->bindToGpu(this, op.vertexData->vertexBufferBinding, op.vertexData->vertexStart);
1383 
1384         // We treat index buffer binding inside VAO as volatile, always updating and never relying onto it,
1385         // as one shared vertex buffer could be rendered with several index buffers, from submeshes and/or LODs
1386         if (op.useIndexes)
1387             mStateCacheManager->bindGLBuffer(GL_ELEMENT_ARRAY_BUFFER,
1388                 static_cast<GL3PlusHardwareIndexBuffer*>(op.indexData->indexBuffer.get())->getGLBufferId());
1389 
1390         // unconditionally modify VAO for global instance data (FIXME bad API)
1391         VertexDeclaration::VertexElementList::const_iterator elemIter, elemEnd;
1392         if ( globalInstanceVertexBuffer && globalVertexDeclaration )
1393         {
1394             elemEnd = globalVertexDeclaration->getElements().end();
1395             for (elemIter = globalVertexDeclaration->getElements().begin(); elemIter != elemEnd; ++elemIter)
1396             {
1397                 const VertexElement & elem = *elemIter;
1398                 bindVertexElementToGpu(elem, globalInstanceVertexBuffer, 0);
1399             }
1400         }
1401 
1402         // Launch compute shader job(s).
1403         if (mCurrentComputeShader)
1404         {
1405             _dispatchCompute(Vector3i(mCurrentComputeShader->getComputeGroupDimensions()));
1406         }
1407 
1408         int operationType = op.operationType;
1409         // Use adjacency if there is a geometry program and it requested adjacency info
1410         if(mGeometryProgramBound && mCurrentGeometryShader && mCurrentGeometryShader->isAdjacencyInfoRequired())
1411             operationType |= RenderOperation::OT_DETAIL_ADJACENCY_BIT;
1412 
1413         // Determine the correct primitive type to render.
1414         GLint primType;
1415         switch (operationType)
1416         {
1417         case RenderOperation::OT_POINT_LIST:
1418             primType = GL_POINTS;
1419             break;
1420         case RenderOperation::OT_LINE_LIST:
1421             primType = GL_LINES;
1422             break;
1423         case RenderOperation::OT_LINE_LIST_ADJ:
1424             primType = GL_LINES_ADJACENCY;
1425             break;
1426         case RenderOperation::OT_LINE_STRIP:
1427             primType = GL_LINE_STRIP;
1428             break;
1429         case RenderOperation::OT_LINE_STRIP_ADJ:
1430             primType = GL_LINE_STRIP_ADJACENCY;
1431             break;
1432         default:
1433         case RenderOperation::OT_TRIANGLE_LIST:
1434             primType = GL_TRIANGLES;
1435             break;
1436         case RenderOperation::OT_TRIANGLE_LIST_ADJ:
1437             primType = GL_TRIANGLES_ADJACENCY;
1438             break;
1439         case RenderOperation::OT_TRIANGLE_STRIP:
1440             primType = GL_TRIANGLE_STRIP;
1441             break;
1442         case RenderOperation::OT_TRIANGLE_STRIP_ADJ:
1443             primType = GL_TRIANGLE_STRIP_ADJACENCY;
1444             break;
1445         case RenderOperation::OT_TRIANGLE_FAN:
1446             primType = GL_TRIANGLE_FAN;
1447             break;
1448         }
1449 
1450 
1451         // Bind atomic counter buffers.
1452         // if (Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_ATOMIC_COUNTERS))
1453         // {
1454         //     GLuint atomicsBuffer = 0;
1455 
1456         //     glGenBuffers(1, &atomicsBuffer);
1457         //     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER,
1458         //                  static_cast<GL3PlusHardwareCounterBuffer*>(HardwareBufferManager::getSingleton().getCounterBuffer().getGLBufferId()));
1459         //                  //static_cast<GL3PlusHardwareCounterBuffer*>(op..getCounterBuffer().getGLBufferId()));
1460         //     // glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(GLuint) * 3, NULL, GL_DYNAMIC_DRAW);
1461         //     // glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
1462         // }
1463         //TODO: Reset atomic counters somewhere
1464 
1465 
1466         // Render to screen!
1467         if (mCurrentDomainShader)
1468         {
1469             // Tessellation shader special case.
1470             // Note: Only evaluation (domain) shaders are required.
1471 
1472             // GLuint primCount = 0;
1473             // // Useful primitives for tessellation
1474             // switch( op.operationType )
1475             // {
1476             // case RenderOperation::OT_LINE_LIST:
1477             //     primCount = (GLuint)(op.useIndexes ? op.indexData->indexCount : op.vertexData->vertexCount) / 2;
1478             //     break;
1479 
1480             // case RenderOperation::OT_LINE_STRIP:
1481             //     primCount = (GLuint)(op.useIndexes ? op.indexData->indexCount : op.vertexData->vertexCount) - 1;
1482             //     break;
1483 
1484             // case RenderOperation::OT_TRIANGLE_LIST:
1485             //     primCount = (GLuint)(op.useIndexes ? op.indexData->indexCount : op.vertexData->vertexCount);
1486             //     //primCount = (GLuint)(op.useIndexes ? op.indexData->indexCount : op.vertexData->vertexCount) / 3;
1487             //     break;
1488 
1489             // case RenderOperation::OT_TRIANGLE_STRIP:
1490             //     primCount = (GLuint)(op.useIndexes ? op.indexData->indexCount : op.vertexData->vertexCount) - 2;
1491             //     break;
1492             // default:
1493             //     break;
1494             // }
1495 
1496             // These are set via shader in DX11, SV_InsideTessFactor and SV_OutsideTessFactor
1497             // Hardcoding for the sample
1498             // float patchLevel(1.f);
1499             // OGRE_CHECK_GL_ERROR(glPatchParameterfv(GL_PATCH_DEFAULT_INNER_LEVEL, &patchLevel));
1500             // OGRE_CHECK_GL_ERROR(glPatchParameterfv(GL_PATCH_DEFAULT_OUTER_LEVEL, &patchLevel));
1501             // OGRE_CHECK_GL_ERROR(glPatchParameteri(GL_PATCH_VERTICES, op.vertexData->vertexCount));
1502 
1503             if (op.useIndexes)
1504             {
1505                 void *pBufferData = GL_BUFFER_OFFSET(op.indexData->indexStart *
1506                                                      op.indexData->indexBuffer->getIndexSize());
1507                 GLenum indexType = (op.indexData->indexBuffer->getType() == HardwareIndexBuffer::IT_32BIT) ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT;
1508                 OGRE_CHECK_GL_ERROR(glDrawElements(GL_PATCHES, op.indexData->indexCount, indexType, pBufferData));
1509                 //OGRE_CHECK_GL_ERROR(glDrawElements(GL_PATCHES, op.indexData->indexCount, indexType, pBufferData));
1510                 //                OGRE_CHECK_GL_ERROR(glDrawArraysInstanced(GL_PATCHES, 0, primCount, 1));
1511             }
1512             else
1513             {
1514                 OGRE_CHECK_GL_ERROR(glDrawArrays(GL_PATCHES, 0, op.vertexData->vertexCount));
1515                 //OGRE_CHECK_GL_ERROR(glDrawArrays(GL_PATCHES, 0, primCount));
1516                 //                OGRE_CHECK_GL_ERROR(glDrawArraysInstanced(GL_PATCHES, 0, primCount, 1));
1517             }
1518         }
1519         else if (op.useIndexes)
1520         {
1521             void *pBufferData = GL_BUFFER_OFFSET(op.indexData->indexStart *
1522                                                  op.indexData->indexBuffer->getIndexSize());
1523 
1524             //TODO : GL_UNSIGNED_INT or GL_UNSIGNED_BYTE?  Latter breaks samples.
1525             GLenum indexType = (op.indexData->indexBuffer->getType() == HardwareIndexBuffer::IT_16BIT) ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
1526 
1527             do
1528             {
1529                 // Update derived depth bias.
1530                 if (mDerivedDepthBias && mCurrentPassIterationNum > 0)
1531                 {
1532                     _setDepthBias(mDerivedDepthBiasBase +
1533                                   mDerivedDepthBiasMultiplier * mCurrentPassIterationNum,
1534                                   mDerivedDepthBiasSlopeScale);
1535                 }
1536 
1537                 if (hasInstanceData)
1538                 {
1539                     OGRE_CHECK_GL_ERROR(glDrawElementsInstanced(primType, op.indexData->indexCount, indexType, pBufferData, numberOfInstances));
1540                 }
1541                 else
1542                 {
1543                     OGRE_CHECK_GL_ERROR(glDrawElements(primType, op.indexData->indexCount, indexType, pBufferData));
1544                 }
1545             } while (updatePassIterationRenderState());
1546         }
1547         else
1548         {
1549             do
1550             {
1551                 // Update derived depth bias.
1552                 if (mDerivedDepthBias && mCurrentPassIterationNum > 0)
1553                 {
1554                     _setDepthBias(mDerivedDepthBiasBase +
1555                                   mDerivedDepthBiasMultiplier * mCurrentPassIterationNum,
1556                                   mDerivedDepthBiasSlopeScale);
1557                 }
1558 
1559                 if (hasInstanceData)
1560                 {
1561                     OGRE_CHECK_GL_ERROR(glDrawArraysInstanced(primType, 0, op.vertexData->vertexCount, numberOfInstances));
1562                 }
1563                 else
1564                 {
1565                     OGRE_CHECK_GL_ERROR(glDrawArrays(primType, 0, op.vertexData->vertexCount));
1566                 }
1567             } while (updatePassIterationRenderState());
1568         }
1569 
1570         // Do not unbind the vertex array object
1571         // VAOs > 0 are selected each time before usage
1572         // VAO #0 is not supported in Core profiles, and WOULD NOT be used by Ogre even in compatibility profiles
1573     }
1574 
setScissorTest(bool enabled,size_t left,size_t top,size_t right,size_t bottom)1575     void GL3PlusRenderSystem::setScissorTest(bool enabled, size_t left,
1576                                              size_t top, size_t right,
1577                                              size_t bottom)
1578     {
1579         mScissorsEnabled = enabled;
1580         // If request texture flipping, use "upper-left", otherwise use "lower-left"
1581         bool flipping = mActiveRenderTarget->requiresTextureFlipping();
1582         //  GL measures from the bottom, not the top
1583         size_t targetHeight = mActiveRenderTarget->getHeight();
1584         // Calculate the "lower-left" corner of the viewport
1585         int x = 0, y = 0, w = 0, h = 0;
1586 
1587         if (enabled)
1588         {
1589             mStateCacheManager->setEnabled(GL_SCISSOR_TEST, true);
1590             // NB GL uses width / height rather than right / bottom
1591             x = left;
1592             if (flipping)
1593                 y = top;
1594             else
1595                 y = targetHeight - bottom;
1596             w = right - left;
1597             h = bottom - top;
1598             OGRE_CHECK_GL_ERROR(glScissor(static_cast<GLsizei>(x),
1599                                           static_cast<GLsizei>(y),
1600                                           static_cast<GLsizei>(w),
1601                                           static_cast<GLsizei>(h)));
1602 
1603             mScissorBox[0] = x;
1604             mScissorBox[1] = y;
1605             mScissorBox[2] = w;
1606             mScissorBox[3] = h;
1607         }
1608         else
1609         {
1610             mStateCacheManager->setEnabled(GL_SCISSOR_TEST, false);
1611             // GL requires you to reset the scissor when disabling
1612             w = mActiveViewport->getActualWidth();
1613             h = mActiveViewport->getActualHeight();
1614             x = mActiveViewport->getActualLeft();
1615             if (flipping)
1616                 y = mActiveViewport->getActualTop();
1617             else
1618                 y = targetHeight - mActiveViewport->getActualTop() - h;
1619             OGRE_CHECK_GL_ERROR(glScissor(static_cast<GLsizei>(x),
1620                                           static_cast<GLsizei>(y),
1621                                           static_cast<GLsizei>(w),
1622                                           static_cast<GLsizei>(h)));
1623 
1624             mScissorBox[0] = x;
1625             mScissorBox[1] = y;
1626             mScissorBox[2] = w;
1627             mScissorBox[3] = h;
1628         }
1629     }
1630 
clearFrameBuffer(unsigned int buffers,const ColourValue & colour,Real depth,unsigned short stencil)1631     void GL3PlusRenderSystem::clearFrameBuffer(unsigned int buffers,
1632                                                const ColourValue& colour,
1633                                                Real depth, unsigned short stencil)
1634     {
1635         bool colourMask = !mColourWrite[0] || !mColourWrite[1] ||
1636             !mColourWrite[2] || !mColourWrite[3];
1637 
1638         GLbitfield flags = 0;
1639         if (buffers & FBT_COLOUR)
1640         {
1641             flags |= GL_COLOR_BUFFER_BIT;
1642             // Enable buffer for writing if it isn't
1643             if (colourMask)
1644             {
1645                 mStateCacheManager->setColourMask(true, true, true, true);
1646             }
1647             mStateCacheManager->setClearColour(colour.r, colour.g, colour.b, colour.a);
1648         }
1649         if (buffers & FBT_DEPTH)
1650         {
1651             flags |= GL_DEPTH_BUFFER_BIT;
1652             // Enable buffer for writing if it isn't
1653             if (!mDepthWrite)
1654             {
1655                 mStateCacheManager->setDepthMask( GL_TRUE );
1656             }
1657             mStateCacheManager->setClearDepth(depth);
1658         }
1659         if (buffers & FBT_STENCIL)
1660         {
1661             flags |= GL_STENCIL_BUFFER_BIT;
1662             // Enable buffer for writing if it isn't
1663             mStateCacheManager->setStencilMask(0xFFFFFFFF);
1664             OGRE_CHECK_GL_ERROR(glClearStencil(stencil));
1665         }
1666 
1667         // Should be enable scissor test due the clear region is
1668         // relied on scissor box bounds.
1669         if (!mScissorsEnabled)
1670         {
1671             mStateCacheManager->setEnabled(GL_SCISSOR_TEST, true);
1672         }
1673 
1674         // Sets the scissor box as same as viewport
1675         GLint viewport[4];
1676         mStateCacheManager->getViewport(viewport);
1677         bool scissorBoxDifference =
1678             viewport[0] != mScissorBox[0] || viewport[1] != mScissorBox[1] ||
1679             viewport[2] != mScissorBox[2] || viewport[3] != mScissorBox[3];
1680         if (scissorBoxDifference)
1681         {
1682             OGRE_CHECK_GL_ERROR(glScissor(viewport[0], viewport[1], viewport[2], viewport[3]));
1683         }
1684 
1685         // Clear buffers
1686         OGRE_CHECK_GL_ERROR(glClear(flags));
1687 
1688         // Restore scissor box
1689         if (scissorBoxDifference)
1690         {
1691             OGRE_CHECK_GL_ERROR(glScissor(mScissorBox[0], mScissorBox[1], mScissorBox[2], mScissorBox[3]));
1692         }
1693 
1694         // Restore scissor test
1695         if (!mScissorsEnabled)
1696         {
1697             mStateCacheManager->setEnabled(GL_SCISSOR_TEST, false);
1698         }
1699 
1700         // Reset buffer write state
1701         if (!mDepthWrite && (buffers & FBT_DEPTH))
1702         {
1703             mStateCacheManager->setDepthMask( GL_FALSE );
1704         }
1705 
1706         if (colourMask && (buffers & FBT_COLOUR))
1707         {
1708             mStateCacheManager->setColourMask(mColourWrite[0], mColourWrite[1], mColourWrite[2], mColourWrite[3]);
1709         }
1710 
1711         if (buffers & FBT_STENCIL)
1712         {
1713             mStateCacheManager->setStencilMask(mStencilWriteMask);
1714         }
1715     }
1716 
_switchContext(GL3PlusContext * context)1717     void GL3PlusRenderSystem::_switchContext(GL3PlusContext *context)
1718     {
1719         // Unbind GPU programs and rebind to new context later, because
1720         // scene manager treat render system as ONE 'context' ONLY, and it
1721         // cached the GPU programs using state.
1722         if (mCurrentVertexShader)
1723             mCurrentVertexShader->unbind();
1724         if (mCurrentGeometryShader)
1725             mCurrentGeometryShader->unbind();
1726         if (mCurrentFragmentShader)
1727             mCurrentFragmentShader->unbind();
1728         if (mCurrentHullShader)
1729             mCurrentHullShader->unbind();
1730         if (mCurrentDomainShader)
1731             mCurrentDomainShader->unbind();
1732         if (mCurrentComputeShader)
1733             mCurrentComputeShader->unbind();
1734 
1735         // Disable textures
1736         _disableTextureUnitsFrom(0);
1737 
1738         // It's ready for switching
1739         if (mCurrentContext!=context)
1740         {
1741 #if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
1742             // NSGLContext::makeCurrentContext does not flush automatically. everybody else does.
1743             glFlushRenderAPPLE();
1744 #endif
1745             mCurrentContext->endCurrent();
1746             mCurrentContext = context;
1747         }
1748         mCurrentContext->setCurrent();
1749 
1750         mStateCacheManager = mCurrentContext->createOrRetrieveStateCacheManager<GL3PlusStateCacheManager>();
1751         _completeDeferredVaoFboDestruction();
1752 
1753         // Check if the context has already done one-time initialisation
1754         if (!mCurrentContext->getInitialized())
1755         {
1756             _oneTimeContextInitialization();
1757             mCurrentContext->setInitialized();
1758         }
1759 
1760         // Rebind GPU programs to new context
1761         if (mCurrentVertexShader)
1762             mCurrentVertexShader->bind();
1763         if (mCurrentGeometryShader)
1764             mCurrentGeometryShader->bind();
1765         if (mCurrentFragmentShader)
1766             mCurrentFragmentShader->bind();
1767         if (mCurrentHullShader)
1768             mCurrentHullShader->bind();
1769         if (mCurrentDomainShader)
1770             mCurrentDomainShader->bind();
1771         if (mCurrentComputeShader)
1772             mCurrentComputeShader->bind();
1773 
1774         // Must reset depth/colour write mask to according with user desired, otherwise,
1775         // clearFrameBuffer would be wrong because the value we are recorded may be
1776         // difference with the really state stored in GL context.
1777         mStateCacheManager->setDepthMask(mDepthWrite);
1778         mStateCacheManager->setColourMask(mColourWrite[0], mColourWrite[1], mColourWrite[2], mColourWrite[3]);
1779         mStateCacheManager->setStencilMask(mStencilWriteMask);
1780     }
1781 
_unregisterContext(GL3PlusContext * context)1782     void GL3PlusRenderSystem::_unregisterContext(GL3PlusContext *context)
1783     {
1784         static_cast<GL3PlusHardwareBufferManager*>(HardwareBufferManager::getSingletonPtr())->notifyContextDestroyed(context);
1785 
1786         for(RenderTargetMap::iterator it = mRenderTargets.begin(); it!=mRenderTargets.end(); ++it)
1787         {
1788             if(auto target = dynamic_cast<GLRenderTarget*>(it->second))
1789             {
1790                 if(auto fbo = target->getFBO())
1791                     fbo->notifyContextDestroyed(context);
1792             }
1793         }
1794 
1795         if (mCurrentContext == context)
1796         {
1797             // Change the context to something else so that a valid context
1798             // remains active. When this is the main context being unregistered,
1799             // we set the main context to 0.
1800             if (mCurrentContext != mMainContext)
1801             {
1802                 _switchContext(mMainContext);
1803             }
1804             else
1805             {
1806                 /// No contexts remain
1807                 mCurrentContext->endCurrent();
1808                 mCurrentContext = 0;
1809                 mMainContext = 0;
1810                 mStateCacheManager = 0;
1811             }
1812         }
1813     }
1814 
_createVao()1815     uint32 GL3PlusRenderSystem::_createVao()
1816     {
1817         uint32 vao = 0;
1818         OGRE_CHECK_GL_ERROR(glGenVertexArrays(1, &vao));
1819         return vao;
1820     }
1821 
_destroyVao(GLContext * context,uint32 vao)1822     void GL3PlusRenderSystem::_destroyVao(GLContext* context, uint32 vao)
1823     {
1824         if(context != mCurrentContext)
1825             context->_getVaoDeferredForDestruction().push_back(vao);
1826         else
1827             OGRE_CHECK_GL_ERROR(glDeleteVertexArrays(1, &vao));
1828     }
1829 
_destroyFbo(GLContext * context,uint32 fbo)1830     void GL3PlusRenderSystem::_destroyFbo(GLContext* context, uint32 fbo)
1831     {
1832         if(context != mCurrentContext)
1833             context->_getFboDeferredForDestruction().push_back(fbo);
1834         else
1835             _getStateCacheManager()->deleteGLFrameBuffer(GL_FRAMEBUFFER, fbo);
1836     }
1837 
_bindVao(GLContext * context,uint32 vao)1838     void GL3PlusRenderSystem::_bindVao(GLContext* context, uint32 vao)
1839     {
1840         OgreAssert(context == mCurrentContext, "VAO used in wrong OpenGL context");
1841         _getStateCacheManager()->bindGLVertexArray(vao);
1842     }
1843 
_oneTimeContextInitialization()1844     void GL3PlusRenderSystem::_oneTimeContextInitialization()
1845     {
1846         OGRE_CHECK_GL_ERROR(glDisable(GL_DITHER));
1847 
1848         // Check for FSAA
1849         // Enable the extension if it was enabled by the GL3PlusSupport
1850         int fsaa_active = false;
1851         OGRE_CHECK_GL_ERROR(glGetIntegerv(GL_SAMPLE_BUFFERS, (GLint*)&fsaa_active));
1852         if (fsaa_active)
1853         {
1854             OGRE_CHECK_GL_ERROR(glEnable(GL_MULTISAMPLE));
1855             LogManager::getSingleton().logMessage("Using FSAA.");
1856         }
1857 
1858         if (checkExtension("GL_EXT_texture_filter_anisotropic"))
1859         {
1860             OGRE_CHECK_GL_ERROR(glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &mLargestSupportedAnisotropy));
1861         }
1862 
1863         if (hasMinGLVersion(3, 2) || checkExtension("GL_ARB_seamless_cube_map"))
1864         {
1865             // Enable seamless cube maps
1866             OGRE_CHECK_GL_ERROR(glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS));
1867         }
1868 
1869         if (hasMinGLVersion(3, 2) || checkExtension("GL_ARB_provoking_vertex"))
1870         {
1871             // Set provoking vertex convention
1872             OGRE_CHECK_GL_ERROR(glProvokingVertex(GL_FIRST_VERTEX_CONVENTION));
1873         }
1874 
1875         if (getCapabilities()->hasCapability(RSC_DEBUG))
1876         {
1877 #if ENABLE_GL_DEBUG_OUTPUT
1878             OGRE_CHECK_GL_ERROR(glEnable(GL_DEBUG_OUTPUT));
1879             OGRE_CHECK_GL_ERROR(glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS));
1880             OGRE_CHECK_GL_ERROR(glDebugMessageCallbackARB(&GLDebugCallback, NULL));
1881             OGRE_CHECK_GL_ERROR(glDebugMessageControlARB(GL_DEBUG_SOURCE_THIRD_PARTY, GL_DEBUG_TYPE_OTHER, GL_DONT_CARE, 0, NULL, GL_TRUE));
1882 #endif
1883         }
1884 
1885         if(getCapabilities()->hasCapability(RSC_PRIMITIVE_RESTART))
1886         {
1887             OGRE_CHECK_GL_ERROR(glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX));
1888         }
1889 
1890         glEnable(GL_PROGRAM_POINT_SIZE);
1891 
1892         if(getCapabilities()->getVendor() == GPU_NVIDIA)
1893         {
1894             // bug in NVIDIA driver, see e.g.
1895             // https://www.opengl.org/discussion_boards/showthread.php/168217-gl_PointCoord-and-OpenGL-3-1-GLSL-1-4
1896             glEnable(0x8861); // GL_POINT_SPRITE
1897             glGetError();     // clear the error that it generates nevertheless..
1898         }
1899     }
1900 
initialiseContext(RenderWindow * primary)1901     void GL3PlusRenderSystem::initialiseContext(RenderWindow* primary)
1902     {
1903         // Set main and current context
1904         mMainContext = dynamic_cast<GLRenderTarget*>(primary)->getContext();
1905         mCurrentContext = mMainContext;
1906 
1907         // Set primary context as active
1908         if (mCurrentContext)
1909             mCurrentContext->setCurrent();
1910 
1911         // Initialise GL3W
1912         if (gl3wInit2(get_proc)) { // gl3wInit() fails if GL3.0 is not supported
1913             OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
1914                         "OpenGL 3.0 is not supported",
1915                         "GL3PlusRenderSystem::initialiseContext");
1916         }
1917 
1918         // Setup GL3PlusSupport
1919         initialiseExtensions();
1920 
1921         mStateCacheManager = mCurrentContext->createOrRetrieveStateCacheManager<GL3PlusStateCacheManager>();
1922 
1923         LogManager::getSingleton().logMessage("**************************************");
1924         LogManager::getSingleton().logMessage("***   OpenGL 3+ Renderer Started   ***");
1925         LogManager::getSingleton().logMessage("**************************************");
1926     }
1927 
_setRenderTarget(RenderTarget * target)1928     void GL3PlusRenderSystem::_setRenderTarget(RenderTarget *target)
1929     {
1930         // Unbind frame buffer object
1931         if (mActiveRenderTarget)
1932             mRTTManager->unbind(mActiveRenderTarget);
1933 
1934         mActiveRenderTarget = target;
1935         if (target)
1936         {
1937             // Switch context if different from current one
1938             GL3PlusContext *newContext = dynamic_cast<GLRenderTarget*>(target)->getContext();
1939             if (newContext && mCurrentContext != newContext)
1940             {
1941                 _switchContext(newContext);
1942             }
1943 
1944             // Check the FBO's depth buffer status
1945             GL3PlusDepthBuffer *depthBuffer = static_cast<GL3PlusDepthBuffer*>(target->getDepthBuffer());
1946 
1947             if ( target->getDepthBufferPool() != DepthBuffer::POOL_NO_DEPTH &&
1948                  (!depthBuffer || depthBuffer->getGLContext() != mCurrentContext ) )
1949             {
1950                 // Depth is automatically managed and there is no depth buffer attached to this RT
1951                 // or the Current context doesn't match the one this Depth buffer was created with
1952                 setDepthBufferFor( target );
1953             }
1954 
1955             // Bind frame buffer object
1956             mRTTManager->bind(target);
1957 
1958             // Enable / disable sRGB states
1959             if (target->isHardwareGammaEnabled())
1960             {
1961                 OGRE_CHECK_GL_ERROR(glEnable(GL_FRAMEBUFFER_SRGB));
1962 
1963                 // Note: could test GL_FRAMEBUFFER_SRGB_CAPABLE here before
1964                 // enabling, but GL spec says incapable surfaces ignore the setting
1965                 // anyway. We test the capability to enable isHardwareGammaEnabled.
1966             }
1967             else
1968             {
1969                 OGRE_CHECK_GL_ERROR(glDisable(GL_FRAMEBUFFER_SRGB));
1970             }
1971         }
1972     }
1973 
convertCompareFunction(CompareFunction func)1974     GLint GL3PlusRenderSystem::convertCompareFunction(CompareFunction func)
1975     {
1976         switch(func)
1977         {
1978         case CMPF_ALWAYS_FAIL:
1979             return GL_NEVER;
1980         case CMPF_ALWAYS_PASS:
1981             return GL_ALWAYS;
1982         case CMPF_LESS:
1983             return GL_LESS;
1984         case CMPF_LESS_EQUAL:
1985             return GL_LEQUAL;
1986         case CMPF_EQUAL:
1987             return GL_EQUAL;
1988         case CMPF_NOT_EQUAL:
1989             return GL_NOTEQUAL;
1990         case CMPF_GREATER_EQUAL:
1991             return GL_GEQUAL;
1992         case CMPF_GREATER:
1993             return GL_GREATER;
1994         };
1995         // To keep compiler happy
1996         return GL_ALWAYS;
1997     }
1998 
convertStencilOp(StencilOperation op,bool invert)1999     GLint GL3PlusRenderSystem::convertStencilOp(StencilOperation op, bool invert)
2000     {
2001         switch(op)
2002         {
2003         case SOP_KEEP:
2004             return GL_KEEP;
2005         case SOP_ZERO:
2006             return GL_ZERO;
2007         case SOP_REPLACE:
2008             return GL_REPLACE;
2009         case SOP_INCREMENT:
2010             return invert ? GL_DECR : GL_INCR;
2011         case SOP_DECREMENT:
2012             return invert ? GL_INCR : GL_DECR;
2013         case SOP_INCREMENT_WRAP:
2014             return invert ? GL_DECR_WRAP : GL_INCR_WRAP;
2015         case SOP_DECREMENT_WRAP:
2016             return invert ? GL_INCR_WRAP : GL_DECR_WRAP;
2017         case SOP_INVERT:
2018             return GL_INVERT;
2019         };
2020         // to keep compiler happy
2021         return SOP_KEEP;
2022     }
2023 
2024 
bindGpuProgram(GpuProgram * prg)2025     void GL3PlusRenderSystem::bindGpuProgram(GpuProgram* prg)
2026     {
2027         GLSLShader* glprg = static_cast<GLSLShader*>(prg);
2028 
2029         // Unbind previous shader first.
2030         //
2031         // Note:
2032         //  1. Even if both previous and current are the same object, we can't
2033         //     bypass re-bind completely since the object itself may be modified.
2034         //     But we can bypass unbind based on the assumption that the object's
2035         //     internal GL program type shouldn't change after object creation.
2036         //     The behavior of binding to a GL program type twice
2037         //     should be the same as unbinding and rebinding that GL program type,
2038         //     even for different objects.
2039         //  2. We also assumed that the program's type (vertex or fragment) should
2040         //     not change during its use. If not, the following switch
2041         //     statement will confuse GL state completely, and we can't fix it
2042         //     here. To fix this case we must code the program implementation
2043         //     itself: if type is changing (during load/unload, etc), and it's in
2044         //     use, unbind and notify render system to correct for its state.
2045         //
2046         switch (glprg->getType())
2047         {
2048         case GPT_VERTEX_PROGRAM:
2049             if (mCurrentVertexShader != glprg)
2050             {
2051                 if (mCurrentVertexShader)
2052                     mCurrentVertexShader->unbind();
2053                 mCurrentVertexShader = glprg;
2054             }
2055             break;
2056         case GPT_HULL_PROGRAM:
2057             if (mCurrentHullShader != glprg)
2058             {
2059                 if (mCurrentHullShader)
2060                     mCurrentHullShader->unbind();
2061                 mCurrentHullShader = glprg;
2062             }
2063             break;
2064         case GPT_DOMAIN_PROGRAM:
2065             if (mCurrentDomainShader != glprg)
2066             {
2067                 if (mCurrentDomainShader)
2068                     mCurrentDomainShader->unbind();
2069                 mCurrentDomainShader = glprg;
2070             }
2071             break;
2072         case GPT_GEOMETRY_PROGRAM:
2073             if (mCurrentGeometryShader != glprg)
2074             {
2075                 if (mCurrentGeometryShader)
2076                     mCurrentGeometryShader->unbind();
2077                 mCurrentGeometryShader = glprg;
2078             }
2079             break;
2080         case GPT_FRAGMENT_PROGRAM:
2081             if (mCurrentFragmentShader != glprg)
2082             {
2083                 if (mCurrentFragmentShader)
2084                     mCurrentFragmentShader->unbind();
2085                 mCurrentFragmentShader = glprg;
2086             }
2087             break;
2088         case GPT_COMPUTE_PROGRAM:
2089             if (mCurrentComputeShader != glprg)
2090             {
2091                 if (mCurrentComputeShader )
2092                     mCurrentComputeShader ->unbind();
2093                 mCurrentComputeShader  = glprg;
2094             }
2095             break;
2096         default:
2097             break;
2098         }
2099 
2100         // Bind the program
2101         glprg->bind();
2102 
2103         RenderSystem::bindGpuProgram(prg);
2104 
2105         // TextureManager::ResourceMapIterator resource = TextureManager::getSingletonPtr()->getResourceIterator();
2106 
2107         // while(resource.hasMoreElements())
2108         // {
2109         //     TextureManager::ResourceMapPtr resource_map = resource.getNext();
2110         //     resource_map.getResourceType();
2111         // }
2112 
2113         // //FIXME Either a new TextureShaderUsage enum needs to be introduced,
2114         // // or additional TextureUsages must be created.  See OgreTexture.h
2115         // if (tex->getUsage() == TU_DYNAMIC_SHADER)
2116         // {
2117         //     // OGRE_CHECK_GL_ERROR(glBindImageTexture(0, mTextureID, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8));
2118         //     OGRE_CHECK_GL_ERROR(glBindImageTexture(0, tex->getGLID(), 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8));
2119         // }
2120     }
2121 
unbindGpuProgram(GpuProgramType gptype)2122     void GL3PlusRenderSystem::unbindGpuProgram(GpuProgramType gptype)
2123     {
2124         if (gptype == GPT_VERTEX_PROGRAM && mCurrentVertexShader)
2125         {
2126             mActiveVertexGpuProgramParameters.reset();
2127             mCurrentVertexShader->unbind();
2128             mCurrentVertexShader = 0;
2129         }
2130         else if (gptype == GPT_GEOMETRY_PROGRAM && mCurrentGeometryShader)
2131         {
2132             mActiveGeometryGpuProgramParameters.reset();
2133             mCurrentGeometryShader->unbind();
2134             mCurrentGeometryShader = 0;
2135         }
2136         else if (gptype == GPT_FRAGMENT_PROGRAM && mCurrentFragmentShader)
2137         {
2138             mActiveFragmentGpuProgramParameters.reset();
2139             mCurrentFragmentShader->unbind();
2140             mCurrentFragmentShader = 0;
2141         }
2142         else if (gptype == GPT_HULL_PROGRAM && mCurrentHullShader)
2143         {
2144             mActiveTessellationHullGpuProgramParameters.reset();
2145             mCurrentHullShader->unbind();
2146             mCurrentHullShader = 0;
2147         }
2148         else if (gptype == GPT_DOMAIN_PROGRAM && mCurrentDomainShader)
2149         {
2150             mActiveTessellationDomainGpuProgramParameters.reset();
2151             mCurrentDomainShader->unbind();
2152             mCurrentDomainShader = 0;
2153         }
2154         else if (gptype == GPT_COMPUTE_PROGRAM && mCurrentComputeShader)
2155         {
2156             mActiveComputeGpuProgramParameters.reset();
2157             mCurrentComputeShader->unbind();
2158             mCurrentComputeShader = 0;
2159         }
2160         RenderSystem::unbindGpuProgram(gptype);
2161     }
2162 
bindGpuProgramParameters(GpuProgramType gptype,const GpuProgramParametersPtr & params,uint16 mask)2163     void GL3PlusRenderSystem::bindGpuProgramParameters(GpuProgramType gptype, const GpuProgramParametersPtr& params, uint16 mask)
2164     {
2165         if (mask & (uint16)GPV_GLOBAL)
2166         {
2167             // TODO We could maybe use GL_EXT_bindable_uniform here to produce Dx10-style
2168             // shared constant buffers, but GPU support seems fairly weak?
2169             // check the match to constant buffers & use rendersystem data hooks to store
2170             // for now, just copy
2171             params->_copySharedParams();
2172 
2173             switch (gptype)
2174             {
2175             case GPT_VERTEX_PROGRAM:
2176                 mActiveVertexGpuProgramParameters = params;
2177                 mCurrentVertexShader->bindSharedParameters(params, mask);
2178                 break;
2179             case GPT_FRAGMENT_PROGRAM:
2180                 mActiveFragmentGpuProgramParameters = params;
2181                 mCurrentFragmentShader->bindSharedParameters(params, mask);
2182                 break;
2183             case GPT_GEOMETRY_PROGRAM:
2184                 mActiveGeometryGpuProgramParameters = params;
2185                 mCurrentGeometryShader->bindSharedParameters(params, mask);
2186                 break;
2187             case GPT_HULL_PROGRAM:
2188                 mActiveTessellationHullGpuProgramParameters = params;
2189                 mCurrentHullShader->bindSharedParameters(params, mask);
2190                 break;
2191             case GPT_DOMAIN_PROGRAM:
2192                 mActiveTessellationDomainGpuProgramParameters = params;
2193                 mCurrentDomainShader->bindSharedParameters(params, mask);
2194                 break;
2195             case GPT_COMPUTE_PROGRAM:
2196                 mActiveComputeGpuProgramParameters = params;
2197                 mCurrentComputeShader->bindSharedParameters(params, mask);
2198                 break;
2199             default:
2200                 break;
2201             }
2202         }
2203 
2204         switch (gptype)
2205         {
2206         case GPT_VERTEX_PROGRAM:
2207             mActiveVertexGpuProgramParameters = params;
2208             mCurrentVertexShader->bindParameters(params, mask);
2209             break;
2210         case GPT_FRAGMENT_PROGRAM:
2211             mActiveFragmentGpuProgramParameters = params;
2212             mCurrentFragmentShader->bindParameters(params, mask);
2213             break;
2214         case GPT_GEOMETRY_PROGRAM:
2215             mActiveGeometryGpuProgramParameters = params;
2216             mCurrentGeometryShader->bindParameters(params, mask);
2217             break;
2218         case GPT_HULL_PROGRAM:
2219             mActiveTessellationHullGpuProgramParameters = params;
2220             mCurrentHullShader->bindParameters(params, mask);
2221             break;
2222         case GPT_DOMAIN_PROGRAM:
2223             mActiveTessellationDomainGpuProgramParameters = params;
2224             mCurrentDomainShader->bindParameters(params, mask);
2225             break;
2226         case GPT_COMPUTE_PROGRAM:
2227             mActiveComputeGpuProgramParameters = params;
2228             mCurrentComputeShader->bindParameters(params, mask);
2229             break;
2230         default:
2231             break;
2232         }
2233 
2234         // FIXME This needs to be moved somewhere texture specific.
2235         // Update image bindings for image load/store
2236         // static_cast<GL3PlusTextureManager*>(mTextureManager)->bindImages();
2237     }
2238 
bindGpuProgramPassIterationParameters(GpuProgramType gptype)2239     void GL3PlusRenderSystem::bindGpuProgramPassIterationParameters(GpuProgramType gptype)
2240     {
2241         switch (gptype)
2242         {
2243         case GPT_VERTEX_PROGRAM:
2244             mCurrentVertexShader->bindPassIterationParameters(mActiveVertexGpuProgramParameters);
2245             break;
2246         case GPT_FRAGMENT_PROGRAM:
2247             mCurrentFragmentShader->bindPassIterationParameters(mActiveFragmentGpuProgramParameters);
2248             break;
2249         case GPT_GEOMETRY_PROGRAM:
2250             mCurrentGeometryShader->bindPassIterationParameters(mActiveGeometryGpuProgramParameters);
2251             break;
2252         case GPT_HULL_PROGRAM:
2253             mCurrentHullShader->bindPassIterationParameters(mActiveTessellationHullGpuProgramParameters);
2254             break;
2255         case GPT_DOMAIN_PROGRAM:
2256             mCurrentDomainShader->bindPassIterationParameters(mActiveTessellationDomainGpuProgramParameters);
2257             break;
2258         case GPT_COMPUTE_PROGRAM:
2259             mCurrentComputeShader->bindPassIterationParameters(mActiveComputeGpuProgramParameters);
2260             break;
2261         default:
2262             break;
2263         }
2264     }
2265 
registerThread()2266     void GL3PlusRenderSystem::registerThread()
2267     {
2268         OGRE_LOCK_MUTEX(mThreadInitMutex);
2269         // This is only valid once we've created the main context
2270         if (!mMainContext)
2271         {
2272             OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
2273                         "Cannot register a background thread before the main context "
2274                         "has been created.",
2275                         "GL3PlusRenderSystem::registerThread");
2276         }
2277 
2278         // Create a new context for this thread. Cloning from the main context
2279         // will ensure that resources are shared with the main context
2280         // We want a separate context so that we can safely create GL
2281         // objects in parallel with the main thread
2282         GL3PlusContext* newContext = mMainContext->clone();
2283         mBackgroundContextList.push_back(newContext);
2284 
2285         // Bind this new context to this thread.
2286         newContext->setCurrent();
2287 
2288         _oneTimeContextInitialization();
2289         newContext->setInitialized();
2290     }
2291 
unregisterThread()2292     void GL3PlusRenderSystem::unregisterThread()
2293     {
2294         // nothing to do here?
2295         // Don't need to worry about active context, just make sure we delete
2296         // on shutdown.
2297     }
2298 
preExtraThreadsStarted()2299     void GL3PlusRenderSystem::preExtraThreadsStarted()
2300     {
2301         OGRE_LOCK_MUTEX(mThreadInitMutex);
2302         // free context, we'll need this to share lists
2303         if (mCurrentContext)
2304             mCurrentContext->endCurrent();
2305     }
2306 
postExtraThreadsStarted()2307     void GL3PlusRenderSystem::postExtraThreadsStarted()
2308     {
2309         OGRE_LOCK_MUTEX(mThreadInitMutex);
2310         // reacquire context
2311         if (mCurrentContext)
2312             mCurrentContext->setCurrent();
2313     }
2314 
getDisplayMonitorCount() const2315     unsigned int GL3PlusRenderSystem::getDisplayMonitorCount() const
2316     {
2317         return mGLSupport->getDisplayMonitorCount();
2318     }
2319 
2320 
beginProfileEvent(const String & eventName)2321     void GL3PlusRenderSystem::beginProfileEvent( const String &eventName )
2322     {
2323         if (getCapabilities()->hasCapability(RSC_DEBUG))
2324             OGRE_CHECK_GL_ERROR(glPushDebugGroup(GL_DEBUG_SOURCE_THIRD_PARTY, 0, static_cast<GLint>(eventName.length()), eventName.c_str()));
2325     }
2326 
2327 
endProfileEvent(void)2328     void GL3PlusRenderSystem::endProfileEvent( void )
2329     {
2330         if (getCapabilities()->hasCapability(RSC_DEBUG))
2331             OGRE_CHECK_GL_ERROR(glPopDebugGroup());
2332     }
2333 
2334 
markProfileEvent(const String & eventName)2335     void GL3PlusRenderSystem::markProfileEvent( const String &eventName )
2336     {
2337         if ( eventName.empty() )
2338             return;
2339 
2340         if (getCapabilities()->hasCapability(RSC_DEBUG))
2341             glDebugMessageInsert(GL_DEBUG_SOURCE_THIRD_PARTY,
2342                                  GL_DEBUG_TYPE_PERFORMANCE,
2343                                  0,
2344                                  GL_DEBUG_SEVERITY_LOW,
2345                                  static_cast<GLint>(eventName.length()),
2346                                  eventName.c_str());
2347     }
2348 
bindVertexElementToGpu(const VertexElement & elem,const HardwareVertexBufferSharedPtr & vertexBuffer,const size_t vertexStart)2349     void GL3PlusRenderSystem::bindVertexElementToGpu(const VertexElement& elem,
2350                                                      const HardwareVertexBufferSharedPtr& vertexBuffer,
2351                                                      const size_t vertexStart)
2352     {
2353         VertexElementSemantic sem = elem.getSemantic();
2354         unsigned short elemIndex = elem.getIndex();
2355 
2356         GLuint attrib = (GLuint)GLSLProgramCommon::getFixedAttributeIndex(sem, elemIndex);
2357 
2358         const GL3PlusHardwareVertexBuffer* hwGlBuffer = static_cast<const GL3PlusHardwareVertexBuffer*>(vertexBuffer.get());
2359         mStateCacheManager->bindGLBuffer(GL_ARRAY_BUFFER, hwGlBuffer->getGLBufferId());
2360         void* pBufferData = GL_BUFFER_OFFSET(elem.getOffset() + vertexStart * vertexBuffer->getVertexSize());
2361 
2362         if (hwGlBuffer->isInstanceData())
2363         {
2364             OGRE_CHECK_GL_ERROR(glVertexAttribDivisor(attrib, hwGlBuffer->getInstanceDataStepRate()));
2365         }
2366 
2367         unsigned short typeCount = VertexElement::getTypeCount(elem.getType());
2368         GLboolean normalised = GL_FALSE;
2369         switch(elem.getType())
2370         {
2371         case VET_COLOUR:
2372         case VET_COLOUR_ABGR:
2373         case VET_COLOUR_ARGB:
2374             // Because GL takes these as a sequence of single unsigned bytes, count needs to be 4
2375             // VertexElement::getTypeCount treats them as 1 (RGBA)
2376             // Also need to normalise the fixed-point data
2377             typeCount = 4;
2378             normalised = GL_TRUE;
2379             break;
2380         case VET_UBYTE4_NORM:
2381         case VET_SHORT2_NORM:
2382         case VET_USHORT2_NORM:
2383         case VET_SHORT4_NORM:
2384         case VET_USHORT4_NORM:
2385             normalised = GL_TRUE;
2386             break;
2387         default:
2388             break;
2389         };
2390 
2391         switch(elem.getBaseType(elem.getType()))
2392         {
2393         default:
2394         case VET_FLOAT1:
2395             OGRE_CHECK_GL_ERROR(glVertexAttribPointer(attrib,
2396                                                       typeCount,
2397                                                       GL3PlusHardwareBufferManager::getGLType(elem.getType()),
2398                                                       normalised,
2399                                                       static_cast<GLsizei>(vertexBuffer->getVertexSize()),
2400                                                       pBufferData));
2401             break;
2402         case VET_DOUBLE1:
2403             OGRE_CHECK_GL_ERROR(glVertexAttribLPointer(attrib,
2404                                                        typeCount,
2405                                                        GL3PlusHardwareBufferManager::getGLType(elem.getType()),
2406                                                        static_cast<GLsizei>(vertexBuffer->getVertexSize()),
2407                                                        pBufferData));
2408             break;
2409         }
2410 
2411         // If this attribute hasn't been enabled, do so and keep a record of it.
2412         OGRE_CHECK_GL_ERROR(glEnableVertexAttribArray(attrib));
2413     }
2414 #if OGRE_NO_QUAD_BUFFER_STEREO == 0
setDrawBuffer(ColourBufferType colourBuffer)2415 	bool GL3PlusRenderSystem::setDrawBuffer(ColourBufferType colourBuffer)
2416 	{
2417 		bool result = true;
2418 
2419 		switch (colourBuffer)
2420 		{
2421             case CBT_BACK:
2422                 OGRE_CHECK_GL_ERROR(glDrawBuffer(GL_BACK));
2423                 break;
2424             case CBT_BACK_LEFT:
2425                 OGRE_CHECK_GL_ERROR(glDrawBuffer(GL_BACK_LEFT));
2426                 break;
2427             case CBT_BACK_RIGHT:
2428                 OGRE_CHECK_GL_ERROR(glDrawBuffer(GL_BACK_RIGHT));
2429 //                break;
2430             default:
2431                 result = false;
2432 		}
2433 
2434 		return result;
2435 	}
2436 #endif
2437 
_copyContentsToMemory(Viewport * vp,const Box & src,const PixelBox & dst,RenderWindow::FrameBuffer buffer)2438     void GL3PlusRenderSystem::_copyContentsToMemory(Viewport* vp, const Box& src, const PixelBox &dst, RenderWindow::FrameBuffer buffer)
2439     {
2440         GLenum format = GL3PlusPixelUtil::getGLOriginFormat(dst.format);
2441         GLenum type = GL3PlusPixelUtil::getGLOriginDataType(dst.format);
2442 
2443         if ((format == GL_NONE) || (type == 0))
2444         {
2445             OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Unsupported format", "GL3PlusRenderSystem::_copyContentsToMemory");
2446         }
2447 
2448         // Switch context if different from current one
2449         _setViewport(vp);
2450 
2451         if(dst.getWidth() != dst.rowPitch)
2452             glPixelStorei(GL_PACK_ROW_LENGTH, dst.rowPitch);
2453         // Must change the packing to ensure no overruns!
2454         glPixelStorei(GL_PACK_ALIGNMENT, 1);
2455 
2456         uint32_t height = vp->getTarget()->getHeight();
2457 
2458         glReadBuffer((buffer == RenderWindow::FB_FRONT)? GL_FRONT : GL_BACK);
2459         glReadPixels((GLint)src.left, (GLint)(height - src.bottom),
2460                      (GLsizei)dst.getWidth(), (GLsizei)dst.getHeight(),
2461                      format, type, dst.getTopLeftFrontPixelPtr());
2462 
2463         // restore default alignment
2464         glPixelStorei(GL_PACK_ALIGNMENT, 4);
2465         glPixelStorei(GL_PACK_ROW_LENGTH, 0);
2466 
2467         PixelUtil::bulkPixelVerticalFlip(dst);
2468     }
2469 
initialiseExtensions(void)2470     void GL3PlusRenderSystem::initialiseExtensions(void)
2471     {
2472         // get driver version.
2473         // this is the recommended way for GL3 see: https://www.opengl.org/wiki/Get_Context_Info
2474         glGetIntegerv(GL_MAJOR_VERSION, &mDriverVersion.major);
2475         glGetIntegerv(GL_MINOR_VERSION, &mDriverVersion.minor);
2476 
2477         LogManager::getSingleton().logMessage("GL_VERSION = " + mDriverVersion.toString());
2478 
2479         // Get vendor
2480         const GLubyte* pcVendor = glGetString(GL_VENDOR);
2481         String tmpStr = (const char*)pcVendor;
2482         LogManager::getSingleton().logMessage("GL_VENDOR = " + tmpStr);
2483         mVendor = tmpStr.substr(0, tmpStr.find(' '));
2484 
2485         // Get renderer
2486         const GLubyte* pcRenderer = glGetString(GL_RENDERER);
2487         tmpStr = (const char*)pcRenderer;
2488         LogManager::getSingleton().logMessage("GL_RENDERER = " + tmpStr);
2489 
2490         // Set extension list
2491         Log::Stream log = LogManager::getSingleton().stream();
2492         String str;
2493 
2494         GLint numExt;
2495         glGetIntegerv(GL_NUM_EXTENSIONS, &numExt);
2496 
2497         log << "GL_EXTENSIONS = ";
2498         for(int i = 0; i < numExt; i++)
2499         {
2500             const GLubyte* pcExt = glGetStringi(GL_EXTENSIONS, i);
2501             assert(pcExt && "Problems getting GL extension string using glGetString");
2502             str = String((const char*)pcExt);
2503             log << str << " ";
2504             mExtensionList.insert(str);
2505         }
2506     }
2507 }
2508