• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "precompiled.h"
2 //
3 // Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
4 // Use of this source code is governed by a BSD-style license that can be
5 // found in the LICENSE file.
6 //
7 
8 // TextureStorage9.cpp: Implements the abstract rx::TextureStorage9 class and its concrete derived
9 // classes TextureStorage9_2D and TextureStorage9_Cube, which act as the interface to the
10 // D3D9 texture.
11 
12 #include "libGLESv2/main.h"
13 #include "libGLESv2/renderer/Renderer9.h"
14 #include "libGLESv2/renderer/TextureStorage9.h"
15 #include "libGLESv2/renderer/SwapChain9.h"
16 #include "libGLESv2/renderer/RenderTarget9.h"
17 #include "libGLESv2/renderer/renderer9_utils.h"
18 #include "libGLESv2/Texture.h"
19 
20 namespace rx
21 {
TextureStorage9(Renderer * renderer,DWORD usage)22 TextureStorage9::TextureStorage9(Renderer *renderer, DWORD usage)
23     : mLodOffset(0),
24       mRenderer(Renderer9::makeRenderer9(renderer)),
25       mD3DUsage(usage),
26       mD3DPool(mRenderer->getTexturePool(usage))
27 {
28 }
29 
~TextureStorage9()30 TextureStorage9::~TextureStorage9()
31 {
32 }
33 
makeTextureStorage9(TextureStorage * storage)34 TextureStorage9 *TextureStorage9::makeTextureStorage9(TextureStorage *storage)
35 {
36     ASSERT(HAS_DYNAMIC_TYPE(TextureStorage9*, storage));
37     return static_cast<TextureStorage9*>(storage);
38 }
39 
GetTextureUsage(D3DFORMAT d3dfmt,GLenum glusage,bool forceRenderable)40 DWORD TextureStorage9::GetTextureUsage(D3DFORMAT d3dfmt, GLenum glusage, bool forceRenderable)
41 {
42     DWORD d3dusage = 0;
43 
44     if (d3dfmt == D3DFMT_INTZ)
45     {
46         d3dusage |= D3DUSAGE_DEPTHSTENCIL;
47     }
48     else if(forceRenderable || (TextureStorage9::IsTextureFormatRenderable(d3dfmt) && (glusage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE)))
49     {
50         d3dusage |= D3DUSAGE_RENDERTARGET;
51     }
52     return d3dusage;
53 }
54 
IsTextureFormatRenderable(D3DFORMAT format)55 bool TextureStorage9::IsTextureFormatRenderable(D3DFORMAT format)
56 {
57     if (format == D3DFMT_INTZ)
58     {
59         return true;
60     }
61     switch(format)
62     {
63       case D3DFMT_L8:
64       case D3DFMT_A8L8:
65       case D3DFMT_DXT1:
66       case D3DFMT_DXT3:
67       case D3DFMT_DXT5:
68         return false;
69       case D3DFMT_A8R8G8B8:
70       case D3DFMT_X8R8G8B8:
71       case D3DFMT_A16B16G16R16F:
72       case D3DFMT_A32B32G32R32F:
73         return true;
74       default:
75         UNREACHABLE();
76     }
77 
78     return false;
79 }
80 
isRenderTarget() const81 bool TextureStorage9::isRenderTarget() const
82 {
83     return (mD3DUsage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL)) != 0;
84 }
85 
isManaged() const86 bool TextureStorage9::isManaged() const
87 {
88     return (mD3DPool == D3DPOOL_MANAGED);
89 }
90 
getPool() const91 D3DPOOL TextureStorage9::getPool() const
92 {
93     return mD3DPool;
94 }
95 
getUsage() const96 DWORD TextureStorage9::getUsage() const
97 {
98     return mD3DUsage;
99 }
100 
getLodOffset() const101 int TextureStorage9::getLodOffset() const
102 {
103     return mLodOffset;
104 }
105 
levelCount()106 int TextureStorage9::levelCount()
107 {
108     return getBaseTexture() ? getBaseTexture()->GetLevelCount() - getLodOffset() : 0;
109 }
110 
TextureStorage9_2D(Renderer * renderer,SwapChain9 * swapchain)111 TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, SwapChain9 *swapchain) : TextureStorage9(renderer, D3DUSAGE_RENDERTARGET)
112 {
113     IDirect3DTexture9 *surfaceTexture = swapchain->getOffscreenTexture();
114     mTexture = surfaceTexture;
115     mRenderTarget = NULL;
116 
117     initializeRenderTarget();
118 }
119 
TextureStorage9_2D(Renderer * renderer,int levels,GLenum internalformat,GLenum usage,bool forceRenderable,GLsizei width,GLsizei height)120 TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height)
121     : TextureStorage9(renderer, GetTextureUsage(Renderer9::makeRenderer9(renderer)->ConvertTextureInternalFormat(internalformat), usage, forceRenderable))
122 {
123     mTexture = NULL;
124     mRenderTarget = NULL;
125     // if the width or height is not positive this should be treated as an incomplete texture
126     // we handle that here by skipping the d3d texture creation
127     if (width > 0 && height > 0)
128     {
129         IDirect3DDevice9 *device = mRenderer->getDevice();
130         gl::MakeValidSize(false, gl::IsCompressed(internalformat), &width, &height, &mLodOffset);
131         HRESULT result = device->CreateTexture(width, height, levels ? levels + mLodOffset : 0, getUsage(),
132                                                mRenderer->ConvertTextureInternalFormat(internalformat), getPool(), &mTexture, NULL);
133 
134         if (FAILED(result))
135         {
136             ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
137             gl::error(GL_OUT_OF_MEMORY);
138         }
139     }
140 
141     initializeRenderTarget();
142 }
143 
~TextureStorage9_2D()144 TextureStorage9_2D::~TextureStorage9_2D()
145 {
146     if (mTexture)
147     {
148         mTexture->Release();
149     }
150 
151     delete mRenderTarget;
152 }
153 
makeTextureStorage9_2D(TextureStorage * storage)154 TextureStorage9_2D *TextureStorage9_2D::makeTextureStorage9_2D(TextureStorage *storage)
155 {
156     ASSERT(HAS_DYNAMIC_TYPE(TextureStorage9_2D*, storage));
157     return static_cast<TextureStorage9_2D*>(storage);
158 }
159 
160 // Increments refcount on surface.
161 // caller must Release() the returned surface
getSurfaceLevel(int level,bool dirty)162 IDirect3DSurface9 *TextureStorage9_2D::getSurfaceLevel(int level, bool dirty)
163 {
164     IDirect3DSurface9 *surface = NULL;
165 
166     if (mTexture)
167     {
168         HRESULT result = mTexture->GetSurfaceLevel(level + mLodOffset, &surface);
169         ASSERT(SUCCEEDED(result));
170 
171         // With managed textures the driver needs to be informed of updates to the lower mipmap levels
172         if (level + mLodOffset != 0 && isManaged() && dirty)
173         {
174             mTexture->AddDirtyRect(NULL);
175         }
176     }
177 
178     return surface;
179 }
180 
getRenderTarget()181 RenderTarget *TextureStorage9_2D::getRenderTarget()
182 {
183     return mRenderTarget;
184 }
185 
generateMipmap(int level)186 void TextureStorage9_2D::generateMipmap(int level)
187 {
188     IDirect3DSurface9 *upper = getSurfaceLevel(level - 1, false);
189     IDirect3DSurface9 *lower = getSurfaceLevel(level, true);
190 
191     if (upper != NULL && lower != NULL)
192     {
193         mRenderer->boxFilter(upper, lower);
194     }
195 
196     if (upper != NULL) upper->Release();
197     if (lower != NULL) lower->Release();
198 }
199 
getBaseTexture() const200 IDirect3DBaseTexture9 *TextureStorage9_2D::getBaseTexture() const
201 {
202     return mTexture;
203 }
204 
initializeRenderTarget()205 void TextureStorage9_2D::initializeRenderTarget()
206 {
207     ASSERT(mRenderTarget == NULL);
208 
209     if (mTexture != NULL && isRenderTarget())
210     {
211         IDirect3DSurface9 *surface = getSurfaceLevel(0, false);
212 
213         mRenderTarget = new RenderTarget9(mRenderer, surface);
214     }
215 }
216 
TextureStorage9_Cube(Renderer * renderer,int levels,GLenum internalformat,GLenum usage,bool forceRenderable,int size)217 TextureStorage9_Cube::TextureStorage9_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size)
218     : TextureStorage9(renderer, GetTextureUsage(Renderer9::makeRenderer9(renderer)->ConvertTextureInternalFormat(internalformat), usage, forceRenderable))
219 {
220     mTexture = NULL;
221     for (int i = 0; i < 6; ++i)
222     {
223         mRenderTarget[i] = NULL;
224     }
225 
226     // if the size is not positive this should be treated as an incomplete texture
227     // we handle that here by skipping the d3d texture creation
228     if (size > 0)
229     {
230         IDirect3DDevice9 *device = mRenderer->getDevice();
231         int height = size;
232         gl::MakeValidSize(false, gl::IsCompressed(internalformat), &size, &height, &mLodOffset);
233         HRESULT result = device->CreateCubeTexture(size, levels ? levels + mLodOffset : 0, getUsage(),
234                                                    mRenderer->ConvertTextureInternalFormat(internalformat), getPool(), &mTexture, NULL);
235 
236         if (FAILED(result))
237         {
238             ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
239             gl::error(GL_OUT_OF_MEMORY);
240         }
241     }
242 
243     initializeRenderTarget();
244 }
245 
~TextureStorage9_Cube()246 TextureStorage9_Cube::~TextureStorage9_Cube()
247 {
248     if (mTexture)
249     {
250         mTexture->Release();
251     }
252 
253     for (int i = 0; i < 6; ++i)
254     {
255         delete mRenderTarget[i];
256     }
257 }
258 
makeTextureStorage9_Cube(TextureStorage * storage)259 TextureStorage9_Cube *TextureStorage9_Cube::makeTextureStorage9_Cube(TextureStorage *storage)
260 {
261     ASSERT(HAS_DYNAMIC_TYPE(TextureStorage9_Cube*, storage));
262     return static_cast<TextureStorage9_Cube*>(storage);
263 }
264 
265 // Increments refcount on surface.
266 // caller must Release() the returned surface
getCubeMapSurface(GLenum faceTarget,int level,bool dirty)267 IDirect3DSurface9 *TextureStorage9_Cube::getCubeMapSurface(GLenum faceTarget, int level, bool dirty)
268 {
269     IDirect3DSurface9 *surface = NULL;
270 
271     if (mTexture)
272     {
273         D3DCUBEMAP_FACES face = gl_d3d9::ConvertCubeFace(faceTarget);
274         HRESULT result = mTexture->GetCubeMapSurface(face, level + mLodOffset, &surface);
275         ASSERT(SUCCEEDED(result));
276 
277         // With managed textures the driver needs to be informed of updates to the lower mipmap levels
278         if (level != 0 && isManaged() && dirty)
279         {
280             mTexture->AddDirtyRect(face, NULL);
281         }
282     }
283 
284     return surface;
285 }
286 
getRenderTarget(GLenum faceTarget)287 RenderTarget *TextureStorage9_Cube::getRenderTarget(GLenum faceTarget)
288 {
289     return mRenderTarget[gl::TextureCubeMap::faceIndex(faceTarget)];
290 }
291 
generateMipmap(int face,int level)292 void TextureStorage9_Cube::generateMipmap(int face, int level)
293 {
294     IDirect3DSurface9 *upper = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level - 1, false);
295     IDirect3DSurface9 *lower = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, true);
296 
297     if (upper != NULL && lower != NULL)
298     {
299         mRenderer->boxFilter(upper, lower);
300     }
301 
302     if (upper != NULL) upper->Release();
303     if (lower != NULL) lower->Release();
304 }
305 
getBaseTexture() const306 IDirect3DBaseTexture9 *TextureStorage9_Cube::getBaseTexture() const
307 {
308     return mTexture;
309 }
310 
initializeRenderTarget()311 void TextureStorage9_Cube::initializeRenderTarget()
312 {
313     if (mTexture != NULL && isRenderTarget())
314     {
315         IDirect3DSurface9 *surface = NULL;
316 
317         for (int i = 0; i < 6; ++i)
318         {
319             ASSERT(mRenderTarget[i] == NULL);
320 
321             surface = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, false);
322 
323             mRenderTarget[i] = new RenderTarget9(mRenderer, surface);
324         }
325     }
326 }
327 
328 }