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