blob: 942159514530b22e4f08f546a1ab359d25eeb023 [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.coma2f9fbe2012-11-28 21:03:40 +000019#include "libGLESv2/renderer/ShaderExecutable11.h"
daniel@transgaming.coma60160b2012-11-28 19:41:15 +000020#include "libGLESv2/renderer/SwapChain11.h"
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +000021
22#include "libEGL/Config.h"
23#include "libEGL/Display.h"
24
daniel@transgaming.com071ee6a2012-11-28 21:03:21 +000025#if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL)
26#define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3
27#endif
28
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +000029namespace rx
30{
daniel@transgaming.com65e65372012-11-28 19:33:50 +000031static const DXGI_FORMAT RenderTargetFormats[] =
32 {
33 DXGI_FORMAT_R8G8B8A8_UNORM
34 };
35
36static const DXGI_FORMAT DepthStencilFormats[] =
37 {
38 DXGI_FORMAT_D24_UNORM_S8_UINT
39 };
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +000040
41Renderer11::Renderer11(egl::Display *display, HDC hDc) : Renderer(display), mDc(hDc)
42{
43 mD3d11Module = NULL;
44 mDxgiModule = NULL;
daniel@transgaming.com04af90f2012-11-28 21:03:09 +000045 mD3dCompilerModule = NULL;
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +000046
daniel@transgaming.comb9bb2792012-11-28 19:36:49 +000047 mDeviceLost = false;
48
daniel@transgaming.com25072f62012-11-28 19:31:32 +000049 mDevice = NULL;
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +000050 mDeviceContext = NULL;
daniel@transgaming.com65e65372012-11-28 19:33:50 +000051 mDxgiAdapter = NULL;
52 mDxgiFactory = NULL;
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +000053}
54
55Renderer11::~Renderer11()
56{
57 releaseDeviceResources();
58
daniel@transgaming.com65e65372012-11-28 19:33:50 +000059 if (mDxgiFactory)
60 {
61 mDxgiFactory->Release();
62 mDxgiFactory = NULL;
63 }
64
65 if (mDxgiAdapter)
66 {
67 mDxgiAdapter->Release();
68 mDxgiAdapter = NULL;
69 }
70
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +000071 if (mDeviceContext)
72 {
73 mDeviceContext->Release();
74 mDeviceContext = NULL;
75 }
76
daniel@transgaming.com25072f62012-11-28 19:31:32 +000077 if (mDevice)
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +000078 {
daniel@transgaming.com25072f62012-11-28 19:31:32 +000079 mDevice->Release();
80 mDevice = NULL;
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +000081 }
82
83 if (mD3d11Module)
84 {
daniel@transgaming.comc1e26342012-11-28 19:31:16 +000085 FreeLibrary(mD3d11Module);
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +000086 mD3d11Module = NULL;
87 }
88
89 if (mDxgiModule)
90 {
daniel@transgaming.comc1e26342012-11-28 19:31:16 +000091 FreeLibrary(mDxgiModule);
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +000092 mDxgiModule = NULL;
93 }
daniel@transgaming.com04af90f2012-11-28 21:03:09 +000094
95 if (mD3dCompilerModule)
96 {
97 FreeLibrary(mD3dCompilerModule);
98 mD3dCompilerModule = NULL;
99 }
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000100}
101
daniel@transgaming.comb64ed282012-11-28 20:54:02 +0000102Renderer11 *Renderer11::makeRenderer11(Renderer *renderer)
103{
104 ASSERT(dynamic_cast<rx::Renderer11*>(renderer) != NULL);
105 return static_cast<rx::Renderer11*>(renderer);
106}
107
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000108EGLint Renderer11::initialize()
109{
daniel@transgaming.comc1e26342012-11-28 19:31:16 +0000110 mDxgiModule = LoadLibrary(TEXT("dxgi.dll"));
111 mD3d11Module = LoadLibrary(TEXT("d3d11.dll"));
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000112
113 if (mD3d11Module == NULL || mDxgiModule == NULL)
114 {
daniel@transgaming.comc1e26342012-11-28 19:31:16 +0000115 ERR("Could not load D3D11 or DXGI library - aborting!\n");
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000116 return EGL_NOT_INITIALIZED;
117 }
118
daniel@transgaming.comc1e26342012-11-28 19:31:16 +0000119 PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice");
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000120
daniel@transgaming.comc1e26342012-11-28 19:31:16 +0000121 if (D3D11CreateDevice == NULL)
122 {
123 ERR("Could not retrieve D3D11CreateDevice address - aborting!\n");
124 return EGL_NOT_INITIALIZED;
125 }
daniel@transgaming.com25072f62012-11-28 19:31:32 +0000126
127 D3D_FEATURE_LEVEL featureLevel[] =
128 {
129 D3D_FEATURE_LEVEL_11_0,
130 D3D_FEATURE_LEVEL_10_1,
131 D3D_FEATURE_LEVEL_10_0,
132 };
133
daniel@transgaming.comc1e26342012-11-28 19:31:16 +0000134 HRESULT result = D3D11CreateDevice(NULL,
135 D3D_DRIVER_TYPE_HARDWARE,
136 NULL,
daniel@transgaming.coma60160b2012-11-28 19:41:15 +0000137 #if defined(_DEBUG)
138 D3D11_CREATE_DEVICE_DEBUG,
139 #else
140 0,
141 #endif
daniel@transgaming.com25072f62012-11-28 19:31:32 +0000142 featureLevel,
143 sizeof(featureLevel)/sizeof(featureLevel[0]),
daniel@transgaming.comc1e26342012-11-28 19:31:16 +0000144 D3D11_SDK_VERSION,
daniel@transgaming.com25072f62012-11-28 19:31:32 +0000145 &mDevice,
146 &mFeatureLevel,
daniel@transgaming.comc1e26342012-11-28 19:31:16 +0000147 &mDeviceContext);
daniel@transgaming.com25072f62012-11-28 19:31:32 +0000148
149 if (!mDevice || FAILED(result))
daniel@transgaming.comc1e26342012-11-28 19:31:16 +0000150 {
151 ERR("Could not create D3D11 device - aborting!\n");
152 return EGL_NOT_INITIALIZED; // Cleanup done by destructor through glDestroyRenderer
153 }
daniel@transgaming.com65e65372012-11-28 19:33:50 +0000154
155 IDXGIDevice *dxgiDevice = NULL;
156 result = mDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice);
157
158 if (FAILED(result))
159 {
160 ERR("Could not query DXGI device - aborting!\n");
161 return EGL_NOT_INITIALIZED;
162 }
163
164 result = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&mDxgiAdapter);
165
166 if (FAILED(result))
167 {
168 ERR("Could not retrieve DXGI adapter - aborting!\n");
169 return EGL_NOT_INITIALIZED;
170 }
171
172 dxgiDevice->Release();
173
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000174 mDxgiAdapter->GetDesc(&mAdapterDescription);
175 memset(mDescription, 0, sizeof(mDescription));
176 wcstombs(mDescription, mAdapterDescription.Description, sizeof(mDescription) - 1);
177
daniel@transgaming.com65e65372012-11-28 19:33:50 +0000178 result = mDxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void**)&mDxgiFactory);
179
180 if (!mDxgiFactory || FAILED(result))
181 {
182 ERR("Could not create DXGI factory - aborting!\n");
183 return EGL_NOT_INITIALIZED;
184 }
185
daniel@transgaming.com04af90f2012-11-28 21:03:09 +0000186#if defined(ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES)
187 // Find a D3DCompiler module that had already been loaded based on a predefined list of versions.
188 static TCHAR* d3dCompilerNames[] = ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES;
189
190 for (int i = 0; i < sizeof(d3dCompilerNames) / sizeof(*d3dCompilerNames); ++i)
191 {
192 if (GetModuleHandleEx(0, d3dCompilerNames[i], &mD3dCompilerModule))
193 {
194 break;
195 }
196 }
197#else
198 // Load the version of the D3DCompiler DLL associated with the Direct3D version ANGLE was built with.
199 mD3dCompilerModule = LoadLibrary(D3DCOMPILER_DLL);
200#endif // ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES
201
202 if (!mD3dCompilerModule)
203 {
204 terminate();
205 return false;
206 }
207
208 mD3DCompileFunc = reinterpret_cast<pD3DCompile>(GetProcAddress(mD3dCompilerModule, "D3DCompile"));
209 ASSERT(mD3DCompileFunc);
210
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000211 initializeDevice();
212
213 return EGL_SUCCESS;
214}
215
216// do any one-time device initialization
217// NOTE: this is also needed after a device lost/reset
218// to reset the scene status and ensure the default states are reset.
219void Renderer11::initializeDevice()
220{
daniel@transgaming.comf8ba1092012-11-28 19:37:53 +0000221 mStateCache.initialize(mDevice);
222
daniel@transgaming.comc43a6052012-11-28 19:41:51 +0000223 markAllStateDirty();
224
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000225 // Permanent non-default states
226 // TODO
daniel@transgaming.comc1e26342012-11-28 19:31:16 +0000227 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000228}
229
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000230int Renderer11::generateConfigs(ConfigDesc **configDescList)
231{
daniel@transgaming.come3e826d2012-11-28 19:42:35 +0000232 unsigned int numRenderFormats = sizeof(RenderTargetFormats) / sizeof(RenderTargetFormats[0]);
233 unsigned int numDepthFormats = sizeof(DepthStencilFormats) / sizeof(DepthStencilFormats[0]);
daniel@transgaming.com65e65372012-11-28 19:33:50 +0000234 (*configDescList) = new ConfigDesc[numRenderFormats * numDepthFormats];
235 int numConfigs = 0;
236
daniel@transgaming.come3e826d2012-11-28 19:42:35 +0000237 for (unsigned int formatIndex = 0; formatIndex < numRenderFormats; formatIndex++)
daniel@transgaming.com65e65372012-11-28 19:33:50 +0000238 {
daniel@transgaming.come3e826d2012-11-28 19:42:35 +0000239 for (unsigned int depthStencilIndex = 0; depthStencilIndex < numDepthFormats; depthStencilIndex++)
daniel@transgaming.com65e65372012-11-28 19:33:50 +0000240 {
241 DXGI_FORMAT renderTargetFormat = RenderTargetFormats[formatIndex];
242
243 UINT formatSupport = 0;
244 HRESULT result = mDevice->CheckFormatSupport(renderTargetFormat, &formatSupport);
245
246 if (SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_RENDER_TARGET))
247 {
248 DXGI_FORMAT depthStencilFormat = DepthStencilFormats[depthStencilIndex];
249
250 UINT formatSupport = 0;
251 HRESULT result = mDevice->CheckFormatSupport(depthStencilFormat, &formatSupport);
252
253 if (SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_DEPTH_STENCIL))
254 {
255 ConfigDesc newConfig;
256 newConfig.renderTargetFormat = d3d11_gl::ConvertBackBufferFormat(renderTargetFormat);
257 newConfig.depthStencilFormat = d3d11_gl::ConvertDepthStencilFormat(depthStencilFormat);
258 newConfig.multiSample = 0; // FIXME: enumerate multi-sampling
259 newConfig.fastConfig = true; // Assume all DX11 format conversions to be fast
260
261 (*configDescList)[numConfigs++] = newConfig;
262 }
263 }
264 }
265 }
266
267 return numConfigs;
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000268}
269
270void Renderer11::deleteConfigs(ConfigDesc *configDescList)
271{
272 delete [] (configDescList);
273}
274
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000275void Renderer11::sync(bool block)
276{
277 // TODO
278 UNIMPLEMENTED();
279}
280
daniel@transgaming.comb9bb2792012-11-28 19:36:49 +0000281SwapChain *Renderer11::createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat)
282{
daniel@transgaming.coma60160b2012-11-28 19:41:15 +0000283 return new rx::SwapChain11(this, window, shareHandle, backBufferFormat, depthBufferFormat);
daniel@transgaming.comb9bb2792012-11-28 19:36:49 +0000284}
285
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000286void Renderer11::setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &samplerState)
287{
288 // TODO
289 UNIMPLEMENTED();
290}
291
292void Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *texture)
293{
294 // TODO
295 UNIMPLEMENTED();
296}
297
daniel@transgaming.com237bc7e2012-11-28 21:01:06 +0000298void Renderer11::setRasterizerState(const gl::RasterizerState &rasterState)
daniel@transgaming.com493d4f82012-11-28 19:35:45 +0000299{
daniel@transgaming.com237bc7e2012-11-28 21:01:06 +0000300 if (mForceSetRasterState || memcmp(&rasterState, &mCurRasterState, sizeof(gl::RasterizerState)) != 0)
daniel@transgaming.comdcf1e672012-11-28 19:38:19 +0000301 {
daniel@transgaming.com237bc7e2012-11-28 21:01:06 +0000302 ID3D11RasterizerState *dxRasterState = mStateCache.getRasterizerState(rasterState, mCurDepthSize);
daniel@transgaming.comdcf1e672012-11-28 19:38:19 +0000303 if (!dxRasterState)
304 {
305 ERR("NULL blend state returned by RenderStateCache::getRasterizerState, setting the "
306 "rasterizer state.");
307 }
308
309 mDeviceContext->RSSetState(dxRasterState);
310
311 if (dxRasterState)
312 {
313 dxRasterState->Release();
314 }
315 mCurRasterState = rasterState;
daniel@transgaming.comdcf1e672012-11-28 19:38:19 +0000316 }
317
318 mForceSetRasterState = false;
daniel@transgaming.com493d4f82012-11-28 19:35:45 +0000319}
320
321void Renderer11::setBlendState(const gl::BlendState &blendState, const gl::Color &blendColor,
322 unsigned int sampleMask)
323{
daniel@transgaming.comf8ba1092012-11-28 19:37:53 +0000324 if (mForceSetBlendState ||
325 memcmp(&blendState, &mCurBlendState, sizeof(gl::BlendState)) != 0 ||
326 memcmp(&blendColor, &mCurBlendColor, sizeof(gl::Color)) != 0 ||
327 sampleMask != mCurSampleMask)
328 {
329 ID3D11BlendState *dxBlendState = mStateCache.getBlendState(blendState);
330 if (!dxBlendState)
331 {
332 ERR("NULL blend state returned by RenderStateCache::getBlendState, setting the default "
333 "blend state.");
334 }
335
336 const float blendColors[] = { blendColor.red, blendColor.green, blendColor.blue, blendColor.alpha };
337 mDeviceContext->OMSetBlendState(dxBlendState, blendColors, sampleMask);
338
339 if (dxBlendState)
340 {
341 dxBlendState->Release();
342 }
343 mCurBlendState = blendState;
344 mCurBlendColor = blendColor;
345 mCurSampleMask = sampleMask;
346 }
347
348 mForceSetBlendState = false;
daniel@transgaming.com493d4f82012-11-28 19:35:45 +0000349}
350
daniel@transgaming.com08c331d2012-11-28 19:38:39 +0000351void Renderer11::setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef,
daniel@transgaming.com3a0ef482012-11-28 21:01:20 +0000352 int stencilBackRef, bool frontFaceCCW)
daniel@transgaming.com493d4f82012-11-28 19:35:45 +0000353{
daniel@transgaming.com5503fd02012-11-28 19:38:57 +0000354 if (mForceSetDepthStencilState ||
355 memcmp(&depthStencilState, &mCurDepthStencilState, sizeof(gl::DepthStencilState)) != 0 ||
356 stencilRef != mCurStencilRef || stencilBackRef != mCurStencilBackRef)
357 {
358 if (depthStencilState.stencilWritemask != depthStencilState.stencilBackWritemask ||
359 stencilRef != stencilBackRef ||
360 depthStencilState.stencilMask != depthStencilState.stencilBackMask)
361 {
362 ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are "
363 "invalid under WebGL.");
364 return error(GL_INVALID_OPERATION);
365 }
366
367 ID3D11DepthStencilState *dxDepthStencilState = mStateCache.getDepthStencilState(depthStencilState);
368 if (!dxDepthStencilState)
369 {
370 ERR("NULL depth stencil state returned by RenderStateCache::getDepthStencilState, "
371 "setting the default depth stencil state.");
372 }
373
374 mDeviceContext->OMSetDepthStencilState(dxDepthStencilState, static_cast<UINT>(stencilRef));
375
376 if (dxDepthStencilState)
377 {
378 dxDepthStencilState->Release();
379 }
380 mCurDepthStencilState = depthStencilState;
381 mCurStencilRef = stencilRef;
382 mCurStencilBackRef = stencilBackRef;
383 }
384
385 mForceSetDepthStencilState = false;
daniel@transgaming.com493d4f82012-11-28 19:35:45 +0000386}
387
daniel@transgaming.com04f1b332012-11-28 21:00:40 +0000388void Renderer11::setScissorRectangle(const gl::Rectangle &scissor)
daniel@transgaming.com493d4f82012-11-28 19:35:45 +0000389{
daniel@transgaming.com04f1b332012-11-28 21:00:40 +0000390 if (mForceSetScissor || memcmp(&scissor, &mCurScissor, sizeof(gl::Rectangle)) != 0)
daniel@transgaming.comdcf1e672012-11-28 19:38:19 +0000391 {
392 D3D11_RECT rect;
daniel@transgaming.com04f1b332012-11-28 21:00:40 +0000393 rect.left = gl::clamp(scissor.x, 0, static_cast<int>(mRenderTargetDesc.width));
394 rect.top = gl::clamp(scissor.y, 0, static_cast<int>(mRenderTargetDesc.height));
395 rect.right = gl::clamp(scissor.x + scissor.width, 0, static_cast<int>(mRenderTargetDesc.width));
396 rect.bottom = gl::clamp(scissor.y + scissor.height, 0, static_cast<int>(mRenderTargetDesc.height));
daniel@transgaming.comdcf1e672012-11-28 19:38:19 +0000397
398 mDeviceContext->RSSetScissorRects(1, &rect);
399
400 mCurScissor = scissor;
daniel@transgaming.comdcf1e672012-11-28 19:38:19 +0000401 }
402
403 mForceSetScissor = false;
daniel@transgaming.com493d4f82012-11-28 19:35:45 +0000404}
405
daniel@transgaming.com4c4ce232012-11-28 21:01:40 +0000406bool Renderer11::setViewport(const gl::Rectangle &viewport, float zNear, float zFar, bool ignoreViewport,
daniel@transgaming.com83e80ee2012-11-28 19:40:53 +0000407 gl::ProgramBinary *currentProgram, bool forceSetUniforms)
408{
daniel@transgaming.com4c4ce232012-11-28 21:01:40 +0000409 gl::Rectangle actualViewport = viewport;
410 float actualZNear = gl::clamp01(zNear);
411 float actualZFar = gl::clamp01(zFar);
412 if (ignoreViewport)
413 {
414 actualViewport.x = 0;
415 actualViewport.y = 0;
416 actualViewport.width = mRenderTargetDesc.width;
417 actualViewport.height = mRenderTargetDesc.height;
418 actualZNear = 0.0f;
419 actualZFar = 1.0f;
420 }
daniel@transgaming.com53670042012-11-28 20:55:51 +0000421
422 D3D11_VIEWPORT dxViewport;
daniel@transgaming.com4c4ce232012-11-28 21:01:40 +0000423 dxViewport.TopLeftX = gl::clamp(actualViewport.x, 0, static_cast<int>(mRenderTargetDesc.width));
424 dxViewport.TopLeftY = gl::clamp(actualViewport.y, 0, static_cast<int>(mRenderTargetDesc.height));
425 dxViewport.Width = gl::clamp(actualViewport.width, 0, static_cast<int>(mRenderTargetDesc.width) - static_cast<int>(dxViewport.TopLeftX));
426 dxViewport.Height = gl::clamp(actualViewport.height, 0, static_cast<int>(mRenderTargetDesc.height) - static_cast<int>(dxViewport.TopLeftY));
427 dxViewport.MinDepth = actualZNear;
428 dxViewport.MaxDepth = actualZFar;
daniel@transgaming.com53670042012-11-28 20:55:51 +0000429
430 if (dxViewport.Width <= 0 || dxViewport.Height <= 0)
431 {
432 return false; // Nothing to render
433 }
434
daniel@transgaming.com4c4ce232012-11-28 21:01:40 +0000435 bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 ||
436 actualZNear != mCurNear || actualZFar != mCurFar;
437
daniel@transgaming.com53670042012-11-28 20:55:51 +0000438 if (viewportChanged)
439 {
440 mDeviceContext->RSSetViewports(1, &dxViewport);
441
daniel@transgaming.com4c4ce232012-11-28 21:01:40 +0000442 mCurViewport = actualViewport;
443 mCurNear = actualZNear;
444 mCurFar = actualZFar;
daniel@transgaming.com53670042012-11-28 20:55:51 +0000445 }
446
447 if (currentProgram && (viewportChanged || forceSetUniforms))
448 {
449 GLint halfPixelSize = currentProgram->getDxHalfPixelSizeLocation();
450 GLfloat xy[2] = { 0.0f, 0.0f };
451 currentProgram->setUniform2fv(halfPixelSize, 1, xy);
452
453 // These values are used for computing gl_FragCoord in Program::linkVaryings().
454 GLint coord = currentProgram->getDxCoordLocation();
daniel@transgaming.com4c4ce232012-11-28 21:01:40 +0000455 GLfloat whxy[4] = { actualViewport.width * 0.5f,
456 actualViewport.height * 0.5f,
457 actualViewport.x + (actualViewport.width * 0.5f),
458 actualViewport.y + (actualViewport.height * 0.5f) };
daniel@transgaming.com53670042012-11-28 20:55:51 +0000459 currentProgram->setUniform4fv(coord, 1, whxy);
460
461 GLint depth = currentProgram->getDxDepthLocation();
daniel@transgaming.com4c4ce232012-11-28 21:01:40 +0000462 GLfloat dz[2] = { (actualZFar - actualZNear) * 0.5f, (actualZNear + actualZFar) * 0.5f };
daniel@transgaming.com53670042012-11-28 20:55:51 +0000463 currentProgram->setUniform2fv(depth, 1, dz);
464
465 GLint depthRange = currentProgram->getDxDepthRangeLocation();
daniel@transgaming.com4c4ce232012-11-28 21:01:40 +0000466 GLfloat nearFarDiff[3] = { actualZNear, actualZFar, actualZFar - actualZNear };
daniel@transgaming.com53670042012-11-28 20:55:51 +0000467 currentProgram->setUniform3fv(depthRange, 1, nearFarDiff);
468 }
469
470 mForceSetViewport = false;
daniel@transgaming.com83e80ee2012-11-28 19:40:53 +0000471 return true;
472}
473
daniel@transgaming.com91207b72012-11-28 20:56:43 +0000474bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count)
475{
daniel@transgaming.com0b03b062012-11-28 21:03:49 +0000476 mPrimitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
daniel@transgaming.com91207b72012-11-28 20:56:43 +0000477
daniel@transgaming.com0b03b062012-11-28 21:03:49 +0000478 switch (mode)
479 {
480 case GL_POINTS: mPrimitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST; break;
481 case GL_LINES: mPrimitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINELIST; break;
482 case GL_LINE_LOOP: UNIMPLEMENTED(); /* TODO */ break;
483 case GL_LINE_STRIP: mPrimitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; break;
484 case GL_TRIANGLES: mPrimitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; break;
485 case GL_TRIANGLE_STRIP: mPrimitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; break;
486 case GL_TRIANGLE_FAN: UNIMPLEMENTED(); /* TODO */ break;
487 default:
488 return error(GL_INVALID_ENUM, false);
489 }
490
491 mVertexCount = count;
492
493 return count > 0;
daniel@transgaming.com91207b72012-11-28 20:56:43 +0000494}
495
496bool Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer)
daniel@transgaming.com493d4f82012-11-28 19:35:45 +0000497{
daniel@transgaming.com80fc3322012-11-28 21:02:13 +0000498 // Get the color render buffer and serial
499 gl::Renderbuffer *renderbufferObject = NULL;
500 unsigned int renderTargetSerial = 0;
501 if (framebuffer->getColorbufferType() != GL_NONE)
502 {
503 renderbufferObject = framebuffer->getColorbuffer();
daniel@transgaming.comdcf1e672012-11-28 19:38:19 +0000504
daniel@transgaming.com80fc3322012-11-28 21:02:13 +0000505 if (!renderbufferObject)
506 {
507 ERR("render target pointer unexpectedly null.");
daniel@transgaming.come9c71b42012-11-28 21:02:23 +0000508 return false;
daniel@transgaming.com80fc3322012-11-28 21:02:13 +0000509 }
510
511 renderTargetSerial = renderbufferObject->getSerial();
512 }
513
514 // Get the depth stencil render buffer and serials
515 gl::Renderbuffer *depthStencil = NULL;
516 unsigned int depthbufferSerial = 0;
517 unsigned int stencilbufferSerial = 0;
518 if (framebuffer->getDepthbufferType() != GL_NONE)
519 {
520 depthStencil = framebuffer->getDepthbuffer();
521 if (!depthStencil)
522 {
523 ERR("Depth stencil pointer unexpectedly null.");
524 return false;
525 }
526
527 depthbufferSerial = depthStencil->getSerial();
528 }
529 else if (framebuffer->getStencilbufferType() != GL_NONE)
530 {
531 depthStencil = framebuffer->getStencilbuffer();
532 if (!depthStencil)
533 {
534 ERR("Depth stencil pointer unexpectedly null.");
535 return false;
536 }
537
538 stencilbufferSerial = depthStencil->getSerial();
539 }
540
541 // Extract the render target dimensions and view
542 unsigned int renderTargetWidth = 0;
543 unsigned int renderTargetHeight = 0;
544 GLenum renderTargetFormat = 0;
545 ID3D11RenderTargetView* framebufferRTV = NULL;
546 if (renderbufferObject)
547 {
548 RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(renderbufferObject->getRenderTarget());
549 if (!renderTarget)
550 {
551 ERR("render target pointer unexpectedly null.");
552 return false;
553 }
554
555 framebufferRTV = renderTarget->getRenderTargetView();
556 if (!framebufferRTV)
557 {
558 ERR("render target view pointer unexpectedly null.");
559 return false;
560 }
561
562 renderTargetWidth = renderbufferObject->getWidth();
563 renderTargetHeight = renderbufferObject->getHeight();
564 renderTargetFormat = renderbufferObject->getActualFormat();
565 }
566
567 // Extract the depth stencil sizes and view
568 unsigned int depthSize = 0;
569 unsigned int stencilSize = 0;
570 ID3D11DepthStencilView* framebufferDSV = NULL;
571 if (depthStencil)
572 {
573 RenderTarget11 *depthStencilRenderTarget = RenderTarget11::makeRenderTarget11(depthStencil->getDepthStencil());
574 if (!depthStencilRenderTarget)
575 {
576 ERR("render target pointer unexpectedly null.");
577 if (framebufferRTV)
578 {
579 framebufferRTV->Release();
580 }
581 return false;
582 }
583
584 framebufferDSV = depthStencilRenderTarget->getDepthStencilView();
585 if (!framebufferDSV)
586 {
587 ERR("depth stencil view pointer unexpectedly null.");
588 if (framebufferRTV)
589 {
590 framebufferRTV->Release();
591 }
592 return false;
593 }
594
595 // If there is no render buffer, the width, height and format values come from
596 // the depth stencil
597 if (!renderbufferObject)
598 {
599 renderTargetWidth = depthStencil->getWidth();
600 renderTargetHeight = depthStencil->getHeight();
601 renderTargetFormat = depthStencil->getActualFormat();
602 }
603
604 depthSize = depthStencil->getDepthSize();
605 stencilSize = depthStencil->getStencilSize();
606 }
607
608 // Apply the render target and depth stencil
609 if (!mRenderTargetDescInitialized || !mDepthStencilInitialized ||
610 renderTargetSerial != mAppliedRenderTargetSerial ||
611 depthbufferSerial != mAppliedDepthbufferSerial ||
612 stencilbufferSerial != mAppliedStencilbufferSerial)
613 {
614 mDeviceContext->OMSetRenderTargets(1, &framebufferRTV, framebufferDSV);
615
616 mRenderTargetDesc.width = renderTargetWidth;
617 mRenderTargetDesc.height = renderTargetHeight;
618 mRenderTargetDesc.format = renderTargetFormat;
619 mForceSetViewport = true; // TODO: It may not be required to clamp the viewport in D3D11
620 mForceSetScissor = true; // TODO: It may not be required to clamp the scissor in D3D11
621
622 if (!mDepthStencilInitialized || depthSize != mCurDepthSize)
623 {
624 mCurDepthSize = depthSize;
625 mForceSetRasterState = true;
626 }
627
628 mCurStencilSize = stencilSize;
629
630 mAppliedRenderTargetSerial = renderTargetSerial;
631 mAppliedDepthbufferSerial = depthbufferSerial;
632 mAppliedStencilbufferSerial = stencilbufferSerial;
633 mRenderTargetDescInitialized = true;
634 mDepthStencilInitialized = true;
635 }
636
637 if (framebufferRTV)
638 {
639 framebufferRTV->Release();
640 }
641 if (framebufferDSV)
642 {
643 framebufferDSV->Release();
644 }
daniel@transgaming.comae39ee22012-11-28 19:42:02 +0000645
646 return true;
daniel@transgaming.com493d4f82012-11-28 19:35:45 +0000647}
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000648
daniel@transgaming.com91207b72012-11-28 20:56:43 +0000649GLenum Renderer11::applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances)
daniel@transgaming.comdef9f0f2012-11-28 20:53:20 +0000650{
daniel@transgaming.comda495a12012-11-28 21:03:56 +0000651 // TODO: Build the input layout from the (translated) attribute information
652 D3D11_INPUT_ELEMENT_DESC inputElementDescriptions[1] =
653 {
654 {"TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}
655 };
656
657 ID3D11InputLayout *inputLayout = NULL;
658 mDevice->CreateInputLayout(inputElementDescriptions, 1, NULL /*FIXME: vertex shader blob */, 0 /* FIXME: vertex shader size */, &inputLayout);
659
660 mDeviceContext->IASetInputLayout(inputLayout);
661 inputLayout->Release(); // TODO: Build a cache of input layouts
662
daniel@transgaming.comdef9f0f2012-11-28 20:53:20 +0000663 // TODO
664 UNIMPLEMENTED();
665
666 return GL_OUT_OF_MEMORY;
667}
668
daniel@transgaming.com91207b72012-11-28 20:56:43 +0000669GLenum Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, gl::TranslatedIndexData *indexInfo)
670{
671 // TODO
672 UNIMPLEMENTED();
673
674 return GL_OUT_OF_MEMORY;
675}
676
677void Renderer11::drawArrays(GLenum mode, GLsizei count, GLsizei instances)
678{
679 // TODO
680 UNIMPLEMENTED();
681}
682
daniel@transgaming.com97400dd2012-11-28 20:57:00 +0000683void 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 +0000684{
685 // TODO
686 UNIMPLEMENTED();
687}
688
daniel@transgaming.com5fbf1772012-11-28 20:54:43 +0000689void Renderer11::applyShaders(gl::ProgramBinary *programBinary)
690{
691 // TODO
692 UNIMPLEMENTED();
693}
694
daniel@transgaming.com084a2572012-11-28 20:55:17 +0000695void Renderer11::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer)
daniel@transgaming.comd084c622012-11-28 19:36:05 +0000696{
daniel@transgaming.com54e67542012-11-28 21:02:31 +0000697 if (clearParams.mask & GL_COLOR_BUFFER_BIT)
698 {
699 gl::Renderbuffer *renderbufferObject = frameBuffer->getColorbuffer();
700 if (renderbufferObject)
701 {
702 RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(renderbufferObject->getRenderTarget());
703 if (!renderTarget)
704 {
705 ERR("render target pointer unexpectedly null.");
706 return;
707 }
708
709 ID3D11RenderTargetView *framebufferRTV = renderTarget->getRenderTargetView();
710 if (!framebufferRTV)
711 {
712 ERR("render target view pointer unexpectedly null.");
713 return;
714 }
715
716 if (mCurScissor.x > 0 || mCurScissor.y > 0 ||
717 mCurScissor.x + mCurScissor.width < renderTarget->getWidth() ||
718 mCurScissor.y + mCurScissor.height < renderTarget->getHeight())
719 {
720 // TODO: clearing of subregion of render target
721 UNIMPLEMENTED();
722 }
723
724 bool alphaUnmasked = (gl::GetAlphaSize(mRenderTargetDesc.format) == 0) || clearParams.colorMaskAlpha;
725 const bool needMaskedColorClear = (clearParams.mask & GL_COLOR_BUFFER_BIT) &&
726 !(clearParams.colorMaskRed && clearParams.colorMaskGreen &&
727 clearParams.colorMaskBlue && alphaUnmasked);
728
729 if (needMaskedColorClear)
730 {
731 // TODO: masked color clearing
732 UNIMPLEMENTED();
733 }
734 else
735 {
736 const float clearValues[4] = { clearParams.colorClearValue.red,
737 clearParams.colorClearValue.green,
738 clearParams.colorClearValue.blue,
739 clearParams.colorClearValue.alpha };
740 mDeviceContext->ClearRenderTargetView(framebufferRTV, clearValues);
741 }
742
743 framebufferRTV->Release();
744 }
745 }
746 if (clearParams.mask & GL_DEPTH_BUFFER_BIT || clearParams.mask & GL_STENCIL_BUFFER_BIT)
747 {
748 gl::Renderbuffer *renderbufferObject = frameBuffer->getDepthOrStencilbuffer();
749 if (renderbufferObject)
750 {
751 RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(renderbufferObject->getRenderTarget());
752 if (!renderTarget)
753 {
754 ERR("render target pointer unexpectedly null.");
755 return;
756 }
757
758 ID3D11DepthStencilView *framebufferDSV = renderTarget->getDepthStencilView();
759 if (!framebufferDSV)
760 {
761 ERR("depth stencil view pointer unexpectedly null.");
762 return;
763 }
764
765 if (mCurScissor.x > 0 || mCurScissor.y > 0 ||
766 mCurScissor.x + mCurScissor.width < renderTarget->getWidth() ||
767 mCurScissor.y + mCurScissor.height < renderTarget->getHeight())
768 {
769 // TODO: clearing of subregion of depth stencil view
770 UNIMPLEMENTED();
771 }
772
773 unsigned int stencilUnmasked = 0x0;
774 if ((clearParams.mask & GL_STENCIL_BUFFER_BIT) && frameBuffer->hasStencil())
775 {
776 unsigned int stencilSize = gl::GetStencilSize(frameBuffer->getStencilbuffer()->getActualFormat());
777 stencilUnmasked = (0x1 << stencilSize) - 1;
778 }
779
780 const bool needMaskedStencilClear = (clearParams.mask & GL_STENCIL_BUFFER_BIT) &&
781 (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked;
782
783 if (needMaskedStencilClear)
784 {
785 // TODO: masked clearing of depth stencil
786 UNIMPLEMENTED();
787 }
788 else
789 {
790 UINT clearFlags = 0;
791 if (clearParams.mask & GL_DEPTH_BUFFER_BIT)
792 {
793 clearFlags |= D3D11_CLEAR_DEPTH;
794 }
795 if (clearParams.mask & GL_STENCIL_BUFFER_BIT)
796 {
797 clearFlags |= D3D11_CLEAR_STENCIL;
798 }
799
800 float depthClear = clearParams.depthClearValue;
801 UINT8 stencilClear = clearParams.stencilClearValue & 0x000000FF;
802
803 mDeviceContext->ClearDepthStencilView(framebufferDSV, clearFlags, depthClear, stencilClear);
804 }
805
806 framebufferDSV->Release();
807 }
808 }
daniel@transgaming.comd084c622012-11-28 19:36:05 +0000809}
810
daniel@transgaming.comc43a6052012-11-28 19:41:51 +0000811void Renderer11::markAllStateDirty()
812{
daniel@transgaming.com7b6b83e2012-11-28 21:00:30 +0000813 mDepthStencilInitialized = false;
814 mRenderTargetDescInitialized = false;
815
daniel@transgaming.comc43a6052012-11-28 19:41:51 +0000816 mForceSetBlendState = true;
817 mForceSetRasterState = true;
818 mForceSetDepthStencilState = true;
819 mForceSetScissor = true;
daniel@transgaming.com53670042012-11-28 20:55:51 +0000820 mForceSetViewport = true;
daniel@transgaming.comc43a6052012-11-28 19:41:51 +0000821}
822
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000823void Renderer11::releaseDeviceResources()
824{
825 // TODO
daniel@transgaming.comc1e26342012-11-28 19:31:16 +0000826 // UNIMPLEMENTED();
daniel@transgaming.comf8ba1092012-11-28 19:37:53 +0000827 mStateCache.clear();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000828}
829
830void Renderer11::markDeviceLost()
831{
832 mDeviceLost = true;
833}
834
835bool Renderer11::isDeviceLost()
836{
837 return mDeviceLost;
838}
839
840// set notify to true to broadcast a message to all contexts of the device loss
841bool Renderer11::testDeviceLost(bool notify)
842{
843 bool isLost = false;
844
845 // TODO
daniel@transgaming.comb9bb2792012-11-28 19:36:49 +0000846 //UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000847
848 if (isLost)
849 {
850 // ensure we note the device loss --
851 // we'll probably get this done again by markDeviceLost
852 // but best to remember it!
853 // Note that we don't want to clear the device loss status here
854 // -- this needs to be done by resetDevice
855 mDeviceLost = true;
856 if (notify)
857 {
858 mDisplay->notifyDeviceLost();
859 }
860 }
861
862 return isLost;
863}
864
865bool Renderer11::testDeviceResettable()
866{
867 HRESULT status = D3D_OK;
868
869 // TODO
870 UNIMPLEMENTED();
871
872 switch (status)
873 {
874 case D3DERR_DEVICENOTRESET:
875 case D3DERR_DEVICEHUNG:
876 return true;
877 default:
878 return false;
879 }
880}
881
882bool Renderer11::resetDevice()
883{
884 releaseDeviceResources();
885
886 // TODO
887 UNIMPLEMENTED();
888
889 // reset device defaults
890 initializeDevice();
891 mDeviceLost = false;
892
893 return true;
894}
895
896DWORD Renderer11::getAdapterVendor() const
897{
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000898 return mAdapterDescription.VendorId;
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000899}
900
901const char *Renderer11::getAdapterDescription() const
902{
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000903 return mDescription;
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000904}
905
906GUID Renderer11::getAdapterIdentifier() const
907{
908 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000909 // UNIMPLEMENTED();
910 GUID foo = {0};
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000911 return foo;
912}
913
914bool Renderer11::getDXT1TextureSupport()
915{
916 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000917 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000918 return false;
919}
920
921bool Renderer11::getDXT3TextureSupport()
922{
923 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000924 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000925 return false;
926}
927
928bool Renderer11::getDXT5TextureSupport()
929{
930 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000931 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000932 return false;
933}
934
935bool Renderer11::getDepthTextureSupport() const
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::getFloat32TextureSupport(bool *filtering, bool *renderable)
943{
944 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000945 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000946
947 *filtering = false;
948 *renderable = false;
949 return false;
950}
951
952bool Renderer11::getFloat16TextureSupport(bool *filtering, bool *renderable)
953{
954 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000955 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000956
957 *filtering = false;
958 *renderable = false;
959 return false;
960}
961
962bool Renderer11::getLuminanceTextureSupport()
963{
964 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000965 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000966 return false;
967}
968
969bool Renderer11::getLuminanceAlphaTextureSupport()
970{
971 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000972 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000973 return false;
974}
975
976bool Renderer11::getTextureFilterAnisotropySupport() const
977{
978 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000979 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000980 return false;
981}
982
983float Renderer11::getTextureMaxAnisotropy() const
984{
985 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000986 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000987 return 1.0f;
988}
989
990bool Renderer11::getEventQuerySupport()
991{
992 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000993 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000994 return false;
995}
996
997bool Renderer11::getVertexTextureSupport() const
998{
999 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +00001000 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001001 return false;
1002}
1003
1004bool Renderer11::getNonPower2TextureSupport() const
1005{
1006 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +00001007 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001008 return false;
1009}
1010
1011bool Renderer11::getOcclusionQuerySupport() const
1012{
1013 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +00001014 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001015 return false;
1016}
1017
1018bool Renderer11::getInstancingSupport() const
1019{
1020 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +00001021 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001022 return false;
1023}
1024
1025bool Renderer11::getShareHandleSupport() const
1026{
1027 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +00001028 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001029
1030 // PIX doesn't seem to support using share handles, so disable them.
1031 return false && !gl::perfActive();
1032}
1033
daniel@transgaming.com9549bea2012-11-28 20:57:23 +00001034int Renderer11::getMajorShaderModel() const
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001035{
daniel@transgaming.com9549bea2012-11-28 20:57:23 +00001036 switch (mFeatureLevel)
1037 {
1038 case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MAJOR_VERSION; // 5
1039 case D3D_FEATURE_LEVEL_10_1:
1040 case D3D_FEATURE_LEVEL_10_0: return D3D10_SHADER_MAJOR_VERSION; // 4
1041 default: UNREACHABLE(); return 0;
1042 }
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001043}
1044
1045float Renderer11::getMaxPointSize() const
1046{
1047 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +00001048 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001049 return 1.0f;
1050}
1051
1052int Renderer11::getMaxTextureWidth() const
1053{
daniel@transgaming.com25072f62012-11-28 19:31:32 +00001054 switch (mFeatureLevel)
1055 {
1056 case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384
1057 case D3D_FEATURE_LEVEL_10_1:
1058 case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192
1059 default: UNREACHABLE(); return 0;
1060 }
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001061}
1062
1063int Renderer11::getMaxTextureHeight() const
1064{
daniel@transgaming.com25072f62012-11-28 19:31:32 +00001065 switch (mFeatureLevel)
1066 {
1067 case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384
1068 case D3D_FEATURE_LEVEL_10_1:
1069 case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192
1070 default: UNREACHABLE(); return 0;
1071 }
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001072}
1073
1074bool Renderer11::get32BitIndexSupport() const
1075{
daniel@transgaming.com25072f62012-11-28 19:31:32 +00001076 switch (mFeatureLevel)
1077 {
1078 case D3D_FEATURE_LEVEL_11_0:
1079 case D3D_FEATURE_LEVEL_10_1:
1080 case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP >= 32; // true
1081 default: UNREACHABLE(); return false;
1082 }
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001083}
1084
1085int Renderer11::getMinSwapInterval() const
1086{
daniel@transgaming.com8c7b1a92012-11-28 19:34:06 +00001087 return 0;
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001088}
1089
1090int Renderer11::getMaxSwapInterval() const
1091{
daniel@transgaming.com8c7b1a92012-11-28 19:34:06 +00001092 return 4;
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001093}
1094
1095int Renderer11::getMaxSupportedSamples() const
1096{
1097 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +00001098 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001099 return 1;
1100}
1101
daniel@transgaming.com31b13e12012-11-28 19:34:30 +00001102bool Renderer11::copyToRenderTarget(TextureStorage2D *dest, TextureStorage2D *source)
daniel@transgaming.comad6aee72012-11-28 19:33:42 +00001103{
1104 // TODO
1105 UNIMPLEMENTED();
1106 return false;
1107}
1108
daniel@transgaming.com31b13e12012-11-28 19:34:30 +00001109bool Renderer11::copyToRenderTarget(TextureStorageCubeMap *dest, TextureStorageCubeMap *source)
daniel@transgaming.comad6aee72012-11-28 19:33:42 +00001110{
1111 // TODO
1112 UNIMPLEMENTED();
1113 return false;
1114}
1115
daniel@transgaming.com38380882012-11-28 19:36:39 +00001116bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat,
1117 GLint xoffset, GLint yoffset, TextureStorage2D *storage, GLint level)
1118{
1119 // TODO
1120 UNIMPLEMENTED();
1121 return false;
1122}
1123
1124bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat,
1125 GLint xoffset, GLint yoffset, TextureStorageCubeMap *storage, GLenum target, GLint level)
1126{
1127 // TODO
1128 UNIMPLEMENTED();
1129 return false;
1130}
1131
daniel@transgaming.comf2423652012-11-28 20:53:50 +00001132RenderTarget *Renderer11::createRenderTarget(SwapChain *swapChain, bool depth)
1133{
daniel@transgaming.comb6b27bc2012-11-28 20:54:30 +00001134 SwapChain11 *swapChain11 = SwapChain11::makeSwapChain11(swapChain);
1135 RenderTarget11 *renderTarget = NULL;
1136 if (depth)
1137 {
1138 renderTarget = new RenderTarget11(this, swapChain11->getDepthStencil(), swapChain11->getWidth(), swapChain11->getHeight());
1139 }
1140 else
1141 {
1142 renderTarget = new RenderTarget11(this, swapChain11->getRenderTarget(), swapChain11->getWidth(), swapChain11->getHeight());
1143 }
1144 return renderTarget;
daniel@transgaming.comf2423652012-11-28 20:53:50 +00001145}
1146
1147RenderTarget *Renderer11::createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth)
1148{
1149 // TODO
1150 UNIMPLEMENTED();
1151 return NULL;
1152}
1153
daniel@transgaming.com55318902012-11-28 20:58:58 +00001154ShaderExecutable *Renderer11::loadExecutable(const DWORD *function, size_t length, GLenum type, void *data)
1155{
daniel@transgaming.coma2f9fbe2012-11-28 21:03:40 +00001156 ShaderExecutable11 *executable = NULL;
1157
1158 switch (type)
1159 {
1160 case GL_VERTEX_SHADER:
1161 {
1162 ID3D11VertexShader *vshader = NULL;
1163 HRESULT result = mDevice->CreateVertexShader(function, length, NULL, &vshader);
1164 ASSERT(SUCCEEDED(result));
1165
1166 if (vshader)
1167 {
1168 executable = new ShaderExecutable11(vshader);
1169 }
1170 }
1171 break;
1172 case GL_FRAGMENT_SHADER:
1173 {
1174 ID3D11PixelShader *pshader = NULL;
1175 HRESULT result = mDevice->CreatePixelShader(function, length, NULL, &pshader);
1176 ASSERT(SUCCEEDED(result));
1177
1178 if (pshader)
1179 {
1180 executable = new ShaderExecutable11(pshader);
1181 }
1182 }
1183 break;
1184 default:
1185 UNREACHABLE();
1186 break;
1187 }
1188
1189 return executable;
daniel@transgaming.com55318902012-11-28 20:58:58 +00001190}
1191
daniel@transgaming.coma9c71422012-11-28 20:58:45 +00001192ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, GLenum type)
1193{
daniel@transgaming.com071ee6a2012-11-28 21:03:21 +00001194 const char *profile = NULL;
1195
1196 switch (type)
1197 {
1198 case GL_VERTEX_SHADER:
1199 profile = "vs_4_0";
1200 break;
1201 case GL_FRAGMENT_SHADER:
1202 profile = "ps_4_0";
1203 break;
1204 default:
1205 UNREACHABLE();
1206 return NULL;
1207 }
1208
1209 ID3DBlob *binary = compileToBinary(infoLog, shaderHLSL, profile);
1210 if (!binary)
1211 return NULL;
1212
1213 ShaderExecutable *executable = loadExecutable((DWORD *)binary->GetBufferPointer(), binary->GetBufferSize(), type, NULL);
1214 binary->Release();
1215
1216 return executable;
1217}
1218
1219// Compiles the HLSL code of the attached shaders into executable binaries
1220ID3DBlob *Renderer11::compileToBinary(gl::InfoLog &infoLog, const char *hlsl, const char *profile)
1221{
1222 if (!hlsl)
1223 {
1224 return NULL;
1225 }
1226
1227 HRESULT result = S_OK;
1228 UINT flags = 0;
1229 std::string sourceText;
1230 if (gl::perfActive())
1231 {
1232 flags |= D3DCOMPILE_DEBUG;
1233#ifdef NDEBUG
1234 flags |= ANGLE_COMPILE_OPTIMIZATION_LEVEL;
1235#else
1236 flags |= D3DCOMPILE_SKIP_OPTIMIZATION;
1237#endif
1238
1239 std::string sourcePath = getTempPath();
1240 sourceText = std::string("#line 2 \"") + sourcePath + std::string("\"\n\n") + std::string(hlsl);
1241 writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size());
1242 }
1243 else
1244 {
1245 flags |= ANGLE_COMPILE_OPTIMIZATION_LEVEL;
1246 sourceText = hlsl;
1247 }
1248
1249 // Sometimes D3DCompile will fail with the default compilation flags for complicated shaders when it would otherwise pass with alternative options.
1250 // Try the default flags first and if compilation fails, try some alternatives.
1251 const static UINT extraFlags[] =
1252 {
1253 0,
1254 // D3DCOMPILE_AVOID_FLOW_CONTROL,
1255 // D3DCOMPILE_PREFER_FLOW_CONTROL
1256 };
1257
1258 const static char * const extraFlagNames[] =
1259 {
1260 "default",
1261 "avoid flow control",
1262 "prefer flow control"
1263 };
1264
1265 for (int i = 0; i < sizeof(extraFlags) / sizeof(UINT); ++i)
1266 {
1267 ID3DBlob *errorMessage = NULL;
1268 ID3DBlob *binary = NULL;
1269 result = mD3DCompileFunc(hlsl, strlen(hlsl), gl::g_fakepath, NULL, NULL,
1270 "main", profile, flags | extraFlags[i], 0, &binary, &errorMessage);
1271 if (errorMessage)
1272 {
1273 const char *message = (const char*)errorMessage->GetBufferPointer();
1274
1275 infoLog.appendSanitized(message);
1276 TRACE("\n%s", hlsl);
1277 TRACE("\n%s", message);
1278
1279 errorMessage->Release();
1280 errorMessage = NULL;
1281 }
1282
1283 if (SUCCEEDED(result))
1284 {
1285 return binary;
1286 }
1287 else
1288 {
1289 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
1290 {
1291 return error(GL_OUT_OF_MEMORY, (ID3DBlob*) NULL);
1292 }
1293
1294 infoLog.append("Warning: D3D shader compilation failed with ");
1295 infoLog.append(extraFlagNames[i]);
1296 infoLog.append(" flags.");
1297 if (i + 1 < sizeof(extraFlagNames) / sizeof(char*))
1298 {
1299 infoLog.append(" Retrying with ");
1300 infoLog.append(extraFlagNames[i + 1]);
1301 infoLog.append(".\n");
1302 }
1303 }
1304 }
1305
daniel@transgaming.coma9c71422012-11-28 20:58:45 +00001306 return NULL;
1307}
1308
daniel@transgaming.com6c872172012-11-28 19:39:33 +00001309bool Renderer11::blitRect(gl::Framebuffer *readTarget, gl::Rectangle *readRect, gl::Framebuffer *drawTarget, gl::Rectangle *drawRect,
1310 bool blitRenderTarget, bool blitDepthStencil)
1311{
1312 // TODO
1313 UNIMPLEMENTED();
1314 return false;
1315}
1316
1317void Renderer11::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type,
1318 GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels)
1319{
1320 // TODO
1321 UNIMPLEMENTED();
1322 return;
1323}
1324
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001325}