| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2008, Google Inc. All rights reserved. | 2 * Copyright (c) 2008, Google Inc. All rights reserved. |
| 3 * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> | 3 * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> |
| 4 * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved. | 4 * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved. |
| 5 * | 5 * |
| 6 * Redistribution and use in source and binary forms, with or without | 6 * Redistribution and use in source and binary forms, with or without |
| 7 * modification, are permitted provided that the following conditions are | 7 * modification, are permitted provided that the following conditions are |
| 8 * met: | 8 * met: |
| 9 * | 9 * |
| 10 * * Redistributions of source code must retain the above copyright | 10 * * Redistributions of source code must retain the above copyright |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 73 if (!surface->isValid()) | 73 if (!surface->isValid()) |
| 74 return nullptr; | 74 return nullptr; |
| 75 return WTF::wrapUnique(new ImageBuffer(std::move(surface))); | 75 return WTF::wrapUnique(new ImageBuffer(std::move(surface))); |
| 76 } | 76 } |
| 77 | 77 |
| 78 std::unique_ptr<ImageBuffer> ImageBuffer::create( | 78 std::unique_ptr<ImageBuffer> ImageBuffer::create( |
| 79 const IntSize& size, | 79 const IntSize& size, |
| 80 OpacityMode opacityMode, | 80 OpacityMode opacityMode, |
| 81 ImageInitializationMode initializationMode, | 81 ImageInitializationMode initializationMode, |
| 82 sk_sp<SkColorSpace> colorSpace) { | 82 sk_sp<SkColorSpace> colorSpace) { |
| 83 std::unique_ptr<ImageBufferSurface> surface( | 83 SkColorType colorType = kN32_SkColorType; |
| 84 WTF::wrapUnique(new UnacceleratedImageBufferSurface( | 84 if (colorSpace && |
| 85 size, opacityMode, initializationMode, std::move(colorSpace)))); | 85 SkColorSpace::Equals( |
| 86 colorSpace.get(), |
| 87 SkColorSpace::MakeNamed(SkColorSpace::kSRGBLinear_Named).get())) |
| 88 colorType = kRGBA_F16_SkColorType; |
| 89 |
| 90 std::unique_ptr<ImageBufferSurface> surface(WTF::wrapUnique( |
| 91 new UnacceleratedImageBufferSurface(size, opacityMode, initializationMode, |
| 92 std::move(colorSpace), colorType))); |
| 93 |
| 86 if (!surface->isValid()) | 94 if (!surface->isValid()) |
| 87 return nullptr; | 95 return nullptr; |
| 88 return WTF::wrapUnique(new ImageBuffer(std::move(surface))); | 96 return WTF::wrapUnique(new ImageBuffer(std::move(surface))); |
| 89 } | 97 } |
| 90 | 98 |
| 91 ImageBuffer::ImageBuffer(std::unique_ptr<ImageBufferSurface> surface) | 99 ImageBuffer::ImageBuffer(std::unique_ptr<ImageBufferSurface> surface) |
| 92 : m_weakPtrFactory(this), | 100 : m_weakPtrFactory(this), |
| 93 m_snapshotState(InitialSnapshotState), | 101 m_snapshotState(InitialSnapshotState), |
| 94 m_surface(std::move(surface)), | 102 m_surface(std::move(surface)), |
| 95 m_client(0), | 103 m_client(0), |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 328 | 336 |
| 329 void ImageBuffer::flushGpu(FlushReason reason) { | 337 void ImageBuffer::flushGpu(FlushReason reason) { |
| 330 if (m_surface->canvas()) { | 338 if (m_surface->canvas()) { |
| 331 m_surface->flushGpu(reason); | 339 m_surface->flushGpu(reason); |
| 332 } | 340 } |
| 333 } | 341 } |
| 334 | 342 |
| 335 bool ImageBuffer::getImageData(Multiply multiplied, | 343 bool ImageBuffer::getImageData(Multiply multiplied, |
| 336 const IntRect& rect, | 344 const IntRect& rect, |
| 337 WTF::ArrayBufferContents& contents) const { | 345 WTF::ArrayBufferContents& contents) const { |
| 338 CheckedNumeric<int> dataSize = 4; | 346 uint8_t bytesPerPixel = 4; |
| 347 if (m_surface->colorSpace()) |
| 348 bytesPerPixel = SkColorTypeBytesPerPixel(m_surface->colorType()); |
| 349 CheckedNumeric<int> dataSize = bytesPerPixel; |
| 339 dataSize *= rect.width(); | 350 dataSize *= rect.width(); |
| 340 dataSize *= rect.height(); | 351 dataSize *= rect.height(); |
| 341 if (!dataSize.IsValid()) | 352 if (!dataSize.IsValid()) |
| 342 return false; | 353 return false; |
| 343 | 354 |
| 344 if (!isSurfaceValid()) { | 355 if (!isSurfaceValid()) { |
| 345 size_t allocSizeInBytes = rect.width() * rect.height() * 4; | 356 size_t allocSizeInBytes = rect.width() * rect.height() * bytesPerPixel; |
| 346 void* data; | 357 void* data; |
| 347 WTF::ArrayBufferContents::allocateMemoryOrNull( | 358 WTF::ArrayBufferContents::allocateMemoryOrNull( |
| 348 allocSizeInBytes, WTF::ArrayBufferContents::ZeroInitialize, data); | 359 allocSizeInBytes, WTF::ArrayBufferContents::ZeroInitialize, data); |
| 349 if (!data) | 360 if (!data) |
| 350 return false; | 361 return false; |
| 351 WTF::ArrayBufferContents result(data, allocSizeInBytes, | 362 WTF::ArrayBufferContents result(data, allocSizeInBytes, |
| 352 WTF::ArrayBufferContents::NotShared); | 363 WTF::ArrayBufferContents::NotShared); |
| 353 result.transfer(contents); | 364 result.transfer(contents); |
| 354 return true; | 365 return true; |
| 355 } | 366 } |
| 356 | 367 |
| 357 DCHECK(canvas()); | 368 DCHECK(canvas()); |
| 358 | 369 |
| 359 if (ExpensiveCanvasHeuristicParameters::GetImageDataForcesNoAcceleration && | 370 if (ExpensiveCanvasHeuristicParameters::GetImageDataForcesNoAcceleration && |
| 360 !RuntimeEnabledFeatures::canvas2dFixedRenderingModeEnabled()) { | 371 !RuntimeEnabledFeatures::canvas2dFixedRenderingModeEnabled()) { |
| 361 const_cast<ImageBuffer*>(this)->disableAcceleration(); | 372 const_cast<ImageBuffer*>(this)->disableAcceleration(); |
| 362 } | 373 } |
| 363 | 374 |
| 364 sk_sp<SkImage> snapshot = m_surface->newImageSnapshot( | 375 sk_sp<SkImage> snapshot = m_surface->newImageSnapshot( |
| 365 PreferNoAcceleration, SnapshotReasonGetImageData); | 376 PreferNoAcceleration, SnapshotReasonGetImageData); |
| 366 if (!snapshot) | 377 if (!snapshot) |
| 367 return false; | 378 return false; |
| 368 | 379 |
| 369 const bool mayHaveStrayArea = | 380 const bool mayHaveStrayArea = |
| 370 m_surface->isAccelerated() // GPU readback may fail silently | 381 m_surface->isAccelerated() // GPU readback may fail silently |
| 371 || rect.x() < 0 || rect.y() < 0 || | 382 || rect.x() < 0 || rect.y() < 0 || |
| 372 rect.maxX() > m_surface->size().width() || | 383 rect.maxX() > m_surface->size().width() || |
| 373 rect.maxY() > m_surface->size().height(); | 384 rect.maxY() > m_surface->size().height(); |
| 374 size_t allocSizeInBytes = rect.width() * rect.height() * 4; | 385 size_t allocSizeInBytes = rect.width() * rect.height() * bytesPerPixel; |
| 375 void* data; | 386 void* data; |
| 376 WTF::ArrayBufferContents::InitializationPolicy initializationPolicy = | 387 WTF::ArrayBufferContents::InitializationPolicy initializationPolicy = |
| 377 mayHaveStrayArea ? WTF::ArrayBufferContents::ZeroInitialize | 388 mayHaveStrayArea ? WTF::ArrayBufferContents::ZeroInitialize |
| 378 : WTF::ArrayBufferContents::DontInitialize; | 389 : WTF::ArrayBufferContents::DontInitialize; |
| 379 WTF::ArrayBufferContents::allocateMemoryOrNull(allocSizeInBytes, | 390 WTF::ArrayBufferContents::allocateMemoryOrNull(allocSizeInBytes, |
| 380 initializationPolicy, data); | 391 initializationPolicy, data); |
| 381 if (!data) | 392 if (!data) |
| 382 return false; | 393 return false; |
| 383 WTF::ArrayBufferContents result(data, allocSizeInBytes, | 394 WTF::ArrayBufferContents result(data, allocSizeInBytes, |
| 384 WTF::ArrayBufferContents::NotShared); | 395 WTF::ArrayBufferContents::NotShared); |
| 385 | 396 |
| 386 // Skia does not support unpremultiplied read with an F16 to 8888 conversion | 397 // Skia does not support unpremultiplied read with an F16 to 8888 conversion |
| 387 bool useF16Workaround = m_surface->colorType() == kRGBA_F16_SkColorType; | 398 bool useF16Workaround = m_surface->colorType() == kRGBA_F16_SkColorType; |
| 388 | 399 |
| 389 SkAlphaType alphaType = (multiplied == Premultiplied || useF16Workaround) | 400 SkAlphaType alphaType = (multiplied == Premultiplied || useF16Workaround) |
| 390 ? kPremul_SkAlphaType | 401 ? kPremul_SkAlphaType |
| 391 : kUnpremul_SkAlphaType; | 402 : kUnpremul_SkAlphaType; |
| 392 // The workaround path use a canvas draw under the hood, which can only | 403 // The workaround path use a canvas draw under the hood, which can only |
| 393 // use N32 at this time. | 404 // use N32 at this time. |
| 394 SkColorType colorType = | 405 SkColorType colorType = |
| 395 useF16Workaround ? kN32_SkColorType : kRGBA_8888_SkColorType; | 406 useF16Workaround ? kN32_SkColorType : kRGBA_8888_SkColorType; |
| 396 SkImageInfo info = | 407 SkImageInfo info = |
| 397 SkImageInfo::Make(rect.width(), rect.height(), colorType, alphaType, | 408 SkImageInfo::Make(rect.width(), rect.height(), colorType, alphaType, |
| 398 SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named)); | 409 SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named)); |
| 399 | 410 |
| 400 snapshot->readPixels(info, result.data(), 4 * rect.width(), rect.x(), | 411 snapshot->readPixels(info, result.data(), bytesPerPixel * rect.width(), |
| 401 rect.y()); | 412 rect.x(), rect.y()); |
| 402 | 413 |
| 403 if (useF16Workaround) { | 414 if (useF16Workaround) { |
| 404 uint32_t* pixel = (uint32_t*)result.data(); | 415 uint32_t* pixel = (uint32_t*)result.data(); |
| 405 size_t pixelCount = allocSizeInBytes / sizeof(uint32_t); | 416 size_t pixelCount = allocSizeInBytes / sizeof(uint32_t); |
| 406 // TODO(skbug.com/5853): make readPixels support RGBA output so that we no | 417 // TODO(skbug.com/5853): make readPixels support RGBA output so that we no |
| 407 // longer | 418 // longer |
| 408 // have to do this. | 419 // have to do this. |
| 409 if (kN32_SkColorType == kBGRA_8888_SkColorType) { | 420 if (kN32_SkColorType == kBGRA_8888_SkColorType) { |
| 410 // Convert BGRA to RGBA if necessary on this platform. | 421 // Convert BGRA to RGBA if necessary on this platform. |
| 411 SkSwapRB(pixel, pixel, pixelCount); | 422 SkSwapRB(pixel, pixel, pixelCount); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 425 return true; | 436 return true; |
| 426 } | 437 } |
| 427 | 438 |
| 428 void ImageBuffer::putByteArray(Multiply multiplied, | 439 void ImageBuffer::putByteArray(Multiply multiplied, |
| 429 const unsigned char* source, | 440 const unsigned char* source, |
| 430 const IntSize& sourceSize, | 441 const IntSize& sourceSize, |
| 431 const IntRect& sourceRect, | 442 const IntRect& sourceRect, |
| 432 const IntPoint& destPoint) { | 443 const IntPoint& destPoint) { |
| 433 if (!isSurfaceValid()) | 444 if (!isSurfaceValid()) |
| 434 return; | 445 return; |
| 446 uint8_t bytesPerPixel = 4; |
| 447 if (m_surface->colorSpace()) |
| 448 bytesPerPixel = SkColorTypeBytesPerPixel(m_surface->colorType()); |
| 435 | 449 |
| 436 DCHECK_GT(sourceRect.width(), 0); | 450 DCHECK_GT(sourceRect.width(), 0); |
| 437 DCHECK_GT(sourceRect.height(), 0); | 451 DCHECK_GT(sourceRect.height(), 0); |
| 438 | 452 |
| 439 int originX = sourceRect.x(); | 453 int originX = sourceRect.x(); |
| 440 int destX = destPoint.x() + sourceRect.x(); | 454 int destX = destPoint.x() + sourceRect.x(); |
| 441 DCHECK_GE(destX, 0); | 455 DCHECK_GE(destX, 0); |
| 442 DCHECK_LT(destX, m_surface->size().width()); | 456 DCHECK_LT(destX, m_surface->size().width()); |
| 443 DCHECK_GE(originX, 0); | 457 DCHECK_GE(originX, 0); |
| 444 DCHECK_LT(originX, sourceRect.maxX()); | 458 DCHECK_LT(originX, sourceRect.maxX()); |
| 445 | 459 |
| 446 int originY = sourceRect.y(); | 460 int originY = sourceRect.y(); |
| 447 int destY = destPoint.y() + sourceRect.y(); | 461 int destY = destPoint.y() + sourceRect.y(); |
| 448 DCHECK_GE(destY, 0); | 462 DCHECK_GE(destY, 0); |
| 449 DCHECK_LT(destY, m_surface->size().height()); | 463 DCHECK_LT(destY, m_surface->size().height()); |
| 450 DCHECK_GE(originY, 0); | 464 DCHECK_GE(originY, 0); |
| 451 DCHECK_LT(originY, sourceRect.maxY()); | 465 DCHECK_LT(originY, sourceRect.maxY()); |
| 452 | 466 |
| 453 const size_t srcBytesPerRow = 4 * sourceSize.width(); | 467 const size_t srcBytesPerRow = bytesPerPixel * sourceSize.width(); |
| 454 const void* srcAddr = source + originY * srcBytesPerRow + originX * 4; | 468 const void* srcAddr = |
| 469 source + originY * srcBytesPerRow + originX * bytesPerPixel; |
| 455 SkAlphaType alphaType = (multiplied == Premultiplied) ? kPremul_SkAlphaType | 470 SkAlphaType alphaType = (multiplied == Premultiplied) ? kPremul_SkAlphaType |
| 456 : kUnpremul_SkAlphaType; | 471 : kUnpremul_SkAlphaType; |
| 457 SkImageInfo info = SkImageInfo::Make( | 472 SkImageInfo info; |
| 458 sourceRect.width(), sourceRect.height(), kRGBA_8888_SkColorType, | 473 if (m_surface->colorSpace()) { |
| 459 alphaType, SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named)); | 474 info = SkImageInfo::Make(sourceRect.width(), sourceRect.height(), |
| 460 | 475 m_surface->colorType(), alphaType, |
| 476 m_surface->colorSpace()); |
| 477 } else { |
| 478 info = SkImageInfo::Make( |
| 479 sourceRect.width(), sourceRect.height(), kRGBA_8888_SkColorType, |
| 480 alphaType, SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named)); |
| 481 } |
| 461 m_surface->writePixels(info, srcAddr, srcBytesPerRow, destX, destY); | 482 m_surface->writePixels(info, srcAddr, srcBytesPerRow, destX, destY); |
| 462 } | 483 } |
| 463 | 484 |
| 464 void ImageBuffer::updateGPUMemoryUsage() const { | 485 void ImageBuffer::updateGPUMemoryUsage() const { |
| 465 if (this->isAccelerated()) { | 486 if (this->isAccelerated()) { |
| 466 // If image buffer is accelerated, we should keep track of GPU memory usage. | 487 // If image buffer is accelerated, we should keep track of GPU memory usage. |
| 467 int gpuBufferCount = 2; | 488 int gpuBufferCount = 2; |
| 468 CheckedNumeric<intptr_t> checkedGPUUsage = 4 * gpuBufferCount; | 489 CheckedNumeric<intptr_t> checkedGPUUsage = |
| 490 SkColorTypeBytesPerPixel(m_surface->colorType()) * gpuBufferCount; |
| 469 checkedGPUUsage *= this->size().width(); | 491 checkedGPUUsage *= this->size().width(); |
| 470 checkedGPUUsage *= this->size().height(); | 492 checkedGPUUsage *= this->size().height(); |
| 471 intptr_t gpuMemoryUsage = | 493 intptr_t gpuMemoryUsage = |
| 472 checkedGPUUsage.ValueOrDefault(std::numeric_limits<intptr_t>::max()); | 494 checkedGPUUsage.ValueOrDefault(std::numeric_limits<intptr_t>::max()); |
| 473 | 495 |
| 474 if (!m_gpuMemoryUsage) // was not accelerated before | 496 if (!m_gpuMemoryUsage) // was not accelerated before |
| 475 s_globalAcceleratedImageBufferCount++; | 497 s_globalAcceleratedImageBufferCount++; |
| 476 | 498 |
| 477 s_globalGPUMemoryUsage += (gpuMemoryUsage - m_gpuMemoryUsage); | 499 s_globalGPUMemoryUsage += (gpuMemoryUsage - m_gpuMemoryUsage); |
| 478 m_gpuMemoryUsage = gpuMemoryUsage; | 500 m_gpuMemoryUsage = gpuMemoryUsage; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 512 void ImageBuffer::disableAcceleration() { | 534 void ImageBuffer::disableAcceleration() { |
| 513 if (!isAccelerated()) | 535 if (!isAccelerated()) |
| 514 return; | 536 return; |
| 515 | 537 |
| 516 // Create and configure a recording (unaccelerated) surface. | 538 // Create and configure a recording (unaccelerated) surface. |
| 517 std::unique_ptr<RecordingImageBufferFallbackSurfaceFactory> surfaceFactory = | 539 std::unique_ptr<RecordingImageBufferFallbackSurfaceFactory> surfaceFactory = |
| 518 WTF::makeUnique<UnacceleratedSurfaceFactory>(); | 540 WTF::makeUnique<UnacceleratedSurfaceFactory>(); |
| 519 std::unique_ptr<ImageBufferSurface> surface = | 541 std::unique_ptr<ImageBufferSurface> surface = |
| 520 WTF::wrapUnique(new RecordingImageBufferSurface( | 542 WTF::wrapUnique(new RecordingImageBufferSurface( |
| 521 m_surface->size(), std::move(surfaceFactory), | 543 m_surface->size(), std::move(surfaceFactory), |
| 522 m_surface->getOpacityMode(), m_surface->colorSpace())); | 544 m_surface->getOpacityMode(), m_surface->colorSpace(), |
| 545 m_surface->colorType())); |
| 523 setSurface(std::move(surface)); | 546 setSurface(std::move(surface)); |
| 524 } | 547 } |
| 525 | 548 |
| 526 void ImageBuffer::setSurface(std::unique_ptr<ImageBufferSurface> surface) { | 549 void ImageBuffer::setSurface(std::unique_ptr<ImageBufferSurface> surface) { |
| 527 sk_sp<SkImage> image = | 550 sk_sp<SkImage> image = |
| 528 m_surface->newImageSnapshot(PreferNoAcceleration, SnapshotReasonPaint); | 551 m_surface->newImageSnapshot(PreferNoAcceleration, SnapshotReasonPaint); |
| 529 | 552 |
| 530 if (surface->isRecording()) { | 553 if (surface->isRecording()) { |
| 531 // Using a GPU-backed image with RecordingImageBufferSurface | 554 // Using a GPU-backed image with RecordingImageBufferSurface |
| 532 // will fail at playback time. | 555 // will fail at playback time. |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 568 DCHECK(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)); | 591 DCHECK(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)); |
| 569 | 592 |
| 570 Vector<unsigned char> result; | 593 Vector<unsigned char> result; |
| 571 if (!encodeImage(mimeType, quality, &result)) | 594 if (!encodeImage(mimeType, quality, &result)) |
| 572 return "data:,"; | 595 return "data:,"; |
| 573 | 596 |
| 574 return "data:" + mimeType + ";base64," + base64Encode(result); | 597 return "data:" + mimeType + ";base64," + base64Encode(result); |
| 575 } | 598 } |
| 576 | 599 |
| 577 } // namespace blink | 600 } // namespace blink |
| OLD | NEW |