1 /*
2  * DSFML - The Simple and Fast Multimedia Library for D
3  *
4  * Copyright (c) 2013 - 2017 Jeremy DeHaan (dehaan.jeremiah@gmail.com)
5  *
6  * This software is provided 'as-is', without any express or implied warranty.
7  * In no event will the authors be held liable for any damages arising from the
8  * use of this software.
9  *
10  * Permission is granted to anyone to use this software for any purpose,
11  * including commercial applications, and to alter it and redistribute it
12  * freely, subject to the following restrictions:
13  *
14  * 1. The origin of this software must not be misrepresented; you must not claim
15  * that you wrote the original software. If you use this software in a product,
16  * an acknowledgment in the product documentation would be appreciated but is
17  * not required.
18  *
19  * 2. Altered source versions must be plainly marked as such, and must not be
20  * misrepresented as being the original software.
21  *
22  * 3. This notice may not be removed or altered from any source distribution
23  */
24 
25 /**
26  * A video mode is defined by a width and a height (in pixels) and a depth (in
27  * bits per pixel). Video modes are used to setup windows ($(WINDOW_LINK)) at
28  * creation time.
29  *
30  * The main usage of video modes is for fullscreen mode: indeed you must use one
31  * of the valid video modes allowed by the OS (which are defined by what the
32  * monitor and the graphics card support), otherwise your window creation will
33  *
34  * $(U VideoMode) provides a static function for retrieving the list of all the
35  * video modes supported by the system: `getFullscreenModes()`.
36  *
37  * A custom video mode can also be checked directly for fullscreen compatibility
38  * with its `isValid()` function.
39  *
40  * Additionnally, $(U VideoMode) provides a static function to get the mode
41  * currently used by the desktop: `getDesktopMode()`. This allows to build
42  * windows with the same size or pixel depth as the current resolution.
43  *
44  * Example:
45  * ---
46  * // Display the list of all the video modes available for fullscreen
47  * auto modes = VideoMode.getFullscreenModes();
48  * for (size_t i = 0; i < modes.length; ++i)
49  * {
50  *     VideoMode mode = modes[i];
51  *     writeln("Mode #", i, ": ",
52  * 	           mode.width, "x", mode.height, " - ",
53  *             mode.bitsPerPixel, " bpp");
54  * }
55  *
56  * // Create a window with the same pixel depth as the desktop
57  * VideoMode desktop = VideoMode.getDesktopMode();
58  * window.create(VideoMode(1024, 768, desktop.bitsPerPixel), "DSFML window");
59  * ---
60  */
61 module dsfml.window.videomode;
62 
63 /**
64  * VideoMode defines a video mode (width, height, bpp).
65  */
66 struct VideoMode
67 {
68 	///Video mode width, in pixels.
69 	uint width;
70 	///Video mode height, in pixels.
71 	uint height;
72 	///Video mode pixel depth, in bits per pixels.
73 	uint bitsPerPixel;
74 
75 	/**
76 	 * Construct the video mode with its attributes.
77 	 *
78 	 * Params:
79      * 		modeWidth = Width in pixels
80      * 		modeHeight = Height in pixels
81      * 		modeBitsPerPixel = Pixel depths in bits per pixel
82 	 */
83 	this(uint Width, uint Height, uint bits= 32)
84 	{
85 		width = Width;
86 		height = Height;
87 		bitsPerPixel = bits;
88 	}
89 
90 	/**
91 	 * Get the current desktop video mode.
92 	 *
93 	 * Returns: Current desktop video mode.
94 	 */
95 	static VideoMode getDesktopMode()
96 	{
97 		VideoMode temp;
98 		sfVideoMode_getDesktopMode(&temp.width, &temp.height, &temp.bitsPerPixel);
99 		return temp;
100 	}
101 
102 	/**
103 	 * Retrieve all the video modes supported in fullscreen mode.
104 	 *
105 	 * When creating a fullscreen window, the video mode is restricted to be
106 	 * compatible with what the graphics driver and monitor support. This
107 	 * function returns the complete list of all video modes that can be used in
108 	 * fullscreen mode. The returned array is sorted from best to worst, so that
109 	 * the first element will always give the best mode (higher width, height
110 	 * and bits-per-pixel).
111 	 *
112 	 * Returns: Array containing all the supported fullscreen modes.
113 	 */
114 	static VideoMode[] getFullscreenModes()
115 	{
116 		//stores all video modes after the first call
117 		static VideoMode[] videoModes;
118 
119 		//if getFullscreenModes hasn't been called yet
120 		if(videoModes.length == 0)
121 		{
122 			uint* modes;
123 			size_t counts;
124 
125 			//returns uints instead of structs due to 64 bit bug
126 			modes = sfVideoMode_getFullscreenModes(&counts);
127 
128 			//calculate real length
129 			videoModes.length = counts/3;
130 
131 			//populate videoModes
132 			int videoModeIndex = 0;
133 			for(uint i = 0; i < counts; i+=3)
134 			{
135 				VideoMode temp = VideoMode(modes[i], modes[i+1], modes[i+2]);
136 
137 				videoModes[videoModeIndex] = temp;
138 				++videoModeIndex;
139 			}
140 
141 		}
142 
143 		return videoModes;
144 	}
145 
146 	/**
147 	 * Tell whether or not the video mode is valid.
148 	 *
149 	 * The validity of video modes is only relevant when using fullscreen
150 	 * windows; otherwise any video mode can be used with no restriction.
151 	 *
152 	 * Returns: true if the video mode is valid for fullscreen mode.
153 	 */
154 	bool isValid() const
155 	{
156 		return sfVideoMode_isValid(width, height, bitsPerPixel);
157 	}
158 
159 	///Returns a string representation of the video mode.
160 	string toString()
161 	{
162 		import std.conv: text;
163 		return "Width: " ~ text(width) ~ " Height: " ~ text(height) ~ " Bits per pixel: " ~ text(bitsPerPixel);
164 	}
165 }
166 
167 unittest
168 {
169 	version(DSFML_Unittest_Window)
170 	{
171 		import std.stdio;
172 
173 		writeln("Unit test for VideoMode struct");
174 
175 		size_t modesCount = VideoMode.getFullscreenModes().length;
176 
177 		writeln("There are ", modesCount, " full screen modes available.");
178 		writeln("Your current desktop video mode is ",VideoMode.getDesktopMode().toString());
179 
180 		writeln("Confirming all fullscreen modes are valid.");
181 		foreach(mode; VideoMode.getFullscreenModes())
182 		{
183 			assert(mode.isValid());
184 		}
185 		writeln("All video modes are valid.");
186 
187 		writeln();
188 	}
189 }
190 
191 private extern(C)
192 {
193 	void sfVideoMode_getDesktopMode(uint* width, uint* height, uint* bitsPerPixel);
194 	uint* sfVideoMode_getFullscreenModes(size_t* Count);
195 	bool sfVideoMode_isValid(uint width, uint height, uint bitsPerPixel);
196 }