summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornick@chromium.org <nick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-02-02 23:31:07 +0000
committernick@chromium.org <nick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-02-02 23:31:07 +0000
commitd748d0ffa9996ae58ab39c2cfdd5abbfcb6dcec4 (patch)
treeaf8aab17d5d6a08ba69022f408792733471da483
parent89ae13ed038c80228a532f42c92cd5de5bbc8a35 (diff)
downloadchromium_src-d748d0ffa9996ae58ab39c2cfdd5abbfcb6dcec4.zip
chromium_src-d748d0ffa9996ae58ab39c2cfdd5abbfcb6dcec4.tar.gz
chromium_src-d748d0ffa9996ae58ab39c2cfdd5abbfcb6dcec4.tar.bz2
Change PlatformBitmap memory ownership story. Fix CopyFromBackingStore threading issues.
PlatformBitmap: restructure this class so that, on all platforms, it is safe to use an SkBitmap derived from the PlatformBitmap even after the PlatformBitmap is destroyed. In practice this means changes to Linux (use a different cairo creation routine that allows us to allocate the memory) and Windows (the HDC is owned by PlatformBitmap, the HBITMAP by the SkPixelRef). CopyFromBackingStore: instead of requiring the caller to provide a PlatformBitmap, modify the signature so that the completion callback accepts an SkBitmap. Sometimes, the backing store copiers will allocate a PlatformBitmap and pass its SkBitmap to the completion callback, but this becomes merely an implementation detail. Meanwhile, in the accelerated case, it is not at all necessary to allocate a PlatformBitmap, so don't. This fixes a bug on Linux where the cairo surface context was being freed on a thread other than the UI thread. PlatformBitmap is basically not thread safe on Linux, and this change fixes that. Also fixed is a Dr. Memory GDI usage warning -- we are sure to de-select the HBITMAP before deleting the memory DC. Lastly, moving CopyFromBackingStore's interface to use a callee-managed SkBitmap conditions the architecture for doing RGBA->YUV on the GPU, prior to readback. BUG=109963,159234,161537 Review URL: https://codereview.chromium.org/12087016 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@180271 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/extensions/api/tabs/tabs_api.cc11
-rw-r--r--chrome/browser/extensions/api/tabs/tabs_api.h8
-rw-r--r--chrome/browser/prerender/prerender_tab_helper.cc11
-rw-r--r--chrome/browser/thumbnails/thumbnail_tab_helper.cc16
-rw-r--r--content/browser/renderer_host/compositing_iosurface_mac.h26
-rw-r--r--content/browser/renderer_host/compositing_iosurface_mac.mm27
-rw-r--r--content/browser/renderer_host/media/web_contents_video_capture_device.cc54
-rw-r--r--content/browser/renderer_host/media/web_contents_video_capture_device_unittest.cc16
-rw-r--r--content/browser/renderer_host/render_widget_host_impl.cc13
-rw-r--r--content/browser/renderer_host/render_widget_host_impl.h3
-rw-r--r--content/browser/renderer_host/render_widget_host_view_android.cc5
-rw-r--r--content/browser/renderer_host/render_widget_host_view_android.h3
-rw-r--r--content/browser/renderer_host/render_widget_host_view_aura.cc23
-rw-r--r--content/browser/renderer_host/render_widget_host_view_aura.h6
-rw-r--r--content/browser/renderer_host/render_widget_host_view_browsertest.cc7
-rw-r--r--content/browser/renderer_host/render_widget_host_view_gtk.cc17
-rw-r--r--content/browser/renderer_host/render_widget_host_view_gtk.h3
-rw-r--r--content/browser/renderer_host/render_widget_host_view_guest.cc4
-rw-r--r--content/browser/renderer_host/render_widget_host_view_guest.h3
-rw-r--r--content/browser/renderer_host/render_widget_host_view_mac.h3
-rw-r--r--content/browser/renderer_host/render_widget_host_view_mac.mm17
-rw-r--r--content/browser/renderer_host/render_widget_host_view_win.cc10
-rw-r--r--content/browser/renderer_host/render_widget_host_view_win.h3
-rw-r--r--content/browser/renderer_host/test_render_view_host.cc5
-rw-r--r--content/browser/renderer_host/test_render_view_host.h3
-rw-r--r--content/browser/web_contents/navigation_controller_impl.cc11
-rw-r--r--content/browser/web_contents/navigation_controller_impl.h9
-rw-r--r--content/browser/web_contents/navigation_controller_impl_unittest.cc16
-rw-r--r--content/port/browser/render_widget_host_view_port.h8
-rw-r--r--content/public/browser/render_widget_host.h38
-rw-r--r--skia/ext/bitmap_platform_device_android.cc5
-rw-r--r--skia/ext/bitmap_platform_device_linux.cc25
-rw-r--r--skia/ext/bitmap_platform_device_win.cc97
-rw-r--r--skia/ext/platform_canvas.h11
-rw-r--r--skia/ext/platform_canvas_unittest.cc65
-rw-r--r--tools/valgrind/drmemory/suppressions.txt7
-rw-r--r--ui/surface/accelerated_surface_win.cc46
-rw-r--r--ui/surface/accelerated_surface_win.h11
38 files changed, 366 insertions, 280 deletions
diff --git a/chrome/browser/extensions/api/tabs/tabs_api.cc b/chrome/browser/extensions/api/tabs/tabs_api.cc
index 315b72b..c70373e 100644
--- a/chrome/browser/extensions/api/tabs/tabs_api.cc
+++ b/chrome/browser/extensions/api/tabs/tabs_api.cc
@@ -1708,23 +1708,20 @@ bool TabsCaptureVisibleTabFunction::RunImpl() {
error_ = keys::kInternalVisibleTabCaptureError;
return false;
}
- skia::PlatformBitmap* temp_bitmap = new skia::PlatformBitmap;
render_view_host->CopyFromBackingStore(
gfx::Rect(),
view->GetViewBounds().size(),
base::Bind(&TabsCaptureVisibleTabFunction::CopyFromBackingStoreComplete,
- this,
- base::Owned(temp_bitmap)),
- temp_bitmap);
+ this));
return true;
}
void TabsCaptureVisibleTabFunction::CopyFromBackingStoreComplete(
- skia::PlatformBitmap* bitmap,
- bool succeeded) {
+ bool succeeded,
+ const SkBitmap& bitmap) {
if (succeeded) {
VLOG(1) << "captureVisibleTab() got image from backing store.";
- SendResultFromBitmap(bitmap->GetBitmap());
+ SendResultFromBitmap(bitmap);
return;
}
diff --git a/chrome/browser/extensions/api/tabs/tabs_api.h b/chrome/browser/extensions/api/tabs/tabs_api.h
index 71d7d49..851aa77 100644
--- a/chrome/browser/extensions/api/tabs/tabs_api.h
+++ b/chrome/browser/extensions/api/tabs/tabs_api.h
@@ -37,10 +37,6 @@ struct InjectDetails;
} // namespace api
} // namespace extensions
-namespace skia {
-class PlatformBitmap;
-}
-
// Windows
class WindowsGetFunction : public SyncExtensionFunction {
virtual ~WindowsGetFunction() {}
@@ -201,8 +197,8 @@ class TabsCaptureVisibleTabFunction : public AsyncExtensionFunction,
void SendResultFromBitmap(const SkBitmap& screen_capture);
private:
- void CopyFromBackingStoreComplete(skia::PlatformBitmap* bitmap,
- bool succeeded);
+ void CopyFromBackingStoreComplete(bool succeeded,
+ const SkBitmap& bitmap);
content::NotificationRegistrar registrar_;
diff --git a/chrome/browser/prerender/prerender_tab_helper.cc b/chrome/browser/prerender/prerender_tab_helper.cc
index 7139547..7950027 100644
--- a/chrome/browser/prerender/prerender_tab_helper.cc
+++ b/chrome/browser/prerender/prerender_tab_helper.cc
@@ -55,26 +55,23 @@ class PrerenderTabHelper::PixelStats {
return;
}
- skia::PlatformBitmap* temp_bitmap = new skia::PlatformBitmap;
web_contents->GetRenderViewHost()->CopyFromBackingStore(
gfx::Rect(),
gfx::Size(),
base::Bind(&PrerenderTabHelper::PixelStats::HandleBitmapResult,
weak_factory_.GetWeakPtr(),
bitmap_type,
- web_contents,
- base::Owned(temp_bitmap)),
- temp_bitmap);
+ web_contents));
}
private:
void HandleBitmapResult(BitmapType bitmap_type,
WebContents* web_contents,
- skia::PlatformBitmap* temp_bitmap,
- bool succeeded) {
+ bool succeeded,
+ const SkBitmap& canvas_bitmap) {
scoped_ptr<SkBitmap> bitmap;
if (succeeded) {
- const SkBitmap& canvas_bitmap = temp_bitmap->GetBitmap();
+ // TODO(nick): This copy may now be unnecessary.
bitmap.reset(new SkBitmap());
canvas_bitmap.copyTo(bitmap.get(), SkBitmap::kARGB_8888_Config);
}
diff --git a/chrome/browser/thumbnails/thumbnail_tab_helper.cc b/chrome/browser/thumbnails/thumbnail_tab_helper.cc
index fcd71df..2ea7feb 100644
--- a/chrome/browser/thumbnails/thumbnail_tab_helper.cc
+++ b/chrome/browser/thumbnails/thumbnail_tab_helper.cc
@@ -16,7 +16,6 @@
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host_view.h"
-#include "skia/ext/platform_canvas.h"
#include "ui/gfx/color_utils.h"
#include "ui/gfx/size_conversions.h"
#include "ui/gfx/screen.h"
@@ -29,6 +28,8 @@
DEFINE_WEB_CONTENTS_USER_DATA_KEY(ThumbnailTabHelper);
+class SkBitmap;
+
// Overview
// --------
// This class provides a service for updating thumbnails to be used in
@@ -61,15 +62,14 @@ void UpdateThumbnail(const ThumbnailingContext& context,
<< context.score.ToString();
}
-void ProcessCanvas(ThumbnailingContext* context,
- ThumbnailingAlgorithm* algorithm,
- skia::PlatformBitmap* temp_bitmap,
- bool succeeded) {
+void ProcessCapturedBitmap(ThumbnailingContext* context,
+ ThumbnailingAlgorithm* algorithm,
+ bool succeeded,
+ const SkBitmap& bitmap) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
if (!succeeded)
return;
- SkBitmap bitmap = temp_bitmap->GetBitmap();
algorithm->ProcessBitmap(context, base::Bind(&UpdateThumbnail), bitmap);
}
@@ -116,12 +116,10 @@ void AsyncProcessThumbnail(content::WebContents* web_contents,
&copy_rect,
&copy_size);
- skia::PlatformBitmap* temp_bitmap = new skia::PlatformBitmap;
render_widget_host->CopyFromBackingStore(
copy_rect,
copy_size,
- base::Bind(&ProcessCanvas, context, algorithm, base::Owned(temp_bitmap)),
- temp_bitmap);
+ base::Bind(&ProcessCapturedBitmap, context, algorithm));
}
} // namespace
diff --git a/content/browser/renderer_host/compositing_iosurface_mac.h b/content/browser/renderer_host/compositing_iosurface_mac.h
index cd834ce..44cc639 100644
--- a/content/browser/renderer_host/compositing_iosurface_mac.h
+++ b/content/browser/renderer_host/compositing_iosurface_mac.h
@@ -15,6 +15,7 @@
#include "base/synchronization/lock.h"
#include "base/time.h"
#include "base/timer.h"
+#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/size.h"
@@ -58,14 +59,14 @@ class CompositingIOSurfaceMac {
// into |out|. The copied region is specified with |src_pixel_subrect| and
// the data is transformed so that it fits in |dst_pixel_size|.
// |src_pixel_subrect| and |dst_pixel_size| are not in DIP but in pixel.
- // Caller must ensure that |out| is allocated with the size no less than
- // |4 * dst_pixel_size.width() * dst_pixel_size.height()| bytes.
+ // Caller must ensure that |out| is allocated to dimensions that match
+ // dst_pixel_size, with no additional padding.
// |callback| is invoked when the operation is completed or failed.
// Do no call this method again before |callback| is invoked.
void CopyTo(const gfx::Rect& src_pixel_subrect,
const gfx::Size& dst_pixel_size,
- void* out,
- const base::Callback<void(bool)>& callback);
+ const SkBitmap& out,
+ const base::Callback<void(bool, const SkBitmap&)>& callback);
// Unref the IOSurface and delete the associated GL texture. If the GPU
// process is no longer referencing it, this will delete the IOSurface.
@@ -170,7 +171,7 @@ class CompositingIOSurfaceMac {
pixel_buffer = 0;
use_fence = false;
fence = 0;
- out_buf = NULL;
+ out_buf.reset();
callback.Reset();
}
@@ -183,8 +184,8 @@ class CompositingIOSurfaceMac {
GLuint fence;
gfx::Rect src_rect;
gfx::Size dest_size;
- void* out_buf;
- base::Callback<void(bool)> callback;
+ SkBitmap out_buf;
+ base::Callback<void(bool, const SkBitmap&)> callback;
};
CompositingIOSurfaceMac(IOSurfaceSupport* io_surface_support,
@@ -221,11 +222,12 @@ class CompositingIOSurfaceMac {
// Two implementations of CopyTo() in synchronous and asynchronous mode.
bool SynchronousCopyTo(const gfx::Rect& src_pixel_subrect,
const gfx::Size& dst_pixel_size,
- void* out);
- bool AsynchronousCopyTo(const gfx::Rect& src_pixel_subrect,
- const gfx::Size& dst_pixel_size,
- void* out,
- const base::Callback<void(bool)>& callback);
+ const SkBitmap& out);
+ bool AsynchronousCopyTo(
+ const gfx::Rect& src_pixel_subrect,
+ const gfx::Size& dst_pixel_size,
+ const SkBitmap& out,
+ const base::Callback<void(bool, const SkBitmap&)>& callback);
void FinishCopy();
void CleanupResourcesForCopy();
diff --git a/content/browser/renderer_host/compositing_iosurface_mac.mm b/content/browser/renderer_host/compositing_iosurface_mac.mm
index 89deb02..c22fde3 100644
--- a/content/browser/renderer_host/compositing_iosurface_mac.mm
+++ b/content/browser/renderer_host/compositing_iosurface_mac.mm
@@ -301,7 +301,7 @@ CompositingIOSurfaceMac::~CompositingIOSurfaceMac() {
// Make sure we still run the callback if we are being destroyed with an
// active copy_timer_ that has not yet fired.
if (copy_context_.started)
- copy_context_.callback.Run(false);
+ copy_context_.callback.Run(false, SkBitmap());
CVDisplayLinkRelease(display_link_);
CGLSetCurrentContext(cglContext_);
@@ -435,8 +435,8 @@ void CompositingIOSurfaceMac::DrawIOSurface(NSView* view, float scale_factor) {
void CompositingIOSurfaceMac::CopyTo(
const gfx::Rect& src_pixel_subrect,
const gfx::Size& dst_pixel_size,
- void* out,
- const base::Callback<void(bool)>& callback) {
+ const SkBitmap& out,
+ const base::Callback<void(bool, const SkBitmap&)>& callback) {
CGLSetCurrentContext(cglContext_);
// Using PBO crashes on Intel drivers but not on newer Mountain Lion
@@ -457,9 +457,9 @@ void CompositingIOSurfaceMac::CopyTo(
if (async_copy) {
if (!ret)
- callback.Run(false);
+ callback.Run(false, SkBitmap());
} else {
- callback.Run(ret);
+ callback.Run(ret, out);
}
}
@@ -637,7 +637,7 @@ void CompositingIOSurfaceMac::StopDisplayLink() {
bool CompositingIOSurfaceMac::SynchronousCopyTo(
const gfx::Rect& src_pixel_subrect,
const gfx::Size& dst_pixel_size,
- void* out) {
+ const SkBitmap& out) {
if (!MapIOSurfaceToTexture(io_surface_handle_))
return false;
@@ -701,7 +701,7 @@ bool CompositingIOSurfaceMac::SynchronousCopyTo(
CGLFlushDrawable(cglContext_);
glReadPixels(0, 0, dst_pixel_size.width(), dst_pixel_size.height(),
- GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, out);
+ GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, out.getPixels());
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); CHECK_GL_ERROR();
@@ -713,8 +713,8 @@ bool CompositingIOSurfaceMac::SynchronousCopyTo(
bool CompositingIOSurfaceMac::AsynchronousCopyTo(
const gfx::Rect& src_pixel_subrect,
const gfx::Size& dst_pixel_size,
- void* out,
- const base::Callback<void(bool)>& callback) {
+ const SkBitmap& out,
+ const base::Callback<void(bool, const SkBitmap&)>& callback) {
if (copy_context_.started)
return false;
@@ -840,7 +840,6 @@ void CompositingIOSurfaceMac::FinishCopy() {
}
}
copy_timer_.Stop();
-
glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, copy_context_.pixel_buffer);
CHECK_GL_ERROR();
@@ -848,16 +847,18 @@ void CompositingIOSurfaceMac::FinishCopy() {
CHECK_GL_ERROR();
if (buf) {
- memcpy(copy_context_.out_buf, buf, copy_context_.dest_size.GetArea() * 4);
+ SkAutoLockPixels bitmap_lock(copy_context_.out_buf);
+ memcpy(copy_context_.out_buf.getPixels(), buf,
+ copy_context_.dest_size.GetArea() * 4);
glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB); CHECK_GL_ERROR();
}
glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0); CHECK_GL_ERROR();
- base::Callback<void(bool)> callback = copy_context_.callback;
+ base::Callback<void(bool, const SkBitmap&)> callback = copy_context_.callback;
CleanupResourcesForCopy();
CGLSetCurrentContext(0);
- callback.Run(buf != NULL);
+ callback.Run(buf != NULL, copy_context_.out_buf);
}
void CompositingIOSurfaceMac::CleanupResourcesForCopy() {
diff --git a/content/browser/renderer_host/media/web_contents_video_capture_device.cc b/content/browser/renderer_host/media/web_contents_video_capture_device.cc
index 0240f8b..bba926d 100644
--- a/content/browser/renderer_host/media/web_contents_video_capture_device.cc
+++ b/content/browser/renderer_host/media/web_contents_video_capture_device.cc
@@ -66,7 +66,6 @@
#include "media/base/bind_to_loop.h"
#include "media/video/capture/video_capture_types.h"
#include "skia/ext/image_operations.h"
-#include "skia/ext/platform_canvas.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/gfx/rect.h"
@@ -147,7 +146,7 @@ class BackingStoreCopier : public WebContentsObserver {
NO_SOURCE,
};
typedef base::Callback<void(Result result,
- scoped_ptr<skia::PlatformBitmap> capture,
+ const SkBitmap& capture,
const base::Time& capture_time)> DoneCB;
BackingStoreCopier(int render_process_id, int render_view_id);
@@ -178,8 +177,9 @@ class BackingStoreCopier : public WebContentsObserver {
void LookUpAndObserveWebContents();
void CopyFromBackingStoreComplete(int frame_number,
- scoped_ptr<skia::PlatformBitmap> capture,
- const DoneCB& done_cb, bool success);
+ const DoneCB& done_cb,
+ bool success,
+ const SkBitmap& result);
// The "starting point" to find the capture source.
const int render_process_id_;
@@ -211,7 +211,7 @@ class VideoFrameRenderer {
// invoke |done_cb| with a pointer to the result. The caller must guarantee
// Release() will be called after the result is no longer needed.
void Render(int frame_number,
- scoped_ptr<skia::PlatformBitmap> capture,
+ const SkBitmap& capture,
int frame_width, int frame_height,
const DoneCB& done_cb);
@@ -220,7 +220,7 @@ class VideoFrameRenderer {
private:
void RenderOnRenderThread(int frame_number,
- scoped_ptr<skia::PlatformBitmap> capture,
+ const SkBitmap& capture,
int frame_width, int frame_height,
const DoneCB& done_cb);
@@ -338,8 +338,7 @@ void BackingStoreCopier::StartCopy(int frame_number,
if (!web_contents()) { // No source yet.
LookUpAndObserveWebContents();
if (!web_contents()) { // No source ever.
- done_cb.Run(NO_SOURCE,
- scoped_ptr<skia::PlatformBitmap>(NULL), base::Time());
+ done_cb.Run(NO_SOURCE, SkBitmap(), base::Time());
return;
}
}
@@ -354,8 +353,7 @@ void BackingStoreCopier::StartCopy(int frame_number,
if (!rwh) {
// Transient failure state (e.g., a RenderView is being replaced).
- done_cb.Run(TRANSIENT_ERROR,
- scoped_ptr<skia::PlatformBitmap>(NULL), base::Time());
+ done_cb.Run(TRANSIENT_ERROR, SkBitmap(), base::Time());
return;
}
}
@@ -378,40 +376,32 @@ void BackingStoreCopier::StartCopy(int frame_number,
}
}
- // TODO(miu): Look into tweaking the interface to CopyFromBackingStore, since
- // it seems poor to have to allocate a new skia::PlatformBitmap as an output
- // buffer for each successive frame (rather than reuse buffers). Perhaps
- // PlatformBitmap itself should only re-Allocate when necessary?
- skia::PlatformBitmap* const bitmap = new skia::PlatformBitmap();
- scoped_ptr<skia::PlatformBitmap> capture(bitmap);
rwh->CopyFromBackingStore(
gfx::Rect(),
fitted_size,
base::Bind(&BackingStoreCopier::CopyFromBackingStoreComplete,
base::Unretained(this),
- frame_number, base::Passed(&capture), done_cb),
- bitmap);
+ frame_number, done_cb));
// TODO(miu): When a tab is not visible to the user, rendering stops. For
// mirroring, however, it's important that rendering continues to happen.
}
void BackingStoreCopier::CopyFromBackingStoreComplete(
- int frame_number, scoped_ptr<skia::PlatformBitmap> capture,
- const DoneCB& done_cb, bool success) {
+ int frame_number,
+ const DoneCB& done_cb,
+ bool success,
+ const SkBitmap& frame) {
// Note: No restriction on which thread invokes this method but, currently,
// it's always the UI BrowserThread.
-
TRACE_EVENT_ASYNC_END1("mirroring", "Capture", this,
"frame_number", frame_number);
-
if (success) {
- done_cb.Run(OK, capture.Pass(), base::Time::Now());
+ done_cb.Run(OK, frame, base::Time::Now());
} else {
// Capture can fail due to transient issues, so just skip this frame.
DVLOG(1) << "CopyFromBackingStore was not successful; skipping frame.";
- done_cb.Run(TRANSIENT_ERROR,
- scoped_ptr<skia::PlatformBitmap>(NULL), base::Time());
+ done_cb.Run(TRANSIENT_ERROR, SkBitmap(), base::Time());
}
}
@@ -423,27 +413,26 @@ VideoFrameRenderer::VideoFrameRenderer()
}
void VideoFrameRenderer::Render(int frame_number,
- scoped_ptr<skia::PlatformBitmap> capture,
+ const SkBitmap& capture,
int frame_width, int frame_height,
const DoneCB& done_cb) {
render_thread_.message_loop()->PostTask(
FROM_HERE,
base::Bind(&VideoFrameRenderer::RenderOnRenderThread,
base::Unretained(this),
- frame_number, base::Passed(&capture),
+ frame_number, capture,
frame_width, frame_height, done_cb));
}
void VideoFrameRenderer::RenderOnRenderThread(
int frame_number,
- scoped_ptr<skia::PlatformBitmap> capture,
+ const SkBitmap& captured_bitmap,
int frame_width, int frame_height,
const DoneCB& done_cb) {
DCHECK_EQ(render_thread_.message_loop(), MessageLoop::current());
TRACE_EVENT1("mirroring", "RenderFrame", "frame_number", frame_number);
- const SkBitmap& captured_bitmap = capture->GetBitmap();
gfx::Size fitted_size;
{
SkAutoLockPixels locker(captured_bitmap);
@@ -714,7 +703,7 @@ class CaptureMachine
void SnapshotComplete(int frame_number,
const base::Time& start_time,
BackingStoreCopier::Result result,
- scoped_ptr<skia::PlatformBitmap> capture,
+ const SkBitmap& capture,
const base::Time& capture_time);
void RenderComplete(int frame_number,
const base::Time& capture_time,
@@ -964,7 +953,7 @@ void CaptureMachine::StartSnapshot() {
void CaptureMachine::SnapshotComplete(int frame_number,
const base::Time& start_time,
BackingStoreCopier::Result result,
- scoped_ptr<skia::PlatformBitmap> capture,
+ const SkBitmap& capture,
const base::Time& capture_time) {
DCHECK_EQ(manager_thread_.message_loop(), MessageLoop::current());
@@ -981,11 +970,10 @@ void CaptureMachine::SnapshotComplete(int frame_number,
base::Time::Now() - start_time);
if (num_renders_pending_ <= 1) {
++num_renders_pending_;
- DCHECK(capture);
DCHECK(!capture_time.is_null());
renderer_.Render(
frame_number,
- capture.Pass(),
+ capture,
settings_.width, settings_.height,
media::BindToLoop(manager_thread_.message_loop_proxy(),
base::Bind(&CaptureMachine::RenderComplete, this,
diff --git a/content/browser/renderer_host/media/web_contents_video_capture_device_unittest.cc b/content/browser/renderer_host/media/web_contents_video_capture_device_unittest.cc
index f86efc5..53b2d2f 100644
--- a/content/browser/renderer_host/media/web_contents_video_capture_device_unittest.cc
+++ b/content/browser/renderer_host/media/web_contents_video_capture_device_unittest.cc
@@ -44,18 +44,18 @@ class StubRenderWidgetHost : public RenderWidgetHostImpl {
virtual void CopyFromBackingStore(
const gfx::Rect& src_rect,
const gfx::Size& accelerated_dst_size,
- const base::Callback<void(bool)>& callback,
- skia::PlatformBitmap* output) OVERRIDE {
- DCHECK(output);
- EXPECT_TRUE(output->Allocate(kTestWidth, kTestHeight, true));
- SkBitmap bitmap = output->GetBitmap();
+ const base::Callback<void(bool, const SkBitmap&)>& callback) OVERRIDE {
+ // Although it's not necessary, use a PlatformBitmap here (instead of a
+ // regular SkBitmap) to exercise possible threading issues.
+ scoped_ptr<skia::PlatformBitmap> platform_bitmap(new skia::PlatformBitmap);
+ EXPECT_TRUE(platform_bitmap->Allocate(kTestWidth, kTestHeight, false));
{
- SkAutoLockPixels locker(bitmap);
+ SkAutoLockPixels locker(platform_bitmap->GetBitmap());
base::AutoLock guard(lock_);
- bitmap.eraseColor(color_);
+ platform_bitmap->GetBitmap().eraseColor(color_);
}
- callback.Run(true);
+ callback.Run(true, platform_bitmap->GetBitmap());
}
private:
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index 5ad3ad4..028aa9b 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -572,8 +572,7 @@ void RenderWidgetHostImpl::SetIsLoading(bool is_loading) {
void RenderWidgetHostImpl::CopyFromBackingStore(
const gfx::Rect& src_subrect,
const gfx::Size& accelerated_dst_size,
- const base::Callback<void(bool)>& callback,
- skia::PlatformBitmap* output) {
+ const base::Callback<void(bool, const SkBitmap&)>& callback) {
if (view_ && is_accelerated_compositing_active_) {
TRACE_EVENT0("browser",
"RenderWidgetHostImpl::CopyFromBackingStore::FromCompositingSurface");
@@ -581,14 +580,13 @@ void RenderWidgetHostImpl::CopyFromBackingStore(
gfx::Rect(view_->GetViewBounds().size()) : src_subrect;
view_->CopyFromCompositingSurface(copy_rect,
accelerated_dst_size,
- callback,
- output);
+ callback);
return;
}
BackingStore* backing_store = GetBackingStore(false);
if (!backing_store) {
- callback.Run(false);
+ callback.Run(false, SkBitmap());
return;
}
@@ -598,8 +596,9 @@ void RenderWidgetHostImpl::CopyFromBackingStore(
gfx::Rect(backing_store->size()) : src_subrect;
// When the result size is equal to the backing store size, copy from the
// backing store directly to the output canvas.
- bool result = backing_store->CopyFromBackingStore(copy_rect, output);
- callback.Run(result);
+ skia::PlatformBitmap output;
+ bool result = backing_store->CopyFromBackingStore(copy_rect, &output);
+ callback.Run(result, output.GetBitmap());
}
#if defined(TOOLKIT_GTK)
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h
index 8c05b49..bd228ac 100644
--- a/content/browser/renderer_host/render_widget_host_impl.h
+++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -109,8 +109,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
virtual void CopyFromBackingStore(
const gfx::Rect& src_rect,
const gfx::Size& accelerated_dst_size,
- const base::Callback<void(bool)>& callback,
- skia::PlatformBitmap* output) OVERRIDE;
+ const base::Callback<void(bool, const SkBitmap&)>& callback) OVERRIDE;
#if defined(TOOLKIT_GTK)
virtual bool CopyFromBackingStoreToGtkWindow(const gfx::Rect& dest_rect,
GdkWindow* target) OVERRIDE;
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc
index b6c54b2..3bdc775 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.cc
+++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -380,10 +380,9 @@ void RenderWidgetHostViewAndroid::SetBackground(const SkBitmap& background) {
void RenderWidgetHostViewAndroid::CopyFromCompositingSurface(
const gfx::Rect& src_subrect,
const gfx::Size& dst_size,
- const base::Callback<void(bool)>& callback,
- skia::PlatformBitmap* output) {
+ const base::Callback<void(bool, const SkBitmap&)>& callback) {
NOTIMPLEMENTED();
- callback.Run(false);
+ callback.Run(false, SkBitmap());
}
void RenderWidgetHostViewAndroid::ShowDisambiguationPopup(
diff --git a/content/browser/renderer_host/render_widget_host_view_android.h b/content/browser/renderer_host/render_widget_host_view_android.h
index 5ff8298..8c35d917 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.h
+++ b/content/browser/renderer_host/render_widget_host_view_android.h
@@ -110,8 +110,7 @@ class RenderWidgetHostViewAndroid : public RenderWidgetHostViewBase {
virtual void CopyFromCompositingSurface(
const gfx::Rect& src_subrect,
const gfx::Size& dst_size,
- const base::Callback<void(bool)>& callback,
- skia::PlatformBitmap* output) OVERRIDE;
+ const base::Callback<void(bool, const SkBitmap&)>& callback) OVERRIDE;
virtual BackingStore* AllocBackingStore(const gfx::Size& size) OVERRIDE;
virtual gfx::GLSurfaceHandle GetCompositingSurface() OVERRIDE;
virtual void GetScreenInfo(WebKit::WebScreenInfo* results) OVERRIDE;
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc
index 914b155..7abf0ef 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -711,31 +711,35 @@ BackingStore* RenderWidgetHostViewAura::AllocBackingStore(
void RenderWidgetHostViewAura::CopyFromCompositingSurface(
const gfx::Rect& src_subrect,
const gfx::Size& dst_size,
- const base::Callback<void(bool)>& callback,
- skia::PlatformBitmap* output) {
- base::ScopedClosureRunner scoped_callback_runner(base::Bind(callback, false));
+ const base::Callback<void(bool, const SkBitmap&)>& callback) {
+ base::ScopedClosureRunner scoped_callback_runner(
+ base::Bind(callback, false, SkBitmap()));
if (!current_surface_)
return;
gfx::Size dst_size_in_pixel = ConvertSizeToPixel(this, dst_size);
- if (!output->Allocate(
- dst_size_in_pixel.width(), dst_size_in_pixel.height(), true))
+
+ SkBitmap output;
+ output.setConfig(SkBitmap::kARGB_8888_Config,
+ dst_size_in_pixel.width(), dst_size_in_pixel.height());
+ if (!output.allocPixels())
return;
+ output.setIsOpaque(true);
ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
GLHelper* gl_helper = factory->GetGLHelper();
if (!gl_helper)
return;
- unsigned char* addr = static_cast<unsigned char*>(
- output->GetBitmap().getPixels());
+ unsigned char* addr = static_cast<unsigned char*>(output.getPixels());
scoped_callback_runner.Release();
// Wrap the callback with an internal handler so that we can inject our
// own completion handlers (where we can try to free the frontbuffer).
base::Callback<void(bool)> wrapper_callback = base::Bind(
&RenderWidgetHostViewAura::CopyFromCompositingSurfaceFinished,
AsWeakPtr(),
+ output,
callback);
++pending_thumbnail_tasks_;
@@ -1012,9 +1016,10 @@ void RenderWidgetHostViewAura::SetSurfaceNotInUseByCompositor(
void RenderWidgetHostViewAura::CopyFromCompositingSurfaceFinished(
base::WeakPtr<RenderWidgetHostViewAura> render_widget_host_view,
- const base::Callback<void(bool)>& callback,
+ const SkBitmap& bitmap,
+ const base::Callback<void(bool, const SkBitmap&)>& callback,
bool result) {
- callback.Run(result);
+ callback.Run(result, bitmap);
if (!render_widget_host_view.get())
return;
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h
index e2f27a9..f47e110 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.h
+++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -146,8 +146,7 @@ class RenderWidgetHostViewAura
virtual void CopyFromCompositingSurface(
const gfx::Rect& src_subrect,
const gfx::Size& dst_size,
- const base::Callback<void(bool)>& callback,
- skia::PlatformBitmap* output) OVERRIDE;
+ const base::Callback<void(bool, const SkBitmap&)>& callback) OVERRIDE;
virtual void OnAcceleratedCompositingStateChange() OVERRIDE;
virtual void AcceleratedSurfaceBuffersSwapped(
const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params_in_pixel,
@@ -325,7 +324,8 @@ class RenderWidgetHostViewAura
// AdjustSurfaceProtection.
static void CopyFromCompositingSurfaceFinished(
base::WeakPtr<RenderWidgetHostViewAura> render_widget_host_view,
- const base::Callback<void(bool)>& callback,
+ const SkBitmap& bitmap,
+ const base::Callback<void(bool, const SkBitmap&)>& callback,
bool result);
ui::Compositor* GetCompositor();
diff --git a/content/browser/renderer_host/render_widget_host_view_browsertest.cc b/content/browser/renderer_host/render_widget_host_view_browsertest.cc
index 0a32b98..066ba35 100644
--- a/content/browser/renderer_host/render_widget_host_view_browsertest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_browsertest.cc
@@ -33,7 +33,8 @@ class RenderWidgetHostViewBrowserTest : public ContentBrowserTest {
ui::DisableTestCompositor();
}
- void FinishCopyFromBackingStore(bool expected_result, bool result) {
+ void FinishCopyFromBackingStore(bool expected_result, bool result,
+ const SkBitmap& bitmap) {
ASSERT_EQ(expected_result, result);
finish_called_ = true;
}
@@ -73,13 +74,11 @@ IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewBrowserTest,
ASSERT_LT(increment, 50);
}
- skia::PlatformBitmap bitmap;
rwh->CopyFromBackingStore(
gfx::Rect(),
size,
base::Bind(&RenderWidgetHostViewBrowserTest::FinishCopyFromBackingStore,
- base::Unretained(this), false),
- &bitmap);
+ base::Unretained(this), false));
// Delete the surface before the callback is run. This is synchronous until
// we get to the copy_timer_, so we will always end up in the destructor
diff --git a/content/browser/renderer_host/render_widget_host_view_gtk.cc b/content/browser/renderer_host/render_widget_host_view_gtk.cc
index 04396df..132f8b8 100644
--- a/content/browser/renderer_host/render_widget_host_view_gtk.cc
+++ b/content/browser/renderer_host/render_widget_host_view_gtk.cc
@@ -1020,9 +1020,9 @@ BackingStore* RenderWidgetHostViewGtk::AllocBackingStore(
void RenderWidgetHostViewGtk::CopyFromCompositingSurface(
const gfx::Rect& src_subrect,
const gfx::Size& /* dst_size */,
- const base::Callback<void(bool)>& callback,
- skia::PlatformBitmap* output) {
- base::ScopedClosureRunner scoped_callback_runner(base::Bind(callback, false));
+ const base::Callback<void(bool, const SkBitmap&)>& callback) {
+ base::ScopedClosureRunner scoped_callback_runner(
+ base::Bind(callback, false, SkBitmap()));
gfx::Rect src_subrect_in_view = src_subrect;
src_subrect_in_view.Offset(GetViewBounds().OffsetFromOrigin());
@@ -1036,10 +1036,15 @@ void RenderWidgetHostViewGtk::CopyFromCompositingSurface(
if (!image.get())
return;
- if (!output->Allocate(src_subrect.width(), src_subrect.height(), true))
+ SkBitmap bitmap;
+ bitmap.setConfig(SkBitmap::kARGB_8888_Config,
+ image->width,
+ image->height,
+ image->bytes_per_line);
+ if (!bitmap.allocPixels())
return;
+ bitmap.setIsOpaque(true);
- const SkBitmap& bitmap = output->GetBitmap();
const size_t bitmap_size = bitmap.getSize();
DCHECK_EQ(bitmap_size,
static_cast<size_t>(image->height * image->bytes_per_line));
@@ -1047,7 +1052,7 @@ void RenderWidgetHostViewGtk::CopyFromCompositingSurface(
memcpy(pixels, image->data, bitmap_size);
scoped_callback_runner.Release();
- callback.Run(true);
+ callback.Run(true, bitmap);
}
void RenderWidgetHostViewGtk::AcceleratedSurfaceBuffersSwapped(
diff --git a/content/browser/renderer_host/render_widget_host_view_gtk.h b/content/browser/renderer_host/render_widget_host_view_gtk.h
index 4b5acf0..7eaa107 100644
--- a/content/browser/renderer_host/render_widget_host_view_gtk.h
+++ b/content/browser/renderer_host/render_widget_host_view_gtk.h
@@ -103,8 +103,7 @@ class CONTENT_EXPORT RenderWidgetHostViewGtk
virtual void CopyFromCompositingSurface(
const gfx::Rect& src_subrect,
const gfx::Size& dst_size,
- const base::Callback<void(bool)>& callback,
- skia::PlatformBitmap* output) OVERRIDE;
+ const base::Callback<void(bool, const SkBitmap&)>& callback) OVERRIDE;
virtual void OnAcceleratedCompositingStateChange() OVERRIDE;
virtual void AcceleratedSurfaceBuffersSwapped(
const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params,
diff --git a/content/browser/renderer_host/render_widget_host_view_guest.cc b/content/browser/renderer_host/render_widget_host_view_guest.cc
index 8f0cd12..0039df7 100644
--- a/content/browser/renderer_host/render_widget_host_view_guest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_guest.cc
@@ -208,8 +208,8 @@ BackingStore* RenderWidgetHostViewGuest::AllocBackingStore(
void RenderWidgetHostViewGuest::CopyFromCompositingSurface(
const gfx::Rect& src_subrect,
const gfx::Size& /* dst_size */,
- const base::Callback<void(bool)>& callback,
- skia::PlatformBitmap* output) {
+ const base::Callback<void(bool, const SkBitmap&)>& callback) {
+ callback.Run(false, SkBitmap());
}
void RenderWidgetHostViewGuest::AcceleratedSurfaceSuspend() {
diff --git a/content/browser/renderer_host/render_widget_host_view_guest.h b/content/browser/renderer_host/render_widget_host_view_guest.h
index f705b78..c84a2ae 100644
--- a/content/browser/renderer_host/render_widget_host_view_guest.h
+++ b/content/browser/renderer_host/render_widget_host_view_guest.h
@@ -91,8 +91,7 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest
virtual void CopyFromCompositingSurface(
const gfx::Rect& src_subrect,
const gfx::Size& dst_size,
- const base::Callback<void(bool)>& callback,
- skia::PlatformBitmap* output) OVERRIDE;
+ const base::Callback<void(bool, const SkBitmap&)>& callback) OVERRIDE;
virtual void OnAcceleratedCompositingStateChange() OVERRIDE;
virtual void AcceleratedSurfaceBuffersSwapped(
const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params,
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.h b/content/browser/renderer_host/render_widget_host_view_mac.h
index 894673b..88200bd 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.h
+++ b/content/browser/renderer_host/render_widget_host_view_mac.h
@@ -267,8 +267,7 @@ class RenderWidgetHostViewMac : public RenderWidgetHostViewBase {
virtual void CopyFromCompositingSurface(
const gfx::Rect& src_subrect,
const gfx::Size& dst_size,
- const base::Callback<void(bool)>& callback,
- skia::PlatformBitmap* output) OVERRIDE;
+ const base::Callback<void(bool, const SkBitmap&)>& callback) OVERRIDE;
virtual void OnAcceleratedCompositingStateChange() OVERRIDE;
virtual void OnAccessibilityNotifications(
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm
index dff78cb..7d35517 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -935,9 +935,9 @@ BackingStore* RenderWidgetHostViewMac::AllocBackingStore(
void RenderWidgetHostViewMac::CopyFromCompositingSurface(
const gfx::Rect& src_subrect,
const gfx::Size& dst_size,
- const base::Callback<void(bool)>& callback,
- skia::PlatformBitmap* output) {
- base::ScopedClosureRunner scoped_callback_runner(base::Bind(callback, false));
+ const base::Callback<void(bool, const SkBitmap&)>& callback) {
+ base::ScopedClosureRunner scoped_callback_runner(
+ base::Bind(callback, false, SkBitmap()));
if (!compositing_iosurface_.get() ||
!compositing_iosurface_->HasIOSurface())
return;
@@ -945,9 +945,14 @@ void RenderWidgetHostViewMac::CopyFromCompositingSurface(
float scale = ScaleFactor(cocoa_view_);
gfx::Size dst_pixel_size = gfx::ToFlooredSize(
gfx::ScaleSize(dst_size, scale));
- if (!output->Allocate(
- dst_pixel_size.width(), dst_pixel_size.height(), true))
+
+ SkBitmap output;
+ output.setConfig(SkBitmap::kARGB_8888_Config,
+ dst_pixel_size.width(), dst_pixel_size.height());
+ if (!output.allocPixels())
return;
+ output.setIsOpaque(true);
+
scoped_callback_runner.Release();
// Convert |src_subrect| from the views coordinate (upper-left origin) into
@@ -960,7 +965,7 @@ void RenderWidgetHostViewMac::CopyFromCompositingSurface(
compositing_iosurface_->CopyTo(
src_pixel_gl_subrect,
dst_pixel_size,
- output->GetBitmap().getPixels(),
+ output,
callback);
}
diff --git a/content/browser/renderer_host/render_widget_host_view_win.cc b/content/browser/renderer_host/render_widget_host_view_win.cc
index cc7b84b..0e3e081 100644
--- a/content/browser/renderer_host/render_widget_host_view_win.cc
+++ b/content/browser/renderer_host/render_widget_host_view_win.cc
@@ -816,23 +816,19 @@ BackingStore* RenderWidgetHostViewWin::AllocBackingStore(
void RenderWidgetHostViewWin::CopyFromCompositingSurface(
const gfx::Rect& src_subrect,
const gfx::Size& dst_size,
- const base::Callback<void(bool)>& callback,
- skia::PlatformBitmap* output) {
- base::ScopedClosureRunner scoped_callback_runner(base::Bind(callback, false));
+ const base::Callback<void(bool, const SkBitmap&)>& callback) {
+ base::ScopedClosureRunner scoped_callback_runner(
+ base::Bind(callback, false, SkBitmap()));
if (!accelerated_surface_.get())
return;
if (dst_size.IsEmpty())
return;
- if (!output->Allocate(dst_size.width(), dst_size.height(), true))
- return;
-
scoped_callback_runner.Release();
accelerated_surface_->AsyncCopyTo(
src_subrect,
dst_size,
- output->GetBitmap().getPixels(),
callback);
}
diff --git a/content/browser/renderer_host/render_widget_host_view_win.h b/content/browser/renderer_host/render_widget_host_view_win.h
index d70f355..357b845 100644
--- a/content/browser/renderer_host/render_widget_host_view_win.h
+++ b/content/browser/renderer_host/render_widget_host_view_win.h
@@ -205,8 +205,7 @@ class RenderWidgetHostViewWin
virtual void CopyFromCompositingSurface(
const gfx::Rect& src_subrect,
const gfx::Size& dst_size,
- const base::Callback<void(bool)>& callback,
- skia::PlatformBitmap* output) OVERRIDE;
+ const base::Callback<void(bool, const SkBitmap&)>& callback) OVERRIDE;
virtual void OnAcceleratedCompositingStateChange() OVERRIDE;
virtual void ProcessAckedTouchEvent(const WebKit::WebTouchEvent& touch,
InputEventAckState ack_result) OVERRIDE;
diff --git a/content/browser/renderer_host/test_render_view_host.cc b/content/browser/renderer_host/test_render_view_host.cc
index 6bea59f..3b34061 100644
--- a/content/browser/renderer_host/test_render_view_host.cc
+++ b/content/browser/renderer_host/test_render_view_host.cc
@@ -118,9 +118,8 @@ BackingStore* TestRenderWidgetHostView::AllocBackingStore(
void TestRenderWidgetHostView::CopyFromCompositingSurface(
const gfx::Rect& src_subrect,
const gfx::Size& dst_size,
- const base::Callback<void(bool)>& callback,
- skia::PlatformBitmap* output) {
- callback.Run(false);
+ const base::Callback<void(bool, const SkBitmap&)>& callback) {
+ callback.Run(false, SkBitmap());
}
void TestRenderWidgetHostView::OnAcceleratedCompositingStateChange() {
diff --git a/content/browser/renderer_host/test_render_view_host.h b/content/browser/renderer_host/test_render_view_host.h
index ceab8e5..f5b9632 100644
--- a/content/browser/renderer_host/test_render_view_host.h
+++ b/content/browser/renderer_host/test_render_view_host.h
@@ -111,8 +111,7 @@ class TestRenderWidgetHostView : public RenderWidgetHostViewBase {
virtual void CopyFromCompositingSurface(
const gfx::Rect& src_subrect,
const gfx::Size& dst_size,
- const base::Callback<void(bool)>& callback,
- skia::PlatformBitmap* output) OVERRIDE;
+ const base::Callback<void(bool, const SkBitmap&)>& callback) OVERRIDE;
virtual void OnAcceleratedCompositingStateChange() OVERRIDE;
virtual void AcceleratedSurfaceBuffersSwapped(
const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params,
diff --git a/content/browser/web_contents/navigation_controller_impl.cc b/content/browser/web_contents/navigation_controller_impl.cc
index a4ec35f..3d74699 100644
--- a/content/browser/web_contents/navigation_controller_impl.cc
+++ b/content/browser/web_contents/navigation_controller_impl.cc
@@ -501,20 +501,17 @@ void NavigationControllerImpl::TakeScreenshot() {
if (!take_screenshot_callback_.is_null())
take_screenshot_callback_.Run(render_view_host);
- skia::PlatformBitmap* temp_bitmap = new skia::PlatformBitmap;
render_view_host->CopyFromBackingStore(gfx::Rect(),
view->GetViewBounds().size(),
base::Bind(&NavigationControllerImpl::OnScreenshotTaken,
base::Unretained(this),
- entry->GetUniqueID(),
- base::Owned(temp_bitmap)),
- temp_bitmap);
+ entry->GetUniqueID()));
}
void NavigationControllerImpl::OnScreenshotTaken(
int unique_id,
- skia::PlatformBitmap* bitmap,
- bool success) {
+ bool success,
+ const SkBitmap& bitmap) {
NavigationEntryImpl* entry = NULL;
for (NavigationEntries::iterator i = entries_.begin();
i != entries_.end();
@@ -536,7 +533,7 @@ void NavigationControllerImpl::OnScreenshotTaken(
}
std::vector<unsigned char> data;
- if (gfx::PNGCodec::EncodeBGRASkBitmap(bitmap->GetBitmap(), true, &data)) {
+ if (gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, true, &data)) {
if (!entry->screenshot())
++screenshot_count_;
entry->SetScreenshotPNGData(data);
diff --git a/content/browser/web_contents/navigation_controller_impl.h b/content/browser/web_contents/navigation_controller_impl.h
index 6661120..4b86829 100644
--- a/content/browser/web_contents/navigation_controller_impl.h
+++ b/content/browser/web_contents/navigation_controller_impl.h
@@ -15,12 +15,9 @@
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_type.h"
+class SkBitmap;
struct ViewHostMsg_FrameNavigate_Params;
-namespace skia {
-class PlatformBitmap;
-}
-
namespace content {
class NavigationEntryImpl;
class RenderViewHost;
@@ -325,8 +322,8 @@ class CONTENT_EXPORT NavigationControllerImpl
// The callback invoked when taking the screenshot of the page is complete.
// This sets the screenshot on the navigation entry.
void OnScreenshotTaken(int unique_id,
- skia::PlatformBitmap* bitmap,
- bool success);
+ bool success,
+ const SkBitmap& bitmap);
// Removes the screenshot for the entry (and updates the count as
// appropriate).
diff --git a/content/browser/web_contents/navigation_controller_impl_unittest.cc b/content/browser/web_contents/navigation_controller_impl_unittest.cc
index 2a4592b..8e527a7 100644
--- a/content/browser/web_contents/navigation_controller_impl_unittest.cc
+++ b/content/browser/web_contents/navigation_controller_impl_unittest.cc
@@ -3030,8 +3030,10 @@ TEST_F(NavigationControllerTest, MAYBE_PurgeScreenshot) {
NavigationControllerImpl& controller = controller_impl();
// Prepare some data to use as screenshot for each navigation.
- skia::PlatformBitmap bitmap;
- ASSERT_TRUE(bitmap.Allocate(1, 1, false));
+ SkBitmap bitmap;
+ bitmap.setConfig(SkBitmap::kARGB_8888_Config, 1, 1);
+ ASSERT_TRUE(bitmap.allocPixels());
+ bitmap.setIsOpaque(false);
NavigationEntryImpl* entry;
// Navigate enough times to make sure that some screenshots are purged.
@@ -3044,7 +3046,7 @@ TEST_F(NavigationControllerTest, MAYBE_PurgeScreenshot) {
for (int i = 0; i < controller.GetEntryCount(); ++i) {
entry = NavigationEntryImpl::FromNavigationEntry(
controller.GetEntryAtIndex(i));
- controller.OnScreenshotTaken(entry->GetUniqueID(), &bitmap, true);
+ controller.OnScreenshotTaken(entry->GetUniqueID(), true, bitmap);
EXPECT_TRUE(entry->screenshot());
}
@@ -3052,7 +3054,7 @@ TEST_F(NavigationControllerTest, MAYBE_PurgeScreenshot) {
EXPECT_EQ(13, controller.GetEntryCount());
entry = NavigationEntryImpl::FromNavigationEntry(
controller.GetEntryAtIndex(11));
- controller.OnScreenshotTaken(entry->GetUniqueID(), &bitmap, true);
+ controller.OnScreenshotTaken(entry->GetUniqueID(), true, bitmap);
for (int i = 0; i < 2; ++i) {
entry = NavigationEntryImpl::FromNavigationEntry(
@@ -3073,14 +3075,14 @@ TEST_F(NavigationControllerTest, MAYBE_PurgeScreenshot) {
for (int i = 0; i < controller.GetEntryCount() - 1; ++i) {
entry = NavigationEntryImpl::FromNavigationEntry(
controller.GetEntryAtIndex(i));
- controller.OnScreenshotTaken(entry->GetUniqueID(), &bitmap, true);
+ controller.OnScreenshotTaken(entry->GetUniqueID(), true, bitmap);
}
for (int i = 10; i <= 12; ++i) {
entry = NavigationEntryImpl::FromNavigationEntry(
controller.GetEntryAtIndex(i));
EXPECT_FALSE(entry->screenshot()) << "Screenshot " << i << " not purged";
- controller.OnScreenshotTaken(entry->GetUniqueID(), &bitmap, true);
+ controller.OnScreenshotTaken(entry->GetUniqueID(), true, bitmap);
}
// Navigate to index 7 and assign screenshot to all entries.
@@ -3090,7 +3092,7 @@ TEST_F(NavigationControllerTest, MAYBE_PurgeScreenshot) {
for (int i = 0; i < controller.GetEntryCount() - 1; ++i) {
entry = NavigationEntryImpl::FromNavigationEntry(
controller.GetEntryAtIndex(i));
- controller.OnScreenshotTaken(entry->GetUniqueID(), &bitmap, true);
+ controller.OnScreenshotTaken(entry->GetUniqueID(), true, bitmap);
}
for (int i = 0; i < 2; ++i) {
diff --git a/content/port/browser/render_widget_host_view_port.h b/content/port/browser/render_widget_host_view_port.h
index 70d6b7d..953296c 100644
--- a/content/port/browser/render_widget_host_view_port.h
+++ b/content/port/browser/render_widget_host_view_port.h
@@ -17,6 +17,7 @@
#include "ui/base/range/range.h"
#include "ui/surface/transport_dib.h"
+class SkBitmap;
class WebCursor;
struct AccessibilityHostMsg_NotificationParams;
@@ -34,10 +35,6 @@ namespace WebKit {
struct WebScreenInfo;
}
-namespace skia {
-class PlatformBitmap;
-};
-
namespace content {
class BackingStore;
class SmoothScrollGesture;
@@ -164,8 +161,7 @@ class CONTENT_EXPORT RenderWidgetHostViewPort : public RenderWidgetHostView {
virtual void CopyFromCompositingSurface(
const gfx::Rect& src_subrect,
const gfx::Size& dst_size,
- const base::Callback<void(bool)>& callback,
- skia::PlatformBitmap* output) = 0;
+ const base::Callback<void(bool, const SkBitmap&)>& callback) = 0;
// Called when accelerated compositing state changes.
virtual void OnAcceleratedCompositingStateChange() = 0;
diff --git a/content/public/browser/render_widget_host.h b/content/public/browser/render_widget_host.h
index 033b91c..a0e8d8a 100644
--- a/content/public/browser/render_widget_host.h
+++ b/content/public/browser/render_widget_host.h
@@ -22,14 +22,12 @@
#include "skia/ext/platform_device.h"
#endif
+class SkBitmap;
+
namespace gfx {
class Rect;
}
-namespace skia {
-class PlatformBitmap;
-}
-
namespace content {
class RenderProcessHost;
@@ -170,22 +168,24 @@ class CONTENT_EXPORT RenderWidgetHost : public IPC::Sender {
// contents, but e.g. in the omnibox.
virtual void SetActive(bool active) = 0;
- // Copies the given subset of the backing store into the given (uninitialized)
- // PlatformCanvas. If |src_rect| is empty, the whole contents is copied.
- // If non empty |accelerated_dest_size| is given and accelerated compositing
- // is active, the content is shrinked so that it fits in
- // |accelerated_dest_size|. If |accelerated_dest_size| is larger than the
- // contens size, the content is not resized. If |accelerated_dest_size| is
- // empty, the size copied from the source contents is used.
- // |callback| is invoked with true on success, false otherwise. |output| can
- // be initialized even on failure.
+ // Copies the given subset of the backing store, and passes the result as a
+ // bitmap to a callback.
+ //
+ // If |src_rect| is empty, the whole contents is copied. If non empty
+ // |accelerated_dst_size| is given and accelerated compositing is active, the
+ // content is shrunk so that it fits in |accelerated_dst_size|. If
+ // |accelerated_dst_size| is larger than the content size, the content is not
+ // resized. If |accelerated_dst_size| is empty, the size copied from the
+ // source contents is used. |callback| is invoked with true on success, false
+ // otherwise, along with a SkBitmap containing the copied pixel data.
+ //
// NOTE: |callback| is called synchronously if the backing store is available.
- // When accelerated compositing is active, it is called asynchronously on Aura
- // and synchronously on the other platforms.
- virtual void CopyFromBackingStore(const gfx::Rect& src_rect,
- const gfx::Size& accelerated_dest_size,
- const base::Callback<void(bool)>& callback,
- skia::PlatformBitmap* output) = 0;
+ // When accelerated compositing is active, |callback| may be called
+ // asynchronously.
+ virtual void CopyFromBackingStore(
+ const gfx::Rect& src_rect,
+ const gfx::Size& accelerated_dst_size,
+ const base::Callback<void(bool, const SkBitmap&)>& callback) = 0;
#if defined(TOOLKIT_GTK)
// Paint the backing store into the target's |dest_rect|.
virtual bool CopyFromBackingStoreToGtkWindow(const gfx::Rect& dest_rect,
diff --git a/skia/ext/bitmap_platform_device_android.cc b/skia/ext/bitmap_platform_device_android.cc
index 3a043a8..8a29586 100644
--- a/skia/ext/bitmap_platform_device_android.cc
+++ b/skia/ext/bitmap_platform_device_android.cc
@@ -82,8 +82,9 @@ SkCanvas* CreatePlatformCanvas(int width, int height, bool is_opaque,
}
// Port of PlatformBitmap to android
-
-PlatformBitmap::~PlatformBitmap() {}
+PlatformBitmap::~PlatformBitmap() {
+ // Nothing to do.
+}
bool PlatformBitmap::Allocate(int width, int height, bool is_opaque) {
bitmap_.setConfig(SkBitmap::kARGB_8888_Config, width, height);
diff --git a/skia/ext/bitmap_platform_device_linux.cc b/skia/ext/bitmap_platform_device_linux.cc
index a35ba77..c9a0214 100644
--- a/skia/ext/bitmap_platform_device_linux.cc
+++ b/skia/ext/bitmap_platform_device_linux.cc
@@ -186,27 +186,34 @@ SkCanvas* CreatePlatformCanvas(int width, int height, bool is_opaque,
}
// Port of PlatformBitmap to linux
-
PlatformBitmap::~PlatformBitmap() {
cairo_destroy(surface_);
}
bool PlatformBitmap::Allocate(int width, int height, bool is_opaque) {
- cairo_surface_t* surf = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
- width, height);
+ // The SkBitmap allocates and owns the bitmap memory; PlatformBitmap owns the
+ // cairo drawing context tied to the bitmap. The SkBitmap's pixelRef can
+ // outlive the PlatformBitmap if additional copies are made.
+ int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);
+ bitmap_.setConfig(SkBitmap::kARGB_8888_Config, width, height, stride);
+ if (!bitmap_.allocPixels()) // Using the default allocator.
+ return false;
+ bitmap_.setIsOpaque(is_opaque);
+
+ cairo_surface_t* surf = cairo_image_surface_create_for_data(
+ reinterpret_cast<unsigned char*>(bitmap_.getPixels()),
+ CAIRO_FORMAT_ARGB32,
+ width,
+ height,
+ stride);
if (cairo_surface_status(surf) != CAIRO_STATUS_SUCCESS) {
cairo_surface_destroy(surf);
return false;
}
- bitmap_.setConfig(SkBitmap::kARGB_8888_Config, width, height,
- cairo_image_surface_get_stride(surf));
- bitmap_.setPixels(cairo_image_surface_get_data(surf));
- bitmap_.setIsOpaque(is_opaque);
-
surface_ = cairo_create(surf);
cairo_surface_destroy(surf);
return true;
}
-
+
} // namespace skia
diff --git a/skia/ext/bitmap_platform_device_win.cc b/skia/ext/bitmap_platform_device_win.cc
index 8c304e6..201866a 100644
--- a/skia/ext/bitmap_platform_device_win.cc
+++ b/skia/ext/bitmap_platform_device_win.cc
@@ -13,15 +13,35 @@
#include "third_party/skia/include/core/SkRegion.h"
#include "third_party/skia/include/core/SkUtils.h"
-static HBITMAP CreateHBitmap(int width, int height, bool is_opaque,
- HANDLE shared_section, SkBitmap* output) {
+namespace {
+
+// PlatformBitmapPixelRef is an SkPixelRef that, on Windows, is backed by an
+// HBITMAP.
+class SK_API PlatformBitmapPixelRef : public SkPixelRef {
+ public:
+ PlatformBitmapPixelRef(HBITMAP bitmap_handle, void* pixels);
+ virtual ~PlatformBitmapPixelRef();
+
+ SK_DECLARE_UNFLATTENABLE_OBJECT();
+
+ protected:
+ virtual void* onLockPixels(SkColorTable**) SK_OVERRIDE;
+ virtual void onUnlockPixels() SK_OVERRIDE;
+
+ private:
+ HBITMAP bitmap_handle_;
+ void* pixels_;
+};
+
+HBITMAP CreateHBitmap(int width, int height, bool is_opaque,
+ HANDLE shared_section, void** data) {
// CreateDIBSection appears to get unhappy if we create an empty bitmap, so
// just create a minimal bitmap
if ((width == 0) || (height == 0)) {
width = 1;
height = 1;
}
-
+
BITMAPINFOHEADER hdr = {0};
hdr.biSize = sizeof(BITMAPINFOHEADER);
hdr.biWidth = width;
@@ -35,17 +55,35 @@ static HBITMAP CreateHBitmap(int width, int height, bool is_opaque,
hdr.biClrUsed = 0;
hdr.biClrImportant = 0;
- void* data = NULL;
HBITMAP hbitmap = CreateDIBSection(NULL, reinterpret_cast<BITMAPINFO*>(&hdr),
- 0, &data, shared_section, 0);
- if (hbitmap) {
- output->setConfig(SkBitmap::kARGB_8888_Config, width, height);
- output->setPixels(data);
- output->setIsOpaque(is_opaque);
- }
+ 0, data, shared_section, 0);
return hbitmap;
}
+PlatformBitmapPixelRef::PlatformBitmapPixelRef(HBITMAP bitmap_handle,
+ void* pixels)
+ : bitmap_handle_(bitmap_handle),
+ pixels_(pixels) {
+ setPreLocked(pixels, NULL);
+}
+
+PlatformBitmapPixelRef::~PlatformBitmapPixelRef() {
+ if (bitmap_handle_)
+ DeleteObject(bitmap_handle_);
+}
+
+void* PlatformBitmapPixelRef::onLockPixels(SkColorTable** color_table) {
+ *color_table = NULL;
+ return pixels_;
+}
+
+void PlatformBitmapPixelRef::onUnlockPixels() {
+ // Nothing to do.
+ return;
+}
+
+} // namespace
+
namespace skia {
BitmapPlatformDevice::BitmapPlatformDeviceData::BitmapPlatformDeviceData(
@@ -125,13 +163,18 @@ BitmapPlatformDevice* BitmapPlatformDevice::Create(
int height,
bool is_opaque,
HANDLE shared_section) {
- SkBitmap bitmap;
+ void* data;
HBITMAP hbitmap = CreateHBitmap(width, height, is_opaque, shared_section,
- &bitmap);
+ &data);
if (!hbitmap)
return NULL;
+ SkBitmap bitmap;
+ bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
+ bitmap.setPixels(data);
+ bitmap.setIsOpaque(is_opaque);
+
#ifndef NDEBUG
// If we were given data, then don't clobber it!
if (!shared_section && is_opaque)
@@ -279,28 +322,34 @@ SkCanvas* CreatePlatformCanvas(int width,
// Port of PlatformBitmap to win
PlatformBitmap::~PlatformBitmap() {
- if (surface_)
+ if (surface_) {
+ if (platform_extra_)
+ SelectObject(surface_, reinterpret_cast<HGDIOBJ>(platform_extra_));
DeleteDC(surface_);
-
- HBITMAP hbitmap = (HBITMAP)platform_extra_;
- if (hbitmap)
- DeleteObject(hbitmap);
+ }
}
bool PlatformBitmap::Allocate(int width, int height, bool is_opaque) {
- HBITMAP hbitmap = CreateHBitmap(width, height, is_opaque, 0, &bitmap_);
+ void* data;
+ HBITMAP hbitmap = CreateHBitmap(width, height, is_opaque, 0, &data);
if (!hbitmap)
return false;
surface_ = CreateCompatibleDC(NULL);
InitializeDC(surface_);
- HGDIOBJ old_bitmap = SelectObject(surface_, hbitmap);
// When the memory DC is created, its display surface is exactly one
- // monochrome pixel wide and one monochrome pixel high. Since we select our
- // own bitmap, we must delete the previous one.
- DeleteObject(old_bitmap);
- // remember the hbitmap, so we can free it in our destructor
- platform_extra_ = (intptr_t)hbitmap;
+ // monochrome pixel wide and one monochrome pixel high. Save this object
+ // off, we'll restore it just before deleting the memory DC.
+ HGDIOBJ stock_bitmap = SelectObject(surface_, hbitmap);
+ platform_extra_ = reinterpret_cast<intptr_t>(stock_bitmap);
+
+ bitmap_.setConfig(SkBitmap::kARGB_8888_Config, width, height);
+ // PlatformBitmapPixelRef takes ownership of |hbitmap|.
+ bitmap_.setPixelRef(
+ skia::AdoptRef(new PlatformBitmapPixelRef(hbitmap, data)).get());
+ bitmap_.setIsOpaque(is_opaque);
+ bitmap_.lockPixels();
+
return true;
}
diff --git a/skia/ext/platform_canvas.h b/skia/ext/platform_canvas.h
index 68e00072..d8fd727 100644
--- a/skia/ext/platform_canvas.h
+++ b/skia/ext/platform_canvas.h
@@ -10,7 +10,9 @@
#include "base/basictypes.h"
#include "skia/ext/platform_device.h"
#include "skia/ext/refptr.h"
+#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkPixelRef.h"
namespace skia {
@@ -163,6 +165,7 @@ class SK_API ScopedPlatformPaint {
ScopedPlatformPaint& operator=(const ScopedPlatformPaint&);
};
+// PlatformBitmap holds a PlatformSurface that can also be used as an SkBitmap.
class SK_API PlatformBitmap {
public:
PlatformBitmap();
@@ -176,12 +179,16 @@ class SK_API PlatformBitmap {
// Return the skia bitmap, which will be empty if Allocate() did not
// return true.
+ //
+ // The resulting SkBitmap holds a refcount on the underlying platform surface,
+ // so the surface will remain allocated so long as the SkBitmap or its copies
+ // stay around.
const SkBitmap& GetBitmap() { return bitmap_; }
private:
SkBitmap bitmap_;
- PlatformSurface surface_; // initialized to 0
- intptr_t platform_extra_; // initialized to 0, specific to each platform
+ PlatformSurface surface_; // initialized to 0
+ intptr_t platform_extra_; // platform specific, initialized to 0
DISALLOW_COPY_AND_ASSIGN(PlatformBitmap);
};
diff --git a/skia/ext/platform_canvas_unittest.cc b/skia/ext/platform_canvas_unittest.cc
index 3c8b017..572180e 100644
--- a/skia/ext/platform_canvas_unittest.cc
+++ b/skia/ext/platform_canvas_unittest.cc
@@ -14,11 +14,13 @@
#include <unistd.h>
#endif
+#include "base/memory/scoped_ptr.h"
#include "skia/ext/platform_canvas.h"
#include "skia/ext/platform_device.h"
#include "testing/gtest/include/gtest/gtest.h"
-
-#include "SkColor.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "third_party/skia/include/core/SkPixelRef.h"
namespace skia {
@@ -395,4 +397,63 @@ TEST(PlatformCanvas, TranslateLayer) {
#endif // #if !defined(USE_AURA)
+TEST(PlatformBitmapTest, PlatformBitmap) {
+ const int kWidth = 400;
+ const int kHeight = 300;
+ scoped_ptr<PlatformBitmap> platform_bitmap(new PlatformBitmap);
+
+ EXPECT_TRUE(0 == platform_bitmap->GetSurface());
+ EXPECT_TRUE(platform_bitmap->GetBitmap().empty());
+ EXPECT_TRUE(platform_bitmap->GetBitmap().isNull());
+
+ EXPECT_TRUE(platform_bitmap->Allocate(kWidth, kHeight, /*is_opaque=*/false));
+
+ EXPECT_TRUE(0 != platform_bitmap->GetSurface());
+ EXPECT_FALSE(platform_bitmap->GetBitmap().empty());
+ EXPECT_FALSE(platform_bitmap->GetBitmap().isNull());
+ EXPECT_EQ(kWidth, platform_bitmap->GetBitmap().width());
+ EXPECT_EQ(kHeight, platform_bitmap->GetBitmap().height());
+ EXPECT_LE(platform_bitmap->GetBitmap().width()*4,
+ platform_bitmap->GetBitmap().rowBytes());
+ EXPECT_EQ(SkBitmap::kARGB_8888_Config, // Same for all platforms.
+ platform_bitmap->GetBitmap().config());
+ EXPECT_TRUE(platform_bitmap->GetBitmap().lockPixelsAreWritable());
+ EXPECT_TRUE(platform_bitmap->GetBitmap().pixelRef()->isLocked());
+ EXPECT_EQ(1, platform_bitmap->GetBitmap().pixelRef()->getRefCnt());
+
+ *(platform_bitmap->GetBitmap().getAddr32(10, 20)) = 0xDEED1020;
+ *(platform_bitmap->GetBitmap().getAddr32(20, 30)) = 0xDEED2030;
+
+ SkBitmap sk_bitmap = platform_bitmap->GetBitmap();
+ sk_bitmap.lockPixels();
+
+ EXPECT_EQ(2, platform_bitmap->GetBitmap().pixelRef()->getRefCnt());
+ EXPECT_EQ(2, sk_bitmap.pixelRef()->getRefCnt());
+
+ EXPECT_EQ(0xDEED1020, *sk_bitmap.getAddr32(10, 20));
+ EXPECT_EQ(0xDEED2030, *sk_bitmap.getAddr32(20, 30));
+
+ *(platform_bitmap->GetBitmap().getAddr32(30, 40)) = 0xDEED3040;
+
+ // The SkBitmaps derived from a PlatformBitmap must be capable of outliving
+ // the PlatformBitmap.
+ platform_bitmap.reset();
+
+ EXPECT_EQ(1, sk_bitmap.pixelRef()->getRefCnt());
+
+ EXPECT_EQ(0xDEED1020, *sk_bitmap.getAddr32(10, 20));
+ EXPECT_EQ(0xDEED2030, *sk_bitmap.getAddr32(20, 30));
+ EXPECT_EQ(0xDEED3040, *sk_bitmap.getAddr32(30, 40));
+ sk_bitmap.unlockPixels();
+
+ EXPECT_EQ(NULL, sk_bitmap.getPixels());
+
+ sk_bitmap.lockPixels();
+ EXPECT_EQ(0xDEED1020, *sk_bitmap.getAddr32(10, 20));
+ EXPECT_EQ(0xDEED2030, *sk_bitmap.getAddr32(20, 30));
+ EXPECT_EQ(0xDEED3040, *sk_bitmap.getAddr32(30, 40));
+ sk_bitmap.unlockPixels();
+}
+
+
} // namespace skia
diff --git a/tools/valgrind/drmemory/suppressions.txt b/tools/valgrind/drmemory/suppressions.txt
index 5bfa76a..433d963 100644
--- a/tools/valgrind/drmemory/suppressions.txt
+++ b/tools/valgrind/drmemory/suppressions.txt
@@ -307,13 +307,6 @@ system call NtGdiDeleteObjectApp
...
*!skia::BitmapPlatformDevice::BitmapPlatformDeviceData::ReleaseBitmapDC
-GDI USAGE ERROR
-name=http://crbug.com/109963 c
-system call NtGdiDeleteObjectApp
-...
-skia.dll!skia::PlatformBitmap::~PlatformBitmap
-*!skia::PlatformBitmap*
-
# GDI usage errors in 3rd-party components
GDI USAGE ERROR
name=http://crbug.com/119552 a
diff --git a/ui/surface/accelerated_surface_win.cc b/ui/surface/accelerated_surface_win.cc
index cfd0d6c..8523493 100644
--- a/ui/surface/accelerated_surface_win.cc
+++ b/ui/surface/accelerated_surface_win.cc
@@ -23,6 +23,7 @@
#include "base/threading/thread_restrictions.h"
#include "base/time.h"
#include "base/win/wrapped_window_proc.h"
+#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/win/dpi.h"
#include "ui/base/win/hwnd_util.h"
#include "ui/base/win/shell.h"
@@ -306,15 +307,13 @@ void AcceleratedPresenter::Present(HDC dc) {
void AcceleratedPresenter::AsyncCopyTo(
const gfx::Rect& requested_src_subrect,
const gfx::Size& dst_size,
- void* buf,
- const base::Callback<void(bool)>& callback) {
+ const base::Callback<void(bool, const SkBitmap&)>& callback) {
present_thread_->message_loop()->PostTask(
FROM_HERE,
base::Bind(&AcceleratedPresenter::DoCopyToAndAcknowledge,
this,
requested_src_subrect,
dst_size,
- buf,
base::MessageLoopProxy::current(),
callback));
}
@@ -322,19 +321,21 @@ void AcceleratedPresenter::AsyncCopyTo(
void AcceleratedPresenter::DoCopyToAndAcknowledge(
const gfx::Rect& src_subrect,
const gfx::Size& dst_size,
- void* buf,
scoped_refptr<base::SingleThreadTaskRunner> callback_runner,
- const base::Callback<void(bool)>& callback) {
+ const base::Callback<void(bool, const SkBitmap&)>& callback) {
- bool result = DoCopyTo(src_subrect, dst_size, buf);
+ SkBitmap target;
+ bool result = DoCopyTo(src_subrect, dst_size, &target);
+ if (!result)
+ target.reset();
callback_runner->PostTask(
FROM_HERE,
- base::Bind(callback, result));
+ base::Bind(callback, result, target));
}
bool AcceleratedPresenter::DoCopyTo(const gfx::Rect& requested_src_subrect,
const gfx::Size& dst_size,
- void* buf) {
+ SkBitmap* bitmap) {
TRACE_EVENT2(
"gpu", "CopyTo",
"width", dst_size.width(),
@@ -410,19 +411,19 @@ bool AcceleratedPresenter::DoCopyTo(const gfx::Rect& requested_src_subrect,
{
TRACE_EVENT0("gpu", "memcpy");
- size_t bytesPerDstRow = 4 * dst_size.width();
- size_t bytesPerSrcRow = locked_rect.Pitch;
- if (bytesPerDstRow == bytesPerSrcRow) {
- memcpy(reinterpret_cast<int8*>(buf),
- reinterpret_cast<int8*>(locked_rect.pBits),
- bytesPerDstRow * dst_size.height());
- } else {
- for (int i = 0; i < dst_size.height(); ++i) {
- memcpy(reinterpret_cast<int8*>(buf) + bytesPerDstRow * i,
- reinterpret_cast<int8*>(locked_rect.pBits) + bytesPerSrcRow * i,
- bytesPerDstRow);
- }
+
+ bitmap->setConfig(SkBitmap::kARGB_8888_Config,
+ dst_size.width(), dst_size.height(),
+ locked_rect.Pitch);
+ if (!bitmap->allocPixels()) {
+ final_surface->UnlockRect();
+ return false;
}
+ bitmap->setIsOpaque(true);
+
+ memcpy(reinterpret_cast<int8*>(bitmap->getPixels()),
+ reinterpret_cast<int8*>(locked_rect.pBits),
+ locked_rect.Pitch * dst_size.height());
}
final_surface->UnlockRect();
@@ -854,9 +855,8 @@ void AcceleratedSurface::Present(HDC dc) {
void AcceleratedSurface::AsyncCopyTo(
const gfx::Rect& src_subrect,
const gfx::Size& dst_size,
- void* buf,
- const base::Callback<void(bool)>& callback) {
- presenter_->AsyncCopyTo(src_subrect, dst_size, buf, callback);
+ const base::Callback<void(bool, const SkBitmap&)>& callback) {
+ presenter_->AsyncCopyTo(src_subrect, dst_size, callback);
}
void AcceleratedSurface::Suspend() {
diff --git a/ui/surface/accelerated_surface_win.h b/ui/surface/accelerated_surface_win.h
index 4dacb87..1af2482 100644
--- a/ui/surface/accelerated_surface_win.h
+++ b/ui/surface/accelerated_surface_win.h
@@ -64,8 +64,7 @@ class SURFACE_EXPORT AcceleratedPresenter
void Present(HDC dc);
void AsyncCopyTo(const gfx::Rect& src_subrect,
const gfx::Size& dst_size,
- void* buf,
- const base::Callback<void(bool)>& callback);
+ const base::Callback<void(bool, const SkBitmap&)>& callback);
void Invalidate();
#if defined(USE_AURA)
@@ -91,12 +90,11 @@ class SURFACE_EXPORT AcceleratedPresenter
void DoCopyToAndAcknowledge(
const gfx::Rect& src_subrect,
const gfx::Size& dst_size,
- void* buf,
scoped_refptr<base::SingleThreadTaskRunner> callback_runner,
- const base::Callback<void(bool)>& callback);
+ const base::Callback<void(bool, const SkBitmap&)>& callback);
bool DoCopyTo(const gfx::Rect& src_subrect,
const gfx::Size& dst_size,
- void* buf);
+ SkBitmap* bitmap);
void PresentWithGDI(HDC dc);
gfx::Size GetWindowSize();
@@ -174,8 +172,7 @@ class SURFACE_EXPORT AcceleratedSurface {
// |4 * dst_size.width() * dst_size.height()| bytes.
void AsyncCopyTo(const gfx::Rect& src_subrect,
const gfx::Size& dst_size,
- void* buf,
- const base::Callback<void(bool)>& callback);
+ const base::Callback<void(bool, const SkBitmap&)>& callback);
// Temporarily release resources until a new surface is asynchronously
// presented. Present will not be able to represent the last surface after