28
28
#include "micmap.h"
29
29
#include "miline.h"
30
30
#include "shmint.h"
31
+ #include "present_priv.h"
31
32
#include "misyncshm.h"
32
33
#include "glxserver.h"
33
34
#include "glxutil.h"
@@ -50,6 +51,7 @@ extern DeviceIntPtr lorieMouse, lorieKeyboard;
50
51
struct vblank {
51
52
struct xorg_list link ;
52
53
uint64_t id , msc ;
54
+ bool flip ;
53
55
};
54
56
55
57
static struct present_screen_info loriePresentInfo ;
@@ -60,6 +62,7 @@ typedef struct {
60
62
DamagePtr damage ;
61
63
OsTimerPtr fpsTimer ;
62
64
65
+ SetWindowPixmapProcPtr SetWindowPixmap ;
63
66
CloseScreenProcPtr CloseScreen ;
64
67
65
68
int eventFd , stateFd ;
@@ -94,7 +97,7 @@ static char *xstartup = NULL;
94
97
95
98
typedef struct {
96
99
LorieBuffer * buffer ;
97
- bool flipped , imported ;
100
+ bool flipped , wasLocked ;
98
101
void * locked ;
99
102
void * mem ;
100
103
} LoriePixmapPriv ;
@@ -392,14 +395,16 @@ static miPointerScreenFuncRec loriePointerCursorFuncs = {
392
395
.WarpCursor = miPointerWarpCursor
393
396
};
394
397
395
- static void loriePerformVblanks (void );
398
+ static void loriePerformVblanks (bool );
396
399
397
400
static Bool lorieRedraw (__unused ClientPtr pClient , __unused void * closure ) {
398
401
int status , nonEmpty ;
399
402
LoriePixmapPriv * priv ;
400
403
PixmapPtr root = pScreenPtr && pScreenPtr -> root ? pScreenPtr -> GetWindowPixmap (pScreenPtr -> root ) : NULL ;
401
404
402
- loriePerformVblanks ();
405
+ pvfb -> current_msc ++ ;
406
+ loriePerformVblanks (true);
407
+ loriePerformVblanks (false);
403
408
404
409
pvfb -> state -> waitForNextFrame = false;
405
410
@@ -419,10 +424,12 @@ static Bool lorieRedraw(__unused ClientPtr pClient, __unused void *closure) {
419
424
// and this is not needed. But according to docs we should do it for any case.
420
425
// Also according to AHardwareBuffer docs simultaneous reading in rendering thread and
421
426
// locking for writing in other thread is fine.
422
- LorieBuffer_unlock (priv -> buffer );
423
- status = LorieBuffer_lock (priv -> buffer , & priv -> locked );
424
- if (status )
425
- FatalError ("Failed to lock the surface: %d\n" , status );
427
+ if (priv -> locked ) {
428
+ LorieBuffer_unlock (priv -> buffer );
429
+ status = LorieBuffer_lock (priv -> buffer , & priv -> locked );
430
+ if (status )
431
+ FatalError ("Failed to lock the surface: %d\n" , status );
432
+ }
426
433
427
434
DamageEmpty (pvfb -> damage );
428
435
pvfb -> state -> drawRequested = TRUE;
@@ -472,6 +479,30 @@ static Bool lorieCloseScreen(ScreenPtr pScreen) {
472
479
return pScreen -> CloseScreen (pScreen );
473
480
}
474
481
482
+ void lorieSetWindowPixmap (WindowPtr pWindow , PixmapPtr newPixmap ) {
483
+ bool isRoot = pWindow == pScreenPtr -> root ;
484
+ PixmapPtr oldPixmap = isRoot ? pScreenPtr -> GetWindowPixmap (pWindow ) : NULL ;
485
+ LoriePixmapPriv * old , * new ;
486
+ if (isRoot ) {
487
+ old = LORIE_PIXMAP_PRIV_FROM_PIXMAP (oldPixmap );
488
+ new = LORIE_PIXMAP_PRIV_FROM_PIXMAP (newPixmap );
489
+ if (old && old -> buffer && old -> locked ) {
490
+ LorieBuffer_unlock (old -> buffer );
491
+ old -> locked = NULL ;
492
+ old -> wasLocked = false;
493
+ }
494
+ if (new && new -> buffer && !new -> locked ) {
495
+ LorieBuffer_lock (new -> buffer , & new -> locked );
496
+ new -> wasLocked = false;
497
+ }
498
+ }
499
+
500
+ pScreenPtr -> SetWindowPixmap = pvfb -> SetWindowPixmap ;
501
+ (* pScreenPtr -> SetWindowPixmap ) (pWindow , newPixmap );
502
+ pvfb -> SetWindowPixmap = pScreenPtr -> SetWindowPixmap ;
503
+ pScreenPtr -> SetWindowPixmap = lorieSetWindowPixmap ;
504
+ }
505
+
475
506
static int lorieSetPixmapVisitWindow (WindowPtr window , void * data ) {
476
507
ScreenPtr screen = window -> drawable .pScreen ;
477
508
@@ -487,6 +518,13 @@ static Bool lorieRRScreenSetSize(ScreenPtr pScreen, CARD16 width, CARD16 height,
487
518
PixmapPtr oldPixmap , newPixmap ;
488
519
BoxRec box = { 0 , 0 , width , height };
489
520
521
+ // Drain all pending vblanks.
522
+ loriePerformVblanks (true);
523
+ loriePerformVblanks (false);
524
+
525
+ // Restore root window pixmap.
526
+ present_restore_screen_pixmap (pScreenPtr );
527
+
490
528
SetRootClip (pScreen , ROOT_CLIP_NONE );
491
529
492
530
pScreen -> root -> drawable .width = pvfb -> root .width = pScreen -> width = width ;
@@ -623,7 +661,9 @@ static Bool lorieScreenInit(ScreenPtr pScreen, unused int argc, unused char **ar
623
661
return FALSE;
624
662
625
663
pvfb -> CloseScreen = pScreen -> CloseScreen ;
664
+ pvfb -> SetWindowPixmap = pScreenPtr -> SetWindowPixmap ;
626
665
pScreen -> CloseScreen = lorieCloseScreen ;
666
+ pScreen -> SetWindowPixmap = lorieSetWindowPixmap ;
627
667
628
668
ShmRegisterFbFuncs (pScreen );
629
669
miSyncShmScreenInit (pScreen );
@@ -702,20 +742,24 @@ static int loriePresentGetUstMsc(__unused RRCrtcPtr crtc, uint64_t *ust, uint64_
702
742
return Success ;
703
743
}
704
744
705
- static Bool loriePresentQueueVblank (__unused RRCrtcPtr crtc , uint64_t event_id , uint64_t msc ) {
745
+ static Bool loriePresentQueueVblankInternal (__unused RRCrtcPtr crtc , uint64_t event_id , uint64_t msc , bool flip ) {
706
746
#pragma clang diagnostic push
707
747
#pragma ide diagnostic ignored "MemoryLeak" // it is not leaked, it is destroyed in lorieRedraw
708
748
struct vblank * vblank = calloc (1 , sizeof (* vblank ));
709
749
if (!vblank )
710
750
return BadAlloc ;
711
751
712
- * vblank = (struct vblank ) { .id = event_id , .msc = msc };
752
+ * vblank = (struct vblank ) { .id = event_id , .msc = msc , . flip = flip };
713
753
xorg_list_add (& vblank -> link , & pvfb -> vblank_queue );
714
754
715
755
return Success ;
716
756
#pragma clang diagnostic pop
717
757
}
718
758
759
+ static Bool loriePresentQueueVblank (RRCrtcPtr crtc , uint64_t event_id , uint64_t msc ) {
760
+ return loriePresentQueueVblankInternal (crtc , event_id , msc , false);
761
+ }
762
+
719
763
static void loriePresentAbortVblank (__unused RRCrtcPtr crtc , uint64_t id , __unused uint64_t msc ) {
720
764
struct vblank * vblank , * tmp ;
721
765
@@ -728,16 +772,18 @@ static void loriePresentAbortVblank(__unused RRCrtcPtr crtc, uint64_t id, __unus
728
772
}
729
773
}
730
774
731
- static void loriePerformVblanks (void ) {
775
+ static void loriePerformVblanks (bool flip ) {
776
+ BoxRec box = { 0 , 0 , 1 , 1 }; // lorieRedraw only checks if it is empty or not.
732
777
struct vblank * vblank , * tmp ;
733
778
uint64_t ust , msc ;
734
- pvfb -> current_msc ++ ;
735
779
736
780
xorg_list_for_each_entry_safe (vblank , tmp , & pvfb -> vblank_queue , link ) {
737
- if (vblank -> msc <= pvfb -> current_msc ) {
781
+ if (vblank -> flip == flip && vblank -> msc <= pvfb -> current_msc ) {
738
782
loriePresentGetUstMsc (NULL , & ust , & msc );
739
783
present_event_notify (vblank -> id , ust , msc );
740
784
xorg_list_del (& vblank -> link );
785
+ if (flip )
786
+ RegionReset (DamageRegion (pvfb -> damage ), & box );
741
787
free (vblank );
742
788
}
743
789
}
@@ -764,17 +810,27 @@ Bool loriePresentCheckFlip(__unused RRCrtcPtr crtc, WindowPtr window, PixmapPtr
764
810
if (desc -> type != LORIEBUFFER_FD && desc -> type != LORIEBUFFER_AHARDWAREBUFFER )
765
811
return FALSE;
766
812
767
- /* currently not implemented */
768
- return FALSE;
813
+ lorieRegisterBuffer (priv -> buffer );
814
+ present_get_window_priv (window , true);
815
+ return TRUE;
816
+ }
817
+
818
+ Bool loriePerformFlips (__unused ClientPtr clientPtr , __unused void * closure ) {
819
+ loriePerformVblanks (true);
820
+ return TRUE;
769
821
}
770
822
771
823
Bool loriePresentFlip (__unused RRCrtcPtr crtc , uint64_t event_id , uint64_t target_msc , PixmapPtr pixmap , __unused Bool sync_flip ) {
772
- /* currently not implemented */
773
- return FALSE;
824
+ // Unfortunately we can not call present_event_notify inside of present_screen_info::flip
825
+ // So we queue new vblank and tell Xorg to process all vblanks immediately after processing client requests
826
+ loriePresentQueueVblankInternal (crtc , event_id , target_msc , true);
827
+ QueueWorkProc (loriePerformFlips , NULL , NULL );
828
+ lorieTriggerWorkingQueue ();
829
+ return true;
774
830
}
775
831
776
832
void loriePresentUnflip (__unused ScreenPtr screen , uint64_t event_id ) {
777
- /* currently not implemented */
833
+ present_event_notify ( event_id , 0 , 0 );
778
834
}
779
835
780
836
static struct present_screen_info loriePresentInfo = {
@@ -818,7 +874,7 @@ void *lorieCreatePixmap(__unused ScreenPtr pScreen, int width, int height, __unu
818
874
void lorieExaDestroyPixmap (__unused ScreenPtr pScreen , void * driverPriv ) {
819
875
LoriePixmapPriv * priv = driverPriv ;
820
876
if (priv -> buffer ) {
821
- if (! priv -> imported )
877
+ if (priv -> locked )
822
878
LorieBuffer_unlock (priv -> buffer );
823
879
LorieBuffer_release (priv -> buffer );
824
880
lorieUnregisterBuffer (priv -> buffer );
@@ -828,7 +884,7 @@ void lorieExaDestroyPixmap(__unused ScreenPtr pScreen, void *driverPriv) {
828
884
829
885
Bool lorieModifyPixmapHeader (PixmapPtr pPix , __unused int w , __unused int h , __unused int depth , __unused int bitsPerbppPixel , __unused int devKind , __unused void * data ) {
830
886
LoriePixmapPriv * priv = exaGetPixmapDriverPrivate (pPix );
831
- if (priv )
887
+ if (priv && data )
832
888
priv -> mem = data ;
833
889
return FALSE;
834
890
}
@@ -838,11 +894,17 @@ Bool loriePrepareAccess(PixmapPtr pPix, int index) {
838
894
if (index == EXA_PREPARE_DEST && pScreenPtr -> GetScreenPixmap (pScreenPtr ) == pPix )
839
895
lorie_mutex_lock (& pvfb -> state -> lock , & pvfb -> state -> lockingPid );
840
896
841
- if (priv -> imported ) {
842
- if (LorieBuffer_lock (priv -> buffer , & pPix -> devPrivate .ptr ))
897
+ if (!priv -> locked && !priv -> mem ) {
898
+ int err = LorieBuffer_lock (priv -> buffer , & priv -> locked );
899
+ if (err ) {
900
+ dprintf (2 , "Failed to lock buffer, err %d\n" , err );
843
901
return FALSE;
902
+ }
903
+ priv -> wasLocked = FALSE;
844
904
} else
845
- pPix -> devPrivate .ptr = priv -> locked ?: priv -> mem ;
905
+ priv -> wasLocked = TRUE;
906
+
907
+ pPix -> devPrivate .ptr = priv -> locked ?: priv -> mem ;
846
908
return TRUE;
847
909
}
848
910
@@ -851,8 +913,11 @@ void lorieFinishAccess(PixmapPtr pPix, int index) {
851
913
if (index == EXA_PREPARE_DEST && pScreenPtr -> GetScreenPixmap (pScreenPtr ) == pPix )
852
914
lorie_mutex_unlock (& pvfb -> state -> lock , & pvfb -> state -> lockingPid );
853
915
854
- if (priv -> imported )
916
+ if (! priv -> wasLocked ) {
855
917
LorieBuffer_unlock (priv -> buffer );
918
+ priv -> locked = NULL ;
919
+ priv -> wasLocked = FALSE;
920
+ }
856
921
}
857
922
858
923
static ExaDriverRec lorieExa = {
@@ -886,8 +951,6 @@ static PixmapPtr loriePixmapFromFds(ScreenPtr screen, CARD8 num_fds, const int *
886
951
priv = exaGetPixmapDriverPrivate (pixmap );
887
952
check (!priv , "DRI3: failed to obtain pixmap private" );
888
953
889
- priv -> imported = true;
890
-
891
954
if (modifier == DRM_FORMAT_MOD_INVALID || modifier == RAW_MMAPPABLE_FD ) {
892
955
check (!(priv -> buffer = LorieBuffer_wrapFileDescriptor (width , strides [0 ]/4 , height , AHARDWAREBUFFER_FORMAT_B8G8R8A8_UNORM , fds [0 ], offsets [0 ])), "DRI3: LorieBuffer_wrapAHardwareBuffer failed." );
893
956
screen -> ModifyPixmapHeader (pixmap , width , height , 0 , 0 , strides [0 ], NULL );
0 commit comments