1 /**
2 * TODO
3 */
4 module dash.graphics.adapters.linux;
5 
6 version( linux ):
7 
8 import dash.core, dash.graphics, dash.utility;
9 
10 import x11.X, x11.Xlib, x11.Xutil;
11 public import derelict.opengl3.glx;
12 import derelict.opengl3.gl3, derelict.opengl3.glxext;
13 
14 import std.traits;
15 
16 /**
17 * TODO
18 */
19 final class Linux : OpenGL
20 {
21 private:
22     // Because the XVisualStyle type returned from this function is
23     // seemingly not defined, we can get it with templates.
24     alias PointerTarget!(ReturnType!(glXChooseVisual)) GLXVisualInfo;
25 
26     /// Events we want to listen for
27     enum EventMask = ExposureMask | KeyPressMask;
28 
29     /// The display to render to.
30     Display* display;
31     Window root;
32     Window window;
33     GLXContext context;
34     XSetWindowAttributes windowAttributes;
35     XVisualInfo* xvi;
36     GLXVisualInfo* glvi;
37     Colormap cmap;
38 
39 public:
40 
41     /// TODO
42     static @property Linux get() { return cast(Linux)Graphics.adapter; }
43 
44     /**
45     * TODO
46     */
47     override void initialize()
48     {
49         // Load opengl functions
50         DerelictGL3.load();
51 
52         int[ 10 ] attrList =
53         [
54             GLX_RGBA,
55             GLX_RED_SIZE, 4,
56             GLX_GREEN_SIZE, 4,
57             GLX_BLUE_SIZE, 4,
58             GLX_DEPTH_SIZE, 16,
59             None
60         ];
61 
62         int screen;
63 
64         // Get display and screen
65         display = XOpenDisplay( null );
66         screen = DefaultScreen( display );
67 
68         // Setup the window
69         screenWidth = DisplayWidth( display, screen );
70         screenHeight = DisplayHeight( display, screen );
71 
72         loadProperties();
73 
74         if( display is null )
75         {
76             logFatal( "Cannot connect to X server." );
77             return;
78         }
79 
80         // Get root monitor window
81         root = DefaultRootWindow( display );
82 
83         // Chose visual based on attributes and display
84         glvi = glXChooseVisual( display, 0, attrList.ptr );
85         xvi = cast(XVisualInfo*)glvi;
86 
87         if( xvi is null )
88         {
89             logFatal( "No appropriate visual found." );
90             return;
91         }
92 
93         cmap = XCreateColormap( display, root, xvi.visual, AllocNone );
94 
95         // Set attributes for window
96         windowAttributes.colormap = cmap;
97         windowAttributes.event_mask = EventMask;
98 
99         openWindow();
100 
101         // Get address of gl functions
102         DerelictGL3.reload();
103     }
104 
105     /**
106     * TODO
107     */
108     override void shutdown()
109     {
110         closeWindow();
111         XCloseDisplay( display );
112     }
113 
114     /**
115     * TODO
116     */
117     override void resize()
118     {
119         XResizeWindow( display, window, width, height );
120         glViewport( 0, 0, width, height );
121     }
122 
123     /**
124     * TODO
125     */
126     override void refresh()
127     {
128         resize();
129 
130         // Enable back face culling
131         if( backfaceCulling )
132         {
133             glEnable( GL_CULL_FACE );
134             glCullFace( GL_BACK );
135         }
136 
137         // Turn on of off the v sync
138         glXSwapIntervalEXT( display, glXGetCurrentDrawable(), vsync );
139     }
140 
141     /**
142     * TODO
143     */
144     override void swapBuffers()
145     {
146         glXSwapBuffers( display, cast(uint)window );
147     }
148 
149     /**
150     * TODO
151     */
152     override void openWindow()
153     {
154         window = XCreateWindow(
155             display, root,
156             0, 0, width, height, 0,
157             xvi.depth, InputOutput, xvi.visual,
158             CWColormap | CWEventMask, &windowAttributes );
159 
160         XMapWindow( display, window );
161         XStoreName( display, window, DGame.instance.title.dup.ptr );
162 
163         context = glXCreateContext( display, glvi, null, GL_TRUE );
164         glXMakeCurrent( display, cast(uint)window, context );
165     }
166 
167     /**
168     * TODO
169     */
170     override void closeWindow()
171     {
172         glXMakeCurrent( display, None, null );
173         glXDestroyContext( display, context );
174         XDestroyWindow( display, window );
175     }
176 
177     /**
178     * TODO
179     */
180     override void messageLoop()
181     {
182         XEvent event;
183         while( XCheckWindowEvent( display, window, EventMask, &event ) )
184         {
185             switch( event.type )
186             {
187                 case KeyPress:
188                     break;
189                 case Expose:
190                     break;
191                 default:
192                     break;
193             }
194         }
195     }
196 }