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