mac opengl support. proper coordinate flipping

This commit is contained in:
IoI_xD 2026-03-04 22:56:04 -07:00
commit db577bb01f
7 changed files with 610 additions and 390 deletions

View file

@ -1,7 +1,13 @@
#define TITLE "cube" #define TITLE "cube"
#include "glutlayer.c" #include "glutlayer.c"
#if defined(__APPLE__)
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#else
#include <GL/gl.h>
#include <GL/glu.h> #include <GL/glu.h>
#endif
static double deg = 0; static double deg = 0;
@ -14,13 +20,19 @@ static void draw(void) {
glRotatef(deg, 0, 1, 0); glRotatef(deg, 0, 1, 0);
glRotatef(deg, 0, 0, 1); glRotatef(deg, 0, 0, 1);
for(i = 0; i < 6; i++) { for (i = 0; i < 6; i++) {
if(i == 0) glColor3f(1, 0, 0); if (i == 0)
if(i == 1) glColor3f(0, 1, 0); glColor3f(1, 0, 0);
if(i == 2) glColor3f(1, 1, 0); if (i == 1)
if(i == 3) glColor3f(0, 0, 1); glColor3f(0, 1, 0);
if(i == 4) glColor3f(1, 0, 1); if (i == 2)
if(i == 5) glColor3f(0, 1, 1); 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); glBegin(GL_QUADS);
glNormal3f(0, 1, 0); glNormal3f(0, 1, 0);
@ -30,16 +42,17 @@ static void draw(void) {
glVertex3f(1, 1, -1); glVertex3f(1, 1, -1);
glEnd(); glEnd();
if(i < 3) glRotatef(90, 0, 0, 1); if (i < 3)
if(i == 3) glRotatef(90, 1, 0, 0); glRotatef(90, 0, 0, 1);
if(i == 4) glRotatef(180, 0, 0, 1); if (i == 3)
glRotatef(90, 1, 0, 0);
if (i == 4)
glRotatef(180, 0, 0, 1);
} }
glPopMatrix(); glPopMatrix();
} }
static void idle(void) { static void idle(void) { deg += 1.0; }
deg += 1.0;
}
static void reshape(int width, int height) { static void reshape(int width, int height) {
GLfloat lpos[4]; GLfloat lpos[4];
@ -73,6 +86,4 @@ static void init(void) {
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
} }
static void key(int k) { static void key(int k) { (void)k; }
(void)k;
}

View file

@ -119,6 +119,7 @@
- (void)destroy; - (void)destroy;
- (NSWindow *)parentWindow; - (NSWindow *)parentWindow;
- (NSView *)getView;
@end @end
#define OBJC(x) x #define OBJC(x) x

View file

@ -5,17 +5,24 @@
#ifndef __MW_WIDGET_OPENGL_H__ #ifndef __MW_WIDGET_OPENGL_H__
#define __MW_WIDGET_OPENGL_H__ #define __MW_WIDGET_OPENGL_H__
#include <Mw/Core.h>
#include <Mw/MachDep.h> #include <Mw/MachDep.h>
#include <Mw/TypeDefs.h> #include <Mw/TypeDefs.h>
#include <Mw/Core.h>
#if !defined(MW_OPENGL_NO_INCLUDE) && !defined(__gl_h_) #if !defined(MW_OPENGL_NO_INCLUDE) && !defined(__gl_h_)
#ifdef _WIN32 #ifdef _WIN32
#include <windows.h> #include <windows.h>
#elif defined(__APPLE__)
#else #else
#include <GL/glx.h> #include <GL/glx.h>
#endif #endif
#if defined(__APPLE__)
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#else
#include <GL/gl.h> #include <GL/gl.h>
#include <GL/glu.h>
#endif
#ifndef GLAPIENTRY #ifndef GLAPIENTRY
#define GLAPIENTRY APIENTRY #define GLAPIENTRY APIENTRY
@ -45,8 +52,8 @@ MwInline void MwOpenGLMakeCurrent(MwWidget handle) {
* @param name Name * @param name Name
* @return Procedure * @return Procedure
*/ */
MwInline void* MwOpenGLGetProcAddress(MwWidget handle, const char* name) { MwInline void *MwOpenGLGetProcAddress(MwWidget handle, const char *name) {
void* out; void *out;
MwVaWidgetExecute(handle, "mwOpenGLGetProcAddress", &out, name); MwVaWidgetExecute(handle, "mwOpenGLGetProcAddress", &out, name);
return out; return out;
} }

View file

@ -50,7 +50,14 @@ if (grep(/^cocoa$/, @backends)) {
add_cflags("-DUSE_COCOA"); add_cflags("-DUSE_COCOA");
new_object("src/backend/cocoa.m"); 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")) { if (param_get("stb-image")) {

View file

@ -3,6 +3,29 @@
#pragma clang push #pragma clang push
#pragma clang diagnostic ignored "-Wdeprecated-declarations" #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 @implementation MilskoCocoaPixmap
+ (MilskoCocoaPixmap *)newWithWidth:(int)width height:(int)height { + (MilskoCocoaPixmap *)newWithWidth:(int)width height:(int)height {
@ -70,8 +93,7 @@
centerY = true; centerY = true;
} }
c->application = [NSApplication sharedApplication]; c->application = [NSApplication sharedApplication];
c->rect = rectFlip(NSMakeRect(x, y, width, height));
c->rect = NSMakeRect(x, y, width, height);
if (parent == NULL) { if (parent == NULL) {
c->window = [[NSWindow alloc] c->window = [[NSWindow alloc]
@ -81,12 +103,12 @@
backing:NSBackingStoreBuffered backing:NSBackingStoreBuffered
defer:NO]; defer:NO];
} else { } else {
double offset = 0;
NSWindow *parentWindow = parent->cocoa.real->window; NSWindow *parentWindow = parent->cocoa.real->window;
offset =
c->rect = [parentWindow frameRectForContentRect:c->rect]; [parentWindow frameRectForContentRect:parentWindow.frame].size.height -
c->rect.origin.y =
y -
[parentWindow contentRectForFrameRect:parentWindow.frame].size.height; [parentWindow contentRectForFrameRect:parentWindow.frame].size.height;
c->rect.origin.y -= offset;
c->window = [[NSWindow alloc] initWithContentRect:c->rect c->window = [[NSWindow alloc] initWithContentRect:c->rect
styleMask:NSBorderlessWindowMask styleMask:NSBorderlessWindowMask
@ -160,10 +182,10 @@
- (void)lineWithPoints:(MwPoint *)points color:(MwLLColor)color { - (void)lineWithPoints:(MwPoint *)points color:(MwLLColor)color {
}; };
- (void)getX:(int *)x Y:(int *)y W:(unsigned int *)w H:(unsigned int *)h { - (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; *x = frame.origin.x;
*y = frame.origin.y - frame.size.height; *y = frame.origin.y;
*w = frame.size.width; *w = frame.size.width;
*h = frame.size.height; *h = frame.size.height;
@ -174,12 +196,17 @@
frame.origin.x = x; frame.origin.x = x;
frame.origin.y = y; frame.origin.y = y;
if (self->parent) { frame = rectFlip(frame);
NSWindow *parentWindow = [self parentWindow];
NSRect correctedFrame = if (parent) {
[parentWindow contentRectForFrameRect:parentWindow.frame]; double offset = 0;
frame.origin.y = (correctedFrame.size.height - y); 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]; [self->window setFrame:frame display:YES animate:false];
}; };
@ -187,8 +214,10 @@
NSRect frame = [self->window frame]; NSRect frame = [self->window frame];
frame.size.width = w; frame.size.width = w;
frame.size.height = h; frame.size.height = h;
self->rect = frame; self->rect = frame;
[self->view setFrameSize:frame.size];
[self->window setFrame:frame display:YES animate:false]; [self->window setFrame:frame display:YES animate:false];
}; };
- (int)pending { - (int)pending {
@ -207,10 +236,6 @@
if (self->lastEvent != nil) { if (self->lastEvent != nil) {
NSWindow *win = [self->lastEvent window]; NSWindow *win = [self->lastEvent window];
NSWindow *parentWindow = [self parentWindow]; NSWindow *parentWindow = [self parentWindow];
NSRect realFrame = parentWindow.frame;
NSRect correctedFrame =
[parentWindow frameRectForContentRect:parentWindow.frame];
CGFloat offset = realFrame.size.height - correctedFrame.size.height;
MwLL h; MwLL h;
if ([win contentView].subviews.count == 0) { if ([win contentView].subviews.count == 0) {
@ -228,6 +253,7 @@
case NSEventTypeOtherMouseUp: { case NSEventTypeOtherMouseUp: {
MwLLMouse mouse = {}; MwLLMouse mouse = {};
MwBool isDown = MwTRUE; MwBool isDown = MwTRUE;
CGPoint mousePoint = pointFlip([lastEvent locationInWindow]);
switch (self->lastEvent.type) { switch (self->lastEvent.type) {
case NSEventTypeLeftMouseUp: case NSEventTypeLeftMouseUp:
isDown = MwFALSE; isDown = MwFALSE;
@ -247,9 +273,8 @@
default: default:
break; break;
} }
mouse.point.x = [lastEvent locationInWindow].x; mouse.point.x = mousePoint.x;
mouse.point.y = [win contentRectForFrameRect:win.frame].size.height - mouse.point.y = mousePoint.y;
[lastEvent locationInWindow].y;
if (isDown) { if (isDown) {
MwLLDispatch(h, down, &mouse); MwLLDispatch(h, down, &mouse);
@ -428,6 +453,10 @@
topmostWindow = topmostWindow.parentWindow; topmostWindow = topmostWindow.parentWindow;
return topmostWindow; return topmostWindow;
} }
- (NSView *)getView {
return view;
}
@end @end
@implementation MilskoCocoaView @implementation MilskoCocoaView
@ -471,13 +500,13 @@
} }
- (void)drawRect:(NSRect)dirtyRect { - (void)drawRect:(NSRect)dirtyRect {
NSSize sz = [self->rep size]; NSSize sz = self->rep.size;
[super drawRect:dirtyRect]; [super drawRect:dirtyRect];
if (!self->rep) { if (!self->rep) {
return; return;
} }
[self->rep drawInRect:NSMakeRect(0, 0, width, height)]; [self->rep drawInRect:NSMakeRect(0, 0, sz.width, sz.height)];
[self->rep bitmapData]; [self->rep bitmapData];
} }
@ -488,12 +517,7 @@
- (void)setFrameSize:(NSSize)newSize { - (void)setFrameSize:(NSSize)newSize {
[super setFrameSize:newSize]; [super setFrameSize:newSize];
if (newSize.width != 0 && newSize.height != 0) { [self->rep setSize:newSize];
// [self->rep setSize:newSize];
// width = newSize.width;
// height = newSize.height;
// [self->context setImageInterpolation:NSImageInterpolationHigh];
}
} }
- (void)displayRect:(NSRect)rect { - (void)displayRect:(NSRect)rect {

View file

@ -1,17 +1,19 @@
#ifndef __APPLE__
#include <Mw/Milsko.h> #include <Mw/Milsko.h>
#include <Mw/Widget/OpenGL.h> #include <Mw/Widget/OpenGL.h>
#ifdef USE_GDI #ifdef USE_GDI
typedef HGLRC(WINAPI* MWwglCreateContext)(HDC); typedef HGLRC(WINAPI *MWwglCreateContext)(HDC);
typedef BOOL(WINAPI* MWwglMakeCurrent)(HDC, HGLRC); typedef BOOL(WINAPI *MWwglMakeCurrent)(HDC, HGLRC);
typedef PROC(WINAPI* MWwglGetProcAddress)(LPCSTR); typedef PROC(WINAPI *MWwglGetProcAddress)(LPCSTR);
typedef BOOL(WINAPI* MWwglDeleteContext)(HGLRC); typedef BOOL(WINAPI *MWwglDeleteContext)(HGLRC);
typedef struct gdiopengl { typedef struct gdiopengl {
HDC dc; HDC dc;
HGLRC gl; HGLRC gl;
void* lib; void *lib;
MWwglCreateContext wglCreateContext; MWwglCreateContext wglCreateContext;
MWwglMakeCurrent wglMakeCurrent; MWwglMakeCurrent wglMakeCurrent;
@ -20,18 +22,21 @@ typedef struct gdiopengl {
} gdiopengl_t; } gdiopengl_t;
#endif #endif
#ifdef USE_X11 #ifdef USE_X11
typedef XVisualInfo* (*MWglXChooseVisual)(Display* dpy, int screen, int* attribList); typedef XVisualInfo *(*MWglXChooseVisual)(Display *dpy, int screen,
typedef GLXContext (*MWglXCreateContext)(Display* dpy, XVisualInfo* vis, GLXContext shareList, Bool direct); int *attribList);
typedef void (*MWglXDestroyContext)(Display* dpy, GLXContext ctx); typedef GLXContext (*MWglXCreateContext)(Display *dpy, XVisualInfo *vis,
typedef Bool (*MWglXMakeCurrent)(Display* dpy, GLXDrawable drawable, GLXContext ctx); GLXContext shareList, Bool direct);
typedef void (*MWglXSwapBuffers)(Display* dpy, GLXDrawable drawable); typedef void (*MWglXDestroyContext)(Display *dpy, GLXContext ctx);
typedef void* (*MWglXGetProcAddress)(const GLubyte* procname); 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 { typedef struct x11opengl {
XVisualInfo* visual; XVisualInfo *visual;
GLXContext gl; GLXContext gl;
void* lib; void *lib;
MWglXChooseVisual glXChooseVisual; MWglXChooseVisual glXChooseVisual;
MWglXCreateContext glXCreateContext; MWglXCreateContext glXCreateContext;
@ -56,14 +61,14 @@ typedef struct waylandopengl {
#endif #endif
static int create(MwWidget handle) { static int create(MwWidget handle) {
void* r = NULL; void *r = NULL;
MwWidget w = handle; MwWidget w = handle;
#ifdef USE_GDI #ifdef USE_GDI
if(handle->lowlevel->common.type == MwLLBackendGDI) { if (handle->lowlevel->common.type == MwLLBackendGDI) {
PIXELFORMATDESCRIPTOR pfd; PIXELFORMATDESCRIPTOR pfd;
int pf; int pf;
gdiopengl_t* o = r = malloc(sizeof(*o)); gdiopengl_t *o = r = malloc(sizeof(*o));
memset(&pfd, 0, sizeof(pfd)); memset(&pfd, 0, sizeof(pfd));
pfd.nSize = sizeof(pfd); pfd.nSize = sizeof(pfd);
@ -79,24 +84,25 @@ static int create(MwWidget handle) {
o->lib = MwDynamicOpen("opengl32.dll"); o->lib = MwDynamicOpen("opengl32.dll");
o->wglCreateContext = (MWwglCreateContext)(void*)MwDynamicSymbol(o->lib, "wglCreateContext"); o->wglCreateContext =
o->wglMakeCurrent = (MWwglMakeCurrent)(void*)MwDynamicSymbol(o->lib, "wglMakeCurrent"); (MWwglCreateContext)(void *)MwDynamicSymbol(o->lib, "wglCreateContext");
o->wglDeleteContext = (MWwglDeleteContext)(void*)MwDynamicSymbol(o->lib, "wglDeleteContext"); o->wglMakeCurrent =
o->wglGetProcAddress = (MWwglGetProcAddress)(void*)MwDynamicSymbol(o->lib, "wglGetProcAddress"); (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 #endif
#ifdef USE_X11 #ifdef USE_X11
if(handle->lowlevel->common.type == MwLLBackendX11) { if (handle->lowlevel->common.type == MwLLBackendX11) {
int attribs[5]; int attribs[5];
const char* glpath[] = { const char *glpath[] = {"libGL.so", "/usr/local/lib/libGL.so",
"libGL.so", "/usr/X11R7/lib/libGL.so", "/usr/pkg/lib/libGL.so"};
"/usr/local/lib/libGL.so",
"/usr/X11R7/lib/libGL.so",
"/usr/pkg/lib/libGL.so"};
int glincr = 0; int glincr = 0;
x11opengl_t* o = r = malloc(sizeof(*o)); x11opengl_t *o = r = malloc(sizeof(*o));
attribs[0] = GLX_RGBA; attribs[0] = GLX_RGBA;
attribs[1] = GLX_DOUBLEBUFFER; attribs[1] = GLX_DOUBLEBUFFER;
@ -104,86 +110,110 @@ static int create(MwWidget handle) {
attribs[3] = 24; attribs[3] = 24;
attribs[4] = None; 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->glXChooseVisual =
o->glXCreateContext = (MWglXCreateContext)MwDynamicSymbol(o->lib, "glXCreateContext"); (MWglXChooseVisual)MwDynamicSymbol(o->lib, "glXChooseVisual");
o->glXDestroyContext = (MWglXDestroyContext)MwDynamicSymbol(o->lib, "glXDestroyContext"); o->glXCreateContext =
o->glXMakeCurrent = (MWglXMakeCurrent)MwDynamicSymbol(o->lib, "glXMakeCurrent"); (MWglXCreateContext)MwDynamicSymbol(o->lib, "glXCreateContext");
o->glXSwapBuffers = (MWglXSwapBuffers)MwDynamicSymbol(o->lib, "glXSwapBuffers"); o->glXDestroyContext =
o->glXGetProcAddress = (MWglXGetProcAddress)MwDynamicSymbol(o->lib, "glXGetProcAddress"); (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 */ /* XXX: fix this */
o->visual = o->glXChooseVisual(handle->lowlevel->x11.display, DefaultScreen(handle->lowlevel->x11.display), attribs); o->visual = o->glXChooseVisual(handle->lowlevel->x11.display,
o->gl = o->glXCreateContext(handle->lowlevel->x11.display, o->visual, NULL, GL_TRUE); DefaultScreen(handle->lowlevel->x11.display),
attribs);
o->gl = o->glXCreateContext(handle->lowlevel->x11.display, o->visual, NULL,
GL_TRUE);
} }
#endif #endif
#ifdef USE_WAYLAND #ifdef USE_WAYLAND
if(handle->lowlevel->common.type == MwLLBackendWayland) { if (handle->lowlevel->common.type == MwLLBackendWayland) {
int err; int err;
EGLint numConfigs; EGLint numConfigs;
EGLint majorVersion; EGLint majorVersion;
EGLint minorVersion; EGLint minorVersion;
EGLContext context; EGLContext context;
EGLSurface surface; EGLSurface surface;
EGLint fbAttribs[] = EGLint fbAttribs[] = {EGL_SURFACE_TYPE,
{ EGL_WINDOW_BIT,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RENDERABLE_TYPE,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_OPENGL_ES2_BIT,
EGL_RED_SIZE, 8, EGL_RED_SIZE,
EGL_GREEN_SIZE, 8, 8,
EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE,
EGL_DEPTH_SIZE, 24, 8,
EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, EGL_BLUE_SIZE,
8,
EGL_DEPTH_SIZE,
24,
EGL_RENDERABLE_TYPE,
EGL_OPENGL_BIT,
EGL_NONE}; EGL_NONE};
EGLint contextAttribs[] = { EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION,
EGL_CONTEXT_CLIENT_VERSION, 1, 1,
EGL_CONTEXT_MAJOR_VERSION, 1, EGL_CONTEXT_MAJOR_VERSION,
EGL_CONTEXT_MINOR_VERSION, 1, 1,
EGL_CONTEXT_MINOR_VERSION,
1,
EGL_NONE}; EGL_NONE};
EGLDisplay display; EGLDisplay display;
waylandopengl_t* o = r = malloc(sizeof(*o)); waylandopengl_t *o = r = malloc(sizeof(*o));
MwLL topmost_parent = handle->lowlevel->wayland.parent; MwLL topmost_parent = handle->lowlevel->wayland.parent;
topmost_parent->wayland.always_render = MwTRUE; topmost_parent->wayland.always_render = MwTRUE;
while(topmost_parent->wayland.parent != NULL) { while (topmost_parent->wayland.parent != NULL) {
topmost_parent = topmost_parent->wayland.parent; topmost_parent = topmost_parent->wayland.parent;
topmost_parent->wayland.always_render = MwTRUE; topmost_parent->wayland.always_render = MwTRUE;
} }
display = eglGetDisplay((EGLNativeDisplayType)handle->lowlevel->wayland.display); display =
if(display == EGL_NO_DISPLAY) { eglGetDisplay((EGLNativeDisplayType)handle->lowlevel->wayland.display);
if (display == EGL_NO_DISPLAY) {
printf("ERROR: eglGetDisplay, %0X\n", eglGetError()); printf("ERROR: eglGetDisplay, %0X\n", eglGetError());
return MwFALSE; return MwFALSE;
} }
/* Initialize EGL */ /* Initialize EGL */
if(!eglInitialize(display, &majorVersion, &minorVersion)) { if (!eglInitialize(display, &majorVersion, &minorVersion)) {
printf("ERROR: eglInitialize, %0X\n", eglGetError()); printf("ERROR: eglInitialize, %0X\n", eglGetError());
return MwFALSE; return MwFALSE;
} }
/* Get configs */ /* Get configs */
if((eglGetConfigs(display, NULL, 0, &numConfigs) != EGL_TRUE) || (numConfigs == 0)) { if ((eglGetConfigs(display, NULL, 0, &numConfigs) != EGL_TRUE) ||
(numConfigs == 0)) {
printf("ERROR: eglGetConfigs, %0X\n", eglGetError()); printf("ERROR: eglGetConfigs, %0X\n", eglGetError());
return MwFALSE; return MwFALSE;
} }
/* Choose config */ /* Choose config */
if((eglChooseConfig(display, fbAttribs, &o->egl_config, 1, &numConfigs) != EGL_TRUE) || (numConfigs != 1)) { if ((eglChooseConfig(display, fbAttribs, &o->egl_config, 1, &numConfigs) !=
EGL_TRUE) ||
(numConfigs != 1)) {
printf("ERROR: eglChooseConfig, %0X\n", eglGetError()); printf("ERROR: eglChooseConfig, %0X\n", eglGetError());
return MwFALSE; return MwFALSE;
} }
o->egl_window_native = o->egl_window_native = (EGLNativeWindowType)wl_egl_window_create(
(EGLNativeWindowType)wl_egl_window_create(handle->lowlevel->wayland.framebuffer.surface, handle->lowlevel->wayland.ww, handle->lowlevel->wayland.wh); handle->lowlevel->wayland.framebuffer.surface,
if(!o->egl_window_native) { handle->lowlevel->wayland.ww, handle->lowlevel->wayland.wh);
if (!o->egl_window_native) {
printf("ERROR: wl_egl_window_create, EGL_NO_SURFACE\n"); printf("ERROR: wl_egl_window_create, EGL_NO_SURFACE\n");
return MwFALSE; return MwFALSE;
} }
/* Create a surface */ /* Create a surface */
surface = eglCreateWindowSurface(display, o->egl_config, o->egl_window_native, NULL); surface = eglCreateWindowSurface(display, o->egl_config,
if(surface == EGL_NO_SURFACE) { o->egl_window_native, NULL);
if (surface == EGL_NO_SURFACE) {
printf("ERROR: eglCreateWindowSurface, %0X\n", eglGetError()); printf("ERROR: eglCreateWindowSurface, %0X\n", eglGetError());
return MwFALSE; return MwFALSE;
} }
@ -191,13 +221,14 @@ static int create(MwWidget handle) {
eglBindAPI(EGL_OPENGL_API); eglBindAPI(EGL_OPENGL_API);
/* Create a GL context */ /* Create a GL context */
context = eglCreateContext(display, o->egl_config, EGL_NO_CONTEXT, contextAttribs); context = eglCreateContext(display, o->egl_config, EGL_NO_CONTEXT,
if(context == EGL_NO_CONTEXT) { contextAttribs);
if (context == EGL_NO_CONTEXT) {
printf("ERROR: eglCreateContext, %0X\n", eglGetError()); printf("ERROR: eglCreateContext, %0X\n", eglGetError());
return MwFALSE; return MwFALSE;
} }
if(!eglMakeCurrent(display, surface, surface, context)) { if (!eglMakeCurrent(display, surface, surface, context)) {
printf("ERROR: eglMakeCurrent (setup): %0X\n", eglGetError()); printf("ERROR: eglMakeCurrent (setup): %0X\n", eglGetError());
} }
@ -212,7 +243,8 @@ static int create(MwWidget handle) {
MwSetDefault(handle); MwSetDefault(handle);
while(w->parent != NULL) w = w->parent; while (w->parent != NULL)
w = w->parent;
w->berserk++; w->berserk++;
@ -223,8 +255,8 @@ static void destroy(MwWidget handle) {
MwWidget w = handle; MwWidget w = handle;
#ifdef USE_GDI #ifdef USE_GDI
if(handle->lowlevel->common.type == MwLLBackendGDI) { if (handle->lowlevel->common.type == MwLLBackendGDI) {
gdiopengl_t* o = handle->internal; gdiopengl_t *o = handle->internal;
o->wglMakeCurrent(NULL, NULL); o->wglMakeCurrent(NULL, NULL);
DeleteDC(o->dc); DeleteDC(o->dc);
@ -234,8 +266,8 @@ static void destroy(MwWidget handle) {
} }
#endif #endif
#ifdef USE_X11 #ifdef USE_X11
if(handle->lowlevel->common.type == MwLLBackendX11) { if (handle->lowlevel->common.type == MwLLBackendX11) {
x11opengl_t* o = handle->internal; x11opengl_t *o = handle->internal;
o->glXMakeCurrent(handle->lowlevel->x11.display, None, NULL); o->glXMakeCurrent(handle->lowlevel->x11.display, None, NULL);
o->glXDestroyContext(handle->lowlevel->x11.display, o->gl); o->glXDestroyContext(handle->lowlevel->x11.display, o->gl);
@ -244,12 +276,13 @@ static void destroy(MwWidget handle) {
} }
#endif #endif
#ifdef USE_WAYLAND #ifdef USE_WAYLAND
if(handle->lowlevel->common.type == MwLLBackendWayland) { if (handle->lowlevel->common.type == MwLLBackendWayland) {
/* todo */ /* todo */
} }
#endif #endif
while(w->parent != NULL) w = w->parent; while (w->parent != NULL)
w = w->parent;
w->berserk--; w->berserk--;
@ -260,44 +293,51 @@ static void mwOpenGLMakeCurrentImpl(MwWidget handle) {
/* these swap interval functions belonging here actually stink! */ /* these swap interval functions belonging here actually stink! */
#ifdef USE_GDI #ifdef USE_GDI
if(handle->lowlevel->common.type == MwLLBackendGDI) { if (handle->lowlevel->common.type == MwLLBackendGDI) {
gdiopengl_t* o = handle->internal; gdiopengl_t *o = handle->internal;
void (*swap_interval_ext)(int) = NULL; 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) { if ((swap_interval_ext =
MwOpenGLGetProcAddress(handle, "wglSwapIntervalEXT")) != NULL) {
swap_interval_ext(1); swap_interval_ext(1);
} }
} }
#endif #endif
#ifdef USE_X11 #ifdef USE_X11
if(handle->lowlevel->common.type == MwLLBackendX11) { if (handle->lowlevel->common.type == MwLLBackendX11) {
x11opengl_t* o = handle->internal; x11opengl_t *o = handle->internal;
void (*swap_interval_ext)(Display*, GLXDrawable, int) = NULL; void (*swap_interval_ext)(Display *, GLXDrawable, int) = NULL;
void (*swap_interval_mesa)(unsigned int) = NULL; void (*swap_interval_mesa)(unsigned int) = NULL;
void (*swap_interval_sgi)(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) { if ((swap_interval_ext =
swap_interval_ext(handle->lowlevel->x11.display, handle->lowlevel->x11.window, 1); MwOpenGLGetProcAddress(handle, "glXSwapIntervalEXT")) != NULL) {
swap_interval_ext(handle->lowlevel->x11.display,
handle->lowlevel->x11.window, 1);
} }
if((swap_interval_mesa = MwOpenGLGetProcAddress(handle, "glXSwapIntervalMESA")) != NULL) { if ((swap_interval_mesa =
MwOpenGLGetProcAddress(handle, "glXSwapIntervalMESA")) != NULL) {
swap_interval_mesa(1); swap_interval_mesa(1);
} }
if((swap_interval_sgi = MwOpenGLGetProcAddress(handle, "glXSwapIntervalSGI")) != NULL) { if ((swap_interval_sgi =
MwOpenGLGetProcAddress(handle, "glXSwapIntervalSGI")) != NULL) {
swap_interval_sgi(1); swap_interval_sgi(1);
} }
} }
#endif #endif
#ifdef USE_WAYLAND #ifdef USE_WAYLAND
if(handle->lowlevel->common.type == MwLLBackendWayland) { if (handle->lowlevel->common.type == MwLLBackendWayland) {
waylandopengl_t* o = handle->internal; waylandopengl_t *o = handle->internal;
if(!eglMakeCurrent(o->egl_display, o->egl_surface, o->egl_surface, o->egl_context)) { if (!eglMakeCurrent(o->egl_display, o->egl_surface, o->egl_surface,
o->egl_context)) {
printf("ERROR: eglMakeCurrent, %0X\n", eglGetError()); printf("ERROR: eglMakeCurrent, %0X\n", eglGetError());
} }
@ -308,70 +348,73 @@ static void mwOpenGLMakeCurrentImpl(MwWidget handle) {
static void mwOpenGLSwapBufferImpl(MwWidget handle) { static void mwOpenGLSwapBufferImpl(MwWidget handle) {
#ifdef USE_GDI #ifdef USE_GDI
if(handle->lowlevel->common.type == MwLLBackendGDI) { if (handle->lowlevel->common.type == MwLLBackendGDI) {
gdiopengl_t* o = handle->internal; gdiopengl_t *o = handle->internal;
SwapBuffers(o->dc); SwapBuffers(o->dc);
} }
#endif #endif
#ifdef USE_X11 #ifdef USE_X11
if(handle->lowlevel->common.type == MwLLBackendX11) { if (handle->lowlevel->common.type == MwLLBackendX11) {
x11opengl_t* o = handle->internal; 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 #endif
#ifdef USE_WAYLAND #ifdef USE_WAYLAND
if(handle->lowlevel->common.type == MwLLBackendWayland) { if (handle->lowlevel->common.type == MwLLBackendWayland) {
waylandopengl_t* o = handle->internal; waylandopengl_t *o = handle->internal;
eglSwapInterval(o->egl_display, 0); eglSwapInterval(o->egl_display, 0);
if(!eglSwapBuffers(o->egl_display, o->egl_surface)) { if (!eglSwapBuffers(o->egl_display, o->egl_surface)) {
printf("ERROR: eglSwapBuffers, %0X\n", eglGetError()); 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); 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); MwLLForceRender(handle->lowlevel);
} }
#endif #endif
} }
static void* mwOpenGLGetProcAddressImpl(MwWidget handle, const char* name) { static void *mwOpenGLGetProcAddressImpl(MwWidget handle, const char *name) {
#ifdef USE_GDI #ifdef USE_GDI
if(handle->lowlevel->common.type == MwLLBackendGDI) { if (handle->lowlevel->common.type == MwLLBackendGDI) {
gdiopengl_t* o = handle->internal; gdiopengl_t *o = handle->internal;
return o->wglGetProcAddress(name); return o->wglGetProcAddress(name);
} }
#endif #endif
#ifdef USE_X11 #ifdef USE_X11
if(handle->lowlevel->common.type == MwLLBackendX11) { if (handle->lowlevel->common.type == MwLLBackendX11) {
x11opengl_t* o = handle->internal; x11opengl_t *o = handle->internal;
return o->glXGetProcAddress((const GLubyte*)name); return o->glXGetProcAddress((const GLubyte *)name);
} }
#endif #endif
#ifdef USE_WAYLAND #ifdef USE_WAYLAND
if(handle->lowlevel->common.type == MwLLBackendWayland) { if (handle->lowlevel->common.type == MwLLBackendWayland) {
return eglGetProcAddress(name); return eglGetProcAddress(name);
} }
#endif #endif
return NULL; return NULL;
} }
static void func_handler(MwWidget handle, const char* name, void* out, va_list va) { static void func_handler(MwWidget handle, const char *name, void *out,
if(strcmp(name, "mwOpenGLMakeCurrent") == 0) { va_list va) {
if (strcmp(name, "mwOpenGLMakeCurrent") == 0) {
mwOpenGLMakeCurrentImpl(handle); mwOpenGLMakeCurrentImpl(handle);
} }
if(strcmp(name, "mwOpenGLSwapBuffer") == 0) { if (strcmp(name, "mwOpenGLSwapBuffer") == 0) {
mwOpenGLSwapBufferImpl(handle); mwOpenGLSwapBufferImpl(handle);
} }
if(strcmp(name, "mwOpenGLGetProcAddress") == 0) { if (strcmp(name, "mwOpenGLGetProcAddress") == 0) {
const char* _name = va_arg(va, const char*); const char *_name = va_arg(va, const char *);
*(void**)out = mwOpenGLGetProcAddressImpl(handle, _name); *(void **)out = mwOpenGLGetProcAddressImpl(handle, _name);
} }
} }
MwClassRec MwOpenGLClassRec = { MwClassRec MwOpenGLClassRec = {create, /* create */
create, /* create */
destroy, /* destroy */ destroy, /* destroy */
NULL, /* draw */ NULL, /* draw */
NULL, /* click */ NULL, /* click */
@ -387,8 +430,7 @@ MwClassRec MwOpenGLClassRec = {
NULL, /* children_update */ NULL, /* children_update */
NULL, /* children_prop_change */ NULL, /* children_prop_change */
NULL, /* clipboard */ NULL, /* clipboard */
NULL, NULL, NULL, NULL, NULL};
NULL,
NULL,
NULL};
MwClass MwOpenGLClass = &MwOpenGLClassRec; MwClass MwOpenGLClass = &MwOpenGLClassRec;
#endif

128
src/widget/opengl_cocoa.m Normal file
View file

@ -0,0 +1,128 @@
#include "Mw/Core.h"
#include "Mw/StringDefs.h"
#include <Mw/Milsko.h>
#include <Mw/Widget/OpenGL.h>
#import <mach-o/dyld.h>
@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;