Create new GLSurface for cross process image transport.

Currently cross process image transport (on OSX and TOUCH_UI) uses the WebGL code path to render to a texture via FBO. This makes a clean break with path and centralizes the GL context specific IPC communication in one location.

By separating from the WebGL code, I was able to avoid wasting a texture attached to the FBO in the decoder (the old code ignored this attachment --- the new code makes no such attachment at the decoder level).

As a test of the new architecture, I have also implemented XComposite/GLX_texture_from_pixmap image transport (i.e. it's now possible to use the --use-gl=desktop backend on touch_ui builds).

BUG=none
TEST=3D CSS and WebGL on TOUCH_UI.

Review URL: http://codereview.chromium.org/7395020

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@93681 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/content/common/gpu/gpu_command_buffer_stub.cc b/content/common/gpu/gpu_command_buffer_stub.cc
index 3890e81..b86750a 100644
--- a/content/common/gpu/gpu_command_buffer_stub.cc
+++ b/content/common/gpu/gpu_command_buffer_stub.cc
@@ -22,6 +22,8 @@
 
 #if defined(OS_WIN)
 #include "base/win/wrapped_window_proc.h"
+#elif defined(TOUCH_UI)
+#include "content/common/gpu/image_transport_surface_linux.h"
 #endif
 
 using gpu::Buffer;
@@ -115,14 +117,19 @@
   return !scheduler_.get() || scheduler_->IsScheduled();
 }
 
+void GpuCommandBufferStub::OnInitializeFailed(IPC::Message* reply_message) {
+  scheduler_.reset();
+  command_buffer_.reset();
+  GpuCommandBufferMsg_Initialize::WriteReplyParams(reply_message, false);
+  Send(reply_message);
+}
+
 void GpuCommandBufferStub::OnInitialize(
     base::SharedMemoryHandle ring_buffer,
     int32 size,
     IPC::Message* reply_message) {
   DCHECK(!command_buffer_.get());
 
-  bool result = false;
-
   command_buffer_.reset(new gpu::CommandBufferService);
 
 #if defined(OS_WIN)
@@ -142,6 +149,41 @@
     scheduler_.reset(gpu::GpuScheduler::Create(command_buffer_.get(),
                                                channel_,
                                                NULL));
+#if defined(TOUCH_UI)
+    if (software_) {
+      OnInitializeFailed(reply_message);
+      return;
+    }
+
+    scoped_refptr<gfx::GLSurface> surface;
+    if (handle_)
+      surface = ImageTransportSurface::CreateSurface(this);
+    else
+      surface = gfx::GLSurface::CreateOffscreenGLSurface(software_,
+                                                         gfx::Size(1, 1));
+    if (!surface.get()) {
+      LOG(ERROR) << "GpuCommandBufferStub: failed to create surface.";
+      OnInitializeFailed(reply_message);
+      return;
+    }
+
+    scoped_refptr<gfx::GLContext> context(
+        gfx::GLContext::CreateGLContext(channel_->share_group(),
+                                        surface.get()));
+    if (!context.get()) {
+      LOG(ERROR) << "GpuCommandBufferStub: failed to create context.";
+      OnInitializeFailed(reply_message);
+      return;
+    }
+
+    if (scheduler_->InitializeCommon(
+        surface,
+        context,
+        initial_size_,
+        disallowed_extensions_,
+        allowed_extensions_.c_str(),
+        requested_attribs_)) {
+#else
     if (scheduler_->Initialize(
         handle_,
         initial_size_,
@@ -150,6 +192,7 @@
         allowed_extensions_.c_str(),
         requested_attribs_,
         channel_->share_group())) {
+#endif
       command_buffer_->SetPutOffsetChangeCallback(
           NewCallback(scheduler_.get(),
                       &gpu::GpuScheduler::PutChanged));
@@ -165,7 +208,7 @@
         scheduler_->SetCommandProcessedCallback(
             NewCallback(this, &GpuCommandBufferStub::OnCommandProcessed));
 
-#if defined(OS_MACOSX) || defined(TOUCH_UI)
+#if defined(OS_MACOSX)
       if (handle_) {
         // This context conceptually puts its output directly on the
         // screen, rendered by the accelerated plugin layer in
@@ -175,12 +218,19 @@
             NewCallback(this,
                         &GpuCommandBufferStub::SwapBuffersCallback));
       }
-#endif  // defined(OS_MACOSX) || defined(TOUCH_UI)
+#endif  // defined(OS_MACOSX)
 
       // Set up a pathway for resizing the output window or framebuffer at the
       // right time relative to other GL commands.
+#if defined(TOUCH_UI)
+      if (handle_ == gfx::kNullPluginWindow) {
+        scheduler_->SetResizeCallback(
+            NewCallback(this, &GpuCommandBufferStub::ResizeCallback));
+      }
+#else
       scheduler_->SetResizeCallback(
           NewCallback(this, &GpuCommandBufferStub::ResizeCallback));
+#endif
 
       if (parent_stub_for_initialization_) {
         scheduler_->SetParent(parent_stub_for_initialization_->scheduler_.get(),
@@ -189,14 +239,13 @@
         parent_texture_for_initialization_ = 0;
       }
 
-      result = true;
     } else {
-      scheduler_.reset();
-      command_buffer_.reset();
+      OnInitializeFailed(reply_message);
+      return;
     }
   }
 
-  GpuCommandBufferMsg_Initialize::WriteReplyParams(reply_message, result);
+  GpuCommandBufferMsg_Initialize::WriteReplyParams(reply_message, true);
   Send(reply_message);
 }
 
@@ -438,34 +487,7 @@
 
   scheduler_->SetScheduled(false);
 }
-#endif  // defined(OS_MACOSX)
 
-#if defined(TOUCH_UI)
-void GpuCommandBufferStub::SwapBuffersCallback() {
-  TRACE_EVENT0("gpu", "GpuCommandBufferStub::SwapBuffersCallback");
-  GpuChannelManager* gpu_channel_manager = channel_->gpu_channel_manager();
-  GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params;
-  params.renderer_id = renderer_id_;
-  params.render_view_id = render_view_id_;
-  params.surface_id = scheduler_->GetFrontSurfaceId();
-  params.route_id = route_id();
-  params.swap_buffers_count = scheduler_->swap_buffers_count();
-  gpu_channel_manager->Send(
-      new GpuHostMsg_AcceleratedSurfaceBuffersSwapped(params));
-
-  scheduler_->SetScheduled(false);
-}
-
-void GpuCommandBufferStub::AcceleratedSurfaceIOSurfaceSet(uint64 surface_id) {
-  scheduler_->SetScheduled(true);
-}
-
-void GpuCommandBufferStub::AcceleratedSurfaceReleased(uint64 surface_id) {
-  scheduler_->ReleaseSurface(surface_id);
-}
-#endif  // defined(TOUCH_UI)
-
-#if defined(OS_MACOSX) || defined(TOUCH_UI)
 void GpuCommandBufferStub::AcceleratedSurfaceBuffersSwapped(
     uint64 swap_buffers_count) {
   TRACE_EVENT1("gpu",
@@ -485,7 +507,7 @@
     scheduler_->SetScheduled(true);
   }
 }
-#endif  // defined(OS_MACOSX) || defined(TOUCH_UI)
+#endif  // defined(OS_MACOSX)
 
 void GpuCommandBufferStub::AddSetTokenCallback(
     const base::Callback<void(int32)>& callback) {
@@ -511,31 +533,6 @@
                                   size));
 
     scheduler_->SetScheduled(false);
-#elif defined(TOUCH_UI)
-    if (scheduler_->GetBackSurfaceId()) {
-      GpuHostMsg_AcceleratedSurfaceRelease_Params params;
-      params.renderer_id = renderer_id_;
-      params.render_view_id = render_view_id_;
-      params.identifier = scheduler_->GetBackSurfaceId();
-      params.route_id = route_id();
-
-      GpuChannelManager* gpu_channel_manager = channel_->gpu_channel_manager();
-      gpu_channel_manager->Send(
-          new GpuHostMsg_AcceleratedSurfaceRelease(params));
-    }
-    scheduler_->CreateBackSurface(size);
-    GpuHostMsg_AcceleratedSurfaceSetIOSurface_Params params;
-    params.renderer_id = renderer_id_;
-    params.render_view_id = render_view_id_;
-    params.width = size.width();
-    params.height = size.height();
-    params.identifier = scheduler_->GetBackSurfaceId();
-    params.route_id = route_id();
-
-    GpuChannelManager* gpu_channel_manager = channel_->gpu_channel_manager();
-    gpu_channel_manager->Send(
-        new GpuHostMsg_AcceleratedSurfaceSetIOSurface(params));
-    scheduler_->SetScheduled(false);
 #endif
   }
 }