mirror of
				https://gitlab.com/freepascal.org/lazarus/lazarus.git
				synced 2025-11-04 05:39:34 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			255 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			255 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
{
 | 
						|
 *****************************************************************************
 | 
						|
 *                                                                           *
 | 
						|
 *  See the file COPYING.modifiedLGPL.txt, included in this distribution,    *
 | 
						|
 *  for details about the copyright.                                         *
 | 
						|
 *                                                                           *
 | 
						|
 *  This program is distributed in the hope that it will be useful,          *
 | 
						|
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
 | 
						|
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                     *
 | 
						|
 *                                                                           *
 | 
						|
 *****************************************************************************
 | 
						|
 | 
						|
  Author: Mattias Gaertner
 | 
						|
 | 
						|
}
 | 
						|
unit GLCarbonAGLContext;
 | 
						|
 | 
						|
{$mode objfpc}{$H+}
 | 
						|
 | 
						|
interface
 | 
						|
 | 
						|
uses
 | 
						|
  Classes, SysUtils, LCLProc, LCLType, gl, Forms,
 | 
						|
  MacOSAll,
 | 
						|
  AGL, CarbonProc, CarbonDef, CarbonPrivate,
 | 
						|
  WSLCLClasses, CarbonWSControls, CarbonUtils,
 | 
						|
  Controls;
 | 
						|
 | 
						|
procedure LOpenGLViewport(Left, Top, Width, Height: integer);
 | 
						|
procedure LOpenGLSwapBuffers(Handle: HWND);
 | 
						|
function LOpenGLMakeCurrent(Handle: HWND): boolean;
 | 
						|
procedure LOpenGLClip(Handle: HWND);
 | 
						|
function LOpenGLCreateContext(AWinControl: TWinControl;
 | 
						|
              {%H-}WSPrivate: TWSPrivateClass; SharedControl: TWinControl;
 | 
						|
              DoubleBuffered, RGBA: boolean;
 | 
						|
              const {%H-}AParams: TCreateParams): HWND;
 | 
						|
procedure LOpenGLDestroyContextInfo(AWinControl: TWinControl);
 | 
						|
function CreateOpenGLContextAttrList(DoubleBuffered: boolean;
 | 
						|
  RGBA: boolean): PInteger;
 | 
						|
 | 
						|
 | 
						|
type
 | 
						|
  TAGLControlInfo = record
 | 
						|
    Control: ControlRef;
 | 
						|
    WinControl: TWinControl;
 | 
						|
    AGLContext: TAGLContext;
 | 
						|
  end;
 | 
						|
  PAGLControlInfo = ^TAGLControlInfo;
 | 
						|
 | 
						|
var
 | 
						|
  AGLControlInfo_FOURCC: FourCharCode;
 | 
						|
 | 
						|
function CreateAGLControlInfo(Control: ControlRef; AGLContext: TAGLContext;
 | 
						|
  WinControl: TWinControl): PAGLControlInfo;
 | 
						|
function GetAGLControlInfo(Control: ControlRef): PAGLControlInfo;
 | 
						|
procedure FreeAGLControlInfo(Control: ControlRef);
 | 
						|
function GetAGLContext(Control: ControlRef): TAGLContext;
 | 
						|
 | 
						|
implementation
 | 
						|
 | 
						|
procedure LOpenGLViewport(Left, Top, Width, Height: integer);
 | 
						|
begin
 | 
						|
  glViewport(Left,Top,Width,Height);
 | 
						|
end;
 | 
						|
 | 
						|
procedure LOpenGLSwapBuffers(Handle: HWND);
 | 
						|
var
 | 
						|
  AGLContext: TAGLContext;
 | 
						|
begin
 | 
						|
  AGLContext:=GetAGLContext(ControlRef(Handle));
 | 
						|
  aglSwapBuffers(AGLContext);
 | 
						|
end;
 | 
						|
 | 
						|
function LOpenGLMakeCurrent(Handle: HWND): boolean;
 | 
						|
var
 | 
						|
  AGLContext: TAGLContext;
 | 
						|
  Info: PAGLControlInfo;
 | 
						|
  Control: TCarbonCustomControl;
 | 
						|
begin
 | 
						|
  Control:=TCarbonCustomControl(Handle);
 | 
						|
  Info:=GetAGLControlInfo(Control.Widget);
 | 
						|
  if Info=nil then exit;
 | 
						|
  AGLContext:=Info^.AGLContext;
 | 
						|
  Result:=aglSetCurrentContext(AGLContext)<>0;
 | 
						|
end;
 | 
						|
 | 
						|
procedure LOpenGLClip(Handle: HWND);
 | 
						|
var
 | 
						|
  AGLContext: TAGLContext;
 | 
						|
  Info: PAGLControlInfo;
 | 
						|
  Form: TCustomForm;
 | 
						|
  Win: WindowRef;
 | 
						|
  //b: Rect;
 | 
						|
  clipRgn: RgnHandle;
 | 
						|
  Control: TCarbonCustomControl;
 | 
						|
begin
 | 
						|
  Control:=TCarbonCustomControl(Handle);
 | 
						|
  Info:=GetAGLControlInfo(Control.Widget);
 | 
						|
  debugln(['LOpenGLMakeCurrent AAA0']);
 | 
						|
  if Info=nil then exit;
 | 
						|
  AGLContext:=Info^.AGLContext;
 | 
						|
  aglSetCurrentContext(AGLContext);
 | 
						|
  debugln(['LOpenGLMakeCurrent AAA1 ',dbgs(Handle)]);
 | 
						|
  debugln(['LOpenGLMakeCurrent AAA2']);
 | 
						|
  Form:=GetParentForm(Info^.WinControl);
 | 
						|
  debugln(['LOpenGLMakeCurrent AAA3']);
 | 
						|
  Win:=TCarbonWindow(Form.Handle).Window;
 | 
						|
 | 
						|
  debugln(['LOpenGLMakeCurrent ']);
 | 
						|
  //GetWindowPortBounds(Win,b);
 | 
						|
  clipRgn:=NewRgn;
 | 
						|
  SetRectRgn(clipRgn,10,10,100,100);
 | 
						|
  aglSetInteger(TAGLContext(GetWRefCon(Win)),AGL_CLIP_REGION,clipRgn);
 | 
						|
  aglEnable(TAGLContext(GetWRefCon(Win)),AGL_CLIP_REGION);
 | 
						|
  DisposeRgn(clipRgn);
 | 
						|
end;
 | 
						|
 | 
						|
function LOpenGLCreateContext(AWinControl: TWinControl;
 | 
						|
  WSPrivate: TWSPrivateClass; SharedControl: TWinControl;
 | 
						|
  DoubleBuffered, RGBA: boolean;
 | 
						|
  const AParams: TCreateParams): HWND;
 | 
						|
var
 | 
						|
  disp: GDHandle;
 | 
						|
  aglPixFmt: TAGLPixelFormat;
 | 
						|
  aglContext: TAGLContext;
 | 
						|
  Control: TCarbonCustomControl;
 | 
						|
  AttrList: PInteger;
 | 
						|
  C: TCreateParams;
 | 
						|
  AGLInfo: PAGLControlInfo;
 | 
						|
begin
 | 
						|
  Result:=0;
 | 
						|
  if AWinControl.Parent=nil then
 | 
						|
    RaiseGDBException('GLCarbonAGLContext.LOpenGLCreateContext no parent');
 | 
						|
 | 
						|
  C.X := AWinControl.Left;
 | 
						|
  C.Y := AWinControl.Top;
 | 
						|
  C.Width := AWinControl.Width;
 | 
						|
  C.Height := AWinControl.Height;
 | 
						|
  // create a custom control
 | 
						|
  Control := TCarbonCustomControl.Create(AWinControl, C);
 | 
						|
  //debugln(['LOpenGLCreateContext ',dbgsName(Control)]);
 | 
						|
 | 
						|
  // create the AGL context
 | 
						|
  disp := GetMainDevice ();
 | 
						|
  AttrList:=CreateOpenGLContextAttrList(DoubleBuffered,RGBA);
 | 
						|
  aglPixFmt := aglChoosePixelFormat (@disp, 1, AttrList);
 | 
						|
  System.FreeMem(AttrList);
 | 
						|
  aglContext := aglCreateContext (aglPixFmt, NIL);
 | 
						|
  aglDestroyPixelFormat(aglPixFmt);
 | 
						|
 | 
						|
  // use the carbon window.
 | 
						|
  // TODO: find a way to use only the control for the context
 | 
						|
  aglSetDrawable(aglContext,
 | 
						|
    GetWindowPort(TCarbonWindow(GetParentForm(AWinControl).Handle).Window));
 | 
						|
 | 
						|
  AGLControlInfo_FOURCC := MakeFourCC('ACI ');
 | 
						|
 | 
						|
  AGLInfo:=CreateAGLControlInfo(Control.Widget, AGLContext, AWinControl);
 | 
						|
  if AGLInfo<>GetAGLControlInfo(Control.Widget) then
 | 
						|
    RaiseGDBException('GLCarbonAGLContext.LOpenGLCreateContext inconsistency');
 | 
						|
  Result:=HWnd(Control);
 | 
						|
  //debugln(['LOpenGLCreateContext ',dbgs(Result)]);
 | 
						|
end;
 | 
						|
 | 
						|
procedure LOpenGLDestroyContextInfo(AWinControl: TWinControl);
 | 
						|
var
 | 
						|
  Ref: ControlRef;
 | 
						|
  Info: PAGLControlInfo;
 | 
						|
begin
 | 
						|
  if not AWinControl.HandleAllocated then exit;
 | 
						|
  Ref := ControlRef(TCarbonControl(AWinControl.Handle).Widget);
 | 
						|
  Info := GetAGLControlInfo(Ref);
 | 
						|
  if Info=nil then exit;
 | 
						|
  aglDestroyContext(Info^.AGLContext);
 | 
						|
  Info^.AGLContext := nil;
 | 
						|
  FreeAGLControlInfo(Ref);
 | 
						|
end;
 | 
						|
 | 
						|
function CreateOpenGLContextAttrList(DoubleBuffered: boolean; RGBA: boolean
 | 
						|
  ): PInteger;
 | 
						|
var
 | 
						|
  p: integer;
 | 
						|
 | 
						|
  procedure Add(i: integer);
 | 
						|
  begin
 | 
						|
    if Result<>nil then
 | 
						|
      Result[p]:=i;
 | 
						|
    inc(p);
 | 
						|
  end;
 | 
						|
 | 
						|
  procedure CreateList;
 | 
						|
  begin
 | 
						|
    Add(AGL_WINDOW);
 | 
						|
    if DoubleBuffered then
 | 
						|
      Add(AGL_DOUBLEBUFFER);
 | 
						|
    if RGBA then
 | 
						|
      Add(AGL_RGBA);
 | 
						|
    Add(AGL_NO_RECOVERY);
 | 
						|
    Add(AGL_MAXIMUM_POLICY);
 | 
						|
    Add(AGL_SINGLE_RENDERER);
 | 
						|
    Add(AGL_RED_SIZE); Add(1);
 | 
						|
    Add(AGL_GREEN_SIZE); Add(1);
 | 
						|
    Add(AGL_BLUE_SIZE); Add(1);
 | 
						|
    Add(AGL_DEPTH_SIZE); Add(1);
 | 
						|
    Add(AGL_NONE);
 | 
						|
  end;
 | 
						|
 | 
						|
begin
 | 
						|
  Result:=nil;
 | 
						|
  p:=0;
 | 
						|
  CreateList;
 | 
						|
  GetMem(Result,SizeOf(integer)*p);
 | 
						|
  p:=0;
 | 
						|
  CreateList;
 | 
						|
end;
 | 
						|
 | 
						|
function CreateAGLControlInfo(Control: ControlRef; AGLContext: TAGLContext;
 | 
						|
  WinControl: TWinControl): PAGLControlInfo;
 | 
						|
begin
 | 
						|
  New(Result);
 | 
						|
  FillByte(Result^, SizeOf(Result^), 0);
 | 
						|
  Result^.Control:=Control;
 | 
						|
  Result^.WinControl:=WinControl;
 | 
						|
  Result^.AGLContext:=AGLContext;
 | 
						|
 | 
						|
  SetControlProperty(Control, LAZARUS_FOURCC, AGLControlInfo_FOURCC,
 | 
						|
                     SizeOf(Result), @Result);
 | 
						|
end;
 | 
						|
 | 
						|
function GetAGLControlInfo(Control: ControlRef): PAGLControlInfo;
 | 
						|
var
 | 
						|
  m: LongWord;
 | 
						|
begin
 | 
						|
  GetControlProperty(Control, LAZARUS_FOURCC, AGLControlInfo_FOURCC,
 | 
						|
                     SizeOf(Result), @m, @Result);
 | 
						|
end;
 | 
						|
 | 
						|
procedure FreeAGLControlInfo(Control: ControlRef);
 | 
						|
var
 | 
						|
  Info: PAGLControlInfo;
 | 
						|
begin
 | 
						|
  Info:=GetAGLControlInfo(Control);
 | 
						|
  if Info=nil then exit;
 | 
						|
  RemoveControlProperty(Control, LAZARUS_FOURCC, AGLControlInfo_FOURCC);
 | 
						|
  System.FreeMem(Info);
 | 
						|
end;
 | 
						|
 | 
						|
function GetAGLContext(Control: ControlRef): TAGLContext;
 | 
						|
begin
 | 
						|
  Result:=GetAGLControlInfo(TCarbonCustomControl(Control).Widget)^.AGLContext;
 | 
						|
end;
 | 
						|
 | 
						|
end.
 | 
						|
 |