Commit 9a61fc0f authored by danakj's avatar danakj Committed by Commit Bot

Register SharedMemory through CompositorFrameSink for OffscreenCanavas

This converts from using the SharedBitmapManager, which registers
shared memory through its own parallel channel, to allocating
SharedMemory directly and reporting it to the CompositorFrameSink.

The SharedBitmapManager path was racey with the submission of
CompositorFrames, unless sequence numbers were used (they were not
in this code), and required the display compositor to live in the
browser process.

With this change, OffscreenCanvas will work with viz software
compositing.

R=kylechar@chromium.org

Bug: 730660
Cq-Include-Trybots: master.tryserver.blink:linux_trusty_blink_rel;master.tryserver.chromium.linux:linux_layout_tests_slimming_paint_v2
Change-Id: I0daa654112e9834a325754ade37d19325793e01e
Reviewed-on: https://chromium-review.googlesource.com/1017316Reviewed-by: default avatarJustin Novosad <junov@chromium.org>
Reviewed-by: default avatarkylechar <kylechar@chromium.org>
Commit-Queue: danakj <danakj@chromium.org>
Cr-Commit-Position: refs/heads/master@{#552106}
parent 5b0ae3db
...@@ -14,6 +14,7 @@ include_rules = [ ...@@ -14,6 +14,7 @@ include_rules = [
"+base/logging.h", "+base/logging.h",
"+base/memory", "+base/memory",
"+base/observer_list.h", "+base/observer_list.h",
"+base/memory/shared_memory.h",
"+base/message_loop/message_loop.h", "+base/message_loop/message_loop.h",
"+base/metrics/histogram.h", "+base/metrics/histogram.h",
"+base/metrics/histogram_base.h", "+base/metrics/histogram_base.h",
......
...@@ -62,7 +62,8 @@ OffscreenCanvasFrameDispatcherImpl::OffscreenCanvasFrameDispatcherImpl( ...@@ -62,7 +62,8 @@ OffscreenCanvasFrameDispatcherImpl::OffscreenCanvasFrameDispatcherImpl(
mojo::MakeRequest(&sink_)); mojo::MakeRequest(&sink_));
} }
offscreen_canvas_resource_provider_ = offscreen_canvas_resource_provider_ =
std::make_unique<OffscreenCanvasResourceProvider>(width, height); std::make_unique<OffscreenCanvasResourceProvider>(width, height,
sink_.get());
} }
OffscreenCanvasFrameDispatcherImpl::~OffscreenCanvasFrameDispatcherImpl() = OffscreenCanvasFrameDispatcherImpl::~OffscreenCanvasFrameDispatcherImpl() =
......
...@@ -82,9 +82,6 @@ class PLATFORM_EXPORT OffscreenCanvasFrameDispatcherImpl ...@@ -82,9 +82,6 @@ class PLATFORM_EXPORT OffscreenCanvasFrameDispatcherImpl
void SetNeedsBeginFrameInternal(); void SetNeedsBeginFrameInternal();
std::unique_ptr<OffscreenCanvasResourceProvider>
offscreen_canvas_resource_provider_;
bool VerifyImageSize(const IntSize); bool VerifyImageSize(const IntSize);
void PostImageToPlaceholderIfNotBlocked(scoped_refptr<StaticBitmapImage>, void PostImageToPlaceholderIfNotBlocked(scoped_refptr<StaticBitmapImage>,
unsigned resource_id); unsigned resource_id);
...@@ -94,6 +91,8 @@ class PLATFORM_EXPORT OffscreenCanvasFrameDispatcherImpl ...@@ -94,6 +91,8 @@ class PLATFORM_EXPORT OffscreenCanvasFrameDispatcherImpl
viz::mojom::blink::CompositorFrameSinkPtr sink_; viz::mojom::blink::CompositorFrameSinkPtr sink_;
mojo::Binding<viz::mojom::blink::CompositorFrameSinkClient> binding_; mojo::Binding<viz::mojom::blink::CompositorFrameSinkClient> binding_;
std::unique_ptr<OffscreenCanvasResourceProvider>
offscreen_canvas_resource_provider_;
int placeholder_canvas_id_; int placeholder_canvas_id_;
......
...@@ -4,9 +4,13 @@ ...@@ -4,9 +4,13 @@
#include "third_party/blink/renderer/platform/graphics/offscreen_canvas_resource_provider.h" #include "third_party/blink/renderer/platform/graphics/offscreen_canvas_resource_provider.h"
#include "base/memory/shared_memory.h"
#include "base/numerics/checked_math.h" #include "base/numerics/checked_math.h"
#include "components/viz/common/quads/shared_bitmap.h"
#include "components/viz/common/resources/bitmap_allocation.h"
#include "gpu/command_buffer/client/gles2_interface.h" #include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/common/capabilities.h" #include "gpu/command_buffer/common/capabilities.h"
#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h" #include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_graphics_context_3d_provider.h" #include "third_party/blink/public/platform/web_graphics_context_3d_provider.h"
#include "third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.h" #include "third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.h"
...@@ -19,18 +23,35 @@ ...@@ -19,18 +23,35 @@
#include "third_party/skia/include/core/SkSwizzle.h" #include "third_party/skia/include/core/SkSwizzle.h"
#include "third_party/skia/include/gpu/GrContext.h" #include "third_party/skia/include/gpu/GrContext.h"
namespace {
// TODO(danakj): One day the gpu::mojom::Mailbox type should be shared with
// blink directly and we won't need to use gpu::mojom::blink::Mailbox, nor the
// conversion through WTF::Vector.
gpu::mojom::blink::MailboxPtr SharedBitmapIdToGpuMailboxPtr(
const viz::SharedBitmapId& id) {
WTF::Vector<int8_t> name(GL_MAILBOX_SIZE_CHROMIUM);
for (int i = 0; i < GL_MAILBOX_SIZE_CHROMIUM; ++i)
name[i] = id.name[i];
return {base::in_place, name};
}
} // namespace
namespace blink { namespace blink {
OffscreenCanvasResourceProvider::OffscreenCanvasResourceProvider(int width, OffscreenCanvasResourceProvider::OffscreenCanvasResourceProvider(
int height) int width,
: width_(width), height_(height), next_resource_id_(0u) {} int height,
viz::mojom::blink::CompositorFrameSink* sink)
: sink_(sink), width_(width), height_(height) {}
OffscreenCanvasResourceProvider::~OffscreenCanvasResourceProvider() = default; OffscreenCanvasResourceProvider::~OffscreenCanvasResourceProvider() = default;
std::unique_ptr<OffscreenCanvasResourceProvider::FrameResource> std::unique_ptr<OffscreenCanvasResourceProvider::FrameResource>
OffscreenCanvasResourceProvider::CreateOrRecycleFrameResource() { OffscreenCanvasResourceProvider::CreateOrRecycleFrameResource() {
if (recyclable_resource_) { if (recyclable_resource_) {
recyclable_resource_->spare_lock_ = true; recyclable_resource_->spare_lock = true;
return std::move(recyclable_resource_); return std::move(recyclable_resource_);
} }
return std::make_unique<FrameResource>(); return std::make_unique<FrameResource>();
...@@ -55,13 +76,19 @@ void OffscreenCanvasResourceProvider::SetTransferableResourceToSharedBitmap( ...@@ -55,13 +76,19 @@ void OffscreenCanvasResourceProvider::SetTransferableResourceToSharedBitmap(
scoped_refptr<StaticBitmapImage> image) { scoped_refptr<StaticBitmapImage> image) {
std::unique_ptr<FrameResource> frame_resource = std::unique_ptr<FrameResource> frame_resource =
CreateOrRecycleFrameResource(); CreateOrRecycleFrameResource();
if (!frame_resource->shared_bitmap_) { if (!frame_resource->shared_memory) {
frame_resource->shared_bitmap_ = Platform::Current()->AllocateSharedBitmap( frame_resource->provider = this;
IntSize(width_, height_), viz::ResourceFormat::RGBA_8888); frame_resource->shared_bitmap_id = viz::SharedBitmap::GenerateId();
if (!frame_resource->shared_bitmap_) frame_resource->shared_memory =
return; viz::bitmap_allocation::AllocateMappedBitmap(
gfx::Size(width_, height_), viz::ResourceFormat::RGBA_8888);
sink_->DidAllocateSharedBitmap(
viz::bitmap_allocation::DuplicateAndCloseMappedBitmap(
frame_resource->shared_memory.get(), gfx::Size(width_, height_),
viz::ResourceFormat::RGBA_8888),
SharedBitmapIdToGpuMailboxPtr(frame_resource->shared_bitmap_id));
} }
unsigned char* pixels = frame_resource->shared_bitmap_->pixels(); void* pixels = frame_resource->shared_memory->memory();
DCHECK(pixels); DCHECK(pixels);
// TODO(xlai): Optimize to avoid copying pixels. See crbug.com/651456. // TODO(xlai): Optimize to avoid copying pixels. See crbug.com/651456.
// However, in the case when |image| is texture backed, this function call // However, in the case when |image| is texture backed, this function call
...@@ -80,7 +107,7 @@ void OffscreenCanvasResourceProvider::SetTransferableResourceToSharedBitmap( ...@@ -80,7 +107,7 @@ void OffscreenCanvasResourceProvider::SetTransferableResourceToSharedBitmap(
DCHECK(read_pixels_successful); DCHECK(read_pixels_successful);
if (!read_pixels_successful) if (!read_pixels_successful)
return; return;
resource.mailbox_holder.mailbox = frame_resource->shared_bitmap_->id(); resource.mailbox_holder.mailbox = frame_resource->shared_bitmap_id;
resource.mailbox_holder.texture_target = 0; resource.mailbox_holder.texture_target = 0;
resource.is_software = true; resource.is_software = true;
...@@ -102,12 +129,11 @@ void OffscreenCanvasResourceProvider:: ...@@ -102,12 +129,11 @@ void OffscreenCanvasResourceProvider::
std::unique_ptr<FrameResource> frame_resource = std::unique_ptr<FrameResource> frame_resource =
CreateOrRecycleFrameResource(); CreateOrRecycleFrameResource();
frame_resource->image_ = std::move(image); frame_resource->provider = this;
frame_resource->image = std::move(image);
resources_.insert(next_resource_id_, std::move(frame_resource)); resources_.insert(next_resource_id_, std::move(frame_resource));
} }
OffscreenCanvasResourceProvider::FrameResource::~FrameResource() = default;
void OffscreenCanvasResourceProvider::ReclaimResources( void OffscreenCanvasResourceProvider::ReclaimResources(
const WTF::Vector<viz::ReturnedResource>& resources) { const WTF::Vector<viz::ReturnedResource>& resources) {
for (const auto& resource : resources) { for (const auto& resource : resources) {
...@@ -117,9 +143,9 @@ void OffscreenCanvasResourceProvider::ReclaimResources( ...@@ -117,9 +143,9 @@ void OffscreenCanvasResourceProvider::ReclaimResources(
if (it == resources_.end()) if (it == resources_.end())
continue; continue;
if (it->value->image_ && it->value->image_->ContextProviderWrapper() && if (it->value->image && it->value->image->ContextProviderWrapper() &&
resource.sync_token.HasData()) { resource.sync_token.HasData()) {
it->value->image_->ContextProviderWrapper() it->value->image->ContextProviderWrapper()
->ContextProvider() ->ContextProvider()
->ContextGL() ->ContextGL()
->WaitSyncTokenCHROMIUM(resource.sync_token.GetConstData()); ->WaitSyncTokenCHROMIUM(resource.sync_token.GetConstData());
...@@ -137,15 +163,20 @@ void OffscreenCanvasResourceProvider::ReclaimResource(unsigned resource_id) { ...@@ -137,15 +163,20 @@ void OffscreenCanvasResourceProvider::ReclaimResource(unsigned resource_id) {
void OffscreenCanvasResourceProvider::ReclaimResourceInternal( void OffscreenCanvasResourceProvider::ReclaimResourceInternal(
const ResourceMap::iterator& it) { const ResourceMap::iterator& it) {
if (it->value->spare_lock_) { if (it->value->spare_lock) {
it->value->spare_lock_ = false; it->value->spare_lock = false;
} else { } else {
// Really reclaim the resources // Really reclaim the resources.
recyclable_resource_ = std::move(it->value); recyclable_resource_ = std::move(it->value);
// release SkImage immediately since it is not recyclable // Release SkImage immediately since it is not recyclable.
recyclable_resource_->image_ = nullptr; recyclable_resource_->image = nullptr;
resources_.erase(it); resources_.erase(it);
} }
} }
OffscreenCanvasResourceProvider::FrameResource::~FrameResource() {
provider->sink_->DidDeleteSharedBitmap(
SharedBitmapIdToGpuMailboxPtr(shared_bitmap_id));
}
} // namespace blink } // namespace blink
...@@ -5,16 +5,32 @@ ...@@ -5,16 +5,32 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_OFFSCREEN_CANVAS_RESOURCE_PROVIDER_H_ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_OFFSCREEN_CANVAS_RESOURCE_PROVIDER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_OFFSCREEN_CANVAS_RESOURCE_PROVIDER_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_OFFSCREEN_CANVAS_RESOURCE_PROVIDER_H_
#include "components/viz/common/quads/shared_bitmap.h"
#include "components/viz/common/resources/returned_resource.h" #include "components/viz/common/resources/returned_resource.h"
#include "components/viz/common/resources/transferable_resource.h" #include "components/viz/common/resources/transferable_resource.h"
#include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h" #include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h"
namespace base {
class SharedMemory;
}
namespace viz {
namespace mojom {
namespace blink {
class CompositorFrameSink;
}
} // namespace mojom
} // namespace viz
namespace blink { namespace blink {
class PLATFORM_EXPORT OffscreenCanvasResourceProvider { class PLATFORM_EXPORT OffscreenCanvasResourceProvider {
public: public:
OffscreenCanvasResourceProvider(int width, int height); // The CompositorFrameSink given here must be kept alive as long as this
// class is, as it is used to free the software-backed resources in the
// display compositor.
OffscreenCanvasResourceProvider(int width,
int height,
viz::mojom::blink::CompositorFrameSink*);
~OffscreenCanvasResourceProvider(); ~OffscreenCanvasResourceProvider();
...@@ -33,31 +49,46 @@ class PLATFORM_EXPORT OffscreenCanvasResourceProvider { ...@@ -33,31 +49,46 @@ class PLATFORM_EXPORT OffscreenCanvasResourceProvider {
void Reshape(int width, int height) { void Reshape(int width, int height) {
width_ = width; width_ = width;
height_ = height; height_ = height;
// TODO(junov): Prevent recycling resources of the wrong size.
} }
private: private:
int width_;
int height_;
unsigned next_resource_id_;
struct FrameResource { struct FrameResource {
scoped_refptr<StaticBitmapImage> image_;
std::unique_ptr<viz::SharedBitmap> shared_bitmap_;
bool spare_lock_ = true;
gpu::Mailbox mailbox_;
FrameResource() = default; FrameResource() = default;
~FrameResource(); ~FrameResource();
// TODO(junov): What does this do?
bool spare_lock = true;
// Holds the backing for a gpu-backed resource. The Mailbox() of the image
// is given to the display compositor to present it.
scoped_refptr<StaticBitmapImage> image;
// Holds the backing for a software-backed resource.
std::unique_ptr<base::SharedMemory> shared_memory;
// The id given to the display compositor to display a software-backed
// resource.
viz::SharedBitmapId shared_bitmap_id;
// Back-pointer to the OffscreenCanvasResourceProvider. FrameResource does
// not outlive the provider.
OffscreenCanvasResourceProvider* provider = nullptr;
}; };
std::unique_ptr<FrameResource> recyclable_resource_; using ResourceMap = HashMap<unsigned, std::unique_ptr<FrameResource>>;
std::unique_ptr<FrameResource> CreateOrRecycleFrameResource();
void SetNeedsBeginFrameInternal(); void SetNeedsBeginFrameInternal();
std::unique_ptr<FrameResource> CreateOrRecycleFrameResource();
typedef HashMap<unsigned, std::unique_ptr<FrameResource>> ResourceMap;
void ReclaimResourceInternal(const ResourceMap::iterator&); void ReclaimResourceInternal(const ResourceMap::iterator&);
// Holds a pointer to the FrameSink where SharedBitmapIds are reported on
// allocation and destruction, in order to later give those ids to the display
// compositor in a DrawQuad to present the resource.
viz::mojom::blink::CompositorFrameSink* const sink_;
int width_;
int height_;
unsigned next_resource_id_ = 0;
std::unique_ptr<FrameResource> recyclable_resource_;
ResourceMap resources_; ResourceMap resources_;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment