1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/angle/src/libGLESv2/renderer/TextureStorage9.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,328 @@ 1.4 +#include "precompiled.h" 1.5 +// 1.6 +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. 1.7 +// Use of this source code is governed by a BSD-style license that can be 1.8 +// found in the LICENSE file. 1.9 +// 1.10 + 1.11 +// TextureStorage9.cpp: Implements the abstract rx::TextureStorage9 class and its concrete derived 1.12 +// classes TextureStorage9_2D and TextureStorage9_Cube, which act as the interface to the 1.13 +// D3D9 texture. 1.14 + 1.15 +#include "libGLESv2/main.h" 1.16 +#include "libGLESv2/renderer/Renderer9.h" 1.17 +#include "libGLESv2/renderer/TextureStorage9.h" 1.18 +#include "libGLESv2/renderer/SwapChain9.h" 1.19 +#include "libGLESv2/renderer/RenderTarget9.h" 1.20 +#include "libGLESv2/renderer/renderer9_utils.h" 1.21 +#include "libGLESv2/Texture.h" 1.22 + 1.23 +namespace rx 1.24 +{ 1.25 +TextureStorage9::TextureStorage9(Renderer *renderer, DWORD usage) 1.26 + : mLodOffset(0), 1.27 + mRenderer(Renderer9::makeRenderer9(renderer)), 1.28 + mD3DUsage(usage), 1.29 + mD3DPool(mRenderer->getTexturePool(usage)) 1.30 +{ 1.31 +} 1.32 + 1.33 +TextureStorage9::~TextureStorage9() 1.34 +{ 1.35 +} 1.36 + 1.37 +TextureStorage9 *TextureStorage9::makeTextureStorage9(TextureStorage *storage) 1.38 +{ 1.39 + ASSERT(HAS_DYNAMIC_TYPE(TextureStorage9*, storage)); 1.40 + return static_cast<TextureStorage9*>(storage); 1.41 +} 1.42 + 1.43 +DWORD TextureStorage9::GetTextureUsage(D3DFORMAT d3dfmt, GLenum glusage, bool forceRenderable) 1.44 +{ 1.45 + DWORD d3dusage = 0; 1.46 + 1.47 + if (d3dfmt == D3DFMT_INTZ) 1.48 + { 1.49 + d3dusage |= D3DUSAGE_DEPTHSTENCIL; 1.50 + } 1.51 + else if(forceRenderable || (TextureStorage9::IsTextureFormatRenderable(d3dfmt) && (glusage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE))) 1.52 + { 1.53 + d3dusage |= D3DUSAGE_RENDERTARGET; 1.54 + } 1.55 + return d3dusage; 1.56 +} 1.57 + 1.58 +bool TextureStorage9::IsTextureFormatRenderable(D3DFORMAT format) 1.59 +{ 1.60 + if (format == D3DFMT_INTZ) 1.61 + { 1.62 + return true; 1.63 + } 1.64 + switch(format) 1.65 + { 1.66 + case D3DFMT_L8: 1.67 + case D3DFMT_A8L8: 1.68 + case D3DFMT_DXT1: 1.69 + case D3DFMT_DXT3: 1.70 + case D3DFMT_DXT5: 1.71 + return false; 1.72 + case D3DFMT_A8R8G8B8: 1.73 + case D3DFMT_X8R8G8B8: 1.74 + case D3DFMT_A16B16G16R16F: 1.75 + case D3DFMT_A32B32G32R32F: 1.76 + return true; 1.77 + default: 1.78 + UNREACHABLE(); 1.79 + } 1.80 + 1.81 + return false; 1.82 +} 1.83 + 1.84 +bool TextureStorage9::isRenderTarget() const 1.85 +{ 1.86 + return (mD3DUsage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL)) != 0; 1.87 +} 1.88 + 1.89 +bool TextureStorage9::isManaged() const 1.90 +{ 1.91 + return (mD3DPool == D3DPOOL_MANAGED); 1.92 +} 1.93 + 1.94 +D3DPOOL TextureStorage9::getPool() const 1.95 +{ 1.96 + return mD3DPool; 1.97 +} 1.98 + 1.99 +DWORD TextureStorage9::getUsage() const 1.100 +{ 1.101 + return mD3DUsage; 1.102 +} 1.103 + 1.104 +int TextureStorage9::getLodOffset() const 1.105 +{ 1.106 + return mLodOffset; 1.107 +} 1.108 + 1.109 +int TextureStorage9::levelCount() 1.110 +{ 1.111 + return getBaseTexture() ? getBaseTexture()->GetLevelCount() - getLodOffset() : 0; 1.112 +} 1.113 + 1.114 +TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, SwapChain9 *swapchain) : TextureStorage9(renderer, D3DUSAGE_RENDERTARGET) 1.115 +{ 1.116 + IDirect3DTexture9 *surfaceTexture = swapchain->getOffscreenTexture(); 1.117 + mTexture = surfaceTexture; 1.118 + mRenderTarget = NULL; 1.119 + 1.120 + initializeRenderTarget(); 1.121 +} 1.122 + 1.123 +TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height) 1.124 + : TextureStorage9(renderer, GetTextureUsage(Renderer9::makeRenderer9(renderer)->ConvertTextureInternalFormat(internalformat), usage, forceRenderable)) 1.125 +{ 1.126 + mTexture = NULL; 1.127 + mRenderTarget = NULL; 1.128 + // if the width or height is not positive this should be treated as an incomplete texture 1.129 + // we handle that here by skipping the d3d texture creation 1.130 + if (width > 0 && height > 0) 1.131 + { 1.132 + IDirect3DDevice9 *device = mRenderer->getDevice(); 1.133 + gl::MakeValidSize(false, gl::IsCompressed(internalformat), &width, &height, &mLodOffset); 1.134 + HRESULT result = device->CreateTexture(width, height, levels ? levels + mLodOffset : 0, getUsage(), 1.135 + mRenderer->ConvertTextureInternalFormat(internalformat), getPool(), &mTexture, NULL); 1.136 + 1.137 + if (FAILED(result)) 1.138 + { 1.139 + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); 1.140 + gl::error(GL_OUT_OF_MEMORY); 1.141 + } 1.142 + } 1.143 + 1.144 + initializeRenderTarget(); 1.145 +} 1.146 + 1.147 +TextureStorage9_2D::~TextureStorage9_2D() 1.148 +{ 1.149 + if (mTexture) 1.150 + { 1.151 + mTexture->Release(); 1.152 + } 1.153 + 1.154 + delete mRenderTarget; 1.155 +} 1.156 + 1.157 +TextureStorage9_2D *TextureStorage9_2D::makeTextureStorage9_2D(TextureStorage *storage) 1.158 +{ 1.159 + ASSERT(HAS_DYNAMIC_TYPE(TextureStorage9_2D*, storage)); 1.160 + return static_cast<TextureStorage9_2D*>(storage); 1.161 +} 1.162 + 1.163 +// Increments refcount on surface. 1.164 +// caller must Release() the returned surface 1.165 +IDirect3DSurface9 *TextureStorage9_2D::getSurfaceLevel(int level, bool dirty) 1.166 +{ 1.167 + IDirect3DSurface9 *surface = NULL; 1.168 + 1.169 + if (mTexture) 1.170 + { 1.171 + HRESULT result = mTexture->GetSurfaceLevel(level + mLodOffset, &surface); 1.172 + ASSERT(SUCCEEDED(result)); 1.173 + 1.174 + // With managed textures the driver needs to be informed of updates to the lower mipmap levels 1.175 + if (level + mLodOffset != 0 && isManaged() && dirty) 1.176 + { 1.177 + mTexture->AddDirtyRect(NULL); 1.178 + } 1.179 + } 1.180 + 1.181 + return surface; 1.182 +} 1.183 + 1.184 +RenderTarget *TextureStorage9_2D::getRenderTarget() 1.185 +{ 1.186 + return mRenderTarget; 1.187 +} 1.188 + 1.189 +void TextureStorage9_2D::generateMipmap(int level) 1.190 +{ 1.191 + IDirect3DSurface9 *upper = getSurfaceLevel(level - 1, false); 1.192 + IDirect3DSurface9 *lower = getSurfaceLevel(level, true); 1.193 + 1.194 + if (upper != NULL && lower != NULL) 1.195 + { 1.196 + mRenderer->boxFilter(upper, lower); 1.197 + } 1.198 + 1.199 + if (upper != NULL) upper->Release(); 1.200 + if (lower != NULL) lower->Release(); 1.201 +} 1.202 + 1.203 +IDirect3DBaseTexture9 *TextureStorage9_2D::getBaseTexture() const 1.204 +{ 1.205 + return mTexture; 1.206 +} 1.207 + 1.208 +void TextureStorage9_2D::initializeRenderTarget() 1.209 +{ 1.210 + ASSERT(mRenderTarget == NULL); 1.211 + 1.212 + if (mTexture != NULL && isRenderTarget()) 1.213 + { 1.214 + IDirect3DSurface9 *surface = getSurfaceLevel(0, false); 1.215 + 1.216 + mRenderTarget = new RenderTarget9(mRenderer, surface); 1.217 + } 1.218 +} 1.219 + 1.220 +TextureStorage9_Cube::TextureStorage9_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size) 1.221 + : TextureStorage9(renderer, GetTextureUsage(Renderer9::makeRenderer9(renderer)->ConvertTextureInternalFormat(internalformat), usage, forceRenderable)) 1.222 +{ 1.223 + mTexture = NULL; 1.224 + for (int i = 0; i < 6; ++i) 1.225 + { 1.226 + mRenderTarget[i] = NULL; 1.227 + } 1.228 + 1.229 + // if the size is not positive this should be treated as an incomplete texture 1.230 + // we handle that here by skipping the d3d texture creation 1.231 + if (size > 0) 1.232 + { 1.233 + IDirect3DDevice9 *device = mRenderer->getDevice(); 1.234 + int height = size; 1.235 + gl::MakeValidSize(false, gl::IsCompressed(internalformat), &size, &height, &mLodOffset); 1.236 + HRESULT result = device->CreateCubeTexture(size, levels ? levels + mLodOffset : 0, getUsage(), 1.237 + mRenderer->ConvertTextureInternalFormat(internalformat), getPool(), &mTexture, NULL); 1.238 + 1.239 + if (FAILED(result)) 1.240 + { 1.241 + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); 1.242 + gl::error(GL_OUT_OF_MEMORY); 1.243 + } 1.244 + } 1.245 + 1.246 + initializeRenderTarget(); 1.247 +} 1.248 + 1.249 +TextureStorage9_Cube::~TextureStorage9_Cube() 1.250 +{ 1.251 + if (mTexture) 1.252 + { 1.253 + mTexture->Release(); 1.254 + } 1.255 + 1.256 + for (int i = 0; i < 6; ++i) 1.257 + { 1.258 + delete mRenderTarget[i]; 1.259 + } 1.260 +} 1.261 + 1.262 +TextureStorage9_Cube *TextureStorage9_Cube::makeTextureStorage9_Cube(TextureStorage *storage) 1.263 +{ 1.264 + ASSERT(HAS_DYNAMIC_TYPE(TextureStorage9_Cube*, storage)); 1.265 + return static_cast<TextureStorage9_Cube*>(storage); 1.266 +} 1.267 + 1.268 +// Increments refcount on surface. 1.269 +// caller must Release() the returned surface 1.270 +IDirect3DSurface9 *TextureStorage9_Cube::getCubeMapSurface(GLenum faceTarget, int level, bool dirty) 1.271 +{ 1.272 + IDirect3DSurface9 *surface = NULL; 1.273 + 1.274 + if (mTexture) 1.275 + { 1.276 + D3DCUBEMAP_FACES face = gl_d3d9::ConvertCubeFace(faceTarget); 1.277 + HRESULT result = mTexture->GetCubeMapSurface(face, level + mLodOffset, &surface); 1.278 + ASSERT(SUCCEEDED(result)); 1.279 + 1.280 + // With managed textures the driver needs to be informed of updates to the lower mipmap levels 1.281 + if (level != 0 && isManaged() && dirty) 1.282 + { 1.283 + mTexture->AddDirtyRect(face, NULL); 1.284 + } 1.285 + } 1.286 + 1.287 + return surface; 1.288 +} 1.289 + 1.290 +RenderTarget *TextureStorage9_Cube::getRenderTarget(GLenum faceTarget) 1.291 +{ 1.292 + return mRenderTarget[gl::TextureCubeMap::faceIndex(faceTarget)]; 1.293 +} 1.294 + 1.295 +void TextureStorage9_Cube::generateMipmap(int face, int level) 1.296 +{ 1.297 + IDirect3DSurface9 *upper = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level - 1, false); 1.298 + IDirect3DSurface9 *lower = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, true); 1.299 + 1.300 + if (upper != NULL && lower != NULL) 1.301 + { 1.302 + mRenderer->boxFilter(upper, lower); 1.303 + } 1.304 + 1.305 + if (upper != NULL) upper->Release(); 1.306 + if (lower != NULL) lower->Release(); 1.307 +} 1.308 + 1.309 +IDirect3DBaseTexture9 *TextureStorage9_Cube::getBaseTexture() const 1.310 +{ 1.311 + return mTexture; 1.312 +} 1.313 + 1.314 +void TextureStorage9_Cube::initializeRenderTarget() 1.315 +{ 1.316 + if (mTexture != NULL && isRenderTarget()) 1.317 + { 1.318 + IDirect3DSurface9 *surface = NULL; 1.319 + 1.320 + for (int i = 0; i < 6; ++i) 1.321 + { 1.322 + ASSERT(mRenderTarget[i] == NULL); 1.323 + 1.324 + surface = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, false); 1.325 + 1.326 + mRenderTarget[i] = new RenderTarget9(mRenderer, surface); 1.327 + } 1.328 + } 1.329 +} 1.330 + 1.331 +} 1.332 \ No newline at end of file