[PATCH 5/6] DirectFB integration

Denis Oliver Kropp dfbdok at gmail.com
Fri Oct 25 00:11:11 CEST 2013


compositor: Add DirectFB compositor with EGL and Pixman
 support

Please see http://www.directfb.org/docs/DirectFB_Foreseeing_2013-
10-07.pdf
and http://www.directfb.org/docs/DirectFB_EGL_2013-10-07.pdf for details
and plans.

With this version you can run Weston on any DirectFB enabled platform
including OpenGL ES support
via EGL where available.
---
 src/Makefile.am                   |   25 +
 src/compositor-directfb-input.cpp |  214 +++++
 src/compositor-directfb-input.h   |   91 +++
 src/compositor-directfb.cpp       | 1614
+++++++++++++++++++++++++++++++++++++
 src/compositor-directfb.h         |  225 ++++++
 src/compositor.c                  |   13 +
 6 files changed, 2182 insertions(+)
 create mode 100644 src/compositor-directfb-input.cpp
 create mode 100644 src/compositor-directfb-input.h
 create mode 100644 src/compositor-directfb.cpp
 create mode 100644 src/compositor-directfb.h

diff --git a/src/Makefile.am b/src/Makefile.am
index 4224495..4da3039 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -117,6 +117,7 @@ module_LTLIBRARIES = \
  $(drm_backend) \
  $(wayland_backend) \
  $(headless_backend) \
+ $(directfb_backend) \
  $(fbdev_backend) \
  $(rdp_backend)

@@ -237,6 +238,30 @@ headless_backend_la_CFLAGS = \
 headless_backend_la_SOURCES = compositor-headless.c
 endif

+if ENABLE_DIRECTFB_COMPOSITOR
+directfb_backend = directfb-backend.la
+directfb_backend_la_LDFLAGS = -module -avoid-version
+directfb_backend_la_LIBADD = \
+ $(COMPOSITOR_LIBS) \
+ $(DIRECTFB_COMPOSITOR_LIBS) \
+ $(DRM_COMPOSITOR_LIBS) \
+ ../shared/libshared.la
+directfb_backend_la_CFLAGS = \
+ $(COMPOSITOR_CFLAGS) \
+ $(DIRECTFB_COMPOSITOR_CFLAGS) \
+ $(PIXMAN_CFLAGS) \
+ $(GCC_CFLAGS)
+directfb_backend_la_CXXFLAGS = \
+ $(directfb_backend_la_CFLAGS)
+directfb_backend_la_SOURCES = \
+ compositor-directfb.cpp \
+ compositor-directfb-input.cpp \
+ launcher-util.c
+# Replaced by weston-dfb-adapter for now
+# compositor-directfb-windows.cpp \
+#
+endif
+
 if ENABLE_FBDEV_COMPOSITOR
 fbdev_backend = fbdev-backend.la
 fbdev_backend_la_LDFLAGS = -module -avoid-version
diff --git a/src/compositor-directfb-input.cpp
b/src/compositor-directfb-input.cpp
new file mode 100644
index 0000000..9c08f75
--- /dev/null
+++ b/src/compositor-directfb-input.cpp
@@ -0,0 +1,214 @@
+/*
+ * Copyright © 2008-2011 Kristian Høgsberg
+ * Copyright © 2011 Intel Corporation
+ * Copyright © 2012 Raspberry Pi Foundation
+ * Copyright © 2013 Philip Withnall
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee,
provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission.  The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "config.h"
+
+#include <++dfb.h>
+
+#include <++dfb_mangle.h>
+#include <wayland-dfb.h>
+#include <++dfb_unmangle.h>
+
+#include <stdexcept>
+
+extern "C" {
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <linux/fb.h>
+#include <linux/input.h>
+}
+
+#include "compositor-directfb.h"
+#include "compositor-directfb-input.h"
+
+
+D_DEBUG_DOMAIN( WestonDFB_Input,      "WestonDFB/Input",      "Weston
DirectFB Input" );
+
+/**********************************************************************************************************************/
+
+InputDeviceManager::InputDeviceManager( directfb_compositor &compositor )
+ :
+ compositor( compositor )
+{
+}
+
+InputDeviceManager::~InputDeviceManager()
+{
+}
+
+void
+InputDeviceManager::init()
+{
+ D_DEBUG_AT( WestonDFB_Input, "InputDeviceManager::%s()\n", __FUNCTION__ );
+
+ struct xkb_keymap *keymap;
+
+ weston_seat_init(&seat, &compositor.base, "default");
+
+ if (compositor.param.no_input)
+ return;
+
+ weston_seat_init_pointer(&seat);
+
+ keymap = NULL;//directfb_compositor_get_keymap(c);
+
+ if (weston_seat_init_keyboard( &seat, keymap ) < 0)
+ return;
+
+ if (keymap)
+ xkb_map_unref(keymap);
+
+ //notify_keyboard_focus_in(&seat, &keys, STATE_UPDATE_AUTOMATIC);
+
+// directfb_compositor_setup_xkb(c);
+}
+
+void
+InputDeviceManager::shutdown()
+{
+ D_DEBUG_AT( WestonDFB_Input, "InputDeviceManager::%s()\n", __FUNCTION__ );
+
+ devices.clear();
+
+ weston_seat_release(&seat);
+}
+
+void
+InputDeviceManager::AddDevice( DFBInputDeviceID device_id )
+{
+ D_DEBUG_AT( WestonDFB_Input, "InputDeviceManager::%s( %u )\n",
__FUNCTION__, device_id );
+
+ auto device = devices[device_id];
+
+ if (device) {
+ D_WARN( "device %u already added", device_id );
+ return;
+ }
+
+ device = compositor.dfb.GetInputDevice( device_id );
+
+ devices[device_id] = device;
+}
+
+void
+InputDeviceManager::RemoveDevice( DFBInputDeviceID device_id )
+{
+ D_DEBUG_AT( WestonDFB_Input, "InputDeviceManager::%s( %u )\n",
__FUNCTION__, device_id );
+
+ if (!devices[device_id])
+ D_WARN( "device %u not added", device_id );
+ else
+ devices[device_id] = NULL;
+}
+
+void
+InputDeviceManager::HandleInputEvent( const DFBInputEvent &event )
+{
+ D_DEBUG_AT( WestonDFB_Input, "InputDeviceManager::%s( %p, event %p ) <-
type 0x%04x\n", __FUNCTION__, this, &event, event.type );
+
+ switch (event.type) {
+ //case DIET_DEVICE_ADDED:
+ //     AddDevice( event.device_id );
+ //     break;
+ //
+ //case DIET_DEVICE_REMOVED:
+ //     RemoveDevice( event.device_id );
+ //     break;
+
+ case DIET_AXISMOTION:
+ switch (event.axis) {
+ case DIAI_X:
+ D_DEBUG_AT( WestonDFB_Input, "  -> AXIS X %d\n", event.axisabs );
+
+ if (event.flags & DIEF_AXISABS) {
+ px = event.axisabs;
+
+ notify_motion_absolute( &seat, weston_compositor_get_time(),
+ wl_fixed_from_int( px ),
+ wl_fixed_from_int( py ) );
+ } else
+ notify_motion( &seat, weston_compositor_get_time(),
+       wl_fixed_from_int( event.axisrel ), 0 );
+ break;
+
+ case DIAI_Y:
+ D_DEBUG_AT( WestonDFB_Input, "  -> AXIS Y %d\n", event.axisabs );
+
+ if (event.flags & DIEF_AXISABS) {
+ py = event.axisabs;
+
+ notify_motion_absolute( &seat, weston_compositor_get_time(),
+ wl_fixed_from_int( px ),
+ wl_fixed_from_int( py ) );
+ } else
+ notify_motion( &seat, weston_compositor_get_time(),
+       0, wl_fixed_from_int( event.axisrel ) );
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case DIET_BUTTONPRESS:
+ D_DEBUG_AT( WestonDFB_Input, "  -> BUTTON PRESS %d\n", event.button );
+
+ notify_button( &seat, weston_compositor_get_time(), event.button +
BTN_LEFT - DIBI_FIRST,
+       WL_POINTER_BUTTON_STATE_PRESSED );
+ break;
+
+ case DIET_BUTTONRELEASE:
+ D_DEBUG_AT( WestonDFB_Input, "  -> BUTTON RELEASE %d\n", event.button );
+
+ notify_button( &seat, weston_compositor_get_time(), event.button +
BTN_LEFT - DIBI_FIRST,
+       WL_POINTER_BUTTON_STATE_RELEASED );
+ break;
+
+ case DIET_KEYPRESS:
+ D_DEBUG_AT( WestonDFB_Input, "  -> KEY PRESS %d\n", event.key_code );
+
+ notify_key( &seat, weston_compositor_get_time(), event.key_code,
+    WL_KEYBOARD_KEY_STATE_PRESSED, STATE_UPDATE_AUTOMATIC );
+ break;
+
+ case DIET_KEYRELEASE:
+ D_DEBUG_AT( WestonDFB_Input, "  -> KEY RELEASE %d\n", event.key_code );
+
+ notify_key( &seat, weston_compositor_get_time(), event.key_code,
+    WL_KEYBOARD_KEY_STATE_RELEASED, STATE_UPDATE_AUTOMATIC );
+ break;
+
+ default:
+ break;
+ }
+}
+
diff --git a/src/compositor-directfb-input.h
b/src/compositor-directfb-input.h
new file mode 100644
index 0000000..a8adef3
--- /dev/null
+++ b/src/compositor-directfb-input.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright © 2008-2011 Kristian Høgsberg
+ * Copyright © 2011 Intel Corporation
+ * Copyright © 2012 Raspberry Pi Foundation
+ * Copyright © 2013 Philip Withnall
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee,
provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission.  The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __COMPOSITOR_DIRECTFB_INPUT_H__
+#define __COMPOSITOR_DIRECTFB_INPUT_H__
+
+#include <++dfb.h>
+
+#include <++dfb_mangle.h>
+#include <wayland-dfb.h>
+#include <++dfb_unmangle.h>
+
+#include <stdexcept>
+
+extern "C" {
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <linux/fb.h>
+#include <linux/input.h>
+
+#include "launcher-util.h"
+#include "gl-renderer.h"
+#include "pixman-renderer.h"
+}
+
+class InputDevice {
+private:
+
+public:
+
+};
+
+class directfb_compositor;
+
+
+class InputDeviceManager {
+private:
+ directfb_compositor                              &compositor;
+ struct weston_seat                                seat;
+ std::map<DFBInputDeviceID,IDirectFBInputDevice>   devices;
+
+public:
+ InputDeviceManager( directfb_compositor &compositor );
+ ~InputDeviceManager();
+
+ void AddDevice( DFBInputDeviceID device_id );
+ void RemoveDevice( DFBInputDeviceID device_id );
+
+ void HandleInputEvent( const DFBInputEvent &event );
+
+private:
+ friend class directfb_compositor;
+
+ int px, py;
+
+ void init();
+ void shutdown();
+};
+
+
+#endif
+
diff --git a/src/compositor-directfb.cpp b/src/compositor-directfb.cpp
new file mode 100644
index 0000000..cc1e764
--- /dev/null
+++ b/src/compositor-directfb.cpp
@@ -0,0 +1,1614 @@
+/*
+ * Copyright © 2008-2011 Kristian Høgsberg
+ * Copyright © 2011 Intel Corporation
+ * Copyright © 2012 Raspberry Pi Foundation
+ * Copyright © 2013 Philip Withnall
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee,
provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission.  The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "config.h"
+
+#include <++dfb.h>
+
+#include <++dfb_mangle.h>
+#include <wayland-dfb.h>
+#include <++dfb_unmangle.h>
+
+#include <stdexcept>
+
+#include <wayland-client.h>
+
+extern "C" {
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <linux/fb.h>
+#include <linux/input.h>
+
+#include "compositor.h"
+#include "launcher-util.h"
+#include "gl-renderer.h"
+#include "pixman-renderer.h"
+}
+
+#include "compositor-directfb.h"
+
+
+D_DEBUG_DOMAIN( WestonDFB_Compositor, "WestonDFB/Compositor", "Weston
DirectFB Compositor" );
+D_DEBUG_DOMAIN( WestonDFB_Output,     "WestonDFB/Output",     "Weston
DirectFB Output" );
+
+/**********************************************************************************************************************/
+
+static const char default_seat[] = "seat0";
+
+static struct gl_renderer_interface *gl_renderer;
+
+/**********************************************************************************************************************/
+
+static void
+directfb_output_start_repaint_loop(struct weston_output *output)
+{
+ uint32_t msec;
+ struct timeval tv;
+
+ D_DEBUG_AT( WestonDFB_Compositor, "%s()\n", __FUNCTION__ );
+
+ gettimeofday(&tv, NULL);
+ msec = tv.tv_sec * 1000 + tv.tv_usec / 1000;
+ weston_output_finish_frame(output, msec);
+}
+
+/**********************************************************************************************************************/
+/**********************************************************************************************************************/
+
+static void
+output_get_buffer_damage(struct weston_output *output,
+ pixman_region32_t *buffer_damage)
+{
+ struct directfb_output *dfboutput = to_directfb_output(output);
+
+ EGLint buffer_age = 0;
+ int i;
+
+ if (buffer_age == 0 || buffer_age - 1 > BUFFER_DAMAGE_COUNT)
+ pixman_region32_copy(buffer_damage, &output->region);
+ else
+ for (i = 0; i < buffer_age - 1; i++)
+ pixman_region32_union(buffer_damage, buffer_damage,
+      &dfboutput->buffer_damage[i]);
+}
+
+static void
+output_rotate_damage(struct weston_output *output,
+     pixman_region32_t *output_damage)
+{
+ struct directfb_output *dfboutput = to_directfb_output(output);
+
+ int i;
+
+ for (i = BUFFER_DAMAGE_COUNT - 1; i >= 1; i--)
+ pixman_region32_copy(&dfboutput->buffer_damage[i],
+     &dfboutput->buffer_damage[i - 1]);
+
+ pixman_region32_copy(&dfboutput->buffer_damage[0], output_damage);
+}
+
+static void
+box_scale(pixman_box32_t *dst, int scale)
+{
+ dst->x1 *= scale;
+ dst->x2 *= scale;
+ dst->y1 *= scale;
+ dst->y2 *= scale;
+}
+
+static void
+scale_region (pixman_region32_t *region, int scale)
+{
+ pixman_box32_t *rects, *scaled_rects;
+ int nrects, i;
+
+ if (scale != 1) {
+ rects = pixman_region32_rectangles(region, &nrects);
+ scaled_rects = (pixman_box32_t*) calloc(nrects, sizeof(pixman_box32_t));
+
+ for (i = 0; i < nrects; i++) {
+ scaled_rects[i] = rects[i];
+ box_scale(&scaled_rects[i], scale);
+ }
+ pixman_region32_clear(region);
+
+ pixman_region32_init_rects (region, scaled_rects, nrects);
+ free (scaled_rects);
+ }
+}
+
+static void
+transform_region (pixman_region32_t *region, int width, int height, enum
wl_output_transform transform)
+{
+ pixman_box32_t *rects, *transformed_rects;
+ int nrects, i;
+
+ if (transform == WL_OUTPUT_TRANSFORM_NORMAL)
+ return;
+
+ rects = pixman_region32_rectangles(region, &nrects);
+ transformed_rects = (pixman_box32_t*) calloc(nrects,
sizeof(pixman_box32_t));
+
+ for (i = 0; i < nrects; i++) {
+ switch (transform) {
+ default:
+ case WL_OUTPUT_TRANSFORM_NORMAL:
+ transformed_rects[i].x1 = rects[i].x1;
+ transformed_rects[i].y1 = rects[i].y1;
+ transformed_rects[i].x2 = rects[i].x2;
+ transformed_rects[i].y2 = rects[i].y2;
+ break;
+ case WL_OUTPUT_TRANSFORM_90:
+ transformed_rects[i].x1 = height - rects[i].y2;
+ transformed_rects[i].y1 = rects[i].x1;
+ transformed_rects[i].x2 = height - rects[i].y1;
+ transformed_rects[i].y2 = rects[i].x2;
+ break;
+ case WL_OUTPUT_TRANSFORM_180:
+ transformed_rects[i].x1 = width - rects[i].x2;
+ transformed_rects[i].y1 = height - rects[i].y2;
+ transformed_rects[i].x2 = width - rects[i].x1;
+ transformed_rects[i].y2 = height - rects[i].y1;
+ break;
+ case WL_OUTPUT_TRANSFORM_270:
+ transformed_rects[i].x1 = rects[i].y1;
+ transformed_rects[i].y1 = width - rects[i].x2;
+ transformed_rects[i].x2 = rects[i].y2;
+ transformed_rects[i].y2 = width - rects[i].x1;
+ break;
+ case WL_OUTPUT_TRANSFORM_FLIPPED:
+ transformed_rects[i].x1 = width - rects[i].x2;
+ transformed_rects[i].y1 = rects[i].y1;
+ transformed_rects[i].x2 = width - rects[i].x1;
+ transformed_rects[i].y2 = rects[i].y2;
+ break;
+ case WL_OUTPUT_TRANSFORM_FLIPPED_90:
+ transformed_rects[i].x1 = height - rects[i].y2;
+ transformed_rects[i].y1 = width - rects[i].x2;
+ transformed_rects[i].x2 = height - rects[i].y1;
+ transformed_rects[i].y2 = width - rects[i].x1;
+ break;
+ case WL_OUTPUT_TRANSFORM_FLIPPED_180:
+ transformed_rects[i].x1 = rects[i].x1;
+ transformed_rects[i].y1 = height - rects[i].y2;
+ transformed_rects[i].x2 = rects[i].x2;
+ transformed_rects[i].y2 = height - rects[i].y1;
+ break;
+ case WL_OUTPUT_TRANSFORM_FLIPPED_270:
+ transformed_rects[i].x1 = rects[i].y1;
+ transformed_rects[i].y1 = rects[i].x1;
+ transformed_rects[i].x2 = rects[i].y2;
+ transformed_rects[i].y2 = rects[i].x2;
+ break;
+ }
+ }
+ pixman_region32_clear(region);
+
+ pixman_region32_init_rects (region, transformed_rects, nrects);
+ free (transformed_rects);
+}
+
+static void
+region_global_to_output(struct weston_output *output, pixman_region32_t
*region)
+{
+ pixman_region32_translate(region, -output->x, -output->y);
+ transform_region (region, output->width, output->height,
(wl_output_transform) output->transform);
+ scale_region (region, output->current_scale);
+}
+
+#define D2F(v) pixman_double_to_fixed((double)v)
+
+static void
+repaint_region(struct weston_view *ev, struct weston_output *output,
+       pixman_region32_t *region, pixman_region32_t *surf_region,
+       pixman_op_t pixman_op)
+{
+ D_DEBUG_AT( WestonDFB_Compositor, "directfb_compositor::%s(
weston_surface %p )\n", __FUNCTION__, ev );
+
+ struct directfb_surface_state *state  = (directfb_surface_state*)
ev->surface->compositor_state;
+ IDirectFBSurface               source = state->surface;
+
+ if (!source) {
+ D_DEBUG_AT( WestonDFB_Compositor, "  -> No surface attached!\n" );
+ return;
+ }
+
+ struct directfb_output *dfboutput = to_directfb_output(output);
+ IDirectFBSurface        dest      = dfboutput->surface;
+
+ pixman_region32_t final_region;
+ float surface_x, surface_y;
+ pixman_transform_t transform;
+ pixman_fixed_t fw, fh;
+
+ /* The final region to be painted is the intersection of
+ * 'region' and 'surf_region'. However, 'region' is in the global
+ * coordinates, and 'surf_region' is in the surface-local
+ * coordinates
+ */
+ pixman_region32_init(&final_region);
+ if (surf_region) {
+ pixman_region32_copy(&final_region, surf_region);
+
+ /* Convert from surface to global coordinates */
+ if (!ev->transform.enabled) {
+ pixman_region32_translate(&final_region, ev->geometry.x, ev->geometry.y);
+ } else {
+ weston_view_to_global_float(ev, 0, 0, &surface_x, &surface_y);
+ pixman_region32_translate(&final_region, (int)surface_x, (int)surface_y);
+ }
+
+ /* We need to paint the intersection */
+ pixman_region32_intersect(&final_region, &final_region, region);
+ } else {
+ /* If there is no surface region, just use the global region */
+ pixman_region32_copy(&final_region, region);
+ }
+
+ /* Convert from global to output coord */
+ region_global_to_output(output, &final_region);
+
+ DFBRegion dfbclip( final_region.extents.x1, final_region.extents.y1,
final_region.extents.x2-1, final_region.extents.y2-1 );
+
+ dest.SetClip( &dfbclip );
+
+ /* Set up the source transformation based on the surface
+   position, the output position/transform/scale and the client
+   specified buffer transform/scale */
+ pixman_transform_init_identity(&transform);
+ pixman_transform_scale(&transform, NULL,
+       pixman_double_to_fixed ((double)1.0/output->current_scale),
+       pixman_double_to_fixed ((double)1.0/output->current_scale));
+
+ fw = pixman_int_to_fixed(output->width);
+ fh = pixman_int_to_fixed(output->height);
+ switch (output->transform) {
+ default:
+ case WL_OUTPUT_TRANSFORM_NORMAL:
+ case WL_OUTPUT_TRANSFORM_FLIPPED:
+ break;
+ case WL_OUTPUT_TRANSFORM_90:
+ case WL_OUTPUT_TRANSFORM_FLIPPED_90:
+ pixman_transform_rotate(&transform, NULL, 0, -pixman_fixed_1);
+ pixman_transform_translate(&transform, NULL, 0, fh);
+ break;
+ case WL_OUTPUT_TRANSFORM_180:
+ case WL_OUTPUT_TRANSFORM_FLIPPED_180:
+ pixman_transform_rotate(&transform, NULL, -pixman_fixed_1, 0);
+ pixman_transform_translate(&transform, NULL, fw, fh);
+ break;
+ case WL_OUTPUT_TRANSFORM_270:
+ case WL_OUTPUT_TRANSFORM_FLIPPED_270:
+ pixman_transform_rotate(&transform, NULL, 0, pixman_fixed_1);
+ pixman_transform_translate(&transform, NULL, fw, 0);
+ break;
+ }
+
+ switch (output->transform) {
+ case WL_OUTPUT_TRANSFORM_FLIPPED:
+ case WL_OUTPUT_TRANSFORM_FLIPPED_90:
+ case WL_OUTPUT_TRANSFORM_FLIPPED_180:
+ case WL_OUTPUT_TRANSFORM_FLIPPED_270:
+ pixman_transform_scale(&transform, NULL,
+       pixman_int_to_fixed (-1),
+       pixman_int_to_fixed (1));
+ pixman_transform_translate(&transform, NULL, fw, 0);
+ break;
+ }
+
+ pixman_transform_translate(&transform, NULL,
+   pixman_double_to_fixed (output->x),
+   pixman_double_to_fixed (output->y));
+
+ if (ev->transform.enabled) {
+ /* Pixman supports only 2D transform matrix, but Weston uses 3D,
+ * so we're omitting Z coordinate here
+ */
+ pixman_transform_t surface_transform = {{
+ { D2F(ev->transform.matrix.d[0]),
+ D2F(ev->transform.matrix.d[4]),
+ D2F(ev->transform.matrix.d[12]),
+ },
+ { D2F(ev->transform.matrix.d[1]),
+ D2F(ev->transform.matrix.d[5]),
+ D2F(ev->transform.matrix.d[13]),
+ },
+ { D2F(ev->transform.matrix.d[3]),
+ D2F(ev->transform.matrix.d[7]),
+ D2F(ev->transform.matrix.d[15]),
+ }
+ }};
+
+ pixman_transform_invert(&surface_transform, &surface_transform);
+ pixman_transform_multiply (&transform, &surface_transform, &transform);
+ } else {
+ pixman_transform_translate(&transform, NULL,
+   pixman_double_to_fixed ((double)-ev->geometry.x),
+   pixman_double_to_fixed ((double)-ev->geometry.y));
+ }
+
+
+ fw = pixman_int_to_fixed(ev->geometry.width);
+ fh = pixman_int_to_fixed(ev->geometry.height);
+
+ switch (ev->surface->buffer_transform) {
+ case WL_OUTPUT_TRANSFORM_FLIPPED:
+ case WL_OUTPUT_TRANSFORM_FLIPPED_90:
+ case WL_OUTPUT_TRANSFORM_FLIPPED_180:
+ case WL_OUTPUT_TRANSFORM_FLIPPED_270:
+ pixman_transform_scale(&transform, NULL,
+       pixman_int_to_fixed (-1),
+       pixman_int_to_fixed (1));
+ pixman_transform_translate(&transform, NULL, fw, 0);
+ break;
+ }
+
+ switch (ev->surface->buffer_transform) {
+ default:
+ case WL_OUTPUT_TRANSFORM_NORMAL:
+ case WL_OUTPUT_TRANSFORM_FLIPPED:
+ break;
+ case WL_OUTPUT_TRANSFORM_90:
+ case WL_OUTPUT_TRANSFORM_FLIPPED_90:
+ pixman_transform_rotate(&transform, NULL, 0, pixman_fixed_1);
+ pixman_transform_translate(&transform, NULL, fh, 0);
+ break;
+ case WL_OUTPUT_TRANSFORM_180:
+ case WL_OUTPUT_TRANSFORM_FLIPPED_180:
+ pixman_transform_rotate(&transform, NULL, -pixman_fixed_1, 0);
+ pixman_transform_translate(&transform, NULL, fw, fh);
+ break;
+ case WL_OUTPUT_TRANSFORM_270:
+ case WL_OUTPUT_TRANSFORM_FLIPPED_270:
+ pixman_transform_rotate(&transform, NULL, 0, -pixman_fixed_1);
+ pixman_transform_translate(&transform, NULL, 0, fw);
+ break;
+ }
+
+ pixman_transform_scale(&transform, NULL,
+       pixman_double_to_fixed ((double)ev->surface->buffer_scale),
+       pixman_double_to_fixed ((double)ev->surface->buffer_scale));
+
+ if (pixman_op == PIXMAN_OP_OVER &&
DFB_PIXELFORMAT_HAS_ALPHA(state->format) && !dfboutput->initial) {
+ dest.SetBlittingFlags( DSBLIT_BLEND_ALPHACHANNEL );
+ dest.SetPorterDuff( DSPD_SRC_OVER );
+ } else
+ dest.SetBlittingFlags( DSBLIT_NOFX );
+
+ dfboutput->initial = false;
+
+ dest.Blit( source, NULL, ev->geometry.x, ev->geometry.y );
+
+ pixman_image_set_clip_region32 (dfboutput->shadow_surface, NULL);
+
+ pixman_region32_fini(&final_region);
+}
+
+static void
+draw_view(struct weston_view *ev, struct weston_output *output,
+  pixman_region32_t *damage) /* in global coordinates */
+{
+ /* repaint bounding region in global coordinates: */
+ pixman_region32_t repaint;
+ /* non-opaque region in surface coordinates: */
+ pixman_region32_t surface_blend;
+
+ pixman_region32_init(&repaint);
+ pixman_region32_intersect(&repaint,
+  &ev->transform.boundingbox, damage);
+ pixman_region32_subtract(&repaint, &repaint, &ev->clip);
+
+ if (!pixman_region32_not_empty(&repaint))
+ goto out;
+
+ if (output->zoom.active) {
+ weston_log("pixman renderer does not support zoom\n");
+ goto out;
+ }
+
+ /* TODO: Implement repaint_region_complex() using
pixman_composite_trapezoids() */
+ if (ev->transform.enabled && ev->transform.matrix.type !=
WESTON_MATRIX_TRANSFORM_TRANSLATE) {
+ repaint_region(ev, output, &repaint, NULL, PIXMAN_OP_OVER);
+ } else {
+ /* blended region is whole surface minus opaque region: */
+ pixman_region32_init_rect(&surface_blend, 0, 0,
+  ev->geometry.width, ev->geometry.height);
+ pixman_region32_subtract(&surface_blend, &surface_blend,
&ev->surface->opaque);
+
+ if (pixman_region32_not_empty(&ev->surface->opaque)) {
+ repaint_region(ev, output, &repaint, &ev->surface->opaque, PIXMAN_OP_SRC);
+ }
+
+ if (pixman_region32_not_empty(&surface_blend)) {
+ repaint_region(ev, output, &repaint, &surface_blend, PIXMAN_OP_OVER);
+ }
+ pixman_region32_fini(&surface_blend);
+ }
+
+
+ out:
+ pixman_region32_fini(&repaint);
+}
+
+static void
+repaint_surfaces(struct weston_output *output, pixman_region32_t *damage)
+{
+ struct directfb_output   *dfboutput  = to_directfb_output(output);
+ struct weston_compositor *compositor = output->compositor;
+ struct weston_view       *view;
+
+ dfboutput->initial = true;
+
+ wl_list_for_each_reverse(view, &compositor->view_list, link)
+ if (view->plane == &compositor->primary_plane)
+ draw_view(view, output, damage);
+}
+
+/**********************************************************************************************************************/
+
+static void
+directfb_output_repaint_2d(struct weston_output *output,
+   pixman_region32_t    *output_damage)
+{
+ struct directfb_output   *dfboutput  = to_directfb_output(output);
+ IDirectFBSurface          surface    = dfboutput->surface;
+
+ pixman_region32_t buffer_damage, total_damage;
+
+ D_DEBUG_AT( WestonDFB_Compositor, "%s()\n", __FUNCTION__ );
+
+ pixman_region32_init(&total_damage);
+ pixman_region32_init(&buffer_damage);
+
+ output_get_buffer_damage(output, &buffer_damage);
+ output_rotate_damage(output, output_damage);
+
+ pixman_region32_union(&total_damage, &buffer_damage, output_damage);
+
+
+ repaint_surfaces(output, &total_damage);
+
+
+ pixman_box32_t *rects;
+ int nrects;
+
+ rects = pixman_region32_rectangles(&total_damage, &nrects);
+
+ for (int i = 0; i < nrects; i++) {
+ DFBRegion bounds = { rects[i].x1, rects[i].y1, rects[i].x2, rects[i].y2};
+
+ dfb_updates_add( &dfboutput->flip_updates, &bounds );
+ }
+
+ pixman_region32_fini(&total_damage);
+ pixman_region32_fini(&buffer_damage);
+
+ pixman_region32_copy(&output->previous_damage, output_damage);
+ wl_signal_emit(&output->frame_signal, output);
+}
+
+static int
+directfb_output_repaint_gl(struct weston_output *base,
+   pixman_region32_t    *damage)
+{
+ struct directfb_output *output = to_directfb_output(base);
+ struct weston_compositor *ec = output->base.compositor;
+
+ D_DEBUG_AT( WestonDFB_Compositor, "%s()\n", __FUNCTION__ );
+
+ /* Schedule the end of the frame. We do not sync this to the frame
+ * buffer clock because users who want that should be using the DRM
+ * compositor. FBIO_WAITFORVSYNC blocks and FB_ACTIVATE_VBL requires
+ * panning, which is broken in most kernel drivers.
+ *
+ * Finish the frame synchronised to the specified refresh rate. The
+ * refresh rate is given in mHz and the interval in ms. */
+ wl_event_source_timer_update(output->finish_frame_timer,
+     1000 / output->mode.refresh);
+
+ if (output->param.use_2d) {
+ EGLDisplay display = eglGetCurrentDisplay();
+
+ if (display != EGL_NO_DISPLAY)
+ eglMakeCurrent( display,
+ EGL_NO_SURFACE, EGL_NO_SURFACE,
+ EGL_NO_CONTEXT );
+
+ D_ASSERT( eglGetCurrentDisplay() == NULL );
+
+ directfb_output_repaint_2d( base, damage );
+
+ if (output->flip_updates.num_regions) {
+ DFBRegion region( output->flip_updates.bounding );
+
+ output->surface.Flip( &region, DSFLIP_NONE );
+
+ dfb_updates_reset( &output->flip_updates );
+ }
+ } else {
+ ec->renderer->repaint_output(base, damage);
+ }
+
+ pixman_region32_subtract(&ec->primary_plane.damage,
+ &ec->primary_plane.damage, damage);
+
+ return 0;
+}
+
+static int
+directfb_output_repaint_pixman(struct weston_output *base,
pixman_region32_t *damage)
+{
+ struct directfb_output *output = to_directfb_output(base);
+ struct weston_compositor *ec = output->base.compositor;
+ pixman_box32_t *rects;
+ int nrects, i, src_x, src_y, x1, y1, x2, y2, width, height;
+
+ D_DEBUG_AT( WestonDFB_Compositor, "%s()\n", __FUNCTION__ );
+
+ /* Schedule the end of the frame. We do not sync this to the frame
+ * buffer clock because users who want that should be using the DRM
+ * compositor. FBIO_WAITFORVSYNC blocks and FB_ACTIVATE_VBL requires
+ * panning, which is broken in most kernel drivers.
+ *
+ * Finish the frame synchronised to the specified refresh rate. The
+ * refresh rate is given in mHz and the interval in ms. */
+ wl_event_source_timer_update(output->finish_frame_timer,
+     1000 / output->mode.refresh);
+
+ if (output->param.use_2d) {
+ directfb_output_repaint_2d( base, damage );
+ } else {
+ /* Repaint the damaged region onto the back buffer. */
+ pixman_renderer_output_set_buffer(base, output->shadow_surface);
+
+ ec->renderer->repaint_output(base, damage);
+
+ /* Transform and composite onto the frame buffer. */
+ width = pixman_image_get_width(output->shadow_surface);
+ height = pixman_image_get_height(output->shadow_surface);
+ rects = pixman_region32_rectangles(damage, &nrects);
+
+ if (nrects > 0) {
+ IDirectFBSurface  surface = output->surface;
+ DFBRegion         bounds = { -1, -1, -1, -1};
+
+ for (i = 0; i < nrects; i++) {
+ switch (base->transform) {
+ default:
+ case WL_OUTPUT_TRANSFORM_NORMAL:
+ x1 = rects[i].x1;
+ x2 = rects[i].x2;
+ y1 = rects[i].y1;
+ y2 = rects[i].y2;
+ break;
+ case WL_OUTPUT_TRANSFORM_180:
+ x1 = width - rects[i].x2;
+ x2 = width - rects[i].x1;
+ y1 = height - rects[i].y2;
+ y2 = height - rects[i].y1;
+ break;
+ case WL_OUTPUT_TRANSFORM_90:
+ x1 = height - rects[i].y2;
+ x2 = height - rects[i].y1;
+ y1 = rects[i].x1;
+ y2 = rects[i].x2;
+ break;
+ case WL_OUTPUT_TRANSFORM_270:
+ x1 = rects[i].y1;
+ x2 = rects[i].y2;
+ y1 = width - rects[i].x2;
+ y2 = width - rects[i].x1;
+ break;
+ }
+ src_x = x1;
+ src_y = y1;
+
+ if (bounds.x1 == -1 || bounds.x1 > x1)
+ bounds.x1 = x1;
+
+ if (bounds.y1 == -1 || bounds.y1 > y1)
+ bounds.y1 = y1;
+
+ if (bounds.x2 == -1 || bounds.x2 < x2)
+ bounds.x2 = x2;
+
+ if (bounds.y2 == -1 || bounds.y2 < y2)
+ bounds.y2 = y2;
+
+ DFBRectangle rect = {x1, y1, /* dest_x, dest_y */
+ x2 - x1, /* width */
+ y2 - y1 /* height */};
+
+ surface.Write( (char*) output->shadow_buf
+       + src_y * output->fb_info.line_length
+       + DFB_BYTES_PER_LINE( output->fb_info.format, src_x ),
+       output->fb_info.line_length,
+       &rect );
+ }
+
+ dfb_updates_add( &output->flip_updates, &bounds );
+ }
+ }
+
+ if (output->flip_updates.num_regions) {
+ DFBRegion region( output->flip_updates.bounding );
+
+ output->surface.Flip( &region, DSFLIP_NONE );
+
+ dfb_updates_reset( &output->flip_updates );
+ }
+
+ /* Update the damage region. */
+ pixman_region32_subtract(&ec->primary_plane.damage,
+ &ec->primary_plane.damage, damage);
+
+ return 0;
+}
+
+/**********************************************************************************************************************/
+
+static int
+finish_frame_handler(void *data)
+{
+ struct directfb_output *output = (struct directfb_output *) data;
+
+ D_DEBUG_AT( WestonDFB_Compositor, "%s()\n", __FUNCTION__ );
+
+ directfb_output_start_repaint_loop(&output->base);
+
+ return 1;
+}
+
+static pixman_format_code_t
+calculate_pixman_format( DFBSurfacePixelFormat format )
+{
+ D_DEBUG_AT( WestonDFB_Compositor, "%s( %s )\n", __FUNCTION__,
dfb_pixelformat_name( format ) );
+
+ switch (format) {
+ case DSPF_ARGB:
+ return PIXMAN_a8r8g8b8;
+
+ case DSPF_ABGR:
+ return PIXMAN_a8b8g8r8;
+
+ case DSPF_RGB32:
+ return PIXMAN_x8r8g8b8;
+
+ default:
+ return(pixman_format_code_t) 0;
+ }
+}
+
+static struct directfb_mode *
+directfb_output_add_mode( struct directfb_output *output,
DFBScreenOutputResolution resolution, int width, int height, int refresh )
+{
+ D_DEBUG_AT( WestonDFB_Compositor, "%s()\n", __FUNCTION__ );
+
+ struct directfb_mode *mode;
+
+ mode = (struct directfb_mode *) malloc(sizeof *mode);
+ if (mode == NULL)
+ return NULL;
+
+ mode->base.flags   = 0;
+ mode->base.width   = width;
+ mode->base.height  = height;
+ mode->base.refresh = refresh;
+
+ mode->resolution   = resolution;
+
+ wl_list_insert(output->base.mode_list.prev, &mode->base.link);
+
+ return mode;
+}
+
+static void directfb_output_destroy(struct weston_output *base);
+
+static struct directfb_mode *
+choose_mode (struct directfb_output *output, struct weston_mode
*target_mode)
+{
+ struct directfb_mode *tmp_mode = NULL, *mode;
+
+ D_DEBUG_AT( WestonDFB_Compositor, "%s()\n", __FUNCTION__ );
+
+ if (output->base.current_mode->width == target_mode->width &&
+    output->base.current_mode->height == target_mode->height &&
+    (output->base.current_mode->refresh == target_mode->refresh ||
+     target_mode->refresh == 0))
+ return(struct directfb_mode *)output->base.current_mode;
+
+ wl_list_for_each(mode, &output->base.mode_list, base.link) {
+ if (mode->base.width == target_mode->width &&
+    mode->base.height == target_mode->height) {
+ if (mode->base.refresh == target_mode->refresh || target_mode->refresh ==
0) {
+ return mode;
+ } else if (!tmp_mode)
+ tmp_mode = mode;
+ }
+ }
+
+ return tmp_mode;
+}
+
+static void
+directfb_output_init_shadow(struct directfb_output *output)
+{
+ pixman_transform_t transform;
+ int shadow_width, shadow_height;
+ int width, height;
+
+ D_DEBUG_AT( WestonDFB_Compositor, "%s()\n", __FUNCTION__ );
+
+ if (output->shadow_buf) {
+ free( output->shadow_buf );
+ output->shadow_buf = NULL;
+ }
+
+ if (output->shadow_surface) {
+ pixman_image_unref( output->shadow_surface );
+ output->shadow_surface = NULL;
+ }
+
+ width  = output->mode.width;
+ height = output->mode.height;
+
+ pixman_transform_init_identity(&transform);
+
+ switch (output->base.transform) {
+ default:
+ case WL_OUTPUT_TRANSFORM_NORMAL:
+ shadow_width = width;
+ shadow_height = height;
+ pixman_transform_rotate(&transform,
+ NULL, 0, 0);
+ pixman_transform_translate(&transform, NULL,
+   0, 0);
+ break;
+ case WL_OUTPUT_TRANSFORM_180:
+ shadow_width = width;
+ shadow_height = height;
+ pixman_transform_rotate(&transform,
+ NULL, -pixman_fixed_1, 0);
+ pixman_transform_translate(NULL, &transform,
+   pixman_int_to_fixed(shadow_width),
+   pixman_int_to_fixed(shadow_height));
+ break;
+ case WL_OUTPUT_TRANSFORM_270:
+ shadow_width = height;
+ shadow_height = width;
+ pixman_transform_rotate(&transform,
+ NULL, 0, pixman_fixed_1);
+ pixman_transform_translate(&transform,
+   NULL,
+   pixman_int_to_fixed(shadow_width),
+   0);
+ break;
+ case WL_OUTPUT_TRANSFORM_90:
+ shadow_width = height;
+ shadow_height = width;
+ pixman_transform_rotate(&transform,
+ NULL, 0, -pixman_fixed_1);
+ pixman_transform_translate(&transform,
+   NULL,
+   0,
+   pixman_int_to_fixed(shadow_height));
+ break;
+ }
+
+ output->shadow_buf = malloc( output->fb_info.buffer_length );
+ if (!output->shadow_buf)
+ throw std::runtime_error( "malloc failed" );
+
+ output->shadow_surface = pixman_image_create_bits(
output->fb_info.pixel_format,
+   shadow_width, shadow_height,
+   (uint32_t*) output->shadow_buf,
+   output->fb_info.line_length );
+ if (!output->shadow_surface)
+ throw std::runtime_error( "pixman_image_create_bits failed" );
+
+
+ if (output->param.use_pixman) {
+ if (output->base.renderer_state != NULL) {
+ pixman_renderer_output_destroy( &output->base );
+ output->base.renderer_state = NULL;
+ }
+
+ if (pixman_renderer_output_create( &output->base ) < 0)
+ throw std::runtime_error( "failed to init output pixman state with new
mode" );
+ } else {
+ if (output->base.renderer_state != NULL) {
+ gl_renderer->output_destroy( &output->base );
+ output->base.renderer_state = NULL;
+ }
+
+
+ IDirectFBSurface sub;
+
+ sub = output->surface.GetSubSurface( NULL );
+
+ if (gl_renderer->output_create(&output->base,
(EGLNativeWindowType)sub.iface) < 0)
+ throw std::runtime_error( "failed to init output egl state with new mode"
);
+ }
+}
+
+static int
+directfb_output_switch_mode(struct weston_output *output_base, struct
weston_mode *mode)
+{
+ struct directfb_output *output;
+ struct directfb_mode *directfb_mode;
+ struct directfb_compositor *ec;
+
+ D_DEBUG_AT( WestonDFB_Compositor, "%s()\n", __FUNCTION__ );
+
+ if (output_base == NULL) {
+ weston_log("output is NULL.\n");
+ return -1;
+ }
+
+ if (mode == NULL) {
+ weston_log("mode is NULL.\n");
+ return -1;
+ }
+
+ (void) ec;
+
+ ec = (struct directfb_compositor *)output_base->compositor;
+ output = (struct directfb_output *)output_base;
+ directfb_mode = choose_mode (output, mode);
+
+ if (!directfb_mode) {
+ weston_log("%s, invalid resolution:%dx%d\n", __func__, mode->width,
mode->height);
+ return -1;
+ }
+
+ if (&directfb_mode->base == output->base.current_mode)
+ return 0;
+
+
+ DFBScreenOutputConfig config;
+
+ config.flags      = DSOCONF_RESOLUTION;
+ config.resolution = directfb_mode->resolution;
+
+ ec->screen.SetOutputConfiguration( output->index, config );
+
+
+ DFBDisplayLayerConfig lconf;
+
+ lconf.flags  = (DFBDisplayLayerConfigFlags)( DLCONF_WIDTH | DLCONF_HEIGHT
);
+ lconf.width  = mode->width;
+ lconf.height = mode->height;
+
+ output->layer.SetConfiguration( lconf );
+
+
+ output->base.current_mode->flags = 0;
+
+ output->base.current_mode = &directfb_mode->base;
+ output->base.current_mode->flags = WL_OUTPUT_MODE_CURRENT |
WL_OUTPUT_MODE_PREFERRED;
+
+ output->mode = *mode;
+
+ directfb_output_init_shadow( output );
+
+ return 0;
+}
+
+/**********************************************************************************************************************/
+
+static int
+directfb_output_create( struct directfb_compositor        *compositor,
+ int                                index,
+ const DFBScreenDescription        *sdesc,
+ const DFBScreenMixerDescription   *mdescs,
+ const DFBScreenEncoderDescription *edescs,
+ const DFBScreenOutputDescription  *odescs )
+{
+ struct directfb_output *output;
+ struct wl_event_loop *loop;
+
+ IDirectFB dfb = compositor->dfb;
+
+ D_DEBUG_AT( WestonDFB_Compositor, "%s()\n", __FUNCTION__ );
+
+ weston_log("Creating directfb output.\n");
+
+ output = new directfb_output();
+ if (!output)
+ return -1;
+
+ try {
+ int i = 0;
+
+ output->param      = compositor->param;
+ output->compositor = compositor;
+ output->index      = index;
+ output->odesc      = odescs[index];
+
+ compositor->screen.GetOutputConfiguration( index, &output->oconf );
+
+ output->encoder = -1;
+ output->mixer   = -1;
+
+ if (output->oconf.flags & DSOCONF_ENCODER) {
+ output->encoder    = output->oconf.encoder;
+ output->edesc      = edescs[output->encoder];
+
+ compositor->screen.GetEncoderConfiguration( output->encoder,
&output->econf );
+
+ if (output->econf.flags & DSECONF_MIXER) {
+ output->mixer      = output->econf.mixer;
+ output->mdesc      = mdescs[output->mixer];
+
+ compositor->screen.GetMixerConfiguration( output->mixer, &output->mconf );
+
+ for (i=0; i<32; i++) {
+ if (output->mconf.layers & (1 << i)) {
+ break;
+ }
+ }
+
+ if (i == 32)
+ i = 0;
+
+ output->mconf.layers = (1 << i);
+
+ compositor->screen.SetMixerConfiguration( output->mixer, output->mconf );
+ }
+ }
+
+ D_INFO( "Weston/DirectFB: Output %d, Encoder %d, Mixer %d (layers
0x%04x)\n", index, output->encoder, output->mixer, output->mconf.layers );
+
+
+ output->layer = dfb.GetDisplayLayer( i );
+
+ output->layer.GetConfiguration( &output->lconf );
+
+ if (output->param.headless) {
+ DFBSurfaceDescription desc;
+
+ desc.flags  = (DFBSurfaceDescriptionFlags)( DSDESC_WIDTH | DSDESC_HEIGHT
);
+ desc.width  = output->lconf.width;
+ desc.height = output->lconf.height;
+
+ output->surface = compositor->dfb.CreateSurface( desc );
+
+ D_INFO( "WestonDFB/Output: Headless surface ID %u\n",
output->surface.GetID() );
+ } else {
+ output->layer.SetCooperativeLevel( DLSCL_EXCLUSIVE );
+
+ output->layer.GetConfiguration( &output->lconf );
+
+ output->lconf.pixelformat = DSPF_RGB32;
+ output->lconf.buffermode  = DLBM_TRIPLE;
+
+ try {
+ output->layer.SetConfiguration( output->lconf );
+ } catch (DFBException *e) {
+ output->lconf.buffermode = DLBM_BACKVIDEO;
+
+ try {
+ output->layer.SetConfiguration( output->lconf );
+ } catch (DFBException *e) {
+ output->lconf.buffermode = DLBM_BACKSYSTEM;
+
+ try {
+ output->layer.SetConfiguration( output->lconf );
+ } catch (DFBException *e) {
+ }
+ }
+ }
+
+ output->surface = output->layer.GetSurface();
+ }
+
+
+ /* Store the pertinent data. */
+ output->surface.GetSize( &output->fb_info.x_resolution,
&output->fb_info.y_resolution );
+ output->fb_info.format = output->surface.GetPixelFormat();
+
+ output->fb_info.width_mm = output->fb_info.x_resolution;
+ output->fb_info.height_mm = output->fb_info.y_resolution;
+
+ output->fb_info.line_length   = DFB_BYTES_PER_LINE(
output->fb_info.format, output->fb_info.x_resolution );
+ output->fb_info.buffer_length = DFB_PLANE_MULTIPLY(
output->fb_info.format, output->fb_info.y_resolution )
+ * output->fb_info.line_length;
+
+ output->fb_info.pixel_format = calculate_pixman_format(
output->fb_info.format );
+ output->fb_info.refresh_rate = 60;
+
+
+ output->base.start_repaint_loop = directfb_output_start_repaint_loop;
+ if (!output->param.use_pixman)
+ output->base.repaint = directfb_output_repaint_gl;
+ else
+ output->base.repaint = directfb_output_repaint_pixman;
+ output->base.destroy = directfb_output_destroy;
+ output->base.set_backlight = NULL;
+ output->base.set_dpms = NULL;
+ output->base.switch_mode = directfb_output_switch_mode;
+
+ /* only one static mode in list */
+ output->mode.flags = WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
+ output->mode.width = output->fb_info.x_resolution;
+ output->mode.height = output->fb_info.y_resolution;
+ output->mode.refresh = output->fb_info.refresh_rate;
+ wl_list_init(&output->base.mode_list);
+ wl_list_insert(&output->base.mode_list, &output->mode.link);
+
+ directfb_output_add_mode( output, DSOR_1920_1080, 1920, 1080, 60 );
+ directfb_output_add_mode( output, DSOR_1280_1024, 1280, 1024, 60 );
+ directfb_output_add_mode( output, DSOR_1024_768, 1024, 768, 60 );
+ directfb_output_add_mode( output, DSOR_800_600, 800, 600, 60 );
+ directfb_output_add_mode( output, DSOR_640_480, 640, 480, 60 );
+
+ output->base.current_mode = &output->mode;
+ output->base.original_mode = &output->mode;
+ output->base.subpixel = WL_OUTPUT_SUBPIXEL_UNKNOWN;
+ output->base.make  = strdup( "unknown" );
+ output->base.model = strdup( output->odesc.name );
+
+ weston_output_init(&output->base, &compositor->base,
+   0, 0, output->fb_info.width_mm,
+   output->fb_info.height_mm,
+   WL_OUTPUT_TRANSFORM_NORMAL,
+   1);
+ output->base_init = true;
+
+
+ directfb_output_init_shadow( output );
+
+
+ loop = wl_display_get_event_loop(compositor->base.wl_display);
+
+ output->finish_frame_timer = wl_event_loop_add_timer(loop,
finish_frame_handler, output);
+
+ wl_list_insert( compositor->base.output_list.prev, &output->base.link );
+
+ weston_log( "directfb output %d×%d px\n", output->mode.width,
output->mode.height );
+ weston_log_continue( STAMP_SPACE "guessing %d Hz and 96 dpi\n",
output->mode.refresh / 1000 );
+ } catch (...) {
+ delete output;
+
+ throw;
+ }
+
+ return 0;
+}
+
+static void
+directfb_output_destroy(struct weston_output *base)
+{
+ struct directfb_output *output = to_directfb_output(base);
+
+ D_DEBUG_AT( WestonDFB_Compositor, "%s()\n", __FUNCTION__ );
+
+ weston_log("Destroying directfb output.\n");
+
+ weston_output_destroy(&output->base);
+
+ free(output);
+}
+
+/**********************************************************************************************************************/
+/**********************************************************************************************************************/
+
+directfb_output::directfb_output()
+{
+ D_DEBUG_AT( WestonDFB_Output, "directfb_output::%s( %p )\n",
__FUNCTION__, this );
+
+ memset( this, 0, sizeof(*this) );
+
+ dfb_updates_init( &flip_updates, flip_regions, D_ARRAY_SIZE(flip_regions)
);
+}
+
+directfb_output::~directfb_output()
+{
+ D_DEBUG_AT( WestonDFB_Output, "directfb_output::%s( %p )\n",
__FUNCTION__, this );
+
+ if (base.renderer_state != NULL) {
+ if (param.use_pixman)
+ pixman_renderer_output_destroy(&base);
+ else
+ gl_renderer->output_destroy(&base);
+ }
+
+ if (shadow_surface != NULL) {
+ pixman_image_unref(shadow_surface);
+ shadow_surface = NULL;
+ }
+
+ if (shadow_buf != NULL) {
+ free(shadow_buf);
+ shadow_buf = NULL;
+ }
+
+ dfb_updates_deinit( &flip_updates );
+
+ if (base_init) {
+ /* Remove the output. */
+ wl_list_remove(&base.link);
+
+ weston_output_destroy( &base );
+ }
+}
+
+/**********************************************************************************************************************/
+/**********************************************************************************************************************/
+
+static int
+directfb_create_surface( struct weston_surface *surface )
+{
+ int                  ret;
+ weston_compositor   *ec         = surface->compositor;
+ directfb_compositor *compositor = to_directfb_compositor( ec );
+
+ D_DEBUG_AT( WestonDFB_Compositor, "%s( compositor %p, surface %p )\n",
__FUNCTION__, compositor, surface );
+
+ ret = compositor->create_surface( surface );
+ if (ret)
+ return ret;
+
+ directfb_surface_state *state = new directfb_surface_state();
+
+ surface->compositor_state = state;
+
+ return 0;
+}
+
+static void
+directfb_destroy_surface( struct weston_surface *surface )
+{
+ weston_compositor      *ec         = surface->compositor;
+ directfb_compositor    *compositor = to_directfb_compositor( ec );
+ directfb_surface_state *state      = (directfb_surface_state*)
surface->compositor_state;
+
+ D_DEBUG_AT( WestonDFB_Compositor, "%s( surface %p )\n", __FUNCTION__,
surface );
+
+ delete state;
+ surface->compositor_state = NULL;
+
+ compositor->destroy_surface( surface );
+}
+
+/**********************************************************************************************************************/
+
+struct pixman_surface_state {
+ pixman_image_t *image;
+ struct weston_buffer_reference buffer_ref;
+};
+
+static void
+directfb_surface_attach( struct weston_surface *es, struct weston_buffer
*buffer )
+{
+ weston_compositor      *ec         = es->compositor;
+ directfb_compositor    *compositor = to_directfb_compositor( ec );
+ directfb_surface_state *state      = (directfb_surface_state*)
es->compositor_state;
+ struct wl_shm_buffer   *shm_buffer;
+
+ D_DEBUG_AT( WestonDFB_Compositor, "%s( surface %p, buffer %p )\n",
__FUNCTION__, es, buffer );
+
+ if (!buffer) {
+ compositor->attach( es, buffer );
+ return;
+ }
+
+ shm_buffer = wl_shm_buffer_get( buffer->resource );
+ if (shm_buffer) {
+ compositor->attach( es, buffer );
+
+ if (!state->window) {
+ DFBWindowDescription desc;
+
+ desc.flags       = (DFBWindowDescriptionFlags)( DWDESC_WIDTH |
DWDESC_HEIGHT | DWDESC_PIXELFORMAT | DWDESC_RESOURCE_ID );
+ desc.width       = buffer->width;
+ desc.height      = buffer->height;
+ desc.resource_id = wl_resource_get_id( buffer->resource );
+
+ switch (wl_shm_buffer_get_format(shm_buffer)) {
+ case WL_SHM_FORMAT_XRGB8888:
+ desc.pixelformat = DSPF_RGB32;
+ break;
+ case WL_SHM_FORMAT_ARGB8888:
+ desc.pixelformat = DSPF_ARGB;
+ break;
+ default:
+ weston_log("Unsupported SHM buffer format\n");
+ return;
+ }
+
+ state->window  = compositor->layer.CreateWindow( desc );
+ state->surface = state->window.GetSurface();
+
+ state->size.w = buffer->width;
+ state->size.h = buffer->height;
+ state->format = desc.pixelformat;
+ } else if (state->size.w != buffer->width || state->size.h !=
buffer->height)
+ state->window.Resize( buffer->width, buffer->height );
+
+ state->surface.Write( wl_shm_buffer_get_data(shm_buffer),
+      wl_shm_buffer_get_stride(shm_buffer) );
+
+ state->surface.Flip();
+ } else {
+ WL::Buffer *dfb_buffer = (WL::Buffer *) wl_resource_get_user_data(
buffer->resource );
+
+ state->unlock();
+
+ buffer->width  = dfb_buffer->size.w;
+ buffer->height = dfb_buffer->size.h;
+
+ state->surface = dfb_buffer->surface;
+
+ state->size    = dfb_buffer->size;
+ state->format  = dfb_buffer->format;
+
+ if (compositor->param.use_pixman) {
+ struct pixman_surface_state *ps = (struct pixman_surface_state *)
es->renderer_state;
+ pixman_format_code_t         pixman_format;
+
+ weston_buffer_reference(&ps->buffer_ref, buffer);
+
+ if (ps->image) {
+ pixman_image_unref(ps->image);
+ ps->image = NULL;
+ }
+
+ pixman_format = calculate_pixman_format( dfb_buffer->format );
+ if (!pixman_format) {
+ D_ERROR( "WestonDFB/Surface: Unsupported DirectFB pixel format 0x%08x
(%s)\n",
+ dfb_buffer->format, dfb_pixelformat_name(dfb_buffer->format) );
+ weston_buffer_reference( &ps->buffer_ref, NULL );
+ return;
+ }
+
+ state->lock();
+
+ ps->image = pixman_image_create_bits( pixman_format,
+      buffer->width, buffer->height,
+      (u32*) state->data, state->pitch );
+ } else
+ compositor->attach( es, buffer );
+ }
+
+ D_DEBUG_AT( WestonDFB_Compositor, "  -> size %dx%d\n", buffer->width,
buffer->height );
+ D_DEBUG_AT( WestonDFB_Compositor, "  -> busy count %u\n",
buffer->busy_count );
+}
+
+/**********************************************************************************************************************/
+/**********************************************************************************************************************/
+
+directfb_compositor::directfb_compositor( struct wl_display *display, int
*argc, char *argv[],
+  struct weston_config *config,
+  const directfb_parameters &param )
+ :
+ param( param ),
+ input_manager( *this )
+{
+ D_DEBUG_AT( WestonDFB_Compositor, "directfb_compositor::%s( %p )\n",
__FUNCTION__, this );
+
+ if (weston_compositor_init(&this->base, display, argc, argv, config) < 0)
+ throw std::runtime_error( "weston_compositor_init failed" );
+
+ DFBScreenDescription        sdesc;
+ int                         i;
+
+ IDirectFB dfb;
+
+ DirectFB::Init( argc, &argv );
+
+ dfb = DirectFB::Create();
+
+
+ this->dfb     = dfb;
+
+
+ this->events   = dfb.CreateInputEventBuffer( DICAPS_ALL, DFB_TRUE );
+
+ this->event_fd = this->events.CreateFileDescriptor();
+
+
+ this->screen = dfb.GetScreen( DSCID_PRIMARY );
+ this->layer  = dfb.GetDisplayLayer( DLID_PRIMARY );
+
+ sdesc = this->screen.GetDescription();
+
+ D_INFO( "Weston/DirectFB: %d mixers, %d encoders, %d outputs\n",
sdesc.mixers, sdesc.encoders, sdesc.outputs );
+
+ DFBScreenMixerDescription   mdescs[sdesc.mixers];
+ DFBScreenEncoderDescription edescs[sdesc.encoders];
+ DFBScreenOutputDescription  odescs[sdesc.outputs];
+
+ if (sdesc.mixers)
+ this->screen.GetMixerDescriptions( mdescs );
+
+ if (sdesc.encoders)
+ this->screen.GetEncoderDescriptions( edescs );
+
+ if (sdesc.outputs)
+ this->screen.GetOutputDescriptions( odescs );
+
+
+ if (!param.use_pixman) {
+ if (gl_renderer->create(&this->base, (EGLNativeDisplayType)0,
gl_renderer->opaque_attribs, NULL) < 0)
+ throw std::runtime_error( "gl_renderer_create failed" );
+ } else {
+ if (pixman_renderer_init(&this->base) < 0)
+ throw std::runtime_error( "pixman_renderer_init failed" );
+ }
+
+
+ for (i=0; i<sdesc.outputs && (param.outputs == 0 || param.outputs > i);
i++) {
+ if (directfb_output_create( this, i, &sdesc, mdescs, edescs, odescs ) < 0)
+ throw std::runtime_error( "directfb_output_create failed" );
+ }
+
+
+ this->create_surface  = this->base.renderer->create_surface;
+ this->destroy_surface = this->base.renderer->destroy_surface;
+ this->attach          = this->base.renderer->attach;
+
+ this->base.renderer->create_surface  = directfb_create_surface;
+ this->base.renderer->destroy_surface = directfb_destroy_surface;
+ this->base.renderer->attach          = directfb_surface_attach;
+ this->base.renderer->create_view     = NULL;
+ this->base.renderer->destroy_view    = NULL;
+
+
+ this->base.destroy = directfb_compositor::destroy;
+
+ this->wldfb = WL::wayland_dfb_init( display, dfb.iface, client_callback,
this, events.iface );
+
+ this->event_source = wl_event_loop_add_fd( this->base.input_loop,
+   this->event_fd,
+   WL_EVENT_READABLE,
+   directfb_compositor::handle_event, this );
+
+ wl_event_loop_add_idle( this->base.input_loop,
directfb_compositor::idle_init, this );
+}
+
+directfb_compositor::~directfb_compositor()
+{
+ D_DEBUG_AT( WestonDFB_Compositor, "directfb_compositor::%s( %p )\n",
__FUNCTION__, this );
+
+ WL::wayland_dfb_uninit( this->wldfb );
+
+ shutdown();
+
+ /* Destroy the output. */
+ weston_compositor_shutdown( &base );
+
+ /* Chain up. */
+ base.renderer->destroy( &base );
+}
+
+void
+directfb_compositor::HandleInputEvent( const DFBInputEvent *event )
+{
+ D_DEBUG_AT( WestonDFB_Compositor, "directfb_compositor::%s( %p, event %p
) <- type 0x%04x\n", __FUNCTION__, this, event, event->type );
+
+ input_manager.HandleInputEvent( *event );
+}
+
+void
+directfb_compositor::HandleWindowEvent( const DFBWindowEvent *event )
+{
+ D_DEBUG_AT( WestonDFB_Compositor, "directfb_compositor::%s( %p, event %p
) <- type 0x%04x\n", __FUNCTION__, this, event, event->type );
+
+}
+
+void
+directfb_compositor::HandleSurfaceEvent( const DFBSurfaceEvent *event )
+{
+ D_DEBUG_AT( WestonDFB_Compositor, "directfb_compositor::%s( %p, event %p
) <- type 0x%04x\n", __FUNCTION__, this, event, event->type );
+
+ WL::wayland_dfb_handle_surface_event( wldfb, event );
+}
+
+int
+directfb_compositor::handle_event( int fd, uint32_t mask, void *data )
+{
+ struct directfb_compositor *compositor = (struct directfb_compositor *)
data;
+ DFBEvent                    events[200];
+ ssize_t                     ret;
+ int                         count = 0;
+
+ D_DEBUG_AT( WestonDFB_Compositor, "directfb_compositor::%s( %p, fd %d,
mask 0x%08x )\n", __FUNCTION__, compositor, fd, mask );
+
+ D_DEBUG_AT( WestonDFB_Compositor, "  -> reading...\n" );
+
+ if ((ret = read( fd, events, sizeof(events) )) >= sizeof(events[0])) {
+ size_t num = ret / sizeof(events[0]);
+
+ D_DEBUG_AT( WestonDFB_Compositor, "  -> got %zd (%zu events)\n", ret, num
);
+
+ count += num;
+
+ for (size_t i=0; i<num; i++) {
+ switch (events[i].clazz) {
+ case DFEC_INPUT:
+ compositor->HandleInputEvent( &events[i].input );
+ break;
+
+ case DFEC_WINDOW:
+ compositor->HandleWindowEvent( &events[i].window );
+ break;
+
+ case DFEC_SURFACE:
+ compositor->HandleSurfaceEvent( &events[i].surface );
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ if (ret < 0)
+ D_PERROR( "WestonDFB/Compositor: Reading from event file descriptor
failed!\n" );
+ else if (count == 0)
+ D_DEBUG_AT( WestonDFB_Compositor, "  -> GOT NO EVENT!\n" );
+
+ return count;
+}
+
+void
+directfb_compositor::idle_init( void *data )
+{
+ struct directfb_compositor *compositor = (struct directfb_compositor *)
data;
+
+ D_DEBUG_AT( WestonDFB_Compositor, "directfb_compositor::%s( %p )\n",
__FUNCTION__, compositor );
+
+ compositor->init();
+}
+
+void
+directfb_compositor::client_callback( void             *context,
+      struct wl_client *client )
+{
+}
+
+void
+directfb_compositor::init()
+{
+ input_manager.init();
+
+}
+
+void
+directfb_compositor::shutdown()
+{
+ input_manager.shutdown();
+}
+
+void
+directfb_compositor::destroy(struct weston_compositor *base)
+{
+ struct directfb_compositor *compositor = to_directfb_compositor(base);
+
+ compositor->shutdown();
+
+ delete compositor;
+}
+
+/**********************************************************************************************************************/
+/**********************************************************************************************************************/
+
+directfb_surface_state::directfb_surface_state()
+ :
+ data( NULL ),
+ pitch( 0 )
+{
+ D_DEBUG_AT( WestonDFB_Compositor, "%s()\n", __FUNCTION__ );
+}
+
+directfb_surface_state::~directfb_surface_state()
+{
+ D_DEBUG_AT( WestonDFB_Compositor, "%s()\n", __FUNCTION__ );
+
+ if (data)
+ surface.Unlock();
+}
+
+void
+directfb_surface_state::lock()
+{
+ D_DEBUG_AT( WestonDFB_Compositor, "%s()\n", __FUNCTION__ );
+
+ if (!data)
+ surface.Lock( DSLF_READ, &data, &pitch );
+}
+
+void
+directfb_surface_state::unlock()
+{
+ D_DEBUG_AT( WestonDFB_Compositor, "%s()\n", __FUNCTION__ );
+
+ if (data) {
+ data = NULL;
+ surface.Unlock();
+ }
+}
+
+/**********************************************************************************************************************/
+/**********************************************************************************************************************/
+
+struct weston_compositor *
+directfb_compositor::create( struct wl_display *display, int *argc, char
*argv[],
+     struct weston_config *config,
+     struct directfb_parameters *param )
+{
+ struct directfb_compositor *compositor;
+
+ D_DEBUG_AT( WestonDFB_Compositor, "%s()\n", __FUNCTION__ );
+
+ D_INFO( "WestonDFB/Compositor: Initialising...\n" );
+
+ gl_renderer = (struct gl_renderer_interface*)
weston_load_module("gl-renderer.so",
+ "gl_renderer_interface");
+ if (!gl_renderer)
+ return NULL;
+
+ compositor = new directfb_compositor( display, argc, argv, config, *param
);
+
+ return &compositor->base;
+}
+
+/**********************************************************************************************************************/
+
+WL_EXPORT struct weston_compositor *
+backend_init(struct wl_display *display, int *argc, char *argv[],
+     struct weston_config *config)
+{
+ D_DEBUG_AT( WestonDFB_Compositor, "%s()\n", __FUNCTION__ );
+
+ /* TODO: Ideally, available frame buffers should be enumerated using
+ * udev, rather than passing a device node in as a parameter. */
+ struct directfb_parameters param;
+
+ memset( &param, 0, sizeof(param) );
+
+ const struct weston_option directfb_options[] = {
+ { WESTON_OPTION_INTEGER, "width", 0, &param.width},
+ { WESTON_OPTION_INTEGER, "height", 0, &param.height},
+ { WESTON_OPTION_INTEGER, "outputs", 0, &param.outputs},
+ { WESTON_OPTION_BOOLEAN, "no-input", 0, &param.no_input},
+ { WESTON_OPTION_BOOLEAN, "use-2d", 0, &param.use_2d},
+ { WESTON_OPTION_BOOLEAN, "use-pixman", 0, &param.use_pixman},
+ { WESTON_OPTION_BOOLEAN, "headless", 0, &param.headless},
+ };
+
+ parse_options(directfb_options, ARRAY_LENGTH(directfb_options), argc,
argv);
+
+ return directfb_compositor::create(display, argc, argv, config, &param);
+}
+
diff --git a/src/compositor-directfb.h b/src/compositor-directfb.h
new file mode 100644
index 0000000..fb53d48
--- /dev/null
+++ b/src/compositor-directfb.h
@@ -0,0 +1,225 @@
+/*
+ * Copyright © 2008-2011 Kristian Høgsberg
+ * Copyright © 2011 Intel Corporation
+ * Copyright © 2012 Raspberry Pi Foundation
+ * Copyright © 2013 Philip Withnall
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee,
provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission.  The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __COMPOSITOR_DIRECTFB_H__
+#define __COMPOSITOR_DIRECTFB_H__
+
+#include <++dfb.h>
+
+#include <++dfb_mangle.h>
+#include <wayland-dfb.h>
+#include <++dfb_unmangle.h>
+
+#include <stdexcept>
+
+extern "C" {
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <linux/fb.h>
+#include <linux/input.h>
+
+#include "compositor.h"
+#include "launcher-util.h"
+#include "gl-renderer.h"
+#include "pixman-renderer.h"
+}
+
+#include "compositor-directfb-input.h"
+//#include "compositor-directfb-windows.h"
+
+
+struct directfb_parameters {
+ int width;
+ int height;
+ int fullscreen;
+ int outputs;
+ int no_input;
+ int use_2d;
+ int use_pixman;
+ int headless;
+};
+
+struct directfb_compositor {
+//     friend class WindowAdapter;
+
+public:
+ static struct weston_compositor *create( struct wl_display *display, int
*argc, char *argv[],
+ struct weston_config *config,
+ struct directfb_parameters *param );
+
+
+ directfb_compositor( struct wl_display *display, int *argc, char *argv[],
+     struct weston_config *config,
+     const directfb_parameters &param );
+ ~directfb_compositor();
+
+ struct weston_compositor   base;
+
+ struct directfb_parameters param;
+
+ InputDeviceManager         input_manager;
+//     WindowAdapter              window_adapter;
+
+ IDirectFB                  dfb;
+ IDirectFBEventBuffer       events;
+ IDirectFBScreen            screen;
+ IDirectFBDisplayLayer      layer;
+
+ int                        event_fd;
+ struct wl_event_source    *event_source;
+
+ WL::wl_dfb                *wldfb;
+
+ /* Backup original function pointers */
+ int (*create_surface)(struct weston_surface *surface);
+ void (*destroy_surface)(struct weston_surface *surface);
+ void (*attach)(struct weston_surface *es, struct weston_buffer *buffer);
+
+public:
+ void HandleInputEvent  ( const DFBInputEvent   *event );
+ void HandleWindowEvent ( const DFBWindowEvent  *event );
+ void HandleSurfaceEvent( const DFBSurfaceEvent *event );
+
+private:
+ void init();
+ void shutdown();
+
+ static void destroy( struct weston_compositor *base );
+ static int handle_event( int fd, uint32_t mask, void *data );
+ static void idle_init( void *data );
+
+ static void client_callback( void             *context,
+     struct wl_client *client );
+};
+
+struct directfb_mode {
+ struct weston_mode            base;
+ DFBScreenOutputResolution     resolution;
+};
+
+struct directfb_screeninfo {
+ int x_resolution; /* pixels, visible area */
+ int y_resolution; /* pixels, visible area */
+ unsigned int width_mm; /* visible screen width in mm */
+ unsigned int height_mm; /* visible screen height in mm */
+ DFBSurfacePixelFormat format;
+
+ size_t buffer_length; /* length of frame buffer memory in bytes */
+ size_t line_length; /* length of a line in bytes */
+
+ pixman_format_code_t pixel_format; /* frame buffer pixel format */
+ unsigned int refresh_rate; /* Hertz */
+};
+
+#define BUFFER_DAMAGE_COUNT 3
+
+struct directfb_output {
+public:
+ directfb_output();
+ ~directfb_output();
+
+ struct directfb_compositor   *compositor;
+
+ struct weston_output          base;
+ bool                          base_init;
+
+ struct directfb_parameters    param;
+
+ int                           index;
+
+ IDirectFBSurface              surface;
+ IDirectFBDisplayLayer         layer;
+
+ DFBDisplayLayerConfig         lconf;
+
+ int                           mixer;
+ int                           encoder;
+
+ DFBScreenMixerDescription     mdesc;
+ DFBScreenEncoderDescription   edesc;
+ DFBScreenOutputDescription    odesc;
+
+ DFBScreenMixerConfig          mconf;
+ DFBScreenEncoderConfig        econf;
+ DFBScreenOutputConfig         oconf;
+
+ struct weston_mode            mode;
+ struct wl_event_source       *finish_frame_timer;
+
+ /* Frame buffer details. */
+ struct directfb_screeninfo fb_info;
+
+ /* pixman details. */
+ pixman_image_t *shadow_surface;
+ void *shadow_buf;
+ uint8_t depth;
+
+ pixman_region32_t buffer_damage[BUFFER_DAMAGE_COUNT];
+
+ DFBRegion                     flip_regions[8];
+ DFBUpdates                    flip_updates;
+
+ bool                          initial;
+};
+
+struct directfb_surface_state {
+ IDirectFBWindow   window;
+ IDirectFBSurface  surface;
+
+ DFBDimension             size;
+ DFBSurfacePixelFormat    format;
+
+ void             *data;
+ int               pitch;
+
+ directfb_surface_state();
+ ~directfb_surface_state();
+
+ void lock();
+ void unlock();
+};
+
+/**********************************************************************************************************************/
+
+static inline struct directfb_output *
+to_directfb_output(struct weston_output *base) {
+ return container_of(base, struct directfb_output, base);
+}
+
+static inline struct directfb_compositor *
+to_directfb_compositor(struct weston_compositor *base) {
+ return container_of(base, struct directfb_compositor, base);
+}
+
+
+#endif
+
diff --git a/src/compositor.c b/src/compositor.c
index 632bbe7..10a2ce0 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -3603,6 +3603,19 @@ usage(int error_code)
  "  --log==FILE\t\tLog to the given file\n"
  "  -h, --help\t\tThis help message\n\n");

+#if defined(BUILD_DIRECTFB_COMPOSITOR)
+ fprintf(stderr,
+ "Options for directfb-backend.so:\n\n"
+ "  --width=WIDTH\t\tWidth of output window/layer\n"
+ "  --height=HEIGHT\tHeight of output window/layer\n"
+ "  --fullscreen\t\tRun in fullscreen mode\n"
+ "  --outputs=COUNT\tCreate not more than COUNT outputs\n"
+ "  --no-input\t\tDont create input devices\n"
+ "  --use-2d\t\tUse the 2D (GPU) renderer (DirectFB API)\n"
+ "  --use-pixman\t\tUse the pixman (CPU) renderer\n\n"
+ "  --headless\t\tRun weston in the background (no compositing)\n\n");
+#endif
+
  fprintf(stderr,
  "Options for drm-backend.so:\n\n"
  "  --connector=ID\tBring up only this connector\n"
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/wayland-devel/attachments/20131025/2bb8888e/attachment-0001.html>


More information about the wayland-devel mailing list