37
37
#include < wtf/FastMalloc.h>
38
38
#include < wtf/OptionSet.h>
39
39
#include < wtf/RunLoop.h>
40
+ #include < wtf/SafeStrerror.h>
40
41
#include < wtf/Seconds.h>
41
42
#include < wtf/glib/GRefPtr.h>
42
43
#include < wtf/glib/WTFGType.h>
@@ -57,6 +58,7 @@ struct _WPEViewDRMPrivate {
57
58
std::optional<uint32_t > modeBlob;
58
59
GRefPtr<WPEBuffer> pendingBuffer;
59
60
GRefPtr<WPEBuffer> committedBuffer;
61
+ Vector<drm_mode_rect> damageRects;
60
62
drmEventContext eventContext;
61
63
GRefPtr<GSource> eventSource;
62
64
OptionSet<UpdateFlags> updateFlags;
@@ -247,10 +249,11 @@ WPE::DRM::Plane::Properties emptyPlaneProperties(const WPE::DRM::Plane& plane)
247
249
properties.srcY .second = 0 ;
248
250
properties.srcW .second = 0 ;
249
251
properties.srcH .second = 0 ;
252
+ properties.fbDamageClips .second = 0 ;
250
253
return properties;
251
254
}
252
255
253
- WPE::DRM::Plane::Properties primaryPlaneProperties (const WPE::DRM::Plane& plane, uint32_t crtcID, drmModeModeInfo* mode, const WPE::DRM::Buffer& buffer)
256
+ WPE::DRM::Plane::Properties primaryPlaneProperties (const WPE::DRM::Plane& plane, uint32_t crtcID, drmModeModeInfo* mode, const WPE::DRM::Buffer& buffer, std::optional< uint32_t > damageID )
254
257
{
255
258
auto properties = plane.properties ();
256
259
properties.crtcID .second = crtcID;
@@ -263,6 +266,8 @@ WPE::DRM::Plane::Properties primaryPlaneProperties(const WPE::DRM::Plane& plane,
263
266
properties.srcY .second = 0 ;
264
267
properties.srcW .second = (static_cast <uint64_t >(gbm_bo_get_width (buffer.bufferObject ())) << 16 );
265
268
properties.srcH .second = (static_cast <uint64_t >(gbm_bo_get_height (buffer.bufferObject ())) << 16 );
269
+ if (properties.fbDamageClips .first && damageID)
270
+ properties.fbDamageClips .second = damageID.value ();
266
271
return properties;
267
272
}
268
273
@@ -294,10 +299,12 @@ static bool addPlaneProperties(drmModeAtomicReq* request, const WPE::DRM::Plane&
294
299
success &= drmAtomicAddProperty (request, plane.id (), properties.srcY );
295
300
success &= drmAtomicAddProperty (request, plane.id (), properties.srcW );
296
301
success &= drmAtomicAddProperty (request, plane.id (), properties.srcH );
302
+ if (properties.fbDamageClips .first )
303
+ success &= drmAtomicAddProperty (request, plane.id (), properties.fbDamageClips );
297
304
return success;
298
305
}
299
306
300
- static bool wpeViewDRMCommitAtomic (WPEViewDRM* view, WPE::DRM::Buffer* buffer, GError** error)
307
+ static bool wpeViewDRMCommitAtomic (WPEViewDRM* view, WPE::DRM::Buffer* buffer, std::optional< uint32_t > damageID, GError** error)
301
308
{
302
309
WPE::DRM::UniquePtr<drmModeAtomicReq> request (drmModeAtomicAlloc ());
303
310
uint32_t flags = DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_NONBLOCK;
@@ -312,8 +319,9 @@ static bool wpeViewDRMCommitAtomic(WPEViewDRM* view, WPE::DRM::Buffer* buffer, G
312
319
313
320
if (!view->priv ->modeBlob ) {
314
321
uint32_t blobID;
315
- if (drmModeCreatePropertyBlob (fd, mode, sizeof (drmModeModeInfo), &blobID) == -1 ) {
316
- g_set_error_literal (error, WPE_VIEW_ERROR, WPE_VIEW_ERROR_RENDER_FAILED, " Failed to render buffer: failed to crate blob from DRM mode" );
322
+ auto result = drmModeCreatePropertyBlob (fd, mode, sizeof (drmModeModeInfo), &blobID);
323
+ if (result < 0 ) {
324
+ g_set_error (error, WPE_VIEW_ERROR, WPE_VIEW_ERROR_RENDER_FAILED, " Failed to render buffer: failed to crate blob from DRM mode: %s" , safeStrerror (-result).data ());
317
325
return false ;
318
326
}
319
327
@@ -330,7 +338,7 @@ static bool wpeViewDRMCommitAtomic(WPEViewDRM* view, WPE::DRM::Buffer* buffer, G
330
338
}
331
339
332
340
auto & plane = wpeDisplayDRMGetPrimaryPlane (display);
333
- if (!addPlaneProperties (request.get (), plane, buffer ? primaryPlaneProperties (plane, crtc.id (), mode, *buffer) : emptyPlaneProperties (plane))) {
341
+ if (!addPlaneProperties (request.get (), plane, buffer ? primaryPlaneProperties (plane, crtc.id (), mode, *buffer, damageID ) : emptyPlaneProperties (plane))) {
334
342
g_set_error_literal (error, WPE_VIEW_ERROR, WPE_VIEW_ERROR_RENDER_FAILED, " Failed to render buffer: failed to set plane properties" );
335
343
return false ;
336
344
}
@@ -382,18 +390,50 @@ static std::pair<uint32_t, uint64_t> wpeBufferFormat(WPEBuffer* buffer)
382
390
return { DRM_FORMAT_INVALID, DRM_FORMAT_MOD_INVALID };
383
391
}
384
392
393
+ static std::optional<uint32_t > buildDamageBlob (WPEDisplayDRM* display, const Vector<drm_mode_rect>& damageRects, GError** error)
394
+ {
395
+ if (damageRects.isEmpty ())
396
+ return std::nullopt;
397
+
398
+ uint32_t blobID;
399
+ int fd = gbm_device_get_fd (wpe_display_drm_get_device (display));
400
+ auto result = drmModeCreatePropertyBlob (fd, damageRects.data (), damageRects.sizeInBytes (), &blobID);
401
+ if (result < 0 ) {
402
+ g_set_error (error, WPE_VIEW_ERROR, WPE_VIEW_ERROR_RENDER_FAILED, " Failed to render buffer: failed to crate damage blob: %s" , safeStrerror (-result).data ());
403
+ return 0 ;
404
+ }
405
+
406
+ return blobID;
407
+ }
408
+
409
+ static void destroyDamageBlob (WPEDisplayDRM* display, uint32_t blobID)
410
+ {
411
+ int fd = gbm_device_get_fd (wpe_display_drm_get_device (display));
412
+ drmModeDestroyPropertyBlob (fd, blobID);
413
+ }
414
+
385
415
static gboolean wpeViewDRMRequestUpdate (WPEViewDRM* view, GError** error)
386
416
{
387
417
auto * priv = view->priv ;
388
418
auto * buffer = priv->pendingBuffer ? priv->pendingBuffer .get () : priv->committedBuffer .get ();
389
419
auto * drmBuffer = buffer ? static_cast <WPE::DRM::Buffer*>(wpe_buffer_get_user_data (buffer)) : nullptr ;
390
- if (wpe_display_drm_supports_atomic (WPE_DISPLAY_DRM (wpe_view_get_display (WPE_VIEW (view)))))
391
- return wpeViewDRMCommitAtomic (WPE_VIEW_DRM (view), drmBuffer, error);
420
+ auto * display = WPE_DISPLAY_DRM (wpe_view_get_display (WPE_VIEW (view)));
421
+ if (wpe_display_drm_supports_atomic (display)) {
422
+ auto damageID = drmBuffer ? buildDamageBlob (display, priv->damageRects , error) : std::nullopt;
423
+ if (damageID.has_value () && !damageID.value ())
424
+ return FALSE ;
425
+
426
+ auto result = wpeViewDRMCommitAtomic (WPE_VIEW_DRM (view), drmBuffer, damageID, error);
427
+ if (damageID)
428
+ destroyDamageBlob (display, damageID.value ());
429
+ priv->damageRects .clear ();
430
+ return result;
431
+ }
392
432
393
433
return wpeViewDRMCommitLegacy (WPE_VIEW_DRM (view), *drmBuffer, error);
394
434
}
395
435
396
- static gboolean wpeViewDRMRenderBuffer (WPEView* view, WPEBuffer* buffer, const WPERectangle*, guint, GError** error)
436
+ static gboolean wpeViewDRMRenderBuffer (WPEView* view, WPEBuffer* buffer, const WPERectangle* damageRects , guint nDamageRects , GError** error)
397
437
{
398
438
auto * drmBuffer = static_cast <WPE::DRM::Buffer*>(wpe_buffer_get_user_data (buffer));
399
439
if (!drmBuffer) {
@@ -411,6 +451,10 @@ static gboolean wpeViewDRMRenderBuffer(WPEView* view, WPEBuffer* buffer, const W
411
451
}
412
452
auto * priv = WPE_VIEW_DRM (view)->priv ;
413
453
priv->pendingBuffer = buffer;
454
+ priv->damageRects .clear ();
455
+ priv->damageRects .reserveInitialCapacity (nDamageRects);
456
+ for (unsigned i = 0 ; i < nDamageRects; ++i)
457
+ priv->damageRects .append ({ damageRects[i].x , damageRects[i].y , damageRects[i].x + damageRects[i].width , damageRects[i].y + damageRects[i].height });
414
458
415
459
if (priv->updateFlags .contains (UpdateFlags::CursorUpdateRequested)) {
416
460
priv->updateFlags .add (UpdateFlags::BufferUpdatePending);
0 commit comments