blob: 7d7396ac40b6cc6ab519a1ca8a638a720ee68207 [file] [log] [blame]
daniel@transgaming.comd8e36562012-10-31 19:52:19 +00001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
daniel@transgaming.comd8e36562012-10-31 19:52:19 +00003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// renderer9_utils.cpp: Conversion functions and other utility routines
8// specific to the D3D9 renderer.
9
Brandon Jonesc7a41042014-06-23 12:03:25 -070010#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h"
11#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h"
Geoff Langcec35902014-04-16 10:52:36 -040012#include "libGLESv2/formatutils.h"
Jamie Madill9f0b42a2014-09-12 10:25:27 -040013#include "libGLESv2/Framebuffer.h"
14#include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h"
daniel@transgaming.comd8e36562012-10-31 19:52:19 +000015
Geoff Lang0b7eef72014-06-12 14:10:47 -040016#include "common/mathutil.h"
daniel@transgaming.comd8e36562012-10-31 19:52:19 +000017#include "common/debug.h"
18
Geoff Langcec35902014-04-16 10:52:36 -040019#include "third_party/systeminfo/SystemInfo.h"
20
shannonwoods@chromium.orged0adcf2013-05-30 00:08:20 +000021namespace rx
22{
23
daniel@transgaming.com682a37c2012-11-28 19:34:44 +000024namespace gl_d3d9
daniel@transgaming.comd8e36562012-10-31 19:52:19 +000025{
26
27D3DCMPFUNC ConvertComparison(GLenum comparison)
28{
29 D3DCMPFUNC d3dComp = D3DCMP_ALWAYS;
30 switch (comparison)
31 {
32 case GL_NEVER: d3dComp = D3DCMP_NEVER; break;
33 case GL_ALWAYS: d3dComp = D3DCMP_ALWAYS; break;
34 case GL_LESS: d3dComp = D3DCMP_LESS; break;
35 case GL_LEQUAL: d3dComp = D3DCMP_LESSEQUAL; break;
36 case GL_EQUAL: d3dComp = D3DCMP_EQUAL; break;
37 case GL_GREATER: d3dComp = D3DCMP_GREATER; break;
38 case GL_GEQUAL: d3dComp = D3DCMP_GREATEREQUAL; break;
39 case GL_NOTEQUAL: d3dComp = D3DCMP_NOTEQUAL; break;
40 default: UNREACHABLE();
41 }
42
43 return d3dComp;
44}
45
Geoff Lang2a64ee42013-05-31 11:22:40 -040046D3DCOLOR ConvertColor(gl::ColorF color)
daniel@transgaming.comd8e36562012-10-31 19:52:19 +000047{
48 return D3DCOLOR_RGBA(gl::unorm<8>(color.red),
49 gl::unorm<8>(color.green),
50 gl::unorm<8>(color.blue),
51 gl::unorm<8>(color.alpha));
52}
53
54D3DBLEND ConvertBlendFunc(GLenum blend)
55{
56 D3DBLEND d3dBlend = D3DBLEND_ZERO;
57
58 switch (blend)
59 {
60 case GL_ZERO: d3dBlend = D3DBLEND_ZERO; break;
61 case GL_ONE: d3dBlend = D3DBLEND_ONE; break;
62 case GL_SRC_COLOR: d3dBlend = D3DBLEND_SRCCOLOR; break;
63 case GL_ONE_MINUS_SRC_COLOR: d3dBlend = D3DBLEND_INVSRCCOLOR; break;
64 case GL_DST_COLOR: d3dBlend = D3DBLEND_DESTCOLOR; break;
65 case GL_ONE_MINUS_DST_COLOR: d3dBlend = D3DBLEND_INVDESTCOLOR; break;
66 case GL_SRC_ALPHA: d3dBlend = D3DBLEND_SRCALPHA; break;
67 case GL_ONE_MINUS_SRC_ALPHA: d3dBlend = D3DBLEND_INVSRCALPHA; break;
68 case GL_DST_ALPHA: d3dBlend = D3DBLEND_DESTALPHA; break;
69 case GL_ONE_MINUS_DST_ALPHA: d3dBlend = D3DBLEND_INVDESTALPHA; break;
70 case GL_CONSTANT_COLOR: d3dBlend = D3DBLEND_BLENDFACTOR; break;
71 case GL_ONE_MINUS_CONSTANT_COLOR: d3dBlend = D3DBLEND_INVBLENDFACTOR; break;
72 case GL_CONSTANT_ALPHA: d3dBlend = D3DBLEND_BLENDFACTOR; break;
73 case GL_ONE_MINUS_CONSTANT_ALPHA: d3dBlend = D3DBLEND_INVBLENDFACTOR; break;
74 case GL_SRC_ALPHA_SATURATE: d3dBlend = D3DBLEND_SRCALPHASAT; break;
75 default: UNREACHABLE();
76 }
77
78 return d3dBlend;
79}
80
81D3DBLENDOP ConvertBlendOp(GLenum blendOp)
82{
83 D3DBLENDOP d3dBlendOp = D3DBLENDOP_ADD;
84
85 switch (blendOp)
86 {
87 case GL_FUNC_ADD: d3dBlendOp = D3DBLENDOP_ADD; break;
88 case GL_FUNC_SUBTRACT: d3dBlendOp = D3DBLENDOP_SUBTRACT; break;
89 case GL_FUNC_REVERSE_SUBTRACT: d3dBlendOp = D3DBLENDOP_REVSUBTRACT; break;
Geoff Lang496123f2014-02-12 11:33:51 -050090 case GL_MIN_EXT: d3dBlendOp = D3DBLENDOP_MIN; break;
91 case GL_MAX_EXT: d3dBlendOp = D3DBLENDOP_MAX; break;
daniel@transgaming.comd8e36562012-10-31 19:52:19 +000092 default: UNREACHABLE();
93 }
94
95 return d3dBlendOp;
96}
97
98D3DSTENCILOP ConvertStencilOp(GLenum stencilOp)
99{
100 D3DSTENCILOP d3dStencilOp = D3DSTENCILOP_KEEP;
101
102 switch (stencilOp)
103 {
104 case GL_ZERO: d3dStencilOp = D3DSTENCILOP_ZERO; break;
105 case GL_KEEP: d3dStencilOp = D3DSTENCILOP_KEEP; break;
106 case GL_REPLACE: d3dStencilOp = D3DSTENCILOP_REPLACE; break;
107 case GL_INCR: d3dStencilOp = D3DSTENCILOP_INCRSAT; break;
108 case GL_DECR: d3dStencilOp = D3DSTENCILOP_DECRSAT; break;
109 case GL_INVERT: d3dStencilOp = D3DSTENCILOP_INVERT; break;
110 case GL_INCR_WRAP: d3dStencilOp = D3DSTENCILOP_INCR; break;
111 case GL_DECR_WRAP: d3dStencilOp = D3DSTENCILOP_DECR; break;
112 default: UNREACHABLE();
113 }
114
115 return d3dStencilOp;
116}
117
118D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap)
119{
120 D3DTEXTUREADDRESS d3dWrap = D3DTADDRESS_WRAP;
121
122 switch (wrap)
123 {
124 case GL_REPEAT: d3dWrap = D3DTADDRESS_WRAP; break;
125 case GL_CLAMP_TO_EDGE: d3dWrap = D3DTADDRESS_CLAMP; break;
126 case GL_MIRRORED_REPEAT: d3dWrap = D3DTADDRESS_MIRROR; break;
127 default: UNREACHABLE();
128 }
129
130 return d3dWrap;
131}
132
133D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace)
134{
135 D3DCULL cull = D3DCULL_CCW;
136 switch (cullFace)
137 {
138 case GL_FRONT:
139 cull = (frontFace == GL_CCW ? D3DCULL_CW : D3DCULL_CCW);
140 break;
141 case GL_BACK:
142 cull = (frontFace == GL_CCW ? D3DCULL_CCW : D3DCULL_CW);
143 break;
144 case GL_FRONT_AND_BACK:
145 cull = D3DCULL_NONE; // culling will be handled during draw
146 break;
147 default: UNREACHABLE();
148 }
149
150 return cull;
151}
152
153D3DCUBEMAP_FACES ConvertCubeFace(GLenum cubeFace)
154{
155 D3DCUBEMAP_FACES face = D3DCUBEMAP_FACE_POSITIVE_X;
156
157 switch (cubeFace)
158 {
159 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
160 face = D3DCUBEMAP_FACE_POSITIVE_X;
161 break;
162 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
163 face = D3DCUBEMAP_FACE_NEGATIVE_X;
164 break;
165 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
166 face = D3DCUBEMAP_FACE_POSITIVE_Y;
167 break;
168 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
169 face = D3DCUBEMAP_FACE_NEGATIVE_Y;
170 break;
171 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
172 face = D3DCUBEMAP_FACE_POSITIVE_Z;
173 break;
174 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
175 face = D3DCUBEMAP_FACE_NEGATIVE_Z;
176 break;
177 default: UNREACHABLE();
178 }
179
180 return face;
181}
182
183DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha)
184{
185 return (red ? D3DCOLORWRITEENABLE_RED : 0) |
186 (green ? D3DCOLORWRITEENABLE_GREEN : 0) |
187 (blue ? D3DCOLORWRITEENABLE_BLUE : 0) |
188 (alpha ? D3DCOLORWRITEENABLE_ALPHA : 0);
189}
190
191D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter, float maxAnisotropy)
192{
193 if (maxAnisotropy > 1.0f)
194 {
195 return D3DTEXF_ANISOTROPIC;
196 }
197
198 D3DTEXTUREFILTERTYPE d3dMagFilter = D3DTEXF_POINT;
199 switch (magFilter)
200 {
201 case GL_NEAREST: d3dMagFilter = D3DTEXF_POINT; break;
202 case GL_LINEAR: d3dMagFilter = D3DTEXF_LINEAR; break;
203 default: UNREACHABLE();
204 }
205
206 return d3dMagFilter;
207}
208
209void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter, float maxAnisotropy)
210{
211 switch (minFilter)
212 {
213 case GL_NEAREST:
214 *d3dMinFilter = D3DTEXF_POINT;
215 *d3dMipFilter = D3DTEXF_NONE;
216 break;
217 case GL_LINEAR:
218 *d3dMinFilter = D3DTEXF_LINEAR;
219 *d3dMipFilter = D3DTEXF_NONE;
220 break;
221 case GL_NEAREST_MIPMAP_NEAREST:
222 *d3dMinFilter = D3DTEXF_POINT;
223 *d3dMipFilter = D3DTEXF_POINT;
224 break;
225 case GL_LINEAR_MIPMAP_NEAREST:
226 *d3dMinFilter = D3DTEXF_LINEAR;
227 *d3dMipFilter = D3DTEXF_POINT;
228 break;
229 case GL_NEAREST_MIPMAP_LINEAR:
230 *d3dMinFilter = D3DTEXF_POINT;
231 *d3dMipFilter = D3DTEXF_LINEAR;
232 break;
233 case GL_LINEAR_MIPMAP_LINEAR:
234 *d3dMinFilter = D3DTEXF_LINEAR;
235 *d3dMipFilter = D3DTEXF_LINEAR;
236 break;
237 default:
238 *d3dMinFilter = D3DTEXF_POINT;
239 *d3dMipFilter = D3DTEXF_NONE;
240 UNREACHABLE();
241 }
242
243 if (maxAnisotropy > 1.0f)
244 {
245 *d3dMinFilter = D3DTEXF_ANISOTROPIC;
246 }
247}
248
Geoff Lang91fa9ce2014-07-04 17:30:27 -0400249D3DMULTISAMPLE_TYPE GetMultisampleType(GLuint samples)
250{
251 return (samples > 1) ? static_cast<D3DMULTISAMPLE_TYPE>(samples) : D3DMULTISAMPLE_NONE;
252}
253
daniel@transgaming.comd8e36562012-10-31 19:52:19 +0000254}
shannonwoods@chromium.orged0adcf2013-05-30 00:08:20 +0000255
Geoff Langcec35902014-04-16 10:52:36 -0400256namespace d3d9_gl
257{
258
Geoff Lang91fa9ce2014-07-04 17:30:27 -0400259GLsizei GetSamplesCount(D3DMULTISAMPLE_TYPE type)
260{
261 return (type != D3DMULTISAMPLE_NONMASKABLE) ? type : 0;
262}
263
264bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format)
265{
266 GLenum internalFormat = d3d9::GetD3DFormatInfo(d3dformat).internalFormat;
267 GLenum convertedFormat = gl::GetInternalFormatInfo(internalFormat).format;
268 return convertedFormat == format;
269}
270
Geoff Lange4a492b2014-06-19 14:14:41 -0400271static gl::TextureCaps GenerateTextureFormatCaps(GLenum internalFormat, IDirect3D9 *d3d9, D3DDEVTYPE deviceType,
Geoff Langcec35902014-04-16 10:52:36 -0400272 UINT adapter, D3DFORMAT adapterFormat)
273{
274 gl::TextureCaps textureCaps;
275
Geoff Lang91fa9ce2014-07-04 17:30:27 -0400276 const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalFormat);
277 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400278 if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400279 {
Geoff Lang91fa9ce2014-07-04 17:30:27 -0400280 textureCaps.texturable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, 0, D3DRTYPE_TEXTURE, d3dFormatInfo.renderFormat));
281 textureCaps.filterable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_QUERY_FILTER, D3DRTYPE_TEXTURE, d3dFormatInfo.renderFormat));
282 textureCaps.renderable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, d3dFormatInfo.renderFormat)) ||
283 SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, d3dFormatInfo.renderFormat));
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400284 }
285 else
286 {
Geoff Lang91fa9ce2014-07-04 17:30:27 -0400287 textureCaps.texturable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, 0, D3DRTYPE_TEXTURE, d3dFormatInfo.texFormat)) &&
288 SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, 0, D3DRTYPE_CUBETEXTURE, d3dFormatInfo.texFormat));
289 textureCaps.filterable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_QUERY_FILTER, D3DRTYPE_TEXTURE, d3dFormatInfo.texFormat));
290 textureCaps.renderable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, d3dFormatInfo.texFormat)) ||
291 SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, d3dFormatInfo.texFormat));
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400292 }
Geoff Langcec35902014-04-16 10:52:36 -0400293
294 textureCaps.sampleCounts.insert(1);
295 for (size_t i = D3DMULTISAMPLE_2_SAMPLES; i <= D3DMULTISAMPLE_16_SAMPLES; i++)
296 {
297 D3DMULTISAMPLE_TYPE multisampleType = D3DMULTISAMPLE_TYPE(i);
298
Geoff Lang91fa9ce2014-07-04 17:30:27 -0400299 HRESULT result = d3d9->CheckDeviceMultiSampleType(adapter, deviceType, d3dFormatInfo.renderFormat, TRUE, multisampleType, NULL);
Geoff Langcec35902014-04-16 10:52:36 -0400300 if (SUCCEEDED(result))
301 {
302 textureCaps.sampleCounts.insert(i);
303 }
304 }
305
306 return textureCaps;
307}
308
Geoff Langc0b9ef42014-07-02 10:02:37 -0400309void GenerateCaps(IDirect3D9 *d3d9, IDirect3DDevice9 *device, D3DDEVTYPE deviceType, UINT adapter, gl::Caps *caps,
310 gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions)
Geoff Langcec35902014-04-16 10:52:36 -0400311{
Geoff Langcec35902014-04-16 10:52:36 -0400312 D3DCAPS9 deviceCaps;
313 if (FAILED(d3d9->GetDeviceCaps(adapter, deviceType, &deviceCaps)))
314 {
315 // Can't continue with out device caps
Geoff Langc0b9ef42014-07-02 10:02:37 -0400316 return;
Geoff Langcec35902014-04-16 10:52:36 -0400317 }
318
319 D3DDISPLAYMODE currentDisplayMode;
320 d3d9->GetAdapterDisplayMode(adapter, &currentDisplayMode);
321
Geoff Lang5f4c4632014-07-03 13:46:52 -0400322 GLuint maxSamples = 0;
Geoff Lange4a492b2014-06-19 14:14:41 -0400323 const gl::FormatSet &allFormats = gl::GetAllSizedInternalFormats();
Geoff Langcec35902014-04-16 10:52:36 -0400324 for (gl::FormatSet::const_iterator internalFormat = allFormats.begin(); internalFormat != allFormats.end(); ++internalFormat)
325 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400326 gl::TextureCaps textureCaps = GenerateTextureFormatCaps(*internalFormat, d3d9, deviceType, adapter,
327 currentDisplayMode.Format);
328 textureCapsMap->insert(*internalFormat, textureCaps);
Geoff Lang5f4c4632014-07-03 13:46:52 -0400329
330 maxSamples = std::max(maxSamples, textureCaps.getMaxSamples());
Geoff Lang900013c2014-07-07 11:32:19 -0400331
332 if (gl::GetInternalFormatInfo(*internalFormat).compressed)
333 {
334 caps->compressedTextureFormats.push_back(*internalFormat);
335 }
Geoff Langcec35902014-04-16 10:52:36 -0400336 }
337
Geoff Langaae65a42014-05-26 12:43:44 -0400338 // GL core feature limits
Geoff Langc0b9ef42014-07-02 10:02:37 -0400339 caps->maxElementIndex = static_cast<GLint64>(std::numeric_limits<unsigned int>::max());
Geoff Langaae65a42014-05-26 12:43:44 -0400340
341 // 3D textures are unimplemented in D3D9
Geoff Langc0b9ef42014-07-02 10:02:37 -0400342 caps->max3DTextureSize = 1;
Geoff Langaae65a42014-05-26 12:43:44 -0400343
344 // Only one limit in GL, use the minimum dimension
Geoff Langc0b9ef42014-07-02 10:02:37 -0400345 caps->max2DTextureSize = std::min(deviceCaps.MaxTextureWidth, deviceCaps.MaxTextureHeight);
Geoff Langaae65a42014-05-26 12:43:44 -0400346
347 // D3D treats cube maps as a special case of 2D textures
Geoff Langc0b9ef42014-07-02 10:02:37 -0400348 caps->maxCubeMapTextureSize = caps->max2DTextureSize;
Geoff Langaae65a42014-05-26 12:43:44 -0400349
350 // Array textures are not available in D3D9
Geoff Langc0b9ef42014-07-02 10:02:37 -0400351 caps->maxArrayTextureLayers = 1;
Geoff Langaae65a42014-05-26 12:43:44 -0400352
353 // ES3-only feature
Geoff Langc0b9ef42014-07-02 10:02:37 -0400354 caps->maxLODBias = 0.0f;
Geoff Langaae65a42014-05-26 12:43:44 -0400355
356 // No specific limits on render target size, maximum 2D texture size is equivalent
Geoff Langc0b9ef42014-07-02 10:02:37 -0400357 caps->maxRenderbufferSize = caps->max2DTextureSize;
Geoff Langaae65a42014-05-26 12:43:44 -0400358
359 // Draw buffers are not supported in D3D9
Geoff Langc0b9ef42014-07-02 10:02:37 -0400360 caps->maxDrawBuffers = 1;
361 caps->maxColorAttachments = 1;
Geoff Langaae65a42014-05-26 12:43:44 -0400362
363 // No specific limits on viewport size, maximum 2D texture size is equivalent
Geoff Langc0b9ef42014-07-02 10:02:37 -0400364 caps->maxViewportWidth = caps->max2DTextureSize;
365 caps->maxViewportHeight = caps->maxViewportWidth;
Geoff Langaae65a42014-05-26 12:43:44 -0400366
367 // Point size is clamped to 1.0f when the shader model is less than 3
Geoff Langc0b9ef42014-07-02 10:02:37 -0400368 caps->minAliasedPointSize = 1.0f;
369 caps->maxAliasedPointSize = ((D3DSHADER_VERSION_MAJOR(deviceCaps.PixelShaderVersion) >= 3) ? deviceCaps.MaxPointSize : 1.0f);
Geoff Langaae65a42014-05-26 12:43:44 -0400370
371 // Wide lines not supported
Geoff Langc0b9ef42014-07-02 10:02:37 -0400372 caps->minAliasedLineWidth = 1.0f;
373 caps->maxAliasedLineWidth = 1.0f;
Geoff Langaae65a42014-05-26 12:43:44 -0400374
Geoff Lang900013c2014-07-07 11:32:19 -0400375 // Primitive count limits (unused in ES2)
376 caps->maxElementsIndices = 0;
377 caps->maxElementsVertices = 0;
378
379 // Program and shader binary formats (no supported shader binary formats)
380 caps->programBinaryFormats.push_back(GL_PROGRAM_BINARY_ANGLE);
381
382 // WaitSync is ES3-only, set to zero
383 caps->maxServerWaitTimeout = 0;
384
Geoff Lang301d1612014-07-09 10:34:37 -0400385 // Vertex shader limits
386 caps->maxVertexAttributes = 16;
387
388 const size_t reservedVertexUniformVectors = 2; // dx_ViewAdjust and dx_DepthRange.
389 const size_t MAX_VERTEX_CONSTANT_VECTORS_D3D9 = 256;
390 caps->maxVertexUniformVectors = MAX_VERTEX_CONSTANT_VECTORS_D3D9 - reservedVertexUniformVectors;
391 caps->maxVertexUniformComponents = caps->maxVertexUniformVectors * 4;
392
393 caps->maxVertexUniformBlocks = 0;
394
395 const size_t MAX_VERTEX_OUTPUT_VECTORS_SM3 = 10;
396 const size_t MAX_VERTEX_OUTPUT_VECTORS_SM2 = 8;
397 caps->maxVertexOutputComponents = ((deviceCaps.VertexShaderVersion >= D3DVS_VERSION(3, 0)) ? MAX_VERTEX_OUTPUT_VECTORS_SM3
398 : MAX_VERTEX_OUTPUT_VECTORS_SM2) * 4;
399
400 // Only Direct3D 10 ready devices support all the necessary vertex texture formats.
401 // We test this using D3D9 by checking support for the R16F format.
402 if (deviceCaps.VertexShaderVersion >= D3DVS_VERSION(3, 0) &&
403 SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, currentDisplayMode.Format,
404 D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_R16F)))
405 {
406 const size_t MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 = 4;
407 caps->maxVertexTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS_VTF_SM3;
408 }
409 else
410 {
411 caps->maxVertexTextureImageUnits = 0;
412 }
413
414 // Fragment shader limits
415 const size_t reservedPixelUniformVectors = 3; // dx_ViewCoords, dx_DepthFront and dx_DepthRange.
416
417 const size_t MAX_PIXEL_CONSTANT_VECTORS_SM3 = 224;
418 const size_t MAX_PIXEL_CONSTANT_VECTORS_SM2 = 32;
419 caps->maxFragmentUniformVectors = ((deviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0)) ? MAX_PIXEL_CONSTANT_VECTORS_SM3
420 : MAX_PIXEL_CONSTANT_VECTORS_SM2) - reservedPixelUniformVectors;
421 caps->maxFragmentUniformComponents = caps->maxFragmentUniformVectors * 4;
422 caps->maxFragmentUniformBlocks = 0;
423 caps->maxFragmentInputComponents = caps->maxVertexOutputComponents;
424 caps->maxTextureImageUnits = 16;
425 caps->minProgramTexelOffset = 0;
426 caps->maxProgramTexelOffset = 0;
427
Geoff Lang3a61c322014-07-10 13:01:54 -0400428 // Aggregate shader limits (unused in ES2)
429 caps->maxUniformBufferBindings = 0;
430 caps->maxUniformBlockSize = 0;
431 caps->uniformBufferOffsetAlignment = 0;
432 caps->maxCombinedUniformBlocks = 0;
433 caps->maxCombinedVertexUniformComponents = 0;
434 caps->maxCombinedFragmentUniformComponents = 0;
435 caps->maxVaryingComponents = 0;
436
437 // Aggregate shader limits
438 caps->maxVaryingVectors = caps->maxVertexOutputComponents / 4;
Geoff Lang76b10c92014-09-05 16:28:14 -0400439 caps->maxCombinedTextureImageUnits = caps->maxVertexTextureImageUnits + caps->maxTextureImageUnits;
Geoff Lang3a61c322014-07-10 13:01:54 -0400440
Geoff Lang05881a02014-07-10 14:05:30 -0400441 // Transform feedback limits
442 caps->maxTransformFeedbackInterleavedComponents = 0;
443 caps->maxTransformFeedbackSeparateAttributes = 0;
444 caps->maxTransformFeedbackSeparateComponents = 0;
445
Geoff Langaae65a42014-05-26 12:43:44 -0400446 // GL extension support
Geoff Langc0b9ef42014-07-02 10:02:37 -0400447 extensions->setTextureExtensionSupport(*textureCapsMap);
448 extensions->elementIndexUint = deviceCaps.MaxVertexIndex >= (1 << 16);
449 extensions->packedDepthStencil = true;
450 extensions->getProgramBinary = true;
451 extensions->rgb8rgba8 = true;
452 extensions->readFormatBGRA = true;
453 extensions->pixelBufferObject = false;
454 extensions->mapBuffer = false;
455 extensions->mapBufferRange = false;
Geoff Langcec35902014-04-16 10:52:36 -0400456
457 // ATI cards on XP have problems with non-power-of-two textures.
458 D3DADAPTER_IDENTIFIER9 adapterId = { 0 };
459 if (SUCCEEDED(d3d9->GetAdapterIdentifier(adapter, 0, &adapterId)))
460 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400461 extensions->textureNPOT = !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_POW2) &&
Geoff Langcec35902014-04-16 10:52:36 -0400462 !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) &&
463 !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) &&
Shannon Woods5af475e2014-10-20 18:30:17 -0400464 !(!isWindowsVistaOrGreater() && adapterId.VendorId == VENDOR_ID_AMD);
Geoff Langcec35902014-04-16 10:52:36 -0400465 }
466 else
467 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400468 extensions->textureNPOT = false;
Geoff Langcec35902014-04-16 10:52:36 -0400469 }
470
Geoff Langc0b9ef42014-07-02 10:02:37 -0400471 extensions->drawBuffers = false;
472 extensions->textureStorage = true;
Geoff Langcec35902014-04-16 10:52:36 -0400473
474 // Must support a minimum of 2:1 anisotropy for max anisotropy to be considered supported, per the spec
Geoff Langc0b9ef42014-07-02 10:02:37 -0400475 extensions->textureFilterAnisotropic = (deviceCaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) != 0 && deviceCaps.MaxAnisotropy >= 2;
476 extensions->maxTextureAnisotropy = static_cast<GLfloat>(deviceCaps.MaxAnisotropy);
Geoff Langcec35902014-04-16 10:52:36 -0400477
478 // Check occlusion query support by trying to create one
479 IDirect3DQuery9 *occlusionQuery = NULL;
Geoff Langc0b9ef42014-07-02 10:02:37 -0400480 extensions->occlusionQueryBoolean = SUCCEEDED(device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery)) && occlusionQuery;
Geoff Langcec35902014-04-16 10:52:36 -0400481 SafeRelease(occlusionQuery);
482
483 // Check event query support by trying to create one
484 IDirect3DQuery9 *eventQuery = NULL;
Geoff Langc0b9ef42014-07-02 10:02:37 -0400485 extensions->fence = SUCCEEDED(device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery)) && eventQuery;
Geoff Langcec35902014-04-16 10:52:36 -0400486 SafeRelease(eventQuery);
487
Geoff Langc0b9ef42014-07-02 10:02:37 -0400488 extensions->timerQuery = false; // Unimplemented
489 extensions->robustness = true;
490 extensions->blendMinMax = true;
491 extensions->framebufferBlit = true;
492 extensions->framebufferMultisample = true;
Geoff Lang5f4c4632014-07-03 13:46:52 -0400493 extensions->maxSamples = maxSamples;
Geoff Langc0b9ef42014-07-02 10:02:37 -0400494 extensions->instancedArrays = deviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0);
495 extensions->packReverseRowOrder = true;
496 extensions->standardDerivatives = (deviceCaps.PS20Caps.Caps & D3DPS20CAPS_GRADIENTINSTRUCTIONS) != 0;
497 extensions->shaderTextureLOD = true;
498 extensions->fragDepth = true;
499 extensions->textureUsage = true;
500 extensions->translatedShaderSource = true;
501 extensions->colorBufferFloat = false;
Geoff Langcec35902014-04-16 10:52:36 -0400502}
503
504}
505
Geoff Lang91fa9ce2014-07-04 17:30:27 -0400506namespace d3d9
507{
508
509GLuint ComputeBlockSize(D3DFORMAT format, GLuint width, GLuint height)
510{
511 const D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(format);
512 GLuint numBlocksWide = (width + d3dFormatInfo.blockWidth - 1) / d3dFormatInfo.blockWidth;
513 GLuint numBlocksHight = (height + d3dFormatInfo.blockHeight - 1) / d3dFormatInfo.blockHeight;
514 return (d3dFormatInfo.pixelBytes * numBlocksWide * numBlocksHight);
515}
516
517void MakeValidSize(bool isImage, D3DFORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset)
518{
519 const D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(format);
520
521 int upsampleCount = 0;
522 // Don't expand the size of full textures that are at least (blockWidth x blockHeight) already.
523 if (isImage || *requestWidth < static_cast<GLsizei>(d3dFormatInfo.blockWidth) ||
524 *requestHeight < static_cast<GLsizei>(d3dFormatInfo.blockHeight))
525 {
526 while (*requestWidth % d3dFormatInfo.blockWidth != 0 || *requestHeight % d3dFormatInfo.blockHeight != 0)
527 {
528 *requestWidth <<= 1;
529 *requestHeight <<= 1;
530 upsampleCount++;
531 }
532 }
533 *levelOffset = upsampleCount;
534}
535
Jamie Madill9f0b42a2014-09-12 10:25:27 -0400536RenderTarget9 *GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment)
537{
538 RenderTarget *renderTarget = rx::GetAttachmentRenderTarget(attachment);
539 return RenderTarget9::makeRenderTarget9(renderTarget);
540}
541
Geoff Lang91fa9ce2014-07-04 17:30:27 -0400542}
543
shannonwoods@chromium.orged0adcf2013-05-30 00:08:20 +0000544}