Bonjour,
Je souhaite avoir une classe de création de context opengl maison. Je me suis fortement inspiré de ta classe Laurent pour ne pas dire que j'ai tout pris. ^^.
Voilà le code de ma classe.
//hpp
#ifndef GLCONTEXT_H
#define GLCONTEXT_H
#include <windows.h>
struct GLContextSettings
{
explicit GLContextSettings(unsigned int depth = 0, unsigned int stencil = 0, unsigned int antialiasing = 0, unsigned int major = 2, unsigned int minor = 0) :
DepthBits (depth),
StencilBits (stencil),
AntialiasingLevel(antialiasing),
MajorVersion (major),
MinorVersion (minor)
{
}
unsigned int DepthBits;
unsigned int StencilBits;
unsigned int AntialiasingLevel;
unsigned int MajorVersion;
unsigned int MinorVersion;
};
class GLContext
{
public:
GLContext(GLContext* shared, const GLContextSettings& settings);
virtual ~GLContext();
const GLContextSettings& getSettings() const;
bool isValid() const;
bool MakeCurrent();
static GLContext* getCurrentGLContext();
private:
GLContext();
void createContext(GLContext* shared, unsigned int bitsPerPixel, const GLContextSettings& settings);
static int EvaluateFormat(unsigned int bitsPerPixel, const GLContextSettings& settings, int colorBits, int depthBits, int stencilBits, int antialiasing);
static GLContext* m_staticCurrentContext;
HWND m_window;
HDC m_deviceContext;
HGLRC m_context;
GLContextSettings m_settings;
};
#endif // GLCONTEXT_H
#include "glcontext.h"
#include <windows.h>
#include <GL/gl.h>
#include "glext/wglext.h"
#include <cstdio>
#include <cmath>
#define ABS(x) ((x)>0)?(x):(-(x))
GLContext* GLContext::m_staticCurrentContext = NULL;
GLContext::GLContext()
: m_window(NULL)
, m_deviceContext(NULL)
, m_context(NULL)
, m_settings()
{
}
GLContext::GLContext(GLContext* shared, const GLContextSettings& settings)
: m_window(NULL)
, m_deviceContext(NULL)
, m_context(NULL)
, m_settings()
{
// if constext isn't valid we create a dummy window
if(shared != NULL)
{
m_deviceContext = shared->m_deviceContext;
}
if(m_deviceContext == NULL)
{
// Creating a dummy window is mandatory: we could create a memory DC but then
// its pixel format wouldn't match the regular contexts' format, and thus
// wglShareLists would always fail. Too bad...
m_window = CreateWindowA("STATIC", "", WS_POPUP | WS_DISABLED, 0, 0, 1, 1, NULL, NULL, GetModuleHandle(NULL), NULL);
ShowWindow(m_window, SW_HIDE);
m_deviceContext = GetDC(m_window);
}
// Create the context
if (m_deviceContext)
createContext(shared,32,settings);
}
GLContext::~GLContext()
{
if (m_context)
{
if (wglGetCurrentContext() == m_context) wglMakeCurrent(NULL, NULL);
wglDeleteContext(m_context);
}
// if we own a window we also own his DC
if (m_window)
{
ReleaseDC(m_window, m_deviceContext);
DestroyWindow(m_window);
}
}
bool GLContext::MakeCurrent()
{
return m_deviceContext && m_context && wglMakeCurrent(m_deviceContext, m_context);
}
const GLContextSettings& GLContext::getSettings() const
{
return m_settings;
}
bool GLContext::isValid() const
{
return (m_deviceContext != NULL) && (m_context != NULL);
}
GLContext* GLContext::getCurrentGLContext()
{
if(m_staticCurrentContext == NULL) m_staticCurrentContext = new GLContext();
PIXELFORMATDESCRIPTOR descriptor;
int iPixelFormat = GetPixelFormat(m_staticCurrentContext->m_deviceContext );
DescribePixelFormat(m_staticCurrentContext->m_deviceContext, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &descriptor);
m_staticCurrentContext->m_deviceContext = wglGetCurrentDC();
m_staticCurrentContext->m_context = wglGetCurrentContext();
m_staticCurrentContext->m_settings.DepthBits = descriptor.cDepthBits;
m_staticCurrentContext->m_settings.StencilBits = descriptor.cStencilBits;
// TODO : use wglgetpixelformatattribivarb to retreive antialiasing level
m_staticCurrentContext->m_settings.AntialiasingLevel = 0;
// TODO : look at wglCreateContextAttribsARB to retreive openGL version
m_staticCurrentContext->m_settings.MajorVersion = 2;
m_staticCurrentContext->m_settings.MinorVersion = 0;
return m_staticCurrentContext;
}
void GLContext::createContext(GLContext* shared, unsigned int bitsPerPixel, const GLContextSettings& settings)
{
// Save the creation settings
m_settings = settings;
// Let's find a suitable pixel format -- first try with antialiasing
int bestFormat = 0;
if (m_settings.AntialiasingLevel > 0)
{
// Get the wglChoosePixelFormatARB function (it is an extension)
PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = reinterpret_cast<PFNWGLCHOOSEPIXELFORMATARBPROC>(wglGetProcAddress("wglChoosePixelFormatARB"));
if (wglChoosePixelFormatARB)
{
// Define the basic attributes we want for our window
int intAttributes[] =
{
WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
WGL_SAMPLE_BUFFERS_ARB, (m_settings.AntialiasingLevel ? GL_TRUE : GL_FALSE),
WGL_SAMPLES_ARB, m_settings.AntialiasingLevel,
0, 0
};
// Let's check how many formats are supporting our requirements
int formats[128];
UINT nbFormats;
float floatAttributes[] = {0, 0};
bool isValid = wglChoosePixelFormatARB(m_deviceContext, intAttributes, floatAttributes, sizeof(formats) / sizeof(*formats), formats, &nbFormats) != 0;
while ((!isValid || (nbFormats == 0)) && m_settings.AntialiasingLevel > 0)
{
// Decrease the antialiasing level until we find a valid one
m_settings.AntialiasingLevel--;
intAttributes[11] = m_settings.AntialiasingLevel;
isValid = wglChoosePixelFormatARB(m_deviceContext, intAttributes, floatAttributes, sizeof(formats) / sizeof(*formats), formats, &nbFormats) != 0;
}
// Get the best format among the returned ones
if (isValid && (nbFormats > 0))
{
int bestScore = 0xFFFF;
for (UINT i = 0; i < nbFormats; ++i)
{
// Get the current format's attributes
PIXELFORMATDESCRIPTOR attributes;
attributes.nSize = sizeof(attributes);
attributes.nVersion = 1;
DescribePixelFormat(m_deviceContext, formats[i], sizeof(attributes), &attributes);
// Evaluate the current configuration
int color = attributes.cRedBits + attributes.cGreenBits + attributes.cBlueBits + attributes.cAlphaBits;
int score = EvaluateFormat(bitsPerPixel, m_settings, color, attributes.cDepthBits, attributes.cStencilBits, m_settings.AntialiasingLevel);
// Keep it if it's better than the current best
if (score < bestScore)
{
bestScore = score;
bestFormat = formats[i];
}
}
}
}
else
{
// wglChoosePixelFormatARB not supported ; disabling antialiasing
printf("Antialiasing is not supported ; it will be disabled\n");
m_settings.AntialiasingLevel = 0;
}
}
// Find a pixel format with no antialiasing, if not needed or not supported
if (bestFormat == 0)
{
// Setup a pixel format descriptor from the rendering settings
PIXELFORMATDESCRIPTOR descriptor;
ZeroMemory(&descriptor, sizeof(descriptor));
descriptor.nSize = sizeof(descriptor);
descriptor.nVersion = 1;
descriptor.iLayerType = PFD_MAIN_PLANE;
descriptor.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
descriptor.iPixelType = PFD_TYPE_RGBA;
descriptor.cColorBits = static_cast<BYTE>(bitsPerPixel);
descriptor.cDepthBits = static_cast<BYTE>(m_settings.DepthBits);
descriptor.cStencilBits = static_cast<BYTE>(m_settings.StencilBits);
descriptor.cAlphaBits = bitsPerPixel == 32 ? 8 : 0;
// Get the pixel format that best matches our requirements
bestFormat = ChoosePixelFormat(m_deviceContext, &descriptor);
if (bestFormat == 0)
{
printf("Failed to find a suitable pixel format for device context -- cannot create OpenGL context\n");
return;
}
}
// Extract the depth and stencil bits from the chosen format
PIXELFORMATDESCRIPTOR actualFormat;
actualFormat.nSize = sizeof(actualFormat);
actualFormat.nVersion = 1;
DescribePixelFormat(m_deviceContext, bestFormat, sizeof(actualFormat), &actualFormat);
m_settings.DepthBits = actualFormat.cDepthBits;
m_settings.StencilBits = actualFormat.cStencilBits;
// Set the chosen pixel format
if (!SetPixelFormat(m_deviceContext, bestFormat, &actualFormat))
{
printf("Failed to set pixel format for device context -- cannot create OpenGL context\n");
return;
}
// Get the context to share display lists with
HGLRC sharedContext = shared ? shared->m_context : NULL;
// Create the OpenGL context -- first try context versions >= 3.0 if it is requested (they require special code)
while (!m_context && (m_settings.MajorVersion >= 3))
{
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = reinterpret_cast<PFNWGLCREATECONTEXTATTRIBSARBPROC>(wglGetProcAddress("wglCreateContextAttribsARB"));
if (wglCreateContextAttribsARB)
{
int attributes[] =
{
WGL_CONTEXT_MAJOR_VERSION_ARB, m_settings.MajorVersion,
WGL_CONTEXT_MINOR_VERSION_ARB, m_settings.MinorVersion,
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
0, 0
};
m_context = wglCreateContextAttribsARB(m_deviceContext, sharedContext, attributes);
}
// If we couldn't create the context, lower the version number and try again -- stop at 3.0
// Invalid version numbers will be generated by this algorithm (like 3.9), but we really don't care
if (!m_context)
{
if (m_settings.MinorVersion > 0)
{
// If the minor version is not 0, we decrease it and try again
m_settings.MinorVersion--;
}
else
{
// If the minor version is 0, we decrease the major version
m_settings.MajorVersion--;
m_settings.MinorVersion = 9;
}
}
}
// If the OpenGL >= 3.0 context failed or if we don't want one, create a regular OpenGL 1.x/2.x context
if (!m_context)
{
// set the context version to 2.0 (arbitrary)
m_settings.MajorVersion = 2;
m_settings.MinorVersion = 0;
m_context = wglCreateContext(m_deviceContext);
if (!m_context)
{
printf("Failed to create an OpenGL context for this window\n");
return;
}
// Share this context with others
if (sharedContext)
{
// WARNING : wglShareLists doesn't seem to be thread-saf
if (!wglShareLists(sharedContext, m_context))
printf("Failed to share the OpenGL context\n");
}
}
}
int GLContext::EvaluateFormat(unsigned int bitsPerPixel, const GLContextSettings& settings, int colorBits, int depthBits, int stencilBits, int antialiasing)
{
return ABS(static_cast<int>(bitsPerPixel - colorBits)) +
ABS(static_cast<int>(settings.DepthBits - depthBits)) +
ABS(static_cast<int>(settings.StencilBits - stencilBits)) +
ABS(static_cast<int>(settings.AntialiasingLevel - antialiasing));
}
//cpp
J'arrive à créer des contextes depuis rien, à en partager, mais si j'essaie d'en créer un partagé avec un fenetre SFML j'ai une erreur lors du SetPixelFormat. Je test avec ce code :
int main(int argc, char** argv)
{
sf::RenderWindow App(sf::VideoMode(800, 600), "DEMO_MDE");
//GLContext context(NULL,GLContextSettings());
GLContext context2(GLContext::getCurrentGLContext(),GLContextSettings());
printf("active other context : %d\n",context.MakeCurrent());
printf("active other context : %d\n",context2.MakeCurrent());
}
Mais si je décommente la ligne deux et que je commente la première je n'ai plus d'erreur. Je ne comprends pas vraiment ce qu'il se passe. Si quelqu'un avait une idée.
Merci d'avance.