mirror of
https://github.com/Ryujinx/Opentk.git
synced 2024-12-25 16:05:31 +00:00
Use one display connection for all X11 communication. Seems to fix (not 100%) the crash problems encountered.
This commit is contained in:
parent
5b4bed3a09
commit
ef16998dca
|
@ -2,7 +2,7 @@
|
|||
/* Licensed under the MIT/X11 license.
|
||||
* Copyright (c) 2006-2008 the OpenTK Team.
|
||||
* This notice may not be removed from any source distribution.
|
||||
* See license.txt for licensing detailed licensing details.
|
||||
* See license.txt for licensing details.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
|
|
|
@ -339,8 +339,8 @@ namespace OpenTK.Graphics
|
|||
Form form = new Form();
|
||||
form.ShowInTaskbar = false;
|
||||
form.StartPosition = FormStartPosition.Manual;
|
||||
form.FormBorderStyle = FormBorderStyle.None;
|
||||
form.WindowState = FormWindowState.Maximized;
|
||||
form.FormBorderStyle = FormBorderStyle.None;
|
||||
form.TopMost = true;
|
||||
|
||||
form.BackColor = System.Drawing.Color.Black;
|
||||
|
@ -353,9 +353,13 @@ namespace OpenTK.Graphics
|
|||
|
||||
void MoveToStartPositions()
|
||||
{
|
||||
//int count = 0;
|
||||
//foreach (Screen s in Screen.AllScreens)
|
||||
int count = 0;
|
||||
foreach (Screen s in Screen.AllScreens)
|
||||
{
|
||||
// forms[count++].Location = new System.Drawing.Point(s.Bounds.X, s.Bounds.Y);
|
||||
//forms[count].Size = new System.Drawing.Size(4096, 4096);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
bool FadedOut
|
||||
|
|
|
@ -9,6 +9,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace OpenTK.Platform.X11
|
||||
{
|
||||
|
@ -38,7 +39,6 @@ namespace OpenTK.Platform.X11
|
|||
using Rotation = System.UInt16;
|
||||
using Status = System.Int32;
|
||||
using SizeID = System.UInt16;
|
||||
using System.Diagnostics;
|
||||
|
||||
#endregion
|
||||
|
||||
|
@ -57,37 +57,56 @@ namespace OpenTK.Platform.X11
|
|||
static int screenCount;
|
||||
|
||||
internal static Display DefaultDisplay { get { return defaultDisplay; } }
|
||||
internal static int DefaultScreen { get { return defaultScreen; } }
|
||||
internal static Window RootWindow { get { return rootWindow; } }
|
||||
//internal static int DefaultScreen { get { return defaultScreen; } }
|
||||
//internal static Window RootWindow { get { return rootWindow; } }
|
||||
internal static int ScreenCount { get { return screenCount; } }
|
||||
|
||||
internal static object Lock = new object();
|
||||
|
||||
#endregion
|
||||
|
||||
static API()
|
||||
{
|
||||
//AppDomain.CurrentDomain.ProcessExit += new EventHandler(CurrentDomain_ProcessExit);
|
||||
AppDomain.CurrentDomain.ProcessExit += new EventHandler(CurrentDomain_ProcessExit);
|
||||
|
||||
//using (System.Windows.Forms.Control c = new System.Windows.Forms.Control()) { }
|
||||
//Type xplatui = Type.GetType("System.Windows.Forms.XplatUIX11, System.Windows.Forms");
|
||||
//defaultDisplay = (IntPtr)xplatui.GetField("DisplayHandle", System.Reflection.BindingFlags.Static |
|
||||
// System.Reflection.BindingFlags.NonPublic).GetValue(null);
|
||||
|
||||
defaultDisplay = Functions.XOpenDisplay(IntPtr.Zero);
|
||||
defaultScreen = Functions.XDefaultScreen(DefaultDisplay);
|
||||
rootWindow = Functions.XRootWindow(DefaultDisplay, DefaultScreen);
|
||||
|
||||
if (defaultDisplay == IntPtr.Zero)
|
||||
throw new PlatformException("Could not establish connection to the X-Server.");
|
||||
|
||||
//defaultScreen = Functions.XDefaultScreen(DefaultDisplay);
|
||||
//rootWindow = Functions.XRootWindow(DefaultDisplay, DefaultScreen);
|
||||
screenCount = Functions.XScreenCount(DefaultDisplay);
|
||||
Debug.Print("Default Display: {0}, Default Screen: {1}, Default Root Window: {2}, Screen Count: {3}",
|
||||
DefaultDisplay, DefaultScreen, RootWindow, ScreenCount);
|
||||
//Debug.Print("Default Display: {0}, Default Screen: {1}, Default Root Window: {2}, Screen Count: {3}",
|
||||
// DefaultDisplay, DefaultScreen, RootWindow, ScreenCount);
|
||||
Debug.Print("Display connection: {0}, Screen count: {1}", DefaultDisplay, ScreenCount);
|
||||
}
|
||||
|
||||
static void CurrentDomain_ProcessExit(object sender, EventArgs e)
|
||||
{
|
||||
if (defaultDisplay != IntPtr.Zero) { Functions.XCloseDisplay(defaultDisplay); defaultDisplay = IntPtr.Zero; }
|
||||
if (defaultDisplay != IntPtr.Zero)
|
||||
{
|
||||
Functions.XCloseDisplay(defaultDisplay);
|
||||
defaultDisplay = IntPtr.Zero;
|
||||
defaultScreen = 0;
|
||||
rootWindow = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
// Display management
|
||||
[DllImport(_dll_name, EntryPoint = "XOpenDisplay")]
|
||||
extern public static IntPtr OpenDisplay([MarshalAs(UnmanagedType.LPTStr)] string display_name);
|
||||
//[DllImport(_dll_name, EntryPoint = "XOpenDisplay")]
|
||||
//extern public static IntPtr OpenDisplay([MarshalAs(UnmanagedType.LPTStr)] string display_name);
|
||||
|
||||
[DllImport(_dll_name, EntryPoint = "XCloseDisplay")]
|
||||
extern public static void CloseDisplay(Display display);
|
||||
//[DllImport(_dll_name, EntryPoint = "XCloseDisplay")]
|
||||
//extern public static void CloseDisplay(Display display);
|
||||
|
||||
[DllImport(_dll_name, EntryPoint = "XCreateColormap")]
|
||||
extern public static IntPtr CreateColormap(Display display, Window window, IntPtr visual, int alloc);
|
||||
//[DllImport(_dll_name, EntryPoint = "XCreateColormap")]
|
||||
//extern public static IntPtr CreateColormap(Display display, Window window, IntPtr visual, int alloc);
|
||||
|
||||
#region Window handling
|
||||
|
||||
|
|
|
@ -13,6 +13,35 @@ using System.Runtime.InteropServices;
|
|||
|
||||
namespace OpenTK.Platform.X11
|
||||
{
|
||||
#region Types
|
||||
|
||||
// using XID = System.Int32;
|
||||
using Window = System.IntPtr;
|
||||
using Drawable = System.IntPtr;
|
||||
using Font = System.IntPtr;
|
||||
using Pixmap = System.IntPtr;
|
||||
using Cursor = System.IntPtr;
|
||||
using Colormap = System.IntPtr;
|
||||
using GContext = System.IntPtr;
|
||||
using KeySym = System.IntPtr;
|
||||
using Mask = System.IntPtr;
|
||||
using Atom = System.IntPtr;
|
||||
using VisualID = System.IntPtr;
|
||||
using Time = System.UInt32;
|
||||
using KeyCode = System.Byte; // Or maybe ushort?
|
||||
|
||||
using Display = System.IntPtr;
|
||||
using XPointer = System.IntPtr;
|
||||
|
||||
// Randr and Xrandr
|
||||
using Bool = System.Boolean;
|
||||
using XRRScreenConfiguration = System.IntPtr; // opaque datatype
|
||||
using Rotation = System.UInt16;
|
||||
using Status = System.Int32;
|
||||
using SizeID = System.UInt16;
|
||||
|
||||
#endregion
|
||||
|
||||
internal static partial class Functions
|
||||
{
|
||||
public static readonly object Lock = new object();
|
||||
|
@ -337,13 +366,15 @@ namespace OpenTK.Platform.X11
|
|||
public extern static void XPeekEvent(IntPtr display, ref XEvent xevent);
|
||||
|
||||
[DllImport("libX11", EntryPoint = "XGetVisualInfo")]
|
||||
static extern IntPtr XGetVisualInfoInternal(IntPtr display, IntPtr vinfo_mask, ref XVisualInfo template,
|
||||
out int nitems);
|
||||
|
||||
static extern IntPtr XGetVisualInfoInternal(IntPtr display, IntPtr vinfo_mask, ref XVisualInfo template, out int nitems);
|
||||
|
||||
public static IntPtr XGetVisualInfo(IntPtr display, XVisualInfoMask vinfo_mask, ref XVisualInfo template, out int nitems)
|
||||
{
|
||||
return XGetVisualInfoInternal(display, (IntPtr)(int)vinfo_mask, ref template, out nitems);
|
||||
}
|
||||
|
||||
[DllImport("libX11")]
|
||||
public static extern IntPtr XCreateColormap(Display display, Window window, IntPtr visual, int alloc);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ namespace OpenTK.Platform.X11
|
|||
xplatui.GetField("CustomVisual", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic)
|
||||
.SetValue(null, window.VisualInfo.visual);
|
||||
xplatui.GetField("CustomColormap", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic)
|
||||
.SetValue(null, API.CreateColormap(window.Display, window.RootWindow, window.VisualInfo.visual, 0));
|
||||
.SetValue(null, Functions.XCreateColormap(window.Display, window.RootWindow, window.VisualInfo.visual, 0));
|
||||
}
|
||||
|
||||
#region --- IGLControl Members ---
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#region --- License ---
|
||||
/* Copyright (c) 2007 Stefanos Apostolopoulos
|
||||
* See license.txt for license info
|
||||
/* Licensed under the MIT/X11 license.
|
||||
* Copyright (c) 2006-2008 the OpenTK Team.
|
||||
* This notice may not be removed from any source distribution.
|
||||
* See license.txt for licensing detailed licensing details.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
|
@ -93,7 +95,7 @@ namespace OpenTK.Platform.X11
|
|||
// System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null);
|
||||
|
||||
// Open a display connection to the X server, and obtain the screen and root window.
|
||||
window.Display = API.OpenDisplay(null); // null == default display //window.Display = API.DefaultDisplay;
|
||||
window.Display = API.DefaultDisplay;//Functions.XOpenDisplay(IntPtr.Zero); // IntPtr.Zero == default display
|
||||
if (window.Display == IntPtr.Zero)
|
||||
throw new Exception("Could not open connection to X");
|
||||
window.Screen = Functions.XDefaultScreen(window.Display); //API.DefaultScreen;
|
||||
|
@ -157,13 +159,11 @@ namespace OpenTK.Platform.X11
|
|||
XSetWindowAttributes attributes = new XSetWindowAttributes();
|
||||
attributes.background_pixel = IntPtr.Zero;
|
||||
attributes.border_pixel = IntPtr.Zero;
|
||||
attributes.colormap =
|
||||
API.CreateColormap(window.Display, window.RootWindow, window.VisualInfo.visual, 0/*AllocNone*/);
|
||||
window.EventMask =
|
||||
EventMask.StructureNotifyMask | EventMask.SubstructureNotifyMask | EventMask.ExposureMask |
|
||||
EventMask.KeyReleaseMask | EventMask.KeyPressMask |
|
||||
EventMask.PointerMotionMask | // Bad! EventMask.PointerMotionHintMask |
|
||||
EventMask.ButtonPressMask | EventMask.ButtonReleaseMask;
|
||||
attributes.colormap = Functions.XCreateColormap(window.Display, window.RootWindow, window.VisualInfo.visual, 0/*AllocNone*/);
|
||||
window.EventMask = EventMask.StructureNotifyMask | EventMask.SubstructureNotifyMask | EventMask.ExposureMask |
|
||||
EventMask.KeyReleaseMask | EventMask.KeyPressMask |
|
||||
EventMask.PointerMotionMask | // Bad! EventMask.PointerMotionHintMask |
|
||||
EventMask.ButtonPressMask | EventMask.ButtonReleaseMask;
|
||||
attributes.event_mask = (IntPtr)window.EventMask;
|
||||
|
||||
uint mask = (uint)SetWindowValuemask.ColorMap | (uint)SetWindowValuemask.EventMask |
|
||||
|
@ -666,8 +666,8 @@ namespace OpenTK.Platform.X11
|
|||
{
|
||||
if (window.WindowHandle != IntPtr.Zero)
|
||||
Functions.XDestroyWindow(window.Display, window.WindowHandle);
|
||||
if (window.Display != IntPtr.Zero)
|
||||
Functions.XCloseDisplay(window.Display);
|
||||
//if (window.Display != IntPtr.Zero)
|
||||
// Functions.XCloseDisplay(window.Display);
|
||||
window = null;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,11 @@ namespace OpenTK.Platform.X11
|
|||
public GraphicsMode SelectGraphicsMode(ColorFormat color, int depth, int stencil, int samples, ColorFormat accum,
|
||||
int buffers, bool stereo)
|
||||
{
|
||||
GraphicsMode gfx; // The actual GraphicsMode that will be selected.
|
||||
List<int> visualAttributes = new List<int>();
|
||||
IntPtr visual;
|
||||
|
||||
Debug.Print("Bits per pixel: {0}", color.BitsPerPixel);
|
||||
|
||||
if (color.BitsPerPixel > 0)
|
||||
{
|
||||
|
@ -41,6 +45,8 @@ namespace OpenTK.Platform.X11
|
|||
visualAttributes.Add(color.Alpha);
|
||||
}
|
||||
|
||||
Debug.Print("Depth: {0}", depth);
|
||||
|
||||
if (depth > 0)
|
||||
{
|
||||
visualAttributes.Add((int)GLXAttribute.DEPTH_SIZE);
|
||||
|
@ -73,53 +79,67 @@ namespace OpenTK.Platform.X11
|
|||
|
||||
visualAttributes.Add((int)0);
|
||||
|
||||
// Select a visual that matches the parameters set by the user.
|
||||
lock (API.Lock)
|
||||
{
|
||||
IntPtr display = API.DefaultDisplay; //Functions.XOpenDisplay(IntPtr.Zero);
|
||||
int screen = Functions.XDefaultScreen(display);
|
||||
IntPtr root = Functions.XRootWindow(display, screen);
|
||||
Debug.Print("Display: {0}, Screen: {1}, RootWindow: {2}", display, screen, root);
|
||||
|
||||
visual = Glx.ChooseVisual(display, screen, visualAttributes.ToArray());
|
||||
|
||||
if (visual == IntPtr.Zero)
|
||||
throw new GraphicsContextException("Requested GraphicsMode not available.");
|
||||
|
||||
XVisualInfo info = (XVisualInfo)Marshal.PtrToStructure(visual, typeof(XVisualInfo));
|
||||
|
||||
// See what we *really* got:
|
||||
int r, g, b, a;
|
||||
Glx.GetConfig(display, ref info, GLXAttribute.ALPHA_SIZE, out a);
|
||||
Glx.GetConfig(display, ref info, GLXAttribute.RED_SIZE, out r);
|
||||
Glx.GetConfig(display, ref info, GLXAttribute.GREEN_SIZE, out g);
|
||||
Glx.GetConfig(display, ref info, GLXAttribute.BLUE_SIZE, out b);
|
||||
int ar, ag, ab, aa;
|
||||
Glx.GetConfig(display, ref info, GLXAttribute.ACCUM_ALPHA_SIZE, out aa);
|
||||
Glx.GetConfig(display, ref info, GLXAttribute.ACCUM_RED_SIZE, out ar);
|
||||
Glx.GetConfig(display, ref info, GLXAttribute.ACCUM_GREEN_SIZE, out ag);
|
||||
Glx.GetConfig(display, ref info, GLXAttribute.ACCUM_BLUE_SIZE, out ab);
|
||||
Glx.GetConfig(display, ref info, GLXAttribute.DEPTH_SIZE, out depth);
|
||||
Glx.GetConfig(display, ref info, GLXAttribute.STENCIL_SIZE, out stencil);
|
||||
Glx.GetConfig(display, ref info, GLXAttribute.SAMPLES, out samples);
|
||||
Glx.GetConfig(display, ref info, GLXAttribute.DOUBLEBUFFER, out buffers);
|
||||
++buffers; // the above lines returns 0 - false and 1 - true.
|
||||
int st;
|
||||
Glx.GetConfig(display, ref info, GLXAttribute.STEREO, out st);
|
||||
stereo = st != 0;
|
||||
|
||||
gfx = new GraphicsMode(info.visualid, new ColorFormat(r, g, b, a), depth, stencil, samples,
|
||||
new ColorFormat(ar, ag, ab, aa), buffers, stereo);
|
||||
|
||||
//Functions.XCloseDisplay(display);
|
||||
}
|
||||
|
||||
// Prepare Windows.Forms for creating OpenGL drawables.
|
||||
// We reuse the display connection.
|
||||
// TODO: Multiple screens.
|
||||
Type xplatui = Type.GetType("System.Windows.Forms.XplatUIX11, System.Windows.Forms");
|
||||
IntPtr display = (IntPtr)xplatui.GetField("DisplayHandle",
|
||||
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null);
|
||||
IntPtr root = (IntPtr)xplatui.GetField("RootWindow",
|
||||
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null);
|
||||
int screen = (int)xplatui.GetField("ScreenNo",
|
||||
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null);
|
||||
lock (API.Lock)
|
||||
{
|
||||
Type xplatui = Type.GetType("System.Windows.Forms.XplatUIX11, System.Windows.Forms");
|
||||
IntPtr display = (IntPtr)xplatui.GetField("DisplayHandle",
|
||||
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null);
|
||||
IntPtr root = (IntPtr)xplatui.GetField("RootWindow",
|
||||
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null);
|
||||
int screen = (int)xplatui.GetField("ScreenNo",
|
||||
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null);
|
||||
|
||||
Debug.Print("Display: {0}, Screen: {1}, RootWindow: {2}", display, screen, root);
|
||||
|
||||
IntPtr visual = Glx.ChooseVisual(display, screen, visualAttributes.ToArray());
|
||||
xplatui.GetField("CustomVisual", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic)
|
||||
.SetValue(null, visual);
|
||||
xplatui.GetField("CustomColormap", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic)
|
||||
.SetValue(null, Functions.XCreateColormap(display, root, visual, 0));
|
||||
|
||||
if (visual == IntPtr.Zero)
|
||||
throw new GraphicsContextException("Requested GraphicsMode not available.");
|
||||
}
|
||||
|
||||
XVisualInfo info = (XVisualInfo)Marshal.PtrToStructure(visual, typeof(XVisualInfo));
|
||||
|
||||
// See what we *really* got:
|
||||
int r, g, b, a;
|
||||
Glx.GetConfig(display, ref info, GLXAttribute.ALPHA_SIZE, out a);
|
||||
Glx.GetConfig(display, ref info, GLXAttribute.RED_SIZE, out r);
|
||||
Glx.GetConfig(display, ref info, GLXAttribute.GREEN_SIZE, out g);
|
||||
Glx.GetConfig(display, ref info, GLXAttribute.BLUE_SIZE, out b);
|
||||
int ar, ag, ab, aa;
|
||||
Glx.GetConfig(display, ref info, GLXAttribute.ACCUM_ALPHA_SIZE, out aa);
|
||||
Glx.GetConfig(display, ref info, GLXAttribute.ACCUM_RED_SIZE, out ar);
|
||||
Glx.GetConfig(display, ref info, GLXAttribute.ACCUM_GREEN_SIZE, out ag);
|
||||
Glx.GetConfig(display, ref info, GLXAttribute.ACCUM_BLUE_SIZE, out ab);
|
||||
Glx.GetConfig(display, ref info, GLXAttribute.DEPTH_SIZE, out depth);
|
||||
Glx.GetConfig(display, ref info, GLXAttribute.STENCIL_SIZE, out stencil);
|
||||
Glx.GetConfig(display, ref info, GLXAttribute.SAMPLES, out samples);
|
||||
Glx.GetConfig(display, ref info, GLXAttribute.DOUBLEBUFFER, out buffers);
|
||||
++buffers; // the above lines returns 0 - false and 1 - true.
|
||||
int st;
|
||||
Glx.GetConfig(display, ref info, GLXAttribute.STEREO, out st);
|
||||
stereo = st != 0;
|
||||
|
||||
GraphicsMode gfx = new GraphicsMode(info.visualid, new ColorFormat(r, g, b, a), depth, stencil, samples,
|
||||
new ColorFormat(ar, ag, ab, aa), buffers, stereo);
|
||||
|
||||
xplatui.GetField("CustomVisual", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic)
|
||||
.SetValue(null, visual);
|
||||
xplatui.GetField("CustomColormap", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic)
|
||||
.SetValue(null, API.CreateColormap(display, root, visual, 0));
|
||||
Functions.XFree(visual);
|
||||
|
||||
return gfx;
|
||||
}
|
||||
|
|
|
@ -37,7 +37,6 @@ namespace OpenTK.Platform.X11
|
|||
{
|
||||
// Get available resolutions. Then, for each resolution get all
|
||||
// available rates.
|
||||
// TODO: Find a way to get all available depths, too.
|
||||
// TODO: Global X11 lock.
|
||||
for (int screen = 0; screen < API.ScreenCount; screen++)
|
||||
{
|
||||
|
@ -85,11 +84,10 @@ namespace OpenTK.Platform.X11
|
|||
int current_resolution_index = Functions.XRRConfigCurrentConfiguration(screen_config, out current_rotation);
|
||||
|
||||
DisplayDevice current_device = new DisplayDevice(
|
||||
new DisplayResolution(
|
||||
available_res[current_resolution_index].Width,
|
||||
available_res[current_resolution_index].Height,
|
||||
current_depth, current_refresh_rate),
|
||||
screen == API.DefaultScreen, available_res);
|
||||
new DisplayResolution(available_res[current_resolution_index].Width, available_res[current_resolution_index].Height,
|
||||
current_depth, current_refresh_rate),
|
||||
screen == Functions.XDefaultScreen(API.DefaultDisplay),
|
||||
available_res);
|
||||
|
||||
deviceToScreen.Add(current_device, screen);
|
||||
deviceToDefaultResolution.Add(current_device, current_resolution_index);
|
||||
|
@ -127,7 +125,7 @@ namespace OpenTK.Platform.X11
|
|||
|
||||
static float FindCurrentRefreshRate(int screen)
|
||||
{
|
||||
IntPtr screen_config = Functions.XRRGetScreenInfo(API.DefaultDisplay, API.RootWindow);
|
||||
IntPtr screen_config = Functions.XRRGetScreenInfo(API.DefaultDisplay, Functions.XRootWindow(API.DefaultDisplay, screen));
|
||||
ushort rotation = 0;
|
||||
int size = Functions.XRRConfigCurrentConfiguration(screen_config, out rotation);
|
||||
short rate = Functions.XRRConfigCurrentRate(screen_config);
|
||||
|
|
Loading…
Reference in a new issue