Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / angle / src / libGLESv2 / renderer / d3d / d3d11 / renderer11_utils.cpp
1 #include "precompiled.h"
2 //
3 // Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved.
4 // Use of this source code is governed by a BSD-style license that can be
5 // found in the LICENSE file.
6 //
7
8 // renderer11_utils.cpp: Conversion functions and other utility routines
9 // specific to the D3D11 renderer.
10
11 #include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h"
12 #include "libGLESv2/renderer/d3d/d3d11/formatutils11.h"
13 #include "common/debug.h"
14
15 namespace rx
16 {
17
18 namespace gl_d3d11
19 {
20
21 D3D11_BLEND ConvertBlendFunc(GLenum glBlend, bool isAlpha)
22 {
23     D3D11_BLEND d3dBlend = D3D11_BLEND_ZERO;
24
25     switch (glBlend)
26     {
27       case GL_ZERO:                     d3dBlend = D3D11_BLEND_ZERO;                break;
28       case GL_ONE:                      d3dBlend = D3D11_BLEND_ONE;                 break;
29       case GL_SRC_COLOR:                d3dBlend = (isAlpha ? D3D11_BLEND_SRC_ALPHA : D3D11_BLEND_SRC_COLOR);           break;
30       case GL_ONE_MINUS_SRC_COLOR:      d3dBlend = (isAlpha ? D3D11_BLEND_INV_SRC_ALPHA : D3D11_BLEND_INV_SRC_COLOR);   break;
31       case GL_DST_COLOR:                d3dBlend = (isAlpha ? D3D11_BLEND_DEST_ALPHA : D3D11_BLEND_DEST_COLOR);         break;
32       case GL_ONE_MINUS_DST_COLOR:      d3dBlend = (isAlpha ? D3D11_BLEND_INV_DEST_ALPHA : D3D11_BLEND_INV_DEST_COLOR); break;
33       case GL_SRC_ALPHA:                d3dBlend = D3D11_BLEND_SRC_ALPHA;           break;
34       case GL_ONE_MINUS_SRC_ALPHA:      d3dBlend = D3D11_BLEND_INV_SRC_ALPHA;       break;
35       case GL_DST_ALPHA:                d3dBlend = D3D11_BLEND_DEST_ALPHA;          break;
36       case GL_ONE_MINUS_DST_ALPHA:      d3dBlend = D3D11_BLEND_INV_DEST_ALPHA;      break;
37       case GL_CONSTANT_COLOR:           d3dBlend = D3D11_BLEND_BLEND_FACTOR;        break;
38       case GL_ONE_MINUS_CONSTANT_COLOR: d3dBlend = D3D11_BLEND_INV_BLEND_FACTOR;    break;
39       case GL_CONSTANT_ALPHA:           d3dBlend = D3D11_BLEND_BLEND_FACTOR;        break;
40       case GL_ONE_MINUS_CONSTANT_ALPHA: d3dBlend = D3D11_BLEND_INV_BLEND_FACTOR;    break;
41       case GL_SRC_ALPHA_SATURATE:       d3dBlend = D3D11_BLEND_SRC_ALPHA_SAT;       break;
42       default: UNREACHABLE();
43     }
44
45     return d3dBlend;
46 }
47
48 D3D11_BLEND_OP ConvertBlendOp(GLenum glBlendOp)
49 {
50     D3D11_BLEND_OP d3dBlendOp = D3D11_BLEND_OP_ADD;
51
52     switch (glBlendOp)
53     {
54       case GL_FUNC_ADD:              d3dBlendOp = D3D11_BLEND_OP_ADD;           break;
55       case GL_FUNC_SUBTRACT:         d3dBlendOp = D3D11_BLEND_OP_SUBTRACT;      break;
56       case GL_FUNC_REVERSE_SUBTRACT: d3dBlendOp = D3D11_BLEND_OP_REV_SUBTRACT;  break;
57       case GL_MIN:                   d3dBlendOp = D3D11_BLEND_OP_MIN;           break;
58       case GL_MAX:                   d3dBlendOp = D3D11_BLEND_OP_MAX;           break;
59       default: UNREACHABLE();
60     }
61
62     return d3dBlendOp;
63 }
64
65 UINT8 ConvertColorMask(bool red, bool green, bool blue, bool alpha)
66 {
67     UINT8 mask = 0;
68     if (red)
69     {
70         mask |= D3D11_COLOR_WRITE_ENABLE_RED;
71     }
72     if (green)
73     {
74         mask |= D3D11_COLOR_WRITE_ENABLE_GREEN;
75     }
76     if (blue)
77     {
78         mask |= D3D11_COLOR_WRITE_ENABLE_BLUE;
79     }
80     if (alpha)
81     {
82         mask |= D3D11_COLOR_WRITE_ENABLE_ALPHA;
83     }
84     return mask;
85 }
86
87 D3D11_CULL_MODE ConvertCullMode(bool cullEnabled, GLenum cullMode)
88 {
89     D3D11_CULL_MODE cull = D3D11_CULL_NONE;
90
91     if (cullEnabled)
92     {
93         switch (cullMode)
94         {
95           case GL_FRONT:            cull = D3D11_CULL_FRONT;    break;
96           case GL_BACK:             cull = D3D11_CULL_BACK;     break;
97           case GL_FRONT_AND_BACK:   cull = D3D11_CULL_NONE;     break;
98           default: UNREACHABLE();
99         }
100     }
101     else
102     {
103         cull = D3D11_CULL_NONE;
104     }
105
106     return cull;
107 }
108
109 D3D11_COMPARISON_FUNC ConvertComparison(GLenum comparison)
110 {
111     D3D11_COMPARISON_FUNC d3dComp = D3D11_COMPARISON_NEVER;
112     switch (comparison)
113     {
114       case GL_NEVER:    d3dComp = D3D11_COMPARISON_NEVER;           break;
115       case GL_ALWAYS:   d3dComp = D3D11_COMPARISON_ALWAYS;          break;
116       case GL_LESS:     d3dComp = D3D11_COMPARISON_LESS;            break;
117       case GL_LEQUAL:   d3dComp = D3D11_COMPARISON_LESS_EQUAL;      break;
118       case GL_EQUAL:    d3dComp = D3D11_COMPARISON_EQUAL;           break;
119       case GL_GREATER:  d3dComp = D3D11_COMPARISON_GREATER;         break;
120       case GL_GEQUAL:   d3dComp = D3D11_COMPARISON_GREATER_EQUAL;   break;
121       case GL_NOTEQUAL: d3dComp = D3D11_COMPARISON_NOT_EQUAL;       break;
122       default: UNREACHABLE();
123     }
124
125     return d3dComp;
126 }
127
128 D3D11_DEPTH_WRITE_MASK ConvertDepthMask(bool depthWriteEnabled)
129 {
130     return depthWriteEnabled ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
131 }
132
133 UINT8 ConvertStencilMask(GLuint stencilmask)
134 {
135     return static_cast<UINT8>(stencilmask);
136 }
137
138 D3D11_STENCIL_OP ConvertStencilOp(GLenum stencilOp)
139 {
140     D3D11_STENCIL_OP d3dStencilOp = D3D11_STENCIL_OP_KEEP;
141
142     switch (stencilOp)
143     {
144       case GL_ZERO:      d3dStencilOp = D3D11_STENCIL_OP_ZERO;      break;
145       case GL_KEEP:      d3dStencilOp = D3D11_STENCIL_OP_KEEP;      break;
146       case GL_REPLACE:   d3dStencilOp = D3D11_STENCIL_OP_REPLACE;   break;
147       case GL_INCR:      d3dStencilOp = D3D11_STENCIL_OP_INCR_SAT;  break;
148       case GL_DECR:      d3dStencilOp = D3D11_STENCIL_OP_DECR_SAT;  break;
149       case GL_INVERT:    d3dStencilOp = D3D11_STENCIL_OP_INVERT;    break;
150       case GL_INCR_WRAP: d3dStencilOp = D3D11_STENCIL_OP_INCR;      break;
151       case GL_DECR_WRAP: d3dStencilOp = D3D11_STENCIL_OP_DECR;      break;
152       default: UNREACHABLE();
153     }
154
155     return d3dStencilOp;
156 }
157
158 D3D11_FILTER ConvertFilter(GLenum minFilter, GLenum magFilter, float maxAnisotropy, GLenum comparisonMode)
159 {
160     bool comparison = comparisonMode != GL_NONE;
161
162     if (maxAnisotropy > 1.0f)
163     {
164         return D3D11_ENCODE_ANISOTROPIC_FILTER(static_cast<D3D11_COMPARISON_FUNC>(comparison));
165     }
166     else
167     {
168         D3D11_FILTER_TYPE dxMin = D3D11_FILTER_TYPE_POINT;
169         D3D11_FILTER_TYPE dxMip = D3D11_FILTER_TYPE_POINT;
170         switch (minFilter)
171         {
172           case GL_NEAREST:                dxMin = D3D11_FILTER_TYPE_POINT;  dxMip = D3D11_FILTER_TYPE_POINT;  break;
173           case GL_LINEAR:                 dxMin = D3D11_FILTER_TYPE_LINEAR; dxMip = D3D11_FILTER_TYPE_POINT;  break;
174           case GL_NEAREST_MIPMAP_NEAREST: dxMin = D3D11_FILTER_TYPE_POINT;  dxMip = D3D11_FILTER_TYPE_POINT;  break;
175           case GL_LINEAR_MIPMAP_NEAREST:  dxMin = D3D11_FILTER_TYPE_LINEAR; dxMip = D3D11_FILTER_TYPE_POINT;  break;
176           case GL_NEAREST_MIPMAP_LINEAR:  dxMin = D3D11_FILTER_TYPE_POINT;  dxMip = D3D11_FILTER_TYPE_LINEAR; break;
177           case GL_LINEAR_MIPMAP_LINEAR:   dxMin = D3D11_FILTER_TYPE_LINEAR; dxMip = D3D11_FILTER_TYPE_LINEAR; break;
178           default:                        UNREACHABLE();
179         }
180
181         D3D11_FILTER_TYPE dxMag = D3D11_FILTER_TYPE_POINT;
182         switch (magFilter)
183         {
184           case GL_NEAREST: dxMag = D3D11_FILTER_TYPE_POINT;  break;
185           case GL_LINEAR:  dxMag = D3D11_FILTER_TYPE_LINEAR; break;
186           default:         UNREACHABLE();
187         }
188
189         return D3D11_ENCODE_BASIC_FILTER(dxMin, dxMag, dxMip, static_cast<D3D11_COMPARISON_FUNC>(comparison));
190     }
191 }
192
193 D3D11_TEXTURE_ADDRESS_MODE ConvertTextureWrap(GLenum wrap)
194 {
195     switch (wrap)
196     {
197       case GL_REPEAT:          return D3D11_TEXTURE_ADDRESS_WRAP;
198       case GL_CLAMP_TO_EDGE:   return D3D11_TEXTURE_ADDRESS_CLAMP;
199       case GL_MIRRORED_REPEAT: return D3D11_TEXTURE_ADDRESS_MIRROR;
200       default:                 UNREACHABLE();
201     }
202
203     return D3D11_TEXTURE_ADDRESS_WRAP;
204 }
205
206 D3D11_QUERY ConvertQueryType(GLenum queryType)
207 {
208     switch (queryType)
209     {
210       case GL_ANY_SAMPLES_PASSED_EXT:
211       case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:   return D3D11_QUERY_OCCLUSION;
212       case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: return D3D11_QUERY_SO_STATISTICS;
213       default: UNREACHABLE();                        return D3D11_QUERY_EVENT;
214     }
215 }
216
217 }
218
219
220 namespace d3d11_gl
221 {
222
223 static gl::TextureCaps GenerateTextureFormatCaps(GLenum internalFormat, ID3D11Device *device)
224 {
225     gl::TextureCaps textureCaps;
226
227     const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalFormat);
228
229     UINT formatSupport;
230     if (SUCCEEDED(device->CheckFormatSupport(formatInfo.texFormat, &formatSupport)))
231     {
232         const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
233         if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
234         {
235             textureCaps.texturable = ((formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0);
236         }
237         else
238         {
239             textureCaps.texturable = ((formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0) &&
240                                      ((formatSupport & D3D11_FORMAT_SUPPORT_TEXTURECUBE) != 0) &&
241                                      ((formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE3D) != 0);
242         }
243     }
244
245     if (SUCCEEDED(device->CheckFormatSupport(formatInfo.renderFormat, &formatSupport)) &&
246         ((formatSupport & D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET) != 0))
247     {
248         for (size_t sampleCount = 1; sampleCount <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; sampleCount++)
249         {
250             UINT qualityCount = 0;
251             if (SUCCEEDED(device->CheckMultisampleQualityLevels(formatInfo.renderFormat, sampleCount, &qualityCount)) &&
252                 qualityCount > 0)
253             {
254                 textureCaps.sampleCounts.insert(sampleCount);
255             }
256         }
257     }
258
259     textureCaps.filterable = SUCCEEDED(device->CheckFormatSupport(formatInfo.srvFormat, &formatSupport)) &&
260                              ((formatSupport & D3D11_FORMAT_SUPPORT_SHADER_SAMPLE)) != 0;
261     textureCaps.renderable = (SUCCEEDED(device->CheckFormatSupport(formatInfo.rtvFormat, &formatSupport)) &&
262                               ((formatSupport & D3D11_FORMAT_SUPPORT_RENDER_TARGET)) != 0) ||
263                              (SUCCEEDED(device->CheckFormatSupport(formatInfo.dsvFormat, &formatSupport)) &&
264                               ((formatSupport & D3D11_FORMAT_SUPPORT_DEPTH_STENCIL) != 0));
265
266     return textureCaps;
267 }
268
269 static bool GetNPOTTextureSupport(D3D_FEATURE_LEVEL featureLevel)
270 {
271     switch (featureLevel)
272     {
273       case D3D_FEATURE_LEVEL_11_1:
274       case D3D_FEATURE_LEVEL_11_0:
275       case D3D_FEATURE_LEVEL_10_1:
276       case D3D_FEATURE_LEVEL_10_0: return true;
277
278         // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx
279       case D3D_FEATURE_LEVEL_9_3:
280       case D3D_FEATURE_LEVEL_9_2:
281       case D3D_FEATURE_LEVEL_9_1:  return false;
282
283       default: UNREACHABLE();      return false;
284     }
285 }
286
287 static float GetMaximumAnisotropy(D3D_FEATURE_LEVEL featureLevel)
288 {
289     switch (featureLevel)
290     {
291       case D3D_FEATURE_LEVEL_11_1:
292       case D3D_FEATURE_LEVEL_11_0: return D3D11_MAX_MAXANISOTROPY;
293
294       case D3D_FEATURE_LEVEL_10_1:
295       case D3D_FEATURE_LEVEL_10_0: return D3D10_MAX_MAXANISOTROPY;
296
297         // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx
298       case D3D_FEATURE_LEVEL_9_3:
299       case D3D_FEATURE_LEVEL_9_2:  return 16;
300
301       case D3D_FEATURE_LEVEL_9_1:  return D3D_FL9_1_DEFAULT_MAX_ANISOTROPY;
302
303       default: UNREACHABLE();      return 0;
304     }
305 }
306
307 static bool GetOcclusionQuerySupport(D3D_FEATURE_LEVEL featureLevel)
308 {
309     switch (featureLevel)
310     {
311       case D3D_FEATURE_LEVEL_11_1:
312       case D3D_FEATURE_LEVEL_11_0:
313       case D3D_FEATURE_LEVEL_10_1:
314       case D3D_FEATURE_LEVEL_10_0: return true;
315
316         // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateQuery
317       case D3D_FEATURE_LEVEL_9_3:
318       case D3D_FEATURE_LEVEL_9_2:  return true;
319       case D3D_FEATURE_LEVEL_9_1:  return false;
320
321       default: UNREACHABLE();      return false;
322     }
323 }
324
325 static bool GetEventQuerySupport(D3D_FEATURE_LEVEL featureLevel)
326 {
327     // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateQuery
328
329     switch (featureLevel)
330     {
331       case D3D_FEATURE_LEVEL_11_1:
332       case D3D_FEATURE_LEVEL_11_0:
333       case D3D_FEATURE_LEVEL_10_1:
334       case D3D_FEATURE_LEVEL_10_0:
335       case D3D_FEATURE_LEVEL_9_3:
336       case D3D_FEATURE_LEVEL_9_2:
337       case D3D_FEATURE_LEVEL_9_1:  return true;
338
339       default: UNREACHABLE();      return false;
340     }
341 }
342
343 static bool GetInstancingSupport(D3D_FEATURE_LEVEL featureLevel)
344 {
345     // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateInputLayout
346
347     switch (featureLevel)
348     {
349       case D3D_FEATURE_LEVEL_11_1:
350       case D3D_FEATURE_LEVEL_11_0:
351       case D3D_FEATURE_LEVEL_10_1:
352       case D3D_FEATURE_LEVEL_10_0:
353       case D3D_FEATURE_LEVEL_9_3:  return true;
354
355       case D3D_FEATURE_LEVEL_9_2:
356       case D3D_FEATURE_LEVEL_9_1:  return false;
357
358       default: UNREACHABLE();      return false;
359     }
360 }
361
362 static bool GetDerivativeInstructionSupport(D3D_FEATURE_LEVEL featureLevel)
363 {
364     // http://msdn.microsoft.com/en-us/library/windows/desktop/bb509588.aspx states that shader model
365     // ps_2_x is required for the ddx (and other derivative functions).
366
367     // http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx states that feature level
368     // 9.3 supports shader model ps_2_x.
369
370     switch (featureLevel)
371     {
372       case D3D_FEATURE_LEVEL_11_1:
373       case D3D_FEATURE_LEVEL_11_0:
374       case D3D_FEATURE_LEVEL_10_1:
375       case D3D_FEATURE_LEVEL_10_0:
376       case D3D_FEATURE_LEVEL_9_3:  return true;
377       case D3D_FEATURE_LEVEL_9_2:
378       case D3D_FEATURE_LEVEL_9_1:  return false;
379
380       default: UNREACHABLE();      return false;
381     }
382 }
383
384 static size_t GetMaximumSimultaneousRenderTargets(D3D_FEATURE_LEVEL featureLevel)
385 {
386     // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateInputLayout
387
388     switch (featureLevel)
389     {
390       case D3D_FEATURE_LEVEL_11_1:
391       case D3D_FEATURE_LEVEL_11_0: return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT;
392
393         // FIXME(geofflang): Work around NVIDIA driver bug by repacking buffers
394       case D3D_FEATURE_LEVEL_10_1:
395       case D3D_FEATURE_LEVEL_10_0: return 1; /* D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT; */
396
397       case D3D_FEATURE_LEVEL_9_3:  return D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT;
398       case D3D_FEATURE_LEVEL_9_2:
399       case D3D_FEATURE_LEVEL_9_1:  return D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT;
400
401       default: UNREACHABLE();      return 0;
402     }
403 }
404
405 static size_t GetMaximum2DTextureSize(D3D_FEATURE_LEVEL featureLevel)
406 {
407     switch (featureLevel)
408     {
409       case D3D_FEATURE_LEVEL_11_1:
410       case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
411
412       case D3D_FEATURE_LEVEL_10_1:
413       case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION;
414
415       case D3D_FEATURE_LEVEL_9_3:  return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION;
416       case D3D_FEATURE_LEVEL_9_2:
417       case D3D_FEATURE_LEVEL_9_1:  return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION;
418
419       default: UNREACHABLE();      return 0;
420     }
421 }
422
423 static size_t GetMaximumCubeMapTextureSize(D3D_FEATURE_LEVEL featureLevel)
424 {
425     switch (featureLevel)
426     {
427       case D3D_FEATURE_LEVEL_11_1:
428       case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURECUBE_DIMENSION;
429
430       case D3D_FEATURE_LEVEL_10_1:
431       case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURECUBE_DIMENSION;
432
433       case D3D_FEATURE_LEVEL_9_3:  return D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION;
434       case D3D_FEATURE_LEVEL_9_2:
435       case D3D_FEATURE_LEVEL_9_1:  return D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION;
436
437       default: UNREACHABLE();      return 0;
438     }
439 }
440
441 static size_t GetMaximum2DTextureArraySize(D3D_FEATURE_LEVEL featureLevel)
442 {
443     switch (featureLevel)
444     {
445       case D3D_FEATURE_LEVEL_11_1:
446       case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;
447
448       case D3D_FEATURE_LEVEL_10_1:
449       case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;
450
451       case D3D_FEATURE_LEVEL_9_3:
452       case D3D_FEATURE_LEVEL_9_2:
453       case D3D_FEATURE_LEVEL_9_1:  return 0;
454
455       default: UNREACHABLE();      return 0;
456     }
457 }
458
459 static size_t GetMaximum3DTextureSize(D3D_FEATURE_LEVEL featureLevel)
460 {
461     switch (featureLevel)
462     {
463       case D3D_FEATURE_LEVEL_11_1:
464       case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION;
465
466       case D3D_FEATURE_LEVEL_10_1:
467       case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE3D_U_V_OR_W_DIMENSION;
468
469       case D3D_FEATURE_LEVEL_9_3:
470       case D3D_FEATURE_LEVEL_9_2:
471       case D3D_FEATURE_LEVEL_9_1:  return D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION;
472
473       default: UNREACHABLE();      return 0;
474     }
475 }
476
477 static size_t GetMaximumViewportSize(D3D_FEATURE_LEVEL featureLevel)
478 {
479     switch (featureLevel)
480     {
481       case D3D_FEATURE_LEVEL_11_1:
482       case D3D_FEATURE_LEVEL_11_0: return D3D11_VIEWPORT_BOUNDS_MAX;
483
484       case D3D_FEATURE_LEVEL_10_1:
485       case D3D_FEATURE_LEVEL_10_0: return D3D10_VIEWPORT_BOUNDS_MAX;
486
487         // No constants for D3D9 viewport size limits, use the maximum texture sizes
488       case D3D_FEATURE_LEVEL_9_3:  return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION;
489       case D3D_FEATURE_LEVEL_9_2:
490       case D3D_FEATURE_LEVEL_9_1:  return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION;
491
492       default: UNREACHABLE();      return 0;
493     }
494 }
495
496 void GenerateCaps(ID3D11Device *device, gl::Caps *caps, gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions)
497 {
498     GLuint maxSamples = 0;
499     const gl::FormatSet &allFormats = gl::GetAllSizedInternalFormats();
500     for (gl::FormatSet::const_iterator internalFormat = allFormats.begin(); internalFormat != allFormats.end(); ++internalFormat)
501     {
502         gl::TextureCaps textureCaps = GenerateTextureFormatCaps(*internalFormat, device);
503         textureCapsMap->insert(*internalFormat, textureCaps);
504
505         maxSamples = std::max(maxSamples, textureCaps.getMaxSamples());
506     }
507
508     D3D_FEATURE_LEVEL featureLevel = device->GetFeatureLevel();
509
510     // GL core feature limits
511     caps->maxElementIndex = static_cast<GLint64>(std::numeric_limits<unsigned int>::max());
512     caps->max3DTextureSize = GetMaximum3DTextureSize(featureLevel);
513     caps->max2DTextureSize = GetMaximum2DTextureSize(featureLevel);
514     caps->maxCubeMapTextureSize = GetMaximumCubeMapTextureSize(featureLevel);
515     caps->maxArrayTextureLayers = GetMaximum2DTextureArraySize(featureLevel);
516
517     // Unimplemented, set to minimum required
518     caps->maxLODBias = 2.0f;
519
520     // No specific limits on render target size, maximum 2D texture size is equivalent
521     caps->maxRenderbufferSize = caps->max2DTextureSize;
522
523     // Maximum draw buffers and color attachments are the same, max color attachments could eventually be
524     // increased to 16
525     caps->maxDrawBuffers = GetMaximumSimultaneousRenderTargets(featureLevel);
526     caps->maxColorAttachments = GetMaximumSimultaneousRenderTargets(featureLevel);
527
528     // D3D11 has the same limit for viewport width and height
529     caps->maxViewportWidth = GetMaximumViewportSize(featureLevel);
530     caps->maxViewportHeight = caps->maxViewportWidth;
531
532     // Choose a reasonable maximum, enforced in the shader.
533     caps->minAliasedPointSize = 1.0f;
534     caps->maxAliasedPointSize = 1024.0f;
535
536     // Wide lines not supported
537     caps->minAliasedLineWidth = 1.0f;
538     caps->maxAliasedLineWidth = 1.0f;
539
540     // GL extension support
541     extensions->setTextureExtensionSupport(*textureCapsMap);
542     extensions->elementIndexUint = true;
543     extensions->packedDepthStencil = true;
544     extensions->getProgramBinary = true;
545     extensions->rgb8rgba8 = true;
546     extensions->readFormatBGRA = true;
547     extensions->pixelBufferObject = true;
548     extensions->mapBuffer = true;
549     extensions->mapBufferRange = true;
550     extensions->textureNPOT = GetNPOTTextureSupport(featureLevel);
551     extensions->drawBuffers = GetMaximumSimultaneousRenderTargets(featureLevel) > 1;
552     extensions->textureStorage = true;
553     extensions->textureFilterAnisotropic = true;
554     extensions->maxTextureAnisotropy = GetMaximumAnisotropy(featureLevel);
555     extensions->occlusionQueryBoolean = GetOcclusionQuerySupport(featureLevel);
556     extensions->fence = GetEventQuerySupport(featureLevel);
557     extensions->timerQuery = false; // Unimplemented
558     extensions->robustness = true;
559     extensions->blendMinMax = true;
560     extensions->framebufferBlit = true;
561     extensions->framebufferMultisample = true;
562     extensions->maxSamples = maxSamples;
563     extensions->instancedArrays = GetInstancingSupport(featureLevel);
564     extensions->packReverseRowOrder = true;
565     extensions->standardDerivatives = GetDerivativeInstructionSupport(featureLevel);
566     extensions->shaderTextureLOD = true;
567     extensions->fragDepth = true;
568     extensions->textureUsage = true; // This could be false since it has no effect in D3D11
569     extensions->translatedShaderSource = true;
570 }
571
572 }
573
574 namespace d3d11
575 {
576
577 void MakeValidSize(bool isImage, DXGI_FORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset)
578 {
579     const DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(format);
580
581     int upsampleCount = 0;
582     // Don't expand the size of full textures that are at least (blockWidth x blockHeight) already.
583     if (isImage || *requestWidth  < static_cast<GLsizei>(dxgiFormatInfo.blockWidth) ||
584                    *requestHeight < static_cast<GLsizei>(dxgiFormatInfo.blockHeight))
585     {
586         while (*requestWidth % dxgiFormatInfo.blockWidth != 0 || *requestHeight % dxgiFormatInfo.blockHeight != 0)
587         {
588             *requestWidth <<= 1;
589             *requestHeight <<= 1;
590             upsampleCount++;
591         }
592     }
593     *levelOffset = upsampleCount;
594 }
595
596 void GenerateInitialTextureData(GLint internalFormat, GLuint width, GLuint height, GLuint depth,
597                                 GLuint mipLevels, std::vector<D3D11_SUBRESOURCE_DATA> *outSubresourceData,
598                                 std::vector< std::vector<BYTE> > *outData)
599 {
600     const d3d11::TextureFormat &d3dFormatInfo = d3d11::GetTextureFormatInfo(internalFormat);
601     ASSERT(d3dFormatInfo.dataInitializerFunction != NULL);
602
603     const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(d3dFormatInfo.texFormat);
604
605     outSubresourceData->resize(mipLevels);
606     outData->resize(mipLevels);
607
608     for (unsigned int i = 0; i < mipLevels; i++)
609     {
610         unsigned int mipWidth = std::max(width >> i, 1U);
611         unsigned int mipHeight = std::max(height >> i, 1U);
612         unsigned int mipDepth = std::max(depth >> i, 1U);
613
614         unsigned int rowWidth = dxgiFormatInfo.pixelBytes * mipWidth;
615         unsigned int imageSize = rowWidth * height;
616
617         outData->at(i).resize(rowWidth * mipHeight * mipDepth);
618         d3dFormatInfo.dataInitializerFunction(mipWidth, mipHeight, mipDepth, outData->at(i).data(), rowWidth, imageSize);
619
620         outSubresourceData->at(i).pSysMem = outData->at(i).data();
621         outSubresourceData->at(i).SysMemPitch = rowWidth;
622         outSubresourceData->at(i).SysMemSlicePitch = imageSize;
623     }
624 }
625
626 void SetPositionTexCoordVertex(PositionTexCoordVertex* vertex, float x, float y, float u, float v)
627 {
628     vertex->x = x;
629     vertex->y = y;
630     vertex->u = u;
631     vertex->v = v;
632 }
633
634 void SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex* vertex, float x, float y,
635                                       unsigned int layer, float u, float v, float s)
636 {
637     vertex->x = x;
638     vertex->y = y;
639     vertex->l = layer;
640     vertex->u = u;
641     vertex->v = v;
642     vertex->s = s;
643 }
644
645 HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name)
646 {
647 #if defined(_DEBUG)
648     return resource->SetPrivateData(WKPDID_D3DDebugObjectName, strlen(name), name);
649 #else
650     return S_OK;
651 #endif
652 }
653
654 }
655
656 }