Commit 9b3c1cb1 authored by orglofch's avatar orglofch Committed by Commit bot

Add optimization for CHROMIUM_subscribe_uniform extension.

We only pass ValueState updates via IPC if the Gpu Service has
signalled that a Valuebuffer is subscribed to the respective target.

BUG=422978

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

Cr-Commit-Position: refs/heads/master@{#308389}
parent d3446885
......@@ -230,6 +230,8 @@ bool GpuProcessHostUIShim::OnControlMessageReceived(
OnVideoMemoryUsageStatsReceived);
IPC_MESSAGE_HANDLER(GpuHostMsg_ResourcesRelinquished,
OnResourcesRelinquished)
IPC_MESSAGE_HANDLER(GpuHostMsg_AddSubscription, OnAddSubscription);
IPC_MESSAGE_HANDLER(GpuHostMsg_RemoveSubscription, OnRemoveSubscription);
IPC_MESSAGE_UNHANDLED_ERROR()
IPC_END_MESSAGE_MAP()
......@@ -306,4 +308,20 @@ void GpuProcessHostUIShim::OnResourcesRelinquished() {
}
}
void GpuProcessHostUIShim::OnAddSubscription(
int32 process_id, unsigned int target) {
RenderProcessHost* rph = RenderProcessHost::FromID(process_id);
if (rph) {
rph->OnAddSubscription(target);
}
}
void GpuProcessHostUIShim::OnRemoveSubscription(
int32 process_id, unsigned int target) {
RenderProcessHost* rph = RenderProcessHost::FromID(process_id);
if (rph) {
rph->OnRemoveSubscription(target);
}
}
} // namespace content
......@@ -95,6 +95,8 @@ class GpuProcessHostUIShim : public IPC::Listener,
void OnVideoMemoryUsageStatsReceived(
const GPUVideoMemoryUsageStats& video_memory_usage_stats);
void OnResourcesRelinquished();
void OnAddSubscription(int32 process_id, unsigned int target);
void OnRemoveSubscription(int32 process_id, unsigned int target);
// The serial number of the GpuProcessHost / GpuProcessHostUIShim pair.
int host_id_;
......
......@@ -458,6 +458,8 @@ RenderProcessHostImpl::RenderProcessHostImpl(
power_monitor_broadcaster_(this),
worker_ref_count_(0),
permission_service_context_(new PermissionServiceContext(this)),
pending_valuebuffer_state_(new gpu::ValueStateMap()),
subscribe_uniform_enabled_(false),
weak_factory_(this) {
widget_helper_ = new RenderWidgetHelper();
......@@ -476,6 +478,9 @@ RenderProcessHostImpl::RenderProcessHostImpl(
base::Bind(&CacheShaderInfo, GetID(),
storage_partition_impl_->GetPath()));
}
subscribe_uniform_enabled_ =
base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableSubscribeUniformExtension);
// Note: When we create the RenderProcessHostImpl, it's technically
// backgrounded, because it has no visible listeners. But the process
......@@ -930,6 +935,38 @@ const base::TimeTicks& RenderProcessHostImpl::GetInitTimeForNavigationMetrics()
return init_time_;
}
bool RenderProcessHostImpl::SubscribeUniformEnabled() const {
return subscribe_uniform_enabled_;
}
void RenderProcessHostImpl::OnAddSubscription(unsigned int target) {
DCHECK(subscribe_uniform_enabled_);
subscription_set_.insert(target);
const gpu::ValueState* state = pending_valuebuffer_state_->GetState(target);
if (state) {
SendUpdateValueState(target, *state);
}
}
void RenderProcessHostImpl::OnRemoveSubscription(unsigned int target) {
DCHECK(subscribe_uniform_enabled_);
subscription_set_.erase(target);
}
void RenderProcessHostImpl::SendUpdateValueState(unsigned int target,
const gpu::ValueState& state) {
DCHECK(subscribe_uniform_enabled_);
if (subscription_set_.find(target) != subscription_set_.end()) {
GpuProcessHost::SendOnIO(
GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH,
new GpuMsg_UpdateValueState(id_, target, state));
} else {
// Store the ValueState locally in case a Valuebuffer subscribes to it later
pending_valuebuffer_state_->UpdateState(target, state);
}
}
void RenderProcessHostImpl::AddRoute(
int32 routing_id,
IPC::Listener* listener) {
......
......@@ -33,6 +33,10 @@ namespace gfx {
class Size;
}
namespace gpu {
class ValueStateMap;
}
namespace IPC {
class ChannelMojoHost;
}
......@@ -140,6 +144,11 @@ class CONTENT_EXPORT RenderProcessHostImpl
void NotifyTimezoneChange() override;
ServiceRegistry* GetServiceRegistry() override;
const base::TimeTicks& GetInitTimeForNavigationMetrics() const override;
bool SubscribeUniformEnabled() const override;
void OnAddSubscription(unsigned int target) override;
void OnRemoveSubscription(unsigned int target) override;
void SendUpdateValueState(
unsigned int target, const gpu::ValueState& state) override;
// IPC::Sender via RenderProcessHost.
bool Send(IPC::Message* msg) override;
......@@ -470,6 +479,20 @@ class CONTENT_EXPORT RenderProcessHostImpl
// Context shared for each PermissionService instance created for this RPH.
scoped_ptr<PermissionServiceContext> permission_service_context_;
// This is a set of all subscription targets valuebuffers in the GPU process
// are currently subscribed too. Used to prevent sending unnecessary
// ValueState updates.
typedef base::hash_set<unsigned int> SubscriptionSet;
SubscriptionSet subscription_set_;
// Maintains ValueStates which are not currently subscribed too so we can
// pass them to the GpuService if a Valuebuffer ever subscribes to the
// respective subscription target
scoped_refptr<gpu::ValueStateMap> pending_valuebuffer_state_;
// Whether or not the CHROMIUM_subscribe_uniform WebGL extension is enabled
bool subscribe_uniform_enabled_;
base::WeakPtrFactory<RenderProcessHostImpl> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(RenderProcessHostImpl);
......
......@@ -183,7 +183,6 @@ RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
pending_mouse_lock_request_(false),
allow_privileged_mouse_lock_(false),
has_touch_handler_(false),
subscribe_uniform_enabled_(false),
next_browser_snapshot_id_(1),
weak_factory_(this) {
CHECK(delegate_);
......@@ -233,10 +232,6 @@ RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
base::Bind(&RenderWidgetHostImpl::RendererIsUnresponsive,
weak_factory_.GetWeakPtr())));
}
subscribe_uniform_enabled_ =
base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableSubscribeUniformExtension);
}
RenderWidgetHostImpl::~RenderWidgetHostImpl() {
......@@ -902,17 +897,13 @@ void RenderWidgetHostImpl::ForwardMouseEventWithLatencyInfo(
// Pass mouse state to gpu service if the subscribe uniform
// extension is enabled.
// TODO(orglofch): Only pass mouse information if one of the GL Contexts
// is subscribed to GL_MOUSE_POSITION_CHROMIUM
if (subscribe_uniform_enabled_) {
if (process_->SubscribeUniformEnabled()) {
gpu::ValueState state;
state.int_value[0] = mouse_event.x;
state.int_value[1] = mouse_event.y;
GpuProcessHost::SendOnIO(
GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH,
new GpuMsg_UpdateValueState(
process_->GetID(), GL_MOUSE_POSITION_CHROMIUM, state));
// TODO(orglofch) Separate the mapping of pending value states to the
// Gpu Service to be per RWH not per process
process_->SendUpdateValueState(GL_MOUSE_POSITION_CHROMIUM, state);
}
}
......
......@@ -825,8 +825,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl
RenderWidgetHostLatencyTracker latency_tracker_;
bool subscribe_uniform_enabled_;
int next_browser_snapshot_id_;
typedef std::map<int,
base::Callback<void(const unsigned char*, size_t)> > PendingSnapshotMap;
......
......@@ -29,6 +29,7 @@
#include "gpu/command_buffer/service/image_factory.h"
#include "gpu/command_buffer/service/mailbox_manager_impl.h"
#include "gpu/command_buffer/service/sync_point_manager.h"
#include "gpu/command_buffer/service/valuebuffer_manager.h"
#include "ipc/ipc_channel.h"
#include "ipc/message_filter.h"
#include "ui/gl/gl_context.h"
......@@ -425,10 +426,14 @@ GpuChannel::GpuChannel(GpuChannelManager* gpu_channel_manager,
const base::CommandLine* command_line =
base::CommandLine::ForCurrentProcess();
log_messages_ = command_line->HasSwitch(switches::kLogPluginMessages);
subscription_ref_set_ = new gpu::gles2::SubscriptionRefSet();
subscription_ref_set_->AddObserver(this);
}
GpuChannel::~GpuChannel() {
STLDeleteElements(&deferred_messages_);
subscription_ref_set_->RemoveObserver(this);
if (preempting_flag_.get())
preempting_flag_->Reset();
}
......@@ -512,6 +517,16 @@ bool GpuChannel::Send(IPC::Message* message) {
return channel_->Send(message);
}
void GpuChannel::OnAddSubscription(unsigned int target) {
gpu_channel_manager()->Send(
new GpuHostMsg_AddSubscription(client_id_, target));
}
void GpuChannel::OnRemoveSubscription(unsigned int target) {
gpu_channel_manager()->Send(
new GpuHostMsg_RemoveSubscription(client_id_, target));
}
void GpuChannel::RequeueMessage() {
DCHECK(currently_processing_message_);
deferred_messages_.push_front(
......@@ -581,6 +596,7 @@ CreateCommandBufferResult GpuChannel::CreateViewCommandBuffer(
share_group,
window,
mailbox_manager_.get(),
subscription_ref_set_.get(),
pending_valuebuffer_state_.get(),
gfx::Size(),
disallowed_features_,
......@@ -740,6 +756,7 @@ void GpuChannel::OnCreateOffscreenCommandBuffer(
share_group,
gfx::GLSurfaceHandle(),
mailbox_manager_.get(),
subscription_ref_set_.get(),
pending_valuebuffer_state_.get(),
size,
disallowed_features_,
......
......@@ -19,6 +19,7 @@
#include "content/common/gpu/gpu_memory_manager.h"
#include "content/common/gpu/gpu_result_codes.h"
#include "content/common/message_router.h"
#include "gpu/command_buffer/service/valuebuffer_manager.h"
#include "ipc/ipc_sync_channel.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/size.h"
......@@ -37,6 +38,7 @@ class PreemptionFlag;
union ValueState;
class ValueStateMap;
namespace gles2 {
class SubscriptionRefSet;
}
}
......@@ -52,7 +54,8 @@ class GpuWatchdog;
// Encapsulates an IPC channel between the GPU process and one renderer
// process. On the renderer side there's a corresponding GpuChannelHost.
class GpuChannel : public IPC::Listener, public IPC::Sender {
class GpuChannel : public IPC::Listener, public IPC::Sender,
public gpu::gles2::SubscriptionRefSet::Observer {
public:
// Takes ownership of the renderer process handle.
GpuChannel(GpuChannelManager* gpu_channel_manager,
......@@ -99,6 +102,10 @@ class GpuChannel : public IPC::Listener, public IPC::Sender {
// unscheduling conditions.
void RequeueMessage();
// SubscriptionRefSet::Observer implementation
void OnAddSubscription(unsigned int target) override;
void OnRemoveSubscription(unsigned int target) override;
// This is called when a command buffer transitions from the unscheduled
// state to the scheduled state, which potentially means the channel
// transitions from the unscheduled to the scheduled state. When this occurs
......@@ -219,6 +226,8 @@ class GpuChannel : public IPC::Listener, public IPC::Sender {
scoped_refptr<gpu::gles2::MailboxManager> mailbox_manager_;
scoped_refptr<gpu::gles2::SubscriptionRefSet> subscription_ref_set_;
scoped_refptr<gpu::ValueStateMap> pending_valuebuffer_state_;
typedef IDMap<GpuCommandBufferStub, IDMapOwnPointer> StubMap;
......
......@@ -148,6 +148,7 @@ GpuCommandBufferStub::GpuCommandBufferStub(
GpuCommandBufferStub* share_group,
const gfx::GLSurfaceHandle& handle,
gpu::gles2::MailboxManager* mailbox_manager,
gpu::gles2::SubscriptionRefSet* subscription_ref_set,
gpu::ValueStateMap* pending_valuebuffer_state,
const gfx::Size& size,
const gpu::gles2::DisallowedFeatures& disallowed_features,
......@@ -193,6 +194,7 @@ GpuCommandBufferStub::GpuCommandBufferStub(
new GpuCommandBufferMemoryTracker(channel),
channel_->gpu_channel_manager()->shader_translator_cache(),
NULL,
subscription_ref_set,
pending_valuebuffer_state,
attrib_parser.bind_generates_resource);
}
......
......@@ -36,6 +36,7 @@ struct Mailbox;
class ValueStateMap;
namespace gles2 {
class MailboxManager;
class SubscriptionRefSet;
}
}
......@@ -70,6 +71,7 @@ class GpuCommandBufferStub
GpuCommandBufferStub* share_group,
const gfx::GLSurfaceHandle& handle,
gpu::gles2::MailboxManager* mailbox_manager,
gpu::gles2::SubscriptionRefSet* subscription_ref_set,
gpu::ValueStateMap* pending_valuebuffer_state,
const gfx::Size& size,
const gpu::gles2::DisallowedFeatures& disallowed_features,
......
......@@ -417,6 +417,18 @@ IPC_MESSAGE_CONTROL1(GpuHostMsg_GpuMemoryUmaStats,
// Response to GpuMsg_RelinquishResources.
IPC_MESSAGE_CONTROL0(GpuHostMsg_ResourcesRelinquished)
// Tells the browser that a context has subscribed to a new target and
// the browser should start sending the corresponding information
IPC_MESSAGE_CONTROL2(GpuHostMsg_AddSubscription,
int32 /* client_id */,
unsigned int /* target */);
// Tells the browser that no contexts are subscribed to the target anymore
// so the browser should stop sending the corresponding information
IPC_MESSAGE_CONTROL2(GpuHostMsg_RemoveSubscription,
int32 /* client_id */,
unsigned int /* target */);
//------------------------------------------------------------------------------
// GPU Channel Messages
// These are messages from a renderer process to the GPU process.
......
......@@ -22,6 +22,10 @@ namespace base {
class TimeDelta;
}
namespace gpu {
union ValueState;
}
namespace content {
class BrowserContext;
class BrowserMessageFilter;
......@@ -239,6 +243,18 @@ class CONTENT_EXPORT RenderProcessHost : public IPC::Sender,
// Note: Do not use! Will disappear after PlzNavitate is completed.
virtual const base::TimeTicks& GetInitTimeForNavigationMetrics() const = 0;
// Returns whether or not the CHROMIUM_subscribe_uniform WebGL extension
// is currently enabled
virtual bool SubscribeUniformEnabled() const = 0;
// Handlers for subscription target changes to update subscription_set_
virtual void OnAddSubscription(unsigned int target) = 0;
virtual void OnRemoveSubscription(unsigned int target) = 0;
// Send a new ValueState to the Gpu Service to update a subscription target
virtual void SendUpdateValueState(
unsigned int target, const gpu::ValueState& state) = 0;
// Static management functions -----------------------------------------------
// Flag to run the renderer in process. This is primarily
......
......@@ -234,6 +234,20 @@ const base::TimeTicks& MockRenderProcessHost::GetInitTimeForNavigationMetrics()
return dummy_time;
}
bool MockRenderProcessHost::SubscribeUniformEnabled() const {
return false;
}
void MockRenderProcessHost::OnAddSubscription(unsigned int target) {
}
void MockRenderProcessHost::OnRemoveSubscription(unsigned int target) {
}
void MockRenderProcessHost::SendUpdateValueState(
unsigned int target, const gpu::ValueState& state) {
}
void MockRenderProcessHost::FilterURL(bool empty_allowed, GURL* url) {
RenderProcessHostImpl::FilterURL(this, empty_allowed, url);
}
......
......@@ -83,6 +83,11 @@ class MockRenderProcessHost : public RenderProcessHost {
void NotifyTimezoneChange() override;
ServiceRegistry* GetServiceRegistry() override;
const base::TimeTicks& GetInitTimeForNavigationMetrics() const override;
bool SubscribeUniformEnabled() const override;
void OnAddSubscription(unsigned int target) override;
void OnRemoveSubscription(unsigned int target) override;
void SendUpdateValueState(
unsigned int target, const gpu::ValueState& state) override;
// IPC::Sender via RenderProcessHost.
bool Send(IPC::Message* msg) override;
......
......@@ -32,11 +32,13 @@ ContextGroup::ContextGroup(
const scoped_refptr<MemoryTracker>& memory_tracker,
const scoped_refptr<ShaderTranslatorCache>& shader_translator_cache,
const scoped_refptr<FeatureInfo>& feature_info,
const scoped_refptr<SubscriptionRefSet>& subscription_ref_set,
const scoped_refptr<ValueStateMap>& pending_valuebuffer_state,
bool bind_generates_resource)
: mailbox_manager_(mailbox_manager),
memory_tracker_(memory_tracker),
shader_translator_cache_(shader_translator_cache),
subscription_ref_set_(subscription_ref_set),
pending_valuebuffer_state_(pending_valuebuffer_state),
enforce_gl_minimums_(CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnforceGLMinimums)),
......@@ -56,6 +58,8 @@ ContextGroup::ContextGroup(
{
if (!mailbox_manager_.get())
mailbox_manager_ = new MailboxManagerImpl;
if (!subscription_ref_set_.get())
subscription_ref_set_ = new SubscriptionRefSet();
if (!pending_valuebuffer_state_.get())
pending_valuebuffer_state_ = new ValueStateMap();
if (!feature_info.get())
......@@ -128,7 +132,8 @@ bool ContextGroup::Initialize(
depth24_supported));
shader_manager_.reset(new ShaderManager());
valuebuffer_manager_.reset(
new ValuebufferManager(pending_valuebuffer_state_.get()));
new ValuebufferManager(subscription_ref_set_.get(),
pending_valuebuffer_state_.get()));
// Lookup GL things we need to know.
const GLint kGLES2RequiredMinimumVertexAttribs = 8u;
......
......@@ -36,6 +36,7 @@ class RenderbufferManager;
class ProgramManager;
class ShaderManager;
class TextureManager;
class SubscriptionRefSet;
class ValuebufferManager;
class MemoryTracker;
struct DisallowedFeatures;
......@@ -49,6 +50,7 @@ class GPU_EXPORT ContextGroup : public base::RefCounted<ContextGroup> {
const scoped_refptr<MemoryTracker>& memory_tracker,
const scoped_refptr<ShaderTranslatorCache>& shader_translator_cache,
const scoped_refptr<FeatureInfo>& feature_info,
const scoped_refptr<SubscriptionRefSet>& subscription_ref_set,
const scoped_refptr<ValueStateMap>& pending_valuebuffer_state,
bool bind_generates_resource);
......@@ -226,7 +228,8 @@ class GPU_EXPORT ContextGroup : public base::RefCounted<ContextGroup> {
scoped_refptr<MemoryTracker> memory_tracker_;
scoped_refptr<ShaderTranslatorCache> shader_translator_cache_;
scoped_ptr<TransferBufferManagerInterface> transfer_buffer_manager_;
scoped_refptr<gpu::ValueStateMap> pending_valuebuffer_state_;
scoped_refptr<SubscriptionRefSet> subscription_ref_set_;
scoped_refptr<ValueStateMap> pending_valuebuffer_state_;
bool enforce_gl_minimums_;
bool bind_generates_resource_;
......
......@@ -11,6 +11,7 @@
#include "gpu/command_buffer/service/mailbox_manager.h"
#include "gpu/command_buffer/service/test_helper.h"
#include "gpu/command_buffer/service/texture_manager.h"
#include "gpu/command_buffer/service/valuebuffer_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gl/gl_mock.h"
......@@ -39,8 +40,8 @@ class ContextGroupTest : public GpuServiceTest {
void SetUp() override {
GpuServiceTest::SetUp();
decoder_.reset(new MockGLES2Decoder());
group_ = scoped_refptr<ContextGroup>(
new ContextGroup(NULL, NULL, NULL, NULL, NULL, kBindGeneratesResource));
group_ = scoped_refptr<ContextGroup>(new ContextGroup(
NULL, NULL, NULL, NULL, NULL, NULL, kBindGeneratesResource));
}
scoped_ptr<MockGLES2Decoder> decoder_;
......
......@@ -176,6 +176,7 @@ void GLES2DecoderTestBase::InitDecoderWithCommandLine(
memory_tracker_,
new ShaderTranslatorCache,
feature_info.get(),
new SubscriptionRefSet,
new ValueStateMap,
normalized_init.bind_generates_resource));
bool use_default_textures = normalized_init.bind_generates_resource;
......
......@@ -32,6 +32,7 @@
#include "gpu/command_buffer/service/memory_tracking.h"
#include "gpu/command_buffer/service/query_manager.h"
#include "gpu/command_buffer/service/transfer_buffer_manager.h"
#include "gpu/command_buffer/service/valuebuffer_manager.h"
#include "ui/gfx/size.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_image.h"
......@@ -198,10 +199,18 @@ InProcessCommandBuffer::Service::mailbox_manager() {
return mailbox_manager_;
}
scoped_refptr<gpu::ValueStateMap>
scoped_refptr<gles2::SubscriptionRefSet>
InProcessCommandBuffer::Service::subscription_ref_set() {
if (!subscription_ref_set_.get()) {
subscription_ref_set_ = new gles2::SubscriptionRefSet();
}
return subscription_ref_set_;
}
scoped_refptr<ValueStateMap>
InProcessCommandBuffer::Service::pending_valuebuffer_state() {
if (!pending_valuebuffer_state_.get()) {
pending_valuebuffer_state_ = new gpu::ValueStateMap();
pending_valuebuffer_state_ = new ValueStateMap();
}
return pending_valuebuffer_state_;
}
......@@ -351,6 +360,7 @@ bool InProcessCommandBuffer::InitializeOnGpuThread(
NULL,
service_->shader_translator_cache(),
NULL,
service_->subscription_ref_set(),
service_->pending_valuebuffer_state(),
bind_generates_resource)));
......
......@@ -52,6 +52,7 @@ namespace gles2 {
class GLES2Decoder;
class MailboxManager;
class ShaderTranslatorCache;
class SubscriptionRefSet;
}
class CommandBufferServiceBase;
......@@ -139,10 +140,12 @@ class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer,
virtual scoped_refptr<gles2::ShaderTranslatorCache>
shader_translator_cache() = 0;
scoped_refptr<gles2::MailboxManager> mailbox_manager();
scoped_refptr<gles2::SubscriptionRefSet> subscription_ref_set();
scoped_refptr<gpu::ValueStateMap> pending_valuebuffer_state();
private:
scoped_refptr<gles2::MailboxManager> mailbox_manager_;
scoped_refptr<gles2::SubscriptionRefSet> subscription_ref_set_;
scoped_refptr<gpu::ValueStateMap> pending_valuebuffer_state_;
};
......
......@@ -9,6 +9,46 @@
namespace gpu {
namespace gles2 {
SubscriptionRefSet::Observer::~Observer() {
}
SubscriptionRefSet::SubscriptionRefSet() {
}
SubscriptionRefSet::~SubscriptionRefSet() {
// Make sure no valuebuffers are still holding references to targets
DCHECK(reference_set_.empty());
}
void SubscriptionRefSet::AddSubscription(unsigned int target) {
RefSet::iterator it = reference_set_.find(target);
if (it == reference_set_.end()) {
reference_set_.insert(std::make_pair(target, 1));
FOR_EACH_OBSERVER(Observer, observers_, OnAddSubscription(target));
} else {
++it->second;
}
}
void SubscriptionRefSet::RemoveSubscription(unsigned int target) {
RefSet::iterator it = reference_set_.find(target);
DCHECK(it != reference_set_.end());
if (it->second == 1) {
reference_set_.erase(it);
FOR_EACH_OBSERVER(Observer, observers_, OnRemoveSubscription(target));
} else {
--it->second;
}
}
void SubscriptionRefSet::AddObserver(Observer* observer) {
observers_.AddObserver(observer);
}
void SubscriptionRefSet::RemoveObserver(Observer* observer) {
observers_.RemoveObserver(observer);
}
Valuebuffer::Valuebuffer(ValuebufferManager* manager, unsigned int client_id)
: manager_(manager), client_id_(client_id), has_been_bound_(false) {
manager_->StartTracking(this);
......@@ -17,17 +57,28 @@ Valuebuffer::Valuebuffer(ValuebufferManager* manager, unsigned int client_id)
Valuebuffer::~Valuebuffer() {
if (manager_) {
for (SubscriptionSet::const_iterator it = subscriptions_.begin();
it != subscriptions_.end(); ++it) {
manager_->NotifyRemoveSubscription(*it);
}
manager_->StopTracking(this);
manager_ = NULL;
}
}
void Valuebuffer::AddSubscription(unsigned int subscription) {
if (subscriptions_.find(subscription) == subscriptions_.end()) {
subscriptions_.insert(subscription);
manager_->NotifyAddSubscription(subscription);
}
}
void Valuebuffer::RemoveSubscription(unsigned int subscription) {
subscriptions_.erase(subscription);
SubscriptionSet::iterator it = subscriptions_.find(subscription);
if (subscriptions_.find(subscription) != subscriptions_.end()) {
subscriptions_.erase(it);
manager_->NotifyRemoveSubscription(subscription);
}
}
bool Valuebuffer::IsSubscribed(unsigned int subscription) {
......@@ -49,9 +100,11 @@ void Valuebuffer::UpdateState(const ValueStateMap* pending_state) {
}
}
ValuebufferManager::ValuebufferManager(ValueStateMap* state_map)
ValuebufferManager::ValuebufferManager(SubscriptionRefSet* ref_set,
ValueStateMap* state_map)
: valuebuffer_count_(0),
pending_state_map_(state_map) {
pending_state_map_(state_map),
subscription_ref_set_(ref_set) {
}
ValuebufferManager::~ValuebufferManager() {
......@@ -73,6 +126,13 @@ void ValuebufferManager::StopTracking(Valuebuffer* /* valuebuffer */) {
--valuebuffer_count_;
}
void ValuebufferManager::NotifyAddSubscription(unsigned int target) {
subscription_ref_set_->AddSubscription(target);
}
void ValuebufferManager::NotifyRemoveSubscription(unsigned int target) {
subscription_ref_set_->RemoveSubscription(target);
}
void ValuebufferManager::CreateValuebuffer(unsigned int client_id) {
scoped_refptr<Valuebuffer> valuebuffer(new Valuebuffer(this, client_id));
std::pair<ValuebufferMap::iterator, bool> result =
......
......@@ -9,14 +9,55 @@
#include "base/containers/hash_tables.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/observer_list.h"
#include "gpu/command_buffer/common/value_state.h"
#include "gpu/gpu_export.h"
#include "ipc/ipc_sender.h"
namespace content {
class GpuChannel;
}
namespace gpu {
namespace gles2 {
class ValuebufferManager;
class GPU_EXPORT SubscriptionRefSet
: public base::RefCounted<SubscriptionRefSet> {
public:
class GPU_EXPORT Observer {
public:
virtual ~Observer();
virtual void OnAddSubscription(unsigned int target) = 0;
virtual void OnRemoveSubscription(unsigned int target) = 0;
};
SubscriptionRefSet();
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
protected:
virtual ~SubscriptionRefSet();
private:
friend class base::RefCounted<SubscriptionRefSet>;
friend class ValuebufferManager;
typedef base::hash_map<unsigned int, int> RefSet;
void AddSubscription(unsigned int target);
void RemoveSubscription(unsigned int target);
RefSet reference_set_;
ObserverList<Observer, true> observers_;
DISALLOW_COPY_AND_ASSIGN(SubscriptionRefSet);
};
class GPU_EXPORT Valuebuffer : public base::RefCounted<Valuebuffer> {
public:
Valuebuffer(ValuebufferManager* manager, unsigned int client_id);
......@@ -67,7 +108,7 @@ class GPU_EXPORT Valuebuffer : public base::RefCounted<Valuebuffer> {
class GPU_EXPORT ValuebufferManager {
public:
ValuebufferManager(ValueStateMap* state_map);
ValuebufferManager(SubscriptionRefSet* ref_set, ValueStateMap* state_map);
~ValuebufferManager();
// Must call before destruction.
......@@ -96,6 +137,9 @@ class GPU_EXPORT ValuebufferManager {
void StartTracking(Valuebuffer* valuebuffer);
void StopTracking(Valuebuffer* valuebuffer);
void NotifyAddSubscription(unsigned int target);
void NotifyRemoveSubscription(unsigned int target);
// Counts the number of Valuebuffer allocated with 'this' as its manager.
// Allows to check no Valuebuffer will outlive this.
unsigned int valuebuffer_count_;
......@@ -107,6 +151,10 @@ class GPU_EXPORT ValuebufferManager {
// Updated by GpuChannel
scoped_refptr<ValueStateMap> pending_state_map_;
// Subscription targets which are currently subscribed and how
// many value buffers are currently subscribed to each
scoped_refptr<SubscriptionRefSet> subscription_ref_set_;
DISALLOW_COPY_AND_ASSIGN(ValuebufferManager);
};
......
......@@ -15,6 +15,7 @@
#include "gpu/command_buffer/service/gpu_service_test.h"
#include "gpu/command_buffer/service/mocks.h"
#include "gpu/command_buffer/service/test_helper.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_mock.h"
......@@ -22,6 +23,12 @@
namespace gpu {
namespace gles2 {
class MockSubscriptionRefSetObserver : public SubscriptionRefSet::Observer {
public:
MOCK_METHOD1(OnAddSubscription, void(unsigned int target));
MOCK_METHOD1(OnRemoveSubscription, void(unsigned int target));
};
class ValuebufferManagerTest : public GpuServiceTest {
public:
ValuebufferManagerTest() {}
......@@ -29,16 +36,23 @@ class ValuebufferManagerTest : public GpuServiceTest {
void SetUp() override {
GpuServiceTest::SetUp();
subscription_ref_set_ = new SubscriptionRefSet();
pending_state_map_ = new ValueStateMap();
manager_.reset(new ValuebufferManager(pending_state_map_.get()));
subscription_ref_set_->AddObserver(&mock_observer_);
manager_.reset(new ValuebufferManager(subscription_ref_set_.get(),
pending_state_map_.get()));
}
void TearDown() override {
manager_->Destroy();
subscription_ref_set_->RemoveObserver(&mock_observer_);
GpuServiceTest::TearDown();
}
protected:
MockSubscriptionRefSetObserver mock_observer_;
scoped_refptr<SubscriptionRefSet> subscription_ref_set_;
scoped_refptr<ValueStateMap> pending_state_map_;
scoped_ptr<ValuebufferManager> manager_;
};
......@@ -109,5 +123,30 @@ TEST_F(ValuebufferManagerTest, UpdateState) {
ASSERT_TRUE(new_state2->int_value[0] == 222);
}
TEST_F(ValuebufferManagerTest, NotifySubscriptionRefs) {
const GLuint kClientId1 = 1;
const GLuint kClientId2 = 2;
manager_->CreateValuebuffer(kClientId1);
Valuebuffer* valuebuffer1 = manager_->GetValuebuffer(kClientId1);
ASSERT_TRUE(valuebuffer1 != NULL);
manager_->CreateValuebuffer(kClientId2);
Valuebuffer* valuebuffer2 = manager_->GetValuebuffer(kClientId2);
ASSERT_TRUE(valuebuffer2 != NULL);
EXPECT_CALL(mock_observer_, OnAddSubscription(GL_MOUSE_POSITION_CHROMIUM))
.Times(1);
valuebuffer1->AddSubscription(GL_MOUSE_POSITION_CHROMIUM);
EXPECT_CALL(mock_observer_, OnAddSubscription(GL_MOUSE_POSITION_CHROMIUM))
.Times(0);
valuebuffer2->AddSubscription(GL_MOUSE_POSITION_CHROMIUM);
EXPECT_CALL(mock_observer_, OnRemoveSubscription(GL_MOUSE_POSITION_CHROMIUM))
.Times(0);
valuebuffer1->RemoveSubscription(GL_MOUSE_POSITION_CHROMIUM);
// Ensure the manager still thinks a buffer has a reference to the
// subscription target.
EXPECT_CALL(mock_observer_, OnRemoveSubscription(GL_MOUSE_POSITION_CHROMIUM))
.Times(1);
valuebuffer2->RemoveSubscription(GL_MOUSE_POSITION_CHROMIUM);
}
} // namespace gles2
} // namespace gpu
......@@ -27,6 +27,7 @@
#include "gpu/command_buffer/service/image_manager.h"
#include "gpu/command_buffer/service/mailbox_manager_impl.h"
#include "gpu/command_buffer/service/memory_tracking.h"
#include "gpu/command_buffer/service/valuebuffer_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/gpu_memory_buffer.h"
#include "ui/gl/gl_context.h"
......@@ -205,6 +206,7 @@ void GLManager::InitializeWithCommandLine(const GLManager::Options& options,
new gpu::gles2::ShaderTranslatorCache,
feature_info,
NULL,
NULL,
options.bind_generates_resource);
}
......
......@@ -15,6 +15,7 @@
#include "gpu/command_buffer/service/mailbox_manager.h"
#include "gpu/command_buffer/service/memory_tracking.h"
#include "gpu/command_buffer/service/transfer_buffer_manager.h"
#include "gpu/command_buffer/service/valuebuffer_manager.h"
#include "gpu/gles2_conform_support/egl/config.h"
#include "gpu/gles2_conform_support/egl/surface.h"
......@@ -115,8 +116,14 @@ EGLSurface Display::CreateWindowSurface(EGLConfig config,
if (!command_buffer->Initialize())
return NULL;
scoped_refptr<gpu::gles2::ContextGroup> group(new gpu::gles2::ContextGroup(
NULL, NULL, new gpu::gles2::ShaderTranslatorCache, NULL, NULL, true));
scoped_refptr<gpu::gles2::ContextGroup> group(
new gpu::gles2::ContextGroup(NULL,
NULL,
new gpu::gles2::ShaderTranslatorCache,
NULL,
NULL,
NULL,
true));
decoder_.reset(gpu::gles2::GLES2Decoder::Create(group.get()));
if (!decoder_.get())
......
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