mac opengl support. proper coordinate flipping
All checks were successful
pyrite-dev/milsko/pipeline/head This commit looks good

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,78 +1,89 @@
#define TITLE "cube"
#include "glutlayer.c"
#if defined(__APPLE__)
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#else
#include <GL/gl.h>
#include <GL/glu.h>
#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; }

View file

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

View file

@ -5,17 +5,24 @@
#ifndef __MW_WIDGET_OPENGL_H__
#define __MW_WIDGET_OPENGL_H__
#include <Mw/Core.h>
#include <Mw/MachDep.h>
#include <Mw/TypeDefs.h>
#include <Mw/Core.h>
#if !defined(MW_OPENGL_NO_INCLUDE) && !defined(__gl_h_)
#ifdef _WIN32
#include <windows.h>
#elif defined(__APPLE__)
#else
#include <GL/glx.h>
#endif
#if defined(__APPLE__)
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#else
#include <GL/gl.h>
#include <GL/glu.h>
#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

View file

@ -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")) {

View file

@ -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 {

View file

@ -1,44 +1,49 @@
#ifndef __APPLE__
#include <Mw/Milsko.h>
#include <Mw/Widget/OpenGL.h>
#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 <wayland-egl-core.h>
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

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;