GCC Code Coverage Report


Directory: ./
File: submodules/raylib/src/external/glfw/src/monitor.c
Date: 2023-09-29 04:53:15
Exec Total Coverage
Lines: 0 201 0.0%
Branches: 0 132 0.0%

Line Branch Exec Source
1 //========================================================================
2 // GLFW 3.4 - www.glfw.org
3 //------------------------------------------------------------------------
4 // Copyright (c) 2002-2006 Marcus Geelnard
5 // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
6 //
7 // This software is provided 'as-is', without any express or implied
8 // warranty. In no event will the authors be held liable for any damages
9 // arising from the use of this software.
10 //
11 // Permission is granted to anyone to use this software for any purpose,
12 // including commercial applications, and to alter it and redistribute it
13 // freely, subject to the following restrictions:
14 //
15 // 1. The origin of this software must not be misrepresented; you must not
16 // claim that you wrote the original software. If you use this software
17 // in a product, an acknowledgment in the product documentation would
18 // be appreciated but is not required.
19 //
20 // 2. Altered source versions must be plainly marked as such, and must not
21 // be misrepresented as being the original software.
22 //
23 // 3. This notice may not be removed or altered from any source
24 // distribution.
25 //
26 //========================================================================
27 // Please use C89 style variable declarations in this file because VS 2010
28 //========================================================================
29
30 #include "internal.h"
31
32 #include <assert.h>
33 #include <math.h>
34 #include <float.h>
35 #include <string.h>
36 #include <stdlib.h>
37 #include <limits.h>
38
39
40 // Lexically compare video modes, used by qsort
41 //
42 static int compareVideoModes(const void* fp, const void* sp)
43 {
44 const GLFWvidmode* fm = fp;
45 const GLFWvidmode* sm = sp;
46 const int fbpp = fm->redBits + fm->greenBits + fm->blueBits;
47 const int sbpp = sm->redBits + sm->greenBits + sm->blueBits;
48 const int farea = fm->width * fm->height;
49 const int sarea = sm->width * sm->height;
50
51 // First sort on color bits per pixel
52 if (fbpp != sbpp)
53 return fbpp - sbpp;
54
55 // Then sort on screen area
56 if (farea != sarea)
57 return farea - sarea;
58
59 // Then sort on width
60 if (fm->width != sm->width)
61 return fm->width - sm->width;
62
63 // Lastly sort on refresh rate
64 return fm->refreshRate - sm->refreshRate;
65 }
66
67 // Retrieves the available modes for the specified monitor
68 //
69 static GLFWbool refreshVideoModes(_GLFWmonitor* monitor)
70 {
71 int modeCount;
72 GLFWvidmode* modes;
73
74 if (monitor->modes)
75 return GLFW_TRUE;
76
77 modes = _glfw.platform.getVideoModes(monitor, &modeCount);
78 if (!modes)
79 return GLFW_FALSE;
80
81 qsort(modes, modeCount, sizeof(GLFWvidmode), compareVideoModes);
82
83 _glfw_free(monitor->modes);
84 monitor->modes = modes;
85 monitor->modeCount = modeCount;
86
87 return GLFW_TRUE;
88 }
89
90
91 //////////////////////////////////////////////////////////////////////////
92 ////// GLFW event API //////
93 //////////////////////////////////////////////////////////////////////////
94
95 // Notifies shared code of a monitor connection or disconnection
96 //
97 void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement)
98 {
99 assert(monitor != NULL);
100 assert(action == GLFW_CONNECTED || action == GLFW_DISCONNECTED);
101 assert(placement == _GLFW_INSERT_FIRST || placement == _GLFW_INSERT_LAST);
102
103 if (action == GLFW_CONNECTED)
104 {
105 _glfw.monitorCount++;
106 _glfw.monitors =
107 _glfw_realloc(_glfw.monitors,
108 sizeof(_GLFWmonitor*) * _glfw.monitorCount);
109
110 if (placement == _GLFW_INSERT_FIRST)
111 {
112 memmove(_glfw.monitors + 1,
113 _glfw.monitors,
114 ((size_t) _glfw.monitorCount - 1) * sizeof(_GLFWmonitor*));
115 _glfw.monitors[0] = monitor;
116 }
117 else
118 _glfw.monitors[_glfw.monitorCount - 1] = monitor;
119 }
120 else if (action == GLFW_DISCONNECTED)
121 {
122 int i;
123 _GLFWwindow* window;
124
125 for (window = _glfw.windowListHead; window; window = window->next)
126 {
127 if (window->monitor == monitor)
128 {
129 int width, height, xoff, yoff;
130 _glfw.platform.getWindowSize(window, &width, &height);
131 _glfw.platform.setWindowMonitor(window, NULL, 0, 0, width, height, 0);
132 _glfw.platform.getWindowFrameSize(window, &xoff, &yoff, NULL, NULL);
133 _glfw.platform.setWindowPos(window, xoff, yoff);
134 }
135 }
136
137 for (i = 0; i < _glfw.monitorCount; i++)
138 {
139 if (_glfw.monitors[i] == monitor)
140 {
141 _glfw.monitorCount--;
142 memmove(_glfw.monitors + i,
143 _glfw.monitors + i + 1,
144 ((size_t) _glfw.monitorCount - i) * sizeof(_GLFWmonitor*));
145 break;
146 }
147 }
148 }
149
150 if (_glfw.callbacks.monitor)
151 _glfw.callbacks.monitor((GLFWmonitor*) monitor, action);
152
153 if (action == GLFW_DISCONNECTED)
154 _glfwFreeMonitor(monitor);
155 }
156
157 // Notifies shared code that a full screen window has acquired or released
158 // a monitor
159 //
160 void _glfwInputMonitorWindow(_GLFWmonitor* monitor, _GLFWwindow* window)
161 {
162 assert(monitor != NULL);
163 monitor->window = window;
164 }
165
166
167 //////////////////////////////////////////////////////////////////////////
168 ////// GLFW internal API //////
169 //////////////////////////////////////////////////////////////////////////
170
171 // Allocates and returns a monitor object with the specified name and dimensions
172 //
173 _GLFWmonitor* _glfwAllocMonitor(const char* name, int widthMM, int heightMM)
174 {
175 _GLFWmonitor* monitor = _glfw_calloc(1, sizeof(_GLFWmonitor));
176 monitor->widthMM = widthMM;
177 monitor->heightMM = heightMM;
178
179 strncpy(monitor->name, name, sizeof(monitor->name) - 1);
180
181 return monitor;
182 }
183
184 // Frees a monitor object and any data associated with it
185 //
186 void _glfwFreeMonitor(_GLFWmonitor* monitor)
187 {
188 if (monitor == NULL)
189 return;
190
191 _glfw.platform.freeMonitor(monitor);
192
193 _glfwFreeGammaArrays(&monitor->originalRamp);
194 _glfwFreeGammaArrays(&monitor->currentRamp);
195
196 _glfw_free(monitor->modes);
197 _glfw_free(monitor);
198 }
199
200 // Allocates red, green and blue value arrays of the specified size
201 //
202 void _glfwAllocGammaArrays(GLFWgammaramp* ramp, unsigned int size)
203 {
204 ramp->red = _glfw_calloc(size, sizeof(unsigned short));
205 ramp->green = _glfw_calloc(size, sizeof(unsigned short));
206 ramp->blue = _glfw_calloc(size, sizeof(unsigned short));
207 ramp->size = size;
208 }
209
210 // Frees the red, green and blue value arrays and clears the struct
211 //
212 void _glfwFreeGammaArrays(GLFWgammaramp* ramp)
213 {
214 _glfw_free(ramp->red);
215 _glfw_free(ramp->green);
216 _glfw_free(ramp->blue);
217
218 memset(ramp, 0, sizeof(GLFWgammaramp));
219 }
220
221 // Chooses the video mode most closely matching the desired one
222 //
223 const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor,
224 const GLFWvidmode* desired)
225 {
226 int i;
227 unsigned int sizeDiff, leastSizeDiff = UINT_MAX;
228 unsigned int rateDiff, leastRateDiff = UINT_MAX;
229 unsigned int colorDiff, leastColorDiff = UINT_MAX;
230 const GLFWvidmode* current;
231 const GLFWvidmode* closest = NULL;
232
233 if (!refreshVideoModes(monitor))
234 return NULL;
235
236 for (i = 0; i < monitor->modeCount; i++)
237 {
238 current = monitor->modes + i;
239
240 colorDiff = 0;
241
242 if (desired->redBits != GLFW_DONT_CARE)
243 colorDiff += abs(current->redBits - desired->redBits);
244 if (desired->greenBits != GLFW_DONT_CARE)
245 colorDiff += abs(current->greenBits - desired->greenBits);
246 if (desired->blueBits != GLFW_DONT_CARE)
247 colorDiff += abs(current->blueBits - desired->blueBits);
248
249 sizeDiff = abs((current->width - desired->width) *
250 (current->width - desired->width) +
251 (current->height - desired->height) *
252 (current->height - desired->height));
253
254 if (desired->refreshRate != GLFW_DONT_CARE)
255 rateDiff = abs(current->refreshRate - desired->refreshRate);
256 else
257 rateDiff = UINT_MAX - current->refreshRate;
258
259 if ((colorDiff < leastColorDiff) ||
260 (colorDiff == leastColorDiff && sizeDiff < leastSizeDiff) ||
261 (colorDiff == leastColorDiff && sizeDiff == leastSizeDiff && rateDiff < leastRateDiff))
262 {
263 closest = current;
264 leastSizeDiff = sizeDiff;
265 leastRateDiff = rateDiff;
266 leastColorDiff = colorDiff;
267 }
268 }
269
270 return closest;
271 }
272
273 // Performs lexical comparison between two @ref GLFWvidmode structures
274 //
275 int _glfwCompareVideoModes(const GLFWvidmode* fm, const GLFWvidmode* sm)
276 {
277 return compareVideoModes(fm, sm);
278 }
279
280 // Splits a color depth into red, green and blue bit depths
281 //
282 void _glfwSplitBPP(int bpp, int* red, int* green, int* blue)
283 {
284 int delta;
285
286 // We assume that by 32 the user really meant 24
287 if (bpp == 32)
288 bpp = 24;
289
290 // Convert "bits per pixel" to red, green & blue sizes
291
292 *red = *green = *blue = bpp / 3;
293 delta = bpp - (*red * 3);
294 if (delta >= 1)
295 *green = *green + 1;
296
297 if (delta == 2)
298 *red = *red + 1;
299 }
300
301
302 //////////////////////////////////////////////////////////////////////////
303 ////// GLFW public API //////
304 //////////////////////////////////////////////////////////////////////////
305
306 GLFWAPI GLFWmonitor** glfwGetMonitors(int* count)
307 {
308 assert(count != NULL);
309
310 *count = 0;
311
312 _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
313
314 *count = _glfw.monitorCount;
315 return (GLFWmonitor**) _glfw.monitors;
316 }
317
318 GLFWAPI GLFWmonitor* glfwGetPrimaryMonitor(void)
319 {
320 _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
321
322 if (!_glfw.monitorCount)
323 return NULL;
324
325 return (GLFWmonitor*) _glfw.monitors[0];
326 }
327
328 GLFWAPI void glfwGetMonitorPos(GLFWmonitor* handle, int* xpos, int* ypos)
329 {
330 _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
331 assert(monitor != NULL);
332
333 if (xpos)
334 *xpos = 0;
335 if (ypos)
336 *ypos = 0;
337
338 _GLFW_REQUIRE_INIT();
339
340 _glfw.platform.getMonitorPos(monitor, xpos, ypos);
341 }
342
343 GLFWAPI void glfwGetMonitorWorkarea(GLFWmonitor* handle,
344 int* xpos, int* ypos,
345 int* width, int* height)
346 {
347 _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
348 assert(monitor != NULL);
349
350 if (xpos)
351 *xpos = 0;
352 if (ypos)
353 *ypos = 0;
354 if (width)
355 *width = 0;
356 if (height)
357 *height = 0;
358
359 _GLFW_REQUIRE_INIT();
360
361 _glfw.platform.getMonitorWorkarea(monitor, xpos, ypos, width, height);
362 }
363
364 GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* handle, int* widthMM, int* heightMM)
365 {
366 _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
367 assert(monitor != NULL);
368
369 if (widthMM)
370 *widthMM = 0;
371 if (heightMM)
372 *heightMM = 0;
373
374 _GLFW_REQUIRE_INIT();
375
376 if (widthMM)
377 *widthMM = monitor->widthMM;
378 if (heightMM)
379 *heightMM = monitor->heightMM;
380 }
381
382 GLFWAPI void glfwGetMonitorContentScale(GLFWmonitor* handle,
383 float* xscale, float* yscale)
384 {
385 _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
386 assert(monitor != NULL);
387
388 if (xscale)
389 *xscale = 0.f;
390 if (yscale)
391 *yscale = 0.f;
392
393 _GLFW_REQUIRE_INIT();
394 _glfw.platform.getMonitorContentScale(monitor, xscale, yscale);
395 }
396
397 GLFWAPI const char* glfwGetMonitorName(GLFWmonitor* handle)
398 {
399 _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
400 assert(monitor != NULL);
401
402 _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
403 return monitor->name;
404 }
405
406 GLFWAPI void glfwSetMonitorUserPointer(GLFWmonitor* handle, void* pointer)
407 {
408 _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
409 assert(monitor != NULL);
410
411 _GLFW_REQUIRE_INIT();
412 monitor->userPointer = pointer;
413 }
414
415 GLFWAPI void* glfwGetMonitorUserPointer(GLFWmonitor* handle)
416 {
417 _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
418 assert(monitor != NULL);
419
420 _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
421 return monitor->userPointer;
422 }
423
424 GLFWAPI GLFWmonitorfun glfwSetMonitorCallback(GLFWmonitorfun cbfun)
425 {
426 _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
427 _GLFW_SWAP(GLFWmonitorfun, _glfw.callbacks.monitor, cbfun);
428 return cbfun;
429 }
430
431 GLFWAPI const GLFWvidmode* glfwGetVideoModes(GLFWmonitor* handle, int* count)
432 {
433 _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
434 assert(monitor != NULL);
435 assert(count != NULL);
436
437 *count = 0;
438
439 _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
440
441 if (!refreshVideoModes(monitor))
442 return NULL;
443
444 *count = monitor->modeCount;
445 return monitor->modes;
446 }
447
448 GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* handle)
449 {
450 _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
451 assert(monitor != NULL);
452
453 _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
454
455 _glfw.platform.getVideoMode(monitor, &monitor->currentMode);
456 return &monitor->currentMode;
457 }
458
459 GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma)
460 {
461 unsigned int i;
462 unsigned short* values;
463 GLFWgammaramp ramp;
464 const GLFWgammaramp* original;
465 assert(handle != NULL);
466 assert(gamma > 0.f);
467 assert(gamma <= FLT_MAX);
468
469 _GLFW_REQUIRE_INIT();
470
471 if (gamma != gamma || gamma <= 0.f || gamma > FLT_MAX)
472 {
473 _glfwInputError(GLFW_INVALID_VALUE, "Invalid gamma value %f", gamma);
474 return;
475 }
476
477 original = glfwGetGammaRamp(handle);
478 if (!original)
479 return;
480
481 values = _glfw_calloc(original->size, sizeof(unsigned short));
482
483 for (i = 0; i < original->size; i++)
484 {
485 float value;
486
487 // Calculate intensity
488 value = i / (float) (original->size - 1);
489 // Apply gamma curve
490 value = powf(value, 1.f / gamma) * 65535.f + 0.5f;
491 // Clamp to value range
492 value = _glfw_fminf(value, 65535.f);
493
494 values[i] = (unsigned short) value;
495 }
496
497 ramp.red = values;
498 ramp.green = values;
499 ramp.blue = values;
500 ramp.size = original->size;
501
502 glfwSetGammaRamp(handle, &ramp);
503 _glfw_free(values);
504 }
505
506 GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* handle)
507 {
508 _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
509 assert(monitor != NULL);
510
511 _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
512
513 _glfwFreeGammaArrays(&monitor->currentRamp);
514 if (!_glfw.platform.getGammaRamp(monitor, &monitor->currentRamp))
515 return NULL;
516
517 return &monitor->currentRamp;
518 }
519
520 GLFWAPI void glfwSetGammaRamp(GLFWmonitor* handle, const GLFWgammaramp* ramp)
521 {
522 _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
523 assert(monitor != NULL);
524 assert(ramp != NULL);
525 assert(ramp->size > 0);
526 assert(ramp->red != NULL);
527 assert(ramp->green != NULL);
528 assert(ramp->blue != NULL);
529
530 _GLFW_REQUIRE_INIT();
531
532 if (ramp->size <= 0)
533 {
534 _glfwInputError(GLFW_INVALID_VALUE,
535 "Invalid gamma ramp size %i",
536 ramp->size);
537 return;
538 }
539
540 if (!monitor->originalRamp.size)
541 {
542 if (!_glfw.platform.getGammaRamp(monitor, &monitor->originalRamp))
543 return;
544 }
545
546 _glfw.platform.setGammaRamp(monitor, ramp);
547 }
548
549