github.com/Konstantin8105/c4go@v0.0.0-20240505174241-768bb1c65a51/tests/raylib/external/glfw/src/monitor.c (about) 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