Home | History | Annotate | Download | only in d3d9
      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 }
    545