Browse Source

Create zgl_screen.pas

Seenkao 3 years ago
parent
commit
5635bf2309
1 changed files with 1077 additions and 0 deletions
  1. 1077 0
      Zengl_SRC/src/zgl_screen.pas

+ 1077 - 0
Zengl_SRC/src/zgl_screen.pas

@@ -0,0 +1,1077 @@
+{
+ *  Copyright (c) 2012 Andrey Kemka
+ *
+ *  This software is provided 'as-is', without any express or
+ *  implied warranty. In no event will the authors be held
+ *  liable for any damages arising from the use of this software.
+ *
+ *  Permission is granted to anyone to use this software for any purpose,
+ *  including commercial applications, and to alter it and redistribute
+ *  it freely, subject to the following restrictions:
+ *
+ *  1. The origin of this software must not be misrepresented;
+ *     you must not claim that you wrote the original software.
+ *     If you use this software in a product, an acknowledgment
+ *     in the product documentation would be appreciated but
+ *     is not required.
+ *
+ *  2. Altered source versions must be plainly marked as such,
+ *     and must not be misrepresented as being the original software.
+ *
+ *  3. This notice may not be removed or altered from any
+ *     source distribution.
+
+ !!! modification from Serge 26.02.2022
+}
+unit zgl_screen;
+
+{$I zgl_config.cfg}
+{$IF defined(iOS) or defined(MAC_COCOA)}
+  {$modeswitch objectivec1}
+{$IfEnd}
+
+interface
+
+uses
+{$IFDEF USE_X11}
+  X, XLib, XRandr, UnixType,
+  zgl_glx_wgl,
+{$ENDIF}
+{$IFDEF WINDOWS}
+  Windows,
+  zgl_glx_wgl,
+{$ENDIF}
+{$IFDEF MACOSX}{$IfDef MAC_COCOA}
+  CocoaAll,
+{$EndIf}
+  MacOSAll,
+{$ENDIF}
+{$IFDEF iOS}
+  iPhoneAll, CFBase, CFString,
+{$ENDIF}
+  zgl_gltypeconst,
+  zgl_types;
+
+const
+  REFRESH_MAXIMUM = 0;
+  REFRESH_DEFAULT = 1;
+
+{$IfNDef ANDROID}
+// Rus: инициализация окна.
+// Eng: window initialization.
+procedure scr_Init;
+{$IfNDef MAC_COCOA}
+// Rus: сбросить настройки окна в исходное состояние.
+// Eng: reset the window settings to their original state.
+procedure scr_Reset;
+{$EndIf}
+// Rus: создание окна.
+// Eng: window creation.
+function  scr_Create: Boolean;
+// Rus: уничтожение окна.
+// Eng: window destruction.
+procedure scr_Destroy;
+{$EndIf}
+
+// Rus: очистка окна.
+// Eng: window cleaning.
+procedure scr_Clear;
+// Rus:
+// Eng:
+procedure scr_Flush;
+
+{$IfNDef USE_INIT_HANDLE}
+// Rus: установка заданных значений окна. Значения заданы посредством
+//      zgl_SetParam или по умолчанию.
+// Eng: setting window preset values. Values are set via zgl_SetParam or by default.
+function  scr_SetOptions(): Boolean;
+{$EndIf}
+// Rus: корректировка окна вывода заданным значениям.
+// Eng: adjustment of the output window to the given values.
+procedure scr_CorrectResolution(Width, Height: Word);
+// Rus: установка порта вывода. На данное время только 2D.
+// Eng: setting the output port. Currently only 2D.
+procedure scr_SetViewPort;
+// Rus: включение/выключение вертикальной синхронизации.
+// Eng: enable/disable vertical sync.
+procedure scr_SetVSync(WSync: Boolean);
+// Rus: включение/выключение очистки окна заданным цветом и установка цвета
+//      очистки. RGB, A = 255;
+// Eng: enable/disable window cleaning with a specified color and set the
+//      cleaning color. RGB, A=255;
+procedure scr_SetClearColor(flag: Boolean = true; Color: Cardinal = 0);
+// Rus: процедура вертикальной синхронизации. Вызывать не надо, происходит по
+//      умолчанию, если включена вертикальная синхронизация.
+// Eng: vertical synchronization procedure. Don't call, happens by default if
+//      vertical sync is enabled.
+procedure scr_VSync;
+{$IfNDef USE_INIT_HANDLE}
+// Rus: установка FPS. Требуется доработка на проверку частот монитора.
+// Eng: FPS setting. Improvement is required to check the frequencies of the monitor.
+procedure scr_SetFPS(FPS: LongWord);
+{$EndIf}
+
+//procedure scr_SetFSAA(FSAA: Byte);
+
+// Rus: Чтение определённой области окна в память.
+// Eng: Reading a specific region of a window into memory.
+procedure scr_ReadPixels(var pData: Pointer; X, Y, Width, Height: Word);
+{$IfNDef ANDROID}
+// на данное время ни где не используется, кроме инициализации. Нужен будет
+// выводимый список всех возможных разрешений экрана?
+//procedure scr_GetResList;
+{$EndIf}
+// Rus: установка глубины для 2D режима. Можно использовать и для 3D, учитывая,
+//      что Far не должно быть меньше нуля.
+// Eng: depth setting for 2D mode. Can be used for 3D as well, given that Far
+//      must not be less than zero.
+procedure Set2DNearFar(newNear, newFar: {$IfNDef USE_GLES}Double{$Else}{$IF DEFINED(USE_GLES_ON_DESKTOP) and DEFINED(USE_AMD_DRIVERS)}Double{$Else}Single{$IfEnd}{$EndIf});
+// Rus: установка версии OpenGL, маски и флагов. Вызывать обязательно до
+//      создания окна (до zgl_Init)!!! Совместимые версии только до OpenGL 3.1,
+//      далее они не совместимы со старым контекстом.
+// Eng:
+procedure SetGLVersionAndFlags({$IfNDef MAC_COCOA}major, minor: Integer; flag: LongWord = COMPATIBILITY_VERSION{$Else}mode: LongWord{$EndIf});
+
+type
+  zglPResolutionList = ^zglTResolutionList;
+  zglTResolutionList = record
+    Count : Integer;
+    Width : array of Integer;
+    Height: array of Integer;
+  {$ifdef Windows}
+    frequency: array of Integer;
+  {$endif}
+  end;
+
+{$IFDEF WINDOWS}
+type
+  HMONITOR = THandle;
+  MONITORINFOEX = record              // inormation monitor
+    cbSize   : LongWord;
+    rcMonitor: TRect;
+    rcWork   : TRect;
+    dwFlags  : LongWord;
+    szDevice : array[0..CCHDEVICENAME - 1] of WideChar;
+  end;
+{$ENDIF}
+
+var
+  scrRefresh    : Integer = REFRESH_MAXIMUM;
+  scrVSync      : Boolean = false;
+  {$IfNDef ANDROID}
+  scrResList    : zglTResolutionList;
+  scrInitialized: Boolean;
+  {$EndIf}
+
+  // Viewport
+  scrViewportX: Integer;
+  scrViewportY: Integer;
+  scrViewportW: Integer;
+  scrViewportH: Integer;
+
+  // Resolution Correct
+  scrResW : Integer;
+  scrResH : Integer;
+  scrResCX: Single  = 1;
+  scrResCY: Single  = 1;
+  scrAddCX: Integer = 0;
+  scrAddCY: Integer = 0;
+  scrSubCX: Integer = 0;
+  scrSubCY: Integer = 0;
+
+
+  scrViewPort       : Boolean = True;  // этот флаг можно отключать, если мы не меняем поле прорисовки.
+  scrClearColor     : Boolean = True;
+  scr_UseClearColor : zglTColor;
+
+  {$IFDEF USE_X11}
+  scrDisplay  : PDisplay;
+  scrDefault  : cint;
+  scrSettings : Pointer;
+  scrDesktop  : LongInt;
+  scrCurrent  : LongInt;
+  scrModeCount: LongInt;
+  scrModeList : PXRRScreenSize;
+  scrEventBase: cint;
+  scrErrorBase: cint;
+  scrRotation : Word;
+  {$ENDIF}
+  {$IFDEF WINDOWS}
+  scrSettings: DEVMODEW;
+  scrDesktop : DEVMODEW;
+  scrMonInfo : MONITORINFOEX;
+  {$ENDIF}
+  {$IFDEF MACOSX}
+  scrDisplay  : CGDirectDisplayID;
+  scrDesktop  : {$IfDef MAC_COCOA}CGDisplayModeRef{$Else} CFDictionaryRef{$EndIf};
+  scrDesktopW : Integer;
+  scrDesktopH : Integer;
+  scrSettings : CFDictionaryRef;
+  scrModeCount: CFIndex;
+  scrModeList : CFArrayRef;
+  {$ENDIF}
+  {$IFDEF iOS}
+  scrDisplayLink : CADisplayLink;
+  scrCurrModeW   : Integer;
+  scrCurrModeH   : Integer;
+  scrDesktopW    : Integer;
+  scrDesktopH    : Integer;
+  scrOrientation : UIInterfaceOrientation;
+  scrCanLandscape: Boolean;
+  scrCanPortrait : Boolean;
+  {$ENDIF}
+  {$IFDEF ANDROID}
+  scrDesktopW: Integer;
+  scrDesktopH: Integer;
+  {$ENDIF}
+  {$IfNDef USE_GLES}
+  scrFar: Double = 1;
+  scrNear: Double = - 1;
+  {$Else}
+  {$IF DEFINED(USE_GLES_ON_DESKTOP) and DEFINED(USE_AMD_DRIVERS)}
+  scrFar: Double = 1;
+  scrNear: Double = - 1;
+  {$Else}
+  scrFar: Single = 1;
+  scrNear: Single = - 1;
+  {$EndIf}
+  {$EndIf}
+
+
+implementation
+uses
+  zgl_application,
+  zgl_window,
+  {$IFNDEF USE_GLES}
+  zgl_opengl,
+  zgl_opengl_all,
+  {$ELSE}
+  zgl_opengles,
+  zgl_opengles_all,
+  {$ENDIF}
+  zgl_render,
+  zgl_render_2d,
+  zgl_camera_2d,
+  zgl_log,
+  zgl_utils
+  ;
+
+{$IFDEF USE_X11}
+function XOpenIM(para1:PDisplay; para2:PXrmHashBucketRec; para3:PAnsiChar; para4:Pchar):PXIM;cdecl;external;
+function XCloseIM(im: PXIM): TStatus;cdecl;external;
+function XCreateIC(para1: PXIM; para2: array of const):PXIC;cdecl;external;
+procedure XDestroyIC(ic: PXIC);cdecl;external;
+{$ENDIF}
+{$IFDEF WINDOWS}
+const
+  MONITOR_DEFAULTTOPRIMARY = $00000001;
+function MonitorFromWindow(hwnd: HWND; dwFlags: LongWord): THandle; stdcall; external 'user32.dll';
+function GetMonitorInfoW(monitor: HMONITOR; var moninfo: MONITORINFOEX): BOOL; stdcall; external 'user32.dll';
+{$ENDIF}
+
+{$IfNDef ANDROID}
+procedure scr_GetResList;
+var
+  i: Integer;
+  {$IFDEF USE_X11}
+  tmpSettings: PXRRScreenSize;
+  {$ENDIF}
+  {$IFDEF WINDOWS}
+  tmpSettings: DEVMODEW;
+  {$ENDIF}
+  {$IFDEF MACOSX}
+  tmpSettings  : UnivPtr;
+  width, height: Integer;
+
+  {$ENDIF}
+  function Already(Width, Height: Integer): Boolean;
+  var
+    j: Integer;
+  begin
+    Result := FALSE;
+    for j := 0 to scrResList.Count - 1 do
+      if (scrResList.Width[j] = Width) and (scrResList.Height[j] = Height) Then Result := TRUE;
+  end;
+begin
+{$IFDEF USE_X11}
+  tmpSettings := scrModeList;
+  for i := 0 to scrModeCount - 1 do
+  begin
+    if not Already(tmpSettings.Width, tmpSettings.Height) Then
+    begin
+      INC(scrResList.Count);
+      SetLength(scrResList.Width, scrResList.Count);
+      SetLength(scrResList.Height, scrResList.Count);
+      scrResList.Width[scrResList.Count - 1]  := tmpSettings.Width;
+      scrResList.Height[scrResList.Count - 1] := tmpSettings.Height;
+    end;
+    INC(tmpSettings);
+  end;
+{$ENDIF}
+{$IFDEF WINDOWS}
+  i := 0;
+  FillChar(tmpSettings, SizeOf(DEVMODEW), 0);
+  tmpSettings.dmSize := SizeOf(DEVMODEW);
+  while EnumDisplaySettingsW(scrMonInfo.szDevice, i, tmpSettings) <> FALSE do             
+  begin
+    if not Already(tmpSettings.dmPelsWidth, tmpSettings.dmPelsHeight) Then
+    begin
+      INC(scrResList.Count);                                                              
+      SetLength(scrResList.Width, scrResList.Count);
+      SetLength(scrResList.Height, scrResList.Count);
+      SetLength(scrResList.frequency, scrResList.Count);
+      scrResList.Width[scrResList.Count - 1]  := tmpSettings.dmPelsWidth;
+      scrResList.Height[scrResList.Count - 1] := tmpSettings.dmPelsHeight;
+      scrResList.frequency[scrResList.Count - 1] := tmpSettings.dmDisplayFrequency;       
+    end;
+    INC(i);
+  end;
+{$ENDIF}
+{$IFDEF MACOSX}
+  tmpSettings := scrModeList;
+  for i := 0 to scrModeCount - 1 do
+  begin
+    tmpSettings := CFArrayGetValueAtIndex(scrModeList, i);
+
+    CFNumberGetValue(CFDictionaryGetValue(tmpSettings, CFSTRP('Width')), kCFNumberIntType, @width);
+    CFNumberGetValue(CFDictionaryGetValue(tmpSettings, CFSTRP('Height')), kCFNumberIntType, @height);
+    if not Already(width, height) Then
+    begin
+      INC(scrResList.Count);
+      SetLength(scrResList.Width, scrResList.Count);
+      SetLength(scrResList.Height, scrResList.Count);
+      scrResList.Width[scrResList.Count - 1]  := width;
+      scrResList.Height[scrResList.Count - 1] := height;
+    end;
+  end;
+{$ENDIF}
+{$IFDEF iOS}
+  scrResList.Count := 1;
+  SetLength(scrResList.Width, 1);
+  SetLength(scrResList.Height, 1);
+  scrResList.Width[0] := scrDesktopW;
+  scrResList.Height[0] := scrDesktopH;
+{$ENDIF}
+end;
+
+procedure scr_Init;
+  {$IFDEF iOS}
+  var
+    i           : Integer;
+    orientations: NSArray;
+    tmp         : array[0..255] of AnsiChar;
+  {$ENDIF}
+  {$ifdef windows}
+  var
+    scrMonitor: THandle;
+    i: Integer;
+  {$endif}
+begin
+{$IFDEF USE_X11}
+  if not appInitialized Then
+  begin
+    log_Init();
+
+    if Assigned(scrDisplay) Then
+      XCloseDisplay(scrDisplay);
+
+    scrDisplay := XOpenDisplay(nil);
+    if not Assigned(scrDisplay) Then
+    begin
+      u_Error('Cannot connect to X server.');
+      exit;
+    end;
+
+    scrDefault := DefaultScreen(scrDisplay);
+    wndRoot    := DefaultRootWindow(scrDisplay);
+
+    XRRSelectInput(scrDisplay, wndRoot, RRScreenChangeNotifyMask);
+    XRRQueryExtension(scrDisplay, @scrEventBase, @scrErrorBase) ;
+  end;
+
+  scrModeList := XRRSizes(scrDisplay, XRRRootToScreen(scrDisplay, wndRoot), @scrModeCount);
+  scrSettings := XRRGetScreenInfo(scrDisplay, wndRoot);
+  scrDesktop  := XRRConfigCurrentConfiguration(scrSettings, @scrRotation);
+{$ENDIF}
+{$IFDEF WINDOWS}
+  i := SizeOf(MONITORINFOEX);
+  if scrMonInfo.cbSize <> i Then
+  begin
+    scrMonitor := MonitorFromWindow(wndHandle, MONITOR_DEFAULTTOPRIMARY);
+    FillChar(scrMonInfo, i, 0);
+    scrMonInfo.cbSize := i;
+    GetMonitorInfoW(scrMonitor, scrMonInfo);
+  end;
+
+  i := SizeOf(DEVMODEW);
+  FillChar(scrDesktop, i, 0);
+  scrDesktop.dmSize := i;
+  // Delphi: standard ENUM_REGISTRY_SETTINGS doesn't exist in Windows unit, no comments...
+  EnumDisplaySettingsW(scrMonInfo.szDevice, LongWord(-2), scrDesktop);
+{$ENDIF}
+{$IFDEF MACOSX}
+  scrDisplay  := CGMainDisplayID();
+  scrDesktop  := {$IfNDef MAC_COCOA}CGDisplayCurrentMode(scrDisplay);{$Else}CGDisplayCopyDisplayMode(scrDisplay);{$EndIf}
+  scrDesktopW := CGDisplayPixelsWide(scrDisplay);
+  scrDesktopH := CGDisplayPixelsHigh(scrDisplay);
+
+  scrModeList  := {$IfNDef MAC_COCOA}CGDisplayAvailableModes(scrDisplay){$Else}CGDisplayCopyAllDisplayModes(scrDisplay, nil){$EndIf};
+  scrModeCount := CFArrayGetCount(scrModeList);
+{$ENDIF}
+{$IFDEF iOS}
+  if not appInitialized Then exit;
+
+  app_InitPool();
+
+  orientations := NSBundle.mainBundle.infoDictionary.objectForKey(utf8_GetNSString('UISupportedInterfaceOrientations'));
+  for i := 0 to orientations.count() - 1 do
+  begin
+    CFStringGetCString(CFStringRef(orientations.objectAtIndex(i)), @tmp[0], 255, kCFStringEncodingUTF8);
+    if (tmp = 'UIInterfaceOrientationLandscapeLeft') or (tmp = 'UIInterfaceOrientationLandscapeRight') Then
+      scrCanLandscape := TRUE;
+    if (tmp = 'UIInterfaceOrientationPortrait') or (tmp = 'UIInterfaceOrientationPortraitUpsideDown') Then
+      scrCanPortrait := TRUE;
+  end;
+
+  if UIDevice.currentDevice.systemVersion.floatValue >= 3.2 Then
+  begin
+    scrCurrModeW := Round(UIScreen.mainScreen.currentMode.size.width);
+    scrCurrModeH := Round(UIScreen.mainScreen.currentMode.size.height);
+
+    if (UIDevice.currentDevice.userInterfaceIdiom = UIUserInterfaceIdiomPhone) and (UIDevice.currentDevice.model.rangeOfString(utf8_GetNSString('iPad')).location <> NSNotFound) Then
+    begin
+      scrCurrModeW := Round(480 * UIScreen.mainScreen.scale);
+      scrCurrModeH := Round(320 * UIScreen.mainScreen.scale);
+    end;
+  end else
+  begin
+    scrCurrModeW := Round(UIScreen.mainScreen.bounds.size.width);
+    scrCurrModeH := Round(UIScreen.mainScreen.bounds.size.height);
+  end;
+
+  if (scrCurrModeW > scrCurrModeH) Then
+  begin
+    scrDesktopH  := scrCurrModeW;
+    scrCurrModeW := scrCurrModeH;
+    scrCurrModeH := scrDesktopH;
+  end;
+
+  scrOrientation := UIApplication.sharedApplication.statusBarOrientation();
+  if scrCanPortrait and ((scrOrientation = UIInterfaceOrientationPortrait) or (scrOrientation = UIInterfaceOrientationPortraitUpsideDown)) Then
+  begin
+    wndPortrait := TRUE;
+    scrDesktopW := scrCurrModeW;
+    scrDesktopH := scrCurrModeH;
+  end else
+    if scrCanLandscape and ((scrOrientation = UIInterfaceOrientationLandscapeLeft) or (scrOrientation = UIInterfaceOrientationLandscapeRight)) Then
+    begin
+      wndPortrait := FALSE;
+      scrDesktopW := scrCurrModeH;
+      scrDesktopH := scrCurrModeW;
+    end else
+    begin
+      wndPortrait := scrCanPortrait;
+      scrDesktopW := scrCurrModeW;
+      scrDesktopH := scrCurrModeH;
+    end;
+
+  oglWidth    := scrDesktopW;
+  oglHeight   := scrDesktopH;
+  oglTargetW  := scrDesktopW;
+  oglTargetH  := scrDesktopH;
+{$ENDIF}
+{$IfNDef MAC_COCOA}
+  scr_GetResList;
+{$EndIf}
+  scrInitialized := TRUE;
+end;
+
+{$IfNDef MAC_COCOA}
+procedure scr_Reset;
+begin
+{$IFDEF USE_X11}
+  XRRSetScreenConfig(scrDisplay, scrSettings, wndRoot, scrDesktop, scrRotation, CurrentTime);
+{$ENDIF}
+{$IFDEF WINDOWS}
+  ChangeDisplaySettingsExW(scrMonInfo.szDevice, DEVMODEW(nil^), 0, CDS_FULLSCREEN, nil);
+{$ENDIF}
+{$IFDEF MACOSX}
+  CGDisplaySwitchToMode(scrDisplay, scrDesktop);
+  //CGDisplayRelease(scrDisplay);
+{$ENDIF}
+end;
+
+procedure scr_SetWindowedMode;
+  {$IFDEF WINDOWS}
+  var
+    settings: DEVMODEW;
+  {$ENDIF}
+begin
+  {$IFDEF USE_X11}
+  scr_Reset();
+  XMapWindow(scrDisplay, wndHandle);
+  {$ENDIF}
+  {$IFDEF WINDOWS}
+  if scrDesktop.dmBitsPerPel <> 32 Then
+  begin
+    settings              := scrDesktop;
+    settings.dmBitsPerPel := 32;
+
+    if ChangeDisplaySettingsExW(scrMonInfo.szDevice, settings, 0, CDS_TEST, nil) <> DISP_CHANGE_SUCCESSFUL Then
+    begin
+      u_Error('Desktop doesn''t support 32-bit color mode.');
+      winOn := FALSE;
+    end else
+      ChangeDisplaySettingsExW(scrMonInfo.szDevice, settings, 0, CDS_FULLSCREEN, nil);
+
+    scrRefresh := scrDesktop.dmDisplayFrequency;
+  end else
+    scr_Reset();
+  {$ENDIF}
+  {$IFDEF MACOSX}
+  scr_Reset();
+  ShowMenuBar();
+  {$ENDIF}
+end;
+{$EndIf}
+
+function scr_Create: Boolean;
+{$IfDef MAC_COCOA}
+var
+  pool: NSAutoreleasePool;
+  mainMenu: NSMenu;
+{$EndIf}
+begin
+  {$IfNDef ANDROID}
+  scr_Init();
+  {$EndIf}
+  {$IFDEF USE_X11}
+  if DefaultDepth(scrDisplay, scrDefault) < 24 Then
+    begin
+      u_Error('DefaultDepth not set to 24-bit.');
+      winOn := false;
+      Result := FALSE;
+      exit;
+    end;
+
+  {$IfDef OLD_METHODS}
+  appXIM := XOpenIM(scrDisplay, nil, nil, nil);
+  if not Assigned(appXIM) Then
+    log_Add('XOpenIM - Fail')
+  else
+    log_Add('XOpenIM - ok'); }
+
+  appXIC := XCreateIC(appXIM, [XNInputStyle, XIMPreeditNothing or XIMStatusNothing, 0]);
+  if not Assigned(appXIC) Then
+    log_Add('XCreateIC - Fail')
+  else
+    log_Add('XCreateIC - ok');
+  {$EndIf}
+  {$ENDIF}
+  {$IFDEF WINDOWS}
+  if (not wndFullScreen) and (scrDesktop.dmBitsPerPel <> 32) Then
+    scr_SetWindowedMode();
+  {$ENDIF}
+  {$IFDEF MACOSX}{$IfDef MAC_COCOA}
+  pool := NSAutoreleasePool.new;
+  NSApp := NSApplication.sharedApplication;
+  NSApp.setActivationPolicy(0);
+  NSApp.activateIgnoringOtherApps(true);
+
+  mainMenu := NSMenu.alloc.init.autorelease;
+  NSApp.setMainMenu(mainMenu);
+  mainMenu.setMenuBarVisible(false);        // menu not visible
+
+  pool.dealloc;
+
+  {$Else}
+  if CGDisplayBitsPerPixel(scrDisplay) <> 32 Then
+    begin
+      u_Error('Desktop not set to 32-bit mode.');
+      winOn := False;
+      Result := FALSE;
+      exit;
+    end;
+  {$ENDIF}{$EndIf}
+  log_Add('Current mode: ' + u_IntToStr(zgl_Get(DESKTOP_WIDTH)) + ' x ' + u_IntToStr(zgl_Get(DESKTOP_HEIGHT)));
+  Result := TRUE;
+end;
+
+procedure scr_Destroy;
+begin
+  {$IfNDef MAC_COCOA}
+  if wndFullScreen Then
+    scr_Reset();
+  {$EndIf}
+  {$IFDEF USE_X11}
+  XRRFreeScreenConfigInfo(scrSettings);
+  {$IfDef OLD_METHODS}
+  XDestroyIC(appXIC);
+  XCloseIM(appXIM);
+  {$EndIf}
+  {$ENDIF}
+
+  scrResList.Count := 0;
+  SetLength(scrResList.Width, 0);
+  SetLength(scrResList.Height, 0);
+  {$ifdef windows}
+  SetLength(scrResList.frequency, 0);
+  {$endif}
+
+  scrInitialized := FALSE;
+end;
+{$EndIf}
+
+procedure scr_Clear;
+begin
+  batch2d_Flush();
+  if scrClearColor then
+    glClearColor(scr_UseClearColor.R, scr_UseClearColor.G, scr_UseClearColor.b, scr_UseClearColor.A);
+  glClear(GL_COLOR_BUFFER_BIT * Byte(appFlags and COLOR_BUFFER_CLEAR > 0) or GL_DEPTH_BUFFER_BIT * Byte(appFlags and DEPTH_BUFFER_CLEAR > 0) or
+           GL_STENCIL_BUFFER_BIT * Byte(appFlags and STENCIL_BUFFER_CLEAR > 0));
+end;
+
+procedure scr_Flush;
+begin
+  batch2d_Flush();
+{$IFNDEF USE_GLES}
+  {$IFDEF LINUX}
+  glXSwapBuffers(scrDisplay, wndHandle);
+  {$ENDIF}
+  {$IFDEF WINDOWS}
+  SwapBuffers(wndDC);
+  {$ENDIF}
+  {$IFDEF MACOSX}{$IfDef MAC_COCOA}
+  oglContext.flushBuffer;
+  {$Else}
+  aglSwapBuffers(oglContext);
+  {$ENDIF}{$EndIf}
+{$ELSE}
+  {$IFNDEF NO_EGL}
+  eglSwapBuffers(oglDisplay, oglSurface);
+  {$ENDIF}
+  {$IFDEF iOS}
+  eglContext.presentRenderbuffer(GL_RENDERBUFFER);
+  {$ENDIF}
+  {$IFDEF ANDROID}
+  appEnv^.CallVoidMethod(appEnv, appObject, appSwapBuffers);
+  {$ENDIF}
+{$ENDIF}
+end;
+
+{$IfNDef USE_INIT_HANDLE}
+function scr_SetOptions(): Boolean;
+  {$IFDEF USE_X11}
+  var
+    modeToSet: Integer;
+    mode     : PXRRScreenSize;
+  {$ENDIF}
+  {$IFDEF WINDOWS}
+  var
+    i: Integer;
+    r: Integer;
+  {$ENDIF}
+  {$IFDEF MACOSX}
+  var
+    b: Integer;
+  {$ENDIF}
+begin
+{$IF DEFINED(iOS) or DEFINED(ANDROID)}
+  wndWidth      := scrDesktopW;
+  wndHeight     := scrDesktopH;
+  scrRefresh    := REFRESH_DEFAULT;
+  wndFullScreen := TRUE;
+  scrVsync      := TRUE;
+{$IFEND}
+
+  Result        := TRUE;
+  if not appInitialized Then
+  begin
+    oglWidth   := wndWidth;
+    oglHeight  := wndHeight;
+    oglTargetW := wndWidth;
+    oglTargetH := wndHeight;
+    exit;
+  end;
+  scr_VSync;
+
+{$IFDEF USE_X11}
+  if wndFullScreen Then
+  begin
+    scrCurrent := -1;
+    mode       := scrModeList;
+
+    for modeToSet := 0 to scrModeCount - 1 do
+      if (mode.Width = wndWidth) and (mode.Height = wndHeight) Then
+      begin
+        scrCurrent := modeToSet;
+        break;
+      end else
+        INC(mode);
+
+    if (scrCurrent = -1) or (XRRSetScreenConfig(scrDisplay, scrSettings, wndRoot, scrCurrent, scrRotation, CurrentTime) <> 0) Then
+    begin
+      u_Warning('Cannot set fullscreen mode: ' + u_IntToStr(wndWidth) + 'x' + u_IntToStr(wndHeight));
+      scrCurrent    := scrDesktop;
+      wndFullScreen := FALSE;
+      Result        := FALSE;
+      exit;
+    end;
+  end else
+    scr_SetWindowedMode();
+{$ENDIF}
+{$IFDEF WINDOWS}
+  if wndFullScreen Then
+  begin
+    i := 0;
+    r := 0;
+    FillChar(scrSettings, SizeOf(DEVMODEW), 0);
+    scrSettings.dmSize := SizeOf(DEVMODEW);
+    while EnumDisplaySettingsW(scrMonInfo.szDevice, i, scrSettings) <> FALSE do
+      with scrSettings do
+      begin
+        dmFields := DM_PELSWIDTH or DM_PELSHEIGHT or DM_BITSPERPEL or DM_DISPLAYFREQUENCY;
+        if (dmPelsWidth = wndWidth) and (dmPelsHeight = wndHeight) and (dmBitsPerPel = 32) and (dmDisplayFrequency > r) and
+               (dmDisplayFrequency <= scrDesktop.dmDisplayFrequency) Then
+        begin
+          if ChangeDisplaySettingsExW(scrMonInfo.szDevice, scrSettings, 0, CDS_TEST, nil) = DISP_CHANGE_SUCCESSFUL Then
+            r := dmDisplayFrequency
+          else
+            break;
+        end;
+        INC(i);
+      end;
+
+    with scrSettings do
+    begin
+      if scrRefresh = REFRESH_MAXIMUM Then scrRefresh := r;
+      if scrRefresh = REFRESH_DEFAULT Then scrRefresh := 0;
+
+      dmPelsWidth        := wndWidth;
+      dmPelsHeight       := wndHeight;
+      dmBitsPerPel       := 32;
+      dmDisplayFrequency := scrRefresh;
+      dmFields           := DM_PELSWIDTH or DM_PELSHEIGHT or DM_BITSPERPEL or DM_DISPLAYFREQUENCY;
+    end;
+
+    if ChangeDisplaySettingsExW(scrMonInfo.szDevice, scrSettings, 0, CDS_TEST, nil) <> DISP_CHANGE_SUCCESSFUL Then
+    begin
+      u_Warning('Cannot set fullscreen mode: ' + u_IntToStr(wndWidth) + 'x' + u_IntToStr(wndHeight));
+      wndFullScreen := FALSE;
+      Result        := FALSE;
+      exit;
+    end else
+      ChangeDisplaySettingsExW(scrMonInfo.szDevice, scrSettings, 0, CDS_FULLSCREEN, nil);
+
+    scrRefresh := scrDesktop.dmDisplayFrequency;
+  end else
+    scr_SetWindowedMode();
+{$ENDIF}
+{$IFDEF MACOSX}{$IfDef MAC_COCOA}
+  if winOn then
+  begin
+    if wndFullScreen then
+    begin
+      viewNSRect.origin.x := 0;
+      viewNSRect.origin.y := 0;
+      viewNSRect.size.width := scrDesktopW;
+      viewNSRect.size.height := scrDesktopH;
+      wndHandle.setStyleMask(NSBorderlessWindowMask);
+      wndHandle.setFrame_display(viewNSRect, True);
+    end
+    else begin
+      viewNSRect.origin.x := wndX;
+      viewNSRect.origin.y := wndY;
+      viewNSRect.size.width := wndWidth;
+      viewNSRect.size.height := wndHeight + 0;
+      wndHandle.setStyleMask(NSTitledWindowMask or NSClosableWindowMask);
+      wndHandle.setFrame_display(viewNSRect, True);
+    end;
+  end;
+{$Else}
+  if wndFullScreen Then
+  begin
+    if (scrRefresh <> 0) and (scrRefresh <> 1) Then
+    begin
+      scrSettings := CGDisplayBestModeForParametersAndRefreshRate(scrDisplay, 32, wndWidth, wndHeight, scrRefresh, b);
+      scrRefresh  := b;
+    end;
+    if (scrRefresh = 0) or (scrRefresh = 1) Then
+      scrSettings := CGDisplayBestModeForParameters(scrDisplay, 32, wndWidth, wndHeight, b);
+
+    if (b <> 1) or (CGDisplaySwitchToMode(scrDisplay, scrSettings) <> kCGErrorSuccess) Then
+    begin
+      u_Warning('Cannot set fullscreen mode: ' + u_IntToStr(wndWidth) + 'x' + u_IntToStr(wndHeight));
+      wndFullScreen := FALSE;
+      Result        := FALSE;
+      exit;
+    end;
+
+    HideMenuBar();
+  end else
+    scr_SetWindowedMode();
+{$ENDIF}{$EndIf}
+  if wndFullScreen Then
+    log_Add('Screen options changed to: ' + u_IntToStr(wndWidth) + ' x ' + u_IntToStr(wndHeight) + ' fullscreen')
+  else
+    log_Add('Screen options changed to: ' + u_IntToStr(wndWidth) + ' x ' + u_IntToStr(wndHeight) + ' windowed');
+  {$IfNDef ANDROID}
+
+  if winOn Then
+    wnd_Update();
+  {$Else}
+  wnd_SetSize(wndWidth, wndHeight);
+  {$EndIf}
+end;
+{$EndIf}
+
+procedure scr_CorrectResolution(Width, Height: Word);
+begin
+  {$IfDef MAC_COCOA}
+  zgl_Disable(CORRECT_RESOLUTION);
+  {$Else}
+  scrResW        := Width;
+  scrResH        := Height;
+  scrResCX       := wndWidth  / Width;
+  scrResCY       := wndHeight / Height;
+  render2dClipW  := Width;
+  render2dClipH  := Height;
+  render2dClipXW := render2dClipX + render2dClipW;
+  render2dClipYH := render2dClipY + render2dClipH;
+
+  if scrResCX < scrResCY Then
+  begin
+    scrAddCX := 0;
+    scrAddCY := Round((wndHeight - Height * scrResCX) / 2);
+    scrResCY := scrResCX;
+  end else
+  begin
+    scrAddCX := Round((wndWidth - Width * scrResCY) / 2);
+    scrAddCY := 0;
+    scrResCX := scrResCY;
+  end;
+
+  if appFlags and CORRECT_HEIGHT = 0 Then
+  begin
+    scrResCY := wndHeight / Height;
+    scrAddCY := 0;
+  end;
+  if appFlags and CORRECT_WIDTH = 0 Then
+  begin
+    scrResCX := wndWidth / Width;
+    scrAddCX := 0;
+  end;
+
+  oglWidth  := Round(wndWidth / scrResCX);
+  oglHeight := Round(wndHeight / scrResCY);
+  scrSubCX  := oglWidth - Width;
+  scrSubCY  := oglHeight - Height;
+  SetCurrentMode();
+  {$EndIf}
+end;
+
+procedure scr_SetViewPort;
+begin
+  if oglTarget = TARGET_SCREEN Then
+  begin
+    if (appFlags and CORRECT_RESOLUTION > 0) and (oglMode = 2) Then
+    begin
+      scrViewportX := scrAddCX;
+      scrViewportY := scrAddCY;
+      scrViewportW := wndWidth - scrAddCX * 2;
+      scrViewportH := wndHeight - scrAddCY * 2;
+    end else
+    begin
+      scrViewportX := 0;
+      scrViewportY := 0;
+      scrViewportW := wndWidth;
+      scrViewportH := wndHeight;
+    end;
+  end else
+  begin
+    scrViewportX := 0;
+    scrViewportY := 0;
+    scrViewportW := oglTargetW;
+    scrViewportH := oglTargetH;
+  end;
+
+  if appFlags and CORRECT_RESOLUTION > 0 Then
+  begin
+    render2dClipW  := scrResW;
+    render2dClipH  := scrResH;
+    render2dClipXW := render2dClipX + render2dClipW;
+    render2dClipYH := render2dClipY + render2dClipH;
+  end else
+  begin
+    render2dClipW  := scrViewportW;
+    render2dClipH  := scrViewportH;
+    render2dClipXW := render2dClipX + render2dClipW;
+    render2dClipYH := render2dClipY + render2dClipH;
+  end;
+
+  glViewPort(scrViewportX, scrViewportY, scrViewportW, scrViewportH);
+end;
+
+procedure scr_SetVSync(WSync: Boolean);
+begin
+  {$IfNDef USE_INIT_HANDLE}
+  if (useFPS > 60) and WSync then
+    scr_SetFPS(60);
+  {$EndIf}
+  scrVSync := WSync;
+end;
+
+procedure scr_SetClearColor(flag: Boolean = true; Color: Cardinal = 0);
+begin
+  scrClearColor := flag;
+  scr_UseClearColor.R := (Color shr 16) / 255;
+  scr_UseClearColor.G := ((Color and $FF00) shr 8) / 255;
+  scr_UseClearColor.B := (Color and $FF) / 255;
+  scr_UseClearColor.A := 1;
+end;
+
+procedure scr_VSync;                  
+begin
+{$IFNDEF USE_GLES}
+  {$IFDEF USE_X11}
+  if oglCanVSync Then
+    glXSwapIntervalSGI(Integer(scrVSync));
+  {$ENDIF}
+  {$IFDEF WINDOWS}
+  if oglCanVSync Then
+    wglSwapIntervalEXT(Integer(scrVSync));
+  {$ENDIF}
+  {$IFDEF MACOSX}{$IfDef MAC_COCOA}
+//  oglContext.setValues_forParameter(30, NSOpenGLCPSwapInterval);
+  {$Else}
+  if Assigned(oglContext) Then
+    aglSetInt(oglContext, AGL_SWAP_INTERVAL, Byte(scrVSync));
+  {$ENDIF}{$EndIf}
+{$ELSE}
+  {$IFNDEF NO_EGL}
+  if oglCanVSync Then
+    eglSwapInterval(oglDisplay, Integer(scrVSync));
+  {$ENDIF}
+{$ENDIF}
+end;
+
+{$IfNDef USE_INIT_HANDLE}
+procedure scr_SetFPS(FPS: LongWord);
+begin
+  if FPS < 30 then
+    FPS := 30;
+  if (FPS <> 60) and (FPS <> 75) and (FPS <> 85) and (FPS <> 90) and (FPS <> 100) and (FPS <> 120) and (FPS <> 144) then
+    FPS := 60;
+  useFPS := FPS;
+  if useFPS > 60 then
+  begin
+    scrVSync := True;
+    scr_VSync;
+  end;
+  maxFPS := 1000 / FPS;
+end;
+{$EndIf}
+
+{procedure scr_SetFSAA(FSAA: Byte);
+begin
+  if oglFSAA = FSAA Then exit;
+  oglFSAA := FSAA;
+
+  gl_Destroy();
+  log_Add('Start reinitialization of OpenGL');
+
+  gl_Create();
+  wnd_Destroy();
+  wnd_Create();
+//  wnd_SetCaption();
+  gl_Initialize();
+  if oglFSAA <> 0 Then
+    log_Add('FSAA changed to: ' + u_IntToStr(oglFSAA) + 'x')
+  else
+    log_Add('FSAA changed to: off');
+end;}
+
+procedure scr_ReadPixels(var pData: Pointer; X, Y, Width, Height: Word);
+begin
+  batch2d_Flush();
+  GetMem(pData, Width * Height * 4);
+  glReadPixels(X, oglHeight - Height - Y, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, pData);
+end;
+
+procedure Set2DNearFar(newNear, newFar: {$IfNDef USE_GLES}Double{$Else}{$IF DEFINED(USE_GLES_ON_DESKTOP) and DEFINED(USE_AMD_DRIVERS)}Double{$Else}Single{$IfEnd}{$EndIf});
+begin
+  scrFar := newFar;
+  scrNear := newNear;
+end;
+
+procedure SetGLVersionAndFlags({$IfNDef MAC_COCOA}major, minor: Integer; flag: LongWord = COMPATIBILITY_VERSION{$Else}mode: LongWord{$EndIf});
+  {$IfNDef MAC_COCOA}
+  procedure MajorMinor;
+  begin
+    if major > 4 then
+      major := 4;
+    maxGLVerMajor := major;
+    if major = 4 then
+    begin
+      if minor > 6 then
+        minor := 6;
+      maxGLVerMinor := minor;
+      exit;
+    end;
+    if major = 3 then
+    begin
+      if minor > 3 then
+        minor := 3;
+      maxGLVerMinor := minor;
+      exit;
+    end;
+    if major = 2 then
+    begin
+      if minor > 1 then
+        minor := 1;
+      maxGLVerMinor := minor;
+      exit;
+    end;
+    if major = 1 then
+    begin
+      if minor > 5 then
+        minor := 5;
+      maxGLVerMinor := minor;
+    end;
+  end;
+  {$EndIf}
+
+begin
+  {$IfDef MACOSX}
+  if (mode > CORE_4_1) or (mode = 0) then
+    mode := CORE_2_1;
+  if mode = CORE_3_2 then
+  begin
+    oglAttr[8] := $3200;
+    exit;
+  end;
+  if mode = CORE_4_1 then
+  begin
+    oglAttr[8] := $4100;
+    exit;
+  end;
+  oglAttr[8] := $1000;
+  {$Else}
+
+  if (flag and 3) = 3 then
+    flag := flag and 13;
+  contextMask := flag and 3;
+  contextFlags := (flag and 12) shr 2;
+
+  MajorMinor;
+  {$IfDef LINUX}
+  if (major > 3) or ((major = 3) and (minor >= 2)) then
+  begin
+    if contextMask = 2 then
+      contextMask := 1;
+  end;
+  {$EndIf}
+  {$EndIf}
+end;
+
+end.