Commit de648460 authored by Maksim Sisov's avatar Maksim Sisov Committed by Commit Bot

[ozone/wayland] Add partial swap support.

This CL enables partial swap support in Wayland by
enabling SupportsPostSubBuffer.

A damage region describes the regions where the pending
buffer is different from the current surface contents, and where
the surface therefore needs to be repainted.

Enabling this needs requires fixing http://crbug.com/339493
as well for Intel drivers.

Bug: 880726
Change-Id: I3bb2c7f876e3b5297c0d5595e309e3853772430f
Reviewed-on: https://chromium-review.googlesource.com/1206370
Commit-Queue: Maksim Sisov <msisov@igalia.com>
Reviewed-by: default avatarTom Sepez <tsepez@chromium.org>
Reviewed-by: default avatarRobert Kroeger <rjkroege@chromium.org>
Cr-Commit-Position: refs/heads/master@{#589477}
parent 37baf0b2
...@@ -69,8 +69,7 @@ bool GbmSurfacelessWayland::SupportsAsyncSwap() { ...@@ -69,8 +69,7 @@ bool GbmSurfacelessWayland::SupportsAsyncSwap() {
} }
bool GbmSurfacelessWayland::SupportsPostSubBuffer() { bool GbmSurfacelessWayland::SupportsPostSubBuffer() {
// TODO(msisov): figure out how to enable subbuffers with wayland/dmabuf. return true;
return false;
} }
gfx::SwapResult GbmSurfacelessWayland::PostSubBuffer( gfx::SwapResult GbmSurfacelessWayland::PostSubBuffer(
...@@ -135,8 +134,10 @@ void GbmSurfacelessWayland::PostSubBufferAsync( ...@@ -135,8 +134,10 @@ void GbmSurfacelessWayland::PostSubBufferAsync(
int height, int height,
const SwapCompletionCallback& completion_callback, const SwapCompletionCallback& completion_callback,
const PresentationCallback& presentation_callback) { const PresentationCallback& presentation_callback) {
// See the comment in SupportsPostSubBuffer. PendingFrame* frame = unsubmitted_frames_.back().get();
NOTREACHED(); frame->damage_region_ = gfx::Rect(x, y, width, height);
SwapBuffersAsync(completion_callback, presentation_callback);
} }
EGLConfig GbmSurfacelessWayland::GetConfig() { EGLConfig GbmSurfacelessWayland::GetConfig() {
...@@ -203,6 +204,7 @@ void GbmSurfacelessWayland::SubmitFrame() { ...@@ -203,6 +204,7 @@ void GbmSurfacelessWayland::SubmitFrame() {
weak_factory_.GetWeakPtr()); weak_factory_.GetWeakPtr());
uint32_t buffer_id = planes_.back().pixmap->GetUniqueId(); uint32_t buffer_id = planes_.back().pixmap->GetUniqueId();
surface_factory_->ScheduleBufferSwap(widget_, buffer_id, surface_factory_->ScheduleBufferSwap(widget_, buffer_id,
submitted_frame_->damage_region_,
std::move(callback)); std::move(callback));
} }
} }
......
...@@ -68,6 +68,10 @@ class GbmSurfacelessWayland : public gl::SurfacelessEGL { ...@@ -68,6 +68,10 @@ class GbmSurfacelessWayland : public gl::SurfacelessEGL {
bool ready = false; bool ready = false;
gfx::SwapResult swap_result = gfx::SwapResult::SWAP_FAILED; gfx::SwapResult swap_result = gfx::SwapResult::SWAP_FAILED;
// A region of the updated content in a corresponding frame. It's used to
// advice Wayland which part of a buffer is going to be updated. Passing {0,
// 0, 0, 0} results in a whole buffer update on the Wayland compositor side.
gfx::Rect damage_region_ = gfx::Rect();
std::vector<gl::GLSurfaceOverlay> overlays; std::vector<gl::GLSurfaceOverlay> overlays;
SwapCompletionCallback completion_callback; SwapCompletionCallback completion_callback;
PresentationCallback presentation_callback; PresentationCallback presentation_callback;
......
...@@ -89,10 +89,12 @@ void WaylandConnectionProxy::DestroyZwpLinuxDmabufInternal(uint32_t buffer_id) { ...@@ -89,10 +89,12 @@ void WaylandConnectionProxy::DestroyZwpLinuxDmabufInternal(uint32_t buffer_id) {
void WaylandConnectionProxy::ScheduleBufferSwap( void WaylandConnectionProxy::ScheduleBufferSwap(
gfx::AcceleratedWidget widget, gfx::AcceleratedWidget widget,
uint32_t buffer_id, uint32_t buffer_id,
const gfx::Rect& damage_region,
wl::BufferSwapCallback callback) { wl::BufferSwapCallback callback) {
DCHECK(gpu_thread_runner_->BelongsToCurrentThread()); DCHECK(gpu_thread_runner_->BelongsToCurrentThread());
DCHECK(wc_ptr_); DCHECK(wc_ptr_);
wc_ptr_->ScheduleBufferSwap(widget, buffer_id, std::move(callback)); wc_ptr_->ScheduleBufferSwap(widget, buffer_id, damage_region,
std::move(callback));
} }
WaylandWindow* WaylandConnectionProxy::GetWindow( WaylandWindow* WaylandConnectionProxy::GetWindow(
......
...@@ -22,7 +22,8 @@ struct wl_shm; ...@@ -22,7 +22,8 @@ struct wl_shm;
namespace gfx { namespace gfx {
enum class SwapResult; enum class SwapResult;
} class Rect;
} // namespace gfx
namespace ui { namespace ui {
...@@ -67,6 +68,7 @@ class WaylandConnectionProxy : public ozone::mojom::WaylandConnectionClient { ...@@ -67,6 +68,7 @@ class WaylandConnectionProxy : public ozone::mojom::WaylandConnectionClient {
// is received. // is received.
void ScheduleBufferSwap(gfx::AcceleratedWidget widget, void ScheduleBufferSwap(gfx::AcceleratedWidget widget,
uint32_t buffer_id, uint32_t buffer_id,
const gfx::Rect& damage_region,
wl::BufferSwapCallback callback); wl::BufferSwapCallback callback);
#if defined(WAYLAND_GBM) #if defined(WAYLAND_GBM)
......
...@@ -117,6 +117,7 @@ bool WaylandBufferManager::CreateBuffer(base::File file, ...@@ -117,6 +117,7 @@ bool WaylandBufferManager::CreateBuffer(base::File file,
// TODO(msisov): handle buffer swap failure or success. // TODO(msisov): handle buffer swap failure or success.
bool WaylandBufferManager::ScheduleBufferSwap(gfx::AcceleratedWidget widget, bool WaylandBufferManager::ScheduleBufferSwap(gfx::AcceleratedWidget widget,
uint32_t buffer_id, uint32_t buffer_id,
const gfx::Rect& damage_region,
wl::BufferSwapCallback callback) { wl::BufferSwapCallback callback) {
TRACE_EVENT1("Wayland", "WaylandBufferManager::ScheduleSwapBuffer", TRACE_EVENT1("Wayland", "WaylandBufferManager::ScheduleSwapBuffer",
"Buffer id", buffer_id); "Buffer id", buffer_id);
...@@ -138,6 +139,7 @@ bool WaylandBufferManager::ScheduleBufferSwap(gfx::AcceleratedWidget widget, ...@@ -138,6 +139,7 @@ bool WaylandBufferManager::ScheduleBufferSwap(gfx::AcceleratedWidget widget,
// WaylandWindow. // WaylandWindow.
buffer->widget = widget; buffer->widget = widget;
buffer->buffer_swap_callback = std::move(callback); buffer->buffer_swap_callback = std::move(callback);
buffer->damage_region = damage_region;
if (buffer->wl_buffer) { if (buffer->wl_buffer) {
// A wl_buffer might not exist by this time. Silently return. // A wl_buffer might not exist by this time. Silently return.
...@@ -186,10 +188,9 @@ bool WaylandBufferManager::SwapBuffer(Buffer* buffer) { ...@@ -186,10 +188,9 @@ bool WaylandBufferManager::SwapBuffer(Buffer* buffer) {
return false; return false;
} }
// TODO(msisov): it would be beneficial to use real damage regions to improve wl_surface_damage(window->surface(), buffer->damage_region.x(),
// performance. buffer->damage_region.y(), buffer->damage_region.width(),
wl_surface_damage(window->surface(), 0, 0, window->GetBounds().width(), buffer->damage_region.height());
window->GetBounds().height());
wl_surface_attach(window->surface(), buffer->wl_buffer.get(), 0, 0); wl_surface_attach(window->surface(), buffer->wl_buffer.get(), 0, 0);
static const wl_callback_listener frame_listener = { static const wl_callback_listener frame_listener = {
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "base/containers/flat_map.h" #include "base/containers/flat_map.h"
#include "base/files/file.h" #include "base/files/file.h"
#include "base/macros.h" #include "base/macros.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/native_widget_types.h" #include "ui/gfx/native_widget_types.h"
#include "ui/gfx/presentation_feedback.h" #include "ui/gfx/presentation_feedback.h"
#include "ui/gfx/swap_result.h" #include "ui/gfx/swap_result.h"
...@@ -56,9 +57,12 @@ class WaylandBufferManager { ...@@ -56,9 +57,12 @@ class WaylandBufferManager {
uint32_t buffer_id); uint32_t buffer_id);
// Assigns a wl_buffer with |buffer_id| to a window with the same |widget|. On // Assigns a wl_buffer with |buffer_id| to a window with the same |widget|. On
// error, false is returned and |error_message_| is set. // error, false is returned and |error_message_| is set. A |damage_region|
// identifies which part of the buffer is updated. If an empty region is
// provided, the whole buffer is updated.
bool ScheduleBufferSwap(gfx::AcceleratedWidget widget, bool ScheduleBufferSwap(gfx::AcceleratedWidget widget,
uint32_t buffer_id, uint32_t buffer_id,
const gfx::Rect& damage_region,
wl::BufferSwapCallback callback); wl::BufferSwapCallback callback);
// Destroys a buffer with |buffer_id| in |buffers_|. On error, false is // Destroys a buffer with |buffer_id| in |buffers_|. On error, false is
...@@ -87,6 +91,11 @@ class WaylandBufferManager { ...@@ -87,6 +91,11 @@ class WaylandBufferManager {
// Widget to attached/being attach WaylandWindow. // Widget to attached/being attach WaylandWindow.
gfx::AcceleratedWidget widget = gfx::kNullAcceleratedWidget; gfx::AcceleratedWidget widget = gfx::kNullAcceleratedWidget;
// Describes the region where the pending buffer is different from the
// current surface contents, and where the surface therefore needs to be
// repainted.
gfx::Rect damage_region;
// A buffer swap result once the buffer is committed. // A buffer swap result once the buffer is committed.
gfx::SwapResult swap_result; gfx::SwapResult swap_result;
......
...@@ -187,9 +187,10 @@ void WaylandConnection::DestroyZwpLinuxDmabuf(uint32_t buffer_id) { ...@@ -187,9 +187,10 @@ void WaylandConnection::DestroyZwpLinuxDmabuf(uint32_t buffer_id) {
void WaylandConnection::ScheduleBufferSwap( void WaylandConnection::ScheduleBufferSwap(
gfx::AcceleratedWidget widget, gfx::AcceleratedWidget widget,
uint32_t buffer_id, uint32_t buffer_id,
const gfx::Rect& damage_region,
ScheduleBufferSwapCallback callback) { ScheduleBufferSwapCallback callback) {
DCHECK(base::MessageLoopForUI::IsCurrent()); DCHECK(base::MessageLoopForUI::IsCurrent());
if (!buffer_manager_->ScheduleBufferSwap(widget, buffer_id, if (!buffer_manager_->ScheduleBufferSwap(widget, buffer_id, damage_region,
std::move(callback))) { std::move(callback))) {
TerminateGpuProcess(buffer_manager_->error_message()); TerminateGpuProcess(buffer_manager_->error_message());
} }
......
...@@ -61,6 +61,7 @@ class WaylandConnection : public PlatformEventSource, ...@@ -61,6 +61,7 @@ class WaylandConnection : public PlatformEventSource,
// WaylandWindow with the specified |widget|. // WaylandWindow with the specified |widget|.
void ScheduleBufferSwap(gfx::AcceleratedWidget widget, void ScheduleBufferSwap(gfx::AcceleratedWidget widget,
uint32_t buffer_id, uint32_t buffer_id,
const gfx::Rect& damage_region,
ScheduleBufferSwapCallback callback) override; ScheduleBufferSwapCallback callback) override;
// Schedules a flush of the Wayland connection. // Schedules a flush of the Wayland connection.
......
...@@ -234,8 +234,10 @@ GbmSurfacelessWayland* WaylandSurfaceFactory::GetSurface( ...@@ -234,8 +234,10 @@ GbmSurfacelessWayland* WaylandSurfaceFactory::GetSurface(
void WaylandSurfaceFactory::ScheduleBufferSwap( void WaylandSurfaceFactory::ScheduleBufferSwap(
gfx::AcceleratedWidget widget, gfx::AcceleratedWidget widget,
uint32_t buffer_id, uint32_t buffer_id,
const gfx::Rect& damage_region,
wl::BufferSwapCallback callback) { wl::BufferSwapCallback callback) {
connection_->ScheduleBufferSwap(widget, buffer_id, std::move(callback)); connection_->ScheduleBufferSwap(widget, buffer_id, damage_region,
std::move(callback));
} }
std::unique_ptr<SurfaceOzoneCanvas> std::unique_ptr<SurfaceOzoneCanvas>
......
...@@ -7,13 +7,16 @@ ...@@ -7,13 +7,16 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "ui/gl/gl_surface.h"
#include "ui/ozone/public/surface_factory_ozone.h"
#include "base/posix/eintr_wrapper.h" #include "base/posix/eintr_wrapper.h"
#include "base/single_thread_task_runner.h" #include "base/single_thread_task_runner.h"
#include "base/threading/sequenced_task_runner_handle.h" #include "base/threading/sequenced_task_runner_handle.h"
#include "ui/gl/gl_surface.h"
#include "ui/ozone/platform/wayland/wayland_util.h" #include "ui/ozone/platform/wayland/wayland_util.h"
#include "ui/ozone/public/surface_factory_ozone.h"
namespace gfx {
class Rect;
} // namespace gfx
namespace ui { namespace ui {
...@@ -28,6 +31,7 @@ class WaylandSurfaceFactory : public SurfaceFactoryOzone { ...@@ -28,6 +31,7 @@ class WaylandSurfaceFactory : public SurfaceFactoryOzone {
// These methods are used, when a dmabuf based approach is used. // These methods are used, when a dmabuf based approach is used.
void ScheduleBufferSwap(gfx::AcceleratedWidget widget, void ScheduleBufferSwap(gfx::AcceleratedWidget widget,
uint32_t buffer_id, uint32_t buffer_id,
const gfx::Rect& damage_region_,
wl::BufferSwapCallback callback); wl::BufferSwapCallback callback);
void RegisterSurface(gfx::AcceleratedWidget widget, void RegisterSurface(gfx::AcceleratedWidget widget,
GbmSurfacelessWayland* surface); GbmSurfacelessWayland* surface);
......
...@@ -11,6 +11,7 @@ mojom("wayland_interfaces") { ...@@ -11,6 +11,7 @@ mojom("wayland_interfaces") {
public_deps = [ public_deps = [
"//mojo/public/mojom/base", "//mojo/public/mojom/base",
"//ui/gfx/geometry/mojo",
"//ui/gfx/mojo", "//ui/gfx/mojo",
] ]
} }
...@@ -6,6 +6,7 @@ module ui.ozone.mojom; ...@@ -6,6 +6,7 @@ module ui.ozone.mojom;
import "mojo/public/mojom/base/file.mojom"; import "mojo/public/mojom/base/file.mojom";
import "mojo/public/mojom/base/file_path.mojom"; import "mojo/public/mojom/base/file_path.mojom";
import "ui/gfx/geometry/mojo/geometry.mojom";
import "ui/gfx/mojo/accelerated_widget.mojom"; import "ui/gfx/mojo/accelerated_widget.mojom";
import "ui/gfx/mojo/presentation_feedback.mojom"; import "ui/gfx/mojo/presentation_feedback.mojom";
import "ui/gfx/mojo/swap_result.mojom"; import "ui/gfx/mojo/swap_result.mojom";
...@@ -28,7 +29,8 @@ interface WaylandConnection { ...@@ -28,7 +29,8 @@ interface WaylandConnection {
DestroyZwpLinuxDmabuf(uint32 buffer_id); DestroyZwpLinuxDmabuf(uint32 buffer_id);
// Swaps wl_buffers for a WaylandWindow with the following |widget|. // Swaps wl_buffers for a WaylandWindow with the following |widget|.
ScheduleBufferSwap(gfx.mojom.AcceleratedWidget widget, uint32 buffer_id) ScheduleBufferSwap(gfx.mojom.AcceleratedWidget widget, uint32 buffer_id,
gfx.mojom.Rect damage_region)
=> (gfx.mojom.SwapResult swap_result, => (gfx.mojom.SwapResult swap_result,
gfx.mojom.PresentationFeedback feedback); gfx.mojom.PresentationFeedback feedback);
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment