Wayland Entry Point#
/*!***************************************************************************
\File OpenGLESHelloAPI_LinuxWayland.cpp
\Title OpenGL ES 2.0 HelloAPI Tutorial
\Author PowerVR by Imagination, Developer Technology Team
\Copyright Copyright (c) Imagination Technologies Limited.
\brief Basic Tutorial that shows step-by-step how to initialise OpenGL ES 2.0, use it for drawing a triangle and terminate it.
Entry Point: main
*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "OpenGLESHelloAPI.h"
wl_registry* wlRegistry = NULL;
wl_compositor* wlCompositor = NULL;
wl_shell* wlShell = NULL;
wl_seat* wlSeat = NULL;
wl_surface* wlSurface = NULL;
wl_pointer* wlPointer = NULL;
wl_shell_surface* wlShellSurface = NULL;
short pointerXY[2];
static void pointer_handle_enter(void* data, struct wl_pointer* pointer, uint32_t serial, struct wl_surface* surface, wl_fixed_t sx, wl_fixed_t sy) {}
static void pointer_handle_leave(void* data, struct wl_pointer* pointer, uint32_t serial, struct wl_surface* surface) {}
static void pointer_handle_motion(void* data, struct wl_pointer* pointer, uint32_t time, wl_fixed_t sx, wl_fixed_t sy)
{
pointerXY[0] = (short)sx;
pointerXY[1] = (short)sy;
}
static void pointer_handle_button(void* data, struct wl_pointer* wl_pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state)
{
if (button == BTN_LEFT && state == WL_POINTER_BUTTON_STATE_PRESSED)
{
wl_shell_surface_move(wlShellSurface, wlSeat, serial);
}
}
static void pointer_handle_axis(void* data, struct wl_pointer* wl_pointer, uint32_t time, uint32_t axis, wl_fixed_t value) {}
static const struct wl_pointer_listener pointer_listener = {
pointer_handle_enter,
pointer_handle_leave,
pointer_handle_motion,
pointer_handle_button,
pointer_handle_axis,
};
static void seat_handle_capabilities(void* data, struct wl_seat* seat, uint32_t caps)
{
if ((caps & WL_SEAT_CAPABILITY_POINTER) && !wlPointer)
{
wlPointer = wl_seat_get_pointer(seat);
wl_pointer_add_listener(wlPointer, &pointer_listener, NULL);
}
else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && wlPointer)
{
wl_pointer_destroy(wlPointer);
wlPointer = NULL;
}
}
static void seat_handle_name(void* data, struct wl_seat* seat, const char* name) {}
static const struct wl_seat_listener seatListener = { seat_handle_capabilities, seat_handle_name };
static void registerGlobalCallback(void* data, wl_registry* registry, uint32_t name, const char* interface, uint32_t version)
{
if (strcmp(interface, "wl_compositor") == 0)
{
wlCompositor = (wl_compositor*)wl_registry_bind(registry, name, &wl_compositor_interface, 1);
}
else if (strcmp(interface, "wl_shell") == 0)
{
wlShell = (wl_shell*)wl_registry_bind(registry, name, &wl_shell_interface, 1);
}
else if (strcmp(interface, "wl_seat") == 0)
{
wlSeat = (wl_seat*)wl_registry_bind(registry, name, &wl_seat_interface, 1);
wl_seat_add_listener(wlSeat, &seatListener, NULL);
}
}
static void globalObjectRemove(void* data, struct wl_registry* wl_registry, uint32_t name) {}
static const wl_registry_listener registryListener = { registerGlobalCallback, globalObjectRemove };
static void ping_cb(void* data, struct wl_shell_surface* shell_surface, uint32_t serial)
{
wl_shell_surface_pong(shell_surface, serial);
}
static void configure_cb(void* /*data*/, struct wl_shell_surface* /*shell_surface*/, uint32_t /*edges*/, int32_t /*width*/, int32_t /*height*/) {}
static void popupDone_cb(void* /*data*/, struct wl_shell_surface* /*shell_surface*/) {}
static void redraw(void* data, struct wl_callback* callback, uint32_t time)
{
printf("Redrawing\n");
}
static const struct wl_callback_listener FrameListener = { redraw };
static void configure_cb(void* data, struct wl_callback* callback, uint32_t time)
{
if (callback == NULL)
redraw(data, NULL, time);
}
static struct wl_callback_listener ConfigureCbListener = {
configure_cb,
};
static const struct wl_shell_surface_listener shellSurfaceListeners = { ping_cb, configure_cb, popupDone_cb };
bool initWaylandConnection(OpenGLESAPI& helloAPI)
{
if ((helloAPI._surfaceData.deviceContext = wl_display_connect(NULL)) == NULL)
{
printf("Failed to connect to Wayland display!");
return false;
}
if ((wlRegistry = wl_display_get_registry(helloAPI._surfaceData.deviceContext)) == NULL)
{
printf("Failed to get Wayland registry!");
return false;
}
wl_registry_add_listener(wlRegistry, ®istryListener, NULL);
wl_display_dispatch(helloAPI._surfaceData.deviceContext);
if (!wlCompositor) // || !internalOS.seat)
{
printf("Could not bind Wayland protocols!");
return false;
}
return true;
}
bool initializeWindow(OpenGLESAPI& helloAPI)
{
if (!initWaylandConnection(helloAPI))
return false;
wlSurface = wl_compositor_create_surface(wlCompositor);
if (wlSurface == NULL)
{
printf("Failed to create Wayland surface");
return false;
}
wlShellSurface = wl_shell_get_shell_surface(wlShell, wlSurface);
if (wlShellSurface == NULL)
{
printf("Failed to get Wayland shell surface");
return false;
}
wl_shell_surface_add_listener(wlShellSurface, &shellSurfaceListeners, NULL);
wl_shell_surface_set_toplevel(wlShellSurface);
wl_shell_surface_set_title(wlShellSurface, "OpenGLESHelloApi");
return true;
}
void releaseWaylandConnection(wl_display* dislay)
{
wl_shell_surface_destroy(wlShellSurface);
wl_surface_destroy(wlSurface);
if (wlPointer)
{
wl_pointer_destroy(wlPointer);
}
wl_seat_destroy(wlSeat);
wl_shell_destroy(wlShell);
wl_compositor_destroy(wlCompositor);
wl_registry_destroy(wlRegistry);
wl_display_disconnect(dislay);
}
/*!***************************************************************************
\param[in] argc Number of arguments passed to the application, ignored.
\param[in] argv Command line strings passed to the application, ignored.
\return Result code to send to the Operating System
\brief Main function of the program, executes other functions.
*****************************************************************************/
int main(int /*argc*/, char** /*argv*/)
{
OpenGLESAPI helloAPI;
Get access to a native display.
initializeWindow(helloAPI);
helloAPI._surfaceData.window = wl_egl_window_create(wlSurface, helloAPI._surfaceData.width, helloAPI._surfaceData.height);
if (helloAPI._surfaceData.window == EGL_NO_SURFACE)
{
printf("Can't create egl window\n");
}
else
{
printf("Created wl egl window\n");
}
Setup OpenGL ES state and objects.
helloAPI.initializeEGL();
helloAPI.initializeGLES();
Renders a triangle for 800 frames using the state setup in the previous function.
for (int i = 0; i < 800; ++i)
{
wl_display_dispatch_pending(helloAPI._surfaceData.deviceContext);
if (!helloAPI.drawFrame() || !helloAPI.swapEGLBuffers())
{
break;
}
}
Release any resources we created in the Initialise functions.
helloAPI.releaseGLState();
helloAPI.releaseEGLState();
Release the Wayland connection.
releaseWaylandConnection(helloAPI._surfaceData.deviceContext);
Destroy the eglWindow.
return 0;
}