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