swc

Unnamed repository; edit this file 'description' to name the repository.
git clone git://git.nihaljere.xyz/swc
Log | Files | Refs | README | LICENSE

commit 4b382ea2e0f88509a9b691cd6db956397e5ba8f6
parent 47694ff382121a862965177f6cdd6e03c106a4f3
Author: Michael Forney <mforney@mforney.org>
Date:   Wed, 11 Sep 2013 01:44:49 -0700

Introduce planes

Diffstat:
Mlibswc/Makefile.am | 1+
Mlibswc/drm.c | 11++++++++++-
Mlibswc/drm.h | 3+++
Alibswc/plane.c | 225+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alibswc/plane.h | 66++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mlibswc/util.h | 25+++++++++++++++++++++++++
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