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