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