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-2013 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 #include "OgreD3D11RenderWindow.h"
29 #include "OgreException.h"
30 #include "OgreD3D11RenderSystem.h"
31 #include "OgreWindowEventUtilities.h"
32 #include "OgreD3D11Driver.h"
33 #include "OgreRoot.h"
34 #include "OgreD3D11DepthBuffer.h"
35 #include "OgreD3D11Texture.h"
36 
37 namespace Ogre
38 {
39 	//---------------------------------------------------------------------
40 	// class D3D11RenderWindowBase
41 	//---------------------------------------------------------------------
42 #pragma region D3D11RenderWindowBase
D3D11RenderWindowBase(D3D11Device & device,IDXGIFactoryN * pDXGIFactory)43 	D3D11RenderWindowBase::D3D11RenderWindowBase(D3D11Device & device, IDXGIFactoryN*	pDXGIFactory)
44 		: mDevice(device)
45 		, mpDXGIFactory(pDXGIFactory)
46 	{
47 		mIsFullScreen = false;
48 		mIsExternal = false;
49 		mActive = false;
50 		mSizing = false;
51 		mClosed = false;
52 		mHidden = false;
53 		mDisplayFrequency = 0;
54 		mRenderTargetView = 0;
55 		mDepthStencilView = 0;
56 		mpBackBuffer = 0;
57 	}
58     //---------------------------------------------------------------------
~D3D11RenderWindowBase()59     D3D11RenderWindowBase::~D3D11RenderWindowBase()
60     {
61         destroy();
62     }
63 	//---------------------------------------------------------------------
_checkMultiSampleQuality(UINT SampleCount,UINT * outQuality,DXGI_FORMAT format)64 	bool D3D11RenderWindowBase::_checkMultiSampleQuality(UINT SampleCount, UINT *outQuality, DXGI_FORMAT format)
65 	{
66 		//TODO :CheckMultisampleQualityLevels
67 		if (SUCCEEDED(mDevice->CheckMultisampleQualityLevels(//CheckDeviceMultiSampleType(
68 			format,
69 			SampleCount,
70 			outQuality)))
71 		{
72 			return true;
73 		}
74 		else
75 			return false;
76 	}
77 	//---------------------------------------------------------------------
create(const String & name,unsigned int width,unsigned int height,bool fullScreen,const NameValuePairList * miscParams)78 	void D3D11RenderWindowBase::create(const String& name, unsigned int width, unsigned int height,
79 		bool fullScreen, const NameValuePairList *miscParams)
80 	{
81 		mFSAAType.Count = 1;
82 		mFSAAType.Quality = 0;
83 		mFSAA = 0;
84 		mFSAAHint = "";
85 		mVSync = false;
86 		mVSyncInterval = 1;
87 
88 		unsigned int colourDepth = 32;
89 		bool depthBuffer = true;
90 
91 		if(miscParams)
92 		{
93 			// Get variable-length params
94 			NameValuePairList::const_iterator opt;
95 			// vsync	[parseBool]
96 			opt = miscParams->find("vsync");
97 			if(opt != miscParams->end())
98 				mVSync = StringConverter::parseBool(opt->second);
99 			// vsyncInterval	[parseUnsignedInt]
100 			opt = miscParams->find("vsyncInterval");
101 			if(opt != miscParams->end())
102 				mVSyncInterval = StringConverter::parseUnsignedInt(opt->second);
103 			// hidden	[parseBool]
104 			opt = miscParams->find("hidden");
105 			if(opt != miscParams->end())
106 				mHidden = StringConverter::parseBool(opt->second);
107 			// displayFrequency
108 			opt = miscParams->find("displayFrequency");
109 			if(opt != miscParams->end())
110 				mDisplayFrequency = StringConverter::parseUnsignedInt(opt->second);
111 			// colourDepth
112 			opt = miscParams->find("colourDepth");
113 			if(opt != miscParams->end())
114 				colourDepth = StringConverter::parseUnsignedInt(opt->second);
115 			// depthBuffer [parseBool]
116 			opt = miscParams->find("depthBuffer");
117 			if(opt != miscParams->end())
118 				depthBuffer = StringConverter::parseBool(opt->second);
119 			// FSAA type
120 			opt = miscParams->find("FSAA");
121 			if(opt != miscParams->end())
122 				mFSAA = StringConverter::parseUnsignedInt(opt->second);
123 			// FSAA quality
124 			opt = miscParams->find("FSAAHint");
125 			if(opt != miscParams->end())
126 				mFSAAHint = opt->second;
127 			// sRGB?
128 			opt = miscParams->find("gamma");
129 			if(opt != miscParams->end())
130 				mHwGamma = StringConverter::parseBool(opt->second);
131 		}
132 
133 		mName = name;
134 		mDepthBufferPoolId = depthBuffer ? DepthBuffer::POOL_DEFAULT : DepthBuffer::POOL_NO_DEPTH;
135 		mIsFullScreen = fullScreen;
136 		mColourDepth = colourDepth;
137 
138 		mWidth = mHeight = mLeft = mTop = 0;
139 
140 		mActive = true;
141 		mClosed = false;
142 	}
143 	//---------------------------------------------------------------------
_createSizeDependedD3DResources(void)144 	void D3D11RenderWindowBase::_createSizeDependedD3DResources(void)
145 	{
146 		assert(mpBackBuffer && !mRenderTargetView && !mDepthStencilView);
147 
148 		HRESULT hr;
149 
150 		// get the backbuffer desc
151 		D3D11_TEXTURE2D_DESC BBDesc;
152 		mpBackBuffer->GetDesc( &BBDesc );
153 
154 		// create the render target view
155 		D3D11_RENDER_TARGET_VIEW_DESC RTVDesc;
156 		ZeroMemory( &RTVDesc, sizeof(RTVDesc) );
157 
158 		RTVDesc.Format = BBDesc.Format;
159 		RTVDesc.ViewDimension = mFSAA ? D3D11_RTV_DIMENSION_TEXTURE2DMS : D3D11_RTV_DIMENSION_TEXTURE2D;
160 		RTVDesc.Texture2D.MipSlice = 0;
161 		hr = mDevice->CreateRenderTargetView( mpBackBuffer, &RTVDesc, &mRenderTargetView );
162 
163 		if( FAILED(hr) )
164 		{
165 			String errorDescription = mDevice.getErrorDescription();
166 			OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
167 				"Unable to create rendertagert view\nError Description:" + errorDescription,
168 				"D3D11RenderWindow::_createSizeDependedD3DResources");
169 		}
170 
171 
172 		if( mDepthBufferPoolId != DepthBuffer::POOL_NO_DEPTH )
173 		{
174 			// Create depth stencil texture
175 			ID3D11Texture2D* pDepthStencil = NULL;
176 			D3D11_TEXTURE2D_DESC descDepth;
177 
178 			descDepth.Width = BBDesc.Width;
179 			descDepth.Height = BBDesc.Height;
180 			descDepth.MipLevels = 1;
181 			descDepth.ArraySize = 1;
182 			descDepth.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
183 			descDepth.SampleDesc.Count = mFSAAType.Count;
184 			descDepth.SampleDesc.Quality = mFSAAType.Quality;
185 			descDepth.Usage = D3D11_USAGE_DEFAULT;
186 			descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL;
187 			descDepth.CPUAccessFlags = 0;
188 			descDepth.MiscFlags = 0;
189 
190 			hr = mDevice->CreateTexture2D( &descDepth, NULL, &pDepthStencil );
191 			if( FAILED(hr) || mDevice.isError())
192 			{
193 				String errorDescription = mDevice.getErrorDescription(hr);
194 				OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
195 					"Unable to create depth texture\nError Description:" + errorDescription,
196 					"D3D11RenderWindow::_createSizeDependedD3DResources");
197 			}
198 
199 			// Create the depth stencil view
200 			D3D11_DEPTH_STENCIL_VIEW_DESC descDSV;
201 			ZeroMemory( &descDSV, sizeof(D3D11_DEPTH_STENCIL_VIEW_DESC) );
202 
203 			descDSV.Format =  descDepth.Format;
204 			descDSV.ViewDimension = mFSAA ? D3D11_DSV_DIMENSION_TEXTURE2DMS : D3D11_DSV_DIMENSION_TEXTURE2D;
205 			descDSV.Texture2D.MipSlice = 0;
206 			hr = mDevice->CreateDepthStencilView( pDepthStencil, &descDSV, &mDepthStencilView );
207 
208             SAFE_RELEASE(pDepthStencil);
209 
210 			if( FAILED(hr) )
211 			{
212 				String errorDescription = mDevice.getErrorDescription();
213 				OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
214 					"Unable to create depth stencil view\nError Description:" + errorDescription,
215 					"D3D11RenderWindow::_createSizeDependedD3DResources");
216 			}
217 
218 			D3D11RenderSystem* rsys = static_cast<D3D11RenderSystem*>(Root::getSingleton().getRenderSystem());
219 			DepthBuffer *depthBuf = rsys->_addManualDepthBuffer( mDepthStencilView, mWidth, mHeight,
220 																 mFSAAType.Count, mFSAAType.Quality );
221 
222 			//Don't forget we want this window to use _this_ depth buffer
223 			this->attachDepthBuffer( depthBuf );
224 		}
225 	}
226 	//---------------------------------------------------------------------
_destroySizeDependedD3DResources()227 	void D3D11RenderWindowBase::_destroySizeDependedD3DResources()
228 	{
229 		SAFE_RELEASE(mpBackBuffer);
230 		SAFE_RELEASE(mRenderTargetView);
231 
232 		// delete manual depth buffer (depth buffer view non-owning wrapper)
233 		DepthBuffer* depthBuf = this->getDepthBuffer();
234 		detachDepthBuffer();
235 		D3D11RenderSystem* rsys = static_cast<D3D11RenderSystem*>(Root::getSingleton().getRenderSystem());
236 		rsys->_removeManualDepthBuffer(depthBuf);
237 		delete depthBuf;
238 
239 		SAFE_RELEASE(mDepthStencilView);
240 	}
241 	//---------------------------------------------------------------------
destroy()242 	void D3D11RenderWindowBase::destroy()
243 	{
244 		_destroySizeDependedD3DResources();
245 
246 		mActive = false;
247 		mClosed = true;
248 	}
249 	//---------------------------------------------------------------------
_updateViewportsDimensions()250 	void D3D11RenderWindowBase::_updateViewportsDimensions()
251 	{
252 		// Notify viewports of resize
253 		ViewportList::iterator it = mViewportList.begin();
254 		while( it != mViewportList.end() )
255 			(*it++).second->_updateDimensions();
256 	}
257 	//---------------------------------------------------------------------
_queryDxgiDevice()258 	IDXGIDeviceN* D3D11RenderWindowBase::_queryDxgiDevice()
259 	{
260 		if (mDevice.isNull())
261 		{
262 			OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR,
263 				"D3D11Device is NULL!",
264 				"D3D11RenderWindowBase::_queryDxgiDevice");
265 		}
266 
267 		IDXGIDeviceN* pDXGIDevice = NULL;
268 		HRESULT hr = mDevice->QueryInterface( __uuidof(IDXGIDeviceN), (void**)&pDXGIDevice );
269 		if( FAILED(hr) )
270 		{
271 			OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
272 				"Unable to query a DXGIDevice",
273 				"D3D11RenderWindowBase::_queryDxgiDevice");
274 		}
275 
276 		return pDXGIDevice;
277 	}
278 	//---------------------------------------------------------------------
getCustomAttribute(const String & name,void * pData)279 	void D3D11RenderWindowBase::getCustomAttribute( const String& name, void* pData )
280 	{
281 		// Valid attributes and their equvalent native functions:
282 		// D3DDEVICE			: getD3DDevice
283 		// WINDOW				: getWindowHandle
284 
285 		if( name == "D3DDEVICE" )
286 		{
287 			ID3D11DeviceN  **device = (ID3D11DeviceN **)pData;
288 			*device = mDevice.get();
289 			return;
290 		}
291 		else if( name == "isTexture" )
292 		{
293 			bool *b = reinterpret_cast< bool * >( pData );
294 			*b = false;
295 			return;
296 		}
297 		else if( name == "ID3D11RenderTargetView" )
298 		{
299 			*static_cast<ID3D11RenderTargetView**>(pData) = mRenderTargetView;
300 			return;
301 		}
302 		else if( name == "ID3D11Texture2D" )
303 		{
304 			ID3D11Texture2D **pBackBuffer = (ID3D11Texture2D**)pData;
305 			*pBackBuffer = mpBackBuffer;
306 			return;
307 		}
308 		else if( name == "numberOfViews" )
309 		{
310 			unsigned int* n = reinterpret_cast<unsigned int*>(pData);
311 			*n = 1;
312 			return;
313 		}
314 		else if( name == "DDBACKBUFFER" )
315 		{
316 			ID3D11Texture2D **ppBackBuffer = (ID3D11Texture2D**) pData;
317 			ppBackBuffer[0] = NULL;
318 			return;
319 		}
320 
321 		RenderWindow::getCustomAttribute(name, pData);
322 	}
323 	//---------------------------------------------------------------------
copyContentsToMemory(const PixelBox & dst,FrameBuffer buffer)324 	void D3D11RenderWindowBase::copyContentsToMemory(const PixelBox &dst, FrameBuffer buffer)
325 	{
326 		if(mpBackBuffer == NULL)
327 			return;
328 
329 		// get the backbuffer desc
330 		D3D11_TEXTURE2D_DESC BBDesc;
331 		mpBackBuffer->GetDesc( &BBDesc );
332 
333         ID3D11Texture2D *backbuffer = NULL;
334 
335         if(BBDesc.SampleDesc.Quality > 0)
336         {
337                 D3D11_TEXTURE2D_DESC desc = BBDesc;
338                 desc.Usage = D3D11_USAGE_DEFAULT;
339                 desc.CPUAccessFlags = 0;
340                 desc.BindFlags = 0;
341                 desc.SampleDesc.Quality = 0;
342                 desc.SampleDesc.Count = 1;
343 
344                 HRESULT hr = mDevice->CreateTexture2D(
345                         &desc,
346                         NULL,
347                         &backbuffer);
348 
349                 if (FAILED(hr) || mDevice.isError())
350                 {
351                         String errorDescription = mDevice.getErrorDescription(hr);
352                         OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
353                                 "Error creating texture\nError Description:" + errorDescription,
354                                 "D3D11RenderWindow::copyContentsToMemory" );
355                 }
356 
357                 mDevice.GetImmediateContext()->ResolveSubresource(backbuffer, D3D11CalcSubresource(0, 0, 1), mpBackBuffer, D3D11CalcSubresource(0, 0, 1), desc.Format);
358         }
359 
360 
361 		// change the parameters of the texture so we can read it
362 		BBDesc.Usage = D3D11_USAGE_STAGING;
363 		BBDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
364 		BBDesc.BindFlags = 0;
365 		BBDesc.SampleDesc.Quality = 0;
366         BBDesc.SampleDesc.Count = 1;
367 
368 		// create a temp buffer to copy to
369 		ID3D11Texture2D * pTempTexture2D;
370 		HRESULT hr = mDevice->CreateTexture2D(
371                         &BBDesc,
372                         NULL,
373                         &pTempTexture2D);
374 
375         if (FAILED(hr) || mDevice.isError())
376         {
377                 String errorDescription = mDevice.getErrorDescription(hr);
378                 OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
379                         "Error creating texture\nError Description:" + errorDescription,
380                         "D3D11RenderWindow::copyContentsToMemory" );
381         }
382 		// copy the back buffer
383 		mDevice.GetImmediateContext()->CopyResource(pTempTexture2D, backbuffer != NULL ? backbuffer : mpBackBuffer);
384 
385 		// map the copied texture
386 		D3D11_MAPPED_SUBRESOURCE mappedTex2D;
387 		mDevice.GetImmediateContext()->Map(pTempTexture2D, 0,D3D11_MAP_READ, 0, &mappedTex2D);
388 
389 		// copy the the texture to the dest
390 		PixelUtil::bulkPixelConversion(
391 			PixelBox(mWidth, mHeight, 1, D3D11Mappings::_getPF(BBDesc.Format), mappedTex2D.pData),
392 			dst);
393 
394 		// unmap the temp buffer
395 		mDevice.GetImmediateContext()->Unmap(pTempTexture2D, 0);
396 
397 		// Release the temp buffer
398 		SAFE_RELEASE(pTempTexture2D);
399 		SAFE_RELEASE(backbuffer);
400 	}
401 #pragma endregion
402 	//---------------------------------------------------------------------
403 	// class D3D11RenderWindowSwapChainBased
404 	//---------------------------------------------------------------------
405 #pragma region D3D11RenderWindowSwapChainBased
D3D11RenderWindowSwapChainBased(D3D11Device & device,IDXGIFactoryN * pDXGIFactory)406 	D3D11RenderWindowSwapChainBased::D3D11RenderWindowSwapChainBased(D3D11Device & device, IDXGIFactoryN*	pDXGIFactory)
407 		: D3D11RenderWindowBase(device, pDXGIFactory)
408 		, mpSwapChain(NULL)
409 	{
410 		ZeroMemory( &mSwapChainDesc, sizeof(DXGI_SWAP_CHAIN_DESC_N) );
411 	}
412 	//---------------------------------------------------------------------
destroy()413 	void D3D11RenderWindowSwapChainBased::destroy()
414 	{
415         if(mIsFullScreen && mpSwapChain != NULL)
416         {
417             mpSwapChain->SetFullscreenState(false, NULL); // get back from fullscreen
418             mIsFullScreen = false;
419         }
420 
421 		SAFE_RELEASE(mpSwapChain);
422 
423 		D3D11RenderWindowBase::destroy();
424 	}
425 	//---------------------------------------------------------------------
_createSwapChain(void)426 	void D3D11RenderWindowSwapChainBased::_createSwapChain(void)
427 	{
428 		ZeroMemory( &mSwapChainDesc, sizeof(DXGI_SWAP_CHAIN_DESC_N) );
429 
430 		// get the dxgi device
431 		IDXGIDeviceN* pDXGIDevice = _queryDxgiDevice();
432 		// here the mSwapChainDesc and mpSwapChain are initialized
433 		HRESULT hr = _createSwapChainImpl(pDXGIDevice);
434 
435 		SAFE_RELEASE(pDXGIDevice);
436 
437         if (FAILED(hr))
438 		{
439 			OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
440 				"Unable to create swap chain",
441 				"D3D11RenderWindowSwapChainBased::_createSwapChain");
442 		}
443 	}
444 
_createSizeDependedD3DResources()445 	void D3D11RenderWindowSwapChainBased::_createSizeDependedD3DResources()
446 	{
447 		// obtain back buffer
448 		SAFE_RELEASE(mpBackBuffer);
449 
450 		HRESULT hr = mpSwapChain->GetBuffer( 0,  __uuidof( ID3D11Texture2D ), (LPVOID*)&mpBackBuffer  );
451 		if( FAILED(hr) )
452 		{
453 			OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
454 				"Unable to Get Back Buffer for swap chain",
455 				"D3D11RenderWindow::_createSizeDependedD3DResources");
456 		}
457 
458 		// create all other size depended resources
459 		D3D11RenderWindowBase::_createSizeDependedD3DResources();
460 	}
461 	//---------------------------------------------------------------------
_resizeSwapChainBuffers(unsigned width,unsigned height)462 	void D3D11RenderWindowSwapChainBased::_resizeSwapChainBuffers(unsigned width, unsigned height)
463 	{
464 		_destroySizeDependedD3DResources();
465 
466 		// width and height can be zero to autodetect size, therefore do not rely on them
467 #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
468 		UINT Flags = mIsFullScreen ? DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH : 0;
469 		mpSwapChain->ResizeBuffers(mSwapChainDesc.BufferCount, width, height, mSwapChainDesc.BufferDesc.Format, Flags);
470 		mpSwapChain->GetDesc(&mSwapChainDesc);
471 		mWidth = mSwapChainDesc.BufferDesc.Width;
472 		mHeight = mSwapChainDesc.BufferDesc.Height;
473 		mIsFullScreen = (0 == mSwapChainDesc.Windowed); // Alt-Enter together with SetWindowAssociation() can change this state
474 
475 #elif OGRE_PLATFORM == OGRE_PLATFORM_WINRT
476 		mpSwapChain->ResizeBuffers(mSwapChainDesc.BufferCount, width, height, mSwapChainDesc.Format, 0);
477 		mpSwapChain->GetDesc1(&mSwapChainDesc);
478 		mWidth = mSwapChainDesc.Width;
479 		mHeight = mSwapChainDesc.Height;
480 #endif
481 
482 		_createSizeDependedD3DResources();
483 
484 		// Notify viewports of resize
485 		_updateViewportsDimensions();
486 	}
487 	//---------------------------------------------------------------------
swapBuffers()488 	void D3D11RenderWindowSwapChainBased::swapBuffers( )
489 	{
490 		if( !mDevice.isNull() )
491 		{
492 #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
493 			HRESULT hr = mpSwapChain->Present(mVSync ? mVSyncInterval : 0, 0);
494 #elif OGRE_PLATFORM == OGRE_PLATFORM_WINRT
495 			HRESULT hr = mpSwapChain->Present(1, 0); // flip presentation model swap chains have another semantic for first parameter
496 #endif
497 			if( FAILED(hr) )
498 				OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Error Presenting surfaces", "D3D11RenderWindowSwapChainBased::swapBuffers" );
499 		}
500 	}
501 	//---------------------------------------------------------------------
502 #pragma endregion
503 
504 #pragma region D3D11RenderWindowHwnd
505 #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
506 	//---------------------------------------------------------------------
507 	// class D3D11RenderWindowHwnd
508 	//---------------------------------------------------------------------
D3D11RenderWindowHwnd(D3D11Device & device,IDXGIFactoryN * pDXGIFactory)509 	D3D11RenderWindowHwnd::D3D11RenderWindowHwnd(D3D11Device & device, IDXGIFactoryN*	pDXGIFactory)
510 		: D3D11RenderWindowSwapChainBased(device, pDXGIFactory)
511 	{
512 		mHWnd = 0;
513 		mSwitchingFullscreen = false;
514 	}
515 	//---------------------------------------------------------------------
create(const String & name,unsigned int width,unsigned int height,bool fullScreen,const NameValuePairList * miscParams)516 	void D3D11RenderWindowHwnd::create(const String& name, unsigned int width, unsigned int height,
517 		bool fullScreen, const NameValuePairList *miscParams)
518 	{
519 		D3D11RenderWindowSwapChainBased::create(name, width, height, fullScreen, miscParams);
520 
521 		HWND parentHWnd = 0;
522 		HWND externalHandle = 0;
523 		String title = name;
524 		int left = -1; // Defaults to screen center
525 		int top = -1; // Defaults to screen center
526 		String border = "";
527 		bool outerSize = false;
528 		bool enableDoubleClick = false;
529 
530 		if(miscParams)
531 		{
532 			// Get variable-length params
533 			NameValuePairList::const_iterator opt;
534 			// left (x)
535 			opt = miscParams->find("left");
536 			if(opt != miscParams->end())
537 				left = StringConverter::parseInt(opt->second);
538 			// top (y)
539 			opt = miscParams->find("top");
540 			if(opt != miscParams->end())
541 				top = StringConverter::parseInt(opt->second);
542 			// Window title
543 			opt = miscParams->find("title");
544 			if(opt != miscParams->end())
545 				title = opt->second;
546 			// parentWindowHandle		-> parentHWnd
547 			opt = miscParams->find("parentWindowHandle");
548 			if(opt != miscParams->end())
549 				parentHWnd = (HWND)StringConverter::parseSizeT(opt->second);
550 			// externalWindowHandle		-> externalHandle
551 			opt = miscParams->find("externalWindowHandle");
552 			if(opt != miscParams->end())
553 				externalHandle = (HWND)StringConverter::parseSizeT(opt->second);
554 			// window border style
555 			opt = miscParams->find("border");
556 			if(opt != miscParams->end())
557 				border = opt->second;
558 			// set outer dimensions?
559 			opt = miscParams->find("outerDimensions");
560 			if(opt != miscParams->end())
561 				outerSize = StringConverter::parseBool(opt->second);
562 			// enable double click messages
563 			opt = miscParams->find("enableDoubleClick");
564 			if(opt != miscParams->end())
565 				enableDoubleClick = StringConverter::parseBool(opt->second);
566 
567 		}
568 
569 		// Destroy current window if any
570 		if( mHWnd )
571 			destroy();
572 
573 		if (!externalHandle)
574 		{
575 			DWORD dwStyle = (mHidden ? 0 : WS_VISIBLE) | WS_CLIPCHILDREN;
576 			RECT rc;
577 
578 			mWidth = width;
579 			mHeight = height;
580 			mTop = top;
581 			mLeft = left;
582 
583 			if (!fullScreen)
584 			{
585 				if (parentHWnd)
586 				{
587 					dwStyle |= WS_CHILD;
588 				}
589 				else
590 				{
591 					if (border == "none")
592 						dwStyle |= WS_POPUP;
593 					else if (border == "fixed")
594 						dwStyle |= WS_OVERLAPPED | WS_BORDER | WS_CAPTION |
595 						WS_SYSMENU | WS_MINIMIZEBOX;
596 					else
597 						dwStyle |= WS_OVERLAPPEDWINDOW;
598 				}
599 
600 				if (!outerSize)
601 				{
602 					// Calculate window dimensions required
603 					// to get the requested client area
604 					SetRect(&rc, 0, 0, mWidth, mHeight);
605 					AdjustWindowRect(&rc, dwStyle, false);
606 					mWidth = rc.right - rc.left;
607 					mHeight = rc.bottom - rc.top;
608 
609 					// Clamp width and height to the desktop dimensions
610 					int screenw = GetSystemMetrics(SM_CXSCREEN);
611 					int screenh = GetSystemMetrics(SM_CYSCREEN);
612 					if ((int)mWidth > screenw)
613 						mWidth = screenw;
614 					if ((int)mHeight > screenh)
615 						mHeight = screenh;
616 					if (mLeft < 0)
617 						mLeft = (screenw - mWidth) / 2;
618 					if (mTop < 0)
619 						mTop = (screenh - mHeight) / 2;
620 				}
621 			}
622 			else
623 			{
624 				dwStyle |= WS_POPUP;
625 				mTop = mLeft = 0;
626 			}
627 
628 			UINT classStyle = 0;
629 			if (enableDoubleClick)
630 				classStyle |= CS_DBLCLKS;
631 
632 			HINSTANCE hInst = NULL;
633 
634 			// Register the window class
635 			// NB allow 4 bytes of window data for D3D11RenderWindow pointer
636 			WNDCLASS wc = { classStyle, WindowEventUtilities::_WndProc, 0, 0, hInst,
637 				LoadIcon(0, IDI_APPLICATION), LoadCursor(NULL, IDC_ARROW),
638 				(HBRUSH)GetStockObject(BLACK_BRUSH), 0, "OgreD3D11Wnd" };
639 
640 
641 			RegisterClass(&wc);
642 
643 			// Create our main window
644 			// Pass pointer to self
645 			mIsExternal = false;
646 			mHWnd = CreateWindow("OgreD3D11Wnd", title.c_str(), dwStyle,
647 				mLeft, mTop, mWidth, mHeight, parentHWnd, 0, hInst, this);
648 
649 			WindowEventUtilities::_addRenderWindow(this);
650 		}
651 		else
652 		{
653 			mHWnd = externalHandle;
654 			mIsExternal = true;
655 		}
656 
657 		RECT rc;
658 		// top and left represent outer window coordinates
659 		GetWindowRect(mHWnd, &rc);
660 		mTop = rc.top;
661 		mLeft = rc.left;
662 		// width and height represent interior drawable area
663 		GetClientRect(mHWnd, &rc);
664 		mWidth = rc.right;
665 		mHeight = rc.bottom;
666 
667 		LogManager::getSingleton().stream()
668 			<< "D3D11 : Created D3D11 Rendering Window '"
669 			<< mName << "' : " << mWidth << "x" << mHeight
670 			<< ", " << mColourDepth << "bpp";
671 
672 		_createSwapChain();
673 		_createSizeDependedD3DResources();
674 		mpDXGIFactory->MakeWindowAssociation(mHWnd, NULL);
675 		setHidden(mHidden);
676 	}
677 	//---------------------------------------------------------------------
destroy()678 	void D3D11RenderWindowHwnd::destroy()
679 	{
680 		D3D11RenderWindowSwapChainBased::destroy();
681 
682 		if (mHWnd && !mIsExternal)
683 		{
684 			WindowEventUtilities::_removeRenderWindow(this);
685 			DestroyWindow(mHWnd);
686 		}
687 
688 		mHWnd = NULL;
689 	}
690 	//---------------------------------------------------------------------
_createSwapChainImpl(IDXGIDeviceN * pDXGIDevice)691 	HRESULT D3D11RenderWindowHwnd::_createSwapChainImpl(IDXGIDeviceN* pDXGIDevice)
692 	{
693 		ZeroMemory( &mSwapChainDesc, sizeof(DXGI_SWAP_CHAIN_DESC_N) );
694 		DXGI_FORMAT format = DXGI_FORMAT_R8G8B8A8_UNORM;
695 		mSwapChainDesc.BufferDesc.Width		= mWidth;
696 		mSwapChainDesc.BufferDesc.Height	= mHeight;
697 		mSwapChainDesc.BufferDesc.Format	= format;
698 
699 		mSwapChainDesc.BufferDesc.RefreshRate.Numerator=0;
700 		mSwapChainDesc.BufferDesc.RefreshRate.Denominator = 0;
701 
702 		mSwapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
703 		mSwapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
704 		mSwapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH ;
705 
706 		// triple buffer if VSync is on
707 		mSwapChainDesc.BufferUsage			= DXGI_USAGE_RENDER_TARGET_OUTPUT;
708 		mSwapChainDesc.BufferCount			= mVSync ? 2 : 1;
709 		mSwapChainDesc.SwapEffect			= DXGI_SWAP_EFFECT_DISCARD ;
710 
711 		mSwapChainDesc.OutputWindow 		= mHWnd;
712 		mSwapChainDesc.Windowed				= !mIsFullScreen;
713 
714 		D3D11RenderSystem* rsys = static_cast<D3D11RenderSystem*>(Root::getSingleton().getRenderSystem());
715 		rsys->determineFSAASettings(mFSAA, mFSAAHint, format, &mFSAAType);
716 		mSwapChainDesc.SampleDesc.Count = mFSAAType.Count;
717 		mSwapChainDesc.SampleDesc.Quality = mFSAAType.Quality;
718 
719 		if (!mVSync && !mIsFullScreen)
720 		{
721 			// NB not using vsync in windowed mode in D3D11 can cause jerking at low
722 			// frame rates no matter what buffering modes are used (odd - perhaps a
723 			// timer issue in D3D11 since GL doesn't suffer from this)
724 			// low is < 200fps in this context
725 			LogManager::getSingleton().logMessage("D3D11 : WARNING - "
726 				"disabling VSync in windowed mode can cause timing issues at lower "
727 				"frame rates, turn VSync on if you observe this problem.");
728 		}
729 
730 		HRESULT hr;
731 
732 		// Create swap chain
733 		hr = mpDXGIFactory->CreateSwapChain(pDXGIDevice, &mSwapChainDesc, &mpSwapChain);
734 
735 		if (FAILED(hr))
736 		{
737 			// Try a second time, may fail the first time due to back buffer count,
738 			// which will be corrected by the runtime
739 			hr = mpDXGIFactory->CreateSwapChain(pDXGIDevice, &mSwapChainDesc, &mpSwapChain);
740 		}
741 
742 		return hr;
743 	}
744 	//---------------------------------------------------------------------
isVisible() const745 	bool D3D11RenderWindowHwnd::isVisible() const
746 	{
747 		return (mHWnd && !IsIconic(mHWnd));
748 	}
749 	//---------------------------------------------------------------------
setHidden(bool hidden)750 	void D3D11RenderWindowHwnd::setHidden(bool hidden)
751 	{
752 		mHidden = hidden;
753 		if (!mIsExternal)
754 		{
755 			if (hidden)
756 				ShowWindow(mHWnd, SW_HIDE);
757 			else
758 				ShowWindow(mHWnd, SW_SHOWNORMAL);
759 		}
760 	}
761 	//---------------------------------------------------------------------
reposition(int top,int left)762 	void D3D11RenderWindowHwnd::reposition(int top, int left)
763 	{
764 		if (mHWnd && !mIsFullScreen)
765 		{
766 			SetWindowPos(mHWnd, 0, top, left, 0, 0,
767 				SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
768 		}
769 	}
770 	//---------------------------------------------------------------------
resize(unsigned int width,unsigned int height)771 	void D3D11RenderWindowHwnd::resize(unsigned int width, unsigned int height)
772 	{
773 		if (!mIsExternal)
774 		{
775 			if (mHWnd && !mIsFullScreen)
776 			{
777 				RECT rc = { 0, 0, width, height };
778 				AdjustWindowRect(&rc, GetWindowLong(mHWnd, GWL_STYLE), false);
779 				width = rc.right - rc.left;
780 				height = rc.bottom - rc.top;
781 				SetWindowPos(mHWnd, 0, 0, 0, width, height,
782 					SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
783 			}
784 		}
785 		else
786 			windowMovedOrResized();
787 	}
788 	//---------------------------------------------------------------------
windowMovedOrResized()789 	void D3D11RenderWindowHwnd::windowMovedOrResized()
790 	{
791 		if (!mHWnd || IsIconic(mHWnd))
792 			return;
793 
794 		RECT rc;
795 		// top and left represent outer window position
796 		GetWindowRect(mHWnd, &rc);
797 		mTop = rc.top;
798 		mLeft = rc.left;
799 		// width and height represent drawable area only
800 		GetClientRect(mHWnd, &rc);
801 		unsigned int width = rc.right - rc.left;
802 		unsigned int height = rc.bottom - rc.top;
803 
804 		if (width == 0)
805 			width = 1;
806 		if (height == 0)
807 			height = 1;
808 
809 		if (mWidth == width && mHeight == height)
810 			return;
811 
812 		_resizeSwapChainBuffers(width, height);
813 	}
814 	//---------------------------------------------------------------------
getCustomAttribute(const String & name,void * pData)815 	void D3D11RenderWindowHwnd::getCustomAttribute( const String& name, void* pData )
816 	{
817 		// Valid attributes and their equvalent native functions:
818 		// D3DDEVICE			: getD3DDevice
819 		// WINDOW				: getWindowHandle
820 
821 		if( name == "WINDOW" )
822 		{
823 			HWND *pWnd = (HWND*)pData;
824 			*pWnd = mHWnd;
825 			return;
826 		}
827 
828 		D3D11RenderWindowSwapChainBased::getCustomAttribute(name, pData);
829 	}
830 	//---------------------------------------------------------------------
setFullscreen(bool fullScreen,unsigned int width,unsigned int height)831 	void D3D11RenderWindowHwnd::setFullscreen(bool fullScreen, unsigned int width, unsigned int height)
832 	{
833 		if (fullScreen != mIsFullScreen || width != mWidth || height != mHeight)
834 		{
835 
836 			if (fullScreen != mIsFullScreen)
837 				mSwitchingFullscreen = true;
838 
839 			DWORD dwStyle = WS_VISIBLE | WS_CLIPCHILDREN;
840 
841 			bool oldFullscreen = mIsFullScreen;
842 			mIsFullScreen = fullScreen;
843 
844 			if (fullScreen)
845 			{
846 				dwStyle |= WS_POPUP;
847 				mTop = mLeft = 0;
848 				mWidth = width;
849 				mHeight = height;
850 				// need different ordering here
851 
852 				if (oldFullscreen)
853 				{
854 					// was previously fullscreen, just changing the resolution
855 					SetWindowPos(mHWnd, HWND_TOPMOST, 0, 0, width, height, SWP_NOACTIVATE);
856 				}
857 				else
858 				{
859 					SetWindowPos(mHWnd, HWND_TOPMOST, 0, 0, width, height, SWP_NOACTIVATE);
860 					//MoveWindow(mHWnd, mLeft, mTop, mWidth, mHeight, FALSE);
861 					SetWindowLong(mHWnd, GWL_STYLE, dwStyle);
862 					SetWindowPos(mHWnd, 0, 0,0, 0,0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER);
863 				}
864 			}
865 			else
866 			{
867 				dwStyle |= WS_OVERLAPPEDWINDOW;
868 				// Calculate window dimensions required
869 				// to get the requested client area
870 				RECT rc;
871 				SetRect(&rc, 0, 0, width, height);
872 				AdjustWindowRect(&rc, dwStyle, false);
873 				unsigned int winWidth = rc.right - rc.left;
874 				unsigned int winHeight = rc.bottom - rc.top;
875 
876 				SetWindowLong(mHWnd, GWL_STYLE, dwStyle);
877 				SetWindowPos(mHWnd, HWND_NOTOPMOST, 0, 0, winWidth, winHeight,
878 					SWP_DRAWFRAME | SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOACTIVATE);
879 				// Note that we also set the position in the restoreLostDevice method
880 				// via _finishSwitchingFullScreen
881 			}
882 
883 			mSwapChainDesc.Windowed = !fullScreen;
884 			mSwapChainDesc.BufferDesc.RefreshRate.Numerator = 0;
885 			mSwapChainDesc.BufferDesc.RefreshRate.Denominator=0;
886 			mSwapChainDesc.BufferDesc.Height = height;
887 			mSwapChainDesc.BufferDesc.Width = width;
888 
889 			if ((oldFullscreen && fullScreen) || mIsExternal)
890 			{
891 				// Notify viewports of resize
892 				_updateViewportsDimensions();
893 			}
894 		}
895 	}
896 	//---------------------------------------------------------------------
_finishSwitchingFullscreen()897 	void D3D11RenderWindowHwnd::_finishSwitchingFullscreen()
898 	{
899 		if(mIsFullScreen)
900 		{
901 			// Need to reset the region on the window sometimes, when the
902 			// windowed mode was constrained by desktop
903 			HRGN hRgn = CreateRectRgn(0,0,mSwapChainDesc.BufferDesc.Width, mSwapChainDesc.BufferDesc.Height);
904 			SetWindowRgn(mHWnd, hRgn, FALSE);
905 		}
906 		else
907 		{
908 			// When switching back to windowed mode, need to reset window size
909 			// after device has been restored
910 			RECT rc;
911 			SetRect(&rc, 0, 0, mSwapChainDesc.BufferDesc.Width, mSwapChainDesc.BufferDesc.Height);
912 			AdjustWindowRect(&rc, GetWindowLong(mHWnd, GWL_STYLE), false);
913 			unsigned int winWidth = rc.right - rc.left;
914 			unsigned int winHeight = rc.bottom - rc.top;
915 			int screenw = GetSystemMetrics(SM_CXSCREEN);
916 			int screenh = GetSystemMetrics(SM_CYSCREEN);
917 			int left = (screenw - winWidth) / 2;
918 			int top = (screenh - winHeight) / 2;
919 			SetWindowPos(mHWnd, HWND_NOTOPMOST, left, top, winWidth, winHeight,
920 				SWP_DRAWFRAME | SWP_FRAMECHANGED | SWP_NOACTIVATE);
921 
922 		}
923 		mpSwapChain->SetFullscreenState(mIsFullScreen, NULL);
924 		mSwitchingFullscreen = false;
925 	}
926     //---------------------------------------------------------------------
setActive(bool state)927     void D3D11RenderWindowHwnd::setActive(bool state)
928     {
929             if (mHWnd && mpSwapChain && mIsFullScreen)
930             {
931                     if (state)
932                     {
933                             ShowWindow(mHWnd, SW_RESTORE);
934                             mpSwapChain->SetFullscreenState(mIsFullScreen, NULL);
935                     }
936                     else
937                     {
938                             ShowWindow(mHWnd, SW_SHOWMINIMIZED);
939                             mpSwapChain->SetFullscreenState(FALSE, NULL);
940                     }
941             }
942 
943             RenderWindow::setActive(state);
944     }
945 #endif
946 #pragma endregion
947 #pragma region D3D11RenderWindowCoreWindow
948 #if OGRE_PLATFORM == OGRE_PLATFORM_WINRT
949 	//---------------------------------------------------------------------
950 	// class D3D11RenderWindowCoreWindow
951 	//---------------------------------------------------------------------
D3D11RenderWindowCoreWindow(D3D11Device & device,IDXGIFactoryN * pDXGIFactory)952 	D3D11RenderWindowCoreWindow::D3D11RenderWindowCoreWindow(D3D11Device & device, IDXGIFactoryN*	pDXGIFactory)
953 		: D3D11RenderWindowSwapChainBased(device, pDXGIFactory)
954 	{
955 	}
create(const String & name,unsigned int width,unsigned int height,bool fullScreen,const NameValuePairList * miscParams)956 	void D3D11RenderWindowCoreWindow::create(const String& name, unsigned int width, unsigned int height,
957 		bool fullScreen, const NameValuePairList *miscParams)
958 	{
959 		D3D11RenderWindowSwapChainBased::create(name, width, height, fullScreen, miscParams);
960 
961 		Windows::UI::Core::CoreWindow^ externalHandle = nullptr;
962 
963 		if(miscParams)
964 		{
965 			// Get variable-length params
966 			NameValuePairList::const_iterator opt;
967 			// externalWindowHandle		-> externalHandle
968 			opt = miscParams->find("externalWindowHandle");
969 			if(opt != miscParams->end())
970 				externalHandle = reinterpret_cast<Windows::UI::Core::CoreWindow^>((void*)StringConverter::parseSizeT(opt->second));
971 		}
972 
973 		// Reset current window if any
974 		mCoreWindow = nullptr;
975 
976 		if (!externalHandle)
977 		{
978 			OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS, "External window handle is not specified.", "D3D11RenderWindow::create" );
979 		}
980 		else
981 		{
982 			mCoreWindow = externalHandle;
983 			mIsExternal = true;
984 		}
985 
986 		Windows::Foundation::Rect rc = mCoreWindow->Bounds;
987 		float scale = Windows::Graphics::Display::DisplayProperties::LogicalDpi / 96;
988 		mLeft = (int)(rc.X * scale);
989 		mTop = (int)(rc.Y * scale);
990 		mWidth = (int)(rc.Width * scale);
991 		mHeight = (int)(rc.Height * scale);
992 
993 		LogManager::getSingleton().stream()
994 			<< "D3D11 : Created D3D11 Rendering Window '"
995 			<< mName << "' : " << mWidth << "x" << mHeight
996 			<< ", " << mColourDepth << "bpp";
997 
998 		_createSwapChain();
999 		_createSizeDependedD3DResources();
1000 	}
1001 
1002 	//---------------------------------------------------------------------
destroy()1003 	void D3D11RenderWindowCoreWindow::destroy()
1004 	{
1005 		D3D11RenderWindowSwapChainBased::destroy();
1006 
1007 		if (mCoreWindow.Get() && !mIsExternal)
1008 		{
1009 			OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS, "Only external window handles are supported."
1010 				, "D3D11RenderWindow::destroy" );
1011 		}
1012 
1013 		mCoreWindow = nullptr;
1014 	}
1015 	//---------------------------------------------------------------------
_createSwapChainImpl(IDXGIDeviceN * pDXGIDevice)1016 	HRESULT D3D11RenderWindowCoreWindow::_createSwapChainImpl(IDXGIDeviceN* pDXGIDevice)
1017 	{
1018 		DXGI_FORMAT format = DXGI_FORMAT_B8G8R8A8_UNORM;
1019 		mSwapChainDesc.Width				= 0;									// Use automatic sizing.
1020 		mSwapChainDesc.Height				= 0;
1021 		mSwapChainDesc.Format				= format;
1022 		mSwapChainDesc.Stereo				= false;
1023 
1024 		// triple buffer if VSync is on
1025         mSwapChainDesc.BufferUsage			= DXGI_USAGE_RENDER_TARGET_OUTPUT;
1026 #if (OGRE_PLATFORM == OGRE_PLATFORM_WINRT) && (OGRE_WINRT_TARGET_TYPE == PHONE)
1027 		mSwapChainDesc.BufferCount			= 1;									// WP8: One buffer.
1028 		mSwapChainDesc.Scaling				= DXGI_SCALING_STRETCH;					// WP8: Must be stretch scaling mode.
1029 		mSwapChainDesc.SwapEffect			= DXGI_SWAP_EFFECT_DISCARD;				// WP8: No swap effect.
1030 #else
1031 		mSwapChainDesc.BufferCount			= 2;									// Use two buffers to enable flip effect.
1032 		mSwapChainDesc.Scaling				= DXGI_SCALING_NONE;					// Otherwise stretch would be used by default.
1033 		mSwapChainDesc.SwapEffect			= DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;		// MS recommends using this swap effect for all applications.
1034 #endif
1035 		mSwapChainDesc.AlphaMode			= DXGI_ALPHA_MODE_UNSPECIFIED;
1036 
1037 		D3D11RenderSystem* rsys = static_cast<D3D11RenderSystem*>(Root::getSingleton().getRenderSystem());
1038 		rsys->determineFSAASettings(mFSAA, mFSAAHint, format, &mFSAAType);
1039 		mSwapChainDesc.SampleDesc.Count = mFSAAType.Count;
1040 		mSwapChainDesc.SampleDesc.Quality = mFSAAType.Quality;
1041 
1042 		// Create swap chain
1043 		HRESULT hr = mpDXGIFactory->CreateSwapChainForCoreWindow(pDXGIDevice, reinterpret_cast<IUnknown*>(mCoreWindow.Get()), &mSwapChainDesc, NULL, &mpSwapChain);
1044 
1045 		if (FAILED(hr))
1046 		{
1047 			// Try a second time, may fail the first time due to back buffer count,
1048 			// which will be corrected by the runtime
1049 			hr = mpDXGIFactory->CreateSwapChainForCoreWindow(pDXGIDevice, reinterpret_cast<IUnknown*>(mCoreWindow.Get()), &mSwapChainDesc, NULL, &mpSwapChain);
1050 		}
1051 		if (FAILED(hr))
1052 			return hr;
1053 
1054         // Ensure that DXGI does not queue more than one frame at a time. This both reduces
1055         // latency and ensures that the application will only render after each VSync, minimizing
1056         // power consumption.
1057         hr = pDXGIDevice->SetMaximumFrameLatency(1);
1058 		return hr;
1059 	}
1060 	//---------------------------------------------------------------------
isVisible() const1061 	bool D3D11RenderWindowCoreWindow::isVisible() const
1062 	{
1063 		return (mCoreWindow.Get() && Windows::UI::Core::CoreWindow::GetForCurrentThread() == mCoreWindow.Get());
1064 	}
1065 	//---------------------------------------------------------------------
windowMovedOrResized()1066 	void D3D11RenderWindowCoreWindow::windowMovedOrResized()
1067 	{
1068 		Windows::Foundation::Rect rc = mCoreWindow->Bounds;
1069 		float scale = Windows::Graphics::Display::DisplayProperties::LogicalDpi / 96;
1070 		mLeft = (int)(rc.X * scale);
1071 		mTop = (int)(rc.Y * scale);
1072 		mWidth = (int)(rc.Width * scale);
1073 		mHeight = (int)(rc.Height * scale);
1074 
1075 		_resizeSwapChainBuffers(0, 0);		// pass zero to autodetect size
1076 	}
1077 	//---------------------------------------------------------------------
1078 #endif
1079 #pragma endregion
1080 
1081 	//---------------------------------------------------------------------
1082 	// class D3D11RenderWindowImageSource
1083 	//---------------------------------------------------------------------
1084 #pragma region D3D11RenderWindowImageSource
1085 #if (OGRE_PLATFORM == OGRE_PLATFORM_WINRT) && (OGRE_WINRT_TARGET_TYPE == DESKTOP_APP)
1086 	//---------------------------------------------------------------------
D3D11RenderWindowImageSource(D3D11Device & device,IDXGIFactoryN * pDXGIFactory)1087 	D3D11RenderWindowImageSource::D3D11RenderWindowImageSource(D3D11Device& device, IDXGIFactoryN* pDXGIFactory)
1088 		: D3D11RenderWindowBase(device, pDXGIFactory)
1089 		, mImageSourceNative(NULL)
1090 	{
1091 	}
1092 	//---------------------------------------------------------------------
create(const String & name,unsigned width,unsigned height,bool fullScreen,const NameValuePairList * miscParams)1093 	void D3D11RenderWindowImageSource::create(const String& name, unsigned width, unsigned height, bool fullScreen, const NameValuePairList *miscParams)
1094 	{
1095 		D3D11RenderWindowBase::create(name, width, height, fullScreen, miscParams);
1096 
1097 		mWidth = width;
1098 		mHeight = height;
1099 
1100 		bool isOpaque = true;
1101 		if(miscParams)
1102 		{
1103 			// Get variable-length params
1104 			NameValuePairList::const_iterator opt;
1105 			// isOpaque
1106 			opt = miscParams->find("isOpaque");
1107 			if(opt != miscParams->end())
1108 				isOpaque = StringConverter::parseBool(opt->second);
1109 		}
1110 
1111 		// create brush
1112 		// TODO: obtain from miscParams optional placeholder image and set inside the brush till first render???
1113 		mBrush = ref new Windows::UI::Xaml::Media::ImageBrush;
1114 
1115 		_createSizeDependedD3DResources();
1116 	}
1117 	//---------------------------------------------------------------------
destroy(void)1118 	void D3D11RenderWindowImageSource::destroy(void)
1119 	{
1120 		D3D11RenderWindowBase::destroy();
1121 
1122 		SAFE_RELEASE(mImageSourceNative);
1123 		mImageSource = nullptr;
1124 		mBrush = nullptr;
1125 	}
1126 	//---------------------------------------------------------------------
_createSizeDependedD3DResources()1127 	void D3D11RenderWindowImageSource::_createSizeDependedD3DResources()
1128 	{
1129 		SAFE_RELEASE(mpBackBuffer);
1130 		SAFE_RELEASE(mImageSourceNative);
1131 
1132 		if(mWidth <= 0 || mHeight <= 0)
1133 		{
1134 			mImageSource = nullptr;
1135 			mBrush->ImageSource = nullptr;
1136 			return;
1137 		}
1138 
1139 		// create back buffer - ID3D11Texture2D
1140 		D3D11_TEXTURE2D_DESC desc = {0};
1141 		desc.Width = mWidth;
1142 		desc.Height = mHeight;
1143 		desc.MipLevels = 1;
1144 		desc.ArraySize = 1;
1145 		desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
1146 		desc.SampleDesc.Count = 1;
1147 		desc.SampleDesc.Quality = 0;
1148 		desc.Usage = D3D11_USAGE_DEFAULT;
1149 		desc.BindFlags = D3D11_BIND_RENDER_TARGET;
1150 		desc.CPUAccessFlags = 0;
1151 		desc.MiscFlags = 0;
1152 
1153 		HRESULT hr = mDevice->CreateTexture2D(&desc, NULL, &mpBackBuffer);
1154 		if( FAILED(hr) )
1155 		{
1156 			OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
1157 				"Unable to Create Back Buffer",
1158 				"D3D11RenderWindowImageSource::_createSizeDependedD3DResources");
1159 		}
1160 
1161 		// create front buffer - SurfaceImageSource
1162 		mImageSource = ref new Windows::UI::Xaml::Media::Imaging::SurfaceImageSource(mWidth, mHeight, true);
1163 		reinterpret_cast<IUnknown*>(mImageSource)->QueryInterface(__uuidof(ISurfaceImageSourceNative), (void **)&mImageSourceNative);
1164 
1165 		// set DXGI device for the front buffer
1166 		IDXGIDeviceN* pDXGIDevice = _queryDxgiDevice();
1167 		mImageSourceNative->SetDevice(pDXGIDevice);
1168 		SAFE_RELEASE(pDXGIDevice);
1169 
1170 		// create all other size depended resources
1171 		D3D11RenderWindowBase::_createSizeDependedD3DResources();
1172 
1173 		mBrush->ImageSource = mImageSource;
1174 	}
1175 	//---------------------------------------------------------------------
update(bool swapBuffers)1176 	void D3D11RenderWindowImageSource::update(bool swapBuffers)
1177 	{
1178 		if(mImageSourceNative == NULL)
1179 			return;
1180 
1181 		D3D11RenderWindowBase::update(swapBuffers);
1182 	}
1183 	//---------------------------------------------------------------------
swapBuffers()1184 	void D3D11RenderWindowImageSource::swapBuffers()
1185 	{
1186 		if(mImageSourceNative == NULL)
1187 			return;
1188 
1189 		IDXGISurface* dxgiSurface = NULL;
1190 		RECT updateRect = { 0, 0, mWidth, mHeight };
1191 		POINT offset = { 0, 0 };
1192 
1193 		HRESULT hr = mImageSourceNative->BeginDraw(updateRect, &dxgiSurface, &offset);
1194 		if(hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
1195 			return;
1196 
1197 		if(FAILED(hr))
1198 		{
1199 			OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
1200 				"Unable to Get DXGI surface for SurfaceImageSource",
1201 				"D3D11RenderWindowImageSource::swapBuffers");
1202 		}
1203 
1204 		ID3D11Texture2D* destTexture = NULL;
1205 		hr = dxgiSurface->QueryInterface(__uuidof(ID3D11Texture2D), (void**)&destTexture);
1206 		SAFE_RELEASE(dxgiSurface);
1207 		if(FAILED(hr))
1208 		{
1209 			OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
1210 				"Unable to convert DXGI surface to D3D11 texture",
1211 				"D3D11RenderWindowImageSource::swapBuffers");
1212 		}
1213 
1214 		mDevice.GetImmediateContext()->CopySubresourceRegion1(destTexture, 0, offset.x, offset.y, 0, mpBackBuffer, 0, NULL, 0);
1215 
1216 		hr = mImageSourceNative->EndDraw();
1217 
1218 		SAFE_RELEASE(destTexture);
1219 
1220 		if( FAILED(hr) )
1221 		{
1222 			OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
1223 				"Drawing into SurfaceImageSource failed",
1224 				"D3D11RenderWindowImageSource::swapBuffers");
1225 		}
1226 	}
1227 	//---------------------------------------------------------------------
resize(unsigned width,unsigned height)1228 	void D3D11RenderWindowImageSource::resize(unsigned width, unsigned height)
1229 	{
1230 		_destroySizeDependedD3DResources();
1231 
1232 		mWidth = width;
1233 		mHeight = height;
1234 
1235 		_createSizeDependedD3DResources();
1236 
1237 		// Notify viewports of resize
1238 		_updateViewportsDimensions();
1239 	}
1240 	//---------------------------------------------------------------------
getCustomAttribute(const String & name,void * pData)1241 	void D3D11RenderWindowImageSource::getCustomAttribute( const String& name, void* pData )
1242 	{
1243 		if( name == "ImageBrush" )
1244 		{
1245 			IUnknown** pUnk = (IUnknown **)pData;
1246 			*pUnk = reinterpret_cast<IUnknown*>(mBrush);
1247 			return;
1248 		}
1249 
1250 		D3D11RenderWindowBase::getCustomAttribute(name, pData);
1251 	}
1252 	//---------------------------------------------------------------------
1253 #endif // (OGRE_PLATFORM == OGRE_PLATFORM_WINRT) && (OGRE_WINRT_TARGET_TYPE == DESKTOP_APP)
1254 #pragma endregion
1255 }
1256