Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / content / browser / gpu / browser_gpu_channel_host_factory.cc
index 156dd89..29adc69 100644 (file)
@@ -8,7 +8,9 @@
 #include "base/debug/trace_event.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/threading/thread_restrictions.h"
+#include "base/tracked_objects.h"
 #include "content/browser/gpu/gpu_data_manager_impl.h"
+#include "content/browser/gpu/gpu_memory_buffer_factory_host_impl.h"
 #include "content/browser/gpu/gpu_process_host.h"
 #include "content/browser/gpu/gpu_surface_tracker.h"
 #include "content/common/child_process_host_impl.h"
@@ -26,8 +28,10 @@ namespace content {
 BrowserGpuChannelHostFactory* BrowserGpuChannelHostFactory::instance_ = NULL;
 
 struct BrowserGpuChannelHostFactory::CreateRequest {
-  CreateRequest()
-      : event(true, false), gpu_host_id(0), route_id(MSG_ROUTING_NONE),
+  CreateRequest(int32 route_id)
+      : event(true, false),
+        gpu_host_id(0),
+        route_id(route_id),
         result(CREATE_COMMAND_BUFFER_FAILED) {}
   ~CreateRequest() {}
   base::WaitableEvent event;
@@ -36,6 +40,28 @@ struct BrowserGpuChannelHostFactory::CreateRequest {
   CreateCommandBufferResult result;
 };
 
+struct BrowserGpuChannelHostFactory::AllocateGpuMemoryBufferRequest {
+  AllocateGpuMemoryBufferRequest(size_t width,
+                                 size_t height,
+                                 unsigned internalformat,
+                                 unsigned usage,
+                                 int client_id)
+      : event(true, false),
+        width(width),
+        height(height),
+        internalformat(internalformat),
+        usage(usage),
+        client_id(client_id) {}
+  ~AllocateGpuMemoryBufferRequest() {}
+  base::WaitableEvent event;
+  size_t width;
+  size_t height;
+  unsigned internalformat;
+  unsigned usage;
+  int client_id;
+  scoped_ptr<gfx::GpuMemoryBuffer> result;
+};
+
 class BrowserGpuChannelHostFactory::EstablishRequest
     : public base::RefCountedThreadSafe<EstablishRequest> {
  public:
@@ -171,6 +197,11 @@ void BrowserGpuChannelHostFactory::EstablishRequest::FinishOnMain() {
 void BrowserGpuChannelHostFactory::EstablishRequest::Wait() {
   DCHECK(main_loop_->BelongsToCurrentThread());
   {
+    // Since the current task synchronously waits for establishing a GPU
+    // channel, it shouldn't be tallied because its execution time has nothing
+    // to do with its efficiency. Using task stopwatch to exclude the waiting
+    // time from the current task run time.
+    tracked_objects::TaskStopwatch stopwatch;
     // We're blocking the UI thread, which is generally undesirable.
     // In this case we need to wait for this before we can show any UI
     // /anyway/, so it won't cause additional jank.
@@ -179,6 +210,8 @@ void BrowserGpuChannelHostFactory::EstablishRequest::Wait() {
                  "BrowserGpuChannelHostFactory::EstablishGpuChannelSync");
     base::ThreadRestrictions::ScopedAllowWait allow_wait;
     event_.Wait();
+
+    stopwatch.Stop();
   }
   FinishOnMain();
 }
@@ -210,13 +243,13 @@ void BrowserGpuChannelHostFactory::Terminate() {
 BrowserGpuChannelHostFactory::BrowserGpuChannelHostFactory()
     : gpu_client_id_(ChildProcessHostImpl::GenerateChildProcessUniqueId()),
       shutdown_event_(new base::WaitableEvent(true, false)),
-      gpu_host_id_(0),
-      next_create_gpu_memory_buffer_request_id_(0) {
+      gpu_memory_buffer_factory_host_(new GpuMemoryBufferFactoryHostImpl),
+      gpu_host_id_(0) {
 }
 
 BrowserGpuChannelHostFactory::~BrowserGpuChannelHostFactory() {
   DCHECK(IsMainThread());
-  if (pending_request_)
+  if (pending_request_.get())
     pending_request_->Cancel();
   for (size_t n = 0; n < established_callbacks_.size(); n++)
     established_callbacks_[n].Run();
@@ -278,8 +311,7 @@ CreateCommandBufferResult BrowserGpuChannelHostFactory::CreateViewCommandBuffer(
       int32 surface_id,
       const GPUCreateCommandBufferConfig& init_params,
       int32 route_id) {
-  CreateRequest request;
-  request.route_id = route_id;
+  CreateRequest request(route_id);
   GetIOLoopProxy()->PostTask(FROM_HERE, base::Bind(
         &BrowserGpuChannelHostFactory::CreateViewCommandBufferOnIO,
         base::Unretained(this),
@@ -301,7 +333,7 @@ GpuChannelHost* BrowserGpuChannelHostFactory::EstablishGpuChannelSync(
     CauseForGpuLaunch cause_for_gpu_launch) {
   EstablishGpuChannel(cause_for_gpu_launch, base::Closure());
 
-  if (pending_request_)
+  if (pending_request_.get())
     pending_request_->Wait();
 
   return gpu_channel_.get();
@@ -311,19 +343,19 @@ void BrowserGpuChannelHostFactory::EstablishGpuChannel(
     CauseForGpuLaunch cause_for_gpu_launch,
     const base::Closure& callback) {
   if (gpu_channel_.get() && gpu_channel_->IsLost()) {
-    DCHECK(!pending_request_);
+    DCHECK(!pending_request_.get());
     // Recreate the channel if it has been lost.
     gpu_channel_ = NULL;
   }
 
-  if (!gpu_channel_ && !pending_request_) {
+  if (!gpu_channel_.get() && !pending_request_.get()) {
     // We should only get here if the context was lost.
     pending_request_ = EstablishRequest::Create(
         cause_for_gpu_launch, gpu_client_id_, gpu_host_id_);
   }
 
   if (!callback.is_null()) {
-    if (gpu_channel_)
+    if (gpu_channel_.get())
       callback.Run();
     else
       established_callbacks_.push_back(callback);
@@ -331,17 +363,17 @@ void BrowserGpuChannelHostFactory::EstablishGpuChannel(
 }
 
 GpuChannelHost* BrowserGpuChannelHostFactory::GetGpuChannel() {
-  if (gpu_channel_ && !gpu_channel_->IsLost())
-    return gpu_channel_;
+  if (gpu_channel_.get() && !gpu_channel_->IsLost())
+    return gpu_channel_.get();
 
   return NULL;
 }
 
 void BrowserGpuChannelHostFactory::GpuChannelEstablished() {
   DCHECK(IsMainThread());
-  DCHECK(pending_request_);
+  DCHECK(pending_request_.get());
   if (pending_request_->channel_handle().name.empty()) {
-    DCHECK(!gpu_channel_);
+    DCHECK(!gpu_channel_.get());
   } else {
     GetContentClient()->SetGpuInfo(pending_request_->gpu_info());
     gpu_channel_ = GpuChannelHost::Create(this,
@@ -350,6 +382,7 @@ void BrowserGpuChannelHostFactory::GpuChannelEstablished() {
                                           shutdown_event_.get());
   }
   gpu_host_id_ = pending_request_->gpu_host_id();
+  gpu_memory_buffer_factory_host_->set_gpu_host_id(gpu_host_id_);
   pending_request_ = NULL;
 
   for (size_t n = 0; n < established_callbacks_.size(); n++)
@@ -363,13 +396,21 @@ BrowserGpuChannelHostFactory::AllocateGpuMemoryBuffer(size_t width,
                                                       size_t height,
                                                       unsigned internalformat,
                                                       unsigned usage) {
-  if (!GpuMemoryBufferImpl::IsFormatValid(internalformat) ||
-      !GpuMemoryBufferImpl::IsUsageValid(usage))
-    return scoped_ptr<gfx::GpuMemoryBuffer>();
+  DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
 
-  return GpuMemoryBufferImpl::Create(gfx::Size(width, height),
-                                     internalformat,
-                                     usage).PassAs<gfx::GpuMemoryBuffer>();
+  AllocateGpuMemoryBufferRequest request(
+      width, height, internalformat, usage, gpu_client_id_);
+  GetIOLoopProxy()->PostTask(
+      FROM_HERE,
+      base::Bind(&BrowserGpuChannelHostFactory::AllocateGpuMemoryBufferOnIO,
+                 base::Unretained(&request)));
+
+  // We're blocking the UI thread, which is generally undesirable.
+  TRACE_EVENT0("browser",
+               "BrowserGpuChannelHostFactory::AllocateGpuMemoryBuffer");
+  base::ThreadRestrictions::ScopedAllowWait allow_wait;
+  request.event.Wait();
+  return request.result.Pass();
 }
 
 // static
@@ -406,90 +447,33 @@ void BrowserGpuChannelHostFactory::SetHandlerForControlMessages(
                  filter));
 }
 
-void BrowserGpuChannelHostFactory::CreateGpuMemoryBuffer(
-    const gfx::GpuMemoryBufferHandle& handle,
-    const gfx::Size& size,
-    unsigned internalformat,
-    unsigned usage,
-    const CreateGpuMemoryBufferCallback& callback) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  uint32 request_id = next_create_gpu_memory_buffer_request_id_++;
-  create_gpu_memory_buffer_requests_[request_id] = callback;
-  GetIOLoopProxy()->PostTask(
-      FROM_HERE,
-      base::Bind(&BrowserGpuChannelHostFactory::CreateGpuMemoryBufferOnIO,
-                 base::Unretained(this),
-                 handle,
-                 size,
-                 internalformat,
-                 usage,
-                 request_id));
-}
-
-void BrowserGpuChannelHostFactory::DestroyGpuMemoryBuffer(
-    const gfx::GpuMemoryBufferHandle& handle,
-    int32 sync_point) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  GetIOLoopProxy()->PostTask(
-      FROM_HERE,
-      base::Bind(&BrowserGpuChannelHostFactory::DestroyGpuMemoryBufferOnIO,
-                 base::Unretained(this),
-                 handle,
-                 sync_point));
-}
-
-void BrowserGpuChannelHostFactory::CreateGpuMemoryBufferOnIO(
-    const gfx::GpuMemoryBufferHandle& handle,
-    const gfx::Size& size,
-    unsigned internalformat,
-    unsigned usage,
-    uint32 request_id) {
-  GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_);
-  if (!host) {
-    GpuMemoryBufferCreatedOnIO(request_id, gfx::GpuMemoryBufferHandle());
+// static
+void BrowserGpuChannelHostFactory::AllocateGpuMemoryBufferOnIO(
+    AllocateGpuMemoryBufferRequest* request) {
+  if (!GpuMemoryBufferImpl::IsFormatValid(request->internalformat) ||
+      !GpuMemoryBufferImpl::IsUsageValid(request->usage)) {
+    request->result = scoped_ptr<gfx::GpuMemoryBuffer>();
+    request->event.Signal();
     return;
   }
 
-  host->CreateGpuMemoryBuffer(
-      handle,
-      size,
-      internalformat,
-      usage,
-      base::Bind(&BrowserGpuChannelHostFactory::GpuMemoryBufferCreatedOnIO,
-                 base::Unretained(this),
-                 request_id));
-}
-
-void BrowserGpuChannelHostFactory::GpuMemoryBufferCreatedOnIO(
-    uint32 request_id,
-    const gfx::GpuMemoryBufferHandle& handle) {
-  BrowserThread::PostTask(
-      BrowserThread::UI,
-      FROM_HERE,
+  GpuMemoryBufferImpl::Create(
+      gfx::Size(request->width, request->height),
+      request->internalformat,
+      request->usage,
+      request->client_id,
       base::Bind(&BrowserGpuChannelHostFactory::OnGpuMemoryBufferCreated,
-                 base::Unretained(this),
-                 request_id,
-                 handle));
+                 base::Unretained(request)));
 }
 
+// static
 void BrowserGpuChannelHostFactory::OnGpuMemoryBufferCreated(
-    uint32 request_id,
-    const gfx::GpuMemoryBufferHandle& handle) {
-  CreateGpuMemoryBufferCallbackMap::iterator iter =
-      create_gpu_memory_buffer_requests_.find(request_id);
-  DCHECK(iter != create_gpu_memory_buffer_requests_.end());
-  iter->second.Run(handle);
-  create_gpu_memory_buffer_requests_.erase(iter);
-}
-
-void BrowserGpuChannelHostFactory::DestroyGpuMemoryBufferOnIO(
-    const gfx::GpuMemoryBufferHandle& handle,
-    int32 sync_point) {
-  GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_);
-  if (!host)
-    return;
+    AllocateGpuMemoryBufferRequest* request,
+    scoped_ptr<GpuMemoryBufferImpl> buffer) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
 
-  host->DestroyGpuMemoryBuffer(handle, sync_point);
+  request->result = buffer.PassAs<gfx::GpuMemoryBuffer>();
+  request->event.Signal();
 }
 
 }  // namespace content