daniel@transgaming.com | d8e3656 | 2012-10-31 19:52:19 +0000 | [diff] [blame] | 1 | // |
Geoff Lang | cec3590 | 2014-04-16 10:52:36 -0400 | [diff] [blame] | 2 | // Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. |
daniel@transgaming.com | d8e3656 | 2012-10-31 19:52:19 +0000 | [diff] [blame] | 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 | |
Brandon Jones | c7a4104 | 2014-06-23 12:03:25 -0700 | [diff] [blame] | 10 | #include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" |
| 11 | #include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" |
Geoff Lang | cec3590 | 2014-04-16 10:52:36 -0400 | [diff] [blame] | 12 | #include "libGLESv2/formatutils.h" |
Jamie Madill | 9f0b42a | 2014-09-12 10:25:27 -0400 | [diff] [blame] | 13 | #include "libGLESv2/Framebuffer.h" |
| 14 | #include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h" |
daniel@transgaming.com | d8e3656 | 2012-10-31 19:52:19 +0000 | [diff] [blame] | 15 | |
Geoff Lang | 0b7eef7 | 2014-06-12 14:10:47 -0400 | [diff] [blame] | 16 | #include "common/mathutil.h" |
daniel@transgaming.com | d8e3656 | 2012-10-31 19:52:19 +0000 | [diff] [blame] | 17 | #include "common/debug.h" |
| 18 | |
Geoff Lang | cec3590 | 2014-04-16 10:52:36 -0400 | [diff] [blame] | 19 | #include "third_party/systeminfo/SystemInfo.h" |
| 20 | |
shannonwoods@chromium.org | ed0adcf | 2013-05-30 00:08:20 +0000 | [diff] [blame] | 21 | namespace rx |
| 22 | { |
| 23 | |
daniel@transgaming.com | 682a37c | 2012-11-28 19:34:44 +0000 | [diff] [blame] | 24 | namespace gl_d3d9 |
daniel@transgaming.com | d8e3656 | 2012-10-31 19:52:19 +0000 | [diff] [blame] | 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 | |
Geoff Lang | 2a64ee4 | 2013-05-31 11:22:40 -0400 | [diff] [blame] | 46 | D3DCOLOR ConvertColor(gl::ColorF color) |
daniel@transgaming.com | d8e3656 | 2012-10-31 19:52:19 +0000 | [diff] [blame] | 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; |
Geoff Lang | 496123f | 2014-02-12 11:33:51 -0500 | [diff] [blame] | 90 | case GL_MIN_EXT: d3dBlendOp = D3DBLENDOP_MIN; break; |
| 91 | case GL_MAX_EXT: d3dBlendOp = D3DBLENDOP_MAX; break; |
daniel@transgaming.com | d8e3656 | 2012-10-31 19:52:19 +0000 | [diff] [blame] | 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 | |
Geoff Lang | 91fa9ce | 2014-07-04 17:30:27 -0400 | [diff] [blame] | 249 | D3DMULTISAMPLE_TYPE GetMultisampleType(GLuint samples) |
| 250 | { |
| 251 | return (samples > 1) ? static_cast<D3DMULTISAMPLE_TYPE>(samples) : D3DMULTISAMPLE_NONE; |
| 252 | } |
| 253 | |
daniel@transgaming.com | d8e3656 | 2012-10-31 19:52:19 +0000 | [diff] [blame] | 254 | } |
shannonwoods@chromium.org | ed0adcf | 2013-05-30 00:08:20 +0000 | [diff] [blame] | 255 | |
Geoff Lang | cec3590 | 2014-04-16 10:52:36 -0400 | [diff] [blame] | 256 | namespace d3d9_gl |
| 257 | { |
| 258 | |
Geoff Lang | 91fa9ce | 2014-07-04 17:30:27 -0400 | [diff] [blame] | 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 | |
Geoff Lang | e4a492b | 2014-06-19 14:14:41 -0400 | [diff] [blame] | 271 | static gl::TextureCaps GenerateTextureFormatCaps(GLenum internalFormat, IDirect3D9 *d3d9, D3DDEVTYPE deviceType, |
Geoff Lang | cec3590 | 2014-04-16 10:52:36 -0400 | [diff] [blame] | 272 | UINT adapter, D3DFORMAT adapterFormat) |
| 273 | { |
| 274 | gl::TextureCaps textureCaps; |
| 275 | |
Geoff Lang | 91fa9ce | 2014-07-04 17:30:27 -0400 | [diff] [blame] | 276 | const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalFormat); |
| 277 | const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); |
Geoff Lang | 5d60138 | 2014-07-22 15:14:06 -0400 | [diff] [blame] | 278 | if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) |
Geoff Lang | 6cf8e1b | 2014-07-03 13:03:57 -0400 | [diff] [blame] | 279 | { |
Geoff Lang | 91fa9ce | 2014-07-04 17:30:27 -0400 | [diff] [blame] | 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)); |
Geoff Lang | 6cf8e1b | 2014-07-03 13:03:57 -0400 | [diff] [blame] | 284 | } |
| 285 | else |
| 286 | { |
Geoff Lang | 91fa9ce | 2014-07-04 17:30:27 -0400 | [diff] [blame] | 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)); |
Geoff Lang | 6cf8e1b | 2014-07-03 13:03:57 -0400 | [diff] [blame] | 292 | } |
Geoff Lang | cec3590 | 2014-04-16 10:52:36 -0400 | [diff] [blame] | 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 | |
Geoff Lang | 91fa9ce | 2014-07-04 17:30:27 -0400 | [diff] [blame] | 299 | HRESULT result = d3d9->CheckDeviceMultiSampleType(adapter, deviceType, d3dFormatInfo.renderFormat, TRUE, multisampleType, NULL); |
Geoff Lang | cec3590 | 2014-04-16 10:52:36 -0400 | [diff] [blame] | 300 | if (SUCCEEDED(result)) |
| 301 | { |
| 302 | textureCaps.sampleCounts.insert(i); |
| 303 | } |
| 304 | } |
| 305 | |
| 306 | return textureCaps; |
| 307 | } |
| 308 | |
Geoff Lang | c0b9ef4 | 2014-07-02 10:02:37 -0400 | [diff] [blame] | 309 | void GenerateCaps(IDirect3D9 *d3d9, IDirect3DDevice9 *device, D3DDEVTYPE deviceType, UINT adapter, gl::Caps *caps, |
| 310 | gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions) |
Geoff Lang | cec3590 | 2014-04-16 10:52:36 -0400 | [diff] [blame] | 311 | { |
Geoff Lang | cec3590 | 2014-04-16 10:52:36 -0400 | [diff] [blame] | 312 | D3DCAPS9 deviceCaps; |
| 313 | if (FAILED(d3d9->GetDeviceCaps(adapter, deviceType, &deviceCaps))) |
| 314 | { |
| 315 | // Can't continue with out device caps |
Geoff Lang | c0b9ef4 | 2014-07-02 10:02:37 -0400 | [diff] [blame] | 316 | return; |
Geoff Lang | cec3590 | 2014-04-16 10:52:36 -0400 | [diff] [blame] | 317 | } |
| 318 | |
| 319 | D3DDISPLAYMODE currentDisplayMode; |
| 320 | d3d9->GetAdapterDisplayMode(adapter, ¤tDisplayMode); |
| 321 | |
Geoff Lang | 5f4c463 | 2014-07-03 13:46:52 -0400 | [diff] [blame] | 322 | GLuint maxSamples = 0; |
Geoff Lang | e4a492b | 2014-06-19 14:14:41 -0400 | [diff] [blame] | 323 | const gl::FormatSet &allFormats = gl::GetAllSizedInternalFormats(); |
Geoff Lang | cec3590 | 2014-04-16 10:52:36 -0400 | [diff] [blame] | 324 | for (gl::FormatSet::const_iterator internalFormat = allFormats.begin(); internalFormat != allFormats.end(); ++internalFormat) |
| 325 | { |
Geoff Lang | c0b9ef4 | 2014-07-02 10:02:37 -0400 | [diff] [blame] | 326 | gl::TextureCaps textureCaps = GenerateTextureFormatCaps(*internalFormat, d3d9, deviceType, adapter, |
| 327 | currentDisplayMode.Format); |
| 328 | textureCapsMap->insert(*internalFormat, textureCaps); |
Geoff Lang | 5f4c463 | 2014-07-03 13:46:52 -0400 | [diff] [blame] | 329 | |
| 330 | maxSamples = std::max(maxSamples, textureCaps.getMaxSamples()); |
Geoff Lang | 900013c | 2014-07-07 11:32:19 -0400 | [diff] [blame] | 331 | |
| 332 | if (gl::GetInternalFormatInfo(*internalFormat).compressed) |
| 333 | { |
| 334 | caps->compressedTextureFormats.push_back(*internalFormat); |
| 335 | } |
Geoff Lang | cec3590 | 2014-04-16 10:52:36 -0400 | [diff] [blame] | 336 | } |
| 337 | |
Geoff Lang | aae65a4 | 2014-05-26 12:43:44 -0400 | [diff] [blame] | 338 | // GL core feature limits |
Geoff Lang | c0b9ef4 | 2014-07-02 10:02:37 -0400 | [diff] [blame] | 339 | caps->maxElementIndex = static_cast<GLint64>(std::numeric_limits<unsigned int>::max()); |
Geoff Lang | aae65a4 | 2014-05-26 12:43:44 -0400 | [diff] [blame] | 340 | |
| 341 | // 3D textures are unimplemented in D3D9 |
Geoff Lang | c0b9ef4 | 2014-07-02 10:02:37 -0400 | [diff] [blame] | 342 | caps->max3DTextureSize = 1; |
Geoff Lang | aae65a4 | 2014-05-26 12:43:44 -0400 | [diff] [blame] | 343 | |
| 344 | // Only one limit in GL, use the minimum dimension |
Geoff Lang | c0b9ef4 | 2014-07-02 10:02:37 -0400 | [diff] [blame] | 345 | caps->max2DTextureSize = std::min(deviceCaps.MaxTextureWidth, deviceCaps.MaxTextureHeight); |
Geoff Lang | aae65a4 | 2014-05-26 12:43:44 -0400 | [diff] [blame] | 346 | |
| 347 | // D3D treats cube maps as a special case of 2D textures |
Geoff Lang | c0b9ef4 | 2014-07-02 10:02:37 -0400 | [diff] [blame] | 348 | caps->maxCubeMapTextureSize = caps->max2DTextureSize; |
Geoff Lang | aae65a4 | 2014-05-26 12:43:44 -0400 | [diff] [blame] | 349 | |
| 350 | // Array textures are not available in D3D9 |
Geoff Lang | c0b9ef4 | 2014-07-02 10:02:37 -0400 | [diff] [blame] | 351 | caps->maxArrayTextureLayers = 1; |
Geoff Lang | aae65a4 | 2014-05-26 12:43:44 -0400 | [diff] [blame] | 352 | |
| 353 | // ES3-only feature |
Geoff Lang | c0b9ef4 | 2014-07-02 10:02:37 -0400 | [diff] [blame] | 354 | caps->maxLODBias = 0.0f; |
Geoff Lang | aae65a4 | 2014-05-26 12:43:44 -0400 | [diff] [blame] | 355 | |
| 356 | // No specific limits on render target size, maximum 2D texture size is equivalent |
Geoff Lang | c0b9ef4 | 2014-07-02 10:02:37 -0400 | [diff] [blame] | 357 | caps->maxRenderbufferSize = caps->max2DTextureSize; |
Geoff Lang | aae65a4 | 2014-05-26 12:43:44 -0400 | [diff] [blame] | 358 | |
| 359 | // Draw buffers are not supported in D3D9 |
Geoff Lang | c0b9ef4 | 2014-07-02 10:02:37 -0400 | [diff] [blame] | 360 | caps->maxDrawBuffers = 1; |
| 361 | caps->maxColorAttachments = 1; |
Geoff Lang | aae65a4 | 2014-05-26 12:43:44 -0400 | [diff] [blame] | 362 | |
| 363 | // No specific limits on viewport size, maximum 2D texture size is equivalent |
Geoff Lang | c0b9ef4 | 2014-07-02 10:02:37 -0400 | [diff] [blame] | 364 | caps->maxViewportWidth = caps->max2DTextureSize; |
| 365 | caps->maxViewportHeight = caps->maxViewportWidth; |
Geoff Lang | aae65a4 | 2014-05-26 12:43:44 -0400 | [diff] [blame] | 366 | |
| 367 | // Point size is clamped to 1.0f when the shader model is less than 3 |
Geoff Lang | c0b9ef4 | 2014-07-02 10:02:37 -0400 | [diff] [blame] | 368 | caps->minAliasedPointSize = 1.0f; |
| 369 | caps->maxAliasedPointSize = ((D3DSHADER_VERSION_MAJOR(deviceCaps.PixelShaderVersion) >= 3) ? deviceCaps.MaxPointSize : 1.0f); |
Geoff Lang | aae65a4 | 2014-05-26 12:43:44 -0400 | [diff] [blame] | 370 | |
| 371 | // Wide lines not supported |
Geoff Lang | c0b9ef4 | 2014-07-02 10:02:37 -0400 | [diff] [blame] | 372 | caps->minAliasedLineWidth = 1.0f; |
| 373 | caps->maxAliasedLineWidth = 1.0f; |
Geoff Lang | aae65a4 | 2014-05-26 12:43:44 -0400 | [diff] [blame] | 374 | |
Geoff Lang | 900013c | 2014-07-07 11:32:19 -0400 | [diff] [blame] | 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 | |
Geoff Lang | 301d161 | 2014-07-09 10:34:37 -0400 | [diff] [blame] | 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 | |
Geoff Lang | 3a61c32 | 2014-07-10 13:01:54 -0400 | [diff] [blame] | 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; |
Geoff Lang | 76b10c9 | 2014-09-05 16:28:14 -0400 | [diff] [blame] | 439 | caps->maxCombinedTextureImageUnits = caps->maxVertexTextureImageUnits + caps->maxTextureImageUnits; |
Geoff Lang | 3a61c32 | 2014-07-10 13:01:54 -0400 | [diff] [blame] | 440 | |
Geoff Lang | 05881a0 | 2014-07-10 14:05:30 -0400 | [diff] [blame] | 441 | // Transform feedback limits |
| 442 | caps->maxTransformFeedbackInterleavedComponents = 0; |
| 443 | caps->maxTransformFeedbackSeparateAttributes = 0; |
| 444 | caps->maxTransformFeedbackSeparateComponents = 0; |
| 445 | |
Geoff Lang | aae65a4 | 2014-05-26 12:43:44 -0400 | [diff] [blame] | 446 | // GL extension support |
Geoff Lang | c0b9ef4 | 2014-07-02 10:02:37 -0400 | [diff] [blame] | 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; |
Geoff Lang | cec3590 | 2014-04-16 10:52:36 -0400 | [diff] [blame] | 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 | { |
Geoff Lang | c0b9ef4 | 2014-07-02 10:02:37 -0400 | [diff] [blame] | 461 | extensions->textureNPOT = !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_POW2) && |
Geoff Lang | cec3590 | 2014-04-16 10:52:36 -0400 | [diff] [blame] | 462 | !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) && |
| 463 | !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) && |
Shannon Woods | 5af475e | 2014-10-20 18:30:17 -0400 | [diff] [blame] | 464 | !(!isWindowsVistaOrGreater() && adapterId.VendorId == VENDOR_ID_AMD); |
Geoff Lang | cec3590 | 2014-04-16 10:52:36 -0400 | [diff] [blame] | 465 | } |
| 466 | else |
| 467 | { |
Geoff Lang | c0b9ef4 | 2014-07-02 10:02:37 -0400 | [diff] [blame] | 468 | extensions->textureNPOT = false; |
Geoff Lang | cec3590 | 2014-04-16 10:52:36 -0400 | [diff] [blame] | 469 | } |
| 470 | |
Geoff Lang | c0b9ef4 | 2014-07-02 10:02:37 -0400 | [diff] [blame] | 471 | extensions->drawBuffers = false; |
| 472 | extensions->textureStorage = true; |
Geoff Lang | cec3590 | 2014-04-16 10:52:36 -0400 | [diff] [blame] | 473 | |
| 474 | // Must support a minimum of 2:1 anisotropy for max anisotropy to be considered supported, per the spec |
Geoff Lang | c0b9ef4 | 2014-07-02 10:02:37 -0400 | [diff] [blame] | 475 | extensions->textureFilterAnisotropic = (deviceCaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) != 0 && deviceCaps.MaxAnisotropy >= 2; |
| 476 | extensions->maxTextureAnisotropy = static_cast<GLfloat>(deviceCaps.MaxAnisotropy); |
Geoff Lang | cec3590 | 2014-04-16 10:52:36 -0400 | [diff] [blame] | 477 | |
| 478 | // Check occlusion query support by trying to create one |
| 479 | IDirect3DQuery9 *occlusionQuery = NULL; |
Geoff Lang | c0b9ef4 | 2014-07-02 10:02:37 -0400 | [diff] [blame] | 480 | extensions->occlusionQueryBoolean = SUCCEEDED(device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery)) && occlusionQuery; |
Geoff Lang | cec3590 | 2014-04-16 10:52:36 -0400 | [diff] [blame] | 481 | SafeRelease(occlusionQuery); |
| 482 | |
| 483 | // Check event query support by trying to create one |
| 484 | IDirect3DQuery9 *eventQuery = NULL; |
Geoff Lang | c0b9ef4 | 2014-07-02 10:02:37 -0400 | [diff] [blame] | 485 | extensions->fence = SUCCEEDED(device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery)) && eventQuery; |
Geoff Lang | cec3590 | 2014-04-16 10:52:36 -0400 | [diff] [blame] | 486 | SafeRelease(eventQuery); |
| 487 | |
Geoff Lang | c0b9ef4 | 2014-07-02 10:02:37 -0400 | [diff] [blame] | 488 | extensions->timerQuery = false; // Unimplemented |
| 489 | extensions->robustness = true; |
| 490 | extensions->blendMinMax = true; |
| 491 | extensions->framebufferBlit = true; |
| 492 | extensions->framebufferMultisample = true; |
Geoff Lang | 5f4c463 | 2014-07-03 13:46:52 -0400 | [diff] [blame] | 493 | extensions->maxSamples = maxSamples; |
Geoff Lang | c0b9ef4 | 2014-07-02 10:02:37 -0400 | [diff] [blame] | 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; |
Geoff Lang | cec3590 | 2014-04-16 10:52:36 -0400 | [diff] [blame] | 502 | } |
| 503 | |
| 504 | } |
| 505 | |
Geoff Lang | 91fa9ce | 2014-07-04 17:30:27 -0400 | [diff] [blame] | 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 | |
Jamie Madill | 9f0b42a | 2014-09-12 10:25:27 -0400 | [diff] [blame] | 536 | RenderTarget9 *GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment) |
| 537 | { |
| 538 | RenderTarget *renderTarget = rx::GetAttachmentRenderTarget(attachment); |
| 539 | return RenderTarget9::makeRenderTarget9(renderTarget); |
| 540 | } |
| 541 | |
Geoff Lang | 91fa9ce | 2014-07-04 17:30:27 -0400 | [diff] [blame] | 542 | } |
| 543 | |
shannonwoods@chromium.org | ed0adcf | 2013-05-30 00:08:20 +0000 | [diff] [blame] | 544 | } |