| Index: android_webview/browser/hardware_renderer.cc
|
| diff --git a/android_webview/browser/hardware_renderer.cc b/android_webview/browser/hardware_renderer.cc
|
| index f2cf8e90b17cec80a443857cd5dfff71a943bc9a..e01716a26937ee0451c746b590c9b6048c06906e 100644
|
| --- a/android_webview/browser/hardware_renderer.cc
|
| +++ b/android_webview/browser/hardware_renderer.cc
|
| @@ -5,35 +5,125 @@
|
| #include "android_webview/browser/hardware_renderer.h"
|
|
|
| #include "android_webview/browser/aw_gl_surface.h"
|
| -#include "android_webview/browser/browser_view_renderer_client.h"
|
| +#include "android_webview/browser/deferred_gpu_command_service.h"
|
| +#include "android_webview/browser/parent_output_surface.h"
|
| +#include "android_webview/browser/shared_renderer_state.h"
|
| #include "android_webview/public/browser/draw_gl.h"
|
| +#include "base/auto_reset.h"
|
| #include "base/debug/trace_event.h"
|
| #include "base/strings/string_number_conversions.h"
|
| -#include "content/public/browser/android/synchronous_compositor.h"
|
| -#include "content/public/browser/browser_thread.h"
|
| -#include "gpu/command_buffer/service/shader_translator_cache.h"
|
| +#include "cc/layers/delegated_frame_provider.h"
|
| +#include "cc/layers/delegated_renderer_layer.h"
|
| +#include "cc/layers/layer.h"
|
| +#include "cc/output/compositor_frame.h"
|
| +#include "cc/output/output_surface.h"
|
| +#include "cc/trees/layer_tree_host.h"
|
| +#include "cc/trees/layer_tree_settings.h"
|
| +#include "gpu/command_buffer/client/gl_in_process_context.h"
|
| +#include "ui/gfx/frame_time.h"
|
| #include "ui/gfx/geometry/rect_conversions.h"
|
| #include "ui/gfx/geometry/rect_f.h"
|
| #include "ui/gfx/transform.h"
|
| #include "ui/gl/gl_bindings.h"
|
| +#include "webkit/common/gpu/context_provider_in_process.h"
|
| +#include "webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h"
|
|
|
| namespace android_webview {
|
|
|
| +namespace {
|
| +
|
| +using webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl;
|
| +
|
| +scoped_refptr<cc::ContextProvider> CreateContext(
|
| + scoped_refptr<gfx::GLSurface> surface,
|
| + scoped_refptr<gpu::InProcessCommandBuffer::Service> service,
|
| + gpu::GLInProcessContext* share_context) {
|
| + const gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu;
|
| +
|
| + blink::WebGraphicsContext3D::Attributes attributes;
|
| + attributes.antialias = false;
|
| + attributes.depth = false;
|
| + attributes.stencil = false;
|
| + attributes.shareResources = true;
|
| + attributes.noAutomaticFlushes = true;
|
| + gpu::GLInProcessContextAttribs in_process_attribs;
|
| + WebGraphicsContext3DInProcessCommandBufferImpl::ConvertAttributes(
|
| + attributes, &in_process_attribs);
|
| + in_process_attribs.lose_context_when_out_of_memory = 1;
|
| +
|
| + scoped_ptr<gpu::GLInProcessContext> context(
|
| + gpu::GLInProcessContext::Create(service,
|
| + surface,
|
| + surface->IsOffscreen(),
|
| + gfx::kNullAcceleratedWidget,
|
| + surface->GetSize(),
|
| + share_context,
|
| + false /* share_resources */,
|
| + in_process_attribs,
|
| + gpu_preference));
|
| + DCHECK(context.get());
|
| +
|
| + return webkit::gpu::ContextProviderInProcess::Create(
|
| + WebGraphicsContext3DInProcessCommandBufferImpl::WrapContext(
|
| + context.Pass(), attributes),
|
| + "Parent-Compositor");
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| HardwareRenderer::HardwareRenderer(SharedRendererState* state)
|
| : shared_renderer_state_(state),
|
| - last_egl_context_(eglGetCurrentContext()) {
|
| + last_egl_context_(eglGetCurrentContext()),
|
| + view_width_(-1),
|
| + view_height_(-1),
|
| + viewport_clip_valid_for_dcheck_(false),
|
| + root_layer_(cc::Layer::Create()),
|
| + output_surface_(NULL) {
|
| DCHECK(last_egl_context_);
|
|
|
| gl_surface_ = new AwGLSurface;
|
| - bool success =
|
| - shared_renderer_state_->GetCompositor()->
|
| - InitializeHwDraw(gl_surface_);
|
| - DCHECK(success);
|
| +
|
| + cc::LayerTreeSettings settings;
|
| +
|
| + // Should be kept in sync with compositor_impl_android.cc.
|
| + settings.allow_antialiasing = false;
|
| + settings.highp_threshold_min = 2048;
|
| +
|
| + // Webview does not own the surface so should not clear it.
|
| + settings.should_clear_root_render_pass = false;
|
| +
|
| + layer_tree_host_ =
|
| + cc::LayerTreeHost::CreateSingleThreaded(this, this, NULL, settings);
|
| + layer_tree_host_->SetRootLayer(root_layer_);
|
| + layer_tree_host_->SetLayerTreeHostClientReady();
|
| }
|
|
|
| HardwareRenderer::~HardwareRenderer() {
|
| - shared_renderer_state_->GetCompositor()->ReleaseHwDraw();
|
| - gl_surface_ = NULL;
|
| + // Must reset everything before |resource_collection_| to ensure all
|
| + // resources are returned before resetting |resource_collection_| client.
|
| + layer_tree_host_.reset();
|
| + root_layer_ = NULL;
|
| + delegated_layer_ = NULL;
|
| + frame_provider_ = NULL;
|
| + if (resource_collection_.get()) {
|
| +#if DCHECK_IS_ON
|
| + // Check collection is empty.
|
| + cc::ReturnedResourceArray returned_resources;
|
| + resource_collection_->TakeUnusedResourcesForChildCompositor(
|
| + &returned_resources);
|
| + DCHECK_EQ(0, returned_resources.size());
|
| +#endif // DCHECK_IS_ON
|
| +
|
| + resource_collection_->SetClient(NULL);
|
| + }
|
| +}
|
| +
|
| +void HardwareRenderer::DidBeginMainFrame() {
|
| + // This is called after OutputSurface is created, but before the impl frame
|
| + // starts. We set the draw constraints here.
|
| + DCHECK(output_surface_);
|
| + DCHECK(viewport_clip_valid_for_dcheck_);
|
| + output_surface_->SetDrawConstraints(viewport_, clip_);
|
| }
|
|
|
| bool HardwareRenderer::DrawGL(bool stencil_enabled,
|
| @@ -54,54 +144,83 @@ bool HardwareRenderer::DrawGL(bool stencil_enabled,
|
| if (last_egl_context_ != current_context)
|
| DLOG(WARNING) << "EGLContextChanged";
|
|
|
| - if (draw_info->mode != AwDrawGLInfo::kModeDraw)
|
| - return false;
|
| + scoped_ptr<DrawGLInput> input = shared_renderer_state_->PassDrawGLInput();
|
| + if (!resource_collection_.get()) {
|
| + resource_collection_ = new cc::DelegatedFrameResourceCollection;
|
| + resource_collection_->SetClient(this);
|
| + }
|
|
|
| - // Should only need to access SharedRendererState in kModeDraw and kModeSync.
|
| - const DrawGLInput input = shared_renderer_state_->GetDrawGLInput();
|
| - SetCompositorMemoryPolicy();
|
| + if (input.get()) {
|
| + DCHECK(!input->frame.gl_frame_data);
|
| + DCHECK(!input->frame.software_frame_data);
|
| +
|
| + bool size_changed =
|
| + input->width != view_width_ || input->height != view_height_;
|
| + view_width_ = input->width;
|
| + view_height_ = input->height;
|
| + scroll_offset_ = input->scroll_offset;
|
| +
|
| + if (!frame_provider_ || size_changed) {
|
| + if (delegated_layer_) {
|
| + delegated_layer_->RemoveFromParent();
|
| + }
|
| +
|
| + frame_provider_ = new cc::DelegatedFrameProvider(
|
| + resource_collection_.get(), input->frame.delegated_frame_data.Pass());
|
| +
|
| + delegated_layer_ = cc::DelegatedRendererLayer::Create(frame_provider_);
|
| + delegated_layer_->SetBounds(gfx::Size(view_width_, view_height_));
|
| + delegated_layer_->SetIsDrawable(true);
|
| + delegated_layer_->SetAnchorPoint(gfx::PointF(0.f, 0.f));
|
| +
|
| + root_layer_->AddChild(delegated_layer_);
|
| + } else {
|
| + frame_provider_->SetFrameData(input->frame.delegated_frame_data.Pass());
|
| + }
|
| + }
|
|
|
| - gl_surface_->SetBackingFrameBufferObject(framebuffer_binding_ext);
|
| + viewport_.SetSize(draw_info->width, draw_info->height);
|
| + layer_tree_host_->SetViewportSize(viewport_);
|
| + clip_.SetRect(draw_info->clip_left,
|
| + draw_info->clip_top,
|
| + draw_info->clip_right - draw_info->clip_left,
|
| + draw_info->clip_bottom - draw_info->clip_top);
|
|
|
| - gfx::Transform transform;
|
| + gfx::Transform transform(gfx::Transform::kSkipInitialization);
|
| transform.matrix().setColMajorf(draw_info->transform);
|
| - transform.Translate(input.scroll_offset.x(), input.scroll_offset.y());
|
| - gfx::Rect clip_rect(draw_info->clip_left,
|
| - draw_info->clip_top,
|
| - draw_info->clip_right - draw_info->clip_left,
|
| - draw_info->clip_bottom - draw_info->clip_top);
|
| -
|
| - gfx::Rect viewport(draw_info->width, draw_info->height);
|
| - if (!draw_info->is_layer) {
|
| - gfx::RectF view_rect(input.width, input.height);
|
| - transform.TransformRect(&view_rect);
|
| - viewport.Intersect(gfx::ToEnclosingRect(view_rect));
|
| - }
|
| + transform.Translate(scroll_offset_.x(), scroll_offset_.y());
|
| + delegated_layer_->SetTransform(transform);
|
|
|
| - bool did_draw = shared_renderer_state_->GetCompositor()->DemandDrawHw(
|
| - gfx::Size(draw_info->width, draw_info->height),
|
| - transform,
|
| - viewport,
|
| - clip_rect,
|
| - stencil_enabled);
|
| + gl_surface_->SetBackingFrameBufferObject(framebuffer_binding_ext);
|
| + {
|
| + base::AutoReset<bool> frame_resetter(&viewport_clip_valid_for_dcheck_,
|
| + true);
|
| + layer_tree_host_->Composite(gfx::FrameTime::Now());
|
| + }
|
| gl_surface_->ResetBackingFrameBufferObject();
|
|
|
| - if (did_draw) {
|
| - result->frame_id = input.frame_id;
|
| - result->clip_contains_visible_rect =
|
| - clip_rect.Contains(input.global_visible_rect);
|
| - }
|
| - return did_draw;
|
| + return true;
|
| }
|
|
|
| -void HardwareRenderer::SetCompositorMemoryPolicy() {
|
| - if (shared_renderer_state_->IsMemoryPolicyDirty()) {
|
| - content::SynchronousCompositorMemoryPolicy policy =
|
| - shared_renderer_state_->GetMemoryPolicy();
|
| - // Memory policy is set by BrowserViewRenderer on UI thread.
|
| - shared_renderer_state_->GetCompositor()->SetMemoryPolicy(policy);
|
| - shared_renderer_state_->SetMemoryPolicyDirty(false);
|
| - }
|
| +scoped_ptr<cc::OutputSurface> HardwareRenderer::CreateOutputSurface(
|
| + bool fallback) {
|
| + // Android webview does not support losing output surface.
|
| + DCHECK(!fallback);
|
| + scoped_refptr<cc::ContextProvider> context_provider =
|
| + CreateContext(gl_surface_,
|
| + DeferredGpuCommandService::GetInstance(),
|
| + shared_renderer_state_->GetSharedContext());
|
| + scoped_ptr<ParentOutputSurface> output_surface_holder(
|
| + new ParentOutputSurface(context_provider));
|
| + output_surface_ = output_surface_holder.get();
|
| + return output_surface_holder.PassAs<cc::OutputSurface>();
|
| +}
|
| +
|
| +void HardwareRenderer::UnusedResourcesAreAvailable() {
|
| + cc::ReturnedResourceArray returned_resources;
|
| + resource_collection_->TakeUnusedResourcesForChildCompositor(
|
| + &returned_resources);
|
| + shared_renderer_state_->InsertReturnedResources(returned_resources);
|
| }
|
|
|
| } // namespace android_webview
|
|
|