glBlitFramebufferEXT and AA set by the Graphics card settings

Hi,

I have a viewport created with a PixelFormat without multisampling (in theory).



            pfd = new PixelFormatDescriptor();


            OperatingSystem osInfo = System.Environment.OSVersion;

         pfd.dwFlags   = (int) (pixelFormat.DRAW_TO_WINDOW | pixelFormat.SUPPORT_OPENGL | pixelFormat.DOUBLEBUFFER);


                if (osInfo.Version.Major >= 6)


                    pfd.dwFlags = pfd.dwFlags | (int)pixelFormat.SUPPORT_COMPOSITION;


                pfd.PixelType = (int) pixelTypes.TYPE_RGBA;
                pfd.ColorBits = 24;
                pfd.AlphaBits = 8;
                pfd.DepthBits = 24;


                nPixelFormat = Windows.ChoosePixelFormat(theHdc, pfd);

                bool valid = Windows.SetPixelFormat(theHdc, nPixelFormat, pfd);

                theHrc = wglCreateContext(theHdc);                    

                wglMakeCurrent(hdc, theHrc);

I create a Multisample FBO with a number of samples defined by my application



            rbColor = gl.GenRenderbuffersEXT();
            gl.BindRenderbufferEXT(gl.RENDERBUFFER_EXT, rbColor);
            gl.RenderbufferStorageMultisampleEXT(gl.RENDERBUFFER_EXT, samples, gl.RGB, Width, Height);


            rbDepth = gl.GenRenderbuffersEXT();
            gl.BindRenderbufferEXT(gl.RENDERBUFFER_EXT, rbDepth);
            gl.RenderbufferStorageMultisampleEXT(gl.RENDERBUFFER_EXT, samples, gl.DEPTH_COMPONENT, Width, Height);


            fbo = gl.GenFramebuffersEXT();
            FrameBufferObject.Enable(fbo);
            gl.FramebufferRenderbufferEXT(gl.FRAMEBUFFER_EXT, gl.COLOR_ATTACHMENT0_EXT, gl.RENDERBUFFER_EXT, rbColor);
            gl.FramebufferRenderbufferEXT(gl.FRAMEBUFFER_EXT, gl.DEPTH_ATTACHMENT_EXT, gl.RENDERBUFFER_EXT, rbDepth);


            Status = gl.CheckFramebufferStatusEXT(gl.FRAMEBUFFER_EXT);


            CheckFboStatus(Status);


Then I draw my scene on this FBO and I copy it (only the color bits) to the Framebuffer with glBlitFramebufferEXT:


            gl.BindFramebufferEXT(gl.READ_FRAMEBUFFER_EXT, fbo);
            gl.BindFramebufferEXT(gl.DRAW_FRAMEBUFFER_EXT, 0);


            gl.BlitFramebufferEXT(0, 0, width, height, 0, 0, width, height, gl.COLOR_BUFFER_BIT, gl.NEAREST);


            gl.BindFramebufferEXT(gl.READ_FRAMEBUFFER_EXT, 0);
            gl.BindFramebufferEXT(gl.DRAW_FRAMEBUFFER_EXT, 0);  

Now, if the user overrides the Antialiasing settings on the “Graphics Card Settings” page and sets a number of samples different from the one used by my internal FBO, I get a GL_INVALID_OPERATION after the call to glBlitFramebufferEXT.

If instead the user sets the number of Samples equal to the one I use internally for the FBO, or if he leaves the Antialiasing settings to “Application Controlled” it works fine.

My guess is that when the option to override the application settings is set, the Framebuffer is craeted with the number of samples specified by the graphics card settings page and copying between buffers with different samples number gives the error.

Can anybody help?

The solution is to detect that the default framebuffer is a multisampled framebuffer. If it is, create your FBO buffers with the same number of samples. That way, you can successfully blit between them.

First, query GL_SAMPLE_BUFFERS (while the default framebuffer is bound); if it’s 0, then the default framebuffer is not multisampled. If it’s 1, then it is multisampled. To get the number of samples, query GL_SAMPLES, then use that count to create your multisampled framebuffer.

Yeah that works!
Thank you very much Alfonse.

It seems I was wrong: the copy from my FBO created with the same number of samples as the main framebuffer gives GL_Invalid_Operation. :frowning:

I don’t know why it seemed to work 2 weeks ago…

But if I copy from my multisample FBO to a non-multisample FBO and then to the main multisample framebuffer it works.

Is it really necessary to do this double copy, or should the Blit work directly between the two multisample FBO?

The documentation for glBlitFrameBuffer reports:

[LEFT]GL_INVALID_OPERATION is generated if mask contains GL_COLOR_BUFFER_BIT and any of the following conditions hold:

[ul]
[li]The read buffer contains fixed-point or floating-point values and any draw buffer contains neither fixed-point nor floating-point values.[/li]
[li]The read buffer contains unsigned integer values and any draw buffer does not contain unsigned integer values.[/li]
[li]The read buffer contains signed integer values and any draw buffer does not contain signed integer values.[/li]> [/ul]
[/LEFT]

But I don’t quite understand it: how do I know what kind of data my buffer contains?

If SAMPLE_BUFFERS for either the read framebuffer or draw framebuffer is
greater than zero, no copy is performed and an INVALID_OPERATION error is
generated if the dimensions of the source and destination rectangles provided to
BlitFramebuffer are not identical, or if the formats of the read and draw framebuffers
are not identical.

This is from the spec, not ext extension, but it applies there as wel iirc. Right now you dont know what is the format of your rbo - use sized internal format.

But I don’t quite understand it: how do I know what kind of data my buffer contains?

You know that from the format of your attachemnts.

Also note that GL_RGB (or GL_RGB8 which would likely result from it) is not required renderbuffer format.

Hi,

the size of the FBO and the Renderbuffer is the same.

My renderBuffer attached to the FBO is created with internal format GL_RGB.

No its not. RGB is not an internal format. Lots of functions take ‘base internal formats’ for whatever reason, but driver has to resolve this to actual internal format. (ie RGB can be either RGB8 or RGB16 or whatever)

Last part of what i quoted is important - default fbo needs to have the same format as yours (and you usually do have alpha component on it).

So how do I create a renderBuffer with the same internal format of the framebuffer?

Funny thing is - it may not be possible :slight_smile: If pixelformat advertises components that are shifted in a way that default framebuffer is BGRA then it cant be done, since GL doesnt expose such internal formats.

Theory aside, try putting GL_RGBA8 in your renderbuffer storage.

I tried but with no success

Am I the only one having this problem when blitting a multisample fbo on a renderbuffer that is forced to multisample by the graphics card settings?

I think I’ll have to use the blit from my MSAA fbo to a non-MSAA fbo and then to the main framebuffer, since this way it seems to always work…

p.s. I noticed that the problem happens also if I create the main renderBuffer with the same number of samples of my FBO and try to blit directly between the two, not only if I force the MSAA from the Graphics Card settings.

2 things to try:

gl.RGB -> gl.RGBA // or maybe BGRA8 . This will generally match the format of the main FBO, which on Windows usually is BGRA8. (unless running in 16-bit mode, there’s it’s 565, blue at LSB).

Resolve your framebuffer into an FBO that uses textures instead of renderbuffers. Renderbuffers and the default FBO (which consists of color + depth/stencil renderbuffers) can be a subject to driver-overrides, it seems. Textures generally are left intact by the driver.

It’s worked for me when the number of MSAA samples is the same, but IIRC it’s documented as not supported if the number of samples is different and both != 1. Which vendor/drivers? Ilian’s got a good point about making sure the sample formats are exactly the same.

Ok,

since I’m having too many problems using Multisample FBOs I decided to take another approach.

I draw normally on the main multisample framebuffer.

When I need to capture the image of the framebuffer, I blit the FrameBuffer to a FBO without multisampling and read it on a texture (I enable the FBO, set the glReadBuffer to gl.COLOR_ATTACHMENT0_EXT and I use glCopyTexSubImage2D to copy it on the texture).

Problem: on the ATI card the texture is flipped vertically, on NVidia card it is fine. O_O

Why???

I also found this topic (glBlitFramebuffer(EXT) coordinates - OpenGL: Advanced Coding - Khronos Forums) that seems related to the same problem…

Another false success.

Copying the Multisample Framebuffer to a non-multisample FBO and then reading the texture from that gives the same image on a Geforce 8600M GS but gives a different image on a Quadro 600 (there’s a noticeable difference between the texture read from the FBO and the scene drawn on the framebuffer… :frowning:

How can I fix it once and for all???

Just to clarify, what is the exact problem you’re trying to solve? Is it that you are trying to get exactly the same visual result on each GPU+driver combination regardless of the AA setting of the system default framebuffer (where results may differ across different GPU+driver combos)? Or are you trying to get the exact same visual result across all possible combinations of GPU+driver+sysFBres (where results cannot differ across different GPU+driver combos)? The 1st may be possible, the 2nd probably not.

Have you found no way to override the default system FB format? For instance, nuke that default, set your own overrides, and create a new window? What OS is this?

Also, have you tried MSAA rendering to off-screen MS FBO, not to system FB. Then resolve. Then just blit to system FB?

I think it might be time to post a standalone GLUT test program illustrating your problem that we can run/test/hack/repost.

Hi,

I want to read the scene rendered on an OpenGL window with AA into a texture so that I can use that for quick repaints of my scene when doing some mouse operations, and I want the texture to be exactly what I see in the framebuffer so the user won’t notice this “repaint” trick.

I’m using a scene with only lines, so the difference in the AA rendering is quite noticeable.

Yes, I created a multisample FBO and a single sample FBO, drawn my scene on the first one, then blitted from the first to the second one and then from the second to the framebuffer.

That worked, but then I found problems when the multisample was forced by the driver settings and it also became very slow if the number of AA samples was high so I decided to quit this approach and try a simpler one: copy the Multisample Framebuffer to a non-multisample FBO, read the texture from that and then draw a screen aligned quad with that texture for my quick repaint.

That works on a Geforce 8600M GS but not on a Quadro 600 (the texture is a bit different from the rendered scene, and the same happens if I blit from the system FB to my FBO and then back on the system FB).

I’m on a Windows 7, 64 bit system.

It’s not easy for me to create a standalone test program to reproduce it… :frowning:

Hi,
I created a sample that reproduces the problem:
It creates a multisample openGL window and draws some lines (you can move/zoom/rotate with the mouse)

Pressing the ‘C’ key I call the

void CaptureTexture()

function that copies the framebuffer to an FBO and reads the texture from it, and then the
successive draws are done by the

void DrawQuadWithTexture()

that simply draws a quad with the mapped texture.

On the NVidia card you can see a difference between using the texture and doing a standard DrawFrame().

Pressing ‘C’ again switches back to the standard drawing.

Here is the code for the 2 files needed:

main.cpp


#if !defined(WIN32_LEAN_AND_MEAN)
#define WIN32_LEAN_AND_MEAN
#endif


#include <windows.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <cmath>
#include <sstream>
#include <stdexcept>
#include <string>




#if defined(_DEBUG)
#include <crtdbg.h>
#endif


#include "bitmap.h"
#include "gl_font.h"
#include "WGL_ARB_multisample.h"
#include "glext.h"


//-----------------------------------------------------------------------------
// Constants.
//-----------------------------------------------------------------------------


#define APP_TITLE "OpenGL Anti-Aliasing Demo"


// Windows Vista compositing support.
#if !defined(PFD_SUPPORT_COMPOSITION)
#define PFD_SUPPORT_COMPOSITION 0x00008000
#endif


// GL_EXT_texture_filter_anisotropic
#define GL_TEXTURE_MAX_ANISOTROPY_EXT       0x84FE
#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT   0x84FF


// GL_SGIS_generate_mipmap
#define GL_GENERATE_MIPMAP_SGIS             0x8191


#define GL_COLOR_ATTACHMENT0_EXT			0x8CE0
#define GL_DRAW_FRAMEBUFFER_EXT				0x8CA9
#define GL_READ_FRAMEBUFFER_EXT				0x8CA8
#define GL_FRAMEBUFFER_EXT					0x8D40
#define GL_RENDERBUFFER_EXT					0x8D41


static PFNGLRENDERBUFFERSTORAGEEXTPROC		glRenderbufferStorageEXT	;
static PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC	glFramebufferRenderbufferEXT;
static PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC	glCheckFramebufferStatusEXT	;
static PFNGLGENRENDERBUFFERSEXTPROC			glGenRenderbuffersEXT		;
static PFNGLBINDFRAMEBUFFEREXTPROC			glBindFramebufferEXT		;
static PFNGLBLITFRAMEBUFFEREXTPROC			glBlitFramebufferEXT		;
static PFNGLGENFRAMEBUFFERSEXTPROC			glGenFramebuffersEXT;
static PFNGLBINDRENDERBUFFEREXTPROC			glBindRenderbufferEXT;


GLuint capturedTexture = 0;
GLuint fbo;
GLuint rbColor;
GLuint renderBuffer;


int texWidth;
int texHeight;




#define CAMERA_FOVY  45.0f
#define CAMERA_ZFAR  10.0f
#define CAMERA_ZNEAR 0.1f


#define MOUSE_ORBIT_SPEED 0.30f     // 0 = SLOWEST, 1 = FASTEST
#define MOUSE_DOLLY_SPEED 0.02f     // same as above...but much more sensitive
#define MOUSE_TRACK_SPEED 0.005f    // same as above...but much more sensitive








//-----------------------------------------------------------------------------
// Globals.
//-----------------------------------------------------------------------------


HWND                g_hWnd;
HDC                 g_hDC;
HGLRC               g_hRC;
HINSTANCE           g_hInstance;
int                 g_framesPerSecond;
int                 g_windowWidth;
int                 g_windowHeight;
int                 g_maxAnisotrophy;
float               g_heading;
float               g_pitch;
float               g_cameraPos[3] = {0.0f, 0.0f, 4.0f};
float               g_targetPos[3];
bool                g_isFullScreen;
bool                g_hasFocus;
bool                g_enableVerticalSync;
bool                g_enableAlphaToCoverage;
bool                g_supportsGenerateMipMap;
bool                g_displayHelp;
GLuint              g_decalMap;


bool				UseCopyTexture;


//-----------------------------------------------------------------------------
// Functions Prototypes.
//-----------------------------------------------------------------------------


void    Cleanup();
void    CleanupApp();
HWND    CreateAppWindow(const WNDCLASSEX &wcl, const char *pszTitle);
void    DrawFrame();
void    DrawText();
void    EnableVerticalSync(bool enableVerticalSync);
bool    ExtensionSupported(const char *pszExtensionName);
float   GetElapsedTimeInSeconds();
bool    Init();
void    InitApp();
void    InitGL();
void    Log(const char *pszMessage);
void    ProcessMouseInput(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
void    SetProcessorAffinity();
void    ToggleFullScreen();
void    UpdateFrame(float elapsedTimeSec);
void    UpdateFrameRate(float elapsedTimeSec);
LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);




//-----------------------------------------------------------------------------
// Functions.
//-----------------------------------------------------------------------------


void DrawQuadWithTexture()
{
	// Draw a screen Waud with the texture
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glViewport(0, 0, g_windowWidth, g_windowHeight);	
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(0, g_windowWidth, 0, g_windowHeight, -1, 1);	
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();	
	glDisable(GL_LIGHTING);
	//glDisable(GL_DEPTH_TEST);	
	glPolygonMode(GL_FRONT, GL_FILL);	
	glEnable(GL_TEXTURE_2D);


	glBindTexture(GL_TEXTURE_2D, capturedTexture);
	glColor3f(1, 1, 1);


	double wRatio = (double)g_windowWidth / texWidth;
	double hRatio = (double)g_windowHeight / texHeight;
    
	glBegin(GL_QUADS);
    
	glTexCoord2d(0, 0);
    glVertex2i(0, 0);


    glTexCoord2d(wRatio, 0);
    glVertex2i(g_windowWidth, 0);


    glTexCoord2d(wRatio, hRatio);
    glVertex2i(g_windowWidth, g_windowHeight);


    glTexCoord2d(0, hRatio);
    glVertex2i(0, g_windowHeight);


    glEnd();


	glBindTexture(GL_TEXTURE_2D, 0);
	glEnable(GL_DEPTH_TEST);


	DrawText();	
}




int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
#if defined _DEBUG
    _CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF);
    _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
    _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
#endif


    MSG msg = {0};
    WNDCLASSEX wcl = {0};


    wcl.cbSize = sizeof(wcl);
    wcl.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
    wcl.lpfnWndProc = WindowProc;
    wcl.cbClsExtra = 0;
    wcl.cbWndExtra = 0;
    wcl.hInstance = g_hInstance = hInstance;
    wcl.hIcon = LoadIcon(0, IDI_APPLICATION);
    wcl.hCursor = LoadCursor(0, IDC_ARROW);
    wcl.hbrBackground = 0;
    wcl.lpszMenuName = 0;
    wcl.lpszClassName = "GLWindowClass";
    wcl.hIconSm = 0;


    if (!RegisterClassEx(&wcl))
        return 0;


    g_hWnd = CreateAppWindow(wcl, APP_TITLE);


    if (g_hWnd)
    {
        SetProcessorAffinity();


        if (Init())
        {
            ShowWindow(g_hWnd, nShowCmd);
            UpdateWindow(g_hWnd);


            while (true)
            {
                while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
                {
                    if (msg.message == WM_QUIT)
                        break;


                    TranslateMessage(&msg);
                    DispatchMessage(&msg);
                }


                if (msg.message == WM_QUIT)
                    break;


                if (g_hasFocus)
                {
                    UpdateFrame(GetElapsedTimeInSeconds());


					if (UseCopyTexture)
						DrawQuadWithTexture();
					else
						DrawFrame();
                    SwapBuffers(g_hDC);
                }
                else
                {
                    WaitMessage();
                }
            }
        }


        Cleanup();
        UnregisterClass(wcl.lpszClassName, hInstance);
    }


    return static_cast<int>(msg.wParam);
}




void CaptureTexture()
{
	if (capturedTexture == 0)
	{
		// Initialize Texture and FBO
		texWidth = pow(2, ceil(log10 ((double)g_windowWidth)  / log10((double)2)));
		texHeight = pow(2, ceil(log10((double)g_windowHeight) / log10((double)2)));


		glGenTextures(1, &capturedTexture);
        glBindTexture(  GL_TEXTURE_2D, capturedTexture);
        glTexImage2D(   GL_TEXTURE_2D, 0, GL_RGBA8, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
		glBindTexture(  GL_TEXTURE_2D, 0);
		
		glGenFramebuffersEXT(1, &fbo);
        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);


        glGenRenderbuffersEXT(1, &rbColor);
        glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rbColor);
        glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA, g_windowWidth, g_windowHeight);
        glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, rbColor);


        int _status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
	}


	DrawFrame();


	// Copy Frambuffer to FBO
	glReadBuffer(GL_BACK);
	glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fbo);
	glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);


    glBlitFramebufferEXT(0, 0, g_windowWidth, g_windowHeight, 0, 0, g_windowWidth, g_windowHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
    glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
    glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);


	// Copy FrameBuffer to the texture
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
	glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
	glBindTexture(GL_TEXTURE_2D, capturedTexture);
	glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, g_windowWidth, g_windowHeight);	


	glBindTexture(GL_TEXTURE_2D, 0);
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
	glReadBuffer(GL_BACK);
}


LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    case WM_ACTIVATE:
        switch (wParam)
        {
        default:
            break;


        case WA_ACTIVE:
        case WA_CLICKACTIVE:
            g_hasFocus = true;
            break;


        case WA_INACTIVE:
            if (g_isFullScreen)
                ShowWindow(hWnd, SW_MINIMIZE);
            g_hasFocus = false;
            break;
        }
        break;


    case WM_CHAR:
        switch (static_cast<int>(wParam))
        {
        case VK_ESCAPE:
            PostMessage(hWnd, WM_CLOSE, 0, 0);
            break;


        case VK_SPACE:
            if (g_enableAlphaToCoverage = !g_enableAlphaToCoverage)
                glEnable(GL_MULTISAMPLE_ARB);
            else
                glDisable(GL_MULTISAMPLE_ARB);
            break;


		case 'c':
		case 'C':
			UseCopyTexture = !UseCopyTexture;
			if (UseCopyTexture)
				CaptureTexture();
						
			break;


        case 'h':
        case 'H':
            g_displayHelp = !g_displayHelp;
            break;


        case 'v':
        case 'V':
            EnableVerticalSync(!g_enableVerticalSync);
            break;


        default:
            break;
        }
        break;


    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;


    case WM_SIZE:
        g_windowWidth = static_cast<int>(LOWORD(lParam));
        g_windowHeight = static_cast<int>(HIWORD(lParam));
        break;


    case WM_SYSKEYDOWN:
        if (wParam == VK_RETURN)
            ToggleFullScreen();
        break;


    default:
        ProcessMouseInput(hWnd, msg, wParam, lParam);
        break;
    }


    return DefWindowProc(hWnd, msg, wParam, lParam);
}


void Cleanup()
{
    CleanupApp();


    if (g_hDC)
    {
        if (g_hRC)
        {
            wglMakeCurrent(g_hDC, 0);
            wglDeleteContext(g_hRC);
            g_hRC = 0;
        }


        ReleaseDC(g_hWnd, g_hDC);
        g_hDC = 0;
    }
}


void CleanupApp()
{
    if (g_decalMap)
    {
        glDeleteTextures(1, &g_decalMap);
        g_decalMap = 0;
    }
}


HWND CreateAppWindow(const WNDCLASSEX &wcl, const char *pszTitle)
{
    // Create a window that is centered on the desktop. It's exactly 1/4 the
    // size of the desktop. Don't allow it to be resized.


    DWORD wndExStyle = WS_EX_OVERLAPPEDWINDOW;
    DWORD wndStyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU |
                     WS_MINIMIZEBOX | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;


    HWND hWnd = CreateWindowEx(wndExStyle, wcl.lpszClassName, pszTitle,
                    wndStyle, 0, 0, 0, 0, 0, 0, wcl.hInstance, 0);


    if (hWnd)
    {
        int screenWidth = GetSystemMetrics(SM_CXSCREEN);
        int screenHeight = GetSystemMetrics(SM_CYSCREEN);
        int halfScreenWidth = screenWidth / 2;
        int halfScreenHeight = screenHeight / 2;
        int left = (screenWidth - halfScreenWidth) / 2;
        int top = (screenHeight - halfScreenHeight) / 2;
        RECT rc = {0};


        SetRect(&rc, left, top, left + halfScreenWidth, top + halfScreenHeight);
        AdjustWindowRectEx(&rc, wndStyle, FALSE, wndExStyle);
        MoveWindow(hWnd, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, TRUE);


        GetClientRect(hWnd, &rc);
        g_windowWidth = rc.right - rc.left;
        g_windowHeight = rc.bottom - rc.top;
    }


    return hWnd;
}


void DrawFrame()
{
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_TEXTURE_2D);


    // Setup view port.
    glViewport(0, 0, g_windowWidth, g_windowHeight);
    glClearColor(0.3f, 0.5f, 0.9f, 0.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


    // Setup projection matrix.
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(CAMERA_FOVY,
        static_cast<float>(g_windowWidth) / static_cast<float>(g_windowHeight),
        CAMERA_ZNEAR, CAMERA_ZFAR);


    // Setup view matrix.
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(g_cameraPos[0], g_cameraPos[1], g_cameraPos[2],
        g_targetPos[0], g_targetPos[1], g_targetPos[2],
        0.0f, 1.0f, 0.0f);


    // Rotate the scene using the mouse.
    glRotatef(g_pitch, 1.0f, 0.0f, 0.0f);
    glRotatef(g_heading, 0.0f, 1.0f, 0.0f);


	glDisable(GL_TEXTURE_2D);
	glColor3f(0,0,0);
	glBegin(GL_LINE_STRIP);
	     
	for (int xInc = 0; xInc <10; xInc++)
		for (int yInc = 0; yInc <10; yInc++)
			for (int zInc = 0; zInc <10; zInc++)
			{
				glVertex3f(xInc/10.0, yInc/10.0, zInc/10.0);				
			}
	glEnd();


    // Display text.
    DrawText();
}


void DrawText()
{
    static RECT rcClient;
    static char szBuffer[512];


    if (g_displayHelp)
    {
	if (UseCopyTexture)


        sprintf(szBuffer,
            "Left mouse click and drag to track the camera
"
            "Middle mouse click and drag to dolly the camera
"
            "Right mouse click and drag to orbit the camera

"
            "Press V to enable/disable vertical sync
"
            "Press SPACE to enable/disable alpha to coverage sampling
"
            "Press ALT + ENTER to toggle full screen
"
            "Press ESC to exit

"
            "Press H to hide help
"
			"DRAWING THE CAPTURED TEXTURE");


			else
			sprintf(szBuffer,
            "Left mouse click and drag to track the camera
"
            "Middle mouse click and drag to dolly the camera
"
            "Right mouse click and drag to orbit the camera

"
            "Press V to enable/disable vertical sync
"
            "Press SPACE to enable/disable alpha to coverage sampling
"
            "Press ALT + ENTER to toggle full screen
"
            "Press ESC to exit

"
            "Press H to hide help");
		


    }
    else
    {
	if (UseCopyTexture)


        sprintf(szBuffer,
            "FPS: %d
"
            "Vertical sync: %s
"
            "Anti-aliasing: %s
"
            "Anisotropic filtering: %dx
"
            "Alpha to coverage: %s

"
            "Press H to display help
"
			"DRAWING THE CAPTURED TEXTURE",
            g_framesPerSecond,
            ((g_enableVerticalSync) ? "enabled" : "disabled"),
            GetAntiAliasingPixelFormatString(),
            g_maxAnisotrophy,
            ((g_enableAlphaToCoverage) ? "enabled" : "disabled"));


			else




        sprintf(szBuffer,
            "FPS: %d
"
            "Vertical sync: %s
"
            "Anti-aliasing: %s
"
            "Anisotropic filtering: %dx
"
            "Alpha to coverage: %s

"
            "Press H to display help",
            g_framesPerSecond,
            ((g_enableVerticalSync) ? "enabled" : "disabled"),
            GetAntiAliasingPixelFormatString(),
            g_maxAnisotrophy,
            ((g_enableAlphaToCoverage) ? "enabled" : "disabled"));
    }


}


void EnableVerticalSync(bool enableVerticalSync)
{
    // WGL_EXT_swap_control.


    typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC)(GLint);


    static PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT =
        reinterpret_cast<PFNWGLSWAPINTERVALEXTPROC>(
        wglGetProcAddress("wglSwapIntervalEXT"));


    if (wglSwapIntervalEXT)
    {
        wglSwapIntervalEXT(enableVerticalSync ? 1 : 0);
        g_enableVerticalSync = enableVerticalSync;
    }
}


bool ExtensionSupported(const char *pszExtensionName)
{
    static const char *pszGLExtensions = 0;
    static const char *pszWGLExtensions = 0;


    if (!pszGLExtensions)
        pszGLExtensions = reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS));


    if (!pszWGLExtensions)
    {
        // WGL_ARB_extensions_string.


        typedef const char *(WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC)(HDC);


        PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB =
            reinterpret_cast<PFNWGLGETEXTENSIONSSTRINGARBPROC>(
            wglGetProcAddress("wglGetExtensionsStringARB"));


        if (wglGetExtensionsStringARB)
            pszWGLExtensions = wglGetExtensionsStringARB(g_hDC);
    }


    if (!strstr(pszGLExtensions, pszExtensionName))
    {
        if (!strstr(pszWGLExtensions, pszExtensionName))
            return false;
    }


    return true;
}


float GetElapsedTimeInSeconds()
{
    // Returns the elapsed time (in seconds) since the last time this function
    // was called. This elaborate setup is to guard against large spikes in
    // the time returned by QueryPerformanceCounter().


    static const int MAX_SAMPLE_COUNT = 50;


    static float frameTimes[MAX_SAMPLE_COUNT];
    static float timeScale = 0.0f;
    static float actualElapsedTimeSec = 0.0f;
    static INT64 freq = 0;
    static INT64 lastTime = 0;
    static int sampleCount = 0;
    static bool initialized = false;


    INT64 time = 0;
    float elapsedTimeSec = 0.0f;


    if (!initialized)
    {
        initialized = true;
        QueryPerformanceFrequency(reinterpret_cast<LARGE_INTEGER*>(&freq));
        QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER*>(&lastTime));
        timeScale = 1.0f / freq;
    }


    QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER*>(&time));
    elapsedTimeSec = (time - lastTime) * timeScale;
    lastTime = time;


    if (fabsf(elapsedTimeSec - actualElapsedTimeSec) < 1.0f)
    {
        memmove(&frameTimes[1], frameTimes, sizeof(frameTimes) - sizeof(frameTimes[0]));
        frameTimes[0] = elapsedTimeSec;


        if (sampleCount < MAX_SAMPLE_COUNT)
            ++sampleCount;
    }


    actualElapsedTimeSec = 0.0f;


    for (int i = 0; i < sampleCount; ++i)
        actualElapsedTimeSec += frameTimes[i];


    if (sampleCount > 0)
        actualElapsedTimeSec /= sampleCount;


    return actualElapsedTimeSec;
}


bool Init()
{
    try
    {
        InitGL();
        InitApp();
        return true;
    }
    catch (const std::exception &e)
    {
        std::ostringstream msg;


        msg << "Application initialization failed!" << std::endl << std::endl;
        msg << e.what();


        Log(msg.str().c_str());
        return false;
    }
}


void InitApp()
{    
}


void InitGL()
{
    if (!(g_hDC = GetDC(g_hWnd)))
        throw std::runtime_error("GetDC() failed.");


    int pf = 0;
    PIXELFORMATDESCRIPTOR pfd = {0};
    OSVERSIONINFO osvi = {0};


    pfd.nSize = sizeof(pfd);
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cColorBits = 24;
    pfd.cDepthBits = 16;
    pfd.iLayerType = PFD_MAIN_PLANE;


    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);


    if (!GetVersionEx(&osvi))
        throw std::runtime_error("GetVersionEx() failed.");


    // When running under Windows Vista or later support desktop composition.
    if (osvi.dwMajorVersion > 6 || (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion >= 0))
        pfd.dwFlags |=  PFD_SUPPORT_COMPOSITION;


    // Setting up your Windows application to use multisample anti-aliasing
    // (MSAA) is platform dependent. The actual process varies between
    // operating systems. Under Windows we use the WGL_ARB_pixel_format and the
    // WGL_ARB_multisample OpenGL extensions to enumerate an extended pixel
    // format that supports MSAA.
    //
    // For further details check out the source code for these functions
    // (found in the WGL_ARB_multisample.cpp file):
    //  ChooseBestAntiAliasingPixelFormat()
    //  ChooseAntiAliasingPixelFormat()


    // Select a pixel format supporting the highest quality MSAA.
    ChooseBestAntiAliasingPixelFormat(pf);
    g_enableAlphaToCoverage = true;


	UseCopyTexture = false;
    
    // Here's an example of how to select a pixel format that supports a
    // specific number of samples. Here we have chosen 4x MSAA.
    if (false)
    {
        ChooseAntiAliasingPixelFormat(pf, 4);


        if (pf)
            g_enableAlphaToCoverage	 = true;
    }


    // It's always a good idea to fall back to a standard pixel format in case
    // MSAA is not supported. Most modern video cards should support some form
    // of MSAA - one exception is older embedded video cards.
    if (!pf)
    {
        pf = ChoosePixelFormat(g_hDC, &pfd);
        g_enableAlphaToCoverage = false;
    }


    if (!SetPixelFormat(g_hDC, pf, &pfd))
        throw std::runtime_error("SetPixelFormat() failed.");


    if (!(g_hRC = wglCreateContext(g_hDC)))
        throw std::runtime_error("wglCreateContext() failed.");


    if (!wglMakeCurrent(g_hDC, g_hRC))
        throw std::runtime_error("wglMakeCurrent() failed.");


    EnableVerticalSync(false);


    // Check for GL_EXT_texture_filter_anisotropic support.
    if (ExtensionSupported("GL_EXT_texture_filter_anisotropic"))
        glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &g_maxAnisotrophy);
    else
        g_maxAnisotrophy = 1;


    // Check for GL_SGIS_generate_mipmap support.
    if (ExtensionSupported("GL_SGIS_generate_mipmap"))
        g_supportsGenerateMipMap = true;
    else
        g_supportsGenerateMipMap = false;




	glRenderbufferStorageEXT		= (PFNGLRENDERBUFFERSTORAGEEXTPROC)wglGetProcAddress("glRenderbufferStorageEXT");
	glFramebufferRenderbufferEXT	= (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)wglGetProcAddress("glFramebufferRenderbufferEXT");
	glCheckFramebufferStatusEXT		= (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)wglGetProcAddress("glCheckFramebufferStatusEXT");
	glGenRenderbuffersEXT			= (PFNGLGENRENDERBUFFERSEXTPROC)wglGetProcAddress("glGenRenderbuffersEXT");
	glBindFramebufferEXT			= (PFNGLBINDFRAMEBUFFEREXTPROC)wglGetProcAddress("glBindFramebufferEXT");
	glBlitFramebufferEXT			= (PFNGLBLITFRAMEBUFFEREXTPROC)wglGetProcAddress("glBlitFramebufferEXT");
	glGenFramebuffersEXT			= (PFNGLGENFRAMEBUFFERSEXTPROC)wglGetProcAddress("glGenFramebuffersEXT");
	glBindRenderbufferEXT			= (PFNGLBINDRENDERBUFFEREXTPROC)wglGetProcAddress("glBindRenderbufferEXT");
}




void Log(const char *pszMessage)
{
    MessageBox(0, pszMessage, "Error", MB_ICONSTOP);
}


void ProcessMouseInput(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    // Use the left mouse button to track the camera.
    // Use the middle mouse button to dolly the camera.
    // Use the right mouse button to orbit the camera.


    enum CameraMode {CAMERA_NONE, CAMERA_TRACK, CAMERA_DOLLY, CAMERA_ORBIT};


    static CameraMode cameraMode = CAMERA_NONE;
    static POINT ptMousePrev = {0};
    static POINT ptMouseCurrent = {0};
    static int mouseButtonsDown = 0;
    static float dx = 0.0f;
    static float dy = 0.0f;


    switch (msg)
    {
    case WM_LBUTTONDOWN:
        cameraMode = CAMERA_TRACK;
        ++mouseButtonsDown;
        SetCapture(hWnd);
        ptMousePrev.x = static_cast<int>(static_cast<short>(LOWORD(lParam)));
        ptMousePrev.y = static_cast<int>(static_cast<short>(HIWORD(lParam)));
        ClientToScreen(hWnd, &ptMousePrev);
        break;


    case WM_RBUTTONDOWN:
        cameraMode = CAMERA_ORBIT;
        ++mouseButtonsDown;
        SetCapture(hWnd);
        ptMousePrev.x = static_cast<int>(static_cast<short>(LOWORD(lParam)));
        ptMousePrev.y = static_cast<int>(static_cast<short>(HIWORD(lParam)));
        ClientToScreen(hWnd, &ptMousePrev);
        break;


    case WM_MBUTTONDOWN:
        cameraMode = CAMERA_DOLLY;
        ++mouseButtonsDown;
        SetCapture(hWnd);
        ptMousePrev.x = static_cast<int>(static_cast<short>(LOWORD(lParam)));
        ptMousePrev.y = static_cast<int>(static_cast<short>(HIWORD(lParam)));
        ClientToScreen(hWnd, &ptMousePrev);
        break;


    case WM_MOUSEMOVE:
        ptMouseCurrent.x = static_cast<int>(static_cast<short>(LOWORD(lParam)));
        ptMouseCurrent.y = static_cast<int>(static_cast<short>(HIWORD(lParam)));
        ClientToScreen(hWnd, &ptMouseCurrent);


        switch (cameraMode)
        {
        case CAMERA_TRACK:
            dx = static_cast<float>(ptMouseCurrent.x - ptMousePrev.x);
            dx *= MOUSE_TRACK_SPEED;


            dy = static_cast<float>(ptMouseCurrent.y - ptMousePrev.y);
            dy *= MOUSE_TRACK_SPEED;


            g_cameraPos[0] -= dx;
            g_cameraPos[1] += dy;


            g_targetPos[0] -= dx;
            g_targetPos[1] += dy;


            break;


        case CAMERA_DOLLY:
            dy = static_cast<float>(ptMouseCurrent.y - ptMousePrev.y);
            dy *= MOUSE_DOLLY_SPEED;


            g_cameraPos[2] += dy;


            if (g_cameraPos[2] > (CAMERA_ZFAR - 2.0f))
                g_cameraPos[2] = CAMERA_ZFAR - 2.0f;


            if (g_cameraPos[2] < (CAMERA_ZNEAR + 1.0f))
                g_cameraPos[2] = CAMERA_ZNEAR + 1.0f;


            break;


        case CAMERA_ORBIT:
            dx = static_cast<float>(ptMouseCurrent.x - ptMousePrev.x);
            dx *= MOUSE_ORBIT_SPEED;


            dy = static_cast<float>(ptMouseCurrent.y - ptMousePrev.y);
            dy *= MOUSE_ORBIT_SPEED;


            g_heading += dx;
            g_pitch += dy;


            if (g_pitch > 90.0f)
                g_pitch = 90.0f;


            if (g_pitch < -90.0f)
                g_pitch = -90.0f;


            break;
        }


        ptMousePrev.x = ptMouseCurrent.x;
        ptMousePrev.y = ptMouseCurrent.y;
        break;


    case WM_LBUTTONUP:
    case WM_RBUTTONUP:
    case WM_MBUTTONUP:
        if (--mouseButtonsDown <= 0)
        {
            mouseButtonsDown = 0;
            cameraMode = CAMERA_NONE;
            ReleaseCapture();
        }
        else
        {
            if (wParam & MK_LBUTTON)
                cameraMode = CAMERA_TRACK;
            else if (wParam & MK_RBUTTON)
                cameraMode = CAMERA_ORBIT;
            else if (wParam & MK_MBUTTON)
                cameraMode = CAMERA_DOLLY;
        }
        break;


    default:
        break;
    }
}


void SetProcessorAffinity()
{
    // Assign the current thread to one processor. This ensures that timing
    // code runs on only one processor, and will not suffer any ill effects
    // from power management.
    //
    // Based on DXUTSetProcessorAffinity() function from the DXUT framework.


    DWORD_PTR dwProcessAffinityMask = 0;
    DWORD_PTR dwSystemAffinityMask = 0;
    HANDLE hCurrentProcess = GetCurrentProcess();


    if (!GetProcessAffinityMask(hCurrentProcess, &dwProcessAffinityMask, &dwSystemAffinityMask))
        return;


    if (dwProcessAffinityMask)
    {
        // Find the lowest processor that our process is allowed to run against.


        DWORD_PTR dwAffinityMask = (dwProcessAffinityMask & ((~dwProcessAffinityMask) + 1));


        // Set this as the processor that our thread must always run against.
        // This must be a subset of the process affinity mask.


        HANDLE hCurrentThread = GetCurrentThread();


        if (hCurrentThread != INVALID_HANDLE_VALUE)
        {
            SetThreadAffinityMask(hCurrentThread, dwAffinityMask);
            CloseHandle(hCurrentThread);
        }
    }


    CloseHandle(hCurrentProcess);
}


void ToggleFullScreen()
{
    static DWORD savedExStyle;
    static DWORD savedStyle;
    static RECT rcSaved;


    g_isFullScreen = !g_isFullScreen;


    if (g_isFullScreen)
    {
        // Moving to full screen mode.


        savedExStyle = GetWindowLong(g_hWnd, GWL_EXSTYLE);
        savedStyle = GetWindowLong(g_hWnd, GWL_STYLE);
        GetWindowRect(g_hWnd, &rcSaved);


        SetWindowLong(g_hWnd, GWL_EXSTYLE, 0);
        SetWindowLong(g_hWnd, GWL_STYLE, WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
        SetWindowPos(g_hWnd, HWND_TOPMOST, 0, 0, 0, 0,
            SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED | SWP_SHOWWINDOW);


        g_windowWidth = GetSystemMetrics(SM_CXSCREEN);
        g_windowHeight = GetSystemMetrics(SM_CYSCREEN);


        SetWindowPos(g_hWnd, HWND_TOPMOST, 0, 0,
            g_windowWidth, g_windowHeight, SWP_SHOWWINDOW);
    }
    else
    {
        // Moving back to windowed mode.


        SetWindowLong(g_hWnd, GWL_EXSTYLE, savedExStyle);
        SetWindowLong(g_hWnd, GWL_STYLE, savedStyle);
        SetWindowPos(g_hWnd, HWND_NOTOPMOST, 0, 0, 0, 0,
            SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED | SWP_SHOWWINDOW);


        g_windowWidth = rcSaved.right - rcSaved.left;
        g_windowHeight = rcSaved.bottom - rcSaved.top;


        SetWindowPos(g_hWnd, HWND_NOTOPMOST, rcSaved.left, rcSaved.top,
            g_windowWidth, g_windowHeight, SWP_SHOWWINDOW);
    }
}


void UpdateFrame(float elapsedTimeSec)
{
    UpdateFrameRate(elapsedTimeSec);
}


void UpdateFrameRate(float elapsedTimeSec)
{
    static float accumTimeSec = 0.0f;
    static int frames = 0;


    accumTimeSec += elapsedTimeSec;


    if (accumTimeSec > 1.0f)
    {
        g_framesPerSecond = frames;


        frames = 0;
        accumTimeSec = 0.0f;
    }
    else
    {
        ++frames;
    }
}

wgl_Arb_multisample.cpp


//-----------------------------------------------------------------------------
// Copyright (c) 2006-2008 dhpoware. All Rights Reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------


#include <cassert>
#include <cstdio>
#include <cstring>
#include "WGL_ARB_multisample.h"


namespace
{
    WNDCLASSEX g_wcl;
    HWND g_hWnd;
    HDC g_hDC;
    HGLRC g_hRC;
    char g_szAAPixelFormat[32];


    LRESULT CALLBACK DummyGLWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        switch (msg)
        {
        case WM_CREATE:
            if (!(g_hDC = GetDC(hWnd)))
                return -1;
            break;


        case WM_DESTROY:
            if (g_hDC)
            {
                if (g_hRC)
                {
                    wglMakeCurrent(g_hDC, 0);
                    wglDeleteContext(g_hRC);
                    g_hRC = 0;
                }


                ReleaseDC(hWnd, g_hDC);
                g_hDC = 0;
            }


            PostQuitMessage(0);
            return 0;


        default:
            break;
        }


        return DefWindowProc(hWnd, msg, wParam, lParam);
    }


    bool CreateDummyGLWindow()
    {
        g_wcl.cbSize = sizeof(g_wcl);
        g_wcl.style = CS_OWNDC;
        g_wcl.lpfnWndProc = DummyGLWndProc;
        g_wcl.hInstance = reinterpret_cast<HINSTANCE>(GetModuleHandle(0));
        g_wcl.lpszClassName = "DummyGLWindowClass";


        if (!RegisterClassEx(&g_wcl))
            return false;


        g_hWnd = CreateWindow(g_wcl.lpszClassName, "", WS_OVERLAPPEDWINDOW,
                    0, 0, 0, 0, 0, 0, g_wcl.hInstance, 0);


        if (!g_hWnd)
            return false;


        PIXELFORMATDESCRIPTOR pfd = {0};


        pfd.nSize = sizeof(pfd);
        pfd.nVersion = 1;
        pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
        pfd.iPixelType = PFD_TYPE_RGBA;
        pfd.cColorBits = 24;
        pfd.cDepthBits = 16;
        pfd.iLayerType = PFD_MAIN_PLANE;


        int pf = ChoosePixelFormat(g_hDC, &pfd);


        if (!SetPixelFormat(g_hDC, pf, &pfd))
            return false;


        if (!(g_hRC = wglCreateContext(g_hDC)))
            return false;


        if (!wglMakeCurrent(g_hDC, g_hRC))
            return false;


        return true;
    }


    void ChooseBestCSAAPixelFormat(int &pf)
    {
        struct CSAAPixelFormat
        {
            int numColorSamples;
            int numCoverageSamples;
            const char *pszDescription;
        };


        CSAAPixelFormat csaaPixelFormats[] =
        {
            { 4, 8,  "8x CSAA" },
            { 4, 16, "16x CSAA" },
            { 8, 8,  "8xQ (Quality) CSAA" },
            { 8, 16, "16xQ (Quality) CSAA" }
        };


        int totalCSAAFormats = static_cast<int>(sizeof(csaaPixelFormats) /
                                    sizeof(CSAAPixelFormat));


        int attributes[] =
        {
            WGL_SAMPLE_BUFFERS_ARB,  1,
            WGL_COLOR_SAMPLES_NV,    0,
            WGL_COVERAGE_SAMPLES_NV, 0,
            WGL_DOUBLE_BUFFER_ARB,   1,
            0, 0
        };


        int returnedPixelFormat = 0;
        UINT numFormats = 0;
        BOOL bStatus = FALSE;


        for (int i = totalCSAAFormats - 1; i >= 0; --i)
        {
            attributes[3] = csaaPixelFormats[i].numColorSamples;
            attributes[5] = csaaPixelFormats[i].numCoverageSamples;


            bStatus = wglChoosePixelFormatARB(g_hDC, attributes, 0, 1,
                        &returnedPixelFormat, &numFormats);


            if (bStatus == TRUE && numFormats)
            {
                pf = returnedPixelFormat;
                strcpy(g_szAAPixelFormat, csaaPixelFormats[i].pszDescription);
                break;
            }
        }


        if (bStatus == FALSE)
            g_szAAPixelFormat[0] = '\0';
    }


    void ChooseBestMSAAPixelFormat(int &pf)
    {
        int attributes[] =
        {
            WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
            WGL_ACCELERATION_ARB,   WGL_FULL_ACCELERATION_ARB,
            WGL_COLOR_BITS_ARB,     24,
            WGL_ALPHA_BITS_ARB,     8,
            WGL_DEPTH_BITS_ARB,     24,
            WGL_STENCIL_BITS_ARB,   8,
            WGL_DOUBLE_BUFFER_ARB,  GL_TRUE,
            WGL_SAMPLE_BUFFERS_ARB, GL_TRUE,
            WGL_SAMPLES_ARB,        0,
            0, 0
        };


        int returnedPixelFormat = 0;
        UINT numFormats = 0;
        BOOL bStatus = FALSE;
        
        for (int samples = 16; samples > 0; samples /= 2)
        {
            attributes[17] = samples;


            bStatus = wglChoosePixelFormatARB(g_hDC, attributes, 0, 1,
                        &returnedPixelFormat, &numFormats);


            if (bStatus == TRUE && numFormats)
            {
                pf = returnedPixelFormat;
                sprintf(g_szAAPixelFormat, "%dx MSAA", samples);
                break;
            }
        }


        if (bStatus == FALSE)
            g_szAAPixelFormat[0] = '\0';
    }


    void ChooseCSAAPixelFormat(int &pf, int samples)
    {
        struct CSAAPixelFormat
        {
            int numColorSamples;
            int numCoverageSamples;
            const char *pszDescription;
        };


        CSAAPixelFormat csaaPixelFormats[] =
        {
            { 4, 16, "16x CSAA" },
            { 4, 8,  "8x CSAA" }
        };


        CSAAPixelFormat csaaQualityPixelFormats[] =
        {
            { 8, 16, "16xQ (Quality) CSAA" },
            { 8, 8,  "8xQ (Quality) CSAA" }
        };


        CSAAPixelFormat *pCSAAFormats = 0;


        int attributes[] =
        {
            WGL_SAMPLE_BUFFERS_ARB,  1,
            WGL_COLOR_SAMPLES_NV,    0,
            WGL_COVERAGE_SAMPLES_NV, 0,
            WGL_DOUBLE_BUFFER_ARB,   1,
            0, 0
        };


        int returnedPixelFormat = 0;
        UINT numFormats = 0;
        BOOL bStatus = FALSE;


        if (samples >= 8)
            pCSAAFormats = csaaQualityPixelFormats;
        else
            pCSAAFormats = csaaPixelFormats;
        
        for (int i = 0; i < 2; ++i)
        {
            attributes[3] = pCSAAFormats[i].numColorSamples;
            attributes[5] = pCSAAFormats[i].numCoverageSamples;


            bStatus = wglChoosePixelFormatARB(g_hDC, attributes, 0, 1,
                        &returnedPixelFormat, &numFormats);


            if (bStatus == TRUE && numFormats)
            {
                pf = returnedPixelFormat;
                strcpy(g_szAAPixelFormat, pCSAAFormats[i].pszDescription);
                break;
            }
        }


        if (bStatus == FALSE)
            g_szAAPixelFormat[0] = '\0';
    }


    void ChooseMSAAPixelFormat(int &pf, int samples)
    {
        int attributes[] =
        {
            WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
            WGL_ACCELERATION_ARB,   WGL_FULL_ACCELERATION_ARB,
            WGL_COLOR_BITS_ARB,     24,
            WGL_ALPHA_BITS_ARB,     8,
            WGL_DEPTH_BITS_ARB,     24,
            WGL_STENCIL_BITS_ARB,   8,
            WGL_DOUBLE_BUFFER_ARB,  GL_TRUE,
            WGL_SAMPLE_BUFFERS_ARB, GL_TRUE,
            WGL_SAMPLES_ARB,        samples,
            0, 0
        };


        int returnedPixelFormat = 0;
        UINT numFormats = 0;
        BOOL bStatus = wglChoosePixelFormatARB(g_hDC, attributes, 0, 1,
                            &returnedPixelFormat, &numFormats);


        if (bStatus == TRUE && numFormats)
        {
            pf = returnedPixelFormat;
            sprintf(g_szAAPixelFormat, "%dx MSAA", samples);
        }
        else
        {
            g_szAAPixelFormat[0] = '\0';
        }
    }


    void DestroyDummyGLWindow()
    {
        if (g_hWnd)
        {
            PostMessage(g_hWnd, WM_CLOSE, 0, 0);


            BOOL bRet;
            MSG msg;


            while ((bRet = GetMessage(&msg, 0, 0, 0)) != 0)
            { 
                TranslateMessage(&msg); 
                DispatchMessage(&msg); 
            }
        }        


        UnregisterClass(g_wcl.lpszClassName, g_wcl.hInstance);
    }


    bool ExtensionSupported(const char *pszExtensionName)
    {
        static const char *pszGLExtensions = 0;
        static const char *pszWGLExtensions = 0;


        if (!pszGLExtensions)
            pszGLExtensions = reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS));


        if (!pszWGLExtensions)
        {
            // WGL_ARB_extensions_string.


            typedef const char *(WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC)(HDC);


            PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB =
                reinterpret_cast<PFNWGLGETEXTENSIONSSTRINGARBPROC>(
                wglGetProcAddress("wglGetExtensionsStringARB"));


            if (wglGetExtensionsStringARB)
                pszWGLExtensions = wglGetExtensionsStringARB(wglGetCurrentDC());
        }


        if (!strstr(pszGLExtensions, pszExtensionName))
        {
            if (!strstr(pszWGLExtensions, pszExtensionName))
                return false;
        }


        return true;
    }
}


void ChooseBestAntiAliasingPixelFormat(int &pf)
{
    pf = 0;
    
    if (!CreateDummyGLWindow())
    {
        DestroyDummyGLWindow();
        return;
    }
    
    if (ExtensionSupported("GL_NV_multisample_coverage") &&
        ExtensionSupported("WGL_NV_multisample_coverage"))
    {
        ChooseBestCSAAPixelFormat(pf);
    }
    else
    {
        ChooseBestMSAAPixelFormat(pf);
    }


    DestroyDummyGLWindow();
}


void ChooseAntiAliasingPixelFormat(int &pf, int samples)
{
    pf = 0;


    if (!CreateDummyGLWindow())
    {
        DestroyDummyGLWindow();
        return;
    }


    if (ExtensionSupported("GL_NV_multisample_coverage") &&
        ExtensionSupported("WGL_NV_multisample_coverage"))
    {
        ChooseCSAAPixelFormat(pf, samples);
    }
    else
    {
        ChooseMSAAPixelFormat(pf, samples);
    }


    DestroyDummyGLWindow();
}


const char *GetAntiAliasingPixelFormatString()
{
    return g_szAAPixelFormat;
}


// GL_ARB_multisample


void glSampleCoverageARB(GLclampf value, GLboolean invert)
{
    typedef void (APIENTRY * PFNGLSAMPLECOVERAGEARBPROC)(GLclampf value, GLboolean invert);   
    static PFNGLSAMPLECOVERAGEARBPROC pfnSampleCoverageARB = 0;


    if (!pfnSampleCoverageARB)
    {
        pfnSampleCoverageARB = reinterpret_cast<PFNGLSAMPLECOVERAGEARBPROC>(wglGetProcAddress("glSampleCoverageARB"));
        assert(pfnSampleCoverageARB != 0);
    }


    pfnSampleCoverageARB(value, invert);
}


// WGL_ARB_pixel_format


BOOL wglGetPixelFormatAttribivARB(HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues)
{
    typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC)(HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues);
    static PFNWGLGETPIXELFORMATATTRIBIVARBPROC pfnGetPixelFormatAttribivARB = 0;


    if (!pfnGetPixelFormatAttribivARB)
    {
        pfnGetPixelFormatAttribivARB = reinterpret_cast<PFNWGLGETPIXELFORMATATTRIBIVARBPROC>(wglGetProcAddress("wglGetPixelFormatAttribivARB"));
        assert(pfnGetPixelFormatAttribivARB != 0);
    }


    return pfnGetPixelFormatAttribivARB(hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, piValues);
}


BOOL wglGetPixelFormatAttribfvARB(HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues)
{
    typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVARBPROC)(HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues);
    static PFNWGLGETPIXELFORMATATTRIBFVARBPROC pfnGetPixelFormatAttribfvARB = 0;


    if (!pfnGetPixelFormatAttribfvARB)
    {
        pfnGetPixelFormatAttribfvARB = reinterpret_cast<PFNWGLGETPIXELFORMATATTRIBFVARBPROC>(wglGetProcAddress("wglGetPixelFormatAttribfvARB"));
        assert(pfnGetPixelFormatAttribfvARB != 0);
    }


    return pfnGetPixelFormatAttribfvARB(hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, pfValues);
}


BOOL wglChoosePixelFormatARB(HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats)
{
    typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC)(HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);
    static PFNWGLCHOOSEPIXELFORMATARBPROC pfnChoosePixelFormatARB = 0;


    if (!pfnChoosePixelFormatARB)
    {
        pfnChoosePixelFormatARB = reinterpret_cast<PFNWGLCHOOSEPIXELFORMATARBPROC>(wglGetProcAddress("wglChoosePixelFormatARB"));
        assert(pfnChoosePixelFormatARB != 0);
    }


    return pfnChoosePixelFormatARB(hdc, piAttribIList, pfAttribFList, nMaxFormats, piFormats, nNumFormats);
}


Anybody could help please?

Would have run it, but it’s MSWindows only (running Linux here), and uses other code not included. A simple GLUT test program with no dependencies besides std C/C++ would have been better.