Image9.cpp (36302B)
1 // 2 // Copyright 2002 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 "libANGLE/renderer/d3d/d3d9/Image9.h" 11 12 #include "common/utilities.h" 13 #include "libANGLE/Context.h" 14 #include "libANGLE/Framebuffer.h" 15 #include "libANGLE/FramebufferAttachment.h" 16 #include "libANGLE/Renderbuffer.h" 17 #include "libANGLE/formatutils.h" 18 #include "libANGLE/renderer/copyvertex.h" 19 #include "libANGLE/renderer/d3d/d3d9/Context9.h" 20 #include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h" 21 #include "libANGLE/renderer/d3d/d3d9/Renderer9.h" 22 #include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h" 23 #include "libANGLE/renderer/d3d/d3d9/formatutils9.h" 24 #include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" 25 26 namespace rx 27 { 28 29 Image9::Image9(Renderer9 *renderer) 30 { 31 mSurface = nullptr; 32 mRenderer = nullptr; 33 34 mD3DPool = D3DPOOL_SYSTEMMEM; 35 mD3DFormat = D3DFMT_UNKNOWN; 36 37 mRenderer = renderer; 38 } 39 40 Image9::~Image9() 41 { 42 SafeRelease(mSurface); 43 } 44 45 // static 46 angle::Result Image9::GenerateMip(Context9 *context9, 47 IDirect3DSurface9 *destSurface, 48 IDirect3DSurface9 *sourceSurface) 49 { 50 D3DSURFACE_DESC destDesc; 51 HRESULT result = destSurface->GetDesc(&destDesc); 52 ASSERT(SUCCEEDED(result)); 53 ANGLE_TRY_HR(context9, result, 54 "Failed to query the source surface description for mipmap generation"); 55 56 D3DSURFACE_DESC sourceDesc; 57 result = sourceSurface->GetDesc(&sourceDesc); 58 ASSERT(SUCCEEDED(result)); 59 ANGLE_TRY_HR(context9, result, 60 "Failed to query the destination surface description for mipmap generation"); 61 62 ASSERT(sourceDesc.Format == destDesc.Format); 63 ASSERT(sourceDesc.Width == 1 || sourceDesc.Width / 2 == destDesc.Width); 64 ASSERT(sourceDesc.Height == 1 || sourceDesc.Height / 2 == destDesc.Height); 65 66 const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(sourceDesc.Format); 67 ASSERT(d3dFormatInfo.info().mipGenerationFunction != nullptr); 68 69 D3DLOCKED_RECT sourceLocked = {}; 70 result = sourceSurface->LockRect(&sourceLocked, nullptr, D3DLOCK_READONLY); 71 ASSERT(SUCCEEDED(result)); 72 ANGLE_TRY_HR(context9, result, "Failed to lock the source surface for mipmap generation"); 73 74 D3DLOCKED_RECT destLocked = {}; 75 result = destSurface->LockRect(&destLocked, nullptr, 0); 76 ASSERT(SUCCEEDED(result)); 77 ANGLE_TRY_HR(context9, result, "Failed to lock the destination surface for mipmap generation"); 78 79 const uint8_t *sourceData = static_cast<const uint8_t *>(sourceLocked.pBits); 80 uint8_t *destData = static_cast<uint8_t *>(destLocked.pBits); 81 82 ASSERT(sourceData && destData); 83 84 d3dFormatInfo.info().mipGenerationFunction(sourceDesc.Width, sourceDesc.Height, 1, sourceData, 85 sourceLocked.Pitch, 0, destData, destLocked.Pitch, 86 0); 87 88 destSurface->UnlockRect(); 89 sourceSurface->UnlockRect(); 90 91 return angle::Result::Continue; 92 } 93 94 // static 95 angle::Result Image9::GenerateMipmap(Context9 *context9, Image9 *dest, Image9 *source) 96 { 97 IDirect3DSurface9 *sourceSurface = nullptr; 98 ANGLE_TRY(source->getSurface(context9, &sourceSurface)); 99 100 IDirect3DSurface9 *destSurface = nullptr; 101 ANGLE_TRY(dest->getSurface(context9, &destSurface)); 102 103 ANGLE_TRY(GenerateMip(context9, destSurface, sourceSurface)); 104 105 dest->markDirty(); 106 107 return angle::Result::Continue; 108 } 109 110 // static 111 angle::Result Image9::CopyLockableSurfaces(Context9 *context9, 112 IDirect3DSurface9 *dest, 113 IDirect3DSurface9 *source) 114 { 115 D3DLOCKED_RECT sourceLock = {}; 116 D3DLOCKED_RECT destLock = {}; 117 118 HRESULT result; 119 120 result = source->LockRect(&sourceLock, nullptr, 0); 121 ANGLE_TRY_HR(context9, result, "Failed to lock source surface for copy"); 122 123 result = dest->LockRect(&destLock, nullptr, 0); 124 if (FAILED(result)) 125 { 126 source->UnlockRect(); 127 } 128 ANGLE_TRY_HR(context9, result, "Failed to lock destination surface for copy"); 129 130 ASSERT(sourceLock.pBits && destLock.pBits); 131 132 D3DSURFACE_DESC desc; 133 source->GetDesc(&desc); 134 135 const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(desc.Format); 136 unsigned int rows = desc.Height / d3dFormatInfo.blockHeight; 137 138 unsigned int bytes = d3d9::ComputeBlockSize(desc.Format, desc.Width, d3dFormatInfo.blockHeight); 139 ASSERT(bytes <= static_cast<unsigned int>(sourceLock.Pitch) && 140 bytes <= static_cast<unsigned int>(destLock.Pitch)); 141 142 for (unsigned int i = 0; i < rows; i++) 143 { 144 memcpy((char *)destLock.pBits + destLock.Pitch * i, 145 (char *)sourceLock.pBits + sourceLock.Pitch * i, bytes); 146 } 147 148 source->UnlockRect(); 149 dest->UnlockRect(); 150 151 return angle::Result::Continue; 152 } 153 154 // static 155 angle::Result Image9::CopyImage(const gl::Context *context, 156 Image9 *dest, 157 Image9 *source, 158 const gl::Rectangle &sourceRect, 159 const gl::Offset &destOffset, 160 bool unpackFlipY, 161 bool unpackPremultiplyAlpha, 162 bool unpackUnmultiplyAlpha) 163 { 164 Context9 *context9 = GetImplAs<Context9>(context); 165 166 IDirect3DSurface9 *sourceSurface = nullptr; 167 ANGLE_TRY(source->getSurface(context9, &sourceSurface)); 168 169 IDirect3DSurface9 *destSurface = nullptr; 170 ANGLE_TRY(dest->getSurface(context9, &destSurface)); 171 172 D3DSURFACE_DESC destDesc; 173 HRESULT result = destSurface->GetDesc(&destDesc); 174 ASSERT(SUCCEEDED(result)); 175 ANGLE_TRY_HR(context9, result, "Failed to query the source surface description for CopyImage"); 176 const d3d9::D3DFormat &destD3DFormatInfo = d3d9::GetD3DFormatInfo(destDesc.Format); 177 178 D3DSURFACE_DESC sourceDesc; 179 result = sourceSurface->GetDesc(&sourceDesc); 180 ASSERT(SUCCEEDED(result)); 181 ANGLE_TRY_HR(context9, result, 182 "Failed to query the destination surface description for CopyImage"); 183 const d3d9::D3DFormat &sourceD3DFormatInfo = d3d9::GetD3DFormatInfo(sourceDesc.Format); 184 185 D3DLOCKED_RECT sourceLocked = {}; 186 result = sourceSurface->LockRect(&sourceLocked, nullptr, D3DLOCK_READONLY); 187 ASSERT(SUCCEEDED(result)); 188 ANGLE_TRY_HR(context9, result, "Failed to lock the source surface for CopyImage"); 189 190 D3DLOCKED_RECT destLocked = {}; 191 result = destSurface->LockRect(&destLocked, nullptr, 0); 192 ASSERT(SUCCEEDED(result)); 193 if (FAILED(result)) 194 { 195 sourceSurface->UnlockRect(); 196 } 197 ANGLE_TRY_HR(context9, result, "Failed to lock the destination surface for CopyImage"); 198 199 const uint8_t *sourceData = static_cast<const uint8_t *>(sourceLocked.pBits) + 200 sourceRect.x * sourceD3DFormatInfo.pixelBytes + 201 sourceRect.y * sourceLocked.Pitch; 202 uint8_t *destData = static_cast<uint8_t *>(destLocked.pBits) + 203 destOffset.x * destD3DFormatInfo.pixelBytes + 204 destOffset.y * destLocked.Pitch; 205 ASSERT(sourceData && destData); 206 207 CopyImageCHROMIUM(sourceData, sourceLocked.Pitch, sourceD3DFormatInfo.pixelBytes, 0, 208 sourceD3DFormatInfo.info().pixelReadFunction, destData, destLocked.Pitch, 209 destD3DFormatInfo.pixelBytes, 0, destD3DFormatInfo.info().pixelWriteFunction, 210 gl::GetUnsizedFormat(dest->getInternalFormat()), 211 destD3DFormatInfo.info().componentType, sourceRect.width, sourceRect.height, 212 1, unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha); 213 214 dest->markDirty(); 215 216 destSurface->UnlockRect(); 217 sourceSurface->UnlockRect(); 218 219 return angle::Result::Continue; 220 } 221 222 bool Image9::redefine(gl::TextureType type, 223 GLenum internalformat, 224 const gl::Extents &size, 225 bool forceRelease) 226 { 227 // 3D textures are not supported by the D3D9 backend. 228 ASSERT(size.depth <= 1); 229 230 // Only 2D and cube texture are supported by the D3D9 backend. 231 ASSERT(type == gl::TextureType::_2D || type == gl::TextureType::CubeMap); 232 233 if (mWidth != size.width || mHeight != size.height || mDepth != size.depth || 234 mInternalFormat != internalformat || forceRelease) 235 { 236 mWidth = size.width; 237 mHeight = size.height; 238 mDepth = size.depth; 239 mType = type; 240 mInternalFormat = internalformat; 241 242 // compute the d3d format that will be used 243 const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(internalformat); 244 mD3DFormat = d3d9FormatInfo.texFormat; 245 mRenderable = (d3d9FormatInfo.renderFormat != D3DFMT_UNKNOWN); 246 247 SafeRelease(mSurface); 248 mDirty = (d3d9FormatInfo.dataInitializerFunction != nullptr); 249 250 return true; 251 } 252 253 return false; 254 } 255 256 angle::Result Image9::createSurface(Context9 *context9) 257 { 258 if (mSurface) 259 { 260 return angle::Result::Continue; 261 } 262 263 IDirect3DTexture9 *newTexture = nullptr; 264 IDirect3DSurface9 *newSurface = nullptr; 265 const D3DPOOL poolToUse = D3DPOOL_SYSTEMMEM; 266 const D3DFORMAT d3dFormat = getD3DFormat(); 267 268 if (mWidth != 0 && mHeight != 0) 269 { 270 int levelToFetch = 0; 271 GLsizei requestWidth = mWidth; 272 GLsizei requestHeight = mHeight; 273 d3d9::MakeValidSize(true, d3dFormat, &requestWidth, &requestHeight, &levelToFetch); 274 275 IDirect3DDevice9 *device = mRenderer->getDevice(); 276 277 HRESULT result = device->CreateTexture(requestWidth, requestHeight, levelToFetch + 1, 0, 278 d3dFormat, poolToUse, &newTexture, nullptr); 279 280 ANGLE_TRY_HR(context9, result, "Failed to create image surface"); 281 282 newTexture->GetSurfaceLevel(levelToFetch, &newSurface); 283 SafeRelease(newTexture); 284 285 const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat); 286 if (d3dFormatInfo.dataInitializerFunction != nullptr) 287 { 288 RECT entireRect; 289 entireRect.left = 0; 290 entireRect.right = mWidth; 291 entireRect.top = 0; 292 entireRect.bottom = mHeight; 293 294 D3DLOCKED_RECT lockedRect; 295 result = newSurface->LockRect(&lockedRect, &entireRect, 0); 296 ASSERT(SUCCEEDED(result)); 297 ANGLE_TRY_HR(context9, result, "Failed to lock image surface"); 298 299 d3dFormatInfo.dataInitializerFunction( 300 mWidth, mHeight, 1, static_cast<uint8_t *>(lockedRect.pBits), lockedRect.Pitch, 0); 301 302 result = newSurface->UnlockRect(); 303 ASSERT(SUCCEEDED(result)); 304 ANGLE_TRY_HR(context9, result, "Failed to unlock image surface"); 305 } 306 } 307 308 mSurface = newSurface; 309 mDirty = false; 310 mD3DPool = poolToUse; 311 312 return angle::Result::Continue; 313 } 314 315 angle::Result Image9::lock(Context9 *context9, D3DLOCKED_RECT *lockedRect, const RECT &rect) 316 { 317 ANGLE_TRY(createSurface(context9)); 318 319 if (mSurface) 320 { 321 HRESULT result = mSurface->LockRect(lockedRect, &rect, 0); 322 ASSERT(SUCCEEDED(result)); 323 ANGLE_TRY_HR(context9, result, "Failed to lock image surface"); 324 mDirty = true; 325 } 326 327 return angle::Result::Continue; 328 } 329 330 void Image9::unlock() 331 { 332 if (mSurface) 333 { 334 HRESULT result = mSurface->UnlockRect(); 335 ASSERT(SUCCEEDED(result)); 336 } 337 } 338 339 D3DFORMAT Image9::getD3DFormat() const 340 { 341 // this should only happen if the image hasn't been redefined first 342 // which would be a bug by the caller 343 ASSERT(mD3DFormat != D3DFMT_UNKNOWN); 344 345 return mD3DFormat; 346 } 347 348 bool Image9::isDirty() const 349 { 350 // Make sure to that this image is marked as dirty even if the staging texture hasn't been 351 // created yet if initialization is required before use. 352 return (mSurface || 353 d3d9::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != nullptr) && 354 mDirty; 355 } 356 357 angle::Result Image9::getSurface(Context9 *context9, IDirect3DSurface9 **outSurface) 358 { 359 ANGLE_TRY(createSurface(context9)); 360 *outSurface = mSurface; 361 return angle::Result::Continue; 362 } 363 364 angle::Result Image9::setManagedSurface2D(const gl::Context *context, 365 TextureStorage *storage, 366 int level) 367 { 368 IDirect3DSurface9 *surface = nullptr; 369 TextureStorage9 *storage9 = GetAs<TextureStorage9>(storage); 370 ANGLE_TRY(storage9->getSurfaceLevel(context, gl::TextureTarget::_2D, level, false, &surface)); 371 return setManagedSurface(GetImplAs<Context9>(context), surface); 372 } 373 374 angle::Result Image9::setManagedSurfaceCube(const gl::Context *context, 375 TextureStorage *storage, 376 int face, 377 int level) 378 { 379 IDirect3DSurface9 *surface = nullptr; 380 TextureStorage9 *storage9 = GetAs<TextureStorage9>(storage); 381 ANGLE_TRY(storage9->getSurfaceLevel(context, gl::CubeFaceIndexToTextureTarget(face), level, 382 false, &surface)); 383 return setManagedSurface(GetImplAs<Context9>(context), surface); 384 } 385 386 angle::Result Image9::setManagedSurface(Context9 *context9, IDirect3DSurface9 *surface) 387 { 388 D3DSURFACE_DESC desc; 389 surface->GetDesc(&desc); 390 ASSERT(desc.Pool == D3DPOOL_MANAGED); 391 392 if ((GLsizei)desc.Width == mWidth && (GLsizei)desc.Height == mHeight) 393 { 394 if (mSurface) 395 { 396 angle::Result result = CopyLockableSurfaces(context9, surface, mSurface); 397 SafeRelease(mSurface); 398 ANGLE_TRY(result); 399 } 400 401 mSurface = surface; 402 mD3DPool = desc.Pool; 403 } 404 405 return angle::Result::Continue; 406 } 407 408 angle::Result Image9::copyToStorage(const gl::Context *context, 409 TextureStorage *storage, 410 const gl::ImageIndex &index, 411 const gl::Box ®ion) 412 { 413 ANGLE_TRY(createSurface(GetImplAs<Context9>(context))); 414 415 TextureStorage9 *storage9 = GetAs<TextureStorage9>(storage); 416 IDirect3DSurface9 *destSurface = nullptr; 417 ANGLE_TRY(storage9->getSurfaceLevel(context, index.getTarget(), index.getLevelIndex(), true, 418 &destSurface)); 419 420 angle::Result result = copyToSurface(GetImplAs<Context9>(context), destSurface, region); 421 SafeRelease(destSurface); 422 return result; 423 } 424 425 angle::Result Image9::copyToSurface(Context9 *context9, 426 IDirect3DSurface9 *destSurface, 427 const gl::Box &area) 428 { 429 ASSERT(area.width > 0 && area.height > 0 && area.depth == 1); 430 ASSERT(destSurface); 431 432 IDirect3DSurface9 *sourceSurface = nullptr; 433 ANGLE_TRY(getSurface(context9, &sourceSurface)); 434 435 ASSERT(sourceSurface && sourceSurface != destSurface); 436 437 RECT rect; 438 rect.left = area.x; 439 rect.top = area.y; 440 rect.right = area.x + area.width; 441 rect.bottom = area.y + area.height; 442 443 POINT point = {rect.left, rect.top}; 444 445 IDirect3DDevice9 *device = mRenderer->getDevice(); 446 447 if (mD3DPool == D3DPOOL_MANAGED) 448 { 449 D3DSURFACE_DESC desc; 450 sourceSurface->GetDesc(&desc); 451 452 IDirect3DSurface9 *surf = 0; 453 HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, 454 D3DPOOL_SYSTEMMEM, &surf, nullptr); 455 ANGLE_TRY_HR(context9, result, "Internal CreateOffscreenPlainSurface call failed"); 456 457 auto err = CopyLockableSurfaces(context9, surf, sourceSurface); 458 result = device->UpdateSurface(surf, &rect, destSurface, &point); 459 SafeRelease(surf); 460 ANGLE_TRY(err); 461 ASSERT(SUCCEEDED(result)); 462 ANGLE_TRY_HR(context9, result, "Internal UpdateSurface call failed"); 463 } 464 else 465 { 466 // UpdateSurface: source must be SYSTEMMEM, dest must be DEFAULT pools 467 HRESULT result = device->UpdateSurface(sourceSurface, &rect, destSurface, &point); 468 ASSERT(SUCCEEDED(result)); 469 ANGLE_TRY_HR(context9, result, "Internal UpdateSurface call failed"); 470 } 471 472 return angle::Result::Continue; 473 } 474 475 // Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as 476 // format/type at input into the target pixel rectangle. 477 angle::Result Image9::loadData(const gl::Context *context, 478 const gl::Box &area, 479 const gl::PixelUnpackState &unpack, 480 GLenum type, 481 const void *input, 482 bool applySkipImages) 483 { 484 // 3D textures are not supported by the D3D9 backend. 485 ASSERT(area.z == 0 && area.depth == 1); 486 487 Context9 *context9 = GetImplAs<Context9>(context); 488 489 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(mInternalFormat); 490 GLuint inputRowPitch = 0; 491 ANGLE_CHECK_GL_MATH(context9, formatInfo.computeRowPitch(type, area.width, unpack.alignment, 492 unpack.rowLength, &inputRowPitch)); 493 ASSERT(!applySkipImages); 494 ASSERT(unpack.skipPixels == 0); 495 ASSERT(unpack.skipRows == 0); 496 497 const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat); 498 ASSERT(d3dFormatInfo.loadFunction != nullptr); 499 500 RECT lockRect = {area.x, area.y, area.x + area.width, area.y + area.height}; 501 502 D3DLOCKED_RECT locked; 503 ANGLE_TRY(lock(GetImplAs<Context9>(context), &locked, lockRect)); 504 505 d3dFormatInfo.loadFunction(area.width, area.height, area.depth, 506 static_cast<const uint8_t *>(input), inputRowPitch, 0, 507 static_cast<uint8_t *>(locked.pBits), locked.Pitch, 0); 508 509 unlock(); 510 511 return angle::Result::Continue; 512 } 513 514 angle::Result Image9::loadCompressedData(const gl::Context *context, 515 const gl::Box &area, 516 const void *input) 517 { 518 // 3D textures are not supported by the D3D9 backend. 519 ASSERT(area.z == 0 && area.depth == 1); 520 521 Context9 *context9 = GetImplAs<Context9>(context); 522 523 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(mInternalFormat); 524 GLuint inputRowPitch = 0; 525 ANGLE_CHECK_GL_MATH( 526 context9, formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, area.width, 1, 0, &inputRowPitch)); 527 528 GLuint inputDepthPitch = 0; 529 ANGLE_CHECK_GL_MATH( 530 context9, formatInfo.computeDepthPitch(area.height, 0, inputRowPitch, &inputDepthPitch)); 531 532 const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat); 533 534 ASSERT(area.x % d3d9::GetD3DFormatInfo(d3d9FormatInfo.texFormat).blockWidth == 0); 535 ASSERT(area.y % d3d9::GetD3DFormatInfo(d3d9FormatInfo.texFormat).blockHeight == 0); 536 537 ASSERT(d3d9FormatInfo.loadFunction != nullptr); 538 539 RECT lockRect = {area.x, area.y, area.x + area.width, area.y + area.height}; 540 541 D3DLOCKED_RECT locked; 542 ANGLE_TRY(lock(GetImplAs<Context9>(context), &locked, lockRect)); 543 544 d3d9FormatInfo.loadFunction(area.width, area.height, area.depth, 545 static_cast<const uint8_t *>(input), inputRowPitch, inputDepthPitch, 546 static_cast<uint8_t *>(locked.pBits), locked.Pitch, 0); 547 548 unlock(); 549 550 return angle::Result::Continue; 551 } 552 553 // This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats and incomplete 554 // textures 555 angle::Result Image9::copyFromRTInternal(Context9 *context9, 556 const gl::Offset &destOffset, 557 const gl::Rectangle &sourceArea, 558 RenderTargetD3D *source) 559 { 560 ASSERT(source); 561 562 // ES3.0 only behaviour to copy into a 3d texture 563 ASSERT(destOffset.z == 0); 564 565 RenderTarget9 *renderTarget = GetAs<RenderTarget9>(source); 566 567 angle::ComPtr<IDirect3DSurface9> surface = renderTarget->getSurface(); 568 ASSERT(surface); 569 570 IDirect3DDevice9 *device = mRenderer->getDevice(); 571 572 angle::ComPtr<IDirect3DSurface9> renderTargetData = nullptr; 573 D3DSURFACE_DESC description; 574 surface->GetDesc(&description); 575 576 HRESULT hr = device->CreateOffscreenPlainSurface(description.Width, description.Height, 577 description.Format, D3DPOOL_SYSTEMMEM, 578 &renderTargetData, nullptr); 579 580 ANGLE_TRY_HR(context9, hr, "Could not create matching destination surface"); 581 582 hr = device->GetRenderTargetData(surface.Get(), renderTargetData.Get()); 583 584 ANGLE_TRY_HR(context9, hr, "GetRenderTargetData unexpectedly failed"); 585 586 int width = sourceArea.width; 587 int height = sourceArea.height; 588 589 RECT sourceRect = {sourceArea.x, sourceArea.y, sourceArea.x + width, sourceArea.y + height}; 590 RECT destRect = {destOffset.x, destOffset.y, destOffset.x + width, destOffset.y + height}; 591 592 D3DLOCKED_RECT sourceLock = {}; 593 hr = renderTargetData->LockRect(&sourceLock, &sourceRect, 0); 594 595 ANGLE_TRY_HR(context9, hr, "Failed to lock the source surface (rectangle might be invalid)"); 596 597 D3DLOCKED_RECT destLock = {}; 598 angle::Result result = lock(context9, &destLock, destRect); 599 if (result == angle::Result::Stop) 600 { 601 renderTargetData->UnlockRect(); 602 } 603 ANGLE_TRY(result); 604 605 ASSERT(destLock.pBits && sourceLock.pBits); 606 607 unsigned char *sourcePixels = (unsigned char *)sourceLock.pBits; 608 unsigned char *destPixels = (unsigned char *)destLock.pBits; 609 610 switch (description.Format) 611 { 612 case D3DFMT_X8R8G8B8: 613 case D3DFMT_A8R8G8B8: 614 switch (getD3DFormat()) 615 { 616 case D3DFMT_X8R8G8B8: 617 case D3DFMT_A8R8G8B8: 618 for (int y = 0; y < height; y++) 619 { 620 memcpy(destPixels, sourcePixels, 4 * width); 621 sourcePixels += sourceLock.Pitch; 622 destPixels += destLock.Pitch; 623 } 624 break; 625 case D3DFMT_L8: 626 for (int y = 0; y < height; y++) 627 { 628 for (int x = 0; x < width; x++) 629 { 630 destPixels[x] = sourcePixels[x * 4 + 2]; 631 } 632 sourcePixels += sourceLock.Pitch; 633 destPixels += destLock.Pitch; 634 } 635 break; 636 case D3DFMT_A8L8: 637 for (int y = 0; y < height; y++) 638 { 639 for (int x = 0; x < width; x++) 640 { 641 destPixels[x * 2 + 0] = sourcePixels[x * 4 + 2]; 642 destPixels[x * 2 + 1] = sourcePixels[x * 4 + 3]; 643 } 644 sourcePixels += sourceLock.Pitch; 645 destPixels += destLock.Pitch; 646 } 647 break; 648 default: 649 UNREACHABLE(); 650 } 651 break; 652 case D3DFMT_R5G6B5: 653 switch (getD3DFormat()) 654 { 655 case D3DFMT_X8R8G8B8: 656 for (int y = 0; y < height; y++) 657 { 658 for (int x = 0; x < width; x++) 659 { 660 unsigned short rgb = ((unsigned short *)sourcePixels)[x]; 661 unsigned char red = static_cast<unsigned char>((rgb & 0xF800) >> 8); 662 unsigned char green = static_cast<unsigned char>((rgb & 0x07E0) >> 3); 663 unsigned char blue = static_cast<unsigned char>((rgb & 0x001F) << 3); 664 destPixels[x + 0] = blue | (blue >> 5); 665 destPixels[x + 1] = green | (green >> 6); 666 destPixels[x + 2] = red | (red >> 5); 667 destPixels[x + 3] = 0xFF; 668 } 669 sourcePixels += sourceLock.Pitch; 670 destPixels += destLock.Pitch; 671 } 672 break; 673 case D3DFMT_L8: 674 for (int y = 0; y < height; y++) 675 { 676 for (int x = 0; x < width; x++) 677 { 678 unsigned char red = sourcePixels[x * 2 + 1] & 0xF8; 679 destPixels[x] = red | (red >> 5); 680 } 681 sourcePixels += sourceLock.Pitch; 682 destPixels += destLock.Pitch; 683 } 684 break; 685 default: 686 UNREACHABLE(); 687 } 688 break; 689 case D3DFMT_A1R5G5B5: 690 switch (getD3DFormat()) 691 { 692 case D3DFMT_X8R8G8B8: 693 for (int y = 0; y < height; y++) 694 { 695 for (int x = 0; x < width; x++) 696 { 697 unsigned short argb = ((unsigned short *)sourcePixels)[x]; 698 unsigned char red = static_cast<unsigned char>((argb & 0x7C00) >> 7); 699 unsigned char green = static_cast<unsigned char>((argb & 0x03E0) >> 2); 700 unsigned char blue = static_cast<unsigned char>((argb & 0x001F) << 3); 701 destPixels[x + 0] = blue | (blue >> 5); 702 destPixels[x + 1] = green | (green >> 5); 703 destPixels[x + 2] = red | (red >> 5); 704 destPixels[x + 3] = 0xFF; 705 } 706 sourcePixels += sourceLock.Pitch; 707 destPixels += destLock.Pitch; 708 } 709 break; 710 case D3DFMT_A8R8G8B8: 711 for (int y = 0; y < height; y++) 712 { 713 for (int x = 0; x < width; x++) 714 { 715 unsigned short argb = ((unsigned short *)sourcePixels)[x]; 716 unsigned char red = static_cast<unsigned char>((argb & 0x7C00) >> 7); 717 unsigned char green = static_cast<unsigned char>((argb & 0x03E0) >> 2); 718 unsigned char blue = static_cast<unsigned char>((argb & 0x001F) << 3); 719 unsigned char alpha = (signed short)argb >> 15; 720 destPixels[x + 0] = blue | (blue >> 5); 721 destPixels[x + 1] = green | (green >> 5); 722 destPixels[x + 2] = red | (red >> 5); 723 destPixels[x + 3] = alpha; 724 } 725 sourcePixels += sourceLock.Pitch; 726 destPixels += destLock.Pitch; 727 } 728 break; 729 case D3DFMT_L8: 730 for (int y = 0; y < height; y++) 731 { 732 for (int x = 0; x < width; x++) 733 { 734 unsigned char red = sourcePixels[x * 2 + 1] & 0x7C; 735 destPixels[x] = (red << 1) | (red >> 4); 736 } 737 sourcePixels += sourceLock.Pitch; 738 destPixels += destLock.Pitch; 739 } 740 break; 741 case D3DFMT_A8L8: 742 for (int y = 0; y < height; y++) 743 { 744 for (int x = 0; x < width; x++) 745 { 746 unsigned char red = sourcePixels[x * 2 + 1] & 0x7C; 747 destPixels[x * 2 + 0] = (red << 1) | (red >> 4); 748 destPixels[x * 2 + 1] = (signed char)sourcePixels[x * 2 + 1] >> 7; 749 } 750 sourcePixels += sourceLock.Pitch; 751 destPixels += destLock.Pitch; 752 } 753 break; 754 default: 755 UNREACHABLE(); 756 } 757 break; 758 case D3DFMT_A16B16G16R16F: 759 switch (getD3DFormat()) 760 { 761 case D3DFMT_X8R8G8B8: 762 case D3DFMT_A8R8G8B8: 763 for (int y = 0; y < height; y++) 764 { 765 const uint16_t *sourcePixels16F = 766 reinterpret_cast<uint16_t *>(sourcePixels); 767 for (int x = 0; x < width; x++) 768 { 769 float r = gl::float16ToFloat32(sourcePixels16F[x * 4 + 0]); 770 float g = gl::float16ToFloat32(sourcePixels16F[x * 4 + 1]); 771 float b = gl::float16ToFloat32(sourcePixels16F[x * 4 + 2]); 772 float a = gl::float16ToFloat32(sourcePixels16F[x * 4 + 3]); 773 destPixels[x * 4 + 0] = gl::floatToNormalized<uint8_t>(b); 774 destPixels[x * 4 + 1] = gl::floatToNormalized<uint8_t>(g); 775 destPixels[x * 4 + 2] = gl::floatToNormalized<uint8_t>(r); 776 destPixels[x * 4 + 3] = gl::floatToNormalized<uint8_t>(a); 777 } 778 sourcePixels += sourceLock.Pitch; 779 destPixels += destLock.Pitch; 780 } 781 break; 782 case D3DFMT_L8: 783 for (int y = 0; y < height; y++) 784 { 785 const uint16_t *sourcePixels16F = 786 reinterpret_cast<uint16_t *>(sourcePixels); 787 for (int x = 0; x < width; x++) 788 { 789 float r = gl::float16ToFloat32(sourcePixels16F[x * 4]); 790 destPixels[x] = gl::floatToNormalized<uint8_t>(r); 791 } 792 sourcePixels += sourceLock.Pitch; 793 destPixels += destLock.Pitch; 794 } 795 break; 796 case D3DFMT_A8L8: 797 for (int y = 0; y < height; y++) 798 { 799 const uint16_t *sourcePixels16F = 800 reinterpret_cast<uint16_t *>(sourcePixels); 801 for (int x = 0; x < width; x++) 802 { 803 float r = gl::float16ToFloat32(sourcePixels16F[x * 4 + 0]); 804 float a = gl::float16ToFloat32(sourcePixels16F[x * 4 + 3]); 805 destPixels[x * 2 + 0] = gl::floatToNormalized<uint8_t>(r); 806 destPixels[x * 2 + 1] = gl::floatToNormalized<uint8_t>(a); 807 } 808 sourcePixels += sourceLock.Pitch; 809 destPixels += destLock.Pitch; 810 } 811 break; 812 default: 813 UNREACHABLE(); 814 } 815 break; 816 case D3DFMT_A32B32G32R32F: 817 switch (getD3DFormat()) 818 { 819 case D3DFMT_X8R8G8B8: 820 case D3DFMT_A8R8G8B8: 821 for (int y = 0; y < height; y++) 822 { 823 const float *sourcePixels32F = reinterpret_cast<float *>(sourcePixels); 824 for (int x = 0; x < width; x++) 825 { 826 float r = sourcePixels32F[x * 4 + 0]; 827 float g = sourcePixels32F[x * 4 + 1]; 828 float b = sourcePixels32F[x * 4 + 2]; 829 float a = sourcePixels32F[x * 4 + 3]; 830 destPixels[x * 4 + 0] = gl::floatToNormalized<uint8_t>(b); 831 destPixels[x * 4 + 1] = gl::floatToNormalized<uint8_t>(g); 832 destPixels[x * 4 + 2] = gl::floatToNormalized<uint8_t>(r); 833 destPixels[x * 4 + 3] = gl::floatToNormalized<uint8_t>(a); 834 } 835 sourcePixels += sourceLock.Pitch; 836 destPixels += destLock.Pitch; 837 } 838 break; 839 case D3DFMT_L8: 840 for (int y = 0; y < height; y++) 841 { 842 const float *sourcePixels32F = reinterpret_cast<float *>(sourcePixels); 843 for (int x = 0; x < width; x++) 844 { 845 float r = sourcePixels32F[x * 4]; 846 destPixels[x] = gl::floatToNormalized<uint8_t>(r); 847 } 848 sourcePixels += sourceLock.Pitch; 849 destPixels += destLock.Pitch; 850 } 851 break; 852 case D3DFMT_A8L8: 853 for (int y = 0; y < height; y++) 854 { 855 const float *sourcePixels32F = reinterpret_cast<float *>(sourcePixels); 856 for (int x = 0; x < width; x++) 857 { 858 float r = sourcePixels32F[x * 4 + 0]; 859 float a = sourcePixels32F[x * 4 + 3]; 860 destPixels[x * 2 + 0] = gl::floatToNormalized<uint8_t>(r); 861 destPixels[x * 2 + 1] = gl::floatToNormalized<uint8_t>(a); 862 } 863 sourcePixels += sourceLock.Pitch; 864 destPixels += destLock.Pitch; 865 } 866 break; 867 default: 868 UNREACHABLE(); 869 } 870 break; 871 default: 872 UNREACHABLE(); 873 } 874 875 unlock(); 876 renderTargetData->UnlockRect(); 877 878 mDirty = true; 879 return angle::Result::Continue; 880 } 881 882 angle::Result Image9::copyFromTexStorage(const gl::Context *context, 883 const gl::ImageIndex &imageIndex, 884 TextureStorage *source) 885 { 886 RenderTargetD3D *renderTarget = nullptr; 887 ANGLE_TRY(source->getRenderTarget(context, imageIndex, 0, &renderTarget)); 888 889 gl::Rectangle sourceArea(0, 0, mWidth, mHeight); 890 return copyFromRTInternal(GetImplAs<Context9>(context), gl::Offset(), sourceArea, renderTarget); 891 } 892 893 angle::Result Image9::copyFromFramebuffer(const gl::Context *context, 894 const gl::Offset &destOffset, 895 const gl::Rectangle &sourceArea, 896 const gl::Framebuffer *source) 897 { 898 const gl::FramebufferAttachment *srcAttachment = source->getReadColorAttachment(); 899 ASSERT(srcAttachment); 900 901 RenderTargetD3D *renderTarget = nullptr; 902 ANGLE_TRY(srcAttachment->getRenderTarget(context, 0, &renderTarget)); 903 ASSERT(renderTarget); 904 return copyFromRTInternal(GetImplAs<Context9>(context), destOffset, sourceArea, renderTarget); 905 } 906 907 } // namespace rx