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