Commit 84ed5b3e authored by Vasiliy Telezhnikov's avatar Vasiliy Telezhnikov Committed by Commit Bot

aw: Support ExternalStencil with SkiaRenderer

This CL implements External Stencil support for webview with
SkiaRenderer by drawing to intermediate FBO and then drawing
to main frame buffer the quad with it using stencil test.

Bug: 805739
Change-Id: I00a3406cced343a08ee0ed3ad7264d3c8b65ca72
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2031556Reviewed-by: default avatarBo <boliu@chromium.org>
Reviewed-by: default avatarJonathan Backer <backer@chromium.org>
Commit-Queue: Vasiliy Telezhnikov <vasilyt@chromium.org>
Cr-Commit-Position: refs/heads/master@{#739056}
parent fcfcd52d
...@@ -15,6 +15,8 @@ source_set("gfx") { ...@@ -15,6 +15,8 @@ source_set("gfx") {
"aw_gl_functor.h", "aw_gl_functor.h",
"aw_gl_surface.cc", "aw_gl_surface.cc",
"aw_gl_surface.h", "aw_gl_surface.h",
"aw_gl_surface_external_stencil.cc",
"aw_gl_surface_external_stencil.h",
"aw_picture.cc", "aw_picture.cc",
"aw_picture.h", "aw_picture.h",
"aw_render_thread_context_provider.cc", "aw_render_thread_context_provider.cc",
......
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
#define ANDROID_WEBVIEW_BROWSER_GFX_AW_GL_SURFACE_H_ #define ANDROID_WEBVIEW_BROWSER_GFX_AW_GL_SURFACE_H_
#include "base/macros.h" #include "base/macros.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/transform.h"
#include "ui/gl/gl_surface.h" #include "ui/gl/gl_surface.h"
namespace android_webview { namespace android_webview {
...@@ -34,6 +36,10 @@ class AwGLSurface : public gl::GLSurface { ...@@ -34,6 +36,10 @@ class AwGLSurface : public gl::GLSurface {
void SetSize(const gfx::Size& size); void SetSize(const gfx::Size& size);
void MaybeDidPresent(gfx::PresentationFeedback feedback); void MaybeDidPresent(gfx::PresentationFeedback feedback);
virtual void RecalculateClipAndTransform(gfx::Size* viewport,
gfx::Rect* clip_rect,
gfx::Transform* transform) {}
protected: protected:
~AwGLSurface() override; ~AwGLSurface() override;
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "android_webview/browser/gfx/aw_gl_surface_external_stencil.h"
#include "android_webview/browser/gfx/scoped_app_gl_state_restore.h"
#include "base/strings/stringize_macros.h"
#include "ui/gfx/geometry/quad_f.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_helper.h"
namespace android_webview {
class AwGLSurfaceExternalStencil::BlitContext {
public:
BlitContext() {
// NOTE: Quad is flipped vertically.
// clang-format off
const GLchar vertex_shader_str[] =
STRINGIZE(
attribute vec2 position;
attribute vec2 texcoords;
varying vec2 v_texcoords;
void main()
{
v_texcoords = vec2(texcoords.x, 1.0 - texcoords.y);
vec2 pos = position * 2.0 - vec2(1.0);
gl_Position = vec4(pos.x, -pos.y, 0.0, 1.0);
}
);
const GLchar fragment_shader_str[] =
STRINGIZE(
precision mediump float;
varying vec2 v_texcoords;
uniform sampler2D texture;
void main()
{
gl_FragColor = texture2D ( texture, v_texcoords );
}
);
// clang-format on
GLuint vertex_shader =
gl::GLHelper::LoadShader(GL_VERTEX_SHADER, vertex_shader_str);
GLuint fragment_shader =
gl::GLHelper::LoadShader(GL_FRAGMENT_SHADER, fragment_shader_str);
program_ = glCreateProgram();
glAttachShader(program_, vertex_shader);
glAttachShader(program_, fragment_shader);
glBindAttribLocation(program_, 0, "position");
glBindAttribLocation(program_, 1, "texcoords");
glLinkProgram(program_);
GLint linked;
glGetProgramiv(program_, GL_LINK_STATUS, &linked);
DCHECK(linked);
glDeleteShader(vertex_shader);
glDeleteShader(fragment_shader);
texture_uniform_ = glGetUniformLocation(program_, "texture");
glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &gl_max_vertex_attribs_);
}
~BlitContext() { glDeleteProgram(program_); }
void Bind() {
glUseProgram(program_);
for (GLint i = 2; i < gl_max_vertex_attribs_; ++i) {
glDisableVertexAttribArray(i);
}
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glUniform1i(texture_uniform_, 0);
}
private:
GLuint program_;
GLint texture_uniform_;
GLint gl_max_vertex_attribs_;
};
class AwGLSurfaceExternalStencil::FrameBuffer {
public:
FrameBuffer(gfx::Size size) : size_(size) {
glGenTextures(1, &texture_id_);
glBindTexture(GL_TEXTURE_2D, texture_id_);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0,
GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
glGenFramebuffersEXT(1, &frame_buffer_object_);
glBindFramebufferEXT(GL_FRAMEBUFFER, frame_buffer_object_);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, texture_id_, 0);
DCHECK(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER) ==
GL_FRAMEBUFFER_COMPLETE)
<< "Failed to set up framebuffer for WebView GL drawing.";
}
void Clear() {
glBindFramebufferEXT(GL_FRAMEBUFFER, frame_buffer_object_);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
}
~FrameBuffer() {
glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
glBindTexture(GL_TEXTURE_2D, 0);
if (frame_buffer_object_)
glDeleteFramebuffersEXT(1, &frame_buffer_object_);
if (texture_id_)
glDeleteTextures(1, &texture_id_);
}
GLuint frame_buffer_object() const { return frame_buffer_object_; }
GLuint texture_id() const { return texture_id_; }
gfx::Size size() const { return size_; }
private:
GLuint frame_buffer_object_ = 0;
GLuint texture_id_ = 0;
gfx::Size size_;
};
AwGLSurfaceExternalStencil::AwGLSurfaceExternalStencil() {}
AwGLSurfaceExternalStencil::~AwGLSurfaceExternalStencil() = default;
unsigned int AwGLSurfaceExternalStencil::GetBackingFramebufferObject() {
const auto& stencil_state =
android_webview::ScopedAppGLStateRestore::Current()->stencil_state();
if (stencil_state.stencil_test_enabled) {
// Framebuffer was created during RecalculateClipAndTransform();
DCHECK(framebuffer_);
return framebuffer_->frame_buffer_object();
}
return AwGLSurface::GetBackingFramebufferObject();
}
gfx::SwapResult AwGLSurfaceExternalStencil::SwapBuffers(
PresentationCallback callback) {
const auto& stencil_state =
android_webview::ScopedAppGLStateRestore::Current()->stencil_state();
if (stencil_state.stencil_test_enabled) {
DCHECK(framebuffer_);
DCHECK(blit_context_);
// Restore stencil state.
glEnable(GL_STENCIL_TEST);
glStencilFuncSeparate(GL_FRONT, stencil_state.stencil_front_func,
stencil_state.stencil_front_mask,
stencil_state.stencil_front_ref);
glStencilFuncSeparate(GL_BACK, stencil_state.stencil_back_func,
stencil_state.stencil_back_mask,
stencil_state.stencil_back_ref);
glStencilMaskSeparate(GL_FRONT, stencil_state.stencil_front_writemask);
glStencilMaskSeparate(GL_BACK, stencil_state.stencil_back_writemask);
glStencilOpSeparate(GL_FRONT, stencil_state.stencil_front_fail_op,
stencil_state.stencil_front_z_fail_op,
stencil_state.stencil_front_z_pass_op);
glStencilOpSeparate(GL_BACK, stencil_state.stencil_back_fail_op,
stencil_state.stencil_back_z_fail_op,
stencil_state.stencil_back_z_pass_op);
// Bind required context.
blit_context_->Bind();
// Bind real frame buffer.
glBindFramebufferEXT(GL_FRAMEBUFFER,
AwGLSurface::GetBackingFramebufferObject());
// Scale clip rect to (0, 0)x(1, 1) space.
gfx::QuadF quad = gfx::QuadF(gfx::RectF(clip_rect_));
quad.Scale(1.0 / viewport_.width(), 1.0 / viewport_.height());
gfx::QuadF tex_quad = gfx::QuadF(gfx::RectF(1.0, 1.0));
// Set-up vertex attributes. p1-p4-p2-p3 forms triangle strip for quad.
// clang-format off
const gfx::PointF data[8] = {quad.p1(), tex_quad.p1(),
quad.p4(), tex_quad.p4(),
quad.p2(), tex_quad.p2(),
quad.p3(), tex_quad.p3()};
// clang-format on
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(gfx::PointF) * 2,
&data[1]);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(gfx::PointF) * 2,
&data[0]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, framebuffer_->texture_id());
// We need to restore viewport as it might have changed by renderer
glViewport(0, 0, viewport_.width(), viewport_.height());
// We draw only inside clip rect, no need to scissor.
glDisable(GL_SCISSOR_TEST);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
return AwGLSurface::SwapBuffers(std::move(callback));
}
void AwGLSurfaceExternalStencil::RecalculateClipAndTransform(
gfx::Size* viewport,
gfx::Rect* clip_rect,
gfx::Transform* transform) {
clip_rect_ = *clip_rect;
viewport_ = *viewport;
const auto& stencil_state =
android_webview::ScopedAppGLStateRestore::Current()->stencil_state();
if (stencil_state.stencil_test_enabled) {
// Initialize graphics part needed for blit with stencil here so we don't
// change any gl state after GrContext reset after this function call.
if (!blit_context_) {
blit_context_ = std::make_unique<BlitContext>();
}
if (!framebuffer_ || framebuffer_->size() != clip_rect_.size()) {
// Delete old one first to reduce peak memory.
framebuffer_.reset();
framebuffer_ = std::make_unique<FrameBuffer>(clip_rect_.size());
}
framebuffer_->Clear();
// Adjust transform, clip rect and viewport to be in original clip rect
// space as we will draw to FBO of clip_rect size and blit it to screen at
// original location.
transform->Translate(-clip_rect->x(), -clip_rect->y());
clip_rect->set_origin(gfx::Point(0, 0));
*viewport = clip_rect_.size();
} else {
// We're not going to draw to frame buffer, so we can free it to save
// memory, assuming |stencil_test_enabled| doesn't change often.
framebuffer_.reset();
}
}
} // namespace android_webview
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ANDROID_WEBVIEW_BROWSER_GFX_AW_GL_SURFACE_EXTERNAL_STENCIL_H_
#define ANDROID_WEBVIEW_BROWSER_GFX_AW_GL_SURFACE_EXTERNAL_STENCIL_H_
#include "android_webview/browser/gfx/aw_gl_surface.h"
namespace android_webview {
class AwGLSurfaceExternalStencil : public AwGLSurface {
public:
AwGLSurfaceExternalStencil();
AwGLSurfaceExternalStencil(const AwGLSurfaceExternalStencil&) = delete;
AwGLSurfaceExternalStencil& operator=(const AwGLSurfaceExternalStencil&) =
delete;
void SetClipRectangle(gfx::Rect clip_rect);
unsigned int GetBackingFramebufferObject() override;
gfx::SwapResult SwapBuffers(PresentationCallback callback) override;
void RecalculateClipAndTransform(gfx::Size* viewport,
gfx::Rect* clip_rect,
gfx::Transform* transform) override;
protected:
~AwGLSurfaceExternalStencil() override;
private:
class BlitContext;
class FrameBuffer;
// Contains GL shader and other info required to draw a quad.
std::unique_ptr<BlitContext> blit_context_;
std::unique_ptr<FrameBuffer> framebuffer_;
gfx::Rect clip_rect_;
gfx::Size viewport_;
};
} // namespace android_webview
#endif // ANDROID_WEBVIEW_BROWSER_GFX_AW_GL_SURFACE_EXTERNAL_STENCIL_H_
...@@ -334,6 +334,9 @@ void HardwareRendererViz::DrawAndSwap(HardwareRendererDrawParams* params) { ...@@ -334,6 +334,9 @@ void HardwareRendererViz::DrawAndSwap(HardwareRendererDrawParams* params) {
params->clip_right - params->clip_left, params->clip_right - params->clip_left,
params->clip_bottom - params->clip_top); params->clip_bottom - params->clip_top);
output_surface_provider_.gl_surface()->RecalculateClipAndTransform(
&viewport, &clip, &transform);
DCHECK(output_surface_provider_.shared_context_state()); DCHECK(output_surface_provider_.shared_context_state());
output_surface_provider_.shared_context_state() output_surface_provider_.shared_context_state()
->PessimisticallyResetGrContext(); ->PessimisticallyResetGrContext();
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "android_webview/browser/gfx/output_surface_provider_webview.h" #include "android_webview/browser/gfx/output_surface_provider_webview.h"
#include "android_webview/browser/gfx/aw_gl_surface_external_stencil.h"
#include "android_webview/browser/gfx/aw_render_thread_context_provider.h" #include "android_webview/browser/gfx/aw_render_thread_context_provider.h"
#include "android_webview/browser/gfx/aw_vulkan_context_provider.h" #include "android_webview/browser/gfx/aw_vulkan_context_provider.h"
#include "android_webview/browser/gfx/deferred_gpu_command_service.h" #include "android_webview/browser/gfx/deferred_gpu_command_service.h"
...@@ -59,7 +60,13 @@ OutputSurfaceProviderWebview::~OutputSurfaceProviderWebview() = default; ...@@ -59,7 +60,13 @@ OutputSurfaceProviderWebview::~OutputSurfaceProviderWebview() = default;
void OutputSurfaceProviderWebview::InitializeContext() { void OutputSurfaceProviderWebview::InitializeContext() {
DCHECK(!gl_surface_) << "InitializeContext() called twice"; DCHECK(!gl_surface_) << "InitializeContext() called twice";
gl_surface_ = base::MakeRefCounted<AwGLSurface>();
if (renderer_settings_.use_skia_renderer && !enable_vulkan_) {
// We need to draw to FBO for External Stencil support with SkiaRenderer
gl_surface_ = base::MakeRefCounted<AwGLSurfaceExternalStencil>();
} else {
gl_surface_ = base::MakeRefCounted<AwGLSurface>();
}
if (renderer_settings_.use_skia_renderer) { if (renderer_settings_.use_skia_renderer) {
auto share_group = base::MakeRefCounted<gl::GLShareGroup>(); auto share_group = base::MakeRefCounted<gl::GLShareGroup>();
......
...@@ -153,4 +153,8 @@ void SkiaOutputSurfaceDependencyWebView::ScheduleDelayedGPUTaskFromGPUThread( ...@@ -153,4 +153,8 @@ void SkiaOutputSurfaceDependencyWebView::ScheduleDelayedGPUTaskFromGPUThread(
task_queue_->ScheduleIdleTask(std::move(task)); task_queue_->ScheduleIdleTask(std::move(task));
} }
bool SkiaOutputSurfaceDependencyWebView::NeedsSupportForExternalStencil() {
return true;
}
} // namespace android_webview } // namespace android_webview
...@@ -55,6 +55,7 @@ class SkiaOutputSurfaceDependencyWebView ...@@ -55,6 +55,7 @@ class SkiaOutputSurfaceDependencyWebView
const GURL& active_url) override; const GURL& active_url) override;
base::TimeDelta GetGpuBlockedTimeSinceLastSwap() override; base::TimeDelta GetGpuBlockedTimeSinceLastSwap() override;
bool NeedsSupportForExternalStencil() override;
private: private:
gl::GLSurface* const gl_surface_; gl::GLSurface* const gl_surface_;
......
...@@ -338,6 +338,8 @@ viz_source_set("gpu_service_dependencies") { ...@@ -338,6 +338,8 @@ viz_source_set("gpu_service_dependencies") {
"display_embedder/skia_output_device_gl.h", "display_embedder/skia_output_device_gl.h",
"display_embedder/skia_output_device_offscreen.cc", "display_embedder/skia_output_device_offscreen.cc",
"display_embedder/skia_output_device_offscreen.h", "display_embedder/skia_output_device_offscreen.h",
"display_embedder/skia_output_device_webview.cc",
"display_embedder/skia_output_device_webview.h",
"display_embedder/skia_output_surface_dependency.h", "display_embedder/skia_output_surface_dependency.h",
"display_embedder/skia_output_surface_dependency_impl.cc", "display_embedder/skia_output_surface_dependency_impl.cc",
"display_embedder/skia_output_surface_dependency_impl.h", "display_embedder/skia_output_surface_dependency_impl.h",
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/viz/service/display_embedder/skia_output_device_webview.h"
#include <utility>
#include "gpu/command_buffer/common/swap_buffers_complete_params.h"
#include "gpu/command_buffer/service/gl_utils.h"
#include "gpu/command_buffer/service/shared_context_state.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "third_party/skia/include/gpu/GrContext.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_surface.h"
namespace viz {
SkiaOutputDeviceWebView::SkiaOutputDeviceWebView(
gpu::SharedContextState* context_state,
scoped_refptr<gl::GLSurface> gl_surface,
gpu::MemoryTracker* memory_tracker,
DidSwapBufferCompleteCallback did_swap_buffer_complete_callback)
: SkiaOutputDevice(/*need_swap_semaphore=*/false,
memory_tracker,
std::move(did_swap_buffer_complete_callback)),
context_state_(context_state),
gl_surface_(std::move(gl_surface)) {
capabilities_.flipped_output_surface = gl_surface_->FlipsVertically();
capabilities_.max_frames_pending = gl_surface_->GetBufferCount() - 1;
DCHECK(context_state_->gr_context());
DCHECK(context_state_->context());
// Get alpha bits from the default frame buffer.
glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
context_state_->gr_context()->resetContext(kRenderTarget_GrGLBackendState);
GLint alpha_bits = 0;
glGetIntegerv(GL_ALPHA_BITS, &alpha_bits);
CHECK_GL_ERROR();
supports_alpha_ = alpha_bits > 0;
}
SkiaOutputDeviceWebView::~SkiaOutputDeviceWebView() = default;
bool SkiaOutputDeviceWebView::Reshape(const gfx::Size& size,
float device_scale_factor,
const gfx::ColorSpace& color_space,
bool has_alpha,
gfx::OverlayTransform transform) {
DCHECK_EQ(transform, gfx::OVERLAY_TRANSFORM_NONE);
if (!gl_surface_->Resize(size, device_scale_factor, color_space, has_alpha)) {
DLOG(ERROR) << "Failed to resize.";
return false;
}
size_ = size;
color_space_ = color_space;
InitSkiaSurface(gl_surface_->GetBackingFramebufferObject());
return !!sk_surface_;
}
void SkiaOutputDeviceWebView::SwapBuffers(
BufferPresentedCallback feedback,
std::vector<ui::LatencyInfo> latency_info) {
StartSwapBuffers({});
gfx::Size surface_size =
gfx::Size(sk_surface_->width(), sk_surface_->height());
FinishSwapBuffers(gl_surface_->SwapBuffers(std::move(feedback)), surface_size,
std::move(latency_info));
}
SkSurface* SkiaOutputDeviceWebView::BeginPaint() {
DCHECK(sk_surface_);
unsigned int fbo = gl_surface_->GetBackingFramebufferObject();
if (last_frame_buffer_object_ != fbo) {
InitSkiaSurface(fbo);
}
return sk_surface_.get();
}
void SkiaOutputDeviceWebView::EndPaint(const GrBackendSemaphore& semaphore) {}
void SkiaOutputDeviceWebView::InitSkiaSurface(unsigned int fbo) {
last_frame_buffer_object_ = fbo;
SkSurfaceProps surface_props =
SkSurfaceProps(0, SkSurfaceProps::kLegacyFontHost_InitType);
GrGLFramebufferInfo framebuffer_info;
framebuffer_info.fFBOID = fbo;
SkColorType color_type;
if (supports_alpha_) {
framebuffer_info.fFormat = GL_RGBA8;
color_type = kRGBA_8888_SkColorType;
} else {
framebuffer_info.fFormat = GL_RGB8_OES;
color_type = kRGB_888x_SkColorType;
}
GrBackendRenderTarget render_target(size_.width(), size_.height(), 0, 8,
framebuffer_info);
auto origin = gl_surface_->FlipsVertically() ? kTopLeft_GrSurfaceOrigin
: kBottomLeft_GrSurfaceOrigin;
sk_surface_ = SkSurface::MakeFromBackendRenderTarget(
context_state_->gr_context(), render_target, origin, color_type,
color_space_.ToSkColorSpace(), &surface_props);
if (!sk_surface_) {
LOG(ERROR) << "Couldn't create surface: "
<< context_state_->gr_context()->abandoned() << " " << color_type
<< " " << framebuffer_info.fFBOID << " "
<< framebuffer_info.fFormat << " " << color_space_.ToString()
<< " " << size_.ToString();
}
}
} // namespace viz
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_DEVICE_WEBVIEW_H_
#define COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_DEVICE_WEBVIEW_H_
#include <memory>
#include <vector>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "components/viz/service/display_embedder/skia_output_device.h"
namespace gl {
class GLSurface;
} // namespace gl
namespace gpu {
class SharedContextState;
} // namespace gpu
namespace viz {
class SkiaOutputDeviceWebView : public SkiaOutputDevice {
public:
SkiaOutputDeviceWebView(
gpu::SharedContextState* context_state,
scoped_refptr<gl::GLSurface> gl_surface,
gpu::MemoryTracker* memory_tracker,
DidSwapBufferCompleteCallback did_swap_buffer_complete_callback);
SkiaOutputDeviceWebView(const SkiaOutputDeviceWebView&) = delete;
SkiaOutputDeviceWebView& operator=(const SkiaOutputDeviceWebView&) = delete;
~SkiaOutputDeviceWebView() override;
bool supports_alpha() const { return supports_alpha_; }
// SkiaOutputDevice implementation:
bool Reshape(const gfx::Size& size,
float device_scale_factor,
const gfx::ColorSpace& color_space,
bool has_alpha,
gfx::OverlayTransform transform) override;
void SwapBuffers(BufferPresentedCallback feedback,
std::vector<ui::LatencyInfo> latency_info) override;
SkSurface* BeginPaint() override;
void EndPaint(const GrBackendSemaphore& semaphore) override;
private:
void InitSkiaSurface(unsigned int fbo);
gpu::SharedContextState* const context_state_;
scoped_refptr<gl::GLSurface> gl_surface_;
sk_sp<SkSurface> sk_surface_;
gfx::Size size_;
gfx::ColorSpace color_space_;
unsigned int last_frame_buffer_object_ = -1;
bool supports_alpha_ = false;
base::WeakPtrFactory<SkiaOutputDeviceWebView> weak_ptr_factory_{this};
};
} // namespace viz
#endif // COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_DEVICE_WEBVIEW_H_
...@@ -112,6 +112,7 @@ class VIZ_SERVICE_EXPORT SkiaOutputSurfaceDependency { ...@@ -112,6 +112,7 @@ class VIZ_SERVICE_EXPORT SkiaOutputSurfaceDependency {
const GURL& active_url) = 0; const GURL& active_url) = 0;
virtual base::TimeDelta GetGpuBlockedTimeSinceLastSwap() = 0; virtual base::TimeDelta GetGpuBlockedTimeSinceLastSwap() = 0;
virtual bool NeedsSupportForExternalStencil() = 0;
}; };
} // namespace viz } // namespace viz
......
...@@ -171,4 +171,8 @@ SkiaOutputSurfaceDependencyImpl::GetGpuBlockedTimeSinceLastSwap() { ...@@ -171,4 +171,8 @@ SkiaOutputSurfaceDependencyImpl::GetGpuBlockedTimeSinceLastSwap() {
return gpu_service_impl_->GetGpuScheduler()->TakeTotalBlockingTime(); return gpu_service_impl_->GetGpuScheduler()->TakeTotalBlockingTime();
} }
bool SkiaOutputSurfaceDependencyImpl::NeedsSupportForExternalStencil() {
return false;
}
} // namespace viz } // namespace viz
...@@ -61,6 +61,7 @@ class VIZ_SERVICE_EXPORT SkiaOutputSurfaceDependencyImpl ...@@ -61,6 +61,7 @@ class VIZ_SERVICE_EXPORT SkiaOutputSurfaceDependencyImpl
const GURL& active_url) override; const GURL& active_url) override;
base::TimeDelta GetGpuBlockedTimeSinceLastSwap() override; base::TimeDelta GetGpuBlockedTimeSinceLastSwap() override;
bool NeedsSupportForExternalStencil() override;
private: private:
GpuServiceImpl* const gpu_service_impl_; GpuServiceImpl* const gpu_service_impl_;
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include "components/viz/service/display_embedder/skia_output_device_buffer_queue.h" #include "components/viz/service/display_embedder/skia_output_device_buffer_queue.h"
#include "components/viz/service/display_embedder/skia_output_device_gl.h" #include "components/viz/service/display_embedder/skia_output_device_gl.h"
#include "components/viz/service/display_embedder/skia_output_device_offscreen.h" #include "components/viz/service/display_embedder/skia_output_device_offscreen.h"
#include "components/viz/service/display_embedder/skia_output_device_webview.h"
#include "components/viz/service/display_embedder/skia_output_surface_dependency.h" #include "components/viz/service/display_embedder/skia_output_surface_dependency.h"
#include "gpu/command_buffer/common/shared_image_usage.h" #include "gpu/command_buffer/common/shared_image_usage.h"
#include "gpu/command_buffer/common/swap_buffers_complete_params.h" #include "gpu/command_buffer/common/swap_buffers_complete_params.h"
...@@ -1503,13 +1504,22 @@ bool SkiaOutputSurfaceImplOnGpu::InitializeForGL() { ...@@ -1503,13 +1504,22 @@ bool SkiaOutputSurfaceImplOnGpu::InitializeForGL() {
output_device_ = std::move(onscreen_device); output_device_ = std::move(onscreen_device);
} else { } else {
std::unique_ptr<SkiaOutputDeviceGL> onscreen_device = if (dependency_->NeedsSupportForExternalStencil()) {
std::make_unique<SkiaOutputDeviceGL>( std::unique_ptr<SkiaOutputDeviceWebView> onscreen_device =
dependency_->GetMailboxManager(), context_state_.get(), std::make_unique<SkiaOutputDeviceWebView>(
gl_surface_, feature_info_, memory_tracker_.get(), context_state_.get(), gl_surface_, memory_tracker_.get(),
did_swap_buffer_complete_callback_); did_swap_buffer_complete_callback_);
supports_alpha_ = onscreen_device->supports_alpha(); supports_alpha_ = onscreen_device->supports_alpha();
output_device_ = std::move(onscreen_device); output_device_ = std::move(onscreen_device);
} else {
std::unique_ptr<SkiaOutputDeviceGL> onscreen_device =
std::make_unique<SkiaOutputDeviceGL>(
dependency_->GetMailboxManager(), context_state_.get(),
gl_surface_, feature_info_, memory_tracker_.get(),
did_swap_buffer_complete_callback_);
supports_alpha_ = onscreen_device->supports_alpha();
output_device_ = std::move(onscreen_device);
}
} }
} else { } else {
gl_surface_ = nullptr; gl_surface_ = nullptr;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment