aboutsummaryrefslogtreecommitdiffstats
path: root/pugl/detail/win_gl.c
diff options
context:
space:
mode:
Diffstat (limited to 'pugl/detail/win_gl.c')
-rw-r--r--pugl/detail/win_gl.c325
1 files changed, 0 insertions, 325 deletions
diff --git a/pugl/detail/win_gl.c b/pugl/detail/win_gl.c
deleted file mode 100644
index 096c715..0000000
--- a/pugl/detail/win_gl.c
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- Copyright 2012-2020 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-/**
- @file win_gl.c
- @brief OpenGL graphics backend for Windows.
-*/
-
-#include "pugl/detail/stub.h"
-#include "pugl/detail/types.h"
-#include "pugl/detail/win.h"
-#include "pugl/pugl_gl.h"
-
-#include <windows.h>
-
-#include <GL/gl.h>
-
-#include <stdbool.h>
-#include <stdlib.h>
-
-#define WGL_DRAW_TO_WINDOW_ARB 0x2001
-#define WGL_ACCELERATION_ARB 0x2003
-#define WGL_SUPPORT_OPENGL_ARB 0x2010
-#define WGL_DOUBLE_BUFFER_ARB 0x2011
-#define WGL_PIXEL_TYPE_ARB 0x2013
-#define WGL_RED_BITS_ARB 0x2015
-#define WGL_GREEN_BITS_ARB 0x2017
-#define WGL_BLUE_BITS_ARB 0x2019
-#define WGL_ALPHA_BITS_ARB 0x201b
-#define WGL_DEPTH_BITS_ARB 0x2022
-#define WGL_STENCIL_BITS_ARB 0x2023
-#define WGL_FULL_ACCELERATION_ARB 0x2027
-#define WGL_TYPE_RGBA_ARB 0x202b
-#define WGL_SAMPLE_BUFFERS_ARB 0x2041
-#define WGL_SAMPLES_ARB 0x2042
-
-#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
-#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
-#define WGL_CONTEXT_FLAGS_ARB 0x2094
-#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
-
-#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
-#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
-#define WGL_CONTEXT_DEBUG_BIT_ARB 0x00000001
-
-typedef HGLRC (*WglCreateContextAttribs)(HDC, HGLRC, const int*);
-typedef BOOL (*WglSwapInterval)(int);
-typedef BOOL (*WglChoosePixelFormat)(
- HDC, const int*, const FLOAT*, UINT, int*, UINT*);
-
-typedef struct {
- WglChoosePixelFormat wglChoosePixelFormat;
- WglCreateContextAttribs wglCreateContextAttribs;
- WglSwapInterval wglSwapInterval;
-} PuglWinGlProcs;
-
-typedef struct {
- PuglWinGlProcs procs;
- HGLRC hglrc;
-} PuglWinGlSurface;
-
-// Struct to manage the fake window used during configuration
-typedef struct {
- HWND hwnd;
- HDC hdc;
-} PuglFakeWindow;
-
-static PuglStatus
-puglWinError(PuglFakeWindow* fakeWin, const PuglStatus status)
-{
- if (fakeWin->hwnd) {
- ReleaseDC(fakeWin->hwnd, fakeWin->hdc);
- DestroyWindow(fakeWin->hwnd);
- }
-
- return status;
-}
-
-static PuglWinGlProcs puglWinGlGetProcs(void)
-{
- const PuglWinGlProcs procs = {
- (WglChoosePixelFormat)(
- wglGetProcAddress("wglChoosePixelFormatARB")),
- (WglCreateContextAttribs)(
- wglGetProcAddress("wglCreateContextAttribsARB")),
- (WglSwapInterval)(
- wglGetProcAddress("wglSwapIntervalEXT"))
- };
-
- return procs;
-}
-
-static PuglStatus
-puglWinGlConfigure(PuglView* view)
-{
- PuglInternals* impl = view->impl;
-
- // Set attributes to default if they are unset
- // (There is no GLX_DONT_CARE equivalent on Windows)
- if (view->hints[PUGL_DEPTH_BITS] == PUGL_DONT_CARE) {
- view->hints[PUGL_DEPTH_BITS] = 0;
- }
- if (view->hints[PUGL_STENCIL_BITS] == PUGL_DONT_CARE) {
- view->hints[PUGL_STENCIL_BITS] = 0;
- }
- if (view->hints[PUGL_SAMPLES] == PUGL_DONT_CARE) {
- view->hints[PUGL_SAMPLES] = 1;
- }
- if (view->hints[PUGL_DOUBLE_BUFFER] == PUGL_DONT_CARE) {
- view->hints[PUGL_DOUBLE_BUFFER] = 1;
- }
- if (view->hints[PUGL_SWAP_INTERVAL] == PUGL_DONT_CARE) {
- view->hints[PUGL_SWAP_INTERVAL] = 1;
- }
-
- // clang-format off
- const int pixelAttrs[] = {
- WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
- WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
- WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
- WGL_DOUBLE_BUFFER_ARB, view->hints[PUGL_DOUBLE_BUFFER],
- WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
- WGL_SAMPLE_BUFFERS_ARB, view->hints[PUGL_SAMPLES] ? 1 : 0,
- WGL_SAMPLES_ARB, view->hints[PUGL_SAMPLES],
- WGL_RED_BITS_ARB, view->hints[PUGL_RED_BITS],
- WGL_GREEN_BITS_ARB, view->hints[PUGL_GREEN_BITS],
- WGL_BLUE_BITS_ARB, view->hints[PUGL_BLUE_BITS],
- WGL_ALPHA_BITS_ARB, view->hints[PUGL_ALPHA_BITS],
- WGL_DEPTH_BITS_ARB, view->hints[PUGL_DEPTH_BITS],
- WGL_STENCIL_BITS_ARB, view->hints[PUGL_STENCIL_BITS],
- 0,
- };
- // clang-format on
-
- PuglWinGlSurface* const surface =
- (PuglWinGlSurface*)calloc(1, sizeof(PuglWinGlSurface));
- impl->surface = surface;
-
- // Create fake window for getting at GL context
- PuglStatus st = PUGL_SUCCESS;
- PuglFakeWindow fakeWin = {0, 0};
- static const char* title = "Pugl Configuration";
- if ((st = puglWinCreateWindow(view, title, &fakeWin.hwnd, &fakeWin.hdc))) {
- return puglWinError(&fakeWin, st);
- }
-
- // Set pixel format for fake window
- const PuglWinPFD fakePfd = puglWinGetPixelFormatDescriptor(view->hints);
- const int fakePfId = ChoosePixelFormat(fakeWin.hdc, &fakePfd);
- if (!fakePfId) {
- return puglWinError(&fakeWin, PUGL_SET_FORMAT_FAILED);
- } else if (!SetPixelFormat(fakeWin.hdc, fakePfId, &fakePfd)) {
- return puglWinError(&fakeWin, PUGL_SET_FORMAT_FAILED);
- }
-
- // Create fake GL context to get at the functions we need
- HGLRC fakeRc = wglCreateContext(fakeWin.hdc);
- if (!fakeRc) {
- return puglWinError(&fakeWin, PUGL_CREATE_CONTEXT_FAILED);
- }
-
- // Enter fake context and get extension functions
- wglMakeCurrent(fakeWin.hdc, fakeRc);
- surface->procs = puglWinGlGetProcs();
-
- if (surface->procs.wglChoosePixelFormat) {
- // Choose pixel format based on attributes
- UINT numFormats = 0;
- if (!surface->procs.wglChoosePixelFormat(
- fakeWin.hdc, pixelAttrs, NULL, 1u, &impl->pfId, &numFormats)) {
- return puglWinError(&fakeWin, PUGL_SET_FORMAT_FAILED);
- }
-
- DescribePixelFormat(
- impl->hdc, impl->pfId, sizeof(impl->pfd), &impl->pfd);
- } else {
- // Modern extensions not available, use basic pixel format
- impl->pfd = fakePfd;
- impl->pfId = fakePfId;
- }
-
- // Dispose of fake window and context
- wglMakeCurrent(NULL, NULL);
- wglDeleteContext(fakeRc);
- ReleaseDC(fakeWin.hwnd, fakeWin.hdc);
- DestroyWindow(fakeWin.hwnd);
-
- return PUGL_SUCCESS;
-}
-
-static PuglStatus
-puglWinGlCreate(PuglView* view)
-{
- PuglInternals* const impl = view->impl;
- PuglWinGlSurface* const surface = (PuglWinGlSurface*)impl->surface;
- PuglStatus st = PUGL_SUCCESS;
-
- const int contextAttribs[] = {
- WGL_CONTEXT_MAJOR_VERSION_ARB,
- view->hints[PUGL_CONTEXT_VERSION_MAJOR],
-
- WGL_CONTEXT_MINOR_VERSION_ARB,
- view->hints[PUGL_CONTEXT_VERSION_MINOR],
-
- WGL_CONTEXT_FLAGS_ARB,
- (view->hints[PUGL_USE_DEBUG_CONTEXT] ? WGL_CONTEXT_DEBUG_BIT_ARB : 0),
-
- WGL_CONTEXT_PROFILE_MASK_ARB,
- (view->hints[PUGL_USE_COMPAT_PROFILE]
- ? WGL_CONTEXT_CORE_PROFILE_BIT_ARB
- : WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB),
-
- 0};
-
- // Create real window with desired pixel format
- if ((st = puglWinCreateWindow(view, "Pugl", &impl->hwnd, &impl->hdc))) {
- return st;
- } else if (!SetPixelFormat(impl->hdc, impl->pfId, &impl->pfd)) {
- ReleaseDC(impl->hwnd, impl->hdc);
- DestroyWindow(impl->hwnd);
- impl->hwnd = NULL;
- impl->hdc = NULL;
- return PUGL_SET_FORMAT_FAILED;
- }
-
- // Create GL context
- if (surface->procs.wglCreateContextAttribs &&
- !(surface->hglrc = surface->procs.wglCreateContextAttribs(
- impl->hdc, 0, contextAttribs))) {
- return PUGL_CREATE_CONTEXT_FAILED;
- } else if (!(surface->hglrc = wglCreateContext(impl->hdc))) {
- return PUGL_CREATE_CONTEXT_FAILED;
- }
-
- // Enter context and set swap interval
- wglMakeCurrent(impl->hdc, surface->hglrc);
- const int swapInterval = view->hints[PUGL_SWAP_INTERVAL];
- if (surface->procs.wglSwapInterval && swapInterval != PUGL_DONT_CARE) {
- surface->procs.wglSwapInterval(swapInterval);
- }
-
- return PUGL_SUCCESS;
-}
-
-static PuglStatus
-puglWinGlDestroy(PuglView* view)
-{
- PuglWinGlSurface* surface = (PuglWinGlSurface*)view->impl->surface;
- if (surface) {
- wglMakeCurrent(NULL, NULL);
- wglDeleteContext(surface->hglrc);
- free(surface);
- view->impl->surface = NULL;
- }
-
- return PUGL_SUCCESS;
-}
-
-static PuglStatus
-puglWinGlEnter(PuglView* view, const PuglEventExpose* expose)
-{
- PuglWinGlSurface* surface = (PuglWinGlSurface*)view->impl->surface;
-
- wglMakeCurrent(view->impl->hdc, surface->hglrc);
-
- if (expose) {
- PAINTSTRUCT ps;
- BeginPaint(view->impl->hwnd, &ps);
- }
-
- return PUGL_SUCCESS;
-}
-
-static PuglStatus
-puglWinGlLeave(PuglView* view, const PuglEventExpose* expose)
-{
- if (expose) {
- PAINTSTRUCT ps;
- EndPaint(view->impl->hwnd, &ps);
- SwapBuffers(view->impl->hdc);
- }
-
- wglMakeCurrent(NULL, NULL);
- return PUGL_SUCCESS;
-}
-
-PuglGlFunc
-puglGetProcAddress(const char* name)
-{
- const PuglGlFunc func = (PuglGlFunc)wglGetProcAddress(name);
-
- /* Windows has the annoying property that wglGetProcAddress returns NULL
- for functions from OpenGL 1.1, so we fall back to pulling them directly
- from opengl32.dll */
-
- return func
- ? func
- : (PuglGlFunc)GetProcAddress(GetModuleHandle("opengl32.dll"), name);
-}
-
-const PuglBackend*
-puglGlBackend(void)
-{
- static const PuglBackend backend = {puglWinGlConfigure,
- puglWinGlCreate,
- puglWinGlDestroy,
- puglWinGlEnter,
- puglWinGlLeave,
- puglStubGetContext};
-
- return &backend;
-}