Home | History | Annotate | Download | only in d3d9
      1 //
      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 // Image9.cpp: Implements the rx::Image9 class, which acts as the interface to
      8 // the actual underlying surfaces of a Texture.
      9 
     10 #include "libGLESv2/renderer/d3d/d3d9/Image9.h"
     11 #include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h"
     12 #include "libGLESv2/renderer/d3d/d3d9/formatutils9.h"
     13 #include "libGLESv2/renderer/d3d/d3d9/Renderer9.h"
     14 #include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h"
     15 #include "libGLESv2/renderer/d3d/d3d9/TextureStorage9.h"
     16 #include "libGLESv2/main.h"
     17 #include "libGLESv2/Framebuffer.h"
     18 #include "libGLESv2/FramebufferAttachment.h"
     19 #include "libGLESv2/Renderbuffer.h"
     20 
     21 
     22 namespace rx
     23 {
     24 
     25 Image9::Image9()
     26 {
     27     mSurface = NULL;
     28     mRenderer = NULL;
     29 
     30     mD3DPool = D3DPOOL_SYSTEMMEM;
     31     mD3DFormat = D3DFMT_UNKNOWN;
     32 }
     33 
     34 Image9::~Image9()
     35 {
     36     SafeRelease(mSurface);
     37 }
     38 
     39 void Image9::generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface)
     40 {
     41     D3DSURFACE_DESC destDesc;
     42     HRESULT result = destSurface->GetDesc(&destDesc);
     43     ASSERT(SUCCEEDED(result));
     44 
     45     D3DSURFACE_DESC sourceDesc;
     46     result = sourceSurface->GetDesc(&sourceDesc);
     47     ASSERT(SUCCEEDED(result));
     48 
     49     ASSERT(sourceDesc.Format == destDesc.Format);
     50     ASSERT(sourceDesc.Width == 1 || sourceDesc.Width / 2 == destDesc.Width);
     51     ASSERT(sourceDesc.Height == 1 || sourceDesc.Height / 2 == destDesc.Height);
     52 
     53     const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(sourceDesc.Format);
     54     ASSERT(d3dFormatInfo.mipGenerationFunction != NULL);
     55 
     56     D3DLOCKED_RECT sourceLocked = {0};
     57     result = sourceSurface->LockRect(&sourceLocked, NULL, D3DLOCK_READONLY);
     58     ASSERT(SUCCEEDED(result));
     59 
     60     D3DLOCKED_RECT destLocked = {0};
     61     result = destSurface->LockRect(&destLocked, NULL, 0);
     62     ASSERT(SUCCEEDED(result));
     63 
     64     const uint8_t *sourceData = reinterpret_cast<const uint8_t*>(sourceLocked.pBits);
     65     uint8_t *destData = reinterpret_cast<uint8_t*>(destLocked.pBits);
     66 
     67     if (sourceData && destData)
     68     {
     69         d3dFormatInfo.mipGenerationFunction(sourceDesc.Width, sourceDesc.Height, 1, sourceData, sourceLocked.Pitch, 0,
     70                                             destData, destLocked.Pitch, 0);
     71     }
     72 
     73     destSurface->UnlockRect();
     74     sourceSurface->UnlockRect();
     75 }
     76 
     77 Image9 *Image9::makeImage9(Image *img)
     78 {
     79     ASSERT(HAS_DYNAMIC_TYPE(rx::Image9*, img));
     80     return static_cast<rx::Image9*>(img);
     81 }
     82 
     83 void Image9::generateMipmap(Image9 *dest, Image9 *source)
     84 {
     85     IDirect3DSurface9 *sourceSurface = source->getSurface();
     86     if (sourceSurface == NULL)
     87         return gl::error(GL_OUT_OF_MEMORY);
     88 
     89     IDirect3DSurface9 *destSurface = dest->getSurface();
     90     generateMip(destSurface, sourceSurface);
     91 
     92     dest->markDirty();
     93 }
     94 
     95 void Image9::copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source)
     96 {
     97     D3DLOCKED_RECT sourceLock = {0};
     98     D3DLOCKED_RECT destLock = {0};
     99 
    100     source->LockRect(&sourceLock, NULL, 0);
    101     dest->LockRect(&destLock, NULL, 0);
    102 
    103     if (sourceLock.pBits && destLock.pBits)
    104     {
    105         D3DSURFACE_DESC desc;
    106         source->GetDesc(&desc);
    107 
    108         const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(desc.Format);
    109         unsigned int rows = desc.Height / d3dFormatInfo.blockHeight;
    110 
    111         unsigned int bytes = d3d9::ComputeBlockSize(desc.Format, desc.Width, d3dFormatInfo.blockHeight);
    112         ASSERT(bytes <= static_cast<unsigned int>(sourceLock.Pitch) &&
    113                bytes <= static_cast<unsigned int>(destLock.Pitch));
    114 
    115         for(unsigned int i = 0; i < rows; i++)
    116         {
    117             memcpy((char*)destLock.pBits + destLock.Pitch * i, (char*)sourceLock.pBits + sourceLock.Pitch * i, bytes);
    118         }
    119 
    120         source->UnlockRect();
    121         dest->UnlockRect();
    122     }
    123     else UNREACHABLE();
    124 }
    125 
    126 bool Image9::redefine(rx::Renderer *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease)
    127 {
    128     // 3D textures are not supported by the D3D9 backend.
    129     ASSERT(depth <= 1);
    130 
    131     // Only 2D and cube texture are supported by the D3D9 backend.
    132     ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
    133 
    134     if (mWidth != width ||
    135         mHeight != height ||
    136         mDepth != depth ||
    137         mInternalFormat != internalformat ||
    138         forceRelease)
    139     {
    140         mRenderer = Renderer9::makeRenderer9(renderer);
    141 
    142         mWidth = width;
    143         mHeight = height;
    144         mDepth = depth;
    145         mInternalFormat = internalformat;
    146 
    147         // compute the d3d format that will be used
    148         const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(internalformat);
    149         const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(d3d9FormatInfo.texFormat);
    150         mD3DFormat = d3d9FormatInfo.texFormat;
    151         mActualFormat = d3dFormatInfo.internalFormat;
    152         mRenderable = (d3d9FormatInfo.renderFormat != D3DFMT_UNKNOWN);
    153 
    154         SafeRelease(mSurface);
    155         mDirty = (d3d9FormatInfo.dataInitializerFunction != NULL);
    156 
    157         return true;
    158     }
    159 
    160     return false;
    161 }
    162 
    163 void Image9::createSurface()
    164 {
    165     if(mSurface)
    166     {
    167         return;
    168     }
    169 
    170     IDirect3DTexture9 *newTexture = NULL;
    171     IDirect3DSurface9 *newSurface = NULL;
    172     const D3DPOOL poolToUse = D3DPOOL_SYSTEMMEM;
    173     const D3DFORMAT d3dFormat = getD3DFormat();
    174 
    175     if (mWidth != 0 && mHeight != 0)
    176     {
    177         int levelToFetch = 0;
    178         GLsizei requestWidth = mWidth;
    179         GLsizei requestHeight = mHeight;
    180         d3d9::MakeValidSize(true, d3dFormat, &requestWidth, &requestHeight, &levelToFetch);
    181 
    182         IDirect3DDevice9 *device = mRenderer->getDevice();
    183 
    184         HRESULT result = device->CreateTexture(requestWidth, requestHeight, levelToFetch + 1, 0, d3dFormat,
    185                                                     poolToUse, &newTexture, NULL);
    186 
    187         if (FAILED(result))
    188         {
    189             ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
    190             ERR("Creating image surface failed.");
    191             return gl::error(GL_OUT_OF_MEMORY);
    192         }
    193 
    194         newTexture->GetSurfaceLevel(levelToFetch, &newSurface);
    195         SafeRelease(newTexture);
    196 
    197         const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat);
    198         if (d3dFormatInfo.dataInitializerFunction != NULL)
    199         {
    200             RECT entireRect;
    201             entireRect.left = 0;
    202             entireRect.right = mWidth;
    203             entireRect.top = 0;
    204             entireRect.bottom = mHeight;
    205 
    206             D3DLOCKED_RECT lockedRect;
    207             result = newSurface->LockRect(&lockedRect, &entireRect, 0);
    208             ASSERT(SUCCEEDED(result));
    209 
    210             d3dFormatInfo.dataInitializerFunction(mWidth, mHeight, 1, reinterpret_cast<uint8_t*>(lockedRect.pBits),
    211                                                   lockedRect.Pitch, 0);
    212 
    213             result = newSurface->UnlockRect();
    214             ASSERT(SUCCEEDED(result));
    215         }
    216     }
    217 
    218     mSurface = newSurface;
    219     mDirty = false;
    220     mD3DPool = poolToUse;
    221 }
    222 
    223 HRESULT Image9::lock(D3DLOCKED_RECT *lockedRect, const RECT *rect)
    224 {
    225     createSurface();
    226 
    227     HRESULT result = D3DERR_INVALIDCALL;
    228 
    229     if (mSurface)
    230     {
    231         result = mSurface->LockRect(lockedRect, rect, 0);
    232         ASSERT(SUCCEEDED(result));
    233 
    234         mDirty = true;
    235     }
    236 
    237     return result;
    238 }
    239 
    240 void Image9::unlock()
    241 {
    242     if (mSurface)
    243     {
    244         HRESULT result = mSurface->UnlockRect();
    245         UNUSED_ASSERTION_VARIABLE(result);
    246         ASSERT(SUCCEEDED(result));
    247     }
    248 }
    249 
    250 D3DFORMAT Image9::getD3DFormat() const
    251 {
    252     // this should only happen if the image hasn't been redefined first
    253     // which would be a bug by the caller
    254     ASSERT(mD3DFormat != D3DFMT_UNKNOWN);
    255 
    256     return mD3DFormat;
    257 }
    258 
    259 bool Image9::isDirty() const
    260 {
    261     // Make sure to that this image is marked as dirty even if the staging texture hasn't been created yet
    262     // if initialization is required before use.
    263     return (mSurface || d3d9::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != NULL) && mDirty;
    264 }
    265 
    266 IDirect3DSurface9 *Image9::getSurface()
    267 {
    268     createSurface();
    269 
    270     return mSurface;
    271 }
    272 
    273 void Image9::setManagedSurface2D(TextureStorage *storage, int level)
    274 {
    275     TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage);
    276     setManagedSurface(storage9->getSurfaceLevel(level, false));
    277 }
    278 
    279 void Image9::setManagedSurfaceCube(TextureStorage *storage, int face, int level)
    280 {
    281     TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage);
    282     setManagedSurface(storage9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, false));
    283 }
    284 
    285 void Image9::setManagedSurface(IDirect3DSurface9 *surface)
    286 {
    287     D3DSURFACE_DESC desc;
    288     surface->GetDesc(&desc);
    289     ASSERT(desc.Pool == D3DPOOL_MANAGED);
    290 
    291     if ((GLsizei)desc.Width == mWidth && (GLsizei)desc.Height == mHeight)
    292     {
    293         if (mSurface)
    294         {
    295             copyLockableSurfaces(surface, mSurface);
    296             SafeRelease(mSurface);
    297         }
    298 
    299         mSurface = surface;
    300         mD3DPool = desc.Pool;
    301     }
    302 }
    303 
    304 bool Image9::copyToStorage2D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
    305 {
    306     ASSERT(getSurface() != NULL);
    307     TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage);
    308     return copyToSurface(storage9->getSurfaceLevel(level, true), xoffset, yoffset, width, height);
    309 }
    310 
    311 bool Image9::copyToStorageCube(TextureStorage *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
    312 {
    313     ASSERT(getSurface() != NULL);
    314     TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage);
    315     return copyToSurface(storage9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, true), xoffset, yoffset, width, height);
    316 }
    317 
    318 bool Image9::copyToStorage3D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth)
    319 {
    320     // 3D textures are not supported by the D3D9 backend.
    321     UNREACHABLE();
    322     return false;
    323 }
    324 
    325 bool Image9::copyToStorage2DArray(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height)
    326 {
    327     // 2D array textures are not supported by the D3D9 backend.
    328     UNREACHABLE();
    329     return false;
    330 }
    331 
    332 bool Image9::copyToSurface(IDirect3DSurface9 *destSurface, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
    333 {
    334     ASSERT(width > 0 && height > 0);
    335 
    336     if (!destSurface)
    337         return false;
    338 
    339     IDirect3DSurface9 *sourceSurface = getSurface();
    340 
    341     if (sourceSurface && sourceSurface != destSurface)
    342     {
    343         RECT rect;
    344         rect.left = xoffset;
    345         rect.top = yoffset;
    346         rect.right = xoffset + width;
    347         rect.bottom = yoffset + height;
    348 
    349         POINT point = {rect.left, rect.top};
    350 
    351         IDirect3DDevice9 *device = mRenderer->getDevice();
    352 
    353         if (mD3DPool == D3DPOOL_MANAGED)
    354         {
    355             D3DSURFACE_DESC desc;
    356             sourceSurface->GetDesc(&desc);
    357 
    358             IDirect3DSurface9 *surf = 0;
    359             HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL);
    360 
    361             if (SUCCEEDED(result))
    362             {
    363                 copyLockableSurfaces(surf, sourceSurface);
    364                 result = device->UpdateSurface(surf, &rect, destSurface, &point);
    365                 ASSERT(SUCCEEDED(result));
    366                 SafeRelease(surf);
    367             }
    368         }
    369         else
    370         {
    371             // UpdateSurface: source must be SYSTEMMEM, dest must be DEFAULT pools
    372             HRESULT result = device->UpdateSurface(sourceSurface, &rect, destSurface, &point);
    373             UNUSED_ASSERTION_VARIABLE(result);
    374             ASSERT(SUCCEEDED(result));
    375         }
    376     }
    377 
    378     SafeRelease(destSurface);
    379     return true;
    380 }
    381 
    382 // Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input
    383 // into the target pixel rectangle.
    384 void Image9::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
    385                       GLint unpackAlignment, GLenum type, const void *input)
    386 {
    387     // 3D textures are not supported by the D3D9 backend.
    388     ASSERT(zoffset == 0 && depth == 1);
    389 
    390     const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
    391     GLsizei inputRowPitch = formatInfo.computeRowPitch(type, width, unpackAlignment);
    392 
    393     const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat);
    394     ASSERT(d3dFormatInfo.loadFunction != NULL);
    395 
    396     RECT lockRect =
    397     {
    398         xoffset, yoffset,
    399         xoffset + width, yoffset + height
    400     };
    401 
    402     D3DLOCKED_RECT locked;
    403     HRESULT result = lock(&locked, &lockRect);
    404     if (FAILED(result))
    405     {
    406         return;
    407     }
    408 
    409     d3dFormatInfo.loadFunction(width, height, depth,
    410                                reinterpret_cast<const uint8_t*>(input), inputRowPitch, 0,
    411                                reinterpret_cast<uint8_t*>(locked.pBits), locked.Pitch, 0);
    412 
    413     unlock();
    414 }
    415 
    416 void Image9::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
    417                                 const void *input)
    418 {
    419     // 3D textures are not supported by the D3D9 backend.
    420     ASSERT(zoffset == 0 && depth == 1);
    421 
    422     const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
    423     GLsizei inputRowPitch = formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, width, 1);
    424     GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, width, height, 1);
    425 
    426     const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat);
    427 
    428     ASSERT(xoffset % d3d9::GetD3DFormatInfo(d3d9FormatInfo.texFormat).blockWidth == 0);
    429     ASSERT(yoffset % d3d9::GetD3DFormatInfo(d3d9FormatInfo.texFormat).blockHeight == 0);
    430 
    431     ASSERT(d3d9FormatInfo.loadFunction != NULL);
    432 
    433     RECT lockRect =
    434     {
    435         xoffset, yoffset,
    436         xoffset + width, yoffset + height
    437     };
    438 
    439     D3DLOCKED_RECT locked;
    440     HRESULT result = lock(&locked, &lockRect);
    441     if (FAILED(result))
    442     {
    443         return;
    444     }
    445 
    446     d3d9FormatInfo.loadFunction(width, height, depth,
    447                                 reinterpret_cast<const uint8_t*>(input), inputRowPitch, inputDepthPitch,
    448                                 reinterpret_cast<uint8_t*>(locked.pBits), locked.Pitch, 0);
    449 
    450     unlock();
    451 }
    452 
    453 // This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats and incomplete textures
    454 void Image9::copy(GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
    455 {
    456     // ES3.0 only behaviour to copy into a 3d texture
    457     ASSERT(zoffset == 0);
    458 
    459     RenderTarget9 *renderTarget = NULL;
    460     IDirect3DSurface9 *surface = NULL;
    461     gl::FramebufferAttachment *colorbuffer = source->getColorbuffer(0);
    462 
    463     if (colorbuffer)
    464     {
    465         renderTarget = d3d9::GetAttachmentRenderTarget(colorbuffer);
    466     }
    467 
    468     if (renderTarget)
    469     {
    470         surface = renderTarget->getSurface();
    471     }
    472 
    473     if (!surface)
    474     {
    475         ERR("Failed to retrieve the render target.");
    476         return gl::error(GL_OUT_OF_MEMORY);
    477     }
    478 
    479     IDirect3DDevice9 *device = mRenderer->getDevice();
    480 
    481     IDirect3DSurface9 *renderTargetData = NULL;
    482     D3DSURFACE_DESC description;
    483     surface->GetDesc(&description);
    484 
    485     HRESULT result = device->CreateOffscreenPlainSurface(description.Width, description.Height, description.Format, D3DPOOL_SYSTEMMEM, &renderTargetData, NULL);
    486 
    487     if (FAILED(result))
    488     {
    489         ERR("Could not create matching destination surface.");
    490         SafeRelease(surface);
    491         return gl::error(GL_OUT_OF_MEMORY);
    492     }
    493 
    494     result = device->GetRenderTargetData(surface, renderTargetData);
    495 
    496     if (FAILED(result))
    497     {
    498         ERR("GetRenderTargetData unexpectedly failed.");
    499         SafeRelease(renderTargetData);
    500         SafeRelease(surface);
    501         return gl::error(GL_OUT_OF_MEMORY);
    502     }
    503 
    504     RECT sourceRect = {x, y, x + width, y + height};
    505     RECT destRect = {xoffset, yoffset, xoffset + width, yoffset + height};
    506 
    507     D3DLOCKED_RECT sourceLock = {0};
    508     result = renderTargetData->LockRect(&sourceLock, &sourceRect, 0);
    509 
    510     if (FAILED(result))
    511     {
    512         ERR("Failed to lock the source surface (rectangle might be invalid).");
    513         SafeRelease(renderTargetData);
    514         SafeRelease(surface);
    515         return gl::error(GL_OUT_OF_MEMORY);
    516     }
    517 
    518     D3DLOCKED_RECT destLock = {0};
    519     result = lock(&destLock, &destRect);
    520 
    521     if (FAILED(result))
    522     {
    523         ERR("Failed to lock the destination surface (rectangle might be invalid).");
    524         renderTargetData->UnlockRect();
    525         SafeRelease(renderTargetData);
    526         SafeRelease(surface);
    527         return gl::error(GL_OUT_OF_MEMORY);
    528     }
    529 
    530     if (destLock.pBits && sourceLock.pBits)
    531     {
    532         unsigned char *source = (unsigned char*)sourceLock.pBits;
    533         unsigned char *dest = (unsigned char*)destLock.pBits;
    534 
    535         switch (description.Format)
    536         {
    537           case D3DFMT_X8R8G8B8:
    538           case D3DFMT_A8R8G8B8:
    539             switch(getD3DFormat())
    540             {
    541               case D3DFMT_X8R8G8B8:
    542               case D3DFMT_A8R8G8B8:
    543                 for(int y = 0; y < height; y++)
    544                 {
    545                     memcpy(dest, source, 4 * width);
    546 
    547                     source += sourceLock.Pitch;
    548                     dest += destLock.Pitch;
    549                 }
    550                 break;
    551               case D3DFMT_L8:
    552                 for(int y = 0; y < height; y++)
    553                 {
    554                     for(int x = 0; x < width; x++)
    555                     {
    556                         dest[x] = source[x * 4 + 2];
    557                     }
    558 
    559                     source += sourceLock.Pitch;
    560                     dest += destLock.Pitch;
    561                 }
    562                 break;
    563               case D3DFMT_A8L8:
    564                 for(int y = 0; y < height; y++)
    565                 {
    566                     for(int x = 0; x < width; x++)
    567                     {
    568                         dest[x * 2 + 0] = source[x * 4 + 2];
    569                         dest[x * 2 + 1] = source[x * 4 + 3];
    570                     }
    571 
    572                     source += sourceLock.Pitch;
    573                     dest += destLock.Pitch;
    574                 }
    575                 break;
    576               default:
    577                 UNREACHABLE();
    578             }
    579             break;
    580           case D3DFMT_R5G6B5:
    581             switch(getD3DFormat())
    582             {
    583               case D3DFMT_X8R8G8B8:
    584                 for(int y = 0; y < height; y++)
    585                 {
    586                     for(int x = 0; x < width; x++)
    587                     {
    588                         unsigned short rgb = ((unsigned short*)source)[x];
    589                         unsigned char red = (rgb & 0xF800) >> 8;
    590                         unsigned char green = (rgb & 0x07E0) >> 3;
    591                         unsigned char blue = (rgb & 0x001F) << 3;
    592                         dest[x + 0] = blue | (blue >> 5);
    593                         dest[x + 1] = green | (green >> 6);
    594                         dest[x + 2] = red | (red >> 5);
    595                         dest[x + 3] = 0xFF;
    596                     }
    597 
    598                     source += sourceLock.Pitch;
    599                     dest += destLock.Pitch;
    600                 }
    601                 break;
    602               case D3DFMT_L8:
    603                 for(int y = 0; y < height; y++)
    604                 {
    605                     for(int x = 0; x < width; x++)
    606                     {
    607                         unsigned char red = source[x * 2 + 1] & 0xF8;
    608                         dest[x] = red | (red >> 5);
    609                     }
    610 
    611                     source += sourceLock.Pitch;
    612                     dest += destLock.Pitch;
    613                 }
    614                 break;
    615               default:
    616                 UNREACHABLE();
    617             }
    618             break;
    619           case D3DFMT_A1R5G5B5:
    620             switch(getD3DFormat())
    621             {
    622               case D3DFMT_X8R8G8B8:
    623                 for(int y = 0; y < height; y++)
    624                 {
    625                     for(int x = 0; x < width; x++)
    626                     {
    627                         unsigned short argb = ((unsigned short*)source)[x];
    628                         unsigned char red = (argb & 0x7C00) >> 7;
    629                         unsigned char green = (argb & 0x03E0) >> 2;
    630                         unsigned char blue = (argb & 0x001F) << 3;
    631                         dest[x + 0] = blue | (blue >> 5);
    632                         dest[x + 1] = green | (green >> 5);
    633                         dest[x + 2] = red | (red >> 5);
    634                         dest[x + 3] = 0xFF;
    635                     }
    636 
    637                     source += sourceLock.Pitch;
    638                     dest += destLock.Pitch;
    639                 }
    640                 break;
    641               case D3DFMT_A8R8G8B8:
    642                 for(int y = 0; y < height; y++)
    643                 {
    644                     for(int x = 0; x < width; x++)
    645                     {
    646                         unsigned short argb = ((unsigned short*)source)[x];
    647                         unsigned char red = (argb & 0x7C00) >> 7;
    648                         unsigned char green = (argb & 0x03E0) >> 2;
    649                         unsigned char blue = (argb & 0x001F) << 3;
    650                         unsigned char alpha = (signed short)argb >> 15;
    651                         dest[x + 0] = blue | (blue >> 5);
    652                         dest[x + 1] = green | (green >> 5);
    653                         dest[x + 2] = red | (red >> 5);
    654                         dest[x + 3] = alpha;
    655                     }
    656 
    657                     source += sourceLock.Pitch;
    658                     dest += destLock.Pitch;
    659                 }
    660                 break;
    661               case D3DFMT_L8:
    662                 for(int y = 0; y < height; y++)
    663                 {
    664                     for(int x = 0; x < width; x++)
    665                     {
    666                         unsigned char red = source[x * 2 + 1] & 0x7C;
    667                         dest[x] = (red << 1) | (red >> 4);
    668                     }
    669 
    670                     source += sourceLock.Pitch;
    671                     dest += destLock.Pitch;
    672                 }
    673                 break;
    674               case D3DFMT_A8L8:
    675                 for(int y = 0; y < height; y++)
    676                 {
    677                     for(int x = 0; x < width; x++)
    678                     {
    679                         unsigned char red = source[x * 2 + 1] & 0x7C;
    680                         dest[x * 2 + 0] = (red << 1) | (red >> 4);
    681                         dest[x * 2 + 1] = (signed char)source[x * 2 + 1] >> 7;
    682                     }
    683 
    684                     source += sourceLock.Pitch;
    685                     dest += destLock.Pitch;
    686                 }
    687                 break;
    688               default:
    689                 UNREACHABLE();
    690             }
    691             break;
    692           default:
    693             UNREACHABLE();
    694         }
    695     }
    696 
    697     unlock();
    698     renderTargetData->UnlockRect();
    699 
    700     SafeRelease(renderTargetData);
    701     SafeRelease(surface);
    702 
    703     mDirty = true;
    704 }
    705 
    706 }
    707