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