blob: 68c5e1f1e6d2da518803cf156c52a02774aad772 [file] [log] [blame]
daniel@transgaming.comb5e1a272012-10-31 19:10:00 +00001//
2// Copyright (c) 2002-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// TextureStorage.cpp: Implements the abstract gl::TextureStorage class and its concrete derived
8// classes TextureStorage2D and TextureStorageCubeMap, which act as the interface to the
9// D3D-side texture.
10
11#include "libGLESv2/main.h"
12#include "libGLESv2/renderer/TextureStorage.h"
13
14#include "common/debug.h"
15
16namespace gl
17{
18unsigned int TextureStorage::mCurrentTextureSerial = 1;
19
20TextureStorage::TextureStorage(DWORD usage)
21 : mD3DUsage(usage),
22 mD3DPool(getDisplay()->getRenderer()->getTexturePool(usage)), // D3D9_REPLACE
23 mTextureSerial(issueTextureSerial()),
24 mLodOffset(0)
25{
26}
27
28TextureStorage::~TextureStorage()
29{
30}
31
daniel@transgaming.comdf14c762012-10-31 19:51:48 +000032DWORD TextureStorage::GetTextureUsage(D3DFORMAT d3dfmt, GLenum glusage, bool forceRenderable)
33{
34 DWORD d3dusage = 0;
35
36 if (d3dfmt == D3DFMT_INTZ)
37 {
38 d3dusage |= D3DUSAGE_DEPTHSTENCIL;
39 }
40 else if(forceRenderable || (TextureStorage::IsTextureFormatRenderable(d3dfmt) && (glusage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE)))
41 {
42 d3dusage |= D3DUSAGE_RENDERTARGET;
43 }
44 return d3dusage;
45}
46
47bool TextureStorage::IsTextureFormatRenderable(D3DFORMAT format)
48{
49 if (format == D3DFMT_INTZ)
50 {
51 return true;
52 }
53 switch(format)
54 {
55 case D3DFMT_L8:
56 case D3DFMT_A8L8:
57 case D3DFMT_DXT1:
58 case D3DFMT_DXT3:
59 case D3DFMT_DXT5:
60 return false;
61 case D3DFMT_A8R8G8B8:
62 case D3DFMT_X8R8G8B8:
63 case D3DFMT_A16B16G16R16F:
64 case D3DFMT_A32B32G32R32F:
65 return true;
66 default:
67 UNREACHABLE();
68 }
69
70 return false;
71}
72
73D3DFORMAT TextureStorage::ConvertTextureInternalFormat(GLint internalformat)
74{
75 switch (internalformat)
76 {
77 case GL_DEPTH_COMPONENT16:
78 case GL_DEPTH_COMPONENT32_OES:
79 case GL_DEPTH24_STENCIL8_OES:
80 return D3DFMT_INTZ;
81 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
82 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
83 return D3DFMT_DXT1;
84 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
85 return D3DFMT_DXT3;
86 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
87 return D3DFMT_DXT5;
88 case GL_RGBA32F_EXT:
89 case GL_RGB32F_EXT:
90 case GL_ALPHA32F_EXT:
91 case GL_LUMINANCE32F_EXT:
92 case GL_LUMINANCE_ALPHA32F_EXT:
93 return D3DFMT_A32B32G32R32F;
94 case GL_RGBA16F_EXT:
95 case GL_RGB16F_EXT:
96 case GL_ALPHA16F_EXT:
97 case GL_LUMINANCE16F_EXT:
98 case GL_LUMINANCE_ALPHA16F_EXT:
99 return D3DFMT_A16B16G16R16F;
100 case GL_LUMINANCE8_EXT:
101 if (getContext()->supportsLuminanceTextures())
102 {
103 return D3DFMT_L8;
104 }
105 break;
106 case GL_LUMINANCE8_ALPHA8_EXT:
107 if (getContext()->supportsLuminanceAlphaTextures())
108 {
109 return D3DFMT_A8L8;
110 }
111 break;
112 case GL_RGB8_OES:
113 case GL_RGB565:
114 return D3DFMT_X8R8G8B8;
115 }
116
117 return D3DFMT_A8R8G8B8;
118}
119
daniel@transgaming.comb5e1a272012-10-31 19:10:00 +0000120bool TextureStorage::isRenderTarget() const
121{
122 return (mD3DUsage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL)) != 0;
123}
124
125bool TextureStorage::isManaged() const
126{
127 return (mD3DPool == D3DPOOL_MANAGED);
128}
129
130D3DPOOL TextureStorage::getPool() const
131{
132 return mD3DPool;
133}
134
135DWORD TextureStorage::getUsage() const
136{
137 return mD3DUsage;
138}
139
140unsigned int TextureStorage::getTextureSerial() const
141{
142 return mTextureSerial;
143}
144
145unsigned int TextureStorage::issueTextureSerial()
146{
147 return mCurrentTextureSerial++;
148}
149
150int TextureStorage::getLodOffset() const
151{
152 return mLodOffset;
153}
154
155TextureStorage2D::TextureStorage2D(IDirect3DTexture9 *surfaceTexture) : TextureStorage(D3DUSAGE_RENDERTARGET), mRenderTargetSerial(RenderbufferStorage::issueSerial())
156{
157 mTexture = surfaceTexture;
158}
159
daniel@transgaming.comf032cb82012-10-31 19:51:52 +0000160TextureStorage2D::TextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height)
161 : TextureStorage(GetTextureUsage(ConvertTextureInternalFormat(internalformat), usage, forceRenderable)),
162 mRenderTargetSerial(RenderbufferStorage::issueSerial())
daniel@transgaming.comb5e1a272012-10-31 19:10:00 +0000163{
164 mTexture = NULL;
165 // if the width or height is not positive this should be treated as an incomplete texture
166 // we handle that here by skipping the d3d texture creation
167 if (width > 0 && height > 0)
168 {
169 IDirect3DDevice9 *device = getDisplay()->getRenderer()->getDevice(); // D3D9_REPLACE
daniel@transgaming.comf032cb82012-10-31 19:51:52 +0000170 MakeValidSize(false, gl::IsCompressed(internalformat), &width, &height, &mLodOffset);
171 HRESULT result = device->CreateTexture(width, height, levels ? levels + mLodOffset : 0, getUsage(),
172 ConvertTextureInternalFormat(internalformat), getPool(), &mTexture, NULL);
daniel@transgaming.comb5e1a272012-10-31 19:10:00 +0000173
174 if (FAILED(result))
175 {
176 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
177 error(GL_OUT_OF_MEMORY);
178 }
179 }
180}
181
182TextureStorage2D::~TextureStorage2D()
183{
184 if (mTexture)
185 {
186 mTexture->Release();
187 }
188}
189
190// Increments refcount on surface.
191// caller must Release() the returned surface
192IDirect3DSurface9 *TextureStorage2D::getSurfaceLevel(int level, bool dirty)
193{
194 IDirect3DSurface9 *surface = NULL;
195
196 if (mTexture)
197 {
198 HRESULT result = mTexture->GetSurfaceLevel(level + mLodOffset, &surface);
199 ASSERT(SUCCEEDED(result));
200
201 // With managed textures the driver needs to be informed of updates to the lower mipmap levels
202 if (level != 0 && isManaged() && dirty)
203 {
204 mTexture->AddDirtyRect(NULL);
205 }
206 }
207
208 return surface;
209}
210
211IDirect3DBaseTexture9 *TextureStorage2D::getBaseTexture() const
212{
213 return mTexture;
214}
215
216unsigned int TextureStorage2D::getRenderTargetSerial(GLenum target) const
217{
218 return mRenderTargetSerial;
219}
220
daniel@transgaming.comf032cb82012-10-31 19:51:52 +0000221TextureStorageCubeMap::TextureStorageCubeMap(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size)
222 : TextureStorage(GetTextureUsage(ConvertTextureInternalFormat(internalformat), usage, forceRenderable)),
223 mFirstRenderTargetSerial(RenderbufferStorage::issueCubeSerials())
daniel@transgaming.comb5e1a272012-10-31 19:10:00 +0000224{
225 mTexture = NULL;
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 = getDisplay()->getRenderer()->getDevice(); // D3D9_REPLACE
231 int height = size;
daniel@transgaming.comf032cb82012-10-31 19:51:52 +0000232 MakeValidSize(false, gl::IsCompressed(internalformat), &size, &height, &mLodOffset);
233 HRESULT result = device->CreateCubeTexture(size, levels ? levels + mLodOffset : 0, getUsage(),
234 ConvertTextureInternalFormat(internalformat), getPool(), &mTexture, NULL);
daniel@transgaming.comb5e1a272012-10-31 19:10:00 +0000235
236 if (FAILED(result))
237 {
238 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
239 error(GL_OUT_OF_MEMORY);
240 }
241 }
242}
243
244TextureStorageCubeMap::~TextureStorageCubeMap()
245{
246 if (mTexture)
247 {
248 mTexture->Release();
249 }
250}
251
252// Increments refcount on surface.
253// caller must Release() the returned surface
254IDirect3DSurface9 *TextureStorageCubeMap::getCubeMapSurface(GLenum faceTarget, int level, bool dirty)
255{
256 IDirect3DSurface9 *surface = NULL;
257
258 if (mTexture)
259 {
260 D3DCUBEMAP_FACES face = es2dx::ConvertCubeFace(faceTarget);
261 HRESULT result = mTexture->GetCubeMapSurface(face, level + mLodOffset, &surface);
262 ASSERT(SUCCEEDED(result));
263
264 // With managed textures the driver needs to be informed of updates to the lower mipmap levels
265 if (level != 0 && isManaged() && dirty)
266 {
267 mTexture->AddDirtyRect(face, NULL);
268 }
269 }
270
271 return surface;
272}
273
274IDirect3DBaseTexture9 *TextureStorageCubeMap::getBaseTexture() const
275{
276 return mTexture;
277}
278
279unsigned int TextureStorageCubeMap::getRenderTargetSerial(GLenum target) const
280{
281 return mFirstRenderTargetSerial + TextureCubeMap::faceIndex(target);
282}
283
284}