Skip to content

Commit

Permalink
[Reland 2] Pepper takes ownership of a mailbox before passing it to t…
Browse files Browse the repository at this point in the history
…he texture layer.

This CL is a reland of two CLs:

Pepper: Associate TextureMailboxes with the Graphics3D they were obtained from.
https://codereview.chromium.org/1951263003

[Reland 1] Pepper takes ownership of a mailbox before passing it to the texture
layer. https://codereview.chromium.org/1943513002

This CL fixes a logic error in GpuChannel where preemption was incorrectly
handled.

BUG=350204, 602484
CQ_INCLUDE_TRYBOTS=tryserver.blink:linux_blink_rel
TBR=ccameron@chromium.org, bbudge@chromium.org, sky@chromium.org, tsepez@chromium.org

Review-Url: https://codereview.chromium.org/1965253002
Cr-Commit-Position: refs/heads/master@{#393003}
  • Loading branch information
erikchen authored and Commit bot committed May 11, 2016
1 parent 9bf2667 commit 438b044
Show file tree
Hide file tree
Showing 24 changed files with 540 additions and 137 deletions.
20 changes: 0 additions & 20 deletions cc/layers/texture_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -154,26 +154,6 @@ void TextureLayer::SetTextureMailbox(
requires_commit, allow_mailbox_reuse);
}

static void IgnoreReleaseCallback(const gpu::SyncToken& sync_token, bool lost) {
}

void TextureLayer::SetTextureMailboxWithoutReleaseCallback(
const TextureMailbox& mailbox) {
// We allow reuse of the mailbox if there is a new sync point signalling new
// content, and the release callback goes nowhere since we'll be calling it
// multiple times for the same mailbox.
DCHECK(!mailbox.IsValid() || !holder_ref_ ||
!mailbox.Equals(holder_ref_->holder()->mailbox()) ||
mailbox.sync_token() != holder_ref_->holder()->mailbox().sync_token());
std::unique_ptr<SingleReleaseCallback> release;
bool requires_commit = true;
bool allow_mailbox_reuse = true;
if (mailbox.IsValid())
release = SingleReleaseCallback::Create(base::Bind(&IgnoreReleaseCallback));
SetTextureMailboxInternal(mailbox, std::move(release), requires_commit,
allow_mailbox_reuse);
}

void TextureLayer::SetNeedsDisplayRect(const gfx::Rect& dirty_rect) {
Layer::SetNeedsDisplayRect(dirty_rect);
}
Expand Down
6 changes: 0 additions & 6 deletions cc/layers/texture_layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,12 +133,6 @@ class CC_EXPORT TextureLayer : public Layer {
const TextureMailbox& mailbox,
std::unique_ptr<SingleReleaseCallback> release_callback);

// Use this for special cases where the same texture is used to back the
// TextureLayer across all frames.
// WARNING: DON'T ACTUALLY USE THIS WHAT YOU ARE DOING IS WRONG.
// TODO(danakj): Remove this when pepper doesn't need it. crbug.com/350204
void SetTextureMailboxWithoutReleaseCallback(const TextureMailbox& mailbox);

void SetNeedsDisplayRect(const gfx::Rect& dirty_rect) override;

void SetLayerTreeHost(LayerTreeHost* layer_tree_host) override;
Expand Down
27 changes: 0 additions & 27 deletions cc/layers/texture_layer_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -332,33 +332,6 @@ TEST_F(TextureLayerWithMailboxTest, ReplaceMailboxOnMainThreadBeforeCommit) {
SingleReleaseCallback::Create(test_data_.release_mailbox1_));
}

TEST_F(TextureLayerTest, SetTextureMailboxWithoutReleaseCallback) {
scoped_refptr<TextureLayer> test_layer =
TextureLayer::CreateForMailbox(nullptr);
ASSERT_TRUE(test_layer.get());

// These use the same gpu::Mailbox, but different sync points.
TextureMailbox mailbox1(MailboxFromChar('a'), SyncTokenFromUInt(1),
GL_TEXTURE_2D);
TextureMailbox mailbox2(MailboxFromChar('a'), SyncTokenFromUInt(2),
GL_TEXTURE_2D);

EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
layer_tree_host_->SetRootLayer(test_layer);
Mock::VerifyAndClearExpectations(layer_tree_host_.get());

// Set the mailbox the first time. It should cause a commit.
EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
test_layer->SetTextureMailboxWithoutReleaseCallback(mailbox1);
Mock::VerifyAndClearExpectations(layer_tree_host_.get());

// Set the mailbox again with a new sync point, as the backing texture has
// been updated. It should cause a new commit.
EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
test_layer->SetTextureMailboxWithoutReleaseCallback(mailbox2);
Mock::VerifyAndClearExpectations(layer_tree_host_.get());
}

class TextureLayerMailboxHolderTest : public TextureLayerTest {
public:
TextureLayerMailboxHolderTest()
Expand Down
7 changes: 6 additions & 1 deletion components/mus/gles2/command_buffer_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,12 @@ void CommandBufferImpl::CreateStreamTexture(
NOTIMPLEMENTED();
}

void CommandBufferImpl::ProduceFrontBuffer(const gpu::Mailbox& mailbox) {
void CommandBufferImpl::TakeFrontBuffer(const gpu::Mailbox& mailbox) {
NOTIMPLEMENTED();
}

void CommandBufferImpl::ReturnFrontBuffer(const gpu::Mailbox& mailbox,
bool is_lost) {
NOTIMPLEMENTED();
}

Expand Down
3 changes: 2 additions & 1 deletion components/mus/gles2/command_buffer_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ class CommandBufferImpl : public mojom::CommandBuffer,
uint32_t client_texture_id,
const mojom::CommandBuffer::CreateStreamTextureCallback& callback
) override;
void ProduceFrontBuffer(const gpu::Mailbox& mailbox) override;
void TakeFrontBuffer(const gpu::Mailbox& mailbox) override;
void ReturnFrontBuffer(const gpu::Mailbox& mailbox, bool is_lost) override;
void SignalQuery(uint32_t query, uint32_t signal_id) override;
void SignalSyncToken(const gpu::SyncToken& sync_token,
uint32_t signal_id) override;
Expand Down
3 changes: 2 additions & 1 deletion components/mus/public/interfaces/command_buffer.mojom
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ interface CommandBuffer {
DestroyImage(int32 id);
CreateStreamTexture(uint32 client_texture_id)
=> (int32 stream_id, bool succeeded);
ProduceFrontBuffer(gpu.mojom.Mailbox mailbox);
TakeFrontBuffer(gpu.mojom.Mailbox mailbox);
ReturnFrontBuffer(gpu.mojom.Mailbox mailbox, bool is_lost);
SignalQuery(uint32 query, uint32 signal_id);
SignalSyncToken(gpu.mojom.SyncToken sync_token, uint32 signal_id);
WaitForGetOffsetInRange(int32 start, int32 end)
Expand Down
111 changes: 95 additions & 16 deletions content/renderer/pepper/pepper_plugin_instance_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -775,22 +775,63 @@ void PepperPluginInstanceImpl::ScrollRect(int dx,
}
}

void PepperPluginInstanceImpl::CommitBackingTexture() {
void PepperPluginInstanceImpl::CommitTextureMailbox(
const cc::TextureMailbox& texture_mailbox) {
if (committed_texture_.IsValid() && !IsTextureInUse(committed_texture_)) {
committed_texture_graphics_3d_->ReturnFrontBuffer(
committed_texture_.mailbox(), committed_texture_consumed_sync_token_,
false);
}

committed_texture_ = texture_mailbox;
committed_texture_graphics_3d_ = bound_graphics_3d_;
committed_texture_consumed_sync_token_ = gpu::SyncToken();

if (!texture_layer_) {
UpdateLayer(true);
return;
}

gpu::Mailbox mailbox;
gpu::SyncToken sync_token;
bound_graphics_3d_->GetBackingMailbox(&mailbox, &sync_token);
DCHECK(!mailbox.IsZero());
DCHECK(sync_token.HasData());
texture_layer_->SetTextureMailboxWithoutReleaseCallback(
cc::TextureMailbox(mailbox, sync_token, GL_TEXTURE_2D));
PassCommittedTextureToTextureLayer();
texture_layer_->SetNeedsDisplay();
}

void PepperPluginInstanceImpl::PassCommittedTextureToTextureLayer() {
DCHECK(bound_graphics_3d_);

if (!committed_texture_.IsValid())
return;

std::unique_ptr<cc::SingleReleaseCallback> callback(
cc::SingleReleaseCallback::Create(base::Bind(
&PepperPluginInstanceImpl::FinishedConsumingCommittedTexture,
weak_factory_.GetWeakPtr(), committed_texture_,
committed_texture_graphics_3d_)));

IncrementTextureReferenceCount(committed_texture_);
texture_layer_->SetTextureMailbox(committed_texture_, std::move(callback));
}

void PepperPluginInstanceImpl::FinishedConsumingCommittedTexture(
const cc::TextureMailbox& texture_mailbox,
scoped_refptr<PPB_Graphics3D_Impl> graphics_3d,
const gpu::SyncToken& sync_token,
bool is_lost) {
bool removed = DecrementTextureReferenceCount(texture_mailbox);
bool is_committed_texture =
committed_texture_.mailbox() == texture_mailbox.mailbox();

if (is_committed_texture && !is_lost) {
committed_texture_consumed_sync_token_ = sync_token;
return;
}

if (removed && !is_committed_texture) {
graphics_3d->ReturnFrontBuffer(texture_mailbox.mailbox(), sync_token,
is_lost);
}
}

void PepperPluginInstanceImpl::InstanceCrashed() {
// Force free all resources and vars.
HostGlobals::Get()->InstanceCrashed(pp_instance());
Expand Down Expand Up @@ -2011,12 +2052,7 @@ void PepperPluginInstanceImpl::UpdateLayer(bool force_creation) {
if (!container_)
return;

gpu::Mailbox mailbox;
gpu::SyncToken sync_token;
if (bound_graphics_3d_.get()) {
bound_graphics_3d_->GetBackingMailbox(&mailbox, &sync_token);
}
bool want_3d_layer = !mailbox.IsZero() && sync_token.HasData();
bool want_3d_layer = !!bound_graphics_3d_.get();
bool want_2d_layer = !!bound_graphics_2d_platform_;
bool want_texture_layer = want_3d_layer || want_2d_layer;
bool want_compositor_layer = !!bound_compositor_;
Expand Down Expand Up @@ -2055,8 +2091,8 @@ void PepperPluginInstanceImpl::UpdateLayer(bool force_creation) {
DCHECK(bound_graphics_3d_.get());
texture_layer_ = cc::TextureLayer::CreateForMailbox(NULL);
opaque = bound_graphics_3d_->IsOpaque();
texture_layer_->SetTextureMailboxWithoutReleaseCallback(
cc::TextureMailbox(mailbox, sync_token, GL_TEXTURE_2D));

PassCommittedTextureToTextureLayer();
} else {
DCHECK(bound_graphics_2d_platform_);
texture_layer_ = cc::TextureLayer::CreateForMailbox(this);
Expand Down Expand Up @@ -3346,4 +3382,47 @@ void PepperPluginInstanceImpl::ConvertDIPToViewport(gfx::Rect* rect) const {
rect->set_height(rect->height() / viewport_to_dip_scale_);
}

void PepperPluginInstanceImpl::IncrementTextureReferenceCount(
const cc::TextureMailbox& mailbox) {
auto it =
std::find_if(texture_ref_counts_.begin(), texture_ref_counts_.end(),
[&mailbox](const TextureMailboxRefCount& ref_count) {
return ref_count.first.mailbox() == mailbox.mailbox();
});
if (it == texture_ref_counts_.end()) {
texture_ref_counts_.push_back(std::make_pair(mailbox, 1));
return;
}

it->second++;
}

bool PepperPluginInstanceImpl::DecrementTextureReferenceCount(
const cc::TextureMailbox& mailbox) {
auto it =
std::find_if(texture_ref_counts_.begin(), texture_ref_counts_.end(),
[&mailbox](const TextureMailboxRefCount& ref_count) {
return ref_count.first.mailbox() == mailbox.mailbox();
});
DCHECK(it != texture_ref_counts_.end());

if (it->second == 1) {
texture_ref_counts_.erase(it);
return true;
}

it->second--;
return false;
}

bool PepperPluginInstanceImpl::IsTextureInUse(
const cc::TextureMailbox& mailbox) const {
auto it =
std::find_if(texture_ref_counts_.begin(), texture_ref_counts_.end(),
[&mailbox](const TextureMailboxRefCount& ref_count) {
return ref_count.first.mailbox() == mailbox.mailbox();
});
return it != texture_ref_counts_.end();
}

} // namespace content
54 changes: 51 additions & 3 deletions content/renderer/pepper/pepper_plugin_instance_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "cc/layers/content_layer_client.h"
#include "cc/layers/layer.h"
#include "cc/layers/texture_layer_client.h"
#include "cc/resources/texture_mailbox.h"
#include "content/common/content_export.h"
#include "content/public/renderer/pepper_plugin_instance.h"
#include "content/public/renderer/plugin_instance_throttler.h"
Expand Down Expand Up @@ -197,9 +198,18 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
// slow path can also be triggered if there is an overlapping frame.
void ScrollRect(int dx, int dy, const gfx::Rect& rect);

// Commit the backing texture to the screen once the side effects some
// rendering up to an offscreen SwapBuffers are visible.
void CommitBackingTexture();
// Commit the texture mailbox to the screen.
void CommitTextureMailbox(const cc::TextureMailbox& texture_mailbox);

// Passes the committed texture to |texture_layer_| and marks it as in use.
void PassCommittedTextureToTextureLayer();

// Callback when the compositor is finished consuming the committed texture.
void FinishedConsumingCommittedTexture(
const cc::TextureMailbox& texture_mailbox,
scoped_refptr<PPB_Graphics3D_Impl> graphics_3d,
const gpu::SyncToken& sync_token,
bool is_lost);

// Called when the out-of-process plugin implementing this instance crashed.
void InstanceCrashed();
Expand Down Expand Up @@ -702,6 +712,28 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
void ConvertRectToDIP(PP_Rect* rect) const;
void ConvertDIPToViewport(gfx::Rect* rect) const;

// Each time CommitTextureMailbox() is called, this instance is given
// ownership
// of a cc::TextureMailbox. This instance always needs to hold on to the most
// recently committed cc::TextureMailbox, since UpdateLayer() might require
// it.
// Since it is possible for a cc::TextureMailbox to be passed to
// texture_layer_ more than once, a reference counting mechanism is necessary
// to ensure that a cc::TextureMailbox isn't returned until all copies of it
// have been released by texture_layer_.
//
// This method should be called each time a cc::TextureMailbox is passed to
// |texture_layer_|. It increments an internal reference count.
void IncrementTextureReferenceCount(const cc::TextureMailbox& mailbox);

// This method should be called each time |texture_layer_| finishes consuming
// a cc::TextureMailbox. It decrements an internal reference count. Returns
// whether the last reference was removed.
bool DecrementTextureReferenceCount(const cc::TextureMailbox& mailbox);

// Whether a given cc::TextureMailbox is in use by |texture_layer_|.
bool IsTextureInUse(const cc::TextureMailbox& mailbox) const;

RenderFrameImpl* render_frame_;
base::Closure instance_deleted_callback_;
scoped_refptr<PluginModule> module_;
Expand Down Expand Up @@ -933,6 +965,22 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
// The text that is currently selected in the plugin.
base::string16 selected_text_;

// The most recently committed texture. This is kept around in case the layer
// needs to be regenerated.
cc::TextureMailbox committed_texture_;

// The Graphics3D that produced the most recently committed texture.
scoped_refptr<PPB_Graphics3D_Impl> committed_texture_graphics_3d_;

gpu::SyncToken committed_texture_consumed_sync_token_;

// Holds the number of references |texture_layer_| has to any given
// cc::TextureMailbox.
// We expect there to be no more than 10 textures in use at a time. A
// std::vector will have better performance than a std::map.
using TextureMailboxRefCount = std::pair<cc::TextureMailbox, int>;
std::vector<TextureMailboxRefCount> texture_ref_counts_;

bool initialized_;

// We use a weak ptr factory for scheduling DidChangeView events so that we
Expand Down
Loading

0 comments on commit 438b044

Please sign in to comment.