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