1 module output;
2 
3 import compositor;
4 import wayland.server;
5 
6 import std.stdio;
7 import core.time;
8 
9 
10 class Output : WlOutput
11 {
12     private Compositor _comp;
13 
14     private uint _mask;
15     private bool _repaintNeeded;
16     private bool _repaintScheduled;
17     private WlTimerEventSource _repaintTimer;
18     private WlTimerEventSource _finishFrameTimer;
19     private MonoTime _startRepaint;
20     enum refreshNsecs = 1_000_000_000 / 60;
21 
22 
23     this(Compositor comp)
24     {
25         _comp = comp;
26         super(comp.display, 3);
27         _repaintTimer = _comp.display.eventLoop.addTimer(&timerRepaint);
28         _finishFrameTimer = _comp.display.eventLoop.addTimer(() {
29             finishFrame(_startRepaint);
30             return 1;
31         });
32 
33     }
34 
35     abstract @property int width();
36     abstract @property int height();
37     abstract @property uint[] buf();
38     abstract void blitBuf();
39 
40     @property uint mask()
41     {
42         return _mask;
43     }
44 
45     @property void mask(uint mask)
46     {
47         _mask = mask;
48     }
49 
50     void scheduleRepaint()
51     {
52         _repaintNeeded = true;
53         if (_repaintScheduled) return;
54         _comp.display.eventLoop.addIdle(&idleRepaint);
55         _repaintScheduled = true;
56     }
57 
58     void idleRepaint()
59     {
60         startRepaintLoop();
61     }
62 
63     void startRepaintLoop()
64     {
65         finishFrame(MonoTime.currTime);
66     }
67 
68     void finishFrame(MonoTime stamp)
69     {
70         auto now = MonoTime.currTime;
71         auto gone = now - stamp;
72         auto msecs = (refreshNsecs - gone.total!"nsecs")/1000000;
73 
74         if (msecs < 1) {
75             timerRepaint();
76         }
77         else {
78             _repaintTimer.update(cast(uint)msecs);
79         }
80     }
81 
82     int timerRepaint()
83     {
84         _startRepaint = MonoTime.currTime;
85 
86         auto w = width;
87         auto h = height;
88         auto b = buf;
89 
90         // background: a 32*32 grid
91         foreach (c; 0 .. w)
92         {
93             foreach (r; 0 .. h)
94             {
95                 if (r % 32 == 0 || c % 32 == 0)
96                 {
97                     b[r*w + c] = 0;
98                 }
99                 else
100                 {
101                     b[r*w + c] = 0xffffffff;
102                 }
103             }
104         }
105 
106         _comp.shell.paint(this);
107 
108         blitBuf();
109         _finishFrameTimer.update(10);
110         return 1;
111     }
112 
113     // WlOutput
114     override void release(WlClient cl, Resource res)
115     {}
116 }