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