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.
7 // renderer9_utils.cpp: Conversion functions and other utility routines
8 // specific to the D3D9 renderer.
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"
16 #include "common/mathutil.h"
17 #include "common/debug.h"
19 #include "third_party/systeminfo/SystemInfo.h"
27 D3DCMPFUNC ConvertComparison(GLenum comparison)
29 D3DCMPFUNC d3dComp = D3DCMP_ALWAYS;
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();
46 D3DCOLOR ConvertColor(gl::ColorF color)
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));
54 D3DBLEND ConvertBlendFunc(GLenum blend)
56 D3DBLEND d3dBlend = D3DBLEND_ZERO;
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();
81 D3DBLENDOP ConvertBlendOp(GLenum blendOp)
83 D3DBLENDOP d3dBlendOp = D3DBLENDOP_ADD;
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();
98 D3DSTENCILOP ConvertStencilOp(GLenum stencilOp)
100 D3DSTENCILOP d3dStencilOp = D3DSTENCILOP_KEEP;
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();
118 D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap)
120 D3DTEXTUREADDRESS d3dWrap = D3DTADDRESS_WRAP;
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();
133 D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace)
135 D3DCULL cull = D3DCULL_CCW;
139 cull = (frontFace == GL_CCW ? D3DCULL_CW : D3DCULL_CCW);
142 cull = (frontFace == GL_CCW ? D3DCULL_CCW : D3DCULL_CW);
144 case GL_FRONT_AND_BACK:
145 cull = D3DCULL_NONE; // culling will be handled during draw
147 default: UNREACHABLE();
153 D3DCUBEMAP_FACES ConvertCubeFace(GLenum cubeFace)
155 D3DCUBEMAP_FACES face = D3DCUBEMAP_FACE_POSITIVE_X;
159 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
160 face = D3DCUBEMAP_FACE_POSITIVE_X;
162 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
163 face = D3DCUBEMAP_FACE_NEGATIVE_X;
165 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
166 face = D3DCUBEMAP_FACE_POSITIVE_Y;
168 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
169 face = D3DCUBEMAP_FACE_NEGATIVE_Y;
171 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
172 face = D3DCUBEMAP_FACE_POSITIVE_Z;
174 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
175 face = D3DCUBEMAP_FACE_NEGATIVE_Z;
177 default: UNREACHABLE();
183 DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha)
185 return (red ? D3DCOLORWRITEENABLE_RED : 0) |
186 (green ? D3DCOLORWRITEENABLE_GREEN : 0) |
187 (blue ? D3DCOLORWRITEENABLE_BLUE : 0) |
188 (alpha ? D3DCOLORWRITEENABLE_ALPHA : 0);
191 D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter, float maxAnisotropy)
193 if (maxAnisotropy > 1.0f)
195 return D3DTEXF_ANISOTROPIC;
198 D3DTEXTUREFILTERTYPE d3dMagFilter = D3DTEXF_POINT;
201 case GL_NEAREST: d3dMagFilter = D3DTEXF_POINT; break;
202 case GL_LINEAR: d3dMagFilter = D3DTEXF_LINEAR; break;
203 default: UNREACHABLE();
209 void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter, float maxAnisotropy)
214 *d3dMinFilter = D3DTEXF_POINT;
215 *d3dMipFilter = D3DTEXF_NONE;
218 *d3dMinFilter = D3DTEXF_LINEAR;
219 *d3dMipFilter = D3DTEXF_NONE;
221 case GL_NEAREST_MIPMAP_NEAREST:
222 *d3dMinFilter = D3DTEXF_POINT;
223 *d3dMipFilter = D3DTEXF_POINT;
225 case GL_LINEAR_MIPMAP_NEAREST:
226 *d3dMinFilter = D3DTEXF_LINEAR;
227 *d3dMipFilter = D3DTEXF_POINT;
229 case GL_NEAREST_MIPMAP_LINEAR:
230 *d3dMinFilter = D3DTEXF_POINT;
231 *d3dMipFilter = D3DTEXF_LINEAR;
233 case GL_LINEAR_MIPMAP_LINEAR:
234 *d3dMinFilter = D3DTEXF_LINEAR;
235 *d3dMipFilter = D3DTEXF_LINEAR;
238 *d3dMinFilter = D3DTEXF_POINT;
239 *d3dMipFilter = D3DTEXF_NONE;
243 if (maxAnisotropy > 1.0f)
245 *d3dMinFilter = D3DTEXF_ANISOTROPIC;
249 D3DMULTISAMPLE_TYPE GetMultisampleType(GLuint samples)
251 return (samples > 1) ? static_cast<D3DMULTISAMPLE_TYPE>(samples) : D3DMULTISAMPLE_NONE;
259 GLsizei GetSamplesCount(D3DMULTISAMPLE_TYPE type)
261 return (type != D3DMULTISAMPLE_NONMASKABLE) ? type : 0;
264 bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format)
266 GLenum internalFormat = d3d9::GetD3DFormatInfo(d3dformat).internalFormat;
267 GLenum convertedFormat = gl::GetInternalFormatInfo(internalFormat).format;
268 return convertedFormat == format;
271 static gl::TextureCaps GenerateTextureFormatCaps(GLenum internalFormat, IDirect3D9 *d3d9, D3DDEVTYPE deviceType,
272 UINT adapter, D3DFORMAT adapterFormat)
274 gl::TextureCaps textureCaps;
276 const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalFormat);
277 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
278 if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
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));
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));
294 textureCaps.sampleCounts.insert(1);
295 for (size_t i = D3DMULTISAMPLE_2_SAMPLES; i <= D3DMULTISAMPLE_16_SAMPLES; i++)
297 D3DMULTISAMPLE_TYPE multisampleType = D3DMULTISAMPLE_TYPE(i);
299 HRESULT result = d3d9->CheckDeviceMultiSampleType(adapter, deviceType, d3dFormatInfo.renderFormat, TRUE, multisampleType, NULL);
300 if (SUCCEEDED(result))
302 textureCaps.sampleCounts.insert(i);
309 void GenerateCaps(IDirect3D9 *d3d9, IDirect3DDevice9 *device, D3DDEVTYPE deviceType, UINT adapter, gl::Caps *caps,
310 gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions)
313 if (FAILED(d3d9->GetDeviceCaps(adapter, deviceType, &deviceCaps)))
315 // Can't continue with out device caps
319 D3DDISPLAYMODE currentDisplayMode;
320 d3d9->GetAdapterDisplayMode(adapter, ¤tDisplayMode);
322 GLuint maxSamples = 0;
323 const gl::FormatSet &allFormats = gl::GetAllSizedInternalFormats();
324 for (gl::FormatSet::const_iterator internalFormat = allFormats.begin(); internalFormat != allFormats.end(); ++internalFormat)
326 gl::TextureCaps textureCaps = GenerateTextureFormatCaps(*internalFormat, d3d9, deviceType, adapter,
327 currentDisplayMode.Format);
328 textureCapsMap->insert(*internalFormat, textureCaps);
330 maxSamples = std::max(maxSamples, textureCaps.getMaxSamples());
332 if (gl::GetInternalFormatInfo(*internalFormat).compressed)
334 caps->compressedTextureFormats.push_back(*internalFormat);
338 // GL core feature limits
339 caps->maxElementIndex = static_cast<GLint64>(std::numeric_limits<unsigned int>::max());
341 // 3D textures are unimplemented in D3D9
342 caps->max3DTextureSize = 1;
344 // Only one limit in GL, use the minimum dimension
345 caps->max2DTextureSize = std::min(deviceCaps.MaxTextureWidth, deviceCaps.MaxTextureHeight);
347 // D3D treats cube maps as a special case of 2D textures
348 caps->maxCubeMapTextureSize = caps->max2DTextureSize;
350 // Array textures are not available in D3D9
351 caps->maxArrayTextureLayers = 1;
354 caps->maxLODBias = 0.0f;
356 // No specific limits on render target size, maximum 2D texture size is equivalent
357 caps->maxRenderbufferSize = caps->max2DTextureSize;
359 // Draw buffers are not supported in D3D9
360 caps->maxDrawBuffers = 1;
361 caps->maxColorAttachments = 1;
363 // No specific limits on viewport size, maximum 2D texture size is equivalent
364 caps->maxViewportWidth = caps->max2DTextureSize;
365 caps->maxViewportHeight = caps->maxViewportWidth;
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);
371 // Wide lines not supported
372 caps->minAliasedLineWidth = 1.0f;
373 caps->maxAliasedLineWidth = 1.0f;
375 // Primitive count limits (unused in ES2)
376 caps->maxElementsIndices = 0;
377 caps->maxElementsVertices = 0;
379 // Program and shader binary formats (no supported shader binary formats)
380 caps->programBinaryFormats.push_back(GL_PROGRAM_BINARY_ANGLE);
382 // WaitSync is ES3-only, set to zero
383 caps->maxServerWaitTimeout = 0;
385 // Vertex shader limits
386 caps->maxVertexAttributes = 16;
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;
393 caps->maxVertexUniformBlocks = 0;
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;
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)))
406 const size_t MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 = 4;
407 caps->maxVertexTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS_VTF_SM3;
411 caps->maxVertexTextureImageUnits = 0;
414 // Fragment shader limits
415 const size_t reservedPixelUniformVectors = 3; // dx_ViewCoords, dx_DepthFront and dx_DepthRange.
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;
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;
437 // Aggregate shader limits
438 caps->maxVaryingVectors = caps->maxVertexOutputComponents / 4;
439 caps->maxCombinedTextureImageUnits = caps->maxVertexTextureImageUnits + caps->maxTextureImageUnits;
441 // Transform feedback limits
442 caps->maxTransformFeedbackInterleavedComponents = 0;
443 caps->maxTransformFeedbackSeparateAttributes = 0;
444 caps->maxTransformFeedbackSeparateComponents = 0;
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;
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)))
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);
468 extensions->textureNPOT = false;
471 extensions->drawBuffers = false;
472 extensions->textureStorage = true;
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);
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);
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);
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;
509 GLuint ComputeBlockSize(D3DFORMAT format, GLuint width, GLuint height)
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);
517 void MakeValidSize(bool isImage, D3DFORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset)
519 const D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(format);
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))
526 while (*requestWidth % d3dFormatInfo.blockWidth != 0 || *requestHeight % d3dFormatInfo.blockHeight != 0)
529 *requestHeight <<= 1;
533 *levelOffset = upsampleCount;
536 RenderTarget9 *GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment)
538 RenderTarget *renderTarget = rx::GetAttachmentRenderTarget(attachment);
539 return RenderTarget9::makeRenderTarget9(renderTarget);