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, &registryListener, 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;
}