| 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 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 139 } | 139 } |
| 140 | 140 |
| 141 bool ImageBuffer::isSurfaceValid() const { | 141 bool ImageBuffer::isSurfaceValid() const { |
| 142 return m_surface->isValid(); | 142 return m_surface->isValid(); |
| 143 } | 143 } |
| 144 | 144 |
| 145 bool ImageBuffer::isDirty() { | 145 bool ImageBuffer::isDirty() { |
| 146 return m_client ? m_client->isDirty() : false; | 146 return m_client ? m_client->isDirty() : false; |
| 147 } | 147 } |
| 148 | 148 |
| 149 void ImageBuffer::didDisableAcceleration() const { | |
| 150 DCHECK(m_gpuMemoryUsage); | |
| 151 DCHECK_GT(s_globalAcceleratedImageBufferCount, 0u); | |
| 152 if (m_client) | |
| 153 m_client->didDisableAcceleration(); | |
| 154 s_globalAcceleratedImageBufferCount--; | |
| 155 s_globalGPUMemoryUsage -= m_gpuMemoryUsage; | |
| 156 m_gpuMemoryUsage = 0; | |
| 157 } | |
| 158 | |
| 159 void ImageBuffer::didFinalizeFrame() { | 149 void ImageBuffer::didFinalizeFrame() { |
| 160 if (m_client) | 150 if (m_client) |
| 161 m_client->didFinalizeFrame(); | 151 m_client->didFinalizeFrame(); |
| 162 } | 152 } |
| 163 | 153 |
| 164 void ImageBuffer::finalizeFrame(const FloatRect& dirtyRect) { | 154 void ImageBuffer::finalizeFrame(const FloatRect& dirtyRect) { |
| 165 m_surface->finalizeFrame(dirtyRect); | 155 m_surface->finalizeFrame(dirtyRect); |
| 166 didFinalizeFrame(); | 156 didFinalizeFrame(); |
| 167 } | 157 } |
| 168 | 158 |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 360 return false; | 350 return false; |
| 361 WTF::ArrayBufferContents result(data, allocSizeInBytes, | 351 WTF::ArrayBufferContents result(data, allocSizeInBytes, |
| 362 WTF::ArrayBufferContents::NotShared); | 352 WTF::ArrayBufferContents::NotShared); |
| 363 result.transfer(contents); | 353 result.transfer(contents); |
| 364 return true; | 354 return true; |
| 365 } | 355 } |
| 366 | 356 |
| 367 DCHECK(canvas()); | 357 DCHECK(canvas()); |
| 368 | 358 |
| 369 if (ExpensiveCanvasHeuristicParameters::GetImageDataForcesNoAcceleration && | 359 if (ExpensiveCanvasHeuristicParameters::GetImageDataForcesNoAcceleration && |
| 370 !RuntimeEnabledFeatures::canvas2dFixedRenderingModeEnabled()) | 360 !RuntimeEnabledFeatures::canvas2dFixedRenderingModeEnabled()) { |
| 371 const_cast<ImageBuffer*>(this)->disableAcceleration(); | 361 const_cast<ImageBuffer*>(this)->disableAcceleration(); |
| 362 } |
| 372 | 363 |
| 373 sk_sp<SkImage> snapshot = m_surface->newImageSnapshot( | 364 sk_sp<SkImage> snapshot = m_surface->newImageSnapshot( |
| 374 PreferNoAcceleration, SnapshotReasonGetImageData); | 365 PreferNoAcceleration, SnapshotReasonGetImageData); |
| 375 if (!snapshot) | 366 if (!snapshot) |
| 376 return false; | 367 return false; |
| 377 | 368 |
| 378 const bool mayHaveStrayArea = | 369 const bool mayHaveStrayArea = |
| 379 m_surface->isAccelerated() // GPU readback may fail silently | 370 m_surface->isAccelerated() // GPU readback may fail silently |
| 380 || rect.x() < 0 || rect.y() < 0 || | 371 || rect.x() < 0 || rect.y() < 0 || |
| 381 rect.maxX() > m_surface->size().width() || | 372 rect.maxX() > m_surface->size().width() || |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 435 } | 426 } |
| 436 | 427 |
| 437 void ImageBuffer::putByteArray(Multiply multiplied, | 428 void ImageBuffer::putByteArray(Multiply multiplied, |
| 438 const unsigned char* source, | 429 const unsigned char* source, |
| 439 const IntSize& sourceSize, | 430 const IntSize& sourceSize, |
| 440 const IntRect& sourceRect, | 431 const IntRect& sourceRect, |
| 441 const IntPoint& destPoint) { | 432 const IntPoint& destPoint) { |
| 442 if (!isSurfaceValid()) | 433 if (!isSurfaceValid()) |
| 443 return; | 434 return; |
| 444 | 435 |
| 445 ASSERT(sourceRect.width() > 0); | 436 DCHECK_GT(sourceRect.width(), 0); |
| 446 ASSERT(sourceRect.height() > 0); | 437 DCHECK_GT(sourceRect.height(), 0); |
| 447 | 438 |
| 448 int originX = sourceRect.x(); | 439 int originX = sourceRect.x(); |
| 449 int destX = destPoint.x() + sourceRect.x(); | 440 int destX = destPoint.x() + sourceRect.x(); |
| 450 ASSERT(destX >= 0); | 441 DCHECK_GE(destX, 0); |
| 451 ASSERT(destX < m_surface->size().width()); | 442 DCHECK_LT(destX, m_surface->size().width()); |
| 452 ASSERT(originX >= 0); | 443 DCHECK_GE(originX, 0); |
| 453 ASSERT(originX < sourceRect.maxX()); | 444 DCHECK_LT(originX, sourceRect.maxX()); |
| 454 | 445 |
| 455 int originY = sourceRect.y(); | 446 int originY = sourceRect.y(); |
| 456 int destY = destPoint.y() + sourceRect.y(); | 447 int destY = destPoint.y() + sourceRect.y(); |
| 457 ASSERT(destY >= 0); | 448 DCHECK_GE(destY, 0); |
| 458 ASSERT(destY < m_surface->size().height()); | 449 DCHECK_LT(destY, m_surface->size().height()); |
| 459 ASSERT(originY >= 0); | 450 DCHECK_GE(originY, 0); |
| 460 ASSERT(originY < sourceRect.maxY()); | 451 DCHECK_LT(originY, sourceRect.maxY()); |
| 461 | 452 |
| 462 const size_t srcBytesPerRow = 4 * sourceSize.width(); | 453 const size_t srcBytesPerRow = 4 * sourceSize.width(); |
| 463 const void* srcAddr = source + originY * srcBytesPerRow + originX * 4; | 454 const void* srcAddr = source + originY * srcBytesPerRow + originX * 4; |
| 464 SkAlphaType alphaType = (multiplied == Premultiplied) ? kPremul_SkAlphaType | 455 SkAlphaType alphaType = (multiplied == Premultiplied) ? kPremul_SkAlphaType |
| 465 : kUnpremul_SkAlphaType; | 456 : kUnpremul_SkAlphaType; |
| 466 SkImageInfo info = SkImageInfo::Make( | 457 SkImageInfo info = SkImageInfo::Make( |
| 467 sourceRect.width(), sourceRect.height(), kRGBA_8888_SkColorType, | 458 sourceRect.width(), sourceRect.height(), kRGBA_8888_SkColorType, |
| 468 alphaType, SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named)); | 459 alphaType, SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named)); |
| 469 | 460 |
| 470 m_surface->writePixels(info, srcAddr, srcBytesPerRow, destX, destY); | 461 m_surface->writePixels(info, srcAddr, srcBytesPerRow, destX, destY); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 485 | 476 |
| 486 s_globalGPUMemoryUsage += (gpuMemoryUsage - m_gpuMemoryUsage); | 477 s_globalGPUMemoryUsage += (gpuMemoryUsage - m_gpuMemoryUsage); |
| 487 m_gpuMemoryUsage = gpuMemoryUsage; | 478 m_gpuMemoryUsage = gpuMemoryUsage; |
| 488 } else if (m_gpuMemoryUsage) { | 479 } else if (m_gpuMemoryUsage) { |
| 489 // In case of switching from accelerated to non-accelerated mode, | 480 // In case of switching from accelerated to non-accelerated mode, |
| 490 // the GPU memory usage needs to be updated too. | 481 // the GPU memory usage needs to be updated too. |
| 491 DCHECK_GT(s_globalAcceleratedImageBufferCount, 0u); | 482 DCHECK_GT(s_globalAcceleratedImageBufferCount, 0u); |
| 492 s_globalAcceleratedImageBufferCount--; | 483 s_globalAcceleratedImageBufferCount--; |
| 493 s_globalGPUMemoryUsage -= m_gpuMemoryUsage; | 484 s_globalGPUMemoryUsage -= m_gpuMemoryUsage; |
| 494 m_gpuMemoryUsage = 0; | 485 m_gpuMemoryUsage = 0; |
| 486 |
| 487 if (m_client) |
| 488 m_client->didDisableAcceleration(); |
| 495 } | 489 } |
| 496 } | 490 } |
| 497 | 491 |
| 498 namespace { | 492 namespace { |
| 499 | 493 |
| 500 class UnacceleratedSurfaceFactory | 494 class UnacceleratedSurfaceFactory |
| 501 : public RecordingImageBufferFallbackSurfaceFactory { | 495 : public RecordingImageBufferFallbackSurfaceFactory { |
| 502 public: | 496 public: |
| 503 virtual std::unique_ptr<ImageBufferSurface> createSurface( | 497 virtual std::unique_ptr<ImageBufferSurface> createSurface( |
| 504 const IntSize& size, | 498 const IntSize& size, |
| 505 OpacityMode opacityMode, | 499 OpacityMode opacityMode, |
| 506 sk_sp<SkColorSpace> colorSpace, | 500 sk_sp<SkColorSpace> colorSpace, |
| 507 SkColorType colorType) { | 501 SkColorType colorType) { |
| 508 return WTF::wrapUnique(new UnacceleratedImageBufferSurface( | 502 return WTF::wrapUnique(new UnacceleratedImageBufferSurface( |
| 509 size, opacityMode, InitializeImagePixels, std::move(colorSpace), | 503 size, opacityMode, InitializeImagePixels, std::move(colorSpace), |
| 510 colorType)); | 504 colorType)); |
| 511 } | 505 } |
| 512 | 506 |
| 513 virtual ~UnacceleratedSurfaceFactory() {} | 507 virtual ~UnacceleratedSurfaceFactory() {} |
| 514 }; | 508 }; |
| 515 | 509 |
| 516 } // namespace | 510 } // namespace |
| 517 | 511 |
| 518 void ImageBuffer::disableAcceleration() { | 512 void ImageBuffer::disableAcceleration() { |
| 519 if (!isAccelerated()) | 513 if (!isAccelerated()) |
| 520 return; | 514 return; |
| 521 | 515 |
| 522 sk_sp<SkImage> image = | |
| 523 m_surface->newImageSnapshot(PreferNoAcceleration, SnapshotReasonPaint); | |
| 524 // Using a GPU-backed image with RecordingImageBufferSurface | |
| 525 // will fail at playback time. | |
| 526 image = image->makeNonTextureImage(); | |
| 527 | |
| 528 // Create and configure a recording (unaccelerated) surface. | 516 // Create and configure a recording (unaccelerated) surface. |
| 529 std::unique_ptr<RecordingImageBufferFallbackSurfaceFactory> surfaceFactory = | 517 std::unique_ptr<RecordingImageBufferFallbackSurfaceFactory> surfaceFactory = |
| 530 WTF::makeUnique<UnacceleratedSurfaceFactory>(); | 518 WTF::makeUnique<UnacceleratedSurfaceFactory>(); |
| 531 std::unique_ptr<ImageBufferSurface> surface = | 519 std::unique_ptr<ImageBufferSurface> surface = |
| 532 WTF::wrapUnique(new RecordingImageBufferSurface( | 520 WTF::wrapUnique(new RecordingImageBufferSurface( |
| 533 m_surface->size(), std::move(surfaceFactory), | 521 m_surface->size(), std::move(surfaceFactory), |
| 534 m_surface->getOpacityMode(), m_surface->colorSpace())); | 522 m_surface->getOpacityMode(), m_surface->colorSpace())); |
| 523 setSurface(std::move(surface)); |
| 524 } |
| 525 |
| 526 void ImageBuffer::setSurface(std::unique_ptr<ImageBufferSurface> surface) { |
| 527 sk_sp<SkImage> image = |
| 528 m_surface->newImageSnapshot(PreferNoAcceleration, SnapshotReasonPaint); |
| 529 |
| 530 if (surface->isRecording()) { |
| 531 // Using a GPU-backed image with RecordingImageBufferSurface |
| 532 // will fail at playback time. |
| 533 image = image->makeNonTextureImage(); |
| 534 } |
| 535 |
| 535 surface->canvas()->drawImage(image.get(), 0, 0); | 536 surface->canvas()->drawImage(image.get(), 0, 0); |
| 536 surface->setImageBuffer(this); | 537 surface->setImageBuffer(this); |
| 537 if (m_client) | 538 if (m_client) |
| 538 m_client->restoreCanvasMatrixClipStack(surface->canvas()); | 539 m_client->restoreCanvasMatrixClipStack(surface->canvas()); |
| 539 m_surface = std::move(surface); | 540 m_surface = std::move(surface); |
| 540 | 541 |
| 541 didDisableAcceleration(); | 542 updateGPUMemoryUsage(); |
| 542 } | 543 } |
| 543 | 544 |
| 544 bool ImageDataBuffer::encodeImage(const String& mimeType, | 545 bool ImageDataBuffer::encodeImage(const String& mimeType, |
| 545 const double& quality, | 546 const double& quality, |
| 546 Vector<unsigned char>* encodedImage) const { | 547 Vector<unsigned char>* encodedImage) const { |
| 547 if (mimeType == "image/jpeg") { | 548 if (mimeType == "image/jpeg") { |
| 548 if (!JPEGImageEncoder::encode(*this, quality, encodedImage)) | 549 if (!JPEGImageEncoder::encode(*this, quality, encodedImage)) |
| 549 return false; | 550 return false; |
| 550 } else if (mimeType == "image/webp") { | 551 } else if (mimeType == "image/webp") { |
| 551 int compressionQuality = WEBPImageEncoder::DefaultCompressionQuality; | 552 int compressionQuality = WEBPImageEncoder::DefaultCompressionQuality; |
| 552 if (quality >= 0.0 && quality <= 1.0) | 553 if (quality >= 0.0 && quality <= 1.0) |
| 553 compressionQuality = static_cast<int>(quality * 100 + 0.5); | 554 compressionQuality = static_cast<int>(quality * 100 + 0.5); |
| 554 if (!WEBPImageEncoder::encode(*this, compressionQuality, encodedImage)) | 555 if (!WEBPImageEncoder::encode(*this, compressionQuality, encodedImage)) |
| 555 return false; | 556 return false; |
| 556 } else { | 557 } else { |
| 557 if (!PNGImageEncoder::encode(*this, encodedImage)) | 558 if (!PNGImageEncoder::encode(*this, encodedImage)) |
| 558 return false; | 559 return false; |
| 559 ASSERT(mimeType == "image/png"); | 560 DCHECK_EQ(mimeType, "image/png"); |
| 560 } | 561 } |
| 561 | 562 |
| 562 return true; | 563 return true; |
| 563 } | 564 } |
| 564 | 565 |
| 565 String ImageDataBuffer::toDataURL(const String& mimeType, | 566 String ImageDataBuffer::toDataURL(const String& mimeType, |
| 566 const double& quality) const { | 567 const double& quality) const { |
| 567 ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)); | 568 DCHECK(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)); |
| 568 | 569 |
| 569 Vector<unsigned char> result; | 570 Vector<unsigned char> result; |
| 570 if (!encodeImage(mimeType, quality, &result)) | 571 if (!encodeImage(mimeType, quality, &result)) |
| 571 return "data:,"; | 572 return "data:,"; |
| 572 | 573 |
| 573 return "data:" + mimeType + ";base64," + base64Encode(result); | 574 return "data:" + mimeType + ";base64," + base64Encode(result); |
| 574 } | 575 } |
| 575 | 576 |
| 576 } // namespace blink | 577 } // namespace blink |
| OLD | NEW |