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

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

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

mercurial