blob: 8fa645e5931f77547262aa3dc502d46b6b50f2b1 [file] [log] [blame]
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001//
2// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// Renderer11.cpp: Implements a back-end specific class for the D3D11 renderer.
8
9#include "common/debug.h"
daniel@transgaming.com5503fd02012-11-28 19:38:57 +000010#include "libGLESv2/main.h"
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +000011#include "libGLESv2/utilities.h"
daniel@transgaming.comdcf1e672012-11-28 19:38:19 +000012#include "libGLESv2/mathutil.h"
daniel@transgaming.com53670042012-11-28 20:55:51 +000013#include "libGLESv2/Program.h"
14#include "libGLESv2/ProgramBinary.h"
daniel@transgaming.com80fc3322012-11-28 21:02:13 +000015#include "libGLESv2/Framebuffer.h"
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +000016#include "libGLESv2/renderer/Renderer11.h"
daniel@transgaming.comb6b27bc2012-11-28 20:54:30 +000017#include "libGLESv2/renderer/RenderTarget11.h"
daniel@transgaming.com65e65372012-11-28 19:33:50 +000018#include "libGLESv2/renderer/renderer11_utils.h"
daniel@transgaming.coma60160b2012-11-28 19:41:15 +000019#include "libGLESv2/renderer/SwapChain11.h"
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +000020
21#include "libEGL/Config.h"
22#include "libEGL/Display.h"
23
daniel@transgaming.com071ee6a2012-11-28 21:03:21 +000024#if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL)
25#define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3
26#endif
27
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +000028namespace rx
29{
daniel@transgaming.com65e65372012-11-28 19:33:50 +000030static const DXGI_FORMAT RenderTargetFormats[] =
31 {
32 DXGI_FORMAT_R8G8B8A8_UNORM
33 };
34
35static const DXGI_FORMAT DepthStencilFormats[] =
36 {
37 DXGI_FORMAT_D24_UNORM_S8_UINT
38 };
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +000039
40Renderer11::Renderer11(egl::Display *display, HDC hDc) : Renderer(display), mDc(hDc)
41{
42 mD3d11Module = NULL;
43 mDxgiModule = NULL;
daniel@transgaming.com04af90f2012-11-28 21:03:09 +000044 mD3dCompilerModule = NULL;
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +000045
daniel@transgaming.comb9bb2792012-11-28 19:36:49 +000046 mDeviceLost = false;
47
daniel@transgaming.com25072f62012-11-28 19:31:32 +000048 mDevice = NULL;
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +000049 mDeviceContext = NULL;
daniel@transgaming.com65e65372012-11-28 19:33:50 +000050 mDxgiAdapter = NULL;
51 mDxgiFactory = NULL;
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +000052}
53
54Renderer11::~Renderer11()
55{
56 releaseDeviceResources();
57
daniel@transgaming.com65e65372012-11-28 19:33:50 +000058 if (mDxgiFactory)
59 {
60 mDxgiFactory->Release();
61 mDxgiFactory = NULL;
62 }
63
64 if (mDxgiAdapter)
65 {
66 mDxgiAdapter->Release();
67 mDxgiAdapter = NULL;
68 }
69
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +000070 if (mDeviceContext)
71 {
72 mDeviceContext->Release();
73 mDeviceContext = NULL;
74 }
75
daniel@transgaming.com25072f62012-11-28 19:31:32 +000076 if (mDevice)
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +000077 {
daniel@transgaming.com25072f62012-11-28 19:31:32 +000078 mDevice->Release();
79 mDevice = NULL;
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +000080 }
81
82 if (mD3d11Module)
83 {
daniel@transgaming.comc1e26342012-11-28 19:31:16 +000084 FreeLibrary(mD3d11Module);
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +000085 mD3d11Module = NULL;
86 }
87
88 if (mDxgiModule)
89 {
daniel@transgaming.comc1e26342012-11-28 19:31:16 +000090 FreeLibrary(mDxgiModule);
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +000091 mDxgiModule = NULL;
92 }
daniel@transgaming.com04af90f2012-11-28 21:03:09 +000093
94 if (mD3dCompilerModule)
95 {
96 FreeLibrary(mD3dCompilerModule);
97 mD3dCompilerModule = NULL;
98 }
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +000099}
100
daniel@transgaming.comb64ed282012-11-28 20:54:02 +0000101Renderer11 *Renderer11::makeRenderer11(Renderer *renderer)
102{
103 ASSERT(dynamic_cast<rx::Renderer11*>(renderer) != NULL);
104 return static_cast<rx::Renderer11*>(renderer);
105}
106
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000107EGLint Renderer11::initialize()
108{
daniel@transgaming.comc1e26342012-11-28 19:31:16 +0000109 mDxgiModule = LoadLibrary(TEXT("dxgi.dll"));
110 mD3d11Module = LoadLibrary(TEXT("d3d11.dll"));
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000111
112 if (mD3d11Module == NULL || mDxgiModule == NULL)
113 {
daniel@transgaming.comc1e26342012-11-28 19:31:16 +0000114 ERR("Could not load D3D11 or DXGI library - aborting!\n");
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000115 return EGL_NOT_INITIALIZED;
116 }
117
daniel@transgaming.comc1e26342012-11-28 19:31:16 +0000118 PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice");
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000119
daniel@transgaming.comc1e26342012-11-28 19:31:16 +0000120 if (D3D11CreateDevice == NULL)
121 {
122 ERR("Could not retrieve D3D11CreateDevice address - aborting!\n");
123 return EGL_NOT_INITIALIZED;
124 }
daniel@transgaming.com25072f62012-11-28 19:31:32 +0000125
126 D3D_FEATURE_LEVEL featureLevel[] =
127 {
128 D3D_FEATURE_LEVEL_11_0,
129 D3D_FEATURE_LEVEL_10_1,
130 D3D_FEATURE_LEVEL_10_0,
131 };
132
daniel@transgaming.comc1e26342012-11-28 19:31:16 +0000133 HRESULT result = D3D11CreateDevice(NULL,
134 D3D_DRIVER_TYPE_HARDWARE,
135 NULL,
daniel@transgaming.coma60160b2012-11-28 19:41:15 +0000136 #if defined(_DEBUG)
137 D3D11_CREATE_DEVICE_DEBUG,
138 #else
139 0,
140 #endif
daniel@transgaming.com25072f62012-11-28 19:31:32 +0000141 featureLevel,
142 sizeof(featureLevel)/sizeof(featureLevel[0]),
daniel@transgaming.comc1e26342012-11-28 19:31:16 +0000143 D3D11_SDK_VERSION,
daniel@transgaming.com25072f62012-11-28 19:31:32 +0000144 &mDevice,
145 &mFeatureLevel,
daniel@transgaming.comc1e26342012-11-28 19:31:16 +0000146 &mDeviceContext);
daniel@transgaming.com25072f62012-11-28 19:31:32 +0000147
148 if (!mDevice || FAILED(result))
daniel@transgaming.comc1e26342012-11-28 19:31:16 +0000149 {
150 ERR("Could not create D3D11 device - aborting!\n");
151 return EGL_NOT_INITIALIZED; // Cleanup done by destructor through glDestroyRenderer
152 }
daniel@transgaming.com65e65372012-11-28 19:33:50 +0000153
154 IDXGIDevice *dxgiDevice = NULL;
155 result = mDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice);
156
157 if (FAILED(result))
158 {
159 ERR("Could not query DXGI device - aborting!\n");
160 return EGL_NOT_INITIALIZED;
161 }
162
163 result = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&mDxgiAdapter);
164
165 if (FAILED(result))
166 {
167 ERR("Could not retrieve DXGI adapter - aborting!\n");
168 return EGL_NOT_INITIALIZED;
169 }
170
171 dxgiDevice->Release();
172
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000173 mDxgiAdapter->GetDesc(&mAdapterDescription);
174 memset(mDescription, 0, sizeof(mDescription));
175 wcstombs(mDescription, mAdapterDescription.Description, sizeof(mDescription) - 1);
176
daniel@transgaming.com65e65372012-11-28 19:33:50 +0000177 result = mDxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void**)&mDxgiFactory);
178
179 if (!mDxgiFactory || FAILED(result))
180 {
181 ERR("Could not create DXGI factory - aborting!\n");
182 return EGL_NOT_INITIALIZED;
183 }
184
daniel@transgaming.com04af90f2012-11-28 21:03:09 +0000185#if defined(ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES)
186 // Find a D3DCompiler module that had already been loaded based on a predefined list of versions.
187 static TCHAR* d3dCompilerNames[] = ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES;
188
189 for (int i = 0; i < sizeof(d3dCompilerNames) / sizeof(*d3dCompilerNames); ++i)
190 {
191 if (GetModuleHandleEx(0, d3dCompilerNames[i], &mD3dCompilerModule))
192 {
193 break;
194 }
195 }
196#else
197 // Load the version of the D3DCompiler DLL associated with the Direct3D version ANGLE was built with.
198 mD3dCompilerModule = LoadLibrary(D3DCOMPILER_DLL);
199#endif // ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES
200
201 if (!mD3dCompilerModule)
202 {
203 terminate();
204 return false;
205 }
206
207 mD3DCompileFunc = reinterpret_cast<pD3DCompile>(GetProcAddress(mD3dCompilerModule, "D3DCompile"));
208 ASSERT(mD3DCompileFunc);
209
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000210 initializeDevice();
211
212 return EGL_SUCCESS;
213}
214
215// do any one-time device initialization
216// NOTE: this is also needed after a device lost/reset
217// to reset the scene status and ensure the default states are reset.
218void Renderer11::initializeDevice()
219{
daniel@transgaming.comf8ba1092012-11-28 19:37:53 +0000220 mStateCache.initialize(mDevice);
221
daniel@transgaming.comc43a6052012-11-28 19:41:51 +0000222 markAllStateDirty();
223
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000224 // Permanent non-default states
225 // TODO
daniel@transgaming.comc1e26342012-11-28 19:31:16 +0000226 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000227}
228
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000229int Renderer11::generateConfigs(ConfigDesc **configDescList)
230{
daniel@transgaming.come3e826d2012-11-28 19:42:35 +0000231 unsigned int numRenderFormats = sizeof(RenderTargetFormats) / sizeof(RenderTargetFormats[0]);
232 unsigned int numDepthFormats = sizeof(DepthStencilFormats) / sizeof(DepthStencilFormats[0]);
daniel@transgaming.com65e65372012-11-28 19:33:50 +0000233 (*configDescList) = new ConfigDesc[numRenderFormats * numDepthFormats];
234 int numConfigs = 0;
235
daniel@transgaming.come3e826d2012-11-28 19:42:35 +0000236 for (unsigned int formatIndex = 0; formatIndex < numRenderFormats; formatIndex++)
daniel@transgaming.com65e65372012-11-28 19:33:50 +0000237 {
daniel@transgaming.come3e826d2012-11-28 19:42:35 +0000238 for (unsigned int depthStencilIndex = 0; depthStencilIndex < numDepthFormats; depthStencilIndex++)
daniel@transgaming.com65e65372012-11-28 19:33:50 +0000239 {
240 DXGI_FORMAT renderTargetFormat = RenderTargetFormats[formatIndex];
241
242 UINT formatSupport = 0;
243 HRESULT result = mDevice->CheckFormatSupport(renderTargetFormat, &formatSupport);
244
245 if (SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_RENDER_TARGET))
246 {
247 DXGI_FORMAT depthStencilFormat = DepthStencilFormats[depthStencilIndex];
248
249 UINT formatSupport = 0;
250 HRESULT result = mDevice->CheckFormatSupport(depthStencilFormat, &formatSupport);
251
252 if (SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_DEPTH_STENCIL))
253 {
254 ConfigDesc newConfig;
255 newConfig.renderTargetFormat = d3d11_gl::ConvertBackBufferFormat(renderTargetFormat);
256 newConfig.depthStencilFormat = d3d11_gl::ConvertDepthStencilFormat(depthStencilFormat);
257 newConfig.multiSample = 0; // FIXME: enumerate multi-sampling
258 newConfig.fastConfig = true; // Assume all DX11 format conversions to be fast
259
260 (*configDescList)[numConfigs++] = newConfig;
261 }
262 }
263 }
264 }
265
266 return numConfigs;
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000267}
268
269void Renderer11::deleteConfigs(ConfigDesc *configDescList)
270{
271 delete [] (configDescList);
272}
273
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000274void Renderer11::sync(bool block)
275{
276 // TODO
277 UNIMPLEMENTED();
278}
279
daniel@transgaming.comb9bb2792012-11-28 19:36:49 +0000280SwapChain *Renderer11::createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat)
281{
daniel@transgaming.coma60160b2012-11-28 19:41:15 +0000282 return new rx::SwapChain11(this, window, shareHandle, backBufferFormat, depthBufferFormat);
daniel@transgaming.comb9bb2792012-11-28 19:36:49 +0000283}
284
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000285void Renderer11::setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &samplerState)
286{
287 // TODO
288 UNIMPLEMENTED();
289}
290
291void Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *texture)
292{
293 // TODO
294 UNIMPLEMENTED();
295}
296
daniel@transgaming.com237bc7e2012-11-28 21:01:06 +0000297void Renderer11::setRasterizerState(const gl::RasterizerState &rasterState)
daniel@transgaming.com493d4f82012-11-28 19:35:45 +0000298{
daniel@transgaming.com237bc7e2012-11-28 21:01:06 +0000299 if (mForceSetRasterState || memcmp(&rasterState, &mCurRasterState, sizeof(gl::RasterizerState)) != 0)
daniel@transgaming.comdcf1e672012-11-28 19:38:19 +0000300 {
daniel@transgaming.com237bc7e2012-11-28 21:01:06 +0000301 ID3D11RasterizerState *dxRasterState = mStateCache.getRasterizerState(rasterState, mCurDepthSize);
daniel@transgaming.comdcf1e672012-11-28 19:38:19 +0000302 if (!dxRasterState)
303 {
304 ERR("NULL blend state returned by RenderStateCache::getRasterizerState, setting the "
305 "rasterizer state.");
306 }
307
308 mDeviceContext->RSSetState(dxRasterState);
309
310 if (dxRasterState)
311 {
312 dxRasterState->Release();
313 }
314 mCurRasterState = rasterState;
daniel@transgaming.comdcf1e672012-11-28 19:38:19 +0000315 }
316
317 mForceSetRasterState = false;
daniel@transgaming.com493d4f82012-11-28 19:35:45 +0000318}
319
320void Renderer11::setBlendState(const gl::BlendState &blendState, const gl::Color &blendColor,
321 unsigned int sampleMask)
322{
daniel@transgaming.comf8ba1092012-11-28 19:37:53 +0000323 if (mForceSetBlendState ||
324 memcmp(&blendState, &mCurBlendState, sizeof(gl::BlendState)) != 0 ||
325 memcmp(&blendColor, &mCurBlendColor, sizeof(gl::Color)) != 0 ||
326 sampleMask != mCurSampleMask)
327 {
328 ID3D11BlendState *dxBlendState = mStateCache.getBlendState(blendState);
329 if (!dxBlendState)
330 {
331 ERR("NULL blend state returned by RenderStateCache::getBlendState, setting the default "
332 "blend state.");
333 }
334
335 const float blendColors[] = { blendColor.red, blendColor.green, blendColor.blue, blendColor.alpha };
336 mDeviceContext->OMSetBlendState(dxBlendState, blendColors, sampleMask);
337
338 if (dxBlendState)
339 {
340 dxBlendState->Release();
341 }
342 mCurBlendState = blendState;
343 mCurBlendColor = blendColor;
344 mCurSampleMask = sampleMask;
345 }
346
347 mForceSetBlendState = false;
daniel@transgaming.com493d4f82012-11-28 19:35:45 +0000348}
349
daniel@transgaming.com08c331d2012-11-28 19:38:39 +0000350void Renderer11::setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef,
daniel@transgaming.com3a0ef482012-11-28 21:01:20 +0000351 int stencilBackRef, bool frontFaceCCW)
daniel@transgaming.com493d4f82012-11-28 19:35:45 +0000352{
daniel@transgaming.com5503fd02012-11-28 19:38:57 +0000353 if (mForceSetDepthStencilState ||
354 memcmp(&depthStencilState, &mCurDepthStencilState, sizeof(gl::DepthStencilState)) != 0 ||
355 stencilRef != mCurStencilRef || stencilBackRef != mCurStencilBackRef)
356 {
357 if (depthStencilState.stencilWritemask != depthStencilState.stencilBackWritemask ||
358 stencilRef != stencilBackRef ||
359 depthStencilState.stencilMask != depthStencilState.stencilBackMask)
360 {
361 ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are "
362 "invalid under WebGL.");
363 return error(GL_INVALID_OPERATION);
364 }
365
366 ID3D11DepthStencilState *dxDepthStencilState = mStateCache.getDepthStencilState(depthStencilState);
367 if (!dxDepthStencilState)
368 {
369 ERR("NULL depth stencil state returned by RenderStateCache::getDepthStencilState, "
370 "setting the default depth stencil state.");
371 }
372
373 mDeviceContext->OMSetDepthStencilState(dxDepthStencilState, static_cast<UINT>(stencilRef));
374
375 if (dxDepthStencilState)
376 {
377 dxDepthStencilState->Release();
378 }
379 mCurDepthStencilState = depthStencilState;
380 mCurStencilRef = stencilRef;
381 mCurStencilBackRef = stencilBackRef;
382 }
383
384 mForceSetDepthStencilState = false;
daniel@transgaming.com493d4f82012-11-28 19:35:45 +0000385}
386
daniel@transgaming.com04f1b332012-11-28 21:00:40 +0000387void Renderer11::setScissorRectangle(const gl::Rectangle &scissor)
daniel@transgaming.com493d4f82012-11-28 19:35:45 +0000388{
daniel@transgaming.com04f1b332012-11-28 21:00:40 +0000389 if (mForceSetScissor || memcmp(&scissor, &mCurScissor, sizeof(gl::Rectangle)) != 0)
daniel@transgaming.comdcf1e672012-11-28 19:38:19 +0000390 {
391 D3D11_RECT rect;
daniel@transgaming.com04f1b332012-11-28 21:00:40 +0000392 rect.left = gl::clamp(scissor.x, 0, static_cast<int>(mRenderTargetDesc.width));
393 rect.top = gl::clamp(scissor.y, 0, static_cast<int>(mRenderTargetDesc.height));
394 rect.right = gl::clamp(scissor.x + scissor.width, 0, static_cast<int>(mRenderTargetDesc.width));
395 rect.bottom = gl::clamp(scissor.y + scissor.height, 0, static_cast<int>(mRenderTargetDesc.height));
daniel@transgaming.comdcf1e672012-11-28 19:38:19 +0000396
397 mDeviceContext->RSSetScissorRects(1, &rect);
398
399 mCurScissor = scissor;
daniel@transgaming.comdcf1e672012-11-28 19:38:19 +0000400 }
401
402 mForceSetScissor = false;
daniel@transgaming.com493d4f82012-11-28 19:35:45 +0000403}
404
daniel@transgaming.com4c4ce232012-11-28 21:01:40 +0000405bool Renderer11::setViewport(const gl::Rectangle &viewport, float zNear, float zFar, bool ignoreViewport,
daniel@transgaming.com83e80ee2012-11-28 19:40:53 +0000406 gl::ProgramBinary *currentProgram, bool forceSetUniforms)
407{
daniel@transgaming.com4c4ce232012-11-28 21:01:40 +0000408 gl::Rectangle actualViewport = viewport;
409 float actualZNear = gl::clamp01(zNear);
410 float actualZFar = gl::clamp01(zFar);
411 if (ignoreViewport)
412 {
413 actualViewport.x = 0;
414 actualViewport.y = 0;
415 actualViewport.width = mRenderTargetDesc.width;
416 actualViewport.height = mRenderTargetDesc.height;
417 actualZNear = 0.0f;
418 actualZFar = 1.0f;
419 }
daniel@transgaming.com53670042012-11-28 20:55:51 +0000420
421 D3D11_VIEWPORT dxViewport;
daniel@transgaming.com4c4ce232012-11-28 21:01:40 +0000422 dxViewport.TopLeftX = gl::clamp(actualViewport.x, 0, static_cast<int>(mRenderTargetDesc.width));
423 dxViewport.TopLeftY = gl::clamp(actualViewport.y, 0, static_cast<int>(mRenderTargetDesc.height));
424 dxViewport.Width = gl::clamp(actualViewport.width, 0, static_cast<int>(mRenderTargetDesc.width) - static_cast<int>(dxViewport.TopLeftX));
425 dxViewport.Height = gl::clamp(actualViewport.height, 0, static_cast<int>(mRenderTargetDesc.height) - static_cast<int>(dxViewport.TopLeftY));
426 dxViewport.MinDepth = actualZNear;
427 dxViewport.MaxDepth = actualZFar;
daniel@transgaming.com53670042012-11-28 20:55:51 +0000428
429 if (dxViewport.Width <= 0 || dxViewport.Height <= 0)
430 {
431 return false; // Nothing to render
432 }
433
daniel@transgaming.com4c4ce232012-11-28 21:01:40 +0000434 bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 ||
435 actualZNear != mCurNear || actualZFar != mCurFar;
436
daniel@transgaming.com53670042012-11-28 20:55:51 +0000437 if (viewportChanged)
438 {
439 mDeviceContext->RSSetViewports(1, &dxViewport);
440
daniel@transgaming.com4c4ce232012-11-28 21:01:40 +0000441 mCurViewport = actualViewport;
442 mCurNear = actualZNear;
443 mCurFar = actualZFar;
daniel@transgaming.com53670042012-11-28 20:55:51 +0000444 }
445
446 if (currentProgram && (viewportChanged || forceSetUniforms))
447 {
448 GLint halfPixelSize = currentProgram->getDxHalfPixelSizeLocation();
449 GLfloat xy[2] = { 0.0f, 0.0f };
450 currentProgram->setUniform2fv(halfPixelSize, 1, xy);
451
452 // These values are used for computing gl_FragCoord in Program::linkVaryings().
453 GLint coord = currentProgram->getDxCoordLocation();
daniel@transgaming.com4c4ce232012-11-28 21:01:40 +0000454 GLfloat whxy[4] = { actualViewport.width * 0.5f,
455 actualViewport.height * 0.5f,
456 actualViewport.x + (actualViewport.width * 0.5f),
457 actualViewport.y + (actualViewport.height * 0.5f) };
daniel@transgaming.com53670042012-11-28 20:55:51 +0000458 currentProgram->setUniform4fv(coord, 1, whxy);
459
460 GLint depth = currentProgram->getDxDepthLocation();
daniel@transgaming.com4c4ce232012-11-28 21:01:40 +0000461 GLfloat dz[2] = { (actualZFar - actualZNear) * 0.5f, (actualZNear + actualZFar) * 0.5f };
daniel@transgaming.com53670042012-11-28 20:55:51 +0000462 currentProgram->setUniform2fv(depth, 1, dz);
463
464 GLint depthRange = currentProgram->getDxDepthRangeLocation();
daniel@transgaming.com4c4ce232012-11-28 21:01:40 +0000465 GLfloat nearFarDiff[3] = { actualZNear, actualZFar, actualZFar - actualZNear };
daniel@transgaming.com53670042012-11-28 20:55:51 +0000466 currentProgram->setUniform3fv(depthRange, 1, nearFarDiff);
467 }
468
469 mForceSetViewport = false;
daniel@transgaming.com83e80ee2012-11-28 19:40:53 +0000470 return true;
471}
472
daniel@transgaming.com91207b72012-11-28 20:56:43 +0000473bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count)
474{
475 // TODO
476 UNIMPLEMENTED();
477
478 return false;
479}
480
481bool Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer)
daniel@transgaming.com493d4f82012-11-28 19:35:45 +0000482{
daniel@transgaming.com80fc3322012-11-28 21:02:13 +0000483 // Get the color render buffer and serial
484 gl::Renderbuffer *renderbufferObject = NULL;
485 unsigned int renderTargetSerial = 0;
486 if (framebuffer->getColorbufferType() != GL_NONE)
487 {
488 renderbufferObject = framebuffer->getColorbuffer();
daniel@transgaming.comdcf1e672012-11-28 19:38:19 +0000489
daniel@transgaming.com80fc3322012-11-28 21:02:13 +0000490 if (!renderbufferObject)
491 {
492 ERR("render target pointer unexpectedly null.");
daniel@transgaming.come9c71b42012-11-28 21:02:23 +0000493 return false;
daniel@transgaming.com80fc3322012-11-28 21:02:13 +0000494 }
495
496 renderTargetSerial = renderbufferObject->getSerial();
497 }
498
499 // Get the depth stencil render buffer and serials
500 gl::Renderbuffer *depthStencil = NULL;
501 unsigned int depthbufferSerial = 0;
502 unsigned int stencilbufferSerial = 0;
503 if (framebuffer->getDepthbufferType() != GL_NONE)
504 {
505 depthStencil = framebuffer->getDepthbuffer();
506 if (!depthStencil)
507 {
508 ERR("Depth stencil pointer unexpectedly null.");
509 return false;
510 }
511
512 depthbufferSerial = depthStencil->getSerial();
513 }
514 else if (framebuffer->getStencilbufferType() != GL_NONE)
515 {
516 depthStencil = framebuffer->getStencilbuffer();
517 if (!depthStencil)
518 {
519 ERR("Depth stencil pointer unexpectedly null.");
520 return false;
521 }
522
523 stencilbufferSerial = depthStencil->getSerial();
524 }
525
526 // Extract the render target dimensions and view
527 unsigned int renderTargetWidth = 0;
528 unsigned int renderTargetHeight = 0;
529 GLenum renderTargetFormat = 0;
530 ID3D11RenderTargetView* framebufferRTV = NULL;
531 if (renderbufferObject)
532 {
533 RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(renderbufferObject->getRenderTarget());
534 if (!renderTarget)
535 {
536 ERR("render target pointer unexpectedly null.");
537 return false;
538 }
539
540 framebufferRTV = renderTarget->getRenderTargetView();
541 if (!framebufferRTV)
542 {
543 ERR("render target view pointer unexpectedly null.");
544 return false;
545 }
546
547 renderTargetWidth = renderbufferObject->getWidth();
548 renderTargetHeight = renderbufferObject->getHeight();
549 renderTargetFormat = renderbufferObject->getActualFormat();
550 }
551
552 // Extract the depth stencil sizes and view
553 unsigned int depthSize = 0;
554 unsigned int stencilSize = 0;
555 ID3D11DepthStencilView* framebufferDSV = NULL;
556 if (depthStencil)
557 {
558 RenderTarget11 *depthStencilRenderTarget = RenderTarget11::makeRenderTarget11(depthStencil->getDepthStencil());
559 if (!depthStencilRenderTarget)
560 {
561 ERR("render target pointer unexpectedly null.");
562 if (framebufferRTV)
563 {
564 framebufferRTV->Release();
565 }
566 return false;
567 }
568
569 framebufferDSV = depthStencilRenderTarget->getDepthStencilView();
570 if (!framebufferDSV)
571 {
572 ERR("depth stencil view pointer unexpectedly null.");
573 if (framebufferRTV)
574 {
575 framebufferRTV->Release();
576 }
577 return false;
578 }
579
580 // If there is no render buffer, the width, height and format values come from
581 // the depth stencil
582 if (!renderbufferObject)
583 {
584 renderTargetWidth = depthStencil->getWidth();
585 renderTargetHeight = depthStencil->getHeight();
586 renderTargetFormat = depthStencil->getActualFormat();
587 }
588
589 depthSize = depthStencil->getDepthSize();
590 stencilSize = depthStencil->getStencilSize();
591 }
592
593 // Apply the render target and depth stencil
594 if (!mRenderTargetDescInitialized || !mDepthStencilInitialized ||
595 renderTargetSerial != mAppliedRenderTargetSerial ||
596 depthbufferSerial != mAppliedDepthbufferSerial ||
597 stencilbufferSerial != mAppliedStencilbufferSerial)
598 {
599 mDeviceContext->OMSetRenderTargets(1, &framebufferRTV, framebufferDSV);
600
601 mRenderTargetDesc.width = renderTargetWidth;
602 mRenderTargetDesc.height = renderTargetHeight;
603 mRenderTargetDesc.format = renderTargetFormat;
604 mForceSetViewport = true; // TODO: It may not be required to clamp the viewport in D3D11
605 mForceSetScissor = true; // TODO: It may not be required to clamp the scissor in D3D11
606
607 if (!mDepthStencilInitialized || depthSize != mCurDepthSize)
608 {
609 mCurDepthSize = depthSize;
610 mForceSetRasterState = true;
611 }
612
613 mCurStencilSize = stencilSize;
614
615 mAppliedRenderTargetSerial = renderTargetSerial;
616 mAppliedDepthbufferSerial = depthbufferSerial;
617 mAppliedStencilbufferSerial = stencilbufferSerial;
618 mRenderTargetDescInitialized = true;
619 mDepthStencilInitialized = true;
620 }
621
622 if (framebufferRTV)
623 {
624 framebufferRTV->Release();
625 }
626 if (framebufferDSV)
627 {
628 framebufferDSV->Release();
629 }
daniel@transgaming.comae39ee22012-11-28 19:42:02 +0000630
631 return true;
daniel@transgaming.com493d4f82012-11-28 19:35:45 +0000632}
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000633
daniel@transgaming.com91207b72012-11-28 20:56:43 +0000634GLenum Renderer11::applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances)
daniel@transgaming.comdef9f0f2012-11-28 20:53:20 +0000635{
636 // TODO
637 UNIMPLEMENTED();
638
639 return GL_OUT_OF_MEMORY;
640}
641
daniel@transgaming.com91207b72012-11-28 20:56:43 +0000642GLenum Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, gl::TranslatedIndexData *indexInfo)
643{
644 // TODO
645 UNIMPLEMENTED();
646
647 return GL_OUT_OF_MEMORY;
648}
649
650void Renderer11::drawArrays(GLenum mode, GLsizei count, GLsizei instances)
651{
652 // TODO
653 UNIMPLEMENTED();
654}
655
daniel@transgaming.com97400dd2012-11-28 20:57:00 +0000656void Renderer11::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const gl::TranslatedIndexData &indexInfo)
daniel@transgaming.com91207b72012-11-28 20:56:43 +0000657{
658 // TODO
659 UNIMPLEMENTED();
660}
661
daniel@transgaming.com5fbf1772012-11-28 20:54:43 +0000662void Renderer11::applyShaders(gl::ProgramBinary *programBinary)
663{
664 // TODO
665 UNIMPLEMENTED();
666}
667
daniel@transgaming.com084a2572012-11-28 20:55:17 +0000668void Renderer11::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer)
daniel@transgaming.comd084c622012-11-28 19:36:05 +0000669{
daniel@transgaming.com54e67542012-11-28 21:02:31 +0000670 if (clearParams.mask & GL_COLOR_BUFFER_BIT)
671 {
672 gl::Renderbuffer *renderbufferObject = frameBuffer->getColorbuffer();
673 if (renderbufferObject)
674 {
675 RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(renderbufferObject->getRenderTarget());
676 if (!renderTarget)
677 {
678 ERR("render target pointer unexpectedly null.");
679 return;
680 }
681
682 ID3D11RenderTargetView *framebufferRTV = renderTarget->getRenderTargetView();
683 if (!framebufferRTV)
684 {
685 ERR("render target view pointer unexpectedly null.");
686 return;
687 }
688
689 if (mCurScissor.x > 0 || mCurScissor.y > 0 ||
690 mCurScissor.x + mCurScissor.width < renderTarget->getWidth() ||
691 mCurScissor.y + mCurScissor.height < renderTarget->getHeight())
692 {
693 // TODO: clearing of subregion of render target
694 UNIMPLEMENTED();
695 }
696
697 bool alphaUnmasked = (gl::GetAlphaSize(mRenderTargetDesc.format) == 0) || clearParams.colorMaskAlpha;
698 const bool needMaskedColorClear = (clearParams.mask & GL_COLOR_BUFFER_BIT) &&
699 !(clearParams.colorMaskRed && clearParams.colorMaskGreen &&
700 clearParams.colorMaskBlue && alphaUnmasked);
701
702 if (needMaskedColorClear)
703 {
704 // TODO: masked color clearing
705 UNIMPLEMENTED();
706 }
707 else
708 {
709 const float clearValues[4] = { clearParams.colorClearValue.red,
710 clearParams.colorClearValue.green,
711 clearParams.colorClearValue.blue,
712 clearParams.colorClearValue.alpha };
713 mDeviceContext->ClearRenderTargetView(framebufferRTV, clearValues);
714 }
715
716 framebufferRTV->Release();
717 }
718 }
719 if (clearParams.mask & GL_DEPTH_BUFFER_BIT || clearParams.mask & GL_STENCIL_BUFFER_BIT)
720 {
721 gl::Renderbuffer *renderbufferObject = frameBuffer->getDepthOrStencilbuffer();
722 if (renderbufferObject)
723 {
724 RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(renderbufferObject->getRenderTarget());
725 if (!renderTarget)
726 {
727 ERR("render target pointer unexpectedly null.");
728 return;
729 }
730
731 ID3D11DepthStencilView *framebufferDSV = renderTarget->getDepthStencilView();
732 if (!framebufferDSV)
733 {
734 ERR("depth stencil view pointer unexpectedly null.");
735 return;
736 }
737
738 if (mCurScissor.x > 0 || mCurScissor.y > 0 ||
739 mCurScissor.x + mCurScissor.width < renderTarget->getWidth() ||
740 mCurScissor.y + mCurScissor.height < renderTarget->getHeight())
741 {
742 // TODO: clearing of subregion of depth stencil view
743 UNIMPLEMENTED();
744 }
745
746 unsigned int stencilUnmasked = 0x0;
747 if ((clearParams.mask & GL_STENCIL_BUFFER_BIT) && frameBuffer->hasStencil())
748 {
749 unsigned int stencilSize = gl::GetStencilSize(frameBuffer->getStencilbuffer()->getActualFormat());
750 stencilUnmasked = (0x1 << stencilSize) - 1;
751 }
752
753 const bool needMaskedStencilClear = (clearParams.mask & GL_STENCIL_BUFFER_BIT) &&
754 (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked;
755
756 if (needMaskedStencilClear)
757 {
758 // TODO: masked clearing of depth stencil
759 UNIMPLEMENTED();
760 }
761 else
762 {
763 UINT clearFlags = 0;
764 if (clearParams.mask & GL_DEPTH_BUFFER_BIT)
765 {
766 clearFlags |= D3D11_CLEAR_DEPTH;
767 }
768 if (clearParams.mask & GL_STENCIL_BUFFER_BIT)
769 {
770 clearFlags |= D3D11_CLEAR_STENCIL;
771 }
772
773 float depthClear = clearParams.depthClearValue;
774 UINT8 stencilClear = clearParams.stencilClearValue & 0x000000FF;
775
776 mDeviceContext->ClearDepthStencilView(framebufferDSV, clearFlags, depthClear, stencilClear);
777 }
778
779 framebufferDSV->Release();
780 }
781 }
daniel@transgaming.comd084c622012-11-28 19:36:05 +0000782}
783
daniel@transgaming.comc43a6052012-11-28 19:41:51 +0000784void Renderer11::markAllStateDirty()
785{
daniel@transgaming.com7b6b83e2012-11-28 21:00:30 +0000786 mDepthStencilInitialized = false;
787 mRenderTargetDescInitialized = false;
788
daniel@transgaming.comc43a6052012-11-28 19:41:51 +0000789 mForceSetBlendState = true;
790 mForceSetRasterState = true;
791 mForceSetDepthStencilState = true;
792 mForceSetScissor = true;
daniel@transgaming.com53670042012-11-28 20:55:51 +0000793 mForceSetViewport = true;
daniel@transgaming.comc43a6052012-11-28 19:41:51 +0000794}
795
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000796void Renderer11::releaseDeviceResources()
797{
798 // TODO
daniel@transgaming.comc1e26342012-11-28 19:31:16 +0000799 // UNIMPLEMENTED();
daniel@transgaming.comf8ba1092012-11-28 19:37:53 +0000800 mStateCache.clear();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000801}
802
803void Renderer11::markDeviceLost()
804{
805 mDeviceLost = true;
806}
807
808bool Renderer11::isDeviceLost()
809{
810 return mDeviceLost;
811}
812
813// set notify to true to broadcast a message to all contexts of the device loss
814bool Renderer11::testDeviceLost(bool notify)
815{
816 bool isLost = false;
817
818 // TODO
daniel@transgaming.comb9bb2792012-11-28 19:36:49 +0000819 //UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000820
821 if (isLost)
822 {
823 // ensure we note the device loss --
824 // we'll probably get this done again by markDeviceLost
825 // but best to remember it!
826 // Note that we don't want to clear the device loss status here
827 // -- this needs to be done by resetDevice
828 mDeviceLost = true;
829 if (notify)
830 {
831 mDisplay->notifyDeviceLost();
832 }
833 }
834
835 return isLost;
836}
837
838bool Renderer11::testDeviceResettable()
839{
840 HRESULT status = D3D_OK;
841
842 // TODO
843 UNIMPLEMENTED();
844
845 switch (status)
846 {
847 case D3DERR_DEVICENOTRESET:
848 case D3DERR_DEVICEHUNG:
849 return true;
850 default:
851 return false;
852 }
853}
854
855bool Renderer11::resetDevice()
856{
857 releaseDeviceResources();
858
859 // TODO
860 UNIMPLEMENTED();
861
862 // reset device defaults
863 initializeDevice();
864 mDeviceLost = false;
865
866 return true;
867}
868
869DWORD Renderer11::getAdapterVendor() const
870{
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000871 return mAdapterDescription.VendorId;
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000872}
873
874const char *Renderer11::getAdapterDescription() const
875{
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000876 return mDescription;
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000877}
878
879GUID Renderer11::getAdapterIdentifier() const
880{
881 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000882 // UNIMPLEMENTED();
883 GUID foo = {0};
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000884 return foo;
885}
886
887bool Renderer11::getDXT1TextureSupport()
888{
889 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000890 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000891 return false;
892}
893
894bool Renderer11::getDXT3TextureSupport()
895{
896 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000897 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000898 return false;
899}
900
901bool Renderer11::getDXT5TextureSupport()
902{
903 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000904 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000905 return false;
906}
907
908bool Renderer11::getDepthTextureSupport() const
909{
910 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000911 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000912 return false;
913}
914
915bool Renderer11::getFloat32TextureSupport(bool *filtering, bool *renderable)
916{
917 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000918 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000919
920 *filtering = false;
921 *renderable = false;
922 return false;
923}
924
925bool Renderer11::getFloat16TextureSupport(bool *filtering, bool *renderable)
926{
927 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000928 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000929
930 *filtering = false;
931 *renderable = false;
932 return false;
933}
934
935bool Renderer11::getLuminanceTextureSupport()
936{
937 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000938 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000939 return false;
940}
941
942bool Renderer11::getLuminanceAlphaTextureSupport()
943{
944 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000945 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000946 return false;
947}
948
949bool Renderer11::getTextureFilterAnisotropySupport() const
950{
951 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000952 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000953 return false;
954}
955
956float Renderer11::getTextureMaxAnisotropy() const
957{
958 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000959 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000960 return 1.0f;
961}
962
963bool Renderer11::getEventQuerySupport()
964{
965 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000966 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000967 return false;
968}
969
970bool Renderer11::getVertexTextureSupport() const
971{
972 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000973 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000974 return false;
975}
976
977bool Renderer11::getNonPower2TextureSupport() const
978{
979 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000980 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000981 return false;
982}
983
984bool Renderer11::getOcclusionQuerySupport() const
985{
986 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000987 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000988 return false;
989}
990
991bool Renderer11::getInstancingSupport() const
992{
993 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000994 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000995 return false;
996}
997
998bool Renderer11::getShareHandleSupport() const
999{
1000 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +00001001 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001002
1003 // PIX doesn't seem to support using share handles, so disable them.
1004 return false && !gl::perfActive();
1005}
1006
daniel@transgaming.com9549bea2012-11-28 20:57:23 +00001007int Renderer11::getMajorShaderModel() const
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001008{
daniel@transgaming.com9549bea2012-11-28 20:57:23 +00001009 switch (mFeatureLevel)
1010 {
1011 case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MAJOR_VERSION; // 5
1012 case D3D_FEATURE_LEVEL_10_1:
1013 case D3D_FEATURE_LEVEL_10_0: return D3D10_SHADER_MAJOR_VERSION; // 4
1014 default: UNREACHABLE(); return 0;
1015 }
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001016}
1017
1018float Renderer11::getMaxPointSize() const
1019{
1020 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +00001021 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001022 return 1.0f;
1023}
1024
1025int Renderer11::getMaxTextureWidth() const
1026{
daniel@transgaming.com25072f62012-11-28 19:31:32 +00001027 switch (mFeatureLevel)
1028 {
1029 case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384
1030 case D3D_FEATURE_LEVEL_10_1:
1031 case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192
1032 default: UNREACHABLE(); return 0;
1033 }
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001034}
1035
1036int Renderer11::getMaxTextureHeight() const
1037{
daniel@transgaming.com25072f62012-11-28 19:31:32 +00001038 switch (mFeatureLevel)
1039 {
1040 case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384
1041 case D3D_FEATURE_LEVEL_10_1:
1042 case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192
1043 default: UNREACHABLE(); return 0;
1044 }
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001045}
1046
1047bool Renderer11::get32BitIndexSupport() const
1048{
daniel@transgaming.com25072f62012-11-28 19:31:32 +00001049 switch (mFeatureLevel)
1050 {
1051 case D3D_FEATURE_LEVEL_11_0:
1052 case D3D_FEATURE_LEVEL_10_1:
1053 case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP >= 32; // true
1054 default: UNREACHABLE(); return false;
1055 }
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001056}
1057
1058int Renderer11::getMinSwapInterval() const
1059{
daniel@transgaming.com8c7b1a92012-11-28 19:34:06 +00001060 return 0;
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001061}
1062
1063int Renderer11::getMaxSwapInterval() const
1064{
daniel@transgaming.com8c7b1a92012-11-28 19:34:06 +00001065 return 4;
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001066}
1067
1068int Renderer11::getMaxSupportedSamples() const
1069{
1070 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +00001071 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001072 return 1;
1073}
1074
daniel@transgaming.com31b13e12012-11-28 19:34:30 +00001075bool Renderer11::copyToRenderTarget(TextureStorage2D *dest, TextureStorage2D *source)
daniel@transgaming.comad6aee72012-11-28 19:33:42 +00001076{
1077 // TODO
1078 UNIMPLEMENTED();
1079 return false;
1080}
1081
daniel@transgaming.com31b13e12012-11-28 19:34:30 +00001082bool Renderer11::copyToRenderTarget(TextureStorageCubeMap *dest, TextureStorageCubeMap *source)
daniel@transgaming.comad6aee72012-11-28 19:33:42 +00001083{
1084 // TODO
1085 UNIMPLEMENTED();
1086 return false;
1087}
1088
daniel@transgaming.com38380882012-11-28 19:36:39 +00001089bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat,
1090 GLint xoffset, GLint yoffset, TextureStorage2D *storage, GLint level)
1091{
1092 // TODO
1093 UNIMPLEMENTED();
1094 return false;
1095}
1096
1097bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat,
1098 GLint xoffset, GLint yoffset, TextureStorageCubeMap *storage, GLenum target, GLint level)
1099{
1100 // TODO
1101 UNIMPLEMENTED();
1102 return false;
1103}
1104
daniel@transgaming.comf2423652012-11-28 20:53:50 +00001105RenderTarget *Renderer11::createRenderTarget(SwapChain *swapChain, bool depth)
1106{
daniel@transgaming.comb6b27bc2012-11-28 20:54:30 +00001107 SwapChain11 *swapChain11 = SwapChain11::makeSwapChain11(swapChain);
1108 RenderTarget11 *renderTarget = NULL;
1109 if (depth)
1110 {
1111 renderTarget = new RenderTarget11(this, swapChain11->getDepthStencil(), swapChain11->getWidth(), swapChain11->getHeight());
1112 }
1113 else
1114 {
1115 renderTarget = new RenderTarget11(this, swapChain11->getRenderTarget(), swapChain11->getWidth(), swapChain11->getHeight());
1116 }
1117 return renderTarget;
daniel@transgaming.comf2423652012-11-28 20:53:50 +00001118}
1119
1120RenderTarget *Renderer11::createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth)
1121{
1122 // TODO
1123 UNIMPLEMENTED();
1124 return NULL;
1125}
1126
daniel@transgaming.com55318902012-11-28 20:58:58 +00001127ShaderExecutable *Renderer11::loadExecutable(const DWORD *function, size_t length, GLenum type, void *data)
1128{
1129 // TODO
1130 UNIMPLEMENTED();
1131 return NULL;
1132}
1133
daniel@transgaming.coma9c71422012-11-28 20:58:45 +00001134ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, GLenum type)
1135{
daniel@transgaming.com071ee6a2012-11-28 21:03:21 +00001136 const char *profile = NULL;
1137
1138 switch (type)
1139 {
1140 case GL_VERTEX_SHADER:
1141 profile = "vs_4_0";
1142 break;
1143 case GL_FRAGMENT_SHADER:
1144 profile = "ps_4_0";
1145 break;
1146 default:
1147 UNREACHABLE();
1148 return NULL;
1149 }
1150
1151 ID3DBlob *binary = compileToBinary(infoLog, shaderHLSL, profile);
1152 if (!binary)
1153 return NULL;
1154
1155 ShaderExecutable *executable = loadExecutable((DWORD *)binary->GetBufferPointer(), binary->GetBufferSize(), type, NULL);
1156 binary->Release();
1157
1158 return executable;
1159}
1160
1161// Compiles the HLSL code of the attached shaders into executable binaries
1162ID3DBlob *Renderer11::compileToBinary(gl::InfoLog &infoLog, const char *hlsl, const char *profile)
1163{
1164 if (!hlsl)
1165 {
1166 return NULL;
1167 }
1168
1169 HRESULT result = S_OK;
1170 UINT flags = 0;
1171 std::string sourceText;
1172 if (gl::perfActive())
1173 {
1174 flags |= D3DCOMPILE_DEBUG;
1175#ifdef NDEBUG
1176 flags |= ANGLE_COMPILE_OPTIMIZATION_LEVEL;
1177#else
1178 flags |= D3DCOMPILE_SKIP_OPTIMIZATION;
1179#endif
1180
1181 std::string sourcePath = getTempPath();
1182 sourceText = std::string("#line 2 \"") + sourcePath + std::string("\"\n\n") + std::string(hlsl);
1183 writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size());
1184 }
1185 else
1186 {
1187 flags |= ANGLE_COMPILE_OPTIMIZATION_LEVEL;
1188 sourceText = hlsl;
1189 }
1190
1191 // Sometimes D3DCompile will fail with the default compilation flags for complicated shaders when it would otherwise pass with alternative options.
1192 // Try the default flags first and if compilation fails, try some alternatives.
1193 const static UINT extraFlags[] =
1194 {
1195 0,
1196 // D3DCOMPILE_AVOID_FLOW_CONTROL,
1197 // D3DCOMPILE_PREFER_FLOW_CONTROL
1198 };
1199
1200 const static char * const extraFlagNames[] =
1201 {
1202 "default",
1203 "avoid flow control",
1204 "prefer flow control"
1205 };
1206
1207 for (int i = 0; i < sizeof(extraFlags) / sizeof(UINT); ++i)
1208 {
1209 ID3DBlob *errorMessage = NULL;
1210 ID3DBlob *binary = NULL;
1211 result = mD3DCompileFunc(hlsl, strlen(hlsl), gl::g_fakepath, NULL, NULL,
1212 "main", profile, flags | extraFlags[i], 0, &binary, &errorMessage);
1213 if (errorMessage)
1214 {
1215 const char *message = (const char*)errorMessage->GetBufferPointer();
1216
1217 infoLog.appendSanitized(message);
1218 TRACE("\n%s", hlsl);
1219 TRACE("\n%s", message);
1220
1221 errorMessage->Release();
1222 errorMessage = NULL;
1223 }
1224
1225 if (SUCCEEDED(result))
1226 {
1227 return binary;
1228 }
1229 else
1230 {
1231 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
1232 {
1233 return error(GL_OUT_OF_MEMORY, (ID3DBlob*) NULL);
1234 }
1235
1236 infoLog.append("Warning: D3D shader compilation failed with ");
1237 infoLog.append(extraFlagNames[i]);
1238 infoLog.append(" flags.");
1239 if (i + 1 < sizeof(extraFlagNames) / sizeof(char*))
1240 {
1241 infoLog.append(" Retrying with ");
1242 infoLog.append(extraFlagNames[i + 1]);
1243 infoLog.append(".\n");
1244 }
1245 }
1246 }
1247
daniel@transgaming.coma9c71422012-11-28 20:58:45 +00001248 return NULL;
1249}
1250
daniel@transgaming.com6c872172012-11-28 19:39:33 +00001251bool Renderer11::blitRect(gl::Framebuffer *readTarget, gl::Rectangle *readRect, gl::Framebuffer *drawTarget, gl::Rectangle *drawRect,
1252 bool blitRenderTarget, bool blitDepthStencil)
1253{
1254 // TODO
1255 UNIMPLEMENTED();
1256 return false;
1257}
1258
1259void Renderer11::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type,
1260 GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels)
1261{
1262 // TODO
1263 UNIMPLEMENTED();
1264 return;
1265}
1266
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001267}