зеркало из https://github.com/electron/electron.git
fix: port OSR code to new viz compositor codepath (#17538)
* fix: make OSR work with viz compositor * fix: update OSR patch * fix: update patch again * fix: update viz_osr.patch for macOS * fix: gn check warnings * chore: no need to change SoftwareOutputDeviceWinProxy * chore: add check in case we missed something * fix: consider scale factor when compare size * fix: make GPU OSR work * fix: autofill popups with OSR * chore: use UNIX line ending for osr_video_consumer * chore: code is already in defined(OS_MACOSX) * fix: share same OSR implementation on macOS This should also fix the crash when there is navigation on macOS. * test: osr window should not crash after navigation * fix: make osr work on Mac properly * fix: software osr on windows * fix: software osr on Linux * fix: compilation error introduced with rebase * fix: split local surface id allocation into two * Update osr_host_display_client_mac.mm * chore: update copyright year * fix: update patch
This commit is contained in:
Родитель
1478bd36fd
Коммит
81bf15877f
13
BUILD.gn
13
BUILD.gn
|
@ -632,11 +632,13 @@ static_library("electron_lib") {
|
|||
|
||||
if (enable_osr) {
|
||||
sources += [
|
||||
"atom/browser/osr/osr_output_device.cc",
|
||||
"atom/browser/osr/osr_output_device.h",
|
||||
"atom/browser/osr/osr_host_display_client.cc",
|
||||
"atom/browser/osr/osr_host_display_client.h",
|
||||
"atom/browser/osr/osr_host_display_client_mac.mm",
|
||||
"atom/browser/osr/osr_render_widget_host_view.cc",
|
||||
"atom/browser/osr/osr_render_widget_host_view.h",
|
||||
"atom/browser/osr/osr_render_widget_host_view_mac.mm",
|
||||
"atom/browser/osr/osr_video_consumer.cc",
|
||||
"atom/browser/osr/osr_video_consumer.h",
|
||||
"atom/browser/osr/osr_view_proxy.cc",
|
||||
"atom/browser/osr/osr_view_proxy.h",
|
||||
"atom/browser/osr/osr_web_contents_view.cc",
|
||||
|
@ -811,6 +813,11 @@ if (is_mac) {
|
|||
"ServiceManagement.framework",
|
||||
"StoreKit.framework",
|
||||
]
|
||||
|
||||
if (enable_osr) {
|
||||
libs += [ "IOSurface.framework" ]
|
||||
}
|
||||
|
||||
ldflags = [
|
||||
"-F",
|
||||
rebase_path("external_binaries", root_build_dir),
|
||||
|
|
|
@ -91,7 +91,6 @@
|
|||
#include "ui/events/base_event_utils.h"
|
||||
|
||||
#if BUILDFLAG(ENABLE_OSR)
|
||||
#include "atom/browser/osr/osr_output_device.h"
|
||||
#include "atom/browser/osr/osr_render_widget_host_view.h"
|
||||
#include "atom/browser/osr/osr_web_contents_view.h"
|
||||
#endif
|
||||
|
|
|
@ -233,7 +233,10 @@ namespace atom {
|
|||
namespace {
|
||||
|
||||
bool IsFramelessWindow(NSView* view) {
|
||||
NativeWindow* window = [static_cast<AtomNSWindow*>([view window]) shell];
|
||||
NSWindow* nswindow = [view window];
|
||||
if (![nswindow respondsToSelector:@selector(shell)])
|
||||
return false;
|
||||
NativeWindow* window = [static_cast<AtomNSWindow*>(nswindow) shell];
|
||||
return window && !window->has_frame();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,121 @@
|
|||
// Copyright (c) 2019 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/osr/osr_host_display_client.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "components/viz/common/resources/resource_format.h"
|
||||
#include "components/viz/common/resources/resource_sizes.h"
|
||||
#include "mojo/public/cpp/system/platform_handle.h"
|
||||
#include "skia/ext/platform_canvas.h"
|
||||
#include "third_party/skia/include/core/SkColor.h"
|
||||
#include "third_party/skia/include/core/SkRect.h"
|
||||
#include "third_party/skia/src/core/SkDevice.h"
|
||||
#include "ui/gfx/skia_util.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include "skia/ext/skia_utils_win.h"
|
||||
#endif
|
||||
|
||||
namespace atom {
|
||||
|
||||
LayeredWindowUpdater::LayeredWindowUpdater(
|
||||
viz::mojom::LayeredWindowUpdaterRequest request,
|
||||
OnPaintCallback callback)
|
||||
: callback_(callback), binding_(this, std::move(request)) {}
|
||||
|
||||
LayeredWindowUpdater::~LayeredWindowUpdater() = default;
|
||||
|
||||
void LayeredWindowUpdater::SetActive(bool active) {
|
||||
active_ = active;
|
||||
}
|
||||
|
||||
void LayeredWindowUpdater::OnAllocatedSharedMemory(
|
||||
const gfx::Size& pixel_size,
|
||||
mojo::ScopedSharedBufferHandle scoped_buffer_handle) {
|
||||
canvas_.reset();
|
||||
|
||||
// Make sure |pixel_size| is sane.
|
||||
size_t expected_bytes;
|
||||
bool size_result = viz::ResourceSizes::MaybeSizeInBytes(
|
||||
pixel_size, viz::ResourceFormat::RGBA_8888, &expected_bytes);
|
||||
if (!size_result)
|
||||
return;
|
||||
|
||||
#if defined(WIN32)
|
||||
base::SharedMemoryHandle shm_handle;
|
||||
size_t required_bytes;
|
||||
MojoResult unwrap_result = mojo::UnwrapSharedMemoryHandle(
|
||||
std::move(scoped_buffer_handle), &shm_handle, &required_bytes, nullptr);
|
||||
if (unwrap_result != MOJO_RESULT_OK)
|
||||
return;
|
||||
|
||||
base::SharedMemory shm(shm_handle, false);
|
||||
if (!shm.Map(required_bytes)) {
|
||||
DLOG(ERROR) << "Failed to map " << required_bytes << " bytes";
|
||||
return;
|
||||
}
|
||||
|
||||
canvas_ = skia::CreatePlatformCanvasWithSharedSection(
|
||||
pixel_size.width(), pixel_size.height(), false, shm.handle().GetHandle(),
|
||||
skia::CRASH_ON_FAILURE);
|
||||
#else
|
||||
auto shm =
|
||||
mojo::UnwrapWritableSharedMemoryRegion(std::move(scoped_buffer_handle));
|
||||
if (!shm.IsValid()) {
|
||||
DLOG(ERROR) << "Failed to unwrap shared memory region";
|
||||
return;
|
||||
}
|
||||
|
||||
shm_mapping_ = shm.Map();
|
||||
if (!shm_mapping_.IsValid()) {
|
||||
DLOG(ERROR) << "Failed to map shared memory region";
|
||||
return;
|
||||
}
|
||||
|
||||
canvas_ = skia::CreatePlatformCanvasWithPixels(
|
||||
pixel_size.width(), pixel_size.height(), false,
|
||||
static_cast<uint8_t*>(shm_mapping_.memory()), skia::CRASH_ON_FAILURE);
|
||||
#endif
|
||||
}
|
||||
|
||||
void LayeredWindowUpdater::Draw(const gfx::Rect& damage_rect,
|
||||
DrawCallback draw_callback) {
|
||||
SkPixmap pixmap;
|
||||
SkBitmap bitmap;
|
||||
|
||||
if (active_ && canvas_->peekPixels(&pixmap)) {
|
||||
bitmap.installPixels(pixmap);
|
||||
callback_.Run(damage_rect, bitmap);
|
||||
}
|
||||
|
||||
std::move(draw_callback).Run();
|
||||
}
|
||||
|
||||
OffScreenHostDisplayClient::OffScreenHostDisplayClient(
|
||||
gfx::AcceleratedWidget widget,
|
||||
OnPaintCallback callback)
|
||||
: viz::HostDisplayClient(widget), callback_(callback) {}
|
||||
OffScreenHostDisplayClient::~OffScreenHostDisplayClient() {}
|
||||
|
||||
void OffScreenHostDisplayClient::SetActive(bool active) {
|
||||
active_ = active;
|
||||
if (layered_window_updater_) {
|
||||
layered_window_updater_->SetActive(active_);
|
||||
}
|
||||
}
|
||||
|
||||
void OffScreenHostDisplayClient::IsOffscreen(IsOffscreenCallback callback) {
|
||||
std::move(callback).Run(true);
|
||||
}
|
||||
|
||||
void OffScreenHostDisplayClient::CreateLayeredWindowUpdater(
|
||||
viz::mojom::LayeredWindowUpdaterRequest request) {
|
||||
layered_window_updater_ =
|
||||
std::make_unique<LayeredWindowUpdater>(std::move(request), callback_);
|
||||
layered_window_updater_->SetActive(active_);
|
||||
}
|
||||
|
||||
} // namespace atom
|
|
@ -0,0 +1,77 @@
|
|||
// Copyright (c) 2019 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_OSR_OSR_HOST_DISPLAY_CLIENT_H_
|
||||
#define ATOM_BROWSER_OSR_OSR_HOST_DISPLAY_CLIENT_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "base/callback.h"
|
||||
#include "base/memory/shared_memory.h"
|
||||
#include "components/viz/host/host_display_client.h"
|
||||
#include "services/viz/privileged/interfaces/compositing/layered_window_updater.mojom.h"
|
||||
#include "third_party/skia/include/core/SkBitmap.h"
|
||||
#include "third_party/skia/include/core/SkCanvas.h"
|
||||
#include "ui/gfx/native_widget_types.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
typedef base::Callback<void(const gfx::Rect&, const SkBitmap&)> OnPaintCallback;
|
||||
|
||||
class LayeredWindowUpdater : public viz::mojom::LayeredWindowUpdater {
|
||||
public:
|
||||
explicit LayeredWindowUpdater(viz::mojom::LayeredWindowUpdaterRequest request,
|
||||
OnPaintCallback callback);
|
||||
~LayeredWindowUpdater() override;
|
||||
|
||||
void SetActive(bool active);
|
||||
|
||||
// viz::mojom::LayeredWindowUpdater implementation.
|
||||
void OnAllocatedSharedMemory(
|
||||
const gfx::Size& pixel_size,
|
||||
mojo::ScopedSharedBufferHandle scoped_buffer_handle) override;
|
||||
void Draw(const gfx::Rect& damage_rect, DrawCallback draw_callback) override;
|
||||
|
||||
private:
|
||||
OnPaintCallback callback_;
|
||||
mojo::Binding<viz::mojom::LayeredWindowUpdater> binding_;
|
||||
std::unique_ptr<SkCanvas> canvas_;
|
||||
bool active_ = false;
|
||||
|
||||
#if !defined(WIN32)
|
||||
base::WritableSharedMemoryMapping shm_mapping_;
|
||||
#endif
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(LayeredWindowUpdater);
|
||||
};
|
||||
|
||||
class OffScreenHostDisplayClient : public viz::HostDisplayClient {
|
||||
public:
|
||||
explicit OffScreenHostDisplayClient(gfx::AcceleratedWidget widget,
|
||||
OnPaintCallback callback);
|
||||
~OffScreenHostDisplayClient() override;
|
||||
|
||||
void SetActive(bool active);
|
||||
|
||||
private:
|
||||
void IsOffscreen(IsOffscreenCallback callback) override;
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
void OnDisplayReceivedCALayerParams(
|
||||
const gfx::CALayerParams& ca_layer_params) override;
|
||||
#endif
|
||||
|
||||
void CreateLayeredWindowUpdater(
|
||||
viz::mojom::LayeredWindowUpdaterRequest request) override;
|
||||
|
||||
std::unique_ptr<LayeredWindowUpdater> layered_window_updater_;
|
||||
OnPaintCallback callback_;
|
||||
bool active_ = false;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(OffScreenHostDisplayClient);
|
||||
};
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_OSR_OSR_HOST_DISPLAY_CLIENT_H_
|
|
@ -0,0 +1,35 @@
|
|||
// Copyright (c) 2019 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/osr/osr_host_display_client.h"
|
||||
|
||||
#include <IOSurface/IOSurface.h>
|
||||
|
||||
namespace atom {
|
||||
|
||||
void OffScreenHostDisplayClient::OnDisplayReceivedCALayerParams(
|
||||
const gfx::CALayerParams& ca_layer_params) {
|
||||
if (!ca_layer_params.is_empty) {
|
||||
base::ScopedCFTypeRef<IOSurfaceRef> io_surface(
|
||||
IOSurfaceLookupFromMachPort(ca_layer_params.io_surface_mach_port));
|
||||
|
||||
gfx::Size pixel_size_ = ca_layer_params.pixel_size;
|
||||
void* pixels = static_cast<void*>(IOSurfaceGetBaseAddress(io_surface));
|
||||
size_t stride = IOSurfaceGetBytesPerRow(io_surface);
|
||||
|
||||
struct IOSurfacePinner {
|
||||
base::ScopedCFTypeRef<IOSurfaceRef> io_surface;
|
||||
};
|
||||
|
||||
SkBitmap bitmap;
|
||||
bitmap.installPixels(
|
||||
SkImageInfo::MakeN32(pixel_size_.width(), pixel_size_.height(),
|
||||
kPremul_SkAlphaType),
|
||||
pixels, stride);
|
||||
bitmap.setImmutable();
|
||||
callback_.Run(ca_layer_params.damage, bitmap);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace atom
|
|
@ -1,101 +0,0 @@
|
|||
// Copyright (c) 2016 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/osr/osr_output_device.h"
|
||||
|
||||
#include "third_party/skia/include/core/SkColor.h"
|
||||
#include "third_party/skia/include/core/SkRect.h"
|
||||
#include "third_party/skia/src/core/SkDevice.h"
|
||||
#include "ui/gfx/skia_util.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
OffScreenOutputDevice::OffScreenOutputDevice(bool transparent,
|
||||
const OnPaintCallback& callback)
|
||||
: transparent_(transparent), callback_(callback) {
|
||||
DCHECK(!callback_.is_null());
|
||||
}
|
||||
|
||||
OffScreenOutputDevice::~OffScreenOutputDevice() {}
|
||||
|
||||
void OffScreenOutputDevice::Resize(const gfx::Size& pixel_size,
|
||||
float scale_factor) {
|
||||
if (viewport_pixel_size_ == pixel_size)
|
||||
return;
|
||||
viewport_pixel_size_ = pixel_size;
|
||||
|
||||
canvas_.reset();
|
||||
bitmap_.reset(new SkBitmap);
|
||||
bitmap_->allocN32Pixels(viewport_pixel_size_.width(),
|
||||
viewport_pixel_size_.height(), !transparent_);
|
||||
if (bitmap_->drawsNothing()) {
|
||||
NOTREACHED();
|
||||
bitmap_.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
if (transparent_) {
|
||||
bitmap_->eraseColor(SK_ColorTRANSPARENT);
|
||||
} else {
|
||||
bitmap_->eraseColor(SK_ColorWHITE);
|
||||
}
|
||||
|
||||
canvas_.reset(new SkCanvas(*bitmap_));
|
||||
}
|
||||
|
||||
SkCanvas* OffScreenOutputDevice::BeginPaint(const gfx::Rect& damage_rect) {
|
||||
DCHECK(canvas_.get());
|
||||
DCHECK(bitmap_.get());
|
||||
|
||||
damage_rect_ = damage_rect;
|
||||
SkIRect damage =
|
||||
SkIRect::MakeXYWH(damage_rect_.x(), damage_rect_.y(),
|
||||
damage_rect_.width(), damage_rect_.height());
|
||||
|
||||
if (transparent_) {
|
||||
bitmap_->erase(SK_ColorTRANSPARENT, damage);
|
||||
} else {
|
||||
bitmap_->erase(SK_ColorWHITE, damage);
|
||||
}
|
||||
|
||||
return canvas_.get();
|
||||
}
|
||||
|
||||
void OffScreenOutputDevice::EndPaint() {
|
||||
DCHECK(canvas_.get());
|
||||
DCHECK(bitmap_.get());
|
||||
|
||||
if (!bitmap_.get())
|
||||
return;
|
||||
|
||||
viz::SoftwareOutputDevice::EndPaint();
|
||||
|
||||
if (active_)
|
||||
OnPaint(damage_rect_);
|
||||
}
|
||||
|
||||
void OffScreenOutputDevice::SetActive(bool active, bool paint) {
|
||||
if (active == active_)
|
||||
return;
|
||||
active_ = active;
|
||||
|
||||
if (!active_ && !pending_damage_rect_.IsEmpty() && paint)
|
||||
OnPaint(gfx::Rect(viewport_pixel_size_));
|
||||
}
|
||||
|
||||
void OffScreenOutputDevice::OnPaint(const gfx::Rect& damage_rect) {
|
||||
gfx::Rect rect = damage_rect;
|
||||
if (!pending_damage_rect_.IsEmpty()) {
|
||||
rect.Union(pending_damage_rect_);
|
||||
pending_damage_rect_.SetRect(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
rect.Intersect(gfx::Rect(viewport_pixel_size_));
|
||||
if (rect.IsEmpty())
|
||||
return;
|
||||
|
||||
callback_.Run(rect, *bitmap_);
|
||||
}
|
||||
|
||||
} // namespace atom
|
|
@ -1,47 +0,0 @@
|
|||
// Copyright (c) 2016 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_OSR_OSR_OUTPUT_DEVICE_H_
|
||||
#define ATOM_BROWSER_OSR_OSR_OUTPUT_DEVICE_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "base/callback.h"
|
||||
#include "components/viz/service/display/software_output_device.h"
|
||||
#include "third_party/skia/include/core/SkBitmap.h"
|
||||
#include "third_party/skia/include/core/SkCanvas.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
typedef base::Callback<void(const gfx::Rect&, const SkBitmap&)> OnPaintCallback;
|
||||
|
||||
class OffScreenOutputDevice : public viz::SoftwareOutputDevice {
|
||||
public:
|
||||
OffScreenOutputDevice(bool transparent, const OnPaintCallback& callback);
|
||||
~OffScreenOutputDevice() override;
|
||||
|
||||
// viz::SoftwareOutputDevice:
|
||||
void Resize(const gfx::Size& pixel_size, float scale_factor) override;
|
||||
SkCanvas* BeginPaint(const gfx::Rect& damage_rect) override;
|
||||
void EndPaint() override;
|
||||
|
||||
void SetActive(bool active, bool paint);
|
||||
void OnPaint(const gfx::Rect& damage_rect);
|
||||
|
||||
private:
|
||||
const bool transparent_;
|
||||
OnPaintCallback callback_;
|
||||
|
||||
bool active_ = false;
|
||||
|
||||
std::unique_ptr<SkCanvas> canvas_;
|
||||
std::unique_ptr<SkBitmap> bitmap_;
|
||||
gfx::Rect pending_damage_rect_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(OffScreenOutputDevice);
|
||||
};
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_OSR_OSR_OUTPUT_DEVICE_H_
|
|
@ -20,14 +20,15 @@
|
|||
#include "components/viz/common/frame_sinks/delay_based_time_source.h"
|
||||
#include "components/viz/common/gl_helper.h"
|
||||
#include "components/viz/common/quads/render_pass.h"
|
||||
#include "content/browser/renderer_host/cursor_manager.h"
|
||||
#include "content/browser/renderer_host/render_widget_host_delegate.h"
|
||||
#include "content/browser/renderer_host/render_widget_host_impl.h"
|
||||
#include "content/browser/renderer_host/render_widget_host_owner_delegate.h"
|
||||
#include "content/browser/renderer_host/cursor_manager.h" // nogncheck
|
||||
#include "content/browser/renderer_host/input/synthetic_gesture_target.h" // nogncheck
|
||||
#include "content/browser/renderer_host/render_widget_host_delegate.h" // nogncheck
|
||||
#include "content/browser/renderer_host/render_widget_host_owner_delegate.h" // nogncheck
|
||||
#include "content/common/view_messages.h"
|
||||
#include "content/public/browser/browser_task_traits.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "content/public/browser/context_factory.h"
|
||||
#include "content/public/browser/gpu_data_manager.h"
|
||||
#include "content/public/browser/render_process_host.h"
|
||||
#include "media/base/video_frame.h"
|
||||
#include "third_party/blink/public/platform/web_input_event.h"
|
||||
|
@ -50,7 +51,6 @@ namespace atom {
|
|||
namespace {
|
||||
|
||||
const float kDefaultScaleFactor = 1.0;
|
||||
const int kFrameRetryLimit = 2;
|
||||
|
||||
ui::MouseEvent UiMouseEventFromWebMouseEvent(blink::WebMouseEvent event) {
|
||||
ui::EventType type = ui::EventType::ET_UNKNOWN;
|
||||
|
@ -120,105 +120,6 @@ ui::MouseWheelEvent UiMouseWheelEventFromWebMouseEvent(
|
|||
|
||||
} // namespace
|
||||
|
||||
class AtomCopyFrameGenerator {
|
||||
public:
|
||||
AtomCopyFrameGenerator(OffScreenRenderWidgetHostView* view,
|
||||
int frame_rate_threshold_us)
|
||||
: view_(view),
|
||||
frame_duration_(
|
||||
base::TimeDelta::FromMicroseconds(frame_rate_threshold_us)),
|
||||
weak_ptr_factory_(this) {
|
||||
last_time_ = base::Time::Now();
|
||||
}
|
||||
|
||||
void GenerateCopyFrame(const gfx::Rect& damage_rect) {
|
||||
if (!view_->render_widget_host() || !view_->IsPainting())
|
||||
return;
|
||||
|
||||
auto request = std::make_unique<viz::CopyOutputRequest>(
|
||||
viz::CopyOutputRequest::ResultFormat::RGBA_BITMAP,
|
||||
base::BindOnce(
|
||||
&AtomCopyFrameGenerator::CopyFromCompositingSurfaceHasResult,
|
||||
weak_ptr_factory_.GetWeakPtr(), damage_rect));
|
||||
|
||||
request->set_area(gfx::Rect(view_->GetCompositorViewportPixelSize()));
|
||||
view_->GetRootLayer()->RequestCopyOfOutput(std::move(request));
|
||||
}
|
||||
|
||||
void set_frame_rate_threshold_us(int frame_rate_threshold_us) {
|
||||
frame_duration_ =
|
||||
base::TimeDelta::FromMicroseconds(frame_rate_threshold_us);
|
||||
}
|
||||
|
||||
private:
|
||||
void CopyFromCompositingSurfaceHasResult(
|
||||
const gfx::Rect& damage_rect,
|
||||
std::unique_ptr<viz::CopyOutputResult> result) {
|
||||
if (result->IsEmpty() || result->size().IsEmpty() ||
|
||||
!view_->render_widget_host()) {
|
||||
OnCopyFrameCaptureFailure(damage_rect);
|
||||
return;
|
||||
}
|
||||
|
||||
DCHECK(!result->IsEmpty());
|
||||
auto source = std::make_unique<SkBitmap>(result->AsSkBitmap());
|
||||
DCHECK(source->readyToDraw());
|
||||
if (source) {
|
||||
base::AutoLock autolock(lock_);
|
||||
std::shared_ptr<SkBitmap> bitmap(source.release());
|
||||
|
||||
base::TimeTicks now = base::TimeTicks::Now();
|
||||
base::TimeDelta next_frame_in = next_frame_time_ - now;
|
||||
if (next_frame_in > frame_duration_ / 4) {
|
||||
next_frame_time_ += frame_duration_;
|
||||
base::PostDelayedTaskWithTraits(
|
||||
FROM_HERE, {content::BrowserThread::UI},
|
||||
base::BindOnce(&AtomCopyFrameGenerator::OnCopyFrameCaptureSuccess,
|
||||
weak_ptr_factory_.GetWeakPtr(), damage_rect, bitmap),
|
||||
next_frame_in);
|
||||
} else {
|
||||
next_frame_time_ = now + frame_duration_;
|
||||
OnCopyFrameCaptureSuccess(damage_rect, bitmap);
|
||||
}
|
||||
|
||||
frame_retry_count_ = 0;
|
||||
} else {
|
||||
OnCopyFrameCaptureFailure(damage_rect);
|
||||
}
|
||||
}
|
||||
|
||||
void OnCopyFrameCaptureFailure(const gfx::Rect& damage_rect) {
|
||||
const bool force_frame = (++frame_retry_count_ <= kFrameRetryLimit);
|
||||
if (force_frame) {
|
||||
// Retry with the same |damage_rect|.
|
||||
base::PostTaskWithTraits(
|
||||
FROM_HERE, {content::BrowserThread::UI},
|
||||
base::BindOnce(&AtomCopyFrameGenerator::GenerateCopyFrame,
|
||||
weak_ptr_factory_.GetWeakPtr(), damage_rect));
|
||||
}
|
||||
}
|
||||
|
||||
void OnCopyFrameCaptureSuccess(const gfx::Rect& damage_rect,
|
||||
const std::shared_ptr<SkBitmap>& bitmap) {
|
||||
base::AutoLock lock(onPaintLock_);
|
||||
view_->OnPaint(damage_rect, *bitmap);
|
||||
}
|
||||
|
||||
base::Lock lock_;
|
||||
base::Lock onPaintLock_;
|
||||
OffScreenRenderWidgetHostView* view_;
|
||||
|
||||
base::Time last_time_;
|
||||
|
||||
int frame_retry_count_ = 0;
|
||||
base::TimeTicks next_frame_time_ = base::TimeTicks::Now();
|
||||
base::TimeDelta frame_duration_;
|
||||
|
||||
base::WeakPtrFactory<AtomCopyFrameGenerator> weak_ptr_factory_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomCopyFrameGenerator);
|
||||
};
|
||||
|
||||
class AtomBeginFrameTimer : public viz::DelayBasedTimeSourceClient {
|
||||
public:
|
||||
AtomBeginFrameTimer(int frame_rate_threshold_us,
|
||||
|
@ -253,7 +154,6 @@ class AtomBeginFrameTimer : public viz::DelayBasedTimeSourceClient {
|
|||
DISALLOW_COPY_AND_ASSIGN(AtomBeginFrameTimer);
|
||||
};
|
||||
|
||||
#if !defined(OS_MACOSX)
|
||||
class AtomDelegatedFrameHostClient : public content::DelegatedFrameHostClient {
|
||||
public:
|
||||
explicit AtomDelegatedFrameHostClient(OffScreenRenderWidgetHostView* view)
|
||||
|
@ -297,7 +197,6 @@ class AtomDelegatedFrameHostClient : public content::DelegatedFrameHostClient {
|
|||
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomDelegatedFrameHostClient);
|
||||
};
|
||||
#endif // !defined(OS_MACOSX)
|
||||
|
||||
OffScreenRenderWidgetHostView::OffScreenRenderWidgetHostView(
|
||||
bool transparent,
|
||||
|
@ -315,19 +214,23 @@ OffScreenRenderWidgetHostView::OffScreenRenderWidgetHostView(
|
|||
frame_rate_(frame_rate),
|
||||
size_(initial_size),
|
||||
painting_(painting),
|
||||
is_showing_(!render_widget_host_->is_hidden()),
|
||||
is_showing_(false),
|
||||
cursor_manager_(new content::CursorManager(this)),
|
||||
mouse_wheel_phase_handler_(this),
|
||||
backing_(new SkBitmap),
|
||||
weak_ptr_factory_(this) {
|
||||
DCHECK(render_widget_host_);
|
||||
bool is_guest_view_hack = parent_host_view_ != nullptr;
|
||||
|
||||
current_device_scale_factor_ = kDefaultScaleFactor;
|
||||
|
||||
#if !defined(OS_MACOSX)
|
||||
local_surface_id_allocator_.GenerateId();
|
||||
local_surface_id_allocation_ =
|
||||
local_surface_id_allocator_.GetCurrentLocalSurfaceIdAllocation();
|
||||
delegated_frame_host_allocator_.GenerateId();
|
||||
delegated_frame_host_allocation_ =
|
||||
delegated_frame_host_allocator_.GetCurrentLocalSurfaceIdAllocation();
|
||||
compositor_allocator_.GenerateId();
|
||||
compositor_allocation_ =
|
||||
compositor_allocator_.GetCurrentLocalSurfaceIdAllocation();
|
||||
|
||||
delegated_frame_host_client_.reset(new AtomDelegatedFrameHostClient(this));
|
||||
delegated_frame_host_ = std::make_unique<content::DelegatedFrameHost>(
|
||||
AllocateFrameSinkId(is_guest_view_hack),
|
||||
|
@ -335,59 +238,49 @@ OffScreenRenderWidgetHostView::OffScreenRenderWidgetHostView(
|
|||
true /* should_register_frame_sink_id */);
|
||||
|
||||
root_layer_.reset(new ui::Layer(ui::LAYER_SOLID_COLOR));
|
||||
#endif
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
last_frame_root_background_color_ = SK_ColorTRANSPARENT;
|
||||
CreatePlatformWidget(is_guest_view_hack);
|
||||
#endif
|
||||
|
||||
bool opaque = SkColorGetA(background_color_) == SK_AlphaOPAQUE;
|
||||
GetRootLayer()->SetFillsBoundsOpaquely(opaque);
|
||||
GetRootLayer()->SetColor(background_color_);
|
||||
|
||||
#if !defined(OS_MACOSX)
|
||||
// On macOS the ui::Compositor is created/owned by the platform view.
|
||||
content::ImageTransportFactory* factory =
|
||||
content::ImageTransportFactory::GetInstance();
|
||||
|
||||
ui::ContextFactoryPrivate* context_factory_private =
|
||||
factory->GetContextFactoryPrivate();
|
||||
compositor_.reset(new ui::Compositor(
|
||||
context_factory_private->AllocateFrameSinkId(),
|
||||
content::GetContextFactory(), context_factory_private,
|
||||
base::ThreadTaskRunnerHandle::Get(), false /* enable_pixel_canvas */));
|
||||
compositor_.reset(
|
||||
new ui::Compositor(context_factory_private->AllocateFrameSinkId(),
|
||||
content::GetContextFactory(), context_factory_private,
|
||||
base::ThreadTaskRunnerHandle::Get(),
|
||||
false /* enable_pixel_canvas */, this));
|
||||
compositor_->SetAcceleratedWidget(gfx::kNullAcceleratedWidget);
|
||||
compositor_->SetRootLayer(root_layer_.get());
|
||||
#endif
|
||||
|
||||
GetCompositor()->SetDelegate(this);
|
||||
|
||||
ResizeRootLayer(false);
|
||||
render_widget_host_->SetView(this);
|
||||
InstallTransparency();
|
||||
|
||||
if (content::GpuDataManager::GetInstance()->HardwareAccelerationEnabled()) {
|
||||
video_consumer_.reset(new OffScreenVideoConsumer(
|
||||
this, base::Bind(&OffScreenRenderWidgetHostView::OnPaint,
|
||||
weak_ptr_factory_.GetWeakPtr())));
|
||||
video_consumer_->SetActive(IsPainting());
|
||||
video_consumer_->SetFrameRate(GetFrameRate());
|
||||
}
|
||||
}
|
||||
|
||||
OffScreenRenderWidgetHostView::~OffScreenRenderWidgetHostView() {
|
||||
#if defined(OS_MACOSX)
|
||||
if (is_showing_)
|
||||
browser_compositor_->SetRenderWidgetHostIsHidden(true);
|
||||
#else
|
||||
// Marking the DelegatedFrameHost as removed from the window hierarchy is
|
||||
// necessary to remove all connections to its old ui::Compositor.
|
||||
if (is_showing_)
|
||||
delegated_frame_host_->WasHidden();
|
||||
delegated_frame_host_->DetachFromCompositor();
|
||||
#endif
|
||||
|
||||
if (copy_frame_generator_.get())
|
||||
copy_frame_generator_.reset(NULL);
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
DestroyPlatformWidget();
|
||||
#else
|
||||
delegated_frame_host_.reset(NULL);
|
||||
compositor_.reset(NULL);
|
||||
root_layer_.reset(NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
content::BrowserAccessibilityManager*
|
||||
|
@ -422,8 +315,17 @@ void OffScreenRenderWidgetHostView::SendBeginFrame(
|
|||
DCHECK(begin_frame_args.IsValid());
|
||||
begin_frame_number_++;
|
||||
|
||||
if (renderer_compositor_frame_sink_)
|
||||
renderer_compositor_frame_sink_->OnBeginFrame(begin_frame_args, {});
|
||||
compositor_->context_factory_private()->IssueExternalBeginFrame(
|
||||
compositor_.get(), begin_frame_args);
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::OnDisplayDidFinishFrame(
|
||||
const viz::BeginFrameAck& ack) {}
|
||||
|
||||
void OffScreenRenderWidgetHostView::OnNeedsExternalBeginFrames(
|
||||
bool needs_begin_frames) {
|
||||
SetupFrameRate(true);
|
||||
begin_frame_timer_->SetActive(needs_begin_frames);
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::InitAsChild(gfx::NativeView) {
|
||||
|
@ -437,7 +339,7 @@ void OffScreenRenderWidgetHostView::InitAsChild(gfx::NativeView) {
|
|||
parent_host_view_->Hide();
|
||||
|
||||
ResizeRootLayer(false);
|
||||
Show();
|
||||
SetPainting(parent_host_view_->IsPainting());
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::SetSize(const gfx::Size& size) {
|
||||
|
@ -478,14 +380,10 @@ void OffScreenRenderWidgetHostView::Show() {
|
|||
|
||||
is_showing_ = true;
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
browser_compositor_->SetRenderWidgetHostIsHidden(false);
|
||||
#else
|
||||
delegated_frame_host_->AttachToCompositor(compositor_.get());
|
||||
delegated_frame_host_->WasShown(
|
||||
GetLocalSurfaceIdAllocation().local_surface_id(),
|
||||
GetRootLayer()->bounds().size(), false);
|
||||
#endif
|
||||
|
||||
if (render_widget_host_)
|
||||
render_widget_host_->WasShown(false);
|
||||
|
@ -498,12 +396,8 @@ void OffScreenRenderWidgetHostView::Hide() {
|
|||
if (render_widget_host_)
|
||||
render_widget_host_->WasHidden();
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
browser_compositor_->SetRenderWidgetHostIsHidden(true);
|
||||
#else
|
||||
GetDelegatedFrameHost()->WasHidden();
|
||||
GetDelegatedFrameHost()->DetachFromCompositor();
|
||||
#endif
|
||||
|
||||
is_showing_ = false;
|
||||
}
|
||||
|
@ -576,67 +470,17 @@ void OffScreenRenderWidgetHostView::DidCreateNewRendererCompositorFrameSink(
|
|||
viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) {
|
||||
renderer_compositor_frame_sink_ = renderer_compositor_frame_sink;
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
browser_compositor_->DidCreateNewRendererCompositorFrameSink(
|
||||
renderer_compositor_frame_sink_);
|
||||
#else
|
||||
if (GetDelegatedFrameHost()) {
|
||||
GetDelegatedFrameHost()->DidCreateNewRendererCompositorFrameSink(
|
||||
renderer_compositor_frame_sink_);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::SubmitCompositorFrame(
|
||||
const viz::LocalSurfaceId& local_surface_id,
|
||||
viz::CompositorFrame frame,
|
||||
base::Optional<viz::HitTestRegionList> hit_test_region_list) {
|
||||
#if defined(OS_MACOSX)
|
||||
last_frame_root_background_color_ = frame.metadata.root_background_color;
|
||||
#endif
|
||||
|
||||
if (frame.metadata.root_scroll_offset != last_scroll_offset_) {
|
||||
last_scroll_offset_ = frame.metadata.root_scroll_offset;
|
||||
}
|
||||
|
||||
if (!frame.render_pass_list.empty()) {
|
||||
if (software_output_device_) {
|
||||
if (!begin_frame_timer_.get() || IsPopupWidget()) {
|
||||
software_output_device_->SetActive(painting_, false);
|
||||
}
|
||||
|
||||
// The compositor will draw directly to the SoftwareOutputDevice which
|
||||
// then calls OnPaint.
|
||||
// We would normally call BrowserCompositorMac::SubmitCompositorFrame on
|
||||
// macOS, however it contains compositor resize logic that we don't want.
|
||||
// Consequently we instead call the SubmitCompositorFrame method directly.
|
||||
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 AtomCopyFrameGenerator(this, frame_rate_threshold_us_));
|
||||
}
|
||||
|
||||
// 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));
|
||||
|
||||
// We would normally call BrowserCompositorMac::SubmitCompositorFrame on
|
||||
// macOS, however it contains compositor resize logic that we don't want.
|
||||
// Consequently we instead call the SubmitCompositorFrame 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);
|
||||
}
|
||||
}
|
||||
NOTREACHED();
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::ClearCompositorFrame() {
|
||||
|
@ -651,13 +495,13 @@ void OffScreenRenderWidgetHostView::InitAsPopup(
|
|||
content::RenderWidgetHostView* parent_host_view,
|
||||
const gfx::Rect& pos) {
|
||||
DCHECK_EQ(parent_host_view_, parent_host_view);
|
||||
DCHECK_EQ(widget_type_, content::WidgetType::kPopup);
|
||||
|
||||
if (parent_host_view_->popup_host_view_) {
|
||||
parent_host_view_->popup_host_view_->CancelWidget();
|
||||
}
|
||||
|
||||
parent_host_view_->set_popup_host_view(this);
|
||||
parent_host_view_->popup_bitmap_.reset(new SkBitmap);
|
||||
parent_callback_ =
|
||||
base::Bind(&OffScreenRenderWidgetHostView::OnPopupPaint,
|
||||
parent_host_view_->weak_ptr_factory_.GetWeakPtr());
|
||||
|
@ -665,6 +509,10 @@ void OffScreenRenderWidgetHostView::InitAsPopup(
|
|||
popup_position_ = pos;
|
||||
|
||||
ResizeRootLayer(false);
|
||||
SetPainting(parent_host_view_->IsPainting());
|
||||
if (video_consumer_) {
|
||||
video_consumer_->SizeChanged();
|
||||
}
|
||||
Show();
|
||||
}
|
||||
|
||||
|
@ -698,7 +546,6 @@ void OffScreenRenderWidgetHostView::Destroy() {
|
|||
} else {
|
||||
if (popup_host_view_)
|
||||
popup_host_view_->CancelWidget();
|
||||
popup_bitmap_.reset();
|
||||
if (child_host_view_)
|
||||
child_host_view_->CancelWidget();
|
||||
if (!guest_host_views_.empty()) {
|
||||
|
@ -748,6 +595,7 @@ void OffScreenRenderWidgetHostView::InitAsGuest(
|
|||
content::RenderWidgetHostView* parent_host_view,
|
||||
content::RenderWidgetHostViewGuest* guest_view) {
|
||||
parent_host_view_->AddGuestHostView(this);
|
||||
SetPainting(parent_host_view_->IsPainting());
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::TransformPointToRootSurface(
|
||||
|
@ -763,6 +611,12 @@ viz::SurfaceId OffScreenRenderWidgetHostView::GetCurrentSurfaceId() const {
|
|||
: viz::SurfaceId();
|
||||
}
|
||||
|
||||
std::unique_ptr<content::SyntheticGestureTarget>
|
||||
OffScreenRenderWidgetHostView::CreateSyntheticGestureTarget() {
|
||||
NOTIMPLEMENTED();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::ImeCompositionRangeChanged(
|
||||
const gfx::Range&,
|
||||
const std::vector<gfx::Rect>&) {}
|
||||
|
@ -800,12 +654,8 @@ const viz::FrameSinkId& OffScreenRenderWidgetHostView::GetFrameSinkId() const {
|
|||
|
||||
void OffScreenRenderWidgetHostView::DidNavigate() {
|
||||
ResizeRootLayer(true);
|
||||
#if defined(OS_MACOSX)
|
||||
browser_compositor_->DidNavigate();
|
||||
#else
|
||||
if (delegated_frame_host_)
|
||||
delegated_frame_host_->DidNavigate();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool OffScreenRenderWidgetHostView::TransformPointToLocalCoordSpaceLegacy(
|
||||
|
@ -829,8 +679,7 @@ bool OffScreenRenderWidgetHostView::TransformPointToLocalCoordSpaceLegacy(
|
|||
bool OffScreenRenderWidgetHostView::TransformPointToCoordSpaceForView(
|
||||
const gfx::PointF& point,
|
||||
RenderWidgetHostViewBase* target_view,
|
||||
gfx::PointF* transformed_point,
|
||||
viz::EventSource source) {
|
||||
gfx::PointF* transformed_point) {
|
||||
if (target_view == this) {
|
||||
*transformed_point = point;
|
||||
return true;
|
||||
|
@ -847,7 +696,6 @@ void OffScreenRenderWidgetHostView::CancelWidget() {
|
|||
if (parent_host_view_) {
|
||||
if (parent_host_view_->popup_host_view_ == this) {
|
||||
parent_host_view_->set_popup_host_view(NULL);
|
||||
parent_host_view_->popup_bitmap_.reset();
|
||||
} else if (parent_host_view_->child_host_view_ == this) {
|
||||
parent_host_view_->set_child_host_view(NULL);
|
||||
parent_host_view_->Show();
|
||||
|
@ -890,29 +738,21 @@ void OffScreenRenderWidgetHostView::ProxyViewDestroyed(
|
|||
Invalidate();
|
||||
}
|
||||
|
||||
std::unique_ptr<viz::SoftwareOutputDevice>
|
||||
OffScreenRenderWidgetHostView::CreateSoftwareOutputDevice(
|
||||
std::unique_ptr<viz::HostDisplayClient>
|
||||
OffScreenRenderWidgetHostView::CreateHostDisplayClient(
|
||||
ui::Compositor* compositor) {
|
||||
DCHECK_EQ(GetCompositor(), compositor);
|
||||
DCHECK(!copy_frame_generator_);
|
||||
DCHECK(!software_output_device_);
|
||||
|
||||
ResizeRootLayer(false);
|
||||
|
||||
software_output_device_ = new OffScreenOutputDevice(
|
||||
transparent_, base::Bind(&OffScreenRenderWidgetHostView::OnPaint,
|
||||
weak_ptr_factory_.GetWeakPtr()));
|
||||
return base::WrapUnique(software_output_device_);
|
||||
host_display_client_ = new OffScreenHostDisplayClient(
|
||||
gfx::kNullAcceleratedWidget,
|
||||
base::Bind(&OffScreenRenderWidgetHostView::OnPaint,
|
||||
weak_ptr_factory_.GetWeakPtr()));
|
||||
host_display_client_->SetActive(IsPainting());
|
||||
return base::WrapUnique(host_display_client_);
|
||||
}
|
||||
|
||||
bool OffScreenRenderWidgetHostView::InstallTransparency() {
|
||||
if (transparent_) {
|
||||
SetBackgroundColor(SkColor());
|
||||
#if defined(OS_MACOSX)
|
||||
browser_compositor_->SetBackgroundColor(SK_ColorTRANSPARENT);
|
||||
#else
|
||||
compositor_->SetBackgroundColor(SK_ColorTRANSPARENT);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -921,76 +761,99 @@ bool OffScreenRenderWidgetHostView::InstallTransparency() {
|
|||
void OffScreenRenderWidgetHostView::SetNeedsBeginFrames(
|
||||
bool needs_begin_frames) {
|
||||
SetupFrameRate(true);
|
||||
|
||||
begin_frame_timer_->SetActive(needs_begin_frames);
|
||||
|
||||
if (software_output_device_) {
|
||||
software_output_device_->SetActive(painting_, false);
|
||||
}
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::SetWantsAnimateOnlyBeginFrames() {
|
||||
if (GetDelegatedFrameHost()) {
|
||||
GetDelegatedFrameHost()->SetWantsAnimateOnlyBeginFrames();
|
||||
}
|
||||
void OffScreenRenderWidgetHostView::SetWantsAnimateOnlyBeginFrames() {}
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
void OffScreenRenderWidgetHostView::SetActive(bool active) {}
|
||||
|
||||
void OffScreenRenderWidgetHostView::ShowDefinitionForSelection() {}
|
||||
|
||||
void OffScreenRenderWidgetHostView::SpeakSelection() {}
|
||||
|
||||
bool OffScreenRenderWidgetHostView::UpdateNSViewAndDisplay() {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
void OffScreenRenderWidgetHostView::OnPaint(const gfx::Rect& damage_rect,
|
||||
const SkBitmap& bitmap) {
|
||||
backing_.reset(new SkBitmap());
|
||||
backing_->allocN32Pixels(bitmap.width(), bitmap.height(), !transparent_);
|
||||
bitmap.readPixels(backing_->pixmap());
|
||||
|
||||
if (IsPopupWidget() && parent_callback_) {
|
||||
parent_callback_.Run(this->popup_position_);
|
||||
} else {
|
||||
CompositeFrame(damage_rect);
|
||||
}
|
||||
}
|
||||
|
||||
gfx::Size OffScreenRenderWidgetHostView::SizeInPixels() {
|
||||
if (IsPopupWidget()) {
|
||||
return gfx::ConvertSizeToPixel(current_device_scale_factor_,
|
||||
popup_position_.size());
|
||||
} else {
|
||||
return gfx::ConvertSizeToPixel(current_device_scale_factor_,
|
||||
GetViewBounds().size());
|
||||
}
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::CompositeFrame(
|
||||
const gfx::Rect& damage_rect) {
|
||||
HoldResize();
|
||||
|
||||
if (parent_callback_) {
|
||||
parent_callback_.Run(damage_rect, bitmap);
|
||||
gfx::Size size_in_pixels = SizeInPixels();
|
||||
|
||||
SkBitmap frame;
|
||||
|
||||
// Optimize for the case when there is no popup
|
||||
if (proxy_views_.size() == 0 && !popup_host_view_) {
|
||||
frame = GetBacking();
|
||||
} else {
|
||||
gfx::Rect damage(damage_rect);
|
||||
frame.allocN32Pixels(size_in_pixels.width(), size_in_pixels.height(),
|
||||
false);
|
||||
if (!GetBacking().drawsNothing()) {
|
||||
SkCanvas canvas(frame);
|
||||
canvas.writePixels(GetBacking(), 0, 0);
|
||||
|
||||
gfx::Size size_in_pixels = gfx::ConvertSizeToPixel(
|
||||
current_device_scale_factor_, GetViewBounds().size());
|
||||
if (popup_host_view_ && !popup_host_view_->GetBacking().drawsNothing()) {
|
||||
gfx::Rect rect = popup_host_view_->popup_position_;
|
||||
gfx::Point origin_in_pixels = gfx::ConvertPointToPixel(
|
||||
current_device_scale_factor_, rect.origin());
|
||||
canvas.writePixels(popup_host_view_->GetBacking(), origin_in_pixels.x(),
|
||||
origin_in_pixels.y());
|
||||
}
|
||||
|
||||
SkBitmap backing;
|
||||
backing.allocN32Pixels(size_in_pixels.width(), size_in_pixels.height(),
|
||||
false);
|
||||
SkCanvas canvas(backing);
|
||||
|
||||
canvas.writePixels(bitmap, 0, 0);
|
||||
|
||||
if (popup_host_view_ && popup_bitmap_.get()) {
|
||||
gfx::Rect rect = popup_host_view_->popup_position_;
|
||||
gfx::Point origin_in_pixels =
|
||||
gfx::ConvertPointToPixel(current_device_scale_factor_, rect.origin());
|
||||
damage.Union(rect);
|
||||
canvas.writePixels(*popup_bitmap_.get(), origin_in_pixels.x(),
|
||||
origin_in_pixels.y());
|
||||
for (auto* proxy_view : proxy_views_) {
|
||||
gfx::Rect rect = proxy_view->GetBounds();
|
||||
gfx::Point origin_in_pixels = gfx::ConvertPointToPixel(
|
||||
current_device_scale_factor_, rect.origin());
|
||||
canvas.writePixels(*proxy_view->GetBitmap(), origin_in_pixels.x(),
|
||||
origin_in_pixels.y());
|
||||
}
|
||||
}
|
||||
|
||||
for (auto* proxy_view : proxy_views_) {
|
||||
gfx::Rect rect = proxy_view->GetBounds();
|
||||
gfx::Point origin_in_pixels =
|
||||
gfx::ConvertPointToPixel(current_device_scale_factor_, rect.origin());
|
||||
damage.Union(rect);
|
||||
canvas.writePixels(*proxy_view->GetBitmap(), origin_in_pixels.x(),
|
||||
origin_in_pixels.y());
|
||||
}
|
||||
|
||||
damage.Intersect(GetViewBounds());
|
||||
paint_callback_running_ = true;
|
||||
callback_.Run(damage, backing);
|
||||
paint_callback_running_ = false;
|
||||
}
|
||||
|
||||
paint_callback_running_ = true;
|
||||
callback_.Run(gfx::IntersectRects(gfx::Rect(size_in_pixels), damage_rect),
|
||||
frame);
|
||||
paint_callback_running_ = false;
|
||||
|
||||
ReleaseResize();
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::OnPopupPaint(const gfx::Rect& damage_rect,
|
||||
const SkBitmap& bitmap) {
|
||||
if (popup_host_view_ && popup_bitmap_.get())
|
||||
popup_bitmap_.reset(new SkBitmap(bitmap));
|
||||
InvalidateBounds(popup_host_view_->popup_position_);
|
||||
void OffScreenRenderWidgetHostView::OnPopupPaint(const gfx::Rect& damage_rect) {
|
||||
InvalidateBounds(
|
||||
gfx::ConvertRectToPixel(current_device_scale_factor_, damage_rect));
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::OnProxyViewPaint(
|
||||
const gfx::Rect& damage_rect) {
|
||||
InvalidateBounds(damage_rect);
|
||||
InvalidateBounds(
|
||||
gfx::ConvertRectToPixel(current_device_scale_factor_, damage_rect));
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::HoldResize() {
|
||||
|
@ -1020,7 +883,7 @@ void OffScreenRenderWidgetHostView::SynchronizeVisualProperties() {
|
|||
return;
|
||||
}
|
||||
|
||||
ResizeRootLayer(false);
|
||||
ResizeRootLayer(true);
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::SendMouseEvent(
|
||||
|
@ -1147,8 +1010,17 @@ void OffScreenRenderWidgetHostView::SendMouseWheelEvent(
|
|||
void OffScreenRenderWidgetHostView::SetPainting(bool painting) {
|
||||
painting_ = painting;
|
||||
|
||||
if (software_output_device_) {
|
||||
software_output_device_->SetActive(painting_, !paint_callback_running_);
|
||||
if (popup_host_view_) {
|
||||
popup_host_view_->SetPainting(painting);
|
||||
}
|
||||
|
||||
for (auto* guest_host_view : guest_host_views_)
|
||||
guest_host_view->SetPainting(painting);
|
||||
|
||||
if (video_consumer_) {
|
||||
video_consumer_->SetActive(IsPainting());
|
||||
} else if (host_display_client_) {
|
||||
host_display_client_->SetActive(IsPainting());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1173,6 +1045,10 @@ void OffScreenRenderWidgetHostView::SetFrameRate(int frame_rate) {
|
|||
|
||||
SetupFrameRate(true);
|
||||
|
||||
if (video_consumer_) {
|
||||
video_consumer_->SetFrameRate(GetFrameRate());
|
||||
}
|
||||
|
||||
for (auto* guest_host_view : guest_host_views_)
|
||||
guest_host_view->SetFrameRate(frame_rate);
|
||||
}
|
||||
|
@ -1181,7 +1057,6 @@ int OffScreenRenderWidgetHostView::GetFrameRate() const {
|
|||
return frame_rate_;
|
||||
}
|
||||
|
||||
#if !defined(OS_MACOSX)
|
||||
ui::Compositor* OffScreenRenderWidgetHostView::GetCompositor() const {
|
||||
return compositor_.get();
|
||||
}
|
||||
|
@ -1190,18 +1065,15 @@ ui::Layer* OffScreenRenderWidgetHostView::GetRootLayer() const {
|
|||
return root_layer_.get();
|
||||
}
|
||||
|
||||
#if !defined(OS_MACOSX)
|
||||
const viz::LocalSurfaceIdAllocation&
|
||||
OffScreenRenderWidgetHostView::GetLocalSurfaceIdAllocation() const {
|
||||
return local_surface_id_allocation_;
|
||||
return delegated_frame_host_allocation_;
|
||||
}
|
||||
#endif // defined(OS_MACOSX)
|
||||
|
||||
content::DelegatedFrameHost*
|
||||
OffScreenRenderWidgetHostView::GetDelegatedFrameHost() const {
|
||||
return delegated_frame_host_.get();
|
||||
}
|
||||
#endif
|
||||
|
||||
void OffScreenRenderWidgetHostView::SetupFrameRate(bool force) {
|
||||
if (!force && frame_rate_threshold_us_ != 0)
|
||||
|
@ -1209,11 +1081,6 @@ void OffScreenRenderWidgetHostView::SetupFrameRate(bool force) {
|
|||
|
||||
frame_rate_threshold_us_ = 1000000 / frame_rate_;
|
||||
|
||||
if (copy_frame_generator_.get()) {
|
||||
copy_frame_generator_->set_frame_rate_threshold_us(
|
||||
frame_rate_threshold_us_);
|
||||
}
|
||||
|
||||
if (begin_frame_timer_.get()) {
|
||||
begin_frame_timer_->SetFrameRateThresholdUs(frame_rate_threshold_us_);
|
||||
} else {
|
||||
|
@ -1225,15 +1092,11 @@ void OffScreenRenderWidgetHostView::SetupFrameRate(bool force) {
|
|||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::Invalidate() {
|
||||
InvalidateBounds(GetViewBounds());
|
||||
InvalidateBounds(gfx::Rect(GetRequestedRendererSize()));
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::InvalidateBounds(const gfx::Rect& bounds) {
|
||||
if (software_output_device_) {
|
||||
software_output_device_->OnPaint(bounds);
|
||||
} else if (copy_frame_generator_) {
|
||||
copy_frame_generator_->GenerateCopyFrame(bounds);
|
||||
}
|
||||
CompositeFrame(bounds);
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::ResizeRootLayer(bool force) {
|
||||
|
@ -1259,23 +1122,24 @@ void OffScreenRenderWidgetHostView::ResizeRootLayer(bool force) {
|
|||
|
||||
GetRootLayer()->SetBounds(gfx::Rect(size));
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
bool resized = UpdateNSViewAndDisplay();
|
||||
#else
|
||||
const gfx::Size& size_in_pixels =
|
||||
gfx::ConvertSizeToPixel(current_device_scale_factor_, size);
|
||||
|
||||
local_surface_id_allocator_.GenerateId();
|
||||
local_surface_id_allocation_ =
|
||||
local_surface_id_allocator_.GetCurrentLocalSurfaceIdAllocation();
|
||||
compositor_allocator_.GenerateId();
|
||||
compositor_allocation_ =
|
||||
compositor_allocator_.GetCurrentLocalSurfaceIdAllocation();
|
||||
|
||||
GetCompositor()->SetScaleAndSize(current_device_scale_factor_, size_in_pixels,
|
||||
local_surface_id_allocation_);
|
||||
compositor_allocation_);
|
||||
|
||||
delegated_frame_host_allocator_.GenerateId();
|
||||
delegated_frame_host_allocation_ =
|
||||
delegated_frame_host_allocator_.GetCurrentLocalSurfaceIdAllocation();
|
||||
|
||||
bool resized = true;
|
||||
GetDelegatedFrameHost()->EmbedSurface(
|
||||
local_surface_id_allocation_.local_surface_id(), size,
|
||||
delegated_frame_host_allocation_.local_surface_id(), size,
|
||||
cc::DeadlinePolicy::UseDefaultDeadline());
|
||||
#endif
|
||||
|
||||
// Note that |render_widget_host_| will retrieve resize parameters from the
|
||||
// DelegatedFrameHost, so it must have SynchronizeVisualProperties called
|
||||
|
|
|
@ -14,7 +14,8 @@
|
|||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "atom/browser/osr/osr_output_device.h"
|
||||
#include "atom/browser/osr/osr_host_display_client.h"
|
||||
#include "atom/browser/osr/osr_video_consumer.h"
|
||||
#include "atom/browser/osr/osr_view_proxy.h"
|
||||
#include "base/process/kill.h"
|
||||
#include "base/threading/thread.h"
|
||||
|
@ -23,12 +24,12 @@
|
|||
#include "components/viz/common/frame_sinks/begin_frame_source.h"
|
||||
#include "components/viz/common/quads/compositor_frame.h"
|
||||
#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
|
||||
#include "content/browser/frame_host/render_widget_host_view_guest.h"
|
||||
#include "content/browser/renderer_host/delegated_frame_host.h"
|
||||
#include "content/browser/renderer_host/input/mouse_wheel_phase_handler.h"
|
||||
#include "content/browser/renderer_host/render_widget_host_impl.h"
|
||||
#include "content/browser/renderer_host/render_widget_host_view_base.h"
|
||||
#include "content/browser/web_contents/web_contents_view.h"
|
||||
#include "content/browser/frame_host/render_widget_host_view_guest.h" // nogncheck
|
||||
#include "content/browser/renderer_host/delegated_frame_host.h" // nogncheck
|
||||
#include "content/browser/renderer_host/input/mouse_wheel_phase_handler.h" // nogncheck
|
||||
#include "content/browser/renderer_host/render_widget_host_impl.h" // nogncheck
|
||||
#include "content/browser/renderer_host/render_widget_host_view_base.h" // nogncheck
|
||||
#include "content/browser/web_contents/web_contents_view.h" // nogncheck
|
||||
#include "third_party/blink/public/platform/web_vector.h"
|
||||
#include "third_party/skia/include/core/SkBitmap.h"
|
||||
#include "ui/base/ime/text_input_client.h"
|
||||
|
@ -37,24 +38,13 @@
|
|||
#include "ui/compositor/layer_owner.h"
|
||||
#include "ui/gfx/geometry/point.h"
|
||||
|
||||
#include "components/viz/host/host_display_client.h"
|
||||
#include "ui/compositor/external_begin_frame_client.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include "ui/gfx/win/window_impl.h"
|
||||
#endif
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
#include "content/browser/renderer_host/browser_compositor_view_mac.h"
|
||||
#endif
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
#ifdef __OBJC__
|
||||
@class CALayer;
|
||||
@class NSWindow;
|
||||
#else
|
||||
class CALayer;
|
||||
class NSWindow;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace content {
|
||||
class CursorManager;
|
||||
} // namespace content
|
||||
|
@ -64,13 +54,13 @@ namespace atom {
|
|||
class AtomCopyFrameGenerator;
|
||||
class AtomBeginFrameTimer;
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
class MacHelper;
|
||||
#else
|
||||
class AtomDelegatedFrameHostClient;
|
||||
#endif
|
||||
|
||||
typedef base::Callback<void(const gfx::Rect&, const SkBitmap&)> OnPaintCallback;
|
||||
typedef base::Callback<void(const gfx::Rect&)> OnPopupPaintCallback;
|
||||
|
||||
class OffScreenRenderWidgetHostView : public content::RenderWidgetHostViewBase,
|
||||
public ui::ExternalBeginFrameClient,
|
||||
public ui::CompositorDelegate,
|
||||
public OffscreenViewProxyObserver {
|
||||
public:
|
||||
|
@ -87,6 +77,9 @@ class OffScreenRenderWidgetHostView : public content::RenderWidgetHostViewBase,
|
|||
content::BrowserAccessibilityDelegate*,
|
||||
bool) override;
|
||||
|
||||
void OnDisplayDidFinishFrame(const viz::BeginFrameAck& ack) override;
|
||||
void OnNeedsExternalBeginFrames(bool needs_begin_frames) override;
|
||||
|
||||
// content::RenderWidgetHostView:
|
||||
void InitAsChild(gfx::NativeView) override;
|
||||
void SetSize(const gfx::Size&) override;
|
||||
|
@ -152,15 +145,12 @@ class OffScreenRenderWidgetHostView : public content::RenderWidgetHostViewBase,
|
|||
void TransformPointToRootSurface(gfx::PointF* point) override;
|
||||
gfx::Rect GetBoundsInRootWindow(void) override;
|
||||
viz::SurfaceId GetCurrentSurfaceId() const override;
|
||||
std::unique_ptr<content::SyntheticGestureTarget>
|
||||
CreateSyntheticGestureTarget() override;
|
||||
void ImeCompositionRangeChanged(const gfx::Range&,
|
||||
const std::vector<gfx::Rect>&) override;
|
||||
gfx::Size GetCompositorViewportPixelSize() const override;
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
viz::ScopedSurfaceIdAllocator DidUpdateVisualProperties(
|
||||
const cc::RenderFrameMetadata& metadata) override;
|
||||
#endif
|
||||
|
||||
content::RenderWidgetHostViewBase* CreateViewForWidget(
|
||||
content::RenderWidgetHost*,
|
||||
content::RenderWidgetHost*,
|
||||
|
@ -179,11 +169,10 @@ class OffScreenRenderWidgetHostView : public content::RenderWidgetHostViewBase,
|
|||
bool TransformPointToCoordSpaceForView(
|
||||
const gfx::PointF& point,
|
||||
RenderWidgetHostViewBase* target_view,
|
||||
gfx::PointF* transformed_point,
|
||||
viz::EventSource source = viz::EventSource::ANY) override;
|
||||
gfx::PointF* transformed_point) override;
|
||||
|
||||
// ui::CompositorDelegate:
|
||||
std::unique_ptr<viz::SoftwareOutputDevice> CreateSoftwareOutputDevice(
|
||||
std::unique_ptr<viz::HostDisplayClient> CreateHostDisplayClient(
|
||||
ui::Compositor* compositor) override;
|
||||
|
||||
bool InstallTransparency();
|
||||
|
@ -191,14 +180,6 @@ class OffScreenRenderWidgetHostView : public content::RenderWidgetHostViewBase,
|
|||
void OnBeginFrameTimerTick();
|
||||
void SendBeginFrame(base::TimeTicks frame_time, base::TimeDelta vsync_period);
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
void CreatePlatformWidget(bool is_guest_view_hack);
|
||||
void DestroyPlatformWidget();
|
||||
SkColor last_frame_root_background_color() const {
|
||||
return last_frame_root_background_color_;
|
||||
}
|
||||
#endif
|
||||
|
||||
void CancelWidget();
|
||||
void AddGuestHostView(OffScreenRenderWidgetHostView* guest_host);
|
||||
void RemoveGuestHostView(OffScreenRenderWidgetHostView* guest_host);
|
||||
|
@ -207,13 +188,19 @@ class OffScreenRenderWidgetHostView : public content::RenderWidgetHostViewBase,
|
|||
void ProxyViewDestroyed(OffscreenViewProxy* proxy) override;
|
||||
|
||||
void OnPaint(const gfx::Rect& damage_rect, const SkBitmap& bitmap);
|
||||
void OnPopupPaint(const gfx::Rect& damage_rect, const SkBitmap& bitmap);
|
||||
void OnPopupPaint(const gfx::Rect& damage_rect);
|
||||
void OnProxyViewPaint(const gfx::Rect& damage_rect) override;
|
||||
|
||||
gfx::Size SizeInPixels();
|
||||
|
||||
void CompositeFrame(const gfx::Rect& damage_rect);
|
||||
|
||||
bool IsPopupWidget() const {
|
||||
return widget_type_ == content::WidgetType::kPopup;
|
||||
}
|
||||
|
||||
const SkBitmap& GetBacking() { return *backing_.get(); }
|
||||
|
||||
void HoldResize();
|
||||
void ReleaseResize();
|
||||
void SynchronizeVisualProperties();
|
||||
|
@ -230,12 +217,6 @@ class OffScreenRenderWidgetHostView : public content::RenderWidgetHostViewBase,
|
|||
ui::Compositor* GetCompositor() const;
|
||||
ui::Layer* GetRootLayer() const;
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
content::BrowserCompositorMac* browser_compositor() const {
|
||||
return browser_compositor_.get();
|
||||
}
|
||||
#endif
|
||||
|
||||
content::DelegatedFrameHost* GetDelegatedFrameHost() const;
|
||||
|
||||
void Invalidate();
|
||||
|
@ -256,12 +237,6 @@ class OffScreenRenderWidgetHostView : public content::RenderWidgetHostViewBase,
|
|||
}
|
||||
|
||||
private:
|
||||
#if defined(OS_MACOSX)
|
||||
display::Display GetDisplay();
|
||||
void OnDidUpdateVisualPropertiesComplete(
|
||||
const cc::RenderFrameMetadata& metadata);
|
||||
#endif
|
||||
|
||||
void SetupFrameRate(bool force);
|
||||
void ResizeRootLayer(bool force);
|
||||
|
||||
|
@ -276,16 +251,13 @@ class OffScreenRenderWidgetHostView : public content::RenderWidgetHostViewBase,
|
|||
|
||||
OffScreenRenderWidgetHostView* parent_host_view_ = nullptr;
|
||||
OffScreenRenderWidgetHostView* popup_host_view_ = nullptr;
|
||||
std::unique_ptr<SkBitmap> popup_bitmap_;
|
||||
OffScreenRenderWidgetHostView* child_host_view_ = nullptr;
|
||||
std::set<OffScreenRenderWidgetHostView*> guest_host_views_;
|
||||
std::set<OffscreenViewProxy*> proxy_views_;
|
||||
|
||||
OffScreenOutputDevice* software_output_device_ = nullptr;
|
||||
|
||||
const bool transparent_;
|
||||
OnPaintCallback callback_;
|
||||
OnPaintCallback parent_callback_;
|
||||
OnPopupPaintCallback parent_callback_;
|
||||
|
||||
int frame_rate_ = 0;
|
||||
int frame_rate_threshold_us_ = 0;
|
||||
|
@ -305,8 +277,11 @@ class OffScreenRenderWidgetHostView : public content::RenderWidgetHostViewBase,
|
|||
|
||||
bool paint_callback_running_ = false;
|
||||
|
||||
viz::LocalSurfaceIdAllocation local_surface_id_allocation_;
|
||||
viz::ParentLocalSurfaceIdAllocator local_surface_id_allocator_;
|
||||
viz::LocalSurfaceIdAllocation delegated_frame_host_allocation_;
|
||||
viz::ParentLocalSurfaceIdAllocator delegated_frame_host_allocator_;
|
||||
|
||||
viz::LocalSurfaceIdAllocation compositor_allocation_;
|
||||
viz::ParentLocalSurfaceIdAllocator compositor_allocator_;
|
||||
|
||||
std::unique_ptr<ui::Layer> root_layer_;
|
||||
std::unique_ptr<ui::Compositor> compositor_;
|
||||
|
@ -314,27 +289,15 @@ class OffScreenRenderWidgetHostView : public content::RenderWidgetHostViewBase,
|
|||
|
||||
std::unique_ptr<content::CursorManager> cursor_manager_;
|
||||
|
||||
std::unique_ptr<AtomCopyFrameGenerator> copy_frame_generator_;
|
||||
std::unique_ptr<AtomBeginFrameTimer> begin_frame_timer_;
|
||||
OffScreenHostDisplayClient* host_display_client_;
|
||||
std::unique_ptr<OffScreenVideoConsumer> video_consumer_;
|
||||
|
||||
// Provides |source_id| for BeginFrameArgs that we create.
|
||||
viz::StubBeginFrameSource begin_frame_source_;
|
||||
uint64_t begin_frame_number_ = viz::BeginFrameArgs::kStartingFrameNumber;
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
std::unique_ptr<content::BrowserCompositorMac> browser_compositor_;
|
||||
|
||||
SkColor last_frame_root_background_color_;
|
||||
|
||||
// Can not be managed by smart pointer because its header can not be included
|
||||
// in the file that has the destructor.
|
||||
MacHelper* mac_helper_;
|
||||
|
||||
// Selected text on the renderer.
|
||||
std::string selected_text_;
|
||||
#else
|
||||
std::unique_ptr<AtomDelegatedFrameHostClient> delegated_frame_host_client_;
|
||||
#endif
|
||||
|
||||
content::MouseWheelPhaseHandler mouse_wheel_phase_handler_;
|
||||
|
||||
|
@ -348,6 +311,8 @@ class OffScreenRenderWidgetHostView : public content::RenderWidgetHostViewBase,
|
|||
|
||||
SkColor background_color_ = SkColor();
|
||||
|
||||
std::unique_ptr<SkBitmap> backing_;
|
||||
|
||||
base::WeakPtrFactory<OffScreenRenderWidgetHostView> weak_ptr_factory_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(OffScreenRenderWidgetHostView);
|
||||
|
|
|
@ -1,150 +0,0 @@
|
|||
// Copyright (c) 2016 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/osr/osr_render_widget_host_view.h"
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "content/common/view_messages.h"
|
||||
#include "ui/accelerated_widget_mac/accelerated_widget_mac.h"
|
||||
#include "ui/display/screen.h"
|
||||
|
||||
#include "components/viz/common/features.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
class MacHelper : public content::BrowserCompositorMacClient,
|
||||
public ui::AcceleratedWidgetMacNSView {
|
||||
public:
|
||||
explicit MacHelper(OffScreenRenderWidgetHostView* view) : view_(view) {
|
||||
[view_->GetNativeView().GetNativeNSView() setWantsLayer:YES];
|
||||
}
|
||||
|
||||
virtual ~MacHelper() {}
|
||||
|
||||
// content::BrowserCompositorMacClient:
|
||||
SkColor BrowserCompositorMacGetGutterColor() const override {
|
||||
// When making an element on the page fullscreen the element's background
|
||||
// may not match the page's, so use black as the gutter color to avoid
|
||||
// flashes of brighter colors during the transition.
|
||||
if (view_->render_widget_host()->delegate() &&
|
||||
view_->render_widget_host()->delegate()->IsFullscreenForCurrentTab()) {
|
||||
return SK_ColorBLACK;
|
||||
}
|
||||
return view_->last_frame_root_background_color();
|
||||
}
|
||||
|
||||
void BrowserCompositorMacOnBeginFrame(base::TimeTicks frame_time) override {}
|
||||
|
||||
void OnFrameTokenChanged(uint32_t frame_token) override {
|
||||
view_->render_widget_host()->DidProcessFrame(frame_token);
|
||||
}
|
||||
|
||||
void AcceleratedWidgetCALayerParamsUpdated() override {}
|
||||
|
||||
void DestroyCompositorForShutdown() override {}
|
||||
|
||||
bool OnBrowserCompositorSurfaceIdChanged() override {
|
||||
return view_->render_widget_host()->SynchronizeVisualProperties();
|
||||
}
|
||||
|
||||
std::vector<viz::SurfaceId> CollectSurfaceIdsForEviction() override {
|
||||
return view_->render_widget_host()->CollectSurfaceIdsForEviction();
|
||||
}
|
||||
|
||||
private:
|
||||
OffScreenRenderWidgetHostView* view_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(MacHelper);
|
||||
};
|
||||
|
||||
void OffScreenRenderWidgetHostView::SetActive(bool active) {}
|
||||
|
||||
void OffScreenRenderWidgetHostView::ShowDefinitionForSelection() {}
|
||||
|
||||
void OffScreenRenderWidgetHostView::SpeakSelection() {}
|
||||
|
||||
bool OffScreenRenderWidgetHostView::UpdateNSViewAndDisplay() {
|
||||
return browser_compositor_->UpdateSurfaceFromNSView(
|
||||
GetRootLayer()->bounds().size(), GetDisplay());
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::CreatePlatformWidget(
|
||||
bool is_guest_view_hack) {
|
||||
mac_helper_ = new MacHelper(this);
|
||||
browser_compositor_.reset(new content::BrowserCompositorMac(
|
||||
mac_helper_, mac_helper_, render_widget_host_->is_hidden(), GetDisplay(),
|
||||
AllocateFrameSinkId(is_guest_view_hack)));
|
||||
|
||||
if (!base::FeatureList::IsEnabled(features::kVizDisplayCompositor)) {
|
||||
SetNeedsBeginFrames(true);
|
||||
}
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::DestroyPlatformWidget() {
|
||||
browser_compositor_.reset();
|
||||
delete mac_helper_;
|
||||
}
|
||||
|
||||
viz::ScopedSurfaceIdAllocator
|
||||
OffScreenRenderWidgetHostView::DidUpdateVisualProperties(
|
||||
const cc::RenderFrameMetadata& metadata) {
|
||||
base::OnceCallback<void()> allocation_task = base::BindOnce(
|
||||
base::IgnoreResult(
|
||||
&OffScreenRenderWidgetHostView::OnDidUpdateVisualPropertiesComplete),
|
||||
weak_ptr_factory_.GetWeakPtr(), metadata);
|
||||
return browser_compositor_->GetScopedRendererSurfaceIdAllocator(
|
||||
std::move(allocation_task));
|
||||
}
|
||||
|
||||
display::Display OffScreenRenderWidgetHostView::GetDisplay() {
|
||||
content::ScreenInfo screen_info;
|
||||
GetScreenInfo(&screen_info);
|
||||
|
||||
// Start with a reasonable display representation.
|
||||
display::Display display =
|
||||
display::Screen::GetScreen()->GetDisplayNearestView(nullptr);
|
||||
|
||||
// Populate attributes based on |screen_info|.
|
||||
display.set_bounds(screen_info.rect);
|
||||
display.set_work_area(screen_info.available_rect);
|
||||
display.set_device_scale_factor(screen_info.device_scale_factor);
|
||||
display.set_color_space(screen_info.color_space);
|
||||
display.set_color_depth(screen_info.depth);
|
||||
display.set_depth_per_component(screen_info.depth_per_component);
|
||||
display.set_is_monochrome(screen_info.is_monochrome);
|
||||
display.SetRotationAsDegree(screen_info.orientation_angle);
|
||||
|
||||
return display;
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::OnDidUpdateVisualPropertiesComplete(
|
||||
const cc::RenderFrameMetadata& metadata) {
|
||||
DCHECK_EQ(current_device_scale_factor_, metadata.device_scale_factor);
|
||||
browser_compositor_->UpdateSurfaceFromChild(
|
||||
metadata.device_scale_factor, metadata.viewport_size_in_pixels,
|
||||
metadata.local_surface_id_allocation.value_or(
|
||||
viz::LocalSurfaceIdAllocation()));
|
||||
}
|
||||
|
||||
const viz::LocalSurfaceIdAllocation&
|
||||
OffScreenRenderWidgetHostView::GetLocalSurfaceIdAllocation() const {
|
||||
return browser_compositor_->GetRendererLocalSurfaceIdAllocation();
|
||||
}
|
||||
|
||||
ui::Compositor* OffScreenRenderWidgetHostView::GetCompositor() const {
|
||||
return browser_compositor_->GetCompositor();
|
||||
}
|
||||
|
||||
ui::Layer* OffScreenRenderWidgetHostView::GetRootLayer() const {
|
||||
return browser_compositor_->GetRootLayer();
|
||||
}
|
||||
|
||||
content::DelegatedFrameHost*
|
||||
OffScreenRenderWidgetHostView::GetDelegatedFrameHost() const {
|
||||
return browser_compositor_->GetDelegatedFrameHost();
|
||||
}
|
||||
|
||||
} // namespace atom
|
|
@ -0,0 +1,137 @@
|
|||
// Copyright (c) 2019 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/osr/osr_video_consumer.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "atom/browser/osr/osr_render_widget_host_view.h"
|
||||
#include "media/base/video_frame_metadata.h"
|
||||
#include "media/capture/mojom/video_capture_types.mojom.h"
|
||||
#include "ui/gfx/skbitmap_operations.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
OffScreenVideoConsumer::OffScreenVideoConsumer(
|
||||
OffScreenRenderWidgetHostView* view,
|
||||
OnPaintCallback callback)
|
||||
: callback_(callback),
|
||||
view_(view),
|
||||
video_capturer_(view->CreateVideoCapturer()),
|
||||
weak_ptr_factory_(this) {
|
||||
video_capturer_->SetResolutionConstraints(view_->SizeInPixels(),
|
||||
view_->SizeInPixels(), true);
|
||||
video_capturer_->SetAutoThrottlingEnabled(false);
|
||||
video_capturer_->SetMinSizeChangePeriod(base::TimeDelta());
|
||||
video_capturer_->SetFormat(media::PIXEL_FORMAT_ARGB,
|
||||
gfx::ColorSpace::CreateREC709());
|
||||
SetFrameRate(view_->GetFrameRate());
|
||||
}
|
||||
|
||||
OffScreenVideoConsumer::~OffScreenVideoConsumer() = default;
|
||||
|
||||
void OffScreenVideoConsumer::SetActive(bool active) {
|
||||
if (active) {
|
||||
video_capturer_->Start(this);
|
||||
} else {
|
||||
video_capturer_->Stop();
|
||||
}
|
||||
}
|
||||
|
||||
void OffScreenVideoConsumer::SetFrameRate(int frame_rate) {
|
||||
video_capturer_->SetMinCapturePeriod(base::TimeDelta::FromSeconds(1) /
|
||||
frame_rate);
|
||||
}
|
||||
|
||||
void OffScreenVideoConsumer::SizeChanged() {
|
||||
video_capturer_->SetResolutionConstraints(view_->SizeInPixels(),
|
||||
view_->SizeInPixels(), true);
|
||||
video_capturer_->RequestRefreshFrame();
|
||||
}
|
||||
|
||||
void OffScreenVideoConsumer::OnFrameCaptured(
|
||||
base::ReadOnlySharedMemoryRegion data,
|
||||
::media::mojom::VideoFrameInfoPtr info,
|
||||
const gfx::Rect& content_rect,
|
||||
viz::mojom::FrameSinkVideoConsumerFrameCallbacksPtr callbacks) {
|
||||
if (!CheckContentRect(content_rect)) {
|
||||
gfx::Size view_size = view_->SizeInPixels();
|
||||
video_capturer_->SetResolutionConstraints(view_size, view_size, true);
|
||||
video_capturer_->RequestRefreshFrame();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!data.IsValid()) {
|
||||
callbacks->Done();
|
||||
return;
|
||||
}
|
||||
base::ReadOnlySharedMemoryMapping mapping = data.Map();
|
||||
if (!mapping.IsValid()) {
|
||||
DLOG(ERROR) << "Shared memory mapping failed.";
|
||||
return;
|
||||
}
|
||||
if (mapping.size() <
|
||||
media::VideoFrame::AllocationSize(info->pixel_format, info->coded_size)) {
|
||||
DLOG(ERROR) << "Shared memory size was less than expected.";
|
||||
return;
|
||||
}
|
||||
|
||||
// The SkBitmap's pixels will be marked as immutable, but the installPixels()
|
||||
// API requires a non-const pointer. So, cast away the const.
|
||||
void* const pixels = const_cast<void*>(mapping.memory());
|
||||
|
||||
// Call installPixels() with a |releaseProc| that: 1) notifies the capturer
|
||||
// that this consumer has finished with the frame, and 2) releases the shared
|
||||
// memory mapping.
|
||||
struct FramePinner {
|
||||
// Keeps the shared memory that backs |frame_| mapped.
|
||||
base::ReadOnlySharedMemoryMapping mapping;
|
||||
// Prevents FrameSinkVideoCapturer from recycling the shared memory that
|
||||
// backs |frame_|.
|
||||
viz::mojom::FrameSinkVideoConsumerFrameCallbacksPtr releaser;
|
||||
};
|
||||
|
||||
SkBitmap bitmap;
|
||||
bitmap.installPixels(
|
||||
SkImageInfo::MakeN32(content_rect.width(), content_rect.height(),
|
||||
kPremul_SkAlphaType),
|
||||
pixels,
|
||||
media::VideoFrame::RowBytes(media::VideoFrame::kARGBPlane,
|
||||
info->pixel_format, info->coded_size.width()),
|
||||
[](void* addr, void* context) {
|
||||
delete static_cast<FramePinner*>(context);
|
||||
},
|
||||
new FramePinner{std::move(mapping), std::move(callbacks)});
|
||||
bitmap.setImmutable();
|
||||
|
||||
media::VideoFrameMetadata metadata;
|
||||
metadata.MergeInternalValuesFrom(info->metadata);
|
||||
gfx::Rect damage_rect;
|
||||
|
||||
auto UPDATE_RECT = media::VideoFrameMetadata::CAPTURE_UPDATE_RECT;
|
||||
if (!metadata.GetRect(UPDATE_RECT, &damage_rect)) {
|
||||
damage_rect = content_rect;
|
||||
}
|
||||
|
||||
callback_.Run(damage_rect, bitmap);
|
||||
}
|
||||
|
||||
void OffScreenVideoConsumer::OnStopped() {}
|
||||
|
||||
bool OffScreenVideoConsumer::CheckContentRect(const gfx::Rect& content_rect) {
|
||||
gfx::Size view_size = view_->SizeInPixels();
|
||||
gfx::Size content_size = content_rect.size();
|
||||
|
||||
if (std::abs(view_size.width() - content_size.width()) > 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (std::abs(view_size.height() - content_size.height()) > 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace atom
|
|
@ -0,0 +1,53 @@
|
|||
// Copyright (c) 2019 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_OSR_OSR_VIDEO_CONSUMER_H_
|
||||
#define ATOM_BROWSER_OSR_OSR_VIDEO_CONSUMER_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "base/callback.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "components/viz/host/client_frame_sink_video_capturer.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
class OffScreenRenderWidgetHostView;
|
||||
|
||||
typedef base::Callback<void(const gfx::Rect&, const SkBitmap&)> OnPaintCallback;
|
||||
|
||||
class OffScreenVideoConsumer : public viz::mojom::FrameSinkVideoConsumer {
|
||||
public:
|
||||
OffScreenVideoConsumer(OffScreenRenderWidgetHostView* view,
|
||||
OnPaintCallback callback);
|
||||
~OffScreenVideoConsumer() override;
|
||||
|
||||
void SetActive(bool active);
|
||||
void SetFrameRate(int frame_rate);
|
||||
void SizeChanged();
|
||||
|
||||
private:
|
||||
// viz::mojom::FrameSinkVideoConsumer implementation.
|
||||
void OnFrameCaptured(
|
||||
base::ReadOnlySharedMemoryRegion data,
|
||||
::media::mojom::VideoFrameInfoPtr info,
|
||||
const gfx::Rect& content_rect,
|
||||
viz::mojom::FrameSinkVideoConsumerFrameCallbacksPtr callbacks) override;
|
||||
void OnStopped() override;
|
||||
|
||||
bool CheckContentRect(const gfx::Rect& content_rect);
|
||||
|
||||
OnPaintCallback callback_;
|
||||
|
||||
OffScreenRenderWidgetHostView* view_;
|
||||
std::unique_ptr<viz::ClientFrameSinkVideoCapturer> video_capturer_;
|
||||
|
||||
base::WeakPtrFactory<OffScreenVideoConsumer> weak_ptr_factory_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(OffScreenVideoConsumer);
|
||||
};
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_OSR_OSR_VIDEO_CONSUMER_H_
|
|
@ -5,7 +5,7 @@
|
|||
#include "atom/browser/osr/osr_web_contents_view.h"
|
||||
|
||||
#include "atom/common/api/api_messages.h"
|
||||
#include "content/browser/web_contents/web_contents_impl.h"
|
||||
#include "content/browser/web_contents/web_contents_impl.h" // nogncheck
|
||||
#include "content/public/browser/render_view_host.h"
|
||||
#include "third_party/blink/public/platform/web_screen_info.h"
|
||||
#include "ui/display/screen.h"
|
||||
|
@ -140,7 +140,7 @@ OffScreenWebContentsView::CreateViewForChildWidget(
|
|||
->GetRenderWidgetHostView()
|
||||
: web_contents_impl->GetRenderWidgetHostView());
|
||||
|
||||
return new OffScreenRenderWidgetHostView(transparent_, true,
|
||||
return new OffScreenRenderWidgetHostView(transparent_, painting_,
|
||||
view->GetFrameRate(), callback_,
|
||||
render_widget_host, view, GetSize());
|
||||
}
|
||||
|
@ -166,11 +166,9 @@ void OffScreenWebContentsView::RenderViewHostChanged(
|
|||
void OffScreenWebContentsView::SetOverscrollControllerEnabled(bool enabled) {}
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
bool OffScreenWebContentsView::IsEventTracking() const {
|
||||
bool OffScreenWebContentsView::CloseTabAfterEventTrackingIfNeeded() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void OffScreenWebContentsView::CloseTabAfterEventTracking() {}
|
||||
#endif // defined(OS_MACOSX)
|
||||
|
||||
void OffScreenWebContentsView::StartDragging(
|
||||
|
@ -189,10 +187,9 @@ void OffScreenWebContentsView::UpdateDragCursor(
|
|||
|
||||
void OffScreenWebContentsView::SetPainting(bool painting) {
|
||||
auto* view = GetView();
|
||||
painting_ = painting;
|
||||
if (view != nullptr) {
|
||||
view->SetPainting(painting);
|
||||
} else {
|
||||
painting_ = painting;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -207,10 +204,9 @@ bool OffScreenWebContentsView::IsPainting() const {
|
|||
|
||||
void OffScreenWebContentsView::SetFrameRate(int frame_rate) {
|
||||
auto* view = GetView();
|
||||
frame_rate_ = frame_rate;
|
||||
if (view != nullptr) {
|
||||
view->SetFrameRate(frame_rate);
|
||||
} else {
|
||||
frame_rate_ = frame_rate;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
#include "atom/browser/native_window_observer.h"
|
||||
|
||||
#include "atom/browser/osr/osr_render_widget_host_view.h"
|
||||
#include "content/browser/renderer_host/render_view_host_delegate_view.h"
|
||||
#include "content/browser/web_contents/web_contents_view.h"
|
||||
#include "content/browser/renderer_host/render_view_host_delegate_view.h" // nogncheck
|
||||
#include "content/browser/web_contents/web_contents_view.h" // nogncheck
|
||||
#include "content/public/browser/web_contents.h"
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
|
@ -67,8 +67,7 @@ class OffScreenWebContentsView : public content::WebContentsView,
|
|||
void SetOverscrollControllerEnabled(bool enabled) override;
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
bool IsEventTracking() const override;
|
||||
void CloseTabAfterEventTracking() override;
|
||||
bool CloseTabAfterEventTrackingIfNeeded() override;
|
||||
#endif
|
||||
|
||||
// content::RenderViewHostDelegateView
|
||||
|
|
|
@ -69,7 +69,6 @@ void AutofillPopup::CreateView(content::RenderFrameHost* frame_host,
|
|||
parent_->AddObserver(this);
|
||||
|
||||
view_ = new AutofillPopupView(this, parent->GetWidget());
|
||||
view_->Show();
|
||||
|
||||
#if BUILDFLAG(ENABLE_OSR)
|
||||
if (offscreen) {
|
||||
|
@ -83,6 +82,9 @@ void AutofillPopup::CreateView(content::RenderFrameHost* frame_host,
|
|||
osr_rwhv->AddViewProxy(view_->view_proxy_.get());
|
||||
}
|
||||
#endif
|
||||
|
||||
// Do this after OSR setup, we check for view_proxy_ when showing
|
||||
view_->Show();
|
||||
}
|
||||
|
||||
void AutofillPopup::Hide() {
|
||||
|
|
|
@ -56,7 +56,11 @@ AutofillPopupView::~AutofillPopupView() {
|
|||
}
|
||||
|
||||
void AutofillPopupView::Show() {
|
||||
if (!popup_ || !parent_widget_->IsVisible() || parent_widget_->IsClosed())
|
||||
bool visible = parent_widget_->IsVisible();
|
||||
#if BUILDFLAG(ENABLE_OSR)
|
||||
visible = visible || view_proxy_;
|
||||
#endif
|
||||
if (!popup_ || !visible || parent_widget_->IsClosed())
|
||||
return;
|
||||
|
||||
const bool initialize_widget = !GetWidget();
|
||||
|
|
|
@ -8,7 +8,7 @@ declare_args() {
|
|||
# Allow running Electron as a node binary.
|
||||
enable_run_as_node = true
|
||||
|
||||
enable_osr = false
|
||||
enable_osr = true
|
||||
|
||||
enable_view_api = false
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@ blink_local_frame.patch
|
|||
blink_world_context.patch
|
||||
browser_compositor_mac.patch
|
||||
can_create_window.patch
|
||||
compositor_delegate.patch
|
||||
disable_hidden.patch
|
||||
dom_storage_limits.patch
|
||||
frame_host_manager.patch
|
||||
|
@ -74,3 +73,4 @@ disable_custom_libcxx_on_windows.patch
|
|||
fix_retain_compatibility_with_msvc.patch
|
||||
disable_network_services_by_default.patch
|
||||
unsandboxed_ppapi_processes_skip_zygote.patch
|
||||
viz_osr.patch
|
||||
|
|
|
@ -1,81 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Anonymous <anonymous@electronjs.org>
|
||||
Date: Thu, 20 Sep 2018 17:45:36 -0700
|
||||
Subject: compositor_delegate.patch
|
||||
|
||||
|
||||
diff --git a/content/browser/compositor/gpu_process_transport_factory.cc b/content/browser/compositor/gpu_process_transport_factory.cc
|
||||
index ff4e3109b11fea4e0a732ebf9ac9c17e4b5d5e8e..09eee0aae0306545af49258a8f11813c06655023 100644
|
||||
--- a/content/browser/compositor/gpu_process_transport_factory.cc
|
||||
+++ b/content/browser/compositor/gpu_process_transport_factory.cc
|
||||
@@ -451,11 +451,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(vsync_callback));
|
||||
+ std::move(output_device), std::move(vsync_callback));
|
||||
} else {
|
||||
DCHECK(context_provider);
|
||||
const auto& capabilities = context_provider->ContextCapabilities();
|
||||
diff --git a/ui/compositor/compositor.h b/ui/compositor/compositor.h
|
||||
index 29784c677f4be6e4fd7cfb298ab3554d22e1beaa..07b61abe7ce666b5eb6448ef795f838ddb805947 100644
|
||||
--- a/ui/compositor/compositor.h
|
||||
+++ b/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_allocation.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"
|
||||
@@ -193,6 +194,15 @@ class COMPOSITOR_EXPORT ContextFactory {
|
||||
virtual bool SyncTokensRequiredForDisplayCompositor() = 0;
|
||||
};
|
||||
|
||||
+class COMPOSITOR_EXPORT CompositorDelegate {
|
||||
+ public:
|
||||
+ virtual std::unique_ptr<viz::SoftwareOutputDevice> CreateSoftwareOutputDevice(
|
||||
+ ui::Compositor* compositor) = 0;
|
||||
+
|
||||
+ 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
|
||||
@@ -235,6 +245,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
|
||||
@@ -458,6 +471,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;
|
||||
|
|
@ -0,0 +1,638 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Heilig Benedek <benecene@gmail.com>
|
||||
Date: Wed, 20 Mar 2019 20:30:44 +0100
|
||||
Subject: feat: offscreen rendering with viz compositor
|
||||
|
||||
|
||||
diff --git a/components/viz/host/host_display_client.cc b/components/viz/host/host_display_client.cc
|
||||
index bdd1e8bde77ac458639d2b6064c58a133becc5ee..b21917e760c9bf183a75d1ed4e4104eeeb8948ad 100644
|
||||
--- a/components/viz/host/host_display_client.cc
|
||||
+++ b/components/viz/host/host_display_client.cc
|
||||
@@ -18,6 +18,10 @@
|
||||
|
||||
namespace viz {
|
||||
|
||||
+void HostDisplayClient::IsOffscreen(IsOffscreenCallback callback) {
|
||||
+ std::move(callback).Run(false);
|
||||
+}
|
||||
+
|
||||
HostDisplayClient::HostDisplayClient(gfx::AcceleratedWidget widget)
|
||||
: binding_(this) {
|
||||
#if defined(OS_MACOSX) || defined(OS_WIN)
|
||||
@@ -49,9 +53,9 @@ void HostDisplayClient::OnDisplayReceivedCALayerParams(
|
||||
}
|
||||
#endif
|
||||
|
||||
-#if defined(OS_WIN)
|
||||
void HostDisplayClient::CreateLayeredWindowUpdater(
|
||||
mojom::LayeredWindowUpdaterRequest request) {
|
||||
+#if defined(OS_WIN)
|
||||
if (!NeedsToUseLayerWindow(widget_)) {
|
||||
DLOG(ERROR) << "HWND shouldn't be using a layered window";
|
||||
return;
|
||||
@@ -59,7 +63,11 @@ void HostDisplayClient::CreateLayeredWindowUpdater(
|
||||
|
||||
layered_window_updater_ =
|
||||
std::make_unique<LayeredWindowUpdaterImpl>(widget_, std::move(request));
|
||||
-}
|
||||
+#else
|
||||
+ CHECK(false) << "Chromium is calling CreateLayeredWindowUpdater for non-OSR "
|
||||
+ "windows on POSIX platforms, something is wrong with "
|
||||
+ "Electron's OSR implementation.";
|
||||
#endif
|
||||
+}
|
||||
|
||||
} // namespace viz
|
||||
diff --git a/components/viz/host/host_display_client.h b/components/viz/host/host_display_client.h
|
||||
index af64385aa93f7abc7a85e1f6eec3c99134e0d2b5..011007ba451e71d46d02cb2d28f6489fe2a805ec 100644
|
||||
--- a/components/viz/host/host_display_client.h
|
||||
+++ b/components/viz/host/host_display_client.h
|
||||
@@ -30,17 +30,17 @@ class VIZ_HOST_EXPORT HostDisplayClient : public mojom::DisplayClient {
|
||||
mojom::DisplayClientPtr GetBoundPtr(
|
||||
scoped_refptr<base::SingleThreadTaskRunner> task_runner);
|
||||
|
||||
- private:
|
||||
+ protected:
|
||||
// mojom::DisplayClient implementation:
|
||||
#if defined(OS_MACOSX)
|
||||
void OnDisplayReceivedCALayerParams(
|
||||
const gfx::CALayerParams& ca_layer_params) override;
|
||||
#endif
|
||||
|
||||
-#if defined(OS_WIN)
|
||||
+ void IsOffscreen(IsOffscreenCallback callback) override;
|
||||
+
|
||||
void CreateLayeredWindowUpdater(
|
||||
mojom::LayeredWindowUpdaterRequest request) override;
|
||||
-#endif
|
||||
|
||||
mojo::Binding<mojom::DisplayClient> binding_;
|
||||
#if defined(OS_MACOSX) || defined(OS_WIN)
|
||||
diff --git a/components/viz/host/layered_window_updater_impl.cc b/components/viz/host/layered_window_updater_impl.cc
|
||||
index d3a49ed8be8dc11b86af67cdd600b05ddc0fc486..88bf86f3938b8267d731b52c8c3baa35d3128c7a 100644
|
||||
--- a/components/viz/host/layered_window_updater_impl.cc
|
||||
+++ b/components/viz/host/layered_window_updater_impl.cc
|
||||
@@ -47,7 +47,9 @@ void LayeredWindowUpdaterImpl::OnAllocatedSharedMemory(
|
||||
shm_handle.Close();
|
||||
}
|
||||
|
||||
-void LayeredWindowUpdaterImpl::Draw(DrawCallback draw_callback) {
|
||||
+void LayeredWindowUpdaterImpl::Draw(
|
||||
+ const gfx::Rect& damage_rect,
|
||||
+ DrawCallback draw_callback) {
|
||||
TRACE_EVENT0("viz", "LayeredWindowUpdaterImpl::Draw");
|
||||
|
||||
if (!canvas_) {
|
||||
diff --git a/components/viz/host/layered_window_updater_impl.h b/components/viz/host/layered_window_updater_impl.h
|
||||
index 93c52d2b928cba6e98723e19b005fb7bd7089a58..4dc645e770a2a039ed8e4ff4de555767fee34a3a 100644
|
||||
--- a/components/viz/host/layered_window_updater_impl.h
|
||||
+++ b/components/viz/host/layered_window_updater_impl.h
|
||||
@@ -33,7 +33,7 @@ class VIZ_HOST_EXPORT LayeredWindowUpdaterImpl
|
||||
void OnAllocatedSharedMemory(
|
||||
const gfx::Size& pixel_size,
|
||||
mojo::ScopedSharedBufferHandle scoped_buffer_handle) override;
|
||||
- void Draw(DrawCallback draw_callback) override;
|
||||
+ void Draw(const gfx::Rect& damage_rect, DrawCallback draw_callback) override;
|
||||
|
||||
private:
|
||||
const HWND hwnd_;
|
||||
diff --git a/components/viz/service/BUILD.gn b/components/viz/service/BUILD.gn
|
||||
index 1ac721a2781faecd0c7ee5709e8ed20b227bf298..dd7ae27ececbe2a81d9dc62f7e49dc520916d58c 100644
|
||||
--- a/components/viz/service/BUILD.gn
|
||||
+++ b/components/viz/service/BUILD.gn
|
||||
@@ -113,6 +113,8 @@ viz_component("service") {
|
||||
"display_embedder/in_process_gpu_memory_buffer_manager.h",
|
||||
"display_embedder/server_shared_bitmap_manager.cc",
|
||||
"display_embedder/server_shared_bitmap_manager.h",
|
||||
+ "display_embedder/software_output_device_proxy.cc",
|
||||
+ "display_embedder/software_output_device_proxy.h",
|
||||
"display_embedder/software_output_surface.cc",
|
||||
"display_embedder/software_output_surface.h",
|
||||
"display_embedder/viz_process_context_provider.cc",
|
||||
diff --git a/components/viz/service/display_embedder/gpu_display_provider.cc b/components/viz/service/display_embedder/gpu_display_provider.cc
|
||||
index 72e6374ccb67b625fa5936a08cc948c653d71e0e..71b1c7e16ea7a48fee3a9c17c66d5d6927c2783a 100644
|
||||
--- a/components/viz/service/display_embedder/gpu_display_provider.cc
|
||||
+++ b/components/viz/service/display_embedder/gpu_display_provider.cc
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
|
||||
#include "components/viz/service/display_embedder/skia_output_surface_impl.h"
|
||||
#include "components/viz/service/display_embedder/skia_output_surface_impl_non_ddl.h"
|
||||
+#include "components/viz/service/display_embedder/software_output_device_proxy.h"
|
||||
#include "components/viz/service/display_embedder/software_output_surface.h"
|
||||
#include "components/viz/service/display_embedder/viz_process_context_provider.h"
|
||||
#include "components/viz/service/gl/gpu_service_impl.h"
|
||||
@@ -279,6 +280,19 @@ GpuDisplayProvider::CreateSoftwareOutputDeviceForPlatform(
|
||||
if (headless_)
|
||||
return std::make_unique<SoftwareOutputDevice>();
|
||||
|
||||
+#if !defined(OS_MACOSX)
|
||||
+ DCHECK(display_client);
|
||||
+ bool offscreen = false;
|
||||
+ if (display_client->IsOffscreen(&offscreen) && offscreen) {
|
||||
+ mojom::LayeredWindowUpdaterPtr layered_window_updater;
|
||||
+ display_client->CreateLayeredWindowUpdater(
|
||||
+ mojo::MakeRequest(&layered_window_updater));
|
||||
+
|
||||
+ return std::make_unique<SoftwareOutputDeviceProxy>(
|
||||
+ std::move(layered_window_updater));
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
#if defined(OS_WIN)
|
||||
return CreateSoftwareOutputDeviceWinGpu(
|
||||
surface_handle, &output_device_backing_, display_client);
|
||||
diff --git a/components/viz/service/display_embedder/software_output_device_mac.cc b/components/viz/service/display_embedder/software_output_device_mac.cc
|
||||
index b9357082293cc55650144ccbc8bada8fe6d1cac4..b4cb07e26d1504719f80e5835c1cb5f138b9f1ab 100644
|
||||
--- a/components/viz/service/display_embedder/software_output_device_mac.cc
|
||||
+++ b/components/viz/service/display_embedder/software_output_device_mac.cc
|
||||
@@ -102,6 +102,8 @@ void SoftwareOutputDeviceMac::UpdateAndCopyBufferDamage(
|
||||
|
||||
SkCanvas* SoftwareOutputDeviceMac::BeginPaint(
|
||||
const gfx::Rect& new_damage_rect) {
|
||||
+ last_damage = new_damage_rect;
|
||||
+
|
||||
// Record the previous paint buffer.
|
||||
Buffer* previous_paint_buffer =
|
||||
buffer_queue_.empty() ? nullptr : buffer_queue_.back().get();
|
||||
@@ -184,6 +186,7 @@ void SoftwareOutputDeviceMac::EndPaint() {
|
||||
ca_layer_params.is_empty = false;
|
||||
ca_layer_params.scale_factor = scale_factor_;
|
||||
ca_layer_params.pixel_size = pixel_size_;
|
||||
+ ca_layer_params.damage = last_damage;
|
||||
ca_layer_params.io_surface_mach_port.reset(
|
||||
IOSurfaceCreateMachPort(current_paint_buffer_->io_surface));
|
||||
client_->SoftwareDeviceUpdatedCALayerParams(ca_layer_params);
|
||||
diff --git a/components/viz/service/display_embedder/software_output_device_mac.h b/components/viz/service/display_embedder/software_output_device_mac.h
|
||||
index f3867356e3d641416e00e6d115ae9ae2a0be90ab..b1d192d2b20ccb63fba07093101d745e5ffe86dd 100644
|
||||
--- a/components/viz/service/display_embedder/software_output_device_mac.h
|
||||
+++ b/components/viz/service/display_embedder/software_output_device_mac.h
|
||||
@@ -56,6 +56,7 @@ class VIZ_SERVICE_EXPORT SoftwareOutputDeviceMac : public SoftwareOutputDevice {
|
||||
void UpdateAndCopyBufferDamage(Buffer* previous_paint_buffer,
|
||||
const SkRegion& new_damage_rect);
|
||||
|
||||
+ gfx::Rect last_damage;
|
||||
gfx::Size pixel_size_;
|
||||
float scale_factor_ = 1;
|
||||
|
||||
diff --git a/components/viz/service/display_embedder/software_output_device_proxy.cc b/components/viz/service/display_embedder/software_output_device_proxy.cc
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..c784a841f74e7a6215595fd8b1166655857f3e31
|
||||
--- /dev/null
|
||||
+++ b/components/viz/service/display_embedder/software_output_device_proxy.cc
|
||||
@@ -0,0 +1,167 @@
|
||||
+// Copyright 2014 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/software_output_device_proxy.h"
|
||||
+
|
||||
+#include "base/memory/shared_memory.h"
|
||||
+#include "base/threading/thread_checker.h"
|
||||
+#include "components/viz/common/resources/resource_sizes.h"
|
||||
+#include "components/viz/service/display_embedder/output_device_backing.h"
|
||||
+#include "mojo/public/cpp/system/platform_handle.h"
|
||||
+#include "services/viz/privileged/interfaces/compositing/layered_window_updater.mojom.h"
|
||||
+#include "skia/ext/platform_canvas.h"
|
||||
+#include "third_party/skia/include/core/SkCanvas.h"
|
||||
+#include "ui/gfx/skia_util.h"
|
||||
+
|
||||
+#if defined(OS_WIN)
|
||||
+#include "skia/ext/skia_utils_win.h"
|
||||
+#include "ui/gfx/gdi_util.h"
|
||||
+#include "ui/gfx/win/hwnd_util.h"
|
||||
+#else
|
||||
+#include "mojo/public/cpp/base/shared_memory_utils.h"
|
||||
+#endif
|
||||
+
|
||||
+namespace viz {
|
||||
+
|
||||
+SoftwareOutputDeviceBase::~SoftwareOutputDeviceBase() {
|
||||
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
+ DCHECK(!in_paint_);
|
||||
+}
|
||||
+
|
||||
+void SoftwareOutputDeviceBase::Resize(const gfx::Size& viewport_pixel_size,
|
||||
+ float scale_factor) {
|
||||
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
+ DCHECK(!in_paint_);
|
||||
+
|
||||
+ if (viewport_pixel_size_ == viewport_pixel_size)
|
||||
+ return;
|
||||
+
|
||||
+ viewport_pixel_size_ = viewport_pixel_size;
|
||||
+ ResizeDelegated();
|
||||
+}
|
||||
+
|
||||
+SkCanvas* SoftwareOutputDeviceBase::BeginPaint(
|
||||
+ const gfx::Rect& damage_rect) {
|
||||
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
+ DCHECK(!in_paint_);
|
||||
+
|
||||
+ damage_rect_ = damage_rect;
|
||||
+ in_paint_ = true;
|
||||
+ return BeginPaintDelegated();
|
||||
+}
|
||||
+
|
||||
+void SoftwareOutputDeviceBase::EndPaint() {
|
||||
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
+ DCHECK(in_paint_);
|
||||
+
|
||||
+ in_paint_ = false;
|
||||
+
|
||||
+ gfx::Rect intersected_damage_rect = damage_rect_;
|
||||
+ intersected_damage_rect.Intersect(gfx::Rect(viewport_pixel_size_));
|
||||
+ if (intersected_damage_rect.IsEmpty())
|
||||
+ return;
|
||||
+
|
||||
+ EndPaintDelegated(intersected_damage_rect);
|
||||
+}
|
||||
+
|
||||
+SoftwareOutputDeviceProxy::~SoftwareOutputDeviceProxy() = default;
|
||||
+
|
||||
+SoftwareOutputDeviceProxy::SoftwareOutputDeviceProxy(
|
||||
+ mojom::LayeredWindowUpdaterPtr layered_window_updater)
|
||||
+ : layered_window_updater_(std::move(layered_window_updater)) {
|
||||
+ DCHECK(layered_window_updater_.is_bound());
|
||||
+}
|
||||
+
|
||||
+void SoftwareOutputDeviceProxy::OnSwapBuffers(
|
||||
+ base::OnceClosure swap_ack_callback) {
|
||||
+ DCHECK(swap_ack_callback_.is_null());
|
||||
+
|
||||
+ // We aren't waiting on DrawAck() and can immediately run the callback.
|
||||
+ if (!waiting_on_draw_ack_) {
|
||||
+ task_runner_->PostTask(FROM_HERE, std::move(swap_ack_callback));
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ swap_ack_callback_ = std::move(swap_ack_callback);
|
||||
+}
|
||||
+
|
||||
+void SoftwareOutputDeviceProxy::ResizeDelegated() {
|
||||
+ canvas_.reset();
|
||||
+
|
||||
+ size_t required_bytes;
|
||||
+ if (!ResourceSizes::MaybeSizeInBytes(
|
||||
+ viewport_pixel_size_, ResourceFormat::RGBA_8888, &required_bytes)) {
|
||||
+ DLOG(ERROR) << "Invalid viewport size " << viewport_pixel_size_.ToString();
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ #if defined(WIN32)
|
||||
+ base::SharedMemory shm;
|
||||
+ if (!shm.CreateAnonymous(required_bytes)) {
|
||||
+ DLOG(ERROR) << "Failed to allocate " << required_bytes << " bytes";
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ canvas_ = skia::CreatePlatformCanvasWithSharedSection(
|
||||
+ viewport_pixel_size_.width(), viewport_pixel_size_.height(), false,
|
||||
+ shm.handle().GetHandle(), skia::CRASH_ON_FAILURE);
|
||||
+
|
||||
+ // Transfer handle ownership to the browser process.
|
||||
+ mojo::ScopedSharedBufferHandle scoped_handle = mojo::WrapSharedMemoryHandle(
|
||||
+ shm.TakeHandle(), required_bytes,
|
||||
+ mojo::UnwrappedSharedMemoryHandleProtection::kReadWrite);
|
||||
+ #else
|
||||
+ auto shm = mojo::CreateWritableSharedMemoryRegion(required_bytes);
|
||||
+ if (!shm.IsValid()) {
|
||||
+ DLOG(ERROR) << "Failed to allocate " << required_bytes << " bytes";
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ shm_mapping_ = shm.Map();
|
||||
+ if (!shm_mapping_.IsValid()) {
|
||||
+ DLOG(ERROR) << "Failed to map " << required_bytes << " bytes";
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ canvas_ = skia::CreatePlatformCanvasWithPixels(
|
||||
+ viewport_pixel_size_.width(), viewport_pixel_size_.height(), false,
|
||||
+ static_cast<uint8_t*>(shm_mapping_.memory()), skia::CRASH_ON_FAILURE);
|
||||
+
|
||||
+ mojo::ScopedSharedBufferHandle scoped_handle =
|
||||
+ mojo::WrapWritableSharedMemoryRegion(std::move(shm));
|
||||
+ #endif
|
||||
+
|
||||
+ layered_window_updater_->OnAllocatedSharedMemory(viewport_pixel_size_,
|
||||
+ std::move(scoped_handle));
|
||||
+}
|
||||
+
|
||||
+SkCanvas* SoftwareOutputDeviceProxy::BeginPaintDelegated() {
|
||||
+ return canvas_.get();
|
||||
+}
|
||||
+
|
||||
+void SoftwareOutputDeviceProxy::EndPaintDelegated(
|
||||
+ const gfx::Rect& damage_rect) {
|
||||
+ DCHECK(!waiting_on_draw_ack_);
|
||||
+
|
||||
+ if (!canvas_)
|
||||
+ return;
|
||||
+
|
||||
+ layered_window_updater_->Draw(damage_rect, base::BindOnce(
|
||||
+ &SoftwareOutputDeviceProxy::DrawAck, base::Unretained(this)));
|
||||
+ waiting_on_draw_ack_ = true;
|
||||
+
|
||||
+ TRACE_EVENT_ASYNC_BEGIN0("viz", "SoftwareOutputDeviceProxy::Draw", this);
|
||||
+}
|
||||
+
|
||||
+void SoftwareOutputDeviceProxy::DrawAck() {
|
||||
+ DCHECK(waiting_on_draw_ack_);
|
||||
+ DCHECK(!swap_ack_callback_.is_null());
|
||||
+
|
||||
+ TRACE_EVENT_ASYNC_END0("viz", "SoftwareOutputDeviceProxy::Draw", this);
|
||||
+
|
||||
+ waiting_on_draw_ack_ = false;
|
||||
+ std::move(swap_ack_callback_).Run();
|
||||
+}
|
||||
+
|
||||
+} // namespace viz
|
||||
diff --git a/components/viz/service/display_embedder/software_output_device_proxy.h b/components/viz/service/display_embedder/software_output_device_proxy.h
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..01e1e2f0860faa1afe42c342c8905a7f838bd363
|
||||
--- /dev/null
|
||||
+++ b/components/viz/service/display_embedder/software_output_device_proxy.h
|
||||
@@ -0,0 +1,88 @@
|
||||
+// Copyright 2014 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_SOFTWARE_OUTPUT_DEVICE_PROXY_H_
|
||||
+#define COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SOFTWARE_OUTPUT_DEVICE_PROXY_H_
|
||||
+
|
||||
+#if defined(OS_WIN)
|
||||
+#include <windows.h>
|
||||
+#endif
|
||||
+
|
||||
+#include <memory>
|
||||
+
|
||||
+#include "components/viz/host/host_display_client.h"
|
||||
+#include "components/viz/service/display/software_output_device.h"
|
||||
+#include "components/viz/service/viz_service_export.h"
|
||||
+#include "services/viz/privileged/interfaces/compositing/display_private.mojom.h"
|
||||
+#include "services/viz/privileged/interfaces/compositing/layered_window_updater.mojom.h"
|
||||
+
|
||||
+namespace viz {
|
||||
+
|
||||
+// Shared base class for SoftwareOutputDevice implementations.
|
||||
+class SoftwareOutputDeviceBase : public SoftwareOutputDevice {
|
||||
+ public:
|
||||
+ SoftwareOutputDeviceBase() = default;
|
||||
+ ~SoftwareOutputDeviceBase() override;
|
||||
+
|
||||
+ // SoftwareOutputDevice implementation.
|
||||
+ void Resize(const gfx::Size& viewport_pixel_size,
|
||||
+ float scale_factor) override;
|
||||
+ SkCanvas* BeginPaint(const gfx::Rect& damage_rect) override;
|
||||
+ void EndPaint() override;
|
||||
+
|
||||
+ // Called from Resize() if |viewport_pixel_size_| has changed.
|
||||
+ virtual void ResizeDelegated() = 0;
|
||||
+
|
||||
+ // Called from BeginPaint() and should return an SkCanvas.
|
||||
+ virtual SkCanvas* BeginPaintDelegated() = 0;
|
||||
+
|
||||
+ // Called from EndPaint() if there is damage.
|
||||
+ virtual void EndPaintDelegated(const gfx::Rect& damage_rect) = 0;
|
||||
+
|
||||
+ private:
|
||||
+ bool in_paint_ = false;
|
||||
+
|
||||
+ THREAD_CHECKER(thread_checker_);
|
||||
+
|
||||
+ DISALLOW_COPY_AND_ASSIGN(SoftwareOutputDeviceBase);
|
||||
+};
|
||||
+
|
||||
+// SoftwareOutputDevice implementation that draws indirectly. An implementation
|
||||
+// of mojom::LayeredWindowUpdater in the browser process handles the actual
|
||||
+// drawing. Pixel backing is in SharedMemory so no copying between processes
|
||||
+// is required.
|
||||
+class SoftwareOutputDeviceProxy : public SoftwareOutputDeviceBase {
|
||||
+ public:
|
||||
+ explicit SoftwareOutputDeviceProxy(
|
||||
+ mojom::LayeredWindowUpdaterPtr layered_window_updater);
|
||||
+ ~SoftwareOutputDeviceProxy() override;
|
||||
+
|
||||
+ // SoftwareOutputDevice implementation.
|
||||
+ void OnSwapBuffers(base::OnceClosure swap_ack_callback) override;
|
||||
+
|
||||
+ // SoftwareOutputDeviceBase implementation.
|
||||
+ void ResizeDelegated() override;
|
||||
+ SkCanvas* BeginPaintDelegated() override;
|
||||
+ void EndPaintDelegated(const gfx::Rect& rect) override;
|
||||
+
|
||||
+ private:
|
||||
+ // Runs |swap_ack_callback_| after draw has happened.
|
||||
+ void DrawAck();
|
||||
+
|
||||
+ mojom::LayeredWindowUpdaterPtr layered_window_updater_;
|
||||
+
|
||||
+ std::unique_ptr<SkCanvas> canvas_;
|
||||
+ bool waiting_on_draw_ack_ = false;
|
||||
+ base::OnceClosure swap_ack_callback_;
|
||||
+
|
||||
+#if !defined(WIN32)
|
||||
+ base::WritableSharedMemoryMapping shm_mapping_;
|
||||
+#endif
|
||||
+
|
||||
+ DISALLOW_COPY_AND_ASSIGN(SoftwareOutputDeviceProxy);
|
||||
+};
|
||||
+
|
||||
+} // namespace viz
|
||||
+
|
||||
+#endif // COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SOFTWARE_OUTPUT_DEVICE_PROXY_H_
|
||||
diff --git a/components/viz/service/display_embedder/software_output_device_win.cc b/components/viz/service/display_embedder/software_output_device_win.cc
|
||||
index a339eaa4dc9ccec292b3df9f31adf1ad45119a77..33146bbe7bb01fbe24cea10d79cad2748dd04a24 100644
|
||||
--- a/components/viz/service/display_embedder/software_output_device_win.cc
|
||||
+++ b/components/viz/service/display_embedder/software_output_device_win.cc
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "components/viz/common/display/use_layered_window.h"
|
||||
#include "components/viz/common/resources/resource_sizes.h"
|
||||
#include "components/viz/service/display_embedder/output_device_backing.h"
|
||||
+#include "components/viz/service/display_embedder/software_output_device_proxy.h"
|
||||
#include "mojo/public/cpp/system/platform_handle.h"
|
||||
#include "services/viz/privileged/interfaces/compositing/layered_window_updater.mojom.h"
|
||||
#include "skia/ext/platform_canvas.h"
|
||||
@@ -321,7 +322,7 @@ void SoftwareOutputDeviceWinProxy::EndPaintDelegated(
|
||||
if (!canvas_)
|
||||
return;
|
||||
|
||||
- layered_window_updater_->Draw(base::BindOnce(
|
||||
+ layered_window_updater_->Draw(damage_rect, base::BindOnce(
|
||||
&SoftwareOutputDeviceWinProxy::DrawAck, base::Unretained(this)));
|
||||
waiting_on_draw_ack_ = true;
|
||||
|
||||
@@ -362,8 +363,13 @@ std::unique_ptr<SoftwareOutputDevice> CreateSoftwareOutputDeviceWinGpu(
|
||||
display_client->CreateLayeredWindowUpdater(
|
||||
mojo::MakeRequest(&layered_window_updater));
|
||||
|
||||
- return std::make_unique<SoftwareOutputDeviceWinProxy>(
|
||||
- hwnd, std::move(layered_window_updater));
|
||||
+ bool offscreen = false;
|
||||
+ if (display_client->IsOffscreen(&offscreen) && offscreen)
|
||||
+ return std::make_unique<SoftwareOutputDeviceProxy>(
|
||||
+ std::move(layered_window_updater));
|
||||
+ else
|
||||
+ return std::make_unique<SoftwareOutputDeviceWinProxy>(
|
||||
+ hwnd, std::move(layered_window_updater));
|
||||
} else {
|
||||
return std::make_unique<SoftwareOutputDeviceWinDirect>(hwnd, backing);
|
||||
}
|
||||
diff --git a/services/viz/privileged/interfaces/compositing/display_private.mojom b/services/viz/privileged/interfaces/compositing/display_private.mojom
|
||||
index 4c29f4ec2cde99749d4642928ff52ad3d4842f4a..5db220422bbc0ec6384c98681c245502a6442d6d 100644
|
||||
--- a/services/viz/privileged/interfaces/compositing/display_private.mojom
|
||||
+++ b/services/viz/privileged/interfaces/compositing/display_private.mojom
|
||||
@@ -58,12 +58,14 @@ interface DisplayPrivate {
|
||||
};
|
||||
|
||||
interface DisplayClient {
|
||||
+ [Sync]
|
||||
+ IsOffscreen() => (bool success);
|
||||
+
|
||||
[EnableIf=is_mac]
|
||||
OnDisplayReceivedCALayerParams(gfx.mojom.CALayerParams ca_layer_params);
|
||||
|
||||
// Creates a LayeredWindowUpdater implementation to draw into a layered
|
||||
// window.
|
||||
- [EnableIf=is_win]
|
||||
CreateLayeredWindowUpdater(LayeredWindowUpdater& layered_window_updater);
|
||||
|
||||
// Notifies that a swap has occurred and provides information about the pixel
|
||||
diff --git a/services/viz/privileged/interfaces/compositing/layered_window_updater.mojom b/services/viz/privileged/interfaces/compositing/layered_window_updater.mojom
|
||||
index 360cab3eee4c5189a55269d76daa1d78a98ed3d3..6834242f23d27fd6d428c2cd6040206a79d5097b 100644
|
||||
--- a/services/viz/privileged/interfaces/compositing/layered_window_updater.mojom
|
||||
+++ b/services/viz/privileged/interfaces/compositing/layered_window_updater.mojom
|
||||
@@ -22,5 +22,5 @@ interface LayeredWindowUpdater {
|
||||
// Draws to the HWND by copying pixels from shared memory. Callback must be
|
||||
// called after draw operation is complete to signal shared memory can be
|
||||
// modified.
|
||||
- Draw() => ();
|
||||
+ Draw(gfx.mojom.Rect damage_rect) => ();
|
||||
};
|
||||
diff --git a/ui/compositor/compositor.h b/ui/compositor/compositor.h
|
||||
index 29784c677f4be6e4fd7cfb298ab3554d22e1beaa..5d7da6481ebedb706c1dd31de1f7dfe4735433e8 100644
|
||||
--- a/ui/compositor/compositor.h
|
||||
+++ b/ui/compositor/compositor.h
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "components/viz/common/frame_sinks/begin_frame_args.h"
|
||||
#include "components/viz/common/surfaces/frame_sink_id.h"
|
||||
#include "components/viz/common/surfaces/local_surface_id_allocation.h"
|
||||
+#include "components/viz/host/host_display_client.h"
|
||||
#include "components/viz/host/host_frame_sink_client.h"
|
||||
#include "third_party/skia/include/core/SkColor.h"
|
||||
#include "third_party/skia/include/core/SkMatrix44.h"
|
||||
@@ -193,6 +194,15 @@ class COMPOSITOR_EXPORT ContextFactory {
|
||||
virtual bool SyncTokensRequiredForDisplayCompositor() = 0;
|
||||
};
|
||||
|
||||
+class COMPOSITOR_EXPORT CompositorDelegate {
|
||||
+ public:
|
||||
+ virtual std::unique_ptr<viz::HostDisplayClient> CreateHostDisplayClient(
|
||||
+ ui::Compositor* compositor) = 0;
|
||||
+
|
||||
+ 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
|
||||
@@ -235,6 +245,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
|
||||
@@ -458,6 +471,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;
|
||||
|
||||
diff --git a/ui/compositor/host/host_context_factory_private.cc b/ui/compositor/host/host_context_factory_private.cc
|
||||
index 8297e1aabe3b29698a965407e24d1e987be679d3..a78d455e99eb27730b6ac42cd5fd9469caa4a7de 100644
|
||||
--- a/ui/compositor/host/host_context_factory_private.cc
|
||||
+++ b/ui/compositor/host/host_context_factory_private.cc
|
||||
@@ -70,8 +70,12 @@ void HostContextFactoryPrivate::ConfigureCompositor(
|
||||
mojo::MakeRequest(&root_params->compositor_frame_sink_client);
|
||||
root_params->display_private =
|
||||
mojo::MakeRequest(&compositor_data.display_private);
|
||||
- compositor_data.display_client =
|
||||
- std::make_unique<viz::HostDisplayClient>(compositor->widget());
|
||||
+ if (compositor->delegate())
|
||||
+ compositor_data.display_client = compositor->delegate()->CreateHostDisplayClient(
|
||||
+ compositor);
|
||||
+ else
|
||||
+ compositor_data.display_client =
|
||||
+ std::make_unique<viz::HostDisplayClient>(compositor->widget());
|
||||
root_params->display_client =
|
||||
compositor_data.display_client->GetBoundPtr(resize_task_runner_)
|
||||
.PassInterface();
|
||||
diff --git a/ui/gfx/ca_layer_params.h b/ui/gfx/ca_layer_params.h
|
||||
index 4014e64a75da88cf66c02e8adb71171c2666cab7..25e57784e1a1ffc546b003daa4cd0059c468432f 100644
|
||||
--- a/ui/gfx/ca_layer_params.h
|
||||
+++ b/ui/gfx/ca_layer_params.h
|
||||
@@ -6,6 +6,7 @@
|
||||
#define UI_GFX_CA_LAYER_PARAMS_H_
|
||||
|
||||
#include "build/build_config.h"
|
||||
+#include "ui/gfx/geometry/rect.h"
|
||||
#include "ui/gfx/geometry/size.h"
|
||||
#include "ui/gfx/gfx_export.h"
|
||||
|
||||
@@ -41,6 +42,8 @@ struct GFX_EXPORT CALayerParams {
|
||||
gfx::ScopedRefCountedIOSurfaceMachPort io_surface_mach_port;
|
||||
#endif
|
||||
|
||||
+ gfx::Rect damage;
|
||||
+
|
||||
// The geometry of the frame.
|
||||
gfx::Size pixel_size;
|
||||
float scale_factor = 1.f;
|
||||
diff --git a/ui/gfx/mojo/ca_layer_params.mojom b/ui/gfx/mojo/ca_layer_params.mojom
|
||||
index 7bf735643541b18bafffe645d3ff37e96caa4dea..f7eaf10ffd665789f10a587142fac0c0c79b9798 100644
|
||||
--- a/ui/gfx/mojo/ca_layer_params.mojom
|
||||
+++ b/ui/gfx/mojo/ca_layer_params.mojom
|
||||
@@ -18,5 +18,6 @@ struct CALayerParams {
|
||||
bool is_empty;
|
||||
CALayerContent content;
|
||||
gfx.mojom.Size pixel_size;
|
||||
+ gfx.mojom.Rect damage;
|
||||
float scale_factor;
|
||||
};
|
||||
diff --git a/ui/gfx/mojo/ca_layer_params_struct_traits.cc b/ui/gfx/mojo/ca_layer_params_struct_traits.cc
|
||||
index dd553996b5c6ff5ec0c210a020a18a6a843b8aae..26d1e0bda2640052d42ea4e691c3df73074dea08 100644
|
||||
--- a/ui/gfx/mojo/ca_layer_params_struct_traits.cc
|
||||
+++ b/ui/gfx/mojo/ca_layer_params_struct_traits.cc
|
||||
@@ -52,6 +52,9 @@ bool StructTraits<gfx::mojom::CALayerParamsDataView, gfx::CALayerParams>::Read(
|
||||
if (!data.ReadPixelSize(&out->pixel_size))
|
||||
return false;
|
||||
|
||||
+ if (!data.ReadDamage(&out->damage))
|
||||
+ return false;
|
||||
+
|
||||
out->scale_factor = data.scale_factor();
|
||||
return true;
|
||||
}
|
||||
diff --git a/ui/gfx/mojo/ca_layer_params_struct_traits.h b/ui/gfx/mojo/ca_layer_params_struct_traits.h
|
||||
index 94127a0d5b50b052318e9e5a360755fe771f87e9..348fa26c5c95a13d1ddd0ff2545aca3a35841a77 100644
|
||||
--- a/ui/gfx/mojo/ca_layer_params_struct_traits.h
|
||||
+++ b/ui/gfx/mojo/ca_layer_params_struct_traits.h
|
||||
@@ -20,6 +20,10 @@ struct StructTraits<gfx::mojom::CALayerParamsDataView, gfx::CALayerParams> {
|
||||
return ca_layer_params.pixel_size;
|
||||
}
|
||||
|
||||
+ static gfx::Rect damage(const gfx::CALayerParams& ca_layer_params) {
|
||||
+ return ca_layer_params.damage;
|
||||
+ }
|
||||
+
|
||||
static float scale_factor(const gfx::CALayerParams& ca_layer_params) {
|
||||
return ca_layer_params.scale_factor;
|
||||
}
|
|
@ -3702,14 +3702,18 @@ describe('BrowserWindow module', () => {
|
|||
w.webContents.once('paint', function (event, rect, data) {
|
||||
assert.notStrictEqual(data.length, 0)
|
||||
const size = data.getSize()
|
||||
const scale = process.platform === 'darwin' ? devicePixelRatio : 1
|
||||
assertWithinDelta(size.width, 100 * scale, 2, 'width')
|
||||
assertWithinDelta(size.height, 100 * scale, 2, 'height')
|
||||
assertWithinDelta(size.width, 100 * devicePixelRatio, 2, 'width')
|
||||
assertWithinDelta(size.height, 100 * devicePixelRatio, 2, 'height')
|
||||
done()
|
||||
})
|
||||
w.loadFile(path.join(fixtures, 'api', 'offscreen-rendering.html'))
|
||||
})
|
||||
|
||||
it('does not crash after navigation', () => {
|
||||
w.webContents.loadURL('about:blank')
|
||||
w.loadFile(path.join(fixtures, 'api', 'offscreen-rendering.html'))
|
||||
})
|
||||
|
||||
describe('window.webContents.isOffscreen()', () => {
|
||||
it('is true for offscreen type', () => {
|
||||
w.loadFile(path.join(fixtures, 'api', 'offscreen-rendering.html'))
|
||||
|
|
Загрузка…
Ссылка в новой задаче