* added glcContext
[LazOpenGLCore.git] / uglcContext.pas
diff --git a/uglcContext.pas b/uglcContext.pas
new file mode 100644 (file)
index 0000000..ad00b99
--- /dev/null
@@ -0,0 +1,244 @@
+unit uglcContext;
+
+{ Package:      OpenGLCore
+  Prefix:       glc - OpenGL Core
+  Beschreibung: diese Unit enthält eine abstrakte Klassen-Kapselung für OpenGL Kontexte
+
+
+Abstrakte Contextklasse zum Erstellen von Renderkontexten auf Windows & Linux(bzw X11/Gtk2)
+Für aktuelle Plattform passende Klasse kann per GetPlatformClass gefunden werden.
+
+Bsp.:
+  //muss im GUI/Main-Thread aufgerufen werden:
+  pf := TglcContext.GetPlatformClass().MakePF();
+  fContext := TglcContext.GetPlatformClass().Create(MyTWinControl, PF);
+
+  //_kann_ in Background Thread abgerufen werden:
+  fContext.BuildContext();
+  [Arbeit mit dem Context]
+  fContext.CloseContext();
+
+  //im MainThread
+  FreeAndNil(fContext)
+
+
+weitere Funktionen:
+  MakePF()             erzeugt PixelFormatDescriptor mit Defaults
+  BuildContext()       baut Kontext (kann in BackgrounThread aufgerufen werden)
+  CloseContext()       gibt den Kontext frei (muss im selben Thread aufgerufen werden wie BuildContext;
+                       wird der Kontext nur im MainThread genutzt, muss CloseContext nicht explizit aufgerufen
+                       werden und wird beim zerstören des Kontext-Objekts ausgeführt)
+  Activate/Deactiveate Kontext aktiv schalten oder nicht
+  SwapBuffers          DoubleBuffering
+  SetSwapInterval      VSync
+  Share                ShareLists
+  EnableDebugOutput    GL-Debug via ARB_debug_output oder AMD_debug_output de/aktivieren
+}
+
+interface
+
+uses
+  SysUtils, Controls, dglOpenGL;
+
+const
+  GLC_CONTEXT_VERSION_UNKNOWN = -1;
+
+type
+  TMultiSample = 1..high(byte);
+  TglcContextPixelFormatSettings = packed record
+    DoubleBuffered: boolean;
+    Stereo: boolean;
+    MultiSampling: TMultiSample;
+    ColorBits: Integer;
+    DepthBits: Integer;
+    StencilBits: Integer;
+    AccumBits: Integer;
+    AuxBuffers: Integer;
+    Layer: Integer;
+  end;
+  TglcContextVersionSettings = packed record
+    Major: Integer;
+    Minor: Integer;
+    ForwardCompatible: Boolean;
+  end;
+
+  TglcDisplayFlag = (
+    dfFullscreen);
+  TglcDisplayFlags = set of TglcDisplayFlag;
+
+  EGLError = class(Exception);
+
+  { TglcContext }
+  TglcContextClass = class of TglcContext;
+  TglcContext = class
+  private
+    fControl: TWinControl;
+    fThreadID: TThreadID;
+    fEnableVsync: Boolean;
+
+    function GetEnableVSync: Boolean;
+    procedure SetEnableVSync(aValue: Boolean);
+
+  protected
+    fUseVersion: Boolean;
+    fPixelFormatSettings: TglcContextPixelFormatSettings;
+    fVersionSettings: TglcContextVersionSettings;
+    procedure OpenContext; virtual;
+
+  public
+    property PixelFormatSettings: TglcContextPixelFormatSettings read fPixelFormatSettings;
+    property VersionSettings:     TglcContextVersionSettings     read fVersionSettings;
+
+    constructor Create(const aControl: TWinControl; const aPixelFormatSettings: TglcContextPixelFormatSettings); virtual; overload;
+    constructor Create(const aControl: TWinControl; const aPixelFormatSettings: TglcContextPixelFormatSettings; const aVersionSettings: TglcContextVersionSettings); virtual; overload;
+    destructor Destroy; override;
+
+    property ThreadID:    TThreadID read fThreadID;
+    property EnableVSync: Boolean   read GetEnableVSync write SetEnableVSync;
+
+    procedure BuildContext;
+    procedure CloseContext; virtual;
+    procedure Activate; virtual; abstract;
+    procedure Deactivate; virtual; abstract;
+    function IsActive: boolean; virtual; abstract;
+    procedure SwapBuffers; virtual; abstract;
+    procedure SetSwapInterval(const aInterval: GLint); virtual; abstract;
+    function GetSwapInterval: GLint; virtual; abstract;
+    procedure Share(const aContext: TglcContext); virtual; abstract;
+
+  private class var
+    fMainContextThreadID: TThreadID;
+  public
+    class property MainContextThreadID: TThreadID read fMainContextThreadID;
+    class function MakePF(DoubleBuffered: boolean = true;
+                          Stereo: boolean=false;
+                          MultiSampling: TMultiSample=1;
+                          ColorBits: Integer=32;
+                          DepthBits: Integer=24;
+                          StencilBits: Integer=0;
+                          AccumBits: Integer=0;
+                          AuxBuffers: Integer=0;
+                          Layer: Integer=0): TglcContextPixelFormatSettings;
+    class function MakeVersion(const aMajor, aMinor: Integer; const aForwardCompatible: Boolean): TglcContextVersionSettings;
+    class function GetPlatformClass: TglcContextClass;
+    class function ChangeDisplaySettings(const aWidth, aHeight,
+      aBitPerPixel, aFreq: Integer; const aFlags: TglcDisplayFlags): Boolean; virtual; abstract;
+    class function IsAnyContextActive: boolean; virtual;
+  end;
+
+implementation
+
+uses
+  {$IFDEF WINDOWS}
+    uglcContextWGL
+  {$ENDIF}
+  {$IFDEF LINUX}
+    uglcContextGtk2GLX
+  {$ENDIF}
+  ;
+
+function TglcContext.GetEnableVSync: Boolean;
+begin
+  result := fEnableVsync;
+end;
+
+procedure TglcContext.SetEnableVSync(aValue: Boolean);
+begin
+  fEnableVsync := aValue;
+  if IsActive then begin
+    if fEnableVsync then
+      SetSwapInterval(1)
+    else
+      SetSwapInterval(0);
+  end;
+end;
+
+procedure TglcContext.OpenContext;
+begin
+  fThreadID := GetCurrentThreadId;
+  if fMainContextThreadID = 0 then
+    fMainContextThreadID := fThreadID;
+end;
+
+class function TglcContext.MakePF(DoubleBuffered: boolean; Stereo: boolean; MultiSampling: TMultiSample; ColorBits: Integer;
+  DepthBits: Integer; StencilBits: Integer; AccumBits: Integer; AuxBuffers: Integer; Layer: Integer): TglcContextPixelFormatSettings;
+begin
+  Result.DoubleBuffered:= DoubleBuffered;
+  Result.Stereo:= Stereo;
+  Result.MultiSampling:= MultiSampling;
+  Result.ColorBits:= ColorBits;
+  Result.DepthBits:= DepthBits;
+  Result.StencilBits:= StencilBits;
+  Result.AccumBits:= AccumBits;
+  Result.AuxBuffers:= AuxBuffers;
+  Result.Layer:= Layer;
+end;
+
+class function TglcContext.MakeVersion(const aMajor, aMinor: Integer; const aForwardCompatible: Boolean): TglcContextVersionSettings;
+begin
+  result.Major := aMajor;
+  result.Minor := aMinor;
+  result.ForwardCompatible := aForwardCompatible;
+end;
+
+class function TglcContext.GetPlatformClass: TglcContextClass;
+begin
+  {$IFDEF WINDOWS}
+  Result:= TglcContextWGL;
+  {$ENDIF}
+  {$IFDEF LINUX}
+  Result:= TglcContextGtk2GLX;
+  {$ENDIF}
+end;
+
+class function TglcContext.IsAnyContextActive: boolean;
+begin
+  Result:= GetPlatformClass.IsAnyContextActive;
+end;
+
+constructor TglcContext.Create(const aControl: TWinControl; const aPixelFormatSettings: TglcContextPixelFormatSettings);
+begin
+  inherited Create;
+  fPixelFormatSettings := aPixelFormatSettings;
+  FControl             := aControl;
+  fThreadID            := 0;
+  fEnableVsync         := false;
+  fUseVersion          := false;
+  InitOpenGL();
+end;
+
+constructor TglcContext.Create(const aControl: TWinControl; const aPixelFormatSettings: TglcContextPixelFormatSettings; const aVersionSettings: TglcContextVersionSettings);
+begin
+  Create(aControl, aPixelFormatSettings);
+  fVersionSettings := aVersionSettings;
+  fUseVersion      := true;
+end;
+
+destructor TglcContext.Destroy;
+begin
+  if (GetCurrentThreadId = fMainContextThreadID) then
+    fMainContextThreadID := 0;
+  CloseContext;
+  inherited Destroy;
+end;
+
+procedure TglcContext.BuildContext;
+begin
+  OpenContext;
+  Activate;
+  ReadImplementationProperties;
+  ReadExtensions;
+  SetEnableVSync(fEnableVsync);
+end;
+
+procedure TglcContext.CloseContext;
+begin
+  if fMainContextThreadID = fThreadID then
+    fMainContextThreadID := 0;
+end;
+
+initialization
+  TglcContext.fMainContextThreadID := 0;
+
+end.
+