From db577bb01f5488e1dfa441a0826cd06916e36823 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Wed, 4 Mar 2026 22:56:04 -0700 Subject: [PATCH] mac opengl support. proper coordinate flipping --- examples/gldemos/cube.c | 113 +++---- include/Mw/LowLevel/Cocoa.h | 1 + include/Mw/Widget/OpenGL.h | 21 +- pl/rules.pl | 9 +- src/backend/cocoa.m | 80 +++-- src/widget/opengl.c | 590 +++++++++++++++++++----------------- src/widget/opengl_cocoa.m | 128 ++++++++ 7 files changed, 581 insertions(+), 361 deletions(-) create mode 100644 src/widget/opengl_cocoa.m diff --git a/examples/gldemos/cube.c b/examples/gldemos/cube.c index c1ba991..2d1954c 100644 --- a/examples/gldemos/cube.c +++ b/examples/gldemos/cube.c @@ -1,78 +1,89 @@ #define TITLE "cube" #include "glutlayer.c" +#if defined(__APPLE__) +#include +#include +#else +#include #include +#endif static double deg = 0; static void draw(void) { - int i; - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + int i; + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glPushMatrix(); - glRotatef(deg, 1, 0, 0); - glRotatef(deg, 0, 1, 0); - glRotatef(deg, 0, 0, 1); + glPushMatrix(); + glRotatef(deg, 1, 0, 0); + glRotatef(deg, 0, 1, 0); + glRotatef(deg, 0, 0, 1); - for(i = 0; i < 6; i++) { - if(i == 0) glColor3f(1, 0, 0); - if(i == 1) glColor3f(0, 1, 0); - if(i == 2) glColor3f(1, 1, 0); - if(i == 3) glColor3f(0, 0, 1); - if(i == 4) glColor3f(1, 0, 1); - if(i == 5) glColor3f(0, 1, 1); + for (i = 0; i < 6; i++) { + if (i == 0) + glColor3f(1, 0, 0); + if (i == 1) + glColor3f(0, 1, 0); + if (i == 2) + glColor3f(1, 1, 0); + if (i == 3) + glColor3f(0, 0, 1); + if (i == 4) + glColor3f(1, 0, 1); + if (i == 5) + glColor3f(0, 1, 1); - glBegin(GL_QUADS); - glNormal3f(0, 1, 0); - glVertex3f(-1, 1, -1); - glVertex3f(-1, 1, 1); - glVertex3f(1, 1, 1); - glVertex3f(1, 1, -1); - glEnd(); + glBegin(GL_QUADS); + glNormal3f(0, 1, 0); + glVertex3f(-1, 1, -1); + glVertex3f(-1, 1, 1); + glVertex3f(1, 1, 1); + glVertex3f(1, 1, -1); + glEnd(); - if(i < 3) glRotatef(90, 0, 0, 1); - if(i == 3) glRotatef(90, 1, 0, 0); - if(i == 4) glRotatef(180, 0, 0, 1); - } - glPopMatrix(); + if (i < 3) + glRotatef(90, 0, 0, 1); + if (i == 3) + glRotatef(90, 1, 0, 0); + if (i == 4) + glRotatef(180, 0, 0, 1); + } + glPopMatrix(); } -static void idle(void) { - deg += 1.0; -} +static void idle(void) { deg += 1.0; } static void reshape(int width, int height) { - GLfloat lpos[4]; + GLfloat lpos[4]; - lpos[0] = 1; - lpos[1] = 1; - lpos[2] = 1; - lpos[3] = 0; + lpos[0] = 1; + lpos[1] = 1; + lpos[2] = 1; + lpos[3] = 0; - glViewport(0, 0, width, height); + glViewport(0, 0, width, height); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - gluPerspective(60, (double)width / height, 1, 100); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(60, (double)width / height, 1, 100); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - gluLookAt(2, 2, 2, 0, 0, 0, 0, 1, 0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt(2, 2, 2, 0, 0, 0, 0, 1, 0); - glLightfv(GL_LIGHT0, GL_POSITION, lpos); + glLightfv(GL_LIGHT0, GL_POSITION, lpos); } static void init(void) { - glEnable(GL_DEPTH_TEST); - glEnable(GL_LIGHTING); - glEnable(GL_LIGHT0); - glEnable(GL_COLOR_MATERIAL); - glEnable(GL_CULL_FACE); - glEnable(GL_NORMALIZE); + glEnable(GL_DEPTH_TEST); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_COLOR_MATERIAL); + glEnable(GL_CULL_FACE); + glEnable(GL_NORMALIZE); - glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); + glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); } -static void key(int k) { - (void)k; -} +static void key(int k) { (void)k; } diff --git a/include/Mw/LowLevel/Cocoa.h b/include/Mw/LowLevel/Cocoa.h index a36dbfd..91679db 100644 --- a/include/Mw/LowLevel/Cocoa.h +++ b/include/Mw/LowLevel/Cocoa.h @@ -119,6 +119,7 @@ - (void)destroy; - (NSWindow *)parentWindow; +- (NSView *)getView; @end #define OBJC(x) x diff --git a/include/Mw/Widget/OpenGL.h b/include/Mw/Widget/OpenGL.h index 26f44ab..c3fab76 100644 --- a/include/Mw/Widget/OpenGL.h +++ b/include/Mw/Widget/OpenGL.h @@ -5,17 +5,24 @@ #ifndef __MW_WIDGET_OPENGL_H__ #define __MW_WIDGET_OPENGL_H__ +#include #include #include -#include #if !defined(MW_OPENGL_NO_INCLUDE) && !defined(__gl_h_) #ifdef _WIN32 #include +#elif defined(__APPLE__) #else #include #endif +#if defined(__APPLE__) +#include +#include +#else #include +#include +#endif #ifndef GLAPIENTRY #define GLAPIENTRY APIENTRY @@ -36,7 +43,7 @@ MWDECL MwClass MwOpenGLClass; * @param handle Widget */ MwInline void MwOpenGLMakeCurrent(MwWidget handle) { - MwVaWidgetExecute(handle, "mwOpenGLMakeCurrent", NULL); + MwVaWidgetExecute(handle, "mwOpenGLMakeCurrent", NULL); } /*! @@ -45,10 +52,10 @@ MwInline void MwOpenGLMakeCurrent(MwWidget handle) { * @param name Name * @return Procedure */ -MwInline void* MwOpenGLGetProcAddress(MwWidget handle, const char* name) { - void* out; - MwVaWidgetExecute(handle, "mwOpenGLGetProcAddress", &out, name); - return out; +MwInline void *MwOpenGLGetProcAddress(MwWidget handle, const char *name) { + void *out; + MwVaWidgetExecute(handle, "mwOpenGLGetProcAddress", &out, name); + return out; } /*! @@ -56,7 +63,7 @@ MwInline void* MwOpenGLGetProcAddress(MwWidget handle, const char* name) { * @param handle Widget */ MwInline void MwOpenGLSwapBuffer(MwWidget handle) { - MwVaWidgetExecute(handle, "mwOpenGLSwapBuffer", NULL); + MwVaWidgetExecute(handle, "mwOpenGLSwapBuffer", NULL); } #ifdef __cplusplus diff --git a/pl/rules.pl b/pl/rules.pl index d4784e1..45bb6da 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -50,7 +50,14 @@ if (grep(/^cocoa$/, @backends)) { add_cflags("-DUSE_COCOA"); new_object("src/backend/cocoa.m"); - $gl_libs = "-lGL -lGLU"; + if (param_get("opengl")) { + new_object("src/widget/opengl_cocoa.m"); + } + + # tim cook my man literally everybody and their mother who knows what opengl is knows its deprecated on macos and i'm not having you spam the console with this + add_cflags("-DGL_SILENCE_DEPRECATION"); + + $gl_libs = "-framework OpenGL"; } if (param_get("stb-image")) { diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index 23e9373..700ebdb 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -3,6 +3,29 @@ #pragma clang push #pragma clang diagnostic ignored "-Wdeprecated-declarations" +static CGRect rectFlip(CGRect originFrame) { + NSScreen *zeroScreen = NSScreen.screens[0]; + double screenHeight = zeroScreen.frame.size.height; + double originY = originFrame.origin.y; + double frameHeight = originFrame.size.height; + double destinationY = screenHeight - (originY + frameHeight); + CGRect destinationFrame = originFrame; + destinationFrame.origin.y = destinationY; + if (destinationFrame.origin.x < 0) + destinationFrame.origin.x = 0; + if (destinationFrame.origin.y < 0) + destinationFrame.origin.y = 0; + if (destinationFrame.size.width < 0) + destinationFrame.size.width = 0; + if (destinationFrame.size.height < 0) + destinationFrame.size.height = 0; + return destinationFrame; +} + +static CGPoint pointFlip(CGPoint point) { + return rectFlip(NSMakeRect(point.x, point.y, 0, 0)).origin; +} + @implementation MilskoCocoaPixmap + (MilskoCocoaPixmap *)newWithWidth:(int)width height:(int)height { @@ -70,8 +93,7 @@ centerY = true; } c->application = [NSApplication sharedApplication]; - - c->rect = NSMakeRect(x, y, width, height); + c->rect = rectFlip(NSMakeRect(x, y, width, height)); if (parent == NULL) { c->window = [[NSWindow alloc] @@ -81,12 +103,12 @@ backing:NSBackingStoreBuffered defer:NO]; } else { + double offset = 0; NSWindow *parentWindow = parent->cocoa.real->window; - - c->rect = [parentWindow frameRectForContentRect:c->rect]; - c->rect.origin.y = - y - + offset = + [parentWindow frameRectForContentRect:parentWindow.frame].size.height - [parentWindow contentRectForFrameRect:parentWindow.frame].size.height; + c->rect.origin.y -= offset; c->window = [[NSWindow alloc] initWithContentRect:c->rect styleMask:NSBorderlessWindowMask @@ -160,10 +182,10 @@ - (void)lineWithPoints:(MwPoint *)points color:(MwLLColor)color { }; - (void)getX:(int *)x Y:(int *)y W:(unsigned int *)w H:(unsigned int *)h { - NSRect frame = [self->window frame]; + NSRect frame = rectFlip([self->window frame]); *x = frame.origin.x; - *y = frame.origin.y - frame.size.height; + *y = frame.origin.y; *w = frame.size.width; *h = frame.size.height; @@ -174,12 +196,17 @@ frame.origin.x = x; frame.origin.y = y; - if (self->parent) { - NSWindow *parentWindow = [self parentWindow]; - NSRect correctedFrame = - [parentWindow contentRectForFrameRect:parentWindow.frame]; - frame.origin.y = (correctedFrame.size.height - y); + frame = rectFlip(frame); + + if (parent) { + double offset = 0; + NSWindow *parentWindow = parent->cocoa.real->window; + offset = + [parentWindow frameRectForContentRect:parentWindow.frame].size.height - + [parentWindow contentRectForFrameRect:parentWindow.frame].size.height; + frame.origin.y -= offset; } + [self->view setFrameSize:frame.size]; [self->window setFrame:frame display:YES animate:false]; }; @@ -187,8 +214,10 @@ NSRect frame = [self->window frame]; frame.size.width = w; frame.size.height = h; + self->rect = frame; + [self->view setFrameSize:frame.size]; [self->window setFrame:frame display:YES animate:false]; }; - (int)pending { @@ -207,10 +236,6 @@ if (self->lastEvent != nil) { NSWindow *win = [self->lastEvent window]; NSWindow *parentWindow = [self parentWindow]; - NSRect realFrame = parentWindow.frame; - NSRect correctedFrame = - [parentWindow frameRectForContentRect:parentWindow.frame]; - CGFloat offset = realFrame.size.height - correctedFrame.size.height; MwLL h; if ([win contentView].subviews.count == 0) { @@ -228,6 +253,7 @@ case NSEventTypeOtherMouseUp: { MwLLMouse mouse = {}; MwBool isDown = MwTRUE; + CGPoint mousePoint = pointFlip([lastEvent locationInWindow]); switch (self->lastEvent.type) { case NSEventTypeLeftMouseUp: isDown = MwFALSE; @@ -247,9 +273,8 @@ default: break; } - mouse.point.x = [lastEvent locationInWindow].x; - mouse.point.y = [win contentRectForFrameRect:win.frame].size.height - - [lastEvent locationInWindow].y; + mouse.point.x = mousePoint.x; + mouse.point.y = mousePoint.y; if (isDown) { MwLLDispatch(h, down, &mouse); @@ -428,6 +453,10 @@ topmostWindow = topmostWindow.parentWindow; return topmostWindow; } + +- (NSView *)getView { + return view; +} @end @implementation MilskoCocoaView @@ -471,13 +500,13 @@ } - (void)drawRect:(NSRect)dirtyRect { - NSSize sz = [self->rep size]; + NSSize sz = self->rep.size; [super drawRect:dirtyRect]; if (!self->rep) { return; } - [self->rep drawInRect:NSMakeRect(0, 0, width, height)]; + [self->rep drawInRect:NSMakeRect(0, 0, sz.width, sz.height)]; [self->rep bitmapData]; } @@ -488,12 +517,7 @@ - (void)setFrameSize:(NSSize)newSize { [super setFrameSize:newSize]; - if (newSize.width != 0 && newSize.height != 0) { - // [self->rep setSize:newSize]; - // width = newSize.width; - // height = newSize.height; - // [self->context setImageInterpolation:NSImageInterpolationHigh]; - } + [self->rep setSize:newSize]; } - (void)displayRect:(NSRect)rect { diff --git a/src/widget/opengl.c b/src/widget/opengl.c index ae87817..0f9c5c2 100644 --- a/src/widget/opengl.c +++ b/src/widget/opengl.c @@ -1,44 +1,49 @@ +#ifndef __APPLE__ + #include #include #ifdef USE_GDI -typedef HGLRC(WINAPI* MWwglCreateContext)(HDC); -typedef BOOL(WINAPI* MWwglMakeCurrent)(HDC, HGLRC); -typedef PROC(WINAPI* MWwglGetProcAddress)(LPCSTR); -typedef BOOL(WINAPI* MWwglDeleteContext)(HGLRC); +typedef HGLRC(WINAPI *MWwglCreateContext)(HDC); +typedef BOOL(WINAPI *MWwglMakeCurrent)(HDC, HGLRC); +typedef PROC(WINAPI *MWwglGetProcAddress)(LPCSTR); +typedef BOOL(WINAPI *MWwglDeleteContext)(HGLRC); typedef struct gdiopengl { - HDC dc; - HGLRC gl; + HDC dc; + HGLRC gl; - void* lib; + void *lib; - MWwglCreateContext wglCreateContext; - MWwglMakeCurrent wglMakeCurrent; - MWwglDeleteContext wglDeleteContext; - MWwglGetProcAddress wglGetProcAddress; + MWwglCreateContext wglCreateContext; + MWwglMakeCurrent wglMakeCurrent; + MWwglDeleteContext wglDeleteContext; + MWwglGetProcAddress wglGetProcAddress; } gdiopengl_t; #endif #ifdef USE_X11 -typedef XVisualInfo* (*MWglXChooseVisual)(Display* dpy, int screen, int* attribList); -typedef GLXContext (*MWglXCreateContext)(Display* dpy, XVisualInfo* vis, GLXContext shareList, Bool direct); -typedef void (*MWglXDestroyContext)(Display* dpy, GLXContext ctx); -typedef Bool (*MWglXMakeCurrent)(Display* dpy, GLXDrawable drawable, GLXContext ctx); -typedef void (*MWglXSwapBuffers)(Display* dpy, GLXDrawable drawable); -typedef void* (*MWglXGetProcAddress)(const GLubyte* procname); +typedef XVisualInfo *(*MWglXChooseVisual)(Display *dpy, int screen, + int *attribList); +typedef GLXContext (*MWglXCreateContext)(Display *dpy, XVisualInfo *vis, + GLXContext shareList, Bool direct); +typedef void (*MWglXDestroyContext)(Display *dpy, GLXContext ctx); +typedef Bool (*MWglXMakeCurrent)(Display *dpy, GLXDrawable drawable, + GLXContext ctx); +typedef void (*MWglXSwapBuffers)(Display *dpy, GLXDrawable drawable); +typedef void *(*MWglXGetProcAddress)(const GLubyte *procname); typedef struct x11opengl { - XVisualInfo* visual; - GLXContext gl; + XVisualInfo *visual; + GLXContext gl; - void* lib; + void *lib; - MWglXChooseVisual glXChooseVisual; - MWglXCreateContext glXCreateContext; - MWglXDestroyContext glXDestroyContext; - MWglXMakeCurrent glXMakeCurrent; - MWglXSwapBuffers glXSwapBuffers; - MWglXGetProcAddress glXGetProcAddress; + MWglXChooseVisual glXChooseVisual; + MWglXCreateContext glXCreateContext; + MWglXDestroyContext glXDestroyContext; + MWglXMakeCurrent glXMakeCurrent; + MWglXSwapBuffers glXSwapBuffers; + MWglXGetProcAddress glXGetProcAddress; } x11opengl_t; #endif @@ -47,348 +52,385 @@ typedef struct x11opengl { #include typedef struct waylandopengl { - EGLNativeWindowType egl_window_native; - EGLDisplay egl_display; - EGLContext egl_context; - EGLSurface egl_surface; - EGLConfig egl_config; + EGLNativeWindowType egl_window_native; + EGLDisplay egl_display; + EGLContext egl_context; + EGLSurface egl_surface; + EGLConfig egl_config; } waylandopengl_t; #endif static int create(MwWidget handle) { - void* r = NULL; - MwWidget w = handle; + void *r = NULL; + MwWidget w = handle; #ifdef USE_GDI - if(handle->lowlevel->common.type == MwLLBackendGDI) { - PIXELFORMATDESCRIPTOR pfd; - int pf; - gdiopengl_t* o = r = malloc(sizeof(*o)); + if (handle->lowlevel->common.type == MwLLBackendGDI) { + PIXELFORMATDESCRIPTOR pfd; + int pf; + gdiopengl_t *o = r = malloc(sizeof(*o)); - memset(&pfd, 0, sizeof(pfd)); - pfd.nSize = sizeof(pfd); - pfd.nVersion = 1; - pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; - pfd.cDepthBits = 32; - pfd.cColorBits = 32; + memset(&pfd, 0, sizeof(pfd)); + pfd.nSize = sizeof(pfd); + pfd.nVersion = 1; + pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; + pfd.cDepthBits = 32; + pfd.cColorBits = 32; - o->dc = GetDC(handle->lowlevel->gdi.hWnd); + o->dc = GetDC(handle->lowlevel->gdi.hWnd); - pf = ChoosePixelFormat(o->dc, &pfd); - SetPixelFormat(o->dc, pf, &pfd); + pf = ChoosePixelFormat(o->dc, &pfd); + SetPixelFormat(o->dc, pf, &pfd); - o->lib = MwDynamicOpen("opengl32.dll"); + o->lib = MwDynamicOpen("opengl32.dll"); - o->wglCreateContext = (MWwglCreateContext)(void*)MwDynamicSymbol(o->lib, "wglCreateContext"); - o->wglMakeCurrent = (MWwglMakeCurrent)(void*)MwDynamicSymbol(o->lib, "wglMakeCurrent"); - o->wglDeleteContext = (MWwglDeleteContext)(void*)MwDynamicSymbol(o->lib, "wglDeleteContext"); - o->wglGetProcAddress = (MWwglGetProcAddress)(void*)MwDynamicSymbol(o->lib, "wglGetProcAddress"); + o->wglCreateContext = + (MWwglCreateContext)(void *)MwDynamicSymbol(o->lib, "wglCreateContext"); + o->wglMakeCurrent = + (MWwglMakeCurrent)(void *)MwDynamicSymbol(o->lib, "wglMakeCurrent"); + o->wglDeleteContext = + (MWwglDeleteContext)(void *)MwDynamicSymbol(o->lib, "wglDeleteContext"); + o->wglGetProcAddress = (MWwglGetProcAddress)(void *)MwDynamicSymbol( + o->lib, "wglGetProcAddress"); - o->gl = o->wglCreateContext(o->dc); - } + o->gl = o->wglCreateContext(o->dc); + } #endif #ifdef USE_X11 - if(handle->lowlevel->common.type == MwLLBackendX11) { - int attribs[5]; - const char* glpath[] = { - "libGL.so", - "/usr/local/lib/libGL.so", - "/usr/X11R7/lib/libGL.so", - "/usr/pkg/lib/libGL.so"}; - int glincr = 0; - x11opengl_t* o = r = malloc(sizeof(*o)); + if (handle->lowlevel->common.type == MwLLBackendX11) { + int attribs[5]; + const char *glpath[] = {"libGL.so", "/usr/local/lib/libGL.so", + "/usr/X11R7/lib/libGL.so", "/usr/pkg/lib/libGL.so"}; + int glincr = 0; + x11opengl_t *o = r = malloc(sizeof(*o)); - attribs[0] = GLX_RGBA; - attribs[1] = GLX_DOUBLEBUFFER; - attribs[2] = GLX_DEPTH_SIZE; - attribs[3] = 24; - attribs[4] = None; + attribs[0] = GLX_RGBA; + attribs[1] = GLX_DOUBLEBUFFER; + attribs[2] = GLX_DEPTH_SIZE; + attribs[3] = 24; + attribs[4] = None; - while(glpath[glincr] != NULL && (o->lib = MwDynamicOpen(glpath[glincr++])) == NULL); + while (glpath[glincr] != NULL && + (o->lib = MwDynamicOpen(glpath[glincr++])) == NULL) + ; - o->glXChooseVisual = (MWglXChooseVisual)MwDynamicSymbol(o->lib, "glXChooseVisual"); - o->glXCreateContext = (MWglXCreateContext)MwDynamicSymbol(o->lib, "glXCreateContext"); - o->glXDestroyContext = (MWglXDestroyContext)MwDynamicSymbol(o->lib, "glXDestroyContext"); - o->glXMakeCurrent = (MWglXMakeCurrent)MwDynamicSymbol(o->lib, "glXMakeCurrent"); - o->glXSwapBuffers = (MWglXSwapBuffers)MwDynamicSymbol(o->lib, "glXSwapBuffers"); - o->glXGetProcAddress = (MWglXGetProcAddress)MwDynamicSymbol(o->lib, "glXGetProcAddress"); + o->glXChooseVisual = + (MWglXChooseVisual)MwDynamicSymbol(o->lib, "glXChooseVisual"); + o->glXCreateContext = + (MWglXCreateContext)MwDynamicSymbol(o->lib, "glXCreateContext"); + o->glXDestroyContext = + (MWglXDestroyContext)MwDynamicSymbol(o->lib, "glXDestroyContext"); + o->glXMakeCurrent = + (MWglXMakeCurrent)MwDynamicSymbol(o->lib, "glXMakeCurrent"); + o->glXSwapBuffers = + (MWglXSwapBuffers)MwDynamicSymbol(o->lib, "glXSwapBuffers"); + o->glXGetProcAddress = + (MWglXGetProcAddress)MwDynamicSymbol(o->lib, "glXGetProcAddress"); - /* XXX: fix this */ - o->visual = o->glXChooseVisual(handle->lowlevel->x11.display, DefaultScreen(handle->lowlevel->x11.display), attribs); - o->gl = o->glXCreateContext(handle->lowlevel->x11.display, o->visual, NULL, GL_TRUE); - } + /* XXX: fix this */ + o->visual = o->glXChooseVisual(handle->lowlevel->x11.display, + DefaultScreen(handle->lowlevel->x11.display), + attribs); + o->gl = o->glXCreateContext(handle->lowlevel->x11.display, o->visual, NULL, + GL_TRUE); + } #endif #ifdef USE_WAYLAND - if(handle->lowlevel->common.type == MwLLBackendWayland) { - int err; - EGLint numConfigs; - EGLint majorVersion; - EGLint minorVersion; - EGLContext context; - EGLSurface surface; - EGLint fbAttribs[] = - { - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, - EGL_RED_SIZE, 8, - EGL_GREEN_SIZE, 8, - EGL_BLUE_SIZE, 8, - EGL_DEPTH_SIZE, 24, - EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, - EGL_NONE}; - EGLint contextAttribs[] = { - EGL_CONTEXT_CLIENT_VERSION, 1, - EGL_CONTEXT_MAJOR_VERSION, 1, - EGL_CONTEXT_MINOR_VERSION, 1, - EGL_NONE}; - EGLDisplay display; - waylandopengl_t* o = r = malloc(sizeof(*o)); - MwLL topmost_parent = handle->lowlevel->wayland.parent; - topmost_parent->wayland.always_render = MwTRUE; + if (handle->lowlevel->common.type == MwLLBackendWayland) { + int err; + EGLint numConfigs; + EGLint majorVersion; + EGLint minorVersion; + EGLContext context; + EGLSurface surface; + EGLint fbAttribs[] = {EGL_SURFACE_TYPE, + EGL_WINDOW_BIT, + EGL_RENDERABLE_TYPE, + EGL_OPENGL_ES2_BIT, + EGL_RED_SIZE, + 8, + EGL_GREEN_SIZE, + 8, + EGL_BLUE_SIZE, + 8, + EGL_DEPTH_SIZE, + 24, + EGL_RENDERABLE_TYPE, + EGL_OPENGL_BIT, + EGL_NONE}; + EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, + 1, + EGL_CONTEXT_MAJOR_VERSION, + 1, + EGL_CONTEXT_MINOR_VERSION, + 1, + EGL_NONE}; + EGLDisplay display; + waylandopengl_t *o = r = malloc(sizeof(*o)); + MwLL topmost_parent = handle->lowlevel->wayland.parent; + topmost_parent->wayland.always_render = MwTRUE; - while(topmost_parent->wayland.parent != NULL) { - topmost_parent = topmost_parent->wayland.parent; - topmost_parent->wayland.always_render = MwTRUE; - } + while (topmost_parent->wayland.parent != NULL) { + topmost_parent = topmost_parent->wayland.parent; + topmost_parent->wayland.always_render = MwTRUE; + } - display = eglGetDisplay((EGLNativeDisplayType)handle->lowlevel->wayland.display); - if(display == EGL_NO_DISPLAY) { - printf("ERROR: eglGetDisplay, %0X\n", eglGetError()); - return MwFALSE; - } - /* Initialize EGL */ - if(!eglInitialize(display, &majorVersion, &minorVersion)) { - printf("ERROR: eglInitialize, %0X\n", eglGetError()); - return MwFALSE; - } + display = + eglGetDisplay((EGLNativeDisplayType)handle->lowlevel->wayland.display); + if (display == EGL_NO_DISPLAY) { + printf("ERROR: eglGetDisplay, %0X\n", eglGetError()); + return MwFALSE; + } + /* Initialize EGL */ + if (!eglInitialize(display, &majorVersion, &minorVersion)) { + printf("ERROR: eglInitialize, %0X\n", eglGetError()); + return MwFALSE; + } - /* Get configs */ - if((eglGetConfigs(display, NULL, 0, &numConfigs) != EGL_TRUE) || (numConfigs == 0)) { - printf("ERROR: eglGetConfigs, %0X\n", eglGetError()); - return MwFALSE; - } + /* Get configs */ + if ((eglGetConfigs(display, NULL, 0, &numConfigs) != EGL_TRUE) || + (numConfigs == 0)) { + printf("ERROR: eglGetConfigs, %0X\n", eglGetError()); + return MwFALSE; + } - /* Choose config */ - if((eglChooseConfig(display, fbAttribs, &o->egl_config, 1, &numConfigs) != EGL_TRUE) || (numConfigs != 1)) { - printf("ERROR: eglChooseConfig, %0X\n", eglGetError()); - return MwFALSE; - } + /* Choose config */ + if ((eglChooseConfig(display, fbAttribs, &o->egl_config, 1, &numConfigs) != + EGL_TRUE) || + (numConfigs != 1)) { + printf("ERROR: eglChooseConfig, %0X\n", eglGetError()); + return MwFALSE; + } - o->egl_window_native = - (EGLNativeWindowType)wl_egl_window_create(handle->lowlevel->wayland.framebuffer.surface, handle->lowlevel->wayland.ww, handle->lowlevel->wayland.wh); - if(!o->egl_window_native) { - printf("ERROR: wl_egl_window_create, EGL_NO_SURFACE\n"); - return MwFALSE; - } + o->egl_window_native = (EGLNativeWindowType)wl_egl_window_create( + handle->lowlevel->wayland.framebuffer.surface, + handle->lowlevel->wayland.ww, handle->lowlevel->wayland.wh); + if (!o->egl_window_native) { + printf("ERROR: wl_egl_window_create, EGL_NO_SURFACE\n"); + return MwFALSE; + } - /* Create a surface */ - surface = eglCreateWindowSurface(display, o->egl_config, o->egl_window_native, NULL); - if(surface == EGL_NO_SURFACE) { - printf("ERROR: eglCreateWindowSurface, %0X\n", eglGetError()); - return MwFALSE; - } + /* Create a surface */ + surface = eglCreateWindowSurface(display, o->egl_config, + o->egl_window_native, NULL); + if (surface == EGL_NO_SURFACE) { + printf("ERROR: eglCreateWindowSurface, %0X\n", eglGetError()); + return MwFALSE; + } - eglBindAPI(EGL_OPENGL_API); + eglBindAPI(EGL_OPENGL_API); - /* Create a GL context */ - context = eglCreateContext(display, o->egl_config, EGL_NO_CONTEXT, contextAttribs); - if(context == EGL_NO_CONTEXT) { - printf("ERROR: eglCreateContext, %0X\n", eglGetError()); - return MwFALSE; - } + /* Create a GL context */ + context = eglCreateContext(display, o->egl_config, EGL_NO_CONTEXT, + contextAttribs); + if (context == EGL_NO_CONTEXT) { + printf("ERROR: eglCreateContext, %0X\n", eglGetError()); + return MwFALSE; + } - if(!eglMakeCurrent(display, surface, surface, context)) { - printf("ERROR: eglMakeCurrent (setup): %0X\n", eglGetError()); - } + if (!eglMakeCurrent(display, surface, surface, context)) { + printf("ERROR: eglMakeCurrent (setup): %0X\n", eglGetError()); + } - o->egl_display = display; - o->egl_surface = surface; - o->egl_context = context; - } + o->egl_display = display; + o->egl_surface = surface; + o->egl_context = context; + } #endif - handle->internal = r; - handle->lowlevel->common.copy_buffer = 0; + handle->internal = r; + handle->lowlevel->common.copy_buffer = 0; - MwSetDefault(handle); + MwSetDefault(handle); - while(w->parent != NULL) w = w->parent; + while (w->parent != NULL) + w = w->parent; - w->berserk++; + w->berserk++; - return 0; + return 0; } static void destroy(MwWidget handle) { - MwWidget w = handle; + MwWidget w = handle; #ifdef USE_GDI - if(handle->lowlevel->common.type == MwLLBackendGDI) { - gdiopengl_t* o = handle->internal; + if (handle->lowlevel->common.type == MwLLBackendGDI) { + gdiopengl_t *o = handle->internal; - o->wglMakeCurrent(NULL, NULL); - DeleteDC(o->dc); - o->wglDeleteContext(o->gl); + o->wglMakeCurrent(NULL, NULL); + DeleteDC(o->dc); + o->wglDeleteContext(o->gl); - MwDynamicClose(o->lib); - } + MwDynamicClose(o->lib); + } #endif #ifdef USE_X11 - if(handle->lowlevel->common.type == MwLLBackendX11) { - x11opengl_t* o = handle->internal; + if (handle->lowlevel->common.type == MwLLBackendX11) { + x11opengl_t *o = handle->internal; - o->glXMakeCurrent(handle->lowlevel->x11.display, None, NULL); - o->glXDestroyContext(handle->lowlevel->x11.display, o->gl); + o->glXMakeCurrent(handle->lowlevel->x11.display, None, NULL); + o->glXDestroyContext(handle->lowlevel->x11.display, o->gl); - MwDynamicClose(o->lib); - } + MwDynamicClose(o->lib); + } #endif #ifdef USE_WAYLAND - if(handle->lowlevel->common.type == MwLLBackendWayland) { - /* todo */ - } + if (handle->lowlevel->common.type == MwLLBackendWayland) { + /* todo */ + } #endif - while(w->parent != NULL) w = w->parent; + while (w->parent != NULL) + w = w->parent; - w->berserk--; + w->berserk--; - free(handle->internal); + free(handle->internal); } static void mwOpenGLMakeCurrentImpl(MwWidget handle) { - /* these swap interval functions belonging here actually stink! */ + /* these swap interval functions belonging here actually stink! */ #ifdef USE_GDI - if(handle->lowlevel->common.type == MwLLBackendGDI) { - gdiopengl_t* o = handle->internal; - void (*swap_interval_ext)(int) = NULL; + if (handle->lowlevel->common.type == MwLLBackendGDI) { + gdiopengl_t *o = handle->internal; + void (*swap_interval_ext)(int) = NULL; - o->wglMakeCurrent(o->dc, o->gl); + o->wglMakeCurrent(o->dc, o->gl); - if((swap_interval_ext = MwOpenGLGetProcAddress(handle, "wglSwapIntervalEXT")) != NULL) { - swap_interval_ext(1); - } - } + if ((swap_interval_ext = + MwOpenGLGetProcAddress(handle, "wglSwapIntervalEXT")) != NULL) { + swap_interval_ext(1); + } + } #endif #ifdef USE_X11 - if(handle->lowlevel->common.type == MwLLBackendX11) { - x11opengl_t* o = handle->internal; - void (*swap_interval_ext)(Display*, GLXDrawable, int) = NULL; - void (*swap_interval_mesa)(unsigned int) = NULL; - void (*swap_interval_sgi)(int) = NULL; + if (handle->lowlevel->common.type == MwLLBackendX11) { + x11opengl_t *o = handle->internal; + void (*swap_interval_ext)(Display *, GLXDrawable, int) = NULL; + void (*swap_interval_mesa)(unsigned int) = NULL; + void (*swap_interval_sgi)(int) = NULL; - o->glXMakeCurrent(handle->lowlevel->x11.display, handle->lowlevel->x11.window, o->gl); + o->glXMakeCurrent(handle->lowlevel->x11.display, + handle->lowlevel->x11.window, o->gl); - if((swap_interval_ext = MwOpenGLGetProcAddress(handle, "glXSwapIntervalEXT")) != NULL) { - swap_interval_ext(handle->lowlevel->x11.display, handle->lowlevel->x11.window, 1); - } + if ((swap_interval_ext = + MwOpenGLGetProcAddress(handle, "glXSwapIntervalEXT")) != NULL) { + swap_interval_ext(handle->lowlevel->x11.display, + handle->lowlevel->x11.window, 1); + } - if((swap_interval_mesa = MwOpenGLGetProcAddress(handle, "glXSwapIntervalMESA")) != NULL) { - swap_interval_mesa(1); - } + if ((swap_interval_mesa = + MwOpenGLGetProcAddress(handle, "glXSwapIntervalMESA")) != NULL) { + swap_interval_mesa(1); + } - if((swap_interval_sgi = MwOpenGLGetProcAddress(handle, "glXSwapIntervalSGI")) != NULL) { - swap_interval_sgi(1); - } - } + if ((swap_interval_sgi = + MwOpenGLGetProcAddress(handle, "glXSwapIntervalSGI")) != NULL) { + swap_interval_sgi(1); + } + } #endif #ifdef USE_WAYLAND - if(handle->lowlevel->common.type == MwLLBackendWayland) { - waylandopengl_t* o = handle->internal; + if (handle->lowlevel->common.type == MwLLBackendWayland) { + waylandopengl_t *o = handle->internal; - if(!eglMakeCurrent(o->egl_display, o->egl_surface, o->egl_surface, o->egl_context)) { - printf("ERROR: eglMakeCurrent, %0X\n", eglGetError()); - } + if (!eglMakeCurrent(o->egl_display, o->egl_surface, o->egl_surface, + o->egl_context)) { + printf("ERROR: eglMakeCurrent, %0X\n", eglGetError()); + } - eglSwapInterval(o->egl_display, 1); - } + eglSwapInterval(o->egl_display, 1); + } #endif } static void mwOpenGLSwapBufferImpl(MwWidget handle) { #ifdef USE_GDI - if(handle->lowlevel->common.type == MwLLBackendGDI) { - gdiopengl_t* o = handle->internal; + if (handle->lowlevel->common.type == MwLLBackendGDI) { + gdiopengl_t *o = handle->internal; - SwapBuffers(o->dc); - } + SwapBuffers(o->dc); + } #endif #ifdef USE_X11 - if(handle->lowlevel->common.type == MwLLBackendX11) { - x11opengl_t* o = handle->internal; + if (handle->lowlevel->common.type == MwLLBackendX11) { + x11opengl_t *o = handle->internal; - o->glXSwapBuffers(handle->lowlevel->x11.display, handle->lowlevel->x11.window); - } + o->glXSwapBuffers(handle->lowlevel->x11.display, + handle->lowlevel->x11.window); + } #endif #ifdef USE_WAYLAND - if(handle->lowlevel->common.type == MwLLBackendWayland) { - waylandopengl_t* o = handle->internal; - eglSwapInterval(o->egl_display, 0); - if(!eglSwapBuffers(o->egl_display, o->egl_surface)) { - printf("ERROR: eglSwapBuffers, %0X\n", eglGetError()); - }; - wl_egl_window_resize((struct wl_egl_window*)o->egl_window_native, handle->lowlevel->wayland.ww, handle->lowlevel->wayland.wh, 0, 0); - MwLLForceRender(handle->lowlevel); - } + if (handle->lowlevel->common.type == MwLLBackendWayland) { + waylandopengl_t *o = handle->internal; + eglSwapInterval(o->egl_display, 0); + if (!eglSwapBuffers(o->egl_display, o->egl_surface)) { + printf("ERROR: eglSwapBuffers, %0X\n", eglGetError()); + }; + wl_egl_window_resize((struct wl_egl_window *)o->egl_window_native, + handle->lowlevel->wayland.ww, + handle->lowlevel->wayland.wh, 0, 0); + MwLLForceRender(handle->lowlevel); + } #endif } -static void* mwOpenGLGetProcAddressImpl(MwWidget handle, const char* name) { +static void *mwOpenGLGetProcAddressImpl(MwWidget handle, const char *name) { #ifdef USE_GDI - if(handle->lowlevel->common.type == MwLLBackendGDI) { - gdiopengl_t* o = handle->internal; + if (handle->lowlevel->common.type == MwLLBackendGDI) { + gdiopengl_t *o = handle->internal; - return o->wglGetProcAddress(name); - } + return o->wglGetProcAddress(name); + } #endif #ifdef USE_X11 - if(handle->lowlevel->common.type == MwLLBackendX11) { - x11opengl_t* o = handle->internal; + if (handle->lowlevel->common.type == MwLLBackendX11) { + x11opengl_t *o = handle->internal; - return o->glXGetProcAddress((const GLubyte*)name); - } + return o->glXGetProcAddress((const GLubyte *)name); + } #endif #ifdef USE_WAYLAND - if(handle->lowlevel->common.type == MwLLBackendWayland) { - return eglGetProcAddress(name); - } + if (handle->lowlevel->common.type == MwLLBackendWayland) { + return eglGetProcAddress(name); + } #endif - return NULL; + return NULL; } -static void func_handler(MwWidget handle, const char* name, void* out, va_list va) { - if(strcmp(name, "mwOpenGLMakeCurrent") == 0) { - mwOpenGLMakeCurrentImpl(handle); - } - if(strcmp(name, "mwOpenGLSwapBuffer") == 0) { - mwOpenGLSwapBufferImpl(handle); - } - if(strcmp(name, "mwOpenGLGetProcAddress") == 0) { - const char* _name = va_arg(va, const char*); - *(void**)out = mwOpenGLGetProcAddressImpl(handle, _name); - } +static void func_handler(MwWidget handle, const char *name, void *out, + va_list va) { + if (strcmp(name, "mwOpenGLMakeCurrent") == 0) { + mwOpenGLMakeCurrentImpl(handle); + } + if (strcmp(name, "mwOpenGLSwapBuffer") == 0) { + mwOpenGLSwapBufferImpl(handle); + } + if (strcmp(name, "mwOpenGLGetProcAddress") == 0) { + const char *_name = va_arg(va, const char *); + *(void **)out = mwOpenGLGetProcAddressImpl(handle, _name); + } } -MwClassRec MwOpenGLClassRec = { - create, /* create */ - destroy, /* destroy */ - NULL, /* draw */ - NULL, /* click */ - NULL, /* parent_resize */ - NULL, /* prop_change */ - NULL, /* mouse_move */ - NULL, /* mouse_up */ - NULL, /* mouse_down */ - NULL, /* key */ - func_handler, /* execute */ - NULL, /* tick */ - NULL, /* resize */ - NULL, /* children_update */ - NULL, /* children_prop_change */ - NULL, /* clipboard */ - NULL, - NULL, - NULL, - NULL}; +MwClassRec MwOpenGLClassRec = {create, /* create */ + destroy, /* destroy */ + NULL, /* draw */ + NULL, /* click */ + NULL, /* parent_resize */ + NULL, /* prop_change */ + NULL, /* mouse_move */ + NULL, /* mouse_up */ + NULL, /* mouse_down */ + NULL, /* key */ + func_handler, /* execute */ + NULL, /* tick */ + NULL, /* resize */ + NULL, /* children_update */ + NULL, /* children_prop_change */ + NULL, /* clipboard */ + NULL, NULL, NULL, NULL}; MwClass MwOpenGLClass = &MwOpenGLClassRec; + +#endif \ No newline at end of file diff --git a/src/widget/opengl_cocoa.m b/src/widget/opengl_cocoa.m new file mode 100644 index 0000000..88e17e3 --- /dev/null +++ b/src/widget/opengl_cocoa.m @@ -0,0 +1,128 @@ +#include "Mw/Core.h" +#include "Mw/StringDefs.h" +#include +#include +#import + +@interface MacOpenGLWidget : NSObject { + NSOpenGLPixelFormat *pixelFormat; + NSOpenGLContext *glc; +} + +- (MacOpenGLWidget *)initWithView:(NSView *)view; +- (void)destroy; +- (void)makeCurrent; +- (void)swapBuffer; +- (void *)getProcAddressWithName:(const char *)name; + +@end + +static int create(MwWidget handle) { + void *r = NULL; + MwWidget w = handle; + + int x = MwGetInteger(w, MwNx); + int y = MwGetInteger(w, MwNy); + int width = MwGetInteger(w, MwNwidth); + int height = MwGetInteger(w, MwNheight); + + printf("%d %d\n", width, height); + + MacOpenGLWidget *o = r = [[MacOpenGLWidget alloc] + initWithView:[handle->lowlevel->cocoa.real getView]]; + + handle->internal = r; + handle->lowlevel->common.copy_buffer = 0; + + MwSetDefault(handle); + + while (w->parent != NULL) + w = w->parent; + + w->berserk++; + + return 0; +} + +static void destroy(MwWidget handle) { + [(MacOpenGLWidget *)handle->internal destroy]; +} + +static void mwOpenGLMakeCurrentImpl(MwWidget handle) { + [(MacOpenGLWidget *)handle->internal makeCurrent]; +} + +static void mwOpenGLSwapBufferImpl(MwWidget handle) { + [(MacOpenGLWidget *)handle->internal swapBuffer]; +} + +static void *mwOpenGLGetProcAddressImpl(MwWidget handle, const char *name) { + return [(MacOpenGLWidget *)handle->internal getProcAddressWithName:name]; +} + +static void func_handler(MwWidget handle, const char *name, void *out, + va_list va) { + if (strcmp(name, "mwOpenGLMakeCurrent") == 0) { + mwOpenGLMakeCurrentImpl(handle); + } + if (strcmp(name, "mwOpenGLSwapBuffer") == 0) { + mwOpenGLSwapBufferImpl(handle); + } + if (strcmp(name, "mwOpenGLGetProcAddress") == 0) { + const char *_name = va_arg(va, const char *); + *(void **)out = mwOpenGLGetProcAddressImpl(handle, _name); + } +} + +@implementation MacOpenGLWidget + +- (MacOpenGLWidget *)initWithView:(NSView *)view { + NSOpenGLPixelFormatAttribute pixelFormatAttributes[] = { + NSOpenGLPFAColorSize, 24, + NSOpenGLPFAStencilSize, 8, + NSOpenGLPFAAlphaSize, 8, + NSOpenGLPFADoubleBuffer, NSOpenGLPFAAccelerated, + NSOpenGLPFANoRecovery, 0}; + self->pixelFormat = + [[NSOpenGLPixelFormat alloc] initWithAttributes:pixelFormatAttributes]; + self->glc = + [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:nil]; + [self->glc setView:view]; + return self; +}; +- (void)destroy { +}; +- (void)makeCurrent { + [self->glc makeCurrentContext]; +}; +- (void)swapBuffer { + [self->glc flushBuffer]; +}; +- (void *)getProcAddressWithName:(const char *)name { + if (NSIsSymbolNameDefined(name)) { + return NSAddressOfSymbol(NSLookupAndBindSymbol(name)); + } else { + return NULL; + } +}; + +@end + +MwClassRec MwOpenGLClassRec = {create, /* create */ + destroy, /* destroy */ + NULL, /* draw */ + NULL, /* click */ + NULL, /* parent_resize */ + NULL, /* prop_change */ + NULL, /* mouse_move */ + NULL, /* mouse_up */ + NULL, /* mouse_down */ + NULL, /* key */ + func_handler, /* execute */ + NULL, /* tick */ + NULL, /* resize */ + NULL, /* children_update */ + NULL, /* children_prop_change */ + NULL, /* clipboard */ + NULL, NULL, NULL, NULL}; +MwClass MwOpenGLClass = &MwOpenGLClassRec; \ No newline at end of file