1 // 2 // Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 7 // Renderer9.cpp: Implements a back-end specific class for the D3D9 renderer. 8 9 #include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" 10 #include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" 11 #include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" 12 #include "libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.h" 13 #include "libGLESv2/renderer/d3d/d3d9/SwapChain9.h" 14 #include "libGLESv2/renderer/d3d/d3d9/TextureStorage9.h" 15 #include "libGLESv2/renderer/d3d/d3d9/Image9.h" 16 #include "libGLESv2/renderer/d3d/d3d9/Blit9.h" 17 #include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h" 18 #include "libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h" 19 #include "libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h" 20 #include "libGLESv2/renderer/d3d/d3d9/Buffer9.h" 21 #include "libGLESv2/renderer/d3d/d3d9/Query9.h" 22 #include "libGLESv2/renderer/d3d/d3d9/Fence9.h" 23 #include "libGLESv2/renderer/d3d/d3d9/VertexArray9.h" 24 #include "libGLESv2/renderer/d3d/IndexDataManager.h" 25 #include "libGLESv2/renderer/d3d/ProgramD3D.h" 26 #include "libGLESv2/renderer/d3d/ShaderD3D.h" 27 #include "libGLESv2/renderer/d3d/TextureD3D.h" 28 #include "libGLESv2/renderer/d3d/TransformFeedbackD3D.h" 29 #include "libGLESv2/main.h" 30 #include "libGLESv2/Buffer.h" 31 #include "libGLESv2/Texture.h" 32 #include "libGLESv2/Framebuffer.h" 33 #include "libGLESv2/FramebufferAttachment.h" 34 #include "libGLESv2/Renderbuffer.h" 35 #include "libGLESv2/ProgramBinary.h" 36 #include "libGLESv2/angletypes.h" 37 38 #include "libEGL/Display.h" 39 40 #include "common/utilities.h" 41 42 #include "third_party/trace_event/trace_event.h" 43 44 #include <sstream> 45 46 // Can also be enabled by defining FORCE_REF_RAST in the project's predefined macros 47 #define REF_RAST 0 48 49 // The "Debug This Pixel..." feature in PIX often fails when using the 50 // D3D9Ex interfaces. In order to get debug pixel to work on a Vista/Win 7 51 // machine, define "ANGLE_ENABLE_D3D9EX=0" in your project file. 52 #if !defined(ANGLE_ENABLE_D3D9EX) 53 // Enables use of the IDirect3D9Ex interface, when available 54 #define ANGLE_ENABLE_D3D9EX 1 55 #endif // !defined(ANGLE_ENABLE_D3D9EX) 56 57 #if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL) 58 #define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3 59 #endif 60 61 const D3DFORMAT D3DFMT_INTZ = ((D3DFORMAT)(MAKEFOURCC('I','N','T','Z'))); 62 const D3DFORMAT D3DFMT_NULL = ((D3DFORMAT)(MAKEFOURCC('N','U','L','L'))); 63 64 namespace rx 65 { 66 static const D3DFORMAT RenderTargetFormats[] = 67 { 68 D3DFMT_A1R5G5B5, 69 // D3DFMT_A2R10G10B10, // The color_ramp conformance test uses ReadPixels with UNSIGNED_BYTE causing it to think that rendering skipped a colour value. 70 D3DFMT_A8R8G8B8, 71 D3DFMT_R5G6B5, 72 // D3DFMT_X1R5G5B5, // Has no compatible OpenGL ES renderbuffer format 73 D3DFMT_X8R8G8B8 74 }; 75 76 static const D3DFORMAT DepthStencilFormats[] = 77 { 78 D3DFMT_UNKNOWN, 79 // D3DFMT_D16_LOCKABLE, 80 D3DFMT_D32, 81 // D3DFMT_D15S1, 82 D3DFMT_D24S8, 83 D3DFMT_D24X8, 84 // D3DFMT_D24X4S4, 85 D3DFMT_D16, 86 // D3DFMT_D32F_LOCKABLE, 87 // D3DFMT_D24FS8 88 }; 89 90 enum 91 { 92 MAX_VERTEX_CONSTANT_VECTORS_D3D9 = 256, 93 MAX_PIXEL_CONSTANT_VECTORS_SM2 = 32, 94 MAX_PIXEL_CONSTANT_VECTORS_SM3 = 224, 95 MAX_VARYING_VECTORS_SM2 = 8, 96 MAX_VARYING_VECTORS_SM3 = 10, 97 98 MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 = 4 99 }; 100 101 Renderer9::Renderer9(egl::Display *display, EGLNativeDisplayType hDc, EGLint requestedDisplay) 102 : Renderer(display), 103 mDc(hDc) 104 { 105 mD3d9Module = NULL; 106 107 mD3d9 = NULL; 108 mD3d9Ex = NULL; 109 mDevice = NULL; 110 mDeviceEx = NULL; 111 mDeviceWindow = NULL; 112 mBlit = NULL; 113 114 mAdapter = D3DADAPTER_DEFAULT; 115 116 #if REF_RAST == 1 || defined(FORCE_REF_RAST) 117 mDeviceType = D3DDEVTYPE_REF; 118 #else 119 mDeviceType = D3DDEVTYPE_HAL; 120 #endif 121 122 mDeviceLost = false; 123 124 mMaskedClearSavedState = NULL; 125 126 mVertexDataManager = NULL; 127 mIndexDataManager = NULL; 128 mLineLoopIB = NULL; 129 mCountingIB = NULL; 130 131 mMaxNullColorbufferLRU = 0; 132 for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++) 133 { 134 mNullColorbufferCache[i].lruCount = 0; 135 mNullColorbufferCache[i].width = 0; 136 mNullColorbufferCache[i].height = 0; 137 mNullColorbufferCache[i].buffer = NULL; 138 } 139 140 mAppliedVertexShader = NULL; 141 mAppliedPixelShader = NULL; 142 mAppliedProgramSerial = 0; 143 } 144 145 Renderer9::~Renderer9() 146 { 147 if (mDevice) 148 { 149 // If the device is lost, reset it first to prevent leaving the driver in an unstable state 150 if (testDeviceLost(false)) 151 { 152 resetDevice(); 153 } 154 } 155 156 release(); 157 } 158 159 void Renderer9::release() 160 { 161 releaseShaderCompiler(); 162 releaseDeviceResources(); 163 164 SafeRelease(mDevice); 165 SafeRelease(mDeviceEx); 166 SafeRelease(mD3d9); 167 SafeRelease(mD3d9Ex); 168 169 mCompiler.release(); 170 171 if (mDeviceWindow) 172 { 173 DestroyWindow(mDeviceWindow); 174 mDeviceWindow = NULL; 175 } 176 177 mD3d9Module = NULL; 178 } 179 180 Renderer9 *Renderer9::makeRenderer9(Renderer *renderer) 181 { 182 ASSERT(HAS_DYNAMIC_TYPE(rx::Renderer9*, renderer)); 183 return static_cast<rx::Renderer9*>(renderer); 184 } 185 186 EGLint Renderer9::initialize() 187 { 188 if (!mCompiler.initialize()) 189 { 190 return EGL_NOT_INITIALIZED; 191 } 192 193 TRACE_EVENT0("gpu", "GetModuleHandle_d3d9"); 194 mD3d9Module = GetModuleHandle(TEXT("d3d9.dll")); 195 196 if (mD3d9Module == NULL) 197 { 198 ERR("No D3D9 module found - aborting!\n"); 199 return EGL_NOT_INITIALIZED; 200 } 201 202 typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex**); 203 Direct3DCreate9ExFunc Direct3DCreate9ExPtr = reinterpret_cast<Direct3DCreate9ExFunc>(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex")); 204 205 // Use Direct3D9Ex if available. Among other things, this version is less 206 // inclined to report a lost context, for example when the user switches 207 // desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are available. 208 if (ANGLE_ENABLE_D3D9EX && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex))) 209 { 210 TRACE_EVENT0("gpu", "D3d9Ex_QueryInterface"); 211 ASSERT(mD3d9Ex); 212 mD3d9Ex->QueryInterface(__uuidof(IDirect3D9), reinterpret_cast<void**>(&mD3d9)); 213 ASSERT(mD3d9); 214 } 215 else 216 { 217 TRACE_EVENT0("gpu", "Direct3DCreate9"); 218 mD3d9 = Direct3DCreate9(D3D_SDK_VERSION); 219 } 220 221 if (!mD3d9) 222 { 223 ERR("Could not create D3D9 device - aborting!\n"); 224 return EGL_NOT_INITIALIZED; 225 } 226 227 if (mDc != NULL) 228 { 229 // UNIMPLEMENTED(); // FIXME: Determine which adapter index the device context corresponds to 230 } 231 232 HRESULT result; 233 234 // Give up on getting device caps after about one second. 235 { 236 TRACE_EVENT0("gpu", "GetDeviceCaps"); 237 for (int i = 0; i < 10; ++i) 238 { 239 result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps); 240 if (SUCCEEDED(result)) 241 { 242 break; 243 } 244 else if (result == D3DERR_NOTAVAILABLE) 245 { 246 Sleep(100); // Give the driver some time to initialize/recover 247 } 248 else if (FAILED(result)) // D3DERR_OUTOFVIDEOMEMORY, E_OUTOFMEMORY, D3DERR_INVALIDDEVICE, or another error we can't recover from 249 { 250 ERR("failed to get device caps (0x%x)\n", result); 251 return EGL_NOT_INITIALIZED; 252 } 253 } 254 } 255 256 if (mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(2, 0)) 257 { 258 ERR("Renderer does not support PS 2.0. aborting!\n"); 259 return EGL_NOT_INITIALIZED; 260 } 261 262 // When DirectX9 is running with an older DirectX8 driver, a StretchRect from a regular texture to a render target texture is not supported. 263 // This is required by Texture2D::ensureRenderTarget. 264 if ((mDeviceCaps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES) == 0) 265 { 266 ERR("Renderer does not support stretctrect from textures!\n"); 267 return EGL_NOT_INITIALIZED; 268 } 269 270 { 271 TRACE_EVENT0("gpu", "GetAdapterIdentifier"); 272 mD3d9->GetAdapterIdentifier(mAdapter, 0, &mAdapterIdentifier); 273 } 274 275 mMinSwapInterval = 4; 276 mMaxSwapInterval = 0; 277 278 if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE) 279 { 280 mMinSwapInterval = std::min(mMinSwapInterval, 0); 281 mMaxSwapInterval = std::max(mMaxSwapInterval, 0); 282 } 283 if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_ONE) 284 { 285 mMinSwapInterval = std::min(mMinSwapInterval, 1); 286 mMaxSwapInterval = std::max(mMaxSwapInterval, 1); 287 } 288 if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_TWO) 289 { 290 mMinSwapInterval = std::min(mMinSwapInterval, 2); 291 mMaxSwapInterval = std::max(mMaxSwapInterval, 2); 292 } 293 if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_THREE) 294 { 295 mMinSwapInterval = std::min(mMinSwapInterval, 3); 296 mMaxSwapInterval = std::max(mMaxSwapInterval, 3); 297 } 298 if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_FOUR) 299 { 300 mMinSwapInterval = std::min(mMinSwapInterval, 4); 301 mMaxSwapInterval = std::max(mMaxSwapInterval, 4); 302 } 303 304 static const TCHAR windowName[] = TEXT("AngleHiddenWindow"); 305 static const TCHAR className[] = TEXT("STATIC"); 306 307 { 308 TRACE_EVENT0("gpu", "CreateWindowEx"); 309 mDeviceWindow = CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL); 310 } 311 312 D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters(); 313 DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES; 314 315 { 316 TRACE_EVENT0("gpu", "D3d9_CreateDevice"); 317 result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice); 318 } 319 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DEVICELOST) 320 { 321 return EGL_BAD_ALLOC; 322 } 323 324 if (FAILED(result)) 325 { 326 TRACE_EVENT0("gpu", "D3d9_CreateDevice2"); 327 result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParameters, &mDevice); 328 329 if (FAILED(result)) 330 { 331 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_NOTAVAILABLE || result == D3DERR_DEVICELOST); 332 return EGL_BAD_ALLOC; 333 } 334 } 335 336 if (mD3d9Ex) 337 { 338 TRACE_EVENT0("gpu", "mDevice_QueryInterface"); 339 result = mDevice->QueryInterface(__uuidof(IDirect3DDevice9Ex), (void**)&mDeviceEx); 340 ASSERT(SUCCEEDED(result)); 341 } 342 343 { 344 TRACE_EVENT0("gpu", "ShaderCache initialize"); 345 mVertexShaderCache.initialize(mDevice); 346 mPixelShaderCache.initialize(mDevice); 347 } 348 349 D3DDISPLAYMODE currentDisplayMode; 350 mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); 351 352 // Check vertex texture support 353 // Only Direct3D 10 ready devices support all the necessary vertex texture formats. 354 // We test this using D3D9 by checking support for the R16F format. 355 mVertexTextureSupport = mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0) && 356 SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 357 D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_R16F)); 358 359 initializeDevice(); 360 361 return EGL_SUCCESS; 362 } 363 364 // do any one-time device initialization 365 // NOTE: this is also needed after a device lost/reset 366 // to reset the scene status and ensure the default states are reset. 367 void Renderer9::initializeDevice() 368 { 369 // Permanent non-default states 370 mDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE); 371 mDevice->SetRenderState(D3DRS_LASTPIXEL, FALSE); 372 373 if (mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0)) 374 { 375 mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, (DWORD&)mDeviceCaps.MaxPointSize); 376 } 377 else 378 { 379 mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, 0x3F800000); // 1.0f 380 } 381 382 const gl::Caps &rendererCaps = getRendererCaps(); 383 384 mForceSetVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits); 385 mCurVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits); 386 387 mForceSetPixelSamplerStates.resize(rendererCaps.maxTextureImageUnits); 388 mCurPixelSamplerStates.resize(rendererCaps.maxTextureImageUnits); 389 390 mCurVertexTextureSerials.resize(rendererCaps.maxVertexTextureImageUnits); 391 mCurPixelTextureSerials.resize(rendererCaps.maxTextureImageUnits); 392 393 markAllStateDirty(); 394 395 mSceneStarted = false; 396 397 ASSERT(!mBlit && !mVertexDataManager && !mIndexDataManager); 398 mBlit = new Blit9(this); 399 mVertexDataManager = new rx::VertexDataManager(this); 400 mIndexDataManager = new rx::IndexDataManager(this); 401 } 402 403 D3DPRESENT_PARAMETERS Renderer9::getDefaultPresentParameters() 404 { 405 D3DPRESENT_PARAMETERS presentParameters = {0}; 406 407 // The default swap chain is never actually used. Surface will create a new swap chain with the proper parameters. 408 presentParameters.AutoDepthStencilFormat = D3DFMT_UNKNOWN; 409 presentParameters.BackBufferCount = 1; 410 presentParameters.BackBufferFormat = D3DFMT_UNKNOWN; 411 presentParameters.BackBufferWidth = 1; 412 presentParameters.BackBufferHeight = 1; 413 presentParameters.EnableAutoDepthStencil = FALSE; 414 presentParameters.Flags = 0; 415 presentParameters.hDeviceWindow = mDeviceWindow; 416 presentParameters.MultiSampleQuality = 0; 417 presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE; 418 presentParameters.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; 419 presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD; 420 presentParameters.Windowed = TRUE; 421 422 return presentParameters; 423 } 424 425 int Renderer9::generateConfigs(ConfigDesc **configDescList) 426 { 427 D3DDISPLAYMODE currentDisplayMode; 428 mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); 429 430 unsigned int numRenderFormats = ArraySize(RenderTargetFormats); 431 unsigned int numDepthFormats = ArraySize(DepthStencilFormats); 432 (*configDescList) = new ConfigDesc[numRenderFormats * numDepthFormats]; 433 int numConfigs = 0; 434 435 for (unsigned int formatIndex = 0; formatIndex < numRenderFormats; formatIndex++) 436 { 437 const d3d9::D3DFormat &renderTargetFormatInfo = d3d9::GetD3DFormatInfo(RenderTargetFormats[formatIndex]); 438 const gl::TextureCaps &renderTargetFormatCaps = getRendererTextureCaps().get(renderTargetFormatInfo.internalFormat); 439 if (renderTargetFormatCaps.renderable) 440 { 441 for (unsigned int depthStencilIndex = 0; depthStencilIndex < numDepthFormats; depthStencilIndex++) 442 { 443 const d3d9::D3DFormat &depthStencilFormatInfo = d3d9::GetD3DFormatInfo(DepthStencilFormats[depthStencilIndex]); 444 const gl::TextureCaps &depthStencilFormatCaps = getRendererTextureCaps().get(depthStencilFormatInfo.internalFormat); 445 if (depthStencilFormatCaps.renderable || DepthStencilFormats[depthStencilIndex] == D3DFMT_UNKNOWN) 446 { 447 ConfigDesc newConfig; 448 newConfig.renderTargetFormat = renderTargetFormatInfo.internalFormat; 449 newConfig.depthStencilFormat = depthStencilFormatInfo.internalFormat; 450 newConfig.multiSample = 0; // FIXME: enumerate multi-sampling 451 newConfig.fastConfig = (currentDisplayMode.Format == RenderTargetFormats[formatIndex]); 452 newConfig.es3Capable = false; 453 454 (*configDescList)[numConfigs++] = newConfig; 455 } 456 } 457 } 458 } 459 460 return numConfigs; 461 } 462 463 void Renderer9::deleteConfigs(ConfigDesc *configDescList) 464 { 465 delete [] (configDescList); 466 } 467 468 void Renderer9::startScene() 469 { 470 if (!mSceneStarted) 471 { 472 long result = mDevice->BeginScene(); 473 if (SUCCEEDED(result)) { 474 // This is defensive checking against the device being 475 // lost at unexpected times. 476 mSceneStarted = true; 477 } 478 } 479 } 480 481 void Renderer9::endScene() 482 { 483 if (mSceneStarted) 484 { 485 // EndScene can fail if the device was lost, for example due 486 // to a TDR during a draw call. 487 mDevice->EndScene(); 488 mSceneStarted = false; 489 } 490 } 491 492 void Renderer9::sync(bool block) 493 { 494 HRESULT result; 495 496 IDirect3DQuery9* query = allocateEventQuery(); 497 if (!query) 498 { 499 return; 500 } 501 502 result = query->Issue(D3DISSUE_END); 503 ASSERT(SUCCEEDED(result)); 504 505 do 506 { 507 result = query->GetData(NULL, 0, D3DGETDATA_FLUSH); 508 509 if(block && result == S_FALSE) 510 { 511 // Keep polling, but allow other threads to do something useful first 512 Sleep(0); 513 // explicitly check for device loss 514 // some drivers seem to return S_FALSE even if the device is lost 515 // instead of D3DERR_DEVICELOST like they should 516 if (testDeviceLost(false)) 517 { 518 result = D3DERR_DEVICELOST; 519 } 520 } 521 } 522 while(block && result == S_FALSE); 523 524 freeEventQuery(query); 525 526 if (d3d9::isDeviceLostError(result)) 527 { 528 notifyDeviceLost(); 529 } 530 } 531 532 SwapChain *Renderer9::createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) 533 { 534 return new rx::SwapChain9(this, window, shareHandle, backBufferFormat, depthBufferFormat); 535 } 536 537 IDirect3DQuery9* Renderer9::allocateEventQuery() 538 { 539 IDirect3DQuery9 *query = NULL; 540 541 if (mEventQueryPool.empty()) 542 { 543 HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &query); 544 UNUSED_ASSERTION_VARIABLE(result); 545 ASSERT(SUCCEEDED(result)); 546 } 547 else 548 { 549 query = mEventQueryPool.back(); 550 mEventQueryPool.pop_back(); 551 } 552 553 return query; 554 } 555 556 void Renderer9::freeEventQuery(IDirect3DQuery9* query) 557 { 558 if (mEventQueryPool.size() > 1000) 559 { 560 SafeRelease(query); 561 } 562 else 563 { 564 mEventQueryPool.push_back(query); 565 } 566 } 567 568 IDirect3DVertexShader9 *Renderer9::createVertexShader(const DWORD *function, size_t length) 569 { 570 return mVertexShaderCache.create(function, length); 571 } 572 573 IDirect3DPixelShader9 *Renderer9::createPixelShader(const DWORD *function, size_t length) 574 { 575 return mPixelShaderCache.create(function, length); 576 } 577 578 HRESULT Renderer9::createVertexBuffer(UINT Length, DWORD Usage, IDirect3DVertexBuffer9 **ppVertexBuffer) 579 { 580 D3DPOOL Pool = getBufferPool(Usage); 581 return mDevice->CreateVertexBuffer(Length, Usage, 0, Pool, ppVertexBuffer, NULL); 582 } 583 584 VertexBuffer *Renderer9::createVertexBuffer() 585 { 586 return new VertexBuffer9(this); 587 } 588 589 HRESULT Renderer9::createIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, IDirect3DIndexBuffer9 **ppIndexBuffer) 590 { 591 D3DPOOL Pool = getBufferPool(Usage); 592 return mDevice->CreateIndexBuffer(Length, Usage, Format, Pool, ppIndexBuffer, NULL); 593 } 594 595 IndexBuffer *Renderer9::createIndexBuffer() 596 { 597 return new IndexBuffer9(this); 598 } 599 600 BufferImpl *Renderer9::createBuffer() 601 { 602 return new Buffer9(this); 603 } 604 605 VertexArrayImpl *Renderer9::createVertexArray() 606 { 607 return new VertexArray9(this); 608 } 609 610 QueryImpl *Renderer9::createQuery(GLenum type) 611 { 612 return new Query9(this, type); 613 } 614 615 FenceImpl *Renderer9::createFence() 616 { 617 return new Fence9(this); 618 } 619 620 TransformFeedbackImpl* Renderer9::createTransformFeedback() 621 { 622 return new TransformFeedbackD3D(); 623 } 624 625 bool Renderer9::supportsFastCopyBufferToTexture(GLenum internalFormat) const 626 { 627 // Pixel buffer objects are not supported in D3D9, since D3D9 is ES2-only and PBOs are ES3. 628 return false; 629 } 630 631 bool Renderer9::fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget, 632 GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) 633 { 634 // Pixel buffer objects are not supported in D3D9, since D3D9 is ES2-only and PBOs are ES3. 635 UNREACHABLE(); 636 return false; 637 } 638 639 void Renderer9::generateSwizzle(gl::Texture *texture) 640 { 641 // Swizzled textures are not available in ES2 or D3D9 642 UNREACHABLE(); 643 } 644 645 void Renderer9::setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &samplerState) 646 { 647 std::vector<bool> &forceSetSamplers = (type == gl::SAMPLER_PIXEL) ? mForceSetPixelSamplerStates : mForceSetVertexSamplerStates; 648 std::vector<gl::SamplerState> &appliedSamplers = (type == gl::SAMPLER_PIXEL) ? mCurPixelSamplerStates: mCurVertexSamplerStates; 649 650 if (forceSetSamplers[index] || memcmp(&samplerState, &appliedSamplers[index], sizeof(gl::SamplerState)) != 0) 651 { 652 int d3dSamplerOffset = (type == gl::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0; 653 int d3dSampler = index + d3dSamplerOffset; 654 655 mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSU, gl_d3d9::ConvertTextureWrap(samplerState.wrapS)); 656 mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSV, gl_d3d9::ConvertTextureWrap(samplerState.wrapT)); 657 658 mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAGFILTER, gl_d3d9::ConvertMagFilter(samplerState.magFilter, samplerState.maxAnisotropy)); 659 D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter; 660 gl_d3d9::ConvertMinFilter(samplerState.minFilter, &d3dMinFilter, &d3dMipFilter, samplerState.maxAnisotropy); 661 mDevice->SetSamplerState(d3dSampler, D3DSAMP_MINFILTER, d3dMinFilter); 662 mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPFILTER, d3dMipFilter); 663 mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXMIPLEVEL, samplerState.baseLevel); 664 if (getRendererExtensions().textureFilterAnisotropic) 665 { 666 mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXANISOTROPY, (DWORD)samplerState.maxAnisotropy); 667 } 668 } 669 670 forceSetSamplers[index] = false; 671 appliedSamplers[index] = samplerState; 672 } 673 674 void Renderer9::setTexture(gl::SamplerType type, int index, gl::Texture *texture) 675 { 676 int d3dSamplerOffset = (type == gl::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0; 677 int d3dSampler = index + d3dSamplerOffset; 678 IDirect3DBaseTexture9 *d3dTexture = NULL; 679 unsigned int serial = 0; 680 bool forceSetTexture = false; 681 682 std::vector<unsigned int> &appliedSerials = (type == gl::SAMPLER_PIXEL) ? mCurPixelTextureSerials : mCurVertexTextureSerials; 683 684 if (texture) 685 { 686 TextureD3D* textureImpl = TextureD3D::makeTextureD3D(texture->getImplementation()); 687 688 TextureStorage *texStorage = textureImpl->getNativeTexture(); 689 if (texStorage) 690 { 691 TextureStorage9 *storage9 = TextureStorage9::makeTextureStorage9(texStorage); 692 d3dTexture = storage9->getBaseTexture(); 693 } 694 // If we get NULL back from getBaseTexture here, something went wrong 695 // in the texture class and we're unexpectedly missing the d3d texture 696 ASSERT(d3dTexture != NULL); 697 698 serial = texture->getTextureSerial(); 699 forceSetTexture = textureImpl->hasDirtyImages(); 700 textureImpl->resetDirty(); 701 } 702 703 if (forceSetTexture || appliedSerials[index] != serial) 704 { 705 mDevice->SetTexture(d3dSampler, d3dTexture); 706 } 707 708 appliedSerials[index] = serial; 709 } 710 711 bool Renderer9::setUniformBuffers(const gl::Buffer* /*vertexUniformBuffers*/[], const gl::Buffer* /*fragmentUniformBuffers*/[]) 712 { 713 // No effect in ES2/D3D9 714 return true; 715 } 716 717 void Renderer9::setRasterizerState(const gl::RasterizerState &rasterState) 718 { 719 bool rasterStateChanged = mForceSetRasterState || memcmp(&rasterState, &mCurRasterState, sizeof(gl::RasterizerState)) != 0; 720 721 if (rasterStateChanged) 722 { 723 // Set the cull mode 724 if (rasterState.cullFace) 725 { 726 mDevice->SetRenderState(D3DRS_CULLMODE, gl_d3d9::ConvertCullMode(rasterState.cullMode, rasterState.frontFace)); 727 } 728 else 729 { 730 mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); 731 } 732 733 if (rasterState.polygonOffsetFill) 734 { 735 if (mCurDepthSize > 0) 736 { 737 mDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *(DWORD*)&rasterState.polygonOffsetFactor); 738 739 float depthBias = ldexp(rasterState.polygonOffsetUnits, -static_cast<int>(mCurDepthSize)); 740 mDevice->SetRenderState(D3DRS_DEPTHBIAS, *(DWORD*)&depthBias); 741 } 742 } 743 else 744 { 745 mDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0); 746 mDevice->SetRenderState(D3DRS_DEPTHBIAS, 0); 747 } 748 749 mCurRasterState = rasterState; 750 } 751 752 mForceSetRasterState = false; 753 } 754 755 void Renderer9::setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, 756 unsigned int sampleMask) 757 { 758 bool blendStateChanged = mForceSetBlendState || memcmp(&blendState, &mCurBlendState, sizeof(gl::BlendState)) != 0; 759 bool blendColorChanged = mForceSetBlendState || memcmp(&blendColor, &mCurBlendColor, sizeof(gl::ColorF)) != 0; 760 bool sampleMaskChanged = mForceSetBlendState || sampleMask != mCurSampleMask; 761 762 if (blendStateChanged || blendColorChanged) 763 { 764 if (blendState.blend) 765 { 766 mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); 767 768 if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA && blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA && 769 blendState.destBlendRGB != GL_CONSTANT_ALPHA && blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA) 770 { 771 mDevice->SetRenderState(D3DRS_BLENDFACTOR, gl_d3d9::ConvertColor(blendColor)); 772 } 773 else 774 { 775 mDevice->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(gl::unorm<8>(blendColor.alpha), 776 gl::unorm<8>(blendColor.alpha), 777 gl::unorm<8>(blendColor.alpha), 778 gl::unorm<8>(blendColor.alpha))); 779 } 780 781 mDevice->SetRenderState(D3DRS_SRCBLEND, gl_d3d9::ConvertBlendFunc(blendState.sourceBlendRGB)); 782 mDevice->SetRenderState(D3DRS_DESTBLEND, gl_d3d9::ConvertBlendFunc(blendState.destBlendRGB)); 783 mDevice->SetRenderState(D3DRS_BLENDOP, gl_d3d9::ConvertBlendOp(blendState.blendEquationRGB)); 784 785 if (blendState.sourceBlendRGB != blendState.sourceBlendAlpha || 786 blendState.destBlendRGB != blendState.destBlendAlpha || 787 blendState.blendEquationRGB != blendState.blendEquationAlpha) 788 { 789 mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); 790 791 mDevice->SetRenderState(D3DRS_SRCBLENDALPHA, gl_d3d9::ConvertBlendFunc(blendState.sourceBlendAlpha)); 792 mDevice->SetRenderState(D3DRS_DESTBLENDALPHA, gl_d3d9::ConvertBlendFunc(blendState.destBlendAlpha)); 793 mDevice->SetRenderState(D3DRS_BLENDOPALPHA, gl_d3d9::ConvertBlendOp(blendState.blendEquationAlpha)); 794 } 795 else 796 { 797 mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE); 798 } 799 } 800 else 801 { 802 mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); 803 } 804 805 if (blendState.sampleAlphaToCoverage) 806 { 807 FIXME("Sample alpha to coverage is unimplemented."); 808 } 809 810 gl::FramebufferAttachment *attachment = framebuffer->getFirstColorbuffer(); 811 GLenum internalFormat = attachment ? attachment->getInternalFormat() : GL_NONE; 812 813 // Set the color mask 814 bool zeroColorMaskAllowed = getAdapterVendor() != VENDOR_ID_AMD; 815 // Apparently some ATI cards have a bug where a draw with a zero color 816 // write mask can cause later draws to have incorrect results. Instead, 817 // set a nonzero color write mask but modify the blend state so that no 818 // drawing is done. 819 // http://code.google.com/p/angleproject/issues/detail?id=169 820 821 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); 822 DWORD colorMask = gl_d3d9::ConvertColorMask(formatInfo.redBits > 0 && blendState.colorMaskRed, 823 formatInfo.greenBits > 0 && blendState.colorMaskGreen, 824 formatInfo.blueBits > 0 && blendState.colorMaskBlue, 825 formatInfo.alphaBits > 0 && blendState.colorMaskAlpha); 826 if (colorMask == 0 && !zeroColorMaskAllowed) 827 { 828 // Enable green channel, but set blending so nothing will be drawn. 829 mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_GREEN); 830 mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); 831 832 mDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO); 833 mDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); 834 mDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); 835 } 836 else 837 { 838 mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, colorMask); 839 } 840 841 mDevice->SetRenderState(D3DRS_DITHERENABLE, blendState.dither ? TRUE : FALSE); 842 843 mCurBlendState = blendState; 844 mCurBlendColor = blendColor; 845 } 846 847 if (sampleMaskChanged) 848 { 849 // Set the multisample mask 850 mDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE); 851 mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, static_cast<DWORD>(sampleMask)); 852 853 mCurSampleMask = sampleMask; 854 } 855 856 mForceSetBlendState = false; 857 } 858 859 void Renderer9::setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, 860 int stencilBackRef, bool frontFaceCCW) 861 { 862 bool depthStencilStateChanged = mForceSetDepthStencilState || 863 memcmp(&depthStencilState, &mCurDepthStencilState, sizeof(gl::DepthStencilState)) != 0; 864 bool stencilRefChanged = mForceSetDepthStencilState || stencilRef != mCurStencilRef || 865 stencilBackRef != mCurStencilBackRef; 866 bool frontFaceCCWChanged = mForceSetDepthStencilState || frontFaceCCW != mCurFrontFaceCCW; 867 868 if (depthStencilStateChanged) 869 { 870 if (depthStencilState.depthTest) 871 { 872 mDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE); 873 mDevice->SetRenderState(D3DRS_ZFUNC, gl_d3d9::ConvertComparison(depthStencilState.depthFunc)); 874 } 875 else 876 { 877 mDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); 878 } 879 880 mCurDepthStencilState = depthStencilState; 881 } 882 883 if (depthStencilStateChanged || stencilRefChanged || frontFaceCCWChanged) 884 { 885 if (depthStencilState.stencilTest && mCurStencilSize > 0) 886 { 887 mDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE); 888 mDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE); 889 890 // FIXME: Unsupported by D3D9 891 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF; 892 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK; 893 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK; 894 895 ASSERT(depthStencilState.stencilWritemask == depthStencilState.stencilBackWritemask); 896 ASSERT(stencilRef == stencilBackRef); 897 ASSERT(depthStencilState.stencilMask == depthStencilState.stencilBackMask); 898 899 // get the maximum size of the stencil ref 900 unsigned int maxStencil = (1 << mCurStencilSize) - 1; 901 902 mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, 903 depthStencilState.stencilWritemask); 904 mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, 905 gl_d3d9::ConvertComparison(depthStencilState.stencilFunc)); 906 907 mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, 908 (stencilRef < (int)maxStencil) ? stencilRef : maxStencil); 909 mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, 910 depthStencilState.stencilMask); 911 912 mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, 913 gl_d3d9::ConvertStencilOp(depthStencilState.stencilFail)); 914 mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, 915 gl_d3d9::ConvertStencilOp(depthStencilState.stencilPassDepthFail)); 916 mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, 917 gl_d3d9::ConvertStencilOp(depthStencilState.stencilPassDepthPass)); 918 919 mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, 920 depthStencilState.stencilBackWritemask); 921 mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, 922 gl_d3d9::ConvertComparison(depthStencilState.stencilBackFunc)); 923 924 mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, 925 (stencilBackRef < (int)maxStencil) ? stencilBackRef : maxStencil); 926 mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, 927 depthStencilState.stencilBackMask); 928 929 mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, 930 gl_d3d9::ConvertStencilOp(depthStencilState.stencilBackFail)); 931 mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, 932 gl_d3d9::ConvertStencilOp(depthStencilState.stencilBackPassDepthFail)); 933 mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, 934 gl_d3d9::ConvertStencilOp(depthStencilState.stencilBackPassDepthPass)); 935 } 936 else 937 { 938 mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); 939 } 940 941 mDevice->SetRenderState(D3DRS_ZWRITEENABLE, depthStencilState.depthMask ? TRUE : FALSE); 942 943 mCurStencilRef = stencilRef; 944 mCurStencilBackRef = stencilBackRef; 945 mCurFrontFaceCCW = frontFaceCCW; 946 } 947 948 mForceSetDepthStencilState = false; 949 } 950 951 void Renderer9::setScissorRectangle(const gl::Rectangle &scissor, bool enabled) 952 { 953 bool scissorChanged = mForceSetScissor || 954 memcmp(&scissor, &mCurScissor, sizeof(gl::Rectangle)) != 0 || 955 enabled != mScissorEnabled; 956 957 if (scissorChanged) 958 { 959 if (enabled) 960 { 961 RECT rect; 962 rect.left = gl::clamp(scissor.x, 0, static_cast<int>(mRenderTargetDesc.width)); 963 rect.top = gl::clamp(scissor.y, 0, static_cast<int>(mRenderTargetDesc.height)); 964 rect.right = gl::clamp(scissor.x + scissor.width, 0, static_cast<int>(mRenderTargetDesc.width)); 965 rect.bottom = gl::clamp(scissor.y + scissor.height, 0, static_cast<int>(mRenderTargetDesc.height)); 966 mDevice->SetScissorRect(&rect); 967 } 968 969 mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, enabled ? TRUE : FALSE); 970 971 mScissorEnabled = enabled; 972 mCurScissor = scissor; 973 } 974 975 mForceSetScissor = false; 976 } 977 978 void Renderer9::setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, 979 bool ignoreViewport) 980 { 981 gl::Rectangle actualViewport = viewport; 982 float actualZNear = gl::clamp01(zNear); 983 float actualZFar = gl::clamp01(zFar); 984 if (ignoreViewport) 985 { 986 actualViewport.x = 0; 987 actualViewport.y = 0; 988 actualViewport.width = mRenderTargetDesc.width; 989 actualViewport.height = mRenderTargetDesc.height; 990 actualZNear = 0.0f; 991 actualZFar = 1.0f; 992 } 993 994 D3DVIEWPORT9 dxViewport; 995 dxViewport.X = gl::clamp(actualViewport.x, 0, static_cast<int>(mRenderTargetDesc.width)); 996 dxViewport.Y = gl::clamp(actualViewport.y, 0, static_cast<int>(mRenderTargetDesc.height)); 997 dxViewport.Width = gl::clamp(actualViewport.width, 0, static_cast<int>(mRenderTargetDesc.width) - static_cast<int>(dxViewport.X)); 998 dxViewport.Height = gl::clamp(actualViewport.height, 0, static_cast<int>(mRenderTargetDesc.height) - static_cast<int>(dxViewport.Y)); 999 dxViewport.MinZ = actualZNear; 1000 dxViewport.MaxZ = actualZFar; 1001 1002 float depthFront = !gl::IsTriangleMode(drawMode) ? 0.0f : (frontFace == GL_CCW ? 1.0f : -1.0f); 1003 1004 bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 || 1005 actualZNear != mCurNear || actualZFar != mCurFar || mCurDepthFront != depthFront; 1006 if (viewportChanged) 1007 { 1008 mDevice->SetViewport(&dxViewport); 1009 1010 mCurViewport = actualViewport; 1011 mCurNear = actualZNear; 1012 mCurFar = actualZFar; 1013 mCurDepthFront = depthFront; 1014 1015 dx_VertexConstants vc = {0}; 1016 dx_PixelConstants pc = {0}; 1017 1018 vc.viewAdjust[0] = (float)((actualViewport.width - (int)dxViewport.Width) + 2 * (actualViewport.x - (int)dxViewport.X) - 1) / dxViewport.Width; 1019 vc.viewAdjust[1] = (float)((actualViewport.height - (int)dxViewport.Height) + 2 * (actualViewport.y - (int)dxViewport.Y) - 1) / dxViewport.Height; 1020 vc.viewAdjust[2] = (float)actualViewport.width / dxViewport.Width; 1021 vc.viewAdjust[3] = (float)actualViewport.height / dxViewport.Height; 1022 1023 pc.viewCoords[0] = actualViewport.width * 0.5f; 1024 pc.viewCoords[1] = actualViewport.height * 0.5f; 1025 pc.viewCoords[2] = actualViewport.x + (actualViewport.width * 0.5f); 1026 pc.viewCoords[3] = actualViewport.y + (actualViewport.height * 0.5f); 1027 1028 pc.depthFront[0] = (actualZFar - actualZNear) * 0.5f; 1029 pc.depthFront[1] = (actualZNear + actualZFar) * 0.5f; 1030 pc.depthFront[2] = depthFront; 1031 1032 vc.depthRange[0] = actualZNear; 1033 vc.depthRange[1] = actualZFar; 1034 vc.depthRange[2] = actualZFar - actualZNear; 1035 1036 pc.depthRange[0] = actualZNear; 1037 pc.depthRange[1] = actualZFar; 1038 pc.depthRange[2] = actualZFar - actualZNear; 1039 1040 if (memcmp(&vc, &mVertexConstants, sizeof(dx_VertexConstants)) != 0) 1041 { 1042 mVertexConstants = vc; 1043 mDxUniformsDirty = true; 1044 } 1045 1046 if (memcmp(&pc, &mPixelConstants, sizeof(dx_PixelConstants)) != 0) 1047 { 1048 mPixelConstants = pc; 1049 mDxUniformsDirty = true; 1050 } 1051 } 1052 1053 mForceSetViewport = false; 1054 } 1055 1056 bool Renderer9::applyPrimitiveType(GLenum mode, GLsizei count) 1057 { 1058 switch (mode) 1059 { 1060 case GL_POINTS: 1061 mPrimitiveType = D3DPT_POINTLIST; 1062 mPrimitiveCount = count; 1063 break; 1064 case GL_LINES: 1065 mPrimitiveType = D3DPT_LINELIST; 1066 mPrimitiveCount = count / 2; 1067 break; 1068 case GL_LINE_LOOP: 1069 mPrimitiveType = D3DPT_LINESTRIP; 1070 mPrimitiveCount = count - 1; // D3D doesn't support line loops, so we draw the last line separately 1071 break; 1072 case GL_LINE_STRIP: 1073 mPrimitiveType = D3DPT_LINESTRIP; 1074 mPrimitiveCount = count - 1; 1075 break; 1076 case GL_TRIANGLES: 1077 mPrimitiveType = D3DPT_TRIANGLELIST; 1078 mPrimitiveCount = count / 3; 1079 break; 1080 case GL_TRIANGLE_STRIP: 1081 mPrimitiveType = D3DPT_TRIANGLESTRIP; 1082 mPrimitiveCount = count - 2; 1083 break; 1084 case GL_TRIANGLE_FAN: 1085 mPrimitiveType = D3DPT_TRIANGLEFAN; 1086 mPrimitiveCount = count - 2; 1087 break; 1088 default: 1089 UNREACHABLE(); 1090 return false; 1091 } 1092 1093 return mPrimitiveCount > 0; 1094 } 1095 1096 1097 gl::FramebufferAttachment *Renderer9::getNullColorbuffer(gl::FramebufferAttachment *depthbuffer) 1098 { 1099 if (!depthbuffer) 1100 { 1101 ERR("Unexpected null depthbuffer for depth-only FBO."); 1102 return NULL; 1103 } 1104 1105 GLsizei width = depthbuffer->getWidth(); 1106 GLsizei height = depthbuffer->getHeight(); 1107 1108 // search cached nullcolorbuffers 1109 for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++) 1110 { 1111 if (mNullColorbufferCache[i].buffer != NULL && 1112 mNullColorbufferCache[i].width == width && 1113 mNullColorbufferCache[i].height == height) 1114 { 1115 mNullColorbufferCache[i].lruCount = ++mMaxNullColorbufferLRU; 1116 return mNullColorbufferCache[i].buffer; 1117 } 1118 } 1119 1120 gl::Renderbuffer *nullRenderbuffer = new gl::Renderbuffer(0, new gl::Colorbuffer(this, width, height, GL_NONE, 0)); 1121 gl::RenderbufferAttachment *nullbuffer = new gl::RenderbufferAttachment(GL_NONE, nullRenderbuffer); 1122 1123 // add nullbuffer to the cache 1124 NullColorbufferCacheEntry *oldest = &mNullColorbufferCache[0]; 1125 for (int i = 1; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++) 1126 { 1127 if (mNullColorbufferCache[i].lruCount < oldest->lruCount) 1128 { 1129 oldest = &mNullColorbufferCache[i]; 1130 } 1131 } 1132 1133 delete oldest->buffer; 1134 oldest->buffer = nullbuffer; 1135 oldest->lruCount = ++mMaxNullColorbufferLRU; 1136 oldest->width = width; 1137 oldest->height = height; 1138 1139 return nullbuffer; 1140 } 1141 1142 bool Renderer9::applyRenderTarget(gl::Framebuffer *framebuffer) 1143 { 1144 // if there is no color attachment we must synthesize a NULL colorattachment 1145 // to keep the D3D runtime happy. This should only be possible if depth texturing. 1146 gl::FramebufferAttachment *attachment = framebuffer->getColorbuffer(0); 1147 if (!attachment) 1148 { 1149 attachment = getNullColorbuffer(framebuffer->getDepthbuffer()); 1150 } 1151 if (!attachment) 1152 { 1153 ERR("unable to locate renderbuffer for FBO."); 1154 return false; 1155 } 1156 1157 bool renderTargetChanged = false; 1158 unsigned int renderTargetSerial = GetAttachmentSerial(attachment); 1159 if (renderTargetSerial != mAppliedRenderTargetSerial) 1160 { 1161 // Apply the render target on the device 1162 IDirect3DSurface9 *renderTargetSurface = NULL; 1163 1164 RenderTarget9 *renderTarget = d3d9::GetAttachmentRenderTarget(attachment); 1165 if (renderTarget) 1166 { 1167 renderTargetSurface = renderTarget->getSurface(); 1168 } 1169 1170 if (!renderTargetSurface) 1171 { 1172 ERR("render target pointer unexpectedly null."); 1173 return false; // Context must be lost 1174 } 1175 1176 mDevice->SetRenderTarget(0, renderTargetSurface); 1177 SafeRelease(renderTargetSurface); 1178 1179 mAppliedRenderTargetSerial = renderTargetSerial; 1180 renderTargetChanged = true; 1181 } 1182 1183 gl::FramebufferAttachment *depthStencil = framebuffer->getDepthbuffer(); 1184 unsigned int depthbufferSerial = 0; 1185 unsigned int stencilbufferSerial = 0; 1186 if (depthStencil) 1187 { 1188 depthbufferSerial = GetAttachmentSerial(depthStencil); 1189 } 1190 else if (framebuffer->getStencilbuffer()) 1191 { 1192 depthStencil = framebuffer->getStencilbuffer(); 1193 stencilbufferSerial = GetAttachmentSerial(depthStencil); 1194 } 1195 1196 if (depthbufferSerial != mAppliedDepthbufferSerial || 1197 stencilbufferSerial != mAppliedStencilbufferSerial || 1198 !mDepthStencilInitialized) 1199 { 1200 unsigned int depthSize = 0; 1201 unsigned int stencilSize = 0; 1202 1203 // Apply the depth stencil on the device 1204 if (depthStencil) 1205 { 1206 IDirect3DSurface9 *depthStencilSurface = NULL; 1207 rx::RenderTarget9 *depthStencilRenderTarget = d3d9::GetAttachmentRenderTarget(depthStencil); 1208 1209 if (depthStencilRenderTarget) 1210 { 1211 depthStencilSurface = depthStencilRenderTarget->getSurface(); 1212 } 1213 1214 if (!depthStencilSurface) 1215 { 1216 ERR("depth stencil pointer unexpectedly null."); 1217 return false; // Context must be lost 1218 } 1219 1220 mDevice->SetDepthStencilSurface(depthStencilSurface); 1221 SafeRelease(depthStencilSurface); 1222 1223 depthSize = depthStencil->getDepthSize(); 1224 stencilSize = depthStencil->getStencilSize(); 1225 } 1226 else 1227 { 1228 mDevice->SetDepthStencilSurface(NULL); 1229 } 1230 1231 if (!mDepthStencilInitialized || depthSize != mCurDepthSize) 1232 { 1233 mCurDepthSize = depthSize; 1234 mForceSetRasterState = true; 1235 } 1236 1237 if (!mDepthStencilInitialized || stencilSize != mCurStencilSize) 1238 { 1239 mCurStencilSize = stencilSize; 1240 mForceSetDepthStencilState = true; 1241 } 1242 1243 mAppliedDepthbufferSerial = depthbufferSerial; 1244 mAppliedStencilbufferSerial = stencilbufferSerial; 1245 mDepthStencilInitialized = true; 1246 } 1247 1248 if (renderTargetChanged || !mRenderTargetDescInitialized) 1249 { 1250 mForceSetScissor = true; 1251 mForceSetViewport = true; 1252 mForceSetBlendState = true; 1253 1254 mRenderTargetDesc.width = attachment->getWidth(); 1255 mRenderTargetDesc.height = attachment->getHeight(); 1256 mRenderTargetDesc.format = attachment->getActualFormat(); 1257 mRenderTargetDescInitialized = true; 1258 } 1259 1260 return true; 1261 } 1262 1263 gl::Error Renderer9::applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], const gl::VertexAttribCurrentValueData currentValues[], 1264 GLint first, GLsizei count, GLsizei instances) 1265 { 1266 TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS]; 1267 gl::Error error = mVertexDataManager->prepareVertexData(vertexAttributes, currentValues, programBinary, first, count, attributes, instances); 1268 if (error.isError()) 1269 { 1270 return error; 1271 } 1272 1273 return mVertexDeclarationCache.applyDeclaration(mDevice, attributes, programBinary, instances, &mRepeatDraw); 1274 } 1275 1276 // Applies the indices and element array bindings to the Direct3D 9 device 1277 gl::Error Renderer9::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) 1278 { 1279 gl::Error error = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo); 1280 if (error.isError()) 1281 { 1282 return error; 1283 } 1284 1285 // Directly binding the storage buffer is not supported for d3d9 1286 ASSERT(indexInfo->storage == NULL); 1287 1288 if (indexInfo->serial != mAppliedIBSerial) 1289 { 1290 IndexBuffer9* indexBuffer = IndexBuffer9::makeIndexBuffer9(indexInfo->indexBuffer); 1291 1292 mDevice->SetIndices(indexBuffer->getBuffer()); 1293 mAppliedIBSerial = indexInfo->serial; 1294 } 1295 1296 return gl::Error(GL_NO_ERROR); 1297 } 1298 1299 void Renderer9::applyTransformFeedbackBuffers(gl::Buffer *transformFeedbackBuffers[], GLintptr offsets[]) 1300 { 1301 UNREACHABLE(); 1302 } 1303 1304 void Renderer9::drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive) 1305 { 1306 ASSERT(!transformFeedbackActive); 1307 1308 startScene(); 1309 1310 if (mode == GL_LINE_LOOP) 1311 { 1312 drawLineLoop(count, GL_NONE, NULL, 0, NULL); 1313 } 1314 else if (instances > 0) 1315 { 1316 StaticIndexBufferInterface *countingIB = getCountingIB(count); 1317 if (!countingIB) 1318 { 1319 return; 1320 } 1321 1322 if (mAppliedIBSerial != countingIB->getSerial()) 1323 { 1324 IndexBuffer9 *indexBuffer = IndexBuffer9::makeIndexBuffer9(countingIB->getIndexBuffer()); 1325 1326 mDevice->SetIndices(indexBuffer->getBuffer()); 1327 mAppliedIBSerial = countingIB->getSerial(); 1328 } 1329 1330 for (int i = 0; i < mRepeatDraw; i++) 1331 { 1332 mDevice->DrawIndexedPrimitive(mPrimitiveType, 0, 0, count, 0, mPrimitiveCount); 1333 } 1334 } 1335 else // Regular case 1336 { 1337 mDevice->DrawPrimitive(mPrimitiveType, 0, mPrimitiveCount); 1338 } 1339 } 1340 1341 void Renderer9::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, 1342 gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei /*instances*/) 1343 { 1344 startScene(); 1345 1346 int minIndex = static_cast<int>(indexInfo.indexRange.start); 1347 1348 if (mode == GL_POINTS) 1349 { 1350 drawIndexedPoints(count, type, indices, minIndex, elementArrayBuffer); 1351 } 1352 else if (mode == GL_LINE_LOOP) 1353 { 1354 drawLineLoop(count, type, indices, minIndex, elementArrayBuffer); 1355 } 1356 else 1357 { 1358 for (int i = 0; i < mRepeatDraw; i++) 1359 { 1360 GLsizei vertexCount = static_cast<int>(indexInfo.indexRange.length()) + 1; 1361 mDevice->DrawIndexedPrimitive(mPrimitiveType, -minIndex, minIndex, vertexCount, indexInfo.startIndex, mPrimitiveCount); 1362 } 1363 } 1364 } 1365 1366 void Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer) 1367 { 1368 // Get the raw indices for an indexed draw 1369 if (type != GL_NONE && elementArrayBuffer) 1370 { 1371 gl::Buffer *indexBuffer = elementArrayBuffer; 1372 BufferImpl *storage = indexBuffer->getImplementation(); 1373 intptr_t offset = reinterpret_cast<intptr_t>(indices); 1374 indices = static_cast<const GLubyte*>(storage->getData()) + offset; 1375 } 1376 1377 unsigned int startIndex = 0; 1378 1379 if (getRendererExtensions().elementIndexUint) 1380 { 1381 if (!mLineLoopIB) 1382 { 1383 mLineLoopIB = new StreamingIndexBufferInterface(this); 1384 gl::Error error = mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT); 1385 if (error.isError()) 1386 { 1387 SafeDelete(mLineLoopIB); 1388 1389 ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP."); 1390 return gl::error(GL_OUT_OF_MEMORY); 1391 } 1392 } 1393 1394 // Checked by Renderer9::applyPrimitiveType 1395 ASSERT(count >= 0); 1396 1397 if (static_cast<unsigned int>(count) + 1 > (std::numeric_limits<unsigned int>::max() / sizeof(unsigned int))) 1398 { 1399 ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required."); 1400 return gl::error(GL_OUT_OF_MEMORY); 1401 } 1402 1403 const unsigned int spaceNeeded = (static_cast<unsigned int>(count)+1) * sizeof(unsigned int); 1404 gl::Error error = mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT); 1405 if (error.isError()) 1406 { 1407 ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP."); 1408 return gl::error(GL_OUT_OF_MEMORY); 1409 } 1410 1411 void* mappedMemory = NULL; 1412 unsigned int offset = 0; 1413 error = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset); 1414 if (error.isError()) 1415 { 1416 ERR("Could not map index buffer for GL_LINE_LOOP."); 1417 return gl::error(GL_OUT_OF_MEMORY); 1418 } 1419 1420 startIndex = static_cast<unsigned int>(offset) / 4; 1421 unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory); 1422 1423 switch (type) 1424 { 1425 case GL_NONE: // Non-indexed draw 1426 for (int i = 0; i < count; i++) 1427 { 1428 data[i] = i; 1429 } 1430 data[count] = 0; 1431 break; 1432 case GL_UNSIGNED_BYTE: 1433 for (int i = 0; i < count; i++) 1434 { 1435 data[i] = static_cast<const GLubyte*>(indices)[i]; 1436 } 1437 data[count] = static_cast<const GLubyte*>(indices)[0]; 1438 break; 1439 case GL_UNSIGNED_SHORT: 1440 for (int i = 0; i < count; i++) 1441 { 1442 data[i] = static_cast<const GLushort*>(indices)[i]; 1443 } 1444 data[count] = static_cast<const GLushort*>(indices)[0]; 1445 break; 1446 case GL_UNSIGNED_INT: 1447 for (int i = 0; i < count; i++) 1448 { 1449 data[i] = static_cast<const GLuint*>(indices)[i]; 1450 } 1451 data[count] = static_cast<const GLuint*>(indices)[0]; 1452 break; 1453 default: UNREACHABLE(); 1454 } 1455 1456 error = mLineLoopIB->unmapBuffer(); 1457 if (error.isError()) 1458 { 1459 ERR("Could not unmap index buffer for GL_LINE_LOOP."); 1460 return gl::error(GL_OUT_OF_MEMORY); 1461 } 1462 } 1463 else 1464 { 1465 if (!mLineLoopIB) 1466 { 1467 mLineLoopIB = new StreamingIndexBufferInterface(this); 1468 gl::Error error = mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT); 1469 if (error.isError()) 1470 { 1471 SafeDelete(mLineLoopIB); 1472 1473 ERR("Could not create a 16-bit looping index buffer for GL_LINE_LOOP."); 1474 return gl::error(GL_OUT_OF_MEMORY); 1475 } 1476 } 1477 1478 // Checked by Renderer9::applyPrimitiveType 1479 ASSERT(count >= 0); 1480 1481 if (static_cast<unsigned int>(count) + 1 > (std::numeric_limits<unsigned short>::max() / sizeof(unsigned short))) 1482 { 1483 ERR("Could not create a 16-bit looping index buffer for GL_LINE_LOOP, too many indices required."); 1484 return gl::error(GL_OUT_OF_MEMORY); 1485 } 1486 1487 const unsigned int spaceNeeded = (static_cast<unsigned int>(count) + 1) * sizeof(unsigned short); 1488 gl::Error error = mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT); 1489 if (error.isError()) 1490 { 1491 ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP."); 1492 return gl::error(GL_OUT_OF_MEMORY); 1493 } 1494 1495 void* mappedMemory = NULL; 1496 unsigned int offset; 1497 error = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset); 1498 if (error.isError()) 1499 { 1500 ERR("Could not map index buffer for GL_LINE_LOOP."); 1501 return gl::error(GL_OUT_OF_MEMORY); 1502 } 1503 1504 startIndex = static_cast<unsigned int>(offset) / 2; 1505 unsigned short *data = reinterpret_cast<unsigned short*>(mappedMemory); 1506 1507 switch (type) 1508 { 1509 case GL_NONE: // Non-indexed draw 1510 for (int i = 0; i < count; i++) 1511 { 1512 data[i] = i; 1513 } 1514 data[count] = 0; 1515 break; 1516 case GL_UNSIGNED_BYTE: 1517 for (int i = 0; i < count; i++) 1518 { 1519 data[i] = static_cast<const GLubyte*>(indices)[i]; 1520 } 1521 data[count] = static_cast<const GLubyte*>(indices)[0]; 1522 break; 1523 case GL_UNSIGNED_SHORT: 1524 for (int i = 0; i < count; i++) 1525 { 1526 data[i] = static_cast<const GLushort*>(indices)[i]; 1527 } 1528 data[count] = static_cast<const GLushort*>(indices)[0]; 1529 break; 1530 case GL_UNSIGNED_INT: 1531 for (int i = 0; i < count; i++) 1532 { 1533 data[i] = static_cast<const GLuint*>(indices)[i]; 1534 } 1535 data[count] = static_cast<const GLuint*>(indices)[0]; 1536 break; 1537 default: UNREACHABLE(); 1538 } 1539 1540 error = mLineLoopIB->unmapBuffer(); 1541 if (error.isError()) 1542 { 1543 ERR("Could not unmap index buffer for GL_LINE_LOOP."); 1544 return gl::error(GL_OUT_OF_MEMORY); 1545 } 1546 } 1547 1548 if (mAppliedIBSerial != mLineLoopIB->getSerial()) 1549 { 1550 IndexBuffer9 *indexBuffer = IndexBuffer9::makeIndexBuffer9(mLineLoopIB->getIndexBuffer()); 1551 1552 mDevice->SetIndices(indexBuffer->getBuffer()); 1553 mAppliedIBSerial = mLineLoopIB->getSerial(); 1554 } 1555 1556 mDevice->DrawIndexedPrimitive(D3DPT_LINESTRIP, -minIndex, minIndex, count, startIndex, count); 1557 } 1558 1559 template <typename T> 1560 static void drawPoints(IDirect3DDevice9* device, GLsizei count, const GLvoid *indices, int minIndex) 1561 { 1562 for (int i = 0; i < count; i++) 1563 { 1564 unsigned int indexValue = static_cast<unsigned int>(static_cast<const T*>(indices)[i]) - minIndex; 1565 device->DrawPrimitive(D3DPT_POINTLIST, indexValue, 1); 1566 } 1567 } 1568 1569 void Renderer9::drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer) 1570 { 1571 // Drawing index point lists is unsupported in d3d9, fall back to a regular DrawPrimitive call 1572 // for each individual point. This call is not expected to happen often. 1573 1574 if (elementArrayBuffer) 1575 { 1576 BufferImpl *storage = elementArrayBuffer->getImplementation(); 1577 intptr_t offset = reinterpret_cast<intptr_t>(indices); 1578 indices = static_cast<const GLubyte*>(storage->getData()) + offset; 1579 } 1580 1581 switch (type) 1582 { 1583 case GL_UNSIGNED_BYTE: drawPoints<GLubyte>(mDevice, count, indices, minIndex); break; 1584 case GL_UNSIGNED_SHORT: drawPoints<GLushort>(mDevice, count, indices, minIndex); break; 1585 case GL_UNSIGNED_INT: drawPoints<GLuint>(mDevice, count, indices, minIndex); break; 1586 default: UNREACHABLE(); 1587 } 1588 } 1589 1590 StaticIndexBufferInterface *Renderer9::getCountingIB(size_t count) 1591 { 1592 // Update the counting index buffer if it is not large enough or has not been created yet. 1593 if (count <= 65536) // 16-bit indices 1594 { 1595 const unsigned int spaceNeeded = count * sizeof(unsigned short); 1596 1597 if (!mCountingIB || mCountingIB->getBufferSize() < spaceNeeded) 1598 { 1599 SafeDelete(mCountingIB); 1600 mCountingIB = new StaticIndexBufferInterface(this); 1601 mCountingIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT); 1602 1603 void *mappedMemory = NULL; 1604 gl::Error error = mCountingIB->mapBuffer(spaceNeeded, &mappedMemory, NULL); 1605 if (error.isError()) 1606 { 1607 ERR("Failed to map counting buffer."); 1608 return NULL; 1609 } 1610 1611 unsigned short *data = reinterpret_cast<unsigned short*>(mappedMemory); 1612 for (size_t i = 0; i < count; i++) 1613 { 1614 data[i] = i; 1615 } 1616 1617 error = mCountingIB->unmapBuffer(); 1618 if (error.isError()) 1619 { 1620 ERR("Failed to unmap counting buffer."); 1621 return NULL; 1622 } 1623 } 1624 1625 return mCountingIB; 1626 } 1627 else if (getRendererExtensions().elementIndexUint) 1628 { 1629 const unsigned int spaceNeeded = count * sizeof(unsigned int); 1630 1631 if (!mCountingIB || mCountingIB->getBufferSize() < spaceNeeded) 1632 { 1633 SafeDelete(mCountingIB); 1634 mCountingIB = new StaticIndexBufferInterface(this); 1635 mCountingIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT); 1636 1637 void *mappedMemory = NULL; 1638 gl::Error error = mCountingIB->mapBuffer(spaceNeeded, &mappedMemory, NULL); 1639 if (error.isError()) 1640 { 1641 ERR("Failed to map counting buffer."); 1642 return NULL; 1643 } 1644 1645 unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory); 1646 for (size_t i = 0; i < count; i++) 1647 { 1648 data[i] = i; 1649 } 1650 1651 error = mCountingIB->unmapBuffer(); 1652 if (error.isError()) 1653 { 1654 ERR("Failed to unmap counting buffer."); 1655 return NULL; 1656 } 1657 } 1658 1659 return mCountingIB; 1660 } 1661 else 1662 { 1663 ERR("Could not create a counting index buffer for glDrawArraysInstanced."); 1664 return gl::error<StaticIndexBufferInterface*>(GL_OUT_OF_MEMORY, NULL); 1665 } 1666 } 1667 1668 void Renderer9::applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, 1669 bool rasterizerDiscard, bool transformFeedbackActive) 1670 { 1671 ASSERT(!transformFeedbackActive); 1672 ASSERT(!rasterizerDiscard); 1673 1674 ShaderExecutable *vertexExe = programBinary->getVertexExecutableForInputLayout(inputLayout); 1675 ShaderExecutable *pixelExe = programBinary->getPixelExecutableForFramebuffer(framebuffer); 1676 1677 IDirect3DVertexShader9 *vertexShader = (vertexExe ? ShaderExecutable9::makeShaderExecutable9(vertexExe)->getVertexShader() : NULL); 1678 IDirect3DPixelShader9 *pixelShader = (pixelExe ? ShaderExecutable9::makeShaderExecutable9(pixelExe)->getPixelShader() : NULL); 1679 1680 if (vertexShader != mAppliedVertexShader) 1681 { 1682 mDevice->SetVertexShader(vertexShader); 1683 mAppliedVertexShader = vertexShader; 1684 } 1685 1686 if (pixelShader != mAppliedPixelShader) 1687 { 1688 mDevice->SetPixelShader(pixelShader); 1689 mAppliedPixelShader = pixelShader; 1690 } 1691 1692 // D3D9 has a quirk where creating multiple shaders with the same content 1693 // can return the same shader pointer. Because GL programs store different data 1694 // per-program, checking the program serial guarantees we upload fresh 1695 // uniform data even if our shader pointers are the same. 1696 // https://code.google.com/p/angleproject/issues/detail?id=661 1697 unsigned int programSerial = programBinary->getSerial(); 1698 if (programSerial != mAppliedProgramSerial) 1699 { 1700 programBinary->dirtyAllUniforms(); 1701 mDxUniformsDirty = true; 1702 mAppliedProgramSerial = programSerial; 1703 } 1704 } 1705 1706 void Renderer9::applyUniforms(const gl::ProgramBinary &programBinary) 1707 { 1708 const std::vector<gl::LinkedUniform*> &uniformArray = programBinary.getUniforms(); 1709 1710 for (size_t uniformIndex = 0; uniformIndex < uniformArray.size(); uniformIndex++) 1711 { 1712 gl::LinkedUniform *targetUniform = uniformArray[uniformIndex]; 1713 1714 if (targetUniform->dirty) 1715 { 1716 GLfloat *f = (GLfloat*)targetUniform->data; 1717 GLint *i = (GLint*)targetUniform->data; 1718 1719 switch (targetUniform->type) 1720 { 1721 case GL_SAMPLER_2D: 1722 case GL_SAMPLER_CUBE: 1723 break; 1724 case GL_BOOL: 1725 case GL_BOOL_VEC2: 1726 case GL_BOOL_VEC3: 1727 case GL_BOOL_VEC4: 1728 applyUniformnbv(targetUniform, i); 1729 break; 1730 case GL_FLOAT: 1731 case GL_FLOAT_VEC2: 1732 case GL_FLOAT_VEC3: 1733 case GL_FLOAT_VEC4: 1734 case GL_FLOAT_MAT2: 1735 case GL_FLOAT_MAT3: 1736 case GL_FLOAT_MAT4: 1737 applyUniformnfv(targetUniform, f); 1738 break; 1739 case GL_INT: 1740 case GL_INT_VEC2: 1741 case GL_INT_VEC3: 1742 case GL_INT_VEC4: 1743 applyUniformniv(targetUniform, i); 1744 break; 1745 default: 1746 UNREACHABLE(); 1747 } 1748 } 1749 } 1750 1751 // Driver uniforms 1752 if (mDxUniformsDirty) 1753 { 1754 mDevice->SetVertexShaderConstantF(0, (float*)&mVertexConstants, sizeof(dx_VertexConstants) / sizeof(float[4])); 1755 mDevice->SetPixelShaderConstantF(0, (float*)&mPixelConstants, sizeof(dx_PixelConstants) / sizeof(float[4])); 1756 mDxUniformsDirty = false; 1757 } 1758 } 1759 1760 void Renderer9::applyUniformnfv(gl::LinkedUniform *targetUniform, const GLfloat *v) 1761 { 1762 if (targetUniform->isReferencedByFragmentShader()) 1763 { 1764 mDevice->SetPixelShaderConstantF(targetUniform->psRegisterIndex, v, targetUniform->registerCount); 1765 } 1766 1767 if (targetUniform->isReferencedByVertexShader()) 1768 { 1769 mDevice->SetVertexShaderConstantF(targetUniform->vsRegisterIndex, v, targetUniform->registerCount); 1770 } 1771 } 1772 1773 void Renderer9::applyUniformniv(gl::LinkedUniform *targetUniform, const GLint *v) 1774 { 1775 ASSERT(targetUniform->registerCount <= MAX_VERTEX_CONSTANT_VECTORS_D3D9); 1776 GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4]; 1777 1778 for (unsigned int i = 0; i < targetUniform->registerCount; i++) 1779 { 1780 vector[i][0] = (GLfloat)v[4 * i + 0]; 1781 vector[i][1] = (GLfloat)v[4 * i + 1]; 1782 vector[i][2] = (GLfloat)v[4 * i + 2]; 1783 vector[i][3] = (GLfloat)v[4 * i + 3]; 1784 } 1785 1786 applyUniformnfv(targetUniform, (GLfloat*)vector); 1787 } 1788 1789 void Renderer9::applyUniformnbv(gl::LinkedUniform *targetUniform, const GLint *v) 1790 { 1791 ASSERT(targetUniform->registerCount <= MAX_VERTEX_CONSTANT_VECTORS_D3D9); 1792 GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4]; 1793 1794 for (unsigned int i = 0; i < targetUniform->registerCount; i++) 1795 { 1796 vector[i][0] = (v[4 * i + 0] == GL_FALSE) ? 0.0f : 1.0f; 1797 vector[i][1] = (v[4 * i + 1] == GL_FALSE) ? 0.0f : 1.0f; 1798 vector[i][2] = (v[4 * i + 2] == GL_FALSE) ? 0.0f : 1.0f; 1799 vector[i][3] = (v[4 * i + 3] == GL_FALSE) ? 0.0f : 1.0f; 1800 } 1801 1802 applyUniformnfv(targetUniform, (GLfloat*)vector); 1803 } 1804 1805 gl::Error Renderer9::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer) 1806 { 1807 if (clearParams.colorClearType != GL_FLOAT) 1808 { 1809 // Clearing buffers with non-float values is not supported by Renderer9 and ES 2.0 1810 UNREACHABLE(); 1811 return gl::Error(GL_INVALID_OPERATION); 1812 } 1813 1814 bool clearColor = clearParams.clearColor[0]; 1815 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) 1816 { 1817 if (clearParams.clearColor[i] != clearColor) 1818 { 1819 // Clearing individual buffers other than buffer zero is not supported by Renderer9 and ES 2.0 1820 UNREACHABLE(); 1821 return gl::Error(GL_INVALID_OPERATION); 1822 } 1823 } 1824 1825 float depth = gl::clamp01(clearParams.depthClearValue); 1826 DWORD stencil = clearParams.stencilClearValue & 0x000000FF; 1827 1828 unsigned int stencilUnmasked = 0x0; 1829 if (clearParams.clearStencil && frameBuffer->hasStencil()) 1830 { 1831 unsigned int stencilSize = gl::GetInternalFormatInfo((frameBuffer->getStencilbuffer()->getActualFormat())).stencilBits; 1832 stencilUnmasked = (0x1 << stencilSize) - 1; 1833 } 1834 1835 const bool needMaskedStencilClear = clearParams.clearStencil && 1836 (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked; 1837 1838 bool needMaskedColorClear = false; 1839 D3DCOLOR color = D3DCOLOR_ARGB(255, 0, 0, 0); 1840 if (clearColor) 1841 { 1842 const gl::FramebufferAttachment *attachment = frameBuffer->getFirstColorbuffer(); 1843 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(attachment->getInternalFormat()); 1844 const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(attachment->getActualFormat()); 1845 1846 color = D3DCOLOR_ARGB(gl::unorm<8>((formatInfo.alphaBits == 0 && actualFormatInfo.alphaBits > 0) ? 1.0f : clearParams.colorFClearValue.alpha), 1847 gl::unorm<8>((formatInfo.redBits == 0 && actualFormatInfo.redBits > 0) ? 0.0f : clearParams.colorFClearValue.red), 1848 gl::unorm<8>((formatInfo.greenBits == 0 && actualFormatInfo.greenBits > 0) ? 0.0f : clearParams.colorFClearValue.green), 1849 gl::unorm<8>((formatInfo.blueBits == 0 && actualFormatInfo.blueBits > 0) ? 0.0f : clearParams.colorFClearValue.blue)); 1850 1851 if ((formatInfo.redBits > 0 && !clearParams.colorMaskRed) || 1852 (formatInfo.greenBits > 0 && !clearParams.colorMaskGreen) || 1853 (formatInfo.blueBits > 0 && !clearParams.colorMaskBlue) || 1854 (formatInfo.alphaBits > 0 && !clearParams.colorMaskAlpha)) 1855 { 1856 needMaskedColorClear = true; 1857 } 1858 } 1859 1860 if (needMaskedColorClear || needMaskedStencilClear) 1861 { 1862 // State which is altered in all paths from this point to the clear call is saved. 1863 // State which is altered in only some paths will be flagged dirty in the case that 1864 // that path is taken. 1865 HRESULT hr; 1866 if (mMaskedClearSavedState == NULL) 1867 { 1868 hr = mDevice->BeginStateBlock(); 1869 ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); 1870 1871 mDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); 1872 mDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS); 1873 mDevice->SetRenderState(D3DRS_ZENABLE, FALSE); 1874 mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); 1875 mDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); 1876 mDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); 1877 mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); 1878 mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); 1879 mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0); 1880 mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); 1881 mDevice->SetPixelShader(NULL); 1882 mDevice->SetVertexShader(NULL); 1883 mDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE); 1884 mDevice->SetStreamSource(0, NULL, 0, 0); 1885 mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); 1886 mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); 1887 mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR); 1888 mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); 1889 mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR); 1890 mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color); 1891 mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF); 1892 1893 for(int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) 1894 { 1895 mDevice->SetStreamSourceFreq(i, 1); 1896 } 1897 1898 hr = mDevice->EndStateBlock(&mMaskedClearSavedState); 1899 ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); 1900 } 1901 1902 ASSERT(mMaskedClearSavedState != NULL); 1903 1904 if (mMaskedClearSavedState != NULL) 1905 { 1906 hr = mMaskedClearSavedState->Capture(); 1907 ASSERT(SUCCEEDED(hr)); 1908 } 1909 1910 mDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); 1911 mDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS); 1912 mDevice->SetRenderState(D3DRS_ZENABLE, FALSE); 1913 mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); 1914 mDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); 1915 mDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); 1916 mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); 1917 mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); 1918 1919 if (clearColor) 1920 { 1921 mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 1922 gl_d3d9::ConvertColorMask(clearParams.colorMaskRed, 1923 clearParams.colorMaskGreen, 1924 clearParams.colorMaskBlue, 1925 clearParams.colorMaskAlpha)); 1926 } 1927 else 1928 { 1929 mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0); 1930 } 1931 1932 if (stencilUnmasked != 0x0 && clearParams.clearStencil) 1933 { 1934 mDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE); 1935 mDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE); 1936 mDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS); 1937 mDevice->SetRenderState(D3DRS_STENCILREF, stencil); 1938 mDevice->SetRenderState(D3DRS_STENCILWRITEMASK, clearParams.stencilWriteMask); 1939 mDevice->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE); 1940 mDevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE); 1941 mDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE); 1942 } 1943 else 1944 { 1945 mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); 1946 } 1947 1948 mDevice->SetPixelShader(NULL); 1949 mDevice->SetVertexShader(NULL); 1950 mDevice->SetFVF(D3DFVF_XYZRHW); 1951 mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); 1952 mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); 1953 mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR); 1954 mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); 1955 mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR); 1956 mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color); 1957 mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF); 1958 1959 for(int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) 1960 { 1961 mDevice->SetStreamSourceFreq(i, 1); 1962 } 1963 1964 float quad[4][4]; // A quadrilateral covering the target, aligned to match the edges 1965 quad[0][0] = -0.5f; 1966 quad[0][1] = mRenderTargetDesc.height - 0.5f; 1967 quad[0][2] = 0.0f; 1968 quad[0][3] = 1.0f; 1969 1970 quad[1][0] = mRenderTargetDesc.width - 0.5f; 1971 quad[1][1] = mRenderTargetDesc.height - 0.5f; 1972 quad[1][2] = 0.0f; 1973 quad[1][3] = 1.0f; 1974 1975 quad[2][0] = -0.5f; 1976 quad[2][1] = -0.5f; 1977 quad[2][2] = 0.0f; 1978 quad[2][3] = 1.0f; 1979 1980 quad[3][0] = mRenderTargetDesc.width - 0.5f; 1981 quad[3][1] = -0.5f; 1982 quad[3][2] = 0.0f; 1983 quad[3][3] = 1.0f; 1984 1985 startScene(); 1986 mDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float[4])); 1987 1988 if (clearParams.clearDepth) 1989 { 1990 mDevice->SetRenderState(D3DRS_ZENABLE, TRUE); 1991 mDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE); 1992 mDevice->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil); 1993 } 1994 1995 if (mMaskedClearSavedState != NULL) 1996 { 1997 mMaskedClearSavedState->Apply(); 1998 } 1999 } 2000 else if (clearColor || clearParams.clearDepth || clearParams.clearStencil) 2001 { 2002 DWORD dxClearFlags = 0; 2003 if (clearColor) 2004 { 2005 dxClearFlags |= D3DCLEAR_TARGET; 2006 } 2007 if (clearParams.clearDepth) 2008 { 2009 dxClearFlags |= D3DCLEAR_ZBUFFER; 2010 } 2011 if (clearParams.clearStencil) 2012 { 2013 dxClearFlags |= D3DCLEAR_STENCIL; 2014 } 2015 2016 mDevice->Clear(0, NULL, dxClearFlags, color, depth, stencil); 2017 } 2018 2019 return gl::Error(GL_NO_ERROR); 2020 } 2021 2022 void Renderer9::markAllStateDirty() 2023 { 2024 mAppliedRenderTargetSerial = 0; 2025 mAppliedDepthbufferSerial = 0; 2026 mAppliedStencilbufferSerial = 0; 2027 mDepthStencilInitialized = false; 2028 mRenderTargetDescInitialized = false; 2029 2030 mForceSetDepthStencilState = true; 2031 mForceSetRasterState = true; 2032 mForceSetScissor = true; 2033 mForceSetViewport = true; 2034 mForceSetBlendState = true; 2035 2036 ASSERT(mForceSetVertexSamplerStates.size() == mCurVertexTextureSerials.size()); 2037 for (unsigned int i = 0; i < mForceSetVertexSamplerStates.size(); i++) 2038 { 2039 mForceSetVertexSamplerStates[i] = true; 2040 mCurVertexTextureSerials[i] = 0; 2041 } 2042 2043 ASSERT(mForceSetPixelSamplerStates.size() == mCurPixelTextureSerials.size()); 2044 for (unsigned int i = 0; i < mForceSetPixelSamplerStates.size(); i++) 2045 { 2046 mForceSetPixelSamplerStates[i] = true; 2047 mCurPixelTextureSerials[i] = 0; 2048 } 2049 2050 mAppliedIBSerial = 0; 2051 mAppliedVertexShader = NULL; 2052 mAppliedPixelShader = NULL; 2053 mAppliedProgramSerial = 0; 2054 mDxUniformsDirty = true; 2055 2056 mVertexDeclarationCache.markStateDirty(); 2057 } 2058 2059 void Renderer9::releaseDeviceResources() 2060 { 2061 for (size_t i = 0; i < mEventQueryPool.size(); i++) 2062 { 2063 SafeRelease(mEventQueryPool[i]); 2064 } 2065 mEventQueryPool.clear(); 2066 2067 SafeRelease(mMaskedClearSavedState); 2068 2069 mVertexShaderCache.clear(); 2070 mPixelShaderCache.clear(); 2071 2072 SafeDelete(mBlit); 2073 SafeDelete(mVertexDataManager); 2074 SafeDelete(mIndexDataManager); 2075 SafeDelete(mLineLoopIB); 2076 SafeDelete(mCountingIB); 2077 2078 for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++) 2079 { 2080 SafeDelete(mNullColorbufferCache[i].buffer); 2081 } 2082 } 2083 2084 void Renderer9::notifyDeviceLost() 2085 { 2086 mDeviceLost = true; 2087 mDisplay->notifyDeviceLost(); 2088 } 2089 2090 bool Renderer9::isDeviceLost() 2091 { 2092 return mDeviceLost; 2093 } 2094 2095 // set notify to true to broadcast a message to all contexts of the device loss 2096 bool Renderer9::testDeviceLost(bool notify) 2097 { 2098 HRESULT status = getDeviceStatusCode(); 2099 bool isLost = FAILED(status); 2100 2101 if (isLost) 2102 { 2103 // ensure we note the device loss -- 2104 // we'll probably get this done again by notifyDeviceLost 2105 // but best to remember it! 2106 // Note that we don't want to clear the device loss status here 2107 // -- this needs to be done by resetDevice 2108 mDeviceLost = true; 2109 if (notify) 2110 { 2111 notifyDeviceLost(); 2112 } 2113 } 2114 2115 return isLost; 2116 } 2117 2118 HRESULT Renderer9::getDeviceStatusCode() 2119 { 2120 HRESULT status = D3D_OK; 2121 2122 if (mDeviceEx) 2123 { 2124 status = mDeviceEx->CheckDeviceState(NULL); 2125 } 2126 else if (mDevice) 2127 { 2128 status = mDevice->TestCooperativeLevel(); 2129 } 2130 2131 return status; 2132 } 2133 2134 bool Renderer9::testDeviceResettable() 2135 { 2136 // On D3D9Ex, DEVICELOST represents a hung device that needs to be restarted 2137 // DEVICEREMOVED indicates the device has been stopped and must be recreated 2138 switch (getDeviceStatusCode()) 2139 { 2140 case D3DERR_DEVICENOTRESET: 2141 case D3DERR_DEVICEHUNG: 2142 return true; 2143 case D3DERR_DEVICELOST: 2144 return (mDeviceEx != NULL); 2145 case D3DERR_DEVICEREMOVED: 2146 ASSERT(mDeviceEx != NULL); 2147 return isRemovedDeviceResettable(); 2148 default: 2149 return false; 2150 } 2151 } 2152 2153 bool Renderer9::resetDevice() 2154 { 2155 releaseDeviceResources(); 2156 2157 D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters(); 2158 2159 HRESULT result = D3D_OK; 2160 bool lost = testDeviceLost(false); 2161 bool removedDevice = (getDeviceStatusCode() == D3DERR_DEVICEREMOVED); 2162 2163 // Device Removed is a feature which is only present with D3D9Ex 2164 ASSERT(mDeviceEx != NULL || !removedDevice); 2165 2166 for (int attempts = 3; lost && attempts > 0; attempts--) 2167 { 2168 if (removedDevice) 2169 { 2170 // Device removed, which may trigger on driver reinstallation, 2171 // may cause a longer wait other reset attempts before the 2172 // system is ready to handle creating a new device. 2173 Sleep(800); 2174 lost = !resetRemovedDevice(); 2175 } 2176 else if (mDeviceEx) 2177 { 2178 Sleep(500); // Give the graphics driver some CPU time 2179 result = mDeviceEx->ResetEx(&presentParameters, NULL); 2180 lost = testDeviceLost(false); 2181 } 2182 else 2183 { 2184 result = mDevice->TestCooperativeLevel(); 2185 while (result == D3DERR_DEVICELOST) 2186 { 2187 Sleep(100); // Give the graphics driver some CPU time 2188 result = mDevice->TestCooperativeLevel(); 2189 } 2190 2191 if (result == D3DERR_DEVICENOTRESET) 2192 { 2193 result = mDevice->Reset(&presentParameters); 2194 } 2195 lost = testDeviceLost(false); 2196 } 2197 } 2198 2199 if (FAILED(result)) 2200 { 2201 ERR("Reset/ResetEx failed multiple times: 0x%08X", result); 2202 return false; 2203 } 2204 2205 if (removedDevice && lost) 2206 { 2207 ERR("Device lost reset failed multiple times"); 2208 return false; 2209 } 2210 2211 // If the device was removed, we already finished re-initialization in resetRemovedDevice 2212 if (!removedDevice) 2213 { 2214 // reset device defaults 2215 initializeDevice(); 2216 } 2217 2218 mDeviceLost = false; 2219 2220 return true; 2221 } 2222 2223 bool Renderer9::isRemovedDeviceResettable() const 2224 { 2225 bool success = false; 2226 2227 #ifdef ANGLE_ENABLE_D3D9EX 2228 IDirect3D9Ex *d3d9Ex = NULL; 2229 typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex**); 2230 Direct3DCreate9ExFunc Direct3DCreate9ExPtr = reinterpret_cast<Direct3DCreate9ExFunc>(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex")); 2231 2232 if (Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &d3d9Ex))) 2233 { 2234 D3DCAPS9 deviceCaps; 2235 HRESULT result = d3d9Ex->GetDeviceCaps(mAdapter, mDeviceType, &deviceCaps); 2236 success = SUCCEEDED(result); 2237 } 2238 2239 SafeRelease(d3d9Ex); 2240 #else 2241 ASSERT(UNREACHABLE()); 2242 #endif 2243 2244 return success; 2245 } 2246 2247 bool Renderer9::resetRemovedDevice() 2248 { 2249 // From http://msdn.microsoft.com/en-us/library/windows/desktop/bb172554(v=vs.85).aspx: 2250 // The hardware adapter has been removed. Application must destroy the device, do enumeration of 2251 // adapters and create another Direct3D device. If application continues rendering without 2252 // calling Reset, the rendering calls will succeed. Applies to Direct3D 9Ex only. 2253 release(); 2254 return (initialize() == EGL_SUCCESS); 2255 } 2256 2257 DWORD Renderer9::getAdapterVendor() const 2258 { 2259 return mAdapterIdentifier.VendorId; 2260 } 2261 2262 std::string Renderer9::getRendererDescription() const 2263 { 2264 std::ostringstream rendererString; 2265 2266 rendererString << mAdapterIdentifier.Description; 2267 if (getShareHandleSupport()) 2268 { 2269 rendererString << " Direct3D9Ex"; 2270 } 2271 else 2272 { 2273 rendererString << " Direct3D9"; 2274 } 2275 2276 rendererString << " vs_" << D3DSHADER_VERSION_MAJOR(mDeviceCaps.VertexShaderVersion) << "_" << D3DSHADER_VERSION_MINOR(mDeviceCaps.VertexShaderVersion); 2277 rendererString << " ps_" << D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion) << "_" << D3DSHADER_VERSION_MINOR(mDeviceCaps.PixelShaderVersion); 2278 2279 return rendererString.str(); 2280 } 2281 2282 GUID Renderer9::getAdapterIdentifier() const 2283 { 2284 return mAdapterIdentifier.DeviceIdentifier; 2285 } 2286 2287 unsigned int Renderer9::getReservedVertexUniformVectors() const 2288 { 2289 return 2; // dx_ViewAdjust and dx_DepthRange. 2290 } 2291 2292 unsigned int Renderer9::getReservedFragmentUniformVectors() const 2293 { 2294 return 3; // dx_ViewCoords, dx_DepthFront and dx_DepthRange. 2295 } 2296 2297 unsigned int Renderer9::getReservedVertexUniformBuffers() const 2298 { 2299 return 0; 2300 } 2301 2302 unsigned int Renderer9::getReservedFragmentUniformBuffers() const 2303 { 2304 return 0; 2305 } 2306 2307 bool Renderer9::getShareHandleSupport() const 2308 { 2309 // PIX doesn't seem to support using share handles, so disable them. 2310 return (mD3d9Ex != NULL) && !gl::perfActive(); 2311 } 2312 2313 bool Renderer9::getPostSubBufferSupport() const 2314 { 2315 return true; 2316 } 2317 2318 int Renderer9::getMajorShaderModel() const 2319 { 2320 return D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion); 2321 } 2322 2323 DWORD Renderer9::getCapsDeclTypes() const 2324 { 2325 return mDeviceCaps.DeclTypes; 2326 } 2327 2328 int Renderer9::getMinSwapInterval() const 2329 { 2330 return mMinSwapInterval; 2331 } 2332 2333 int Renderer9::getMaxSwapInterval() const 2334 { 2335 return mMaxSwapInterval; 2336 } 2337 2338 bool Renderer9::copyToRenderTarget2D(TextureStorage *dest, TextureStorage *source) 2339 { 2340 bool result = false; 2341 2342 if (source && dest) 2343 { 2344 TextureStorage9_2D *source9 = TextureStorage9_2D::makeTextureStorage9_2D(source); 2345 TextureStorage9_2D *dest9 = TextureStorage9_2D::makeTextureStorage9_2D(dest); 2346 2347 int levels = source9->getLevelCount(); 2348 for (int i = 0; i < levels; ++i) 2349 { 2350 IDirect3DSurface9 *srcSurf = source9->getSurfaceLevel(i, false); 2351 IDirect3DSurface9 *dstSurf = dest9->getSurfaceLevel(i, false); 2352 2353 result = copyToRenderTarget(dstSurf, srcSurf, source9->isManaged()); 2354 2355 SafeRelease(srcSurf); 2356 SafeRelease(dstSurf); 2357 2358 if (!result) 2359 { 2360 return false; 2361 } 2362 } 2363 } 2364 2365 return result; 2366 } 2367 2368 bool Renderer9::copyToRenderTargetCube(TextureStorage *dest, TextureStorage *source) 2369 { 2370 bool result = false; 2371 2372 if (source && dest) 2373 { 2374 TextureStorage9_Cube *source9 = TextureStorage9_Cube::makeTextureStorage9_Cube(source); 2375 TextureStorage9_Cube *dest9 = TextureStorage9_Cube::makeTextureStorage9_Cube(dest); 2376 int levels = source9->getLevelCount(); 2377 for (int f = 0; f < 6; f++) 2378 { 2379 for (int i = 0; i < levels; i++) 2380 { 2381 IDirect3DSurface9 *srcSurf = source9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, false); 2382 IDirect3DSurface9 *dstSurf = dest9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, true); 2383 2384 result = copyToRenderTarget(dstSurf, srcSurf, source9->isManaged()); 2385 2386 SafeRelease(srcSurf); 2387 SafeRelease(dstSurf); 2388 2389 if (!result) 2390 { 2391 return false; 2392 } 2393 } 2394 } 2395 } 2396 2397 return result; 2398 } 2399 2400 bool Renderer9::copyToRenderTarget3D(TextureStorage *dest, TextureStorage *source) 2401 { 2402 // 3D textures are not available in the D3D9 backend. 2403 UNREACHABLE(); 2404 return false; 2405 } 2406 2407 bool Renderer9::copyToRenderTarget2DArray(TextureStorage *dest, TextureStorage *source) 2408 { 2409 // 2D array textures are not supported by the D3D9 backend. 2410 UNREACHABLE(); 2411 return false; 2412 } 2413 2414 D3DPOOL Renderer9::getBufferPool(DWORD usage) const 2415 { 2416 if (mD3d9Ex != NULL) 2417 { 2418 return D3DPOOL_DEFAULT; 2419 } 2420 else 2421 { 2422 if (!(usage & D3DUSAGE_DYNAMIC)) 2423 { 2424 return D3DPOOL_MANAGED; 2425 } 2426 } 2427 2428 return D3DPOOL_DEFAULT; 2429 } 2430 2431 bool Renderer9::copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, 2432 GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level) 2433 { 2434 RECT rect; 2435 rect.left = sourceRect.x; 2436 rect.top = sourceRect.y; 2437 rect.right = sourceRect.x + sourceRect.width; 2438 rect.bottom = sourceRect.y + sourceRect.height; 2439 2440 return mBlit->copy2D(framebuffer, rect, destFormat, xoffset, yoffset, storage, level); 2441 } 2442 2443 bool Renderer9::copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, 2444 GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level) 2445 { 2446 RECT rect; 2447 rect.left = sourceRect.x; 2448 rect.top = sourceRect.y; 2449 rect.right = sourceRect.x + sourceRect.width; 2450 rect.bottom = sourceRect.y + sourceRect.height; 2451 2452 return mBlit->copyCube(framebuffer, rect, destFormat, xoffset, yoffset, storage, target, level); 2453 } 2454 2455 bool Renderer9::copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, 2456 GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level) 2457 { 2458 // 3D textures are not available in the D3D9 backend. 2459 UNREACHABLE(); 2460 return false; 2461 } 2462 2463 bool Renderer9::copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, 2464 GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level) 2465 { 2466 // 2D array textures are not available in the D3D9 backend. 2467 UNREACHABLE(); 2468 return false; 2469 } 2470 2471 bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle &readRect, gl::Framebuffer *drawFramebuffer, const gl::Rectangle &drawRect, 2472 const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter) 2473 { 2474 ASSERT(filter == GL_NEAREST); 2475 2476 endScene(); 2477 2478 if (blitRenderTarget) 2479 { 2480 gl::FramebufferAttachment *readBuffer = readFramebuffer->getColorbuffer(0); 2481 gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getColorbuffer(0); 2482 RenderTarget9 *readRenderTarget = NULL; 2483 RenderTarget9 *drawRenderTarget = NULL; 2484 IDirect3DSurface9* readSurface = NULL; 2485 IDirect3DSurface9* drawSurface = NULL; 2486 2487 if (readBuffer) 2488 { 2489 readRenderTarget = d3d9::GetAttachmentRenderTarget(readBuffer); 2490 } 2491 if (drawBuffer) 2492 { 2493 drawRenderTarget = d3d9::GetAttachmentRenderTarget(drawBuffer); 2494 } 2495 2496 if (readRenderTarget) 2497 { 2498 readSurface = readRenderTarget->getSurface(); 2499 } 2500 if (drawRenderTarget) 2501 { 2502 drawSurface = drawRenderTarget->getSurface(); 2503 } 2504 2505 if (!readSurface || !drawSurface) 2506 { 2507 ERR("Failed to retrieve the render target."); 2508 return gl::error(GL_OUT_OF_MEMORY, false); 2509 } 2510 2511 gl::Extents srcSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1); 2512 gl::Extents dstSize(drawRenderTarget->getWidth(), drawRenderTarget->getHeight(), 1); 2513 2514 RECT srcRect; 2515 srcRect.left = readRect.x; 2516 srcRect.right = readRect.x + readRect.width; 2517 srcRect.top = readRect.y; 2518 srcRect.bottom = readRect.y + readRect.height; 2519 2520 RECT dstRect; 2521 dstRect.left = drawRect.x; 2522 dstRect.right = drawRect.x + drawRect.width; 2523 dstRect.top = drawRect.y; 2524 dstRect.bottom = drawRect.y + drawRect.height; 2525 2526 // Clip the rectangles to the scissor rectangle 2527 if (scissor) 2528 { 2529 if (dstRect.left < scissor->x) 2530 { 2531 srcRect.left += (scissor->x - dstRect.left); 2532 dstRect.left = scissor->x; 2533 } 2534 if (dstRect.top < scissor->y) 2535 { 2536 srcRect.top += (scissor->y - dstRect.top); 2537 dstRect.top = scissor->y; 2538 } 2539 if (dstRect.right > scissor->x + scissor->width) 2540 { 2541 srcRect.right -= (dstRect.right - (scissor->x + scissor->width)); 2542 dstRect.right = scissor->x + scissor->width; 2543 } 2544 if (dstRect.bottom > scissor->y + scissor->height) 2545 { 2546 srcRect.bottom -= (dstRect.bottom - (scissor->y + scissor->height)); 2547 dstRect.bottom = scissor->y + scissor->height; 2548 } 2549 } 2550 2551 // Clip the rectangles to the destination size 2552 if (dstRect.left < 0) 2553 { 2554 srcRect.left += -dstRect.left; 2555 dstRect.left = 0; 2556 } 2557 if (dstRect.right > dstSize.width) 2558 { 2559 srcRect.right -= (dstRect.right - dstSize.width); 2560 dstRect.right = dstSize.width; 2561 } 2562 if (dstRect.top < 0) 2563 { 2564 srcRect.top += -dstRect.top; 2565 dstRect.top = 0; 2566 } 2567 if (dstRect.bottom > dstSize.height) 2568 { 2569 srcRect.bottom -= (dstRect.bottom - dstSize.height); 2570 dstRect.bottom = dstSize.height; 2571 } 2572 2573 // Clip the rectangles to the source size 2574 if (srcRect.left < 0) 2575 { 2576 dstRect.left += -srcRect.left; 2577 srcRect.left = 0; 2578 } 2579 if (srcRect.right > srcSize.width) 2580 { 2581 dstRect.right -= (srcRect.right - srcSize.width); 2582 srcRect.right = srcSize.width; 2583 } 2584 if (srcRect.top < 0) 2585 { 2586 dstRect.top += -srcRect.top; 2587 srcRect.top = 0; 2588 } 2589 if (srcRect.bottom > srcSize.height) 2590 { 2591 dstRect.bottom -= (srcRect.bottom - srcSize.height); 2592 srcRect.bottom = srcSize.height; 2593 } 2594 2595 HRESULT result = mDevice->StretchRect(readSurface, &srcRect, drawSurface, &dstRect, D3DTEXF_NONE); 2596 2597 SafeRelease(readSurface); 2598 SafeRelease(drawSurface); 2599 2600 if (FAILED(result)) 2601 { 2602 ERR("BlitFramebufferANGLE failed: StretchRect returned %x.", result); 2603 return false; 2604 } 2605 } 2606 2607 if (blitDepth || blitStencil) 2608 { 2609 gl::FramebufferAttachment *readBuffer = readFramebuffer->getDepthOrStencilbuffer(); 2610 gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getDepthOrStencilbuffer(); 2611 RenderTarget9 *readDepthStencil = NULL; 2612 RenderTarget9 *drawDepthStencil = NULL; 2613 IDirect3DSurface9* readSurface = NULL; 2614 IDirect3DSurface9* drawSurface = NULL; 2615 2616 if (readBuffer) 2617 { 2618 readDepthStencil = d3d9::GetAttachmentRenderTarget(readBuffer); 2619 } 2620 if (drawBuffer) 2621 { 2622 drawDepthStencil = d3d9::GetAttachmentRenderTarget(drawBuffer); 2623 } 2624 2625 if (readDepthStencil) 2626 { 2627 readSurface = readDepthStencil->getSurface(); 2628 } 2629 if (drawDepthStencil) 2630 { 2631 drawSurface = drawDepthStencil->getSurface(); 2632 } 2633 2634 if (!readSurface || !drawSurface) 2635 { 2636 ERR("Failed to retrieve the render target."); 2637 return gl::error(GL_OUT_OF_MEMORY, false); 2638 } 2639 2640 HRESULT result = mDevice->StretchRect(readSurface, NULL, drawSurface, NULL, D3DTEXF_NONE); 2641 2642 SafeRelease(readSurface); 2643 SafeRelease(drawSurface); 2644 2645 if (FAILED(result)) 2646 { 2647 ERR("BlitFramebufferANGLE failed: StretchRect returned %x.", result); 2648 return false; 2649 } 2650 } 2651 2652 return true; 2653 } 2654 2655 gl::Error Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, 2656 GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels) 2657 { 2658 ASSERT(pack.pixelBuffer.get() == NULL); 2659 2660 RenderTarget9 *renderTarget = NULL; 2661 IDirect3DSurface9 *surface = NULL; 2662 gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(0); 2663 2664 if (colorbuffer) 2665 { 2666 renderTarget = d3d9::GetAttachmentRenderTarget(colorbuffer); 2667 } 2668 2669 if (renderTarget) 2670 { 2671 surface = renderTarget->getSurface(); 2672 } 2673 2674 if (!surface) 2675 { 2676 // context must be lost 2677 return gl::Error(GL_NO_ERROR); 2678 } 2679 2680 D3DSURFACE_DESC desc; 2681 surface->GetDesc(&desc); 2682 2683 if (desc.MultiSampleType != D3DMULTISAMPLE_NONE) 2684 { 2685 UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target 2686 SafeRelease(surface); 2687 return gl::Error(GL_OUT_OF_MEMORY, "ReadPixels is unimplemented for multisampled framebuffer attachments."); 2688 } 2689 2690 HRESULT result; 2691 IDirect3DSurface9 *systemSurface = NULL; 2692 bool directToPixels = !pack.reverseRowOrder && pack.alignment <= 4 && getShareHandleSupport() && 2693 x == 0 && y == 0 && UINT(width) == desc.Width && UINT(height) == desc.Height && 2694 desc.Format == D3DFMT_A8R8G8B8 && format == GL_BGRA_EXT && type == GL_UNSIGNED_BYTE; 2695 if (directToPixels) 2696 { 2697 // Use the pixels ptr as a shared handle to write directly into client's memory 2698 result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, 2699 D3DPOOL_SYSTEMMEM, &systemSurface, reinterpret_cast<void**>(&pixels)); 2700 if (FAILED(result)) 2701 { 2702 // Try again without the shared handle 2703 directToPixels = false; 2704 } 2705 } 2706 2707 if (!directToPixels) 2708 { 2709 result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, 2710 D3DPOOL_SYSTEMMEM, &systemSurface, NULL); 2711 if (FAILED(result)) 2712 { 2713 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); 2714 SafeRelease(surface); 2715 return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal texture for ReadPixels."); 2716 } 2717 } 2718 2719 result = mDevice->GetRenderTargetData(surface, systemSurface); 2720 SafeRelease(surface); 2721 2722 if (FAILED(result)) 2723 { 2724 SafeRelease(systemSurface); 2725 2726 // It turns out that D3D will sometimes produce more error 2727 // codes than those documented. 2728 if (d3d9::isDeviceLostError(result)) 2729 { 2730 notifyDeviceLost(); 2731 } 2732 else 2733 { 2734 UNREACHABLE(); 2735 } 2736 2737 return gl::Error(GL_OUT_OF_MEMORY, "Failed to read internal render target data."); 2738 } 2739 2740 if (directToPixels) 2741 { 2742 SafeRelease(systemSurface); 2743 return gl::Error(GL_NO_ERROR); 2744 } 2745 2746 RECT rect; 2747 rect.left = gl::clamp(x, 0L, static_cast<LONG>(desc.Width)); 2748 rect.top = gl::clamp(y, 0L, static_cast<LONG>(desc.Height)); 2749 rect.right = gl::clamp(x + width, 0L, static_cast<LONG>(desc.Width)); 2750 rect.bottom = gl::clamp(y + height, 0L, static_cast<LONG>(desc.Height)); 2751 2752 D3DLOCKED_RECT lock; 2753 result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY); 2754 2755 if (FAILED(result)) 2756 { 2757 UNREACHABLE(); 2758 SafeRelease(systemSurface); 2759 2760 return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal render target."); 2761 } 2762 2763 uint8_t *source; 2764 int inputPitch; 2765 if (pack.reverseRowOrder) 2766 { 2767 source = reinterpret_cast<uint8_t*>(lock.pBits) + lock.Pitch * (rect.bottom - rect.top - 1); 2768 inputPitch = -lock.Pitch; 2769 } 2770 else 2771 { 2772 source = reinterpret_cast<uint8_t*>(lock.pBits); 2773 inputPitch = lock.Pitch; 2774 } 2775 2776 const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(desc.Format); 2777 const gl::InternalFormat &sourceFormatInfo = gl::GetInternalFormatInfo(d3dFormatInfo.internalFormat); 2778 if (sourceFormatInfo.format == format && sourceFormatInfo.type == type) 2779 { 2780 // Direct copy possible 2781 for (int y = 0; y < rect.bottom - rect.top; y++) 2782 { 2783 memcpy(pixels + y * outputPitch, source + y * inputPitch, (rect.right - rect.left) * sourceFormatInfo.pixelBytes); 2784 } 2785 } 2786 else 2787 { 2788 const d3d9::D3DFormat &sourceD3DFormatInfo = d3d9::GetD3DFormatInfo(desc.Format); 2789 ColorCopyFunction fastCopyFunc = sourceD3DFormatInfo.getFastCopyFunction(format, type); 2790 2791 const gl::FormatType &destFormatTypeInfo = gl::GetFormatTypeInfo(format, type); 2792 const gl::InternalFormat &destFormatInfo = gl::GetInternalFormatInfo(destFormatTypeInfo.internalFormat); 2793 2794 if (fastCopyFunc) 2795 { 2796 // Fast copy is possible through some special function 2797 for (int y = 0; y < rect.bottom - rect.top; y++) 2798 { 2799 for (int x = 0; x < rect.right - rect.left; x++) 2800 { 2801 uint8_t *dest = pixels + y * outputPitch + x * destFormatInfo.pixelBytes; 2802 const uint8_t *src = source + y * inputPitch + x * sourceFormatInfo.pixelBytes; 2803 2804 fastCopyFunc(src, dest); 2805 } 2806 } 2807 } 2808 else 2809 { 2810 uint8_t temp[sizeof(gl::ColorF)]; 2811 for (int y = 0; y < rect.bottom - rect.top; y++) 2812 { 2813 for (int x = 0; x < rect.right - rect.left; x++) 2814 { 2815 uint8_t *dest = pixels + y * outputPitch + x * destFormatInfo.pixelBytes; 2816 const uint8_t *src = source + y * inputPitch + x * sourceFormatInfo.pixelBytes; 2817 2818 // readFunc and writeFunc will be using the same type of color, CopyTexImage 2819 // will not allow the copy otherwise. 2820 sourceD3DFormatInfo.colorReadFunction(src, temp); 2821 destFormatTypeInfo.colorWriteFunction(temp, dest); 2822 } 2823 } 2824 } 2825 } 2826 2827 systemSurface->UnlockRect(); 2828 SafeRelease(systemSurface); 2829 2830 return gl::Error(GL_NO_ERROR); 2831 } 2832 2833 RenderTarget *Renderer9::createRenderTarget(SwapChain *swapChain, bool depth) 2834 { 2835 SwapChain9 *swapChain9 = SwapChain9::makeSwapChain9(swapChain); 2836 IDirect3DSurface9 *surface = NULL; 2837 if (depth) 2838 { 2839 surface = swapChain9->getDepthStencil(); 2840 } 2841 else 2842 { 2843 surface = swapChain9->getRenderTarget(); 2844 } 2845 2846 RenderTarget9 *renderTarget = new RenderTarget9(this, surface); 2847 2848 return renderTarget; 2849 } 2850 2851 RenderTarget *Renderer9::createRenderTarget(int width, int height, GLenum format, GLsizei samples) 2852 { 2853 RenderTarget9 *renderTarget = new RenderTarget9(this, width, height, format, samples); 2854 return renderTarget; 2855 } 2856 2857 ShaderImpl *Renderer9::createShader(GLenum type) 2858 { 2859 return new ShaderD3D(type, this); 2860 } 2861 2862 ProgramImpl *Renderer9::createProgram() 2863 { 2864 return new ProgramD3D(this); 2865 } 2866 2867 void Renderer9::releaseShaderCompiler() 2868 { 2869 ShaderD3D::releaseCompiler(); 2870 } 2871 2872 ShaderExecutable *Renderer9::loadExecutable(const void *function, size_t length, rx::ShaderType type, 2873 const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, 2874 bool separatedOutputBuffers) 2875 { 2876 // Transform feedback is not supported in ES2 or D3D9 2877 ASSERT(transformFeedbackVaryings.size() == 0); 2878 2879 ShaderExecutable9 *executable = NULL; 2880 2881 switch (type) 2882 { 2883 case rx::SHADER_VERTEX: 2884 { 2885 IDirect3DVertexShader9 *vshader = createVertexShader((DWORD*)function, length); 2886 if (vshader) 2887 { 2888 executable = new ShaderExecutable9(function, length, vshader); 2889 } 2890 } 2891 break; 2892 case rx::SHADER_PIXEL: 2893 { 2894 IDirect3DPixelShader9 *pshader = createPixelShader((DWORD*)function, length); 2895 if (pshader) 2896 { 2897 executable = new ShaderExecutable9(function, length, pshader); 2898 } 2899 } 2900 break; 2901 default: 2902 UNREACHABLE(); 2903 break; 2904 } 2905 2906 return executable; 2907 } 2908 2909 ShaderExecutable *Renderer9::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, 2910 const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, 2911 bool separatedOutputBuffers, D3DWorkaroundType workaround) 2912 { 2913 // Transform feedback is not supported in ES2 or D3D9 2914 ASSERT(transformFeedbackVaryings.size() == 0); 2915 2916 const char *profile = NULL; 2917 2918 switch (type) 2919 { 2920 case rx::SHADER_VERTEX: 2921 profile = getMajorShaderModel() >= 3 ? "vs_3_0" : "vs_2_0"; 2922 break; 2923 case rx::SHADER_PIXEL: 2924 profile = getMajorShaderModel() >= 3 ? "ps_3_0" : "ps_2_0"; 2925 break; 2926 default: 2927 UNREACHABLE(); 2928 return NULL; 2929 } 2930 2931 UINT flags = ANGLE_COMPILE_OPTIMIZATION_LEVEL; 2932 2933 if (workaround == ANGLE_D3D_WORKAROUND_SKIP_OPTIMIZATION) 2934 { 2935 flags = D3DCOMPILE_SKIP_OPTIMIZATION; 2936 } 2937 else if (workaround == ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION) 2938 { 2939 flags = D3DCOMPILE_OPTIMIZATION_LEVEL3; 2940 } 2941 else ASSERT(workaround == ANGLE_D3D_WORKAROUND_NONE); 2942 2943 if (gl::perfActive()) 2944 { 2945 #ifndef NDEBUG 2946 flags = D3DCOMPILE_SKIP_OPTIMIZATION; 2947 #endif 2948 2949 flags |= D3DCOMPILE_DEBUG; 2950 2951 std::string sourcePath = getTempPath(); 2952 std::string sourceText = std::string("#line 2 \"") + sourcePath + std::string("\"\n\n") + std::string(shaderHLSL); 2953 writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size()); 2954 } 2955 2956 // Sometimes D3DCompile will fail with the default compilation flags for complicated shaders when it would otherwise pass with alternative options. 2957 // Try the default flags first and if compilation fails, try some alternatives. 2958 const UINT extraFlags[] = 2959 { 2960 flags, 2961 flags | D3DCOMPILE_AVOID_FLOW_CONTROL, 2962 flags | D3DCOMPILE_PREFER_FLOW_CONTROL 2963 }; 2964 2965 const static char *extraFlagNames[] = 2966 { 2967 "default", 2968 "avoid flow control", 2969 "prefer flow control" 2970 }; 2971 2972 int attempts = ArraySize(extraFlags); 2973 2974 ID3DBlob *binary = (ID3DBlob*)mCompiler.compileToBinary(infoLog, shaderHLSL, profile, extraFlags, extraFlagNames, attempts); 2975 if (!binary) 2976 { 2977 return NULL; 2978 } 2979 2980 ShaderExecutable *executable = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type, 2981 transformFeedbackVaryings, separatedOutputBuffers); 2982 SafeRelease(binary); 2983 2984 return executable; 2985 } 2986 2987 rx::UniformStorage *Renderer9::createUniformStorage(size_t storageSize) 2988 { 2989 return new UniformStorage(storageSize); 2990 } 2991 2992 bool Renderer9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest) 2993 { 2994 return mBlit->boxFilter(source, dest); 2995 } 2996 2997 D3DPOOL Renderer9::getTexturePool(DWORD usage) const 2998 { 2999 if (mD3d9Ex != NULL) 3000 { 3001 return D3DPOOL_DEFAULT; 3002 } 3003 else 3004 { 3005 if (!(usage & (D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_RENDERTARGET))) 3006 { 3007 return D3DPOOL_MANAGED; 3008 } 3009 } 3010 3011 return D3DPOOL_DEFAULT; 3012 } 3013 3014 bool Renderer9::copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged) 3015 { 3016 if (source && dest) 3017 { 3018 HRESULT result = D3DERR_OUTOFVIDEOMEMORY; 3019 3020 if (fromManaged) 3021 { 3022 D3DSURFACE_DESC desc; 3023 source->GetDesc(&desc); 3024 3025 IDirect3DSurface9 *surf = 0; 3026 result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL); 3027 3028 if (SUCCEEDED(result)) 3029 { 3030 Image9::copyLockableSurfaces(surf, source); 3031 result = mDevice->UpdateSurface(surf, NULL, dest, NULL); 3032 SafeRelease(surf); 3033 } 3034 } 3035 else 3036 { 3037 endScene(); 3038 result = mDevice->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE); 3039 } 3040 3041 if (FAILED(result)) 3042 { 3043 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); 3044 return false; 3045 } 3046 } 3047 3048 return true; 3049 } 3050 3051 Image *Renderer9::createImage() 3052 { 3053 return new Image9(); 3054 } 3055 3056 void Renderer9::generateMipmap(Image *dest, Image *src) 3057 { 3058 Image9 *src9 = Image9::makeImage9(src); 3059 Image9 *dst9 = Image9::makeImage9(dest); 3060 Image9::generateMipmap(dst9, src9); 3061 } 3062 3063 TextureStorage *Renderer9::createTextureStorage2D(SwapChain *swapChain) 3064 { 3065 SwapChain9 *swapChain9 = SwapChain9::makeSwapChain9(swapChain); 3066 return new TextureStorage9_2D(this, swapChain9); 3067 } 3068 3069 TextureStorage *Renderer9::createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) 3070 { 3071 return new TextureStorage9_2D(this, internalformat, renderTarget, width, height, levels); 3072 } 3073 3074 TextureStorage *Renderer9::createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels) 3075 { 3076 return new TextureStorage9_Cube(this, internalformat, renderTarget, size, levels); 3077 } 3078 3079 TextureStorage *Renderer9::createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) 3080 { 3081 // 3D textures are not supported by the D3D9 backend. 3082 UNREACHABLE(); 3083 3084 return NULL; 3085 } 3086 3087 TextureStorage *Renderer9::createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) 3088 { 3089 // 2D array textures are not supported by the D3D9 backend. 3090 UNREACHABLE(); 3091 3092 return NULL; 3093 } 3094 3095 TextureImpl *Renderer9::createTexture(GLenum target) 3096 { 3097 switch(target) 3098 { 3099 case GL_TEXTURE_2D: return new TextureD3D_2D(this); 3100 case GL_TEXTURE_CUBE_MAP: return new TextureD3D_Cube(this); 3101 default: UNREACHABLE(); 3102 } 3103 3104 return NULL; 3105 } 3106 3107 bool Renderer9::getLUID(LUID *adapterLuid) const 3108 { 3109 adapterLuid->HighPart = 0; 3110 adapterLuid->LowPart = 0; 3111 3112 if (mD3d9Ex) 3113 { 3114 mD3d9Ex->GetAdapterLUID(mAdapter, adapterLuid); 3115 return true; 3116 } 3117 3118 return false; 3119 } 3120 3121 rx::VertexConversionType Renderer9::getVertexConversionType(const gl::VertexFormat &vertexFormat) const 3122 { 3123 return d3d9::GetVertexFormatInfo(getCapsDeclTypes(), vertexFormat).conversionType; 3124 } 3125 3126 GLenum Renderer9::getVertexComponentType(const gl::VertexFormat &vertexFormat) const 3127 { 3128 return d3d9::GetVertexFormatInfo(getCapsDeclTypes(), vertexFormat).componentType; 3129 } 3130 3131 void Renderer9::generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const 3132 { 3133 d3d9_gl::GenerateCaps(mD3d9, mDevice, mDeviceType, mAdapter, outCaps, outTextureCaps, outExtensions); 3134 } 3135 3136 } 3137