*
**************************************************************************/
-#include "glimports.hpp"
+
+/*
+ * WGL bindings.
+ */
+
+
+#include <iostream>
+
+#include "glproc.hpp"
#include "glws.hpp"
namespace glws {
+/*
+ * Several WGL functions come in two flavors:
+ * - GDI (ChoosePixelFormat, SetPixelFormat, SwapBuffers, etc)
+ * - WGL (wglChoosePixelFormat, wglSetPixelFormat, wglSwapBuffers, etc)
+ *
+ * The GDI entrypoints will inevitably dispatch to the first module named
+ * "OPENGL32", loading "C:\Windows\System32\opengl32.dll" if none was loaded so
+ * far.
+ *
+ * In order to use a implementation other than the one installed in the system
+ * (when specified via the TRACE_LIBGL environment variable), we need to use
+ * WGL entrypoints.
+ *
+ * See also:
+ * - http://www.opengl.org/archives/resources/faq/technical/mswindows.htm
+ */
+static __PFNWGLCHOOSEPIXELFORMAT pfnChoosePixelFormat = &ChoosePixelFormat;
+static __PFNWGLSETPIXELFORMAT pfnSetPixelFormat = &SetPixelFormat;
+static __PFNWGLSWAPBUFFERS pfnSwapBuffers = &SwapBuffers;
+
+
static LRESULT CALLBACK
WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
{
static bool first = TRUE;
RECT rect;
+ BOOL bRet;
if (first) {
WNDCLASS wc;
}
dwExStyle = 0;
- dwStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE | WS_OVERLAPPEDWINDOW;
+ dwStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW;
int x = 0, y = 0;
hDC = GetDC(hWnd);
memset(&pfd, 0, sizeof pfd);
- pfd.cColorBits = 3;
+ pfd.cColorBits = 4;
pfd.cRedBits = 1;
pfd.cGreenBits = 1;
pfd.cBlueBits = 1;
+ pfd.cAlphaBits = 1;
pfd.cDepthBits = 1;
pfd.cStencilBits = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
pfd.dwFlags |= PFD_DOUBLEBUFFER;
}
- iPixelFormat = ChoosePixelFormat(hDC, &pfd);
+ iPixelFormat = pfnChoosePixelFormat(hDC, &pfd);
+ if (iPixelFormat <= 0) {
+ std::cerr << "error: ChoosePixelFormat failed\n";
+ exit(1);
+ }
- SetPixelFormat(hDC, iPixelFormat, &pfd);
+ bRet = pfnSetPixelFormat(hDC, iPixelFormat, &pfd);
+ if (!bRet) {
+ std::cerr << "error: SetPixelFormat failed\n";
+ exit(1);
+ }
}
~WglDrawable() {
void
resize(int w, int h) {
- Drawable::resize(w, h);
+ if (w == width && h == height) {
+ return;
+ }
+
RECT rClient, rWindow;
GetClientRect(hWnd, &rClient);
GetWindowRect(hWnd, &rWindow);
w += (rWindow.right - rWindow.left) - rClient.right;
h += (rWindow.bottom - rWindow.top) - rClient.bottom;
SetWindowPos(hWnd, NULL, rWindow.left, rWindow.top, w, h, SWP_NOMOVE);
+
+ Drawable::resize(w, h);
+ }
+
+ void show(void) {
+ if (visible) {
+ return;
+ }
+
+ ShowWindow(hWnd, SW_SHOW);
+
+ Drawable::show();
}
void swapBuffers(void) {
- SwapBuffers(hDC);
+ BOOL bRet;
+ bRet = pfnSwapBuffers(hDC);
+ if (!bRet) {
+ std::cerr << "warning: SwapBuffers failed\n";
+ }
+
+ // Drain message queue to prevent window from being considered
+ // non-responsive
+ MSG msg;
+ while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
}
};
{
public:
HGLRC hglrc;
-
- WglContext(const Visual *vis) :
- Context(vis),
- hglrc(0)
+ WglContext *shareContext;
+
+ WglContext(const Visual *vis, Profile prof, WglContext *share) :
+ Context(vis, prof),
+ hglrc(0),
+ shareContext(share)
{}
~WglContext() {
};
-class WglWindowSystem : public WindowSystem
-{
-public:
- Visual *
- createVisual(bool doubleBuffer) {
- Visual *visual = new Visual();
+void
+init(void) {
+ /*
+ * OpenGL library must be loaded by the time we call GDI.
+ */
- visual->doubleBuffer = doubleBuffer;
+ const char * libgl_filename = getenv("TRACE_LIBGL");
- return visual;
+ if (libgl_filename) {
+ pfnChoosePixelFormat = &wglChoosePixelFormat;
+ pfnSetPixelFormat = &wglSetPixelFormat;
+ pfnSwapBuffers = &wglSwapBuffers;
+ } else {
+ libgl_filename = "OPENGL32";
}
-
- Drawable *
- createDrawable(const Visual *visual, int width, int height)
- {
- return new WglDrawable(visual, width, height);
+
+ __libGlHandle = LoadLibraryA(libgl_filename);
+ if (!__libGlHandle) {
+ std::cerr << "error: unable to open " << libgl_filename << "\n";
+ exit(1);
}
+}
- Context *
- createContext(const Visual *visual)
- {
- return new WglContext(visual);
+void
+cleanup(void) {
+}
+
+Visual *
+createVisual(bool doubleBuffer, Profile profile) {
+ if (profile != PROFILE_COMPAT) {
+ return NULL;
}
- bool
- makeCurrent(Drawable *drawable, Context *context)
- {
- if (!drawable || !context) {
- return wglMakeCurrent(NULL, NULL);
- } else {
- WglDrawable *wglDrawable = dynamic_cast<WglDrawable *>(drawable);
- WglContext *wglContext = dynamic_cast<WglContext *>(context);
+ Visual *visual = new Visual();
+ visual->doubleBuffer = doubleBuffer;
+
+ return visual;
+}
+
+Drawable *
+createDrawable(const Visual *visual, int width, int height)
+{
+ return new WglDrawable(visual, width, height);
+}
+
+Context *
+createContext(const Visual *visual, Context *shareContext, Profile profile)
+{
+ if (profile != PROFILE_COMPAT) {
+ return NULL;
+ }
+
+ return new WglContext(visual, profile, static_cast<WglContext *>(shareContext));
+}
+
+bool
+makeCurrent(Drawable *drawable, Context *context)
+{
+ if (!drawable || !context) {
+ return wglMakeCurrent(NULL, NULL);
+ } else {
+ WglDrawable *wglDrawable = static_cast<WglDrawable *>(drawable);
+ WglContext *wglContext = static_cast<WglContext *>(context);
+
+ if (!wglContext->hglrc) {
+ wglContext->hglrc = wglCreateContext(wglDrawable->hDC);
if (!wglContext->hglrc) {
- wglContext->hglrc = wglCreateContext(wglDrawable->hDC);
- if (!wglContext->hglrc) {
- return false;
+ std::cerr << "error: wglCreateContext failed\n";
+ exit(1);
+ return false;
+ }
+ if (wglContext->shareContext) {
+ BOOL bRet;
+ bRet = wglShareLists(wglContext->shareContext->hglrc,
+ wglContext->hglrc);
+ if (!bRet) {
+ std::cerr << "warning: wglShareLists failed\n";
}
}
-
- return wglMakeCurrent(wglDrawable->hDC, wglContext->hglrc);
}
- }
- bool
- processEvents(void) {
- // TODO
- return true;
+ return wglMakeCurrent(wglDrawable->hDC, wglContext->hglrc);
}
-};
-
+}
-WindowSystem *createNativeWindowSystem(void) {
- return new WglWindowSystem();
+bool
+processEvents(void) {
+ // TODO
+ return true;
}
-} /* namespace glretrace */
+} /* namespace glws */