+++ /dev/null
-#include <assert.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <time.h>
-
-#include <drm_fourcc.h>
-#include <pixman.h>
-#include <wayland-server.h>
-#include <libds/log.h>
-#include <libds/backend.h>
-#include <libds/output.h>
-#include <libds/compositor.h>
-#include <libds/xdg_shell.h>
-#include <libds-tizen/allocator/tbm.h>
-#include <libds-tizen/backend/tdm.h>
-#include <libds-tizen/tbm_server.h>
-#include <libds-tizen/backend/tdm_output_hwc.h>
-
-#define USE_TDM_BUFFER_QUEUE
-
-#ifdef USE_TDM_BUFFER_QUEUE
-#include "pixman-tbm-helper.h"
-#include "tinyds-tdm-renderer.h"
-#else
-#include <libds/swapchain.h>
-#endif
-
-#include "pixman-helper.h"
-
-#define TINYDS_UNUSED __attribute__((unused))
-
-struct tinyds_output
-{
- struct tinyds_server *server;
- struct ds_output *ds_output;
- struct ds_allocator *allocator;
-#ifdef USE_TDM_BUFFER_QUEUE
- struct tinyds_renderer renderer;
- struct ds_tdm_buffer_queue *buffer_queue;
- struct wl_listener buffer_queue_acquirable;
-#else
- struct ds_swapchain *swapchain;
-#endif
- struct ds_buffer *front_buffer;
-
- struct wl_listener output_destroy;
- struct wl_listener output_frame;
-
- int width, height;
-
- struct wl_event_source *idle_commit;
- bool commitable;
- bool damaged;
-
- struct ds_tdm_output_hwc *hwc;
-};
-
-struct tinyds_server
-{
- struct ds_tbm_server *tbm_server;
-
- struct wl_display *display;
-
- struct ds_backend *backend;
- struct ds_compositor *compositor;
- struct ds_xdg_shell *xdg_shell;
-
- struct tinyds_output *output;
- struct wl_event_source *stdin_source;
-
- struct wl_list views;
-
- struct wl_listener new_output;
- struct wl_listener new_xdg_surface;
-};
-
-struct tinyds_view
-{
- struct tinyds_server *server;
-
- struct tinyds_texture *texture;
- struct ds_xdg_surface *xdg_surface;
-
- struct wl_listener xdg_surface_map;
- struct wl_listener xdg_surface_unmap;
- struct wl_listener xdg_surface_destroy;
- struct wl_listener surface_commit;
- struct wl_list link; // tinyds_server::views
-
- struct ds_tdm_output_hwc_window *hwc_window;
-
- int x, y;
- bool mapped;
-};
-
-struct tinyds_server tinyds;
-
-static bool init_server(struct tinyds_server *server, struct wl_display *display);
-static int server_dispatch_stdin(int fd, uint32_t mask, void *data);
-static void output_handle_destroy(struct wl_listener *listener, void *data);
-static void output_handle_frame(struct wl_listener *listener, void *data);
-static void draw_server_with_damage(struct tinyds_server *server);
-static void draw_output(struct tinyds_output *output);
-static void output_swap_buffer(struct tinyds_output *output,
- struct ds_buffer *buffer);
-static void view_send_frame_done(struct tinyds_view *view);
-static void output_hwc_init(struct tinyds_output *output);
-static void output_schedule_commit(struct tinyds_output *output);
-static void output_commit(struct tinyds_output *output);
-#ifdef USE_TDM_BUFFER_QUEUE
-static void output_buffer_queue_init(struct tinyds_output *output);
-static void output_renderer_init(struct tinyds_output *output);
-static void output_draw_with_renderer(struct tinyds_output *output);
-#else
-static void output_swapchain_init(struct tinyds_output *output,
- int width, int height, uint32_t format);
-static void output_draw_with_swapchain(struct tinyds_output *output);
-static void draw_view(struct tinyds_view *view, pixman_image_t *dst_image);
-#endif
-
-int
-main(void)
-{
- struct tinyds_server *server = &tinyds;
- struct wl_display *display;
- struct wl_event_loop *loop;
- const char *socket;
- bool res;
-
- ds_log_init(DS_INF, NULL);
-
- display = wl_display_create();
- assert(display);
-
- res = init_server(server, display);
- assert(res);
-
- socket = wl_display_add_socket_auto(display);
- assert(socket);
-
- ds_backend_start(server->backend);
-
- setenv("WAYLAND_DISPLAY", socket, true);
-
- ds_inf("Running Wayland compositor on WAYLAND_DISPLAY=%s", socket);
-
- loop = wl_display_get_event_loop(display);
- server->stdin_source = wl_event_loop_add_fd(loop, STDIN_FILENO,
- WL_EVENT_READABLE, server_dispatch_stdin, server);
-
- wl_display_run(display);
-
- wl_display_destroy_clients(display);
- wl_display_destroy(display);
-
- return 0;
-}
-
-static void
-view_handle_xdg_surface_map(struct wl_listener *listener,
- void *data TINYDS_UNUSED)
-{
- struct tinyds_view *view;
-
- view = wl_container_of(listener, view, xdg_surface_map);
- view->mapped = true;
-}
-
-static void
-view_handle_xdg_surface_unmap(struct wl_listener *listener,
- void *data TINYDS_UNUSED)
-{
- struct tinyds_view *view;
-
- view = wl_container_of(listener, view, xdg_surface_unmap);
- view->mapped = false;
-}
-
-static void
-view_handle_xdg_surface_destroy(struct wl_listener *listener,
- void *data TINYDS_UNUSED)
-{
- struct tinyds_view *view;
-
- view = wl_container_of(listener, view, xdg_surface_destroy);
-
- draw_server_with_damage(view->server);
-
- ds_tdm_output_hwc_window_destroy(view->hwc_window);
-
- wl_list_remove(&view->xdg_surface_destroy.link);
- wl_list_remove(&view->xdg_surface_map.link);
- wl_list_remove(&view->xdg_surface_unmap.link);
- wl_list_remove(&view->surface_commit.link);
- wl_list_remove(&view->link);
- free(view);
-}
-
-static void
-view_handle_surface_commit(struct wl_listener *listener,
- void *data TINYDS_UNUSED)
-{
- struct tinyds_view *view;
-
- view = wl_container_of(listener, view, surface_commit);
-
- draw_server_with_damage(view->server);
-}
-
-static void
-server_new_xdg_surface(struct wl_listener *listener, void *data)
-{
- struct tinyds_server *server;
- struct tinyds_view *view;
- struct ds_xdg_surface *xdg_surface;
-
- server = wl_container_of(listener, server, new_xdg_surface);
- xdg_surface = data;
-
- ds_inf("New xdg_surface(%p)", (void *)xdg_surface);
-
- view = calloc(1, sizeof *view);
- assert(view);
-
- view->server = server;
- view->xdg_surface = xdg_surface;
-
- view->xdg_surface_map.notify = view_handle_xdg_surface_map;
- ds_xdg_surface_add_map_listener(xdg_surface,
- &view->xdg_surface_map);
-
- view->xdg_surface_unmap.notify = view_handle_xdg_surface_unmap;
- ds_xdg_surface_add_unmap_listener(xdg_surface,
- &view->xdg_surface_unmap);
-
- view->xdg_surface_destroy.notify = view_handle_xdg_surface_destroy;
- ds_xdg_surface_add_destroy_listener(xdg_surface,
- &view->xdg_surface_destroy);
-
- view->surface_commit.notify = view_handle_surface_commit;
- ds_surface_add_commit_listener(
- ds_xdg_surface_get_surface(xdg_surface),
- &view->surface_commit);
-
- view->hwc_window = ds_tdm_output_hwc_window_create(server->output->hwc);
-
- wl_list_insert(server->views.prev, &view->link);
-}
-
-static void
-backend_handle_new_output(struct wl_listener *listener, void *data)
-{
- struct tinyds_server *server;
- struct tinyds_output *output;
- struct ds_output *ds_output;
- const struct ds_output_mode *mode;
-
- server = wl_container_of(listener, server, new_output);
- ds_output = data;
-
- ds_inf("New output(%p)", ds_output);
-
- if (server->output)
- return;
-
- mode = ds_output_get_preferred_mode(ds_output);
- ds_output_set_mode(ds_output, mode);
-
- output = calloc(1, sizeof *output);
- if (!output)
- return;
-
- output->server = server;
- output->ds_output = ds_output;
- output->width = mode->width;
- output->height = mode->height;
- output->damaged = true;
- output->commitable = true;
-
-#ifdef USE_TDM_BUFFER_QUEUE
- output_buffer_queue_init(output);
- output_renderer_init(output);
-#else
- output_swapchain_init(output, mode->width, mode->height,
- DRM_FORMAT_XRGB8888);
-#endif
-
- output_hwc_init(output);
-
- output->output_destroy.notify = output_handle_destroy;
- ds_output_add_destroy_listener(ds_output, &output->output_destroy);
-
- output->output_frame.notify = output_handle_frame;
- ds_output_add_frame_listener(ds_output, &output->output_frame);
-
- server->output = output;
-
- output_schedule_commit(output);
-}
-
-static bool
-init_server(struct tinyds_server *server, struct wl_display *display)
-{
- server->display = display;
-
- wl_list_init(&server->views);
-
- if (wl_display_init_shm(display) != 0)
- return false;
-
- server->backend = ds_tdm_backend_create(display);
- if (!server->backend)
- return false;
-
- server->new_output.notify = backend_handle_new_output;
- ds_backend_add_new_output_listener(server->backend,
- &server->new_output);
-
- server->compositor = ds_compositor_create(display);
- if (!server->compositor) {
- ds_backend_destroy(server->backend);
- return false;
- }
-
- server->tbm_server = ds_tbm_server_create(display);
- if (!server->tbm_server) {
- ds_backend_destroy(server->backend);
- return false;
- }
-
- server->xdg_shell = ds_xdg_shell_create(display);
- if (!server->xdg_shell) {
- ds_backend_destroy(server->backend);
- return false;
- }
-
- server->new_xdg_surface.notify = server_new_xdg_surface;
- ds_xdg_shell_add_new_surface_listener(server->xdg_shell,
- &server->new_xdg_surface);
-
- return true;
-}
-
-static void
-output_handle_destroy(struct wl_listener *listener, void *data TINYDS_UNUSED)
-{
- struct tinyds_output *output =
- wl_container_of(listener, output, output_destroy);
-
- wl_list_remove(&output->output_destroy.link);
- wl_list_remove(&output->output_frame.link);
-
- if (output->front_buffer)
- ds_buffer_unlock(output->front_buffer);
-
-#ifdef USE_TDM_BUFFER_QUEUE
- fini_renderer(&output->renderer);
-#else
- if (output->swapchain)
- ds_swapchain_destroy(output->swapchain);
-
- if (output->allocator)
- ds_allocator_destroy(output->allocator);
-#endif
-
- wl_display_terminate(output->server->display);
-
- output->server->output = NULL;
-
- free(output);
-}
-static void
-output_commit(struct tinyds_output *output)
-{
- uint32_t num_changed = 0;
- uint32_t num_windows = 0, current_num_windows = 0;
- struct ds_tdm_output_hwc_window **composited_hwc_windows = NULL;
- struct ds_tdm_output_hwc_window **changed_hwc_windows = NULL;
- enum ds_tdm_output_hwc_window_composition composition;
- struct tinyds_view *view;
- int i;
- bool need_target = false;
-
- if (!output->commitable || !output->damaged)
- return;
-
- wl_list_for_each_reverse(view, &output->server->views, link) {
- if (!view->hwc_window)
- continue;
-
- if (view->mapped)
- num_windows++;
- }
-
- if (num_windows) {
- composited_hwc_windows = calloc(num_windows, sizeof *composited_hwc_windows);
- if (!composited_hwc_windows)
- return;
- }
-
- wl_list_for_each_reverse(view, &output->server->views, link) {
- struct ds_buffer *ds_buffer;
- struct ds_tdm_box src_box;
- int w = 0, h = 0;
-
- if (!view->hwc_window)
- continue;
-
- ds_buffer = ds_surface_get_buffer(
- ds_xdg_surface_get_surface(view->xdg_surface));
- if (!ds_buffer)
- continue;
-
- ds_tdm_output_hwc_window_set_buffer(view->hwc_window, ds_buffer);
-
- if (ds_buffer)
- ds_buffer_get_size(ds_buffer, &w, &h);
-
- src_box.x = 0;
- src_box.y = 0;
- src_box.width = w;
- src_box.height = h;
-
- ds_tdm_output_hwc_window_set_src_box(view->hwc_window, &src_box);
- ds_tdm_output_hwc_window_set_position(view->hwc_window, view->x, view->y);
- ds_tdm_output_hwc_window_set_dest_size(view->hwc_window, w, h);
- ds_tdm_output_hwc_window_set_transform(view->hwc_window, WL_OUTPUT_TRANSFORM_NORMAL);
-
- if (view->mapped) {
- ds_tdm_output_hwc_window_set_composition(view->hwc_window,
- DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_DEVICE);
-
- composited_hwc_windows[current_num_windows] = view->hwc_window;
- current_num_windows++;
- } else {
- ds_tdm_output_hwc_window_set_composition(view->hwc_window,
- DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_NONE);
- }
- }
-
- if (!ds_tdm_output_hwc_validate(output->hwc, composited_hwc_windows,
- num_windows, &num_changed)) {
- free(composited_hwc_windows);
- ds_err("Could not hwc validate");
- return;
- }
-
- if (composited_hwc_windows)
- free(composited_hwc_windows);
-
- if (num_changed > 0) {
- changed_hwc_windows = calloc(num_windows, sizeof *changed_hwc_windows);
- if (!changed_hwc_windows)
- return;
-
- if (!ds_tdm_output_hwc_get_changed_composition(output->hwc, &num_changed,
- changed_hwc_windows)) {
- ds_err("Could not get chaged composition");
- return;
- }
-
- for (i = 0; i < num_changed; i++) {
- composition = ds_tdm_output_hwc_window_get_composition(changed_hwc_windows[i]);
- if (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CLIENT) {
- need_target = true;
- break;
- }
- }
- }
-
- if (changed_hwc_windows)
- free(changed_hwc_windows);
-
- if (!ds_tdm_output_hwc_accept_validation(output->hwc)) {
- ds_err("Could not hwc accept validateion");
- return;
- }
-
- if (need_target)
- draw_output(output);
-
-#ifdef USE_TDM_BUFFER_QUEUE
- struct ds_buffer *buffer;
-
- buffer = ds_tdm_buffer_queue_acquire(output->buffer_queue);
- if (buffer)
- output_swap_buffer(output, buffer);
-#endif
-
- ds_output_commit(output->ds_output);
-
- output->commitable = false;
- output->damaged = false;
-
- wl_list_for_each(view, &output->server->views, link) {
- enum ds_tdm_output_hwc_window_composition composition;
-
- if (!view->mapped)
- continue;
-
- composition = ds_tdm_output_hwc_window_get_composition(view->hwc_window);
- if ((composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_DEVICE) ||
- (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_VIDEO) ||
- (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CURSOR))
- view_send_frame_done(view);
- }
-
- ds_inf("output:%p commit", output);
-}
-
-static void
-output_handle_frame(struct wl_listener *listener, void *data TINYDS_UNUSED)
-{
- struct tinyds_output *output =
- wl_container_of(listener, output, output_frame);
-
- ds_inf("output:%p handle frame", output);
-
- output->commitable = true;
-
- output_commit(output);
-}
-
-static void
-draw_server_with_damage(struct tinyds_server *server)
-{
- server->output->damaged = true;
- output_schedule_commit(server->output);
-}
-
-static void
-output_hwc_init(struct tinyds_output *output)
-{
- struct ds_tdm_output *tdm_output;
-
- tdm_output = ds_tdm_output_from_output(output->ds_output);
- assert(tdm_output);
-
- output->hwc = ds_tdm_output_get_hwc(tdm_output);
- assert(output->hwc);
-
- ds_tdm_output_hwc_set_enabled(output->hwc, true);
-}
-
-#ifdef USE_TDM_BUFFER_QUEUE
-static void
-output_handle_buffer_queue_acquirable(struct wl_listener *listener,
- void *data TINYDS_UNUSED)
-{
- struct tinyds_output *output;
-
- output = wl_container_of(listener, output, buffer_queue_acquirable);
-
- draw_server_with_damage(output->server);
-}
-
-static void
-output_buffer_queue_init(struct tinyds_output *output)
-{
- struct ds_tdm_output *tdm_output;
-
- tdm_output = ds_tdm_output_from_output(output->ds_output);
- assert(tdm_output);
-
- output->buffer_queue = ds_tdm_output_get_buffer_queue(tdm_output);
- assert(output->buffer_queue);
-
- output->buffer_queue_acquirable.notify =
- output_handle_buffer_queue_acquirable;
- ds_tdm_buffer_queue_add_acquirable_listener(output->buffer_queue,
- &output->buffer_queue_acquirable);
-}
-
-static void
-output_renderer_init(struct tinyds_output *output)
-{
- init_renderer(&output->renderer);
-
- renderer_set_surface_queue(&output->renderer,
- ds_tdm_buffer_queue_get_native_queue(output->buffer_queue));
-
- renderer_set_bg_color(&output->renderer, 0, 0, 0);
-}
-
-static void
-output_draw_with_renderer(struct tinyds_output *output)
-{
- struct tinyds_view *view;
-
- ds_dbg(">> BEGIN UPDATE TEXTURES");
-
- wl_list_for_each(view, &output->server->views, link) {
- struct ds_buffer *ds_buffer;
- struct ds_tbm_client_buffer *tbm_buffer;
- tbm_surface_h surface;
- enum ds_tdm_output_hwc_window_composition composition;
-
- if (!view->mapped)
- continue;
-
- composition = ds_tdm_output_hwc_window_get_composition(view->hwc_window);
- if ((composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_DEVICE) ||
- (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_VIDEO) ||
- (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CURSOR))
- continue;
-
- ds_buffer = ds_surface_get_buffer(
- ds_xdg_surface_get_surface(view->xdg_surface));
- assert(ds_buffer);
-
- tbm_buffer = ds_tbm_client_buffer_from_buffer(ds_buffer);
- assert(tbm_buffer);
-
- surface = ds_tbm_client_buffer_get_tbm_surface(tbm_buffer);
-
- renderer_add_texture(&output->renderer, surface, view->x, view->y);
-
- view_send_frame_done(view);
- }
-
- ds_dbg("<< END UPDATE TEXTURES");
-
- renderer_draw(&output->renderer);
-}
-
-#else
-static void
-output_swapchain_init(struct tinyds_output *output,
- int width, int height, uint32_t format)
-
-{
- output->allocator = ds_tbm_allocator_create();
- assert(output->allocator);
-
- output->swapchain = ds_swapchain_create(output->allocator,
- width, height, format);
- assert(output->swapchain);
-}
-
-static void
-output_draw_with_swapchain(struct tinyds_output *output)
-{
- struct tinyds_view *view;
- struct ds_buffer *output_buffer;
- pixman_image_t *output_image;
- enum ds_tdm_output_hwc_window_composition composition;
-
- output_buffer = ds_swapchain_acquire(output->swapchain, NULL);
- if (!output_buffer)
- return;
-
- output_image = pixman_image_from_buffer(output_buffer,
- DS_BUFFER_DATA_PTR_ACCESS_WRITE);
- if (!output_image) {
- ds_buffer_unlock(output_buffer);
- return;
- }
-
- pixman_image_fill_color(output_image, 0, 0, 0);
-
- wl_list_for_each(view, &output->server->views, link) {
- if (!view->mapped)
- continue;
-
- composition = ds_tdm_output_hwc_window_get_composition(view->hwc_window);
- if ((composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_DEVICE) ||
- (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_VIDEO) ||
- (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CURSOR))
- continue;
-
- draw_view(view, output_image);
- }
- pixman_image_unref(output_image);
-
- output_swap_buffer(output, output_buffer);
-}
-
-static void
-draw_view(struct tinyds_view *view, pixman_image_t *dst_image)
-{
- struct ds_buffer *buffer;
- pixman_image_t *src_image;
-
- buffer = ds_surface_get_buffer(
- ds_xdg_surface_get_surface(view->xdg_surface));
- if (!buffer)
- return;
-
- src_image = pixman_image_from_buffer(buffer,
- DS_BUFFER_DATA_PTR_ACCESS_READ);
- pixman_image_composite32(PIXMAN_OP_OVER,
- src_image,
- NULL,
- dst_image,
- 0, 0, 0, 0,
- view->x, view->y,
- pixman_image_get_width(src_image),
- pixman_image_get_height(src_image));
- pixman_image_unref(src_image);
-
- view_send_frame_done(view);
-}
-#endif
-
-static void
-draw_output(struct tinyds_output *output)
-{
-#ifdef USE_TDM_BUFFER_QUEUE
- output_draw_with_renderer(output);
-#else
- output_draw_with_swapchain(output);
-#endif
-
- ds_inf("output:%p draw", output);
-}
-
-static void
-output_swap_buffer(struct tinyds_output *output, struct ds_buffer *buffer)
-{
- ds_output_attach_buffer(output->ds_output, buffer);
-
- if (output->front_buffer)
- ds_buffer_unlock(output->front_buffer);
- output->front_buffer = buffer;
-}
-
-static void
-view_send_frame_done(struct tinyds_view *view)
-{
- struct timespec now;
- clock_gettime(CLOCK_MONOTONIC, &now);
- ds_surface_send_frame_done(ds_xdg_surface_get_surface(view->xdg_surface),
- &now);
-}
-
-static void
-output_schedule_commit_handle_idle_timer(void *data)
-{
- struct tinyds_output *output = data;
- output->idle_commit = NULL;
-
- output_commit(output);
-}
-
-static void
-output_schedule_commit(struct tinyds_output *output)
-{
- if (output->idle_commit)
- return;
-
- output->damaged = true;
-
- struct wl_event_loop *ev = wl_display_get_event_loop(output->server->display);
- output->idle_commit =
- wl_event_loop_add_idle(ev, output_schedule_commit_handle_idle_timer, output);
-}
-
-static int
-server_dispatch_stdin(int fd, uint32_t mask, void *data)
-{
- struct tinyds_server *server = data;
-
- wl_display_terminate(server->display);
-
- return 1;
-}
#include <xkbcommon/xkbcommon.h>
#include <libds/interfaces/keyboard.h>
#include <libds-tizen/launch.h>
+#include <libds-tizen/backend/tdm_output_hwc.h>
#define USE_TDM_BUFFER_QUEUE
int width, height;
- bool drawable;
+ struct wl_event_source *idle_commit;
+ bool committable;
bool damaged;
+ bool target_updated;
+
+ struct ds_tdm_output_hwc *hwc;
+ struct ds_tdm_output_hwc_window *bg_hwc_window;
};
struct tinyds_dpms
struct wl_listener surface_commit;
struct wl_list link; // tinyds_server::views
+ struct ds_tdm_output_hwc_window *hwc_window;
+
int x, y;
bool mapped;
static void output_swap_buffer(struct tinyds_output *output,
struct ds_buffer *buffer);
static void view_send_frame_done(struct tinyds_view *view);
+static void output_hwc_init(struct tinyds_output *output);
+static void output_schedule_commit(struct tinyds_output *output);
+static void output_commit(struct tinyds_output *output);
#ifdef USE_TDM_BUFFER_QUEUE
static void output_buffer_queue_init(struct tinyds_output *output);
static void output_renderer_init(struct tinyds_output *output);
void *data TINYDS_UNUSED)
{
struct tinyds_view *view;
- struct tinyds_server *server;
view = wl_container_of(listener, view, xdg_surface_destroy);
- server = view->server;
+
+ draw_server_with_damage(view->server);
+
+ ds_tdm_output_hwc_window_destroy(view->hwc_window);
wl_list_remove(&view->xdg_surface_destroy.link);
wl_list_remove(&view->xdg_surface_map.link);
wl_list_remove(&view->surface_commit.link);
wl_list_remove(&view->link);
free(view);
-
- draw_server_with_damage(server);
}
static void
ds_xdg_surface_get_surface(xdg_surface),
&view->surface_commit);
- wl_list_insert(server->views.prev, &view->link);
-
view->x = rand() % 1000;
view->y = rand() % 500;
+ view->hwc_window = ds_tdm_output_hwc_window_create(server->output->hwc);
+ assert(view->hwc_window);
+
+ wl_list_insert(server->views.prev, &view->link);
+
view->pid = 0;
view->effect_type = -1;
struct tinyds_output *output;
struct ds_output *ds_output;
const struct ds_output_mode *mode;
+ struct ds_tdm_box src_box;
server = wl_container_of(listener, server, new_output);
ds_output = data;
output->ds_output = ds_output;
output->width = mode->width;
output->height = mode->height;
- output->drawable = true;
output->damaged = true;
+ output->committable = true;
+
+ output_hwc_init(output);
#ifdef USE_TDM_BUFFER_QUEUE
output_buffer_queue_init(output);
DRM_FORMAT_XRGB8888);
#endif
+ output->bg_hwc_window = ds_tdm_output_hwc_window_create(output->hwc);
+ assert(output->bg_hwc_window);
+
+ src_box.x = 0;
+ src_box.y = 0;
+ src_box.width = output->width;
+ src_box.height = output->height;
+
+ ds_tdm_output_hwc_window_set_src_box(output->bg_hwc_window, &src_box);
+ ds_tdm_output_hwc_window_set_position(output->bg_hwc_window, 0, 0);
+ ds_tdm_output_hwc_window_set_dest_size(output->bg_hwc_window, output->width, output->height);
+ ds_tdm_output_hwc_window_set_transform(output->bg_hwc_window, WL_OUTPUT_TRANSFORM_NORMAL);
+
output->output_destroy.notify = output_handle_destroy;
ds_output_add_destroy_listener(ds_output, &output->output_destroy);
server->output = output;
- draw_output(output);
+ output_schedule_commit(output);
}
static bool
struct tinyds_output *output =
wl_container_of(listener, output, output_destroy);
+ if (output->bg_hwc_window)
+ ds_tdm_output_hwc_window_destroy(output->bg_hwc_window);
+
wl_list_remove(&output->output_destroy.link);
wl_list_remove(&output->output_frame.link);
}
static void
+output_commit(struct tinyds_output *output)
+{
+ uint32_t num_changed = 0;
+ uint32_t num_windows = 0, current_num_windows = 0;
+ struct ds_tdm_output_hwc_window **composited_hwc_windows = NULL;
+ struct ds_tdm_output_hwc_window **changed_hwc_windows = NULL;
+ enum ds_tdm_output_hwc_window_composition composition;
+ struct tinyds_view *view;
+ int i;
+ bool need_target = false;
+ bool fully_obscured = false;
+ struct ds_buffer *ds_buffer;
+ struct ds_tdm_box src_box;
+ int w = 0, h = 0;
+
+ if (!output->committable)
+ return;
+
+ if (!output->damaged && !output->target_updated)
+ return;
+
+ wl_list_for_each_reverse(view, &output->server->views, link) {
+ if (!view->hwc_window)
+ continue;
+
+ ds_buffer = ds_surface_get_buffer(
+ ds_xdg_surface_get_surface(view->xdg_surface));
+ if (!ds_buffer)
+ continue;
+
+ if (!view->mapped)
+ continue;
+
+ num_windows++;
+
+ ds_buffer_get_size(ds_buffer, &w, &h);
+
+ if ((output->width <= w) && (output->height <= h))
+ fully_obscured = true;
+ }
+
+ if (fully_obscured) {
+ ds_tdm_output_hwc_window_set_composition(output->bg_hwc_window,
+ DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_NONE);
+ } else {
+ ds_tdm_output_hwc_window_set_composition(output->bg_hwc_window,
+ DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CLIENT);
+ num_windows++;
+ need_target = true;
+ }
+
+ if (num_windows) {
+ composited_hwc_windows = calloc(num_windows, sizeof *composited_hwc_windows);
+ if (!composited_hwc_windows)
+ return;
+
+ wl_list_for_each_reverse(view, &output->server->views, link) {
+ if (!view->hwc_window)
+ continue;
+
+ ds_buffer = ds_surface_get_buffer(
+ ds_xdg_surface_get_surface(view->xdg_surface));
+ if (!ds_buffer)
+ continue;
+
+ ds_tdm_output_hwc_window_set_buffer(view->hwc_window, ds_buffer);
+
+ ds_buffer_get_size(ds_buffer, &w, &h);
+
+ src_box.x = 0;
+ src_box.y = 0;
+ src_box.width = w;
+ src_box.height = h;
+
+ ds_tdm_output_hwc_window_set_src_box(view->hwc_window, &src_box);
+ ds_tdm_output_hwc_window_set_position(view->hwc_window, view->x, view->y);
+ ds_tdm_output_hwc_window_set_dest_size(view->hwc_window, w, h);
+ ds_tdm_output_hwc_window_set_transform(view->hwc_window, WL_OUTPUT_TRANSFORM_NORMAL);
+
+ if (view->mapped) {
+ ds_tdm_output_hwc_window_set_composition(view->hwc_window,
+ DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_DEVICE);
+
+ composited_hwc_windows[current_num_windows] = view->hwc_window;
+ current_num_windows++;
+ } else {
+ ds_tdm_output_hwc_window_set_composition(view->hwc_window,
+ DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_NONE);
+ }
+ }
+
+ if (!fully_obscured) {
+ composited_hwc_windows[current_num_windows] = output->bg_hwc_window;
+ current_num_windows++;
+ }
+ }
+
+ if (!ds_tdm_output_hwc_validate(output->hwc, composited_hwc_windows,
+ num_windows, &num_changed)) {
+ free(composited_hwc_windows);
+ ds_err("Could not hwc validate");
+ return;
+ }
+
+ if (composited_hwc_windows)
+ free(composited_hwc_windows);
+
+ if (num_changed > 0) {
+ changed_hwc_windows = calloc(num_windows, sizeof *changed_hwc_windows);
+ if (!changed_hwc_windows)
+ return;
+
+ if (!ds_tdm_output_hwc_get_changed_composition(output->hwc, &num_changed,
+ changed_hwc_windows)) {
+ free(changed_hwc_windows);
+ ds_err("Could not get chaged composition");
+ return;
+ }
+
+ for (i = 0; i < num_changed; i++) {
+ composition = ds_tdm_output_hwc_window_get_composition(changed_hwc_windows[i]);
+ if (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CLIENT) {
+ need_target = true;
+ break;
+ }
+ }
+ }
+
+ if (changed_hwc_windows)
+ free(changed_hwc_windows);
+
+ if (need_target && output->damaged)
+ draw_output(output);
+
+#ifdef USE_TDM_BUFFER_QUEUE
+ struct ds_buffer *buffer;
+
+ buffer = ds_tdm_buffer_queue_acquire(output->buffer_queue);
+ if (buffer) {
+ if (!ds_tdm_output_hwc_set_client_target_buffer(output->hwc, buffer)) {
+ ds_err("Could not set hwc client target buffer");
+ return;
+ }
+
+ output_swap_buffer(output, buffer);
+ }
+#endif
+
+ if (!ds_tdm_output_hwc_accept_validation(output->hwc)) {
+ ds_err("Could not hwc accept validateion");
+ return;
+ }
+
+ ds_output_commit(output->ds_output);
+
+ output->committable = false;
+ output->damaged = false;
+ output->target_updated = false;
+
+ wl_list_for_each(view, &output->server->views, link) {
+ enum ds_tdm_output_hwc_window_composition composition;
+
+ if (!view->mapped)
+ continue;
+
+ composition = ds_tdm_output_hwc_window_get_composition(view->hwc_window);
+ if ((composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_DEVICE) ||
+ (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_VIDEO) ||
+ (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CURSOR))
+ view_send_frame_done(view);
+ }
+
+ ds_dbg("output:%p commit", output);
+}
+
+static void
output_handle_frame(struct wl_listener *listener, void *data TINYDS_UNUSED)
{
struct tinyds_output *output =
wl_container_of(listener, output, output_frame);
- output->drawable = true;
- draw_output(output);
+ ds_dbg("output:%p handle frame", output);
+
+ output->committable = true;
+
+ output_commit(output);
}
static void
draw_server_with_damage(struct tinyds_server *server)
{
server->output->damaged = true;
- draw_output(server->output);
+ output_schedule_commit(server->output);
+}
+
+static void
+output_hwc_init(struct tinyds_output *output)
+{
+ struct ds_tdm_output *tdm_output;
+
+ tdm_output = ds_tdm_output_from_output(output->ds_output);
+ assert(tdm_output);
+
+ output->hwc = ds_tdm_output_get_hwc(tdm_output);
+ assert(output->hwc);
+
+ ds_tdm_output_hwc_set_enabled(output->hwc, true);
}
#ifdef USE_TDM_BUFFER_QUEUE
void *data TINYDS_UNUSED)
{
struct tinyds_output *output;
- struct ds_buffer *buffer;
output = wl_container_of(listener, output, buffer_queue_acquirable);
- buffer = ds_tdm_buffer_queue_acquire(output->buffer_queue);
- assert(buffer);
-
- output_swap_buffer(output, buffer);
+ output->target_updated = true;
+ output_schedule_commit(output);
}
static void
struct ds_buffer *ds_buffer;
struct ds_tbm_client_buffer *tbm_buffer;
tbm_surface_h surface;
+ enum ds_tdm_output_hwc_window_composition composition;
if (!view->mapped)
continue;
+ composition = ds_tdm_output_hwc_window_get_composition(view->hwc_window);
+ if ((composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_DEVICE) ||
+ (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_VIDEO) ||
+ (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CURSOR))
+ continue;
+
ds_buffer = ds_surface_get_buffer(
ds_xdg_surface_get_surface(view->xdg_surface));
- assert(ds_buffer);
+ if (!ds_buffer)
+ continue;
tbm_buffer = ds_tbm_client_buffer_from_buffer(ds_buffer);
- assert(tbm_buffer);
+ if (!tbm_buffer)
+ continue;
surface = ds_tbm_client_buffer_get_tbm_surface(tbm_buffer);
+ if (!surface)
+ continue;
renderer_add_texture(&output->renderer, surface, view->x, view->y);
ds_dbg("<< END UPDATE TEXTURES");
renderer_draw(&output->renderer);
-
}
#else
static void
output_swapchain_init(struct tinyds_output *output,
- int width, int height, uint32_t format);
+ int width, int height, uint32_t format)
{
output->allocator = ds_tbm_allocator_create();
struct tinyds_view *view;
struct ds_buffer *output_buffer;
pixman_image_t *output_image;
+ enum ds_tdm_output_hwc_window_composition composition;
output_buffer = ds_swapchain_acquire(output->swapchain, NULL);
if (!output_buffer)
wl_list_for_each(view, &output->server->views, link) {
if (!view->mapped)
continue;
+
+ composition = ds_tdm_output_hwc_window_get_composition(view->hwc_window);
+ if ((composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_DEVICE) ||
+ (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_VIDEO) ||
+ (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CURSOR))
+ continue;
+
draw_view(view, output_image);
}
pixman_image_unref(output_image);
+ if (!ds_tdm_output_hwc_set_client_target_buffer(output->hwc, output_buffer)) {
+ ds_err("Could not set hwc client target buffer");
+ ds_buffer_unlock(output_buffer);
+ return;
+ }
+
output_swap_buffer(output, output_buffer);
}
static void
draw_output(struct tinyds_output *output)
{
-
- if (!output->drawable || !output->damaged)
- return;
-
#ifdef USE_TDM_BUFFER_QUEUE
output_draw_with_renderer(output);
#else
output_draw_with_swapchain(output);
#endif
- output->drawable = false;
- output->damaged = false;
+ ds_dbg("output:%p draw", output);
}
static void
output_swap_buffer(struct tinyds_output *output, struct ds_buffer *buffer)
{
ds_output_attach_buffer(output->ds_output, buffer);
- ds_output_commit(output->ds_output);
if (output->front_buffer)
ds_buffer_unlock(output->front_buffer);
ds_inf("Pointer(%p) added", pointer);
}
+
+
+static void
+output_schedule_commit_handle_idle_timer(void *data)
+{
+ struct tinyds_output *output = data;
+ output->idle_commit = NULL;
+
+ output_commit(output);
+}
+
+static void
+output_schedule_commit(struct tinyds_output *output)
+{
+ if (output->idle_commit)
+ return;
+
+ struct wl_event_loop *ev = wl_display_get_event_loop(output->server->display);
+ output->idle_commit =
+ wl_event_loop_add_idle(ev, output_schedule_commit_handle_idle_timer, output);
+}