gpu acclereted osr added

This commit is contained in:
gellert 2016-07-18 16:16:23 +02:00
parent 6e25aea49f
commit 50dc71d1c2
12 changed files with 812 additions and 198 deletions

View file

@ -1194,12 +1194,30 @@ void WebContents::BeginFrameSubscription(mate::Arguments* args) {
const auto view = web_contents()->GetRenderWidgetHostView();
if (view) {
std::unique_ptr<FrameSubscriber> frame_subscriber(new FrameSubscriber(
isolate(), view, callback, only_dirty));
view->BeginFrameSubscription(std::move(frame_subscriber));
// std::unique_ptr<FrameSubscriber> frame_subscriber(new FrameSubscriber(
// isolate(), view, callback, only_dirty));
// view->BeginFrameSubscription(std::move(frame_subscriber));
paint_isolate_ = args->isolate();
auto v = static_cast<OffScreenWindow *>(view);
paint_callback_ = base::Bind(&WebContents::OnPaint,
base::Unretained(this));
v->SetPaintCallback(&paint_callback_);
}
}
void WebContents::OnPaint(
const gfx::Rect& damage_rect,
int bitmap_width,
int bitmap_height,
void* bitmap_pixels) {
v8::MaybeLocal<v8::Object> buffer = node::Buffer::New(paint_isolate_
, (char *)bitmap_pixels, sizeof(bitmap_pixels));
Emit("paint", damage_rect, bitmap_width, bitmap_height, buffer.ToLocalChecked());
}
void WebContents::EndFrameSubscription() {
const auto view = web_contents()->GetRenderWidgetHostView();
if (view)

View file

@ -18,6 +18,8 @@
#include "native_mate/handle.h"
#include "ui/gfx/image/image.h"
#include "atom/browser/osr_window.h"
namespace blink {
struct WebDeviceEmulationParams;
}
@ -141,6 +143,7 @@ class WebContents : public mate::TrackableObject<WebContents>,
// Subscribe to the frame updates.
void BeginFrameSubscription(mate::Arguments* args);
void EndFrameSubscription();
void OnPaint(const gfx::Rect&, int, int, void*);
// Dragging native items.
void StartDrag(const mate::Dictionary& item, mate::Arguments* args);
@ -279,6 +282,8 @@ class WebContents : public mate::TrackableObject<WebContents>,
private:
AtomBrowserContext* GetBrowserContext() const;
OffScreenWindow::OnPaintCallback paint_callback_;
uint32_t GetNextRequestId() {
return ++request_id_;
}
@ -299,6 +304,8 @@ class WebContents : public mate::TrackableObject<WebContents>,
v8::Global<v8::Value> devtools_web_contents_;
v8::Global<v8::Value> debugger_;
v8::Isolate* paint_isolate_;
std::unique_ptr<WebViewGuestDelegate> guest_delegate_;
// The host webcontents that may contain this webcontents.

View file

@ -74,7 +74,8 @@ bool FrameSubscriber::ShouldCaptureFrame(
base::Bind(&FrameSubscriber::ReadbackResultAsBitmap,
base::Unretained(this)));
surface->RequestCopyOfOutput(std::move(request));
// surface->RequestCopyOfOutput(std::move(request));
std::cout << request.get() << surface << std::endl;
return false;
}

View file

@ -191,11 +191,12 @@ void CommonWebContentsDelegate::InitWithWebContents(
content::WebContentsImpl* impl =
reinterpret_cast<content::WebContentsImpl*>(web_contents);
impl->SetView(new OffScreenWebContentsView);
std::cout << "end" << std::endl;
// Create InspectableWebContents.
/*web_contents_.reset(brightray::InspectableWebContents::Create(web_contents));
web_contents_->SetDelegate(this);*/
web_contents_.reset(brightray::InspectableWebContents::Create(web_contents));
web_contents_->SetDelegate(this);
impl->SetView(new OffScreenWebContentsView);
std::cout << "end" << std::endl;
}

View file

@ -171,9 +171,9 @@ class NativeWindowViews : public NativeWindow,
content::WebContents*,
const content::NativeWebKeyboardEvent& event) override;
// views::View:
gfx::Size GetMinimumSize() override;
gfx::Size GetMaximumSize() override;
// // views::View:
// gfx::Size GetMinimumSize() const override;
// gfx::Size GetMaximumSize() const override;
bool AcceleratorPressed(const ui::Accelerator& accelerator) override;
// Register accelerators supported by the menu model.

View file

@ -4,6 +4,7 @@
#include "atom/browser/osr_window.h"
#include "third_party/WebKit/public/platform/WebScreenInfo.h"
#include "content/browser/compositor/gl_helper.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_delegate.h"
#include "content/public/browser/render_widget_host_view_frame_subscriber.h"
@ -24,6 +25,31 @@
#include "third_party/skia/include/core/SkSurface.h"
#include "third_party/skia/include/core/SkPixmap.h"
#include "cc/output/output_surface_client.h"
#include "cc/output/copy_output_request.h"
#include "base/callback_helpers.h"
#include "base/location.h"
#include "base/logging.h"
#include "content/public/browser/browser_thread.h"
#include "cc/scheduler/delay_based_time_source.h"
// const float kDefaultScaleFactor = 1.0;
// The maximum number of retry counts if frame capture fails.
const int kFrameRetryLimit = 2;
// When accelerated compositing is enabled and a widget resize is pending,
// we delay further resizes of the UI. The following constant is the maximum
// length of time that we should delay further UI resizes while waiting for a
// resized frame from a renderer.
// const int kResizeLockTimeoutMs = 67;
#define CEF_UIT content::BrowserThread::UI
#define CEF_POST_TASK(id, task) \
content::BrowserThread::PostTask(id, FROM_HERE, task)
#define CEF_POST_DELAYED_TASK(id, task, delay_ms) \
content::BrowserThread::PostDelayedTask(id, FROM_HERE, task, \
base::TimeDelta::FromMilliseconds(delay_ms))
namespace atom {
@ -166,10 +192,21 @@ void OffScreenWebContentsView::SetOverscrollControllerEnabled(bool enabled){
std::cout << "SetOverscrollControllerEnabled" << std::endl;
}
#if defined(OS_MACOSX)
void OffScreenWebContentsView::SetAllowOtherViews(bool allow) {
}
bool OffScreenWebContentsView::GetAllowOtherViews() const {
return false;
}
bool OffScreenWebContentsView::IsEventTracking() const {
return false;
}
void OffScreenWebContentsView::CloseTabAfterEventTracking() {
}
#endif // defined(OS_MACOSX)
OffScreenOutputDevice::OffScreenOutputDevice() {
std::cout << "OffScreenOutputDevice" << std::endl;
@ -215,99 +252,6 @@ SkCanvas* OffScreenOutputDevice::BeginPaint(const gfx::Rect& damage_rect) {
return canvas_.get();
}
void OffScreenOutputDevice::saveSkBitmapToBMPFile(const SkBitmap& skBitmap, const char* path){
typedef unsigned char UINT8;
typedef signed char SINT8;
typedef unsigned short UINT16;
typedef signed short SINT16;
typedef unsigned int UINT32;
typedef signed int SINT32;
struct BMP_FILEHDR // BMP file header
{
UINT32 bfSize; // size of file
UINT16 bfReserved1;
UINT16 bfReserved2;
UINT32 bfOffBits; // pointer to the pixmap bits
};
struct BMP_INFOHDR // BMP information header
{
UINT32 biSize; // size of this struct
UINT32 biWidth; // pixmap width
UINT32 biHeight; // pixmap height
UINT16 biPlanes; // should be 1
UINT16 biBitCount; // number of bits per pixel
UINT32 biCompression; // compression method
UINT32 biSizeImage; // size of image
UINT32 biXPelsPerMeter; // horizontal resolution
UINT32 biYPelsPerMeter; // vertical resolution
UINT32 biClrUsed; // number of colors used
UINT32 biClrImportant; // number of important colors
};
#define BitmapColorGetA(color) (((color) >> 24) & 0xFF)
#define BitmapColorGetR(color) (((color) >> 16) & 0xFF)
#define BitmapColorGetG(color) (((color) >> 8) & 0xFF)
#define BitmapColorGetB(color) (((color) >> 0) & 0xFF)
int bmpWidth = skBitmap.width();
int bmpHeight = skBitmap.height();
int stride = skBitmap.rowBytes();
char* m_pmap = (char*)skBitmap.getPixels();
//virtual PixelFormat& GetPixelFormat() =0; //assume pf is ARGB;
FILE* fp = fopen(path, "wb");
if(!fp){
printf("saveSkBitmapToBMPFile: fopen %s Error!\n", path);
}
SINT32 bpl=bmpWidth*4;
// BMP file header.
BMP_FILEHDR fhdr;
fputc('B', fp);
fputc('M', fp);
fhdr.bfReserved1=fhdr.bfReserved2=0;
fhdr.bfOffBits=14+40; // File header size + header size.
fhdr.bfSize=fhdr.bfOffBits+bpl*bmpHeight;
fwrite(&fhdr, 1, 12, fp);
// BMP header.
BMP_INFOHDR bhdr;
bhdr.biSize=40;
bhdr.biBitCount=32;
bhdr.biCompression=0; // RGB Format.
bhdr.biPlanes=1;
bhdr.biWidth=bmpWidth;
bhdr.biHeight=bmpHeight;
bhdr.biClrImportant=0;
bhdr.biClrUsed=0;
bhdr.biXPelsPerMeter=2384;
bhdr.biYPelsPerMeter=2384;
bhdr.biSizeImage=bpl*bmpHeight;
fwrite(&bhdr, 1, 40, fp);
// BMP data.
//for(UINT32 y=0; y<m_height; y++)
for(SINT32 y=bmpHeight-1; y>=0; y--)
{
SINT32 base=y*stride;
for(SINT32 x=0; x<(SINT32)bmpWidth; x++)
{
UINT32 i=base+x*4;
UINT32 pixelData = *(UINT32*)(m_pmap+i);
UINT8 b1=BitmapColorGetB(pixelData);
UINT8 g1=BitmapColorGetG(pixelData);
UINT8 r1=BitmapColorGetR(pixelData);
UINT8 a1=BitmapColorGetA(pixelData);
r1=r1*a1/255;
g1=g1*a1/255;
b1=b1*a1/255;
UINT32 temp=(a1<<24)|(r1<<16)|(g1<<8)|b1;//a bmp pixel in little endian is B、G、R、A
fwrite(&temp, 4, 1, fp);
}
}
fflush(fp);
fclose(fp);
}
void OffScreenOutputDevice::EndPaint() {
std::cout << "EndPaint" << std::endl;
@ -322,19 +266,351 @@ void OffScreenOutputDevice::EndPaint() {
//saveSkBitmapToBMPFile(*(bitmap_.get()), "test.bmp");
uint8_t* pixels = reinterpret_cast<uint8_t*>(bitmap_->getPixels());
for (int i = 0; i<4; i++) {
for (int i = 0; i<16; i++) {
int x = static_cast<int>(pixels[i]);
std::cout << std::hex << x << std::dec << std::endl;
}
}
// Used for managing copy requests when GPU compositing is enabled. Based on
// RendererOverridesHandler::InnerSwapCompositorFrame and
// DelegatedFrameHost::CopyFromCompositingSurface.
class CefCopyFrameGenerator {
public:
CefCopyFrameGenerator(int frame_rate_threshold_ms,
OffScreenWindow* view)
: frame_rate_threshold_ms_(frame_rate_threshold_ms),
view_(view),
frame_pending_(false),
frame_in_progress_(false),
frame_retry_count_(0),
weak_ptr_factory_(this) {
}
void GenerateCopyFrame(
bool force_frame,
const gfx::Rect& damage_rect) {
if (force_frame && !frame_pending_)
frame_pending_ = true;
// No frame needs to be generated at this time.
if (!frame_pending_)
return;
// Keep track of |damage_rect| for when the next frame is generated.
if (!damage_rect.IsEmpty())
pending_damage_rect_.Union(damage_rect);
// Don't attempt to generate a frame while one is currently in-progress.
if (frame_in_progress_)
return;
frame_in_progress_ = true;
// Don't exceed the frame rate threshold.
const int64_t frame_rate_delta =
(base::TimeTicks::Now() - frame_start_time_).InMilliseconds();
if (frame_rate_delta < frame_rate_threshold_ms_) {
// Generate the frame after the necessary time has passed.
CEF_POST_DELAYED_TASK(CEF_UIT,
base::Bind(&CefCopyFrameGenerator::InternalGenerateCopyFrame,
weak_ptr_factory_.GetWeakPtr()),
frame_rate_threshold_ms_ - frame_rate_delta);
return;
}
InternalGenerateCopyFrame();
}
bool frame_pending() const { return frame_pending_; }
void set_frame_rate_threshold_ms(int frame_rate_threshold_ms) {
frame_rate_threshold_ms_ = frame_rate_threshold_ms;
}
private:
void InternalGenerateCopyFrame() {
frame_pending_ = false;
frame_start_time_ = base::TimeTicks::Now();
if (!view_->render_widget_host())
return;
const gfx::Rect damage_rect = pending_damage_rect_;
pending_damage_rect_.SetRect(0, 0, 0, 0);
// The below code is similar in functionality to
// DelegatedFrameHost::CopyFromCompositingSurface but we reuse the same
// SkBitmap in the GPU codepath and avoid scaling where possible.
std::unique_ptr<cc::CopyOutputRequest> request =
cc::CopyOutputRequest::CreateRequest(base::Bind(
&CefCopyFrameGenerator::CopyFromCompositingSurfaceHasResult,
weak_ptr_factory_.GetWeakPtr(),
gfx::Rect(view_->GetPhysicalBackingSize())));
// request->set_area(gfx::Rect(view_->GetPhysicalBackingSize()));
view_->DelegatedFrameHostGetLayer()->RequestCopyOfOutput(
std::move(request));
}
void CopyFromCompositingSurfaceHasResult(
const gfx::Rect& damage_rect,
std::unique_ptr<cc::CopyOutputResult> result) {
std::cout << "has result" << std::endl;
if (result->IsEmpty() || result->size().IsEmpty() ||
!view_->render_widget_host()) {
OnCopyFrameCaptureFailure(damage_rect);
return;
}
if (result->HasTexture()) {
PrepareTextureCopyOutputResult(damage_rect, std::move(result));
return;
}
DCHECK(result->HasBitmap());
PrepareBitmapCopyOutputResult(damage_rect, std::move(result));
}
void PrepareTextureCopyOutputResult(
const gfx::Rect& damage_rect,
std::unique_ptr<cc::CopyOutputResult> result) {
DCHECK(result->HasTexture());
base::ScopedClosureRunner scoped_callback_runner(
base::Bind(&CefCopyFrameGenerator::OnCopyFrameCaptureFailure,
weak_ptr_factory_.GetWeakPtr(),
damage_rect));
const gfx::Size& result_size = result->size();
SkIRect bitmap_size;
if (bitmap_)
bitmap_->getBounds(&bitmap_size);
if (!bitmap_ ||
bitmap_size.width() != result_size.width() ||
bitmap_size.height() != result_size.height()) {
// Create a new bitmap if the size has changed.
bitmap_.reset(new SkBitmap);
bitmap_->allocN32Pixels(result_size.width(),
result_size.height(),
true);
if (bitmap_->drawsNothing())
return;
}
content::ImageTransportFactory* factory =
content::ImageTransportFactory::GetInstance();
content::GLHelper* gl_helper = factory->GetGLHelper();
if (!gl_helper)
return;
std::unique_ptr<SkAutoLockPixels> bitmap_pixels_lock(
new SkAutoLockPixels(*bitmap_));
uint8_t* pixels = static_cast<uint8_t*>(bitmap_->getPixels());
cc::TextureMailbox texture_mailbox;
std::unique_ptr<cc::SingleReleaseCallback> release_callback;
result->TakeTexture(&texture_mailbox, &release_callback);
DCHECK(texture_mailbox.IsTexture());
if (!texture_mailbox.IsTexture())
return;
ignore_result(scoped_callback_runner.Release());
gl_helper->CropScaleReadbackAndCleanMailbox(
texture_mailbox.mailbox(),
texture_mailbox.sync_token(),
result_size,
gfx::Rect(result_size),
result_size,
pixels,
kN32_SkColorType,
base::Bind(
&CefCopyFrameGenerator::CopyFromCompositingSurfaceFinishedProxy,
weak_ptr_factory_.GetWeakPtr(),
base::Passed(&release_callback),
damage_rect,
base::Passed(&bitmap_),
base::Passed(&bitmap_pixels_lock)),
content::GLHelper::SCALER_QUALITY_FAST);
}
static void CopyFromCompositingSurfaceFinishedProxy(
base::WeakPtr<CefCopyFrameGenerator> generator,
std::unique_ptr<cc::SingleReleaseCallback> release_callback,
const gfx::Rect& damage_rect,
std::unique_ptr<SkBitmap> bitmap,
std::unique_ptr<SkAutoLockPixels> bitmap_pixels_lock,
bool result) {
// This method may be called after the view has been deleted.
gpu::SyncToken sync_token;
if (result) {
content::GLHelper* gl_helper =
content::ImageTransportFactory::GetInstance()->GetGLHelper();
if (gl_helper)
gl_helper->GenerateSyncToken(&sync_token);
}
const bool lost_resource = !sync_token.HasData();
release_callback->Run(sync_token, lost_resource);
if (generator) {
generator->CopyFromCompositingSurfaceFinished(
damage_rect, std::move(bitmap), std::move(bitmap_pixels_lock),
result);
} else {
bitmap_pixels_lock.reset();
bitmap.reset();
}
}
void CopyFromCompositingSurfaceFinished(
const gfx::Rect& damage_rect,
std::unique_ptr<SkBitmap> bitmap,
std::unique_ptr<SkAutoLockPixels> bitmap_pixels_lock,
bool result) {
// Restore ownership of the bitmap to the view.
DCHECK(!bitmap_);
bitmap_ = std::move(bitmap);
if (result) {
OnCopyFrameCaptureSuccess(damage_rect, *bitmap_,
std::move(bitmap_pixels_lock));
} else {
bitmap_pixels_lock.reset();
OnCopyFrameCaptureFailure(damage_rect);
}
}
void PrepareBitmapCopyOutputResult(
const gfx::Rect& damage_rect,
std::unique_ptr<cc::CopyOutputResult> result) {
DCHECK(result->HasBitmap());
std::unique_ptr<SkBitmap> source = result->TakeBitmap();
DCHECK(source);
if (source) {
std::unique_ptr<SkAutoLockPixels> bitmap_pixels_lock(
new SkAutoLockPixels(*source));
OnCopyFrameCaptureSuccess(damage_rect, *source,
std::move(bitmap_pixels_lock));
} else {
OnCopyFrameCaptureFailure(damage_rect);
}
}
void OnCopyFrameCaptureFailure(
const gfx::Rect& damage_rect) {
// Retry with the same |damage_rect|.
pending_damage_rect_.Union(damage_rect);
const bool force_frame = (++frame_retry_count_ <= kFrameRetryLimit);
OnCopyFrameCaptureCompletion(force_frame);
}
void OnCopyFrameCaptureSuccess(
const gfx::Rect& damage_rect,
const SkBitmap& bitmap,
std::unique_ptr<SkAutoLockPixels> bitmap_pixels_lock) {
// view_->OnPaint(damage_rect, bitmap.width(), bitmap.height(),
// bitmap.getPixels());
uint8_t* pixels = reinterpret_cast<uint8_t*>(bitmap.getPixels());
for (int i = 0; i<4; i++) {
int x = static_cast<int>(pixels[i]);
std::cout << std::hex << x << std::dec << std::endl;
}
if (view_->paintCallback) {
std::cout << "FRAME COPY ARRIVED" << std::endl;
view_->paintCallback->Run(damage_rect, bitmap.width(), bitmap.height(),
pixels);
}
bitmap_pixels_lock.reset();
// Reset the frame retry count on successful frame generation.
if (frame_retry_count_ > 0)
frame_retry_count_ = 0;
OnCopyFrameCaptureCompletion(false);
}
void OnCopyFrameCaptureCompletion(bool force_frame) {
frame_in_progress_ = false;
if (frame_pending_) {
// Another frame was requested while the current frame was in-progress.
// Generate the pending frame now.
CEF_POST_TASK(CEF_UIT,
base::Bind(&CefCopyFrameGenerator::GenerateCopyFrame,
weak_ptr_factory_.GetWeakPtr(),
force_frame,
gfx::Rect()));
}
}
int frame_rate_threshold_ms_;
OffScreenWindow* view_;
base::TimeTicks frame_start_time_;
bool frame_pending_;
bool frame_in_progress_;
int frame_retry_count_;
std::unique_ptr<SkBitmap> bitmap_;
gfx::Rect pending_damage_rect_;
base::WeakPtrFactory<CefCopyFrameGenerator> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(CefCopyFrameGenerator);
};
// Used to control the VSync rate in subprocesses when BeginFrame scheduling is
// enabled.
class CefBeginFrameTimer : public cc::DelayBasedTimeSourceClient {
public:
CefBeginFrameTimer(int frame_rate_threshold_ms,
const base::Closure& callback)
: callback_(callback) {
time_source_ = cc::DelayBasedTimeSource::Create(
base::TimeDelta::FromMilliseconds(frame_rate_threshold_ms),
content::BrowserThread::GetMessageLoopProxyForThread(CEF_UIT).get());
time_source_->SetClient(this);
}
void SetActive(bool active) {
time_source_->SetActive(active);
}
bool IsActive() const {
return time_source_->Active();
}
void SetFrameRateThresholdMs(int frame_rate_threshold_ms) {
time_source_->SetTimebaseAndInterval(
base::TimeTicks::Now(),
base::TimeDelta::FromMilliseconds(frame_rate_threshold_ms));
}
private:
// cc::TimerSourceClient implementation.
void OnTimerTick() override {
callback_.Run();
}
const base::Closure callback_;
std::unique_ptr<cc::DelayBasedTimeSource> time_source_;
DISALLOW_COPY_AND_ASSIGN(CefBeginFrameTimer);
};
OffScreenWindow::OffScreenWindow(content::RenderWidgetHost* host)
: render_widget_host_(content::RenderWidgetHostImpl::From(host)),
delegated_frame_host_(new content::DelegatedFrameHost(this)),
compositor_widget_(gfx::kNullAcceleratedWidget),
frame_rate_threshold_ms_(0),
scale_factor_(1.0f),
is_showing_(!render_widget_host_->is_hidden()),
size_(gfx::Size(800, 600)),
delegated_frame_host_(new content::DelegatedFrameHost(this)),
compositor_widget_(gfx::kNullAcceleratedWidget),
weak_ptr_factory_(this) {
DCHECK(render_widget_host_);
std::cout << "OffScreenWindow" << std::endl;
@ -344,16 +620,61 @@ OffScreenWindow::OffScreenWindow(content::RenderWidgetHost* host)
CreatePlatformWidget();
compositor_.reset(new ui::Compositor(content::GetContextFactory(),
base::ThreadTaskRunnerHandle::Get()));
#if !defined(OS_MACOSX)
// On OS X the ui::Compositor is created/owned by the platform view.
compositor_.reset(
new ui::Compositor(content::GetContextFactory(),
base::ThreadTaskRunnerHandle::Get()));
compositor_->SetAcceleratedWidget(compositor_widget_);
compositor_->SetDelegate(this);
#endif
// compositor_->SetDelegate(this);
compositor_->SetRootLayer(root_layer_.get());
frame_rate_threshold_ms_ = 1000 / 24;
begin_frame_timer_.reset(new CefBeginFrameTimer(
frame_rate_threshold_ms_,
base::Bind(&OffScreenWindow::OnBeginFrameTimerTick,
weak_ptr_factory_.GetWeakPtr())));
// begin_frame_timer_->SetActive(true);
}
void OffScreenWindow::OnBeginFrameTimerTick() {
const base::TimeTicks frame_time = base::TimeTicks::Now();
const base::TimeDelta vsync_period =
base::TimeDelta::FromMilliseconds(frame_rate_threshold_ms_);
SendBeginFrame(frame_time, vsync_period);
std::cout << "tickkkk" << std::endl;
// copy_frame_generator_->GenerateCopyFrame(true, damage_rect);
}
void OffScreenWindow::SendBeginFrame(base::TimeTicks frame_time,
base::TimeDelta vsync_period) {
base::TimeTicks display_time = frame_time + vsync_period;
// TODO(brianderson): Use adaptive draw-time estimation.
base::TimeDelta estimated_browser_composite_time =
base::TimeDelta::FromMicroseconds(
(1.0f * base::Time::kMicrosecondsPerSecond) / (3.0f * 60));
base::TimeTicks deadline = display_time - estimated_browser_composite_time;
render_widget_host_->Send(new ViewMsg_BeginFrame(
render_widget_host_->GetRoutingID(),
cc::BeginFrameArgs::Create(BEGINFRAME_FROM_HERE, frame_time, deadline,
vsync_period, cc::BeginFrameArgs::NORMAL)));
}
void OffScreenWindow::SetPaintCallback(const OnPaintCallback *callback) {
paintCallback.reset(callback);
}
OffScreenWindow::~OffScreenWindow() {
std::cout << "~OffScreenWindow" << std::endl;
if (is_showing_) delegated_frame_host_->WasHidden();
if (is_showing_)
delegated_frame_host_->WasHidden();
delegated_frame_host_->ResetCompositor();
delegated_frame_host_.reset(NULL);
@ -447,7 +768,8 @@ void OffScreenWindow::Show() {
return;
is_showing_ = true;
if (render_widget_host_) render_widget_host_->WasShown(ui::LatencyInfo());
if (render_widget_host_)
render_widget_host_->WasShown(ui::LatencyInfo());
delegated_frame_host_->SetCompositor(compositor_.get());
delegated_frame_host_->WasShown(ui::LatencyInfo());
}
@ -457,7 +779,8 @@ void OffScreenWindow::Hide() {
if (!is_showing_)
return;
if (render_widget_host_) render_widget_host_->WasHidden();
if (render_widget_host_)
render_widget_host_->WasHidden();
delegated_frame_host_->WasHidden();
delegated_frame_host_->ResetCompositor();
is_showing_ = false;
@ -512,9 +835,43 @@ void OffScreenWindow::OnSwapCompositorFrame(
last_scroll_offset_ = frame->metadata.root_scroll_offset;
}
if (!copy_frame_generator_.get()) {
copy_frame_generator_.reset(
new CefCopyFrameGenerator(frame_rate_threshold_ms_, this));
}
// Determine the damage rectangle for the current frame. This is the same
// calculation that SwapDelegatedFrame uses.
// cc::RenderPass* root_pass =
// frame->delegated_frame_data->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));
gfx::Rect damage_rect = gfx::Rect(GetVisibleViewportSize());
if (frame->delegated_frame_data)
delegated_frame_host_->SwapDelegatedFrame(
output_surface_id, std::move(frame));
delegated_frame_host_->SwapDelegatedFrame(output_surface_id,
std::move(frame));
// Request a copy of the last compositor frame which will eventually call
// OnPaint asynchronously.
std::cout << "FRAME COPY REQUESTED" << std::endl;
copy_frame_generator_->GenerateCopyFrame(true, damage_rect);
// gfx::Rect rect = gfx::Rect(GetVisibleViewportSize());
// // The below code is similar in functionality to
// // DelegatedFrameHost::CopyFromCompositingSurface but we reuse the same
// // SkBitmap in the GPU codepath and avoid scaling where possible.
// std::unique_ptr<cc::CopyOutputRequest> request =
// cc::CopyOutputRequest::CreateRequest(base::Bind(
// &OffScreenWindow::CopyFromCompositingSurfaceHasResult,
// weak_ptr_factory_.GetWeakPtr(),
// rect));
//
// request->set_area(gfx::Rect(GetPhysicalBackingSize()));
// DelegatedFrameHostGetLayer()->RequestCopyOfOutput(
// std::move(request));
}
void OffScreenWindow::ClearCompositorFrame() {

View file

@ -25,43 +25,78 @@
#include "cc/output/output_surface_client.h"
#include "cc/scheduler/begin_frame_source.h"
#include "content/browser/web_contents/web_contents_view.h"
// #include "atom/browser/native_window_views.h"
#if defined(OS_WIN)
#include <windows.h>
#include "ui/gfx/win/window_impl.h"
#include "content/browser/web_contents/web_contents_view.h"
#include "atom/browser/native_window_views.h"
#endif
#if defined(OS_MACOSX)
#include "content/browser/renderer_host/browser_compositor_view_mac.h"
#include "ui/accelerated_widget_mac/accelerated_widget_mac.h"
#endif
#if defined(OS_MACOSX)
#ifdef __OBJC__
@class CALayer;
@class NSWindow;
@class NSTextInputContext;
#else
class CALayer;
class NSWindow;
class NSTextInputContext;
#endif
#endif
#if defined(OS_MACOSX)
class AcceleratedWidgetMacNSViewHelper;
#endif
namespace atom {
class CefCopyFrameGenerator;
class CefBeginFrameTimer;
class OffScreenWebContentsView : public content::WebContentsView {
public:
OffScreenWebContentsView();
~OffScreenWebContentsView();
gfx::NativeView GetNativeView() const;
gfx::NativeView GetContentNativeView() const;
gfx::NativeWindow GetTopLevelNativeWindow() const;
gfx::NativeView GetNativeView() const override;
gfx::NativeView GetContentNativeView() const override;
gfx::NativeWindow GetTopLevelNativeWindow() const override;
void GetContainerBounds(gfx::Rect* out) const;
void SizeContents(const gfx::Size& size);
void Focus();
void SetInitialFocus();
void StoreFocus();
void RestoreFocus();
content::DropData* GetDropData() const;
gfx::Rect GetViewBounds() const;
void GetContainerBounds(gfx::Rect* out) const override;
void SizeContents(const gfx::Size& size) override;
void Focus() override;
void SetInitialFocus() override;
void StoreFocus() override;
void RestoreFocus() override;
content::DropData* GetDropData() const override;
gfx::Rect GetViewBounds() const override;
void CreateView(
const gfx::Size& initial_size, gfx::NativeView context);
const gfx::Size& initial_size, gfx::NativeView context) override;
content::RenderWidgetHostViewBase* CreateViewForWidget(
content::RenderWidgetHost* render_widget_host, bool is_guest_view_hack);
content::RenderWidgetHost* render_widget_host, bool is_guest_view_hack) override;
content::RenderWidgetHostViewBase* CreateViewForPopupWidget(
content::RenderWidgetHost* render_widget_host);
content::RenderWidgetHost* render_widget_host) override;
void SetPageTitle(const base::string16& title) override;
void RenderViewCreated(content::RenderViewHost* host) override;
void RenderViewSwappedIn(content::RenderViewHost* host) override;
void SetOverscrollControllerEnabled(bool enabled) override;
#if defined(OS_MACOSX)
void SetAllowOtherViews(bool allow) override;
bool GetAllowOtherViews() const override;
bool IsEventTracking() const override;
void CloseTabAfterEventTracking() override;
#endif
void SetPageTitle(const base::string16& title);
void RenderViewCreated(content::RenderViewHost* host);
void RenderViewSwappedIn(content::RenderViewHost* host);
void SetOverscrollControllerEnabled(bool enabled);
private:
content::RenderWidgetHostViewBase* view_;
};
@ -72,7 +107,7 @@ public:
~OffScreenOutputDevice();
void saveSkBitmapToBMPFile(const SkBitmap& skBitmap, const char* path);
// void saveSkBitmapToBMPFile(const SkBitmap& skBitmap, const char* path);
void Resize(const gfx::Size& pixel_size, float scale_factor) override;
SkCanvas* BeginPaint(const gfx::Rect& damage_rect) override;
void EndPaint() override;
@ -91,16 +126,22 @@ public:
~AtomCompositorDelegate() {};
std::unique_ptr<cc::SoftwareOutputDevice> CreateSoftwareOutputDevice(
ui::Compositor* compositor) {
ui::Compositor* compositor) override {
return std::unique_ptr<cc::SoftwareOutputDevice>(new OffScreenOutputDevice);
}
};
class OffScreenWindow
: public content::RenderWidgetHostViewBase,
public content::DelegatedFrameHostClient,
public ui::CompositorDelegate {
: public content::RenderWidgetHostViewBase,
#if defined(OS_MACOSX)
public ui::AcceleratedWidgetMacNSView,
#endif
public ui::CompositorDelegate,
public content::DelegatedFrameHostClient {
public:
typedef base::Callback<void(const gfx::Rect&,int,int,void*)>
OnPaintCallback;
OffScreenWindow(content::RenderWidgetHost*);
~OffScreenWindow();
@ -108,100 +149,164 @@ public:
//content::RenderWidgetHostView
bool OnMessageReceived(const IPC::Message&) override;
void InitAsChild(gfx::NativeView);
content::RenderWidgetHost* GetRenderWidgetHost(void) const;
void SetSize(const gfx::Size &);
void SetBounds(const gfx::Rect &);
gfx::Vector2dF GetLastScrollOffset(void) const;
gfx::NativeView GetNativeView(void) const;
gfx::NativeViewId GetNativeViewId(void) const;
gfx::NativeViewAccessible GetNativeViewAccessible(void);
void InitAsChild(gfx::NativeView) override;
content::RenderWidgetHost* GetRenderWidgetHost(void) const override;
void SetSize(const gfx::Size &) override;
void SetBounds(const gfx::Rect &) override;
gfx::Vector2dF GetLastScrollOffset(void) const override;
gfx::NativeView GetNativeView(void) const override;
gfx::NativeViewId GetNativeViewId(void) const override;
gfx::NativeViewAccessible GetNativeViewAccessible(void) override;
ui::TextInputClient* GetTextInputClient() override;
void Focus(void);
bool HasFocus(void) const;
bool IsSurfaceAvailableForCopy(void) const;
void Show(void);
void Hide(void);
bool IsShowing(void);
gfx::Rect GetViewBounds(void) const;
void Focus(void) override;
bool HasFocus(void) const override;
bool IsSurfaceAvailableForCopy(void) const override;
void Show(void) override;
void Hide(void) override;
bool IsShowing(void) override;
gfx::Rect GetViewBounds(void) const override;
gfx::Size GetVisibleViewportSize() const override;
void SetInsets(const gfx::Insets&) override;
bool LockMouse(void);
void UnlockMouse(void);
bool GetScreenColorProfile(std::vector<char>*);
bool LockMouse(void) override;
void UnlockMouse(void) override;
bool GetScreenColorProfile(std::vector<char>*) override;
#if defined(OS_MACOSX)
void SetActive(bool active) override;
void ShowDefinitionForSelection() override;
bool SupportsSpeech() const override;
void SpeakSelection() override;
bool IsSpeaking() const override;
void StopSpeaking() override;
#endif // defined(OS_MACOSX)
//content::RenderWidgetHostViewBase
void OnSwapCompositorFrame(uint32_t, std::unique_ptr<cc::CompositorFrame>);
void ClearCompositorFrame(void);
void InitAsPopup(content::RenderWidgetHostView *, const gfx::Rect &);
void InitAsFullscreen(content::RenderWidgetHostView *);
void UpdateCursor(const content::WebCursor &);
void SetIsLoading(bool);
void TextInputStateChanged(const ViewHostMsg_TextInputState_Params &);
void ImeCancelComposition(void);
void RenderProcessGone(base::TerminationStatus,int);
void Destroy(void);
void SetTooltipText(const base::string16 &);
void SelectionBoundsChanged(const ViewHostMsg_SelectionBounds_Params &);
void OnSwapCompositorFrame(uint32_t, std::unique_ptr<cc::CompositorFrame>) override;
void ClearCompositorFrame(void) override;
void InitAsPopup(content::RenderWidgetHostView *, const gfx::Rect &) override;
void InitAsFullscreen(content::RenderWidgetHostView *) override;
void UpdateCursor(const content::WebCursor &) override;
void SetIsLoading(bool) override;
void TextInputStateChanged(const ViewHostMsg_TextInputState_Params &) override;
void ImeCancelComposition(void) override;
void RenderProcessGone(base::TerminationStatus,int) override;
void Destroy(void) override;
void SetTooltipText(const base::string16 &) override;
#if defined(OS_MACOSX)
void SelectionChanged(const base::string16& text,
size_t offset,
const gfx::Range& range) override;
#endif
void SelectionBoundsChanged(const ViewHostMsg_SelectionBounds_Params &) override;
void CopyFromCompositingSurface(const gfx::Rect &,
const gfx::Size &,
const content::ReadbackRequestCallback &,
const SkColorType);
const SkColorType) override;
void CopyFromCompositingSurfaceToVideoFrame(
const gfx::Rect &,
const scoped_refptr<media::VideoFrame> &,
const base::Callback<void (const gfx::Rect &, bool),
base::internal::CopyMode::Copyable> &);
bool CanCopyToVideoFrame(void) const;
base::internal::CopyMode::Copyable> &) override;
bool CanCopyToVideoFrame(void) const override;
void BeginFrameSubscription(
std::unique_ptr<content::RenderWidgetHostViewFrameSubscriber>);
void EndFrameSubscription();
bool HasAcceleratedSurface(const gfx::Size &);
void GetScreenInfo(blink::WebScreenInfo *);
std::unique_ptr<content::RenderWidgetHostViewFrameSubscriber>) override;
void EndFrameSubscription() override;
bool HasAcceleratedSurface(const gfx::Size &) override;
void GetScreenInfo(blink::WebScreenInfo *) override;
bool GetScreenColorProfile(blink::WebVector<char>*);
gfx::Rect GetBoundsInRootWindow(void);
void LockCompositingSurface(void);
void UnlockCompositingSurface(void);
gfx::Rect GetBoundsInRootWindow(void) override;
void LockCompositingSurface(void) override;
void UnlockCompositingSurface(void) override;
void ImeCompositionRangeChanged(
const gfx::Range &, const std::vector<gfx::Rect>&);
const gfx::Range &, const std::vector<gfx::Rect>&) override;
gfx::Size GetPhysicalBackingSize() const override;
gfx::Size GetRequestedRendererSize() const override;
//content::DelegatedFrameHostClient
int DelegatedFrameHostGetGpuMemoryBufferClientId(void) const;
ui::Layer *DelegatedFrameHostGetLayer(void) const;
bool DelegatedFrameHostIsVisible(void) const;
SkColor DelegatedFrameHostGetGutterColor(SkColor) const;
gfx::Size DelegatedFrameHostDesiredSizeInDIP(void) const;
bool DelegatedFrameCanCreateResizeLock(void) const;
std::unique_ptr<content::ResizeLock> DelegatedFrameHostCreateResizeLock(bool);
void DelegatedFrameHostResizeLockWasReleased(void);
ui::Layer *DelegatedFrameHostGetLayer(void) const override;
bool DelegatedFrameHostIsVisible(void) const override;
SkColor DelegatedFrameHostGetGutterColor(SkColor) const override;
gfx::Size DelegatedFrameHostDesiredSizeInDIP(void) const override;
bool DelegatedFrameCanCreateResizeLock(void) const override;
std::unique_ptr<content::ResizeLock> DelegatedFrameHostCreateResizeLock(bool) override;
void DelegatedFrameHostResizeLockWasReleased(void) override;
void DelegatedFrameHostSendCompositorSwapAck(
int, const cc::CompositorFrameAck &);
int, const cc::CompositorFrameAck &) override;
void DelegatedFrameHostSendReclaimCompositorResources(
int, const cc::CompositorFrameAck &);
void DelegatedFrameHostOnLostCompositorResources(void);
int, const cc::CompositorFrameAck &) override;
void DelegatedFrameHostOnLostCompositorResources(void) override;
void DelegatedFrameHostUpdateVSyncParameters(
const base::TimeTicks &, const base::TimeDelta &);
const base::TimeTicks &, const base::TimeDelta &) override;
std::unique_ptr<cc::SoftwareOutputDevice> CreateSoftwareOutputDevice(
ui::Compositor* compositor);
ui::Compositor* compositor) override;
void OnSetNeedsBeginFrames(bool enabled);
#if defined(OS_MACOSX)
// AcceleratedWidgetMacNSView implementation.
NSView* AcceleratedWidgetGetNSView() const override;
void AcceleratedWidgetGetVSyncParameters(
base::TimeTicks* timebase, base::TimeDelta* interval) const override;
void AcceleratedWidgetSwapCompleted() override;
#endif // defined(OS_MACOSX)
ui::Compositor* compositor() const { return compositor_.get(); }
content::RenderWidgetHostImpl* render_widget_host() const
{ return render_widget_host_; }
void OnBeginFrameTimerTick();
void SendBeginFrame(base::TimeTicks frame_time,
base::TimeDelta vsync_period);
std::unique_ptr<const OnPaintCallback> paintCallback;
void SetPaintCallback(const OnPaintCallback*);
private:
content::RenderWidgetHostImpl* render_widget_host_;
std::unique_ptr<content::DelegatedFrameHost> delegated_frame_host_;
std::unique_ptr<ui::Compositor> compositor_;
gfx::AcceleratedWidget compositor_widget_;
std::unique_ptr<ui::Layer> root_layer_;
std::unique_ptr<CefCopyFrameGenerator> copy_frame_generator_;
std::unique_ptr<CefBeginFrameTimer> begin_frame_timer_;
int frame_rate_threshold_ms_;
float scale_factor_;
bool is_showing_;
gfx::Vector2dF last_scroll_offset_;
gfx::Size size_;
std::unique_ptr<content::DelegatedFrameHost> delegated_frame_host_;
std::unique_ptr<ui::Compositor> compositor_;
gfx::AcceleratedWidget compositor_widget_;
std::unique_ptr<ui::Layer> root_layer_;
#if defined(OS_WIN)
std::unique_ptr<gfx::WindowImpl> window_;
#elif defined(OS_MACOSX)
NSWindow* window_;
CALayer* background_layer_;
std::unique_ptr<content::BrowserCompositorMac> browser_compositor_;
#elif defined(USE_X11)
CefWindowX11* window_;
std::unique_ptr<ui::XScopedCursor> invisible_cursor_;
#endif
#if defined(OS_MACOSX)
NSTextInputContext* text_input_context_osr_mac_;
// Selected text on the renderer.
std::string selected_text_;
// The current composition character range and its bounds.
gfx::Range composition_range_;
std::vector<gfx::Rect> composition_bounds_;
// The current caret bounds.
gfx::Rect caret_rect_;
// The current first selection bounds.
gfx::Rect first_selection_rect_;
#endif
base::WeakPtrFactory<OffScreenWindow> weak_ptr_factory_;

View file

@ -0,0 +1,112 @@
#include "atom/browser/osr_window.h"
#include <algorithm>
#include <limits>
#include <utility>
#include <iostream>
#import <Cocoa/Cocoa.h>
#include "base/compiler_specific.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/events/latency_info.h"
NSView* atom::OffScreenWindow::AcceleratedWidgetGetNSView() const {
return [window_ contentView];
}
void atom::OffScreenWindow::AcceleratedWidgetGetVSyncParameters(
base::TimeTicks* timebase, base::TimeDelta* interval) const {
*timebase = base::TimeTicks();
*interval = base::TimeDelta();
}
void atom::OffScreenWindow::AcceleratedWidgetSwapCompleted() {
}
void atom::OffScreenWindow::SetActive(bool active) {
}
void atom::OffScreenWindow::ShowDefinitionForSelection() {
}
bool atom::OffScreenWindow::SupportsSpeech() const {
return false;
}
void atom::OffScreenWindow::SpeakSelection() {
}
bool atom::OffScreenWindow::IsSpeaking() const {
return false;
}
void atom::OffScreenWindow::StopSpeaking() {
}
void atom::OffScreenWindow::SelectionChanged(
const base::string16& text,
size_t offset,
const gfx::Range& range) {
if (range.is_empty() || text.empty()) {
selected_text_.clear();
} else {
size_t pos = range.GetMin() - offset;
size_t n = range.length();
DCHECK(pos + n <= text.length()) << "The text can not fully cover range.";
if (pos >= text.length()) {
DCHECK(false) << "The text can not cover range.";
return;
}
selected_text_ = base::UTF16ToUTF8(text.substr(pos, n));
}
RenderWidgetHostViewBase::SelectionChanged(text, offset, range);
}
void atom::OffScreenWindow::CreatePlatformWidget() {
// Create a borderless non-visible 1x1 window.
window_ = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 1, 1)
styleMask:NSBorderlessWindowMask
backing:NSBackingStoreBuffered
defer:NO];
// Create a CALayer which is used by BrowserCompositorViewMac for rendering.
background_layer_ = [[[CALayer alloc] init] retain];
[background_layer_ setBackgroundColor:CGColorGetConstantColor(kCGColorClear)];
NSView* content_view = [window_ contentView];
[content_view setLayer:background_layer_];
[content_view setWantsLayer:YES];
browser_compositor_ = content::BrowserCompositorMac::Create();
compositor_.reset(browser_compositor_->compositor());
compositor_->SetRootLayer(root_layer_.get());
browser_compositor_->accelerated_widget_mac()->SetNSView(this);
browser_compositor_->compositor()->SetVisible(true);
// CEF needs the browser compositor to remain responsive whereas normal
// rendering on OS X does not. This effectively reverts the changes from
// https://crbug.com/463988#c6
compositor_->SetLocksWillTimeOut(true);
browser_compositor_->Unsuspend();
}
// void atom::OffScreenWindow::PlatformDestroyCompositorWidget() {
// DCHECK(window_);
//
// browser_compositor_->Destroy();
//
// [window_ close];
// window_ = nil;
// [background_layer_ release];
// background_layer_ = nil;
//
// browser_compositor_.reset();
//
// delete accelerated_widget_helper_;
// accelerated_widget_helper_ = nullptr;
// }

View file

@ -23,5 +23,9 @@ exports.load = (appUrl) => {
console.log("asd")
})
})
mainWindow.webContents.on('paint', (e, rect, w, h, data) => {
console.log('ELECTRON EVENT', rect, w, h, data)
})
})
}

View file

@ -129,6 +129,14 @@
e.preventDefault();
return false;
};
document.onload = () => {
var a = false
setInterval(function () {
document.body.querySelector('.container').style.background = a ? 'red' : 'blue'
a = !a
}, 200)
}
</script>
<div class="header">

View file

@ -331,5 +331,5 @@ if (option.file && !option.webdriver) {
startRepl()
} else {
const indexPath = path.join(__dirname, '/index.html')
loadApplicationByUrl(`file://${indexPath}`)
loadApplicationByUrl(`https://vimeo.com/channels/staffpicks/174711575#t=7s`)
}

View file

@ -207,6 +207,7 @@
'atom/browser/osr_window.cc',
'atom/browser/osr_window.h',
'atom/browser/osr_window_win.cc',
'atom/browser/osr_window_mac.mm',
'atom/browser/net/asar/asar_protocol_handler.cc',
'atom/browser/net/asar/asar_protocol_handler.h',
'atom/browser/net/asar/url_request_asar_job.cc',