Skip to content

Commit

Permalink
Make wpe_fdo_initialize_for_egl_display return bool
Browse files Browse the repository at this point in the history
Check that all required EGL extensions are available and that
initialization doesn't fail.

This is an API change but it's both API and ABI backwards compatible.
  • Loading branch information
carlosgcampos committed Feb 22, 2019
1 parent 6daf7eb commit 9991dac
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 124 deletions.
3 changes: 2 additions & 1 deletion include/wpe-fdo/initialize-egl.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@ extern "C" {
#endif

#include <EGL/egl.h>
#include <stdbool.h>

void
bool
wpe_fdo_initialize_for_egl_display(EGLDisplay);

#ifdef __cplusplus
Expand Down
4 changes: 2 additions & 2 deletions src/initialize-egl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
#include "ws.h"

__attribute__((visibility("default")))
void
bool
wpe_fdo_initialize_for_egl_display(EGLDisplay display)
{
WS::Instance::singleton().initialize(display);
return WS::Instance::singleton().initialize(display);
}
118 changes: 4 additions & 114 deletions src/view-backend-exportable-fdo-egl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,33 +34,6 @@

namespace {

#ifndef EGL_EXT_image_dma_buf_import
#define EGL_LINUX_DMA_BUF_EXT 0x3270
#define EGL_DMA_BUF_PLANE0_FD_EXT 0x3272
#define EGL_DMA_BUF_PLANE0_OFFSET_EXT 0x3273
#define EGL_DMA_BUF_PLANE0_PITCH_EXT 0x3274
#define EGL_DMA_BUF_PLANE1_FD_EXT 0x3275
#define EGL_DMA_BUF_PLANE1_OFFSET_EXT 0x3276
#define EGL_DMA_BUF_PLANE1_PITCH_EXT 0x3277
#define EGL_DMA_BUF_PLANE2_FD_EXT 0x3278
#define EGL_DMA_BUF_PLANE2_OFFSET_EXT 0x3279
#define EGL_DMA_BUF_PLANE2_PITCH_EXT 0x327A
#endif /* EGL_EXT_image_dma_buf_import */

#ifndef EGL_EXT_image_dma_buf_import_modifiers
#define EGL_DMA_BUF_PLANE3_FD_EXT 0x3440
#define EGL_DMA_BUF_PLANE3_OFFSET_EXT 0x3441
#define EGL_DMA_BUF_PLANE3_PITCH_EXT 0x3442
#define EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT 0x3443
#define EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT 0x3444
#define EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT 0x3445
#define EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT 0x3446
#define EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT 0x3447
#define EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT 0x3448
#define EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT 0x3449
#define EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT 0x344A
#endif /* EGL_EXT_image_dma_buf_import_modifiers */

struct buffer_data {
struct wl_resource *buffer_resource;
EGLImageKHR egl_image;
Expand All @@ -73,22 +46,13 @@ class ClientBundleEGL final : public ClientBundle {
: ClientBundle(data, viewBackend, initialWidth, initialHeight)
, client(_client)
{
m_eglDisplay = WS::Instance::singleton().getEGLDisplay();
assert (m_eglDisplay);

eglCreateImage = (PFNEGLCREATEIMAGEKHRPROC) eglGetProcAddress ("eglCreateImageKHR");
assert (eglCreateImage);

eglDestroyImage = (PFNEGLDESTROYIMAGEKHRPROC)
eglGetProcAddress ("eglDestroyImageKHR");
assert (eglDestroyImage);
}

virtual ~ClientBundleEGL()
{
for (auto* buf_data : m_buffers) {
assert(buf_data->egl_image);
eglDestroyImage(m_eglDisplay, buf_data->egl_image);
WS::Instance::singleton().destroyImage(buf_data->egl_image);

delete buf_data;
}
Expand All @@ -97,15 +61,7 @@ class ClientBundleEGL final : public ClientBundle {

void exportBuffer(struct wl_resource *bufferResource) override
{
static const EGLint image_attrs[] = {
EGL_WAYLAND_PLANE_WL, 0,
EGL_NONE
};
EGLImageKHR image = eglCreateImage (m_eglDisplay,
EGL_NO_CONTEXT,
EGL_WAYLAND_BUFFER_WL,
bufferResource,
image_attrs);
EGLImageKHR image = WS::Instance::singleton().createImage(bufferResource);
if (!image)
return;

Expand All @@ -119,69 +75,7 @@ class ClientBundleEGL final : public ClientBundle {

void exportBuffer(const struct linux_dmabuf_buffer *dmabuf_buffer) override
{
const struct linux_dmabuf_attributes *buf_attribs =
linux_dmabuf_get_buffer_attributes(dmabuf_buffer);
assert(buf_attribs);

static const struct {
EGLint fd;
EGLint offset;
EGLint pitch;
EGLint modifier_lo;
EGLint modifier_hi;
} plane_enums[4] = {
{EGL_DMA_BUF_PLANE0_FD_EXT,
EGL_DMA_BUF_PLANE0_OFFSET_EXT,
EGL_DMA_BUF_PLANE0_PITCH_EXT,
EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT,
EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT},
{EGL_DMA_BUF_PLANE1_FD_EXT,
EGL_DMA_BUF_PLANE1_OFFSET_EXT,
EGL_DMA_BUF_PLANE1_PITCH_EXT,
EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT,
EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT},
{EGL_DMA_BUF_PLANE2_FD_EXT,
EGL_DMA_BUF_PLANE2_OFFSET_EXT,
EGL_DMA_BUF_PLANE2_PITCH_EXT,
EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT,
EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT},
{EGL_DMA_BUF_PLANE3_FD_EXT,
EGL_DMA_BUF_PLANE3_OFFSET_EXT,
EGL_DMA_BUF_PLANE3_PITCH_EXT,
EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT,
EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT},
};

EGLint attribs[50];
int atti = 0;

attribs[atti++] = EGL_WIDTH;
attribs[atti++] = buf_attribs->width;
attribs[atti++] = EGL_HEIGHT;
attribs[atti++] = buf_attribs->height;
attribs[atti++] = EGL_LINUX_DRM_FOURCC_EXT;
attribs[atti++] = buf_attribs->format;

for (int i = 0; i < buf_attribs->n_planes; i++) {
attribs[atti++] = plane_enums[i].fd;
attribs[atti++] = buf_attribs->fd[i];
attribs[atti++] = plane_enums[i].offset;
attribs[atti++] = buf_attribs->offset[i];
attribs[atti++] = plane_enums[i].pitch;
attribs[atti++] = buf_attribs->stride[i];
attribs[atti++] = plane_enums[i].modifier_lo;
attribs[atti++] = buf_attribs->modifier[i] & 0xFFFFFFFF;
attribs[atti++] = plane_enums[i].modifier_hi;
attribs[atti++] = buf_attribs->modifier[i] >> 32;
}

attribs[atti++] = EGL_NONE;

EGLImageKHR image = eglCreateImage (m_eglDisplay,
EGL_NO_CONTEXT,
EGL_LINUX_DMA_BUF_EXT,
nullptr,
attribs);
EGLImageKHR image = WS::Instance::singleton().createImage(dmabuf_buffer);
if (!image)
return;

Expand All @@ -198,7 +92,7 @@ class ClientBundleEGL final : public ClientBundle {
for (auto* buf_data : m_buffers)
if (buf_data->egl_image == image) {
m_buffers.remove(buf_data);
eglDestroyImage(m_eglDisplay, buf_data->egl_image);
WS::Instance::singleton().destroyImage(buf_data->egl_image);

return buf_data;
}
Expand All @@ -209,10 +103,6 @@ class ClientBundleEGL final : public ClientBundle {
const struct wpe_view_backend_exportable_fdo_egl_client* client;

private:
EGLDisplay m_eglDisplay;
PFNEGLCREATEIMAGEKHRPROC eglCreateImage;
PFNEGLDESTROYIMAGEKHRPROC eglDestroyImage;

std::list<struct buffer_data*> m_buffers;
};

Expand Down
154 changes: 148 additions & 6 deletions src/ws.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,45 @@
#include <EGL/eglext.h>
#include "linux-dmabuf/linux-dmabuf.h"
#include "bridge/wpe-bridge-server-protocol.h"
#include <cassert>
#include <sys/socket.h>
#include <unistd.h>

#ifndef EGL_WL_bind_wayland_display
typedef EGLBoolean (EGLAPIENTRYP PFNEGLBINDWAYLANDDISPLAYWL) (EGLDisplay dpy, struct wl_display *display);
#endif

#ifndef EGL_EXT_image_dma_buf_import
#define EGL_LINUX_DMA_BUF_EXT 0x3270
#define EGL_DMA_BUF_PLANE0_FD_EXT 0x3272
#define EGL_DMA_BUF_PLANE0_OFFSET_EXT 0x3273
#define EGL_DMA_BUF_PLANE0_PITCH_EXT 0x3274
#define EGL_DMA_BUF_PLANE1_FD_EXT 0x3275
#define EGL_DMA_BUF_PLANE1_OFFSET_EXT 0x3276
#define EGL_DMA_BUF_PLANE1_PITCH_EXT 0x3277
#define EGL_DMA_BUF_PLANE2_FD_EXT 0x3278
#define EGL_DMA_BUF_PLANE2_OFFSET_EXT 0x3279
#define EGL_DMA_BUF_PLANE2_PITCH_EXT 0x327A
#endif /* EGL_EXT_image_dma_buf_import */

#ifndef EGL_EXT_image_dma_buf_import_modifiers
#define EGL_DMA_BUF_PLANE3_FD_EXT 0x3440
#define EGL_DMA_BUF_PLANE3_OFFSET_EXT 0x3441
#define EGL_DMA_BUF_PLANE3_PITCH_EXT 0x3442
#define EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT 0x3443
#define EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT 0x3444
#define EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT 0x3445
#define EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT 0x3446
#define EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT 0x3447
#define EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT 0x3448
#define EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT 0x3449
#define EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT 0x344A
#endif /* EGL_EXT_image_dma_buf_import_modifiers */

static PFNEGLBINDWAYLANDDISPLAYWL eglBindWaylandDisplayWL;
static PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR;
static PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR;

namespace WS {

struct Source {
Expand Down Expand Up @@ -258,28 +290,60 @@ Instance::~Instance()
wl_display_destroy(m_display);
}

void Instance::initialize(EGLDisplay eglDisplay)
static bool isEGLExtensionSupported(const char* extensionList, const char* extension)
{
if (!extensionList)
return false;

int extensionLen = strlen(extension);
const char* extensionListPtr = extensionList;
while ((extensionListPtr = strstr(extensionListPtr, extension))) {
if (extensionListPtr[extensionLen] == ' ' || extensionListPtr[extensionLen] == '\0')
return true;
extensionListPtr += extensionLen;
}
return false;
}

bool Instance::initialize(EGLDisplay eglDisplay)
{
if (m_eglDisplay == eglDisplay)
return;
return true;

if (m_eglDisplay != EGL_NO_DISPLAY) {
fprintf(stderr, "WPE fdo doesn't support multiple EGL displays\n");
return;
return false;
}

PFNEGLBINDWAYLANDDISPLAYWL bindWaylandDisplayWL =
reinterpret_cast<PFNEGLBINDWAYLANDDISPLAYWL>(eglGetProcAddress("eglBindWaylandDisplayWL"));
bindWaylandDisplayWL(eglDisplay, m_display);
const char* extensions = eglQueryString(eglDisplay, EGL_EXTENSIONS);
if (isEGLExtensionSupported(extensions, "EGL_WL_bind_wayland_display"))
eglBindWaylandDisplayWL = reinterpret_cast<PFNEGLBINDWAYLANDDISPLAYWL>(eglGetProcAddress("eglBindWaylandDisplayWL"));
if (!eglBindWaylandDisplayWL)
return false;

if (isEGLExtensionSupported(extensions, "EGL_KHR_image_base")) {
eglCreateImageKHR = reinterpret_cast<PFNEGLCREATEIMAGEKHRPROC>(eglGetProcAddress("eglCreateImageKHR"));
eglDestroyImageKHR = reinterpret_cast<PFNEGLDESTROYIMAGEKHRPROC>(eglGetProcAddress("eglDestroyImageKHR"));
}
if (!eglCreateImageKHR || !eglDestroyImageKHR)
return false;

if (!eglBindWaylandDisplayWL(eglDisplay, m_display))
return false;

m_eglDisplay = eglDisplay;

/* Initialize Linux dmabuf subsystem. */
linux_dmabuf_setup(m_display, eglDisplay);

return true;
}

int Instance::createClient()
{
if (m_eglDisplay == EGL_NO_DISPLAY)
return -1;

int pair[2];
if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, pair) < 0)
return -1;
Expand All @@ -296,6 +360,84 @@ void Instance::createSurface(uint32_t id, Surface* surface)
m_viewBackendMap.insert({ id, surface });
}

EGLImageKHR Instance::createImage(struct wl_resource* resourceBuffer)
{
if (m_eglDisplay == EGL_NO_DISPLAY)
return EGL_NO_IMAGE_KHR;
return eglCreateImageKHR(m_eglDisplay, EGL_NO_CONTEXT, EGL_WAYLAND_BUFFER_WL, resourceBuffer, nullptr);
}

EGLImageKHR Instance::createImage(const struct linux_dmabuf_buffer* dmabufBuffer)
{
if (m_eglDisplay == EGL_NO_DISPLAY)
return EGL_NO_IMAGE_KHR;
const struct linux_dmabuf_attributes* bufAttribs =
linux_dmabuf_get_buffer_attributes(dmabufBuffer);
assert(bufAttribs);

static const struct {
EGLint fd;
EGLint offset;
EGLint pitch;
EGLint modifierLo;
EGLint modifierHi;
} planeEnums[4] = {
{EGL_DMA_BUF_PLANE0_FD_EXT,
EGL_DMA_BUF_PLANE0_OFFSET_EXT,
EGL_DMA_BUF_PLANE0_PITCH_EXT,
EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT,
EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT},
{EGL_DMA_BUF_PLANE1_FD_EXT,
EGL_DMA_BUF_PLANE1_OFFSET_EXT,
EGL_DMA_BUF_PLANE1_PITCH_EXT,
EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT,
EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT},
{EGL_DMA_BUF_PLANE2_FD_EXT,
EGL_DMA_BUF_PLANE2_OFFSET_EXT,
EGL_DMA_BUF_PLANE2_PITCH_EXT,
EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT,
EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT},
{EGL_DMA_BUF_PLANE3_FD_EXT,
EGL_DMA_BUF_PLANE3_OFFSET_EXT,
EGL_DMA_BUF_PLANE3_PITCH_EXT,
EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT,
EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT},
};

EGLint attribs[50];
int atti = 0;
attribs[atti++] = EGL_WIDTH;
attribs[atti++] = bufAttribs->width;
attribs[atti++] = EGL_HEIGHT;
attribs[atti++] = bufAttribs->height;
attribs[atti++] = EGL_LINUX_DRM_FOURCC_EXT;
attribs[atti++] = bufAttribs->format;

for (int i = 0; i < bufAttribs->n_planes; i++) {
attribs[atti++] = planeEnums[i].fd;
attribs[atti++] = bufAttribs->fd[i];
attribs[atti++] = planeEnums[i].offset;
attribs[atti++] = bufAttribs->offset[i];
attribs[atti++] = planeEnums[i].pitch;
attribs[atti++] = bufAttribs->stride[i];
attribs[atti++] = planeEnums[i].modifierLo;
attribs[atti++] = bufAttribs->modifier[i] & 0xFFFFFFFF;
attribs[atti++] = planeEnums[i].modifierHi;
attribs[atti++] = bufAttribs->modifier[i] >> 32;
}

attribs[atti++] = EGL_NONE;

return eglCreateImageKHR(m_eglDisplay, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, nullptr, attribs);
}

void Instance::destroyImage(EGLImageKHR image)
{
if (m_eglDisplay == EGL_NO_DISPLAY)
return;
eglDestroyImageKHR(m_eglDisplay, image);
}

struct wl_client* Instance::registerViewBackend(uint32_t id, ExportableClient& exportableClient)
{
auto it = m_viewBackendMap.find(id);
Expand Down
Loading

0 comments on commit 9991dac

Please sign in to comment.