commit 4b382ea2e0f88509a9b691cd6db956397e5ba8f6
parent 47694ff382121a862965177f6cdd6e03c106a4f3
Author: Michael Forney <mforney@mforney.org>
Date: Wed, 11 Sep 2013 01:44:49 -0700
Introduce planes
Diffstat:
6 files changed, 330 insertions(+), 1 deletion(-)
diff --git a/libswc/Makefile.am b/libswc/Makefile.am
@@ -10,6 +10,7 @@ libswc_la_SOURCES = \
util.c util.h \
output.c output.h \
buffer.c buffer.h \
+ plane.c plane.h \
surface.c surface.h \
compositor_surface.c compositor_surface.h \
region.c region.h \
diff --git a/libswc/drm.c b/libswc/drm.c
@@ -213,12 +213,18 @@ bool swc_drm_initialize(struct swc_drm * drm, struct udev * udev,
printf("has blt: %u\n", ret);
}
+ if (!(drm->context = wld_drm_create_context(drm->fd)))
+ {
+ fprintf(stderr, "Could not create WLD DRM context\n");
+ goto error_fd;
+ }
+
drm->bufmgr = drm_intel_bufmgr_gem_init(drm->fd, INTEL_MAX_COMMANDS << 2);
if (!drm->bufmgr)
{
printf("could not create bufmgr\n");
- goto error_fd;
+ goto error_wld;
}
//drm_intel_bufmgr_set_debug(drm->bufmgr, true);
@@ -228,6 +234,8 @@ bool swc_drm_initialize(struct swc_drm * drm, struct udev * udev,
return true;
+ error_wld:
+ wld_drm_destroy_context(drm->context);
error_fd:
close(drm->fd);
error_device:
@@ -238,6 +246,7 @@ bool swc_drm_initialize(struct swc_drm * drm, struct udev * udev,
void swc_drm_finish(struct swc_drm * drm)
{
+ wld_drm_destroy_context(drm->context);
drm_intel_bufmgr_destroy(drm->bufmgr);
close(drm->fd);
}
diff --git a/libswc/drm.h b/libswc/drm.h
@@ -8,6 +8,8 @@
#include <wayland-server.h>
#include <libdrm/intel_bufmgr.h>
+struct wld_drm_context * context;
+
enum swc_drm_event
{
SWC_DRM_PAGE_FLIP
@@ -19,6 +21,7 @@ struct swc_drm
uint32_t id;
drm_intel_bufmgr * bufmgr;
+ struct wld_drm_context * context;
uint32_t taken_output_ids;
diff --git a/libswc/plane.c b/libswc/plane.c
@@ -0,0 +1,225 @@
+/* swc: plane.c
+ *
+ * Copyright (c) 2013 Michael Forney
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "plane.h"
+#include "output.h"
+#include "mode.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <libdrm/drm.h>
+#include <wld/wld.h>
+#include <wld/drm.h>
+
+struct framebuffer
+{
+ struct wld_drawable * drawable;
+ uint32_t fb_id;
+};
+
+static bool framebuffer_initialize(struct swc_plane * plane)
+{
+ struct framebuffer * buffer
+ = swc_double_buffer_front(&plane->double_buffer);
+
+ return drmModeSetCrtc(plane->output->drm->fd, plane->output->crtc_id,
+ buffer->fb_id, 0, 0, &plane->output->connector_id, 1,
+ &plane->output->current_mode->info) == 0;
+}
+
+static void * framebuffer_create_buffer(struct swc_plane * plane)
+{
+ struct wld_drawable * drawable;
+ struct swc_output * output = plane->output;
+ struct framebuffer * buffer;
+ uint32_t handle;
+
+ if (!(buffer = malloc(sizeof *buffer)))
+ goto error0;
+
+ drawable = wld_drm_create_drawable(output->drm->context,
+ output->geometry.width,
+ output->geometry.height,
+ WLD_FORMAT_XRGB8888);
+
+ if (!drawable)
+ {
+ fprintf(stderr, "Could not create DRM drawable for framebuffer\n");
+ goto error1;
+ }
+
+ handle = wld_drm_drawable_get_handle(drawable);
+
+ if (drmModeAddFB(plane->output->drm->fd, drawable->width, drawable->height,
+ 24, 32, drawable->pitch, handle, &buffer->fb_id) != 0)
+ {
+ fprintf(stderr, "drmModeAddFB failed\n");
+ goto error2;
+ }
+
+ buffer->drawable = drawable;
+
+ return buffer;
+
+ error2:
+ wld_destroy_drawable(drawable);
+ error1:
+ free(buffer);
+ error0:
+ return NULL;
+}
+
+static void framebuffer_destroy_buffer(struct swc_plane * plane, void * data)
+{
+ struct framebuffer * buffer = data;
+
+ drmModeRmFB(plane->output->drm->fd, buffer->fb_id);
+ wld_destroy_drawable(buffer->drawable);
+}
+
+static struct wld_drawable * framebuffer_get_buffer(void * data)
+{
+ struct framebuffer * buffer = data;
+
+ return buffer->drawable;
+}
+
+static bool framebuffer_flip(struct swc_plane * plane)
+{
+ struct swc_output * output = plane->output;
+ struct framebuffer * buffer = swc_double_buffer_back(&plane->double_buffer);
+
+ return drmModePageFlip(output->drm->fd, output->crtc_id, buffer->fb_id,
+ DRM_MODE_PAGE_FLIP_EVENT, output) == 0;
+}
+
+const struct swc_plane_interface swc_framebuffer_plane = {
+ .initialize = &framebuffer_initialize,
+ .create_buffer = &framebuffer_create_buffer,
+ .destroy_buffer = &framebuffer_destroy_buffer,
+ .get_buffer = &framebuffer_get_buffer,
+ .flip = &framebuffer_flip
+};
+
+static bool cursor_initialize(struct swc_plane * plane)
+{
+ return true;
+}
+
+static void * cursor_create_buffer(struct swc_plane * plane)
+{
+ return wld_drm_create_drawable(plane->output->drm->context, 64, 64,
+ WLD_FORMAT_ARGB8888);
+}
+
+static void cursor_destroy_buffer(struct swc_plane * plane, void * data)
+{
+ struct wld_drawable * drawable = data;
+
+ wld_destroy_drawable(drawable);
+}
+
+static struct wld_drawable * cursor_get_buffer(void * data)
+{
+ return data;
+}
+
+static bool cursor_flip(struct swc_plane * plane)
+{
+ struct swc_output * output = plane->output;
+ struct wld_drawable * drawable
+ = swc_double_buffer_back(&plane->double_buffer);
+ int handle = wld_drm_drawable_get_handle(drawable);
+
+ return drmModeSetCursor(plane->output->drm->fd, plane->output->crtc_id,
+ handle, 64, 64) == 0;
+}
+
+static bool cursor_move(struct swc_plane * plane, int32_t x, int32_t y)
+{
+ return drmModeMoveCursor(plane->output->drm->fd, plane->output->crtc_id,
+ x, y) == 0;
+}
+
+const struct swc_plane_interface swc_cursor_plane = {
+ .initialize = &cursor_initialize,
+ .create_buffer = &cursor_create_buffer,
+ .destroy_buffer = &cursor_destroy_buffer,
+ .get_buffer = &cursor_get_buffer,
+ .flip = &cursor_flip,
+ .move = &cursor_move
+};
+
+bool swc_plane_initialize(struct swc_plane * plane,
+ const struct swc_plane_interface * interface,
+ struct swc_output * output)
+{
+ plane->interface = interface;
+ plane->output = output;
+ plane->double_buffer.buffers[0] = interface->create_buffer(plane);
+ plane->double_buffer.buffers[1] = interface->create_buffer(plane);
+ plane->double_buffer.front = 0;
+ plane->x = 0;
+ plane->y = 0;
+
+ return plane->interface->initialize(plane);
+}
+
+void swc_plane_finish(struct swc_plane * plane)
+{
+ plane->interface->destroy_buffer(plane, plane->double_buffer.buffers[0]);
+ plane->interface->destroy_buffer(plane, plane->double_buffer.buffers[1]);
+}
+
+bool swc_plane_flip(struct swc_plane * plane)
+{
+ if (plane->interface->flip(plane))
+ {
+ swc_double_buffer_swap(&plane->double_buffer);
+
+ return true;
+ }
+ else
+ return false;
+}
+
+bool swc_plane_move(struct swc_plane * plane, int32_t x, int32_t y)
+{
+ if (plane->interface->move(plane, x, y))
+ {
+ plane->x = x;
+ plane->y = y;
+
+ return true;
+ }
+ else
+ return false;
+}
+
+struct wld_drawable * swc_plane_get_buffer(struct swc_plane * plane)
+{
+ void * back = swc_double_buffer_back(&plane->double_buffer);
+
+ return plane->interface->get_buffer(back);
+}
+
diff --git a/libswc/plane.h b/libswc/plane.h
@@ -0,0 +1,66 @@
+/* swc: plane.h
+ *
+ * Copyright (c) 2013 Michael Forney
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef SWC_PLANE_H
+#define SWC_PLANE_H 1
+
+#include "util.h"
+
+struct swc_plane;
+
+struct swc_plane_interface
+{
+ bool (* initialize)(struct swc_plane * plane);
+ void * (* create_buffer)(struct swc_plane * plane);
+ void (* destroy_buffer)(struct swc_plane * plane, void * data);
+ struct wld_drawable * (* get_buffer)(void * data);
+ bool (* flip)(struct swc_plane * plane);
+ bool (* move)(struct swc_plane * plane, int32_t x, int32_t y);
+};
+
+struct swc_plane
+{
+ const struct swc_plane_interface * interface;
+ struct swc_output * output;
+
+ struct swc_double_buffer double_buffer;
+
+ /* Relative to the output's origin. */
+ int32_t x, y;
+};
+
+bool swc_plane_initialize(struct swc_plane * plane,
+ const struct swc_plane_interface * interface,
+ struct swc_output * output);
+
+bool swc_plane_flip(struct swc_plane * plane);
+
+bool swc_plane_move(struct swc_plane * plane, int32_t x, int32_t y);
+
+struct wld_drawable * swc_plane_get_buffer(struct swc_plane * plane);
+
+extern const struct swc_plane_interface swc_framebuffer_plane;
+extern const struct swc_plane_interface swc_cursor_plane;
+
+#endif
+
diff --git a/libswc/util.h b/libswc/util.h
@@ -29,5 +29,30 @@ static inline bool swc_rectangle_overlap
int swc_launch_open_input_device(int socket, const char * path, int flags);
bool swc_launch_drm_master(int socket, int fd, bool set);
+/* Double Buffers */
+struct swc_double_buffer
+{
+ void * buffers[2];
+ uint8_t front;
+};
+
+static inline void * swc_double_buffer_front
+ (struct swc_double_buffer * double_buffer)
+{
+ return double_buffer->buffers[double_buffer->front];
+}
+
+static inline void * swc_double_buffer_back
+ (struct swc_double_buffer * double_buffer)
+{
+ return double_buffer->buffers[double_buffer->front ^ 1];
+}
+
+static inline void swc_double_buffer_swap
+ (struct swc_double_buffer * double_buffer)
+{
+ double_buffer->front ^= 1;
+}
+
#endif