swc

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

commit 255b466a9a4b46ec8a935159f4173b5c72315e20
parent 828f46972c67c25b6feab657b01e13927b12f59f
Author: Michael Forney <mforney@mforney.org>
Date:   Sat, 21 Dec 2013 00:22:15 -0800

Move rendering code to compositor.c

Diffstat:
Mlibswc/compositor.c | 244+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Mlibswc/compositor.h | 8+++++---
Mlibswc/compositor_surface.c | 6++----
Mlibswc/cursor_surface.c | 2++
Mlibswc/local.mk | 1-
Dlibswc/renderer.c | 242-------------------------------------------------------------------------------
Dlibswc/renderer.h | 34----------------------------------
Mlibswc/swc.c | 1+
Mlibswc/window.c | 1+
9 files changed, 251 insertions(+), 288 deletions(-)

diff --git a/libswc/compositor.c b/libswc/compositor.c @@ -4,6 +4,7 @@ #include "cursor_surface.h" #include "data_device_manager.h" #include "drm.h" +#include "drm_buffer.h" #include "internal.h" #include "output.h" #include "pointer.h" @@ -14,8 +15,235 @@ #include <stdlib.h> #include <stdio.h> +#include <assert.h> +#include <wld/wld.h> +#include <wld/drm.h> #include <xkbcommon/xkbcommon-keysyms.h> +/* Rendering {{{ */ + +struct buffer_state +{ + struct wld_drawable * drawable; + /* Only used for SHM buffers */ + pixman_image_t * dst, * src; + struct wl_listener destroy_listener; +}; + +struct render_target +{ + struct wld_drawable * drawable; + pixman_rectangle32_t geometry; +}; + +static inline uint32_t pixman_format(uint32_t format) +{ + switch (format) + { + case WL_SHM_FORMAT_XRGB8888: + return PIXMAN_x8r8g8b8; + case WL_SHM_FORMAT_ARGB8888: + return PIXMAN_a8r8g8b8; + } + + return 0; +} + +static inline uint32_t wld_format(uint32_t format) +{ + switch (format) + { + case WL_SHM_FORMAT_XRGB8888: + return WLD_FORMAT_XRGB8888; + case WL_SHM_FORMAT_ARGB8888: + return WLD_FORMAT_ARGB8888; + } + + return 0; +} + +static void handle_buffer_destroy(struct wl_listener * listener, void * data) +{ + struct buffer_state * state + = CONTAINER_OF(listener, typeof(*state), destroy_listener); + + if (state->dst) + pixman_image_unref(state->dst); + if (state->src) + pixman_image_unref(state->src); + wld_destroy_drawable(state->drawable); + free(state); +} + +static inline struct buffer_state * buffer_state(struct wl_resource * resource) +{ + struct wl_listener * listener + = wl_resource_get_destroy_listener(resource, &handle_buffer_destroy); + + return listener ? CONTAINER_OF(listener, struct buffer_state, + destroy_listener) + : NULL; +} + +static void repaint_surface(struct render_target * target, + struct swc_surface * surface, + pixman_region32_t * damage) +{ + pixman_region32_t surface_damage; + pixman_region32_t border_damage; + pixman_region32_t surface_region; + struct buffer_state * state; + struct swc_compositor_surface_state * surface_state = surface->view_state; + + if (!surface->state.buffer) + return; + + state = buffer_state(surface->state.buffer); + assert(state); + + pixman_region32_init_with_extents(&surface_damage, &surface_state->extents); + pixman_region32_init(&border_damage); + pixman_region32_init_rect + (&surface_region, surface->geometry.x, surface->geometry.y, + surface->geometry.width, surface->geometry.height); + + pixman_region32_intersect(&surface_damage, &surface_damage, damage); + pixman_region32_subtract(&surface_damage, &surface_damage, + &surface_state->clip); + pixman_region32_subtract(&border_damage, &surface_damage, &surface_region); + pixman_region32_intersect(&surface_damage, &surface_damage, + &surface_region); + + pixman_region32_fini(&surface_region); + + if (pixman_region32_not_empty(&surface_damage)) + { + DEBUG("\tDRM surface %u { x: %d, y: %d, w: %u, h: %u }\n", + wl_resource_get_id(surface->resource), + surface->geometry.x, surface->geometry.y, + surface->geometry.width, surface->geometry.height); + + pixman_region32_translate(&surface_damage, + -surface->geometry.x, -surface->geometry.y); + wld_copy_region(state->drawable, target->drawable, &surface_damage, + surface->geometry.x - target->geometry.x, + surface->geometry.y - target->geometry.y); + } + + pixman_region32_fini(&surface_damage); + + /* Draw border */ + if (pixman_region32_not_empty(&border_damage)) + { + DEBUG("\t\tRedrawing border\n"); + + pixman_region32_translate(&border_damage, + -target->geometry.x, -target->geometry.y); + wld_fill_region(target->drawable, surface_state->border.color, + &border_damage); + } + + pixman_region32_fini(&border_damage); +} + +static void renderer_repaint(struct render_target * target, + pixman_region32_t * damage, + pixman_region32_t * base_damage, + struct wl_list * surfaces) +{ + struct swc_surface * surface; + + DEBUG("Rendering to target { x: %d, y: %d, w: %u, h: %u }\n", + target->geometry.x, target->geometry.y, + target->geometry.width, target->geometry.height); + + /* Paint base damage black. */ + if (pixman_region32_not_empty(base_damage)) + { + pixman_region32_translate(base_damage, + -target->geometry.x, -target->geometry.y); + wld_fill_region(target->drawable, 0xff000000, base_damage); + } + + wl_list_for_each_reverse(surface, surfaces, link) + { + if (swc_rectangle_overlap(&target->geometry, &surface->geometry)) + repaint_surface(target, surface, damage); + } + + wld_flush(target->drawable); +} + +void swc_compositor_attach(struct swc_surface * surface, + struct wl_resource * resource) +{ + struct buffer_state * state; + struct wl_shm_buffer * shm_buffer; + struct swc_drm_buffer * drm_buffer; + + if (!resource) + return; + + /* Check if we have already seen this buffer. */ + if ((state = buffer_state(resource))) + return; + + if (!(state = malloc(sizeof *state))) + return; + + if ((shm_buffer = wl_shm_buffer_get(resource))) + { + uint32_t width = wl_shm_buffer_get_width(shm_buffer), + height = wl_shm_buffer_get_height(shm_buffer), + format = wl_shm_buffer_get_format(shm_buffer), + pitch = wl_shm_buffer_get_stride(shm_buffer); + void * data = wl_shm_buffer_get_data(shm_buffer); + + state->drawable = wld_drm_create_drawable(swc.drm->context, + width, height, + wld_format(format)); + state->src = pixman_image_create_bits_no_clear(pixman_format(format), + width, height, + data, pitch); + state->dst = wld_map(state->drawable); + } + else if ((drm_buffer = swc_drm_buffer_get(resource))) + { + if (!(state = malloc(sizeof *state))) + return; + + state->drawable = drm_buffer->drawable; + state->src = NULL; + state->dst = NULL; + } + else + { + ERROR("Unsupported buffer type\n"); + return; + } + + state->destroy_listener.notify = &handle_buffer_destroy; + wl_resource_add_destroy_listener(resource, &state->destroy_listener); +} + +static void renderer_flush_surface(struct swc_surface * surface) +{ + struct buffer_state * state; + + state = buffer_state(surface->state.buffer); + assert(state); + + if (!state->src || !state->dst) + return; + + pixman_image_set_clip_region32(state->src, &surface->state.damage); + pixman_image_composite32(PIXMAN_OP_SRC, state->src, NULL, state->dst, + 0, 0, 0, 0, 0, 0, + state->drawable->width, state->drawable->height); +} + +/* }}} */ + static void calculate_damage(struct swc_compositor * compositor) { struct swc_surface * surface; @@ -45,7 +273,7 @@ static void calculate_damage(struct swc_compositor * compositor) if (pixman_region32_not_empty(&surface->state.damage)) { - swc_renderer_flush(&compositor->renderer, surface); + renderer_flush_surface(surface); /* Translate surface damage to global coordinates. */ pixman_region32_translate(&surface->state.damage, @@ -88,13 +316,21 @@ static void repaint_output(struct swc_compositor * compositor, pixman_region32_t * damage) { pixman_region32_t base_damage; + struct render_target target; pixman_region32_init(&base_damage); pixman_region32_subtract(&base_damage, damage, &compositor->opaque); - swc_renderer_set_target(&compositor->renderer, &output->framebuffer_plane); - swc_renderer_repaint(&compositor->renderer, damage, &base_damage, - &compositor->surfaces); + target.drawable = swc_plane_get_buffer(&output->framebuffer_plane); + target.geometry.x = output->framebuffer_plane.output->geometry.x + + output->framebuffer_plane.x; + target.geometry.y = output->framebuffer_plane.output->geometry.y + + output->framebuffer_plane.y; + target.geometry.width = target.drawable->width; + target.geometry.height = target.drawable->height; + + renderer_repaint(&target, damage, &base_damage, + &compositor->surfaces); pixman_region32_fini(&base_damage); diff --git a/libswc/compositor.h b/libswc/compositor.h @@ -2,17 +2,16 @@ #define SWC_COMPOSITOR_H #include "pointer.h" -#include "renderer.h" #include "view.h" #include <wayland-server.h> +struct swc_output; + struct swc_compositor { struct wl_display * display; - struct swc_renderer renderer; - struct wl_list outputs; struct wl_list surfaces; @@ -52,5 +51,8 @@ void swc_compositor_add_globals(struct swc_compositor * compositor, void swc_compositor_schedule_update(struct swc_compositor * compositor, struct swc_output * output); +void swc_compositor_attach(struct swc_surface * surface, + struct wl_resource * resource); + #endif diff --git a/libswc/compositor_surface.c b/libswc/compositor_surface.c @@ -24,6 +24,7 @@ #include "compositor_surface.h" #include "compositor.h" #include "event.h" +#include "output.h" #include "util.h" #include <stdio.h> @@ -207,10 +208,7 @@ void remove_(struct swc_surface * surface) void attach(struct swc_surface * surface, struct wl_resource * resource) { - struct swc_compositor * compositor = CONTAINER_OF - (surface->view, typeof(*compositor), compositor_view); - - swc_renderer_attach(&compositor->renderer, surface, resource); + swc_compositor_attach(surface, resource); } void update(struct swc_surface * surface) diff --git a/libswc/cursor_surface.c b/libswc/cursor_surface.c @@ -23,6 +23,8 @@ #include "cursor_surface.h" #include "compositor.h" +#include "output.h" +#include "plane.h" #include <string.h> #include <wld/wld.h> diff --git a/libswc/local.mk b/libswc/local.mk @@ -37,7 +37,6 @@ SWC_SOURCES = \ libswc/compositor_surface.c \ libswc/cursor_surface.c \ libswc/region.c \ - libswc/renderer.c \ libswc/input_focus.c \ libswc/keyboard.c \ libswc/pointer.c \ diff --git a/libswc/renderer.c b/libswc/renderer.c @@ -1,242 +0,0 @@ -#include "renderer.h" -#include "compositor_surface.h" -#include "drm.h" -#include "drm_buffer.h" -#include "internal.h" - -#include <assert.h> -#include <stdio.h> -#include <stdlib.h> -#include <wld/wld.h> -#include <wld/drm.h> - -struct buffer_state -{ - struct wld_drawable * drawable; - /* Only used for SHM buffers */ - pixman_image_t * dst, * src; - struct wl_listener destroy_listener; -}; - -static inline uint32_t pixman_format(uint32_t format) -{ - switch (format) - { - case WL_SHM_FORMAT_XRGB8888: - return PIXMAN_x8r8g8b8; - case WL_SHM_FORMAT_ARGB8888: - return PIXMAN_a8r8g8b8; - } - - return 0; -} - -static inline uint32_t wld_format(uint32_t format) -{ - switch (format) - { - case WL_SHM_FORMAT_XRGB8888: - return WLD_FORMAT_XRGB8888; - case WL_SHM_FORMAT_ARGB8888: - return WLD_FORMAT_ARGB8888; - } - - return 0; -} - -static void handle_buffer_destroy(struct wl_listener * listener, void * data) -{ - struct buffer_state * state - = CONTAINER_OF(listener, typeof(*state), destroy_listener); - - if (state->dst) - pixman_image_unref(state->dst); - if (state->src) - pixman_image_unref(state->src); - wld_destroy_drawable(state->drawable); - free(state); -} - -static inline struct buffer_state * buffer_state(struct wl_resource * resource) -{ - struct wl_listener * listener - = wl_resource_get_destroy_listener(resource, &handle_buffer_destroy); - - return listener ? CONTAINER_OF(listener, struct buffer_state, - destroy_listener) - : NULL; -} - -static void repaint_surface(struct swc_renderer * renderer, - struct swc_surface * surface, - pixman_region32_t * damage) -{ - struct swc_render_target * target = &renderer->target; - pixman_region32_t surface_damage; - pixman_region32_t border_damage; - pixman_region32_t surface_region; - struct buffer_state * state; - struct swc_compositor_surface_state * surface_state = surface->view_state; - - if (!surface->state.buffer) - return; - - state = buffer_state(surface->state.buffer); - assert(state); - - pixman_region32_init_with_extents(&surface_damage, &surface_state->extents); - pixman_region32_init(&border_damage); - pixman_region32_init_rect - (&surface_region, surface->geometry.x, surface->geometry.y, - surface->geometry.width, surface->geometry.height); - - pixman_region32_intersect(&surface_damage, &surface_damage, damage); - pixman_region32_subtract(&surface_damage, &surface_damage, - &surface_state->clip); - pixman_region32_subtract(&border_damage, &surface_damage, &surface_region); - pixman_region32_intersect(&surface_damage, &surface_damage, - &surface_region); - - pixman_region32_fini(&surface_region); - - if (pixman_region32_not_empty(&surface_damage)) - { - DEBUG("\tDRM surface %u { x: %d, y: %d, w: %u, h: %u }\n", - wl_resource_get_id(surface->resource), - surface->geometry.x, surface->geometry.y, - surface->geometry.width, surface->geometry.height); - - pixman_region32_translate(&surface_damage, - -surface->geometry.x, -surface->geometry.y); - wld_copy_region(state->drawable, target->drawable, &surface_damage, - surface->geometry.x - target->geometry.x, - surface->geometry.y - target->geometry.y); - } - - pixman_region32_fini(&surface_damage); - - /* Draw border */ - if (pixman_region32_not_empty(&border_damage)) - { - DEBUG("\t\tRedrawing border\n"); - - pixman_region32_translate(&border_damage, - -target->geometry.x, -target->geometry.y); - wld_fill_region(target->drawable, surface_state->border.color, - &border_damage); - } - - pixman_region32_fini(&border_damage); -} - -void swc_renderer_set_target(struct swc_renderer * renderer, - struct swc_plane * plane) -{ - struct wld_drawable * drawable = swc_plane_get_buffer(plane); - - renderer->target.drawable = drawable; - renderer->target.geometry.x = plane->output->geometry.x + plane->x; - renderer->target.geometry.y = plane->output->geometry.y + plane->y; - renderer->target.geometry.width = drawable->width; - renderer->target.geometry.height = drawable->height; -} - -void swc_renderer_repaint(struct swc_renderer * renderer, - pixman_region32_t * damage, - pixman_region32_t * base_damage, - struct wl_list * surfaces) -{ - struct swc_render_target * target = &renderer->target; - struct swc_surface * surface; - - DEBUG("Rendering to target { x: %d, y: %d, w: %u, h: %u }\n", - target->geometry.x, target->geometry.y, - target->geometry.width, target->geometry.height); - - /* Paint base damage black. */ - if (pixman_region32_not_empty(base_damage)) - { - pixman_region32_translate(base_damage, - -target->geometry.x, -target->geometry.y); - wld_fill_region(target->drawable, 0xff000000, base_damage); - } - - wl_list_for_each_reverse(surface, surfaces, link) - { - if (swc_rectangle_overlap(&target->geometry, &surface->geometry)) - repaint_surface(renderer, surface, damage); - } - - wld_flush(target->drawable); -} - -void swc_renderer_attach(struct swc_renderer * renderer, - struct swc_surface * surface, - struct wl_resource * resource) -{ - struct buffer_state * state; - struct wl_shm_buffer * shm_buffer; - struct swc_drm_buffer * drm_buffer; - - if (!resource) - return; - - /* Check if we have already seen this buffer. */ - if ((state = buffer_state(resource))) - return; - - if (!(state = malloc(sizeof *state))) - return; - - if ((shm_buffer = wl_shm_buffer_get(resource))) - { - uint32_t width = wl_shm_buffer_get_width(shm_buffer), - height = wl_shm_buffer_get_height(shm_buffer), - format = wl_shm_buffer_get_format(shm_buffer), - pitch = wl_shm_buffer_get_stride(shm_buffer); - void * data = wl_shm_buffer_get_data(shm_buffer); - - state->drawable = wld_drm_create_drawable(swc.drm->context, - width, height, - wld_format(format)); - state->src = pixman_image_create_bits_no_clear(pixman_format(format), - width, height, - data, pitch); - state->dst = wld_map(state->drawable); - } - else if ((drm_buffer = swc_drm_buffer_get(resource))) - { - if (!(state = malloc(sizeof *state))) - return; - - state->drawable = drm_buffer->drawable; - state->src = NULL; - state->dst = NULL; - } - else - { - ERROR("Unsupported buffer type\n"); - return; - } - - state->destroy_listener.notify = &handle_buffer_destroy; - wl_resource_add_destroy_listener(resource, &state->destroy_listener); -} - -void swc_renderer_flush(struct swc_renderer * renderer, - struct swc_surface * surface) -{ - struct buffer_state * state; - - state = buffer_state(surface->state.buffer); - assert(state); - - if (!state->src || !state->dst) - return; - - pixman_image_set_clip_region32(state->src, &surface->state.damage); - pixman_image_composite32(PIXMAN_OP_SRC, state->src, NULL, state->dst, - 0, 0, 0, 0, 0, 0, - state->drawable->width, state->drawable->height); -} - diff --git a/libswc/renderer.h b/libswc/renderer.h @@ -1,34 +0,0 @@ -#ifndef SWC_RENDERER_H -#define SWC_RENDERER_H - -#include "output.h" -#include "surface.h" - -struct swc_render_target -{ - struct wld_drawable * drawable; - pixman_rectangle32_t geometry; -}; - -struct swc_renderer -{ - struct swc_render_target target; -}; - -void swc_renderer_set_target(struct swc_renderer * renderer, - struct swc_plane * plane); - -void swc_renderer_repaint(struct swc_renderer * renderer, - pixman_region32_t * damage, - pixman_region32_t * base_damage, - struct wl_list * surfaces); - -void swc_renderer_attach(struct swc_renderer * renderer, - struct swc_surface * surface, - struct wl_resource * resource); - -void swc_renderer_flush(struct swc_renderer * renderer, - struct swc_surface * surface); - -#endif - diff --git a/libswc/swc.c b/libswc/swc.c @@ -28,6 +28,7 @@ #include "drm.h" #include "internal.h" #include "keyboard.h" +#include "output.h" #include "pointer.h" #include "seat.h" #include "shell.h" diff --git a/libswc/window.c b/libswc/window.c @@ -29,6 +29,7 @@ #include "keyboard.h" #include "seat.h" #include "swc.h" +#include "util.h" #include <stdlib.h> #include <string.h>