1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/angle/src/libGLESv2/renderer/Renderer9.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,3222 @@ 1.4 +#include "precompiled.h" 1.5 +// 1.6 +// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. 1.7 +// Use of this source code is governed by a BSD-style license that can be 1.8 +// found in the LICENSE file. 1.9 +// 1.10 + 1.11 +// Renderer9.cpp: Implements a back-end specific class for the D3D9 renderer. 1.12 + 1.13 +#include "libGLESv2/main.h" 1.14 +#include "libGLESv2/Buffer.h" 1.15 +#include "libGLESv2/Texture.h" 1.16 +#include "libGLESv2/Framebuffer.h" 1.17 +#include "libGLESv2/Renderbuffer.h" 1.18 +#include "libGLESv2/ProgramBinary.h" 1.19 +#include "libGLESv2/renderer/IndexDataManager.h" 1.20 +#include "libGLESv2/renderer/Renderer9.h" 1.21 +#include "libGLESv2/renderer/renderer9_utils.h" 1.22 +#include "libGLESv2/renderer/ShaderExecutable9.h" 1.23 +#include "libGLESv2/renderer/SwapChain9.h" 1.24 +#include "libGLESv2/renderer/TextureStorage9.h" 1.25 +#include "libGLESv2/renderer/Image9.h" 1.26 +#include "libGLESv2/renderer/Blit.h" 1.27 +#include "libGLESv2/renderer/RenderTarget9.h" 1.28 +#include "libGLESv2/renderer/VertexBuffer9.h" 1.29 +#include "libGLESv2/renderer/IndexBuffer9.h" 1.30 +#include "libGLESv2/renderer/BufferStorage9.h" 1.31 +#include "libGLESv2/renderer/Query9.h" 1.32 +#include "libGLESv2/renderer/Fence9.h" 1.33 + 1.34 +#include "libEGL/Display.h" 1.35 + 1.36 +// Can also be enabled by defining FORCE_REF_RAST in the project's predefined macros 1.37 +#define REF_RAST 0 1.38 + 1.39 +// The "Debug This Pixel..." feature in PIX often fails when using the 1.40 +// D3D9Ex interfaces. In order to get debug pixel to work on a Vista/Win 7 1.41 +// machine, define "ANGLE_ENABLE_D3D9EX=0" in your project file. 1.42 +#if !defined(ANGLE_ENABLE_D3D9EX) 1.43 +// Enables use of the IDirect3D9Ex interface, when available 1.44 +#define ANGLE_ENABLE_D3D9EX 1 1.45 +#endif // !defined(ANGLE_ENABLE_D3D9EX) 1.46 + 1.47 +namespace rx 1.48 +{ 1.49 +static const D3DFORMAT RenderTargetFormats[] = 1.50 + { 1.51 + D3DFMT_A1R5G5B5, 1.52 + // D3DFMT_A2R10G10B10, // The color_ramp conformance test uses ReadPixels with UNSIGNED_BYTE causing it to think that rendering skipped a colour value. 1.53 + D3DFMT_A8R8G8B8, 1.54 + D3DFMT_R5G6B5, 1.55 + // D3DFMT_X1R5G5B5, // Has no compatible OpenGL ES renderbuffer format 1.56 + D3DFMT_X8R8G8B8 1.57 + }; 1.58 + 1.59 +static const D3DFORMAT DepthStencilFormats[] = 1.60 + { 1.61 + D3DFMT_UNKNOWN, 1.62 + // D3DFMT_D16_LOCKABLE, 1.63 + D3DFMT_D32, 1.64 + // D3DFMT_D15S1, 1.65 + D3DFMT_D24S8, 1.66 + D3DFMT_D24X8, 1.67 + // D3DFMT_D24X4S4, 1.68 + D3DFMT_D16, 1.69 + // D3DFMT_D32F_LOCKABLE, 1.70 + // D3DFMT_D24FS8 1.71 + }; 1.72 + 1.73 +enum 1.74 +{ 1.75 + MAX_VERTEX_CONSTANT_VECTORS_D3D9 = 256, 1.76 + MAX_PIXEL_CONSTANT_VECTORS_SM2 = 32, 1.77 + MAX_PIXEL_CONSTANT_VECTORS_SM3 = 224, 1.78 + MAX_VARYING_VECTORS_SM2 = 8, 1.79 + MAX_VARYING_VECTORS_SM3 = 10, 1.80 + 1.81 + MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 = 4 1.82 +}; 1.83 + 1.84 +Renderer9::Renderer9(egl::Display *display, HDC hDc, bool softwareDevice) : Renderer(display), mDc(hDc), mSoftwareDevice(softwareDevice) 1.85 +{ 1.86 + mD3d9Module = NULL; 1.87 + 1.88 + mD3d9 = NULL; 1.89 + mD3d9Ex = NULL; 1.90 + mDevice = NULL; 1.91 + mDeviceEx = NULL; 1.92 + mDeviceWindow = NULL; 1.93 + mBlit = NULL; 1.94 + 1.95 + mAdapter = D3DADAPTER_DEFAULT; 1.96 + 1.97 + #if REF_RAST == 1 || defined(FORCE_REF_RAST) 1.98 + mDeviceType = D3DDEVTYPE_REF; 1.99 + #else 1.100 + mDeviceType = D3DDEVTYPE_HAL; 1.101 + #endif 1.102 + 1.103 + mDeviceLost = false; 1.104 + 1.105 + mMaxSupportedSamples = 0; 1.106 + 1.107 + mMaskedClearSavedState = NULL; 1.108 + 1.109 + mVertexDataManager = NULL; 1.110 + mIndexDataManager = NULL; 1.111 + mLineLoopIB = NULL; 1.112 + 1.113 + mMaxNullColorbufferLRU = 0; 1.114 + for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++) 1.115 + { 1.116 + mNullColorbufferCache[i].lruCount = 0; 1.117 + mNullColorbufferCache[i].width = 0; 1.118 + mNullColorbufferCache[i].height = 0; 1.119 + mNullColorbufferCache[i].buffer = NULL; 1.120 + } 1.121 +} 1.122 + 1.123 +Renderer9::~Renderer9() 1.124 +{ 1.125 + releaseDeviceResources(); 1.126 + 1.127 + if (mDevice) 1.128 + { 1.129 + // If the device is lost, reset it first to prevent leaving the driver in an unstable state 1.130 + if (testDeviceLost(false)) 1.131 + { 1.132 + resetDevice(); 1.133 + } 1.134 + 1.135 + mDevice->Release(); 1.136 + mDevice = NULL; 1.137 + } 1.138 + 1.139 + if (mDeviceEx) 1.140 + { 1.141 + mDeviceEx->Release(); 1.142 + mDeviceEx = NULL; 1.143 + } 1.144 + 1.145 + if (mD3d9) 1.146 + { 1.147 + mD3d9->Release(); 1.148 + mD3d9 = NULL; 1.149 + } 1.150 + 1.151 + if (mDeviceWindow) 1.152 + { 1.153 + DestroyWindow(mDeviceWindow); 1.154 + mDeviceWindow = NULL; 1.155 + } 1.156 + 1.157 + if (mD3d9Ex) 1.158 + { 1.159 + mD3d9Ex->Release(); 1.160 + mD3d9Ex = NULL; 1.161 + } 1.162 + 1.163 + if (mD3d9Module) 1.164 + { 1.165 + mD3d9Module = NULL; 1.166 + } 1.167 + 1.168 + while (!mMultiSampleSupport.empty()) 1.169 + { 1.170 + delete [] mMultiSampleSupport.begin()->second; 1.171 + mMultiSampleSupport.erase(mMultiSampleSupport.begin()); 1.172 + } 1.173 +} 1.174 + 1.175 +Renderer9 *Renderer9::makeRenderer9(Renderer *renderer) 1.176 +{ 1.177 + ASSERT(HAS_DYNAMIC_TYPE(rx::Renderer9*, renderer)); 1.178 + return static_cast<rx::Renderer9*>(renderer); 1.179 +} 1.180 + 1.181 +EGLint Renderer9::initialize() 1.182 +{ 1.183 + if (!initializeCompiler()) 1.184 + { 1.185 + return EGL_NOT_INITIALIZED; 1.186 + } 1.187 + 1.188 + if (mSoftwareDevice) 1.189 + { 1.190 + mD3d9Module = GetModuleHandle(TEXT("swiftshader_d3d9.dll")); 1.191 + } 1.192 + else 1.193 + { 1.194 + mD3d9Module = GetModuleHandle(TEXT("d3d9.dll")); 1.195 + } 1.196 + 1.197 + if (mD3d9Module == NULL) 1.198 + { 1.199 + ERR("No D3D9 module found - aborting!\n"); 1.200 + return EGL_NOT_INITIALIZED; 1.201 + } 1.202 + 1.203 + typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex**); 1.204 + Direct3DCreate9ExFunc Direct3DCreate9ExPtr = reinterpret_cast<Direct3DCreate9ExFunc>(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex")); 1.205 + 1.206 + // Use Direct3D9Ex if available. Among other things, this version is less 1.207 + // inclined to report a lost context, for example when the user switches 1.208 + // desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are available. 1.209 + if (ANGLE_ENABLE_D3D9EX && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex))) 1.210 + { 1.211 + ASSERT(mD3d9Ex); 1.212 + mD3d9Ex->QueryInterface(IID_IDirect3D9, reinterpret_cast<void**>(&mD3d9)); 1.213 + ASSERT(mD3d9); 1.214 + } 1.215 + else 1.216 + { 1.217 + mD3d9 = Direct3DCreate9(D3D_SDK_VERSION); 1.218 + } 1.219 + 1.220 + if (!mD3d9) 1.221 + { 1.222 + ERR("Could not create D3D9 device - aborting!\n"); 1.223 + return EGL_NOT_INITIALIZED; 1.224 + } 1.225 + 1.226 + if (mDc != NULL) 1.227 + { 1.228 + // UNIMPLEMENTED(); // FIXME: Determine which adapter index the device context corresponds to 1.229 + } 1.230 + 1.231 + HRESULT result; 1.232 + 1.233 + // Give up on getting device caps after about one second. 1.234 + for (int i = 0; i < 10; ++i) 1.235 + { 1.236 + result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps); 1.237 + if (SUCCEEDED(result)) 1.238 + { 1.239 + break; 1.240 + } 1.241 + else if (result == D3DERR_NOTAVAILABLE) 1.242 + { 1.243 + Sleep(100); // Give the driver some time to initialize/recover 1.244 + } 1.245 + else if (FAILED(result)) // D3DERR_OUTOFVIDEOMEMORY, E_OUTOFMEMORY, D3DERR_INVALIDDEVICE, or another error we can't recover from 1.246 + { 1.247 + ERR("failed to get device caps (0x%x)\n", result); 1.248 + return EGL_NOT_INITIALIZED; 1.249 + } 1.250 + } 1.251 + 1.252 + if (mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(2, 0)) 1.253 + { 1.254 + ERR("Renderer does not support PS 2.0. aborting!\n"); 1.255 + return EGL_NOT_INITIALIZED; 1.256 + } 1.257 + 1.258 + // When DirectX9 is running with an older DirectX8 driver, a StretchRect from a regular texture to a render target texture is not supported. 1.259 + // This is required by Texture2D::convertToRenderTarget. 1.260 + if ((mDeviceCaps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES) == 0) 1.261 + { 1.262 + ERR("Renderer does not support stretctrect from textures!\n"); 1.263 + return EGL_NOT_INITIALIZED; 1.264 + } 1.265 + 1.266 + mD3d9->GetAdapterIdentifier(mAdapter, 0, &mAdapterIdentifier); 1.267 + 1.268 + // ATI cards on XP have problems with non-power-of-two textures. 1.269 + mSupportsNonPower2Textures = !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_POW2) && 1.270 + !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) && 1.271 + !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) && 1.272 + !(getComparableOSVersion() < versionWindowsVista && mAdapterIdentifier.VendorId == VENDOR_ID_AMD); 1.273 + 1.274 + // Must support a minimum of 2:1 anisotropy for max anisotropy to be considered supported, per the spec 1.275 + mSupportsTextureFilterAnisotropy = ((mDeviceCaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) && (mDeviceCaps.MaxAnisotropy >= 2)); 1.276 + 1.277 + mMinSwapInterval = 4; 1.278 + mMaxSwapInterval = 0; 1.279 + 1.280 + if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE) 1.281 + { 1.282 + mMinSwapInterval = std::min(mMinSwapInterval, 0); 1.283 + mMaxSwapInterval = std::max(mMaxSwapInterval, 0); 1.284 + } 1.285 + if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_ONE) 1.286 + { 1.287 + mMinSwapInterval = std::min(mMinSwapInterval, 1); 1.288 + mMaxSwapInterval = std::max(mMaxSwapInterval, 1); 1.289 + } 1.290 + if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_TWO) 1.291 + { 1.292 + mMinSwapInterval = std::min(mMinSwapInterval, 2); 1.293 + mMaxSwapInterval = std::max(mMaxSwapInterval, 2); 1.294 + } 1.295 + if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_THREE) 1.296 + { 1.297 + mMinSwapInterval = std::min(mMinSwapInterval, 3); 1.298 + mMaxSwapInterval = std::max(mMaxSwapInterval, 3); 1.299 + } 1.300 + if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_FOUR) 1.301 + { 1.302 + mMinSwapInterval = std::min(mMinSwapInterval, 4); 1.303 + mMaxSwapInterval = std::max(mMaxSwapInterval, 4); 1.304 + } 1.305 + 1.306 + int max = 0; 1.307 + for (unsigned int i = 0; i < ArraySize(RenderTargetFormats); ++i) 1.308 + { 1.309 + bool *multisampleArray = new bool[D3DMULTISAMPLE_16_SAMPLES + 1]; 1.310 + getMultiSampleSupport(RenderTargetFormats[i], multisampleArray); 1.311 + mMultiSampleSupport[RenderTargetFormats[i]] = multisampleArray; 1.312 + 1.313 + for (int j = D3DMULTISAMPLE_16_SAMPLES; j >= 0; --j) 1.314 + { 1.315 + if (multisampleArray[j] && j != D3DMULTISAMPLE_NONMASKABLE && j > max) 1.316 + { 1.317 + max = j; 1.318 + } 1.319 + } 1.320 + } 1.321 + 1.322 + for (unsigned int i = 0; i < ArraySize(DepthStencilFormats); ++i) 1.323 + { 1.324 + if (DepthStencilFormats[i] == D3DFMT_UNKNOWN) 1.325 + continue; 1.326 + 1.327 + bool *multisampleArray = new bool[D3DMULTISAMPLE_16_SAMPLES + 1]; 1.328 + getMultiSampleSupport(DepthStencilFormats[i], multisampleArray); 1.329 + mMultiSampleSupport[DepthStencilFormats[i]] = multisampleArray; 1.330 + 1.331 + for (int j = D3DMULTISAMPLE_16_SAMPLES; j >= 0; --j) 1.332 + { 1.333 + if (multisampleArray[j] && j != D3DMULTISAMPLE_NONMASKABLE && j > max) 1.334 + { 1.335 + max = j; 1.336 + } 1.337 + } 1.338 + } 1.339 + 1.340 + mMaxSupportedSamples = max; 1.341 + 1.342 + static const TCHAR windowName[] = TEXT("AngleHiddenWindow"); 1.343 + static const TCHAR className[] = TEXT("STATIC"); 1.344 + 1.345 + mDeviceWindow = CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL); 1.346 + 1.347 + D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters(); 1.348 + DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES; 1.349 + 1.350 + result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice); 1.351 + if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DEVICELOST) 1.352 + { 1.353 + return EGL_BAD_ALLOC; 1.354 + } 1.355 + 1.356 + if (FAILED(result)) 1.357 + { 1.358 + result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParameters, &mDevice); 1.359 + 1.360 + if (FAILED(result)) 1.361 + { 1.362 + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_NOTAVAILABLE || result == D3DERR_DEVICELOST); 1.363 + return EGL_BAD_ALLOC; 1.364 + } 1.365 + } 1.366 + 1.367 + if (mD3d9Ex) 1.368 + { 1.369 + result = mDevice->QueryInterface(IID_IDirect3DDevice9Ex, (void**) &mDeviceEx); 1.370 + ASSERT(SUCCEEDED(result)); 1.371 + } 1.372 + 1.373 + mVertexShaderCache.initialize(mDevice); 1.374 + mPixelShaderCache.initialize(mDevice); 1.375 + 1.376 + // Check occlusion query support 1.377 + IDirect3DQuery9 *occlusionQuery = NULL; 1.378 + if (SUCCEEDED(mDevice->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery)) && occlusionQuery) 1.379 + { 1.380 + occlusionQuery->Release(); 1.381 + mOcclusionQuerySupport = true; 1.382 + } 1.383 + else 1.384 + { 1.385 + mOcclusionQuerySupport = false; 1.386 + } 1.387 + 1.388 + // Check event query support 1.389 + IDirect3DQuery9 *eventQuery = NULL; 1.390 + if (SUCCEEDED(mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery)) && eventQuery) 1.391 + { 1.392 + eventQuery->Release(); 1.393 + mEventQuerySupport = true; 1.394 + } 1.395 + else 1.396 + { 1.397 + mEventQuerySupport = false; 1.398 + } 1.399 + 1.400 + D3DDISPLAYMODE currentDisplayMode; 1.401 + mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); 1.402 + 1.403 + // Check vertex texture support 1.404 + // Only Direct3D 10 ready devices support all the necessary vertex texture formats. 1.405 + // We test this using D3D9 by checking support for the R16F format. 1.406 + mVertexTextureSupport = mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0) && 1.407 + SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 1.408 + D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_R16F)); 1.409 + 1.410 + // Check depth texture support 1.411 + // we use INTZ for depth textures in Direct3D9 1.412 + // we also want NULL texture support to ensure the we can make depth-only FBOs 1.413 + // see http://aras-p.info/texts/D3D9GPUHacks.html 1.414 + mDepthTextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 1.415 + D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, D3DFMT_INTZ)) && 1.416 + SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 1.417 + D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_NULL)); 1.418 + 1.419 + // Check 32 bit floating point texture support 1.420 + mFloat32FilterSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER, 1.421 + D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) && 1.422 + SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER, 1.423 + D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F)); 1.424 + 1.425 + mFloat32RenderSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, 1.426 + D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) && 1.427 + SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, 1.428 + D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F)); 1.429 + 1.430 + if (!mFloat32FilterSupport && !mFloat32RenderSupport) 1.431 + { 1.432 + mFloat32TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, 1.433 + D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) && 1.434 + SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, 1.435 + D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F)); 1.436 + } 1.437 + else 1.438 + { 1.439 + mFloat32TextureSupport = true; 1.440 + } 1.441 + 1.442 + // Check 16 bit floating point texture support 1.443 + mFloat16FilterSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER, 1.444 + D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) && 1.445 + SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER, 1.446 + D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F)); 1.447 + 1.448 + mFloat16RenderSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, 1.449 + D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) && 1.450 + SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, 1.451 + D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F)); 1.452 + 1.453 + if (!mFloat16FilterSupport && !mFloat16RenderSupport) 1.454 + { 1.455 + mFloat16TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, 1.456 + D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) && 1.457 + SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, 1.458 + D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F)); 1.459 + } 1.460 + else 1.461 + { 1.462 + mFloat16TextureSupport = true; 1.463 + } 1.464 + 1.465 + // Check DXT texture support 1.466 + mDXT1TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT1)); 1.467 + mDXT3TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT3)); 1.468 + mDXT5TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT5)); 1.469 + 1.470 + // Check luminance[alpha] texture support 1.471 + mLuminanceTextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_L8)); 1.472 + mLuminanceAlphaTextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_A8L8)); 1.473 + 1.474 + initializeDevice(); 1.475 + 1.476 + return EGL_SUCCESS; 1.477 +} 1.478 + 1.479 +// do any one-time device initialization 1.480 +// NOTE: this is also needed after a device lost/reset 1.481 +// to reset the scene status and ensure the default states are reset. 1.482 +void Renderer9::initializeDevice() 1.483 +{ 1.484 + // Permanent non-default states 1.485 + mDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE); 1.486 + mDevice->SetRenderState(D3DRS_LASTPIXEL, FALSE); 1.487 + 1.488 + if (mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0)) 1.489 + { 1.490 + mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, (DWORD&)mDeviceCaps.MaxPointSize); 1.491 + } 1.492 + else 1.493 + { 1.494 + mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, 0x3F800000); // 1.0f 1.495 + } 1.496 + 1.497 + markAllStateDirty(); 1.498 + 1.499 + mSceneStarted = false; 1.500 + 1.501 + ASSERT(!mBlit && !mVertexDataManager && !mIndexDataManager); 1.502 + mBlit = new Blit(this); 1.503 + mVertexDataManager = new rx::VertexDataManager(this); 1.504 + mIndexDataManager = new rx::IndexDataManager(this); 1.505 +} 1.506 + 1.507 +D3DPRESENT_PARAMETERS Renderer9::getDefaultPresentParameters() 1.508 +{ 1.509 + D3DPRESENT_PARAMETERS presentParameters = {0}; 1.510 + 1.511 + // The default swap chain is never actually used. Surface will create a new swap chain with the proper parameters. 1.512 + presentParameters.AutoDepthStencilFormat = D3DFMT_UNKNOWN; 1.513 + presentParameters.BackBufferCount = 1; 1.514 + presentParameters.BackBufferFormat = D3DFMT_UNKNOWN; 1.515 + presentParameters.BackBufferWidth = 1; 1.516 + presentParameters.BackBufferHeight = 1; 1.517 + presentParameters.EnableAutoDepthStencil = FALSE; 1.518 + presentParameters.Flags = 0; 1.519 + presentParameters.hDeviceWindow = mDeviceWindow; 1.520 + presentParameters.MultiSampleQuality = 0; 1.521 + presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE; 1.522 + presentParameters.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; 1.523 + presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD; 1.524 + presentParameters.Windowed = TRUE; 1.525 + 1.526 + return presentParameters; 1.527 +} 1.528 + 1.529 +int Renderer9::generateConfigs(ConfigDesc **configDescList) 1.530 +{ 1.531 + D3DDISPLAYMODE currentDisplayMode; 1.532 + mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); 1.533 + 1.534 + unsigned int numRenderFormats = ArraySize(RenderTargetFormats); 1.535 + unsigned int numDepthFormats = ArraySize(DepthStencilFormats); 1.536 + (*configDescList) = new ConfigDesc[numRenderFormats * numDepthFormats]; 1.537 + int numConfigs = 0; 1.538 + 1.539 + for (unsigned int formatIndex = 0; formatIndex < numRenderFormats; formatIndex++) 1.540 + { 1.541 + D3DFORMAT renderTargetFormat = RenderTargetFormats[formatIndex]; 1.542 + 1.543 + HRESULT result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, renderTargetFormat); 1.544 + 1.545 + if (SUCCEEDED(result)) 1.546 + { 1.547 + for (unsigned int depthStencilIndex = 0; depthStencilIndex < numDepthFormats; depthStencilIndex++) 1.548 + { 1.549 + D3DFORMAT depthStencilFormat = DepthStencilFormats[depthStencilIndex]; 1.550 + HRESULT result = D3D_OK; 1.551 + 1.552 + if(depthStencilFormat != D3DFMT_UNKNOWN) 1.553 + { 1.554 + result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, depthStencilFormat); 1.555 + } 1.556 + 1.557 + if (SUCCEEDED(result)) 1.558 + { 1.559 + if(depthStencilFormat != D3DFMT_UNKNOWN) 1.560 + { 1.561 + result = mD3d9->CheckDepthStencilMatch(mAdapter, mDeviceType, currentDisplayMode.Format, renderTargetFormat, depthStencilFormat); 1.562 + } 1.563 + 1.564 + if (SUCCEEDED(result)) 1.565 + { 1.566 + ConfigDesc newConfig; 1.567 + newConfig.renderTargetFormat = d3d9_gl::ConvertBackBufferFormat(renderTargetFormat); 1.568 + newConfig.depthStencilFormat = d3d9_gl::ConvertDepthStencilFormat(depthStencilFormat); 1.569 + newConfig.multiSample = 0; // FIXME: enumerate multi-sampling 1.570 + newConfig.fastConfig = (currentDisplayMode.Format == renderTargetFormat); 1.571 + 1.572 + (*configDescList)[numConfigs++] = newConfig; 1.573 + } 1.574 + } 1.575 + } 1.576 + } 1.577 + } 1.578 + 1.579 + return numConfigs; 1.580 +} 1.581 + 1.582 +void Renderer9::deleteConfigs(ConfigDesc *configDescList) 1.583 +{ 1.584 + delete [] (configDescList); 1.585 +} 1.586 + 1.587 +void Renderer9::startScene() 1.588 +{ 1.589 + if (!mSceneStarted) 1.590 + { 1.591 + long result = mDevice->BeginScene(); 1.592 + if (SUCCEEDED(result)) { 1.593 + // This is defensive checking against the device being 1.594 + // lost at unexpected times. 1.595 + mSceneStarted = true; 1.596 + } 1.597 + } 1.598 +} 1.599 + 1.600 +void Renderer9::endScene() 1.601 +{ 1.602 + if (mSceneStarted) 1.603 + { 1.604 + // EndScene can fail if the device was lost, for example due 1.605 + // to a TDR during a draw call. 1.606 + mDevice->EndScene(); 1.607 + mSceneStarted = false; 1.608 + } 1.609 +} 1.610 + 1.611 +void Renderer9::sync(bool block) 1.612 +{ 1.613 + HRESULT result; 1.614 + 1.615 + IDirect3DQuery9* query = allocateEventQuery(); 1.616 + if (!query) 1.617 + { 1.618 + return; 1.619 + } 1.620 + 1.621 + result = query->Issue(D3DISSUE_END); 1.622 + ASSERT(SUCCEEDED(result)); 1.623 + 1.624 + do 1.625 + { 1.626 + result = query->GetData(NULL, 0, D3DGETDATA_FLUSH); 1.627 + 1.628 + if(block && result == S_FALSE) 1.629 + { 1.630 + // Keep polling, but allow other threads to do something useful first 1.631 + Sleep(0); 1.632 + // explicitly check for device loss 1.633 + // some drivers seem to return S_FALSE even if the device is lost 1.634 + // instead of D3DERR_DEVICELOST like they should 1.635 + if (testDeviceLost(false)) 1.636 + { 1.637 + result = D3DERR_DEVICELOST; 1.638 + } 1.639 + } 1.640 + } 1.641 + while(block && result == S_FALSE); 1.642 + 1.643 + freeEventQuery(query); 1.644 + 1.645 + if (d3d9::isDeviceLostError(result)) 1.646 + { 1.647 + notifyDeviceLost(); 1.648 + } 1.649 +} 1.650 + 1.651 +SwapChain *Renderer9::createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) 1.652 +{ 1.653 + return new rx::SwapChain9(this, window, shareHandle, backBufferFormat, depthBufferFormat); 1.654 +} 1.655 + 1.656 +IDirect3DQuery9* Renderer9::allocateEventQuery() 1.657 +{ 1.658 + IDirect3DQuery9 *query = NULL; 1.659 + 1.660 + if (mEventQueryPool.empty()) 1.661 + { 1.662 + HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &query); 1.663 + ASSERT(SUCCEEDED(result)); 1.664 + } 1.665 + else 1.666 + { 1.667 + query = mEventQueryPool.back(); 1.668 + mEventQueryPool.pop_back(); 1.669 + } 1.670 + 1.671 + return query; 1.672 +} 1.673 + 1.674 +void Renderer9::freeEventQuery(IDirect3DQuery9* query) 1.675 +{ 1.676 + if (mEventQueryPool.size() > 1000) 1.677 + { 1.678 + query->Release(); 1.679 + } 1.680 + else 1.681 + { 1.682 + mEventQueryPool.push_back(query); 1.683 + } 1.684 +} 1.685 + 1.686 +IDirect3DVertexShader9 *Renderer9::createVertexShader(const DWORD *function, size_t length) 1.687 +{ 1.688 + return mVertexShaderCache.create(function, length); 1.689 +} 1.690 + 1.691 +IDirect3DPixelShader9 *Renderer9::createPixelShader(const DWORD *function, size_t length) 1.692 +{ 1.693 + return mPixelShaderCache.create(function, length); 1.694 +} 1.695 + 1.696 +HRESULT Renderer9::createVertexBuffer(UINT Length, DWORD Usage, IDirect3DVertexBuffer9 **ppVertexBuffer) 1.697 +{ 1.698 + D3DPOOL Pool = getBufferPool(Usage); 1.699 + return mDevice->CreateVertexBuffer(Length, Usage, 0, Pool, ppVertexBuffer, NULL); 1.700 +} 1.701 + 1.702 +VertexBuffer *Renderer9::createVertexBuffer() 1.703 +{ 1.704 + return new VertexBuffer9(this); 1.705 +} 1.706 + 1.707 +HRESULT Renderer9::createIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, IDirect3DIndexBuffer9 **ppIndexBuffer) 1.708 +{ 1.709 + D3DPOOL Pool = getBufferPool(Usage); 1.710 + return mDevice->CreateIndexBuffer(Length, Usage, Format, Pool, ppIndexBuffer, NULL); 1.711 +} 1.712 + 1.713 +IndexBuffer *Renderer9::createIndexBuffer() 1.714 +{ 1.715 + return new IndexBuffer9(this); 1.716 +} 1.717 + 1.718 +BufferStorage *Renderer9::createBufferStorage() 1.719 +{ 1.720 + return new BufferStorage9(); 1.721 +} 1.722 + 1.723 +QueryImpl *Renderer9::createQuery(GLenum type) 1.724 +{ 1.725 + return new Query9(this, type); 1.726 +} 1.727 + 1.728 +FenceImpl *Renderer9::createFence() 1.729 +{ 1.730 + return new Fence9(this); 1.731 +} 1.732 + 1.733 +void Renderer9::setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &samplerState) 1.734 +{ 1.735 + bool *forceSetSamplers = (type == gl::SAMPLER_PIXEL) ? mForceSetPixelSamplerStates : mForceSetVertexSamplerStates; 1.736 + gl::SamplerState *appliedSamplers = (type == gl::SAMPLER_PIXEL) ? mCurPixelSamplerStates: mCurVertexSamplerStates; 1.737 + 1.738 + if (forceSetSamplers[index] || memcmp(&samplerState, &appliedSamplers[index], sizeof(gl::SamplerState)) != 0) 1.739 + { 1.740 + int d3dSamplerOffset = (type == gl::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0; 1.741 + int d3dSampler = index + d3dSamplerOffset; 1.742 + 1.743 + mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSU, gl_d3d9::ConvertTextureWrap(samplerState.wrapS)); 1.744 + mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSV, gl_d3d9::ConvertTextureWrap(samplerState.wrapT)); 1.745 + 1.746 + mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAGFILTER, gl_d3d9::ConvertMagFilter(samplerState.magFilter, samplerState.maxAnisotropy)); 1.747 + D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter; 1.748 + gl_d3d9::ConvertMinFilter(samplerState.minFilter, &d3dMinFilter, &d3dMipFilter, samplerState.maxAnisotropy); 1.749 + mDevice->SetSamplerState(d3dSampler, D3DSAMP_MINFILTER, d3dMinFilter); 1.750 + mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPFILTER, d3dMipFilter); 1.751 + mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXMIPLEVEL, samplerState.lodOffset); 1.752 + if (mSupportsTextureFilterAnisotropy) 1.753 + { 1.754 + mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXANISOTROPY, (DWORD)samplerState.maxAnisotropy); 1.755 + } 1.756 + } 1.757 + 1.758 + forceSetSamplers[index] = false; 1.759 + appliedSamplers[index] = samplerState; 1.760 +} 1.761 + 1.762 +void Renderer9::setTexture(gl::SamplerType type, int index, gl::Texture *texture) 1.763 +{ 1.764 + int d3dSamplerOffset = (type == gl::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0; 1.765 + int d3dSampler = index + d3dSamplerOffset; 1.766 + IDirect3DBaseTexture9 *d3dTexture = NULL; 1.767 + unsigned int serial = 0; 1.768 + bool forceSetTexture = false; 1.769 + 1.770 + unsigned int *appliedSerials = (type == gl::SAMPLER_PIXEL) ? mCurPixelTextureSerials : mCurVertexTextureSerials; 1.771 + 1.772 + if (texture) 1.773 + { 1.774 + TextureStorageInterface *texStorage = texture->getNativeTexture(); 1.775 + if (texStorage) 1.776 + { 1.777 + TextureStorage9 *storage9 = TextureStorage9::makeTextureStorage9(texStorage->getStorageInstance()); 1.778 + d3dTexture = storage9->getBaseTexture(); 1.779 + } 1.780 + // If we get NULL back from getBaseTexture here, something went wrong 1.781 + // in the texture class and we're unexpectedly missing the d3d texture 1.782 + ASSERT(d3dTexture != NULL); 1.783 + 1.784 + serial = texture->getTextureSerial(); 1.785 + forceSetTexture = texture->hasDirtyImages(); 1.786 + } 1.787 + 1.788 + if (forceSetTexture || appliedSerials[index] != serial) 1.789 + { 1.790 + mDevice->SetTexture(d3dSampler, d3dTexture); 1.791 + } 1.792 + 1.793 + appliedSerials[index] = serial; 1.794 +} 1.795 + 1.796 +void Renderer9::setRasterizerState(const gl::RasterizerState &rasterState) 1.797 +{ 1.798 + bool rasterStateChanged = mForceSetRasterState || memcmp(&rasterState, &mCurRasterState, sizeof(gl::RasterizerState)) != 0; 1.799 + 1.800 + if (rasterStateChanged) 1.801 + { 1.802 + // Set the cull mode 1.803 + if (rasterState.cullFace) 1.804 + { 1.805 + mDevice->SetRenderState(D3DRS_CULLMODE, gl_d3d9::ConvertCullMode(rasterState.cullMode, rasterState.frontFace)); 1.806 + } 1.807 + else 1.808 + { 1.809 + mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); 1.810 + } 1.811 + 1.812 + if (rasterState.polygonOffsetFill) 1.813 + { 1.814 + if (mCurDepthSize > 0) 1.815 + { 1.816 + mDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *(DWORD*)&rasterState.polygonOffsetFactor); 1.817 + 1.818 + float depthBias = ldexp(rasterState.polygonOffsetUnits, -static_cast<int>(mCurDepthSize)); 1.819 + mDevice->SetRenderState(D3DRS_DEPTHBIAS, *(DWORD*)&depthBias); 1.820 + } 1.821 + } 1.822 + else 1.823 + { 1.824 + mDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0); 1.825 + mDevice->SetRenderState(D3DRS_DEPTHBIAS, 0); 1.826 + } 1.827 + 1.828 + mCurRasterState = rasterState; 1.829 + } 1.830 + 1.831 + mForceSetRasterState = false; 1.832 +} 1.833 + 1.834 +void Renderer9::setBlendState(const gl::BlendState &blendState, const gl::Color &blendColor, unsigned int sampleMask) 1.835 +{ 1.836 + bool blendStateChanged = mForceSetBlendState || memcmp(&blendState, &mCurBlendState, sizeof(gl::BlendState)) != 0; 1.837 + bool blendColorChanged = mForceSetBlendState || memcmp(&blendColor, &mCurBlendColor, sizeof(gl::Color)) != 0; 1.838 + bool sampleMaskChanged = mForceSetBlendState || sampleMask != mCurSampleMask; 1.839 + 1.840 + if (blendStateChanged || blendColorChanged) 1.841 + { 1.842 + if (blendState.blend) 1.843 + { 1.844 + mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); 1.845 + 1.846 + if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA && blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA && 1.847 + blendState.destBlendRGB != GL_CONSTANT_ALPHA && blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA) 1.848 + { 1.849 + mDevice->SetRenderState(D3DRS_BLENDFACTOR, gl_d3d9::ConvertColor(blendColor)); 1.850 + } 1.851 + else 1.852 + { 1.853 + mDevice->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(gl::unorm<8>(blendColor.alpha), 1.854 + gl::unorm<8>(blendColor.alpha), 1.855 + gl::unorm<8>(blendColor.alpha), 1.856 + gl::unorm<8>(blendColor.alpha))); 1.857 + } 1.858 + 1.859 + mDevice->SetRenderState(D3DRS_SRCBLEND, gl_d3d9::ConvertBlendFunc(blendState.sourceBlendRGB)); 1.860 + mDevice->SetRenderState(D3DRS_DESTBLEND, gl_d3d9::ConvertBlendFunc(blendState.destBlendRGB)); 1.861 + mDevice->SetRenderState(D3DRS_BLENDOP, gl_d3d9::ConvertBlendOp(blendState.blendEquationRGB)); 1.862 + 1.863 + if (blendState.sourceBlendRGB != blendState.sourceBlendAlpha || 1.864 + blendState.destBlendRGB != blendState.destBlendAlpha || 1.865 + blendState.blendEquationRGB != blendState.blendEquationAlpha) 1.866 + { 1.867 + mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); 1.868 + 1.869 + mDevice->SetRenderState(D3DRS_SRCBLENDALPHA, gl_d3d9::ConvertBlendFunc(blendState.sourceBlendAlpha)); 1.870 + mDevice->SetRenderState(D3DRS_DESTBLENDALPHA, gl_d3d9::ConvertBlendFunc(blendState.destBlendAlpha)); 1.871 + mDevice->SetRenderState(D3DRS_BLENDOPALPHA, gl_d3d9::ConvertBlendOp(blendState.blendEquationAlpha)); 1.872 + } 1.873 + else 1.874 + { 1.875 + mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE); 1.876 + } 1.877 + } 1.878 + else 1.879 + { 1.880 + mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); 1.881 + } 1.882 + 1.883 + if (blendState.sampleAlphaToCoverage) 1.884 + { 1.885 + FIXME("Sample alpha to coverage is unimplemented."); 1.886 + } 1.887 + 1.888 + // Set the color mask 1.889 + bool zeroColorMaskAllowed = getAdapterVendor() != VENDOR_ID_AMD; 1.890 + // Apparently some ATI cards have a bug where a draw with a zero color 1.891 + // write mask can cause later draws to have incorrect results. Instead, 1.892 + // set a nonzero color write mask but modify the blend state so that no 1.893 + // drawing is done. 1.894 + // http://code.google.com/p/angleproject/issues/detail?id=169 1.895 + 1.896 + DWORD colorMask = gl_d3d9::ConvertColorMask(blendState.colorMaskRed, blendState.colorMaskGreen, 1.897 + blendState.colorMaskBlue, blendState.colorMaskAlpha); 1.898 + if (colorMask == 0 && !zeroColorMaskAllowed) 1.899 + { 1.900 + // Enable green channel, but set blending so nothing will be drawn. 1.901 + mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_GREEN); 1.902 + mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); 1.903 + 1.904 + mDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO); 1.905 + mDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); 1.906 + mDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); 1.907 + } 1.908 + else 1.909 + { 1.910 + mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, colorMask); 1.911 + } 1.912 + 1.913 + mDevice->SetRenderState(D3DRS_DITHERENABLE, blendState.dither ? TRUE : FALSE); 1.914 + 1.915 + mCurBlendState = blendState; 1.916 + mCurBlendColor = blendColor; 1.917 + } 1.918 + 1.919 + if (sampleMaskChanged) 1.920 + { 1.921 + // Set the multisample mask 1.922 + mDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE); 1.923 + mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, static_cast<DWORD>(sampleMask)); 1.924 + 1.925 + mCurSampleMask = sampleMask; 1.926 + } 1.927 + 1.928 + mForceSetBlendState = false; 1.929 +} 1.930 + 1.931 +void Renderer9::setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, 1.932 + int stencilBackRef, bool frontFaceCCW) 1.933 +{ 1.934 + bool depthStencilStateChanged = mForceSetDepthStencilState || 1.935 + memcmp(&depthStencilState, &mCurDepthStencilState, sizeof(gl::DepthStencilState)) != 0; 1.936 + bool stencilRefChanged = mForceSetDepthStencilState || stencilRef != mCurStencilRef || 1.937 + stencilBackRef != mCurStencilBackRef; 1.938 + bool frontFaceCCWChanged = mForceSetDepthStencilState || frontFaceCCW != mCurFrontFaceCCW; 1.939 + 1.940 + if (depthStencilStateChanged) 1.941 + { 1.942 + if (depthStencilState.depthTest) 1.943 + { 1.944 + mDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE); 1.945 + mDevice->SetRenderState(D3DRS_ZFUNC, gl_d3d9::ConvertComparison(depthStencilState.depthFunc)); 1.946 + } 1.947 + else 1.948 + { 1.949 + mDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); 1.950 + } 1.951 + 1.952 + mCurDepthStencilState = depthStencilState; 1.953 + } 1.954 + 1.955 + if (depthStencilStateChanged || stencilRefChanged || frontFaceCCWChanged) 1.956 + { 1.957 + if (depthStencilState.stencilTest && mCurStencilSize > 0) 1.958 + { 1.959 + mDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE); 1.960 + mDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE); 1.961 + 1.962 + // FIXME: Unsupported by D3D9 1.963 + const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF; 1.964 + const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK; 1.965 + const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK; 1.966 + if (depthStencilState.stencilWritemask != depthStencilState.stencilBackWritemask || 1.967 + stencilRef != stencilBackRef || 1.968 + depthStencilState.stencilMask != depthStencilState.stencilBackMask) 1.969 + { 1.970 + ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL."); 1.971 + return gl::error(GL_INVALID_OPERATION); 1.972 + } 1.973 + 1.974 + // get the maximum size of the stencil ref 1.975 + unsigned int maxStencil = (1 << mCurStencilSize) - 1; 1.976 + 1.977 + mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, 1.978 + depthStencilState.stencilWritemask); 1.979 + mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, 1.980 + gl_d3d9::ConvertComparison(depthStencilState.stencilFunc)); 1.981 + 1.982 + mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, 1.983 + (stencilRef < (int)maxStencil) ? stencilRef : maxStencil); 1.984 + mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, 1.985 + depthStencilState.stencilMask); 1.986 + 1.987 + mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, 1.988 + gl_d3d9::ConvertStencilOp(depthStencilState.stencilFail)); 1.989 + mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, 1.990 + gl_d3d9::ConvertStencilOp(depthStencilState.stencilPassDepthFail)); 1.991 + mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, 1.992 + gl_d3d9::ConvertStencilOp(depthStencilState.stencilPassDepthPass)); 1.993 + 1.994 + mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, 1.995 + depthStencilState.stencilBackWritemask); 1.996 + mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, 1.997 + gl_d3d9::ConvertComparison(depthStencilState.stencilBackFunc)); 1.998 + 1.999 + mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, 1.1000 + (stencilBackRef < (int)maxStencil) ? stencilBackRef : maxStencil); 1.1001 + mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, 1.1002 + depthStencilState.stencilBackMask); 1.1003 + 1.1004 + mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, 1.1005 + gl_d3d9::ConvertStencilOp(depthStencilState.stencilBackFail)); 1.1006 + mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, 1.1007 + gl_d3d9::ConvertStencilOp(depthStencilState.stencilBackPassDepthFail)); 1.1008 + mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, 1.1009 + gl_d3d9::ConvertStencilOp(depthStencilState.stencilBackPassDepthPass)); 1.1010 + } 1.1011 + else 1.1012 + { 1.1013 + mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); 1.1014 + } 1.1015 + 1.1016 + mDevice->SetRenderState(D3DRS_ZWRITEENABLE, depthStencilState.depthMask ? TRUE : FALSE); 1.1017 + 1.1018 + mCurStencilRef = stencilRef; 1.1019 + mCurStencilBackRef = stencilBackRef; 1.1020 + mCurFrontFaceCCW = frontFaceCCW; 1.1021 + } 1.1022 + 1.1023 + mForceSetDepthStencilState = false; 1.1024 +} 1.1025 + 1.1026 +void Renderer9::setScissorRectangle(const gl::Rectangle &scissor, bool enabled) 1.1027 +{ 1.1028 + bool scissorChanged = mForceSetScissor || 1.1029 + memcmp(&scissor, &mCurScissor, sizeof(gl::Rectangle)) != 0 || 1.1030 + enabled != mScissorEnabled; 1.1031 + 1.1032 + if (scissorChanged) 1.1033 + { 1.1034 + if (enabled) 1.1035 + { 1.1036 + RECT rect; 1.1037 + rect.left = gl::clamp(scissor.x, 0, static_cast<int>(mRenderTargetDesc.width)); 1.1038 + rect.top = gl::clamp(scissor.y, 0, static_cast<int>(mRenderTargetDesc.height)); 1.1039 + rect.right = gl::clamp(scissor.x + scissor.width, 0, static_cast<int>(mRenderTargetDesc.width)); 1.1040 + rect.bottom = gl::clamp(scissor.y + scissor.height, 0, static_cast<int>(mRenderTargetDesc.height)); 1.1041 + mDevice->SetScissorRect(&rect); 1.1042 + } 1.1043 + 1.1044 + mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, enabled ? TRUE : FALSE); 1.1045 + 1.1046 + mScissorEnabled = enabled; 1.1047 + mCurScissor = scissor; 1.1048 + } 1.1049 + 1.1050 + mForceSetScissor = false; 1.1051 +} 1.1052 + 1.1053 +bool Renderer9::setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, 1.1054 + bool ignoreViewport) 1.1055 +{ 1.1056 + gl::Rectangle actualViewport = viewport; 1.1057 + float actualZNear = gl::clamp01(zNear); 1.1058 + float actualZFar = gl::clamp01(zFar); 1.1059 + if (ignoreViewport) 1.1060 + { 1.1061 + actualViewport.x = 0; 1.1062 + actualViewport.y = 0; 1.1063 + actualViewport.width = mRenderTargetDesc.width; 1.1064 + actualViewport.height = mRenderTargetDesc.height; 1.1065 + actualZNear = 0.0f; 1.1066 + actualZFar = 1.0f; 1.1067 + } 1.1068 + 1.1069 + D3DVIEWPORT9 dxViewport; 1.1070 + dxViewport.X = gl::clamp(actualViewport.x, 0, static_cast<int>(mRenderTargetDesc.width)); 1.1071 + dxViewport.Y = gl::clamp(actualViewport.y, 0, static_cast<int>(mRenderTargetDesc.height)); 1.1072 + dxViewport.Width = gl::clamp(actualViewport.width, 0, static_cast<int>(mRenderTargetDesc.width) - static_cast<int>(dxViewport.X)); 1.1073 + dxViewport.Height = gl::clamp(actualViewport.height, 0, static_cast<int>(mRenderTargetDesc.height) - static_cast<int>(dxViewport.Y)); 1.1074 + dxViewport.MinZ = actualZNear; 1.1075 + dxViewport.MaxZ = actualZFar; 1.1076 + 1.1077 + if (dxViewport.Width <= 0 || dxViewport.Height <= 0) 1.1078 + { 1.1079 + return false; // Nothing to render 1.1080 + } 1.1081 + 1.1082 + bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 || 1.1083 + actualZNear != mCurNear || actualZFar != mCurFar; 1.1084 + if (viewportChanged) 1.1085 + { 1.1086 + mDevice->SetViewport(&dxViewport); 1.1087 + 1.1088 + mCurViewport = actualViewport; 1.1089 + mCurNear = actualZNear; 1.1090 + mCurFar = actualZFar; 1.1091 + 1.1092 + dx_VertexConstants vc = {0}; 1.1093 + dx_PixelConstants pc = {0}; 1.1094 + 1.1095 + vc.viewAdjust[0] = (float)((actualViewport.width - (int)dxViewport.Width) + 2 * (actualViewport.x - (int)dxViewport.X) - 1) / dxViewport.Width; 1.1096 + vc.viewAdjust[1] = (float)((actualViewport.height - (int)dxViewport.Height) + 2 * (actualViewport.y - (int)dxViewport.Y) - 1) / dxViewport.Height; 1.1097 + vc.viewAdjust[2] = (float)actualViewport.width / dxViewport.Width; 1.1098 + vc.viewAdjust[3] = (float)actualViewport.height / dxViewport.Height; 1.1099 + 1.1100 + pc.viewCoords[0] = actualViewport.width * 0.5f; 1.1101 + pc.viewCoords[1] = actualViewport.height * 0.5f; 1.1102 + pc.viewCoords[2] = actualViewport.x + (actualViewport.width * 0.5f); 1.1103 + pc.viewCoords[3] = actualViewport.y + (actualViewport.height * 0.5f); 1.1104 + 1.1105 + pc.depthFront[0] = (actualZFar - actualZNear) * 0.5f; 1.1106 + pc.depthFront[1] = (actualZNear + actualZFar) * 0.5f; 1.1107 + pc.depthFront[2] = !gl::IsTriangleMode(drawMode) ? 0.0f : (frontFace == GL_CCW ? 1.0f : -1.0f);; 1.1108 + 1.1109 + vc.depthRange[0] = actualZNear; 1.1110 + vc.depthRange[1] = actualZFar; 1.1111 + vc.depthRange[2] = actualZFar - actualZNear; 1.1112 + 1.1113 + pc.depthRange[0] = actualZNear; 1.1114 + pc.depthRange[1] = actualZFar; 1.1115 + pc.depthRange[2] = actualZFar - actualZNear; 1.1116 + 1.1117 + if (memcmp(&vc, &mVertexConstants, sizeof(dx_VertexConstants)) != 0) 1.1118 + { 1.1119 + mVertexConstants = vc; 1.1120 + mDxUniformsDirty = true; 1.1121 + } 1.1122 + 1.1123 + if (memcmp(&pc, &mPixelConstants, sizeof(dx_PixelConstants)) != 0) 1.1124 + { 1.1125 + mPixelConstants = pc; 1.1126 + mDxUniformsDirty = true; 1.1127 + } 1.1128 + } 1.1129 + 1.1130 + mForceSetViewport = false; 1.1131 + return true; 1.1132 +} 1.1133 + 1.1134 +bool Renderer9::applyPrimitiveType(GLenum mode, GLsizei count) 1.1135 +{ 1.1136 + switch (mode) 1.1137 + { 1.1138 + case GL_POINTS: 1.1139 + mPrimitiveType = D3DPT_POINTLIST; 1.1140 + mPrimitiveCount = count; 1.1141 + break; 1.1142 + case GL_LINES: 1.1143 + mPrimitiveType = D3DPT_LINELIST; 1.1144 + mPrimitiveCount = count / 2; 1.1145 + break; 1.1146 + case GL_LINE_LOOP: 1.1147 + mPrimitiveType = D3DPT_LINESTRIP; 1.1148 + mPrimitiveCount = count - 1; // D3D doesn't support line loops, so we draw the last line separately 1.1149 + break; 1.1150 + case GL_LINE_STRIP: 1.1151 + mPrimitiveType = D3DPT_LINESTRIP; 1.1152 + mPrimitiveCount = count - 1; 1.1153 + break; 1.1154 + case GL_TRIANGLES: 1.1155 + mPrimitiveType = D3DPT_TRIANGLELIST; 1.1156 + mPrimitiveCount = count / 3; 1.1157 + break; 1.1158 + case GL_TRIANGLE_STRIP: 1.1159 + mPrimitiveType = D3DPT_TRIANGLESTRIP; 1.1160 + mPrimitiveCount = count - 2; 1.1161 + break; 1.1162 + case GL_TRIANGLE_FAN: 1.1163 + mPrimitiveType = D3DPT_TRIANGLEFAN; 1.1164 + mPrimitiveCount = count - 2; 1.1165 + break; 1.1166 + default: 1.1167 + return gl::error(GL_INVALID_ENUM, false); 1.1168 + } 1.1169 + 1.1170 + return mPrimitiveCount > 0; 1.1171 +} 1.1172 + 1.1173 + 1.1174 +gl::Renderbuffer *Renderer9::getNullColorbuffer(gl::Renderbuffer *depthbuffer) 1.1175 +{ 1.1176 + if (!depthbuffer) 1.1177 + { 1.1178 + ERR("Unexpected null depthbuffer for depth-only FBO."); 1.1179 + return NULL; 1.1180 + } 1.1181 + 1.1182 + GLsizei width = depthbuffer->getWidth(); 1.1183 + GLsizei height = depthbuffer->getHeight(); 1.1184 + 1.1185 + // search cached nullcolorbuffers 1.1186 + for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++) 1.1187 + { 1.1188 + if (mNullColorbufferCache[i].buffer != NULL && 1.1189 + mNullColorbufferCache[i].width == width && 1.1190 + mNullColorbufferCache[i].height == height) 1.1191 + { 1.1192 + mNullColorbufferCache[i].lruCount = ++mMaxNullColorbufferLRU; 1.1193 + return mNullColorbufferCache[i].buffer; 1.1194 + } 1.1195 + } 1.1196 + 1.1197 + gl::Renderbuffer *nullbuffer = new gl::Renderbuffer(this, 0, new gl::Colorbuffer(this, width, height, GL_NONE, 0)); 1.1198 + 1.1199 + // add nullbuffer to the cache 1.1200 + NullColorbufferCacheEntry *oldest = &mNullColorbufferCache[0]; 1.1201 + for (int i = 1; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++) 1.1202 + { 1.1203 + if (mNullColorbufferCache[i].lruCount < oldest->lruCount) 1.1204 + { 1.1205 + oldest = &mNullColorbufferCache[i]; 1.1206 + } 1.1207 + } 1.1208 + 1.1209 + delete oldest->buffer; 1.1210 + oldest->buffer = nullbuffer; 1.1211 + oldest->lruCount = ++mMaxNullColorbufferLRU; 1.1212 + oldest->width = width; 1.1213 + oldest->height = height; 1.1214 + 1.1215 + return nullbuffer; 1.1216 +} 1.1217 + 1.1218 +bool Renderer9::applyRenderTarget(gl::Framebuffer *framebuffer) 1.1219 +{ 1.1220 + // if there is no color attachment we must synthesize a NULL colorattachment 1.1221 + // to keep the D3D runtime happy. This should only be possible if depth texturing. 1.1222 + gl::Renderbuffer *renderbufferObject = NULL; 1.1223 + if (framebuffer->getColorbufferType(0) != GL_NONE) 1.1224 + { 1.1225 + renderbufferObject = framebuffer->getColorbuffer(0); 1.1226 + } 1.1227 + else 1.1228 + { 1.1229 + renderbufferObject = getNullColorbuffer(framebuffer->getDepthbuffer()); 1.1230 + } 1.1231 + if (!renderbufferObject) 1.1232 + { 1.1233 + ERR("unable to locate renderbuffer for FBO."); 1.1234 + return false; 1.1235 + } 1.1236 + 1.1237 + bool renderTargetChanged = false; 1.1238 + unsigned int renderTargetSerial = renderbufferObject->getSerial(); 1.1239 + if (renderTargetSerial != mAppliedRenderTargetSerial) 1.1240 + { 1.1241 + // Apply the render target on the device 1.1242 + IDirect3DSurface9 *renderTargetSurface = NULL; 1.1243 + 1.1244 + RenderTarget *renderTarget = renderbufferObject->getRenderTarget(); 1.1245 + if (renderTarget) 1.1246 + { 1.1247 + renderTargetSurface = RenderTarget9::makeRenderTarget9(renderTarget)->getSurface(); 1.1248 + } 1.1249 + 1.1250 + if (!renderTargetSurface) 1.1251 + { 1.1252 + ERR("render target pointer unexpectedly null."); 1.1253 + return false; // Context must be lost 1.1254 + } 1.1255 + 1.1256 + mDevice->SetRenderTarget(0, renderTargetSurface); 1.1257 + renderTargetSurface->Release(); 1.1258 + 1.1259 + mAppliedRenderTargetSerial = renderTargetSerial; 1.1260 + renderTargetChanged = true; 1.1261 + } 1.1262 + 1.1263 + gl::Renderbuffer *depthStencil = NULL; 1.1264 + unsigned int depthbufferSerial = 0; 1.1265 + unsigned int stencilbufferSerial = 0; 1.1266 + if (framebuffer->getDepthbufferType() != GL_NONE) 1.1267 + { 1.1268 + depthStencil = framebuffer->getDepthbuffer(); 1.1269 + if (!depthStencil) 1.1270 + { 1.1271 + ERR("Depth stencil pointer unexpectedly null."); 1.1272 + return false; 1.1273 + } 1.1274 + 1.1275 + depthbufferSerial = depthStencil->getSerial(); 1.1276 + } 1.1277 + else if (framebuffer->getStencilbufferType() != GL_NONE) 1.1278 + { 1.1279 + depthStencil = framebuffer->getStencilbuffer(); 1.1280 + if (!depthStencil) 1.1281 + { 1.1282 + ERR("Depth stencil pointer unexpectedly null."); 1.1283 + return false; 1.1284 + } 1.1285 + 1.1286 + stencilbufferSerial = depthStencil->getSerial(); 1.1287 + } 1.1288 + 1.1289 + if (depthbufferSerial != mAppliedDepthbufferSerial || 1.1290 + stencilbufferSerial != mAppliedStencilbufferSerial || 1.1291 + !mDepthStencilInitialized) 1.1292 + { 1.1293 + unsigned int depthSize = 0; 1.1294 + unsigned int stencilSize = 0; 1.1295 + 1.1296 + // Apply the depth stencil on the device 1.1297 + if (depthStencil) 1.1298 + { 1.1299 + IDirect3DSurface9 *depthStencilSurface = NULL; 1.1300 + RenderTarget *depthStencilRenderTarget = depthStencil->getDepthStencil(); 1.1301 + 1.1302 + if (depthStencilRenderTarget) 1.1303 + { 1.1304 + depthStencilSurface = RenderTarget9::makeRenderTarget9(depthStencilRenderTarget)->getSurface(); 1.1305 + } 1.1306 + 1.1307 + if (!depthStencilSurface) 1.1308 + { 1.1309 + ERR("depth stencil pointer unexpectedly null."); 1.1310 + return false; // Context must be lost 1.1311 + } 1.1312 + 1.1313 + mDevice->SetDepthStencilSurface(depthStencilSurface); 1.1314 + depthStencilSurface->Release(); 1.1315 + 1.1316 + depthSize = depthStencil->getDepthSize(); 1.1317 + stencilSize = depthStencil->getStencilSize(); 1.1318 + } 1.1319 + else 1.1320 + { 1.1321 + mDevice->SetDepthStencilSurface(NULL); 1.1322 + } 1.1323 + 1.1324 + if (!mDepthStencilInitialized || depthSize != mCurDepthSize) 1.1325 + { 1.1326 + mCurDepthSize = depthSize; 1.1327 + mForceSetRasterState = true; 1.1328 + } 1.1329 + 1.1330 + if (!mDepthStencilInitialized || stencilSize != mCurStencilSize) 1.1331 + { 1.1332 + mCurStencilSize = stencilSize; 1.1333 + mForceSetDepthStencilState = true; 1.1334 + } 1.1335 + 1.1336 + mAppliedDepthbufferSerial = depthbufferSerial; 1.1337 + mAppliedStencilbufferSerial = stencilbufferSerial; 1.1338 + mDepthStencilInitialized = true; 1.1339 + } 1.1340 + 1.1341 + if (renderTargetChanged || !mRenderTargetDescInitialized) 1.1342 + { 1.1343 + mForceSetScissor = true; 1.1344 + mForceSetViewport = true; 1.1345 + 1.1346 + mRenderTargetDesc.width = renderbufferObject->getWidth(); 1.1347 + mRenderTargetDesc.height = renderbufferObject->getHeight(); 1.1348 + mRenderTargetDesc.format = renderbufferObject->getActualFormat(); 1.1349 + mRenderTargetDescInitialized = true; 1.1350 + } 1.1351 + 1.1352 + return true; 1.1353 +} 1.1354 + 1.1355 +GLenum Renderer9::applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances) 1.1356 +{ 1.1357 + TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS]; 1.1358 + GLenum err = mVertexDataManager->prepareVertexData(vertexAttributes, programBinary, first, count, attributes, instances); 1.1359 + if (err != GL_NO_ERROR) 1.1360 + { 1.1361 + return err; 1.1362 + } 1.1363 + 1.1364 + return mVertexDeclarationCache.applyDeclaration(mDevice, attributes, programBinary, instances, &mRepeatDraw); 1.1365 +} 1.1366 + 1.1367 +// Applies the indices and element array bindings to the Direct3D 9 device 1.1368 +GLenum Renderer9::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) 1.1369 +{ 1.1370 + GLenum err = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo); 1.1371 + 1.1372 + if (err == GL_NO_ERROR) 1.1373 + { 1.1374 + // Directly binding the storage buffer is not supported for d3d9 1.1375 + ASSERT(indexInfo->storage == NULL); 1.1376 + 1.1377 + if (indexInfo->serial != mAppliedIBSerial) 1.1378 + { 1.1379 + IndexBuffer9* indexBuffer = IndexBuffer9::makeIndexBuffer9(indexInfo->indexBuffer); 1.1380 + 1.1381 + mDevice->SetIndices(indexBuffer->getBuffer()); 1.1382 + mAppliedIBSerial = indexInfo->serial; 1.1383 + } 1.1384 + } 1.1385 + 1.1386 + return err; 1.1387 +} 1.1388 + 1.1389 +void Renderer9::drawArrays(GLenum mode, GLsizei count, GLsizei instances) 1.1390 +{ 1.1391 + startScene(); 1.1392 + 1.1393 + if (mode == GL_LINE_LOOP) 1.1394 + { 1.1395 + drawLineLoop(count, GL_NONE, NULL, 0, NULL); 1.1396 + } 1.1397 + else if (instances > 0) 1.1398 + { 1.1399 + StaticIndexBufferInterface *countingIB = mIndexDataManager->getCountingIndices(count); 1.1400 + if (countingIB) 1.1401 + { 1.1402 + if (mAppliedIBSerial != countingIB->getSerial()) 1.1403 + { 1.1404 + IndexBuffer9 *indexBuffer = IndexBuffer9::makeIndexBuffer9(countingIB->getIndexBuffer()); 1.1405 + 1.1406 + mDevice->SetIndices(indexBuffer->getBuffer()); 1.1407 + mAppliedIBSerial = countingIB->getSerial(); 1.1408 + } 1.1409 + 1.1410 + for (int i = 0; i < mRepeatDraw; i++) 1.1411 + { 1.1412 + mDevice->DrawIndexedPrimitive(mPrimitiveType, 0, 0, count, 0, mPrimitiveCount); 1.1413 + } 1.1414 + } 1.1415 + else 1.1416 + { 1.1417 + ERR("Could not create a counting index buffer for glDrawArraysInstanced."); 1.1418 + return gl::error(GL_OUT_OF_MEMORY); 1.1419 + } 1.1420 + } 1.1421 + else // Regular case 1.1422 + { 1.1423 + mDevice->DrawPrimitive(mPrimitiveType, 0, mPrimitiveCount); 1.1424 + } 1.1425 +} 1.1426 + 1.1427 +void Renderer9::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei /*instances*/) 1.1428 +{ 1.1429 + startScene(); 1.1430 + 1.1431 + if (mode == GL_POINTS) 1.1432 + { 1.1433 + drawIndexedPoints(count, type, indices, elementArrayBuffer); 1.1434 + } 1.1435 + else if (mode == GL_LINE_LOOP) 1.1436 + { 1.1437 + drawLineLoop(count, type, indices, indexInfo.minIndex, elementArrayBuffer); 1.1438 + } 1.1439 + else 1.1440 + { 1.1441 + for (int i = 0; i < mRepeatDraw; i++) 1.1442 + { 1.1443 + GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1; 1.1444 + mDevice->DrawIndexedPrimitive(mPrimitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, vertexCount, indexInfo.startIndex, mPrimitiveCount); 1.1445 + } 1.1446 + } 1.1447 +} 1.1448 + 1.1449 +void Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer) 1.1450 +{ 1.1451 + // Get the raw indices for an indexed draw 1.1452 + if (type != GL_NONE && elementArrayBuffer) 1.1453 + { 1.1454 + gl::Buffer *indexBuffer = elementArrayBuffer; 1.1455 + BufferStorage *storage = indexBuffer->getStorage(); 1.1456 + intptr_t offset = reinterpret_cast<intptr_t>(indices); 1.1457 + indices = static_cast<const GLubyte*>(storage->getData()) + offset; 1.1458 + } 1.1459 + 1.1460 + unsigned int startIndex = 0; 1.1461 + 1.1462 + if (get32BitIndexSupport()) 1.1463 + { 1.1464 + if (!mLineLoopIB) 1.1465 + { 1.1466 + mLineLoopIB = new StreamingIndexBufferInterface(this); 1.1467 + if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT)) 1.1468 + { 1.1469 + delete mLineLoopIB; 1.1470 + mLineLoopIB = NULL; 1.1471 + 1.1472 + ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP."); 1.1473 + return gl::error(GL_OUT_OF_MEMORY); 1.1474 + } 1.1475 + } 1.1476 + 1.1477 + if (static_cast<unsigned int>(count) + 1 > (std::numeric_limits<unsigned int>::max() / sizeof(unsigned int))) 1.1478 + { 1.1479 + ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required."); 1.1480 + return gl::error(GL_OUT_OF_MEMORY); 1.1481 + } 1.1482 + 1.1483 + // Checked by Renderer9::applyPrimitiveType 1.1484 + ASSERT(count >= 0); 1.1485 + 1.1486 + const unsigned int spaceNeeded = (static_cast<unsigned int>(count) + 1) * sizeof(unsigned int); 1.1487 + if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT)) 1.1488 + { 1.1489 + ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP."); 1.1490 + return gl::error(GL_OUT_OF_MEMORY); 1.1491 + } 1.1492 + 1.1493 + void* mappedMemory = NULL; 1.1494 + unsigned int offset = 0; 1.1495 + if (!mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset)) 1.1496 + { 1.1497 + ERR("Could not map index buffer for GL_LINE_LOOP."); 1.1498 + return gl::error(GL_OUT_OF_MEMORY); 1.1499 + } 1.1500 + 1.1501 + startIndex = static_cast<unsigned int>(offset) / 4; 1.1502 + unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory); 1.1503 + 1.1504 + switch (type) 1.1505 + { 1.1506 + case GL_NONE: // Non-indexed draw 1.1507 + for (int i = 0; i < count; i++) 1.1508 + { 1.1509 + data[i] = i; 1.1510 + } 1.1511 + data[count] = 0; 1.1512 + break; 1.1513 + case GL_UNSIGNED_BYTE: 1.1514 + for (int i = 0; i < count; i++) 1.1515 + { 1.1516 + data[i] = static_cast<const GLubyte*>(indices)[i]; 1.1517 + } 1.1518 + data[count] = static_cast<const GLubyte*>(indices)[0]; 1.1519 + break; 1.1520 + case GL_UNSIGNED_SHORT: 1.1521 + for (int i = 0; i < count; i++) 1.1522 + { 1.1523 + data[i] = static_cast<const GLushort*>(indices)[i]; 1.1524 + } 1.1525 + data[count] = static_cast<const GLushort*>(indices)[0]; 1.1526 + break; 1.1527 + case GL_UNSIGNED_INT: 1.1528 + for (int i = 0; i < count; i++) 1.1529 + { 1.1530 + data[i] = static_cast<const GLuint*>(indices)[i]; 1.1531 + } 1.1532 + data[count] = static_cast<const GLuint*>(indices)[0]; 1.1533 + break; 1.1534 + default: UNREACHABLE(); 1.1535 + } 1.1536 + 1.1537 + if (!mLineLoopIB->unmapBuffer()) 1.1538 + { 1.1539 + ERR("Could not unmap index buffer for GL_LINE_LOOP."); 1.1540 + return gl::error(GL_OUT_OF_MEMORY); 1.1541 + } 1.1542 + } 1.1543 + else 1.1544 + { 1.1545 + if (!mLineLoopIB) 1.1546 + { 1.1547 + mLineLoopIB = new StreamingIndexBufferInterface(this); 1.1548 + if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT)) 1.1549 + { 1.1550 + delete mLineLoopIB; 1.1551 + mLineLoopIB = NULL; 1.1552 + 1.1553 + ERR("Could not create a 16-bit looping index buffer for GL_LINE_LOOP."); 1.1554 + return gl::error(GL_OUT_OF_MEMORY); 1.1555 + } 1.1556 + } 1.1557 + 1.1558 + // Checked by Renderer9::applyPrimitiveType 1.1559 + ASSERT(count >= 0); 1.1560 + 1.1561 + if (static_cast<unsigned int>(count) + 1 > (std::numeric_limits<unsigned short>::max() / sizeof(unsigned short))) 1.1562 + { 1.1563 + ERR("Could not create a 16-bit looping index buffer for GL_LINE_LOOP, too many indices required."); 1.1564 + return gl::error(GL_OUT_OF_MEMORY); 1.1565 + } 1.1566 + 1.1567 + const unsigned int spaceNeeded = (static_cast<unsigned int>(count) + 1) * sizeof(unsigned short); 1.1568 + if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT)) 1.1569 + { 1.1570 + ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP."); 1.1571 + return gl::error(GL_OUT_OF_MEMORY); 1.1572 + } 1.1573 + 1.1574 + void* mappedMemory = NULL; 1.1575 + unsigned int offset; 1.1576 + if (mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset)) 1.1577 + { 1.1578 + ERR("Could not map index buffer for GL_LINE_LOOP."); 1.1579 + return gl::error(GL_OUT_OF_MEMORY); 1.1580 + } 1.1581 + 1.1582 + startIndex = static_cast<unsigned int>(offset) / 2; 1.1583 + unsigned short *data = reinterpret_cast<unsigned short*>(mappedMemory); 1.1584 + 1.1585 + switch (type) 1.1586 + { 1.1587 + case GL_NONE: // Non-indexed draw 1.1588 + for (int i = 0; i < count; i++) 1.1589 + { 1.1590 + data[i] = i; 1.1591 + } 1.1592 + data[count] = 0; 1.1593 + break; 1.1594 + case GL_UNSIGNED_BYTE: 1.1595 + for (int i = 0; i < count; i++) 1.1596 + { 1.1597 + data[i] = static_cast<const GLubyte*>(indices)[i]; 1.1598 + } 1.1599 + data[count] = static_cast<const GLubyte*>(indices)[0]; 1.1600 + break; 1.1601 + case GL_UNSIGNED_SHORT: 1.1602 + for (int i = 0; i < count; i++) 1.1603 + { 1.1604 + data[i] = static_cast<const GLushort*>(indices)[i]; 1.1605 + } 1.1606 + data[count] = static_cast<const GLushort*>(indices)[0]; 1.1607 + break; 1.1608 + case GL_UNSIGNED_INT: 1.1609 + for (int i = 0; i < count; i++) 1.1610 + { 1.1611 + data[i] = static_cast<const GLuint*>(indices)[i]; 1.1612 + } 1.1613 + data[count] = static_cast<const GLuint*>(indices)[0]; 1.1614 + break; 1.1615 + default: UNREACHABLE(); 1.1616 + } 1.1617 + 1.1618 + if (!mLineLoopIB->unmapBuffer()) 1.1619 + { 1.1620 + ERR("Could not unmap index buffer for GL_LINE_LOOP."); 1.1621 + return gl::error(GL_OUT_OF_MEMORY); 1.1622 + } 1.1623 + } 1.1624 + 1.1625 + if (mAppliedIBSerial != mLineLoopIB->getSerial()) 1.1626 + { 1.1627 + IndexBuffer9 *indexBuffer = IndexBuffer9::makeIndexBuffer9(mLineLoopIB->getIndexBuffer()); 1.1628 + 1.1629 + mDevice->SetIndices(indexBuffer->getBuffer()); 1.1630 + mAppliedIBSerial = mLineLoopIB->getSerial(); 1.1631 + } 1.1632 + 1.1633 + mDevice->DrawIndexedPrimitive(D3DPT_LINESTRIP, -minIndex, minIndex, count, startIndex, count); 1.1634 +} 1.1635 + 1.1636 +template <typename T> 1.1637 +static void drawPoints(IDirect3DDevice9* device, GLsizei count, const GLvoid *indices) 1.1638 +{ 1.1639 + for (int i = 0; i < count; i++) 1.1640 + { 1.1641 + unsigned int indexValue = static_cast<unsigned int>(static_cast<const T*>(indices)[i]); 1.1642 + device->DrawPrimitive(D3DPT_POINTLIST, indexValue, 1); 1.1643 + } 1.1644 +} 1.1645 + 1.1646 +void Renderer9::drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer) 1.1647 +{ 1.1648 + // Drawing index point lists is unsupported in d3d9, fall back to a regular DrawPrimitive call 1.1649 + // for each individual point. This call is not expected to happen often. 1.1650 + 1.1651 + if (elementArrayBuffer) 1.1652 + { 1.1653 + BufferStorage *storage = elementArrayBuffer->getStorage(); 1.1654 + intptr_t offset = reinterpret_cast<intptr_t>(indices); 1.1655 + indices = static_cast<const GLubyte*>(storage->getData()) + offset; 1.1656 + } 1.1657 + 1.1658 + switch (type) 1.1659 + { 1.1660 + case GL_UNSIGNED_BYTE: drawPoints<GLubyte>(mDevice, count, indices); break; 1.1661 + case GL_UNSIGNED_SHORT: drawPoints<GLushort>(mDevice, count, indices); break; 1.1662 + case GL_UNSIGNED_INT: drawPoints<GLuint>(mDevice, count, indices); break; 1.1663 + default: UNREACHABLE(); 1.1664 + } 1.1665 +} 1.1666 + 1.1667 +void Renderer9::applyShaders(gl::ProgramBinary *programBinary) 1.1668 +{ 1.1669 + unsigned int programBinarySerial = programBinary->getSerial(); 1.1670 + if (programBinarySerial != mAppliedProgramBinarySerial) 1.1671 + { 1.1672 + ShaderExecutable *vertexExe = programBinary->getVertexExecutable(); 1.1673 + ShaderExecutable *pixelExe = programBinary->getPixelExecutable(); 1.1674 + 1.1675 + IDirect3DVertexShader9 *vertexShader = NULL; 1.1676 + if (vertexExe) vertexShader = ShaderExecutable9::makeShaderExecutable9(vertexExe)->getVertexShader(); 1.1677 + 1.1678 + IDirect3DPixelShader9 *pixelShader = NULL; 1.1679 + if (pixelExe) pixelShader = ShaderExecutable9::makeShaderExecutable9(pixelExe)->getPixelShader(); 1.1680 + 1.1681 + mDevice->SetPixelShader(pixelShader); 1.1682 + mDevice->SetVertexShader(vertexShader); 1.1683 + programBinary->dirtyAllUniforms(); 1.1684 + mDxUniformsDirty = true; 1.1685 + 1.1686 + mAppliedProgramBinarySerial = programBinarySerial; 1.1687 + } 1.1688 +} 1.1689 + 1.1690 +void Renderer9::applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray) 1.1691 +{ 1.1692 + for (std::vector<gl::Uniform*>::const_iterator ub = uniformArray->begin(), ue = uniformArray->end(); ub != ue; ++ub) 1.1693 + { 1.1694 + gl::Uniform *targetUniform = *ub; 1.1695 + 1.1696 + if (targetUniform->dirty) 1.1697 + { 1.1698 + GLfloat *f = (GLfloat*)targetUniform->data; 1.1699 + GLint *i = (GLint*)targetUniform->data; 1.1700 + 1.1701 + switch (targetUniform->type) 1.1702 + { 1.1703 + case GL_SAMPLER_2D: 1.1704 + case GL_SAMPLER_CUBE: 1.1705 + break; 1.1706 + case GL_BOOL: 1.1707 + case GL_BOOL_VEC2: 1.1708 + case GL_BOOL_VEC3: 1.1709 + case GL_BOOL_VEC4: 1.1710 + applyUniformnbv(targetUniform, i); 1.1711 + break; 1.1712 + case GL_FLOAT: 1.1713 + case GL_FLOAT_VEC2: 1.1714 + case GL_FLOAT_VEC3: 1.1715 + case GL_FLOAT_VEC4: 1.1716 + case GL_FLOAT_MAT2: 1.1717 + case GL_FLOAT_MAT3: 1.1718 + case GL_FLOAT_MAT4: 1.1719 + applyUniformnfv(targetUniform, f); 1.1720 + break; 1.1721 + case GL_INT: 1.1722 + case GL_INT_VEC2: 1.1723 + case GL_INT_VEC3: 1.1724 + case GL_INT_VEC4: 1.1725 + applyUniformniv(targetUniform, i); 1.1726 + break; 1.1727 + default: 1.1728 + UNREACHABLE(); 1.1729 + } 1.1730 + 1.1731 + targetUniform->dirty = false; 1.1732 + } 1.1733 + } 1.1734 + 1.1735 + // Driver uniforms 1.1736 + if (mDxUniformsDirty) 1.1737 + { 1.1738 + mDevice->SetVertexShaderConstantF(0, (float*)&mVertexConstants, sizeof(dx_VertexConstants) / sizeof(float[4])); 1.1739 + mDevice->SetPixelShaderConstantF(0, (float*)&mPixelConstants, sizeof(dx_PixelConstants) / sizeof(float[4])); 1.1740 + mDxUniformsDirty = false; 1.1741 + } 1.1742 +} 1.1743 + 1.1744 +void Renderer9::applyUniformnfv(gl::Uniform *targetUniform, const GLfloat *v) 1.1745 +{ 1.1746 + if (targetUniform->psRegisterIndex >= 0) 1.1747 + { 1.1748 + mDevice->SetPixelShaderConstantF(targetUniform->psRegisterIndex, v, targetUniform->registerCount); 1.1749 + } 1.1750 + 1.1751 + if (targetUniform->vsRegisterIndex >= 0) 1.1752 + { 1.1753 + mDevice->SetVertexShaderConstantF(targetUniform->vsRegisterIndex, v, targetUniform->registerCount); 1.1754 + } 1.1755 +} 1.1756 + 1.1757 +void Renderer9::applyUniformniv(gl::Uniform *targetUniform, const GLint *v) 1.1758 +{ 1.1759 + ASSERT(targetUniform->registerCount <= MAX_VERTEX_CONSTANT_VECTORS_D3D9); 1.1760 + GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4]; 1.1761 + 1.1762 + for (unsigned int i = 0; i < targetUniform->registerCount; i++) 1.1763 + { 1.1764 + vector[i][0] = (GLfloat)v[4 * i + 0]; 1.1765 + vector[i][1] = (GLfloat)v[4 * i + 1]; 1.1766 + vector[i][2] = (GLfloat)v[4 * i + 2]; 1.1767 + vector[i][3] = (GLfloat)v[4 * i + 3]; 1.1768 + } 1.1769 + 1.1770 + applyUniformnfv(targetUniform, (GLfloat*)vector); 1.1771 +} 1.1772 + 1.1773 +void Renderer9::applyUniformnbv(gl::Uniform *targetUniform, const GLint *v) 1.1774 +{ 1.1775 + ASSERT(targetUniform->registerCount <= MAX_VERTEX_CONSTANT_VECTORS_D3D9); 1.1776 + GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4]; 1.1777 + 1.1778 + for (unsigned int i = 0; i < targetUniform->registerCount; i++) 1.1779 + { 1.1780 + vector[i][0] = (v[4 * i + 0] == GL_FALSE) ? 0.0f : 1.0f; 1.1781 + vector[i][1] = (v[4 * i + 1] == GL_FALSE) ? 0.0f : 1.0f; 1.1782 + vector[i][2] = (v[4 * i + 2] == GL_FALSE) ? 0.0f : 1.0f; 1.1783 + vector[i][3] = (v[4 * i + 3] == GL_FALSE) ? 0.0f : 1.0f; 1.1784 + } 1.1785 + 1.1786 + applyUniformnfv(targetUniform, (GLfloat*)vector); 1.1787 +} 1.1788 + 1.1789 +void Renderer9::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer) 1.1790 +{ 1.1791 + D3DCOLOR color = D3DCOLOR_ARGB(gl::unorm<8>(clearParams.colorClearValue.alpha), 1.1792 + gl::unorm<8>(clearParams.colorClearValue.red), 1.1793 + gl::unorm<8>(clearParams.colorClearValue.green), 1.1794 + gl::unorm<8>(clearParams.colorClearValue.blue)); 1.1795 + float depth = gl::clamp01(clearParams.depthClearValue); 1.1796 + int stencil = clearParams.stencilClearValue & 0x000000FF; 1.1797 + 1.1798 + unsigned int stencilUnmasked = 0x0; 1.1799 + if ((clearParams.mask & GL_STENCIL_BUFFER_BIT) && frameBuffer->hasStencil()) 1.1800 + { 1.1801 + unsigned int stencilSize = gl::GetStencilSize(frameBuffer->getStencilbuffer()->getActualFormat()); 1.1802 + stencilUnmasked = (0x1 << stencilSize) - 1; 1.1803 + } 1.1804 + 1.1805 + bool alphaUnmasked = (gl::GetAlphaSize(mRenderTargetDesc.format) == 0) || clearParams.colorMaskAlpha; 1.1806 + 1.1807 + const bool needMaskedStencilClear = (clearParams.mask & GL_STENCIL_BUFFER_BIT) && 1.1808 + (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked; 1.1809 + const bool needMaskedColorClear = (clearParams.mask & GL_COLOR_BUFFER_BIT) && 1.1810 + !(clearParams.colorMaskRed && clearParams.colorMaskGreen && 1.1811 + clearParams.colorMaskBlue && alphaUnmasked); 1.1812 + 1.1813 + if (needMaskedColorClear || needMaskedStencilClear) 1.1814 + { 1.1815 + // State which is altered in all paths from this point to the clear call is saved. 1.1816 + // State which is altered in only some paths will be flagged dirty in the case that 1.1817 + // that path is taken. 1.1818 + HRESULT hr; 1.1819 + if (mMaskedClearSavedState == NULL) 1.1820 + { 1.1821 + hr = mDevice->BeginStateBlock(); 1.1822 + ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); 1.1823 + 1.1824 + mDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); 1.1825 + mDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS); 1.1826 + mDevice->SetRenderState(D3DRS_ZENABLE, FALSE); 1.1827 + mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); 1.1828 + mDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); 1.1829 + mDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); 1.1830 + mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); 1.1831 + mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); 1.1832 + mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0); 1.1833 + mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); 1.1834 + mDevice->SetPixelShader(NULL); 1.1835 + mDevice->SetVertexShader(NULL); 1.1836 + mDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE); 1.1837 + mDevice->SetStreamSource(0, NULL, 0, 0); 1.1838 + mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); 1.1839 + mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); 1.1840 + mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR); 1.1841 + mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); 1.1842 + mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR); 1.1843 + mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color); 1.1844 + mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF); 1.1845 + 1.1846 + for(int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) 1.1847 + { 1.1848 + mDevice->SetStreamSourceFreq(i, 1); 1.1849 + } 1.1850 + 1.1851 + hr = mDevice->EndStateBlock(&mMaskedClearSavedState); 1.1852 + ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); 1.1853 + } 1.1854 + 1.1855 + ASSERT(mMaskedClearSavedState != NULL); 1.1856 + 1.1857 + if (mMaskedClearSavedState != NULL) 1.1858 + { 1.1859 + hr = mMaskedClearSavedState->Capture(); 1.1860 + ASSERT(SUCCEEDED(hr)); 1.1861 + } 1.1862 + 1.1863 + mDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); 1.1864 + mDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS); 1.1865 + mDevice->SetRenderState(D3DRS_ZENABLE, FALSE); 1.1866 + mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); 1.1867 + mDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); 1.1868 + mDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); 1.1869 + mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); 1.1870 + mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); 1.1871 + 1.1872 + if (clearParams.mask & GL_COLOR_BUFFER_BIT) 1.1873 + { 1.1874 + mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 1.1875 + gl_d3d9::ConvertColorMask(clearParams.colorMaskRed, 1.1876 + clearParams.colorMaskGreen, 1.1877 + clearParams.colorMaskBlue, 1.1878 + clearParams.colorMaskAlpha)); 1.1879 + } 1.1880 + else 1.1881 + { 1.1882 + mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0); 1.1883 + } 1.1884 + 1.1885 + if (stencilUnmasked != 0x0 && (clearParams.mask & GL_STENCIL_BUFFER_BIT)) 1.1886 + { 1.1887 + mDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE); 1.1888 + mDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE); 1.1889 + mDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS); 1.1890 + mDevice->SetRenderState(D3DRS_STENCILREF, stencil); 1.1891 + mDevice->SetRenderState(D3DRS_STENCILWRITEMASK, clearParams.stencilWriteMask); 1.1892 + mDevice->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE); 1.1893 + mDevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE); 1.1894 + mDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE); 1.1895 + } 1.1896 + else 1.1897 + { 1.1898 + mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); 1.1899 + } 1.1900 + 1.1901 + mDevice->SetPixelShader(NULL); 1.1902 + mDevice->SetVertexShader(NULL); 1.1903 + mDevice->SetFVF(D3DFVF_XYZRHW); 1.1904 + mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); 1.1905 + mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); 1.1906 + mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR); 1.1907 + mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); 1.1908 + mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR); 1.1909 + mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color); 1.1910 + mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF); 1.1911 + 1.1912 + for(int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) 1.1913 + { 1.1914 + mDevice->SetStreamSourceFreq(i, 1); 1.1915 + } 1.1916 + 1.1917 + float quad[4][4]; // A quadrilateral covering the target, aligned to match the edges 1.1918 + quad[0][0] = -0.5f; 1.1919 + quad[0][1] = mRenderTargetDesc.height - 0.5f; 1.1920 + quad[0][2] = 0.0f; 1.1921 + quad[0][3] = 1.0f; 1.1922 + 1.1923 + quad[1][0] = mRenderTargetDesc.width - 0.5f; 1.1924 + quad[1][1] = mRenderTargetDesc.height - 0.5f; 1.1925 + quad[1][2] = 0.0f; 1.1926 + quad[1][3] = 1.0f; 1.1927 + 1.1928 + quad[2][0] = -0.5f; 1.1929 + quad[2][1] = -0.5f; 1.1930 + quad[2][2] = 0.0f; 1.1931 + quad[2][3] = 1.0f; 1.1932 + 1.1933 + quad[3][0] = mRenderTargetDesc.width - 0.5f; 1.1934 + quad[3][1] = -0.5f; 1.1935 + quad[3][2] = 0.0f; 1.1936 + quad[3][3] = 1.0f; 1.1937 + 1.1938 + startScene(); 1.1939 + mDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float[4])); 1.1940 + 1.1941 + if (clearParams.mask & GL_DEPTH_BUFFER_BIT) 1.1942 + { 1.1943 + mDevice->SetRenderState(D3DRS_ZENABLE, TRUE); 1.1944 + mDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE); 1.1945 + mDevice->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil); 1.1946 + } 1.1947 + 1.1948 + if (mMaskedClearSavedState != NULL) 1.1949 + { 1.1950 + mMaskedClearSavedState->Apply(); 1.1951 + } 1.1952 + } 1.1953 + else if (clearParams.mask) 1.1954 + { 1.1955 + DWORD dxClearFlags = 0; 1.1956 + if (clearParams.mask & GL_COLOR_BUFFER_BIT) 1.1957 + { 1.1958 + dxClearFlags |= D3DCLEAR_TARGET; 1.1959 + } 1.1960 + if (clearParams.mask & GL_DEPTH_BUFFER_BIT) 1.1961 + { 1.1962 + dxClearFlags |= D3DCLEAR_ZBUFFER; 1.1963 + } 1.1964 + if (clearParams.mask & GL_STENCIL_BUFFER_BIT) 1.1965 + { 1.1966 + dxClearFlags |= D3DCLEAR_STENCIL; 1.1967 + } 1.1968 + 1.1969 + mDevice->Clear(0, NULL, dxClearFlags, color, depth, stencil); 1.1970 + } 1.1971 +} 1.1972 + 1.1973 +void Renderer9::markAllStateDirty() 1.1974 +{ 1.1975 + mAppliedRenderTargetSerial = 0; 1.1976 + mAppliedDepthbufferSerial = 0; 1.1977 + mAppliedStencilbufferSerial = 0; 1.1978 + mDepthStencilInitialized = false; 1.1979 + mRenderTargetDescInitialized = false; 1.1980 + 1.1981 + mForceSetDepthStencilState = true; 1.1982 + mForceSetRasterState = true; 1.1983 + mForceSetScissor = true; 1.1984 + mForceSetViewport = true; 1.1985 + mForceSetBlendState = true; 1.1986 + 1.1987 + for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; i++) 1.1988 + { 1.1989 + mForceSetVertexSamplerStates[i] = true; 1.1990 + mCurVertexTextureSerials[i] = 0; 1.1991 + } 1.1992 + for (unsigned int i = 0; i < gl::MAX_TEXTURE_IMAGE_UNITS; i++) 1.1993 + { 1.1994 + mForceSetPixelSamplerStates[i] = true; 1.1995 + mCurPixelTextureSerials[i] = 0; 1.1996 + } 1.1997 + 1.1998 + mAppliedIBSerial = 0; 1.1999 + mAppliedProgramBinarySerial = 0; 1.2000 + mDxUniformsDirty = true; 1.2001 + 1.2002 + mVertexDeclarationCache.markStateDirty(); 1.2003 +} 1.2004 + 1.2005 +void Renderer9::releaseDeviceResources() 1.2006 +{ 1.2007 + while (!mEventQueryPool.empty()) 1.2008 + { 1.2009 + mEventQueryPool.back()->Release(); 1.2010 + mEventQueryPool.pop_back(); 1.2011 + } 1.2012 + 1.2013 + if (mMaskedClearSavedState) 1.2014 + { 1.2015 + mMaskedClearSavedState->Release(); 1.2016 + mMaskedClearSavedState = NULL; 1.2017 + } 1.2018 + 1.2019 + mVertexShaderCache.clear(); 1.2020 + mPixelShaderCache.clear(); 1.2021 + 1.2022 + delete mBlit; 1.2023 + mBlit = NULL; 1.2024 + 1.2025 + delete mVertexDataManager; 1.2026 + mVertexDataManager = NULL; 1.2027 + 1.2028 + delete mIndexDataManager; 1.2029 + mIndexDataManager = NULL; 1.2030 + 1.2031 + delete mLineLoopIB; 1.2032 + mLineLoopIB = NULL; 1.2033 + 1.2034 + for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++) 1.2035 + { 1.2036 + delete mNullColorbufferCache[i].buffer; 1.2037 + mNullColorbufferCache[i].buffer = NULL; 1.2038 + } 1.2039 + 1.2040 +} 1.2041 + 1.2042 + 1.2043 +void Renderer9::notifyDeviceLost() 1.2044 +{ 1.2045 + mDeviceLost = true; 1.2046 + mDisplay->notifyDeviceLost(); 1.2047 +} 1.2048 + 1.2049 +bool Renderer9::isDeviceLost() 1.2050 +{ 1.2051 + return mDeviceLost; 1.2052 +} 1.2053 + 1.2054 +// set notify to true to broadcast a message to all contexts of the device loss 1.2055 +bool Renderer9::testDeviceLost(bool notify) 1.2056 +{ 1.2057 + HRESULT status = S_OK; 1.2058 + 1.2059 + if (mDeviceEx) 1.2060 + { 1.2061 + status = mDeviceEx->CheckDeviceState(NULL); 1.2062 + } 1.2063 + else if (mDevice) 1.2064 + { 1.2065 + status = mDevice->TestCooperativeLevel(); 1.2066 + } 1.2067 + else 1.2068 + { 1.2069 + // No device yet, so no reset required 1.2070 + } 1.2071 + 1.2072 + bool isLost = FAILED(status) || d3d9::isDeviceLostError(status); 1.2073 + 1.2074 + if (isLost) 1.2075 + { 1.2076 + // ensure we note the device loss -- 1.2077 + // we'll probably get this done again by notifyDeviceLost 1.2078 + // but best to remember it! 1.2079 + // Note that we don't want to clear the device loss status here 1.2080 + // -- this needs to be done by resetDevice 1.2081 + mDeviceLost = true; 1.2082 + if (notify) 1.2083 + { 1.2084 + notifyDeviceLost(); 1.2085 + } 1.2086 + } 1.2087 + 1.2088 + return isLost; 1.2089 +} 1.2090 + 1.2091 +bool Renderer9::testDeviceResettable() 1.2092 +{ 1.2093 + HRESULT status = D3D_OK; 1.2094 + 1.2095 + if (mDeviceEx) 1.2096 + { 1.2097 + status = mDeviceEx->CheckDeviceState(NULL); 1.2098 + } 1.2099 + else if (mDevice) 1.2100 + { 1.2101 + status = mDevice->TestCooperativeLevel(); 1.2102 + } 1.2103 + 1.2104 + // On D3D9Ex, DEVICELOST represents a hung device that needs to be restarted 1.2105 + // DEVICEREMOVED indicates the device has been stopped and must be recreated 1.2106 + switch (status) 1.2107 + { 1.2108 + case D3DERR_DEVICENOTRESET: 1.2109 + case D3DERR_DEVICEHUNG: 1.2110 + return true; 1.2111 + case D3DERR_DEVICELOST: 1.2112 + return (mDeviceEx != NULL); 1.2113 + case D3DERR_DEVICEREMOVED: 1.2114 + UNIMPLEMENTED(); 1.2115 + return false; 1.2116 + default: 1.2117 + return false; 1.2118 + } 1.2119 +} 1.2120 + 1.2121 +bool Renderer9::resetDevice() 1.2122 +{ 1.2123 + releaseDeviceResources(); 1.2124 + 1.2125 + D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters(); 1.2126 + 1.2127 + HRESULT result = D3D_OK; 1.2128 + bool lost = testDeviceLost(false); 1.2129 + int attempts = 3; 1.2130 + 1.2131 + while (lost && attempts > 0) 1.2132 + { 1.2133 + if (mDeviceEx) 1.2134 + { 1.2135 + Sleep(500); // Give the graphics driver some CPU time 1.2136 + result = mDeviceEx->ResetEx(&presentParameters, NULL); 1.2137 + } 1.2138 + else 1.2139 + { 1.2140 + result = mDevice->TestCooperativeLevel(); 1.2141 + while (result == D3DERR_DEVICELOST) 1.2142 + { 1.2143 + Sleep(100); // Give the graphics driver some CPU time 1.2144 + result = mDevice->TestCooperativeLevel(); 1.2145 + } 1.2146 + 1.2147 + if (result == D3DERR_DEVICENOTRESET) 1.2148 + { 1.2149 + result = mDevice->Reset(&presentParameters); 1.2150 + } 1.2151 + } 1.2152 + 1.2153 + lost = testDeviceLost(false); 1.2154 + attempts --; 1.2155 + } 1.2156 + 1.2157 + if (FAILED(result)) 1.2158 + { 1.2159 + ERR("Reset/ResetEx failed multiple times: 0x%08X", result); 1.2160 + return false; 1.2161 + } 1.2162 + 1.2163 + // reset device defaults 1.2164 + initializeDevice(); 1.2165 + mDeviceLost = false; 1.2166 + 1.2167 + return true; 1.2168 +} 1.2169 + 1.2170 +DWORD Renderer9::getAdapterVendor() const 1.2171 +{ 1.2172 + return mAdapterIdentifier.VendorId; 1.2173 +} 1.2174 + 1.2175 +std::string Renderer9::getRendererDescription() const 1.2176 +{ 1.2177 + std::ostringstream rendererString; 1.2178 + 1.2179 + rendererString << mAdapterIdentifier.Description; 1.2180 + if (getShareHandleSupport()) 1.2181 + { 1.2182 + rendererString << " Direct3D9Ex"; 1.2183 + } 1.2184 + else 1.2185 + { 1.2186 + rendererString << " Direct3D9"; 1.2187 + } 1.2188 + 1.2189 + rendererString << " vs_" << D3DSHADER_VERSION_MAJOR(mDeviceCaps.VertexShaderVersion) << "_" << D3DSHADER_VERSION_MINOR(mDeviceCaps.VertexShaderVersion); 1.2190 + rendererString << " ps_" << D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion) << "_" << D3DSHADER_VERSION_MINOR(mDeviceCaps.PixelShaderVersion); 1.2191 + 1.2192 + return rendererString.str(); 1.2193 +} 1.2194 + 1.2195 +GUID Renderer9::getAdapterIdentifier() const 1.2196 +{ 1.2197 + return mAdapterIdentifier.DeviceIdentifier; 1.2198 +} 1.2199 + 1.2200 +void Renderer9::getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray) 1.2201 +{ 1.2202 + for (int multiSampleIndex = 0; multiSampleIndex <= D3DMULTISAMPLE_16_SAMPLES; multiSampleIndex++) 1.2203 + { 1.2204 + HRESULT result = mD3d9->CheckDeviceMultiSampleType(mAdapter, mDeviceType, format, 1.2205 + TRUE, (D3DMULTISAMPLE_TYPE)multiSampleIndex, NULL); 1.2206 + 1.2207 + multiSampleArray[multiSampleIndex] = SUCCEEDED(result); 1.2208 + } 1.2209 +} 1.2210 + 1.2211 +bool Renderer9::getBGRATextureSupport() const 1.2212 +{ 1.2213 + // DirectX 9 always supports BGRA 1.2214 + return true; 1.2215 +} 1.2216 + 1.2217 +bool Renderer9::getDXT1TextureSupport() 1.2218 +{ 1.2219 + return mDXT1TextureSupport; 1.2220 +} 1.2221 + 1.2222 +bool Renderer9::getDXT3TextureSupport() 1.2223 +{ 1.2224 + return mDXT3TextureSupport; 1.2225 +} 1.2226 + 1.2227 +bool Renderer9::getDXT5TextureSupport() 1.2228 +{ 1.2229 + return mDXT5TextureSupport; 1.2230 +} 1.2231 + 1.2232 +bool Renderer9::getDepthTextureSupport() const 1.2233 +{ 1.2234 + return mDepthTextureSupport; 1.2235 +} 1.2236 + 1.2237 +bool Renderer9::getFloat32TextureSupport(bool *filtering, bool *renderable) 1.2238 +{ 1.2239 + *filtering = mFloat32FilterSupport; 1.2240 + *renderable = mFloat32RenderSupport; 1.2241 + return mFloat32TextureSupport; 1.2242 +} 1.2243 + 1.2244 +bool Renderer9::getFloat16TextureSupport(bool *filtering, bool *renderable) 1.2245 +{ 1.2246 + *filtering = mFloat16FilterSupport; 1.2247 + *renderable = mFloat16RenderSupport; 1.2248 + return mFloat16TextureSupport; 1.2249 +} 1.2250 + 1.2251 +bool Renderer9::getLuminanceTextureSupport() 1.2252 +{ 1.2253 + return mLuminanceTextureSupport; 1.2254 +} 1.2255 + 1.2256 +bool Renderer9::getLuminanceAlphaTextureSupport() 1.2257 +{ 1.2258 + return mLuminanceAlphaTextureSupport; 1.2259 +} 1.2260 + 1.2261 +bool Renderer9::getTextureFilterAnisotropySupport() const 1.2262 +{ 1.2263 + return mSupportsTextureFilterAnisotropy; 1.2264 +} 1.2265 + 1.2266 +float Renderer9::getTextureMaxAnisotropy() const 1.2267 +{ 1.2268 + if (mSupportsTextureFilterAnisotropy) 1.2269 + { 1.2270 + return static_cast<float>(mDeviceCaps.MaxAnisotropy); 1.2271 + } 1.2272 + return 1.0f; 1.2273 +} 1.2274 + 1.2275 +bool Renderer9::getEventQuerySupport() 1.2276 +{ 1.2277 + return mEventQuerySupport; 1.2278 +} 1.2279 + 1.2280 +unsigned int Renderer9::getMaxVertexTextureImageUnits() const 1.2281 +{ 1.2282 + META_ASSERT(MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 <= gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS); 1.2283 + return mVertexTextureSupport ? MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 : 0; 1.2284 +} 1.2285 + 1.2286 +unsigned int Renderer9::getMaxCombinedTextureImageUnits() const 1.2287 +{ 1.2288 + return gl::MAX_TEXTURE_IMAGE_UNITS + getMaxVertexTextureImageUnits(); 1.2289 +} 1.2290 + 1.2291 +unsigned int Renderer9::getReservedVertexUniformVectors() const 1.2292 +{ 1.2293 + return 2; // dx_ViewAdjust and dx_DepthRange. 1.2294 +} 1.2295 + 1.2296 +unsigned int Renderer9::getReservedFragmentUniformVectors() const 1.2297 +{ 1.2298 + return 3; // dx_ViewCoords, dx_DepthFront and dx_DepthRange. 1.2299 +} 1.2300 + 1.2301 +unsigned int Renderer9::getMaxVertexUniformVectors() const 1.2302 +{ 1.2303 + return MAX_VERTEX_CONSTANT_VECTORS_D3D9 - getReservedVertexUniformVectors(); 1.2304 +} 1.2305 + 1.2306 +unsigned int Renderer9::getMaxFragmentUniformVectors() const 1.2307 +{ 1.2308 + const int maxPixelConstantVectors = (getMajorShaderModel() >= 3) ? MAX_PIXEL_CONSTANT_VECTORS_SM3 : MAX_PIXEL_CONSTANT_VECTORS_SM2; 1.2309 + 1.2310 + return maxPixelConstantVectors - getReservedFragmentUniformVectors(); 1.2311 +} 1.2312 + 1.2313 +unsigned int Renderer9::getMaxVaryingVectors() const 1.2314 +{ 1.2315 + return (getMajorShaderModel() >= 3) ? MAX_VARYING_VECTORS_SM3 : MAX_VARYING_VECTORS_SM2; 1.2316 +} 1.2317 + 1.2318 +bool Renderer9::getNonPower2TextureSupport() const 1.2319 +{ 1.2320 + return mSupportsNonPower2Textures; 1.2321 +} 1.2322 + 1.2323 +bool Renderer9::getOcclusionQuerySupport() const 1.2324 +{ 1.2325 + return mOcclusionQuerySupport; 1.2326 +} 1.2327 + 1.2328 +bool Renderer9::getInstancingSupport() const 1.2329 +{ 1.2330 + return mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0); 1.2331 +} 1.2332 + 1.2333 +bool Renderer9::getShareHandleSupport() const 1.2334 +{ 1.2335 + // PIX doesn't seem to support using share handles, so disable them. 1.2336 + return (mD3d9Ex != NULL) && !gl::perfActive(); 1.2337 +} 1.2338 + 1.2339 +bool Renderer9::getDerivativeInstructionSupport() const 1.2340 +{ 1.2341 + return (mDeviceCaps.PS20Caps.Caps & D3DPS20CAPS_GRADIENTINSTRUCTIONS) != 0; 1.2342 +} 1.2343 + 1.2344 +bool Renderer9::getPostSubBufferSupport() const 1.2345 +{ 1.2346 + return true; 1.2347 +} 1.2348 + 1.2349 +int Renderer9::getMajorShaderModel() const 1.2350 +{ 1.2351 + return D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion); 1.2352 +} 1.2353 + 1.2354 +float Renderer9::getMaxPointSize() const 1.2355 +{ 1.2356 + // Point size clamped at 1.0f for SM2 1.2357 + return getMajorShaderModel() == 3 ? mDeviceCaps.MaxPointSize : 1.0f; 1.2358 +} 1.2359 + 1.2360 +int Renderer9::getMaxViewportDimension() const 1.2361 +{ 1.2362 + int maxTextureDimension = std::min(std::min(getMaxTextureWidth(), getMaxTextureHeight()), 1.2363 + (int)gl::IMPLEMENTATION_MAX_TEXTURE_SIZE); 1.2364 + return maxTextureDimension; 1.2365 +} 1.2366 + 1.2367 +int Renderer9::getMaxTextureWidth() const 1.2368 +{ 1.2369 + return (int)mDeviceCaps.MaxTextureWidth; 1.2370 +} 1.2371 + 1.2372 +int Renderer9::getMaxTextureHeight() const 1.2373 +{ 1.2374 + return (int)mDeviceCaps.MaxTextureHeight; 1.2375 +} 1.2376 + 1.2377 +bool Renderer9::get32BitIndexSupport() const 1.2378 +{ 1.2379 + return mDeviceCaps.MaxVertexIndex >= (1 << 16); 1.2380 +} 1.2381 + 1.2382 +DWORD Renderer9::getCapsDeclTypes() const 1.2383 +{ 1.2384 + return mDeviceCaps.DeclTypes; 1.2385 +} 1.2386 + 1.2387 +int Renderer9::getMinSwapInterval() const 1.2388 +{ 1.2389 + return mMinSwapInterval; 1.2390 +} 1.2391 + 1.2392 +int Renderer9::getMaxSwapInterval() const 1.2393 +{ 1.2394 + return mMaxSwapInterval; 1.2395 +} 1.2396 + 1.2397 +int Renderer9::getMaxSupportedSamples() const 1.2398 +{ 1.2399 + return mMaxSupportedSamples; 1.2400 +} 1.2401 + 1.2402 +int Renderer9::getNearestSupportedSamples(D3DFORMAT format, int requested) const 1.2403 +{ 1.2404 + if (requested == 0) 1.2405 + { 1.2406 + return requested; 1.2407 + } 1.2408 + 1.2409 + std::map<D3DFORMAT, bool *>::const_iterator itr = mMultiSampleSupport.find(format); 1.2410 + if (itr == mMultiSampleSupport.end()) 1.2411 + { 1.2412 + if (format == D3DFMT_UNKNOWN) 1.2413 + return 0; 1.2414 + return -1; 1.2415 + } 1.2416 + 1.2417 + for (int i = requested; i <= D3DMULTISAMPLE_16_SAMPLES; ++i) 1.2418 + { 1.2419 + if (itr->second[i] && i != D3DMULTISAMPLE_NONMASKABLE) 1.2420 + { 1.2421 + return i; 1.2422 + } 1.2423 + } 1.2424 + 1.2425 + return -1; 1.2426 +} 1.2427 + 1.2428 +unsigned int Renderer9::getMaxRenderTargets() const 1.2429 +{ 1.2430 + // we do not support MRT in d3d9 1.2431 + return 1; 1.2432 +} 1.2433 + 1.2434 +D3DFORMAT Renderer9::ConvertTextureInternalFormat(GLint internalformat) 1.2435 +{ 1.2436 + switch (internalformat) 1.2437 + { 1.2438 + case GL_DEPTH_COMPONENT16: 1.2439 + case GL_DEPTH_COMPONENT32_OES: 1.2440 + case GL_DEPTH24_STENCIL8_OES: 1.2441 + return D3DFMT_INTZ; 1.2442 + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: 1.2443 + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: 1.2444 + return D3DFMT_DXT1; 1.2445 + case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: 1.2446 + return D3DFMT_DXT3; 1.2447 + case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: 1.2448 + return D3DFMT_DXT5; 1.2449 + case GL_RGBA32F_EXT: 1.2450 + case GL_RGB32F_EXT: 1.2451 + case GL_ALPHA32F_EXT: 1.2452 + case GL_LUMINANCE32F_EXT: 1.2453 + case GL_LUMINANCE_ALPHA32F_EXT: 1.2454 + return D3DFMT_A32B32G32R32F; 1.2455 + case GL_RGBA16F_EXT: 1.2456 + case GL_RGB16F_EXT: 1.2457 + case GL_ALPHA16F_EXT: 1.2458 + case GL_LUMINANCE16F_EXT: 1.2459 + case GL_LUMINANCE_ALPHA16F_EXT: 1.2460 + return D3DFMT_A16B16G16R16F; 1.2461 + case GL_LUMINANCE8_EXT: 1.2462 + if (getLuminanceTextureSupport()) 1.2463 + { 1.2464 + return D3DFMT_L8; 1.2465 + } 1.2466 + break; 1.2467 + case GL_LUMINANCE8_ALPHA8_EXT: 1.2468 + if (getLuminanceAlphaTextureSupport()) 1.2469 + { 1.2470 + return D3DFMT_A8L8; 1.2471 + } 1.2472 + break; 1.2473 + case GL_RGB8_OES: 1.2474 + case GL_RGB565: 1.2475 + return D3DFMT_X8R8G8B8; 1.2476 + } 1.2477 + 1.2478 + return D3DFMT_A8R8G8B8; 1.2479 +} 1.2480 + 1.2481 +bool Renderer9::copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source) 1.2482 +{ 1.2483 + bool result = false; 1.2484 + 1.2485 + if (source && dest) 1.2486 + { 1.2487 + TextureStorage9_2D *source9 = TextureStorage9_2D::makeTextureStorage9_2D(source->getStorageInstance()); 1.2488 + TextureStorage9_2D *dest9 = TextureStorage9_2D::makeTextureStorage9_2D(dest->getStorageInstance()); 1.2489 + 1.2490 + int levels = source9->levelCount(); 1.2491 + for (int i = 0; i < levels; ++i) 1.2492 + { 1.2493 + IDirect3DSurface9 *srcSurf = source9->getSurfaceLevel(i, false); 1.2494 + IDirect3DSurface9 *dstSurf = dest9->getSurfaceLevel(i, false); 1.2495 + 1.2496 + result = copyToRenderTarget(dstSurf, srcSurf, source9->isManaged()); 1.2497 + 1.2498 + if (srcSurf) srcSurf->Release(); 1.2499 + if (dstSurf) dstSurf->Release(); 1.2500 + 1.2501 + if (!result) 1.2502 + return false; 1.2503 + } 1.2504 + } 1.2505 + 1.2506 + return result; 1.2507 +} 1.2508 + 1.2509 +bool Renderer9::copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source) 1.2510 +{ 1.2511 + bool result = false; 1.2512 + 1.2513 + if (source && dest) 1.2514 + { 1.2515 + TextureStorage9_Cube *source9 = TextureStorage9_Cube::makeTextureStorage9_Cube(source->getStorageInstance()); 1.2516 + TextureStorage9_Cube *dest9 = TextureStorage9_Cube::makeTextureStorage9_Cube(dest->getStorageInstance()); 1.2517 + int levels = source9->levelCount(); 1.2518 + for (int f = 0; f < 6; f++) 1.2519 + { 1.2520 + for (int i = 0; i < levels; i++) 1.2521 + { 1.2522 + IDirect3DSurface9 *srcSurf = source9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, false); 1.2523 + IDirect3DSurface9 *dstSurf = dest9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, true); 1.2524 + 1.2525 + result = copyToRenderTarget(dstSurf, srcSurf, source9->isManaged()); 1.2526 + 1.2527 + if (srcSurf) srcSurf->Release(); 1.2528 + if (dstSurf) dstSurf->Release(); 1.2529 + 1.2530 + if (!result) 1.2531 + return false; 1.2532 + } 1.2533 + } 1.2534 + } 1.2535 + 1.2536 + return result; 1.2537 +} 1.2538 + 1.2539 +D3DPOOL Renderer9::getBufferPool(DWORD usage) const 1.2540 +{ 1.2541 + if (mD3d9Ex != NULL) 1.2542 + { 1.2543 + return D3DPOOL_DEFAULT; 1.2544 + } 1.2545 + else 1.2546 + { 1.2547 + if (!(usage & D3DUSAGE_DYNAMIC)) 1.2548 + { 1.2549 + return D3DPOOL_MANAGED; 1.2550 + } 1.2551 + } 1.2552 + 1.2553 + return D3DPOOL_DEFAULT; 1.2554 +} 1.2555 + 1.2556 +bool Renderer9::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, 1.2557 + GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level) 1.2558 +{ 1.2559 + RECT rect; 1.2560 + rect.left = sourceRect.x; 1.2561 + rect.top = sourceRect.y; 1.2562 + rect.right = sourceRect.x + sourceRect.width; 1.2563 + rect.bottom = sourceRect.y + sourceRect.height; 1.2564 + 1.2565 + return mBlit->copy(framebuffer, rect, destFormat, xoffset, yoffset, storage, level); 1.2566 +} 1.2567 + 1.2568 +bool Renderer9::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, 1.2569 + GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level) 1.2570 +{ 1.2571 + RECT rect; 1.2572 + rect.left = sourceRect.x; 1.2573 + rect.top = sourceRect.y; 1.2574 + rect.right = sourceRect.x + sourceRect.width; 1.2575 + rect.bottom = sourceRect.y + sourceRect.height; 1.2576 + 1.2577 + return mBlit->copy(framebuffer, rect, destFormat, xoffset, yoffset, storage, target, level); 1.2578 +} 1.2579 + 1.2580 +bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle &readRect, gl::Framebuffer *drawFramebuffer, const gl::Rectangle &drawRect, 1.2581 + bool blitRenderTarget, bool blitDepthStencil) 1.2582 +{ 1.2583 + endScene(); 1.2584 + 1.2585 + if (blitRenderTarget) 1.2586 + { 1.2587 + gl::Renderbuffer *readBuffer = readFramebuffer->getColorbuffer(0); 1.2588 + gl::Renderbuffer *drawBuffer = drawFramebuffer->getColorbuffer(0); 1.2589 + RenderTarget9 *readRenderTarget = NULL; 1.2590 + RenderTarget9 *drawRenderTarget = NULL; 1.2591 + IDirect3DSurface9* readSurface = NULL; 1.2592 + IDirect3DSurface9* drawSurface = NULL; 1.2593 + 1.2594 + if (readBuffer) 1.2595 + { 1.2596 + readRenderTarget = RenderTarget9::makeRenderTarget9(readBuffer->getRenderTarget()); 1.2597 + } 1.2598 + if (drawBuffer) 1.2599 + { 1.2600 + drawRenderTarget = RenderTarget9::makeRenderTarget9(drawBuffer->getRenderTarget()); 1.2601 + } 1.2602 + 1.2603 + if (readRenderTarget) 1.2604 + { 1.2605 + readSurface = readRenderTarget->getSurface(); 1.2606 + } 1.2607 + if (drawRenderTarget) 1.2608 + { 1.2609 + drawSurface = drawRenderTarget->getSurface(); 1.2610 + } 1.2611 + 1.2612 + if (!readSurface || !drawSurface) 1.2613 + { 1.2614 + ERR("Failed to retrieve the render target."); 1.2615 + return gl::error(GL_OUT_OF_MEMORY, false); 1.2616 + } 1.2617 + 1.2618 + RECT srcRect; 1.2619 + srcRect.left = readRect.x; 1.2620 + srcRect.right = readRect.x + readRect.width; 1.2621 + srcRect.top = readRect.y; 1.2622 + srcRect.bottom = readRect.y + readRect.height; 1.2623 + 1.2624 + RECT dstRect; 1.2625 + dstRect.left = drawRect.x; 1.2626 + dstRect.right = drawRect.x + drawRect.width; 1.2627 + dstRect.top = drawRect.y; 1.2628 + dstRect.bottom = drawRect.y + drawRect.height; 1.2629 + 1.2630 + HRESULT result = mDevice->StretchRect(readSurface, &srcRect, drawSurface, &dstRect, D3DTEXF_NONE); 1.2631 + 1.2632 + readSurface->Release(); 1.2633 + drawSurface->Release(); 1.2634 + 1.2635 + if (FAILED(result)) 1.2636 + { 1.2637 + ERR("BlitFramebufferANGLE failed: StretchRect returned %x.", result); 1.2638 + return false; 1.2639 + } 1.2640 + } 1.2641 + 1.2642 + if (blitDepthStencil) 1.2643 + { 1.2644 + gl::Renderbuffer *readBuffer = readFramebuffer->getDepthOrStencilbuffer(); 1.2645 + gl::Renderbuffer *drawBuffer = drawFramebuffer->getDepthOrStencilbuffer(); 1.2646 + RenderTarget9 *readDepthStencil = NULL; 1.2647 + RenderTarget9 *drawDepthStencil = NULL; 1.2648 + IDirect3DSurface9* readSurface = NULL; 1.2649 + IDirect3DSurface9* drawSurface = NULL; 1.2650 + 1.2651 + if (readBuffer) 1.2652 + { 1.2653 + readDepthStencil = RenderTarget9::makeRenderTarget9(readBuffer->getDepthStencil()); 1.2654 + } 1.2655 + if (drawBuffer) 1.2656 + { 1.2657 + drawDepthStencil = RenderTarget9::makeRenderTarget9(drawBuffer->getDepthStencil()); 1.2658 + } 1.2659 + 1.2660 + if (readDepthStencil) 1.2661 + { 1.2662 + readSurface = readDepthStencil->getSurface(); 1.2663 + } 1.2664 + if (drawDepthStencil) 1.2665 + { 1.2666 + drawSurface = drawDepthStencil->getSurface(); 1.2667 + } 1.2668 + 1.2669 + if (!readSurface || !drawSurface) 1.2670 + { 1.2671 + ERR("Failed to retrieve the render target."); 1.2672 + return gl::error(GL_OUT_OF_MEMORY, false); 1.2673 + } 1.2674 + 1.2675 + HRESULT result = mDevice->StretchRect(readSurface, NULL, drawSurface, NULL, D3DTEXF_NONE); 1.2676 + 1.2677 + readSurface->Release(); 1.2678 + drawSurface->Release(); 1.2679 + 1.2680 + if (FAILED(result)) 1.2681 + { 1.2682 + ERR("BlitFramebufferANGLE failed: StretchRect returned %x.", result); 1.2683 + return false; 1.2684 + } 1.2685 + } 1.2686 + 1.2687 + return true; 1.2688 +} 1.2689 + 1.2690 +void Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, 1.2691 + GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels) 1.2692 +{ 1.2693 + RenderTarget9 *renderTarget = NULL; 1.2694 + IDirect3DSurface9 *surface = NULL; 1.2695 + gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(0); 1.2696 + 1.2697 + if (colorbuffer) 1.2698 + { 1.2699 + renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget()); 1.2700 + } 1.2701 + 1.2702 + if (renderTarget) 1.2703 + { 1.2704 + surface = renderTarget->getSurface(); 1.2705 + } 1.2706 + 1.2707 + if (!surface) 1.2708 + { 1.2709 + // context must be lost 1.2710 + return; 1.2711 + } 1.2712 + 1.2713 + D3DSURFACE_DESC desc; 1.2714 + surface->GetDesc(&desc); 1.2715 + 1.2716 + if (desc.MultiSampleType != D3DMULTISAMPLE_NONE) 1.2717 + { 1.2718 + UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target 1.2719 + surface->Release(); 1.2720 + return gl::error(GL_OUT_OF_MEMORY); 1.2721 + } 1.2722 + 1.2723 + HRESULT result; 1.2724 + IDirect3DSurface9 *systemSurface = NULL; 1.2725 + bool directToPixels = !packReverseRowOrder && packAlignment <= 4 && getShareHandleSupport() && 1.2726 + x == 0 && y == 0 && UINT(width) == desc.Width && UINT(height) == desc.Height && 1.2727 + desc.Format == D3DFMT_A8R8G8B8 && format == GL_BGRA_EXT && type == GL_UNSIGNED_BYTE; 1.2728 + if (directToPixels) 1.2729 + { 1.2730 + // Use the pixels ptr as a shared handle to write directly into client's memory 1.2731 + result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, 1.2732 + D3DPOOL_SYSTEMMEM, &systemSurface, &pixels); 1.2733 + if (FAILED(result)) 1.2734 + { 1.2735 + // Try again without the shared handle 1.2736 + directToPixels = false; 1.2737 + } 1.2738 + } 1.2739 + 1.2740 + if (!directToPixels) 1.2741 + { 1.2742 + result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, 1.2743 + D3DPOOL_SYSTEMMEM, &systemSurface, NULL); 1.2744 + if (FAILED(result)) 1.2745 + { 1.2746 + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); 1.2747 + surface->Release(); 1.2748 + return gl::error(GL_OUT_OF_MEMORY); 1.2749 + } 1.2750 + } 1.2751 + 1.2752 + result = mDevice->GetRenderTargetData(surface, systemSurface); 1.2753 + surface->Release(); 1.2754 + surface = NULL; 1.2755 + 1.2756 + if (FAILED(result)) 1.2757 + { 1.2758 + systemSurface->Release(); 1.2759 + 1.2760 + // It turns out that D3D will sometimes produce more error 1.2761 + // codes than those documented. 1.2762 + if (d3d9::isDeviceLostError(result)) 1.2763 + { 1.2764 + notifyDeviceLost(); 1.2765 + return gl::error(GL_OUT_OF_MEMORY); 1.2766 + } 1.2767 + else 1.2768 + { 1.2769 + UNREACHABLE(); 1.2770 + return; 1.2771 + } 1.2772 + 1.2773 + } 1.2774 + 1.2775 + if (directToPixels) 1.2776 + { 1.2777 + systemSurface->Release(); 1.2778 + return; 1.2779 + } 1.2780 + 1.2781 + RECT rect; 1.2782 + rect.left = gl::clamp(x, 0L, static_cast<LONG>(desc.Width)); 1.2783 + rect.top = gl::clamp(y, 0L, static_cast<LONG>(desc.Height)); 1.2784 + rect.right = gl::clamp(x + width, 0L, static_cast<LONG>(desc.Width)); 1.2785 + rect.bottom = gl::clamp(y + height, 0L, static_cast<LONG>(desc.Height)); 1.2786 + 1.2787 + D3DLOCKED_RECT lock; 1.2788 + result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY); 1.2789 + 1.2790 + if (FAILED(result)) 1.2791 + { 1.2792 + UNREACHABLE(); 1.2793 + systemSurface->Release(); 1.2794 + 1.2795 + return; // No sensible error to generate 1.2796 + } 1.2797 + 1.2798 + unsigned char *dest = (unsigned char*)pixels; 1.2799 + unsigned short *dest16 = (unsigned short*)pixels; 1.2800 + 1.2801 + unsigned char *source; 1.2802 + int inputPitch; 1.2803 + if (packReverseRowOrder) 1.2804 + { 1.2805 + source = ((unsigned char*)lock.pBits) + lock.Pitch * (rect.bottom - rect.top - 1); 1.2806 + inputPitch = -lock.Pitch; 1.2807 + } 1.2808 + else 1.2809 + { 1.2810 + source = (unsigned char*)lock.pBits; 1.2811 + inputPitch = lock.Pitch; 1.2812 + } 1.2813 + 1.2814 + unsigned int fastPixelSize = 0; 1.2815 + 1.2816 + if (desc.Format == D3DFMT_A8R8G8B8 && 1.2817 + format == GL_BGRA_EXT && 1.2818 + type == GL_UNSIGNED_BYTE) 1.2819 + { 1.2820 + fastPixelSize = 4; 1.2821 + } 1.2822 + else if ((desc.Format == D3DFMT_A4R4G4B4 && 1.2823 + format == GL_BGRA_EXT && 1.2824 + type == GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT) || 1.2825 + (desc.Format == D3DFMT_A1R5G5B5 && 1.2826 + format == GL_BGRA_EXT && 1.2827 + type == GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT)) 1.2828 + { 1.2829 + fastPixelSize = 2; 1.2830 + } 1.2831 + else if (desc.Format == D3DFMT_A16B16G16R16F && 1.2832 + format == GL_RGBA && 1.2833 + type == GL_HALF_FLOAT_OES) 1.2834 + { 1.2835 + fastPixelSize = 8; 1.2836 + } 1.2837 + else if (desc.Format == D3DFMT_A32B32G32R32F && 1.2838 + format == GL_RGBA && 1.2839 + type == GL_FLOAT) 1.2840 + { 1.2841 + fastPixelSize = 16; 1.2842 + } 1.2843 + 1.2844 + for (int j = 0; j < rect.bottom - rect.top; j++) 1.2845 + { 1.2846 + if (fastPixelSize != 0) 1.2847 + { 1.2848 + // Fast path for formats which require no translation: 1.2849 + // D3DFMT_A8R8G8B8 to BGRA/UNSIGNED_BYTE 1.2850 + // D3DFMT_A4R4G4B4 to BGRA/UNSIGNED_SHORT_4_4_4_4_REV_EXT 1.2851 + // D3DFMT_A1R5G5B5 to BGRA/UNSIGNED_SHORT_1_5_5_5_REV_EXT 1.2852 + // D3DFMT_A16B16G16R16F to RGBA/HALF_FLOAT_OES 1.2853 + // D3DFMT_A32B32G32R32F to RGBA/FLOAT 1.2854 + // 1.2855 + // Note that buffers with no alpha go through the slow path below. 1.2856 + memcpy(dest + j * outputPitch, 1.2857 + source + j * inputPitch, 1.2858 + (rect.right - rect.left) * fastPixelSize); 1.2859 + continue; 1.2860 + } 1.2861 + else if (desc.Format == D3DFMT_A8R8G8B8 && 1.2862 + format == GL_RGBA && 1.2863 + type == GL_UNSIGNED_BYTE) 1.2864 + { 1.2865 + // Fast path for swapping red with blue 1.2866 + for (int i = 0; i < rect.right - rect.left; i++) 1.2867 + { 1.2868 + unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch); 1.2869 + *(unsigned int*)(dest + 4 * i + j * outputPitch) = 1.2870 + (argb & 0xFF00FF00) | // Keep alpha and green 1.2871 + (argb & 0x00FF0000) >> 16 | // Move red to blue 1.2872 + (argb & 0x000000FF) << 16; // Move blue to red 1.2873 + } 1.2874 + continue; 1.2875 + } 1.2876 + 1.2877 + for (int i = 0; i < rect.right - rect.left; i++) 1.2878 + { 1.2879 + float r; 1.2880 + float g; 1.2881 + float b; 1.2882 + float a; 1.2883 + 1.2884 + switch (desc.Format) 1.2885 + { 1.2886 + case D3DFMT_R5G6B5: 1.2887 + { 1.2888 + unsigned short rgb = *(unsigned short*)(source + 2 * i + j * inputPitch); 1.2889 + 1.2890 + a = 1.0f; 1.2891 + b = (rgb & 0x001F) * (1.0f / 0x001F); 1.2892 + g = (rgb & 0x07E0) * (1.0f / 0x07E0); 1.2893 + r = (rgb & 0xF800) * (1.0f / 0xF800); 1.2894 + } 1.2895 + break; 1.2896 + case D3DFMT_A1R5G5B5: 1.2897 + { 1.2898 + unsigned short argb = *(unsigned short*)(source + 2 * i + j * inputPitch); 1.2899 + 1.2900 + a = (argb & 0x8000) ? 1.0f : 0.0f; 1.2901 + b = (argb & 0x001F) * (1.0f / 0x001F); 1.2902 + g = (argb & 0x03E0) * (1.0f / 0x03E0); 1.2903 + r = (argb & 0x7C00) * (1.0f / 0x7C00); 1.2904 + } 1.2905 + break; 1.2906 + case D3DFMT_A8R8G8B8: 1.2907 + { 1.2908 + unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch); 1.2909 + 1.2910 + a = (argb & 0xFF000000) * (1.0f / 0xFF000000); 1.2911 + b = (argb & 0x000000FF) * (1.0f / 0x000000FF); 1.2912 + g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00); 1.2913 + r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000); 1.2914 + } 1.2915 + break; 1.2916 + case D3DFMT_X8R8G8B8: 1.2917 + { 1.2918 + unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * inputPitch); 1.2919 + 1.2920 + a = 1.0f; 1.2921 + b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF); 1.2922 + g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00); 1.2923 + r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000); 1.2924 + } 1.2925 + break; 1.2926 + case D3DFMT_A2R10G10B10: 1.2927 + { 1.2928 + unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch); 1.2929 + 1.2930 + a = (argb & 0xC0000000) * (1.0f / 0xC0000000); 1.2931 + b = (argb & 0x000003FF) * (1.0f / 0x000003FF); 1.2932 + g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00); 1.2933 + r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000); 1.2934 + } 1.2935 + break; 1.2936 + case D3DFMT_A32B32G32R32F: 1.2937 + { 1.2938 + // float formats in D3D are stored rgba, rather than the other way round 1.2939 + r = *((float*)(source + 16 * i + j * inputPitch) + 0); 1.2940 + g = *((float*)(source + 16 * i + j * inputPitch) + 1); 1.2941 + b = *((float*)(source + 16 * i + j * inputPitch) + 2); 1.2942 + a = *((float*)(source + 16 * i + j * inputPitch) + 3); 1.2943 + } 1.2944 + break; 1.2945 + case D3DFMT_A16B16G16R16F: 1.2946 + { 1.2947 + // float formats in D3D are stored rgba, rather than the other way round 1.2948 + r = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 0)); 1.2949 + g = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 1)); 1.2950 + b = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 2)); 1.2951 + a = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 3)); 1.2952 + } 1.2953 + break; 1.2954 + default: 1.2955 + UNIMPLEMENTED(); // FIXME 1.2956 + UNREACHABLE(); 1.2957 + return; 1.2958 + } 1.2959 + 1.2960 + switch (format) 1.2961 + { 1.2962 + case GL_RGBA: 1.2963 + switch (type) 1.2964 + { 1.2965 + case GL_UNSIGNED_BYTE: 1.2966 + dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f); 1.2967 + dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f); 1.2968 + dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f); 1.2969 + dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f); 1.2970 + break; 1.2971 + default: UNREACHABLE(); 1.2972 + } 1.2973 + break; 1.2974 + case GL_BGRA_EXT: 1.2975 + switch (type) 1.2976 + { 1.2977 + case GL_UNSIGNED_BYTE: 1.2978 + dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * b + 0.5f); 1.2979 + dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f); 1.2980 + dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * r + 0.5f); 1.2981 + dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f); 1.2982 + break; 1.2983 + case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT: 1.2984 + // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section 1.2985 + // this type is packed as follows: 1.2986 + // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 1.2987 + // -------------------------------------------------------------------------------- 1.2988 + // | 4th | 3rd | 2nd | 1st component | 1.2989 + // -------------------------------------------------------------------------------- 1.2990 + // in the case of BGRA_EXT, B is the first component, G the second, and so forth. 1.2991 + dest16[i + j * outputPitch / sizeof(unsigned short)] = 1.2992 + ((unsigned short)(15 * a + 0.5f) << 12)| 1.2993 + ((unsigned short)(15 * r + 0.5f) << 8) | 1.2994 + ((unsigned short)(15 * g + 0.5f) << 4) | 1.2995 + ((unsigned short)(15 * b + 0.5f) << 0); 1.2996 + break; 1.2997 + case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT: 1.2998 + // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section 1.2999 + // this type is packed as follows: 1.3000 + // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 1.3001 + // -------------------------------------------------------------------------------- 1.3002 + // | 4th | 3rd | 2nd | 1st component | 1.3003 + // -------------------------------------------------------------------------------- 1.3004 + // in the case of BGRA_EXT, B is the first component, G the second, and so forth. 1.3005 + dest16[i + j * outputPitch / sizeof(unsigned short)] = 1.3006 + ((unsigned short)( a + 0.5f) << 15) | 1.3007 + ((unsigned short)(31 * r + 0.5f) << 10) | 1.3008 + ((unsigned short)(31 * g + 0.5f) << 5) | 1.3009 + ((unsigned short)(31 * b + 0.5f) << 0); 1.3010 + break; 1.3011 + default: UNREACHABLE(); 1.3012 + } 1.3013 + break; 1.3014 + case GL_RGB: 1.3015 + switch (type) 1.3016 + { 1.3017 + case GL_UNSIGNED_SHORT_5_6_5: 1.3018 + dest16[i + j * outputPitch / sizeof(unsigned short)] = 1.3019 + ((unsigned short)(31 * b + 0.5f) << 0) | 1.3020 + ((unsigned short)(63 * g + 0.5f) << 5) | 1.3021 + ((unsigned short)(31 * r + 0.5f) << 11); 1.3022 + break; 1.3023 + case GL_UNSIGNED_BYTE: 1.3024 + dest[3 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f); 1.3025 + dest[3 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f); 1.3026 + dest[3 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f); 1.3027 + break; 1.3028 + default: UNREACHABLE(); 1.3029 + } 1.3030 + break; 1.3031 + default: UNREACHABLE(); 1.3032 + } 1.3033 + } 1.3034 + } 1.3035 + 1.3036 + systemSurface->UnlockRect(); 1.3037 + 1.3038 + systemSurface->Release(); 1.3039 +} 1.3040 + 1.3041 +RenderTarget *Renderer9::createRenderTarget(SwapChain *swapChain, bool depth) 1.3042 +{ 1.3043 + SwapChain9 *swapChain9 = SwapChain9::makeSwapChain9(swapChain); 1.3044 + IDirect3DSurface9 *surface = NULL; 1.3045 + if (depth) 1.3046 + { 1.3047 + surface = swapChain9->getDepthStencil(); 1.3048 + } 1.3049 + else 1.3050 + { 1.3051 + surface = swapChain9->getRenderTarget(); 1.3052 + } 1.3053 + 1.3054 + RenderTarget9 *renderTarget = new RenderTarget9(this, surface); 1.3055 + 1.3056 + return renderTarget; 1.3057 +} 1.3058 + 1.3059 +RenderTarget *Renderer9::createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth) 1.3060 +{ 1.3061 + RenderTarget9 *renderTarget = new RenderTarget9(this, width, height, format, samples); 1.3062 + return renderTarget; 1.3063 +} 1.3064 + 1.3065 +ShaderExecutable *Renderer9::loadExecutable(const void *function, size_t length, rx::ShaderType type) 1.3066 +{ 1.3067 + ShaderExecutable9 *executable = NULL; 1.3068 + 1.3069 + switch (type) 1.3070 + { 1.3071 + case rx::SHADER_VERTEX: 1.3072 + { 1.3073 + IDirect3DVertexShader9 *vshader = createVertexShader((DWORD*)function, length); 1.3074 + if (vshader) 1.3075 + { 1.3076 + executable = new ShaderExecutable9(function, length, vshader); 1.3077 + } 1.3078 + } 1.3079 + break; 1.3080 + case rx::SHADER_PIXEL: 1.3081 + { 1.3082 + IDirect3DPixelShader9 *pshader = createPixelShader((DWORD*)function, length); 1.3083 + if (pshader) 1.3084 + { 1.3085 + executable = new ShaderExecutable9(function, length, pshader); 1.3086 + } 1.3087 + } 1.3088 + break; 1.3089 + default: 1.3090 + UNREACHABLE(); 1.3091 + break; 1.3092 + } 1.3093 + 1.3094 + return executable; 1.3095 +} 1.3096 + 1.3097 +ShaderExecutable *Renderer9::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type) 1.3098 +{ 1.3099 + const char *profile = NULL; 1.3100 + 1.3101 + switch (type) 1.3102 + { 1.3103 + case rx::SHADER_VERTEX: 1.3104 + profile = getMajorShaderModel() >= 3 ? "vs_3_0" : "vs_2_0"; 1.3105 + break; 1.3106 + case rx::SHADER_PIXEL: 1.3107 + profile = getMajorShaderModel() >= 3 ? "ps_3_0" : "ps_2_0"; 1.3108 + break; 1.3109 + default: 1.3110 + UNREACHABLE(); 1.3111 + return NULL; 1.3112 + } 1.3113 + 1.3114 + ID3DBlob *binary = (ID3DBlob*)compileToBinary(infoLog, shaderHLSL, profile, ANGLE_COMPILE_OPTIMIZATION_LEVEL, true); 1.3115 + if (!binary) 1.3116 + return NULL; 1.3117 + 1.3118 + ShaderExecutable *executable = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type); 1.3119 + binary->Release(); 1.3120 + 1.3121 + return executable; 1.3122 +} 1.3123 + 1.3124 +bool Renderer9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest) 1.3125 +{ 1.3126 + return mBlit->boxFilter(source, dest); 1.3127 +} 1.3128 + 1.3129 +D3DPOOL Renderer9::getTexturePool(DWORD usage) const 1.3130 +{ 1.3131 + if (mD3d9Ex != NULL) 1.3132 + { 1.3133 + return D3DPOOL_DEFAULT; 1.3134 + } 1.3135 + else 1.3136 + { 1.3137 + if (!(usage & (D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_RENDERTARGET))) 1.3138 + { 1.3139 + return D3DPOOL_DEFAULT; 1.3140 + } 1.3141 + } 1.3142 + 1.3143 + return D3DPOOL_DEFAULT; 1.3144 +} 1.3145 + 1.3146 +bool Renderer9::copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged) 1.3147 +{ 1.3148 + if (source && dest) 1.3149 + { 1.3150 + HRESULT result = D3DERR_OUTOFVIDEOMEMORY; 1.3151 + 1.3152 + if (fromManaged) 1.3153 + { 1.3154 + D3DSURFACE_DESC desc; 1.3155 + source->GetDesc(&desc); 1.3156 + 1.3157 + IDirect3DSurface9 *surf = 0; 1.3158 + result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL); 1.3159 + 1.3160 + if (SUCCEEDED(result)) 1.3161 + { 1.3162 + Image9::copyLockableSurfaces(surf, source); 1.3163 + result = mDevice->UpdateSurface(surf, NULL, dest, NULL); 1.3164 + surf->Release(); 1.3165 + } 1.3166 + } 1.3167 + else 1.3168 + { 1.3169 + endScene(); 1.3170 + result = mDevice->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE); 1.3171 + } 1.3172 + 1.3173 + if (FAILED(result)) 1.3174 + { 1.3175 + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); 1.3176 + return false; 1.3177 + } 1.3178 + } 1.3179 + 1.3180 + return true; 1.3181 +} 1.3182 + 1.3183 +Image *Renderer9::createImage() 1.3184 +{ 1.3185 + return new Image9(); 1.3186 +} 1.3187 + 1.3188 +void Renderer9::generateMipmap(Image *dest, Image *src) 1.3189 +{ 1.3190 + Image9 *src9 = Image9::makeImage9(src); 1.3191 + Image9 *dst9 = Image9::makeImage9(dest); 1.3192 + Image9::generateMipmap(dst9, src9); 1.3193 +} 1.3194 + 1.3195 +TextureStorage *Renderer9::createTextureStorage2D(SwapChain *swapChain) 1.3196 +{ 1.3197 + SwapChain9 *swapChain9 = SwapChain9::makeSwapChain9(swapChain); 1.3198 + return new TextureStorage9_2D(this, swapChain9); 1.3199 +} 1.3200 + 1.3201 +TextureStorage *Renderer9::createTextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height) 1.3202 +{ 1.3203 + return new TextureStorage9_2D(this, levels, internalformat, usage, forceRenderable, width, height); 1.3204 +} 1.3205 + 1.3206 +TextureStorage *Renderer9::createTextureStorageCube(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size) 1.3207 +{ 1.3208 + return new TextureStorage9_Cube(this, levels, internalformat, usage, forceRenderable, size); 1.3209 +} 1.3210 + 1.3211 +bool Renderer9::getLUID(LUID *adapterLuid) const 1.3212 +{ 1.3213 + adapterLuid->HighPart = 0; 1.3214 + adapterLuid->LowPart = 0; 1.3215 + 1.3216 + if (mD3d9Ex) 1.3217 + { 1.3218 + mD3d9Ex->GetAdapterLUID(mAdapter, adapterLuid); 1.3219 + return true; 1.3220 + } 1.3221 + 1.3222 + return false; 1.3223 +} 1.3224 + 1.3225 +}