SetPixelFormat() fails on canvases

BlitzMax Forums/OpenGL Module/SetPixelFormat() fails on canvases

JoshK(Posted 2006) [#1]
The windows command SetPixelFormat() fails when used on a Canvas gadget. It works correctly on a panel gadget. Why is this significant?

-Canvas gadgets generate GADGET_PAINT events. Panels no not. Therefore, only a canvas can tell you if another window has been dragged over the viewport (and that the viewport needs to be redrawn).

-SetPixelFormat() is necessary to change color depth, antialias mode, and stencil settings. You can't just rely on a pixel format chosen internally by Blitz.

SetPixelFormat can only be used once on any hdc. After that, the gadget/control must be recreated for a new SetPixelFormat to be called. Presumably, Blitz sets the pixel format internally when a canvas is created. Subsequent calls to set the pixel format of the canvas' hDC will therefore fail. The solution would be to add an optional flag to the CreateCanvas() function, which skips setting the pixel format, allowing the user to set their own.


H&K(Posted 2006) [#2]
well... Can you change the pixel colour depth at all? Are you saying you can change it on a Panel? (Stupid question, cos you are)

I dont think this is a bug, the Cavas needs to be the same format as the window, but the panel doesnt, because it is drawn onto a canvas and so its format is converted on drawing. (But im not good at gui at all, do only shout a little bit if Im wrong)


skidracer(Posted 2006) [#3]
Use the flags parameter with your initial call to SetGraphicsDriver to control the properties of the context created with CanvasGraphics.

Casting the result of CanvasGraphics to TGLGraphics will give you access to the context, which I assume you can use for more messing about.


JoshK(Posted 2006) [#4]
I edited my original post. SetPixelFormat() can only be called once on any dc. After that, you have to create a new window and get the dc. You cannot call SetPixelFormat() twice on any dc. For example, to change antialias modes, you have to destroy the viewport panel, create a new one, and set the pixel format with the new antialias mode. I am guessing that by the time I get the handle of a canvas, Blitz has already internally set the pixel format, disallowing me to set it again.

By the way, to add AntiAliasing to Blitz GL graphics, you just add these values when you call wglChoosePixelFormat(), where antialiasmode is 0,2,4,8 or 16:
WGL_SAMPLE_BUFFERS_ARB,GL_TRUE,WGL_SAMPLES_ARB,antialiasmode


JoshK(Posted 2006) [#5]
All I have to do is add an antialias flag to the graphics module. Open the file glgraphics.win32.c and find the flags at the beginning, and make them look like this:
enum{
	_BACKBUFFER=	0x2,
	_ALPHABUFFER=	0x4,
	_DEPTHBUFFER=	0x8,
	_STENCILBUFFER=	0x10,
	_ACCUMBUFFER=	0x20,
	_ANTIALIAS2X=	0x40,
	_ANTIALIAS4X=	0x80,
	_ANTIALIAS8X=	0x100,
	_ANTIALIAS16X=	0x200,
};


Now anywhere the code says ChoosePixelFormat(), we want to use wglChoosePixelFormatARB().

wglChoosePixelFormatARB is an extension. You have to retrieve the function pointer with wglGetProcAddress(). Here is an example of another extensio file being called in the same source file:
typedef BOOL (APIENTRY * WGLSWAPINTERVALEXT) (int);

static int _setSwapInterval( int n ){
	WGLSWAPINTERVALEXT 	wglSwapIntervalEXT=(WGLSWAPINTERVALEXT)wglGetProcAddress("wglSwapIntervalEXT");
	if( wglSwapIntervalEXT ) wglSwapIntervalEXT( n );
}


I need to convert the antialias flags into a multisample value, but I can't make sense enough of C gibberish to do that. In basic it would just be this:
If (_ANTIALIAS2X & flags) multisample=2
If (_ANTIALIAS4X & flags) multisample=4
If (_ANTIALIAS8X & flags) multisample=8
If (_ANTIALIAS16X & flags) multisample=16


Finally, the function wglChoosePixelFormatARB has additional parameters. In my own code, it gets called like this:
wglChoosePixelFormatARB(hDC,[WGL_DRAW_TO_WINDOW_ARB,GL_TRUE,WGL_SUPPORT_OPENGL_ARB,GL_TRUE,WGL_ACCELERATION_ARB,WGL_FULL_ACCELERATION_ARB,WGL_COLOR_BITS_ARB,24,WGL_ALPHA_BITS_ARB,8,WGL_DEPTH_BITS_ARB,16,WGL_DOUBLE_BUFFER_ARB,GL_TRUE,WGL_SAMPLE_BUFFERS_ARB,GL_TRUE,WGL_SAMPLES_ARB,multisample,0,0],[0.0,0.0],1,Varptr lPixelFormat,Varptr numFormats)


So there you have it. Pretty easy to set up, but my limited knowledge of C prevents me from doing it. If this were set up correctly, Max GL graphics could have an optional antialias flag when initialized.