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 }