|
- unit uglcContextWGL;
-
- { Package: OpenGLCore
- Prefix: glc - OpenGL Core
- Beschreibung: diese Unit enthält eine Klassen-Kapselung für OpenGL Kontexte für Windows
- Hint: diese Unit sollte niemals direkt genutzt werden (siehe uglcContext) }
-
- interface
-
- uses
- Classes, SysUtils, Forms, Windows, uglcContext, dglOpenGL, Controls;
-
- type
- EWGLError = class(EGLError);
-
- { TglcContextWGL }
-
- TglcContextWGL = class(TglcContext)
- private
- FDC: HDC;
- FRC: HGLRC;
- fHandle: THandle;
- fPixelFormat: Integer;
- {%H-}constructor Create(const aControl: TWinControl); overload;
- protected
- procedure UpdatePixelFormat;
- procedure OpenContext; override;
- function FindPixelFormat: Integer;
- function FindPixelFormatNoAA: Integer;
- procedure OpenFromPF(PixelFormat: Integer);
- public
- constructor Create(const aControl: TWinControl;
- const aPixelFormatSettings: TglcContextPixelFormatSettings;
- const aShareContext: TglcContext = nil); overload; override;
- constructor Create(const aControl: TWinControl;
- const aPixelFormatSettings: TglcContextPixelFormatSettings;
- const aVersionSettings: TglcContextVersionSettings;
- const aShareContext: TglcContext = nil); overload; override;
-
- procedure CloseContext; override;
- procedure Activate; override;
- procedure Deactivate; override;
- function IsActive: boolean; override;
- procedure SwapBuffers; override;
- procedure SetSwapInterval(const aInterval: GLint); override;
- function GetSwapInterval: GLint; override;
-
- class function ChangeDisplaySettings(const aWidth, aHeight, aBitPerPixel, aFreq: Integer;
- const aFlags: TglcDisplayFlags): Boolean; override;
- class function IsAnyContextActive: boolean; override;
- end;
-
- implementation
-
- { TglcContextWGL }
-
- constructor TglcContextWGL.Create(const aControl: TWinControl);
- begin
- inherited Create(aControl, MakePF());
- fHandle := aControl.Handle;
- end;
-
- procedure TglcContextWGL.UpdatePixelFormat;
- begin
- fPixelFormat := FindPixelFormat;
- if (fPixelFormat = 0) then begin
- // try without MS
- fPixelFormatSettings.MultiSampling := 1;
- fPixelFormat := FindPixelFormat;
- end;
- end;
-
- procedure TglcContextWGL.OpenContext;
- begin
- inherited OpenContext;
- OpenFromPF(fPixelFormat);
- end;
-
- function TglcContextWGL.FindPixelFormat: Integer;
- var
- OldRC: HGLRC; OldDC: HDC;
- tmpWnd: TForm;
- tmpContext: TglcContextWGL;
- pf, i, max: integer;
- Count: GLuint;
- PFList, SampleList: array[0..31] of GLint;
-
- procedure ChoosePF(pPFList, pSampleList: PGLint; MaxCount: integer);
- var
- //ARB_Erweiterung vorhanden
- //| EXT_Erweiterung vorhanden
- MultiARBSup, MultiEXTSup: Boolean;
- //Liste der Integer Attribute
- IAttrib: array[0..22] of GLint;
- //Liste der Float Attribute (nur 0, da kein Wert)
- FAttrib: GLFloat;
- QueryAtrib, i: Integer;
- PPosiblePF, PSample: PglInt;
- begin
- //Pixelformate mit AA auslesen
- MultiARBSup := false;
- MultiEXTSup := false;
- if WGL_ARB_extensions_string and
- WGL_ARB_pixel_format and
- (WGL_ARB_MULTISAMPLE or GL_ARB_MULTISAMPLE) then
- multiARBSup := true;
- if WGL_EXT_extensions_string and
- WGL_EXT_pixel_format and
- (WGL_EXT_MULTISAMPLE or GL_EXT_MULTISAMPLE) then
- multiEXTSup := true;
-
- if multiARBSup then
- Read_WGL_ARB_pixel_format
- else if multiEXTSup then
- Read_WGL_EXT_pixel_format;
-
- if not (MultiARBSup or MultiEXTSup) then
- exit;
-
- IAttrib[00] := WGL_DRAW_TO_WINDOW_ARB;
- IAttrib[01] := 1;
-
- IAttrib[02] := WGL_SUPPORT_OPENGL_ARB;
- IAttrib[03] := 1;
-
- IAttrib[04] := WGL_DOUBLE_BUFFER_ARB;
- if (fPixelFormatSettings.DoubleBuffered) then
- IAttrib[05] := 1
- else
- IAttrib[05] := 0;
-
- IAttrib[06] := WGL_PIXEL_TYPE_ARB;
- IAttrib[07] := WGL_TYPE_RGBA_ARB;
-
- IAttrib[08] := WGL_COLOR_BITS_ARB;
- IAttrib[09] := fPixelFormatSettings.ColorBits;
-
- IAttrib[10] := WGL_ALPHA_BITS_ARB;
- IAttrib[11] := 0; //TODO: fPixelFormatSettings.AlphaBits;
-
- IAttrib[12] := WGL_DEPTH_BITS_ARB;
- IAttrib[13] := fPixelFormatSettings.DepthBits;
-
- IAttrib[14] := WGL_STENCIL_BITS_ARB;
- IAttrib[15] := fPixelFormatSettings.StencilBits;
-
- IAttrib[16] := WGL_ACCUM_BITS_ARB;
- IAttrib[17] := fPixelFormatSettings.AccumBits;
-
- IAttrib[18] := WGL_AUX_BUFFERS_ARB;
- IAttrib[19] := fPixelFormatSettings.AuxBuffers;
-
- IAttrib[20] := WGL_SAMPLE_BUFFERS_ARB;
- IAttrib[21] := 1;
-
- IAttrib[22] := 0;
- FAttrib := 0;
-
- if multiARBSup then
- wglChoosePixelFormatARB(tmpContext.FDC, @IAttrib[0], @FAttrib, MaxCount, pPFList, @Count)
- else if multiEXTSup then
- wglChoosePixelFormatEXT(tmpContext.FDC, @IAttrib[0], @FAttrib, MaxCount, pPFList, @Count);
-
- if Count > length(PFList) then
- Count := length(PFList);
-
- QueryAtrib := WGL_SAMPLES_ARB;
- PSample := pSampleList;
- PPosiblePF := @PFList[0];
- for i := 0 to Count-1 do begin
- if multiARBSup then
- wglGetPixelFormatAttribivARB(tmpContext.FDC, PPosiblePF^, 0, 1, @QueryAtrib, PSample)
- else if multiEXTSup then
- wglGetPixelFormatAttribivEXT(tmpContext.FDC, PPosiblePF^, 0, 1, @QueryAtrib, PSample);
- inc(PSample);
- inc(PPosiblePF);
- end;
- end;
- begin
- if (fPixelFormatSettings.MultiSampling = 1) then begin
- Result := FindPixelFormatNoAA;
- exit;
- end;
- Result := 0;
- OldDC := wglGetCurrentDC();
- OldRC := wglGetCurrentContext();
- try
- tmpWnd := TForm.Create(nil);
- tmpContext := TglcContextWGL.Create(tmpWnd);
- try
- pf := tmpContext.FindPixelFormatNoAA;
- tmpContext.OpenFromPF(pf);
- tmpContext.Activate;
-
- FillChar({%H-}PFList[0], Length(PFList), 0);
- FillChar({%H-}SampleList[0], Length(SampleList), 0);
- ChoosePF(@PFList[0], @SampleList[0], length(SampleList));
- max := 0;
- for i := 0 to Count-1 do begin
- if (max < SampleList[i]) and (SampleList[i] <= fPixelFormatSettings.MultiSampling) and (PFList[i] <> 0) then begin
- max := SampleList[i];
- result := PFList[i];
- if (max = fPixelFormatSettings.MultiSampling) then
- break;
- end;
- end;
- tmpContext.Deactivate;
- finally
- FreeAndNil(tmpContext);
- FreeAndNil(tmpWnd);
- end;
- finally
- if (OldDC <> 0) and (OldRC <> 0) then
- ActivateRenderingContext(OldDC, OldRC);
- end;
- end;
-
- function TglcContextWGL.FindPixelFormatNoAA: Integer;
- const
- MemoryDCs = [OBJ_MEMDC, OBJ_METADC, OBJ_ENHMETADC];
- var
- //DeviceContext
- DC: HDC;
- //Objekttyp des DCs
- AType: DWord;
- //Beschreibung zum passenden Pixelformat
- PFDescriptor: TPixelFormatDescriptor;
- begin
- result := 0;
- DC := GetDC(fHandle);
- if DC = 0 then begin
- exit;
- end;
- FillChar(PFDescriptor{%H-}, SizeOf(PFDescriptor), #0);
- with PFDescriptor do begin
- nSize := SizeOf(PFDescriptor);
- nVersion := 1;
- dwFlags := PFD_SUPPORT_OPENGL;
- AType := GetObjectType(DC);
- if AType = 0 then begin
- exit;
- end;
- if fPixelFormatSettings.DoubleBuffered then
- dwFlags := dwFlags or PFD_DOUBLEBUFFER;
- if fPixelFormatSettings.Stereo then
- dwFlags := dwFlags or PFD_STEREO;
- if AType in MemoryDCs then
- dwFlags := dwFlags or PFD_DRAW_TO_BITMAP
- else
- dwFlags := dwFlags or PFD_DRAW_TO_WINDOW;
-
- iPixelType := PFD_TYPE_RGBA;
- cColorBits := fPixelFormatSettings.ColorBits;
- //TODO: cAlphaBits := fPixelFormatSettings.AlphaBits;
- cDepthBits := fPixelFormatSettings.DepthBits;
- cStencilBits := fPixelFormatSettings.StencilBits;
- cAccumBits := fPixelFormatSettings.AccumBits;
- cAuxBuffers := fPixelFormatSettings.AuxBuffers;
-
- if fPixelFormatSettings.Layer = 0 then
- iLayerType := PFD_MAIN_PLANE
- else if fPixelFormatSettings.Layer > 0 then
- iLayerType := PFD_OVERLAY_PLANE
- else
- iLayerType := Byte(PFD_UNDERLAY_PLANE);
- end;
- result := ChoosePixelFormat(DC, @PFDescriptor);
- end;
-
- procedure TglcContextWGL.OpenFromPF(PixelFormat: Integer);
- var
- tmpRC: HGLRC;
- err: DWORD;
- Attribs: array of GLint;
- CreateContextAttribs: TwglCreateContextAttribsARB;
- begin
- if PixelFormat = 0 then begin
- raise EWGLError.Create('Invalid PixelFormat');
- end;
-
- FDC := GetDC(fHandle);
- if FDC = 0 then begin
- raise EWGLError.CreateFmt('Cannot create DC on %x',[fHandle]);
- end;
-
- if not SetPixelFormat(FDC, PixelFormat, nil) then begin
- ReleaseDC(fHandle, FDC);
- raise EWGLError.CreateFmt('Cannot set PF %d on Control %x DC %d',[PixelFormat, fHandle, FDC]);
- end;
-
- tmpRC := wglCreateContext(FDC);
- if tmpRC = 0 then begin
- ReleaseDC(fHandle, FDC);
- raise EWGLError.CreateFmt('Cannot create context on Control %x DC %d',[PixelFormat, fHandle, FDC]);
- end;
-
- if fUseVersion and
- (fVersionSettings.Major <> GLC_CONTEXT_VERSION_UNKNOWN) and
- (fVersionSettings.Minor <> GLC_CONTEXT_VERSION_UNKNOWN) then
- begin
- { Code from dglOpenGL.pas (modified) }
- wglMakeCurrent(FDC, tmpRC);
-
- // Set attributes to describe our requested context
- SetLength(Attribs, 5);
- Attribs[0] := WGL_CONTEXT_MAJOR_VERSION_ARB;
- Attribs[1] := fVersionSettings.Major;
- Attribs[2] := WGL_CONTEXT_MINOR_VERSION_ARB;
- Attribs[3] := fVersionSettings.Minor;
-
- // Add context flag for forward compatible context
- // Forward compatible means no more support for legacy functions like
- // immediate mode (glvertex, glrotate, gltranslate, etc.)
- if fVersionSettings.ForwardCompatible then begin
- SetLength(Attribs, Length(Attribs)+2);
- Attribs[4] := WGL_CONTEXT_FLAGS_ARB;
- Attribs[5] := WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
- end;
-
- // Attribute flags must be finalized with a zero
- Attribs[High(Attribs)] := 0;
-
- // Get function pointer for new context creation function
- CreateContextAttribs := TwglCreateContextAttribsARB(wglGetProcAddress('wglCreateContextAttribsARB'));
- if not Assigned(CreateContextAttribs) then begin
- wglMakeCurrent(0, 0);
- wglDeleteContext(tmpRC);
- ReleaseDC(fHandle, FDC);
- raise Exception.Create('Could not get function pointer adress for wglCreateContextAttribsARB - OpenGL 3.x and above not supported!');
- end;
-
- // Create context
- FRC := CreateContextAttribs(FDC, 0, @Attribs[0]);
- if (FRC = 0) then begin
- wglMakeCurrent(0, 0);
- wglDeleteContext(tmpRC);
- ReleaseDC(fHandle, FDC);
- raise Exception.Create('Could not create the desired OpenGL rendering context!');
- end;
-
- wglMakeCurrent(0, 0);
- wglDeleteContext(tmpRC);
- end else
- FRC := tmpRC;
-
- if Assigned(ShareContext) then begin
- if (ShareContext.ClassName <> ClassName) then
- raise Exception.Create('share context has invalid type: ' + ShareContext.ClassName);
- if not wglShareLists((ShareContext as TglcContextWGL).FRC, FRC) then begin
- err := GetLastError();
- raise EGLError.Create('wglShareLists failed (' + IntToStr(err) + ') ' + SysErrorMessage(err));
- end;
- end;
- end;
-
- constructor TglcContextWGL.Create(const aControl: TWinControl; const aPixelFormatSettings: TglcContextPixelFormatSettings; const aShareContext: TglcContext);
- begin
- inherited Create(aControl, aPixelFormatSettings, aShareContext);
- fHandle := aControl.Handle;
- UpdatePixelFormat;
- end;
-
- constructor TglcContextWGL.Create(const aControl: TWinControl; const aPixelFormatSettings: TglcContextPixelFormatSettings; const aVersionSettings: TglcContextVersionSettings; const aShareContext: TglcContext);
- begin
- inherited Create(aControl, aPixelFormatSettings, aVersionSettings, aShareContext);
- fHandle := aControl.Handle;
- UpdatePixelFormat;
- end;
-
- procedure TglcContextWGL.CloseContext;
- begin
- if (FRC <> 0) then begin
- Deactivate;
- DestroyRenderingContext(FRC);
- ReleaseDC(fHandle, FDC);
- FRC := 0;
- FDC := 0;
- end;
- end;
-
- procedure TglcContextWGL.Activate;
- var
- err: DWORD;
- begin
- if (FDC = 0) or (FRC = 0) then
- raise Exception.Create('invalid context. did you call build context first?');
- if (not wglMakeCurrent(FDC, FRC)) then begin
- err := GetLastError;
- raise Exception.Create('unable to activate context: (' + IntToStr(err) + ') ' + SysErrorMessage(err));
- end;
- inherited Activate;
- end;
-
- procedure TglcContextWGL.Deactivate;
- var
- err: DWORD;
- begin
- if (wglGetCurrentContext()=FRC) and not wglMakeCurrent(0, 0) then begin
- err := GetLastError;
- raise Exception.Create('unable to deactivate context: (' + IntToStr(err) + ') ' + SysErrorMessage(err));
- end;
- end;
-
- function TglcContextWGL.IsActive: boolean;
- begin
- Result:= (FRC <> 0) and
- (FRC = wglGetCurrentContext()) and
- (FDC = wglGetCurrentDC());
- end;
-
- procedure TglcContextWGL.SwapBuffers;
- begin
- Windows.SwapBuffers(FDC);
- end;
-
- procedure TglcContextWGL.SetSwapInterval(const aInterval: GLint);
- begin
- wglSwapIntervalEXT(aInterval);
- end;
-
- function TglcContextWGL.GetSwapInterval: GLint;
- begin
- result := wglGetSwapIntervalEXT();
- end;
-
- class function TglcContextWGL.ChangeDisplaySettings(const aWidth, aHeight,
- aBitPerPixel, aFreq: Integer; const aFlags: TglcDisplayFlags): Boolean;
- var
- dm: TDeviceMode;
- flags: Cardinal;
- begin
- FillChar(dm{%H-}, SizeOf(dm), 0);
- with dm do begin
- dmSize := SizeOf(dm);
- dmPelsWidth := aWidth;
- dmPelsHeight := aHeight;
- dmDisplayFrequency := aFreq;
- dmBitsPerPel := aBitPerPixel;
- dmFields := DM_PELSWIDTH or DM_PELSHEIGHT or DM_BITSPERPEL or DM_DISPLAYFREQUENCY;
- end;
- flags := 0; //CDS_TEST;
- if (dfFullscreen in aFlags) then
- flags := flags or CDS_FULLSCREEN;
- result := (Windows.ChangeDisplaySettings(dm, flags) = DISP_CHANGE_SUCCESSFUL);
- end;
-
- class function TglcContextWGL.IsAnyContextActive: boolean;
- begin
- Result:= (wglGetCurrentContext()<>0) and (wglGetCurrentDC()<>0);
- end;
-
- end.
|