lazarus/components/opengl/glcarbonaglcontext.pas
2006-06-30 18:52:40 +00:00

220 lines
6.1 KiB
ObjectPascal

{
*****************************************************************************
* *
* See the file COPYING.modifiedLGPL, 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,
FPCMacOSAll, CarbonInt, AGL, CarbonProc, CarbonDef, CarbonPrivate,
WSLCLClasses, CarbonWSControls, CarbonUtils,
Controls;
procedure LOpenGLViewport(Left, Top, Width, Height: integer);
procedure LOpenGLSwapBuffers(Handle: HWND);
function LOpenGLMakeCurrent(Handle: HWND): boolean;
function LOpenGLCreateContext(AWinControl: TWinControl;
WSPrivate: TWSPrivateClass; SharedControl: TWinControl;
DoubleBuffered, RGBA: boolean): HWND;
procedure LOpenGLDestroyContextInfo(AWinControl: TWinControl);
function CreateOpenGLContextAttrList(DoubleBuffered: boolean;
RGBA: boolean): PInteger;
type
TWidgetSetWSWinControl = TCarbonWSWinControl;
TAGLControlInfo = record
Control: ControlRef;
AGLContext: TAGLContext;
end;
PAGLControlInfo = ^TAGLControlInfo;
var
AGLControlInfo_FOURCC: FourCharCode;
function CreateAGLControlInfo(Control: ControlRef; AGLContext: TAGLContext
): 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;
begin
AGLContext:=GetAGLContext(ControlRef(Handle));
Result:=aglSetCurrentContext(aglContext)<>0;
end;
function LOpenGLCreateContext(AWinControl: TWinControl;
WSPrivate: TWSPrivateClass; SharedControl: TWinControl;
DoubleBuffered, RGBA: boolean): HWND;
var
disp: GDHandle;
aglPixFmt: TAGLPixelFormat;
aglContext: TAGLContext;
ACarbonWindow: WindowRef;
CFString: CFStringRef;
Control: ControlRef;
R: FPCMacOSAll.Rect;
Info: PWidgetInfo;
ParentWindow: WindowPtr;
AttrList: PInteger;
begin
if AWinControl.Parent=nil then
RaiseGDBException('GLCarbonAGLContext.LOpenGLCreateContext no parent');
ParentWindow:=WindowRef(AWinControl.Parent.Handle);
// create a dummy control
R:=GetCarbonRect(AWinControl.BoundsRect);
Control:=nil;
CFString := CFStringCreateWithCString(nil, Pointer(PChar('SubControl')),
kCFStringEncodingUTF8);
if CreatePushButtonControl(ParentWindow, R, CFString, Control) <> noErr
then
debugln('CreatePushButtonControl failed');
CFRelease(Pointer(CFString));
// create LCL WidgetInfo
Result:=HWnd(Control);
Info := CreateWidgetInfo(Control, AWinControl, cwtControlRef);
TCarbonPrivateHandleClass(WSPrivate).RegisterEvents(Info);
// 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
ACarbonWindow:=WindowRef(GetParentForm(AWinControl).Handle);
aglSetDrawable(aglContext,GetWindowPort(ACarbonWindow));
AGLControlInfo_FOURCC := MakeFourCC('ACI ');
CreateAGLControlInfo(Control,AGLContext);
end;
procedure LOpenGLDestroyContextInfo(AWinControl: TWinControl);
var
Ref: ControlRef;
Info: PAGLControlInfo;
begin
if not AWinControl.HandleAllocated then exit;
Ref:=ControlRef(AWinControl.Handle);
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
): PAGLControlInfo;
begin
New(Result);
FillChar(Result^, SizeOf(Result^), 0);
Result^.Control:=Control;
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(Control)^.AGLContext;
end;
end.