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