• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2012 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 // TextureStorage9.cpp: Implements the abstract rx::TextureStorage9 class and its concrete derived
8 // classes TextureStorage9_2D and TextureStorage9_Cube, which act as the interface to the
9 // D3D9 texture.
10 
11 #include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h"
12 
13 #include "common/utilities.h"
14 #include "libANGLE/Context.h"
15 #include "libANGLE/Texture.h"
16 #include "libANGLE/formatutils.h"
17 #include "libANGLE/renderer/d3d/EGLImageD3D.h"
18 #include "libANGLE/renderer/d3d/TextureD3D.h"
19 #include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h"
20 #include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
21 #include "libANGLE/renderer/d3d/d3d9/SwapChain9.h"
22 #include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
23 #include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
24 
25 namespace rx
26 {
TextureStorage9(Renderer9 * renderer,DWORD usage,const std::string & label)27 TextureStorage9::TextureStorage9(Renderer9 *renderer, DWORD usage, const std::string &label)
28     : TextureStorage(label),
29       mTopLevel(0),
30       mMipLevels(0),
31       mTextureWidth(0),
32       mTextureHeight(0),
33       mInternalFormat(GL_NONE),
34       mTextureFormat(D3DFMT_UNKNOWN),
35       mRenderer(renderer),
36       mD3DUsage(usage),
37       mD3DPool(mRenderer->getTexturePool(usage))
38 {}
39 
~TextureStorage9()40 TextureStorage9::~TextureStorage9() {}
41 
GetTextureUsage(GLenum internalformat,bool renderTarget)42 DWORD TextureStorage9::GetTextureUsage(GLenum internalformat, bool renderTarget)
43 {
44     DWORD d3dusage = 0;
45 
46     const gl::InternalFormat &formatInfo     = gl::GetSizedInternalFormatInfo(internalformat);
47     const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat);
48     if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
49     {
50         d3dusage |= D3DUSAGE_DEPTHSTENCIL;
51     }
52     else if (renderTarget && (d3dFormatInfo.renderFormat != D3DFMT_UNKNOWN))
53     {
54         d3dusage |= D3DUSAGE_RENDERTARGET;
55     }
56 
57     return d3dusage;
58 }
59 
isRenderTarget() const60 bool TextureStorage9::isRenderTarget() const
61 {
62     return (mD3DUsage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL)) != 0;
63 }
64 
isManaged() const65 bool TextureStorage9::isManaged() const
66 {
67     return (mD3DPool == D3DPOOL_MANAGED);
68 }
69 
supportsNativeMipmapFunction() const70 bool TextureStorage9::supportsNativeMipmapFunction() const
71 {
72     return false;
73 }
74 
getPool() const75 D3DPOOL TextureStorage9::getPool() const
76 {
77     return mD3DPool;
78 }
79 
getUsage() const80 DWORD TextureStorage9::getUsage() const
81 {
82     return mD3DUsage;
83 }
84 
getTopLevel() const85 int TextureStorage9::getTopLevel() const
86 {
87     return mTopLevel;
88 }
89 
getLevelCount() const90 int TextureStorage9::getLevelCount() const
91 {
92     return static_cast<int>(mMipLevels) - mTopLevel;
93 }
94 
setData(const gl::Context * context,const gl::ImageIndex & index,ImageD3D * image,const gl::Box * destBox,GLenum type,const gl::PixelUnpackState & unpack,const uint8_t * pixelData)95 angle::Result TextureStorage9::setData(const gl::Context *context,
96                                        const gl::ImageIndex &index,
97                                        ImageD3D *image,
98                                        const gl::Box *destBox,
99                                        GLenum type,
100                                        const gl::PixelUnpackState &unpack,
101                                        const uint8_t *pixelData)
102 {
103     ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
104     return angle::Result::Stop;
105 }
106 
TextureStorage9_2D(Renderer9 * renderer,SwapChain9 * swapchain,const std::string & label)107 TextureStorage9_2D::TextureStorage9_2D(Renderer9 *renderer,
108                                        SwapChain9 *swapchain,
109                                        const std::string &label)
110     : TextureStorage9(renderer, D3DUSAGE_RENDERTARGET, label)
111 {
112     IDirect3DTexture9 *surfaceTexture = swapchain->getOffscreenTexture();
113     mTexture                          = surfaceTexture;
114     mMipLevels                        = surfaceTexture->GetLevelCount();
115 
116     mInternalFormat = swapchain->getRenderTargetInternalFormat();
117 
118     D3DSURFACE_DESC surfaceDesc;
119     surfaceTexture->GetLevelDesc(0, &surfaceDesc);
120     mTextureWidth  = surfaceDesc.Width;
121     mTextureHeight = surfaceDesc.Height;
122     mTextureFormat = surfaceDesc.Format;
123 
124     mRenderTargets.resize(mMipLevels, nullptr);
125 }
126 
TextureStorage9_2D(Renderer9 * renderer,GLenum internalformat,bool renderTarget,GLsizei width,GLsizei height,int levels,const std::string & label)127 TextureStorage9_2D::TextureStorage9_2D(Renderer9 *renderer,
128                                        GLenum internalformat,
129                                        bool renderTarget,
130                                        GLsizei width,
131                                        GLsizei height,
132                                        int levels,
133                                        const std::string &label)
134     : TextureStorage9(renderer, GetTextureUsage(internalformat, renderTarget), label)
135 {
136     mTexture = nullptr;
137 
138     mInternalFormat = internalformat;
139 
140     const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat);
141     mTextureFormat                           = d3dFormatInfo.texFormat;
142 
143     d3d9::MakeValidSize(false, d3dFormatInfo.texFormat, &width, &height, &mTopLevel);
144     mTextureWidth  = width;
145     mTextureHeight = height;
146     mMipLevels     = mTopLevel + levels;
147 
148     mRenderTargets.resize(levels, nullptr);
149 }
150 
~TextureStorage9_2D()151 TextureStorage9_2D::~TextureStorage9_2D()
152 {
153     SafeRelease(mTexture);
154     for (RenderTargetD3D *renderTarget : mRenderTargets)
155     {
156         SafeDelete(renderTarget);
157     }
158 }
159 
160 // Increments refcount on surface.
161 // caller must Release() the returned surface
getSurfaceLevel(const gl::Context * context,gl::TextureTarget target,int level,bool dirty,IDirect3DSurface9 ** outSurface)162 angle::Result TextureStorage9_2D::getSurfaceLevel(const gl::Context *context,
163                                                   gl::TextureTarget target,
164                                                   int level,
165                                                   bool dirty,
166                                                   IDirect3DSurface9 **outSurface)
167 {
168     ASSERT(target == gl::TextureTarget::_2D);
169 
170     IDirect3DBaseTexture9 *baseTexture = nullptr;
171     ANGLE_TRY(getBaseTexture(context, &baseTexture));
172 
173     IDirect3DTexture9 *texture = static_cast<IDirect3DTexture9 *>(baseTexture);
174 
175     HRESULT result = texture->GetSurfaceLevel(level + mTopLevel, outSurface);
176     ANGLE_TRY_HR(GetImplAs<Context9>(context), result, "Failed to get the surface from a texture");
177 
178     // With managed textures the driver needs to be informed of updates to the lower mipmap levels
179     if (level + mTopLevel != 0 && isManaged() && dirty)
180     {
181         texture->AddDirtyRect(nullptr);
182     }
183 
184     return angle::Result::Continue;
185 }
186 
findRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT) const187 angle::Result TextureStorage9_2D::findRenderTarget(const gl::Context *context,
188                                                    const gl::ImageIndex &index,
189                                                    GLsizei samples,
190                                                    RenderTargetD3D **outRT) const
191 {
192     ASSERT(index.getLevelIndex() < getLevelCount());
193 
194     ASSERT(outRT);
195     *outRT = mRenderTargets[index.getLevelIndex()];
196     return angle::Result::Continue;
197 }
198 
getRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT)199 angle::Result TextureStorage9_2D::getRenderTarget(const gl::Context *context,
200                                                   const gl::ImageIndex &index,
201                                                   GLsizei samples,
202                                                   RenderTargetD3D **outRT)
203 {
204     ASSERT(index.getLevelIndex() < getLevelCount());
205 
206     if (!mRenderTargets[index.getLevelIndex()] && isRenderTarget())
207     {
208         IDirect3DBaseTexture9 *baseTexture = nullptr;
209         ANGLE_TRY(getBaseTexture(context, &baseTexture));
210 
211         IDirect3DSurface9 *surface = nullptr;
212         ANGLE_TRY(getSurfaceLevel(context, gl::TextureTarget::_2D, index.getLevelIndex(), false,
213                                   &surface));
214 
215         size_t textureMipLevel = mTopLevel + index.getLevelIndex();
216         size_t mipWidth        = std::max<size_t>(mTextureWidth >> textureMipLevel, 1u);
217         size_t mipHeight       = std::max<size_t>(mTextureHeight >> textureMipLevel, 1u);
218 
219         baseTexture->AddRef();
220         mRenderTargets[index.getLevelIndex()] = new TextureRenderTarget9(
221             baseTexture, textureMipLevel, surface, mInternalFormat, static_cast<GLsizei>(mipWidth),
222             static_cast<GLsizei>(mipHeight), 1, 0);
223     }
224 
225     ASSERT(outRT);
226     *outRT = mRenderTargets[index.getLevelIndex()];
227     return angle::Result::Continue;
228 }
229 
generateMipmap(const gl::Context * context,const gl::ImageIndex & sourceIndex,const gl::ImageIndex & destIndex)230 angle::Result TextureStorage9_2D::generateMipmap(const gl::Context *context,
231                                                  const gl::ImageIndex &sourceIndex,
232                                                  const gl::ImageIndex &destIndex)
233 {
234     angle::ComPtr<IDirect3DSurface9> upper = nullptr;
235     ANGLE_TRY(getSurfaceLevel(context, gl::TextureTarget::_2D, sourceIndex.getLevelIndex(), false,
236                               &upper));
237 
238     angle::ComPtr<IDirect3DSurface9> lower = nullptr;
239     ANGLE_TRY(
240         getSurfaceLevel(context, gl::TextureTarget::_2D, destIndex.getLevelIndex(), true, &lower));
241 
242     ASSERT(upper && lower);
243     return mRenderer->boxFilter(GetImplAs<Context9>(context), upper.Get(), lower.Get());
244 }
245 
getBaseTexture(const gl::Context * context,IDirect3DBaseTexture9 ** outTexture)246 angle::Result TextureStorage9_2D::getBaseTexture(const gl::Context *context,
247                                                  IDirect3DBaseTexture9 **outTexture)
248 {
249     // if the width or height is not positive this should be treated as an incomplete texture
250     // we handle that here by skipping the d3d texture creation
251     if (mTexture == nullptr && mTextureWidth > 0 && mTextureHeight > 0)
252     {
253         ASSERT(mMipLevels > 0);
254 
255         IDirect3DDevice9 *device = mRenderer->getDevice();
256         HRESULT result           = device->CreateTexture(static_cast<unsigned int>(mTextureWidth),
257                                                static_cast<unsigned int>(mTextureHeight),
258                                                static_cast<unsigned int>(mMipLevels), getUsage(),
259                                                mTextureFormat, getPool(), &mTexture, nullptr);
260         ANGLE_TRY_HR(GetImplAs<Context9>(context), result, "Failed to create 2D storage texture");
261     }
262 
263     *outTexture = mTexture;
264     return angle::Result::Continue;
265 }
266 
copyToStorage(const gl::Context * context,TextureStorage * destStorage)267 angle::Result TextureStorage9_2D::copyToStorage(const gl::Context *context,
268                                                 TextureStorage *destStorage)
269 {
270     ASSERT(destStorage);
271 
272     TextureStorage9_2D *dest9 = GetAs<TextureStorage9_2D>(destStorage);
273 
274     int levels = getLevelCount();
275     for (int i = 0; i < levels; ++i)
276     {
277         angle::ComPtr<IDirect3DSurface9> srcSurf = nullptr;
278         ANGLE_TRY(getSurfaceLevel(context, gl::TextureTarget::_2D, i, false, &srcSurf));
279 
280         angle::ComPtr<IDirect3DSurface9> dstSurf = nullptr;
281         ANGLE_TRY(dest9->getSurfaceLevel(context, gl::TextureTarget::_2D, i, true, &dstSurf));
282 
283         ANGLE_TRY(
284             mRenderer->copyToRenderTarget(context, dstSurf.Get(), srcSurf.Get(), isManaged()));
285     }
286 
287     return angle::Result::Continue;
288 }
289 
TextureStorage9_EGLImage(Renderer9 * renderer,EGLImageD3D * image,RenderTarget9 * renderTarget9,const std::string & label)290 TextureStorage9_EGLImage::TextureStorage9_EGLImage(Renderer9 *renderer,
291                                                    EGLImageD3D *image,
292                                                    RenderTarget9 *renderTarget9,
293                                                    const std::string &label)
294     : TextureStorage9(renderer, D3DUSAGE_RENDERTARGET, label), mImage(image)
295 {
296 
297     mInternalFormat = renderTarget9->getInternalFormat();
298     mTextureFormat  = renderTarget9->getD3DFormat();
299     mTextureWidth   = renderTarget9->getWidth();
300     mTextureHeight  = renderTarget9->getHeight();
301     mTopLevel       = static_cast<int>(renderTarget9->getTextureLevel());
302     mMipLevels      = mTopLevel + 1;
303 }
304 
~TextureStorage9_EGLImage()305 TextureStorage9_EGLImage::~TextureStorage9_EGLImage() {}
306 
getSurfaceLevel(const gl::Context * context,gl::TextureTarget target,int level,bool,IDirect3DSurface9 ** outSurface)307 angle::Result TextureStorage9_EGLImage::getSurfaceLevel(const gl::Context *context,
308                                                         gl::TextureTarget target,
309                                                         int level,
310                                                         bool,
311                                                         IDirect3DSurface9 **outSurface)
312 {
313     ASSERT(target == gl::TextureTarget::_2D);
314     ASSERT(level == 0);
315 
316     RenderTargetD3D *renderTargetD3D = nullptr;
317     ANGLE_TRY(mImage->getRenderTarget(context, &renderTargetD3D));
318 
319     RenderTarget9 *renderTarget9 = GetAs<RenderTarget9>(renderTargetD3D);
320 
321     *outSurface = renderTarget9->getSurface();
322     return angle::Result::Continue;
323 }
324 
findRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT) const325 angle::Result TextureStorage9_EGLImage::findRenderTarget(const gl::Context *context,
326                                                          const gl::ImageIndex &index,
327                                                          GLsizei samples,
328                                                          RenderTargetD3D **outRT) const
329 {
330     // Since the render target of a EGL image will be updated when orphaning, trying to find a cache
331     // of it can be rarely useful.
332     ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
333     return angle::Result::Stop;
334 }
335 
getRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT)336 angle::Result TextureStorage9_EGLImage::getRenderTarget(const gl::Context *context,
337                                                         const gl::ImageIndex &index,
338                                                         GLsizei samples,
339                                                         RenderTargetD3D **outRT)
340 {
341     ASSERT(!index.hasLayer());
342     ASSERT(index.getLevelIndex() == 0);
343     ASSERT(samples == 0);
344 
345     return mImage->getRenderTarget(context, outRT);
346 }
347 
getBaseTexture(const gl::Context * context,IDirect3DBaseTexture9 ** outTexture)348 angle::Result TextureStorage9_EGLImage::getBaseTexture(const gl::Context *context,
349                                                        IDirect3DBaseTexture9 **outTexture)
350 {
351     RenderTargetD3D *renderTargetD3D = nullptr;
352     ANGLE_TRY(mImage->getRenderTarget(context, &renderTargetD3D));
353 
354     RenderTarget9 *renderTarget9 = GetAs<RenderTarget9>(renderTargetD3D);
355     *outTexture                  = renderTarget9->getTexture();
356     ASSERT(*outTexture != nullptr);
357 
358     return angle::Result::Continue;
359 }
360 
generateMipmap(const gl::Context * context,const gl::ImageIndex &,const gl::ImageIndex &)361 angle::Result TextureStorage9_EGLImage::generateMipmap(const gl::Context *context,
362                                                        const gl::ImageIndex &,
363                                                        const gl::ImageIndex &)
364 {
365     ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
366     return angle::Result::Stop;
367 }
368 
copyToStorage(const gl::Context * context,TextureStorage * destStorage)369 angle::Result TextureStorage9_EGLImage::copyToStorage(const gl::Context *context,
370                                                       TextureStorage *destStorage)
371 {
372     ASSERT(destStorage);
373     ASSERT(getLevelCount() == 1);
374 
375     TextureStorage9 *dest9 = GetAs<TextureStorage9>(destStorage);
376 
377     IDirect3DBaseTexture9 *destBaseTexture9 = nullptr;
378     ANGLE_TRY(dest9->getBaseTexture(context, &destBaseTexture9));
379 
380     IDirect3DTexture9 *destTexture9 = static_cast<IDirect3DTexture9 *>(destBaseTexture9);
381 
382     angle::ComPtr<IDirect3DSurface9> destSurface = nullptr;
383     HRESULT result = destTexture9->GetSurfaceLevel(destStorage->getTopLevel(), &destSurface);
384     ANGLE_TRY_HR(GetImplAs<Context9>(context), result, "Failed to get the surface from a texture");
385 
386     RenderTargetD3D *sourceRenderTarget = nullptr;
387     ANGLE_TRY(mImage->getRenderTarget(context, &sourceRenderTarget));
388 
389     RenderTarget9 *sourceRenderTarget9 = GetAs<RenderTarget9>(sourceRenderTarget);
390     ANGLE_TRY(mRenderer->copyToRenderTarget(context, destSurface.Get(),
391                                             sourceRenderTarget9->getSurface(), isManaged()));
392 
393     if (destStorage->getTopLevel() != 0)
394     {
395         destTexture9->AddDirtyRect(nullptr);
396     }
397 
398     return angle::Result::Continue;
399 }
400 
TextureStorage9_Cube(Renderer9 * renderer,GLenum internalformat,bool renderTarget,int size,int levels,bool hintLevelZeroOnly,const std::string & label)401 TextureStorage9_Cube::TextureStorage9_Cube(Renderer9 *renderer,
402                                            GLenum internalformat,
403                                            bool renderTarget,
404                                            int size,
405                                            int levels,
406                                            bool hintLevelZeroOnly,
407                                            const std::string &label)
408     : TextureStorage9(renderer, GetTextureUsage(internalformat, renderTarget), label)
409 {
410     mTexture = nullptr;
411     for (size_t i = 0; i < gl::kCubeFaceCount; ++i)
412     {
413         mRenderTarget[i] = nullptr;
414     }
415 
416     mInternalFormat = internalformat;
417 
418     const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat);
419     mTextureFormat                           = d3dFormatInfo.texFormat;
420 
421     int height = size;
422     d3d9::MakeValidSize(false, d3dFormatInfo.texFormat, &size, &height, &mTopLevel);
423     mTextureWidth  = size;
424     mTextureHeight = size;
425     mMipLevels     = mTopLevel + levels;
426 }
427 
~TextureStorage9_Cube()428 TextureStorage9_Cube::~TextureStorage9_Cube()
429 {
430     SafeRelease(mTexture);
431 
432     for (size_t i = 0; i < gl::kCubeFaceCount; ++i)
433     {
434         SafeDelete(mRenderTarget[i]);
435     }
436 }
437 
438 // Increments refcount on surface.
439 // caller must Release() the returned surface
getSurfaceLevel(const gl::Context * context,gl::TextureTarget target,int level,bool dirty,IDirect3DSurface9 ** outSurface)440 angle::Result TextureStorage9_Cube::getSurfaceLevel(const gl::Context *context,
441                                                     gl::TextureTarget target,
442                                                     int level,
443                                                     bool dirty,
444                                                     IDirect3DSurface9 **outSurface)
445 {
446     IDirect3DBaseTexture9 *baseTexture = nullptr;
447     ANGLE_TRY(getBaseTexture(context, &baseTexture));
448 
449     IDirect3DCubeTexture9 *texture = static_cast<IDirect3DCubeTexture9 *>(baseTexture);
450 
451     D3DCUBEMAP_FACES face = gl_d3d9::ConvertCubeFace(target);
452     HRESULT result        = texture->GetCubeMapSurface(face, level, outSurface);
453     ANGLE_TRY_HR(GetImplAs<Context9>(context), result, "Failed to get the surface from a texture");
454 
455     // With managed textures the driver needs to be informed of updates to the lower mipmap levels
456     if (level != 0 && isManaged() && dirty)
457     {
458         texture->AddDirtyRect(face, nullptr);
459     }
460 
461     return angle::Result::Continue;
462 }
463 
findRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT) const464 angle::Result TextureStorage9_Cube::findRenderTarget(const gl::Context *context,
465                                                      const gl::ImageIndex &index,
466                                                      GLsizei samples,
467                                                      RenderTargetD3D **outRT) const
468 {
469     ASSERT(outRT);
470     ASSERT(index.getLevelIndex() == 0);
471     ASSERT(samples == 0);
472 
473     ASSERT(index.getType() == gl::TextureType::CubeMap &&
474            gl::IsCubeMapFaceTarget(index.getTarget()));
475     const size_t renderTargetIndex = index.cubeMapFaceIndex();
476 
477     *outRT = mRenderTarget[renderTargetIndex];
478     return angle::Result::Continue;
479 }
480 
getRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT)481 angle::Result TextureStorage9_Cube::getRenderTarget(const gl::Context *context,
482                                                     const gl::ImageIndex &index,
483                                                     GLsizei samples,
484                                                     RenderTargetD3D **outRT)
485 {
486     ASSERT(outRT);
487     ASSERT(index.getLevelIndex() == 0);
488     ASSERT(samples == 0);
489 
490     ASSERT(index.getType() == gl::TextureType::CubeMap &&
491            gl::IsCubeMapFaceTarget(index.getTarget()));
492     const size_t renderTargetIndex = index.cubeMapFaceIndex();
493 
494     if (mRenderTarget[renderTargetIndex] == nullptr && isRenderTarget())
495     {
496         IDirect3DBaseTexture9 *baseTexture = nullptr;
497         ANGLE_TRY(getBaseTexture(context, &baseTexture));
498 
499         IDirect3DSurface9 *surface = nullptr;
500         ANGLE_TRY(getSurfaceLevel(context, index.getTarget(), mTopLevel + index.getLevelIndex(),
501                                   false, &surface));
502 
503         baseTexture->AddRef();
504         mRenderTarget[renderTargetIndex] = new TextureRenderTarget9(
505             baseTexture, mTopLevel + index.getLevelIndex(), surface, mInternalFormat,
506             static_cast<GLsizei>(mTextureWidth), static_cast<GLsizei>(mTextureHeight), 1, 0);
507     }
508 
509     *outRT = mRenderTarget[renderTargetIndex];
510     return angle::Result::Continue;
511 }
512 
generateMipmap(const gl::Context * context,const gl::ImageIndex & sourceIndex,const gl::ImageIndex & destIndex)513 angle::Result TextureStorage9_Cube::generateMipmap(const gl::Context *context,
514                                                    const gl::ImageIndex &sourceIndex,
515                                                    const gl::ImageIndex &destIndex)
516 {
517     angle::ComPtr<IDirect3DSurface9> upper = nullptr;
518     ANGLE_TRY(getSurfaceLevel(context, sourceIndex.getTarget(), sourceIndex.getLevelIndex(), false,
519                               &upper));
520 
521     angle::ComPtr<IDirect3DSurface9> lower = nullptr;
522     ANGLE_TRY(
523         getSurfaceLevel(context, destIndex.getTarget(), destIndex.getLevelIndex(), true, &lower));
524 
525     ASSERT(upper && lower);
526     return mRenderer->boxFilter(GetImplAs<Context9>(context), upper.Get(), lower.Get());
527 }
528 
getBaseTexture(const gl::Context * context,IDirect3DBaseTexture9 ** outTexture)529 angle::Result TextureStorage9_Cube::getBaseTexture(const gl::Context *context,
530                                                    IDirect3DBaseTexture9 **outTexture)
531 {
532     // if the size is not positive this should be treated as an incomplete texture
533     // we handle that here by skipping the d3d texture creation
534     if (mTexture == nullptr && mTextureWidth > 0 && mTextureHeight > 0)
535     {
536         ASSERT(mMipLevels > 0);
537         ASSERT(mTextureWidth == mTextureHeight);
538 
539         IDirect3DDevice9 *device = mRenderer->getDevice();
540         HRESULT result           = device->CreateCubeTexture(
541             static_cast<unsigned int>(mTextureWidth), static_cast<unsigned int>(mMipLevels),
542             getUsage(), mTextureFormat, getPool(), &mTexture, nullptr);
543         ANGLE_TRY_HR(GetImplAs<Context9>(context), result, "Failed to create cube storage texture");
544     }
545 
546     *outTexture = mTexture;
547     return angle::Result::Continue;
548 }
549 
copyToStorage(const gl::Context * context,TextureStorage * destStorage)550 angle::Result TextureStorage9_Cube::copyToStorage(const gl::Context *context,
551                                                   TextureStorage *destStorage)
552 {
553     ASSERT(destStorage);
554 
555     TextureStorage9_Cube *dest9 = GetAs<TextureStorage9_Cube>(destStorage);
556 
557     int levels = getLevelCount();
558     for (gl::TextureTarget face : gl::AllCubeFaceTextureTargets())
559     {
560         for (int i = 0; i < levels; i++)
561         {
562             angle::ComPtr<IDirect3DSurface9> srcSurf = nullptr;
563             ANGLE_TRY(getSurfaceLevel(context, face, i, false, &srcSurf));
564 
565             angle::ComPtr<IDirect3DSurface9> dstSurf = nullptr;
566             ANGLE_TRY(dest9->getSurfaceLevel(context, face, i, true, &dstSurf));
567 
568             ANGLE_TRY(
569                 mRenderer->copyToRenderTarget(context, dstSurf.Get(), srcSurf.Get(), isManaged()));
570         }
571     }
572 
573     return angle::Result::Continue;
574 }
575 }  // namespace rx
576