twitchapon-anim

Basic Twitchapon Receiver/Visuals
git clone git://bsandro.tech/twitchapon-anim
Log | Files | Refs | README | LICENSE

x11_monitor.c (19711B)


      1 //========================================================================
      2 // GLFW 3.3 X11 - 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 // It is fine to use C99 in this file because it will not be built with VS
     28 //========================================================================
     29 
     30 #include "internal.h"
     31 
     32 #include <limits.h>
     33 #include <stdlib.h>
     34 #include <string.h>
     35 #include <math.h>
     36 
     37 
     38 // Check whether the display mode should be included in enumeration
     39 //
     40 static GLFWbool modeIsGood(const XRRModeInfo* mi)
     41 {
     42     return (mi->modeFlags & RR_Interlace) == 0;
     43 }
     44 
     45 // Calculates the refresh rate, in Hz, from the specified RandR mode info
     46 //
     47 static int calculateRefreshRate(const XRRModeInfo* mi)
     48 {
     49     if (mi->hTotal && mi->vTotal)
     50         return (int) round((double) mi->dotClock / ((double) mi->hTotal * (double) mi->vTotal));
     51     else
     52         return 0;
     53 }
     54 
     55 // Returns the mode info for a RandR mode XID
     56 //
     57 static const XRRModeInfo* getModeInfo(const XRRScreenResources* sr, RRMode id)
     58 {
     59     for (int i = 0;  i < sr->nmode;  i++)
     60     {
     61         if (sr->modes[i].id == id)
     62             return sr->modes + i;
     63     }
     64 
     65     return NULL;
     66 }
     67 
     68 // Convert RandR mode info to GLFW video mode
     69 //
     70 static GLFWvidmode vidmodeFromModeInfo(const XRRModeInfo* mi,
     71                                        const XRRCrtcInfo* ci)
     72 {
     73     GLFWvidmode mode;
     74 
     75     if (ci->rotation == RR_Rotate_90 || ci->rotation == RR_Rotate_270)
     76     {
     77         mode.width  = mi->height;
     78         mode.height = mi->width;
     79     }
     80     else
     81     {
     82         mode.width  = mi->width;
     83         mode.height = mi->height;
     84     }
     85 
     86     mode.refreshRate = calculateRefreshRate(mi);
     87 
     88     _glfwSplitBPP(DefaultDepth(_glfw.x11.display, _glfw.x11.screen),
     89                   &mode.redBits, &mode.greenBits, &mode.blueBits);
     90 
     91     return mode;
     92 }
     93 
     94 
     95 //////////////////////////////////////////////////////////////////////////
     96 //////                       GLFW internal API                      //////
     97 //////////////////////////////////////////////////////////////////////////
     98 
     99 // Poll for changes in the set of connected monitors
    100 //
    101 void _glfwPollMonitorsX11(void)
    102 {
    103     if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
    104     {
    105         int disconnectedCount, screenCount = 0;
    106         _GLFWmonitor** disconnected = NULL;
    107         XineramaScreenInfo* screens = NULL;
    108         XRRScreenResources* sr = XRRGetScreenResourcesCurrent(_glfw.x11.display,
    109                                                               _glfw.x11.root);
    110         RROutput primary = XRRGetOutputPrimary(_glfw.x11.display,
    111                                                _glfw.x11.root);
    112 
    113         if (_glfw.x11.xinerama.available)
    114             screens = XineramaQueryScreens(_glfw.x11.display, &screenCount);
    115 
    116         disconnectedCount = _glfw.monitorCount;
    117         if (disconnectedCount)
    118         {
    119             disconnected = calloc(_glfw.monitorCount, sizeof(_GLFWmonitor*));
    120             memcpy(disconnected,
    121                    _glfw.monitors,
    122                    _glfw.monitorCount * sizeof(_GLFWmonitor*));
    123         }
    124 
    125         for (int i = 0;  i < sr->noutput;  i++)
    126         {
    127             int j, type, widthMM, heightMM;
    128 
    129             XRROutputInfo* oi = XRRGetOutputInfo(_glfw.x11.display, sr, sr->outputs[i]);
    130             if (oi->connection != RR_Connected || oi->crtc == None)
    131             {
    132                 XRRFreeOutputInfo(oi);
    133                 continue;
    134             }
    135 
    136             for (j = 0;  j < disconnectedCount;  j++)
    137             {
    138                 if (disconnected[j] &&
    139                     disconnected[j]->x11.output == sr->outputs[i])
    140                 {
    141                     disconnected[j] = NULL;
    142                     break;
    143                 }
    144             }
    145 
    146             if (j < disconnectedCount)
    147             {
    148                 XRRFreeOutputInfo(oi);
    149                 continue;
    150             }
    151 
    152             XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, oi->crtc);
    153             if (ci->rotation == RR_Rotate_90 || ci->rotation == RR_Rotate_270)
    154             {
    155                 widthMM  = oi->mm_height;
    156                 heightMM = oi->mm_width;
    157             }
    158             else
    159             {
    160                 widthMM  = oi->mm_width;
    161                 heightMM = oi->mm_height;
    162             }
    163 
    164             if (widthMM <= 0 || heightMM <= 0)
    165             {
    166                 // HACK: If RandR does not provide a physical size, assume the
    167                 //       X11 default 96 DPI and calcuate from the CRTC viewport
    168                 // NOTE: These members are affected by rotation, unlike the mode
    169                 //       info and output info members
    170                 widthMM  = (int) (ci->width * 25.4f / 96.f);
    171                 heightMM = (int) (ci->height * 25.4f / 96.f);
    172             }
    173 
    174             _GLFWmonitor* monitor = _glfwAllocMonitor(oi->name, widthMM, heightMM);
    175             monitor->x11.output = sr->outputs[i];
    176             monitor->x11.crtc   = oi->crtc;
    177 
    178             for (j = 0;  j < screenCount;  j++)
    179             {
    180                 if (screens[j].x_org == ci->x &&
    181                     screens[j].y_org == ci->y &&
    182                     screens[j].width == ci->width &&
    183                     screens[j].height == ci->height)
    184                 {
    185                     monitor->x11.index = j;
    186                     break;
    187                 }
    188             }
    189 
    190             if (monitor->x11.output == primary)
    191                 type = _GLFW_INSERT_FIRST;
    192             else
    193                 type = _GLFW_INSERT_LAST;
    194 
    195             _glfwInputMonitor(monitor, GLFW_CONNECTED, type);
    196 
    197             XRRFreeOutputInfo(oi);
    198             XRRFreeCrtcInfo(ci);
    199         }
    200 
    201         XRRFreeScreenResources(sr);
    202 
    203         if (screens)
    204             XFree(screens);
    205 
    206         for (int i = 0;  i < disconnectedCount;  i++)
    207         {
    208             if (disconnected[i])
    209                 _glfwInputMonitor(disconnected[i], GLFW_DISCONNECTED, 0);
    210         }
    211 
    212         free(disconnected);
    213     }
    214     else
    215     {
    216         const int widthMM = DisplayWidthMM(_glfw.x11.display, _glfw.x11.screen);
    217         const int heightMM = DisplayHeightMM(_glfw.x11.display, _glfw.x11.screen);
    218 
    219         _glfwInputMonitor(_glfwAllocMonitor("Display", widthMM, heightMM),
    220                           GLFW_CONNECTED,
    221                           _GLFW_INSERT_FIRST);
    222     }
    223 }
    224 
    225 // Set the current video mode for the specified monitor
    226 //
    227 void _glfwSetVideoModeX11(_GLFWmonitor* monitor, const GLFWvidmode* desired)
    228 {
    229     if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
    230     {
    231         GLFWvidmode current;
    232         RRMode native = None;
    233 
    234         const GLFWvidmode* best = _glfwChooseVideoMode(monitor, desired);
    235         _glfwPlatformGetVideoMode(monitor, &current);
    236         if (_glfwCompareVideoModes(&current, best) == 0)
    237             return;
    238 
    239         XRRScreenResources* sr =
    240             XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
    241         XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
    242         XRROutputInfo* oi = XRRGetOutputInfo(_glfw.x11.display, sr, monitor->x11.output);
    243 
    244         for (int i = 0;  i < oi->nmode;  i++)
    245         {
    246             const XRRModeInfo* mi = getModeInfo(sr, oi->modes[i]);
    247             if (!modeIsGood(mi))
    248                 continue;
    249 
    250             const GLFWvidmode mode = vidmodeFromModeInfo(mi, ci);
    251             if (_glfwCompareVideoModes(best, &mode) == 0)
    252             {
    253                 native = mi->id;
    254                 break;
    255             }
    256         }
    257 
    258         if (native)
    259         {
    260             if (monitor->x11.oldMode == None)
    261                 monitor->x11.oldMode = ci->mode;
    262 
    263             XRRSetCrtcConfig(_glfw.x11.display,
    264                              sr, monitor->x11.crtc,
    265                              CurrentTime,
    266                              ci->x, ci->y,
    267                              native,
    268                              ci->rotation,
    269                              ci->outputs,
    270                              ci->noutput);
    271         }
    272 
    273         XRRFreeOutputInfo(oi);
    274         XRRFreeCrtcInfo(ci);
    275         XRRFreeScreenResources(sr);
    276     }
    277 }
    278 
    279 // Restore the saved (original) video mode for the specified monitor
    280 //
    281 void _glfwRestoreVideoModeX11(_GLFWmonitor* monitor)
    282 {
    283     if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
    284     {
    285         if (monitor->x11.oldMode == None)
    286             return;
    287 
    288         XRRScreenResources* sr =
    289             XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
    290         XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
    291 
    292         XRRSetCrtcConfig(_glfw.x11.display,
    293                          sr, monitor->x11.crtc,
    294                          CurrentTime,
    295                          ci->x, ci->y,
    296                          monitor->x11.oldMode,
    297                          ci->rotation,
    298                          ci->outputs,
    299                          ci->noutput);
    300 
    301         XRRFreeCrtcInfo(ci);
    302         XRRFreeScreenResources(sr);
    303 
    304         monitor->x11.oldMode = None;
    305     }
    306 }
    307 
    308 
    309 //////////////////////////////////////////////////////////////////////////
    310 //////                       GLFW platform API                      //////
    311 //////////////////////////////////////////////////////////////////////////
    312 
    313 void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor)
    314 {
    315 }
    316 
    317 void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
    318 {
    319     if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
    320     {
    321         XRRScreenResources* sr =
    322             XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
    323         XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
    324 
    325         if (ci)
    326         {
    327             if (xpos)
    328                 *xpos = ci->x;
    329             if (ypos)
    330                 *ypos = ci->y;
    331 
    332             XRRFreeCrtcInfo(ci);
    333         }
    334 
    335         XRRFreeScreenResources(sr);
    336     }
    337 }
    338 
    339 void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
    340                                          float* xscale, float* yscale)
    341 {
    342     if (xscale)
    343         *xscale = _glfw.x11.contentScaleX;
    344     if (yscale)
    345         *yscale = _glfw.x11.contentScaleY;
    346 }
    347 
    348 void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, int* xpos, int* ypos, int* width, int* height)
    349 {
    350     int areaX = 0, areaY = 0, areaWidth = 0, areaHeight = 0;
    351 
    352     if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
    353     {
    354         XRRScreenResources* sr =
    355             XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
    356         XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
    357 
    358         areaX = ci->x;
    359         areaY = ci->y;
    360 
    361         const XRRModeInfo* mi = getModeInfo(sr, ci->mode);
    362 
    363         if (ci->rotation == RR_Rotate_90 || ci->rotation == RR_Rotate_270)
    364         {
    365             areaWidth  = mi->height;
    366             areaHeight = mi->width;
    367         }
    368         else
    369         {
    370             areaWidth  = mi->width;
    371             areaHeight = mi->height;
    372         }
    373 
    374         XRRFreeCrtcInfo(ci);
    375         XRRFreeScreenResources(sr);
    376     }
    377     else
    378     {
    379         areaWidth  = DisplayWidth(_glfw.x11.display, _glfw.x11.screen);
    380         areaHeight = DisplayHeight(_glfw.x11.display, _glfw.x11.screen);
    381     }
    382 
    383     if (_glfw.x11.NET_WORKAREA && _glfw.x11.NET_CURRENT_DESKTOP)
    384     {
    385         Atom* extents = NULL;
    386         Atom* desktop = NULL;
    387         const unsigned long extentCount =
    388             _glfwGetWindowPropertyX11(_glfw.x11.root,
    389                                       _glfw.x11.NET_WORKAREA,
    390                                       XA_CARDINAL,
    391                                       (unsigned char**) &extents);
    392 
    393         if (_glfwGetWindowPropertyX11(_glfw.x11.root,
    394                                       _glfw.x11.NET_CURRENT_DESKTOP,
    395                                       XA_CARDINAL,
    396                                       (unsigned char**) &desktop) > 0)
    397         {
    398             if (extentCount >= 4 && *desktop < extentCount / 4)
    399             {
    400                 const int globalX = extents[*desktop * 4 + 0];
    401                 const int globalY = extents[*desktop * 4 + 1];
    402                 const int globalWidth  = extents[*desktop * 4 + 2];
    403                 const int globalHeight = extents[*desktop * 4 + 3];
    404 
    405                 if (areaX < globalX)
    406                 {
    407                     areaWidth -= globalX - areaX;
    408                     areaX = globalX;
    409                 }
    410 
    411                 if (areaY < globalY)
    412                 {
    413                     areaHeight -= globalY - areaY;
    414                     areaY = globalY;
    415                 }
    416 
    417                 if (areaX + areaWidth > globalX + globalWidth)
    418                     areaWidth = globalX - areaX + globalWidth;
    419                 if (areaY + areaHeight > globalY + globalHeight)
    420                     areaHeight = globalY - areaY + globalHeight;
    421             }
    422         }
    423 
    424         if (extents)
    425             XFree(extents);
    426         if (desktop)
    427             XFree(desktop);
    428     }
    429 
    430     if (xpos)
    431         *xpos = areaX;
    432     if (ypos)
    433         *ypos = areaY;
    434     if (width)
    435         *width = areaWidth;
    436     if (height)
    437         *height = areaHeight;
    438 }
    439 
    440 GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
    441 {
    442     GLFWvidmode* result;
    443 
    444     *count = 0;
    445 
    446     if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
    447     {
    448         XRRScreenResources* sr =
    449             XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
    450         XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
    451         XRROutputInfo* oi = XRRGetOutputInfo(_glfw.x11.display, sr, monitor->x11.output);
    452 
    453         result = calloc(oi->nmode, sizeof(GLFWvidmode));
    454 
    455         for (int i = 0;  i < oi->nmode;  i++)
    456         {
    457             const XRRModeInfo* mi = getModeInfo(sr, oi->modes[i]);
    458             if (!modeIsGood(mi))
    459                 continue;
    460 
    461             const GLFWvidmode mode = vidmodeFromModeInfo(mi, ci);
    462             int j;
    463 
    464             for (j = 0;  j < *count;  j++)
    465             {
    466                 if (_glfwCompareVideoModes(result + j, &mode) == 0)
    467                     break;
    468             }
    469 
    470             // Skip duplicate modes
    471             if (j < *count)
    472                 continue;
    473 
    474             (*count)++;
    475             result[*count - 1] = mode;
    476         }
    477 
    478         XRRFreeOutputInfo(oi);
    479         XRRFreeCrtcInfo(ci);
    480         XRRFreeScreenResources(sr);
    481     }
    482     else
    483     {
    484         *count = 1;
    485         result = calloc(1, sizeof(GLFWvidmode));
    486         _glfwPlatformGetVideoMode(monitor, result);
    487     }
    488 
    489     return result;
    490 }
    491 
    492 void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
    493 {
    494     if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
    495     {
    496         XRRScreenResources* sr =
    497             XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
    498         XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
    499 
    500         if (ci)
    501         {
    502             const XRRModeInfo* mi = getModeInfo(sr, ci->mode);
    503             if (mi)  // mi can be NULL if the monitor has been disconnected
    504                 *mode = vidmodeFromModeInfo(mi, ci);
    505 
    506             XRRFreeCrtcInfo(ci);
    507         }
    508 
    509         XRRFreeScreenResources(sr);
    510     }
    511     else
    512     {
    513         mode->width = DisplayWidth(_glfw.x11.display, _glfw.x11.screen);
    514         mode->height = DisplayHeight(_glfw.x11.display, _glfw.x11.screen);
    515         mode->refreshRate = 0;
    516 
    517         _glfwSplitBPP(DefaultDepth(_glfw.x11.display, _glfw.x11.screen),
    518                       &mode->redBits, &mode->greenBits, &mode->blueBits);
    519     }
    520 }
    521 
    522 GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
    523 {
    524     if (_glfw.x11.randr.available && !_glfw.x11.randr.gammaBroken)
    525     {
    526         const size_t size = XRRGetCrtcGammaSize(_glfw.x11.display,
    527                                                 monitor->x11.crtc);
    528         XRRCrtcGamma* gamma = XRRGetCrtcGamma(_glfw.x11.display,
    529                                               monitor->x11.crtc);
    530 
    531         _glfwAllocGammaArrays(ramp, size);
    532 
    533         memcpy(ramp->red,   gamma->red,   size * sizeof(unsigned short));
    534         memcpy(ramp->green, gamma->green, size * sizeof(unsigned short));
    535         memcpy(ramp->blue,  gamma->blue,  size * sizeof(unsigned short));
    536 
    537         XRRFreeGamma(gamma);
    538         return GLFW_TRUE;
    539     }
    540     else if (_glfw.x11.vidmode.available)
    541     {
    542         int size;
    543         XF86VidModeGetGammaRampSize(_glfw.x11.display, _glfw.x11.screen, &size);
    544 
    545         _glfwAllocGammaArrays(ramp, size);
    546 
    547         XF86VidModeGetGammaRamp(_glfw.x11.display,
    548                                 _glfw.x11.screen,
    549                                 ramp->size, ramp->red, ramp->green, ramp->blue);
    550         return GLFW_TRUE;
    551     }
    552     else
    553     {
    554         _glfwInputError(GLFW_PLATFORM_ERROR,
    555                         "X11: Gamma ramp access not supported by server");
    556         return GLFW_FALSE;
    557     }
    558 }
    559 
    560 void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
    561 {
    562     if (_glfw.x11.randr.available && !_glfw.x11.randr.gammaBroken)
    563     {
    564         if (XRRGetCrtcGammaSize(_glfw.x11.display, monitor->x11.crtc) != ramp->size)
    565         {
    566             _glfwInputError(GLFW_PLATFORM_ERROR,
    567                             "X11: Gamma ramp size must match current ramp size");
    568             return;
    569         }
    570 
    571         XRRCrtcGamma* gamma = XRRAllocGamma(ramp->size);
    572 
    573         memcpy(gamma->red,   ramp->red,   ramp->size * sizeof(unsigned short));
    574         memcpy(gamma->green, ramp->green, ramp->size * sizeof(unsigned short));
    575         memcpy(gamma->blue,  ramp->blue,  ramp->size * sizeof(unsigned short));
    576 
    577         XRRSetCrtcGamma(_glfw.x11.display, monitor->x11.crtc, gamma);
    578         XRRFreeGamma(gamma);
    579     }
    580     else if (_glfw.x11.vidmode.available)
    581     {
    582         XF86VidModeSetGammaRamp(_glfw.x11.display,
    583                                 _glfw.x11.screen,
    584                                 ramp->size,
    585                                 (unsigned short*) ramp->red,
    586                                 (unsigned short*) ramp->green,
    587                                 (unsigned short*) ramp->blue);
    588     }
    589     else
    590     {
    591         _glfwInputError(GLFW_PLATFORM_ERROR,
    592                         "X11: Gamma ramp access not supported by server");
    593     }
    594 }
    595 
    596 
    597 //////////////////////////////////////////////////////////////////////////
    598 //////                        GLFW native API                       //////
    599 //////////////////////////////////////////////////////////////////////////
    600 
    601 GLFWAPI RRCrtc glfwGetX11Adapter(GLFWmonitor* handle)
    602 {
    603     _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
    604     _GLFW_REQUIRE_INIT_OR_RETURN(None);
    605     return monitor->x11.crtc;
    606 }
    607 
    608 GLFWAPI RROutput glfwGetX11Monitor(GLFWmonitor* handle)
    609 {
    610     _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
    611     _GLFW_REQUIRE_INIT_OR_RETURN(None);
    612     return monitor->x11.output;
    613 }
    614