Implement Delegate renderer using frame buffer object on Tizen.
authorvenu.musham <venu.musham@samsung.com>
Fri, 24 Apr 2015 14:08:28 +0000 (19:38 +0530)
committerYoungsoo Choi <kenshin.choi@samsung.com>
Tue, 10 Jul 2018 06:57:09 +0000 (06:57 +0000)
In Tizen, only web contents parts of the browser window in an OpenGL surface
drawn by chromium. The rest of the window is drawn using evas reference
browser/mini browser. This is because we don't have a way to draw on native
surface. evas direct rendering does not support calling native surface swap
from different thread.

To solve this problem, we composite to intermediate texture and use this
texture for rendering on evas native surface.

1. When renderer has new frame that it wants drawn, it sends a
   ViewHostMsg_SwapCompositorFrame to browser process.

2. Browser process takes frame from renderer and passes to RWHV.

3. Frame is passed to DelegatedFrameHost (DFH), which acts as interface
   between ui::Compositor and the renderer.

4. DFH tells the ui::Compositor to draw a new frame with updated
   contents.

5. ui::Compositor requests for commit operation(to draw frame).

6. On receiving commit, ui::Compositor renders frame onto frame buffer
   object created by MailboxOutputSurfaceEfl::EnsureBackBuffer().

7. When done drawing the frame, ui::Compositor's
   cc::LayerTreeHostImpl's cc:OutPutSurface will issue glSwapBuffers
   to GPU process.
   cc::Compositor will be blocked until cc::OutPutSurface client calls
   its OnSwapBuffersComplete().

8. The command buffer will decode and call
   MailboxOutputSurfaceEfl::SwapBuffers(), this will send texture_id
   from FBO to RWHV and calls evas_object_image_pixels_dirty_set() to
   invalidate evas surface and draw updated texture by calling
   glBindTexture(texture_id).

9. After this, cc::Compositor is unblocked, allowing the
   ui::Compositor to produce more frames. DFH::SendDelegatedFrameAck
   is called, which sends ViewHostMsg_SwapCompositorAck to the renderer
   process to produce another frame.
Reviewed by: DaeHyun Ko, KwangHyuk Kim, Prashant Nevase

Change-Id: I539f8aa0333a5a0dde6c921085af11ca7d9c1dc4
Signed-off-by: venu.musham <venu.musham@samsung.com>
tizen_src/chromium_impl/content/browser/renderer_host/context_factory_efl.cc [new file with mode: 0644]
tizen_src/chromium_impl/content/browser/renderer_host/context_factory_efl.h [new file with mode: 0644]
tizen_src/chromium_impl/content/browser/renderer_host/render_widget_host_view_efl.cc
tizen_src/chromium_impl/content/browser/renderer_host/render_widget_host_view_efl.h
tizen_src/chromium_impl/content/content_efl.gypi
tizen_src/chromium_impl/efl/init.cc

diff --git a/tizen_src/chromium_impl/content/browser/renderer_host/context_factory_efl.cc b/tizen_src/chromium_impl/content/browser/renderer_host/context_factory_efl.cc
new file mode 100644 (file)
index 0000000..9f72f4f
--- /dev/null
@@ -0,0 +1,444 @@
+// Copyright 2015 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/context_factory_efl.h"
+
+#include "base/bind.h"
+#include "base/cancelable_callback.h"
+#include "base/memory/ref_counted.h"
+#include "cc/output/gl_frame_data.h"
+#include "cc/output/compositor_frame.h"
+#include "cc/output/output_surface.h"
+#include "cc/output/output_surface_client.h"
+#include "cc/resources/resource_format.h"
+#include "cc/resources/resource_provider.h"
+#include "cc/surfaces/surface_id_allocator.h"
+#include "cc/resources/transferable_resource.h"
+#include "content/public/common/content_switches.h"
+#include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
+#include "content/browser/gpu/gpu_surface_tracker.h"
+#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "content/browser/gpu/browser_gpu_channel_host_factory.h"
+#include "content/browser/gpu/browser_gpu_channel_host_factory.h"
+#include "content/common/gpu/gpu_process_launch_causes.h"
+#include "content/common/gpu/client/command_buffer_proxy_impl.h"
+#include "content/common/gpu/client/context_provider_command_buffer.h"
+#include "content/common/host_shared_bitmap_manager.h"
+#include "ui/gl/gl_shared_context_efl.h"
+#include "gpu/command_buffer/client/context_support.h"
+#include "gpu/command_buffer/client/gles2_interface.h"
+#include "ui/compositor/reflector.h"
+#include "cc/blink/context_provider_web_context.h"
+
+using gpu::gles2::GLES2Interface;
+
+namespace {
+
+// TODO(venu.musham): Move this class into separate file.
+class MailboxOutputSurfaceEfl : public cc::OutputSurface {
+ public:
+  MailboxOutputSurfaceEfl(
+      const scoped_refptr<cc::ContextProvider>& context_provider,
+      base::WeakPtr<ui::ContextFactoryEfl> context_factory_efl,
+      cc::ResourceFormat format)
+      : cc::OutputSurface(context_provider),
+        swap_buffers_completion_callback_(
+            base::Bind(&MailboxOutputSurfaceEfl::OnSwapBuffersCompleted,
+                       base::Unretained(this))),
+        context_factory_efl_(context_factory_efl),
+        fbo_(0),
+        is_backbuffer_discarded_(false),
+        texture_upload_pending_(false),
+        format_(format) {
+    pending_textures_.push_back(TransferableFrame());
+    capabilities_.max_frames_pending = 1;
+    capabilities_.uses_default_gl_framebuffer = false;
+    capabilities_.adjust_deadline_for_parent = false;
+  }
+  virtual ~MailboxOutputSurfaceEfl() {
+    DiscardBackbuffer();
+    while (!pending_textures_.empty()) {
+      if (pending_textures_.front().texture_id) {
+        context_provider_->ContextGL()->DeleteTextures(
+            1, &pending_textures_.front().texture_id);
+      }
+      pending_textures_.pop_front();
+    }
+  }
+  virtual void EnsureBackbuffer() override {
+    is_backbuffer_discarded_ = false;
+
+    GLES2Interface* gl = context_provider_->ContextGL();
+
+    if (!current_backing_.texture_id) {
+      // Find a texture of matching size to recycle.
+      while (!returned_textures_.empty()) {
+        TransferableFrame& texture = returned_textures_.front();
+        if (texture.size == surface_size_) {
+          current_backing_ = texture;
+          if (current_backing_.sync_point)
+            gl->WaitSyncPointCHROMIUM(current_backing_.sync_point);
+          returned_textures_.pop();
+          break;
+        }
+
+        gl->DeleteTextures(1, &texture.texture_id);
+        returned_textures_.pop();
+      }
+
+      if (!current_backing_.texture_id) {
+        gl->GenTextures(1, &current_backing_.texture_id);
+        current_backing_.size = surface_size_;
+        gl->BindTexture(GL_TEXTURE_2D, current_backing_.texture_id);
+        gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+        gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+        gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+        gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+        gl->TexImage2D(GL_TEXTURE_2D, 0, GLInternalFormat(format_),
+                       surface_size_.width(), surface_size_.height(), 0,
+                       GLDataFormat(format_), GLDataType(format_), NULL);
+        gl->GenMailboxCHROMIUM(current_backing_.mailbox.name);
+        gl->ProduceTextureCHROMIUM(GL_TEXTURE_2D,
+                                   current_backing_.mailbox.name);
+        texture_upload_pending_ = true;
+      }
+    }
+  }
+
+  virtual void DiscardBackbuffer() override {
+    is_backbuffer_discarded_ = true;
+
+    GLES2Interface* gl = context_provider_->ContextGL();
+
+    if (current_backing_.texture_id) {
+      gl->DeleteTextures(1, &current_backing_.texture_id);
+      current_backing_ = TransferableFrame();
+    }
+
+    while (!returned_textures_.empty()) {
+      const TransferableFrame& frame = returned_textures_.front();
+      gl->DeleteTextures(1, &frame.texture_id);
+      returned_textures_.pop();
+    }
+
+    if (fbo_) {
+      gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
+      gl->DeleteFramebuffers(1, &fbo_);
+      fbo_ = 0;
+    }
+  }
+
+  void Reshape(const gfx::Size& size, float scale_factor) {
+    if (size == surface_size_)
+      return;
+
+    surface_size_ = size;
+    device_scale_factor_ = scale_factor;
+    DiscardBackbuffer();
+    EnsureBackbuffer();
+  }
+
+  void BindFramebuffer() {
+    EnsureBackbuffer();
+    DCHECK(current_backing_.texture_id);
+
+    GLES2Interface* gl = context_provider_->ContextGL();
+
+    if (!fbo_)
+      gl->GenFramebuffers(1, &fbo_);
+    gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
+    gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+                             GL_TEXTURE_2D, current_backing_.texture_id, 0);
+  }
+
+  void DrawTexture(scoped_ptr<cc::GLFrameData> gl_frame_data) {
+    // Draw texture on RWHV
+    if (gl_frame_data) {
+      gpu::Mailbox pending_mailbox;
+      std::swap(gl_frame_data->mailbox, pending_mailbox);
+      context_factory_efl_->GetFrameFromMailbox(&pending_mailbox,
+                                                surface_size_);
+    }
+  }
+
+  void OnSwapAck(scoped_ptr<cc::GLFrameData> gl_frame_data) {
+    // Ignore message if it's a stale one coming from a different output surface
+    // (e.g. after a lost context).
+    if (!gl_frame_data->mailbox.IsZero()) {
+      DCHECK(!gl_frame_data->size.IsEmpty());
+      // The browser could be returning the oldest or any other pending texture
+      // if it decided to skip a frame.
+      std::deque<TransferableFrame>::iterator it;
+      for (it = pending_textures_.begin(); it != pending_textures_.end();
+           it++) {
+        DCHECK(!it->mailbox.IsZero());
+        if (!memcmp(it->mailbox.name, gl_frame_data->mailbox.name,
+                    sizeof(it->mailbox.name))) {
+          DCHECK(it->size == gl_frame_data->size);
+          break;
+        }
+      }
+      DCHECK(it != pending_textures_.end());
+      it->sync_point = gl_frame_data->sync_point;
+
+      if (!is_backbuffer_discarded_) {
+        returned_textures_.push(*it);
+      } else {
+        context_provider_->ContextGL()->DeleteTextures(1, &it->texture_id);
+      }
+
+      pending_textures_.erase(it);
+    } else {
+      DCHECK(!pending_textures_.empty());
+      // The browser always keeps one texture as the frontbuffer.
+      // If it does not return a mailbox, it discarded the frontbuffer which is
+      // the oldest texture we sent.
+      uint32 texture_id = pending_textures_.front().texture_id;
+      if (texture_id)
+        context_provider_->ContextGL()->DeleteTextures(1, &texture_id);
+      pending_textures_.pop_front();
+    }
+
+    if (gl_frame_data) {
+      base::Closure closure =
+          base::Bind(&MailboxOutputSurfaceEfl::DrawTexture,
+                     base::Unretained(this), base::Passed(&gl_frame_data));
+      base::MessageLoopProxy::current()->PostTask(FROM_HERE, closure);
+    }
+    client_->DidSwapBuffersComplete();
+  }
+
+  virtual void SwapBuffers(cc::CompositorFrame* frame) override {
+    DCHECK(frame->gl_frame_data);
+    DCHECK(!surface_size_.IsEmpty());
+    DCHECK(surface_size_ == current_backing_.size);
+    DCHECK(frame->gl_frame_data->size == current_backing_.size);
+    DCHECK(!current_backing_.mailbox.IsZero() ||
+           context_provider_->IsContextLost());
+
+    frame->gl_frame_data->mailbox = current_backing_.mailbox;
+
+    // Using glFinish call instead of glFlush, fixes black screen issue with
+    // static pages and IE Fish page.
+
+    // Black screen issue is seen on page in Note4 and XU3 devices.
+#if defined(TIZEN_V_3_0) && defined(OS_TIZEN)
+    context_provider_->ContextGL()->Finish();
+#else
+    if (texture_upload_pending_) {
+      context_provider_->ContextGL()->Finish();
+      texture_upload_pending_ = false;
+    } else {
+      context_provider_->ContextGL()->Flush();
+    }
+#endif
+
+    frame->gl_frame_data->sync_point =
+        context_provider_->ContextGL()->InsertSyncPointCHROMIUM();
+
+    base::Closure closure =
+        base::Bind(&MailboxOutputSurfaceEfl::OnSwapAck, base::Unretained(this),
+                   base::Passed(&frame->gl_frame_data));
+    uint32 sync_point =
+        context_provider_->ContextGL()->InsertSyncPointCHROMIUM();
+    context_provider()->ContextSupport()->SignalSyncPoint(sync_point, closure);
+
+    client_->DidSwapBuffers();
+
+    pending_textures_.push_back(current_backing_);
+    current_backing_ = TransferableFrame();
+  }
+
+  virtual bool BindToClient(cc::OutputSurfaceClient* client) override {
+    if (!OutputSurface::BindToClient(client))
+      return false;
+    GetCommandBufferProxy()->SetSwapBuffersCompletionCallback(
+        swap_buffers_completion_callback_.callback());
+    return true;
+  }
+
+  size_t GetNumAcksPending() {
+    DCHECK(pending_textures_.size());
+    return pending_textures_.size() - 1;
+  }
+
+ private:
+  struct TransferableFrame {
+    TransferableFrame() : texture_id(0), sync_point(0) {}
+
+    TransferableFrame(uint32 texture_id,
+                      const gpu::Mailbox& mailbox,
+                      const gfx::Size size)
+        : texture_id(texture_id), mailbox(mailbox), size(size), sync_point(0) {}
+
+    uint32 texture_id;
+    gpu::Mailbox mailbox;
+    gfx::Size size;
+    uint32 sync_point;
+  };
+  content::CommandBufferProxyImpl* GetCommandBufferProxy() {
+    content::ContextProviderCommandBuffer* provider_command_buffer =
+        static_cast<content::ContextProviderCommandBuffer*>(
+            context_provider_.get());
+    content::CommandBufferProxyImpl* command_buffer_proxy =
+        provider_command_buffer->GetCommandBufferProxy();
+    DCHECK(command_buffer_proxy);
+    return command_buffer_proxy;
+  }
+
+  void OnSwapBuffersCompleted(
+      const std::vector<ui::LatencyInfo>& latency_info) {
+    content::RenderWidgetHostImpl::CompositorFrameDrawn(latency_info);
+    OutputSurface::OnSwapBuffersComplete();
+  }
+  base::CancelableCallback<void(const std::vector<ui::LatencyInfo>&)>
+      swap_buffers_completion_callback_;
+
+  scoped_refptr<base::MessageLoopProxy> main_thread_;
+  base::WeakPtr<ui::ContextFactoryEfl> context_factory_efl_;
+
+  TransferableFrame current_backing_;
+  std::deque<TransferableFrame> pending_textures_;
+  std::queue<TransferableFrame> returned_textures_;
+
+  uint32 fbo_;
+  bool is_backbuffer_discarded_;
+  bool texture_upload_pending_;
+  cc::ResourceFormat format_;
+};
+}  // namespace
+
+namespace content {
+
+static scoped_ptr<WebGraphicsContext3DCommandBufferImpl>
+CreateGpuProcessViewContext(
+    const scoped_refptr<GpuChannelHost>& gpu_channel_host,
+    const blink::WebGraphicsContext3D::Attributes attributes,
+    int surface_id) {
+  DCHECK(gpu_channel_host.get());
+
+  GURL url("chrome://gpu/Compositor::createContext3D");
+  bool lose_context_when_out_of_memory = true;
+  return make_scoped_ptr(new WebGraphicsContext3DCommandBufferImpl(
+      surface_id, url, gpu_channel_host.get(), attributes,
+      lose_context_when_out_of_memory,
+      WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits(), NULL));
+}
+}  // namespace content
+
+namespace ui {
+
+ContextFactoryEfl::ContextFactoryEfl(content::ContextFactoryDelegate* delegate,
+                                     int surface_id)
+    : delegate_(delegate),
+      surface_id_(surface_id),
+      next_surface_id_namespace_(1),
+      schedule_draw_factory_(this) {
+}
+
+void ContextFactoryEfl::GetFrameFromMailbox(gpu::Mailbox* mailbox,
+                                            gfx::Size size) {
+  delegate_->GetTextureFromMailbox(mailbox, size);
+}
+
+void ContextFactoryEfl::CreateOutputSurface(
+    base::WeakPtr<Compositor> compositor,
+    bool software_fallback) {
+  blink::WebGraphicsContext3D::Attributes attrs;
+  attrs.depth = false;
+  attrs.stencil = false;
+  attrs.antialias = false;
+  attrs.shareResources = true;
+  attrs.noAutomaticFlushes = true;
+
+  scoped_refptr<content::ContextProviderCommandBuffer> context_provider;
+  content::BrowserGpuChannelHostFactory* factory =
+      content::BrowserGpuChannelHostFactory::instance();
+  content::CauseForGpuLaunch cause = content::
+      CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE;
+  scoped_refptr<content::GpuChannelHost> gpu_channel_host(
+      factory->EstablishGpuChannelSync(cause));
+  if (gpu_channel_host.get() && !gpu_channel_host->IsLost()) {
+    context_provider = content::ContextProviderCommandBuffer::Create(
+        CreateGpuProcessViewContext(gpu_channel_host, attrs, 0),
+        "BrowserCompositor");
+  }
+  if (!context_provider.get()) {
+    LOG(ERROR) << "Failed to create 3D context for compositor.";
+    compositor->SetOutputSurface(scoped_ptr<cc::OutputSurface>());
+  }
+
+  cc::ResourceFormat format = cc::RGBA_8888;
+  compositor->SetOutputSurface(make_scoped_ptr(new MailboxOutputSurfaceEfl(
+      context_provider, schedule_draw_factory_.GetWeakPtr(), format)));
+}
+
+scoped_refptr<Reflector> ContextFactoryEfl::CreateReflector(
+    Compositor* mirrored_compositor,
+    Layer* mirroring_layer) {
+  return new Reflector();
+}
+
+void ContextFactoryEfl::RemoveReflector(scoped_refptr<Reflector> reflector) {
+}
+
+void ContextFactoryEfl::OnLostMainThreadSharedContextInsideCallback() {
+}
+
+scoped_refptr<cc::ContextProvider>
+ContextFactoryEfl::SharedMainThreadContextProvider() {
+  if (shared_main_thread_contexts_.get())
+    return shared_main_thread_contexts_;
+
+  blink::WebGraphicsContext3D::Attributes attrs;
+  attrs.depth = false;
+  attrs.stencil = false;
+  attrs.antialias = false;
+  attrs.shareResources = true;
+  attrs.noAutomaticFlushes = true;
+
+  scoped_refptr<content::ContextProviderCommandBuffer> context_provider;
+  content::BrowserGpuChannelHostFactory* factory =
+      content::BrowserGpuChannelHostFactory::instance();
+  content::CauseForGpuLaunch cause = content::
+      CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE;
+  scoped_refptr<content::GpuChannelHost> gpu_channel_host(
+      factory->EstablishGpuChannelSync(cause));
+  if (gpu_channel_host.get() && !gpu_channel_host->IsLost()) {
+  shared_main_thread_contexts_ = content::ContextProviderCommandBuffer::Create(
+        CreateGpuProcessViewContext(gpu_channel_host, attrs, 0),
+        "Offscreen-MainThread");
+  }
+
+  if (!shared_main_thread_contexts_->BindToCurrentThread())
+    shared_main_thread_contexts_ = NULL;
+  return shared_main_thread_contexts_;
+}
+
+void ContextFactoryEfl::RemoveCompositor(Compositor* compositor) {
+}
+
+bool ContextFactoryEfl::DoesCreateTestContexts() {
+  return false;
+}
+
+cc::SharedBitmapManager* ContextFactoryEfl::GetSharedBitmapManager() {
+  return content::HostSharedBitmapManager::current();
+}
+
+gpu::GpuMemoryBufferManager* ContextFactoryEfl::GetGpuMemoryBufferManager() {
+  return content::BrowserGpuMemoryBufferManager::current();
+}
+
+base::MessageLoopProxy* ContextFactoryEfl::GetCompositorMessageLoop() {
+  return NULL;
+}
+
+scoped_ptr<cc::SurfaceIdAllocator>
+ContextFactoryEfl::CreateSurfaceIdAllocator() {
+  return make_scoped_ptr(
+      new cc::SurfaceIdAllocator(next_surface_id_namespace_++));
+}
+
+}  // namespace ui
diff --git a/tizen_src/chromium_impl/content/browser/renderer_host/context_factory_efl.h b/tizen_src/chromium_impl/content/browser/renderer_host/context_factory_efl.h
new file mode 100644 (file)
index 0000000..d977d71
--- /dev/null
@@ -0,0 +1,78 @@
+// Copyright 2015 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPOSITOR_CONTEXT_FACTORY_EFL_H_
+#define COMPOSITOR_CONTEXT_FACTORY_EFL_H_
+
+#include "ui/compositor/compositor.h"
+
+namespace content {
+class ContextProviderCommandBuffer;
+struct ContextFactoryDelegate {
+  // Updates new texture received from mailbox on evas gl surface
+  virtual void GetTextureFromMailbox(gpu::Mailbox* mailbox, gfx::Size size) = 0;
+};
+
+class RenderWidgetHostViewEfl;
+}
+
+namespace webkit {
+namespace gpu {
+class ContextProviderInProcess;
+}
+}
+
+namespace cc_blink{
+class ContextProviderWebContext;
+}
+
+namespace ui {
+
+class ContextFactoryEfl : public ContextFactory {
+ public:
+  ContextFactoryEfl(content::ContextFactoryDelegate* delegate, int surface_id);
+
+  void CreateOutputSurface(base::WeakPtr<Compositor> compositor,
+                           bool software_fallback) override;
+
+  scoped_refptr<Reflector> CreateReflector(Compositor* mirrored_compositor,
+                                           Layer* mirroring_layer) override;
+
+  void RemoveReflector(scoped_refptr<Reflector> reflector) override;
+
+  scoped_refptr<cc::ContextProvider> SharedMainThreadContextProvider() override;
+
+  void RemoveCompositor(Compositor* compositor) override;
+
+  bool DoesCreateTestContexts() override;
+
+  cc::SharedBitmapManager* GetSharedBitmapManager() override;
+
+  gpu::GpuMemoryBufferManager* GetGpuMemoryBufferManager() override;
+
+  base::MessageLoopProxy* GetCompositorMessageLoop() override;
+
+  scoped_ptr<cc::SurfaceIdAllocator> CreateSurfaceIdAllocator() override;
+
+  void SetSurfaceID(int surface_id, gfx::AcceleratedWidget widget);
+
+  void GetFrameFromMailbox(gpu::Mailbox* mailbox, gfx::Size size);
+
+  void OnLostMainThreadSharedContextInsideCallback();
+
+  // Resize the display corresponding to this compositor to a particular size.
+  void ResizeDisplay(ui::Compositor* compositor,
+                             const gfx::Size& size) override {};
+
+ private:
+  content::ContextFactoryDelegate* delegate_;
+  int surface_id_;
+  uint32_t next_surface_id_namespace_;
+  base::WeakPtrFactory<ContextFactoryEfl> schedule_draw_factory_;
+  scoped_refptr<content::ContextProviderCommandBuffer> shared_main_thread_contexts_;
+};
+
+}  // namespace ui
+
+#endif  // COMPOSITOR_CONTEXT_FACTORY_EFL_H_
index ba1356a..d62dff2 100644 (file)
 #include "base/trace_event/trace_event.h"
 #include "base/message_loop/message_loop.h"
 #include "base/strings/string_number_conversions.h"
+#include "base/thread_task_runner_handle.h"
 #include "base/logging.h"
 #include "base/strings/utf_string_conversions.h"
 #include "content/common/view_messages.h"
+#include "content/browser/compositor/resize_lock.h"
 #include "content/browser/gpu/browser_gpu_channel_host_factory.h"
 #include "content/browser/gpu/compositor_util.h"
 #include "content/browser/renderer_host/render_widget_host_impl.h"
@@ -30,6 +32,7 @@
 #include "content/browser/renderer_host/im_context_efl.h"
 #include "content/browser/renderer_host/edge_effect.h"
 #include "content/browser/renderer_host/event_with_latency_info.h"
+#include "content/browser/renderer_host/context_factory_efl.h"
 #include "content/browser/renderer_host/disambiguation_popup_efl.h"
 #include "content/browser/renderer_host/web_event_factory_efl.h"
 #include "content/browser/renderer_host/input/web_input_event_util.h"
 #include "content/common/cursors/webcursor_efl.h"
 #include "content/public/browser/render_widget_host_view_frame_subscriber.h"
 #include "content/public/browser/screen_orientation_dispatcher_host.h"
-#include "content/public/common/content_switches.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/context_factory.h"
 #include "content/public/browser/render_process_host.h"
+#include "content/public/common/content_switches.h"
 #include "gpu/command_buffer/service/mailbox_manager.h"
 #include "media/base/video_util.h"
 #include "skia/ext/image_operations.h"
@@ -59,6 +63,7 @@
 #include "ui/events/gestures/gesture_provider_aura.h"
 #undef private
 #include "ui/events/gestures/gesture_recognizer_impl_efl.h"
+#include "ui/compositor/compositor.h"
 #include "ui/gfx/display.h"
 #include "ui/gfx/geometry/dip_util.h"
 #include "ui/gfx/geometry/rect.h"
@@ -145,7 +150,9 @@ RenderWidgetHostViewEfl::RenderWidgetHostViewEfl(RenderWidgetHost* widget,
     selection_acked_on_tap_(false),
     was_scrolled_(false),
     web_contents_(web_contents),
-    single_tap_performed_(false) {
+    single_tap_performed_(false),
+    root_layer_(new ui::Layer(ui::LAYER_SOLID_COLOR)),
+    delegated_frame_host_(new DelegatedFrameHost(this)) {
 
   SetDoubleTapSupportEnabled(touch_events_enabled_);
 
@@ -154,6 +161,8 @@ RenderWidgetHostViewEfl::RenderWidgetHostViewEfl(RenderWidgetHost* widget,
 
   host_->SetView(this);
 
+  set_layer_owner_delegate(delegated_frame_host_.get());
+
   static bool scale_factor_initialized = false;
   if (!scale_factor_initialized) {
     std::vector<ui::ScaleFactor> supported_scale_factors;
@@ -477,6 +486,21 @@ void RenderWidgetHostViewEfl::Init_EvasGL(int width, int height) {
   initializeProgram();
 
   evas_gl_initialized_ = true;
+
+  context_factory_.reset(new ui::ContextFactoryEfl(this, host_->surface_id()));
+  compositor_.reset(new ui::Compositor(GetNativeViewId(),
+                                       context_factory_.get(),
+                                       base::ThreadTaskRunnerHandle::Get()));
+  compositor_->SetRootLayer(root_layer_.get());
+  gfx::Size size = GetViewBoundsInPix().size();
+  root_layer_->SetBounds(gfx::Rect(0, 0, size.width(), size.height()));
+  compositor_->SetScaleAndSize(device_scale_factor_, size);
+  compositor_->SetVisible(true);
+}
+
+void RenderWidgetHostViewEfl::ResizeCompositorLayer(int width, int height) {
+  root_layer_->SetBounds(gfx::Rect(0, 0, width, height));
+  compositor_->SetScaleAndSize(device_scale_factor_, gfx::Size(width, height));
 }
 
 void RenderWidgetHostViewEfl::CreateNativeSurface(int width, int height) {
@@ -598,17 +622,17 @@ void RenderWidgetHostViewEfl::SetSize(const gfx::Size& size) {
     host_->SendScreenRects();
     host_->WasResized();
   //}
+    gfx::Size bounds = GetViewBoundsInPix().size();
+    root_layer_->SetBounds(gfx::Rect(0, 0, bounds.width(), bounds.height()));
+    compositor_->SetScaleAndSize(device_scale_factor_, bounds);
 }
 
 void RenderWidgetHostViewEfl::SetBounds(const gfx::Rect& rect) {
-  // FIXME: ditto.
-  NOTIMPLEMENTED();
+  host_->WasResized();
+  delegated_frame_host_->WasResized();
 }
 
 gfx::Vector2dF RenderWidgetHostViewEfl::GetLastScrollOffset() const {
-  // FIXME: Aura RWHV sets last_scroll_offset_ in OnSwapCompositorFrame()
-  // Other ways to get scroll offset are already removed.
-  // We need to switch to the ui::Compositor ASAP!
   return last_scroll_offset_;
 }
 
@@ -628,7 +652,7 @@ gfx::NativeViewAccessible RenderWidgetHostViewEfl::GetNativeViewAccessible() {
 }
 
 bool RenderWidgetHostViewEfl::IsSurfaceAvailableForCopy() const {
-  return false;
+  return delegated_frame_host_->CanCopyToBitmap();
 }
 
 void RenderWidgetHostViewEfl::Show() {
@@ -751,7 +775,6 @@ void RenderWidgetHostViewEfl::UpdateCursor(const WebCursor& webcursor) {
 }
 
 void RenderWidgetHostViewEfl::SetIsLoading(bool is_loading) {
-  is_loading_ = is_loading;
   UpdateCursor(WebCursor());
   if (disambiguation_popup_)
     disambiguation_popup_->Dismiss();
@@ -951,9 +974,11 @@ void RenderWidgetHostViewEfl::DispatchGestureEvent(ui::GestureEvent* event) {
 void RenderWidgetHostViewEfl::CopyFromCompositingSurface(
     const gfx::Rect& src_subrect,
     const gfx::Size& output_size,
-    const ReadbackRequestCallback& callback,
+    ReadbackRequestCallback& callback,
     const SkColorType color_type) {
-  NOTIMPLEMENTED();
+  // FIXME(venu.musham): should find a way to do it effectively.
+  delegated_frame_host_->CopyFromCompositingSurface(src_subrect, output_size,
+                                                    callback, color_type);
 }
 
 void RenderWidgetHostViewEfl::GetSnapshotAsync(const gfx::Rect& snapshot_area, int request_id) {
@@ -1004,17 +1029,16 @@ bool RenderWidgetHostViewEfl::RequestSnapshotAsync(const Eina_Rectangle rect,
 
 // CopyFromCompositingSurfaceToVideoFrame implementation borrowed from Aura port
 bool RenderWidgetHostViewEfl::CanSubscribeFrame() const {
-  return true;
+  return delegated_frame_host_->CanSubscribeFrame();
 }
 
 void RenderWidgetHostViewEfl::BeginFrameSubscription(
     scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) {
-  frame_subscriber_ = subscriber.Pass();
+  delegated_frame_host_->BeginFrameSubscription(subscriber.Pass());
 }
 
 void RenderWidgetHostViewEfl::EndFrameSubscription() {
-  idle_frame_subscriber_textures_.clear();
-  frame_subscriber_.reset();
+  delegated_frame_host_->EndFrameSubscription();
 }
 
 void RenderWidgetHostViewEfl::DidOverscroll(const DidOverscrollParams& params) {
@@ -1207,7 +1231,7 @@ void RenderWidgetHostViewEfl::CopyFromCompositingSurfaceToVideoFrame(
 }
 
 bool RenderWidgetHostViewEfl::CanCopyToVideoFrame() const {
-  return false;
+  return delegated_frame_host_->CanCopyToVideoFrame();
 }
 
 bool RenderWidgetHostViewEfl::HasAcceleratedSurface(const gfx::Size&) {
@@ -1251,6 +1275,7 @@ void RenderWidgetHostViewEfl::OnParentViewResize(
   evas_object_geometry_set(thiz->content_image_elm_host_, x, y, width, height);
   evas_object_image_size_set(thiz->content_image_, width, height);
   thiz->CreateNativeSurface(width, height);
+  thiz->ResizeCompositorLayer(width, height);
   thiz->host_->WasResized();
 }
 
@@ -1732,12 +1757,25 @@ void RenderWidgetHostViewEfl::ConfirmComposition(base::string16& text) {
 // texture_manager.h with efl GL API wrappers.
 extern GLuint GetTextureIdFromTexture(gpu::gles2::Texture* texture);
 
+void RenderWidgetHostViewEfl::GetTextureFromMailbox(gpu::Mailbox* mailbox,
+                                                    gfx::Size surface_size) {
+  gpu::gles2::MailboxManager* manager = GLSharedContextEfl::GetMailboxManager();
+  gpu::gles2::Texture* texture = manager->ConsumeTexture(*mailbox);
+  if (texture != NULL) {
+    surface_size_ = surface_size;
+    texture_id_ = GetTextureIdFromTexture(texture);
+    evas_object_image_pixels_dirty_set(content_image_, true);
+    evas_render(evas_);
+  }
+}
+
 void RenderWidgetHostViewEfl::OnSwapCompositorFrame(
     uint32 output_surface_id, scoped_ptr<cc::CompositorFrame> frame) {
   cc::CompositorFrameAck ack;
-
-  // TODO(prashant.n): Delegated and software frames not supported. So with
+  // TODO(prashant.n): Software frames not supported. So with
   // those frames black screen will appear.
+  last_scroll_offset_ = frame->metadata.root_scroll_offset;
+
   if (frame->gl_frame_data) {
     ack.gl_frame_data = frame->gl_frame_data.Pass();
     surface_size_ = ack.gl_frame_data->size;
@@ -1758,10 +1796,11 @@ void RenderWidgetHostViewEfl::OnSwapCompositorFrame(
 
     ack.gl_frame_data->sync_point = 0;
   } else if (frame->delegated_frame_data) {
-    LOG(ERROR) << "Delegated frame is not supported.";
-    cc::TransferableResource::ReturnResources(
-        frame->delegated_frame_data->resource_list,
-        &ack.resources);
+    // ack is sent by delegated frame host
+    delegated_frame_host_->SwapDelegatedFrame(
+        output_surface_id, frame->delegated_frame_data.Pass(),
+        frame->metadata.device_scale_factor, frame->metadata.latency_info);
+    return;
   } else if (frame->software_frame_data) {
     LOG(ERROR) << "Software frame is not supported.";
     ack.last_software_frame_id = frame->software_frame_data->id;
@@ -1796,4 +1835,63 @@ gfx::Rect RenderWidgetHostViewEfl::GetIMERect() const {
   return gfx::Rect();
 }
 
+///////////////////////////////////////////////////////////////////////////
+// DelegatedFrameHost, public:
+
+ui::Layer* RenderWidgetHostViewEfl::DelegatedFrameHostGetLayer() const {
+  return root_layer_.get();
+}
+
+bool RenderWidgetHostViewEfl::DelegatedFrameHostIsVisible() const {
+  return !host_->is_hidden();
+}
+
+gfx::Size RenderWidgetHostViewEfl::DelegatedFrameHostDesiredSizeInDIP() const{
+  gfx::Rect bounds = GetViewBoundsInPix();
+  return bounds.size();
+}
+
+bool RenderWidgetHostViewEfl::DelegatedFrameCanCreateResizeLock() const {
+  // On Windows and Linux, holding pointer moves will not help throttling
+  // resizes.
+  // TODO(piman): on Windows we need to block (nested message loop?) the
+  // WM_SIZE event. On Linux we need to throttle at the WM level using
+  // _NET_WM_SYNC_REQUESTm .
+  return false;
+}
+
+scoped_ptr<ResizeLock>
+RenderWidgetHostViewEfl::DelegatedFrameHostCreateResizeLock(
+    bool defer_compositor_lock) {
+  ResizeLock* lock = NULL;
+  return scoped_ptr<ResizeLock>(lock);
+}
+
+void RenderWidgetHostViewEfl::DelegatedFrameHostResizeLockWasReleased() {
+  host_->WasResized();
+}
+
+void RenderWidgetHostViewEfl::DelegatedFrameHostSendCompositorSwapAck(
+    int output_surface_id,
+    const cc::CompositorFrameAck& ack) {
+  host_->Send(new ViewMsg_SwapCompositorFrameAck(host_->GetRoutingID(),
+                                                 output_surface_id, ack));
+}
+
+void RenderWidgetHostViewEfl::DelegatedFrameHostSendReclaimCompositorResources(
+    int output_surface_id,
+    const cc::CompositorFrameAck& ack) {
+  host_->Send(new ViewMsg_ReclaimCompositorResources(host_->GetRoutingID(),
+                                                    output_surface_id, ack));
+}
+
+void RenderWidgetHostViewEfl::DelegatedFrameHostOnLostCompositorResources() {
+  host_->ScheduleComposite();
+}
+
+void RenderWidgetHostViewEfl::DelegatedFrameHostUpdateVSyncParameters(
+    const base::TimeTicks& timebase,
+    const base::TimeDelta& interval) {
+  host_->UpdateVSyncParameters(timebase, interval);
+}
 }  // namespace content
index d827606..04a2a6f 100644 (file)
 #include "cc/resources/single_release_callback.h"
 #include "cc/resources/texture_mailbox.h"
 #include "content/browser/accessibility/browser_accessibility_manager.h"
+#include "content/browser/compositor/delegated_frame_host.h"
 #include "content/browser/compositor/image_transport_factory.h"
 #include "content/browser/compositor/owned_mailbox.h"
+#include "content/browser/renderer_host/context_factory_efl.h"
+#include "content/browser/renderer_host/render_widget_host_view_base.h"
 #include "gpu/command_buffer/common/mailbox.h"
 #include "ui/base/ime/composition_text.h"
 #include "ui/base/ime/text_input_client.h"
 #include "ui/base/selection/selection_controller_efl.h"
+#include "ui/compositor/layer_owner.h"
 #include "ui/events/gestures/gesture_types.h"
 #include "ui/events/gestures/gesture_recognizer.h"
 #include "ui/events/gestures/motion_event_aura.h"
@@ -54,6 +58,7 @@ struct ViewHostMsg_TextInputState_Params;
 struct ViewHostMsg_HitTestAsyncReply_Params;
 
 namespace ui {
+class Compositor;
 class GestureEvent;
 class TouchEvent;
 }
@@ -77,11 +82,14 @@ class ScreenshotCapturedCallback;
 
 // RenderWidgetHostView class hierarchy described in render_widget_host_view.h.
 class RenderWidgetHostViewEfl
-  : public RenderWidgetHostViewBase,
-    public ui::GestureConsumer,
-    public ui::GestureEventHelper,
-    public base::SupportsWeakPtr<RenderWidgetHostViewEfl>,
-    public IPC::Sender {
+    : public RenderWidgetHostViewBase,
+      public DelegatedFrameHostClient,
+      public ContextFactoryDelegate,
+      public ui::LayerOwner,
+      public ui::GestureConsumer,
+      public ui::GestureEventHelper,
+      public base::SupportsWeakPtr<RenderWidgetHostViewEfl>,
+      public IPC::Sender {
  public:
   explicit RenderWidgetHostViewEfl(RenderWidgetHost*, WebContents& web_contents);
 
@@ -191,6 +199,7 @@ class RenderWidgetHostViewEfl
   void set_magnifier(bool status);
 
   void Init_EvasGL(int width, int height);
+  void ResizeCompositorLayer(int width, int height);
   void CreateNativeSurface(int width, int height);
 
   void SetEvasHandler(scoped_refptr<EvasEventHandler> evas_event_handler);
@@ -225,6 +234,25 @@ class RenderWidgetHostViewEfl
     void* user_data);
   void OnSnapshotDataReceived(SkBitmap bitmap, int snapshotId);
 
+  // DelegatedFrameHostClient implementation.
+  ui::Layer* DelegatedFrameHostGetLayer() const override;
+  bool DelegatedFrameHostIsVisible() const override;
+  scoped_ptr<ResizeLock> DelegatedFrameHostCreateResizeLock(
+      bool defer_compositor_lock) override;
+  bool DelegatedFrameCanCreateResizeLock() const override;
+  gfx::Size DelegatedFrameHostDesiredSizeInDIP() const override;
+  void DelegatedFrameHostResizeLockWasReleased() override;
+  void DelegatedFrameHostSendCompositorSwapAck(
+      int output_surface_id,
+      const cc::CompositorFrameAck& ack) override;
+  void DelegatedFrameHostSendReclaimCompositorResources(
+      int output_surface_id,
+      const cc::CompositorFrameAck& ack) override;
+  void DelegatedFrameHostOnLostCompositorResources() override;
+  void DelegatedFrameHostUpdateVSyncParameters(
+      const base::TimeTicks& timebase,
+      const base::TimeDelta& interval) override;
+
  protected:
   friend class RenderWidgetHostView;
 
@@ -289,6 +317,10 @@ class RenderWidgetHostViewEfl
 
   void PaintTextureToSurface(GLuint texture_id);
 
+  // overrides ContextFactoryDelegate
+  void GetTextureFromMailbox(gpu::Mailbox* mailbox,
+                             gfx::Size surface_size) override;
+
   RenderWidgetHostImpl* host_;
   IMContextEfl* im_context_;
   Evas* evas_;
@@ -376,6 +408,10 @@ class RenderWidgetHostViewEfl
   scoped_ptr<bool> restore_showing_large_handle_on_gesture_end_;
 
   IDMap<ScreenshotCapturedCallback, IDMapOwnPointer> screen_capture_cb_map_;
+  scoped_ptr<ui::Compositor> compositor_;
+  scoped_ptr<ui::Layer> root_layer_;
+  scoped_ptr<DelegatedFrameHost> delegated_frame_host_;
+  scoped_ptr<ui::ContextFactory> context_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewEfl);
 };
index 6caa74a..266277a 100644 (file)
           'browser/web_contents/web_drag_source_efl.cc',
           'browser/tracing/tracing_controller_efl.h',
           'browser/tracing/tracing_controller_efl.cc',
+          'browser/renderer_host/context_factory_efl.h',
+          'browser/renderer_host/context_factory_efl.cc',
           'browser/renderer_host/disambiguation_popup_efl.h',
           'browser/renderer_host/disambiguation_popup_efl.cc',
           'browser/renderer_host/edge_effect.h',
index 2c5bc96..1bb3fa3 100644 (file)
@@ -14,6 +14,7 @@
 #include "cc/base/switches.h"
 #include "content/common/paths_efl.h"
 #include "content/public/common/content_switches.h"
+#include "ui/compositor/compositor_switches.h"
 #include "ui/gfx/screen_efl.h"
 #include "ui/gfx/switches.h"
 #include "ui/gl/gl_switches.h"
@@ -62,9 +63,9 @@ int Initialize(int argc, const char* argv[]) {
 void AppendPortParams(base::CommandLine& cmdline) {
   cmdline.AppendSwitchASCII(switches::kUseGL,
                             gfx::kGLImplementationEGLName);
-  cmdline.AppendSwitch(cc::switches::kCompositeToMailbox);
   cmdline.AppendSwitch(switches::kInProcessGPU);
-  cmdline.AppendSwitch(switches::kDisableDelegatedRenderer);
+  cmdline.AppendSwitch(switches::kUIDisableThreadedCompositing);
+  cmdline.AppendSwitch(switches::kEnableDelegatedRenderer);
 }
 
 } // namespace efl