gfx/angle/src/libGLESv2/renderer/TextureStorage9.cpp

changeset 0
6474c204b198
     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

mercurial