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