1 /*!
2 	@file
3 	@author		Albert Semenov
4 	@date		04/2008
5 */
6 
7 #include "MyGUI_OgreDataManager.h"
8 #include "MyGUI_OgreRenderManager.h"
9 #include "MyGUI_OgreTexture.h"
10 #include "MyGUI_OgreVertexBuffer.h"
11 #include "MyGUI_LogManager.h"
12 #include "MyGUI_OgreDiagnostic.h"
13 #include "MyGUI_Timer.h"
14 #include "MyGUI_Gui.h"
15 
16 namespace MyGUI
17 {
18 
getInstance()19 	OgreRenderManager& OgreRenderManager::getInstance()
20 	{
21 		return *getInstancePtr();
22 	}
getInstancePtr()23 	OgreRenderManager* OgreRenderManager::getInstancePtr()
24 	{
25 		return static_cast<OgreRenderManager*>(RenderManager::getInstancePtr());
26 	}
27 
OgreRenderManager()28 	OgreRenderManager::OgreRenderManager() :
29 		mUpdate(false),
30 		mSceneManager(nullptr),
31 		mWindow(nullptr),
32 		mActiveViewport(0),
33 		mRenderSystem(nullptr),
34 		mIsInitialise(false),
35 		mManualRender(false),
36 		mCountBatch(0)
37 	{
38 	}
39 
initialise(Ogre::RenderWindow * _window,Ogre::SceneManager * _scene)40 	void OgreRenderManager::initialise(Ogre::RenderWindow* _window, Ogre::SceneManager* _scene)
41 	{
42 		MYGUI_PLATFORM_ASSERT(!mIsInitialise, getClassTypeName() << " initialised twice");
43 		MYGUI_PLATFORM_LOG(Info, "* Initialise: " << getClassTypeName());
44 
45 		mColorBlendMode.blendType = Ogre::LBT_COLOUR;
46 		mColorBlendMode.source1 = Ogre::LBS_TEXTURE;
47 		mColorBlendMode.source2 = Ogre::LBS_DIFFUSE;
48 		mColorBlendMode.operation = Ogre::LBX_MODULATE;
49 
50 		mAlphaBlendMode.blendType = Ogre::LBT_ALPHA;
51 		mAlphaBlendMode.source1 = Ogre::LBS_TEXTURE;
52 		mAlphaBlendMode.source2 = Ogre::LBS_DIFFUSE;
53 		mAlphaBlendMode.operation = Ogre::LBX_MODULATE;
54 
55 		mTextureAddressMode.u = Ogre::TextureUnitState::TAM_CLAMP;
56 		mTextureAddressMode.v = Ogre::TextureUnitState::TAM_CLAMP;
57 		mTextureAddressMode.w = Ogre::TextureUnitState::TAM_CLAMP;
58 
59 		mSceneManager = nullptr;
60 		mWindow = nullptr;
61 		mUpdate = false;
62 		mRenderSystem = nullptr;
63 		mActiveViewport = 0;
64 
65 		Ogre::Root* root = Ogre::Root::getSingletonPtr();
66 		if (root != nullptr)
67 			setRenderSystem(root->getRenderSystem());
68 		setRenderWindow(_window);
69 		setSceneManager(_scene);
70 
71 		MYGUI_PLATFORM_LOG(Info, getClassTypeName() << " successfully initialized");
72 		mIsInitialise = true;
73 	}
74 
shutdown()75 	void OgreRenderManager::shutdown()
76 	{
77 		MYGUI_PLATFORM_ASSERT(mIsInitialise, getClassTypeName() << " is not initialised");
78 		MYGUI_PLATFORM_LOG(Info, "* Shutdown: " << getClassTypeName());
79 
80 		destroyAllResources();
81 
82 		setSceneManager(nullptr);
83 		setRenderWindow(nullptr);
84 		setRenderSystem(nullptr);
85 
86 		MYGUI_PLATFORM_LOG(Info, getClassTypeName() << " successfully shutdown");
87 		mIsInitialise = false;
88 	}
89 
setRenderSystem(Ogre::RenderSystem * _render)90 	void OgreRenderManager::setRenderSystem(Ogre::RenderSystem* _render)
91 	{
92 		// отписываемся
93 		if (mRenderSystem != nullptr)
94 		{
95 			mRenderSystem->removeListener(this);
96 			mRenderSystem = nullptr;
97 		}
98 
99 		mRenderSystem = _render;
100 
101 		// подписываемся на рендер евент
102 		if (mRenderSystem != nullptr)
103 		{
104 			mRenderSystem->addListener(this);
105 
106 			// формат цвета в вершинах
107 			Ogre::VertexElementType vertex_type = mRenderSystem->getColourVertexElementType();
108 			if (vertex_type == Ogre::VET_COLOUR_ARGB)
109 				mVertexFormat = VertexColourType::ColourARGB;
110 			else if (vertex_type == Ogre::VET_COLOUR_ABGR)
111 				mVertexFormat = VertexColourType::ColourABGR;
112 
113 			updateRenderInfo();
114 
115 			if (!mRenderSystem->getCapabilities()->hasCapability(Ogre::RSC_FIXED_FUNCTION))
116 			{
117 				std::string shaderLanguage;
118 				if (Ogre::HighLevelGpuProgramManager::getSingleton().isLanguageSupported("glsl"))
119 					shaderLanguage = "glsl";
120 				else if (Ogre::HighLevelGpuProgramManager::getSingleton().isLanguageSupported("glsles"))
121 					shaderLanguage = "glsles";
122 				else if (Ogre::HighLevelGpuProgramManager::getSingleton().isLanguageSupported("hlsl"))
123 					shaderLanguage = "hlsl";
124 				else
125 					MYGUI_EXCEPT("No supported shader was found. Only glsl, glsles and hlsl are implemented so far.")
126 
127 				mVertexProgram = Ogre::HighLevelGpuProgramManager::getSingleton().createProgram(
128 					"MyGUI_VP." + shaderLanguage,
129 					OgreDataManager::getInstance().getGroup(),
130 					shaderLanguage,
131 					Ogre::GPT_VERTEX_PROGRAM);
132 				mVertexProgram->setSourceFile("MyGUI_VP." + shaderLanguage);
133 				if (shaderLanguage == "hlsl")
134 				{
135 					mVertexProgram->setParameter("target", "vs_4_0");
136 					mVertexProgram->setParameter("entry_point", "main");
137 				}
138 				mVertexProgram->load();
139 
140 				mFragmentProgram = Ogre::HighLevelGpuProgramManager::getSingleton().createProgram(
141 					"MyGUI_FP." + shaderLanguage,
142 					OgreDataManager::getInstance().getGroup(),
143 					shaderLanguage,
144 					Ogre::GPT_FRAGMENT_PROGRAM);
145 				mFragmentProgram->setSourceFile("MyGUI_FP." + shaderLanguage);
146 				if (shaderLanguage == "hlsl")
147 				{
148 					mFragmentProgram->setParameter("target", "ps_4_0");
149 					mFragmentProgram->setParameter("entry_point", "main");
150 				}
151 				mFragmentProgram->load();
152 			}
153 		}
154 	}
155 
getRenderSystem()156 	Ogre::RenderSystem* OgreRenderManager::getRenderSystem()
157 	{
158 		return mRenderSystem;
159 	}
160 
setRenderWindow(Ogre::RenderWindow * _window)161 	void OgreRenderManager::setRenderWindow(Ogre::RenderWindow* _window)
162 	{
163 		mWindow = _window;
164 
165 		if (mWindow != nullptr)
166 		{
167 			if (mWindow->getNumViewports() <= mActiveViewport &&
168 				!mWindow->getViewport(mActiveViewport)->getOverlaysEnabled())
169 			{
170 				MYGUI_PLATFORM_LOG(Warning, "Overlays are disabled. MyGUI won't render in selected viewport.");
171 			}
172 
173 			windowResized(mWindow);
174 		}
175 	}
176 
setSceneManager(Ogre::SceneManager * _scene)177 	void OgreRenderManager::setSceneManager(Ogre::SceneManager* _scene)
178 	{
179 		if (nullptr != mSceneManager)
180 		{
181 			mSceneManager->removeRenderQueueListener(this);
182 			mSceneManager = nullptr;
183 		}
184 
185 		mSceneManager = _scene;
186 
187 		if (nullptr != mSceneManager)
188 		{
189 			mSceneManager->addRenderQueueListener(this);
190 		}
191 	}
192 
setActiveViewport(unsigned short _num)193 	void OgreRenderManager::setActiveViewport(unsigned short _num)
194 	{
195 		mActiveViewport = _num;
196 
197 		if (mWindow != nullptr)
198 		{
199 			if (mWindow->getNumViewports() <= mActiveViewport)
200 			{
201 				MYGUI_PLATFORM_LOG(Error, "Invalid active viewport index selected. There is no viewport with given index.");
202 			}
203 
204 			// рассылка обновлений
205 			windowResized(mWindow);
206 		}
207 	}
208 
renderQueueStarted(Ogre::uint8 queueGroupId,const Ogre::String & invocation,bool & skipThisInvocation)209 	void OgreRenderManager::renderQueueStarted(Ogre::uint8 queueGroupId, const Ogre::String& invocation, bool& skipThisInvocation)
210 	{
211 		Gui* gui = Gui::getInstancePtr();
212 		if (gui == nullptr)
213 			return;
214 
215 		if (Ogre::RENDER_QUEUE_OVERLAY != queueGroupId)
216 			return;
217 
218 		Ogre::Viewport* viewport = mSceneManager->getCurrentViewport();
219 		if (nullptr == viewport
220 			|| !viewport->getOverlaysEnabled())
221 			return;
222 
223 		if (mWindow->getNumViewports() <= mActiveViewport
224 			|| viewport != mWindow->getViewport(mActiveViewport))
225 			return;
226 
227 		mCountBatch = 0;
228 
229 		static Timer timer;
230 		static unsigned long last_time = timer.getMilliseconds();
231 		unsigned long now_time = timer.getMilliseconds();
232 		unsigned long time = now_time - last_time;
233 
234 		onFrameEvent((float)((double)(time) / (double)1000));
235 
236 		last_time = now_time;
237 
238 		begin();
239 		onRenderToTarget(this, mUpdate);
240 		//end();
241 
242 		// сбрасываем флаг
243 		mUpdate = false;
244 	}
245 
renderQueueEnded(Ogre::uint8 queueGroupId,const Ogre::String & invocation,bool & repeatThisInvocation)246 	void OgreRenderManager::renderQueueEnded(Ogre::uint8 queueGroupId, const Ogre::String& invocation, bool& repeatThisInvocation)
247 	{
248 	}
249 
eventOccurred(const Ogre::String & eventName,const Ogre::NameValuePairList * parameters)250 	void OgreRenderManager::eventOccurred(const Ogre::String& eventName, const Ogre::NameValuePairList* parameters)
251 	{
252 		if (eventName == "DeviceLost")
253 		{
254 		}
255 		else if (eventName == "DeviceRestored")
256 		{
257 			// обновить всех
258 			mUpdate = true;
259 		}
260 	}
261 
createVertexBuffer()262 	IVertexBuffer* OgreRenderManager::createVertexBuffer()
263 	{
264 		return new OgreVertexBuffer();
265 	}
266 
destroyVertexBuffer(IVertexBuffer * _buffer)267 	void OgreRenderManager::destroyVertexBuffer(IVertexBuffer* _buffer)
268 	{
269 		delete _buffer;
270 	}
271 
windowResized(Ogre::RenderWindow * _window)272 	void OgreRenderManager::windowResized(Ogre::RenderWindow* _window)
273 	{
274 		if (_window->getNumViewports() > mActiveViewport)
275 		{
276 			Ogre::Viewport* port = _window->getViewport(mActiveViewport);
277 #if OGRE_VERSION >= MYGUI_DEFINE_VERSION(1, 7, 0) && OGRE_NO_VIEWPORT_ORIENTATIONMODE == 0
278 			Ogre::OrientationMode orient = port->getOrientationMode();
279 			if (orient == Ogre::OR_DEGREE_90 || orient == Ogre::OR_DEGREE_270)
280 				setViewSize(port->getActualHeight(), port->getActualWidth());
281 			else
282 				setViewSize(port->getActualWidth(), port->getActualHeight());
283 #else
284 			setViewSize(port->getActualWidth(), port->getActualHeight());
285 #endif
286 		}
287 	}
288 
updateRenderInfo()289 	void OgreRenderManager::updateRenderInfo()
290 	{
291 		if (mRenderSystem != nullptr)
292 		{
293 			if (mRenderSystem->getName() == "Direct3D11 Rendering Subsystem") // special case, it's not working with the value returned by the rendersystem
294 			{
295 				mInfo.maximumDepth = 0.0f;
296 			}
297 			else
298 			{
299 				mInfo.maximumDepth = mRenderSystem->getMaximumDepthInputValue();
300 			}
301 			mInfo.hOffset = mRenderSystem->getHorizontalTexelOffset() / float(mViewSize.width);
302 			mInfo.vOffset = mRenderSystem->getVerticalTexelOffset() / float(mViewSize.height);
303 			mInfo.aspectCoef = float(mViewSize.height) / float(mViewSize.width);
304 			mInfo.pixScaleX = 1.0f / float(mViewSize.width);
305 			mInfo.pixScaleY = 1.0f / float(mViewSize.height);
306 		}
307 	}
308 
doRender(IVertexBuffer * _buffer,ITexture * _texture,size_t _count)309 	void OgreRenderManager::doRender(IVertexBuffer* _buffer, ITexture* _texture, size_t _count)
310 	{
311 		if (_texture)
312 		{
313 			OgreTexture* texture = static_cast<OgreTexture*>(_texture);
314 			Ogre::TexturePtr texture_ptr = texture->getOgreTexture();
315 			if (!texture_ptr.isNull())
316 			{
317 				mRenderSystem->_setTexture(0, true, texture_ptr);
318 				mRenderSystem->_setTextureUnitFiltering(0, Ogre::FO_LINEAR, Ogre::FO_LINEAR, Ogre::FO_NONE);
319 			}
320 		}
321 
322 		OgreVertexBuffer* buffer = static_cast<OgreVertexBuffer*>(_buffer);
323 		Ogre::RenderOperation* operation = buffer->getRenderOperation();
324 		operation->vertexData->vertexCount = _count;
325 
326 		mRenderSystem->_render(*operation);
327 
328 		++ mCountBatch;
329 	}
330 
begin()331 	void OgreRenderManager::begin()
332 	{
333 		// set-up matrices
334 		mRenderSystem->_setWorldMatrix(Ogre::Matrix4::IDENTITY);
335 		mRenderSystem->_setViewMatrix(Ogre::Matrix4::IDENTITY);
336 
337 #if OGRE_VERSION >= MYGUI_DEFINE_VERSION(1, 7, 0) && OGRE_NO_VIEWPORT_ORIENTATIONMODE == 0
338 		Ogre::OrientationMode orient = mWindow->getViewport(mActiveViewport)->getOrientationMode();
339 		mRenderSystem->_setProjectionMatrix(Ogre::Matrix4::IDENTITY * Ogre::Quaternion(Ogre::Degree(orient * 90.f), Ogre::Vector3::UNIT_Z));
340 #else
341 		mRenderSystem->_setProjectionMatrix(Ogre::Matrix4::IDENTITY);
342 #endif
343 
344 		// initialise render settings
345 		mRenderSystem->setLightingEnabled(false);
346 		mRenderSystem->_setDepthBufferParams(false, false);
347 		mRenderSystem->_setDepthBias(0, 0);
348 		mRenderSystem->_setCullingMode(Ogre::CULL_NONE);
349 		mRenderSystem->_setFog(Ogre::FOG_NONE);
350 		mRenderSystem->_setColourBufferWriteEnabled(true, true, true, true);
351 		if (mRenderSystem->getCapabilities()->hasCapability(Ogre::RSC_FIXED_FUNCTION))
352 		{
353 			mRenderSystem->unbindGpuProgram(Ogre::GPT_FRAGMENT_PROGRAM);
354 			mRenderSystem->unbindGpuProgram(Ogre::GPT_VERTEX_PROGRAM);
355 		}
356 		else
357 		{
358 			mRenderSystem->bindGpuProgram(mVertexProgram->_getBindingDelegate());
359 			mRenderSystem->bindGpuProgram(mFragmentProgram->_getBindingDelegate());
360 
361 			Ogre::GpuProgramParametersSharedPtr params = mVertexProgram->getDefaultParameters();
362 			params->setNamedConstant("YFlipScale", 1.0f);
363 			mRenderSystem->bindGpuProgramParameters(Ogre::GPT_VERTEX_PROGRAM, params, Ogre::GPV_ALL);
364 		}
365 		mRenderSystem->setShadingType(Ogre::SO_GOURAUD);
366 
367 		// initialise texture settings
368 		mRenderSystem->_setTextureCoordCalculation(0, Ogre::TEXCALC_NONE);
369 		mRenderSystem->_setTextureCoordSet(0, 0);
370 		mRenderSystem->_setTextureUnitFiltering(0, Ogre::FO_LINEAR, Ogre::FO_LINEAR, Ogre::FO_NONE);
371 		mRenderSystem->_setTextureAddressingMode(0, mTextureAddressMode);
372 		mRenderSystem->_setTextureMatrix(0, Ogre::Matrix4::IDENTITY);
373 #if OGRE_VERSION < MYGUI_DEFINE_VERSION(1, 6, 0)
374 		mRenderSystem->_setAlphaRejectSettings(Ogre::CMPF_ALWAYS_PASS, 0);
375 #else
376 		mRenderSystem->_setAlphaRejectSettings(Ogre::CMPF_ALWAYS_PASS, 0, false);
377 #endif
378 		mRenderSystem->_setTextureBlendMode(0, mColorBlendMode);
379 		mRenderSystem->_setTextureBlendMode(0, mAlphaBlendMode);
380 		mRenderSystem->_disableTextureUnitsFrom(1);
381 
382 		// enable alpha blending
383 		mRenderSystem->_setSceneBlending(Ogre::SBF_SOURCE_ALPHA, Ogre::SBF_ONE_MINUS_SOURCE_ALPHA);
384 
385 		// always use wireframe
386 		// TODO: add option to enable wireframe mode in platform
387 		mRenderSystem->_setPolygonMode(Ogre::PM_SOLID);
388 	}
389 
end()390 	void OgreRenderManager::end()
391 	{
392 	}
393 
createTexture(const std::string & _name)394 	ITexture* OgreRenderManager::createTexture(const std::string& _name)
395 	{
396 		MapTexture::const_iterator item = mTextures.find(_name);
397 		MYGUI_PLATFORM_ASSERT(item == mTextures.end(), "Texture '" << _name << "' already exist");
398 
399 		OgreTexture* texture = new OgreTexture(_name, OgreDataManager::getInstance().getGroup());
400 		mTextures[_name] = texture;
401 		return texture;
402 	}
403 
destroyTexture(ITexture * _texture)404 	void OgreRenderManager::destroyTexture(ITexture* _texture)
405 	{
406 		if (_texture == nullptr) return;
407 
408 		MapTexture::iterator item = mTextures.find(_texture->getName());
409 		MYGUI_PLATFORM_ASSERT(item != mTextures.end(), "Texture '" << _texture->getName() << "' not found");
410 
411 		mTextures.erase(item);
412 		delete _texture;
413 	}
414 
getTexture(const std::string & _name)415 	ITexture* OgreRenderManager::getTexture(const std::string& _name)
416 	{
417 		MapTexture::const_iterator item = mTextures.find(_name);
418 		if (item == mTextures.end())
419 		{
420 			Ogre::TexturePtr texture = (Ogre::TexturePtr)Ogre::TextureManager::getSingleton().getByName(_name);
421 			if (!texture.isNull())
422 			{
423 				ITexture* result = createTexture(_name);
424 				static_cast<OgreTexture*>(result)->setOgreTexture(texture);
425 				return result;
426 			}
427 			return nullptr;
428 		}
429 		return item->second;
430 	}
431 
isFormatSupported(PixelFormat _format,TextureUsage _usage)432 	bool OgreRenderManager::isFormatSupported(PixelFormat _format, TextureUsage _usage)
433 	{
434 		return Ogre::TextureManager::getSingleton().isFormatSupported(
435 			Ogre::TEX_TYPE_2D,
436 			OgreTexture::convertFormat(_format),
437 			OgreTexture::convertUsage(_usage));
438 	}
439 
destroyAllResources()440 	void OgreRenderManager::destroyAllResources()
441 	{
442 		for (MapTexture::const_iterator item = mTextures.begin(); item != mTextures.end(); ++item)
443 		{
444 			delete item->second;
445 		}
446 		mTextures.clear();
447 	}
448 
449 #if MYGUI_DEBUG_MODE == 1
checkTexture(ITexture * _texture)450 	bool OgreRenderManager::checkTexture(ITexture* _texture)
451 	{
452 		for (MapTexture::const_iterator item = mTextures.begin(); item != mTextures.end(); ++item)
453 		{
454 			if (item->second == _texture)
455 				return true;
456 		}
457 		return false;
458 	}
459 #endif
460 
getViewSize() const461 	const IntSize& OgreRenderManager::getViewSize() const
462 	{
463 		return mViewSize;
464 	}
465 
getVertexFormat()466 	VertexColourType OgreRenderManager::getVertexFormat()
467 	{
468 		return mVertexFormat;
469 	}
470 
getInfo()471 	const RenderTargetInfo& OgreRenderManager::getInfo()
472 	{
473 		return mInfo;
474 	}
475 
getActiveViewport()476 	size_t OgreRenderManager::getActiveViewport()
477 	{
478 		return mActiveViewport;
479 	}
480 
getRenderWindow()481 	Ogre::RenderWindow* OgreRenderManager::getRenderWindow()
482 	{
483 		return mWindow;
484 	}
485 
getManualRender()486 	bool OgreRenderManager::getManualRender()
487 	{
488 		return mManualRender;
489 	}
490 
setManualRender(bool _value)491 	void OgreRenderManager::setManualRender(bool _value)
492 	{
493 		mManualRender = _value;
494 	}
495 
getBatchCount() const496 	size_t OgreRenderManager::getBatchCount() const
497 	{
498 		return mCountBatch;
499 	}
500 
setViewSize(int _width,int _height)501 	void OgreRenderManager::setViewSize(int _width, int _height)
502 	{
503 		mViewSize.set(_width, _height);
504 		mUpdate = true;
505 		updateRenderInfo();
506 		onResizeView(mViewSize);
507 	}
508 
doRenderRtt(IVertexBuffer * _buffer,ITexture * _texture,size_t _count,bool flipY)509 	void OgreRenderManager::doRenderRtt(IVertexBuffer* _buffer, ITexture* _texture, size_t _count, bool flipY)
510 	{
511 		if (flipY && !mRenderSystem->getCapabilities()->hasCapability(Ogre::RSC_FIXED_FUNCTION))
512 		{
513 			Ogre::GpuProgramParametersSharedPtr params = mVertexProgram->getDefaultParameters();;
514 			params->setNamedConstant("YFlipScale", -1.0f);
515 			mRenderSystem->bindGpuProgramParameters(Ogre::GPT_VERTEX_PROGRAM,
516 				params, Ogre::GPV_ALL);
517 		}
518 
519 		doRender(_buffer, _texture, _count);
520 
521 		if (flipY && !mRenderSystem->getCapabilities()->hasCapability(Ogre::RSC_FIXED_FUNCTION))
522 		{
523 			Ogre::GpuProgramParametersSharedPtr params = mVertexProgram->getDefaultParameters();;
524 			params->setNamedConstant("YFlipScale", 1.0f);
525 			mRenderSystem->bindGpuProgramParameters(Ogre::GPT_VERTEX_PROGRAM,
526 				params, Ogre::GPV_ALL);
527 		}
528 	}
529 
530 } // namespace MyGUI
531