View Issue Details

IDProjectCategoryView StatusLast Update
0034401LazarusWidgetsetpublic2018-10-15 18:59
ReporterChris RordenAssigned ToZeljan Rikalo 
PrioritynormalSeverityminorReproducibilityalways
Status closedResolutionfixed 
PlatformLinuxOSUbuntuOS Version16.04
Product Version1.9 (SVN)Product Build59267 
Target VersionFixed in Version 
Summary0034401: QT OpenGL support
DescriptionZeljko recently added updated GLGtkGlxContext to support QT5 (instead of just QT4). However, the current GLGtkGlxContext has two limitations:
 1. It ignores the TOpenGLContext MajorVersion and MinorVersion, so it does not support more recent versions of OpenGL.
 2. It ignores TOpenGLContext.Multisampling, so lines look jagged.

I have attached a patch that fixes issue 1: this will allow QT to support modern versions of OpenGL. The code includes the compiler switch
  {$DEFINE ModernGL}
if this line is commented out, you can see the previous behavior. Note that with this line commented out you will be limited to an old version of OpenGL (on my Linux QT4 setup, I am limited to OpenGL 3.0 without this patch), with the patch I get the most recent version supported by my hardware (4.6).

This patch does not appear to fix issue 2. I did copy much of the boilerplate from glgtkglxcontext.pas for supporting multisampling, and the new code does appear to identify a BestFBConfig that supports multisampling, but there must be some other adjustment to enable multisampling.
Steps To ReproduceSee attached project
 1.) Without this patch, when compiled to QT4/5 the caption reports "OpenGL 3.0" with the patch it supports the version supported by your system. Likewise, if you compile to GTK2 it uses the most recent version. Note that this project only uses OpenGL 3.0 so it runs with or without the patch, but projects that use more recent features only work with this patch.
 2.) Note that the lines look jagged when you compile to the QT widgetset, but look smooth when compiled to GTK2 (as the project uses multisampling).
 
TagsNo tags attached.
Fixed in Revision59285,59293
LazTarget-
WidgetsetQT, QT5
Attached Files
  • mypatch.diff (7,143 bytes)
    Index: glqtcontext.pas
    ===================================================================
    --- glqtcontext.pas	(revision 59253)
    +++ glqtcontext.pas	(working copy)
    @@ -12,10 +12,15 @@
     {$mode objfpc}{$H+}
     {$LinkLib GL}
     {$PACKRECORDS C}
    -
    +{$DEFINE ModernGL}
     interface
     
     uses
    +  //  Classes, SysUtils, ctypes, LCLProc, LCLType, X, XUtil, XLib, gl,
    +  //InterfaceBase,
    +  //glx,
    +  //WSLCLClasses,
    +  {$IFDEF ModernGL} ctypes,{$ENDIF}
       Classes, SysUtils, Controls, LCLProc, LCLType, X, XUtil, XLib, gl,
       InterfaceBase,
       WSLCLClasses,glx,
    @@ -60,6 +65,7 @@
     type
       TGLXContext = pointer;
     
    +
     procedure LOpenGLViewport(Handle: HWND; Left, Top, Width, Height: integer);
     procedure LOpenGLSwapBuffers(Handle: HWND);
     function LOpenGLMakeCurrent(Handle: HWND): boolean;
    @@ -168,7 +174,24 @@
       Result := glXMakeCurrent(Widget.xdisplay, 0, nil);
     end;
     
    +{$IFDEF ModernGL}
    +function CustomXErrorHandler({%H-}para1:PDisplay; para2:PXErrorEvent):cint;cdecl;
    +begin
    +  if para2^.error_code=8 then begin
    +    raise Exception.Create('A BadMatch X error occured. Most likely the requested OpenGL version is invalid.');
    +  end;
    +  Result:=0;
    +end;
    +{$ENDIF}
     
    +type
    +TContextAttribs = record
    +  AttributeList: PLongint;
    +  MajorVersion: Cardinal;
    +  MinorVersion: Cardinal;
    +  MultiSampling: Cardinal;
    +  ContextFlags: Cardinal;
    +end;
     {function LOpenGLCreateContext(AWinControl: TWinControl;
       WSPrivate: TWSPrivateClass; SharedControl: TWinControl;
       DoubleBuffered, RGBA: boolean;
    @@ -182,12 +205,25 @@
                               const AParams: TCreateParams): HWND;
     
     var
    -  AttrList: PInteger;
    +  {$IFDEF ModernGL} { Used with glXCreateContextAttribsARB to select 3.X and above context }
    +  Context3X: array [0..6] of Integer;
    +  ScreenNum: cint;
    +  FBConfig: TGLXFBConfig;
    +  FBConfigs: PGLXFBConfig;
    +  FBConfigsCount: Integer;
    +  i: Integer;
    +  Samples: cint;
    +  BestSamples: Integer;
    +  BestFBConfig: Integer;
    +  XVInfo: PXVisualInfo;
    +  XDisplay: PDisplay;
    +  {$ENDIF}
    +  AttrList: TContextAttribs;
       NewQtWidget: TQtGLWidget;
       direct: boolean;
     begin
       if WSPrivate=nil then ;
    -  AttrList:=CreateOpenGLContextAttrList(DoubleBuffered,RGBA,RedBits,GreenBits,BlueBits,AlphaBits,DepthBits,StencilBits,AUXBuffers);
    +  AttrList.AttributeList:=CreateOpenGLContextAttrList(DoubleBuffered,RGBA,RedBits,GreenBits,BlueBits,AlphaBits,DepthBits,StencilBits,AUXBuffers);
       try
         NewQtWidget:=TQtGLWidget.Create(AWinControl,AParams);
         NewQtWidget.setAttribute(QtWA_PaintOnScreen);
    @@ -196,9 +232,88 @@
         NewQtWidget.HasPaint:=true;
         NewQtWidget.xdisplay := QX11Info_display;
         NewQtWidget.visual:=glXChooseVisual(NewQtWidget.xdisplay,
    -      DefaultScreen(NewQtWidget.xdisplay), @attrList[0]);
    +      DefaultScreen(NewQtWidget.xdisplay), @attrList.AttributeList[0]);
         direct:=false;
    -    NewQtWidget.glxcontext := glXCreateContext(NewQtWidget.xdisplay,
    +    {$IFDEF ModernGL}
    +    if GLX_version_1_3(NewQtWidget.xdisplay) then begin
    +        //use approach recommended since glX 1.3
    +        direct := true;
    +        XDisplay := NewQtWidget.xdisplay;//QX11Info_display();
    +        ScreenNum := DefaultScreen (XDisplay);
    +        AttrList.MajorVersion:=MajorVersion;
    +        AttrList.MinorVersion:=MinorVersion;
    +        // fill in context flags
    +        AttrList.ContextFlags:=0;
    +        //if DebugContext then
    +        // AttrList.ContextFlags:=Attribs.ContextFlags or GLX_CONTEXT_DEBUG_BIT_ARB;
    +        if (MultiSampling > 1) and GLX_ARB_multisample(XDisplay,ScreenNum) then begin
    +	   AttrList.MultiSampling:=MultiSampling;
    +        end else begin
    +	    AttrList.MultiSampling:=0;
    +        end;
    +        FBConfigsCount:=0;
    +        FBConfigs:=glXChooseFBConfig(XDisplay, ScreenNum, @AttrList.AttributeList[0], FBConfigsCount);
    +        if FBConfigsCount = 0 then
    +	  raise Exception.Create('Could not find FB config');
    +
    +        // if multisampling is requested try to get a number of sample buffers as
    +        // close to the specified number as possible
    +        if AttrList.MultiSampling>0 then begin
    +	  BestSamples:=0;
    +	  for i:=0 to FBConfigsCount-1 do begin
    +	        Samples:=0;
    +	        glXGetFBConfigAttrib(NewQtWidget.xdisplay, FBConfigs[i], GLX_SAMPLES_ARB, Samples);
    +	        if Samples=AttrList.MultiSampling then begin
    +		  BestFBConfig:=i;
    +		  break;
    +	        end else begin
    +		  if (Samples>BestSamples) and (Samples<AttrList.MultiSampling) then begin
    +		        BestSamples:=Samples;
    +		        BestFBConfig:=i;
    +		  end;
    +	        end;
    +	  end;
    +          //raise Exception.Create('BestFBConfig '+inttostr(BestFBConfig));
    +	  FBConfig := FBConfigs[BestFBConfig];
    +        end else begin
    +	  { just choose the first FB config from the FBConfigs list.
    +	        More involved selection possible. }
    +	  FBConfig := FBConfigs^;
    +        end;
    +        XVInfo:=glXGetVisualFromFBConfig(NewQtWidget.xdisplay, FBConfig);
    +        if XVInfo=nil then
    +           raise Exception.Create('QT no visual found');
    +        if (GLX_ARB_create_context(NewQtWidget.xdisplay, DefaultScreen(NewQtWidget.xdisplay))) and (AttrList.MajorVersion>0) then begin
    +		  // install custom X error handler
    +		  XSetErrorHandler(@CustomXErrorHandler);
    +		  Context3X[0]:=GLX_CONTEXT_MAJOR_VERSION_ARB;
    +		  Context3X[1]:=AttrList.MajorVersion;
    +		  Context3X[2]:=GLX_CONTEXT_MINOR_VERSION_ARB;
    +		  Context3X[3]:=AttrList.MinorVersion;
    +		  Context3X[4]:=GLX_CONTEXT_FLAGS_ARB;
    +		  Context3X[5]:=AttrList.ContextFlags;
    +		  Context3X[6]:=None;
    +		  //if (ShareList<>nil) then begin
    +		  //	NewQtWidget.glxcontext:=glXCreateContextAttribsARB(NewQtWidget.xdisplay, FBConfig,PrivateShareList^.glxcontext, direct, Context3X);
    +		  //end else begin
    +		        NewQtWidget.glxcontext:=glXCreateContextAttribsARB(NewQtWidget.xdisplay, FBConfig, Nil, direct, Context3X);
    +		  //end;
    +                  //raise Exception.Create('key '+inttostr(BestFBConfig));
    +		  // restore default error handler
    +		  XSetErrorHandler(nil);
    +	        end else begin
    +		  //if (ShareList<>nil) then begin
    +		  //	NewQtWidget.glxcontext:=glXCreateNewContext(NewQtWidget.xdisplay, FBConfig, GLX_RGBA_TYPE,PrivateShareList^.glxcontext, direct)
    +		  //end else begin
    +		        NewQtWidget.glxcontext:=glXCreateNewContext(NewQtWidget.xdisplay, FBConfig, GLX_RGBA_TYPE, Nil, direct);
    +		  //end;
    +	        end;
    +	        if FBConfigs<>nil then
    +		  XFree(FBConfigs);
    +
    +    end else
    +    {$ENDIF}
    +            NewQtWidget.glxcontext := glXCreateContext(NewQtWidget.xdisplay,
                                                    NewQtWidget.visual, nil, direct);
         NewQtWidget.ref_count := 1;
     
    @@ -206,7 +321,7 @@
     
         Result:=HWND(PtrUInt(Pointer(NewQtWidget)));
       finally
    -    FreeMem(AttrList);
    +    FreeMem(AttrList.AttributeList);
       end;
     end;
     
    @@ -275,7 +390,11 @@
       {$IFDEF VerboseMultiSampling}
       debugln(['CreateOpenGLContextAttrList MultiSampling=',MultiSampling]);
       {$ENDIF}
    -  UseFBConfig := false; //GLX_version_1_3(GetDefaultXDisplay);
    +   {$IFDEF ModernGL}
    +  UseFBConfig := GLX_version_1_3(QX11Info_display());
    +  {$ELSE}
    +  UseFBConfig := false;
    +  {$ENDIF}
       Result:=nil;
       CreateList;
       GetMem(Result,SizeOf(integer)*p);
    
    
    mypatch.diff (7,143 bytes)
  • lines.zip (52,927 bytes)
  • mypatch2.diff (9,117 bytes)
    Index: glqtcontext.pas
    ===================================================================
    --- glqtcontext.pas	(revision 59272)
    +++ glqtcontext.pas	(working copy)
    @@ -12,10 +12,16 @@
     {$mode objfpc}{$H+}
     {$LinkLib GL}
     {$PACKRECORDS C}
    -
    +{$DEFINE ModernGL}
    +//{$DEFINE VerboseMultiSampling}
     interface
     
     uses
    +  //  Classes, SysUtils, ctypes, LCLProc, LCLType, X, XUtil, XLib, gl,
    +  //InterfaceBase,
    +  //glx,
    +  //WSLCLClasses,
    +  {$IFDEF ModernGL} ctypes,{$ENDIF}
       Classes, SysUtils, Controls, LCLProc, LCLType, X, XUtil, XLib, gl,
       InterfaceBase,
       WSLCLClasses,glx,
    @@ -60,6 +66,7 @@
     type
       TGLXContext = pointer;
     
    +
     procedure LOpenGLViewport(Handle: HWND; Left, Top, Width, Height: integer);
     procedure LOpenGLSwapBuffers(Handle: HWND);
     function LOpenGLMakeCurrent(Handle: HWND): boolean;
    @@ -74,7 +81,7 @@
     procedure LOpenGLDestroyContextInfo(AWinControl: TWinControl);
     function CreateOpenGLContextAttrList(DoubleBuffered: boolean; RGBA: boolean;
                  const RedBits, GreenBits, BlueBits, AlphaBits, DepthBits,
    -             StencilBits,  AUXBuffers: Cardinal): PInteger;
    +             StencilBits,  AUXBuffers, MultiSampling: Cardinal): PInteger;
     
     
     implementation
    @@ -168,7 +175,24 @@
       Result := glXMakeCurrent(Widget.xdisplay, 0, nil);
     end;
     
    +{$IFDEF ModernGL}
    +function CustomXErrorHandler({%H-}para1:PDisplay; para2:PXErrorEvent):cint;cdecl;
    +begin
    +  if para2^.error_code=8 then begin
    +    raise Exception.Create('A BadMatch X error occured. Most likely the requested OpenGL version is invalid.');
    +  end;
    +  Result:=0;
    +end;
    +{$ENDIF}
     
    +type
    +TContextAttribs = record
    +  AttributeList: PLongint;
    +  MajorVersion: Cardinal;
    +  MinorVersion: Cardinal;
    +  MultiSampling: Cardinal;
    +  ContextFlags: Cardinal;
    +end;
     {function LOpenGLCreateContext(AWinControl: TWinControl;
       WSPrivate: TWSPrivateClass; SharedControl: TWinControl;
       DoubleBuffered, RGBA: boolean;
    @@ -182,12 +206,28 @@
                               const AParams: TCreateParams): HWND;
     
     var
    -  AttrList: PInteger;
    +  {$IFDEF ModernGL} { Used with glXCreateContextAttribsARB to select 3.X and above context }
    +  Context3X: array [0..6] of Integer;
    +  ScreenNum: cint;
    +  FBConfig: TGLXFBConfig;
    +  FBConfigs: PGLXFBConfig;
    +  FBConfigsCount: Integer;
    +  i: Integer;
    +  Samples: cint;
    +  BestSamples: Integer;
    +  BestFBConfig: Integer;
    +  XVInfo: PXVisualInfo;
    +  XDisplay: PDisplay;
    +  {$ENDIF}
    +  AttrList: TContextAttribs;
       NewQtWidget: TQtGLWidget;
       direct: boolean;
    +  {$IFDEF VerboseMultiSampling}
    +  samp_buf, visual_id, red_size, blue_size, green_size, alpha_size: integer;
    +  {$ENDIF}
     begin
       if WSPrivate=nil then ;
    -  AttrList:=CreateOpenGLContextAttrList(DoubleBuffered,RGBA,RedBits,GreenBits,BlueBits,AlphaBits,DepthBits,StencilBits,AUXBuffers);
    +  AttrList.AttributeList:=CreateOpenGLContextAttrList(DoubleBuffered,RGBA,RedBits,GreenBits,BlueBits,AlphaBits,DepthBits,StencilBits,AUXBuffers,MultiSampling);
       try
         NewQtWidget:=TQtGLWidget.Create(AWinControl,AParams);
         NewQtWidget.setAttribute(QtWA_PaintOnScreen);
    @@ -196,9 +236,97 @@
         NewQtWidget.HasPaint:=true;
         NewQtWidget.xdisplay := QX11Info_display;
         NewQtWidget.visual:=glXChooseVisual(NewQtWidget.xdisplay,
    -      DefaultScreen(NewQtWidget.xdisplay), @attrList[0]);
    +      DefaultScreen(NewQtWidget.xdisplay), @attrList.AttributeList[0]);
         direct:=false;
    -    NewQtWidget.glxcontext := glXCreateContext(NewQtWidget.xdisplay,
    +    {$IFDEF ModernGL}
    +    if GLX_version_1_3(NewQtWidget.xdisplay) then begin
    +        //use approach recommended since glX 1.3
    +        direct := true;
    +        XDisplay := NewQtWidget.xdisplay;//QX11Info_display();
    +        ScreenNum := DefaultScreen(XDisplay);
    +        AttrList.MajorVersion:=MajorVersion;
    +        AttrList.MinorVersion:=MinorVersion;
    +        // fill in context flags
    +        AttrList.ContextFlags:=0;
    +        //if DebugContext then
    +        // AttrList.ContextFlags:=Attribs.ContextFlags or GLX_CONTEXT_DEBUG_BIT_ARB;
    +        if (MultiSampling > 1) and GLX_ARB_multisample(XDisplay,ScreenNum) then begin
    +	   		AttrList.MultiSampling:=MultiSampling;
    +        end else begin
    +	    	AttrList.MultiSampling:=0;
    +        end;
    +        FBConfigsCount:=0;
    +        FBConfigs:=glXChooseFBConfig(XDisplay, ScreenNum, @AttrList.AttributeList[0], FBConfigsCount);
    +        if FBConfigsCount = 0 then
    +	  raise Exception.Create('Could not find FB config');
    +        // if multisampling is requested try to get a number of sample buffers as
    +        // close to the specified number as possible
    +        if AttrList.MultiSampling>0 then begin
    +	  BestSamples:=0;
    +	  for i:=0 to FBConfigsCount-1 do begin
    +	        Samples:=0;
    +	        glXGetFBConfigAttrib(XDisplay, FBConfigs[i], GLX_SAMPLES_ARB, Samples);
    +	        if Samples=AttrList.MultiSampling then begin
    +		  BestFBConfig:=i;
    +		  break;
    +	        end else begin
    +		  if (Samples>BestSamples) and (Samples<AttrList.MultiSampling) then begin
    +		        BestSamples:=Samples;
    +		        BestFBConfig:=i;
    +		  end;
    +	        end;
    +	  end;
    +          //raise Exception.Create('BestFBConfig '+inttostr(BestFBConfig));
    +	  FBConfig := FBConfigs[BestFBConfig];
    +	  {$IFDEF VerboseMultiSampling}
    +            //https://www.opengl.org/discussion_boards/showthread.php/168359-OpenGL-3-x-and-Qt-framework?styleid=12
    +            glXGetFBConfigAttrib(XDisplay, FBConfig, GLX_SAMPLE_BUFFERS, samp_buf );
    +            glXGetFBConfigAttrib(XDisplay, FBConfig, GLX_SAMPLES, Samples  );
    +            glXGetFBConfigAttrib(XDisplay, FBConfig, GLX_VISUAL_ID, visual_id  );
    +            glXGetFBConfigAttrib(XDisplay, FBConfig, GLX_RED_SIZE, red_size  );
    +            glXGetFBConfigAttrib(XDisplay, FBConfig, GLX_BLUE_SIZE, blue_size  );
    +            glXGetFBConfigAttrib(XDisplay, FBConfig, GLX_GREEN_SIZE, green_size  );
    +            glXGetFBConfigAttrib(XDisplay, FBConfig, GLX_ALPHA_SIZE, alpha_size  );
    +
    +            debugln(format('OpenGL fbconfig %d, ID 0x%x, SAMPLE_BUFFERS %d, SAMPLES %d, R%d G%d B%d A%d',
    +              [BestFBConfig, visual_id, samp_buf, samples, red_size, blue_size, green_size, alpha_size]));
    +          {$ENDIF}
    +        end else //if MultiSampling=0 just choose the first FB config
    +	  FBConfig := FBConfigs^;
    +        XVInfo:=glXGetVisualFromFBConfig(XDisplay, FBConfig);
    +        if XVInfo=nil then
    +           raise Exception.Create('QT no visual found');
    +        if (GLX_ARB_create_context(XDisplay, ScreenNum)) and (AttrList.MajorVersion>0) then begin
    +		  // install custom X error handler
    +		  XSetErrorHandler(@CustomXErrorHandler);
    +		  Context3X[0]:=GLX_CONTEXT_MAJOR_VERSION_ARB;
    +		  Context3X[1]:=AttrList.MajorVersion;
    +		  Context3X[2]:=GLX_CONTEXT_MINOR_VERSION_ARB;
    +		  Context3X[3]:=AttrList.MinorVersion;
    +		  Context3X[4]:=GLX_CONTEXT_FLAGS_ARB;
    +		  Context3X[5]:=AttrList.ContextFlags;
    +		  Context3X[6]:=None;
    +		  //if (ShareList<>nil) then begin
    +		  //	NewQtWidget.glxcontext:=glXCreateContextAttribsARB(NewQtWidget.xdisplay, FBConfig,PrivateShareList^.glxcontext, direct, Context3X);
    +		  //end else begin
    +		        NewQtWidget.glxcontext:=glXCreateContextAttribsARB(XDisplay, FBConfig, Nil, direct, Context3X);
    +		  //end;
    +                  //raise Exception.Create('key '+inttostr(BestFBConfig));
    +		  // restore default error handler
    +		  XSetErrorHandler(nil);
    +	        end else begin
    +		  //if (ShareList<>nil) then begin
    +		  //	NewQtWidget.glxcontext:=glXCreateNewContext(NewQtWidget.xdisplay, FBConfig, GLX_RGBA_TYPE,PrivateShareList^.glxcontext, direct)
    +		  //end else begin
    +		        NewQtWidget.glxcontext:=glXCreateNewContext(XDisplay, FBConfig, GLX_RGBA_TYPE, Nil, direct);
    +		  //end;
    +	        end;
    +	        if FBConfigs<>nil then
    +		  XFree(FBConfigs);
    +
    +    end else
    +    {$ENDIF}
    +            NewQtWidget.glxcontext := glXCreateContext(NewQtWidget.xdisplay,
                                                    NewQtWidget.visual, nil, direct);
         NewQtWidget.ref_count := 1;
     
    @@ -206,7 +334,7 @@
     
         Result:=HWND(PtrUInt(Pointer(NewQtWidget)));
       finally
    -    FreeMem(AttrList);
    +    FreeMem(AttrList.AttributeList);
       end;
     end;
     
    @@ -218,7 +346,7 @@
     
     function CreateOpenGLContextAttrList(DoubleBuffered: boolean; RGBA: boolean;
       const RedBits, GreenBits, BlueBits, AlphaBits, DepthBits, StencilBits,
    -  AUXBuffers: Cardinal): PInteger;
    +  AUXBuffers, MultiSampling: Cardinal): PInteger;
     var
       p: integer;
       UseFBConfig: boolean;
    @@ -267,7 +395,10 @@
         begin
           Add(GLX_AUX_BUFFERS);  Add(AUXBuffers);
         end;
    -
    +	if MultiSampling>0 then begin
    +      Add(GLX_SAMPLE_BUFFERS);  Add(1);
    +      Add(GLX_SAMPLES);  Add(MultiSampling);
    +	end;
         Add(0); { 0 = X.None (be careful: GLX_NONE is something different) }
       end;
     
    @@ -275,7 +406,11 @@
       {$IFDEF VerboseMultiSampling}
       debugln(['CreateOpenGLContextAttrList MultiSampling=',MultiSampling]);
       {$ENDIF}
    -  UseFBConfig := false; //GLX_version_1_3(GetDefaultXDisplay);
    +   {$IFDEF ModernGL}
    +  UseFBConfig := GLX_version_1_3(QX11Info_display());
    +  {$ELSE}
    +  UseFBConfig := false;
    +  {$ENDIF}
       Result:=nil;
       CreateList;
       GetMem(Result,SizeOf(integer)*p);
    
    mypatch2.diff (9,117 bytes)
  • qtPatch3.diff (3,260 bytes)
    Index: components/opengl/glqtcontext.pas
    ===================================================================
    --- components/opengl/glqtcontext.pas	(revision 59290)
    +++ components/opengl/glqtcontext.pas	(working copy)
    @@ -13,6 +13,7 @@
     {$LinkLib GL}
     {$PACKRECORDS C}
     {$DEFINE ModernGL}
    +//{$DEFINE VerboseMultiSampling}
     interface
     
     uses
    @@ -80,7 +81,7 @@
     procedure LOpenGLDestroyContextInfo(AWinControl: TWinControl);
     function CreateOpenGLContextAttrList(DoubleBuffered: boolean; RGBA: boolean;
                  const RedBits, GreenBits, BlueBits, AlphaBits, DepthBits,
    -             StencilBits,  AUXBuffers: Cardinal): PInteger;
    +             StencilBits,  AUXBuffers, MultiSampling: Cardinal): PInteger;
     
     
     implementation
    @@ -290,9 +291,12 @@
       AttrList: TContextAttribs;
       NewQtWidget: TQtGLWidget;
       direct: boolean;
    +  {$IFDEF VerboseMultiSampling}
    +  samp_buf, visual_id, red_size, blue_size, green_size, alpha_size: integer;
    +  {$ENDIF}
     begin
       if WSPrivate=nil then ;
    -  AttrList.AttributeList := CreateOpenGLContextAttrList(DoubleBuffered,RGBA,RedBits,GreenBits,BlueBits,AlphaBits,DepthBits,StencilBits,AUXBuffers);
    +  AttrList.AttributeList := CreateOpenGLContextAttrList(DoubleBuffered,RGBA,RedBits,GreenBits,BlueBits,AlphaBits,DepthBits,StencilBits,AUXBuffers, MultiSampling);
       try
         NewQtWidget:=TQtGLWidget.Create(AWinControl,AParams);
         NewQtWidget.setAttribute(QtWA_PaintOnScreen);
    @@ -354,6 +358,18 @@
             end;
               //raise Exception.Create('BestFBConfig '+inttostr(BestFBConfig));
     	      FBConfig := FBConfigs[BestFBConfig];
    +	      {$IFDEF VerboseMultiSampling}
    +	      //HTTPS://WWW.OPENGL.ORG/DISCUSSION_BOARDS/SHOWTHREAD.PHP/168359-OPENGL-3-X-AND-QT-FRAMEWORK?STYLEID=12
    +	      GLXGETFBCONFIGATTRIB(XDISPLAY, FBCONFIG, GLX_SAMPLE_BUFFERS, SAMP_BUF);
    +	      GLXGETFBCONFIGATTRIB(XDISPLAY, FBCONFIG, GLX_SAMPLES, SAMPLES);
    +	      GLXGETFBCONFIGATTRIB(XDISPLAY, FBCONFIG, GLX_VISUAL_ID, VISUAL_ID);
    +	      GLXGETFBCONFIGATTRIB(XDISPLAY, FBCONFIG, GLX_RED_SIZE, RED_SIZE);
    +	      GLXGETFBCONFIGATTRIB(XDISPLAY, FBCONFIG, GLX_BLUE_SIZE, BLUE_SIZE);
    +	      GLXGETFBCONFIGATTRIB(XDISPLAY, FBCONFIG, GLX_GREEN_SIZE, GREEN_SIZE);
    +	      GLXGETFBCONFIGATTRIB(XDISPLAY, FBCONFIG, GLX_ALPHA_SIZE, ALPHA_SIZE);
    +	      DEBUGLN(FORMAT('OPENGL FBCONFIG %D, ID 0X%X, SAMPLE_BUFFERS %D, SAMPLES %D, R%D G%D B%D A%D',
    +              [BESTFBCONFIG, VISUAL_ID, SAMP_BUF, SAMPLES, RED_SIZE, BLUE_SIZE, GREEN_SIZE, ALPHA_SIZE]));
    +          {$ENDIF}
           end else
           begin
       	    { just choose the first FB config from the FBConfigs list.
    @@ -418,7 +434,7 @@
     
     function CreateOpenGLContextAttrList(DoubleBuffered: boolean; RGBA: boolean;
       const RedBits, GreenBits, BlueBits, AlphaBits, DepthBits, StencilBits,
    -  AUXBuffers: Cardinal): PInteger;
    +  AUXBuffers, MultiSampling: Cardinal): PInteger;
     var
       p: integer;
       UseFBConfig: boolean;
    @@ -468,7 +484,12 @@
         begin
           Add(GLX_AUX_BUFFERS);  Add(AUXBuffers);
         end;
    -
    +    {$IFDEF ModernGL}
    +	if MultiSampling>0 then begin
    +      Add(GLX_SAMPLE_BUFFERS);  Add(1);
    +      Add(GLX_SAMPLES);  Add(MultiSampling);
    +	end;
    +    {$ENDIF}
         Add(0); { 0 = X.None (be careful: GLX_NONE is something different) }
       end;
     
    @@ -490,3 +511,4 @@
     
     end.
     
    +
    
    qtPatch3.diff (3,260 bytes)

Relationships

related to 0032498 closedZeljan Rikalo TOpenGLControl not support qt5 widgeset 

Activities

Chris Rorden

2018-10-07 21:22

reporter  

mypatch.diff (7,143 bytes)
Index: glqtcontext.pas
===================================================================
--- glqtcontext.pas	(revision 59253)
+++ glqtcontext.pas	(working copy)
@@ -12,10 +12,15 @@
 {$mode objfpc}{$H+}
 {$LinkLib GL}
 {$PACKRECORDS C}
-
+{$DEFINE ModernGL}
 interface
 
 uses
+  //  Classes, SysUtils, ctypes, LCLProc, LCLType, X, XUtil, XLib, gl,
+  //InterfaceBase,
+  //glx,
+  //WSLCLClasses,
+  {$IFDEF ModernGL} ctypes,{$ENDIF}
   Classes, SysUtils, Controls, LCLProc, LCLType, X, XUtil, XLib, gl,
   InterfaceBase,
   WSLCLClasses,glx,
@@ -60,6 +65,7 @@
 type
   TGLXContext = pointer;
 
+
 procedure LOpenGLViewport(Handle: HWND; Left, Top, Width, Height: integer);
 procedure LOpenGLSwapBuffers(Handle: HWND);
 function LOpenGLMakeCurrent(Handle: HWND): boolean;
@@ -168,7 +174,24 @@
   Result := glXMakeCurrent(Widget.xdisplay, 0, nil);
 end;
 
+{$IFDEF ModernGL}
+function CustomXErrorHandler({%H-}para1:PDisplay; para2:PXErrorEvent):cint;cdecl;
+begin
+  if para2^.error_code=8 then begin
+    raise Exception.Create('A BadMatch X error occured. Most likely the requested OpenGL version is invalid.');
+  end;
+  Result:=0;
+end;
+{$ENDIF}
 
+type
+TContextAttribs = record
+  AttributeList: PLongint;
+  MajorVersion: Cardinal;
+  MinorVersion: Cardinal;
+  MultiSampling: Cardinal;
+  ContextFlags: Cardinal;
+end;
 {function LOpenGLCreateContext(AWinControl: TWinControl;
   WSPrivate: TWSPrivateClass; SharedControl: TWinControl;
   DoubleBuffered, RGBA: boolean;
@@ -182,12 +205,25 @@
                           const AParams: TCreateParams): HWND;
 
 var
-  AttrList: PInteger;
+  {$IFDEF ModernGL} { Used with glXCreateContextAttribsARB to select 3.X and above context }
+  Context3X: array [0..6] of Integer;
+  ScreenNum: cint;
+  FBConfig: TGLXFBConfig;
+  FBConfigs: PGLXFBConfig;
+  FBConfigsCount: Integer;
+  i: Integer;
+  Samples: cint;
+  BestSamples: Integer;
+  BestFBConfig: Integer;
+  XVInfo: PXVisualInfo;
+  XDisplay: PDisplay;
+  {$ENDIF}
+  AttrList: TContextAttribs;
   NewQtWidget: TQtGLWidget;
   direct: boolean;
 begin
   if WSPrivate=nil then ;
-  AttrList:=CreateOpenGLContextAttrList(DoubleBuffered,RGBA,RedBits,GreenBits,BlueBits,AlphaBits,DepthBits,StencilBits,AUXBuffers);
+  AttrList.AttributeList:=CreateOpenGLContextAttrList(DoubleBuffered,RGBA,RedBits,GreenBits,BlueBits,AlphaBits,DepthBits,StencilBits,AUXBuffers);
   try
     NewQtWidget:=TQtGLWidget.Create(AWinControl,AParams);
     NewQtWidget.setAttribute(QtWA_PaintOnScreen);
@@ -196,9 +232,88 @@
     NewQtWidget.HasPaint:=true;
     NewQtWidget.xdisplay := QX11Info_display;
     NewQtWidget.visual:=glXChooseVisual(NewQtWidget.xdisplay,
-      DefaultScreen(NewQtWidget.xdisplay), @attrList[0]);
+      DefaultScreen(NewQtWidget.xdisplay), @attrList.AttributeList[0]);
     direct:=false;
-    NewQtWidget.glxcontext := glXCreateContext(NewQtWidget.xdisplay,
+    {$IFDEF ModernGL}
+    if GLX_version_1_3(NewQtWidget.xdisplay) then begin
+        //use approach recommended since glX 1.3
+        direct := true;
+        XDisplay := NewQtWidget.xdisplay;//QX11Info_display();
+        ScreenNum := DefaultScreen (XDisplay);
+        AttrList.MajorVersion:=MajorVersion;
+        AttrList.MinorVersion:=MinorVersion;
+        // fill in context flags
+        AttrList.ContextFlags:=0;
+        //if DebugContext then
+        // AttrList.ContextFlags:=Attribs.ContextFlags or GLX_CONTEXT_DEBUG_BIT_ARB;
+        if (MultiSampling > 1) and GLX_ARB_multisample(XDisplay,ScreenNum) then begin
+	   AttrList.MultiSampling:=MultiSampling;
+        end else begin
+	    AttrList.MultiSampling:=0;
+        end;
+        FBConfigsCount:=0;
+        FBConfigs:=glXChooseFBConfig(XDisplay, ScreenNum, @AttrList.AttributeList[0], FBConfigsCount);
+        if FBConfigsCount = 0 then
+	  raise Exception.Create('Could not find FB config');
+
+        // if multisampling is requested try to get a number of sample buffers as
+        // close to the specified number as possible
+        if AttrList.MultiSampling>0 then begin
+	  BestSamples:=0;
+	  for i:=0 to FBConfigsCount-1 do begin
+	        Samples:=0;
+	        glXGetFBConfigAttrib(NewQtWidget.xdisplay, FBConfigs[i], GLX_SAMPLES_ARB, Samples);
+	        if Samples=AttrList.MultiSampling then begin
+		  BestFBConfig:=i;
+		  break;
+	        end else begin
+		  if (Samples>BestSamples) and (Samples<AttrList.MultiSampling) then begin
+		        BestSamples:=Samples;
+		        BestFBConfig:=i;
+		  end;
+	        end;
+	  end;
+          //raise Exception.Create('BestFBConfig '+inttostr(BestFBConfig));
+	  FBConfig := FBConfigs[BestFBConfig];
+        end else begin
+	  { just choose the first FB config from the FBConfigs list.
+	        More involved selection possible. }
+	  FBConfig := FBConfigs^;
+        end;
+        XVInfo:=glXGetVisualFromFBConfig(NewQtWidget.xdisplay, FBConfig);
+        if XVInfo=nil then
+           raise Exception.Create('QT no visual found');
+        if (GLX_ARB_create_context(NewQtWidget.xdisplay, DefaultScreen(NewQtWidget.xdisplay))) and (AttrList.MajorVersion>0) then begin
+		  // install custom X error handler
+		  XSetErrorHandler(@CustomXErrorHandler);
+		  Context3X[0]:=GLX_CONTEXT_MAJOR_VERSION_ARB;
+		  Context3X[1]:=AttrList.MajorVersion;
+		  Context3X[2]:=GLX_CONTEXT_MINOR_VERSION_ARB;
+		  Context3X[3]:=AttrList.MinorVersion;
+		  Context3X[4]:=GLX_CONTEXT_FLAGS_ARB;
+		  Context3X[5]:=AttrList.ContextFlags;
+		  Context3X[6]:=None;
+		  //if (ShareList<>nil) then begin
+		  //	NewQtWidget.glxcontext:=glXCreateContextAttribsARB(NewQtWidget.xdisplay, FBConfig,PrivateShareList^.glxcontext, direct, Context3X);
+		  //end else begin
+		        NewQtWidget.glxcontext:=glXCreateContextAttribsARB(NewQtWidget.xdisplay, FBConfig, Nil, direct, Context3X);
+		  //end;
+                  //raise Exception.Create('key '+inttostr(BestFBConfig));
+		  // restore default error handler
+		  XSetErrorHandler(nil);
+	        end else begin
+		  //if (ShareList<>nil) then begin
+		  //	NewQtWidget.glxcontext:=glXCreateNewContext(NewQtWidget.xdisplay, FBConfig, GLX_RGBA_TYPE,PrivateShareList^.glxcontext, direct)
+		  //end else begin
+		        NewQtWidget.glxcontext:=glXCreateNewContext(NewQtWidget.xdisplay, FBConfig, GLX_RGBA_TYPE, Nil, direct);
+		  //end;
+	        end;
+	        if FBConfigs<>nil then
+		  XFree(FBConfigs);
+
+    end else
+    {$ENDIF}
+            NewQtWidget.glxcontext := glXCreateContext(NewQtWidget.xdisplay,
                                                NewQtWidget.visual, nil, direct);
     NewQtWidget.ref_count := 1;
 
@@ -206,7 +321,7 @@
 
     Result:=HWND(PtrUInt(Pointer(NewQtWidget)));
   finally
-    FreeMem(AttrList);
+    FreeMem(AttrList.AttributeList);
   end;
 end;
 
@@ -275,7 +390,11 @@
   {$IFDEF VerboseMultiSampling}
   debugln(['CreateOpenGLContextAttrList MultiSampling=',MultiSampling]);
   {$ENDIF}
-  UseFBConfig := false; //GLX_version_1_3(GetDefaultXDisplay);
+   {$IFDEF ModernGL}
+  UseFBConfig := GLX_version_1_3(QX11Info_display());
+  {$ELSE}
+  UseFBConfig := false;
+  {$ENDIF}
   Result:=nil;
   CreateList;
   GetMem(Result,SizeOf(integer)*p);

mypatch.diff (7,143 bytes)

Chris Rorden

2018-10-07 21:25

reporter  

lines.zip (52,927 bytes)

Zeljan Rikalo

2018-10-09 19:59

developer   ~0111345

1.This patch looks good, at least now examples and your lines works under Qt4 and Qt5. Qt5 paintdevice floods console with some qdebug messages but it works.
2.Maybe querying samples and samplesBuf should give best fbconfig, not only samples (I've seen such querying in some OpenGL examples).

Andrey Zubarev

2018-10-10 17:20

reporter   ~0111357

This should be in 2.0

Andrey Zubarev

2018-10-10 17:32

reporter   ~0111358

Related to https://bugs.freepascal.org/view.php?id=32498

Zeljan Rikalo

2018-10-11 09:14

developer   ~0111359

I've modified and formatted your patch. Please test if ok.
This issue should stay open because of multisampling. Actually,
I don't know if it's my openGL version (Fedora 25) or my graphics card problem (NVidia). @Home I have Intel graphics and multisampling works w/o problems (but also Fedora 27).

Zeljan Rikalo

2018-10-11 09:14

developer   ~0111360

Last edited: 2018-10-11 09:14

View 2 revisions

Please test, I'll add more stuff today because of Qt5.

Andrey Zubarev

2018-10-11 11:46

reporter   ~0111369

Works good with ubuntu18.04@IntegratedIntel

Zeljan Rikalo

2018-10-11 13:52

developer   ~0111372

@Andrey, does examples/imgui shows valid number of samples in console on your machine (qt4 or/and qt5) ?

Zeljan Rikalo

2018-10-11 13:59

developer   ~0111373

I can confirm that everything works perfect on LinuxMint 19 Cinnamon (qt4 and qt5).

Chris Rorden

2018-10-11 14:09

reporter  

mypatch2.diff (9,117 bytes)
Index: glqtcontext.pas
===================================================================
--- glqtcontext.pas	(revision 59272)
+++ glqtcontext.pas	(working copy)
@@ -12,10 +12,16 @@
 {$mode objfpc}{$H+}
 {$LinkLib GL}
 {$PACKRECORDS C}
-
+{$DEFINE ModernGL}
+//{$DEFINE VerboseMultiSampling}
 interface
 
 uses
+  //  Classes, SysUtils, ctypes, LCLProc, LCLType, X, XUtil, XLib, gl,
+  //InterfaceBase,
+  //glx,
+  //WSLCLClasses,
+  {$IFDEF ModernGL} ctypes,{$ENDIF}
   Classes, SysUtils, Controls, LCLProc, LCLType, X, XUtil, XLib, gl,
   InterfaceBase,
   WSLCLClasses,glx,
@@ -60,6 +66,7 @@
 type
   TGLXContext = pointer;
 
+
 procedure LOpenGLViewport(Handle: HWND; Left, Top, Width, Height: integer);
 procedure LOpenGLSwapBuffers(Handle: HWND);
 function LOpenGLMakeCurrent(Handle: HWND): boolean;
@@ -74,7 +81,7 @@
 procedure LOpenGLDestroyContextInfo(AWinControl: TWinControl);
 function CreateOpenGLContextAttrList(DoubleBuffered: boolean; RGBA: boolean;
              const RedBits, GreenBits, BlueBits, AlphaBits, DepthBits,
-             StencilBits,  AUXBuffers: Cardinal): PInteger;
+             StencilBits,  AUXBuffers, MultiSampling: Cardinal): PInteger;
 
 
 implementation
@@ -168,7 +175,24 @@
   Result := glXMakeCurrent(Widget.xdisplay, 0, nil);
 end;
 
+{$IFDEF ModernGL}
+function CustomXErrorHandler({%H-}para1:PDisplay; para2:PXErrorEvent):cint;cdecl;
+begin
+  if para2^.error_code=8 then begin
+    raise Exception.Create('A BadMatch X error occured. Most likely the requested OpenGL version is invalid.');
+  end;
+  Result:=0;
+end;
+{$ENDIF}
 
+type
+TContextAttribs = record
+  AttributeList: PLongint;
+  MajorVersion: Cardinal;
+  MinorVersion: Cardinal;
+  MultiSampling: Cardinal;
+  ContextFlags: Cardinal;
+end;
 {function LOpenGLCreateContext(AWinControl: TWinControl;
   WSPrivate: TWSPrivateClass; SharedControl: TWinControl;
   DoubleBuffered, RGBA: boolean;
@@ -182,12 +206,28 @@
                           const AParams: TCreateParams): HWND;
 
 var
-  AttrList: PInteger;
+  {$IFDEF ModernGL} { Used with glXCreateContextAttribsARB to select 3.X and above context }
+  Context3X: array [0..6] of Integer;
+  ScreenNum: cint;
+  FBConfig: TGLXFBConfig;
+  FBConfigs: PGLXFBConfig;
+  FBConfigsCount: Integer;
+  i: Integer;
+  Samples: cint;
+  BestSamples: Integer;
+  BestFBConfig: Integer;
+  XVInfo: PXVisualInfo;
+  XDisplay: PDisplay;
+  {$ENDIF}
+  AttrList: TContextAttribs;
   NewQtWidget: TQtGLWidget;
   direct: boolean;
+  {$IFDEF VerboseMultiSampling}
+  samp_buf, visual_id, red_size, blue_size, green_size, alpha_size: integer;
+  {$ENDIF}
 begin
   if WSPrivate=nil then ;
-  AttrList:=CreateOpenGLContextAttrList(DoubleBuffered,RGBA,RedBits,GreenBits,BlueBits,AlphaBits,DepthBits,StencilBits,AUXBuffers);
+  AttrList.AttributeList:=CreateOpenGLContextAttrList(DoubleBuffered,RGBA,RedBits,GreenBits,BlueBits,AlphaBits,DepthBits,StencilBits,AUXBuffers,MultiSampling);
   try
     NewQtWidget:=TQtGLWidget.Create(AWinControl,AParams);
     NewQtWidget.setAttribute(QtWA_PaintOnScreen);
@@ -196,9 +236,97 @@
     NewQtWidget.HasPaint:=true;
     NewQtWidget.xdisplay := QX11Info_display;
     NewQtWidget.visual:=glXChooseVisual(NewQtWidget.xdisplay,
-      DefaultScreen(NewQtWidget.xdisplay), @attrList[0]);
+      DefaultScreen(NewQtWidget.xdisplay), @attrList.AttributeList[0]);
     direct:=false;
-    NewQtWidget.glxcontext := glXCreateContext(NewQtWidget.xdisplay,
+    {$IFDEF ModernGL}
+    if GLX_version_1_3(NewQtWidget.xdisplay) then begin
+        //use approach recommended since glX 1.3
+        direct := true;
+        XDisplay := NewQtWidget.xdisplay;//QX11Info_display();
+        ScreenNum := DefaultScreen(XDisplay);
+        AttrList.MajorVersion:=MajorVersion;
+        AttrList.MinorVersion:=MinorVersion;
+        // fill in context flags
+        AttrList.ContextFlags:=0;
+        //if DebugContext then
+        // AttrList.ContextFlags:=Attribs.ContextFlags or GLX_CONTEXT_DEBUG_BIT_ARB;
+        if (MultiSampling > 1) and GLX_ARB_multisample(XDisplay,ScreenNum) then begin
+	   		AttrList.MultiSampling:=MultiSampling;
+        end else begin
+	    	AttrList.MultiSampling:=0;
+        end;
+        FBConfigsCount:=0;
+        FBConfigs:=glXChooseFBConfig(XDisplay, ScreenNum, @AttrList.AttributeList[0], FBConfigsCount);
+        if FBConfigsCount = 0 then
+	  raise Exception.Create('Could not find FB config');
+        // if multisampling is requested try to get a number of sample buffers as
+        // close to the specified number as possible
+        if AttrList.MultiSampling>0 then begin
+	  BestSamples:=0;
+	  for i:=0 to FBConfigsCount-1 do begin
+	        Samples:=0;
+	        glXGetFBConfigAttrib(XDisplay, FBConfigs[i], GLX_SAMPLES_ARB, Samples);
+	        if Samples=AttrList.MultiSampling then begin
+		  BestFBConfig:=i;
+		  break;
+	        end else begin
+		  if (Samples>BestSamples) and (Samples<AttrList.MultiSampling) then begin
+		        BestSamples:=Samples;
+		        BestFBConfig:=i;
+		  end;
+	        end;
+	  end;
+          //raise Exception.Create('BestFBConfig '+inttostr(BestFBConfig));
+	  FBConfig := FBConfigs[BestFBConfig];
+	  {$IFDEF VerboseMultiSampling}
+            //https://www.opengl.org/discussion_boards/showthread.php/168359-OpenGL-3-x-and-Qt-framework?styleid=12
+            glXGetFBConfigAttrib(XDisplay, FBConfig, GLX_SAMPLE_BUFFERS, samp_buf );
+            glXGetFBConfigAttrib(XDisplay, FBConfig, GLX_SAMPLES, Samples  );
+            glXGetFBConfigAttrib(XDisplay, FBConfig, GLX_VISUAL_ID, visual_id  );
+            glXGetFBConfigAttrib(XDisplay, FBConfig, GLX_RED_SIZE, red_size  );
+            glXGetFBConfigAttrib(XDisplay, FBConfig, GLX_BLUE_SIZE, blue_size  );
+            glXGetFBConfigAttrib(XDisplay, FBConfig, GLX_GREEN_SIZE, green_size  );
+            glXGetFBConfigAttrib(XDisplay, FBConfig, GLX_ALPHA_SIZE, alpha_size  );
+
+            debugln(format('OpenGL fbconfig %d, ID 0x%x, SAMPLE_BUFFERS %d, SAMPLES %d, R%d G%d B%d A%d',
+              [BestFBConfig, visual_id, samp_buf, samples, red_size, blue_size, green_size, alpha_size]));
+          {$ENDIF}
+        end else //if MultiSampling=0 just choose the first FB config
+	  FBConfig := FBConfigs^;
+        XVInfo:=glXGetVisualFromFBConfig(XDisplay, FBConfig);
+        if XVInfo=nil then
+           raise Exception.Create('QT no visual found');
+        if (GLX_ARB_create_context(XDisplay, ScreenNum)) and (AttrList.MajorVersion>0) then begin
+		  // install custom X error handler
+		  XSetErrorHandler(@CustomXErrorHandler);
+		  Context3X[0]:=GLX_CONTEXT_MAJOR_VERSION_ARB;
+		  Context3X[1]:=AttrList.MajorVersion;
+		  Context3X[2]:=GLX_CONTEXT_MINOR_VERSION_ARB;
+		  Context3X[3]:=AttrList.MinorVersion;
+		  Context3X[4]:=GLX_CONTEXT_FLAGS_ARB;
+		  Context3X[5]:=AttrList.ContextFlags;
+		  Context3X[6]:=None;
+		  //if (ShareList<>nil) then begin
+		  //	NewQtWidget.glxcontext:=glXCreateContextAttribsARB(NewQtWidget.xdisplay, FBConfig,PrivateShareList^.glxcontext, direct, Context3X);
+		  //end else begin
+		        NewQtWidget.glxcontext:=glXCreateContextAttribsARB(XDisplay, FBConfig, Nil, direct, Context3X);
+		  //end;
+                  //raise Exception.Create('key '+inttostr(BestFBConfig));
+		  // restore default error handler
+		  XSetErrorHandler(nil);
+	        end else begin
+		  //if (ShareList<>nil) then begin
+		  //	NewQtWidget.glxcontext:=glXCreateNewContext(NewQtWidget.xdisplay, FBConfig, GLX_RGBA_TYPE,PrivateShareList^.glxcontext, direct)
+		  //end else begin
+		        NewQtWidget.glxcontext:=glXCreateNewContext(XDisplay, FBConfig, GLX_RGBA_TYPE, Nil, direct);
+		  //end;
+	        end;
+	        if FBConfigs<>nil then
+		  XFree(FBConfigs);
+
+    end else
+    {$ENDIF}
+            NewQtWidget.glxcontext := glXCreateContext(NewQtWidget.xdisplay,
                                                NewQtWidget.visual, nil, direct);
     NewQtWidget.ref_count := 1;
 
@@ -206,7 +334,7 @@
 
     Result:=HWND(PtrUInt(Pointer(NewQtWidget)));
   finally
-    FreeMem(AttrList);
+    FreeMem(AttrList.AttributeList);
   end;
 end;
 
@@ -218,7 +346,7 @@
 
 function CreateOpenGLContextAttrList(DoubleBuffered: boolean; RGBA: boolean;
   const RedBits, GreenBits, BlueBits, AlphaBits, DepthBits, StencilBits,
-  AUXBuffers: Cardinal): PInteger;
+  AUXBuffers, MultiSampling: Cardinal): PInteger;
 var
   p: integer;
   UseFBConfig: boolean;
@@ -267,7 +395,10 @@
     begin
       Add(GLX_AUX_BUFFERS);  Add(AUXBuffers);
     end;
-
+	if MultiSampling>0 then begin
+      Add(GLX_SAMPLE_BUFFERS);  Add(1);
+      Add(GLX_SAMPLES);  Add(MultiSampling);
+	end;
     Add(0); { 0 = X.None (be careful: GLX_NONE is something different) }
   end;
 
@@ -275,7 +406,11 @@
   {$IFDEF VerboseMultiSampling}
   debugln(['CreateOpenGLContextAttrList MultiSampling=',MultiSampling]);
   {$ENDIF}
-  UseFBConfig := false; //GLX_version_1_3(GetDefaultXDisplay);
+   {$IFDEF ModernGL}
+  UseFBConfig := GLX_version_1_3(QX11Info_display());
+  {$ELSE}
+  UseFBConfig := false;
+  {$ENDIF}
   Result:=nil;
   CreateList;
   GetMem(Result,SizeOf(integer)*p);
mypatch2.diff (9,117 bytes)

Chris Rorden

2018-10-11 14:12

reporter   ~0111374

Zeljan-
  Can you test my second patch - this also supports both modern OpenGL and Multisampling when compiled with QT5. The new patch extends the output provided if compiled with the {$DEFINE VerboseMultiSampling} directive. It also explicitly includes the desired multi-sampling in the attribute list, as suggested by many web sites.

Zeljan Rikalo

2018-10-11 17:34

developer   ~0111376

@Chris, I've found that everything works find with first patch + my changes, only NVidia GLX have problem.
I've found solution here
https://us.download.nvidia.com/XFree86/Linux-x86/173.14.12/README/chapter-11.html
and it works for my NVidia card.
export __GL_FSAA_MODE=5 ./testopenglapplication
says that multisampling works.

Of course I'll check if it works with your second patch and unexported __GL_FSAA_MODE

Zeljan Rikalo

2018-10-11 17:43

developer   ~0111377

Also, please create patch against current trunk since it's pretty hard now to pick up changes for multisampling. Note that I've already tested with adding GLX_SAMPLES and other stuff in attributes but result was same all the time.

Zeljan Rikalo

2018-10-11 18:11

developer   ~0111378

Just found in nvidia docs that nvidia-settings --query=fsaa --verbose lists possible FSAA values which can be exported via __GL_FSAA_MODE env variable and then multisampling works with nvidia glx. IMO, this issue is complete and should be resolved if you agree and everything works for you.

Chris Rorden

2018-10-11 18:50

reporter  

qtPatch3.diff (3,260 bytes)
Index: components/opengl/glqtcontext.pas
===================================================================
--- components/opengl/glqtcontext.pas	(revision 59290)
+++ components/opengl/glqtcontext.pas	(working copy)
@@ -13,6 +13,7 @@
 {$LinkLib GL}
 {$PACKRECORDS C}
 {$DEFINE ModernGL}
+//{$DEFINE VerboseMultiSampling}
 interface
 
 uses
@@ -80,7 +81,7 @@
 procedure LOpenGLDestroyContextInfo(AWinControl: TWinControl);
 function CreateOpenGLContextAttrList(DoubleBuffered: boolean; RGBA: boolean;
              const RedBits, GreenBits, BlueBits, AlphaBits, DepthBits,
-             StencilBits,  AUXBuffers: Cardinal): PInteger;
+             StencilBits,  AUXBuffers, MultiSampling: Cardinal): PInteger;
 
 
 implementation
@@ -290,9 +291,12 @@
   AttrList: TContextAttribs;
   NewQtWidget: TQtGLWidget;
   direct: boolean;
+  {$IFDEF VerboseMultiSampling}
+  samp_buf, visual_id, red_size, blue_size, green_size, alpha_size: integer;
+  {$ENDIF}
 begin
   if WSPrivate=nil then ;
-  AttrList.AttributeList := CreateOpenGLContextAttrList(DoubleBuffered,RGBA,RedBits,GreenBits,BlueBits,AlphaBits,DepthBits,StencilBits,AUXBuffers);
+  AttrList.AttributeList := CreateOpenGLContextAttrList(DoubleBuffered,RGBA,RedBits,GreenBits,BlueBits,AlphaBits,DepthBits,StencilBits,AUXBuffers, MultiSampling);
   try
     NewQtWidget:=TQtGLWidget.Create(AWinControl,AParams);
     NewQtWidget.setAttribute(QtWA_PaintOnScreen);
@@ -354,6 +358,18 @@
         end;
           //raise Exception.Create('BestFBConfig '+inttostr(BestFBConfig));
 	      FBConfig := FBConfigs[BestFBConfig];
+	      {$IFDEF VerboseMultiSampling}
+	      //HTTPS://WWW.OPENGL.ORG/DISCUSSION_BOARDS/SHOWTHREAD.PHP/168359-OPENGL-3-X-AND-QT-FRAMEWORK?STYLEID=12
+	      GLXGETFBCONFIGATTRIB(XDISPLAY, FBCONFIG, GLX_SAMPLE_BUFFERS, SAMP_BUF);
+	      GLXGETFBCONFIGATTRIB(XDISPLAY, FBCONFIG, GLX_SAMPLES, SAMPLES);
+	      GLXGETFBCONFIGATTRIB(XDISPLAY, FBCONFIG, GLX_VISUAL_ID, VISUAL_ID);
+	      GLXGETFBCONFIGATTRIB(XDISPLAY, FBCONFIG, GLX_RED_SIZE, RED_SIZE);
+	      GLXGETFBCONFIGATTRIB(XDISPLAY, FBCONFIG, GLX_BLUE_SIZE, BLUE_SIZE);
+	      GLXGETFBCONFIGATTRIB(XDISPLAY, FBCONFIG, GLX_GREEN_SIZE, GREEN_SIZE);
+	      GLXGETFBCONFIGATTRIB(XDISPLAY, FBCONFIG, GLX_ALPHA_SIZE, ALPHA_SIZE);
+	      DEBUGLN(FORMAT('OPENGL FBCONFIG %D, ID 0X%X, SAMPLE_BUFFERS %D, SAMPLES %D, R%D G%D B%D A%D',
+              [BESTFBCONFIG, VISUAL_ID, SAMP_BUF, SAMPLES, RED_SIZE, BLUE_SIZE, GREEN_SIZE, ALPHA_SIZE]));
+          {$ENDIF}
       end else
       begin
   	    { just choose the first FB config from the FBConfigs list.
@@ -418,7 +434,7 @@
 
 function CreateOpenGLContextAttrList(DoubleBuffered: boolean; RGBA: boolean;
   const RedBits, GreenBits, BlueBits, AlphaBits, DepthBits, StencilBits,
-  AUXBuffers: Cardinal): PInteger;
+  AUXBuffers, MultiSampling: Cardinal): PInteger;
 var
   p: integer;
   UseFBConfig: boolean;
@@ -468,7 +484,12 @@
     begin
       Add(GLX_AUX_BUFFERS);  Add(AUXBuffers);
     end;
-
+    {$IFDEF ModernGL}
+	if MultiSampling>0 then begin
+      Add(GLX_SAMPLE_BUFFERS);  Add(1);
+      Add(GLX_SAMPLES);  Add(MultiSampling);
+	end;
+    {$ENDIF}
     Add(0); { 0 = X.None (be careful: GLX_NONE is something different) }
   end;
 
@@ -490,3 +511,4 @@
 
 end.
 
+
qtPatch3.diff (3,260 bytes)

Chris Rorden

2018-10-11 18:54

reporter   ~0111379

I have uploaded a third patch which applies my patch 2 to the changes you applied to trunk. Again, there are only two small changes:
 1.) If compiled with {$DEFINE VerboseMultiSampling} it provides debug details regarding the selected framebuffer. By default this is not enabled.
 2.) I did add the extra attributes. It is possible that these help some situations, they do seem to be part of the OpenGL specification, they seem to have no influence (for better or worse) on the systems I tested.

Thanks for your work on this. I think this patch is useful, but it is not critical. I leave it to your discretion regarding whether to include it. Once you are happy with the code, please set this issue to fixed and I will close it.

Zeljan Rikalo

2018-10-11 20:10

developer   ~0111380

Added GLX_SAMPLES_BUFFER & GLX_SAMPLES to the attributes.
Notes for NVIDIA & Multisampling are still valid - env variable __GL_FSAA_MODE must be exported with valid value.
Test and close if ok.

Zeljan Rikalo

2018-10-11 21:48

developer   ~0111382

In the meantime I've tested MRICROgl and it works here on Qt4 and Qt5 (Fedora 27 64bit, Intel graphics) :)

Issue History

Date Modified Username Field Change
2018-10-07 21:22 Chris Rorden New Issue
2018-10-07 21:22 Chris Rorden File Added: mypatch.diff
2018-10-07 21:25 Chris Rorden File Added: lines.zip
2018-10-08 12:38 Zeljan Rikalo Assigned To => Zeljan Rikalo
2018-10-08 12:38 Zeljan Rikalo Status new => assigned
2018-10-09 19:59 Zeljan Rikalo Note Added: 0111345
2018-10-10 17:20 Andrey Zubarev Note Added: 0111357
2018-10-10 17:32 Andrey Zubarev Note Added: 0111358
2018-10-11 09:11 Zeljan Rikalo Relationship added related to 0032498
2018-10-11 09:14 Zeljan Rikalo Fixed in Revision => 59285
2018-10-11 09:14 Zeljan Rikalo LazTarget => -
2018-10-11 09:14 Zeljan Rikalo Widgetset QT => QT, QT5
2018-10-11 09:14 Zeljan Rikalo Note Added: 0111359
2018-10-11 09:14 Zeljan Rikalo Status assigned => resolved
2018-10-11 09:14 Zeljan Rikalo Resolution open => fixed
2018-10-11 09:14 Zeljan Rikalo Note Added: 0111360
2018-10-11 09:14 Zeljan Rikalo Status resolved => feedback
2018-10-11 09:14 Zeljan Rikalo Note Edited: 0111360 View Revisions
2018-10-11 11:46 Andrey Zubarev Note Added: 0111369
2018-10-11 13:52 Zeljan Rikalo Note Added: 0111372
2018-10-11 13:59 Zeljan Rikalo Note Added: 0111373
2018-10-11 13:59 Zeljan Rikalo Status feedback => confirmed
2018-10-11 14:09 Chris Rorden File Added: mypatch2.diff
2018-10-11 14:12 Chris Rorden Note Added: 0111374
2018-10-11 17:34 Zeljan Rikalo Note Added: 0111376
2018-10-11 17:34 Zeljan Rikalo Status confirmed => feedback
2018-10-11 17:43 Zeljan Rikalo Note Added: 0111377
2018-10-11 18:11 Zeljan Rikalo Note Added: 0111378
2018-10-11 18:50 Chris Rorden File Added: qtPatch3.diff
2018-10-11 18:54 Chris Rorden Note Added: 0111379
2018-10-11 18:54 Chris Rorden Status feedback => assigned
2018-10-11 20:10 Zeljan Rikalo Fixed in Revision 59285 => 59285,59293
2018-10-11 20:10 Zeljan Rikalo Note Added: 0111380
2018-10-11 20:10 Zeljan Rikalo Status assigned => resolved
2018-10-11 21:48 Zeljan Rikalo Note Added: 0111382
2018-10-11 23:11 Chris Rorden Status resolved => closed