d6f950a5b6237f2e21f9c7fa83d32e10b95f50bd
[platform/framework/web/crosswalk.git] / src / third_party / angle / src / libGLESv2 / renderer / d3d / d3d9 / renderer9_utils.cpp
1 //
2 // Copyright (c) 2002-2014 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 // renderer9_utils.cpp: Conversion functions and other utility routines
8 // specific to the D3D9 renderer.
9
10 #include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h"
11 #include "libGLESv2/renderer/d3d/d3d9/formatutils9.h"
12 #include "libGLESv2/formatutils.h"
13 #include "libGLESv2/Framebuffer.h"
14 #include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h"
15
16 #include "common/mathutil.h"
17 #include "common/debug.h"
18
19 #include "third_party/systeminfo/SystemInfo.h"
20
21 namespace rx
22 {
23
24 namespace gl_d3d9
25 {
26
27 D3DCMPFUNC 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
46 D3DCOLOR ConvertColor(gl::ColorF color)
47 {
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
54 D3DBLEND 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
81 D3DBLENDOP 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;
90       case GL_MIN_EXT:               d3dBlendOp = D3DBLENDOP_MIN;         break;
91       case GL_MAX_EXT:               d3dBlendOp = D3DBLENDOP_MAX;         break;
92       default: UNREACHABLE();
93     }
94
95     return d3dBlendOp;
96 }
97
98 D3DSTENCILOP 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
118 D3DTEXTUREADDRESS 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
133 D3DCULL 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
153 D3DCUBEMAP_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
183 DWORD 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
191 D3DTEXTUREFILTERTYPE 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
209 void 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
249 D3DMULTISAMPLE_TYPE GetMultisampleType(GLuint samples)
250 {
251     return (samples > 1) ? static_cast<D3DMULTISAMPLE_TYPE>(samples) : D3DMULTISAMPLE_NONE;
252 }
253
254 }
255
256 namespace d3d9_gl
257 {
258
259 GLsizei GetSamplesCount(D3DMULTISAMPLE_TYPE type)
260 {
261     return (type != D3DMULTISAMPLE_NONMASKABLE) ? type : 0;
262 }
263
264 bool 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
271 static gl::TextureCaps GenerateTextureFormatCaps(GLenum internalFormat, IDirect3D9 *d3d9, D3DDEVTYPE deviceType,
272                                                  UINT adapter, D3DFORMAT adapterFormat)
273 {
274     gl::TextureCaps textureCaps;
275
276     const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalFormat);
277     const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
278     if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
279     {
280         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));
284     }
285     else
286     {
287         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));
292     }
293
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
299         HRESULT result = d3d9->CheckDeviceMultiSampleType(adapter, deviceType, d3dFormatInfo.renderFormat, TRUE, multisampleType, NULL);
300         if (SUCCEEDED(result))
301         {
302             textureCaps.sampleCounts.insert(i);
303         }
304     }
305
306     return textureCaps;
307 }
308
309 void GenerateCaps(IDirect3D9 *d3d9, IDirect3DDevice9 *device, D3DDEVTYPE deviceType, UINT adapter, gl::Caps *caps,
310                   gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions)
311 {
312     D3DCAPS9 deviceCaps;
313     if (FAILED(d3d9->GetDeviceCaps(adapter, deviceType, &deviceCaps)))
314     {
315         // Can't continue with out device caps
316         return;
317     }
318
319     D3DDISPLAYMODE currentDisplayMode;
320     d3d9->GetAdapterDisplayMode(adapter, &currentDisplayMode);
321
322     GLuint maxSamples = 0;
323     const gl::FormatSet &allFormats = gl::GetAllSizedInternalFormats();
324     for (gl::FormatSet::const_iterator internalFormat = allFormats.begin(); internalFormat != allFormats.end(); ++internalFormat)
325     {
326         gl::TextureCaps textureCaps = GenerateTextureFormatCaps(*internalFormat, d3d9, deviceType, adapter,
327                                                                 currentDisplayMode.Format);
328         textureCapsMap->insert(*internalFormat, textureCaps);
329
330         maxSamples = std::max(maxSamples, textureCaps.getMaxSamples());
331
332         if (gl::GetInternalFormatInfo(*internalFormat).compressed)
333         {
334             caps->compressedTextureFormats.push_back(*internalFormat);
335         }
336     }
337
338     // GL core feature limits
339     caps->maxElementIndex = static_cast<GLint64>(std::numeric_limits<unsigned int>::max());
340
341     // 3D textures are unimplemented in D3D9
342     caps->max3DTextureSize = 1;
343
344     // Only one limit in GL, use the minimum dimension
345     caps->max2DTextureSize = std::min(deviceCaps.MaxTextureWidth, deviceCaps.MaxTextureHeight);
346
347     // D3D treats cube maps as a special case of 2D textures
348     caps->maxCubeMapTextureSize = caps->max2DTextureSize;
349
350     // Array textures are not available in D3D9
351     caps->maxArrayTextureLayers = 1;
352
353     // ES3-only feature
354     caps->maxLODBias = 0.0f;
355
356     // No specific limits on render target size, maximum 2D texture size is equivalent
357     caps->maxRenderbufferSize = caps->max2DTextureSize;
358
359     // Draw buffers are not supported in D3D9
360     caps->maxDrawBuffers = 1;
361     caps->maxColorAttachments = 1;
362
363     // No specific limits on viewport size, maximum 2D texture size is equivalent
364     caps->maxViewportWidth = caps->max2DTextureSize;
365     caps->maxViewportHeight = caps->maxViewportWidth;
366
367     // Point size is clamped to 1.0f when the shader model is less than 3
368     caps->minAliasedPointSize = 1.0f;
369     caps->maxAliasedPointSize = ((D3DSHADER_VERSION_MAJOR(deviceCaps.PixelShaderVersion) >= 3) ? deviceCaps.MaxPointSize : 1.0f);
370
371     // Wide lines not supported
372     caps->minAliasedLineWidth = 1.0f;
373     caps->maxAliasedLineWidth = 1.0f;
374
375     // 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
385     // 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
428     // 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;
439     caps->maxCombinedTextureImageUnits = caps->maxVertexTextureImageUnits + caps->maxTextureImageUnits;
440
441     // Transform feedback limits
442     caps->maxTransformFeedbackInterleavedComponents = 0;
443     caps->maxTransformFeedbackSeparateAttributes = 0;
444     caps->maxTransformFeedbackSeparateComponents = 0;
445
446     // GL extension support
447     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;
456
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     {
461         extensions->textureNPOT = !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_POW2) &&
462                                       !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) &&
463                                       !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) &&
464                                       !(isWindowsVistaOrGreater() && adapterId.VendorId == VENDOR_ID_AMD);
465     }
466     else
467     {
468         extensions->textureNPOT = false;
469     }
470
471     extensions->drawBuffers = false;
472     extensions->textureStorage = true;
473
474     // Must support a minimum of 2:1 anisotropy for max anisotropy to be considered supported, per the spec
475     extensions->textureFilterAnisotropic = (deviceCaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) != 0 && deviceCaps.MaxAnisotropy >= 2;
476     extensions->maxTextureAnisotropy = static_cast<GLfloat>(deviceCaps.MaxAnisotropy);
477
478     // Check occlusion query support by trying to create one
479     IDirect3DQuery9 *occlusionQuery = NULL;
480     extensions->occlusionQueryBoolean = SUCCEEDED(device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery)) && occlusionQuery;
481     SafeRelease(occlusionQuery);
482
483     // Check event query support by trying to create one
484     IDirect3DQuery9 *eventQuery = NULL;
485     extensions->fence = SUCCEEDED(device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery)) && eventQuery;
486     SafeRelease(eventQuery);
487
488     extensions->timerQuery = false; // Unimplemented
489     extensions->robustness = true;
490     extensions->blendMinMax = true;
491     extensions->framebufferBlit = true;
492     extensions->framebufferMultisample = true;
493     extensions->maxSamples = maxSamples;
494     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;
502 }
503
504 }
505
506 namespace d3d9
507 {
508
509 GLuint 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
517 void 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
536 RenderTarget9 *GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment)
537 {
538     RenderTarget *renderTarget = rx::GetAttachmentRenderTarget(attachment);
539     return RenderTarget9::makeRenderTarget9(renderTarget);
540 }
541
542 }
543
544 }