blob: 9fc81ce998d8b1e92abceb089355db01ba6479de [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{
651 // TODO
652 UNIMPLEMENTED();
653
654 return GL_OUT_OF_MEMORY;
655}
656
daniel@transgaming.com91207b72012-11-28 20:56:43 +0000657GLenum Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, gl::TranslatedIndexData *indexInfo)
658{
659 // TODO
660 UNIMPLEMENTED();
661
662 return GL_OUT_OF_MEMORY;
663}
664
665void Renderer11::drawArrays(GLenum mode, GLsizei count, GLsizei instances)
666{
667 // TODO
668 UNIMPLEMENTED();
669}
670
daniel@transgaming.com97400dd2012-11-28 20:57:00 +0000671void 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 +0000672{
673 // TODO
674 UNIMPLEMENTED();
675}
676
daniel@transgaming.com5fbf1772012-11-28 20:54:43 +0000677void Renderer11::applyShaders(gl::ProgramBinary *programBinary)
678{
679 // TODO
680 UNIMPLEMENTED();
681}
682
daniel@transgaming.com084a2572012-11-28 20:55:17 +0000683void Renderer11::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer)
daniel@transgaming.comd084c622012-11-28 19:36:05 +0000684{
daniel@transgaming.com54e67542012-11-28 21:02:31 +0000685 if (clearParams.mask & GL_COLOR_BUFFER_BIT)
686 {
687 gl::Renderbuffer *renderbufferObject = frameBuffer->getColorbuffer();
688 if (renderbufferObject)
689 {
690 RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(renderbufferObject->getRenderTarget());
691 if (!renderTarget)
692 {
693 ERR("render target pointer unexpectedly null.");
694 return;
695 }
696
697 ID3D11RenderTargetView *framebufferRTV = renderTarget->getRenderTargetView();
698 if (!framebufferRTV)
699 {
700 ERR("render target view pointer unexpectedly null.");
701 return;
702 }
703
704 if (mCurScissor.x > 0 || mCurScissor.y > 0 ||
705 mCurScissor.x + mCurScissor.width < renderTarget->getWidth() ||
706 mCurScissor.y + mCurScissor.height < renderTarget->getHeight())
707 {
708 // TODO: clearing of subregion of render target
709 UNIMPLEMENTED();
710 }
711
712 bool alphaUnmasked = (gl::GetAlphaSize(mRenderTargetDesc.format) == 0) || clearParams.colorMaskAlpha;
713 const bool needMaskedColorClear = (clearParams.mask & GL_COLOR_BUFFER_BIT) &&
714 !(clearParams.colorMaskRed && clearParams.colorMaskGreen &&
715 clearParams.colorMaskBlue && alphaUnmasked);
716
717 if (needMaskedColorClear)
718 {
719 // TODO: masked color clearing
720 UNIMPLEMENTED();
721 }
722 else
723 {
724 const float clearValues[4] = { clearParams.colorClearValue.red,
725 clearParams.colorClearValue.green,
726 clearParams.colorClearValue.blue,
727 clearParams.colorClearValue.alpha };
728 mDeviceContext->ClearRenderTargetView(framebufferRTV, clearValues);
729 }
730
731 framebufferRTV->Release();
732 }
733 }
734 if (clearParams.mask & GL_DEPTH_BUFFER_BIT || clearParams.mask & GL_STENCIL_BUFFER_BIT)
735 {
736 gl::Renderbuffer *renderbufferObject = frameBuffer->getDepthOrStencilbuffer();
737 if (renderbufferObject)
738 {
739 RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(renderbufferObject->getRenderTarget());
740 if (!renderTarget)
741 {
742 ERR("render target pointer unexpectedly null.");
743 return;
744 }
745
746 ID3D11DepthStencilView *framebufferDSV = renderTarget->getDepthStencilView();
747 if (!framebufferDSV)
748 {
749 ERR("depth stencil view pointer unexpectedly null.");
750 return;
751 }
752
753 if (mCurScissor.x > 0 || mCurScissor.y > 0 ||
754 mCurScissor.x + mCurScissor.width < renderTarget->getWidth() ||
755 mCurScissor.y + mCurScissor.height < renderTarget->getHeight())
756 {
757 // TODO: clearing of subregion of depth stencil view
758 UNIMPLEMENTED();
759 }
760
761 unsigned int stencilUnmasked = 0x0;
762 if ((clearParams.mask & GL_STENCIL_BUFFER_BIT) && frameBuffer->hasStencil())
763 {
764 unsigned int stencilSize = gl::GetStencilSize(frameBuffer->getStencilbuffer()->getActualFormat());
765 stencilUnmasked = (0x1 << stencilSize) - 1;
766 }
767
768 const bool needMaskedStencilClear = (clearParams.mask & GL_STENCIL_BUFFER_BIT) &&
769 (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked;
770
771 if (needMaskedStencilClear)
772 {
773 // TODO: masked clearing of depth stencil
774 UNIMPLEMENTED();
775 }
776 else
777 {
778 UINT clearFlags = 0;
779 if (clearParams.mask & GL_DEPTH_BUFFER_BIT)
780 {
781 clearFlags |= D3D11_CLEAR_DEPTH;
782 }
783 if (clearParams.mask & GL_STENCIL_BUFFER_BIT)
784 {
785 clearFlags |= D3D11_CLEAR_STENCIL;
786 }
787
788 float depthClear = clearParams.depthClearValue;
789 UINT8 stencilClear = clearParams.stencilClearValue & 0x000000FF;
790
791 mDeviceContext->ClearDepthStencilView(framebufferDSV, clearFlags, depthClear, stencilClear);
792 }
793
794 framebufferDSV->Release();
795 }
796 }
daniel@transgaming.comd084c622012-11-28 19:36:05 +0000797}
798
daniel@transgaming.comc43a6052012-11-28 19:41:51 +0000799void Renderer11::markAllStateDirty()
800{
daniel@transgaming.com7b6b83e2012-11-28 21:00:30 +0000801 mDepthStencilInitialized = false;
802 mRenderTargetDescInitialized = false;
803
daniel@transgaming.comc43a6052012-11-28 19:41:51 +0000804 mForceSetBlendState = true;
805 mForceSetRasterState = true;
806 mForceSetDepthStencilState = true;
807 mForceSetScissor = true;
daniel@transgaming.com53670042012-11-28 20:55:51 +0000808 mForceSetViewport = true;
daniel@transgaming.comc43a6052012-11-28 19:41:51 +0000809}
810
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000811void Renderer11::releaseDeviceResources()
812{
813 // TODO
daniel@transgaming.comc1e26342012-11-28 19:31:16 +0000814 // UNIMPLEMENTED();
daniel@transgaming.comf8ba1092012-11-28 19:37:53 +0000815 mStateCache.clear();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000816}
817
818void Renderer11::markDeviceLost()
819{
820 mDeviceLost = true;
821}
822
823bool Renderer11::isDeviceLost()
824{
825 return mDeviceLost;
826}
827
828// set notify to true to broadcast a message to all contexts of the device loss
829bool Renderer11::testDeviceLost(bool notify)
830{
831 bool isLost = false;
832
833 // TODO
daniel@transgaming.comb9bb2792012-11-28 19:36:49 +0000834 //UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000835
836 if (isLost)
837 {
838 // ensure we note the device loss --
839 // we'll probably get this done again by markDeviceLost
840 // but best to remember it!
841 // Note that we don't want to clear the device loss status here
842 // -- this needs to be done by resetDevice
843 mDeviceLost = true;
844 if (notify)
845 {
846 mDisplay->notifyDeviceLost();
847 }
848 }
849
850 return isLost;
851}
852
853bool Renderer11::testDeviceResettable()
854{
855 HRESULT status = D3D_OK;
856
857 // TODO
858 UNIMPLEMENTED();
859
860 switch (status)
861 {
862 case D3DERR_DEVICENOTRESET:
863 case D3DERR_DEVICEHUNG:
864 return true;
865 default:
866 return false;
867 }
868}
869
870bool Renderer11::resetDevice()
871{
872 releaseDeviceResources();
873
874 // TODO
875 UNIMPLEMENTED();
876
877 // reset device defaults
878 initializeDevice();
879 mDeviceLost = false;
880
881 return true;
882}
883
884DWORD Renderer11::getAdapterVendor() const
885{
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000886 return mAdapterDescription.VendorId;
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000887}
888
889const char *Renderer11::getAdapterDescription() const
890{
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000891 return mDescription;
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000892}
893
894GUID Renderer11::getAdapterIdentifier() const
895{
896 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000897 // UNIMPLEMENTED();
898 GUID foo = {0};
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000899 return foo;
900}
901
902bool Renderer11::getDXT1TextureSupport()
903{
904 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000905 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000906 return false;
907}
908
909bool Renderer11::getDXT3TextureSupport()
910{
911 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000912 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000913 return false;
914}
915
916bool Renderer11::getDXT5TextureSupport()
917{
918 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000919 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000920 return false;
921}
922
923bool Renderer11::getDepthTextureSupport() const
924{
925 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000926 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000927 return false;
928}
929
930bool Renderer11::getFloat32TextureSupport(bool *filtering, bool *renderable)
931{
932 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000933 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000934
935 *filtering = false;
936 *renderable = false;
937 return false;
938}
939
940bool Renderer11::getFloat16TextureSupport(bool *filtering, bool *renderable)
941{
942 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000943 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000944
945 *filtering = false;
946 *renderable = false;
947 return false;
948}
949
950bool Renderer11::getLuminanceTextureSupport()
951{
952 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000953 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000954 return false;
955}
956
957bool Renderer11::getLuminanceAlphaTextureSupport()
958{
959 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000960 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000961 return false;
962}
963
964bool Renderer11::getTextureFilterAnisotropySupport() const
965{
966 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000967 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000968 return false;
969}
970
971float Renderer11::getTextureMaxAnisotropy() const
972{
973 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000974 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000975 return 1.0f;
976}
977
978bool Renderer11::getEventQuerySupport()
979{
980 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000981 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000982 return false;
983}
984
985bool Renderer11::getVertexTextureSupport() const
986{
987 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000988 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000989 return false;
990}
991
992bool Renderer11::getNonPower2TextureSupport() const
993{
994 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000995 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000996 return false;
997}
998
999bool Renderer11::getOcclusionQuerySupport() const
1000{
1001 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +00001002 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001003 return false;
1004}
1005
1006bool Renderer11::getInstancingSupport() const
1007{
1008 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +00001009 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001010 return false;
1011}
1012
1013bool Renderer11::getShareHandleSupport() const
1014{
1015 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +00001016 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001017
1018 // PIX doesn't seem to support using share handles, so disable them.
1019 return false && !gl::perfActive();
1020}
1021
daniel@transgaming.com9549bea2012-11-28 20:57:23 +00001022int Renderer11::getMajorShaderModel() const
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001023{
daniel@transgaming.com9549bea2012-11-28 20:57:23 +00001024 switch (mFeatureLevel)
1025 {
1026 case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MAJOR_VERSION; // 5
1027 case D3D_FEATURE_LEVEL_10_1:
1028 case D3D_FEATURE_LEVEL_10_0: return D3D10_SHADER_MAJOR_VERSION; // 4
1029 default: UNREACHABLE(); return 0;
1030 }
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001031}
1032
1033float Renderer11::getMaxPointSize() const
1034{
1035 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +00001036 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001037 return 1.0f;
1038}
1039
1040int Renderer11::getMaxTextureWidth() const
1041{
daniel@transgaming.com25072f62012-11-28 19:31:32 +00001042 switch (mFeatureLevel)
1043 {
1044 case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384
1045 case D3D_FEATURE_LEVEL_10_1:
1046 case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192
1047 default: UNREACHABLE(); return 0;
1048 }
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001049}
1050
1051int Renderer11::getMaxTextureHeight() const
1052{
daniel@transgaming.com25072f62012-11-28 19:31:32 +00001053 switch (mFeatureLevel)
1054 {
1055 case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384
1056 case D3D_FEATURE_LEVEL_10_1:
1057 case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192
1058 default: UNREACHABLE(); return 0;
1059 }
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001060}
1061
1062bool Renderer11::get32BitIndexSupport() const
1063{
daniel@transgaming.com25072f62012-11-28 19:31:32 +00001064 switch (mFeatureLevel)
1065 {
1066 case D3D_FEATURE_LEVEL_11_0:
1067 case D3D_FEATURE_LEVEL_10_1:
1068 case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP >= 32; // true
1069 default: UNREACHABLE(); return false;
1070 }
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001071}
1072
1073int Renderer11::getMinSwapInterval() const
1074{
daniel@transgaming.com8c7b1a92012-11-28 19:34:06 +00001075 return 0;
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001076}
1077
1078int Renderer11::getMaxSwapInterval() const
1079{
daniel@transgaming.com8c7b1a92012-11-28 19:34:06 +00001080 return 4;
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001081}
1082
1083int Renderer11::getMaxSupportedSamples() const
1084{
1085 // TODO
daniel@transgaming.com1f811f52012-11-28 20:57:39 +00001086 // UNIMPLEMENTED();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001087 return 1;
1088}
1089
daniel@transgaming.com31b13e12012-11-28 19:34:30 +00001090bool Renderer11::copyToRenderTarget(TextureStorage2D *dest, TextureStorage2D *source)
daniel@transgaming.comad6aee72012-11-28 19:33:42 +00001091{
1092 // TODO
1093 UNIMPLEMENTED();
1094 return false;
1095}
1096
daniel@transgaming.com31b13e12012-11-28 19:34:30 +00001097bool Renderer11::copyToRenderTarget(TextureStorageCubeMap *dest, TextureStorageCubeMap *source)
daniel@transgaming.comad6aee72012-11-28 19:33:42 +00001098{
1099 // TODO
1100 UNIMPLEMENTED();
1101 return false;
1102}
1103
daniel@transgaming.com38380882012-11-28 19:36:39 +00001104bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat,
1105 GLint xoffset, GLint yoffset, TextureStorage2D *storage, GLint level)
1106{
1107 // TODO
1108 UNIMPLEMENTED();
1109 return false;
1110}
1111
1112bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat,
1113 GLint xoffset, GLint yoffset, TextureStorageCubeMap *storage, GLenum target, GLint level)
1114{
1115 // TODO
1116 UNIMPLEMENTED();
1117 return false;
1118}
1119
daniel@transgaming.comf2423652012-11-28 20:53:50 +00001120RenderTarget *Renderer11::createRenderTarget(SwapChain *swapChain, bool depth)
1121{
daniel@transgaming.comb6b27bc2012-11-28 20:54:30 +00001122 SwapChain11 *swapChain11 = SwapChain11::makeSwapChain11(swapChain);
1123 RenderTarget11 *renderTarget = NULL;
1124 if (depth)
1125 {
1126 renderTarget = new RenderTarget11(this, swapChain11->getDepthStencil(), swapChain11->getWidth(), swapChain11->getHeight());
1127 }
1128 else
1129 {
1130 renderTarget = new RenderTarget11(this, swapChain11->getRenderTarget(), swapChain11->getWidth(), swapChain11->getHeight());
1131 }
1132 return renderTarget;
daniel@transgaming.comf2423652012-11-28 20:53:50 +00001133}
1134
1135RenderTarget *Renderer11::createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth)
1136{
1137 // TODO
1138 UNIMPLEMENTED();
1139 return NULL;
1140}
1141
daniel@transgaming.com55318902012-11-28 20:58:58 +00001142ShaderExecutable *Renderer11::loadExecutable(const DWORD *function, size_t length, GLenum type, void *data)
1143{
daniel@transgaming.coma2f9fbe2012-11-28 21:03:40 +00001144 ShaderExecutable11 *executable = NULL;
1145
1146 switch (type)
1147 {
1148 case GL_VERTEX_SHADER:
1149 {
1150 ID3D11VertexShader *vshader = NULL;
1151 HRESULT result = mDevice->CreateVertexShader(function, length, NULL, &vshader);
1152 ASSERT(SUCCEEDED(result));
1153
1154 if (vshader)
1155 {
1156 executable = new ShaderExecutable11(vshader);
1157 }
1158 }
1159 break;
1160 case GL_FRAGMENT_SHADER:
1161 {
1162 ID3D11PixelShader *pshader = NULL;
1163 HRESULT result = mDevice->CreatePixelShader(function, length, NULL, &pshader);
1164 ASSERT(SUCCEEDED(result));
1165
1166 if (pshader)
1167 {
1168 executable = new ShaderExecutable11(pshader);
1169 }
1170 }
1171 break;
1172 default:
1173 UNREACHABLE();
1174 break;
1175 }
1176
1177 return executable;
daniel@transgaming.com55318902012-11-28 20:58:58 +00001178}
1179
daniel@transgaming.coma9c71422012-11-28 20:58:45 +00001180ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, GLenum type)
1181{
daniel@transgaming.com071ee6a2012-11-28 21:03:21 +00001182 const char *profile = NULL;
1183
1184 switch (type)
1185 {
1186 case GL_VERTEX_SHADER:
1187 profile = "vs_4_0";
1188 break;
1189 case GL_FRAGMENT_SHADER:
1190 profile = "ps_4_0";
1191 break;
1192 default:
1193 UNREACHABLE();
1194 return NULL;
1195 }
1196
1197 ID3DBlob *binary = compileToBinary(infoLog, shaderHLSL, profile);
1198 if (!binary)
1199 return NULL;
1200
1201 ShaderExecutable *executable = loadExecutable((DWORD *)binary->GetBufferPointer(), binary->GetBufferSize(), type, NULL);
1202 binary->Release();
1203
1204 return executable;
1205}
1206
1207// Compiles the HLSL code of the attached shaders into executable binaries
1208ID3DBlob *Renderer11::compileToBinary(gl::InfoLog &infoLog, const char *hlsl, const char *profile)
1209{
1210 if (!hlsl)
1211 {
1212 return NULL;
1213 }
1214
1215 HRESULT result = S_OK;
1216 UINT flags = 0;
1217 std::string sourceText;
1218 if (gl::perfActive())
1219 {
1220 flags |= D3DCOMPILE_DEBUG;
1221#ifdef NDEBUG
1222 flags |= ANGLE_COMPILE_OPTIMIZATION_LEVEL;
1223#else
1224 flags |= D3DCOMPILE_SKIP_OPTIMIZATION;
1225#endif
1226
1227 std::string sourcePath = getTempPath();
1228 sourceText = std::string("#line 2 \"") + sourcePath + std::string("\"\n\n") + std::string(hlsl);
1229 writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size());
1230 }
1231 else
1232 {
1233 flags |= ANGLE_COMPILE_OPTIMIZATION_LEVEL;
1234 sourceText = hlsl;
1235 }
1236
1237 // Sometimes D3DCompile will fail with the default compilation flags for complicated shaders when it would otherwise pass with alternative options.
1238 // Try the default flags first and if compilation fails, try some alternatives.
1239 const static UINT extraFlags[] =
1240 {
1241 0,
1242 // D3DCOMPILE_AVOID_FLOW_CONTROL,
1243 // D3DCOMPILE_PREFER_FLOW_CONTROL
1244 };
1245
1246 const static char * const extraFlagNames[] =
1247 {
1248 "default",
1249 "avoid flow control",
1250 "prefer flow control"
1251 };
1252
1253 for (int i = 0; i < sizeof(extraFlags) / sizeof(UINT); ++i)
1254 {
1255 ID3DBlob *errorMessage = NULL;
1256 ID3DBlob *binary = NULL;
1257 result = mD3DCompileFunc(hlsl, strlen(hlsl), gl::g_fakepath, NULL, NULL,
1258 "main", profile, flags | extraFlags[i], 0, &binary, &errorMessage);
1259 if (errorMessage)
1260 {
1261 const char *message = (const char*)errorMessage->GetBufferPointer();
1262
1263 infoLog.appendSanitized(message);
1264 TRACE("\n%s", hlsl);
1265 TRACE("\n%s", message);
1266
1267 errorMessage->Release();
1268 errorMessage = NULL;
1269 }
1270
1271 if (SUCCEEDED(result))
1272 {
1273 return binary;
1274 }
1275 else
1276 {
1277 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
1278 {
1279 return error(GL_OUT_OF_MEMORY, (ID3DBlob*) NULL);
1280 }
1281
1282 infoLog.append("Warning: D3D shader compilation failed with ");
1283 infoLog.append(extraFlagNames[i]);
1284 infoLog.append(" flags.");
1285 if (i + 1 < sizeof(extraFlagNames) / sizeof(char*))
1286 {
1287 infoLog.append(" Retrying with ");
1288 infoLog.append(extraFlagNames[i + 1]);
1289 infoLog.append(".\n");
1290 }
1291 }
1292 }
1293
daniel@transgaming.coma9c71422012-11-28 20:58:45 +00001294 return NULL;
1295}
1296
daniel@transgaming.com6c872172012-11-28 19:39:33 +00001297bool Renderer11::blitRect(gl::Framebuffer *readTarget, gl::Rectangle *readRect, gl::Framebuffer *drawTarget, gl::Rectangle *drawRect,
1298 bool blitRenderTarget, bool blitDepthStencil)
1299{
1300 // TODO
1301 UNIMPLEMENTED();
1302 return false;
1303}
1304
1305void Renderer11::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type,
1306 GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels)
1307{
1308 // TODO
1309 UNIMPLEMENTED();
1310 return;
1311}
1312
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001313}