1 module gfx.gl3.swapchain;
2 
3 import gfx.graal.device : Device;
4 import gfx.graal.presentation : Surface, Swapchain;
5 
6 final class GlSurface : Surface
7 {
8     import gfx.core.rc : atomicRcCode;
9 
10     mixin(atomicRcCode);
11 
12     private size_t _handle;
13 
14     this(size_t handle) {
15         _handle = handle;
16     }
17     override void dispose() {}
18 
19     @property size_t handle() {
20         return _handle;
21     }
22 }
23 
24 package final class GlSwapchain : Swapchain
25 {
26     import core.time                : Duration;
27     import gfx.core.rc              : atomicRcCode, Rc;
28     import gfx.gl3                  : GlShare;
29     import gfx.gl3.device           : GlDevice;
30     import gfx.gl3.resource         : GlImage;
31     import gfx.graal.format         : Format;
32     import gfx.graal.image          : ImageBase, ImageInfo, ImageUsage;
33     import gfx.graal.presentation   : CompositeAlpha, ImageAcquisition,
34                                       PresentMode;
35     import gfx.graal.sync           : Semaphore;
36 
37     mixin(atomicRcCode);
38 
39     Rc!Device _dev;
40     Rc!GlShare _share;
41     GlSurface _surface;
42     GlImage[] _imgs;
43     ImageBase[] _imgsB; // same objects, but already cast to interface (points to different addresses)
44     uint[2] _size;
45     Format _format;
46     uint _nextImg;
47 
48 
49     this (GlDevice device, GlShare share, Surface surface, PresentMode pm, uint numImages,
50           Format format, uint[2] size, ImageUsage usage, CompositeAlpha alpha,
51           Swapchain former=null)
52     {
53         _dev = device;
54         _share = share;
55         _surface = cast(GlSurface)surface;
56         _format = format;
57         _size = size;
58 
59         _imgs = new GlImage[numImages];
60         _imgsB = new ImageBase[numImages];
61         auto mem = device.allocateMemory(0, 1); // dummy memory
62         mem.retain();
63         foreach (i; 0 .. numImages) {
64             auto img = new GlImage(
65                 _dev.obj, _share, ImageInfo.d2(size[0], size[1]).withFormat(format).withUsage(usage)
66             );
67             img.bindMemory(mem, 0);
68 
69             _imgs[i] = img;
70             _imgsB[i] = cast(ImageBase)img;
71         }
72         mem.release();
73 
74         import gfx.core.rc : retainArr;
75         retainArr(_imgs);
76     }
77 
78     override void dispose() {
79         import gfx.core.rc : releaseArr;
80         releaseArr(_imgs);
81         _share.unload();
82         _dev.unload();
83     }
84 
85     override @property Device device() {
86         return _dev;
87     }
88 
89     override @property Format format() {
90         return _format;
91     }
92 
93     override @property ImageBase[] images() {
94         return _imgsB;
95     }
96 
97     override ImageAcquisition acquireNextImage(Semaphore semaphore,
98                                                Duration timeout)
99     {
100         const ni = _nextImg++;
101         if (_nextImg >= _imgs.length) _nextImg = 0;
102         return ImageAcquisition.makeOk(ni);
103     }
104 
105     @property GlSurface surface() {
106         return _surface;
107     }
108 
109     @property uint[2] size() {
110         return _size;
111     }
112 }