1 /*
2  *******************************************************************************************
3  * Dgame (a D game framework) - Copyright (c) Randy Schütt
4  * 
5  * This software is provided 'as-is', without any express or implied warranty.
6  * In no event will the authors be held liable for any damages arising from
7  * the use of this software.
8  * 
9  * Permission is granted to anyone to use this software for any purpose,
10  * including commercial applications, and to alter it and redistribute it
11  * freely, subject to the following restrictions:
12  * 
13  * 1. The origin of this software must not be misrepresented; you must not claim
14  *    that you wrote the original software. If you use this software in a product,
15  *    an acknowledgment in the product documentation would be appreciated but is
16  *    not required.
17  * 
18  * 2. Altered source versions must be plainly marked as such, and must not be
19  *    misrepresented as being the original software.
20  * 
21  * 3. This notice may not be removed or altered from any source distribution.
22  *******************************************************************************************
23  */
24 module Dgame.Window.DisplayMode;
25 
26 private:
27 
28 import derelict.sdl2.sdl;
29 
30 import Dgame.Math.Rect;
31 
32 import Dgame.Internal.Error;
33 
34 // All modes
35 DisplayMode[][] modes;
36 
37 package(Dgame):
38 
39 @nogc
40 SDL_DisplayMode* _transfer(ref const DisplayMode mode, ref SDL_DisplayMode sdl_mode) pure nothrow {
41     sdl_mode.w = mode.width;
42     sdl_mode.h = mode.height;
43     sdl_mode.refresh_rate = mode.refreshRate;
44 
45     return &sdl_mode;
46 }
47 
48 public:
49 
50 /**
51  * The DisplayMode struct contains informations about the current window video mode.
52  * It is passed to Window which extract the informations and use them to build a window context.
53  * 
54  * Author: Randy Schuett (rswhite4@googlemail.com)
55  */
56 struct DisplayMode {
57     /**
58      * The width of this video mode
59      */
60     uint width;
61     /**
62      * The height of this video mode
63      */
64     uint height;
65     /**
66      * The refresh rate of this video mode
67      */
68     ubyte refreshRate;
69     
70     /**
71      * CTor
72      */
73     @nogc
74     this(uint width, uint height, ubyte hz = 60) pure nothrow {
75         this.width  = width;
76         this.height = height;
77         this.refreshRate = hz;
78     }
79     
80     /**
81      * opEquals
82      */
83     @nogc
84     bool opEquals(ref const DisplayMode dm) const pure nothrow {
85         return dm.width == this.width && dm.height == this.height && dm.refreshRate == this.refreshRate;
86     }
87     
88     /**
89      * Returns the desktop video mode at the given display
90      *
91      * Note: There's a difference between this and getMode when your application runs in fullscreen 
92      *       and has changed the resolution. In that case this function will return the previous
93      *       native display mode, and not the current display mode.
94      */
95     @nogc
96     static DisplayMode getDesktopMode(ubyte display = 0) nothrow {
97         SDL_DisplayMode mode = void;
98         immutable int result = SDL_GetDesktopDisplayMode(display, &mode);
99         if (result != 0)
100             print_fmt("An error occured: %s\n", SDL_GetError());
101         
102         return DisplayMode(mode.w, mode.h, cast(ubyte) mode.refresh_rate);
103     }
104     
105     /**
106      * Returns the video mode at the given index and display
107      */
108     @nogc
109     static DisplayMode getMode(uint index, ubyte display = 0) nothrow {
110         SDL_DisplayMode mode = void;
111         immutable int result = SDL_GetDisplayMode(display, index, &mode);
112         if (result != 0)
113             print_fmt("An error occured: %s\n", SDL_GetError());
114         
115         return DisplayMode(mode.w, mode.h, cast(ubyte) mode.refresh_rate);
116     }
117 
118     /**
119      * Returns the current video mode at the given display
120      */
121     @nogc
122     static DisplayMode getCurrentMode(ubyte display = 0) nothrow {
123         SDL_DisplayMode mode = void;
124         immutable int result = SDL_GetCurrentDisplayMode(display, &mode);
125         if (result != 0)
126             print_fmt("An error occured: %s\n", SDL_GetError());
127         
128         return DisplayMode(mode.w, mode.h, cast(ubyte) mode.refresh_rate);
129     }
130     
131     /**
132      * Returns a List of all valid supported video modes at the given display
133      */
134     static DisplayMode[] listModes(ubyte display = 0) nothrow {
135         if (modes.length == 0) {
136             immutable int nod = DisplayMode.getNumOfDisplays();
137             modes = new DisplayMode[][](nod);
138         }
139         
140         if (modes[display].length != 0)
141             return modes[display];
142         
143         immutable int num = DisplayMode.getNumOfModes(display);
144         modes[display] = new DisplayMode[](num);
145 
146         for (int i = 0; i < num; ++i) {
147             modes[display][i] = DisplayMode.getMode(i, display);
148         }
149         
150         return modes[display];
151     }
152 
153     /**
154      * Returns the desktop area represented by the given display, with the primary display located at 0|0.
155      */
156     @nogc
157     static Rect getDisplayBounds(ubyte display = 0) nothrow {
158         SDL_Rect rect = void;
159         SDL_GetDisplayBounds(display, &rect);
160 
161         return Rect(rect.x, rect.y, rect.w, rect.h);
162     }
163 
164     /**
165      * Returns the name of the given display
166      */
167     @nogc
168     static string getDisplayName(ubyte display = 0) nothrow {
169         import core.stdc..string : strlen;
170 
171         const char* p = SDL_GetDisplayName(display);
172         if (!p)
173             return null;
174 
175         return cast(immutable) p[0 .. strlen(p)];
176     }
177     
178     /**
179      * Returns how many valid display modes are supported at the given display
180      */
181     @nogc
182     static int getNumOfModes(ubyte display = 0) nothrow {
183         return SDL_GetNumDisplayModes(display);
184     }
185     
186     /**
187      * Returns how many display are available.
188      */
189     @nogc
190     static int getNumOfDisplays() nothrow {
191         return SDL_GetNumVideoDisplays();
192     }
193 
194     /**
195      * Returns how many video drivers are available.
196      */
197     @nogc
198     static int getNumOfVideoDrivers() nothrow {
199         return SDL_GetNumVideoDrivers();
200     }
201 
202     /**
203      * Returns the name of the current video driver.
204      */
205     @nogc
206     static string getCurrentVideoDriver() nothrow {
207         import core.stdc..string : strlen;
208 
209         const char* p = SDL_GetCurrentVideoDriver();
210         if (!p)
211             return null;
212 
213         return cast(immutable) p[0 .. strlen(p)];
214     }
215 }