Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(360)

Side by Side Diff: third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp

Issue 2625873005: Add an heuristic for promoting canvases to GPU acceleration (Closed)
Patch Set: webgl test fix Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/WebKit/Source/platform/graphics/ImageBuffer.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/platform/graphics/ImageBuffer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698