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() {
}
bool GbmSurfacelessWayland::SupportsPostSubBuffer() {
// TODO(msisov): figure out how to enable subbuffers with wayland/dmabuf.
return false;
return true;
}
gfx::SwapResult GbmSurfacelessWayland::PostSubBuffer(
......@@ -135,8 +134,10 @@ void GbmSurfacelessWayland::PostSubBufferAsync(
int height,
const SwapCompletionCallback& completion_callback,
const PresentationCallback& presentation_callback) {
// See the comment in SupportsPostSubBuffer.
NOTREACHED();
PendingFrame* frame = unsubmitted_frames_.back().get();
frame->damage_region_ = gfx::Rect(x, y, width, height);
SwapBuffersAsync(completion_callback, presentation_callback);
}
EGLConfig GbmSurfacelessWayland::GetConfig() {
......@@ -203,6 +204,7 @@ void GbmSurfacelessWayland::SubmitFrame() {
weak_factory_.GetWeakPtr());
uint32_t buffer_id = planes_.back().pixmap->GetUniqueId();
surface_factory_->ScheduleBufferSwap(widget_, buffer_id,
submitted_frame_->damage_region_,
std::move(callback));
}
}
......
......@@ -68,6 +68,10 @@ class GbmSurfacelessWayland : public gl::SurfacelessEGL {
bool ready = false;
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;
SwapCompletionCallback completion_callback;
PresentationCallback presentation_callback;
......
......@@ -89,10 +89,12 @@ void WaylandConnectionProxy::DestroyZwpLinuxDmabufInternal(uint32_t buffer_id) {
void WaylandConnectionProxy::ScheduleBufferSwap(
gfx::AcceleratedWidget widget,
uint32_t buffer_id,
const gfx::Rect& damage_region,
wl::BufferSwapCallback callback) {
DCHECK(gpu_thread_runner_->BelongsToCurrentThread());
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(
......
......@@ -22,7 +22,8 @@ struct wl_shm;
namespace gfx {
enum class SwapResult;
}
class Rect;
} // namespace gfx
namespace ui {
......@@ -67,6 +68,7 @@ class WaylandConnectionProxy : public ozone::mojom::WaylandConnectionClient {
// is received.
void ScheduleBufferSwap(gfx::AcceleratedWidget widget,
uint32_t buffer_id,
const gfx::Rect& damage_region,
wl::BufferSwapCallback callback);
#if defined(WAYLAND_GBM)
......
......@@ -117,6 +117,7 @@ bool WaylandBufferManager::CreateBuffer(base::File file,
// TODO(msisov): handle buffer swap failure or success.
bool WaylandBufferManager::ScheduleBufferSwap(gfx::AcceleratedWidget widget,
uint32_t buffer_id,
const gfx::Rect& damage_region,
wl::BufferSwapCallback callback) {
TRACE_EVENT1("Wayland", "WaylandBufferManager::ScheduleSwapBuffer",
"Buffer id", buffer_id);
......@@ -138,6 +139,7 @@ bool WaylandBufferManager::ScheduleBufferSwap(gfx::AcceleratedWidget widget,
// WaylandWindow.
buffer->widget = widget;
buffer->buffer_swap_callback = std::move(callback);
buffer->damage_region = damage_region;
if (buffer->wl_buffer) {
// A wl_buffer might not exist by this time. Silently return.
......@@ -186,10 +188,9 @@ bool WaylandBufferManager::SwapBuffer(Buffer* buffer) {
return false;
}
// TODO(msisov): it would be beneficial to use real damage regions to improve
// performance.
wl_surface_damage(window->surface(), 0, 0, window->GetBounds().width(),
window->GetBounds().height());
wl_surface_damage(window->surface(), buffer->damage_region.x(),
buffer->damage_region.y(), buffer->damage_region.width(),
buffer->damage_region.height());
wl_surface_attach(window->surface(), buffer->wl_buffer.get(), 0, 0);
static const wl_callback_listener frame_listener = {
......
......@@ -11,6 +11,7 @@
#include "base/containers/flat_map.h"
#include "base/files/file.h"
#include "base/macros.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/presentation_feedback.h"
#include "ui/gfx/swap_result.h"
......@@ -56,9 +57,12 @@ class WaylandBufferManager {
uint32_t buffer_id);
// 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,
uint32_t buffer_id,
const gfx::Rect& damage_region,
wl::BufferSwapCallback callback);
// Destroys a buffer with |buffer_id| in |buffers_|. On error, false is
......@@ -87,6 +91,11 @@ class WaylandBufferManager {
// Widget to attached/being attach WaylandWindow.
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.
gfx::SwapResult swap_result;
......
......@@ -187,9 +187,10 @@ void WaylandConnection::DestroyZwpLinuxDmabuf(uint32_t buffer_id) {
void WaylandConnection::ScheduleBufferSwap(
gfx::AcceleratedWidget widget,
uint32_t buffer_id,
const gfx::Rect& damage_region,
ScheduleBufferSwapCallback callback) {
DCHECK(base::MessageLoopForUI::IsCurrent());
if (!buffer_manager_->ScheduleBufferSwap(widget, buffer_id,
if (!buffer_manager_->ScheduleBufferSwap(widget, buffer_id, damage_region,
std::move(callback))) {
TerminateGpuProcess(buffer_manager_->error_message());
}
......
......@@ -61,6 +61,7 @@ class WaylandConnection : public PlatformEventSource,
// WaylandWindow with the specified |widget|.
void ScheduleBufferSwap(gfx::AcceleratedWidget widget,
uint32_t buffer_id,
const gfx::Rect& damage_region,
ScheduleBufferSwapCallback callback) override;
// Schedules a flush of the Wayland connection.
......
......@@ -234,8 +234,10 @@ GbmSurfacelessWayland* WaylandSurfaceFactory::GetSurface(
void WaylandSurfaceFactory::ScheduleBufferSwap(
gfx::AcceleratedWidget widget,
uint32_t buffer_id,
const gfx::Rect& damage_region,
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>
......
......@@ -7,13 +7,16 @@
#include "base/macros.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/single_thread_task_runner.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/public/surface_factory_ozone.h"
namespace gfx {
class Rect;
} // namespace gfx
namespace ui {
......@@ -28,6 +31,7 @@ class WaylandSurfaceFactory : public SurfaceFactoryOzone {
// These methods are used, when a dmabuf based approach is used.
void ScheduleBufferSwap(gfx::AcceleratedWidget widget,
uint32_t buffer_id,
const gfx::Rect& damage_region_,
wl::BufferSwapCallback callback);
void RegisterSurface(gfx::AcceleratedWidget widget,
GbmSurfacelessWayland* surface);
......
......@@ -11,6 +11,7 @@ mojom("wayland_interfaces") {
public_deps = [
"//mojo/public/mojom/base",
"//ui/gfx/geometry/mojo",
"//ui/gfx/mojo",
]
}
......@@ -6,6 +6,7 @@ module ui.ozone.mojom;
import "mojo/public/mojom/base/file.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/presentation_feedback.mojom";
import "ui/gfx/mojo/swap_result.mojom";
......@@ -28,7 +29,8 @@ interface WaylandConnection {
DestroyZwpLinuxDmabuf(uint32 buffer_id);
// 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.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