Bug 136514 - [OpenGL] Support multisampling in GLCanvas on Windows
Summary: [OpenGL] Support multisampling in GLCanvas on Windows
Status: NEW
Alias: None
Product: Platform
Classification: Eclipse Project
Component: SWT (show other bugs)
Version: 3.2   Edit
Hardware: PC Windows XP
: P3 enhancement with 6 votes (vote)
Target Milestone: ---   Edit
Assignee: Billy Biggs CLA
QA Contact:
URL:
Whiteboard:
Keywords:
: 393215 (view as bug list)
Depends on:
Blocks:
 
Reported: 2006-04-12 22:04 EDT by Bradley Smith CLA
Modified: 2013-07-14 10:13 EDT (History)
7 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Bradley Smith CLA 2006-04-12 22:04:21 EDT
Although the GLData class contains samples and sampleBuffers fields, they are not currently used in the GLCanvas class on Windows. The following code is from the GLCanvas.java for Windows:

//FIXME - use wglChoosePixelFormatARB
// if (data.sampleBuffers > 0) {
// wglAttrib [pos++] = WGL.WGL_SAMPLE_BUFFERS_ARB;
// wglAttrib [pos++] = data.sampleBuffers;
// }
// if (data.samples > 0) {
// wglAttrib [pos++] = WGL.WGL_SAMPLES_ARB;
// wglAttrib [pos++] = data.samples;
// }
Comment 1 Ulf Holm Nielsen CLA 2008-01-28 03:23:25 EST
Any tips on how I would go about fixing this? Is there any specific reason why it is not implemented? 
Comment 2 zik CLA 2010-05-05 17:31:44 EDT
How to get the function wglChoosePixelFormatARB ?
I think in using WGL.wglGetProcAddress("wglChoosePixelFormatARB");
(or something like this)
It will return a pointer on the function.

Do you have any idea how to do this ?
Comment 3 Wade Walker CLA 2011-01-28 16:11:21 EST
Would you guys accept a patch for this functionality? I can try to contribute one if you can integrate it.

This would be a nice enhancement, and would help JOGL 2 work better with SWT's GLCanvas (instead of having to use the one from AWT).
Comment 4 Carlo Salinari CLA 2011-02-07 04:01:02 EST
Wade please go ahead if you can. The only chance of having this enhancement integrated is to actually have a working patch here in bugzilla.
Comment 5 Wade Walker CLA 2011-02-07 09:56:34 EST
Last weekend I got SWT building successfully (both the JAR and the DLLs) on Windows, so now I just need to try making the fix. I'll keep you posted on progress.
Comment 6 Wade Walker CLA 2011-03-19 17:00:42 EDT
After some investigation, it looks like it would be easier to add a new SWT GLCanvas to JOGL 2 than it would be to add multisampling to SWT's current canvas. There's a lot of code for managing ARB extensions and such that's already present in JOGL, but would have to be added to SWT.

Sven Gothel at JogAmp has already done a proof of concept of this. Details are available on the JOGL enhancement request at https://jogamp.org/bugzilla/show_bug.cgi?id=484.
Comment 7 Carlo Salinari CLA 2011-03-19 18:42:40 EDT
I think we should emphasize the fact that there is a much wider issue related to GLCanvas than that of not being able to use multisampling under Windows.

The matter is that the current GLCanvas implementation isn't aware of the ARB Extensions mechanism. This makes impossible to initialize and use contexts supporting the new OpenGL standards (3 and 4), besides not allowing access to useful extensions from legacy OpenGL contexts (the multisampling case).

The "business case" behind this, as I see it, is that eclipse will lose appeal as a platform to developers of 3D applications (data visualization, modeling, simulation  etc.) if they are going to be relegated to use the old (pre 2.1) OpenGL API.

Perhaps a new, more comprehensive bugzilla-issue should stem from this one, addressing the need of re-thinking SWT's support for OpenGL, and possibly coordinating with the JOGL guys who already have all this stuff figured out and working.
Comment 8 Jesús Zazueta CLA 2012-11-03 15:17:23 EDT
*** Bug 393215 has been marked as a duplicate of this bug. ***
Comment 9 Jesús Zazueta CLA 2012-11-03 15:29:20 EDT
Hello everyone.

I just went through most of the discussion in this bug.

From what I can read, the main issue is finding a better way to initialize GLCanvas and OpenGL's extension mechanism, which JOGAMP has already done if I 'm not mistaken.

However, the approach is still specific to JOGL2 (again, I could be wrong).

So (before/in case) the LWJGL people or any other framework would also want to try and define their own OpenGL initialization mechanism on SWT, why not then redefine SWT's GLCanvas as an interface?

After all, it is still the OpenGL binding implementation's responsibility to correctly initialize and deal with (partly of course) the native platform.

Does this make sense? Or is the idea naive?

Thanks!
Comment 10 Florent Masson CLA 2013-07-14 10:13:27 EDT
Hello,

I faced the issue described here, and thanks to the information provided, I developped some code to allow GLCanvas to manage multisampling.
The highest supported value lower or equal than data.samples is used, e.g if you card has 4x and you want 8x, 4x will be used anyway. If multisampling is not supported, it will not be activated.

The only problem is that it requires JNA for the native call (recompiling the swt native libraries was too complex for me), so I doubt it can be integrated as is in SWT, but anyone familiar with SWT native libraries should be able to adapt easily.

I provide the source code as a reference to anyone wanting a workaround or implement in SWT :

In GLVancas class (constants)
	private static final int WGL_NUMBER_PIXEL_FORMATS_ARB = 0x2000, WGL_DRAW_TO_WINDOW_ARB = 0x2001, WGL_DRAW_TO_BITMAP_ARB = 0x2002,
			WGL_ACCELERATION_ARB = 0x2003, WGL_NEED_PALETTE_ARB = 0x2004, WGL_NEED_SYSTEM_PALETTE_ARB = 0x2005, WGL_SWAP_LAYER_BUFFERS_ARB = 0x2006,
			WGL_SWAP_METHOD_ARB = 0x2007, WGL_NUMBER_OVERLAYS_ARB = 0x2008, WGL_NUMBER_UNDERLAYS_ARB = 0x2009, WGL_TRANSPARENT_ARB = 0x200A,
			WGL_TRANSPARENT_RED_VALUE_ARB = 0x2037, WGL_TRANSPARENT_GREEN_VALUE_ARB = 0x2038, WGL_TRANSPARENT_BLUE_VALUE_ARB = 0x2039,
			WGL_TRANSPARENT_ALPHA_VALUE_ARB = 0x203A, WGL_TRANSPARENT_INDEX_VALUE_ARB = 0x203B, WGL_SHARE_DEPTH_ARB = 0x200C, WGL_SHARE_STENCIL_ARB = 0x200D,
			WGL_SHARE_ACCUM_ARB = 0x200E, WGL_SUPPORT_GDI_ARB = 0x200F, WGL_SUPPORT_OPENGL_ARB = 0x2010, WGL_DOUBLE_BUFFER_ARB = 0x2011,
			WGL_STEREO_ARB = 0x2012, WGL_PIXEL_TYPE_ARB = 0x2013, WGL_COLOR_BITS_ARB = 0x2014, WGL_RED_BITS_ARB = 0x2015, WGL_RED_SHIFT_ARB = 0x2016,
			WGL_GREEN_BITS_ARB = 0x2017, WGL_GREEN_SHIFT_ARB = 0x2018, WGL_BLUE_BITS_ARB = 0x2019, WGL_BLUE_SHIFT_ARB = 0x201A, WGL_ALPHA_BITS_ARB = 0x201B,
			WGL_ALPHA_SHIFT_ARB = 0x201C, WGL_ACCUM_BITS_ARB = 0x201D, WGL_ACCUM_RED_BITS_ARB = 0x201E, WGL_ACCUM_GREEN_BITS_ARB = 0x201F,
			WGL_ACCUM_BLUE_BITS_ARB = 0x2020, WGL_ACCUM_ALPHA_BITS_ARB = 0x2021, WGL_DEPTH_BITS_ARB = 0x2022, WGL_STENCIL_BITS_ARB = 0x2023,
			WGL_AUX_BUFFERS_ARB = 0x2024,

			WGL_NO_ACCELERATION_ARB = 0x2025, WGL_GENERIC_ACCELERATION_ARB = 0x2026, WGL_FULL_ACCELERATION_ARB = 0x2027,

			WGL_SWAP_EXCHANGE_ARB = 0x2028, WGL_SWAP_COPY_ARB = 0x2029, WGL_SWAP_UNDEFINED_ARB = 0x202A,

			WGL_TYPE_RGBA_ARB = 0x202B, WGL_TYPE_COLORINDEX_ARB = 0x202C, WGL_SAMPLE_BUFFERS_ARB = 0x2041, WGL_SAMPLES_ARB = 0x2042;;


And in place of the //FIXME code :


		pixelFormat = 0;
		Canvas dummycanvas = new Canvas(parent, checkStyle(parent, style));
		long /* int */hDCdummy = OS.GetDC(dummycanvas.handle);
		pixelFormat = WGL.ChoosePixelFormat(hDCdummy, pfd);
		if (pixelFormat == 0 || !WGL.SetPixelFormat(hDCdummy, pixelFormat, pfd)) {
			OS.ReleaseDC(dummycanvas.handle, hDCdummy);
			dispose();
			SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
		}
		long contextdummy = WGL.wglCreateContext(hDCdummy);
		if (contextdummy == 0) {
			OS.ReleaseDC(dummycanvas.handle, hDCdummy);
			SWT.error(SWT.ERROR_NO_HANDLES);
		}
		WGL.wglMakeCurrent(hDCdummy, contextdummy);

		byte[] funcname = "wglChoosePixelFormatARB".getBytes();
		long addr = WGL.wglGetProcAddress(funcname);
		if (addr != 0) {
			Function f = Function.getFunction(new Pointer(addr));

			int divider = 1;
			Boolean res;
			int numFormats;
			ByteBuffer piFormats = ByteBuffer.allocateDirect(Integer.SIZE / 8);
			piFormats.order(java.nio.ByteOrder.LITTLE_ENDIAN);
			ByteBuffer nNumFormats = ByteBuffer.allocateDirect(Integer.SIZE / 8);
			nNumFormats.order(java.nio.ByteOrder.LITTLE_ENDIAN);
			do {
				// These Attributes Are The Bits We Want To Test For In Our Sample
				// Everything Is Pretty Standard, The Only One We Want To
				// Really Focus On Is The SAMPLE BUFFERS ARB And WGL SAMPLES
				// These Two Are Going To Do The Main Testing For Whether Or Not
				// We Support Multisampling On This Hardware
				int iAttributes[] = { WGL_DRAW_TO_WINDOW_ARB, GL11.GL_TRUE, WGL_SUPPORT_OPENGL_ARB, GL11.GL_TRUE, WGL_DOUBLE_BUFFER_ARB, GL11.GL_TRUE,
						WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB, WGL_COLOR_BITS_ARB, 32, WGL_DEPTH_BITS_ARB, 24, WGL_STENCIL_BITS_ARB, 8,

						WGL_SAMPLE_BUFFERS_ARB, data.sampleBuffers, WGL_SAMPLES_ARB, data.samples / divider,

						WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB, 0, 0 };
				piFormats.clear();
				nNumFormats.clear();
				Object[] args = { hDCdummy, iAttributes, null, 1, piFormats, nNumFormats };
				// BOOL wglChoosePixelFormatARB( HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT
				// *nNumFormats);
				res = (Boolean) f.invoke(Boolean.class, args);
				numFormats = nNumFormats.getInt();
				divider *= 2;
			} while ((!res || numFormats == 0) && (divider < data.samples));
			if (res && numFormats > 0) {
				// sets the new pixel format
				pixelFormat = piFormats.getInt();
				// WGL.DescribePixelFormat(hDC, pixelFormat, PIXELFORMATDESCRIPTOR.sizeof, pfd);
			}
		}
		WGL.wglMakeCurrent(hDCdummy, 0);
		WGL.wglDeleteContext(contextdummy);
		OS.ReleaseDC(dummycanvas.handle, hDCdummy);
		dummycanvas.dispose();

Feel free to contact me for any details