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