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

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/angle/src/libGLESv2/renderer/Image9.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,732 @@
     1.4 +#include "precompiled.h"
     1.5 +//
     1.6 +// Copyright (c) 2002-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 +// Image9.cpp: Implements the rx::Image9 class, which acts as the interface to
    1.12 +// the actual underlying surfaces of a Texture.
    1.13 +
    1.14 +#include "libGLESv2/renderer/Image9.h"
    1.15 +
    1.16 +#include "libGLESv2/main.h"
    1.17 +#include "libGLESv2/Framebuffer.h"
    1.18 +#include "libGLESv2/Renderbuffer.h"
    1.19 +#include "libGLESv2/renderer/Renderer9.h"
    1.20 +#include "libGLESv2/renderer/RenderTarget9.h"
    1.21 +#include "libGLESv2/renderer/TextureStorage9.h"
    1.22 +
    1.23 +#include "libGLESv2/renderer/renderer9_utils.h"
    1.24 +#include "libGLESv2/renderer/generatemip.h"
    1.25 +
    1.26 +namespace rx
    1.27 +{
    1.28 +
    1.29 +Image9::Image9()
    1.30 +{
    1.31 +    mSurface = NULL;
    1.32 +    mRenderer = NULL;
    1.33 +
    1.34 +    mD3DPool = D3DPOOL_SYSTEMMEM;
    1.35 +    mD3DFormat = D3DFMT_UNKNOWN;
    1.36 +}
    1.37 +
    1.38 +Image9::~Image9()
    1.39 +{
    1.40 +    if (mSurface)
    1.41 +    {
    1.42 +        mSurface->Release();
    1.43 +    }
    1.44 +}
    1.45 +
    1.46 +void Image9::generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface)
    1.47 +{
    1.48 +    D3DSURFACE_DESC destDesc;
    1.49 +    HRESULT result = destSurface->GetDesc(&destDesc);
    1.50 +    ASSERT(SUCCEEDED(result));
    1.51 +
    1.52 +    D3DSURFACE_DESC sourceDesc;
    1.53 +    result = sourceSurface->GetDesc(&sourceDesc);
    1.54 +    ASSERT(SUCCEEDED(result));
    1.55 +
    1.56 +    ASSERT(sourceDesc.Format == destDesc.Format);
    1.57 +    ASSERT(sourceDesc.Width == 1 || sourceDesc.Width / 2 == destDesc.Width);
    1.58 +    ASSERT(sourceDesc.Height == 1 || sourceDesc.Height / 2 == destDesc.Height);
    1.59 +
    1.60 +    D3DLOCKED_RECT sourceLocked = {0};
    1.61 +    result = sourceSurface->LockRect(&sourceLocked, NULL, D3DLOCK_READONLY);
    1.62 +    ASSERT(SUCCEEDED(result));
    1.63 +
    1.64 +    D3DLOCKED_RECT destLocked = {0};
    1.65 +    result = destSurface->LockRect(&destLocked, NULL, 0);
    1.66 +    ASSERT(SUCCEEDED(result));
    1.67 +
    1.68 +    const unsigned char *sourceData = reinterpret_cast<const unsigned char*>(sourceLocked.pBits);
    1.69 +    unsigned char *destData = reinterpret_cast<unsigned char*>(destLocked.pBits);
    1.70 +
    1.71 +    if (sourceData && destData)
    1.72 +    {
    1.73 +        switch (sourceDesc.Format)
    1.74 +        {
    1.75 +          case D3DFMT_L8:
    1.76 +            GenerateMip<L8>(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch);
    1.77 +            break;
    1.78 +          case D3DFMT_A8L8:
    1.79 +            GenerateMip<A8L8>(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch);
    1.80 +            break;
    1.81 +          case D3DFMT_A8R8G8B8:
    1.82 +          case D3DFMT_X8R8G8B8:
    1.83 +            GenerateMip<A8R8G8B8>(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch);
    1.84 +            break;
    1.85 +          case D3DFMT_A16B16G16R16F:
    1.86 +            GenerateMip<A16B16G16R16F>(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch);
    1.87 +            break;
    1.88 +          case D3DFMT_A32B32G32R32F:
    1.89 +            GenerateMip<A32B32G32R32F>(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch);
    1.90 +            break;
    1.91 +          default:
    1.92 +            UNREACHABLE();
    1.93 +            break;
    1.94 +        }
    1.95 +
    1.96 +        destSurface->UnlockRect();
    1.97 +        sourceSurface->UnlockRect();
    1.98 +    }
    1.99 +}
   1.100 +
   1.101 +Image9 *Image9::makeImage9(Image *img)
   1.102 +{
   1.103 +    ASSERT(HAS_DYNAMIC_TYPE(rx::Image9*, img));
   1.104 +    return static_cast<rx::Image9*>(img);
   1.105 +}
   1.106 +
   1.107 +void Image9::generateMipmap(Image9 *dest, Image9 *source)
   1.108 +{
   1.109 +    IDirect3DSurface9 *sourceSurface = source->getSurface();
   1.110 +    if (sourceSurface == NULL)
   1.111 +        return gl::error(GL_OUT_OF_MEMORY);
   1.112 +
   1.113 +    IDirect3DSurface9 *destSurface = dest->getSurface();
   1.114 +    generateMip(destSurface, sourceSurface);
   1.115 +
   1.116 +    dest->markDirty();
   1.117 +}
   1.118 +
   1.119 +void Image9::copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source)
   1.120 +{
   1.121 +    D3DLOCKED_RECT sourceLock = {0};
   1.122 +    D3DLOCKED_RECT destLock = {0};
   1.123 +    
   1.124 +    source->LockRect(&sourceLock, NULL, 0);
   1.125 +    dest->LockRect(&destLock, NULL, 0);
   1.126 +    
   1.127 +    if (sourceLock.pBits && destLock.pBits)
   1.128 +    {
   1.129 +        D3DSURFACE_DESC desc;
   1.130 +        source->GetDesc(&desc);
   1.131 +
   1.132 +        int rows = d3d9::IsCompressedFormat(desc.Format) ? desc.Height / 4 : desc.Height;
   1.133 +        int bytes = d3d9::ComputeRowSize(desc.Format, desc.Width);
   1.134 +        ASSERT(bytes <= sourceLock.Pitch && bytes <= destLock.Pitch);
   1.135 +
   1.136 +        for(int i = 0; i < rows; i++)
   1.137 +        {
   1.138 +            memcpy((char*)destLock.pBits + destLock.Pitch * i, (char*)sourceLock.pBits + sourceLock.Pitch * i, bytes);
   1.139 +        }
   1.140 +
   1.141 +        source->UnlockRect();
   1.142 +        dest->UnlockRect();
   1.143 +    }
   1.144 +    else UNREACHABLE();
   1.145 +}
   1.146 +
   1.147 +bool Image9::redefine(rx::Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease)
   1.148 +{
   1.149 +    if (mWidth != width ||
   1.150 +        mHeight != height ||
   1.151 +        mInternalFormat != internalformat ||
   1.152 +        forceRelease)
   1.153 +    {
   1.154 +        mRenderer = Renderer9::makeRenderer9(renderer);
   1.155 +
   1.156 +        mWidth = width;
   1.157 +        mHeight = height;
   1.158 +        mInternalFormat = internalformat;
   1.159 +        // compute the d3d format that will be used
   1.160 +        mD3DFormat = mRenderer->ConvertTextureInternalFormat(internalformat);
   1.161 +        mActualFormat = d3d9_gl::GetEquivalentFormat(mD3DFormat);
   1.162 +
   1.163 +        if (mSurface)
   1.164 +        {
   1.165 +            mSurface->Release();
   1.166 +            mSurface = NULL;
   1.167 +        }
   1.168 +
   1.169 +        return true;
   1.170 +    }
   1.171 +
   1.172 +    return false;
   1.173 +}
   1.174 +
   1.175 +void Image9::createSurface()
   1.176 +{
   1.177 +    if(mSurface)
   1.178 +    {
   1.179 +        return;
   1.180 +    }
   1.181 +
   1.182 +    IDirect3DTexture9 *newTexture = NULL;
   1.183 +    IDirect3DSurface9 *newSurface = NULL;
   1.184 +    const D3DPOOL poolToUse = D3DPOOL_SYSTEMMEM;
   1.185 +    const D3DFORMAT d3dFormat = getD3DFormat();
   1.186 +    ASSERT(d3dFormat != D3DFMT_INTZ); // We should never get here for depth textures
   1.187 +
   1.188 +    if (mWidth != 0 && mHeight != 0)
   1.189 +    {
   1.190 +        int levelToFetch = 0;
   1.191 +        GLsizei requestWidth = mWidth;
   1.192 +        GLsizei requestHeight = mHeight;
   1.193 +        gl::MakeValidSize(true, gl::IsCompressed(mInternalFormat), &requestWidth, &requestHeight, &levelToFetch);
   1.194 +
   1.195 +        IDirect3DDevice9 *device = mRenderer->getDevice();
   1.196 +
   1.197 +        HRESULT result = device->CreateTexture(requestWidth, requestHeight, levelToFetch + 1, 0, d3dFormat,
   1.198 +                                                    poolToUse, &newTexture, NULL);
   1.199 +
   1.200 +        if (FAILED(result))
   1.201 +        {
   1.202 +            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
   1.203 +            ERR("Creating image surface failed.");
   1.204 +            return gl::error(GL_OUT_OF_MEMORY);
   1.205 +        }
   1.206 +
   1.207 +        newTexture->GetSurfaceLevel(levelToFetch, &newSurface);
   1.208 +        newTexture->Release();
   1.209 +    }
   1.210 +
   1.211 +    mSurface = newSurface;
   1.212 +    mDirty = false;
   1.213 +    mD3DPool = poolToUse;
   1.214 +}
   1.215 +
   1.216 +HRESULT Image9::lock(D3DLOCKED_RECT *lockedRect, const RECT *rect)
   1.217 +{
   1.218 +    createSurface();
   1.219 +
   1.220 +    HRESULT result = D3DERR_INVALIDCALL;
   1.221 +
   1.222 +    if (mSurface)
   1.223 +    {
   1.224 +        result = mSurface->LockRect(lockedRect, rect, 0);
   1.225 +        ASSERT(SUCCEEDED(result));
   1.226 +
   1.227 +        mDirty = true;
   1.228 +    }
   1.229 +
   1.230 +    return result;
   1.231 +}
   1.232 +
   1.233 +void Image9::unlock()
   1.234 +{
   1.235 +    if (mSurface)
   1.236 +    {
   1.237 +        HRESULT result = mSurface->UnlockRect();
   1.238 +        ASSERT(SUCCEEDED(result));
   1.239 +    }
   1.240 +}
   1.241 +
   1.242 +bool Image9::isRenderableFormat() const
   1.243 +{    
   1.244 +    return TextureStorage9::IsTextureFormatRenderable(getD3DFormat());
   1.245 +}
   1.246 +
   1.247 +D3DFORMAT Image9::getD3DFormat() const
   1.248 +{
   1.249 +    // this should only happen if the image hasn't been redefined first
   1.250 +    // which would be a bug by the caller
   1.251 +    ASSERT(mD3DFormat != D3DFMT_UNKNOWN);
   1.252 +
   1.253 +    return mD3DFormat;
   1.254 +}
   1.255 +
   1.256 +IDirect3DSurface9 *Image9::getSurface()
   1.257 +{
   1.258 +    createSurface();
   1.259 +
   1.260 +    return mSurface;
   1.261 +}
   1.262 +
   1.263 +void Image9::setManagedSurface(TextureStorageInterface2D *storage, int level)
   1.264 +{
   1.265 +    TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage->getStorageInstance());
   1.266 +    setManagedSurface(storage9->getSurfaceLevel(level, false));
   1.267 +}
   1.268 +
   1.269 +void Image9::setManagedSurface(TextureStorageInterfaceCube *storage, int face, int level)
   1.270 +{
   1.271 +    TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage->getStorageInstance());
   1.272 +    setManagedSurface(storage9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, false));
   1.273 +}
   1.274 +
   1.275 +void Image9::setManagedSurface(IDirect3DSurface9 *surface)
   1.276 +{
   1.277 +    D3DSURFACE_DESC desc;
   1.278 +    surface->GetDesc(&desc);
   1.279 +    ASSERT(desc.Pool == D3DPOOL_MANAGED);
   1.280 +
   1.281 +    if ((GLsizei)desc.Width == mWidth && (GLsizei)desc.Height == mHeight)
   1.282 +    {
   1.283 +        if (mSurface)
   1.284 +        {
   1.285 +            copyLockableSurfaces(surface, mSurface);
   1.286 +            mSurface->Release();
   1.287 +        }
   1.288 +
   1.289 +        mSurface = surface;
   1.290 +        mD3DPool = desc.Pool;
   1.291 +    }
   1.292 +}
   1.293 +
   1.294 +bool Image9::updateSurface(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
   1.295 +{
   1.296 +    ASSERT(getSurface() != NULL);
   1.297 +    TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage->getStorageInstance());
   1.298 +    return updateSurface(storage9->getSurfaceLevel(level, true), xoffset, yoffset, width, height);
   1.299 +}
   1.300 +
   1.301 +bool Image9::updateSurface(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
   1.302 +{
   1.303 +    ASSERT(getSurface() != NULL);
   1.304 +    TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage->getStorageInstance());
   1.305 +    return updateSurface(storage9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, true), xoffset, yoffset, width, height);
   1.306 +}
   1.307 +
   1.308 +bool Image9::updateSurface(IDirect3DSurface9 *destSurface, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
   1.309 +{
   1.310 +    if (!destSurface)
   1.311 +        return false;
   1.312 +
   1.313 +    IDirect3DSurface9 *sourceSurface = getSurface();
   1.314 +
   1.315 +    if (sourceSurface && sourceSurface != destSurface)
   1.316 +    {
   1.317 +        RECT rect;
   1.318 +        rect.left = xoffset;
   1.319 +        rect.top = yoffset;
   1.320 +        rect.right = xoffset + width;
   1.321 +        rect.bottom = yoffset + height;
   1.322 +
   1.323 +        POINT point = {rect.left, rect.top};
   1.324 +
   1.325 +        IDirect3DDevice9 *device = mRenderer->getDevice();
   1.326 +
   1.327 +        if (mD3DPool == D3DPOOL_MANAGED)
   1.328 +        {
   1.329 +            D3DSURFACE_DESC desc;
   1.330 +            sourceSurface->GetDesc(&desc);
   1.331 +
   1.332 +            IDirect3DSurface9 *surf = 0;
   1.333 +            HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL);
   1.334 +
   1.335 +            if (SUCCEEDED(result))
   1.336 +            {
   1.337 +                copyLockableSurfaces(surf, sourceSurface);
   1.338 +                result = device->UpdateSurface(surf, &rect, destSurface, &point);
   1.339 +                ASSERT(SUCCEEDED(result));
   1.340 +                surf->Release();
   1.341 +            }
   1.342 +        }
   1.343 +        else
   1.344 +        {
   1.345 +            // UpdateSurface: source must be SYSTEMMEM, dest must be DEFAULT pools 
   1.346 +            HRESULT result = device->UpdateSurface(sourceSurface, &rect, destSurface, &point);
   1.347 +            ASSERT(SUCCEEDED(result));
   1.348 +        }
   1.349 +    }
   1.350 +
   1.351 +    destSurface->Release();
   1.352 +    return true;
   1.353 +}
   1.354 +
   1.355 +// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input
   1.356 +// into the target pixel rectangle.
   1.357 +void Image9::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
   1.358 +                      GLint unpackAlignment, const void *input)
   1.359 +{
   1.360 +    RECT lockRect =
   1.361 +    {
   1.362 +        xoffset, yoffset,
   1.363 +        xoffset + width, yoffset + height
   1.364 +    };
   1.365 +
   1.366 +    D3DLOCKED_RECT locked;
   1.367 +    HRESULT result = lock(&locked, &lockRect);
   1.368 +    if (FAILED(result))
   1.369 +    {
   1.370 +        return;
   1.371 +    }
   1.372 +
   1.373 +
   1.374 +    GLsizei inputPitch = gl::ComputePitch(width, mInternalFormat, unpackAlignment);
   1.375 +
   1.376 +    switch (mInternalFormat)
   1.377 +    {
   1.378 +      case GL_ALPHA8_EXT:
   1.379 +        if (gl::supportsSSE2())
   1.380 +        {
   1.381 +            loadAlphaDataToBGRASSE2(width, height, inputPitch, input, locked.Pitch, locked.pBits);
   1.382 +        }
   1.383 +        else
   1.384 +        {
   1.385 +            loadAlphaDataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
   1.386 +        }
   1.387 +        break;
   1.388 +      case GL_LUMINANCE8_EXT:
   1.389 +        loadLuminanceDataToNativeOrBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits, getD3DFormat() == D3DFMT_L8);
   1.390 +        break;
   1.391 +      case GL_ALPHA32F_EXT:
   1.392 +        loadAlphaFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
   1.393 +        break;
   1.394 +      case GL_LUMINANCE32F_EXT:
   1.395 +        loadLuminanceFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
   1.396 +        break;
   1.397 +      case GL_ALPHA16F_EXT:
   1.398 +        loadAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
   1.399 +        break;
   1.400 +      case GL_LUMINANCE16F_EXT:
   1.401 +        loadLuminanceHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
   1.402 +        break;
   1.403 +      case GL_LUMINANCE8_ALPHA8_EXT:
   1.404 +        loadLuminanceAlphaDataToNativeOrBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits, getD3DFormat() == D3DFMT_A8L8);
   1.405 +        break;
   1.406 +      case GL_LUMINANCE_ALPHA32F_EXT:
   1.407 +        loadLuminanceAlphaFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
   1.408 +        break;
   1.409 +      case GL_LUMINANCE_ALPHA16F_EXT:
   1.410 +        loadLuminanceAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
   1.411 +        break;
   1.412 +      case GL_RGB8_OES:
   1.413 +        loadRGBUByteDataToBGRX(width, height, inputPitch, input, locked.Pitch, locked.pBits);
   1.414 +        break;
   1.415 +      case GL_RGB565:
   1.416 +        loadRGB565DataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
   1.417 +        break;
   1.418 +      case GL_RGBA8_OES:
   1.419 +        if (gl::supportsSSE2())
   1.420 +        {
   1.421 +            loadRGBAUByteDataToBGRASSE2(width, height, inputPitch, input, locked.Pitch, locked.pBits);
   1.422 +        }
   1.423 +        else
   1.424 +        {
   1.425 +            loadRGBAUByteDataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
   1.426 +        }
   1.427 +        break;
   1.428 +      case GL_RGBA4:
   1.429 +        loadRGBA4444DataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
   1.430 +        break;
   1.431 +      case GL_RGB5_A1:
   1.432 +        loadRGBA5551DataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
   1.433 +        break;
   1.434 +      case GL_BGRA8_EXT:
   1.435 +        loadBGRADataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
   1.436 +        break;
   1.437 +      // float textures are converted to RGBA, not BGRA, as they're stored that way in D3D
   1.438 +      case GL_RGB32F_EXT:
   1.439 +        loadRGBFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
   1.440 +        break;
   1.441 +      case GL_RGB16F_EXT:
   1.442 +        loadRGBHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
   1.443 +        break;
   1.444 +      case GL_RGBA32F_EXT:
   1.445 +        loadRGBAFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
   1.446 +        break;
   1.447 +      case GL_RGBA16F_EXT:
   1.448 +        loadRGBAHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
   1.449 +        break;
   1.450 +      default: UNREACHABLE(); 
   1.451 +    }
   1.452 +
   1.453 +    unlock();
   1.454 +}
   1.455 +
   1.456 +void Image9::loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
   1.457 +                                const void *input)
   1.458 +{
   1.459 +    ASSERT(xoffset % 4 == 0);
   1.460 +    ASSERT(yoffset % 4 == 0);
   1.461 +
   1.462 +    RECT lockRect = {
   1.463 +        xoffset, yoffset,
   1.464 +        xoffset + width, yoffset + height
   1.465 +    };
   1.466 +
   1.467 +    D3DLOCKED_RECT locked;
   1.468 +    HRESULT result = lock(&locked, &lockRect);
   1.469 +    if (FAILED(result))
   1.470 +    {
   1.471 +        return;
   1.472 +    }
   1.473 +
   1.474 +    GLsizei inputSize = gl::ComputeCompressedSize(width, height, mInternalFormat);
   1.475 +    GLsizei inputPitch = gl::ComputeCompressedPitch(width, mInternalFormat);
   1.476 +    int rows = inputSize / inputPitch;
   1.477 +    for (int i = 0; i < rows; ++i)
   1.478 +    {
   1.479 +        memcpy((void*)((BYTE*)locked.pBits + i * locked.Pitch), (void*)((BYTE*)input + i * inputPitch), inputPitch);
   1.480 +    }
   1.481 +
   1.482 +    unlock();
   1.483 +}
   1.484 +
   1.485 +// This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats and incomplete textures
   1.486 +void Image9::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
   1.487 +{
   1.488 +    RenderTarget9 *renderTarget = NULL;
   1.489 +    IDirect3DSurface9 *surface = NULL;
   1.490 +    gl::Renderbuffer *colorbuffer = source->getColorbuffer(0);
   1.491 +
   1.492 +    if (colorbuffer)
   1.493 +    {
   1.494 +        renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget());
   1.495 +    }
   1.496 +    
   1.497 +    if (renderTarget)
   1.498 +    {
   1.499 +        surface = renderTarget->getSurface();
   1.500 +    }
   1.501 +
   1.502 +    if (!surface)
   1.503 +    {
   1.504 +        ERR("Failed to retrieve the render target.");
   1.505 +        return gl::error(GL_OUT_OF_MEMORY);
   1.506 +    }
   1.507 +
   1.508 +    IDirect3DDevice9 *device = mRenderer->getDevice();
   1.509 +
   1.510 +    IDirect3DSurface9 *renderTargetData = NULL;
   1.511 +    D3DSURFACE_DESC description;
   1.512 +    surface->GetDesc(&description);
   1.513 +    
   1.514 +    HRESULT result = device->CreateOffscreenPlainSurface(description.Width, description.Height, description.Format, D3DPOOL_SYSTEMMEM, &renderTargetData, NULL);
   1.515 +
   1.516 +    if (FAILED(result))
   1.517 +    {
   1.518 +        ERR("Could not create matching destination surface.");
   1.519 +        surface->Release();
   1.520 +        return gl::error(GL_OUT_OF_MEMORY);
   1.521 +    }
   1.522 +
   1.523 +    result = device->GetRenderTargetData(surface, renderTargetData);
   1.524 +
   1.525 +    if (FAILED(result))
   1.526 +    {
   1.527 +        ERR("GetRenderTargetData unexpectedly failed.");
   1.528 +        renderTargetData->Release();
   1.529 +        surface->Release();
   1.530 +        return gl::error(GL_OUT_OF_MEMORY);
   1.531 +    }
   1.532 +
   1.533 +    RECT sourceRect = {x, y, x + width, y + height};
   1.534 +    RECT destRect = {xoffset, yoffset, xoffset + width, yoffset + height};
   1.535 +
   1.536 +    D3DLOCKED_RECT sourceLock = {0};
   1.537 +    result = renderTargetData->LockRect(&sourceLock, &sourceRect, 0);
   1.538 +
   1.539 +    if (FAILED(result))
   1.540 +    {
   1.541 +        ERR("Failed to lock the source surface (rectangle might be invalid).");
   1.542 +        renderTargetData->Release();
   1.543 +        surface->Release();
   1.544 +        return gl::error(GL_OUT_OF_MEMORY);
   1.545 +    }
   1.546 +
   1.547 +    D3DLOCKED_RECT destLock = {0};
   1.548 +    result = lock(&destLock, &destRect);
   1.549 +    
   1.550 +    if (FAILED(result))
   1.551 +    {
   1.552 +        ERR("Failed to lock the destination surface (rectangle might be invalid).");
   1.553 +        renderTargetData->UnlockRect();
   1.554 +        renderTargetData->Release();
   1.555 +        surface->Release();
   1.556 +        return gl::error(GL_OUT_OF_MEMORY);
   1.557 +    }
   1.558 +
   1.559 +    if (destLock.pBits && sourceLock.pBits)
   1.560 +    {
   1.561 +        unsigned char *source = (unsigned char*)sourceLock.pBits;
   1.562 +        unsigned char *dest = (unsigned char*)destLock.pBits;
   1.563 +
   1.564 +        switch (description.Format)
   1.565 +        {
   1.566 +          case D3DFMT_X8R8G8B8:
   1.567 +          case D3DFMT_A8R8G8B8:
   1.568 +            switch(getD3DFormat())
   1.569 +            {
   1.570 +              case D3DFMT_X8R8G8B8:
   1.571 +              case D3DFMT_A8R8G8B8:
   1.572 +                for(int y = 0; y < height; y++)
   1.573 +                {
   1.574 +                    memcpy(dest, source, 4 * width);
   1.575 +
   1.576 +                    source += sourceLock.Pitch;
   1.577 +                    dest += destLock.Pitch;
   1.578 +                }
   1.579 +                break;
   1.580 +              case D3DFMT_L8:
   1.581 +                for(int y = 0; y < height; y++)
   1.582 +                {
   1.583 +                    for(int x = 0; x < width; x++)
   1.584 +                    {
   1.585 +                        dest[x] = source[x * 4 + 2];
   1.586 +                    }
   1.587 +
   1.588 +                    source += sourceLock.Pitch;
   1.589 +                    dest += destLock.Pitch;
   1.590 +                }
   1.591 +                break;
   1.592 +              case D3DFMT_A8L8:
   1.593 +                for(int y = 0; y < height; y++)
   1.594 +                {
   1.595 +                    for(int x = 0; x < width; x++)
   1.596 +                    {
   1.597 +                        dest[x * 2 + 0] = source[x * 4 + 2];
   1.598 +                        dest[x * 2 + 1] = source[x * 4 + 3];
   1.599 +                    }
   1.600 +
   1.601 +                    source += sourceLock.Pitch;
   1.602 +                    dest += destLock.Pitch;
   1.603 +                }
   1.604 +                break;
   1.605 +              default:
   1.606 +                UNREACHABLE();
   1.607 +            }
   1.608 +            break;
   1.609 +          case D3DFMT_R5G6B5:
   1.610 +            switch(getD3DFormat())
   1.611 +            {
   1.612 +              case D3DFMT_X8R8G8B8:
   1.613 +                for(int y = 0; y < height; y++)
   1.614 +                {
   1.615 +                    for(int x = 0; x < width; x++)
   1.616 +                    {
   1.617 +                        unsigned short rgb = ((unsigned short*)source)[x];
   1.618 +                        unsigned char red = (rgb & 0xF800) >> 8;
   1.619 +                        unsigned char green = (rgb & 0x07E0) >> 3;
   1.620 +                        unsigned char blue = (rgb & 0x001F) << 3;
   1.621 +                        dest[x + 0] = blue | (blue >> 5);
   1.622 +                        dest[x + 1] = green | (green >> 6);
   1.623 +                        dest[x + 2] = red | (red >> 5);
   1.624 +                        dest[x + 3] = 0xFF;
   1.625 +                    }
   1.626 +
   1.627 +                    source += sourceLock.Pitch;
   1.628 +                    dest += destLock.Pitch;
   1.629 +                }
   1.630 +                break;
   1.631 +              case D3DFMT_L8:
   1.632 +                for(int y = 0; y < height; y++)
   1.633 +                {
   1.634 +                    for(int x = 0; x < width; x++)
   1.635 +                    {
   1.636 +                        unsigned char red = source[x * 2 + 1] & 0xF8;
   1.637 +                        dest[x] = red | (red >> 5);
   1.638 +                    }
   1.639 +
   1.640 +                    source += sourceLock.Pitch;
   1.641 +                    dest += destLock.Pitch;
   1.642 +                }
   1.643 +                break;
   1.644 +              default:
   1.645 +                UNREACHABLE();
   1.646 +            }
   1.647 +            break;
   1.648 +          case D3DFMT_A1R5G5B5:
   1.649 +            switch(getD3DFormat())
   1.650 +            {
   1.651 +              case D3DFMT_X8R8G8B8:
   1.652 +                for(int y = 0; y < height; y++)
   1.653 +                {
   1.654 +                    for(int x = 0; x < width; x++)
   1.655 +                    {
   1.656 +                        unsigned short argb = ((unsigned short*)source)[x];
   1.657 +                        unsigned char red = (argb & 0x7C00) >> 7;
   1.658 +                        unsigned char green = (argb & 0x03E0) >> 2;
   1.659 +                        unsigned char blue = (argb & 0x001F) << 3;
   1.660 +                        dest[x + 0] = blue | (blue >> 5);
   1.661 +                        dest[x + 1] = green | (green >> 5);
   1.662 +                        dest[x + 2] = red | (red >> 5);
   1.663 +                        dest[x + 3] = 0xFF;
   1.664 +                    }
   1.665 +
   1.666 +                    source += sourceLock.Pitch;
   1.667 +                    dest += destLock.Pitch;
   1.668 +                }
   1.669 +                break;
   1.670 +              case D3DFMT_A8R8G8B8:
   1.671 +                for(int y = 0; y < height; y++)
   1.672 +                {
   1.673 +                    for(int x = 0; x < width; x++)
   1.674 +                    {
   1.675 +                        unsigned short argb = ((unsigned short*)source)[x];
   1.676 +                        unsigned char red = (argb & 0x7C00) >> 7;
   1.677 +                        unsigned char green = (argb & 0x03E0) >> 2;
   1.678 +                        unsigned char blue = (argb & 0x001F) << 3;
   1.679 +                        unsigned char alpha = (signed short)argb >> 15;
   1.680 +                        dest[x + 0] = blue | (blue >> 5);
   1.681 +                        dest[x + 1] = green | (green >> 5);
   1.682 +                        dest[x + 2] = red | (red >> 5);
   1.683 +                        dest[x + 3] = alpha;
   1.684 +                    }
   1.685 +
   1.686 +                    source += sourceLock.Pitch;
   1.687 +                    dest += destLock.Pitch;
   1.688 +                }
   1.689 +                break;
   1.690 +              case D3DFMT_L8:
   1.691 +                for(int y = 0; y < height; y++)
   1.692 +                {
   1.693 +                    for(int x = 0; x < width; x++)
   1.694 +                    {
   1.695 +                        unsigned char red = source[x * 2 + 1] & 0x7C;
   1.696 +                        dest[x] = (red << 1) | (red >> 4);
   1.697 +                    }
   1.698 +
   1.699 +                    source += sourceLock.Pitch;
   1.700 +                    dest += destLock.Pitch;
   1.701 +                }
   1.702 +                break;
   1.703 +              case D3DFMT_A8L8:
   1.704 +                for(int y = 0; y < height; y++)
   1.705 +                {
   1.706 +                    for(int x = 0; x < width; x++)
   1.707 +                    {
   1.708 +                        unsigned char red = source[x * 2 + 1] & 0x7C;
   1.709 +                        dest[x * 2 + 0] = (red << 1) | (red >> 4);
   1.710 +                        dest[x * 2 + 1] = (signed char)source[x * 2 + 1] >> 7;
   1.711 +                    }
   1.712 +
   1.713 +                    source += sourceLock.Pitch;
   1.714 +                    dest += destLock.Pitch;
   1.715 +                }
   1.716 +                break;
   1.717 +              default:
   1.718 +                UNREACHABLE();
   1.719 +            }
   1.720 +            break;
   1.721 +          default:
   1.722 +            UNREACHABLE();
   1.723 +        }
   1.724 +    }
   1.725 +
   1.726 +    unlock();
   1.727 +    renderTargetData->UnlockRect();
   1.728 +
   1.729 +    renderTargetData->Release();
   1.730 +    surface->Release();
   1.731 +
   1.732 +    mDirty = true;
   1.733 +}
   1.734 +
   1.735 +}
   1.736 \ No newline at end of file

mercurial