Skip to content

Commit

Permalink
Merge pull request #24 from Metrological/comcast
Browse files Browse the repository at this point in the history
Basic Weseros support added.
  • Loading branch information
zdobersek committed Feb 25, 2016
2 parents 40ea41b + 36f9767 commit e9b7cb0
Show file tree
Hide file tree
Showing 12 changed files with 894 additions and 0 deletions.
25 changes: 25 additions & 0 deletions Source/WPE/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ if (USE_WPE_BACKEND_INTEL_CE)
add_definitions(-DWPE_BACKEND_INTEL_CE=1)
endif ()

if (USE_WPE_BACKEND_WESTEROS)
find_package(westeros REQUIRED)
add_definitions(-DWPE_BACKEND_WESTEROS=1)
endif ()

if (USE_WPE_BUFFER_MANAGEMENT_GBM)
find_package(LibGBM REQUIRED)
add_definitions(-DWPE_BUFFER_MANAGEMENT_GBM=1)
Expand All @@ -60,6 +65,7 @@ set(WPE_INCLUDE_DIRECTORIES
"${CMAKE_SOURCE_DIR}/Source/WPE/Source/Graphics/BCMRPi"
"${CMAKE_SOURCE_DIR}/Source/WPE/Source/Graphics/GBM"
"${CMAKE_SOURCE_DIR}/Source/WPE/Source/Graphics/IntelCE"
"${CMAKE_SOURCE_DIR}/Source/WPE/Source/Graphics/Westeros"
"${CMAKE_SOURCE_DIR}/Source/WPE/Source/Input"
"${CMAKE_SOURCE_DIR}/Source/WPE/Source/Pasteboard"
"${CMAKE_SOURCE_DIR}/Source/WPE/Source/Pasteboard"
Expand All @@ -72,13 +78,15 @@ set(WPE_INCLUDE_DIRECTORIES
"${CMAKE_SOURCE_DIR}/Source/WPE/Source/ViewBackend/IntelCE"
"${CMAKE_SOURCE_DIR}/Source/WPE/Source/ViewBackend/Wayland"
"${CMAKE_SOURCE_DIR}/Source/WPE/Source/ViewBackend/Wayland/Protocols"
"${CMAKE_SOURCE_DIR}/Source/WPE/Source/ViewBackend/Westeros"
${BCM_HOST_INCLUDE_DIRS}
${GDL_INCLUDE_DIRS}
${GLIB_INCLUDE_DIRS}
${LIBINPUT_INCLUDE_DIRS}
${LIBUDEV_INCLUDE_DIRS}
${LIBXKBCOMMON_INCLUDE_DIRS}
${WAYLAND_INCLUDE_DIRS}
${WESTEROS_INCLUDE_DIRS}
)

set(WPE_LIBRARIES
Expand Down Expand Up @@ -138,6 +146,23 @@ if (USE_WPE_BACKEND_INTEL_CE)
)
endif ()

if (USE_WPE_BACKEND_WESTEROS)
list(APPEND WPE_INCLUDE_DIRECTORIES
${WESTEROS_INCLUDE_DIRS}
${WESTEROSEGL_INCLUDE_DIRS}
)
list(APPEND WPE_LIBRARIES
${WESTEROS_LIBRARIES}
${WESTEROSEGL_LIBRARIES}
)
list(APPEND WPE_SOURCES
Source/Graphics/Westeros/RenderingBackendWesteros.cpp

Source/ViewBackend/Westeros/ViewBackendWesteros.cpp
Source/ViewBackend/Westeros/WesterosViewbackendInput.cpp
)
endif ()

if (USE_WPE_BUFFER_MANAGEMENT_GBM)
list(APPEND WPE_INCLUDE_DIRECTORIES
"${CMAKE_SOURCE_DIR}/Source/WPE/Source/Graphics/GBM"
Expand Down
5 changes: 5 additions & 0 deletions Source/WPE/Source/Graphics/RenderingBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "RenderingBackendBCMNexus.h"
#include "RenderingBackendBCMRPi.h"
#include "RenderingBackendIntelCE.h"
#include "RenderingBackendWesteros.h"
#include <cstdio>

#if WPE_BUFFER_MANAGEMENT(GBM)
Expand Down Expand Up @@ -76,6 +77,10 @@ std::unique_ptr<RenderingBackend> RenderingBackend::create(const uint8_t* data,
return std::unique_ptr<RenderingBackendIntelCE>(new RenderingBackendIntelCE);
#endif

#if WPE_BACKEND(WESTEROS)
return std::unique_ptr<RenderingBackendWesteros>(new RenderingBackendWesteros);
#endif

fprintf(stderr, "RenderingBackend: no usable backend found, will crash.\n");
return nullptr;
}
Expand Down
211 changes: 211 additions & 0 deletions Source/WPE/Source/Graphics/Westeros/RenderingBackendWesteros.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
#include "Config.h"

#if WPE_BACKEND(WESTEROS)

#include "RenderingBackendWesteros.h"
#include <EGL/egl.h>
#include <cstring>
#include <array>
#include <unordered_map>
#include <utility>
#include <glib.h>

namespace WPE {

namespace Graphics {

typedef struct _GSource GSource;

class EventSource {
public:
static GSourceFuncs sourceFuncs;

GSource source;
GPollFD pfd;
struct wl_display* display;
};

GSourceFuncs EventSource::sourceFuncs = {
// prepare
[](GSource* base, gint* timeout) -> gboolean
{
auto* source = reinterpret_cast<EventSource*>(base);
struct wl_display* display = source->display;

*timeout = -1;
wl_display_flush(display);
wl_display_dispatch_pending(display);

return FALSE;
},
// check
[](GSource* base) -> gboolean
{
auto* source = reinterpret_cast<EventSource*>(base);
return !!source->pfd.revents;
},
// dispatch
[](GSource* base, GSourceFunc, gpointer) -> gboolean
{
auto* source = reinterpret_cast<EventSource*>(base);
struct wl_display* display = source->display;

if (source->pfd.revents & G_IO_IN)
wl_display_dispatch(display);

if (source->pfd.revents & (G_IO_ERR | G_IO_HUP))
return FALSE;

source->pfd.revents = 0;
return TRUE;
},
nullptr, // finalize
nullptr, // closure_callback
nullptr, // closure_marshall
};

static wl_display* g_WlDisplay = nullptr;

static struct wl_registry_listener registryListener = {

RenderingBackendWesteros::globalCallback,
RenderingBackendWesteros::globalRemoveCallback
};

void RenderingBackendWesteros::globalCallback(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t)
{
auto& backend = *static_cast<RenderingBackendWesteros*>(data);

if (!std::strcmp(interface, "wl_compositor"))
backend.m_compositor = static_cast<struct wl_compositor*>(wl_registry_bind(registry, name, &wl_compositor_interface, 1));
}

void RenderingBackendWesteros::globalRemoveCallback(void*, struct wl_registry*, uint32_t)
{
// FIXME: if this can happen without the UI Process getting shut down
// we should probably destroy our cached display instance.
}

RenderingBackendWesteros::RenderingBackendWesteros()
: m_display(nullptr)
, m_registry(nullptr)
, m_compositor(nullptr)
{
if (const char* nestedDisplay = std::getenv("WPE_WESTEROS_NESTED_DISPLAY")) {
m_display = wl_display_connect(nestedDisplay);
} else {
m_display = wl_display_connect(nullptr);
}
g_WlDisplay = m_display;

if(!m_display)
return;

m_registry = wl_display_get_registry(m_display);
wl_registry_add_listener(m_registry, &registryListener, this);
wl_display_roundtrip(m_display);

m_eventSource = g_source_new(&EventSource::sourceFuncs, sizeof(EventSource));
auto* source = reinterpret_cast<EventSource*>(m_eventSource);
source->display = m_display;

source->pfd.fd = wl_display_get_fd(m_display);
source->pfd.events = G_IO_IN | G_IO_ERR | G_IO_HUP;
source->pfd.revents = 0;
g_source_add_poll(m_eventSource, &source->pfd);

g_source_set_name(m_eventSource, "[WPE] WaylandDisplay");
g_source_set_priority(m_eventSource, G_PRIORITY_HIGH + 30);
g_source_set_can_recurse(m_eventSource, TRUE);
g_source_attach(m_eventSource, g_main_context_get_thread_default());
}

RenderingBackendWesteros::~RenderingBackendWesteros()
{
if (m_eventSource)
g_source_unref(m_eventSource);
m_eventSource = nullptr;

g_WlDisplay = nullptr;

if (m_compositor)
wl_compositor_destroy(m_compositor);
if (m_registry)
wl_registry_destroy(m_registry);
if (m_display)
wl_display_disconnect(m_display);
}

EGLNativeDisplayType RenderingBackendWesteros::nativeDisplay()
{
return m_display;
}

std::unique_ptr<RenderingBackend::Surface> RenderingBackendWesteros::createSurface(uint32_t width, uint32_t height, uint32_t targetHandle, RenderingBackend::Surface::Client& client)
{
return std::unique_ptr<RenderingBackendWesteros::Surface>(new RenderingBackendWesteros::Surface(*this, width, height, targetHandle, client));
}

std::unique_ptr<RenderingBackend::OffscreenSurface> RenderingBackendWesteros::createOffscreenSurface()
{
return std::unique_ptr<RenderingBackendWesteros::OffscreenSurface>(new RenderingBackendWesteros::OffscreenSurface(*this));
}

RenderingBackendWesteros::Surface::Surface(const RenderingBackendWesteros& backend, uint32_t width, uint32_t height, uint32_t, RenderingBackendWesteros::Surface::Client&)
{
m_surface = wl_compositor_create_surface(backend.m_compositor);

if (m_surface)
m_window = wl_egl_window_create(m_surface, width, height);
}

RenderingBackendWesteros::Surface::~Surface()
{
if (m_window)
wl_egl_window_destroy(m_window);
if (m_surface)
wl_surface_destroy(m_surface);
}

EGLNativeWindowType RenderingBackendWesteros::Surface::nativeWindow()
{
return m_window;
}

void RenderingBackendWesteros::Surface::resize(uint32_t width, uint32_t height)
{
if(m_window) {
wl_egl_window_resize(m_window, width, height, 0, 0);
if(g_WlDisplay)
wl_display_flush(g_WlDisplay);
}
}

RenderingBackend::BufferExport RenderingBackendWesteros::Surface::lockFrontBuffer()
{
// This needs to be called for every eglSwapBuffers for the events to get flushed.
if(g_WlDisplay)
wl_display_flush(g_WlDisplay);
return std::make_tuple(-1, nullptr, 0);
}

void RenderingBackendWesteros::Surface::releaseBuffer(uint32_t)
{
}

RenderingBackendWesteros::OffscreenSurface::OffscreenSurface(const RenderingBackendWesteros&)
{
}

RenderingBackendWesteros::OffscreenSurface::~OffscreenSurface() = default;

EGLNativeWindowType RenderingBackendWesteros::OffscreenSurface::nativeWindow()
{
return nullptr;
}

} // namespace Graphics

} // namespace WPE

#endif // WPE_BACKEND(WESTEROS);
60 changes: 60 additions & 0 deletions Source/WPE/Source/Graphics/Westeros/RenderingBackendWesteros.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#ifndef WPE_Graphics_RenderingBackendWesteros_h
#define WPE_Graphics_RenderingBackendWesteros_h

#include <wayland-client.h>
#include <wayland-egl.h>
#include <WPE/Graphics/RenderingBackend.h>

typedef struct _GSource GSource;

namespace WPE {

namespace Graphics {

class RenderingBackendWesteros final : public RenderingBackend {
public:
class Surface final : public RenderingBackend::Surface {
public:
Surface(const RenderingBackendWesteros&, uint32_t, uint32_t, uint32_t, Client&);
WPE_EXPORT virtual ~Surface();

EGLNativeWindowType nativeWindow() override;
void resize(uint32_t, uint32_t) override;

BufferExport lockFrontBuffer() override;
void releaseBuffer(uint32_t) override;

private:
struct wl_surface* m_surface;
struct wl_egl_window* m_window;
};

class OffscreenSurface final : public RenderingBackend::OffscreenSurface {
public:
OffscreenSurface(const RenderingBackendWesteros&);
virtual ~OffscreenSurface();

EGLNativeWindowType nativeWindow() override;
};

RenderingBackendWesteros();
virtual ~RenderingBackendWesteros();

EGLNativeDisplayType nativeDisplay() override;
std::unique_ptr<RenderingBackend::Surface> createSurface(uint32_t, uint32_t, uint32_t, RenderingBackend::Surface::Client&) override;
std::unique_ptr<RenderingBackend::OffscreenSurface> createOffscreenSurface() override;
static void globalCallback(void* data, struct wl_registry*, uint32_t name, const char* interface, uint32_t version);
static void globalRemoveCallback(void* data, struct wl_registry*, uint32_t name);

private:
struct wl_display* m_display;
struct wl_registry* m_registry;
struct wl_compositor* m_compositor;
GSource* m_eventSource;
};

} // namespace Graphics

} // namespace WPE

#endif // WPE_Graphics_RenderingBackendWesteros_h
6 changes: 6 additions & 0 deletions Source/WPE/Source/ViewBackend/ViewBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "ViewBackendBCMNexus.h"
#include "ViewBackendBCMRPi.h"
#include "ViewBackendIntelCE.h"
#include "ViewBackendWesteros.h"
#include <cstring>
#include <cstdio>
#include <cstdlib>
Expand Down Expand Up @@ -74,6 +75,11 @@ std::unique_ptr<ViewBackend> ViewBackend::create()
return std::unique_ptr<ViewBackendIntelCE>(new ViewBackendIntelCE);
#endif

#if WPE_BACKEND(WESTEROS)
if (!backendEnv || !std::strcmp(backendEnv, "westeros"))
return std::unique_ptr<ViewBackendWesteros>(new ViewBackendWesteros);
#endif

fprintf(stderr, "ViewBackend: no usable backend found, will crash.\n");
return nullptr;
}
Expand Down
Loading

0 comments on commit e9b7cb0

Please sign in to comment.