Add support for shared texture and external BeginFrame in OSR mode (issue #1006)

- Add CefWindowInfo::shared_texture_enabled and
  CefRenderHandler::OnAcceleratedPaint for shared texture support. Currently
  only supported on Windows (D3D11).
- Add CefWindowInfo::external_begin_frame_enabled and
  CefBrowserHost::SendExternalBeginFrame for external begin frame support.
This commit is contained in:
Greg Wessels 2018-07-02 19:46:03 -05:00 committed by Marshall Greenblatt
parent 09afa3a843
commit 713eebcafc
43 changed files with 2339 additions and 156 deletions

View File

@ -33,7 +33,7 @@
// by hand. See the translator.README.txt file in the tools directory for
// more information.
//
// $hash=ff3ebc51ed5743aabac0be94caf2edeedbd413b7$
// $hash=caba7ed3d6e19f7a4499fb48f627c2f5b40e46bc$
//
#ifndef CEF_INCLUDE_CAPI_CEF_BROWSER_CAPI_H_
@ -571,6 +571,13 @@ typedef struct _cef_browser_host_t {
void(CEF_CALLBACK* invalidate)(struct _cef_browser_host_t* self,
cef_paint_element_type_t type);
///
// Issue a BeginFrame request to Chromium. Only valid when
// cef_window_tInfo::external_begin_frame_enabled is set to true (1).
///
void(CEF_CALLBACK* send_external_begin_frame)(
struct _cef_browser_host_t* self);
///
// Send a key event to the browser.
///

View File

@ -33,7 +33,7 @@
// by hand. See the translator.README.txt file in the tools directory for
// more information.
//
// $hash=d259309846e69d866a834aa701bbf8c9562dd117$
// $hash=ef8abd4a01fe1047abc0d2ab1c359704611a60ac$
//
#ifndef CEF_INCLUDE_CAPI_CEF_RENDER_HANDLER_CAPI_H_
@ -142,6 +142,18 @@ typedef struct _cef_render_handler_t {
int width,
int height);
///
// Called when an view has been rendered to the given shared texture handle.
// Currently, the shared handle represents a D3D11 Texture2D that can be
// accessed with the OpenSharedResource function available from a ID3D11Device
///
void(CEF_CALLBACK* on_accelerated_paint)(struct _cef_render_handler_t* self,
struct _cef_browser_t* browser,
cef_paint_element_type_t type,
size_t dirtyRectsCount,
cef_rect_t const* dirtyRects,
void* shared_handle);
///
// Called when the browser's cursor has changed. If |type| is CT_CUSTOM then
// |custom_cursor_info| will be populated with the custom cursor information.

View File

@ -595,6 +595,13 @@ class CefBrowserHost : public virtual CefBaseRefCounted {
/*--cef()--*/
virtual void Invalidate(PaintElementType type) = 0;
///
// Issue a BeginFrame request to Chromium. Only valid when
// CefWindowInfo::external_begin_frame_enabled is set to true.
///
/*--cef()--*/
virtual void SendExternalBeginFrame() = 0;
///
// Send a key event to the browser.
///

View File

@ -135,7 +135,8 @@ class CefRenderHandler : public virtual CefBaseRefCounted {
// contains the pixel data for the whole image. |dirtyRects| contains the set
// of rectangles in pixel coordinates that need to be repainted. |buffer| will
// be |width|*|height|*4 bytes in size and represents a BGRA image with an
// upper-left origin.
// upper-left origin. This method is only called when
// CefWindowInfo::shared_texture_enabled is set to false.
///
/*--cef()--*/
virtual void OnPaint(CefRefPtr<CefBrowser> browser,
@ -145,6 +146,21 @@ class CefRenderHandler : public virtual CefBaseRefCounted {
int width,
int height) = 0;
///
// Called when an element has been rendered to the shared texture handle.
// |type| indicates whether the element is the view or the popup widget.
// |dirtyRects| contains the set of rectangles in pixel coordinates that need
// to be repainted. |shared_handle| is the handle for a D3D11 Texture2D that
// can be accessed via ID3D11Device using the OpenSharedResource method. This
// method is only called when CefWindowInfo::shared_texture_enabled is set to
// true, and is currently only supported on Windows.
///
/*--cef()--*/
virtual void OnAcceleratedPaint(CefRefPtr<CefBrowser> browser,
PaintElementType type,
const RectList& dirtyRects,
void* shared_handle) {}
///
// Called when the browser's cursor has changed. If |type| is CT_CUSTOM then
// |custom_cursor_info| will be populated with the custom cursor information.

View File

@ -82,6 +82,8 @@ struct CefWindowInfoTraits {
target->height = src->height;
target->parent_window = src->parent_window;
target->windowless_rendering_enabled = src->windowless_rendering_enabled;
target->shared_texture_enabled = src->shared_texture_enabled;
target->external_begin_frame_enabled = src->external_begin_frame_enabled;
target->window = src->window;
}
};

View File

@ -88,6 +88,8 @@ struct CefWindowInfoTraits {
target->hidden = src->hidden;
target->parent_view = src->parent_view;
target->windowless_rendering_enabled = src->windowless_rendering_enabled;
target->shared_texture_enabled = src->shared_texture_enabled;
target->external_begin_frame_enabled = src->external_begin_frame_enabled;
target->view = src->view;
}
};

View File

@ -96,6 +96,19 @@ typedef struct _cef_window_info_t {
///
int windowless_rendering_enabled;
///
// Set to true (1) to enable shared textures for windowless rendering. Only
// valid if windowless_rendering_enabled above is also set to true. Currently
// only supported on Windows (D3D11).
///
int shared_texture_enabled;
///
// Set to true (1) to enable the ability to issue BeginFrame requests from the
// client application by calling CefBrowserHost::SendExternalBeginFrame.
///
int external_begin_frame_enabled;
///
// Pointer for the new browser window. Only used with windowed rendering.
///

View File

@ -106,6 +106,19 @@ typedef struct _cef_window_info_t {
///
int windowless_rendering_enabled;
///
// Set to true (1) to enable shared textures for windowless rendering. Only
// valid if windowless_rendering_enabled above is also set to true. Currently
// only supported on Windows (D3D11).
///
int shared_texture_enabled;
///
// Set to true (1) to enable the ability to issue BeginFrame from the client
// application.
///
int external_begin_frame_enabled;
///
// NSView pointer for the new browser view. Only used with windowed rendering.
///

View File

@ -84,6 +84,19 @@ typedef struct _cef_window_info_t {
///
int windowless_rendering_enabled;
///
// Set to true (1) to enable shared textures for windowless rendering. Only
// valid if windowless_rendering_enabled above is also set to true. Currently
// only supported on Windows (D3D11).
///
int shared_texture_enabled;
///
// Set to true (1) to enable the ability to issue BeginFrame requests from the
// client application by calling CefBrowserHost::SendExternalBeginFrame.
///
int external_begin_frame_enabled;
///
// Handle for the new browser window. Only used with windowed rendering.
///

View File

@ -88,6 +88,8 @@ struct CefWindowInfoTraits {
target->parent_window = src->parent_window;
target->menu = src->menu;
target->windowless_rendering_enabled = src->windowless_rendering_enabled;
target->shared_texture_enabled = src->shared_texture_enabled;
target->external_begin_frame_enabled = src->external_begin_frame_enabled;
target->window = src->window;
}
};

View File

@ -1156,6 +1156,24 @@ void CefBrowserHostImpl::Invalidate(PaintElementType type) {
platform_delegate_->Invalidate(type);
}
void CefBrowserHostImpl::SendExternalBeginFrame() {
if (!IsWindowless()) {
NOTREACHED() << "Window rendering is not disabled";
return;
}
if (!CEF_CURRENTLY_ON_UIT()) {
CEF_POST_TASK(
CEF_UIT, base::Bind(&CefBrowserHostImpl::SendExternalBeginFrame, this));
return;
}
if (!web_contents() || !platform_delegate_)
return;
platform_delegate_->SendExternalBeginFrame();
}
void CefBrowserHostImpl::SendKeyEvent(const CefKeyEvent& event) {
if (!CEF_CURRENTLY_ON_UIT()) {
CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefBrowserHostImpl::SendKeyEvent,

View File

@ -212,6 +212,7 @@ class CefBrowserHostImpl : public CefBrowserHost,
void WasHidden(bool hidden) override;
void NotifyScreenInfoChanged() override;
void Invalidate(PaintElementType type) override;
void SendExternalBeginFrame() override;
void SendKeyEvent(const CefKeyEvent& event) override;
void SendMouseClickEvent(const CefMouseEvent& event,
MouseButtonType type,

View File

@ -121,6 +121,10 @@ void CefBrowserPlatformDelegate::Invalidate(cef_paint_element_type_t type) {
NOTREACHED();
}
void CefBrowserPlatformDelegate::SendExternalBeginFrame() {
NOTREACHED();
}
void CefBrowserPlatformDelegate::SetWindowlessFrameRate(int frame_rate) {
NOTREACHED();
}

View File

@ -139,6 +139,9 @@ class CefBrowserPlatformDelegate {
// enable transparency.
virtual SkColor GetBackgroundColor() const = 0;
virtual bool CanUseSharedTexture() const = 0;
virtual bool CanUseExternalBeginFrame() const = 0;
// Notify the window that it was resized.
virtual void SynchronizeVisualProperties() = 0;
@ -227,6 +230,8 @@ class CefBrowserPlatformDelegate {
// Invalidate the view. Only used with windowless rendering.
virtual void Invalidate(cef_paint_element_type_t type);
virtual void SendExternalBeginFrame();
// Set the windowless frame rate. Only used with windowless rendering.
virtual void SetWindowlessFrameRate(int frame_rate);

View File

@ -34,10 +34,13 @@ namespace {
std::unique_ptr<CefBrowserPlatformDelegateNative> CreateNativeDelegate(
const CefWindowInfo& window_info,
SkColor background_color) {
SkColor background_color,
bool use_shared_texture,
bool use_external_begin_frame) {
#if defined(OS_WIN)
return std::make_unique<CefBrowserPlatformDelegateNativeWin>(
window_info, background_color);
window_info, background_color, use_shared_texture,
use_external_begin_frame);
#elif defined(OS_MACOSX)
return std::make_unique<CefBrowserPlatformDelegateNativeMac>(
window_info, background_color);
@ -73,10 +76,22 @@ std::unique_ptr<CefBrowserPlatformDelegate> CefBrowserPlatformDelegate::Create(
const SkColor background_color = CefContext::Get()->GetBackgroundColor(
&create_params.settings, is_windowless ? STATE_ENABLED : STATE_DISABLED);
bool use_shared_texture = false;
bool use_external_begin_frame = false;
if (is_windowless) {
use_shared_texture = create_params.window_info &&
create_params.window_info->shared_texture_enabled;
use_external_begin_frame =
create_params.window_info &&
create_params.window_info->external_begin_frame_enabled;
}
if (create_params.window_info) {
std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate =
CreateNativeDelegate(*create_params.window_info.get(),
background_color);
CreateNativeDelegate(*create_params.window_info.get(), background_color,
use_shared_texture, use_external_begin_frame);
if (is_windowless)
return CreateOSRDelegate(std::move(native_delegate));
return std::move(native_delegate);
@ -84,7 +99,8 @@ std::unique_ptr<CefBrowserPlatformDelegate> CefBrowserPlatformDelegate::Create(
extensions::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) {
// Creating a background extension host without a window.
std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate =
CreateNativeDelegate(CefWindowInfo(), background_color);
CreateNativeDelegate(CefWindowInfo(), background_color,
use_shared_texture, use_external_begin_frame);
return std::make_unique<CefBrowserPlatformDelegateBackground>(
std::move(native_delegate));
}
@ -92,7 +108,8 @@ std::unique_ptr<CefBrowserPlatformDelegate> CefBrowserPlatformDelegate::Create(
else {
// CefWindowInfo is not used in this case.
std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate =
CreateNativeDelegate(CefWindowInfo(), background_color);
CreateNativeDelegate(CefWindowInfo(), background_color,
use_shared_texture, use_external_begin_frame);
return std::make_unique<CefBrowserPlatformDelegateViews>(
std::move(native_delegate),
static_cast<CefBrowserViewImpl*>(create_params.browser_view.get()));

View File

@ -35,6 +35,14 @@ CefWindowHandle CefBrowserPlatformDelegateBackground::GetHostWindowHandle()
return kNullWindowHandle;
}
bool CefBrowserPlatformDelegateBackground::CanUseSharedTexture() const {
return native_delegate_->CanUseSharedTexture();
}
bool CefBrowserPlatformDelegateBackground::CanUseExternalBeginFrame() const {
return native_delegate_->CanUseExternalBeginFrame();
}
SkColor CefBrowserPlatformDelegateBackground::GetBackgroundColor() const {
return native_delegate_->GetBackgroundColor();
}

View File

@ -22,6 +22,8 @@ class CefBrowserPlatformDelegateBackground
void CloseHostWindow() override;
CefWindowHandle GetHostWindowHandle() const override;
SkColor GetBackgroundColor() const override;
bool CanUseSharedTexture() const override;
bool CanUseExternalBeginFrame() const override;
void SynchronizeVisualProperties() override;
void SendKeyEvent(const content::NativeWebKeyboardEvent& event) override;
void SendMouseEvent(const blink::WebMouseEvent& event) override;

View File

@ -42,8 +42,8 @@ void CefMimeHandlerViewGuestDelegate::OverrideWebContentsCreateParams(
CefRefPtr<CefBrowserHostImpl> owner_browser = GetOwnerBrowser(guest_);
if (owner_browser->IsWindowless()) {
CefWebContentsViewOSR* view_osr =
new CefWebContentsViewOSR(owner_browser->GetBackgroundColor());
CefWebContentsViewOSR* view_osr = new CefWebContentsViewOSR(
owner_browser->GetBackgroundColor(), false, false);
params->view = view_osr;
params->delegate_view = view_osr;
}

View File

@ -0,0 +1,341 @@
// Copyright 2018 The Chromium Embedded Framework 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 "cef/libcef/browser/gpu/external_texture_manager.h"
#include "gpu/command_buffer/service/service_utils.h"
#include "third_party/khronos/EGL/egl.h"
#include "third_party/khronos/EGL/eglext.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_context_egl.h"
#include "ui/gl/gl_image.h"
#include "ui/gl/gl_surface_egl.h"
#include "ui/gl/init/gl_factory.h"
#if defined(OS_WIN)
#include <d3d11_1.h>
#include "ui/gl/gl_angle_util_win.h"
#include "ui/gl/gl_image_dxgi.h"
#endif
#ifndef EGL_ANGLE_d3d_texture_client_buffer
#define EGL_ANGLE_d3d_texture_client_buffer 1
#define EGL_D3D_TEXTURE_ANGLE 0x33A3
#endif
namespace gpu {
namespace gles2 {
namespace {
#if defined(OS_WIN)
class GLImageDXGISharedHandle : public gl::GLImageDXGIBase {
public:
GLImageDXGISharedHandle(const gfx::Size& size)
: GLImageDXGIBase(size),
handle_((HANDLE)0),
surface_(EGL_NO_SURFACE),
texture_id_(0) {}
void* share_handle() const { return handle_; }
bool Initialize() {
Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device =
gl::QueryD3D11DeviceObjectFromANGLE();
if (!d3d11_device) {
return false;
}
Microsoft::WRL::ComPtr<ID3D11Device1> d3d11_device1;
HRESULT hr = d3d11_device.As(&d3d11_device1);
if (FAILED(hr)) {
return false;
}
D3D11_TEXTURE2D_DESC td = {0};
td.ArraySize = 1;
td.CPUAccessFlags = 0;
td.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
td.Width = GetSize().width();
td.Height = GetSize().height();
td.MipLevels = 1;
td.SampleDesc.Count = 1;
td.SampleDesc.Quality = 0;
td.Usage = D3D11_USAGE_DEFAULT;
td.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
td.MiscFlags = 0;
hr = d3d11_device1->CreateTexture2D(&td, nullptr, texture_.GetAddressOf());
if (FAILED(hr)) {
return false;
}
// Create a staging texture that will not be a render-target, but will be
// shared. We could make the render target directly shareable, but the
// staged copy is safer for synchronization and less problematic
td.BindFlags = D3D11_BIND_SHADER_RESOURCE;
td.MiscFlags = D3D11_RESOURCE_MISC_SHARED;
hr = d3d11_device1->CreateTexture2D(&td, nullptr,
staging_texture_.GetAddressOf());
if (FAILED(hr)) {
return false;
}
// If using a staging texture ... then we need the shared handle for that
Microsoft::WRL::ComPtr<IDXGIResource> dxgi_res;
if (staging_texture_.Get()) {
hr = staging_texture_.As(&dxgi_res);
} else {
hr = texture_.As(&dxgi_res);
}
if (SUCCEEDED(hr)) {
dxgi_res->GetSharedHandle(&handle_);
}
return true;
}
void Lock() {
// In the future a keyed mutex could be utilized here.
}
void Unlock() {
if (staging_texture_.Get() && texture_.Get()) {
Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device;
staging_texture_->GetDevice(&d3d11_device);
if (d3d11_device.Get()) {
Microsoft::WRL::ComPtr<ID3D11DeviceContext> d3d11_ctx;
d3d11_device->GetImmediateContext(&d3d11_ctx);
if (d3d11_ctx.Get()) {
d3d11_ctx->CopyResource(staging_texture_.Get(), texture_.Get());
}
}
}
}
void SetSurface(EGLSurface surface, GLuint texture_id) {
surface_ = surface;
texture_id_ = texture_id;
}
EGLSurface surface() const { return surface_; }
GLuint texture_id() const { return texture_id_; }
protected:
~GLImageDXGISharedHandle() override {}
private:
HANDLE handle_;
Microsoft::WRL::ComPtr<ID3D11Texture2D> staging_texture_;
EGLSurface surface_;
GLuint texture_id_;
};
#endif // defined(OS_WIN)
} // namespace
ExternalTextureManager::ExternalTextureManager() {}
ExternalTextureManager::~ExternalTextureManager() {}
void* ExternalTextureManager::CreateTexture(GLuint texture_id,
uint32_t width,
uint32_t height,
TextureManager* tex_man) {
void* share_handle = nullptr;
#if defined(OS_WIN)
EGLDisplay egl_display = gl::GLSurfaceEGL::GetHardwareDisplay();
if (egl_display == EGL_NO_DISPLAY) {
return nullptr;
}
EGLContext curContext = eglGetCurrentContext();
if (curContext == EGL_NO_CONTEXT) {
return nullptr;
}
gfx::Size size(width, height);
scoped_refptr<gl::GLImage> image;
void* texture = nullptr;
GLImageDXGISharedHandle* dxgi_image = new GLImageDXGISharedHandle(size);
if (!dxgi_image->Initialize()) {
return nullptr;
}
image = dxgi_image;
share_handle = dxgi_image->share_handle();
texture = dxgi_image->texture().Get();
if (!image) { // this check seems unnecessary
return nullptr;
}
EGLint numConfigs = 0;
EGLint configAttrs[] = {
EGL_RENDERABLE_TYPE,
EGL_OPENGL_ES3_BIT, // must remain in this position for ES2 fallback
EGL_SURFACE_TYPE,
EGL_PBUFFER_BIT,
EGL_BUFFER_SIZE,
32,
EGL_RED_SIZE,
8,
EGL_GREEN_SIZE,
8,
EGL_BLUE_SIZE,
8,
EGL_ALPHA_SIZE,
8,
EGL_DEPTH_SIZE,
0,
EGL_STENCIL_SIZE,
0,
EGL_SAMPLE_BUFFERS,
0,
EGL_NONE};
EGLConfig config = nullptr;
if (eglChooseConfig(egl_display, configAttrs, &config, 1, &numConfigs) !=
EGL_TRUE) {
return nullptr;
}
EGLSurface surface = EGL_NO_SURFACE;
EGLint surfAttrs[] = {EGL_WIDTH,
width,
EGL_HEIGHT,
height,
EGL_TEXTURE_TARGET,
EGL_TEXTURE_2D,
EGL_TEXTURE_FORMAT,
EGL_TEXTURE_RGBA,
EGL_NONE};
surface = eglCreatePbufferFromClientBuffer(egl_display, EGL_D3D_TEXTURE_ANGLE,
texture, config, surfAttrs);
if (surface == EGL_NO_SURFACE) {
// fallback to ES2 - it could be that we're running on older hardware
// and ES3 isn't available
// EGL_RENDERABLE_TYPE is the bit at configAttrs[0]
configAttrs[1] = EGL_OPENGL_ES2_BIT;
config = nullptr;
if (eglChooseConfig(egl_display, configAttrs, &config, 1, &numConfigs) ==
EGL_TRUE) {
surface = eglCreatePbufferFromClientBuffer(
egl_display, EGL_D3D_TEXTURE_ANGLE, texture, config, surfAttrs);
}
// still no surface? we're done
if (surface == EGL_NO_SURFACE) {
return nullptr;
}
}
dxgi_image->SetSurface(surface, texture_id);
surfaceMap_[share_handle] = image;
EGLSurface drawSurface = eglGetCurrentSurface(EGL_DRAW);
EGLSurface readSurface = eglGetCurrentSurface(EGL_READ);
eglMakeCurrent(egl_display, surface, surface, curContext);
if (eglBindTexImage(egl_display, surface, EGL_BACK_BUFFER)) {
if (tex_man) {
TextureRef* texture_ref = tex_man->GetTexture(texture_id);
tex_man->SetLevelInfo(texture_ref, GL_TEXTURE_2D, 0, GL_BGRA_EXT, width,
height, 1, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE,
gfx::Rect(size));
tex_man->SetLevelImage(texture_ref, GL_TEXTURE_2D, 0, image.get(),
Texture::BOUND);
}
}
eglMakeCurrent(egl_display, drawSurface, readSurface, curContext);
#endif // defined(OS_WIN)
return share_handle;
}
void ExternalTextureManager::LockTexture(void* handle) {
#if defined(OS_WIN)
auto const img = surfaceMap_.find(handle);
if (img != surfaceMap_.end()) {
GLImageDXGISharedHandle* dxgi_image =
reinterpret_cast<GLImageDXGISharedHandle*>(img->second.get());
dxgi_image->Lock();
}
#endif // defined(OS_WIN)
}
void ExternalTextureManager::UnlockTexture(void* handle) {
#if defined(OS_WIN)
auto const img = surfaceMap_.find(handle);
if (img != surfaceMap_.end()) {
GLImageDXGISharedHandle* dxgi_image =
reinterpret_cast<GLImageDXGISharedHandle*>(img->second.get());
dxgi_image->Unlock();
}
#endif // defined(OS_WIN)
}
void ExternalTextureManager::DeleteTexture(void* handle,
TextureManager* tex_man) {
#if defined(OS_WIN)
EGLDisplay egl_display = gl::GLSurfaceEGL::GetHardwareDisplay();
if (egl_display == EGL_NO_DISPLAY) {
return;
}
auto const img = surfaceMap_.find(handle);
if (img == surfaceMap_.end()) {
return;
}
EGLSurface surface = EGL_NO_SURFACE;
GLuint texture_id = 0;
GLImageDXGISharedHandle* dxgi_image =
reinterpret_cast<GLImageDXGISharedHandle*>(img->second.get());
surface = dxgi_image->surface();
texture_id = dxgi_image->texture_id();
if (surface != EGL_NO_SURFACE) {
EGLContext curContext = eglGetCurrentContext();
if (curContext != EGL_NO_CONTEXT) {
EGLSurface drawSurface = eglGetCurrentSurface(EGL_DRAW);
EGLSurface readSurface = eglGetCurrentSurface(EGL_READ);
eglMakeCurrent(egl_display, surface, surface, curContext);
TextureRef* texture_ref = nullptr;
if (tex_man) {
texture_ref = tex_man->GetTexture(texture_id);
}
eglReleaseTexImage(egl_display, surface, EGL_BACK_BUFFER);
if (tex_man && texture_ref) {
tex_man->SetLevelInfo(texture_ref, GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 1,
0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect());
tex_man->SetLevelImage(texture_ref, GL_TEXTURE_2D, 0, nullptr,
Texture::UNBOUND);
}
eglMakeCurrent(egl_display, drawSurface, readSurface, curContext);
eglDestroySurface(egl_display, surface);
}
}
surfaceMap_.erase(img);
#endif // defined(OS_WIN)
}
} // namespace gles2
} // namespace gpu

View File

@ -0,0 +1,46 @@
// Copyright 2018 The Chromium Embedded Framework 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 CEF_LIBCEF_BROWSER_GPU_EXTERNAL_TEXTURE_MANAGER_H_
#define CEF_LIBCEF_BROWSER_GPU_EXTERNAL_TEXTURE_MANAGER_H_
#pragma once
#include <map>
#include "gpu/command_buffer/service/texture_manager.h"
#include "gpu/gpu_export.h"
#include "ui/gl/gl_image.h"
#include "ui/gl/gl_surface_egl.h"
namespace gl {
class GLImage;
}
namespace gpu {
namespace gles2 {
class GPU_GLES2_EXPORT ExternalTextureManager {
public:
ExternalTextureManager();
~ExternalTextureManager();
void* CreateTexture(GLuint texture_id,
uint32_t width,
uint32_t height,
TextureManager* tex_man);
void LockTexture(void* handle);
void UnlockTexture(void* handle);
void DeleteTexture(void* handle, TextureManager* tex_man);
private:
typedef std::map<void*, scoped_refptr<gl::GLImage>> ExternalSurfaceMap;
ExternalSurfaceMap surfaceMap_;
};
} // namespace gles2
} // namespace gpu
#endif // CEF_LIBCEF_BROWSER_GPU_EXTERNAL_TEXTURE_MANAGER_H_

View File

@ -11,15 +11,27 @@
CefBrowserPlatformDelegateNative::CefBrowserPlatformDelegateNative(
const CefWindowInfo& window_info,
SkColor background_color)
SkColor background_color,
bool use_shared_texture,
bool use_external_begin_frame)
: window_info_(window_info),
background_color_(background_color),
use_shared_texture_(use_shared_texture),
use_external_begin_frame_(use_external_begin_frame),
windowless_handler_(nullptr) {}
SkColor CefBrowserPlatformDelegateNative::GetBackgroundColor() const {
return background_color_;
}
bool CefBrowserPlatformDelegateNative::CanUseSharedTexture() const {
return use_shared_texture_;
}
bool CefBrowserPlatformDelegateNative::CanUseExternalBeginFrame() const {
return use_external_begin_frame_;
}
void CefBrowserPlatformDelegateNative::SynchronizeVisualProperties() {
content::RenderViewHost* host = browser_->web_contents()->GetRenderViewHost();
if (host)

View File

@ -25,6 +25,8 @@ class CefBrowserPlatformDelegateNative : public CefBrowserPlatformDelegate {
};
// CefBrowserPlatformDelegate methods:
bool CanUseSharedTexture() const override;
bool CanUseExternalBeginFrame() const override;
SkColor GetBackgroundColor() const override;
void SynchronizeVisualProperties() override;
void SendKeyEvent(const content::NativeWebKeyboardEvent& event) override;
@ -41,10 +43,14 @@ class CefBrowserPlatformDelegateNative : public CefBrowserPlatformDelegate {
protected:
CefBrowserPlatformDelegateNative(const CefWindowInfo& window_info,
SkColor background_color);
SkColor background_color,
bool use_shared_texture,
bool use_external_begin_frame);
CefWindowInfo window_info_;
const SkColor background_color_;
const bool use_shared_texture_;
const bool use_external_begin_frame_;
WindowlessHandler* windowless_handler_; // Not owned by this object.
};

View File

@ -41,7 +41,10 @@ long GetSystemUptime() {
CefBrowserPlatformDelegateNativeLinux::CefBrowserPlatformDelegateNativeLinux(
const CefWindowInfo& window_info,
SkColor background_color)
: CefBrowserPlatformDelegateNative(window_info, background_color),
: CefBrowserPlatformDelegateNative(window_info,
background_color,
false,
false),
host_window_created_(false),
window_widget_(nullptr),
window_x11_(nullptr) {}

View File

@ -144,7 +144,10 @@ NSUInteger NativeModifiers(int cef_modifiers) {
CefBrowserPlatformDelegateNativeMac::CefBrowserPlatformDelegateNativeMac(
const CefWindowInfo& window_info,
SkColor background_color)
: CefBrowserPlatformDelegateNative(window_info, background_color),
: CefBrowserPlatformDelegateNative(window_info,
background_color,
false,
false),
host_window_created_(false) {}
void CefBrowserPlatformDelegateNativeMac::BrowserDestroyed(

View File

@ -125,8 +125,13 @@ float GetWindowScaleFactor(HWND hwnd) {
CefBrowserPlatformDelegateNativeWin::CefBrowserPlatformDelegateNativeWin(
const CefWindowInfo& window_info,
SkColor background_color)
: CefBrowserPlatformDelegateNative(window_info, background_color),
SkColor background_color,
bool use_shared_texture,
bool use_external_begin_frame)
: CefBrowserPlatformDelegateNative(window_info,
background_color,
use_shared_texture,
use_external_begin_frame),
host_window_created_(false),
window_widget_(nullptr) {}

View File

@ -14,7 +14,9 @@ class CefBrowserPlatformDelegateNativeWin
: public CefBrowserPlatformDelegateNative {
public:
CefBrowserPlatformDelegateNativeWin(const CefWindowInfo& window_info,
SkColor background_color);
SkColor background_color,
bool use_shared_texture,
bool use_external_begin_frame);
// CefBrowserPlatformDelegate methods:
void BrowserDestroyed(CefBrowserHostImpl* browser) override;

View File

@ -30,7 +30,8 @@ void CefBrowserPlatformDelegateOsr::CreateViewForWebContents(
DCHECK(!view_osr_);
// Use the OSR view instead of the default platform view.
view_osr_ = new CefWebContentsViewOSR(GetBackgroundColor());
view_osr_ = new CefWebContentsViewOSR(
GetBackgroundColor(), CanUseSharedTexture(), CanUseExternalBeginFrame());
*view = view_osr_;
*delegate_view = view_osr_;
}
@ -69,6 +70,14 @@ void CefBrowserPlatformDelegateOsr::BrowserDestroyed(
view_osr_ = nullptr;
}
bool CefBrowserPlatformDelegateOsr::CanUseSharedTexture() const {
return native_delegate_->CanUseSharedTexture();
}
bool CefBrowserPlatformDelegateOsr::CanUseExternalBeginFrame() const {
return native_delegate_->CanUseExternalBeginFrame();
}
SkColor CefBrowserPlatformDelegateOsr::GetBackgroundColor() const {
return native_delegate_->GetBackgroundColor();
}
@ -215,6 +224,12 @@ void CefBrowserPlatformDelegateOsr::Invalidate(cef_paint_element_type_t type) {
view->Invalidate(type);
}
void CefBrowserPlatformDelegateOsr::SendExternalBeginFrame() {
CefRenderWidgetHostViewOSR* view = GetOSRHostView();
if (view)
view->SendExternalBeginFrame();
}
void CefBrowserPlatformDelegateOsr::SetWindowlessFrameRate(int frame_rate) {
CefRenderWidgetHostViewOSR* view = GetOSRHostView();
if (view)

View File

@ -28,7 +28,10 @@ class CefBrowserPlatformDelegateOsr
void BrowserCreated(CefBrowserHostImpl* browser) override;
void BrowserDestroyed(CefBrowserHostImpl* browser) override;
SkColor GetBackgroundColor() const override;
bool CanUseSharedTexture() const override;
bool CanUseExternalBeginFrame() const override;
void SynchronizeVisualProperties() override;
void SendExternalBeginFrame() override;
void SendKeyEvent(const content::NativeWebKeyboardEvent& event) override;
void SendMouseEvent(const blink::WebMouseEvent& event) override;
void SendMouseWheelEvent(const blink::WebMouseWheelEvent& event) override;

View File

@ -45,6 +45,10 @@
namespace {
// The maximum number of damage rects to cache for outstanding frame requests
// (for OnAcceleratedPaint).
const size_t kMaxDamageRects = 10;
const float kDefaultScaleFactor = 1.0;
// The maximum number of retry counts if frame capture fails.
@ -65,6 +69,45 @@ static content::ScreenInfo ScreenInfoFrom(const CefScreenInfo& src) {
return screenInfo;
}
class CefCompositorFrameSinkClient
: public viz::mojom::CompositorFrameSinkClient {
public:
CefCompositorFrameSinkClient(viz::mojom::CompositorFrameSinkClient* forward,
CefRenderWidgetHostViewOSR* rwhv)
: forward_(forward), render_widget_host_view_(rwhv) {}
void DidReceiveCompositorFrameAck(
const std::vector<viz::ReturnedResource>& resources) override {
forward_->DidReceiveCompositorFrameAck(resources);
}
void DidPresentCompositorFrame(
uint32_t presentation_token,
const gfx::PresentationFeedback& feedback) override {
forward_->DidPresentCompositorFrame(presentation_token, feedback);
if (render_widget_host_view_) {
render_widget_host_view_->OnPresentCompositorFrame(presentation_token);
}
}
void OnBeginFrame(const viz::BeginFrameArgs& args) override {
forward_->OnBeginFrame(args);
}
void OnBeginFramePausedChanged(bool paused) override {
forward_->OnBeginFramePausedChanged(paused);
}
void ReclaimResources(
const std::vector<viz::ReturnedResource>& resources) override {
forward_->ReclaimResources(resources);
}
private:
viz::mojom::CompositorFrameSinkClient* const forward_;
CefRenderWidgetHostViewOSR* const render_widget_host_view_;
};
} // namespace
// Used for managing copy requests when GPU compositing is enabled. Based on
@ -204,6 +247,8 @@ class CefBeginFrameTimer : public viz::DelayBasedTimeSourceClient {
CefRenderWidgetHostViewOSR::CefRenderWidgetHostViewOSR(
SkColor background_color,
bool use_shared_texture,
bool use_external_begin_frame,
content::RenderWidgetHost* widget,
CefRenderWidgetHostViewOSR* parent_host_view,
bool is_guest_view_hack)
@ -257,6 +302,8 @@ CefRenderWidgetHostViewOSR::CefRenderWidgetHostViewOSR(
GetRootLayer()->SetFillsBoundsOpaquely(opaque);
GetRootLayer()->SetColor(background_color_);
external_begin_frame_enabled_ = use_external_begin_frame;
#if !defined(OS_MACOSX)
// On macOS the ui::Compositor is created/owned by the platform view.
content::ImageTransportFactory* factory =
@ -264,13 +311,22 @@ CefRenderWidgetHostViewOSR::CefRenderWidgetHostViewOSR(
ui::ContextFactoryPrivate* context_factory_private =
factory->GetContextFactoryPrivate();
// Matching the attributes from RecyclableCompositorMac.
compositor_.reset(
new ui::Compositor(context_factory_private->AllocateFrameSinkId(),
content::GetContextFactory(), context_factory_private,
base::ThreadTaskRunnerHandle::Get(),
features::IsSurfaceSynchronizationEnabled(),
false /* enable_pixel_canvas */));
compositor_.reset(new ui::Compositor(
context_factory_private->AllocateFrameSinkId(),
content::GetContextFactory(), context_factory_private,
base::ThreadTaskRunnerHandle::Get(),
features::IsSurfaceSynchronizationEnabled(),
false /* enable_pixel_canvas */, use_external_begin_frame));
compositor_->SetAcceleratedWidget(compositor_widget_);
// Tell the compositor to use shared textures if the client can handle
// OnAcceleratedPaint.
compositor_->EnableSharedTexture(use_shared_texture);
if (use_external_begin_frame) {
compositor_->SetExternalBeginFrameClient(this);
}
compositor_->SetDelegate(this);
compositor_->SetRootLayer(root_layer_.get());
#endif
@ -289,6 +345,13 @@ CefRenderWidgetHostViewOSR::~CefRenderWidgetHostViewOSR() {
if (is_showing_)
browser_compositor_->SetRenderWidgetHostIsHidden(true);
#else
if (external_begin_frame_enabled_) {
ui::Compositor* compositor = GetCompositor();
if (compositor) {
compositor->SetExternalBeginFrameClient(nullptr);
}
}
// Marking the DelegatedFrameHost as removed from the window hierarchy is
// necessary to remove all connections to its old ui::Compositor.
if (is_showing_)
@ -468,19 +531,85 @@ void CefRenderWidgetHostViewOSR::TakeFallbackContentFrom(
void CefRenderWidgetHostViewOSR::DidCreateNewRendererCompositorFrameSink(
viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) {
renderer_compositor_frame_sink_ = renderer_compositor_frame_sink;
renderer_compositor_frame_sink_.reset(
new CefCompositorFrameSinkClient(renderer_compositor_frame_sink, this));
if (GetDelegatedFrameHost()) {
GetDelegatedFrameHost()->DidCreateNewRendererCompositorFrameSink(
renderer_compositor_frame_sink_);
renderer_compositor_frame_sink_.get());
}
}
void CefRenderWidgetHostViewOSR::OnPresentCompositorFrame(
uint32_t presentation_token) {
// Is Chromium rendering to a shared texture?
void* shared_texture = nullptr;
ui::Compositor* compositor = GetCompositor();
if (compositor) {
shared_texture = compositor->GetSharedTexture();
}
if (shared_texture) {
CefRefPtr<CefRenderHandler> handler =
browser_impl_->GetClient()->GetRenderHandler();
CHECK(handler);
CefRenderHandler::RectList rcList;
{
// Find the corresponding damage rect. If there isn't one pass the entire
// view size for a full redraw.
base::AutoLock lock_scope(damage_rect_lock_);
gfx::Rect damage;
auto const i = damage_rects_.find(presentation_token);
if (i != damage_rects_.end()) {
damage = i->second;
} else {
damage = GetViewBounds();
}
rcList.push_back(
CefRect(damage.x(), damage.y(), damage.width(), damage.height()));
}
handler->OnAcceleratedPaint(browser_impl_.get(),
IsPopupWidget() ? PET_POPUP : PET_VIEW, rcList,
shared_texture);
}
}
void CefRenderWidgetHostViewOSR::AddDamageRect(uint32_t presentation_token,
const gfx::Rect& rect) {
// Associate the given damage rect with the presentation token.
// For OnAcceleratedPaint we'll lookup the corresponding damage area based on
// the frame token which is passed back to OnPresentCompositorFrame.
base::AutoLock lock_scope(damage_rect_lock_);
// We assume our presentation_token is a counter. Since we're using an ordered
// map we can enforce a max size and remove oldest from the front. Worst case,
// if a damage rect isn't associated, we can simply pass the entire view size.
while (damage_rects_.size() >= kMaxDamageRects) {
damage_rects_.erase(damage_rects_.begin());
}
damage_rects_[presentation_token] = rect;
}
void CefRenderWidgetHostViewOSR::SubmitCompositorFrame(
const viz::LocalSurfaceId& local_surface_id,
viz::CompositorFrame frame,
base::Optional<viz::HitTestRegionList> hit_test_region_list) {
TRACE_EVENT0("libcef", "CefRenderWidgetHostViewOSR::OnSwapCompositorFrame");
// Update the frame rate. At this point we should have a valid connection back
// to the Synthetic Frame Source, which is important so we can actually modify
// the frame rate to something other than the default of 60Hz.
if (sync_frame_rate_) {
if (frame_rate_threshold_us_ != 0) {
GetCompositor()->SetAuthoritativeVSyncInterval(
base::TimeDelta::FromMicroseconds(frame_rate_threshold_us_));
}
sync_frame_rate_ = false;
}
if (frame.metadata.root_scroll_offset != last_scroll_offset_) {
last_scroll_offset_ = frame.metadata.root_scroll_offset;
@ -510,31 +639,50 @@ void CefRenderWidgetHostViewOSR::SubmitCompositorFrame(
GetDelegatedFrameHost()->SubmitCompositorFrame(
local_surface_id, std::move(frame), std::move(hit_test_region_list));
} else {
if (!copy_frame_generator_.get()) {
copy_frame_generator_.reset(
new CefCopyFrameGenerator(frame_rate_threshold_us_, this));
}
ui::Compositor* compositor = GetCompositor();
if (!compositor)
return;
// Determine the damage rectangle for the current frame. This is the same
// calculation that SwapDelegatedFrame uses.
// Will be nullptr if we're not using shared textures.
const void* shared_texture = compositor->GetSharedTexture();
// Determine the damage rectangle for the current frame. This is the
// same calculation that SwapDelegatedFrame uses.
viz::RenderPass* root_pass = frame.render_pass_list.back().get();
gfx::Size frame_size = root_pass->output_rect.size();
gfx::Rect damage_rect =
gfx::ToEnclosingRect(gfx::RectF(root_pass->damage_rect));
damage_rect.Intersect(gfx::Rect(frame_size));
if (shared_texture) {
// Indicate that we want feedback every frame.
if (!++presentation_token_)
++presentation_token_;
AddDamageRect(presentation_token_, damage_rect);
frame.metadata.frame_token = presentation_token_;
frame.metadata.request_presentation_feedback = true;
}
// We would normally call BrowserCompositorMac::SubmitCompositorFrame on
// macOS, however it contains compositor resize logic that we don't want.
// Consequently we instead call the SwapDelegatedFrame method directly.
// macOS, however it contains compositor resize logic that we don't
// want. Consequently we instead call the SwapDelegatedFrame method
// directly.
GetDelegatedFrameHost()->SubmitCompositorFrame(
local_surface_id, std::move(frame), std::move(hit_test_region_list));
// Request a copy of the last compositor frame which will eventually call
// OnPaint asynchronously.
copy_frame_generator_->GenerateCopyFrame(damage_rect);
}
if (!shared_texture) {
if (!copy_frame_generator_.get()) {
copy_frame_generator_.reset(
new CefCopyFrameGenerator(frame_rate_threshold_us_, this));
}
return;
// Request a copy of the last compositor frame which will eventually
// call OnPaint asynchronously.
copy_frame_generator_->GenerateCopyFrame(damage_rect);
}
}
}
}
@ -727,7 +875,8 @@ void CefRenderWidgetHostViewOSR::GetScreenInfo(
screen_info.available_rect.width == 0 ||
screen_info.available_rect.height == 0) {
// If a screen rectangle was not provided, try using the view rectangle
// instead. Otherwise, popup views may be drawn incorrectly, or not at all.
// instead. Otherwise, popup views may be drawn incorrectly, or not at
// all.
CefRect screenRect;
handler->GetViewRect(browser_impl_.get(), screenRect);
CHECK_GT(screenRect.width, 0);
@ -879,8 +1028,11 @@ const viz::FrameSinkId& CefRenderWidgetHostViewOSR::GetFrameSinkId() const {
void CefRenderWidgetHostViewOSR::SetNeedsBeginFrames(bool enabled) {
SetFrameRate();
// Start/stop the timer that sends BeginFrame requests.
begin_frame_timer_->SetActive(enabled);
if (!external_begin_frame_enabled_) {
// Start/stop the timer that sends BeginFrame requests.
begin_frame_timer_->SetActive(enabled);
}
if (software_output_device_) {
// When the SoftwareOutputDevice is active it will call OnPaint for each
// frame. If the SoftwareOutputDevice is deactivated while an invalidation
@ -938,6 +1090,16 @@ void CefRenderWidgetHostViewOSR::DidNavigate() {
#endif
}
void CefRenderWidgetHostViewOSR::OnDisplayDidFinishFrame(
const viz::BeginFrameAck& /*ack*/) {
// TODO(cef): is there something we need to track with this notification?
}
void CefRenderWidgetHostViewOSR::OnNeedsExternalBeginFrames(
bool needs_begin_frames) {
needs_external_begin_frames_ = needs_begin_frames;
}
std::unique_ptr<viz::SoftwareOutputDevice>
CefRenderWidgetHostViewOSR::CreateSoftwareOutputDevice(
ui::Compositor* compositor) {
@ -1035,8 +1197,8 @@ void CefRenderWidgetHostViewOSR::OnScreenInfoChanged() {
#endif
// We might want to change the cursor scale factor here as well - see the
// cache for the current_cursor_, as passed by UpdateCursor from the renderer
// in the rwhv_aura (current_cursor_.SetScaleFactor)
// cache for the current_cursor_, as passed by UpdateCursor from the
// renderer in the rwhv_aura (current_cursor_.SetScaleFactor)
// Notify the guest hosts if any.
for (auto guest_host_view : guest_host_views_)
@ -1056,6 +1218,31 @@ void CefRenderWidgetHostViewOSR::Invalidate(
InvalidateInternal(gfx::Rect(GetCompositorViewportPixelSize()));
}
void CefRenderWidgetHostViewOSR::SendExternalBeginFrame() {
DCHECK(external_begin_frame_enabled_);
base::TimeTicks frame_time = base::TimeTicks::Now();
base::TimeTicks deadline = base::TimeTicks();
base::TimeDelta interval = viz::BeginFrameArgs::DefaultInterval();
viz::BeginFrameArgs begin_frame_args = viz::BeginFrameArgs::Create(
BEGINFRAME_FROM_HERE, begin_frame_source_.source_id(),
begin_frame_number_, frame_time, deadline, interval,
viz::BeginFrameArgs::NORMAL);
DCHECK(begin_frame_args.IsValid());
begin_frame_number_++;
if (renderer_compositor_frame_sink_) {
GetCompositor()->IssueExternalBeginFrame(begin_frame_args);
renderer_compositor_frame_sink_->OnBeginFrame(begin_frame_args);
}
if (!IsPopupWidget() && popup_host_view_) {
popup_host_view_->SendExternalBeginFrame();
}
}
void CefRenderWidgetHostViewOSR::SendKeyEvent(
const content::NativeWebKeyboardEvent& event) {
TRACE_EVENT0("libcef", "CefRenderWidgetHostViewOSR::SendKeyEvent");
@ -1155,8 +1342,8 @@ void CefRenderWidgetHostViewOSR::SendMouseWheelEvent(
return;
} else {
// Scrolling outside of the popup widget so destroy it.
// Execute asynchronously to avoid deleting the widget from inside some
// other callback.
// Execute asynchronously to avoid deleting the widget from inside
// some other callback.
CEF_POST_TASK(
CEF_UIT,
base::Bind(&CefRenderWidgetHostViewOSR::CancelWidget,
@ -1298,13 +1485,26 @@ void CefRenderWidgetHostViewOSR::SetFrameRate() {
if (frame_rate_threshold_us_ != 0)
return;
const int frame_rate =
osr_util::ClampFrameRate(browser->settings().windowless_frame_rate);
ui::Compositor* compositor = GetCompositor();
int frame_rate;
if (compositor && compositor->shared_texture_enabled()) {
// No upper-bound when using OnAcceleratedPaint.
frame_rate = browser->settings().windowless_frame_rate;
if (frame_rate <= 0) {
frame_rate = 1;
}
sync_frame_rate_ = true;
} else {
frame_rate =
osr_util::ClampFrameRate(browser->settings().windowless_frame_rate);
}
frame_rate_threshold_us_ = 1000000 / frame_rate;
if (GetCompositor()) {
if (compositor) {
// Configure the VSync interval for the browser process.
GetCompositor()->vsync_manager()->SetAuthoritativeVSyncInterval(
compositor->vsync_manager()->SetAuthoritativeVSyncInterval(
base::TimeDelta::FromMicroseconds(frame_rate_threshold_us_));
}
@ -1313,13 +1513,15 @@ void CefRenderWidgetHostViewOSR::SetFrameRate() {
frame_rate_threshold_us_);
}
if (begin_frame_timer_.get()) {
begin_frame_timer_->SetFrameRateThresholdUs(frame_rate_threshold_us_);
} else {
begin_frame_timer_.reset(new CefBeginFrameTimer(
frame_rate_threshold_us_,
base::Bind(&CefRenderWidgetHostViewOSR::OnBeginFrameTimerTick,
weak_ptr_factory_.GetWeakPtr())));
if (!external_begin_frame_enabled_) {
if (begin_frame_timer_.get()) {
begin_frame_timer_->SetFrameRateThresholdUs(frame_rate_threshold_us_);
} else {
begin_frame_timer_.reset(new CefBeginFrameTimer(
frame_rate_threshold_us_,
base::Bind(&CefRenderWidgetHostViewOSR::OnBeginFrameTimerTick,
weak_ptr_factory_.GetWeakPtr())));
}
}
}
@ -1459,8 +1661,8 @@ void CefRenderWidgetHostViewOSR::CancelWidget() {
if (render_widget_host_ && !is_destroyed_) {
is_destroyed_ = true;
// Don't delete the RWHI manually while owned by a scoped_ptr in RVHI. This
// matches a CHECK() in RenderWidgetHostImpl::Destroy().
// Don't delete the RWHI manually while owned by a scoped_ptr in RVHI.
// This matches a CHECK() in RenderWidgetHostImpl::Destroy().
const bool also_delete = !render_widget_host_->owner_delegate();
// Results in a call to Destroy().

View File

@ -7,6 +7,7 @@
#define CEF_LIBCEF_BROWSER_OSR_RENDER_WIDGET_HOST_VIEW_OSR_H_
#pragma once
#include <map>
#include <set>
#include <vector>
@ -21,6 +22,8 @@
#include "content/browser/renderer_host/input/mouse_wheel_phase_handler.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/external_begin_frame_client.h"
#include "ui/gfx/geometry/rect.h"
#if defined(OS_LINUX)
#include "ui/base/x/x11_util.h"
@ -90,6 +93,7 @@ class MacHelper;
#endif
class CefRenderWidgetHostViewOSR : public content::RenderWidgetHostViewBase,
public ui::ExternalBeginFrameClient,
public ui::CompositorDelegate
#if !defined(OS_MACOSX)
,
@ -98,6 +102,8 @@ class CefRenderWidgetHostViewOSR : public content::RenderWidgetHostViewBase,
{
public:
CefRenderWidgetHostViewOSR(SkColor background_color,
bool use_shared_texture,
bool use_external_begin_frame,
content::RenderWidgetHost* widget,
CefRenderWidgetHostViewOSR* parent_host_view,
bool is_guest_view_hack);
@ -198,6 +204,10 @@ class CefRenderWidgetHostViewOSR : public content::RenderWidgetHostViewBase,
const viz::LocalSurfaceId& GetLocalSurfaceId() const override;
const viz::FrameSinkId& GetFrameSinkId() const override;
// ui::ExternalBeginFrameClient implementation:
void OnDisplayDidFinishFrame(const viz::BeginFrameAck& ack) override;
void OnNeedsExternalBeginFrames(bool needs_begin_frames) override;
// ui::CompositorDelegate implementation.
std::unique_ptr<viz::SoftwareOutputDevice> CreateSoftwareOutputDevice(
ui::Compositor* compositor) override;
@ -217,6 +227,7 @@ class CefRenderWidgetHostViewOSR : public content::RenderWidgetHostViewBase,
void SynchronizeVisualProperties();
void OnScreenInfoChanged();
void Invalidate(CefBrowserHost::PaintElementType type);
void SendExternalBeginFrame();
void SendKeyEvent(const content::NativeWebKeyboardEvent& event);
void SendMouseEvent(const blink::WebMouseEvent& event);
void SendMouseWheelEvent(const blink::WebMouseWheelEvent& event);
@ -267,6 +278,8 @@ class CefRenderWidgetHostViewOSR : public content::RenderWidgetHostViewBase,
}
#endif
void OnPresentCompositorFrame(uint32_t presentation_token);
private:
content::DelegatedFrameHost* GetDelegatedFrameHost() const;
@ -299,6 +312,8 @@ class CefRenderWidgetHostViewOSR : public content::RenderWidgetHostViewBase,
viz::FrameSinkId AllocateFrameSinkId(bool is_guest_view_hack);
void AddDamageRect(uint32_t presentation_token, const gfx::Rect& rect);
// Applies background color without notifying the RenderWidget about
// opaqueness changes.
void UpdateBackgroundColorFromRenderer(SkColor color);
@ -358,6 +373,10 @@ class CefRenderWidgetHostViewOSR : public content::RenderWidgetHostViewBase,
viz::StubBeginFrameSource begin_frame_source_;
uint64_t begin_frame_number_ = viz::BeginFrameArgs::kStartingFrameNumber;
bool sync_frame_rate_ = false;
bool external_begin_frame_enabled_ = false;
bool needs_external_begin_frames_ = false;
// Used for direct rendering from the compositor when GPU compositing is
// disabled. This object is owned by the compositor.
CefSoftwareOutputDeviceOSR* software_output_device_;
@ -384,6 +403,9 @@ class CefRenderWidgetHostViewOSR : public content::RenderWidgetHostViewBase,
bool is_showing_;
bool is_destroyed_;
gfx::Rect popup_position_;
uint32_t presentation_token_ = 0;
base::Lock damage_rect_lock_;
std::map<uint32_t, gfx::Rect> damage_rects_;
// The last scroll offset of the view.
gfx::Vector2dF last_scroll_offset_;
@ -391,8 +413,8 @@ class CefRenderWidgetHostViewOSR : public content::RenderWidgetHostViewBase,
content::MouseWheelPhaseHandler mouse_wheel_phase_handler_;
viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink_ =
nullptr;
std::unique_ptr<viz::mojom::CompositorFrameSinkClient>
renderer_compositor_frame_sink_;
// Latest capture sequence number which is incremented when the caller
// requests surfaces be synchronized via

View File

@ -15,8 +15,13 @@
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/render_widget_host.h"
CefWebContentsViewOSR::CefWebContentsViewOSR(SkColor background_color)
: background_color_(background_color), web_contents_(NULL) {}
CefWebContentsViewOSR::CefWebContentsViewOSR(SkColor background_color,
bool use_shared_texture,
bool use_external_begin_frame)
: background_color_(background_color),
use_shared_texture_(use_shared_texture),
use_external_begin_frame_(use_external_begin_frame),
web_contents_(NULL) {}
CefWebContentsViewOSR::~CefWebContentsViewOSR() {}
@ -109,8 +114,9 @@ content::RenderWidgetHostViewBase* CefWebContentsViewOSR::CreateViewForWidget(
}
const bool is_guest_view_hack = !!embedder_render_widget_host;
return new CefRenderWidgetHostViewOSR(background_color_, render_widget_host,
embedder_host_view, is_guest_view_hack);
return new CefRenderWidgetHostViewOSR(
background_color_, use_shared_texture_, use_external_begin_frame_,
render_widget_host, embedder_host_view, is_guest_view_hack);
}
// Called for popup and fullscreen widgets.
@ -120,8 +126,9 @@ CefWebContentsViewOSR::CreateViewForPopupWidget(
CefRenderWidgetHostViewOSR* view = GetView();
CHECK(view);
return new CefRenderWidgetHostViewOSR(background_color_, render_widget_host,
view, false);
return new CefRenderWidgetHostViewOSR(background_color_, use_shared_texture_,
use_external_begin_frame_,
render_widget_host, view, false);
}
void CefWebContentsViewOSR::SetPageTitle(const base::string16& title) {}

View File

@ -23,7 +23,9 @@ class CefRenderWidgetHostViewOSR;
class CefWebContentsViewOSR : public content::WebContentsView,
public content::RenderViewHostDelegateView {
public:
explicit CefWebContentsViewOSR(SkColor background_color);
explicit CefWebContentsViewOSR(SkColor background_color,
bool use_shared_texture,
bool use_external_begin_frame);
~CefWebContentsViewOSR() override;
void WebContentsCreated(content::WebContents* web_contents);
@ -82,6 +84,8 @@ class CefWebContentsViewOSR : public content::WebContentsView,
CefBrowserHostImpl* GetBrowser() const;
const SkColor background_color_;
const bool use_shared_texture_;
const bool use_external_begin_frame_;
content::WebContents* web_contents_;

View File

@ -165,6 +165,14 @@ void CefBrowserPlatformDelegateViews::PopupBrowserCreated(
}
}
bool CefBrowserPlatformDelegateViews::CanUseSharedTexture() const {
return native_delegate_->CanUseSharedTexture();
}
bool CefBrowserPlatformDelegateViews::CanUseExternalBeginFrame() const {
return native_delegate_->CanUseExternalBeginFrame();
}
SkColor CefBrowserPlatformDelegateViews::GetBackgroundColor() const {
return native_delegate_->GetBackgroundColor();
}

View File

@ -41,6 +41,8 @@ class CefBrowserPlatformDelegateViews
bool is_devtools) override;
void PopupBrowserCreated(CefBrowserHostImpl* new_browser,
bool is_devtools) override;
bool CanUseSharedTexture() const override;
bool CanUseExternalBeginFrame() const override;
SkColor GetBackgroundColor() const override;
void SynchronizeVisualProperties() override;
void SendKeyEvent(const content::NativeWebKeyboardEvent& event) override;

View File

@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=099ec6c9deac65288a47cec317ab6b355e707179$
// $hash=2357c186875d3086fa4931a3ac8346d866cab1e3$
//
#include "libcef_dll/cpptoc/browser_host_cpptoc.h"
@ -615,6 +615,18 @@ void CEF_CALLBACK browser_host_invalidate(struct _cef_browser_host_t* self,
CefBrowserHostCppToC::Get(self)->Invalidate(type);
}
void CEF_CALLBACK
browser_host_send_external_begin_frame(struct _cef_browser_host_t* self) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return;
// Execute
CefBrowserHostCppToC::Get(self)->SendExternalBeginFrame();
}
void CEF_CALLBACK
browser_host_send_key_event(struct _cef_browser_host_t* self,
const struct _cef_key_event_t* event) {
@ -1111,6 +1123,8 @@ CefBrowserHostCppToC::CefBrowserHostCppToC() {
GetStruct()->notify_screen_info_changed =
browser_host_notify_screen_info_changed;
GetStruct()->invalidate = browser_host_invalidate;
GetStruct()->send_external_begin_frame =
browser_host_send_external_begin_frame;
GetStruct()->send_key_event = browser_host_send_key_event;
GetStruct()->send_mouse_click_event = browser_host_send_mouse_click_event;
GetStruct()->send_mouse_move_event = browser_host_send_mouse_move_event;

View File

@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=6cf6466ab2a1b87a1b57b5994aab64992b9f12dd$
// $hash=8df4ed4bd6e80bd90fb9563a021a59848fc40ecc$
//
#include "libcef_dll/cpptoc/render_handler_cpptoc.h"
@ -266,6 +266,45 @@ void CEF_CALLBACK render_handler_on_paint(struct _cef_render_handler_t* self,
width, height);
}
void CEF_CALLBACK
render_handler_on_accelerated_paint(struct _cef_render_handler_t* self,
cef_browser_t* browser,
cef_paint_element_type_t type,
size_t dirtyRectsCount,
cef_rect_t const* dirtyRects,
void* shared_handle) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return;
// Verify param: browser; type: refptr_diff
DCHECK(browser);
if (!browser)
return;
// Verify param: dirtyRects; type: simple_vec_byref_const
DCHECK(dirtyRectsCount == 0 || dirtyRects);
if (dirtyRectsCount > 0 && !dirtyRects)
return;
// Verify param: shared_handle; type: simple_byaddr
DCHECK(shared_handle);
if (!shared_handle)
return;
// Translate param: dirtyRects; type: simple_vec_byref_const
std::vector<CefRect> dirtyRectsList;
if (dirtyRectsCount > 0) {
for (size_t i = 0; i < dirtyRectsCount; ++i) {
CefRect dirtyRectsVal = dirtyRects[i];
dirtyRectsList.push_back(dirtyRectsVal);
}
}
// Execute
CefRenderHandlerCppToC::Get(self)->OnAcceleratedPaint(
CefBrowserCToCpp::Wrap(browser), type, dirtyRectsList, shared_handle);
}
void CEF_CALLBACK render_handler_on_cursor_change(
struct _cef_render_handler_t* self,
cef_browser_t* browser,
@ -444,6 +483,7 @@ CefRenderHandlerCppToC::CefRenderHandlerCppToC() {
GetStruct()->on_popup_show = render_handler_on_popup_show;
GetStruct()->on_popup_size = render_handler_on_popup_size;
GetStruct()->on_paint = render_handler_on_paint;
GetStruct()->on_accelerated_paint = render_handler_on_accelerated_paint;
GetStruct()->on_cursor_change = render_handler_on_cursor_change;
GetStruct()->start_dragging = render_handler_start_dragging;
GetStruct()->update_drag_cursor = render_handler_update_drag_cursor;

View File

@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=9a1691bbc0a509032dd60b463189dd1eb0f6cc4d$
// $hash=5d699bfd2e9f2d689a5bca3372563b1578fa1ba1$
//
#include "libcef_dll/ctocpp/browser_host_ctocpp.h"
@ -557,6 +557,17 @@ void CefBrowserHostCToCpp::Invalidate(PaintElementType type) {
_struct->invalidate(_struct, type);
}
NO_SANITIZE("cfi-icall") void CefBrowserHostCToCpp::SendExternalBeginFrame() {
cef_browser_host_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, send_external_begin_frame))
return;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
_struct->send_external_begin_frame(_struct);
}
NO_SANITIZE("cfi-icall")
void CefBrowserHostCToCpp::SendKeyEvent(const CefKeyEvent& event) {
cef_browser_host_t* _struct = GetStruct();

View File

@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=39ab8db08e667fac8e6dccffaa99935d8aa7d4b5$
// $hash=0a61852aa1a8c8c808e9d2258e09a0fa341056e0$
//
#ifndef CEF_LIBCEF_DLL_CTOCPP_BROWSER_HOST_CTOCPP_H_
@ -86,6 +86,7 @@ class CefBrowserHostCToCpp : public CefCToCppRefCounted<CefBrowserHostCToCpp,
void WasHidden(bool hidden) OVERRIDE;
void NotifyScreenInfoChanged() OVERRIDE;
void Invalidate(PaintElementType type) OVERRIDE;
void SendExternalBeginFrame() OVERRIDE;
void SendKeyEvent(const CefKeyEvent& event) OVERRIDE;
void SendMouseClickEvent(const CefMouseEvent& event,
MouseButtonType type,

View File

@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=db89496c825cdc7fe1eaa4b7822d8492ae3a3f23$
// $hash=3c149c932cf4ebd4b2b8c81102851ebd1d6c1d63$
//
#include "libcef_dll/ctocpp/render_handler_ctocpp.h"
@ -204,6 +204,48 @@ void CefRenderHandlerCToCpp::OnPaint(CefRefPtr<CefBrowser> browser,
delete[] dirtyRectsList;
}
NO_SANITIZE("cfi-icall")
void CefRenderHandlerCToCpp::OnAcceleratedPaint(CefRefPtr<CefBrowser> browser,
PaintElementType type,
const RectList& dirtyRects,
void* shared_handle) {
cef_render_handler_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, on_accelerated_paint))
return;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Verify param: browser; type: refptr_diff
DCHECK(browser.get());
if (!browser.get())
return;
// Verify param: shared_handle; type: simple_byaddr
DCHECK(shared_handle);
if (!shared_handle)
return;
// Translate param: dirtyRects; type: simple_vec_byref_const
const size_t dirtyRectsCount = dirtyRects.size();
cef_rect_t* dirtyRectsList = NULL;
if (dirtyRectsCount > 0) {
dirtyRectsList = new cef_rect_t[dirtyRectsCount];
DCHECK(dirtyRectsList);
if (dirtyRectsList) {
for (size_t i = 0; i < dirtyRectsCount; ++i) {
dirtyRectsList[i] = dirtyRects[i];
}
}
}
// Execute
_struct->on_accelerated_paint(_struct, CefBrowserCppToC::Wrap(browser), type,
dirtyRectsCount, dirtyRectsList, shared_handle);
// Restore param:dirtyRects; type: simple_vec_byref_const
if (dirtyRectsList)
delete[] dirtyRectsList;
}
NO_SANITIZE("cfi-icall")
void CefRenderHandlerCToCpp::OnCursorChange(
CefRefPtr<CefBrowser> browser,

View File

@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=46dd8560076264a776129a02ba11e2c2f56bf209$
// $hash=2f19b04733f565830f873853695e9163086a8ee0$
//
#ifndef CEF_LIBCEF_DLL_CTOCPP_RENDER_HANDLER_CTOCPP_H_
@ -52,6 +52,10 @@ class CefRenderHandlerCToCpp
const void* buffer,
int width,
int height) override;
void OnAcceleratedPaint(CefRefPtr<CefBrowser> browser,
PaintElementType type,
const RectList& dirtyRects,
void* shared_handle) override;
void OnCursorChange(CefRefPtr<CefBrowser> browser,
CefCursorHandle cursor,
CursorType type,

View File

@ -103,11 +103,6 @@ patches = [
# https://bitbucket.org/chromiumembedded/cef/issues/1565
'name': 'web_contents_1257_1565',
},
{
# Allow creation of a custom SoftwareOutputDevice.
# https://bitbucket.org/chromiumembedded/cef/issues/1368
'name': 'compositor_1368',
},
{
# Support custom RenderWidgetHostViewOSR for BrowserPluginGuest.
# https://bitbucket.org/chromiumembedded/cef/issues/1565
@ -365,6 +360,11 @@ patches = [
# https://bugs.chromium.org/p/chromium/issues/detail?id=757974#c23
'name': 'mac_gpu',
},
{
# Support rendering to a hardware GL/D3D texture/surface provided by the client
# https://bitbucket.org/chromiumembedded/cef/issues/1006
'name': 'external_textures_1006',
},
{
# Fix crash in CookieMonsterChangeDispatcher::Subscription destructor.
# https://bugs.chromium.org/p/chromium/issues/detail?id=729800#c48

View File

@ -1,76 +0,0 @@
diff --git content/browser/compositor/gpu_process_transport_factory.cc content/browser/compositor/gpu_process_transport_factory.cc
index 642fff3b4367..45faeed249c0 100644
--- content/browser/compositor/gpu_process_transport_factory.cc
+++ content/browser/compositor/gpu_process_transport_factory.cc
@@ -493,10 +493,20 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
// surfaces as they are not following the correct mode.
DisableGpuCompositing(compositor.get());
}
+
+ std::unique_ptr<viz::SoftwareOutputDevice> output_device;
+ if (compositor->delegate()) {
+ output_device = compositor->delegate()->CreateSoftwareOutputDevice(
+ compositor.get());
+ }
+ if (!output_device) {
+ output_device = CreateSoftwareOutputDevice(compositor->widget(),
+ compositor->task_runner());
+ }
+
display_output_surface =
std::make_unique<SoftwareBrowserCompositorOutputSurface>(
- CreateSoftwareOutputDevice(compositor->widget(),
- compositor->task_runner()),
+ std::move(output_device),
std::move(vsync_callback));
} else {
DCHECK(context_provider);
diff --git ui/compositor/compositor.h ui/compositor/compositor.h
index a974ea654834..cfb3ff7f8a0c 100644
--- ui/compositor/compositor.h
+++ ui/compositor/compositor.h
@@ -25,6 +25,7 @@
#include "components/viz/common/surfaces/frame_sink_id.h"
#include "components/viz/common/surfaces/local_surface_id.h"
#include "components/viz/host/host_frame_sink_client.h"
+#include "components/viz/service/display/software_output_device.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkMatrix44.h"
#include "ui/compositor/compositor_animation_observer.h"
@@ -200,6 +201,17 @@ class COMPOSITOR_EXPORT ContextFactory {
virtual bool SyncTokensRequiredForDisplayCompositor() = 0;
};
+class COMPOSITOR_EXPORT CompositorDelegate {
+ public:
+ virtual std::unique_ptr<viz::SoftwareOutputDevice> CreateSoftwareOutputDevice(
+ ui::Compositor* compositor) {
+ return nullptr;
+ }
+
+ protected:
+ virtual ~CompositorDelegate() {}
+};
+
// Compositor object to take care of GPU painting.
// A Browser compositor object is responsible for generating the final
// displayable form of pixels comprising a single widget's contents. It draws an
@@ -240,6 +252,9 @@ class COMPOSITOR_EXPORT Compositor : public cc::LayerTreeHostClient,
// Schedules a redraw of the layer tree associated with this compositor.
void ScheduleDraw();
+ CompositorDelegate* delegate() const { return delegate_; }
+ void SetDelegate(CompositorDelegate* delegate) { delegate_ = delegate; }
+
// Sets the root of the layer tree drawn by this Compositor. The root layer
// must have no parent. The compositor's root layer is reset if the root layer
// is destroyed. NULL can be passed to reset the root layer, in which case the
@@ -463,6 +478,8 @@ class COMPOSITOR_EXPORT Compositor : public cc::LayerTreeHostClient,
ui::ContextFactory* context_factory_;
ui::ContextFactoryPrivate* context_factory_private_;
+ CompositorDelegate* delegate_ = nullptr;
+
// The root of the Layer tree drawn by this compositor.
Layer* root_layer_ = nullptr;

File diff suppressed because it is too large Load Diff