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/aw_render_thread_context_provider.h"
9 #include "android_webview/browser/child_frame.h"
10 #include "android_webview/browser/deferred_gpu_command_service.h"
11 #include "android_webview/browser/parent_compositor_draw_constraints.h"
12 #include "android_webview/browser/parent_output_surface.h"
13 #include "android_webview/browser/shared_renderer_state.h"
14 #include "android_webview/public/browser/draw_gl.h"
15 #include "base/auto_reset.h"
16 #include "base/strings/string_number_conversions.h"
17 #include "base/trace_event/trace_event.h"
18 #include "cc/output/compositor_frame.h"
19 #include "cc/output/output_surface.h"
20 #include "cc/output/renderer_settings.h"
21 #include "cc/quads/shared_quad_state.h"
22 #include "cc/quads/surface_draw_quad.h"
23 #include "cc/surfaces/display.h"
24 #include "cc/surfaces/surface_factory.h"
25 #include "cc/surfaces/surface_id_allocator.h"
26 #include "gpu/command_buffer/client/gl_in_process_context.h"
27 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
28 #include "ui/gfx/geometry/rect_conversions.h"
29 #include "ui/gfx/geometry/rect_f.h"
30 #include "ui/gfx/transform.h"
31 #include "ui/gl/gl_bindings.h"
33 namespace android_webview
{
35 HardwareRenderer::HardwareRenderer(SharedRendererState
* state
)
36 : shared_renderer_state_(state
),
37 last_egl_context_(eglGetCurrentContext()),
38 gl_surface_(new AwGLSurface
),
39 output_surface_(NULL
) {
40 DCHECK(last_egl_context_
);
42 cc::RendererSettings settings
;
44 // Should be kept in sync with compositor_impl_android.cc.
45 settings
.allow_antialiasing
= false;
46 settings
.highp_threshold_min
= 2048;
48 // Webview does not own the surface so should not clear it.
49 settings
.should_clear_root_render_pass
= false;
51 surface_manager_
.reset(new cc::SurfaceManager
);
52 surface_id_allocator_
.reset(new cc::SurfaceIdAllocator(1));
53 display_
.reset(new cc::Display(this, surface_manager_
.get(), nullptr, nullptr,
55 surface_factory_
.reset(new cc::SurfaceFactory(surface_manager_
.get(), this));
58 HardwareRenderer::~HardwareRenderer() {
59 // Must reset everything before |surface_factory_| to ensure all
60 // resources are returned before resetting.
61 if (!root_id_
.is_null())
62 surface_factory_
->Destroy(root_id_
);
63 if (!child_id_
.is_null())
64 surface_factory_
->Destroy(child_id_
);
66 surface_factory_
.reset();
68 // Reset draw constraints.
69 shared_renderer_state_
->PostExternalDrawConstraintsToChildCompositorOnRT(
70 ParentCompositorDrawConstraints());
73 void HardwareRenderer::CommitFrame() {
74 TRACE_EVENT0("android_webview", "CommitFrame");
75 scroll_offset_
= shared_renderer_state_
->GetScrollOffsetOnRT();
77 scoped_ptr
<ChildFrame
> child_frame
=
78 shared_renderer_state_
->PassCompositorFrameOnRT();
79 if (!child_frame
.get())
81 child_frame_
= child_frame
.Pass();
84 scoped_ptr
<cc::CompositorFrame
> frame
= child_frame_
->frame
.Pass();
86 DCHECK(!frame
->gl_frame_data
);
88 // On Android we put our browser layers in physical pixels and set our
89 // browser CC device_scale_factor to 1, so suppress the transform between
91 frame
->delegated_frame_data
->device_scale_factor
= 1.0f
;
93 gfx::Size frame_size
=
94 frame
->delegated_frame_data
->render_pass_list
.back()->output_rect
.size();
95 bool size_changed
= frame_size
!= frame_size_
;
96 frame_size_
= frame_size
;
97 if (child_id_
.is_null() || size_changed
) {
98 if (!child_id_
.is_null())
99 surface_factory_
->Destroy(child_id_
);
100 child_id_
= surface_id_allocator_
->GenerateId();
101 surface_factory_
->Create(child_id_
);
104 surface_factory_
->SubmitFrame(child_id_
, frame
.Pass(),
105 cc::SurfaceFactory::DrawCallback());
108 void HardwareRenderer::DrawGL(bool stencil_enabled
,
109 int framebuffer_binding_ext
,
110 AwDrawGLInfo
* draw_info
) {
111 TRACE_EVENT0("android_webview", "HardwareRenderer::DrawGL");
113 // We need to watch if the current Android context has changed and enforce
114 // a clean-up in the compositor.
115 EGLContext current_context
= eglGetCurrentContext();
116 DCHECK(current_context
) << "DrawGL called without EGLContext";
118 // TODO(boliu): Handle context loss.
119 if (last_egl_context_
!= current_context
)
120 DLOG(WARNING
) << "EGLContextChanged";
122 gfx::Transform
transform(gfx::Transform::kSkipInitialization
);
123 transform
.matrix().setColMajorf(draw_info
->transform
);
124 transform
.Translate(scroll_offset_
.x(), scroll_offset_
.y());
126 gfx::Size
viewport(draw_info
->width
, draw_info
->height
);
127 // Need to post the new transform matrix back to child compositor
128 // because there is no onDraw during a Render Thread animation, and child
129 // compositor might not have the tiles rasterized as the animation goes on.
130 ParentCompositorDrawConstraints
draw_constraints(
131 draw_info
->is_layer
, transform
, viewport
.IsEmpty());
132 if (!child_frame_
.get() || draw_constraints
.NeedUpdate(*child_frame_
)) {
133 shared_renderer_state_
->PostExternalDrawConstraintsToChildCompositorOnRT(
137 if (child_id_
.is_null())
140 gfx::Rect
clip(draw_info
->clip_left
, draw_info
->clip_top
,
141 draw_info
->clip_right
- draw_info
->clip_left
,
142 draw_info
->clip_bottom
- draw_info
->clip_top
);
144 // Create a frame with a single SurfaceDrawQuad referencing the child
145 // Surface and transformed using the given transform.
146 scoped_ptr
<cc::RenderPass
> render_pass
= cc::RenderPass::Create();
147 render_pass
->SetAll(cc::RenderPassId(1, 1), gfx::Rect(viewport
), clip
,
148 gfx::Transform(), true);
150 cc::SharedQuadState
* quad_state
=
151 render_pass
->CreateAndAppendSharedQuadState();
152 quad_state
->quad_to_target_transform
= transform
;
153 quad_state
->quad_layer_bounds
= frame_size_
;
154 quad_state
->visible_quad_layer_rect
= gfx::Rect(frame_size_
);
155 quad_state
->opacity
= 1.f
;
157 cc::SurfaceDrawQuad
* surface_quad
=
158 render_pass
->CreateAndAppendDrawQuad
<cc::SurfaceDrawQuad
>();
159 surface_quad
->SetNew(quad_state
, gfx::Rect(quad_state
->quad_layer_bounds
),
160 gfx::Rect(quad_state
->quad_layer_bounds
), child_id_
);
162 scoped_ptr
<cc::DelegatedFrameData
> delegated_frame(
163 new cc::DelegatedFrameData
);
164 delegated_frame
->render_pass_list
.push_back(render_pass
.Pass());
165 scoped_ptr
<cc::CompositorFrame
> frame(new cc::CompositorFrame
);
166 frame
->delegated_frame_data
= delegated_frame
.Pass();
168 if (root_id_
.is_null()) {
169 root_id_
= surface_id_allocator_
->GenerateId();
170 surface_factory_
->Create(root_id_
);
171 display_
->SetSurfaceId(root_id_
, 1.f
);
173 surface_factory_
->SubmitFrame(root_id_
, frame
.Pass(),
174 cc::SurfaceFactory::DrawCallback());
176 display_
->Resize(viewport
);
178 gl_surface_
->SetBackingFrameBufferObject(framebuffer_binding_ext
);
179 if (!output_surface_
) {
180 scoped_refptr
<cc::ContextProvider
> context_provider
=
181 AwRenderThreadContextProvider::Create(
182 gl_surface_
, DeferredGpuCommandService::GetInstance());
183 scoped_ptr
<ParentOutputSurface
> output_surface_holder(
184 new ParentOutputSurface(context_provider
));
185 output_surface_
= output_surface_holder
.get();
186 display_
->Initialize(output_surface_holder
.Pass(), nullptr);
188 output_surface_
->SetExternalStencilTest(stencil_enabled
);
189 display_
->SetExternalClip(clip
);
190 display_
->DrawAndSwap();
191 gl_surface_
->ResetBackingFrameBufferObject();
194 void HardwareRenderer::ReturnResources(
195 const cc::ReturnedResourceArray
& resources
) {
196 shared_renderer_state_
->InsertReturnedResourcesOnRT(resources
);
199 } // namespace android_webview