summaryrefslogtreecommitdiffstats
path: root/skia/ext
diff options
context:
space:
mode:
authortomhudson <tomhudson@google.com>2015-11-05 15:06:36 -0800
committerCommit bot <commit-bot@chromium.org>2015-11-05 23:07:42 +0000
commit4a207e610fc0c36a82bf6406db294577c688c14c (patch)
tree5a11ec16a381e987b025c484f28e3a4fb32bf4ba /skia/ext
parent924e64c4a2126553b0e2d6cf3dd7bca9030f2a84 (diff)
downloadchromium_src-4a207e610fc0c36a82bf6406db294577c688c14c.zip
chromium_src-4a207e610fc0c36a82bf6406db294577c688c14c.tar.gz
chromium_src-4a207e610fc0c36a82bf6406db294577c688c14c.tar.bz2
SkDevice shouldn't be accessed outside of Skia; it will soon be
deprecated. This refactoring adds a function to Chromium's skia namespace that wraps the code required to get write access to the pixel data backing a *raster* SkCanvas. Instead of returning a SkBitmap with complicated lifetime semantics, we use the simpler SkPixmap where possible. The previous version of ImageDataPlatformBackend::Map() forcibly changed the bitmap descriptor from opaque to premultiplied; this isn't guaranteed to actually work. Instead we change the initialization of the bitmap so that it's premultiplied instead of opaque. R=reed@chromium.org,bbudge@chromium.org,piman@chromium.org,msw@chromium.org BUG=543755 TEST=gfx_unittests,ppapi_unittests Review URL: https://codereview.chromium.org/1420283003 Cr-Commit-Position: refs/heads/master@{#358166}
Diffstat (limited to 'skia/ext')
-rw-r--r--skia/ext/platform_canvas.cc17
-rw-r--r--skia/ext/platform_canvas.h10
-rw-r--r--skia/ext/skia_utils_mac.h8
-rw-r--r--skia/ext/skia_utils_mac.mm51
4 files changed, 61 insertions, 25 deletions
diff --git a/skia/ext/platform_canvas.cc b/skia/ext/platform_canvas.cc
index 5e5aeb2..cf362b3 100644
--- a/skia/ext/platform_canvas.cc
+++ b/skia/ext/platform_canvas.cc
@@ -20,6 +20,23 @@ SkBitmap ReadPixels(SkCanvas* canvas) {
return bitmap;
}
+bool GetWritablePixels(SkCanvas* canvas, SkPixmap* result) {
+ if (!canvas || !result) {
+ return false;
+ }
+
+ SkImageInfo info;
+ size_t row_bytes;
+ void* pixels = canvas->accessTopLayerPixels(&info, &row_bytes);
+ if (!pixels) {
+ result->reset();
+ return false;
+ }
+
+ result->reset(info, pixels, row_bytes);
+ return true;
+}
+
bool SupportsPlatformPaint(const SkCanvas* canvas) {
PlatformDevice* platform_device = GetPlatformDevice(GetTopDevice(*canvas));
return platform_device && platform_device->SupportsPlatformPaint();
diff --git a/skia/ext/platform_canvas.h b/skia/ext/platform_canvas.h
index 4499041..c46d6c4 100644
--- a/skia/ext/platform_canvas.h
+++ b/skia/ext/platform_canvas.h
@@ -13,6 +13,7 @@
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkPixelRef.h"
+#include "third_party/skia/include/core/SkPixmap.h"
namespace skia {
@@ -123,6 +124,15 @@ SK_API SkBaseDevice* GetTopDevice(const SkCanvas& canvas);
// of the pixels.
SK_API SkBitmap ReadPixels(SkCanvas* canvas);
+// Gives the pixmap passed in *writable* access to the pixels backing this
+// canvas. All writes to the pixmap should be visible if the canvas is
+// raster-backed.
+//
+// Returns false on failure: if either argument is nullptr, or if the
+// pixels can not be retrieved from the canvas. In the latter case resets
+// the pixmap to empty.
+SK_API bool GetWritablePixels(SkCanvas* canvas, SkPixmap* pixmap);
+
// Returns true if native platform routines can be used to draw on the
// given canvas. If this function returns false, BeginPlatformPaint will
// return NULL PlatformSurface.
diff --git a/skia/ext/skia_utils_mac.h b/skia/ext/skia_utils_mac.h
index b60f9e8..e99913f 100644
--- a/skia/ext/skia_utils_mac.h
+++ b/skia/ext/skia_utils_mac.h
@@ -10,6 +10,7 @@
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkColor.h"
+#include "third_party/skia/include/core/SkPixmap.h"
struct SkIRect;
struct SkPoint;
@@ -129,12 +130,13 @@ class SK_API SkiaBitLocker {
bool userClipRectSpecified_;
CGContextRef cgContext_;
- SkBitmap bitmap_;
+ // offscreen_ is only valid if useDeviceBits_ is false
+ SkBitmap offscreen_;
SkIPoint bitmapOffset_;
SkScalar bitmapScaleFactor_;
- // True if we are drawing to |canvas_|'s SkBaseDevice's bits directly through
- // |bitmap_|. Otherwise, the bits in |bitmap_| are our allocation and need to
+ // True if we are drawing to |canvas_|'s backing store directly.
+ // Otherwise, the bits in |bitmap_| are our allocation and need to
// be copied over to |canvas_|.
bool useDeviceBits_;
diff --git a/skia/ext/skia_utils_mac.mm b/skia/ext/skia_utils_mac.mm
index 9e552eb..fe05464c 100644
--- a/skia/ext/skia_utils_mac.mm
+++ b/skia/ext/skia_utils_mac.mm
@@ -11,6 +11,7 @@
#include "base/mac/scoped_nsobject.h"
#include "base/memory/scoped_ptr.h"
#include "skia/ext/bitmap_platform_device_mac.h"
+#include "skia/ext/platform_canvas.h"
#include "third_party/skia/include/core/SkRegion.h"
#include "third_party/skia/include/utils/mac/SkCGUtils.h"
@@ -297,15 +298,15 @@ SkIRect SkiaBitLocker::computeDirtyRect() {
// If the user specified a clip region, assume that it was tight and that the
// dirty rect is approximately the whole bitmap.
if (userClipRectSpecified_)
- return SkIRect::MakeWH(bitmap_.width(), bitmap_.height());
+ return SkIRect::MakeWH(offscreen_.width(), offscreen_.height());
// Find the bits that were drawn to.
- SkAutoLockPixels lockedPixels(bitmap_);
+ SkAutoLockPixels lockedPixels(offscreen_);
const uint32_t* pixelBase
- = reinterpret_cast<uint32_t*>(bitmap_.getPixels());
- int rowPixels = bitmap_.rowBytesAsPixels();
- int width = bitmap_.width();
- int height = bitmap_.height();
+ = reinterpret_cast<uint32_t*>(offscreen_.getPixels());
+ int rowPixels = offscreen_.rowBytesAsPixels();
+ int width = offscreen_.width();
+ int height = offscreen_.height();
SkIRect bounds;
bounds.fTop = 0;
int x;
@@ -367,13 +368,11 @@ foundRight:
void SkiaBitLocker::releaseIfNeeded() {
if (!cgContext_)
return;
- if (useDeviceBits_) {
- bitmap_.unlockPixels();
- } else if (!bitmapIsDummy_) {
+ if (!useDeviceBits_ && !bitmapIsDummy_) {
// Find the bits that were drawn to.
SkIRect bounds = computeDirtyRect();
SkBitmap subset;
- if (!bitmap_.extractSubset(&subset, bounds)) {
+ if (!offscreen_.extractSubset(&subset, bounds)) {
return;
}
subset.setImmutable(); // Prevents a defensive copy inside Skia.
@@ -414,41 +413,49 @@ CGContextRef SkiaBitLocker::cgContext() {
// Now make clip_bounds be relative to the current layer/device
clip_bounds.offset(-device->getOrigin());
- const SkBitmap& deviceBits = device->accessBitmap(true);
+ SkPixmap devicePixels;
+ skia::GetWritablePixels(canvas_, &devicePixels);
// Only draw directly if we have pixels, and we're only rect-clipped.
// If not, we allocate an offscreen and draw into that, relying on the
// compositing step to apply skia's clip.
- useDeviceBits_ = deviceBits.getPixels() &&
+ useDeviceBits_ = devicePixels.addr() &&
canvas_->isClipRect() &&
!bitmapIsDummy_;
+ base::ScopedCFTypeRef<CGColorSpaceRef> colorSpace(
+ CGColorSpaceCreateDeviceRGB());
+
+ int displayHeight;
if (useDeviceBits_) {
- bool result = deviceBits.extractSubset(&bitmap_, clip_bounds);
+ SkPixmap subset;
+ bool result = devicePixels.extractSubset(&subset, clip_bounds);
DCHECK(result);
if (!result)
return 0;
- bitmap_.lockPixels();
+ displayHeight = subset.height();
+ cgContext_ = CGBitmapContextCreate(subset.writable_addr(), subset.width(),
+ subset.height(), 8, subset.rowBytes(), colorSpace,
+ kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst);
} else {
- bool result = bitmap_.tryAllocN32Pixels(
+ bool result = offscreen_.tryAllocN32Pixels(
SkScalarCeilToInt(bitmapScaleFactor_ * clip_bounds.width()),
SkScalarCeilToInt(bitmapScaleFactor_ * clip_bounds.height()));
DCHECK(result);
if (!result)
return 0;
- bitmap_.eraseColor(0);
+ offscreen_.eraseColor(0);
+ displayHeight = offscreen_.height();
+ cgContext_ = CGBitmapContextCreate(offscreen_.getPixels(),
+ offscreen_.width(), offscreen_.height(), 8, offscreen_.rowBytes(),
+ colorSpace, kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst);
}
- base::ScopedCFTypeRef<CGColorSpaceRef> colorSpace(
- CGColorSpaceCreateDeviceRGB());
- cgContext_ = CGBitmapContextCreate(bitmap_.getPixels(), bitmap_.width(),
- bitmap_.height(), 8, bitmap_.rowBytes(), colorSpace,
- kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst);
DCHECK(cgContext_);
SkMatrix matrix = canvas_->getTotalMatrix();
matrix.postTranslate(-SkIntToScalar(bitmapOffset_.x()),
-SkIntToScalar(bitmapOffset_.y()));
matrix.postScale(bitmapScaleFactor_, -bitmapScaleFactor_);
- matrix.postTranslate(0, SkIntToScalar(bitmap_.height()));
+ matrix.postTranslate(0, SkIntToScalar(displayHeight));
CGContextConcatCTM(cgContext_, SkMatrixToCGAffineTransform(matrix));