1 //
2 // Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 // 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/Texture.h"
15 #include "libANGLE/formatutils.h"
16 #include "libANGLE/renderer/d3d/EGLImageD3D.h"
17 #include "libANGLE/renderer/d3d/TextureD3D.h"
18 #include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h"
19 #include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
20 #include "libANGLE/renderer/d3d/d3d9/SwapChain9.h"
21 #include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
22 #include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
23
24 namespace rx
25 {
TextureStorage9(Renderer9 * renderer,DWORD usage)26 TextureStorage9::TextureStorage9(Renderer9 *renderer, DWORD usage)
27 : mTopLevel(0),
28 mMipLevels(0),
29 mTextureWidth(0),
30 mTextureHeight(0),
31 mInternalFormat(GL_NONE),
32 mTextureFormat(D3DFMT_UNKNOWN),
33 mRenderer(renderer),
34 mD3DUsage(usage),
35 mD3DPool(mRenderer->getTexturePool(usage))
36 {
37 }
38
~TextureStorage9()39 TextureStorage9::~TextureStorage9()
40 {
41 }
42
GetTextureUsage(GLenum internalformat,bool renderTarget)43 DWORD TextureStorage9::GetTextureUsage(GLenum internalformat, bool renderTarget)
44 {
45 DWORD d3dusage = 0;
46
47 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
48 const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat);
49 if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
50 {
51 d3dusage |= D3DUSAGE_DEPTHSTENCIL;
52 }
53 else if (renderTarget && (d3dFormatInfo.renderFormat != D3DFMT_UNKNOWN))
54 {
55 d3dusage |= D3DUSAGE_RENDERTARGET;
56 }
57
58 return d3dusage;
59 }
60
61
isRenderTarget() const62 bool TextureStorage9::isRenderTarget() const
63 {
64 return (mD3DUsage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL)) != 0;
65 }
66
isManaged() const67 bool TextureStorage9::isManaged() const
68 {
69 return (mD3DPool == D3DPOOL_MANAGED);
70 }
71
supportsNativeMipmapFunction() const72 bool TextureStorage9::supportsNativeMipmapFunction() const
73 {
74 return false;
75 }
76
getPool() const77 D3DPOOL TextureStorage9::getPool() const
78 {
79 return mD3DPool;
80 }
81
getUsage() const82 DWORD TextureStorage9::getUsage() const
83 {
84 return mD3DUsage;
85 }
86
getTopLevel() const87 int TextureStorage9::getTopLevel() const
88 {
89 return mTopLevel;
90 }
91
getLevelCount() const92 int TextureStorage9::getLevelCount() const
93 {
94 return static_cast<int>(mMipLevels) - mTopLevel;
95 }
96
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)97 gl::Error TextureStorage9::setData(const gl::Context *context,
98 const gl::ImageIndex &index,
99 ImageD3D *image,
100 const gl::Box *destBox,
101 GLenum type,
102 const gl::PixelUnpackState &unpack,
103 const uint8_t *pixelData)
104 {
105 UNREACHABLE();
106 return gl::InternalError();
107 }
108
TextureStorage9_2D(Renderer9 * renderer,SwapChain9 * swapchain)109 TextureStorage9_2D::TextureStorage9_2D(Renderer9 *renderer, SwapChain9 *swapchain)
110 : TextureStorage9(renderer, D3DUSAGE_RENDERTARGET)
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)127 TextureStorage9_2D::TextureStorage9_2D(Renderer9 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels)
128 : TextureStorage9(renderer, GetTextureUsage(internalformat, renderTarget))
129 {
130 mTexture = nullptr;
131
132 mInternalFormat = internalformat;
133
134 const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat);
135 mTextureFormat = d3dFormatInfo.texFormat;
136
137 d3d9::MakeValidSize(false, d3dFormatInfo.texFormat, &width, &height, &mTopLevel);
138 mTextureWidth = width;
139 mTextureHeight = height;
140 mMipLevels = mTopLevel + levels;
141
142 mRenderTargets.resize(levels, nullptr);
143 }
144
~TextureStorage9_2D()145 TextureStorage9_2D::~TextureStorage9_2D()
146 {
147 SafeRelease(mTexture);
148 for (RenderTargetD3D *renderTarget : mRenderTargets)
149 {
150 SafeDelete(renderTarget);
151 }
152 }
153
154 // Increments refcount on surface.
155 // caller must Release() the returned surface
getSurfaceLevel(const gl::Context * context,GLenum target,int level,bool dirty,IDirect3DSurface9 ** outSurface)156 gl::Error TextureStorage9_2D::getSurfaceLevel(const gl::Context *context,
157 GLenum target,
158 int level,
159 bool dirty,
160 IDirect3DSurface9 **outSurface)
161 {
162 ASSERT(target == GL_TEXTURE_2D);
163
164 IDirect3DBaseTexture9 *baseTexture = nullptr;
165 gl::Error error = getBaseTexture(context, &baseTexture);
166 if (error.isError())
167 {
168 return error;
169 }
170
171 IDirect3DTexture9 *texture = static_cast<IDirect3DTexture9*>(baseTexture);
172
173 HRESULT result = texture->GetSurfaceLevel(level + mTopLevel, outSurface);
174
175 ASSERT(SUCCEEDED(result));
176 if (FAILED(result))
177 {
178 return gl::OutOfMemory() << "Failed to get the surface from a texture, "
179 << gl::FmtHR(result);
180 }
181
182 // With managed textures the driver needs to be informed of updates to the lower mipmap levels
183 if (level + mTopLevel != 0 && isManaged() && dirty)
184 {
185 texture->AddDirtyRect(nullptr);
186 }
187
188 return gl::NoError();
189 }
190
getRenderTarget(const gl::Context * context,const gl::ImageIndex & index,RenderTargetD3D ** outRT)191 gl::Error TextureStorage9_2D::getRenderTarget(const gl::Context *context,
192 const gl::ImageIndex &index,
193 RenderTargetD3D **outRT)
194 {
195 ASSERT(index.mipIndex < getLevelCount());
196
197 if (!mRenderTargets[index.mipIndex] && isRenderTarget())
198 {
199 IDirect3DBaseTexture9 *baseTexture = nullptr;
200 gl::Error error = getBaseTexture(context, &baseTexture);
201 if (error.isError())
202 {
203 return error;
204 }
205
206 IDirect3DSurface9 *surface = nullptr;
207 error = getSurfaceLevel(context, GL_TEXTURE_2D, index.mipIndex, false, &surface);
208 if (error.isError())
209 {
210 return error;
211 }
212
213 size_t textureMipLevel = mTopLevel + index.mipIndex;
214 size_t mipWidth = std::max<size_t>(mTextureWidth >> textureMipLevel, 1u);
215 size_t mipHeight = std::max<size_t>(mTextureHeight >> textureMipLevel, 1u);
216
217 baseTexture->AddRef();
218 mRenderTargets[index.mipIndex] = new TextureRenderTarget9(
219 baseTexture, textureMipLevel, surface, mInternalFormat, static_cast<GLsizei>(mipWidth),
220 static_cast<GLsizei>(mipHeight), 1, 0);
221 }
222
223 ASSERT(outRT);
224 *outRT = mRenderTargets[index.mipIndex];
225 return gl::NoError();
226 }
227
generateMipmap(const gl::Context * context,const gl::ImageIndex & sourceIndex,const gl::ImageIndex & destIndex)228 gl::Error TextureStorage9_2D::generateMipmap(const gl::Context *context,
229 const gl::ImageIndex &sourceIndex,
230 const gl::ImageIndex &destIndex)
231 {
232 IDirect3DSurface9 *upper = nullptr;
233 gl::Error error = getSurfaceLevel(context, GL_TEXTURE_2D, sourceIndex.mipIndex, false, &upper);
234 if (error.isError())
235 {
236 return error;
237 }
238
239 IDirect3DSurface9 *lower = nullptr;
240 error = getSurfaceLevel(context, GL_TEXTURE_2D, destIndex.mipIndex, true, &lower);
241 if (error.isError())
242 {
243 SafeRelease(upper);
244 return error;
245 }
246
247 ASSERT(upper && lower);
248 error = mRenderer->boxFilter(upper, lower);
249
250 SafeRelease(upper);
251 SafeRelease(lower);
252
253 return error;
254 }
255
getBaseTexture(const gl::Context * context,IDirect3DBaseTexture9 ** outTexture)256 gl::Error TextureStorage9_2D::getBaseTexture(const gl::Context *context,
257 IDirect3DBaseTexture9 **outTexture)
258 {
259 // if the width or height is not positive this should be treated as an incomplete texture
260 // we handle that here by skipping the d3d texture creation
261 if (mTexture == nullptr && mTextureWidth > 0 && mTextureHeight > 0)
262 {
263 ASSERT(mMipLevels > 0);
264
265 IDirect3DDevice9 *device = mRenderer->getDevice();
266 HRESULT result = device->CreateTexture(static_cast<unsigned int>(mTextureWidth),
267 static_cast<unsigned int>(mTextureHeight),
268 static_cast<unsigned int>(mMipLevels), getUsage(),
269 mTextureFormat, getPool(), &mTexture, nullptr);
270
271 if (FAILED(result))
272 {
273 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
274 return gl::OutOfMemory()
275 << "Failed to create 2D storage texture, " << gl::FmtHR(result);
276 }
277 }
278
279 *outTexture = mTexture;
280 return gl::NoError();
281 }
282
copyToStorage(const gl::Context * context,TextureStorage * destStorage)283 gl::Error TextureStorage9_2D::copyToStorage(const gl::Context *context, TextureStorage *destStorage)
284 {
285 ASSERT(destStorage);
286
287 TextureStorage9_2D *dest9 = GetAs<TextureStorage9_2D>(destStorage);
288
289 int levels = getLevelCount();
290 for (int i = 0; i < levels; ++i)
291 {
292 IDirect3DSurface9 *srcSurf = nullptr;
293 gl::Error error = getSurfaceLevel(context, GL_TEXTURE_2D, i, false, &srcSurf);
294 if (error.isError())
295 {
296 return error;
297 }
298
299 IDirect3DSurface9 *dstSurf = nullptr;
300 error = dest9->getSurfaceLevel(context, GL_TEXTURE_2D, i, true, &dstSurf);
301 if (error.isError())
302 {
303 SafeRelease(srcSurf);
304 return error;
305 }
306
307 error = mRenderer->copyToRenderTarget(dstSurf, srcSurf, isManaged());
308
309 SafeRelease(srcSurf);
310 SafeRelease(dstSurf);
311
312 if (error.isError())
313 {
314 return error;
315 }
316 }
317
318 return gl::NoError();
319 }
320
TextureStorage9_EGLImage(Renderer9 * renderer,EGLImageD3D * image,RenderTarget9 * renderTarget9)321 TextureStorage9_EGLImage::TextureStorage9_EGLImage(Renderer9 *renderer,
322 EGLImageD3D *image,
323 RenderTarget9 *renderTarget9)
324 : TextureStorage9(renderer, D3DUSAGE_RENDERTARGET), mImage(image)
325 {
326 mInternalFormat = renderTarget9->getInternalFormat();
327 mTextureFormat = renderTarget9->getD3DFormat();
328 mTextureWidth = renderTarget9->getWidth();
329 mTextureHeight = renderTarget9->getHeight();
330 mTopLevel = static_cast<int>(renderTarget9->getTextureLevel());
331 mMipLevels = mTopLevel + 1;
332 }
333
~TextureStorage9_EGLImage()334 TextureStorage9_EGLImage::~TextureStorage9_EGLImage()
335 {
336 }
337
getSurfaceLevel(const gl::Context * context,GLenum target,int level,bool,IDirect3DSurface9 ** outSurface)338 gl::Error TextureStorage9_EGLImage::getSurfaceLevel(const gl::Context *context,
339 GLenum target,
340 int level,
341 bool,
342 IDirect3DSurface9 **outSurface)
343 {
344 ASSERT(target == GL_TEXTURE_2D);
345 ASSERT(level == 0);
346
347 RenderTargetD3D *renderTargetD3D = nullptr;
348 gl::Error error = mImage->getRenderTarget(context, &renderTargetD3D);
349 if (error.isError())
350 {
351 return error;
352 }
353
354 RenderTarget9 *renderTarget9 = GetAs<RenderTarget9>(renderTargetD3D);
355
356 *outSurface = renderTarget9->getSurface();
357 return gl::NoError();
358 }
359
getRenderTarget(const gl::Context * context,const gl::ImageIndex & index,RenderTargetD3D ** outRT)360 gl::Error TextureStorage9_EGLImage::getRenderTarget(const gl::Context *context,
361 const gl::ImageIndex &index,
362 RenderTargetD3D **outRT)
363 {
364 ASSERT(!index.hasLayer());
365 ASSERT(index.mipIndex == 0);
366
367 return mImage->getRenderTarget(context, outRT);
368 }
369
getBaseTexture(const gl::Context * context,IDirect3DBaseTexture9 ** outTexture)370 gl::Error TextureStorage9_EGLImage::getBaseTexture(const gl::Context *context,
371 IDirect3DBaseTexture9 **outTexture)
372 {
373 RenderTargetD3D *renderTargetD3D = nullptr;
374 gl::Error error = mImage->getRenderTarget(context, &renderTargetD3D);
375 if (error.isError())
376 {
377 return error;
378 }
379
380 RenderTarget9 *renderTarget9 = GetAs<RenderTarget9>(renderTargetD3D);
381 *outTexture = renderTarget9->getTexture();
382 ASSERT(*outTexture != nullptr);
383
384 return gl::NoError();
385 }
386
generateMipmap(const gl::Context * context,const gl::ImageIndex &,const gl::ImageIndex &)387 gl::Error TextureStorage9_EGLImage::generateMipmap(const gl::Context *context,
388 const gl::ImageIndex &,
389 const gl::ImageIndex &)
390 {
391 UNREACHABLE();
392 return gl::InternalError();
393 }
394
copyToStorage(const gl::Context * context,TextureStorage * destStorage)395 gl::Error TextureStorage9_EGLImage::copyToStorage(const gl::Context *context,
396 TextureStorage *destStorage)
397 {
398 ASSERT(destStorage);
399 ASSERT(getLevelCount() == 1);
400
401 TextureStorage9 *dest9 = GetAs<TextureStorage9>(destStorage);
402
403 IDirect3DBaseTexture9 *destBaseTexture9 = nullptr;
404 gl::Error error = dest9->getBaseTexture(context, &destBaseTexture9);
405 if (error.isError())
406 {
407 return error;
408 }
409
410 IDirect3DTexture9 *destTexture9 = static_cast<IDirect3DTexture9 *>(destBaseTexture9);
411
412 IDirect3DSurface9 *destSurface = nullptr;
413 HRESULT result = destTexture9->GetSurfaceLevel(destStorage->getTopLevel(), &destSurface);
414 if (FAILED(result))
415 {
416 return gl::OutOfMemory() << "Failed to get the surface from a texture, "
417 << gl::FmtHR(result);
418 }
419
420 RenderTargetD3D *sourceRenderTarget = nullptr;
421 error = mImage->getRenderTarget(context, &sourceRenderTarget);
422 if (error.isError())
423 {
424 SafeRelease(destSurface);
425 return error;
426 }
427
428 RenderTarget9 *sourceRenderTarget9 = GetAs<RenderTarget9>(sourceRenderTarget);
429 error =
430 mRenderer->copyToRenderTarget(destSurface, sourceRenderTarget9->getSurface(), isManaged());
431 if (error.isError())
432 {
433 SafeRelease(destSurface);
434 return error;
435 }
436
437 if (destStorage->getTopLevel() != 0)
438 {
439 destTexture9->AddDirtyRect(nullptr);
440 }
441
442 SafeRelease(destSurface);
443 return gl::NoError();
444 }
445
TextureStorage9_Cube(Renderer9 * renderer,GLenum internalformat,bool renderTarget,int size,int levels,bool hintLevelZeroOnly)446 TextureStorage9_Cube::TextureStorage9_Cube(Renderer9 *renderer, GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly)
447 : TextureStorage9(renderer, GetTextureUsage(internalformat, renderTarget))
448 {
449 mTexture = nullptr;
450 for (size_t i = 0; i < gl::CUBE_FACE_COUNT; ++i)
451 {
452 mRenderTarget[i] = nullptr;
453 }
454
455 mInternalFormat = internalformat;
456
457 const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat);
458 mTextureFormat = d3dFormatInfo.texFormat;
459
460 int height = size;
461 d3d9::MakeValidSize(false, d3dFormatInfo.texFormat, &size, &height, &mTopLevel);
462 mTextureWidth = size;
463 mTextureHeight = size;
464 mMipLevels = mTopLevel + levels;
465 }
466
~TextureStorage9_Cube()467 TextureStorage9_Cube::~TextureStorage9_Cube()
468 {
469 SafeRelease(mTexture);
470
471 for (size_t i = 0; i < gl::CUBE_FACE_COUNT; ++i)
472 {
473 SafeDelete(mRenderTarget[i]);
474 }
475 }
476
477 // Increments refcount on surface.
478 // caller must Release() the returned surface
getSurfaceLevel(const gl::Context * context,GLenum target,int level,bool dirty,IDirect3DSurface9 ** outSurface)479 gl::Error TextureStorage9_Cube::getSurfaceLevel(const gl::Context *context,
480 GLenum target,
481 int level,
482 bool dirty,
483 IDirect3DSurface9 **outSurface)
484 {
485 IDirect3DBaseTexture9 *baseTexture = nullptr;
486 gl::Error error = getBaseTexture(context, &baseTexture);
487 if (error.isError())
488 {
489 return error;
490 }
491
492 IDirect3DCubeTexture9 *texture = static_cast<IDirect3DCubeTexture9*>(baseTexture);
493
494 D3DCUBEMAP_FACES face = gl_d3d9::ConvertCubeFace(target);
495 HRESULT result = texture->GetCubeMapSurface(face, level, outSurface);
496
497 ASSERT(SUCCEEDED(result));
498 if (FAILED(result))
499 {
500 return gl::OutOfMemory() << "Failed to get the surface from a texture, "
501 << gl::FmtHR(result);
502 }
503
504 // With managed textures the driver needs to be informed of updates to the lower mipmap levels
505 if (level != 0 && isManaged() && dirty)
506 {
507 texture->AddDirtyRect(face, nullptr);
508 }
509
510 return gl::NoError();
511 }
512
getRenderTarget(const gl::Context * context,const gl::ImageIndex & index,RenderTargetD3D ** outRT)513 gl::Error TextureStorage9_Cube::getRenderTarget(const gl::Context *context,
514 const gl::ImageIndex &index,
515 RenderTargetD3D **outRT)
516 {
517 ASSERT(outRT);
518 ASSERT(index.mipIndex == 0);
519
520 ASSERT(index.type == GL_TEXTURE_CUBE_MAP && gl::IsCubeMapTextureTarget(index.target));
521 const size_t renderTargetIndex = index.cubeMapFaceIndex();
522
523 if (mRenderTarget[renderTargetIndex] == nullptr && isRenderTarget())
524 {
525 IDirect3DBaseTexture9 *baseTexture = nullptr;
526 gl::Error error = getBaseTexture(context, &baseTexture);
527 if (error.isError())
528 {
529 return error;
530 }
531
532 IDirect3DSurface9 *surface = nullptr;
533 error = getSurfaceLevel(context, index.target, mTopLevel + index.mipIndex, false, &surface);
534 if (error.isError())
535 {
536 return error;
537 }
538
539 baseTexture->AddRef();
540 mRenderTarget[renderTargetIndex] = new TextureRenderTarget9(
541 baseTexture, mTopLevel + index.mipIndex, surface, mInternalFormat,
542 static_cast<GLsizei>(mTextureWidth), static_cast<GLsizei>(mTextureHeight), 1, 0);
543 }
544
545 *outRT = mRenderTarget[renderTargetIndex];
546 return gl::NoError();
547 }
548
generateMipmap(const gl::Context * context,const gl::ImageIndex & sourceIndex,const gl::ImageIndex & destIndex)549 gl::Error TextureStorage9_Cube::generateMipmap(const gl::Context *context,
550 const gl::ImageIndex &sourceIndex,
551 const gl::ImageIndex &destIndex)
552 {
553 IDirect3DSurface9 *upper = nullptr;
554 gl::Error error =
555 getSurfaceLevel(context, sourceIndex.target, sourceIndex.mipIndex, false, &upper);
556 if (error.isError())
557 {
558 return error;
559 }
560
561 IDirect3DSurface9 *lower = nullptr;
562 error = getSurfaceLevel(context, destIndex.target, destIndex.mipIndex, true, &lower);
563 if (error.isError())
564 {
565 SafeRelease(upper);
566 return error;
567 }
568
569 ASSERT(upper && lower);
570 error = mRenderer->boxFilter(upper, lower);
571
572 SafeRelease(upper);
573 SafeRelease(lower);
574
575 return error;
576 }
577
getBaseTexture(const gl::Context * context,IDirect3DBaseTexture9 ** outTexture)578 gl::Error TextureStorage9_Cube::getBaseTexture(const gl::Context *context,
579 IDirect3DBaseTexture9 **outTexture)
580 {
581 // if the size is not positive this should be treated as an incomplete texture
582 // we handle that here by skipping the d3d texture creation
583 if (mTexture == nullptr && mTextureWidth > 0 && mTextureHeight > 0)
584 {
585 ASSERT(mMipLevels > 0);
586 ASSERT(mTextureWidth == mTextureHeight);
587
588 IDirect3DDevice9 *device = mRenderer->getDevice();
589 HRESULT result = device->CreateCubeTexture(
590 static_cast<unsigned int>(mTextureWidth), static_cast<unsigned int>(mMipLevels),
591 getUsage(), mTextureFormat, getPool(), &mTexture, nullptr);
592
593 if (FAILED(result))
594 {
595 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
596 return gl::OutOfMemory()
597 << "Failed to create cube storage texture, " << gl::FmtHR(result);
598 }
599 }
600
601 *outTexture = mTexture;
602 return gl::NoError();
603 }
604
copyToStorage(const gl::Context * context,TextureStorage * destStorage)605 gl::Error TextureStorage9_Cube::copyToStorage(const gl::Context *context,
606 TextureStorage *destStorage)
607 {
608 ASSERT(destStorage);
609
610 TextureStorage9_Cube *dest9 = GetAs<TextureStorage9_Cube>(destStorage);
611
612 int levels = getLevelCount();
613 for (int f = 0; f < static_cast<int>(gl::CUBE_FACE_COUNT); f++)
614 {
615 for (int i = 0; i < levels; i++)
616 {
617 IDirect3DSurface9 *srcSurf = nullptr;
618 gl::Error error =
619 getSurfaceLevel(context, GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, false, &srcSurf);
620 if (error.isError())
621 {
622 return error;
623 }
624
625 IDirect3DSurface9 *dstSurf = nullptr;
626 error = dest9->getSurfaceLevel(context, GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, true,
627 &dstSurf);
628 if (error.isError())
629 {
630 SafeRelease(srcSurf);
631 return error;
632 }
633
634 error = mRenderer->copyToRenderTarget(dstSurf, srcSurf, isManaged());
635
636 SafeRelease(srcSurf);
637 SafeRelease(dstSurf);
638
639 if (error.isError())
640 {
641 return error;
642 }
643 }
644 }
645
646 return gl::NoError();
647 }
648
649 }
650