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