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