From edc7eb2c7d685a00b68167a5fd20dbff45d64a47 Mon Sep 17 00:00:00 2001 From: "venu.musham" Date: Fri, 24 Apr 2015 19:38:28 +0530 Subject: [PATCH] Implement Delegate renderer using frame buffer object on Tizen. 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 --- .../browser/renderer_host/context_factory_efl.cc | 444 +++++++++++++++++++++ .../browser/renderer_host/context_factory_efl.h | 78 ++++ .../renderer_host/render_widget_host_view_efl.cc | 142 ++++++- .../renderer_host/render_widget_host_view_efl.h | 46 ++- tizen_src/chromium_impl/content/content_efl.gypi | 2 + tizen_src/chromium_impl/efl/init.cc | 5 +- 6 files changed, 688 insertions(+), 29 deletions(-) create mode 100644 tizen_src/chromium_impl/content/browser/renderer_host/context_factory_efl.cc create mode 100644 tizen_src/chromium_impl/content/browser/renderer_host/context_factory_efl.h 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 index 0000000..9f72f4f --- /dev/null +++ b/tizen_src/chromium_impl/content/browser/renderer_host/context_factory_efl.cc @@ -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& context_provider, + base::WeakPtr 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, ¤t_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, ¤t_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 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 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::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( + 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& latency_info) { + content::RenderWidgetHostImpl::CompositorFrameDrawn(latency_info); + OutputSurface::OnSwapBuffersComplete(); + } + base::CancelableCallback&)> + swap_buffers_completion_callback_; + + scoped_refptr main_thread_; + base::WeakPtr context_factory_efl_; + + TransferableFrame current_backing_; + std::deque pending_textures_; + std::queue returned_textures_; + + uint32 fbo_; + bool is_backbuffer_discarded_; + bool texture_upload_pending_; + cc::ResourceFormat format_; +}; +} // namespace + +namespace content { + +static scoped_ptr +CreateGpuProcessViewContext( + const scoped_refptr& 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, + bool software_fallback) { + blink::WebGraphicsContext3D::Attributes attrs; + attrs.depth = false; + attrs.stencil = false; + attrs.antialias = false; + attrs.shareResources = true; + attrs.noAutomaticFlushes = true; + + scoped_refptr context_provider; + content::BrowserGpuChannelHostFactory* factory = + content::BrowserGpuChannelHostFactory::instance(); + content::CauseForGpuLaunch cause = content:: + CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE; + scoped_refptr 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::ResourceFormat format = cc::RGBA_8888; + compositor->SetOutputSurface(make_scoped_ptr(new MailboxOutputSurfaceEfl( + context_provider, schedule_draw_factory_.GetWeakPtr(), format))); +} + +scoped_refptr ContextFactoryEfl::CreateReflector( + Compositor* mirrored_compositor, + Layer* mirroring_layer) { + return new Reflector(); +} + +void ContextFactoryEfl::RemoveReflector(scoped_refptr reflector) { +} + +void ContextFactoryEfl::OnLostMainThreadSharedContextInsideCallback() { +} + +scoped_refptr +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 context_provider; + content::BrowserGpuChannelHostFactory* factory = + content::BrowserGpuChannelHostFactory::instance(); + content::CauseForGpuLaunch cause = content:: + CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE; + scoped_refptr 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 +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 index 0000000..d977d71 --- /dev/null +++ b/tizen_src/chromium_impl/content/browser/renderer_host/context_factory_efl.h @@ -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, + bool software_fallback) override; + + scoped_refptr CreateReflector(Compositor* mirrored_compositor, + Layer* mirroring_layer) override; + + void RemoveReflector(scoped_refptr reflector) override; + + scoped_refptr SharedMainThreadContextProvider() override; + + void RemoveCompositor(Compositor* compositor) override; + + bool DoesCreateTestContexts() override; + + cc::SharedBitmapManager* GetSharedBitmapManager() override; + + gpu::GpuMemoryBufferManager* GetGpuMemoryBufferManager() override; + + base::MessageLoopProxy* GetCompositorMessageLoop() override; + + scoped_ptr 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 schedule_draw_factory_; + scoped_refptr shared_main_thread_contexts_; +}; + +} // namespace ui + +#endif // COMPOSITOR_CONTEXT_FACTORY_EFL_H_ diff --git a/tizen_src/chromium_impl/content/browser/renderer_host/render_widget_host_view_efl.cc b/tizen_src/chromium_impl/content/browser/renderer_host/render_widget_host_view_efl.cc index ba1356a..d62dff2 100644 --- a/tizen_src/chromium_impl/content/browser/renderer_host/render_widget_host_view_efl.cc +++ b/tizen_src/chromium_impl/content/browser/renderer_host/render_widget_host_view_efl.cc @@ -20,9 +20,11 @@ #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" @@ -42,9 +45,10 @@ #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 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 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 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 +RenderWidgetHostViewEfl::DelegatedFrameHostCreateResizeLock( + bool defer_compositor_lock) { + ResizeLock* lock = NULL; + return scoped_ptr(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 diff --git a/tizen_src/chromium_impl/content/browser/renderer_host/render_widget_host_view_efl.h b/tizen_src/chromium_impl/content/browser/renderer_host/render_widget_host_view_efl.h index d827606..04a2a6f 100644 --- a/tizen_src/chromium_impl/content/browser/renderer_host/render_widget_host_view_efl.h +++ b/tizen_src/chromium_impl/content/browser/renderer_host/render_widget_host_view_efl.h @@ -28,12 +28,16 @@ #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, - public IPC::Sender { + : public RenderWidgetHostViewBase, + public DelegatedFrameHostClient, + public ContextFactoryDelegate, + public ui::LayerOwner, + public ui::GestureConsumer, + public ui::GestureEventHelper, + public base::SupportsWeakPtr, + 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 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 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 restore_showing_large_handle_on_gesture_end_; IDMap screen_capture_cb_map_; + scoped_ptr compositor_; + scoped_ptr root_layer_; + scoped_ptr delegated_frame_host_; + scoped_ptr context_factory_; DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewEfl); }; diff --git a/tizen_src/chromium_impl/content/content_efl.gypi b/tizen_src/chromium_impl/content/content_efl.gypi index 6caa74a..266277a 100644 --- a/tizen_src/chromium_impl/content/content_efl.gypi +++ b/tizen_src/chromium_impl/content/content_efl.gypi @@ -133,6 +133,8 @@ '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', diff --git a/tizen_src/chromium_impl/efl/init.cc b/tizen_src/chromium_impl/efl/init.cc index 2c5bc96..1bb3fa3 100644 --- a/tizen_src/chromium_impl/efl/init.cc +++ b/tizen_src/chromium_impl/efl/init.cc @@ -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 -- 2.7.4