Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / android_webview / browser / hardware_renderer.cc
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "android_webview/browser/hardware_renderer.h"
6
7 #include "android_webview/browser/aw_gl_surface.h"
8 #include "android_webview/browser/deferred_gpu_command_service.h"
9 #include "android_webview/browser/parent_output_surface.h"
10 #include "android_webview/browser/shared_renderer_state.h"
11 #include "android_webview/public/browser/draw_gl.h"
12 #include "base/auto_reset.h"
13 #include "base/debug/trace_event.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "cc/layers/delegated_frame_provider.h"
16 #include "cc/layers/delegated_renderer_layer.h"
17 #include "cc/layers/layer.h"
18 #include "cc/output/compositor_frame.h"
19 #include "cc/output/output_surface.h"
20 #include "cc/trees/layer_tree_host.h"
21 #include "cc/trees/layer_tree_settings.h"
22 #include "gpu/command_buffer/client/gl_in_process_context.h"
23 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
24 #include "ui/gfx/frame_time.h"
25 #include "ui/gfx/geometry/rect_conversions.h"
26 #include "ui/gfx/geometry/rect_f.h"
27 #include "ui/gfx/transform.h"
28 #include "ui/gl/gl_bindings.h"
29 #include "webkit/common/gpu/context_provider_in_process.h"
30 #include "webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h"
31
32 namespace android_webview {
33
34 namespace {
35
36 using webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl;
37 using webkit::gpu::WebGraphicsContext3DImpl;
38
39 scoped_refptr<cc::ContextProvider> CreateContext(
40     scoped_refptr<gfx::GLSurface> surface,
41     scoped_refptr<gpu::InProcessCommandBuffer::Service> service) {
42   const gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu;
43
44   blink::WebGraphicsContext3D::Attributes attributes;
45   attributes.antialias = false;
46   attributes.depth = false;
47   attributes.stencil = false;
48   attributes.shareResources = true;
49   attributes.noAutomaticFlushes = true;
50   gpu::gles2::ContextCreationAttribHelper attribs_for_gles2;
51   WebGraphicsContext3DImpl::ConvertAttributes(
52       attributes, &attribs_for_gles2);
53   attribs_for_gles2.lose_context_when_out_of_memory = true;
54
55   scoped_ptr<gpu::GLInProcessContext> context(gpu::GLInProcessContext::Create(
56       service,
57       surface,
58       surface->IsOffscreen(),
59       gfx::kNullAcceleratedWidget,
60       surface->GetSize(),
61       NULL /* share_context */,
62       false /* share_resources */,
63       attribs_for_gles2,
64       gpu_preference,
65       gpu::GLInProcessContextSharedMemoryLimits(),
66       nullptr,
67       nullptr));
68   DCHECK(context.get());
69
70   return webkit::gpu::ContextProviderInProcess::Create(
71       WebGraphicsContext3DInProcessCommandBufferImpl::WrapContext(
72           context.Pass(), attributes),
73       "Parent-Compositor");
74 }
75
76 }  // namespace
77
78 HardwareRenderer::HardwareRenderer(SharedRendererState* state)
79     : shared_renderer_state_(state),
80       last_egl_context_(eglGetCurrentContext()),
81       stencil_enabled_(false),
82       viewport_clip_valid_for_dcheck_(false),
83       gl_surface_(new AwGLSurface),
84       root_layer_(cc::Layer::Create()),
85       resource_collection_(new cc::DelegatedFrameResourceCollection),
86       output_surface_(NULL) {
87   DCHECK(last_egl_context_);
88
89   resource_collection_->SetClient(this);
90
91   cc::LayerTreeSettings settings;
92
93   // Should be kept in sync with compositor_impl_android.cc.
94   settings.allow_antialiasing = false;
95   settings.highp_threshold_min = 2048;
96
97   // Webview does not own the surface so should not clear it.
98   settings.should_clear_root_render_pass = false;
99
100   // TODO(enne): Update this this compositor to use a synchronous scheduler.
101   settings.single_thread_proxy_scheduler = false;
102
103   layer_tree_host_ = cc::LayerTreeHost::CreateSingleThreaded(
104       this, this, NULL, NULL, settings, NULL);
105   layer_tree_host_->SetRootLayer(root_layer_);
106   layer_tree_host_->SetLayerTreeHostClientReady();
107   layer_tree_host_->set_has_transparent_background(true);
108 }
109
110 HardwareRenderer::~HardwareRenderer() {
111   SetFrameData();
112
113   // Must reset everything before |resource_collection_| to ensure all
114   // resources are returned before resetting |resource_collection_| client.
115   layer_tree_host_.reset();
116   root_layer_ = NULL;
117   delegated_layer_ = NULL;
118   frame_provider_ = NULL;
119 #if DCHECK_IS_ON
120   // Check collection is empty.
121   cc::ReturnedResourceArray returned_resources;
122   resource_collection_->TakeUnusedResourcesForChildCompositor(
123       &returned_resources);
124   DCHECK_EQ(0u, returned_resources.size());
125 #endif  // DCHECK_IS_ON
126
127   resource_collection_->SetClient(NULL);
128
129   // Reset draw constraints.
130   shared_renderer_state_->UpdateDrawConstraintsOnRT(
131       ParentCompositorDrawConstraints());
132 }
133
134 void HardwareRenderer::DidBeginMainFrame() {
135   // This is called after OutputSurface is created, but before the impl frame
136   // starts. We set the draw constraints here.
137   DCHECK(output_surface_);
138   DCHECK(viewport_clip_valid_for_dcheck_);
139   output_surface_->SetExternalStencilTest(stencil_enabled_);
140   output_surface_->SetDrawConstraints(viewport_, clip_);
141 }
142
143 void HardwareRenderer::CommitFrame() {
144   scroll_offset_ = shared_renderer_state_->GetScrollOffsetOnRT();
145   if (committed_frame_.get()) {
146     TRACE_EVENT_INSTANT0("android_webview",
147                          "EarlyOut_PreviousFrameUnconsumed",
148                          TRACE_EVENT_SCOPE_THREAD);
149     shared_renderer_state_->DidSkipCommitFrameOnRT();
150     return;
151   }
152
153   committed_frame_ = shared_renderer_state_->PassCompositorFrameOnRT();
154   // Happens with empty global visible rect.
155   if (!committed_frame_.get())
156     return;
157
158   DCHECK(!committed_frame_->gl_frame_data);
159   DCHECK(!committed_frame_->software_frame_data);
160
161   // DelegatedRendererLayerImpl applies the inverse device_scale_factor of the
162   // renderer frame, assuming that the browser compositor will scale
163   // it back up to device scale.  But on Android we put our browser layers in
164   // physical pixels and set our browser CC device_scale_factor to 1, so this
165   // suppresses the transform.
166   committed_frame_->delegated_frame_data->device_scale_factor = 1.0f;
167 }
168
169 void HardwareRenderer::SetFrameData() {
170   if (!committed_frame_.get())
171     return;
172
173   scoped_ptr<cc::CompositorFrame> frame = committed_frame_.Pass();
174   gfx::Size frame_size =
175       frame->delegated_frame_data->render_pass_list.back()->output_rect.size();
176   bool size_changed = frame_size != frame_size_;
177   frame_size_ = frame_size;
178
179   if (!frame_provider_.get() || size_changed) {
180     if (delegated_layer_.get()) {
181       delegated_layer_->RemoveFromParent();
182     }
183
184     frame_provider_ = new cc::DelegatedFrameProvider(
185         resource_collection_.get(), frame->delegated_frame_data.Pass());
186
187     delegated_layer_ = cc::DelegatedRendererLayer::Create(frame_provider_);
188     delegated_layer_->SetBounds(frame_size_);
189     delegated_layer_->SetIsDrawable(true);
190
191     root_layer_->AddChild(delegated_layer_);
192   } else {
193     frame_provider_->SetFrameData(frame->delegated_frame_data.Pass());
194   }
195 }
196
197 void HardwareRenderer::DrawGL(bool stencil_enabled,
198                               int framebuffer_binding_ext,
199                               AwDrawGLInfo* draw_info) {
200   TRACE_EVENT0("android_webview", "HardwareRenderer::DrawGL");
201
202   // We need to watch if the current Android context has changed and enforce
203   // a clean-up in the compositor.
204   EGLContext current_context = eglGetCurrentContext();
205   DCHECK(current_context) << "DrawGL called without EGLContext";
206
207   // TODO(boliu): Handle context loss.
208   if (last_egl_context_ != current_context)
209     DLOG(WARNING) << "EGLContextChanged";
210
211   SetFrameData();
212   if (shared_renderer_state_->ForceCommitOnRT()) {
213     CommitFrame();
214     SetFrameData();
215   }
216
217   gfx::Transform transform(gfx::Transform::kSkipInitialization);
218   transform.matrix().setColMajorf(draw_info->transform);
219   transform.Translate(scroll_offset_.x(), scroll_offset_.y());
220
221   // Need to post the new transform matrix back to child compositor
222   // because there is no onDraw during a Render Thread animation, and child
223   // compositor might not have the tiles rasterized as the animation goes on.
224   ParentCompositorDrawConstraints draw_constraints(
225       draw_info->is_layer, transform, gfx::Rect(viewport_));
226
227   draw_constraints_ = draw_constraints;
228   shared_renderer_state_->PostExternalDrawConstraintsToChildCompositorOnRT(
229       draw_constraints);
230
231   if (!delegated_layer_.get())
232     return;
233
234   viewport_.SetSize(draw_info->width, draw_info->height);
235   layer_tree_host_->SetViewportSize(viewport_);
236   clip_.SetRect(draw_info->clip_left,
237                 draw_info->clip_top,
238                 draw_info->clip_right - draw_info->clip_left,
239                 draw_info->clip_bottom - draw_info->clip_top);
240   stencil_enabled_ = stencil_enabled;
241
242   delegated_layer_->SetTransform(transform);
243
244   gl_surface_->SetBackingFrameBufferObject(framebuffer_binding_ext);
245   {
246     base::AutoReset<bool> frame_resetter(&viewport_clip_valid_for_dcheck_,
247                                          true);
248     layer_tree_host_->SetNeedsRedrawRect(clip_);
249     layer_tree_host_->Composite(gfx::FrameTime::Now());
250   }
251   gl_surface_->ResetBackingFrameBufferObject();
252 }
253
254 void HardwareRenderer::RequestNewOutputSurface(bool fallback) {
255   // Android webview does not support losing output surface.
256   DCHECK(!fallback);
257   scoped_refptr<cc::ContextProvider> context_provider =
258       CreateContext(gl_surface_,
259                     DeferredGpuCommandService::GetInstance());
260   scoped_ptr<ParentOutputSurface> output_surface_holder(
261       new ParentOutputSurface(context_provider));
262   output_surface_ = output_surface_holder.get();
263   layer_tree_host_->SetOutputSurface(output_surface_holder.Pass());
264 }
265
266 void HardwareRenderer::UnusedResourcesAreAvailable() {
267   cc::ReturnedResourceArray returned_resources;
268   resource_collection_->TakeUnusedResourcesForChildCompositor(
269       &returned_resources);
270   shared_renderer_state_->InsertReturnedResourcesOnRT(returned_resources);
271 }
272
273 }  // namespace android_webview