Skip to content

Commit

Permalink
Use a helper wpe_fdo_rect type for damage regions
Browse files Browse the repository at this point in the history
Instead of a series of groups of four integer values, group each damage
entry in a wpe_fdo_rect instance, which defines a rectangle explicitly
documented to use the origin of coordinates at the top-left corner of
exported images.

This approach is more readable, uses the same amount of memory, allows
defining the wpe_fdo_egl_exported_image_get_damage_regions() function in
a more idiomatic way (returning pointer to rect array, and receiving a
pointer where to store the number of entries), simplifies the code that
returns the damage rectangle list, and also the code that stores a
damage rectangle (also improved by using emplace+move).

While at it, document wpe_fdo_egl_exported_image_get_damage_regions()
and the new wpe_fdo_rect type.
  • Loading branch information
aperezdc committed Mar 16, 2024
1 parent 11b4e6d commit f236deb
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 30 deletions.
61 changes: 59 additions & 2 deletions include/wpe/exported-image-egl.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,22 @@ typedef void* EGLImageKHR;

struct wpe_fdo_egl_exported_image;

/**
* wpe_fdo_rect:
* @x: Horizontal position.
* @y: Vertical position.
* @width: Rectange width.
* @height: Rectangle height.
*
* Describes the position and size of a rectangle.
*
* This is used to report damaged regions for exported images.
* The origin of coordinates is at the top-left corner of the image.
*/
struct wpe_fdo_rect {
uint32_t x, y, width, height;
};

/**
* wpe_fdo_egl_exported_image_get_width:
* @image: (transfer none): An exported EGL image.
Expand Down Expand Up @@ -85,8 +101,49 @@ wpe_fdo_egl_exported_image_get_height(struct wpe_fdo_egl_exported_image *image);
EGLImageKHR
wpe_fdo_egl_exported_image_get_egl_image(struct wpe_fdo_egl_exported_image *image);

uint32_t
wpe_fdo_egl_exported_image_get_damage_regions(struct wpe_fdo_egl_exported_image*, const int32_t**);
/**
* wpe_fdo_egl_exported_image_get_damage_regions:
* @image: (transfer none): An exported EGL image.
* @n_rectangles: (transfer none) (out) (not nullable): Location where to store the number of rectangles.
*
* Gets rectangles describing the damage regions for an @image.
*
* Images may indicate which parts have changed since the previous exported
* image. If the set of damaged regions cannot be determined, then `NULL` is
* returned and @n_regions set to zero. This may be the case if:
*
* - The image contains many changes compared to the previous exported image
* and it is considered that it is not worth it using damage regions.
* - Some component in the graphics stack is not able to handle damage
* regions.
*
* When the set of regions is empty, the whole image **must** be considered
* to be changed.
*
* **Important:** Damage regions are only meaningful when an image is used
* to be displayed right after the one exported immediately before it! In
* particular, if an exported image is kept around to be displayed later,
* and not at the moment when it has been exported, damage information *must
* not* be used.
*
* Note that the layout of the `wpe_fdo_rect` type is designed in such a way
* that the result from this function may be passed directly to EGL for
* swapping buffers:
*
* ```c
* struct wpe_fdo_egl_exported_image *image = get_image();
*
* uint32_t n_regions;
* const struct wpe_fdo_rect *regions =
* wpe_fdo_egl_exported_image_get_damage_regions(image, &n_regions);
*
* eglSwapBuffersWithDamageEXT(eglDisplay, eglSurface, (EGLint*) regions, n_regions);
* ```
*
* Returns: (transfer none) (nullable): Pointer to an array of regions.
*/
const struct wpe_fdo_rect*
wpe_fdo_egl_exported_image_get_damage_regions(struct wpe_fdo_egl_exported_image*, uint32_t *n_rectangles);

#ifdef __cplusplus
}
Expand Down
15 changes: 12 additions & 3 deletions src/exported-image-egl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,19 @@ wpe_fdo_egl_exported_image_get_egl_image(struct wpe_fdo_egl_exported_image* imag
}

__attribute__((visibility("default")))
uint32_t
wpe_fdo_egl_exported_image_get_damage_regions(struct wpe_fdo_egl_exported_image* image, const int32_t** target)
const struct wpe_fdo_rect*
wpe_fdo_egl_exported_image_get_damage_regions(struct wpe_fdo_egl_exported_image *image, uint32_t *n_rectangles)
{
return WS::Instance::singleton().exportDamageRegions(image->bufferResource, target);
g_return_val_if_fail(n_rectangles, nullptr);

const auto* regions = WS::Instance::singleton().getDamageRegions(image->bufferResource);
if (regions && regions->size()) {
*n_rectangles = regions->size();
return regions->data();
} else {
*n_rectangles = 0;
return nullptr;
}
}

}
36 changes: 14 additions & 22 deletions src/ws.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -693,44 +693,36 @@ bool Instance::dispatchFrameCallbacks(uint32_t bridgeId)
return it->second->dispatchFrameCallbacks();
}

void Instance::addBufferDamageRegion(struct wl_resource *surfaceResource, int32_t x, int32_t y, int32_t width, int32_t height)
void Instance::addBufferDamageRegion(struct wl_resource *surfaceResource, uint32_t x, uint32_t y, uint32_t width, uint32_t height)
{
if (!surfaceResource)
return;

auto key = surfaceResource;
std::array<int32_t, 4> region = {x, y, width, height};
auto it = m_damageRegions.find(key);

wpe_fdo_rect rect {x, y, width, height};
auto it = m_damageRegions.find(surfaceResource);
if (it == m_damageRegions.end()) {
std::vector<std::array<int32_t, 4>> vec = {};
m_damageRegions.insert(std::make_pair(key, vec));
it = m_damageRegions.find(key);
std::vector<struct wpe_fdo_rect> regions = { std::move(rect) };
m_damageRegions.emplace(surfaceResource, std::move(regions));
} else {
it->second.emplace_back(std::move(rect));
}

auto& vec = it->second;
vec.push_back(region);
}

void Instance::clearPendingBufferDamage(struct wl_resource* bufferResource)
{
m_damageRegions.erase(bufferResource);
}

uint32_t Instance::exportDamageRegions(struct wl_resource* bufferResource, const int32_t** target)
const std::vector<struct wpe_fdo_rect>* Instance::getDamageRegions(struct wl_resource* bufferResource)
{
if (!bufferResource) {
*target = nullptr;
return 0;
}
if (!bufferResource)
return nullptr;

auto it = m_damageRegions.find(bufferResource);
if (it == m_damageRegions.cend() || it->second.empty() || !it->second.data()) {
*target = nullptr;
return 0;
}
*target = reinterpret_cast<int32_t*>(it->second.data());
return it->second.size();
if (it == m_damageRegions.cend())
return nullptr;

return &it->second;
}

} // namespace WS
7 changes: 4 additions & 3 deletions src/ws.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

#pragma once

#include "../include/wpe/exported-image-egl.h"
#include "ws-types.h"
#include <functional>
#include <glib.h>
Expand Down Expand Up @@ -153,9 +154,9 @@ class Instance {

void registerSurface(uint32_t, Surface*);
void unregisterSurface(Surface*);
void addBufferDamageRegion(struct wl_resource*, int32_t x, int32_t y, int32_t width, int32_t height);
void addBufferDamageRegion(struct wl_resource*, uint32_t x, uint32_t y, uint32_t width, uint32_t height);
void clearPendingBufferDamage(struct wl_resource*);
uint32_t exportDamageRegions(struct wl_resource*, const int32_t** target);
const std::vector<struct wpe_fdo_rect>* getDamageRegions(struct wl_resource* bufferResource);
void registerViewBackend(uint32_t, APIClient&);
void unregisterViewBackend(uint32_t);
bool dispatchFrameCallbacks(uint32_t);
Expand Down Expand Up @@ -192,7 +193,7 @@ class Instance {
struct wl_global* m_wpeBridge { nullptr };
struct wl_global* m_wpeDmabufPoolManager { nullptr };
GSource* m_source { nullptr };
std::unordered_map<struct wl_resource*, std::vector<std::array<int32_t, 4>>> m_damageRegions;
std::unordered_map<struct wl_resource*, std::vector<struct wpe_fdo_rect>> m_damageRegions;

// (bridgeId -> Surface)
std::unordered_map<uint32_t, Surface*> m_viewBackendMap;
Expand Down

0 comments on commit f236deb

Please sign in to comment.