[go: nahoru, domu]

cc: Use SkMultiPicture for GPU rasterization

GpuRasterWorkerPool holds an SkMultiPicture, the RasterBufferImpl is
created with a pointer to SkMultiPicture, and returns the
SkPictureRecorder's canvas when AquireSkCanvas is called.  When the
canvas is released, we get the surface canvas and pass it to the
multipicture along with the recorded picture.

When we're finished with all of the tiles, we draw the multipicture.

Updated Picture::Raster() to call canvas->drawPicture(), instead of
picture->draw().  This is required to prevent parsing the skia ops
twice when using the multipicturedraw, since picture->draw() always
parses the ops, whereas canvas->drawPicture() might parse the ops,
or it might simply place the whole picture on the canvas (as it will
for the recorder's canvas)

BUG=skia:2315

Review URL: https://codereview.chromium.org/595553002

Cr-Commit-Position: refs/heads/master@{#296227}
diff --git a/cc/resources/gpu_raster_worker_pool.cc b/cc/resources/gpu_raster_worker_pool.cc
index d0f9721..cee01fe 100644
--- a/cc/resources/gpu_raster_worker_pool.cc
+++ b/cc/resources/gpu_raster_worker_pool.cc
@@ -13,6 +13,8 @@
 #include "cc/resources/resource_provider.h"
 #include "cc/resources/scoped_gpu_raster.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
+#include "third_party/skia/include/core/SkMultiPictureDraw.h"
+#include "third_party/skia/include/core/SkPictureRecorder.h"
 #include "third_party/skia/include/core/SkSurface.h"
 #include "third_party/skia/include/gpu/GrContext.h"
 #include "third_party/skia/include/utils/SkNullCanvas.h"
@@ -23,19 +25,23 @@
 class RasterBufferImpl : public RasterBuffer {
  public:
   RasterBufferImpl(ResourceProvider* resource_provider,
-                   const Resource* resource)
+                   const Resource* resource,
+                   SkMultiPictureDraw* multi_picture_draw)
       : resource_provider_(resource_provider),
         resource_(resource),
-        surface_(resource_provider->LockForWriteToSkSurface(resource->id())) {}
+        surface_(resource_provider->LockForWriteToSkSurface(resource->id())),
+        multi_picture_draw_(multi_picture_draw) {}
   virtual ~RasterBufferImpl() {
     resource_provider_->UnlockForWriteToSkSurface(resource_->id());
   }
 
   // Overridden from RasterBuffer:
   virtual skia::RefPtr<SkCanvas> AcquireSkCanvas() OVERRIDE {
-    skia::RefPtr<SkCanvas> canvas = surface_
-                                        ? skia::SharePtr(surface_->getCanvas())
-                                        : skia::AdoptRef(SkCreateNullCanvas());
+    if (!surface_)
+      return skia::AdoptRef(SkCreateNullCanvas());
+
+    skia::RefPtr<SkCanvas> canvas = skia::SharePtr(recorder_.beginRecording(
+        resource_->size().width(), resource_->size().height()));
 
     // Balanced with restore() call in ReleaseSkCanvas. save()/restore() calls
     // are needed to ensure that canvas returns to its previous state after use.
@@ -43,14 +49,23 @@
     return canvas;
   }
   virtual void ReleaseSkCanvas(const skia::RefPtr<SkCanvas>& canvas) OVERRIDE {
+    if (!surface_)
+      return;
+
     // Balanced with save() call in AcquireSkCanvas.
     canvas->restore();
+
+    // Add the canvas and recorded picture to |multi_picture_draw_|.
+    skia::RefPtr<SkPicture> picture = skia::AdoptRef(recorder_.endRecording());
+    multi_picture_draw_->add(surface_->getCanvas(), picture.get());
   }
 
  private:
   ResourceProvider* resource_provider_;
   const Resource* resource_;
   SkSurface* surface_;
+  SkMultiPictureDraw* multi_picture_draw_;
+  SkPictureRecorder recorder_;
 
   DISALLOW_COPY_AND_ASSIGN(RasterBufferImpl);
 };
@@ -188,7 +203,7 @@
   resource_provider_->AcquireSkSurface(resource->id());
 
   return make_scoped_ptr<RasterBuffer>(
-      new RasterBufferImpl(resource_provider_, resource));
+      new RasterBufferImpl(resource_provider_, resource, &multi_picture_draw_));
 }
 
 void GpuRasterWorkerPool::ReleaseBufferForRaster(
@@ -224,6 +239,10 @@
 
   ScopedGpuRaster gpu_raster(context_provider_);
   task_graph_runner_->RunUntilIdle();
+
+  // Draw each all of the pictures that were collected.  This will also clear
+  // the pictures and canvases added to |multi_picture_draw_|
+  multi_picture_draw_.draw();
 }
 
 }  // namespace cc