mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-17 11:35:08 -04:00
Decouple window system from OpenGL context system
This commit is contained in:
parent
dd0b35d1d5
commit
c7c552e27f
46
src/Core.h
46
src/Core.h
@ -80,43 +80,45 @@ typedef struct TextureRec_ { float U1, V1, U2, V2; } TextureRec;
|
|||||||
|
|
||||||
/*#define CC_BUILD_GL11*/
|
/*#define CC_BUILD_GL11*/
|
||||||
#ifndef CC_BUILD_MANUAL
|
#ifndef CC_BUILD_MANUAL
|
||||||
#ifdef _WIN32
|
#if defined _WIN32
|
||||||
#define CC_BUILD_D3D9
|
|
||||||
#define CC_BUILD_WIN
|
#define CC_BUILD_WIN
|
||||||
#endif
|
#define CC_BUILD_D3D9
|
||||||
#ifdef __linux__
|
#define CC_BUILD_WINGUI
|
||||||
|
#define CC_BUILD_WGL
|
||||||
|
#elif defined __linux__
|
||||||
#define CC_BUILD_LINUX
|
#define CC_BUILD_LINUX
|
||||||
#define CC_BUILD_X11
|
|
||||||
#define CC_BUILD_POSIX
|
#define CC_BUILD_POSIX
|
||||||
#endif
|
#define CC_BUILD_X11
|
||||||
#ifdef __APPLE__
|
#define CC_BUILD_GLX
|
||||||
|
#elif defined __APPLE__
|
||||||
#define CC_BUILD_OSX
|
#define CC_BUILD_OSX
|
||||||
#define CC_BUILD_POSIX
|
#define CC_BUILD_POSIX
|
||||||
#endif
|
#define CC_BUILD_CARBON
|
||||||
#ifdef __sun__
|
#define CC_BUILD_AGL
|
||||||
|
#elif defined __sun__
|
||||||
#define CC_BUILD_SOLARIS
|
#define CC_BUILD_SOLARIS
|
||||||
#define CC_BUILD_X11
|
|
||||||
#define CC_BUILD_POSIX
|
#define CC_BUILD_POSIX
|
||||||
#endif
|
#define CC_BUILD_X11
|
||||||
#ifdef __FreeBSD__
|
#define CC_BUILD_GLX
|
||||||
|
#elif defined __FreeBSD__
|
||||||
#define CC_BUILD_FREEBSD
|
#define CC_BUILD_FREEBSD
|
||||||
#define CC_BUILD_X11
|
|
||||||
#define CC_BUILD_POSIX
|
#define CC_BUILD_POSIX
|
||||||
#endif
|
#define CC_BUILD_X11
|
||||||
#ifdef __OpenBSD__
|
#define CC_BUILD_GLX
|
||||||
|
#elif defined __OpenBSD__
|
||||||
#define CC_BUILD_OPENBSD
|
#define CC_BUILD_OPENBSD
|
||||||
#define CC_BUILD_X11
|
|
||||||
#define CC_BUILD_POSIX
|
#define CC_BUILD_POSIX
|
||||||
#endif
|
#define CC_BUILD_X11
|
||||||
#ifdef __NetBSD__
|
#define CC_BUILD_GLX
|
||||||
|
#elif defined __NetBSD__
|
||||||
#define CC_BUILD_NETBSD
|
#define CC_BUILD_NETBSD
|
||||||
|
#define CC_BUILD_POSIX
|
||||||
#define CC_BUILD_X11
|
#define CC_BUILD_X11
|
||||||
#define CC_BUILD_POSIX
|
#define CC_BUILD_GLX
|
||||||
#endif
|
#elif defined __EMSCRIPTEN__
|
||||||
#ifdef __EMSCRIPTEN__
|
|
||||||
#define CC_BUILD_WEB
|
#define CC_BUILD_WEB
|
||||||
#define CC_BUILD_SDL
|
|
||||||
#define CC_BUILD_POSIX
|
#define CC_BUILD_POSIX
|
||||||
|
#define CC_BUILD_SDL
|
||||||
#define CC_BUILD_GLMODERN
|
#define CC_BUILD_GLMODERN
|
||||||
#error "Web backend is still a WIP. Please do not publicly mention it, thanks."
|
#error "Web backend is still a WIP. Please do not publicly mention it, thanks."
|
||||||
#endif
|
#endif
|
||||||
|
@ -1225,7 +1225,7 @@ void Gfx_DeleteIb(GfxResourceID* ib) {
|
|||||||
|
|
||||||
void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, int vCount) {
|
void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, int vCount) {
|
||||||
uint32_t size = vCount * gfx_batchStride;
|
uint32_t size = vCount * gfx_batchStride;
|
||||||
_glBindBuffer(GL_ARRAY_BUFFER, vb);
|
_glBindBuffer(GL_ARRAY_BUFFER, (GLuint)vb);
|
||||||
_glBufferSubData(GL_ARRAY_BUFFER, 0, size, vertices);
|
_glBufferSubData(GL_ARRAY_BUFFER, 0, size, vertices);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
839
src/Window.c
839
src/Window.c
@ -95,7 +95,7 @@ void GraphicsMode_MakeDefault(struct GraphicsMode* m) {
|
|||||||
/*########################################################################################################################*
|
/*########################################################################################################################*
|
||||||
*------------------------------------------------------Win32 window-------------------------------------------------------*
|
*------------------------------------------------------Win32 window-------------------------------------------------------*
|
||||||
*#########################################################################################################################*/
|
*#########################################################################################################################*/
|
||||||
#ifdef CC_BUILD_WIN
|
#ifdef CC_BUILD_WINGUI
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#define NOSERVICE
|
#define NOSERVICE
|
||||||
#define NOMCX
|
#define NOMCX
|
||||||
@ -655,90 +655,6 @@ void Window_DrawRaw(Rect2D r) {
|
|||||||
BOOL success = BitBlt(win_DC, r.X, r.Y, r.Width, r.Height, draw_DC, r.X, r.Y, SRCCOPY);
|
BOOL success = BitBlt(win_DC, r.X, r.Y, r.Width, r.Height, draw_DC, r.X, r.Y, SRCCOPY);
|
||||||
SelectObject(draw_DC, oldSrc);
|
SelectObject(draw_DC, oldSrc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*########################################################################################################################*
|
|
||||||
*-----------------------------------------------------OpenGL context------------------------------------------------------*
|
|
||||||
*#########################################################################################################################*/
|
|
||||||
#ifndef CC_BUILD_D3D9
|
|
||||||
void GLContext_SelectGraphicsMode(struct GraphicsMode* mode) {
|
|
||||||
PIXELFORMATDESCRIPTOR pfd = { 0 };
|
|
||||||
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
|
|
||||||
pfd.nVersion = 1;
|
|
||||||
pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER;
|
|
||||||
/* TODO: PFD_SUPPORT_COMPOSITION FLAG? CHECK IF IT WORKS ON XP */
|
|
||||||
pfd.cColorBits = mode->R + mode->G + mode->B;
|
|
||||||
|
|
||||||
pfd.iPixelType = mode->IsIndexed ? PFD_TYPE_COLORINDEX : PFD_TYPE_RGBA;
|
|
||||||
pfd.cRedBits = mode->R;
|
|
||||||
pfd.cGreenBits = mode->G;
|
|
||||||
pfd.cBlueBits = mode->B;
|
|
||||||
pfd.cAlphaBits = mode->A;
|
|
||||||
|
|
||||||
pfd.cDepthBits = mode->DepthBits;
|
|
||||||
pfd.cStencilBits = mode->StencilBits;
|
|
||||||
|
|
||||||
int modeIndex = ChoosePixelFormat(win_DC, &pfd);
|
|
||||||
if (modeIndex == 0) { Logger_Abort("Requested graphics mode not available"); }
|
|
||||||
|
|
||||||
Mem_Set(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
|
|
||||||
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
|
|
||||||
pfd.nVersion = 1;
|
|
||||||
|
|
||||||
DescribePixelFormat(win_DC, modeIndex, pfd.nSize, &pfd);
|
|
||||||
if (!SetPixelFormat(win_DC, modeIndex, &pfd)) {
|
|
||||||
Logger_Abort2(GetLastError(), "SetPixelFormat failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static HGLRC ctx_Handle;
|
|
||||||
static HDC ctx_DC;
|
|
||||||
typedef BOOL (WINAPI *FN_WGLSWAPINTERVAL)(int interval);
|
|
||||||
static FN_WGLSWAPINTERVAL wglSwapIntervalEXT;
|
|
||||||
static bool ctx_supports_vSync;
|
|
||||||
|
|
||||||
void GLContext_Init(struct GraphicsMode* mode) {
|
|
||||||
GLContext_SelectGraphicsMode(mode);
|
|
||||||
ctx_Handle = wglCreateContext(win_DC);
|
|
||||||
if (!ctx_Handle) {
|
|
||||||
ctx_Handle = wglCreateContext(win_DC);
|
|
||||||
}
|
|
||||||
if (!ctx_Handle) {
|
|
||||||
Logger_Abort2(GetLastError(), "Failed to create OpenGL context");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!wglMakeCurrent(win_DC, ctx_Handle)) {
|
|
||||||
Logger_Abort2(GetLastError(), "Failed to make OpenGL context current");
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx_DC = wglGetCurrentDC();
|
|
||||||
wglSwapIntervalEXT = (FN_WGLSWAPINTERVAL)GLContext_GetAddress("wglSwapIntervalEXT");
|
|
||||||
ctx_supports_vSync = wglSwapIntervalEXT != NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLContext_Update(void) { }
|
|
||||||
void GLContext_Free(void) {
|
|
||||||
if (!wglDeleteContext(ctx_Handle)) {
|
|
||||||
Logger_Abort2(GetLastError(), "Failed to destroy OpenGL context");
|
|
||||||
}
|
|
||||||
ctx_Handle = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* GLContext_GetAddress(const char* function) {
|
|
||||||
void* address = wglGetProcAddress(function);
|
|
||||||
return GLContext_IsInvalidAddress(address) ? NULL : address;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLContext_SwapBuffers(void) {
|
|
||||||
if (!SwapBuffers(ctx_DC)) {
|
|
||||||
Logger_Abort2(GetLastError(), "Failed to swap buffers");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLContext_SetVSync(bool enabled) {
|
|
||||||
if (ctx_supports_vSync) wglSwapIntervalEXT(enabled);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -747,7 +663,6 @@ void GLContext_SetVSync(bool enabled) {
|
|||||||
*#########################################################################################################################*/
|
*#########################################################################################################################*/
|
||||||
#ifdef CC_BUILD_X11
|
#ifdef CC_BUILD_X11
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
#include <GL/glx.h>
|
|
||||||
|
|
||||||
#define _NET_WM_STATE_REMOVE 0
|
#define _NET_WM_STATE_REMOVE 0
|
||||||
#define _NET_WM_STATE_ADD 1
|
#define _NET_WM_STATE_ADD 1
|
||||||
@ -1635,150 +1550,13 @@ void Window_DrawRaw(Rect2D r) {
|
|||||||
XPutImage(win_display, win_handle, win_gc, win_image,
|
XPutImage(win_display, win_handle, win_gc, win_image,
|
||||||
r.X, r.Y, r.X, r.Y, r.Width, r.Height);
|
r.X, r.Y, r.X, r.Y, r.Width, r.Height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*########################################################################################################################*
|
|
||||||
*-----------------------------------------------------OpenGL context------------------------------------------------------*
|
|
||||||
*#########################################################################################################################*/
|
|
||||||
static GLXContext ctx_Handle;
|
|
||||||
typedef int (*FN_GLXSWAPINTERVAL)(int interval);
|
|
||||||
static FN_GLXSWAPINTERVAL swapIntervalMESA, swapIntervalSGI;
|
|
||||||
static bool ctx_supports_vSync;
|
|
||||||
|
|
||||||
void GLContext_Init(struct GraphicsMode* mode) {
|
|
||||||
const static String ext_mesa = String_FromConst("GLX_MESA_swap_control");
|
|
||||||
const static String ext_sgi = String_FromConst("GLX_SGI_swap_control");
|
|
||||||
|
|
||||||
const char* raw_exts;
|
|
||||||
String exts;
|
|
||||||
ctx_Handle = glXCreateContext(win_display, &win_visual, NULL, true);
|
|
||||||
|
|
||||||
if (!ctx_Handle) {
|
|
||||||
Platform_LogConst("Context create failed. Trying indirect...");
|
|
||||||
ctx_Handle = glXCreateContext(win_display, &win_visual, NULL, false);
|
|
||||||
}
|
|
||||||
if (!ctx_Handle) Logger_Abort("Failed to create OpenGL context");
|
|
||||||
|
|
||||||
if (!glXIsDirect(win_display, ctx_Handle)) {
|
|
||||||
Platform_LogConst("== WARNING: Context is not direct ==");
|
|
||||||
}
|
|
||||||
if (!glXMakeCurrent(win_display, win_handle, ctx_Handle)) {
|
|
||||||
Logger_Abort("Failed to make OpenGL context current.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* GLX may return non-null function pointers that don't actually work */
|
|
||||||
/* So we need to manually check the extensions string for support */
|
|
||||||
raw_exts = glXQueryExtensionsString(win_display, win_screen);
|
|
||||||
exts = String_FromReadonly(raw_exts);
|
|
||||||
|
|
||||||
if (String_CaselessContains(&exts, &ext_mesa)) {
|
|
||||||
swapIntervalMESA = (FN_GLXSWAPINTERVAL)GLContext_GetAddress("glXSwapIntervalMESA");
|
|
||||||
}
|
|
||||||
if (String_CaselessContains(&exts, &ext_sgi)) {
|
|
||||||
swapIntervalSGI = (FN_GLXSWAPINTERVAL)GLContext_GetAddress("glXSwapIntervalSGI");
|
|
||||||
}
|
|
||||||
ctx_supports_vSync = swapIntervalMESA || swapIntervalSGI;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLContext_Update(void) { }
|
|
||||||
void GLContext_Free(void) {
|
|
||||||
if (!ctx_Handle) return;
|
|
||||||
|
|
||||||
if (glXGetCurrentContext() == ctx_Handle) {
|
|
||||||
glXMakeCurrent(win_display, None, NULL);
|
|
||||||
}
|
|
||||||
glXDestroyContext(win_display, ctx_Handle);
|
|
||||||
ctx_Handle = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* GLContext_GetAddress(const char* function) {
|
|
||||||
void* address = glXGetProcAddress(function);
|
|
||||||
return GLContext_IsInvalidAddress(address) ? NULL : address;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLContext_SwapBuffers(void) {
|
|
||||||
glXSwapBuffers(win_display, win_handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLContext_SetVSync(bool enabled) {
|
|
||||||
int res;
|
|
||||||
if (!ctx_supports_vSync) return;
|
|
||||||
|
|
||||||
if (swapIntervalMESA) {
|
|
||||||
res = swapIntervalMESA(enabled);
|
|
||||||
} else {
|
|
||||||
res = swapIntervalSGI(enabled);
|
|
||||||
}
|
|
||||||
if (res) Platform_Log1("Set VSync failed, error: %i", &res);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void GLContext_GetAttribs(struct GraphicsMode* mode, int* attribs) {
|
|
||||||
int i = 0;
|
|
||||||
/* See http://www-01.ibm.com/support/knowledgecenter/ssw_aix_61/com.ibm.aix.opengl/doc/openglrf/glXChooseFBConfig.htm%23glxchoosefbconfig */
|
|
||||||
/* See http://www-01.ibm.com/support/knowledgecenter/ssw_aix_71/com.ibm.aix.opengl/doc/openglrf/glXChooseVisual.htm%23b5c84be452rree */
|
|
||||||
/* for the attribute declarations. Note that the attributes are different than those used in glxChooseVisual */
|
|
||||||
|
|
||||||
if (!mode->IsIndexed) { attribs[i++] = GLX_RGBA; }
|
|
||||||
attribs[i++] = GLX_RED_SIZE; attribs[i++] = mode->R;
|
|
||||||
attribs[i++] = GLX_GREEN_SIZE; attribs[i++] = mode->G;
|
|
||||||
attribs[i++] = GLX_BLUE_SIZE; attribs[i++] = mode->B;
|
|
||||||
attribs[i++] = GLX_ALPHA_SIZE; attribs[i++] = mode->A;
|
|
||||||
|
|
||||||
if (mode->DepthBits) {
|
|
||||||
attribs[i++] = GLX_DEPTH_SIZE; attribs[i++] = mode->DepthBits;
|
|
||||||
}
|
|
||||||
if (mode->StencilBits) {
|
|
||||||
attribs[i++] = GLX_STENCIL_SIZE; attribs[i++] = mode->StencilBits;
|
|
||||||
}
|
|
||||||
|
|
||||||
attribs[i++] = GLX_DOUBLEBUFFER;
|
|
||||||
attribs[i++] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static XVisualInfo GLContext_SelectVisual(struct GraphicsMode* mode) {
|
|
||||||
int attribs[20];
|
|
||||||
int major, minor;
|
|
||||||
XVisualInfo* visual = NULL;
|
|
||||||
|
|
||||||
int fbcount;
|
|
||||||
GLXFBConfig* fbconfigs;
|
|
||||||
XVisualInfo info;
|
|
||||||
|
|
||||||
GLContext_GetAttribs(mode, attribs);
|
|
||||||
if (!glXQueryVersion(win_display, &major, &minor)) {
|
|
||||||
Logger_Abort("glXQueryVersion failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (major >= 1 && minor >= 3) {
|
|
||||||
/* ChooseFBConfig returns an array of GLXFBConfig opaque structures */
|
|
||||||
fbconfigs = glXChooseFBConfig(win_display, win_screen, attribs, &fbcount);
|
|
||||||
if (fbconfigs && fbcount) {
|
|
||||||
/* Use the first GLXFBConfig from the fbconfigs array (best match) */
|
|
||||||
visual = glXGetVisualFromFBConfig(win_display, *fbconfigs);
|
|
||||||
XFree(fbconfigs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!visual) {
|
|
||||||
Platform_LogConst("Falling back to glXChooseVisual.");
|
|
||||||
visual = glXChooseVisual(win_display, win_screen, attribs);
|
|
||||||
}
|
|
||||||
if (!visual) {
|
|
||||||
Logger_Abort("Requested GraphicsMode not available.");
|
|
||||||
}
|
|
||||||
|
|
||||||
info = *visual;
|
|
||||||
XFree(visual);
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*########################################################################################################################*
|
/*########################################################################################################################*
|
||||||
*------------------------------------------------------Carbon window------------------------------------------------------*
|
*------------------------------------------------------Carbon window------------------------------------------------------*
|
||||||
*#########################################################################################################################*/
|
*#########################################################################################################################*/
|
||||||
#ifdef CC_BUILD_OSX
|
#ifdef CC_BUILD_CARBON
|
||||||
#include <AGL/agl.h>
|
|
||||||
#include <ApplicationServices/ApplicationServices.h>
|
#include <ApplicationServices/ApplicationServices.h>
|
||||||
|
|
||||||
static WindowRef win_handle;
|
static WindowRef win_handle;
|
||||||
@ -2402,179 +2180,6 @@ void Window_DrawRaw(Rect2D r) {
|
|||||||
CGImageRelease(win_image);
|
CGImageRelease(win_image);
|
||||||
CGDataProviderRelease(provider);
|
CGDataProviderRelease(provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*########################################################################################################################*
|
|
||||||
*-----------------------------------------------------OpenGL context------------------------------------------------------*
|
|
||||||
*#########################################################################################################################*/
|
|
||||||
static AGLContext ctx_handle;
|
|
||||||
static bool ctx_fullscreen, ctx_firstFullscreen;
|
|
||||||
static Rect2D ctx_windowedBounds;
|
|
||||||
|
|
||||||
static void GLContext_Check(int code, const char* place) {
|
|
||||||
ReturnCode res;
|
|
||||||
if (code) return;
|
|
||||||
|
|
||||||
res = aglGetError();
|
|
||||||
if (res) Logger_Abort2(res, place);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void GLContext_MakeCurrent(void) {
|
|
||||||
int code = aglSetCurrentContext(ctx_handle);
|
|
||||||
GLContext_Check(code, "Setting GL context");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void GLContext_SetDrawable(void) {
|
|
||||||
CGrafPtr windowPort = GetWindowPort(win_handle);
|
|
||||||
int code = aglSetDrawable(ctx_handle, windowPort);
|
|
||||||
GLContext_Check(code, "Attaching GL context");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void GLContext_GetAttribs(struct GraphicsMode* mode, int* attribs, bool fullscreen) {
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
if (!mode->IsIndexed) { attribs[i++] = AGL_RGBA; }
|
|
||||||
attribs[i++] = AGL_RED_SIZE; attribs[i++] = mode->R;
|
|
||||||
attribs[i++] = AGL_GREEN_SIZE; attribs[i++] = mode->G;
|
|
||||||
attribs[i++] = AGL_BLUE_SIZE; attribs[i++] = mode->B;
|
|
||||||
attribs[i++] = AGL_ALPHA_SIZE; attribs[i++] = mode->A;
|
|
||||||
|
|
||||||
if (mode->DepthBits) {
|
|
||||||
attribs[i++] = AGL_DEPTH_SIZE; attribs[i++] = mode->DepthBits;
|
|
||||||
}
|
|
||||||
if (mode->StencilBits) {
|
|
||||||
attribs[i++] = AGL_STENCIL_SIZE; attribs[i++] = mode->StencilBits;
|
|
||||||
}
|
|
||||||
|
|
||||||
attribs[i++] = AGL_DOUBLEBUFFER;
|
|
||||||
if (fullscreen) { attribs[i++] = AGL_FULLSCREEN; }
|
|
||||||
attribs[i++] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void GLContext_UnsetFullscreen(void) {
|
|
||||||
int code;
|
|
||||||
Platform_LogConst("Unsetting AGL fullscreen.");
|
|
||||||
|
|
||||||
code = aglSetDrawable(ctx_handle, NULL);
|
|
||||||
GLContext_Check(code, "Unattaching GL context");
|
|
||||||
code = aglUpdateContext(ctx_handle);
|
|
||||||
GLContext_Check(code, "Updating GL context (from Fullscreen)");
|
|
||||||
|
|
||||||
CGDisplayRelease(CGMainDisplayID());
|
|
||||||
GLContext_SetDrawable();
|
|
||||||
|
|
||||||
ctx_fullscreen = false;
|
|
||||||
Window_UpdateWindowState();
|
|
||||||
Window_SetSize(ctx_windowedBounds.Width, ctx_windowedBounds.Height);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void GLContext_SetFullscreen(void) {
|
|
||||||
int displayWidth = Display_Bounds.Width;
|
|
||||||
int displayHeight = Display_Bounds.Height;
|
|
||||||
int code;
|
|
||||||
|
|
||||||
Platform_LogConst("Switching to AGL fullscreen");
|
|
||||||
CGDisplayCapture(CGMainDisplayID());
|
|
||||||
|
|
||||||
code = aglSetFullScreen(ctx_handle, displayWidth, displayHeight, 0, 0);
|
|
||||||
GLContext_Check(code, "aglSetFullScreen");
|
|
||||||
GLContext_MakeCurrent();
|
|
||||||
|
|
||||||
/* This is a weird hack to workaround a bug where the first time a context */
|
|
||||||
/* is made fullscreen, we just end up with a blank screen. So we undo it as fullscreen */
|
|
||||||
/* and redo it as fullscreen. */
|
|
||||||
if (!ctx_firstFullscreen) {
|
|
||||||
ctx_firstFullscreen = true;
|
|
||||||
GLContext_UnsetFullscreen();
|
|
||||||
GLContext_SetFullscreen();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx_fullscreen = true;
|
|
||||||
ctx_windowedBounds = Window_ClientBounds;
|
|
||||||
|
|
||||||
Window_ClientBounds = Display_Bounds;
|
|
||||||
Window_Bounds = Display_Bounds;
|
|
||||||
win_state = WINDOW_STATE_FULLSCREEN;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLContext_Init(struct GraphicsMode* mode) {
|
|
||||||
int attribs[20];
|
|
||||||
AGLPixelFormat fmt;
|
|
||||||
GDHandle gdevice;
|
|
||||||
OSStatus res;
|
|
||||||
|
|
||||||
/* Initially try creating fullscreen compatible context */
|
|
||||||
res = DMGetGDeviceByDisplayID(CGMainDisplayID(), &gdevice, false);
|
|
||||||
if (res) Logger_Abort2(res, "Getting display device failed");
|
|
||||||
|
|
||||||
GLContext_GetAttribs(mode, attribs, true);
|
|
||||||
fmt = aglChoosePixelFormat(&gdevice, 1, attribs);
|
|
||||||
res = aglGetError();
|
|
||||||
|
|
||||||
/* Try again with non-compatible context if that fails */
|
|
||||||
if (!fmt || res == AGL_BAD_PIXELFMT) {
|
|
||||||
Platform_LogConst("Failed to create full screen pixel format.");
|
|
||||||
Platform_LogConst("Trying again to create a non-fullscreen pixel format.");
|
|
||||||
|
|
||||||
GLContext_GetAttribs(mode, attribs, false);
|
|
||||||
fmt = aglChoosePixelFormat(NULL, 0, attribs);
|
|
||||||
res = aglGetError();
|
|
||||||
}
|
|
||||||
if (res) Logger_Abort2(res, "Choosing pixel format");
|
|
||||||
|
|
||||||
ctx_handle = aglCreateContext(fmt, NULL);
|
|
||||||
GLContext_Check(0, "Creating GL context");
|
|
||||||
|
|
||||||
aglDestroyPixelFormat(fmt);
|
|
||||||
GLContext_Check(0, "Destroying pixel format");
|
|
||||||
|
|
||||||
GLContext_SetDrawable();
|
|
||||||
GLContext_Update();
|
|
||||||
GLContext_MakeCurrent();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLContext_Update(void) {
|
|
||||||
if (ctx_pendingFullscreen) {
|
|
||||||
ctx_pendingFullscreen = false;
|
|
||||||
GLContext_SetFullscreen();
|
|
||||||
return;
|
|
||||||
} else if (ctx_pendingWindowed) {
|
|
||||||
ctx_pendingWindowed = false;
|
|
||||||
GLContext_UnsetFullscreen();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctx_fullscreen) return;
|
|
||||||
GLContext_SetDrawable();
|
|
||||||
aglUpdateContext(ctx_handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLContext_Free(void) {
|
|
||||||
int code;
|
|
||||||
if (!ctx_handle) return;
|
|
||||||
|
|
||||||
code = aglSetCurrentContext(NULL);
|
|
||||||
GLContext_Check(code, "Unsetting GL context");
|
|
||||||
|
|
||||||
code = aglDestroyContext(ctx_handle);
|
|
||||||
GLContext_Check(code, "Destroying GL context");
|
|
||||||
ctx_handle = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* GLContext_GetAddress(const char* function) {
|
|
||||||
void* address = DynamicLib_GetFrom("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", function);
|
|
||||||
return GLContext_IsInvalidAddress(address) ? NULL : address;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLContext_SwapBuffers(void) {
|
|
||||||
aglSwapBuffers(ctx_handle);
|
|
||||||
GLContext_Check(0, "Swapping buffers");
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLContext_SetVSync(bool enabled) {
|
|
||||||
int value = enabled ? 1 : 0;
|
|
||||||
aglSetInteger(ctx_handle, AGL_SWAP_INTERVAL, &value);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -2910,8 +2515,432 @@ void Window_DrawRaw(Rect2D r) {
|
|||||||
SDL_UpdateWindowSurfaceRects(win_handle, &rect, 1);
|
SDL_UpdateWindowSurfaceRects(win_handle, &rect, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Window_EnableRawMouse(void) {
|
||||||
|
Window_RegrabMouse();
|
||||||
|
SDL_SetRelativeMouseMode(true);
|
||||||
|
win_rawMouse = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window_UpdateRawMouse(void) {
|
||||||
|
Window_CentreMousePosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window_DisableRawMouse(void) {
|
||||||
|
Window_RegrabMouse();
|
||||||
|
SDL_SetRelativeMouseMode(false);
|
||||||
|
win_rawMouse = false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifndef CC_BUILD_D3D9
|
#ifndef CC_BUILD_D3D9
|
||||||
|
/*########################################################################################################################*
|
||||||
|
*-------------------------------------------------------WGL OpenGL--------------------------------------------------------*
|
||||||
|
*#########################################################################################################################*/
|
||||||
|
#ifdef CC_BUILD_WGL
|
||||||
|
static HGLRC ctx_Handle;
|
||||||
|
static HDC ctx_DC;
|
||||||
|
typedef BOOL (WINAPI *FN_WGLSWAPINTERVAL)(int interval);
|
||||||
|
static FN_WGLSWAPINTERVAL wglSwapIntervalEXT;
|
||||||
|
static bool ctx_supports_vSync;
|
||||||
|
|
||||||
|
static void GLContext_SelectGraphicsMode(struct GraphicsMode* mode) {
|
||||||
|
PIXELFORMATDESCRIPTOR pfd = { 0 };
|
||||||
|
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
|
||||||
|
pfd.nVersion = 1;
|
||||||
|
pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER;
|
||||||
|
/* TODO: PFD_SUPPORT_COMPOSITION FLAG? CHECK IF IT WORKS ON XP */
|
||||||
|
pfd.cColorBits = mode->R + mode->G + mode->B;
|
||||||
|
|
||||||
|
pfd.iPixelType = mode->IsIndexed ? PFD_TYPE_COLORINDEX : PFD_TYPE_RGBA;
|
||||||
|
pfd.cRedBits = mode->R;
|
||||||
|
pfd.cGreenBits = mode->G;
|
||||||
|
pfd.cBlueBits = mode->B;
|
||||||
|
pfd.cAlphaBits = mode->A;
|
||||||
|
|
||||||
|
pfd.cDepthBits = mode->DepthBits;
|
||||||
|
pfd.cStencilBits = mode->StencilBits;
|
||||||
|
|
||||||
|
int modeIndex = ChoosePixelFormat(win_DC, &pfd);
|
||||||
|
if (modeIndex == 0) { Logger_Abort("Requested graphics mode not available"); }
|
||||||
|
|
||||||
|
Mem_Set(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
|
||||||
|
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
|
||||||
|
pfd.nVersion = 1;
|
||||||
|
|
||||||
|
DescribePixelFormat(win_DC, modeIndex, pfd.nSize, &pfd);
|
||||||
|
if (!SetPixelFormat(win_DC, modeIndex, &pfd)) {
|
||||||
|
Logger_Abort2(GetLastError(), "SetPixelFormat failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLContext_Init(struct GraphicsMode* mode) {
|
||||||
|
GLContext_SelectGraphicsMode(mode);
|
||||||
|
ctx_Handle = wglCreateContext(win_DC);
|
||||||
|
if (!ctx_Handle) {
|
||||||
|
ctx_Handle = wglCreateContext(win_DC);
|
||||||
|
}
|
||||||
|
if (!ctx_Handle) {
|
||||||
|
Logger_Abort2(GetLastError(), "Failed to create OpenGL context");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wglMakeCurrent(win_DC, ctx_Handle)) {
|
||||||
|
Logger_Abort2(GetLastError(), "Failed to make OpenGL context current");
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx_DC = wglGetCurrentDC();
|
||||||
|
wglSwapIntervalEXT = (FN_WGLSWAPINTERVAL)GLContext_GetAddress("wglSwapIntervalEXT");
|
||||||
|
ctx_supports_vSync = wglSwapIntervalEXT != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLContext_Update(void) { }
|
||||||
|
void GLContext_Free(void) {
|
||||||
|
if (!wglDeleteContext(ctx_Handle)) {
|
||||||
|
Logger_Abort2(GetLastError(), "Failed to destroy OpenGL context");
|
||||||
|
}
|
||||||
|
ctx_Handle = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* GLContext_GetAddress(const char* function) {
|
||||||
|
void* address = wglGetProcAddress(function);
|
||||||
|
return GLContext_IsInvalidAddress(address) ? NULL : address;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLContext_SwapBuffers(void) {
|
||||||
|
if (!SwapBuffers(ctx_DC)) {
|
||||||
|
Logger_Abort2(GetLastError(), "Failed to swap buffers");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLContext_SetVSync(bool enabled) {
|
||||||
|
if (ctx_supports_vSync) wglSwapIntervalEXT(enabled);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*########################################################################################################################*
|
||||||
|
*-------------------------------------------------------glX OpenGL--------------------------------------------------------*
|
||||||
|
*#########################################################################################################################*/
|
||||||
|
#ifdef CC_BUILD_GLX
|
||||||
|
#include <GL/glx.h>
|
||||||
|
static GLXContext ctx_Handle;
|
||||||
|
typedef int (*FN_GLXSWAPINTERVAL)(int interval);
|
||||||
|
static FN_GLXSWAPINTERVAL swapIntervalMESA, swapIntervalSGI;
|
||||||
|
static bool ctx_supports_vSync;
|
||||||
|
|
||||||
|
void GLContext_Init(struct GraphicsMode* mode) {
|
||||||
|
const static String ext_mesa = String_FromConst("GLX_MESA_swap_control");
|
||||||
|
const static String ext_sgi = String_FromConst("GLX_SGI_swap_control");
|
||||||
|
|
||||||
|
const char* raw_exts;
|
||||||
|
String exts;
|
||||||
|
ctx_Handle = glXCreateContext(win_display, &win_visual, NULL, true);
|
||||||
|
|
||||||
|
if (!ctx_Handle) {
|
||||||
|
Platform_LogConst("Context create failed. Trying indirect...");
|
||||||
|
ctx_Handle = glXCreateContext(win_display, &win_visual, NULL, false);
|
||||||
|
}
|
||||||
|
if (!ctx_Handle) Logger_Abort("Failed to create OpenGL context");
|
||||||
|
|
||||||
|
if (!glXIsDirect(win_display, ctx_Handle)) {
|
||||||
|
Platform_LogConst("== WARNING: Context is not direct ==");
|
||||||
|
}
|
||||||
|
if (!glXMakeCurrent(win_display, win_handle, ctx_Handle)) {
|
||||||
|
Logger_Abort("Failed to make OpenGL context current.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* GLX may return non-null function pointers that don't actually work */
|
||||||
|
/* So we need to manually check the extensions string for support */
|
||||||
|
raw_exts = glXQueryExtensionsString(win_display, win_screen);
|
||||||
|
exts = String_FromReadonly(raw_exts);
|
||||||
|
|
||||||
|
if (String_CaselessContains(&exts, &ext_mesa)) {
|
||||||
|
swapIntervalMESA = (FN_GLXSWAPINTERVAL)GLContext_GetAddress("glXSwapIntervalMESA");
|
||||||
|
}
|
||||||
|
if (String_CaselessContains(&exts, &ext_sgi)) {
|
||||||
|
swapIntervalSGI = (FN_GLXSWAPINTERVAL)GLContext_GetAddress("glXSwapIntervalSGI");
|
||||||
|
}
|
||||||
|
ctx_supports_vSync = swapIntervalMESA || swapIntervalSGI;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLContext_Update(void) { }
|
||||||
|
void GLContext_Free(void) {
|
||||||
|
if (!ctx_Handle) return;
|
||||||
|
|
||||||
|
if (glXGetCurrentContext() == ctx_Handle) {
|
||||||
|
glXMakeCurrent(win_display, None, NULL);
|
||||||
|
}
|
||||||
|
glXDestroyContext(win_display, ctx_Handle);
|
||||||
|
ctx_Handle = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* GLContext_GetAddress(const char* function) {
|
||||||
|
void* address = glXGetProcAddress(function);
|
||||||
|
return GLContext_IsInvalidAddress(address) ? NULL : address;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLContext_SwapBuffers(void) {
|
||||||
|
glXSwapBuffers(win_display, win_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLContext_SetVSync(bool enabled) {
|
||||||
|
int res;
|
||||||
|
if (!ctx_supports_vSync) return;
|
||||||
|
|
||||||
|
if (swapIntervalMESA) {
|
||||||
|
res = swapIntervalMESA(enabled);
|
||||||
|
} else {
|
||||||
|
res = swapIntervalSGI(enabled);
|
||||||
|
}
|
||||||
|
if (res) Platform_Log1("Set VSync failed, error: %i", &res);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void GLContext_GetAttribs(struct GraphicsMode* mode, int* attribs) {
|
||||||
|
int i = 0;
|
||||||
|
/* See http://www-01.ibm.com/support/knowledgecenter/ssw_aix_61/com.ibm.aix.opengl/doc/openglrf/glXChooseFBConfig.htm%23glxchoosefbconfig */
|
||||||
|
/* See http://www-01.ibm.com/support/knowledgecenter/ssw_aix_71/com.ibm.aix.opengl/doc/openglrf/glXChooseVisual.htm%23b5c84be452rree */
|
||||||
|
/* for the attribute declarations. Note that the attributes are different than those used in glxChooseVisual */
|
||||||
|
|
||||||
|
if (!mode->IsIndexed) { attribs[i++] = GLX_RGBA; }
|
||||||
|
attribs[i++] = GLX_RED_SIZE; attribs[i++] = mode->R;
|
||||||
|
attribs[i++] = GLX_GREEN_SIZE; attribs[i++] = mode->G;
|
||||||
|
attribs[i++] = GLX_BLUE_SIZE; attribs[i++] = mode->B;
|
||||||
|
attribs[i++] = GLX_ALPHA_SIZE; attribs[i++] = mode->A;
|
||||||
|
|
||||||
|
if (mode->DepthBits) {
|
||||||
|
attribs[i++] = GLX_DEPTH_SIZE; attribs[i++] = mode->DepthBits;
|
||||||
|
}
|
||||||
|
if (mode->StencilBits) {
|
||||||
|
attribs[i++] = GLX_STENCIL_SIZE; attribs[i++] = mode->StencilBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
attribs[i++] = GLX_DOUBLEBUFFER;
|
||||||
|
attribs[i++] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static XVisualInfo GLContext_SelectVisual(struct GraphicsMode* mode) {
|
||||||
|
int attribs[20];
|
||||||
|
int major, minor;
|
||||||
|
XVisualInfo* visual = NULL;
|
||||||
|
|
||||||
|
int fbcount;
|
||||||
|
GLXFBConfig* fbconfigs;
|
||||||
|
XVisualInfo info;
|
||||||
|
|
||||||
|
GLContext_GetAttribs(mode, attribs);
|
||||||
|
if (!glXQueryVersion(win_display, &major, &minor)) {
|
||||||
|
Logger_Abort("glXQueryVersion failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (major >= 1 && minor >= 3) {
|
||||||
|
/* ChooseFBConfig returns an array of GLXFBConfig opaque structures */
|
||||||
|
fbconfigs = glXChooseFBConfig(win_display, win_screen, attribs, &fbcount);
|
||||||
|
if (fbconfigs && fbcount) {
|
||||||
|
/* Use the first GLXFBConfig from the fbconfigs array (best match) */
|
||||||
|
visual = glXGetVisualFromFBConfig(win_display, *fbconfigs);
|
||||||
|
XFree(fbconfigs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!visual) {
|
||||||
|
Platform_LogConst("Falling back to glXChooseVisual.");
|
||||||
|
visual = glXChooseVisual(win_display, win_screen, attribs);
|
||||||
|
}
|
||||||
|
if (!visual) {
|
||||||
|
Logger_Abort("Requested GraphicsMode not available.");
|
||||||
|
}
|
||||||
|
|
||||||
|
info = *visual;
|
||||||
|
XFree(visual);
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*########################################################################################################################*
|
||||||
|
*-------------------------------------------------------AGL OpenGL--------------------------------------------------------*
|
||||||
|
*#########################################################################################################################*/
|
||||||
|
#ifdef CC_BUILD_AGL
|
||||||
|
#include <AGL/agl.h>
|
||||||
|
|
||||||
|
static AGLContext ctx_handle;
|
||||||
|
static bool ctx_fullscreen, ctx_firstFullscreen;
|
||||||
|
static Rect2D ctx_windowedBounds;
|
||||||
|
|
||||||
|
static void GLContext_Check(int code, const char* place) {
|
||||||
|
ReturnCode res;
|
||||||
|
if (code) return;
|
||||||
|
|
||||||
|
res = aglGetError();
|
||||||
|
if (res) Logger_Abort2(res, place);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void GLContext_MakeCurrent(void) {
|
||||||
|
int code = aglSetCurrentContext(ctx_handle);
|
||||||
|
GLContext_Check(code, "Setting GL context");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void GLContext_SetDrawable(void) {
|
||||||
|
CGrafPtr windowPort = GetWindowPort(win_handle);
|
||||||
|
int code = aglSetDrawable(ctx_handle, windowPort);
|
||||||
|
GLContext_Check(code, "Attaching GL context");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void GLContext_GetAttribs(struct GraphicsMode* mode, int* attribs, bool fullscreen) {
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
if (!mode->IsIndexed) { attribs[i++] = AGL_RGBA; }
|
||||||
|
attribs[i++] = AGL_RED_SIZE; attribs[i++] = mode->R;
|
||||||
|
attribs[i++] = AGL_GREEN_SIZE; attribs[i++] = mode->G;
|
||||||
|
attribs[i++] = AGL_BLUE_SIZE; attribs[i++] = mode->B;
|
||||||
|
attribs[i++] = AGL_ALPHA_SIZE; attribs[i++] = mode->A;
|
||||||
|
|
||||||
|
if (mode->DepthBits) {
|
||||||
|
attribs[i++] = AGL_DEPTH_SIZE; attribs[i++] = mode->DepthBits;
|
||||||
|
}
|
||||||
|
if (mode->StencilBits) {
|
||||||
|
attribs[i++] = AGL_STENCIL_SIZE; attribs[i++] = mode->StencilBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
attribs[i++] = AGL_DOUBLEBUFFER;
|
||||||
|
if (fullscreen) { attribs[i++] = AGL_FULLSCREEN; }
|
||||||
|
attribs[i++] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void GLContext_UnsetFullscreen(void) {
|
||||||
|
int code;
|
||||||
|
Platform_LogConst("Unsetting AGL fullscreen.");
|
||||||
|
|
||||||
|
code = aglSetDrawable(ctx_handle, NULL);
|
||||||
|
GLContext_Check(code, "Unattaching GL context");
|
||||||
|
code = aglUpdateContext(ctx_handle);
|
||||||
|
GLContext_Check(code, "Updating GL context (from Fullscreen)");
|
||||||
|
|
||||||
|
CGDisplayRelease(CGMainDisplayID());
|
||||||
|
GLContext_SetDrawable();
|
||||||
|
|
||||||
|
ctx_fullscreen = false;
|
||||||
|
Window_UpdateWindowState();
|
||||||
|
Window_SetSize(ctx_windowedBounds.Width, ctx_windowedBounds.Height);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void GLContext_SetFullscreen(void) {
|
||||||
|
int displayWidth = Display_Bounds.Width;
|
||||||
|
int displayHeight = Display_Bounds.Height;
|
||||||
|
int code;
|
||||||
|
|
||||||
|
Platform_LogConst("Switching to AGL fullscreen");
|
||||||
|
CGDisplayCapture(CGMainDisplayID());
|
||||||
|
|
||||||
|
code = aglSetFullScreen(ctx_handle, displayWidth, displayHeight, 0, 0);
|
||||||
|
GLContext_Check(code, "aglSetFullScreen");
|
||||||
|
GLContext_MakeCurrent();
|
||||||
|
|
||||||
|
/* This is a weird hack to workaround a bug where the first time a context */
|
||||||
|
/* is made fullscreen, we just end up with a blank screen. So we undo it as fullscreen */
|
||||||
|
/* and redo it as fullscreen. */
|
||||||
|
if (!ctx_firstFullscreen) {
|
||||||
|
ctx_firstFullscreen = true;
|
||||||
|
GLContext_UnsetFullscreen();
|
||||||
|
GLContext_SetFullscreen();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx_fullscreen = true;
|
||||||
|
ctx_windowedBounds = Window_ClientBounds;
|
||||||
|
|
||||||
|
Window_ClientBounds = Display_Bounds;
|
||||||
|
Window_Bounds = Display_Bounds;
|
||||||
|
win_state = WINDOW_STATE_FULLSCREEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLContext_Init(struct GraphicsMode* mode) {
|
||||||
|
int attribs[20];
|
||||||
|
AGLPixelFormat fmt;
|
||||||
|
GDHandle gdevice;
|
||||||
|
OSStatus res;
|
||||||
|
|
||||||
|
/* Initially try creating fullscreen compatible context */
|
||||||
|
res = DMGetGDeviceByDisplayID(CGMainDisplayID(), &gdevice, false);
|
||||||
|
if (res) Logger_Abort2(res, "Getting display device failed");
|
||||||
|
|
||||||
|
GLContext_GetAttribs(mode, attribs, true);
|
||||||
|
fmt = aglChoosePixelFormat(&gdevice, 1, attribs);
|
||||||
|
res = aglGetError();
|
||||||
|
|
||||||
|
/* Try again with non-compatible context if that fails */
|
||||||
|
if (!fmt || res == AGL_BAD_PIXELFMT) {
|
||||||
|
Platform_LogConst("Failed to create full screen pixel format.");
|
||||||
|
Platform_LogConst("Trying again to create a non-fullscreen pixel format.");
|
||||||
|
|
||||||
|
GLContext_GetAttribs(mode, attribs, false);
|
||||||
|
fmt = aglChoosePixelFormat(NULL, 0, attribs);
|
||||||
|
res = aglGetError();
|
||||||
|
}
|
||||||
|
if (res) Logger_Abort2(res, "Choosing pixel format");
|
||||||
|
|
||||||
|
ctx_handle = aglCreateContext(fmt, NULL);
|
||||||
|
GLContext_Check(0, "Creating GL context");
|
||||||
|
|
||||||
|
aglDestroyPixelFormat(fmt);
|
||||||
|
GLContext_Check(0, "Destroying pixel format");
|
||||||
|
|
||||||
|
GLContext_SetDrawable();
|
||||||
|
GLContext_Update();
|
||||||
|
GLContext_MakeCurrent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLContext_Update(void) {
|
||||||
|
if (ctx_pendingFullscreen) {
|
||||||
|
ctx_pendingFullscreen = false;
|
||||||
|
GLContext_SetFullscreen();
|
||||||
|
return;
|
||||||
|
} else if (ctx_pendingWindowed) {
|
||||||
|
ctx_pendingWindowed = false;
|
||||||
|
GLContext_UnsetFullscreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx_fullscreen) return;
|
||||||
|
GLContext_SetDrawable();
|
||||||
|
aglUpdateContext(ctx_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLContext_Free(void) {
|
||||||
|
int code;
|
||||||
|
if (!ctx_handle) return;
|
||||||
|
|
||||||
|
code = aglSetCurrentContext(NULL);
|
||||||
|
GLContext_Check(code, "Unsetting GL context");
|
||||||
|
|
||||||
|
code = aglDestroyContext(ctx_handle);
|
||||||
|
GLContext_Check(code, "Destroying GL context");
|
||||||
|
ctx_handle = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* GLContext_GetAddress(const char* function) {
|
||||||
|
void* address = DynamicLib_GetFrom("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", function);
|
||||||
|
return GLContext_IsInvalidAddress(address) ? NULL : address;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLContext_SwapBuffers(void) {
|
||||||
|
aglSwapBuffers(ctx_handle);
|
||||||
|
GLContext_Check(0, "Swapping buffers");
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLContext_SetVSync(bool enabled) {
|
||||||
|
int value = enabled ? 1 : 0;
|
||||||
|
aglSetInteger(ctx_handle, AGL_SWAP_INTERVAL, &value);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*########################################################################################################################*
|
||||||
|
*-------------------------------------------------------SDL OpenGL--------------------------------------------------------*
|
||||||
|
*#########################################################################################################################*/
|
||||||
|
#ifdef CC_BUILD_SDL
|
||||||
|
#include <SDL2/SDL.h>
|
||||||
static SDL_GLContext win_ctx;
|
static SDL_GLContext win_ctx;
|
||||||
|
|
||||||
void GLContext_Init(struct GraphicsMode* mode) {
|
void GLContext_Init(struct GraphicsMode* mode) {
|
||||||
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, mode->R);
|
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, mode->R);
|
||||||
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, mode->G);
|
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, mode->G);
|
||||||
@ -2944,20 +2973,4 @@ void GLContext_SetVSync(bool enabled) {
|
|||||||
SDL_GL_SetSwapInterval(enabled);
|
SDL_GL_SetSwapInterval(enabled);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void Window_EnableRawMouse(void) {
|
|
||||||
Window_RegrabMouse();
|
|
||||||
SDL_SetRelativeMouseMode(true);
|
|
||||||
win_rawMouse = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window_UpdateRawMouse(void) {
|
|
||||||
Window_CentreMousePosition();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window_DisableRawMouse(void) {
|
|
||||||
Window_RegrabMouse();
|
|
||||||
SDL_SetRelativeMouseMode(false);
|
|
||||||
win_rawMouse = false;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
Loading…
x
Reference in New Issue
Block a user