Some checks failed
pyrite-dev/milsko/pipeline/head There was a failure building this commit
642 lines
18 KiB
C
642 lines
18 KiB
C
#include <sys/mman.h>
|
|
#ifndef __APPLE__
|
|
|
|
#include <Mw/Milsko.h>
|
|
|
|
#ifndef MW_OPENGL
|
|
#define MW_OPENGL_NO_INCLUDE
|
|
#endif
|
|
#include <Mw/Widget/OpenGL.h>
|
|
|
|
#ifdef MW_OPENGL
|
|
#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 struct gdiopengl {
|
|
HDC dc;
|
|
HGLRC gl;
|
|
|
|
void* lib;
|
|
|
|
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 struct x11opengl {
|
|
XVisualInfo* visual;
|
|
GLXContext gl;
|
|
|
|
void* lib;
|
|
|
|
MWglXChooseVisual glXChooseVisual;
|
|
MWglXCreateContext glXCreateContext;
|
|
MWglXDestroyContext glXDestroyContext;
|
|
MWglXMakeCurrent glXMakeCurrent;
|
|
MWglXSwapBuffers glXSwapBuffers;
|
|
MWglXGetProcAddress glXGetProcAddress;
|
|
} x11opengl_t;
|
|
#endif
|
|
|
|
#ifdef USE_WAYLAND
|
|
#include <EGL/egl.h>
|
|
#include <wayland-egl-core.h>
|
|
#include <gbm.h>
|
|
typedef void* EGLLabelKHR;
|
|
|
|
typedef struct waylandopengl {
|
|
EGLDisplay egl_display;
|
|
EGLContext egl_context;
|
|
EGLSurface egl_surface;
|
|
EGLConfig egl_config;
|
|
struct gbm_device* gbm;
|
|
struct gbm_surface* gbm_surface;
|
|
struct gbm_bo* previous_bo;
|
|
int drm_fd;
|
|
MwLLPixmap frontbuffer;
|
|
MwU8* frontbuffer_data;
|
|
|
|
void* gllib;
|
|
void* gbmlib;
|
|
EGLBoolean (*eglGetConfigs)(EGLDisplay display,
|
|
EGLConfig* configs,
|
|
EGLint config_size,
|
|
EGLint* num_config);
|
|
EGLBoolean (*eglInitialize)(EGLDisplay display,
|
|
EGLint* major,
|
|
EGLint* minor);
|
|
EGLContext (*eglCreateContext)(EGLDisplay display,
|
|
EGLConfig config,
|
|
EGLContext share_context,
|
|
EGLint const* attrib_list);
|
|
EGLBoolean (*eglMakeCurrent)(EGLDisplay display,
|
|
EGLSurface draw,
|
|
EGLSurface read,
|
|
EGLContext context);
|
|
void* (*eglGetProcAddress)(char const* procname);
|
|
EGLBoolean (*eglSwapBuffers)(EGLDisplay display,
|
|
EGLSurface surface);
|
|
EGLBoolean (*eglSwapInterval)(EGLDisplay display,
|
|
EGLint interval);
|
|
EGLint (*eglGetError)(void);
|
|
EGLBoolean (*eglBindAPI)(EGLenum api);
|
|
EGLDisplay (*eglGetDisplay)(NativeDisplayType native_display);
|
|
EGLDisplay (*eglGetPlatformDisplay)(EGLenum platform, void* native_display, const EGLAttrib* attrib_list);
|
|
EGLSurface (*eglCreatePlatformWindowSurface)(EGLDisplay display,
|
|
EGLConfig config,
|
|
void* native_window,
|
|
EGLint const* attrib_list);
|
|
EGLBoolean (*eglChooseConfig)(EGLDisplay display,
|
|
EGLint const* attrib_list,
|
|
EGLConfig* configs,
|
|
EGLint config_size,
|
|
EGLint* num_config);
|
|
EGLBoolean (*eglGetConfigAttrib)(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint* value);
|
|
|
|
struct wl_egl_window* (*wl_egl_window_create)(struct wl_surface* surface,
|
|
int width, int height);
|
|
void (*wl_egl_window_resize)(struct wl_egl_window* egl_window,
|
|
int width, int height,
|
|
int dx, int dy);
|
|
struct gbm_device* (*gbm_create_device)(int fd);
|
|
struct gbm_surface* (*gbm_surface_create)(struct gbm_device* gbm, uint32_t width, uint32_t height, uint32_t format, uint32_t flags);
|
|
|
|
struct gbm_bo* (*gbm_surface_lock_front_buffer)(struct gbm_surface* surface);
|
|
union gbm_bo_handle (*gbm_bo_get_handle)(struct gbm_bo* bo);
|
|
uint32_t (*gbm_bo_get_stride)(struct gbm_bo* bo);
|
|
uint32_t (*gbm_bo_get_width)(struct gbm_bo* bo);
|
|
uint32_t (*gbm_bo_get_height)(struct gbm_bo* bo);
|
|
void (*gbm_surface_release_buffer)(struct gbm_surface* surface, struct gbm_bo* bo);
|
|
void* (*gbm_bo_map)(struct gbm_bo* bo, uint32_t x, uint32_t y, uint32_t width, uint32_t height, uint32_t flags, uint32_t* stride, void** map_data);
|
|
void (*gbm_bo_unmap)(struct gbm_bo* bo, void* map_data);
|
|
|
|
} waylandopengl_t;
|
|
#endif
|
|
|
|
static int wcreate(MwWidget 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));
|
|
|
|
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);
|
|
|
|
pf = ChoosePixelFormat(o->dc, &pfd);
|
|
SetPixelFormat(o->dc, pf, &pfd);
|
|
|
|
o->lib = MwDynamicOpen("opengl32.dll");
|
|
if(!o->lib) {
|
|
printf("Could not load OpenGL widget under WGL!\n");
|
|
return 1;
|
|
}
|
|
|
|
#define WGL_FUNC(x) \
|
|
o->x = MwDynamicSymbol(o->lib, #x); \
|
|
if(o->x == NULL) { \
|
|
printf("Could not load OpenGL widget under WGL! " #x " missing.\n"); \
|
|
return 1; \
|
|
}
|
|
|
|
WGL_FUNC(wglCreateContext);
|
|
WGL_FUNC(wglMakeCurrent);
|
|
WGL_FUNC(wglDeleteContext);
|
|
WGL_FUNC(wglGetProcAddress);
|
|
|
|
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));
|
|
|
|
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);
|
|
|
|
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);
|
|
}
|
|
#endif
|
|
#ifdef USE_WAYLAND
|
|
if(handle->lowlevel->common.type == MwLLBackendWayland) {
|
|
EGLint numConfigs;
|
|
EGLint numConfigsMatched;
|
|
EGLint majorVersion;
|
|
EGLint minorVersion;
|
|
EGLContext context;
|
|
EGLSurface surface;
|
|
EGLint fbAttribs[] = {EGL_SURFACE_TYPE,
|
|
EGL_WINDOW_BIT,
|
|
EGL_RENDERABLE_TYPE,
|
|
EGL_OPENGL_BIT,
|
|
EGL_RED_SIZE,
|
|
8,
|
|
EGL_GREEN_SIZE,
|
|
8,
|
|
EGL_BLUE_SIZE,
|
|
8,
|
|
EGL_DEPTH_SIZE,
|
|
24,
|
|
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));
|
|
int gbm_format = 0;
|
|
memset(o, 0, sizeof(waylandopengl_t));
|
|
|
|
o->gllib = MwDynamicOpen("libEGL.so");
|
|
if(!o->gllib) {
|
|
printf("Could not load OpenGL widget under Wayland! libEGL.so missing.\n");
|
|
return 1;
|
|
}
|
|
o->gbmlib = MwDynamicOpen("libgbm.so");
|
|
if(!o->gbmlib) {
|
|
printf("Could not load OpenGL widget under Wayland! libgbm.so missing.\n");
|
|
return 1;
|
|
}
|
|
#define EGL_FUNC(x) \
|
|
o->x = MwDynamicSymbol(o->gllib, #x); \
|
|
if(!o->x) { \
|
|
printf("Could not load OpenGL widget under Wayland! " #x " missing.\n"); \
|
|
return 1; \
|
|
};
|
|
#define GBM_FUNC(x) \
|
|
o->x = MwDynamicSymbol(o->gbmlib, #x); \
|
|
if(!o->x) { \
|
|
printf("Could not load OpenGL widget under Wayland! " #x " missing.\n"); \
|
|
return 1; \
|
|
};
|
|
EGL_FUNC(eglGetConfigs)
|
|
EGL_FUNC(eglInitialize)
|
|
EGL_FUNC(eglCreateContext)
|
|
EGL_FUNC(eglMakeCurrent)
|
|
EGL_FUNC(eglGetProcAddress)
|
|
EGL_FUNC(eglSwapBuffers)
|
|
EGL_FUNC(eglSwapInterval)
|
|
EGL_FUNC(eglGetError)
|
|
EGL_FUNC(eglBindAPI)
|
|
EGL_FUNC(eglGetDisplay)
|
|
EGL_FUNC(eglCreatePlatformWindowSurface)
|
|
EGL_FUNC(eglChooseConfig)
|
|
EGL_FUNC(eglGetPlatformDisplay)
|
|
EGL_FUNC(eglGetConfigAttrib)
|
|
GBM_FUNC(gbm_create_device)
|
|
GBM_FUNC(gbm_surface_create)
|
|
GBM_FUNC(gbm_surface_lock_front_buffer)
|
|
GBM_FUNC(gbm_bo_get_handle)
|
|
GBM_FUNC(gbm_bo_get_stride)
|
|
GBM_FUNC(gbm_bo_get_width)
|
|
GBM_FUNC(gbm_bo_get_height)
|
|
GBM_FUNC(gbm_surface_release_buffer)
|
|
GBM_FUNC(gbm_bo_map)
|
|
GBM_FUNC(gbm_bo_unmap)
|
|
|
|
#define eglGetConfigs o->eglGetConfigs
|
|
#define eglInitialize o->eglInitialize
|
|
#define eglCreateContext o->eglCreateContext
|
|
#define eglMakeCurrent o->eglMakeCurrent
|
|
#define eglGetProcAddress o->eglGetProcAddress
|
|
#define eglSwapBuffers o->eglSwapBuffers
|
|
#define eglSwapInterval o->eglSwapInterval
|
|
#define eglGetError o->eglGetError
|
|
#define wl_egl_window_create o->wl_egl_window_create
|
|
#define eglBindAPI o->eglBindAPI
|
|
#define eglGetDisplay o->eglGetDisplay
|
|
#define wl_egl_window_resize o->wl_egl_window_resize
|
|
#define eglCreatePlatformWindowSurface o->eglCreatePlatformWindowSurface
|
|
#define eglChooseConfig o->eglChooseConfig
|
|
#define eglGetPlatformDisplay o->eglGetPlatformDisplay
|
|
|
|
o->drm_fd = open("/dev/dri/renderD128", O_RDWR);
|
|
assert(o->drm_fd > 0);
|
|
o->gbm = o->gbm_create_device(o->drm_fd);
|
|
assert(o->gbm != NULL);
|
|
|
|
display = eglGetPlatformDisplay(0x31D7, o->gbm, NULL);
|
|
if(display == EGL_NO_DISPLAY) {
|
|
printf("ERROR: eglGetDisplay, %0X\n", eglGetError());
|
|
return 1;
|
|
}
|
|
|
|
/* Initialize EGL */
|
|
if(!eglInitialize(display, &majorVersion, &minorVersion)) {
|
|
printf("ERROR: eglInitialize, %0X\n", eglGetError());
|
|
return 1;
|
|
}
|
|
|
|
eglBindAPI(EGL_OPENGL_API);
|
|
|
|
/* Get configs */
|
|
if((eglGetConfigs(display, NULL, 0, &numConfigs) != EGL_TRUE)) {
|
|
printf("ERROR: eglGetConfigs, %0X\n", eglGetError());
|
|
return 1;
|
|
}
|
|
EGLConfig egl_configs[1024];
|
|
|
|
/* Choose config */
|
|
if((eglChooseConfig(display, fbAttribs, egl_configs, numConfigs, &numConfigsMatched) !=
|
|
EGL_TRUE)) {
|
|
printf("ERROR: eglChooseConfig, %0X\n", eglGetError());
|
|
return 1;
|
|
}
|
|
|
|
for(int i = 0; i < numConfigsMatched; i++) {
|
|
if(o->eglGetConfigAttrib(display, egl_configs[i],
|
|
EGL_NATIVE_VISUAL_ID,
|
|
&gbm_format) == EGL_FALSE) {
|
|
printf("ERROR: eglGetConfigAttrib, %0X\n", eglGetError());
|
|
} else {
|
|
if(gbm_format == GBM_FORMAT_ARGB8888) {
|
|
o->egl_config = egl_configs[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
/* 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 1;
|
|
}
|
|
|
|
o->gbm_surface = o->gbm_surface_create(o->gbm, handle->lowlevel->wayland.ww, handle->lowlevel->wayland.wh, GBM_FORMAT_ARGB8888, GBM_BO_USE_LINEAR | GBM_BO_USE_RENDERING);
|
|
|
|
/* Create a surface */
|
|
surface = eglCreatePlatformWindowSurface(display, o->egl_config,
|
|
o->gbm_surface, NULL);
|
|
if(surface == EGL_NO_SURFACE) {
|
|
printf("ERROR: eglCreatePlatformWindowSurface, %0X\n", eglGetError());
|
|
return 1;
|
|
}
|
|
|
|
if(!eglMakeCurrent(display, surface, surface, context)) {
|
|
printf("ERROR: eglMakeCurrent (setup): %0X\n", eglGetError());
|
|
}
|
|
|
|
o->frontbuffer_data = malloc(handle->lowlevel->wayland.ww * handle->lowlevel->wayland.wh * 4);
|
|
memset(o->frontbuffer_data, 255, handle->lowlevel->wayland.ww * handle->lowlevel->wayland.wh * 4);
|
|
|
|
o->frontbuffer = MwLoadRaw(handle, o->frontbuffer_data, handle->lowlevel->wayland.ww, handle->lowlevel->wayland.wh);
|
|
|
|
MwVaApply(handle, MwNpixmap, o->frontbuffer, NULL);
|
|
|
|
o->egl_display = display;
|
|
o->egl_surface = surface;
|
|
o->egl_context = context;
|
|
}
|
|
#endif
|
|
|
|
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) {
|
|
MwWidget w = handle;
|
|
|
|
#ifdef USE_GDI
|
|
if(handle->lowlevel->common.type == MwLLBackendGDI) {
|
|
gdiopengl_t* o = handle->internal;
|
|
|
|
o->wglMakeCurrent(NULL, NULL);
|
|
DeleteDC(o->dc);
|
|
o->wglDeleteContext(o->gl);
|
|
|
|
MwDynamicClose(o->lib);
|
|
}
|
|
#endif
|
|
#ifdef USE_X11
|
|
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);
|
|
|
|
MwDynamicClose(o->lib);
|
|
}
|
|
#endif
|
|
#ifdef USE_WAYLAND
|
|
if(handle->lowlevel->common.type == MwLLBackendWayland) {
|
|
/* todo */
|
|
}
|
|
#endif
|
|
|
|
while(w->parent != NULL)
|
|
w = w->parent;
|
|
|
|
w->berserk--;
|
|
|
|
free(handle->internal);
|
|
}
|
|
|
|
static void mwOpenGLMakeCurrentImpl(MwWidget handle) {
|
|
/* these swap interval functions belonging here actually stink! */
|
|
|
|
#ifdef USE_GDI
|
|
if(handle->lowlevel->common.type == MwLLBackendGDI) {
|
|
gdiopengl_t* o = handle->internal;
|
|
BOOL(APIENTRY * swap_interval_ext)(int) = NULL;
|
|
|
|
o->wglMakeCurrent(o->dc, o->gl);
|
|
|
|
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;
|
|
|
|
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_mesa =
|
|
MwOpenGLGetProcAddress(handle, "glXSwapIntervalMESA")) != NULL) {
|
|
swap_interval_mesa(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(!eglMakeCurrent(o->egl_display, o->egl_surface, o->egl_surface,
|
|
o->egl_context)) {
|
|
printf("ERROR: eglMakeCurrent, %0X\n", eglGetError());
|
|
}
|
|
|
|
MwLLForceRender(handle->lowlevel);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static void mwOpenGLSwapBufferImpl(MwWidget handle) {
|
|
#ifdef USE_GDI
|
|
if(handle->lowlevel->common.type == MwLLBackendGDI) {
|
|
gdiopengl_t* o = handle->internal;
|
|
|
|
SwapBuffers(o->dc);
|
|
}
|
|
#endif
|
|
#ifdef USE_X11
|
|
if(handle->lowlevel->common.type == MwLLBackendX11) {
|
|
x11opengl_t* o = handle->internal;
|
|
|
|
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());
|
|
}
|
|
struct gbm_bo* bo = o->gbm_surface_lock_front_buffer(o->gbm_surface);
|
|
if(bo) {
|
|
void* gbmBoMapData = NULL; // Needed for unmapping if gbm_bo_map is used
|
|
MwU32 width = o->gbm_bo_get_width(bo);
|
|
MwU32 height = o->gbm_bo_get_height(bo);
|
|
MwU32 stride = o->gbm_bo_get_stride(bo);
|
|
void* map = o->gbm_bo_map(bo, 0, 0, width, height, GBM_BO_TRANSFER_READ, &stride, &gbmBoMapData);
|
|
MwU32 size = height * stride;
|
|
|
|
if(map) {
|
|
for(int y = 0; y < height; y++) {
|
|
const MwU8* row = map + y * stride;
|
|
for(int x = 0; x < width; x++) {
|
|
/* Memory layout per pixel: [B][G][R][A] */
|
|
MwU8 b = row[x * 4 + 0];
|
|
MwU8 g = row[x * 4 + 1];
|
|
MwU8 r = row[x * 4 + 2];
|
|
|
|
int out = (y * width + x) * 4;
|
|
o->frontbuffer_data[out + 0] = r;
|
|
o->frontbuffer_data[out + 1] = g;
|
|
o->frontbuffer_data[out + 2] = b;
|
|
o->frontbuffer_data[out + 3] = 255;
|
|
}
|
|
}
|
|
|
|
MwPixmapReloadRaw(
|
|
o->frontbuffer, o->frontbuffer_data);
|
|
}
|
|
o->gbm_bo_unmap(bo, gbmBoMapData);
|
|
}
|
|
if(o->previous_bo) {
|
|
o->gbm_surface_release_buffer(o->gbm_surface, o->previous_bo);
|
|
}
|
|
o->previous_bo = bo;
|
|
|
|
MwForceRender(handle);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static void* mwOpenGLGetProcAddressImpl(MwWidget handle, const char* name) {
|
|
#ifdef USE_GDI
|
|
if(handle->lowlevel->common.type == MwLLBackendGDI) {
|
|
gdiopengl_t* o = handle->internal;
|
|
|
|
return o->wglGetProcAddress(name);
|
|
}
|
|
#endif
|
|
#ifdef USE_X11
|
|
if(handle->lowlevel->common.type == MwLLBackendX11) {
|
|
x11opengl_t* o = handle->internal;
|
|
|
|
return o->glXGetProcAddress((const GLubyte*)name);
|
|
}
|
|
#endif
|
|
#ifdef USE_WAYLAND
|
|
if(handle->lowlevel->common.type == MwLLBackendWayland) {
|
|
waylandopengl_t* o = handle->internal;
|
|
return eglGetProcAddress(name);
|
|
}
|
|
#endif
|
|
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 frontbuffer_draw(MwWidget handle) {
|
|
#ifdef USE_WAYLAND
|
|
if(handle->lowlevel->common.type == MwLLBackendWayland) {
|
|
waylandopengl_t* o = handle->internal;
|
|
MwRect r;
|
|
r.x = 0;
|
|
r.y = 0;
|
|
r.width = handle->lowlevel->wayland.ww;
|
|
r.height = handle->lowlevel->wayland.wh;
|
|
MwLLDrawPixmap(handle->lowlevel, &r, o->frontbuffer);
|
|
}
|
|
|
|
#endif
|
|
}
|
|
|
|
MwClassRec MwOpenGLClassRec = {wcreate, /* create */
|
|
destroy, /* destroy */
|
|
#ifdef USE_WAYLAND
|
|
frontbuffer_draw, /* draw */
|
|
#else
|
|
NULL, /* draw */
|
|
#endif
|
|
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, /* props_change */
|
|
NULL, NULL, NULL};
|
|
MwClass MwOpenGLClass = &MwOpenGLClassRec;
|
|
#else
|
|
MWDECL MwClass MwOpenGLClass;
|
|
|
|
MwClass MwOpenGLClass = NULL;
|
|
#endif
|
|
|
|
#endif
|