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, ¤tDisplayMode); 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