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 |