--- /dev/null
+#ifndef LIBDS_TIZEN_ALLOCATOR_TBM_H
+#define LIBDS_TIZEN_ALLOCATOR_TBM_H
+
+#include <libds/allocator.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct ds_allocator *
+ds_tbm_allocator_create(void);
+
+WL_EXPORT void *
+ds_tbm_buffer_get_surface(struct ds_buffer *ds_buffer);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+#ifndef LIBDS_TIZEN_BACKEND_TDM_H
+#define LIBDS_TIZEN_BACKEND_TDM_H
+
+#include <libds/backend.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct ds_backend *
+ds_tdm_backend_create(struct wl_display *display);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+++ /dev/null
-#ifndef LIBDS_ALLOCATOR_TBM_H
-#define LIBDS_ALLOCATOR_TBM_H
-
-#include <libds/allocator.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct ds_allocator *
-ds_tbm_allocator_create(void);
-
-WL_EXPORT void *
-ds_tbm_buffer_get_surface(struct ds_buffer *ds_buffer);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+++ /dev/null
-#ifndef LIBDS_BACKEND_TDM_H
-#define LIBDS_BACKEND_TDM_H
-
-#include <libds/backend.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct ds_backend *
-ds_tdm_backend_create(struct wl_display *display);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-exclude_files = []
-if not features.get('tdm-backend')
- exclude_files += 'backend/tdm.h'
-endif
-
-if not features.get('tbm-allocator')
- exclude_files += 'allocator/tbm.h'
-endif
-
install_subdir('libds',
install_dir: get_option('includedir'),
- exclude_files: exclude_files,
)
+
+if get_option('tizen')
+ install_subdir('libds-tizen',
+ install_dir: get_option('includedir'),
+ )
+endif
cdata.set('LIBDS_VERSION_MINOR', libds_version_minor)
cdata.set('LIBDS_VERSION_PATCH', libds_version_patch)
-features = {
- 'tdm-backend': false,
- 'tbm-allocator': false,
-}
-
subdir('src')
subdir('include')
configure_file(output: 'config.h', install: false, configuration: cdata)
-
-summary(features, bool_yn: true)
-option('backends', type: 'array', choices: ['auto', 'tdm'], value: ['auto'], description: 'Select built-in backends')
+option('tizen', type: 'boolean', value: false, description: 'Build Tizen features')
%description devel
Development package of Wayland Compositor Library
+%package tizen-devel
+Summary: Wayland Compositor development package on Tizen
+
+%description tizen-devel
+Wayland Compositor development library for Tizen platform
+
%prep
%setup -q
cp %{SOURCE1001} .
--prefix /usr \
--libdir %{_libdir} \
--bindir %{_bindir} \
- builddir
+ builddir \
+ -Dtizen=true
ninja -C builddir all
%install
%manifest %{name}.manifest
%defattr(-,root,root,-)
%license LICENSE
-%{_includedir}/*
+%{_includedir}/libds/*
%{_libdir}/pkgconfig/libds.pc
%{_libdir}/libds.so
-%{_bindir}/*
+%{_bindir}/wl-backend
+%{_bindir}/tinyds
+
+%files tizen-devel
+%manifest %{name}.manifest
+%defattr(-,root,root,-)
+%license LICENSE
+%{_includedir}/libds-tizen/*
+%{_libdir}/pkgconfig/libds-tizen.pc
+%{_libdir}/libds-tizen.so
+%{_bindir}/tdm-backend
+%{_bindir}/tinyds-tdm
+%{_bindir}/ds-simple-tbm
install : true
)
-if features.get('tdm-backend')
+if get_option('tizen')
+ common_deps += dep_libds_tizen
+
executable('tdm-backend',
'tdm-backend.c',
dependencies: common_deps,
#include <libds/log.h>
#include <libds/backend.h>
#include <libds/output.h>
-#include <libds/allocator/tbm.h>
-#include <libds/backend/tdm.h>
#include <libds/swapchain.h>
#include <libds/compositor.h>
+#include <libds-tizen/allocator/tbm.h>
+#include <libds-tizen/backend/tdm.h>
#define WIDTH 1280
#define HEIGHT 720
#include <libds/log.h>
#include <libds/backend.h>
#include <libds/output.h>
-#include <libds/allocator/tbm.h>
-#include <libds/backend/tdm.h>
#include <libds/swapchain.h>
#include <libds/compositor.h>
#include <libds/xdg_shell.h>
+#include <libds-tizen/allocator/tbm.h>
+#include <libds-tizen/backend/tdm.h>
#define TINYDS_UNUSED __attribute__((unused))
--- /dev/null
+libds_tizen_files += files('tbm.c')
+libds_tizen_deps += dependency('libtbm', required: true)
--- /dev/null
+#include <assert.h>
+#include <stdlib.h>
+
+#include <drm_fourcc.h>
+#include <wayland-server.h>
+#include <tbm_bufmgr.h>
+#include <tbm_surface.h>
+
+#include "libds/interfaces/allocator.h"
+#include "libds/interfaces/buffer.h"
+#include "libds/log.h"
+
+struct ds_tbm_allocator
+{
+ struct ds_allocator base;
+ tbm_bufmgr bufmgr;
+};
+
+struct ds_tbm_buffer
+{
+ struct ds_buffer base;
+ tbm_surface_h surface;
+};
+
+static const struct ds_allocator_interface tbm_allocator_iface;
+static struct ds_tbm_buffer *tbm_buffer_from_buffer(struct ds_buffer *buffer);
+
+WL_EXPORT struct ds_allocator *
+ds_tbm_allocator_create(void)
+{
+ struct ds_tbm_allocator *alloc;
+
+ alloc = calloc(1, sizeof *alloc);
+ if (!alloc)
+ return NULL;
+
+ alloc->bufmgr = tbm_bufmgr_init(-1);
+ if (!alloc->bufmgr) {
+ ds_err("Could not initialize tbm_bufmgr");
+ free(alloc);
+ return NULL;
+ }
+
+ ds_allocator_init(&alloc->base, &tbm_allocator_iface,
+ DS_BUFFER_CAP_DATA_PTR);
+
+ ds_inf("TBM allocator(%p) created", alloc);
+
+ return &alloc->base;
+}
+
+WL_EXPORT void *
+ds_tbm_buffer_get_surface(struct ds_buffer *ds_buffer)
+{
+ struct ds_tbm_buffer *buffer;
+
+ buffer = tbm_buffer_from_buffer(ds_buffer);
+ if (!buffer)
+ return NULL;
+
+ return buffer->surface;
+}
+
+static struct ds_tbm_allocator *
+tbm_allocator_from_allocator(struct ds_allocator *ds_allocator)
+{
+ assert(ds_allocator->iface == &tbm_allocator_iface);
+ return (struct ds_tbm_allocator *)ds_allocator;
+}
+
+static const struct ds_buffer_interface tbm_buffer_iface;
+
+static struct ds_tbm_buffer *
+tbm_buffer_from_buffer(struct ds_buffer *buffer)
+{
+ assert(buffer->iface == &tbm_buffer_iface);
+ return (struct ds_tbm_buffer *)buffer;
+}
+
+static void
+tbm_buffer_destroy(struct ds_buffer *ds_buffer)
+{
+ struct ds_tbm_buffer *buffer;
+
+ buffer = tbm_buffer_from_buffer(ds_buffer);
+
+ ds_dbg("Destroy tbm buffer(%p)", buffer);
+
+ tbm_surface_destroy(buffer->surface);
+ free(buffer);
+}
+
+static bool
+tbm_buffer_begin_data_ptr_access(struct ds_buffer *ds_buffer, uint32_t flags,
+ void **data, uint32_t *format, size_t *stride)
+{
+ struct ds_tbm_buffer *buffer;
+ tbm_surface_info_s info;
+ int tbm_access_flags = 0;
+ int ret;
+
+ buffer = tbm_buffer_from_buffer(ds_buffer);
+
+ if (flags & DS_BUFFER_DATA_PTR_ACCESS_READ)
+ tbm_access_flags |= TBM_OPTION_READ;
+ else if (flags & DS_BUFFER_DATA_PTR_ACCESS_WRITE)
+ tbm_access_flags |= TBM_OPTION_WRITE;
+
+ ret = tbm_surface_map(buffer->surface, tbm_access_flags, &info);
+ if (ret != TBM_SURFACE_ERROR_NONE) {
+ ds_err("Could not map tbm_surface of buffer(%p)", buffer);
+ return false;
+ }
+
+ *data = info.planes[0].ptr;
+ *format = info.format;
+ *stride = info.planes[0].stride;
+
+ return true;
+}
+
+static void
+tbm_buffer_end_data_ptr_access(struct ds_buffer *ds_buffer)
+{
+ struct ds_tbm_buffer *buffer;
+
+ buffer = tbm_buffer_from_buffer(ds_buffer);
+
+ tbm_surface_unmap(buffer->surface);
+}
+
+static const struct ds_buffer_interface tbm_buffer_iface =
+{
+ .destroy = tbm_buffer_destroy,
+ .begin_data_ptr_access = tbm_buffer_begin_data_ptr_access,
+ .end_data_ptr_access = tbm_buffer_end_data_ptr_access,
+};
+
+static void
+tbm_allocator_destroy(struct ds_allocator *ds_allocator)
+{
+ struct ds_tbm_allocator *alloc;
+
+ alloc = tbm_allocator_from_allocator(ds_allocator);
+
+ ds_inf("Destroy TBM allocator(%p)", alloc);
+
+ tbm_bufmgr_deinit(alloc->bufmgr);
+ free(alloc);
+}
+
+static struct ds_buffer *
+tbm_allocator_create_buffer(struct ds_allocator *ds_allocator,
+ int width, int height, uint32_t format)
+{
+ static int num_buffers = 0;
+ struct ds_tbm_buffer *buffer;
+
+ buffer = calloc(1, sizeof *buffer);
+ if (!buffer)
+ return NULL;
+
+ ds_buffer_init(&buffer->base, &tbm_buffer_iface, width, height);
+
+ buffer->surface = tbm_surface_create(width, height, TBM_FORMAT_XRGB8888);
+
+ ds_dbg("tbm buffer(%p) created: size(%dx%d) number of buffers: %d",
+ buffer, width, height, ++num_buffers);
+
+ return &buffer->base;
+}
+
+static const struct ds_allocator_interface tbm_allocator_iface =
+{
+ .destroy = tbm_allocator_destroy,
+ .create_buffer = tbm_allocator_create_buffer,
+};
--- /dev/null
+subdir('tdm')
--- /dev/null
+#include <assert.h>
+#include <stdlib.h>
+
+#include "libds/log.h"
+
+#include "tdm.h"
+
+static const struct ds_backend_interface tdm_backend_iface;
+
+static void tdm_backend_handle_display_destroy(struct wl_listener *listener,
+ void *data);
+static void tdm_backend_destroy(struct ds_tdm_backend *tdm);
+static int tdm_backend_handle_tdm_event(int fd, uint32_t mask, void *data);
+
+WL_EXPORT struct ds_backend *
+ds_tdm_backend_create(struct wl_display *display)
+{
+ struct ds_tdm_backend *tdm;
+ struct wl_event_loop *loop;
+ tdm_error err;
+
+ ds_inf("Initializing TDM backend");
+
+ tdm = calloc(1, sizeof *tdm);
+ if (!tdm)
+ return NULL;
+
+ ds_backend_init(&tdm->base, &tdm_backend_iface);
+
+ tdm->wl_display = display;
+ tdm->clock = CLOCK_MONOTONIC; // FIXME
+
+ wl_list_init(&tdm->outputs);
+ wl_list_init(&tdm->buffers);
+
+ tdm->tdm_display = tdm_display_init(&err);
+ if (err != TDM_ERROR_NONE) {
+ ds_err("Could not initialize tdm_display");
+ goto err_display;
+ }
+
+ err = tdm_display_get_fd(tdm->tdm_display, &tdm->fd);
+ if (err != TDM_ERROR_NONE || tdm->fd < 0) {
+ ds_err("Could not get fd from tdm_display: err(%d)", err);
+ goto err_fd;
+ }
+
+ loop = wl_display_get_event_loop(display);
+ tdm->tdm_event = wl_event_loop_add_fd(loop, tdm->fd, WL_EVENT_READABLE,
+ tdm_backend_handle_tdm_event, tdm);
+ if (!tdm->tdm_event) {
+ ds_err("could not add fd event handler for tdm event");
+ goto err_event;
+ }
+
+ tdm->display_destroy.notify = tdm_backend_handle_display_destroy;
+ wl_display_add_destroy_listener(display, &tdm->display_destroy);
+
+ return &tdm->base;
+
+err_event:
+ close(tdm->fd);
+err_fd:
+ tdm_display_deinit(tdm->tdm_display);
+err_display:
+ free(tdm);
+
+ return NULL;
+}
+
+struct ds_tdm_backend *
+tdm_backend_from_backend(struct ds_backend *backend)
+{
+ assert(backend->iface == &tdm_backend_iface);
+ return (struct ds_tdm_backend *)backend;
+}
+
+static void
+tdm_backend_destroy(struct ds_tdm_backend *tdm)
+{
+ struct ds_tdm_output *output, *tmp_output;
+ struct ds_tdm_buffer *buffer, *tmp_buffer;
+
+ wl_list_for_each_safe(output, tmp_output, &tdm->outputs, link)
+ ds_output_destroy(&output->base);
+
+ wl_list_for_each_safe(buffer, tmp_buffer, &tdm->buffers, link)
+ destroy_tdm_buffer(buffer);
+
+ wl_list_remove(&tdm->display_destroy.link);
+ wl_event_source_remove(tdm->tdm_event);
+ close(tdm->fd);
+ tdm_display_deinit(tdm->tdm_display);
+ ds_backend_finish(&tdm->base);
+ free(tdm);
+}
+
+static bool
+tdm_backend_scan_outputs(struct ds_tdm_backend *tdm)
+{
+ struct ds_tdm_output *output;
+ tdm_output *tdm_output;
+ tdm_error err;
+ int num_outputs, i;
+
+ err = tdm_display_get_output_count(tdm->tdm_display, &num_outputs);
+ if (err != TDM_ERROR_NONE) {
+ ds_err("Could not get number of outputs: err(%d)", err);
+ return false;
+ }
+
+ for (i = 0; i < num_outputs; i++) {
+ tdm_output = tdm_display_get_output(tdm->tdm_display, i, &err);
+ if (err != TDM_ERROR_NONE || !tdm_output) {
+ ds_err("Could not get output from tdm_display: index(%d) err(%d)",
+ i, err);
+ continue;
+ }
+
+ output = create_tdm_output(tdm, tdm_output);
+ if (!output) {
+ ds_err("Could not create output: index(%d)", i);
+ continue;
+ }
+
+ wl_list_insert(&tdm->outputs, &output->link);
+
+ wl_signal_emit(&tdm->base.events.new_output, &output->base);
+ }
+
+ return true;
+}
+
+static bool
+tdm_backend_iface_start(struct ds_backend *backend)
+{
+ struct ds_tdm_backend *tdm;
+
+ tdm = tdm_backend_from_backend(backend);
+ return tdm_backend_scan_outputs(tdm);
+}
+
+static void
+tdm_backend_iface_destroy(struct ds_backend *backend)
+{
+ struct ds_tdm_backend *tdm;
+
+ tdm = tdm_backend_from_backend(backend);
+ tdm_backend_destroy(tdm);
+}
+
+static const struct ds_backend_interface tdm_backend_iface =
+{
+ .start = tdm_backend_iface_start,
+ .destroy = tdm_backend_iface_destroy,
+ .get_drm_fd = NULL,
+};
+
+static void
+tdm_backend_handle_display_destroy(struct wl_listener *listener, void *data)
+{
+ struct ds_tdm_backend *tdm;
+
+ tdm = wl_container_of(listener, tdm, display_destroy);
+ tdm_backend_destroy(tdm);
+}
+
+static int
+tdm_backend_handle_tdm_event(int fd, uint32_t mask, void *data)
+{
+ struct ds_tdm_backend *tdm = data;
+
+ tdm_display_handle_events(tdm->tdm_display);
+
+ return 0;
+}
--- /dev/null
+libds_tizen_files += files(
+ 'backend.c',
+ 'output.c',
+)
+
+libtdm = dependency('libtdm', required: true)
+libtbm = dependency('libtbm', required: true)
+
+libds_tizen_deps += [
+ libtdm,
+ libtbm
+]
--- /dev/null
+#include <assert.h>
+#include <stdlib.h>
+
+#include <tbm_surface.h>
+
+#include "libds/log.h"
+#include "libds-tizen/allocator/tbm.h"
+
+#include "tdm.h"
+
+static const struct ds_output_interface tdm_output_iface;
+static bool output_init_modes(struct ds_tdm_output *output);
+static void output_destroy(struct ds_tdm_output *output);
+static void output_init_hwc(struct ds_tdm_output *output);
+static bool output_update_mode(struct ds_tdm_output *output);
+static bool output_set_pending_fb(struct ds_tdm_output *output,
+ struct ds_buffer *ds_buffer);
+static bool output_hwc_commit(struct ds_tdm_output *output);
+
+struct ds_tdm_output *
+create_tdm_output(struct ds_tdm_backend *tdm, tdm_output *tdm_output)
+{
+ struct ds_tdm_output *output;
+ tdm_output_conn_status conn;
+ tdm_error err;
+
+ output = calloc(1, sizeof *output);
+ if (!output)
+ return NULL;
+
+ ds_output_init(&output->base, &tdm->base, &tdm_output_iface,
+ tdm->wl_display);
+
+ output->backend = tdm;
+ output->tdm.output = tdm_output;
+
+ err = tdm_output_get_conn_status(tdm_output, &conn);
+ if (err != TDM_ERROR_NONE) {
+ ds_err("Could not get connection status of tdm output(%p): err(%d)",
+ tdm_output, err);
+ goto err_status;
+ }
+
+ if (conn == TDM_OUTPUT_CONN_STATUS_CONNECTED) {
+ output->status = DS_TDM_OUTPUT_CONNECTED;
+
+ if (!output_init_modes(output)) {
+ ds_err("Could not initialize modes of tdm output(%p)",
+ tdm_output);
+ goto err_status;
+ }
+ }
+ else if (conn == TDM_OUTPUT_CONN_STATUS_DISCONNECTED) {
+ output->status = DS_TDM_OUTPUT_DISCONNECTED;
+ }
+
+ if (tdm_output_get_hwc(output->tdm.output, NULL) != NULL)
+ output_init_hwc(output);
+
+ ds_inf("TDM output(%p) created: hwc(%p)", output, output->tdm.hwc);
+
+ return output;
+
+err_status:
+ free(output);
+
+ return NULL;
+}
+
+static struct ds_tdm_output *
+tdm_output_from_output(struct ds_output *ds_output)
+{
+ assert(ds_output->iface == &tdm_output_iface);
+ return (struct ds_tdm_output *)ds_output;
+}
+
+static void
+output_iface_destroy(struct ds_output *ds_output)
+{
+ struct ds_tdm_output *output;
+
+ output = tdm_output_from_output(ds_output);
+ output_destroy(output);
+}
+
+void
+destroy_tdm_buffer(struct ds_tdm_buffer *buffer)
+{
+ if (buffer == NULL)
+ return;
+
+ wl_list_remove(&buffer->buffer_destroy.link);
+ wl_list_remove(&buffer->link);
+ free(buffer);
+}
+
+static void
+buffer_handle_buffer_destroy(struct wl_listener *listener, void *data)
+{
+ struct ds_tdm_buffer *buffer;
+
+ buffer = wl_container_of(listener, buffer, buffer_destroy);
+ destroy_tdm_buffer(buffer);
+}
+
+static struct ds_tdm_buffer *
+create_tdm_buffer(struct ds_tdm_backend *backend, struct ds_buffer *ds_buffer)
+{
+ struct ds_tdm_buffer *buffer;
+ tbm_surface_h surface;
+
+ surface = ds_tbm_buffer_get_surface(ds_buffer);
+ if (!surface) {
+ ds_err("Could not get tbm_surface_h");
+ return NULL;
+ }
+
+ buffer = calloc(1, sizeof *buffer);
+ if (!buffer)
+ return NULL;
+
+ buffer->surface = surface;
+ buffer->buffer = ds_buffer_lock(ds_buffer);
+ wl_list_insert(&backend->buffers, &buffer->link);
+
+ buffer->buffer_destroy.notify = buffer_handle_buffer_destroy;
+ ds_buffer_add_destroy_listener(ds_buffer, &buffer->buffer_destroy);
+
+ return buffer;
+}
+
+static struct ds_tdm_buffer *
+get_or_create_tdm_buffer(struct ds_tdm_backend *backend,
+ struct ds_buffer *ds_buffer)
+{
+ struct ds_tdm_buffer *buffer;
+
+ wl_list_for_each(buffer, &backend->buffers, link) {
+ if (buffer->buffer == ds_buffer && buffer->released) {
+ buffer->released = false;
+ ds_buffer_lock(buffer->buffer);
+ return buffer;
+ }
+ }
+
+ return create_tdm_buffer(backend, ds_buffer);
+}
+
+static void
+tdm_buffer_release(struct ds_tdm_buffer *buffer)
+{
+ buffer->released = true;
+ ds_buffer_unlock(buffer->buffer);
+}
+
+static void
+output_update_front_buffer(struct ds_tdm_output *output)
+{
+ if (output->front_buffer)
+ tdm_buffer_release(output->front_buffer);
+ output->front_buffer = output->back_buffer;
+ output->back_buffer = NULL;
+}
+
+static void
+output_attach_back_buffer(struct ds_tdm_output *output,
+ struct ds_tdm_buffer *buffer)
+{
+ if (output->back_buffer)
+ tdm_buffer_release(output->back_buffer);
+ output->back_buffer = buffer;
+}
+
+static bool
+output_iface_commit(struct ds_output *ds_output)
+{
+ struct ds_tdm_output *output;
+
+ output = tdm_output_from_output(ds_output);
+
+ if (ds_output->pending.committed & DS_OUTPUT_STATE_MODE) {
+ if (!output_update_mode(output)) {
+ ds_err("Could not update TDM mode");
+ return false;
+ }
+ }
+
+ if (ds_output->pending.committed & DS_OUTPUT_STATE_BUFFER) {
+ if (!output_set_pending_fb(output, ds_output->pending.buffer))
+ ds_err("Could not update buffer");
+ }
+
+ if (!output_hwc_commit(output)) {
+ ds_err("Could not commit tdm output");
+ if (output->back_buffer) {
+ tdm_buffer_release(output->back_buffer);
+ }
+ }
+
+ return true;
+}
+
+static const struct ds_output_interface tdm_output_iface =
+{
+ .destroy = output_iface_destroy,
+ .commit = output_iface_commit,
+};
+
+static void
+output_destroy(struct ds_tdm_output *output)
+{
+ struct ds_tdm_output_mode *mode, *mode_tmp;
+
+ wl_list_for_each_safe(mode, mode_tmp, &output->base.modes, base.link) {
+ wl_list_remove(&mode->base.link);
+ free(mode);
+ }
+
+ if (output->back_buffer)
+ ds_buffer_unlock(output->back_buffer->buffer);
+
+ if (output->front_buffer)
+ ds_buffer_unlock(output->front_buffer->buffer);
+
+ free(output);
+}
+
+static bool
+output_init_modes(struct ds_tdm_output *output)
+{
+ struct ds_tdm_output_mode *mode;
+ const tdm_output_mode *tdm_modes, *tdm_mode;
+ tdm_error err;
+ int num_modes, i;
+
+ err = tdm_output_get_available_modes(output->tdm.output, &tdm_modes,
+ &num_modes);
+ if (err != TDM_ERROR_NONE) {
+ ds_err("Could not get available modes: output(%p)", output);
+ return false;
+ }
+
+ ds_dbg("Detected modes:");
+
+ for (i = 0; i < num_modes; i++) {
+ tdm_mode = &tdm_modes[i];
+
+ mode = calloc(1, sizeof *mode);
+ if (!mode) {
+ ds_err("Could not allocate memory");
+ continue;
+ }
+
+ mode->tdm_mode = tdm_mode;
+ mode->base.width = tdm_mode->hdisplay;
+ mode->base.height = tdm_mode->vdisplay;
+ mode->base.refresh = (int32_t)tdm_mode->vrefresh; // FIXME
+
+ if (tdm_mode->type & TDM_OUTPUT_MODE_TYPE_PREFERRED)
+ mode->base.preferred = true;
+
+ ds_dbg(" %dx%d@%d %s", mode->base.width, mode->base.height,
+ mode->base.refresh,
+ mode->base.preferred ? "(preferred)" : "");
+
+ if (tdm_mode->type & TDM_OUTPUT_MODE_TYPE_DEFAULT)
+ wl_list_insert(&output->base.modes, &mode->base.link);
+ else
+ wl_list_insert(output->base.modes.prev, &mode->base.link);
+ }
+
+ return true;
+}
+
+static void
+output_init_hwc(struct ds_tdm_output *output)
+{
+ tdm_error err;
+
+ output->tdm.hwc = tdm_output_get_hwc(output->tdm.output, &err);
+ if (err != TDM_ERROR_NONE || !output->tdm.hwc) {
+ ds_err("Could not get tdm_hwc: output(%p)", output);
+ return;
+ }
+}
+
+static bool
+output_update_mode(struct ds_tdm_output *output)
+{
+ const struct ds_tdm_output_mode *mode;
+ tdm_error err;
+
+ mode = (struct ds_tdm_output_mode *)output->base.pending.mode;
+
+ ds_inf("TDM output(%p) set mode %dx%d %d mHz", output,
+ mode->base.width, mode->base.height, mode->base.refresh);
+
+ err = tdm_output_set_mode(output->tdm.output, mode->tdm_mode);
+ if (err != TDM_ERROR_NONE)
+ return false;
+
+ return true;
+}
+
+static bool
+output_set_pending_fb(struct ds_tdm_output *output,
+ struct ds_buffer *ds_buffer)
+{
+ struct ds_tdm_buffer *buffer;
+ tdm_region fb_damage;
+ tdm_error err;
+
+ buffer = get_or_create_tdm_buffer(output->backend, ds_buffer);
+ if (!buffer)
+ return false;
+
+ memset(&fb_damage, 0, sizeof(fb_damage));
+ err = tdm_hwc_set_client_target_buffer(output->tdm.hwc,
+ buffer->surface, fb_damage);
+ if (err != TDM_ERROR_NONE) {
+ ds_err("Could not set hwc client target buffer");
+ ds_buffer_unlock(buffer->buffer);
+ return false;
+ }
+
+ output_attach_back_buffer(output, buffer);
+
+ return true;
+}
+
+static void
+output_hwc_commit_handler(tdm_hwc *hwc, unsigned int sequence,
+ unsigned int tv_sec, unsigned int tv_usec, void *user_data)
+{
+ struct ds_tdm_output *output = user_data;
+
+ output_update_front_buffer(output);
+
+ wl_signal_emit(&output->base.events.frame, &output->base);
+}
+
+static bool
+output_hwc_commit(struct ds_tdm_output *output)
+{
+ tdm_error err;
+ uint32_t num_changes;
+
+ err = tdm_hwc_validate(output->tdm.hwc, NULL, 0, &num_changes);
+ if (err != TDM_ERROR_NONE) {
+ ds_err("Could not hwc validate");
+ return false;
+ }
+
+ err = tdm_hwc_accept_validation(output->tdm.hwc);
+ if (err != TDM_ERROR_NONE) {
+ ds_err("Could not hwc accept validation");
+ return false;
+ }
+
+ err = tdm_hwc_commit(output->tdm.hwc, 0, output_hwc_commit_handler,
+ output);
+ if (err != TDM_ERROR_NONE) {
+ ds_err("Could not hwc commit");
+ return false;
+ }
+
+ return true;
+}
--- /dev/null
+#ifndef DS_TIZEN_BACKEND_TDM_H
+#define DS_TIZEN_BACKEND_TDM_H
+
+#include <time.h>
+
+#include <tdm.h>
+
+#include "libds/interfaces/backend.h"
+#include "libds/interfaces/output.h"
+
+enum ds_tdm_output_status {
+ DS_TDM_OUTPUT_DISCONNECTED,
+ DS_TDM_OUTPUT_CONNECTED,
+};
+
+struct ds_tdm_output_mode {
+ struct ds_output_mode base;
+ const tdm_output_mode *tdm_mode;
+};
+
+struct ds_tdm_backend
+{
+ struct ds_backend base;
+
+ tdm_display *tdm_display;
+ struct wl_display *wl_display;
+ struct wl_event_source *tdm_event;
+
+ struct wl_list outputs; // ds_tdm_output.link
+ struct wl_list buffers; // ds_tdm_buffer.link
+
+ struct wl_listener display_destroy;
+
+ clockid_t clock;
+ int fd;
+};
+
+struct ds_tdm_output
+{
+ struct ds_output base;
+
+ struct ds_tdm_backend *backend;
+ struct ds_tdm_buffer *front_buffer, *back_buffer;
+
+ struct {
+ tdm_output *output;
+ tdm_hwc *hwc;
+ } tdm;
+
+ struct wl_list link;
+
+ enum ds_tdm_output_status status;
+};
+
+struct ds_tdm_buffer
+{
+ struct ds_buffer *buffer;
+ tbm_surface_h surface;
+ struct wl_list link; // ds_wl_backend.buffers
+ struct wl_listener buffer_destroy;
+
+ bool released;
+};
+
+struct ds_tdm_backend *tdm_backend_from_backend(struct ds_backend *backend);
+
+struct ds_tdm_output *create_tdm_output(struct ds_tdm_backend *tdm,
+ tdm_output *tdm_output);
+
+void destroy_tdm_buffer(struct ds_tdm_buffer *buffer);
+
+
+#endif
--- /dev/null
+libds_tizen_files = []
+
+libds_tizen_deps = [
+ dep_libds,
+]
+
+subdir('allocator')
+subdir('backend')
+
+lib_libds_tizen = shared_library('ds-tizen', libds_tizen_files,
+ dependencies: libds_tizen_deps,
+ include_directories: [ common_inc, include_directories('.') ],
+ version: meson.project_version(),
+ install: true
+)
+
+dep_libds_tizen = declare_dependency(
+ link_with: lib_libds_tizen,
+ dependencies: libds_tizen_deps,
+ include_directories: [ common_inc, include_directories('.') ],
+)
+
+pkgconfig = import('pkgconfig')
+pkgconfig.generate(lib_libds_tizen,
+ version: meson.project_version(),
+ filebase: 'libds-tizen',
+ name: 'libds-tizen',
+ description: 'extension of libds for tizen platform',
+)
libds_files += files('shm.c')
-
-libtbm = dependency(
- 'libtbm',
- required: false,
- not_found_message: 'Required for TBM allocator support.'
-)
-if libtbm.found()
- libds_files += files('tbm.c')
- libds_deps += libtbm
- features += { 'tbm-allocator': true }
-endif
+++ /dev/null
-#include <assert.h>
-#include <stdlib.h>
-
-#include <drm_fourcc.h>
-#include <wayland-server.h>
-#include <tbm_bufmgr.h>
-#include <tbm_surface.h>
-
-#include "libds/interfaces/allocator.h"
-#include "libds/interfaces/buffer.h"
-#include "libds/log.h"
-
-struct ds_tbm_allocator
-{
- struct ds_allocator base;
- tbm_bufmgr bufmgr;
-};
-
-struct ds_tbm_buffer
-{
- struct ds_buffer base;
- tbm_surface_h surface;
-};
-
-static const struct ds_allocator_interface tbm_allocator_iface;
-static struct ds_tbm_buffer *tbm_buffer_from_buffer(struct ds_buffer *buffer);
-
-WL_EXPORT struct ds_allocator *
-ds_tbm_allocator_create(void)
-{
- struct ds_tbm_allocator *alloc;
-
- alloc = calloc(1, sizeof *alloc);
- if (!alloc)
- return NULL;
-
- alloc->bufmgr = tbm_bufmgr_init(-1);
- if (!alloc->bufmgr) {
- ds_err("Could not initialize tbm_bufmgr");
- free(alloc);
- return NULL;
- }
-
- ds_allocator_init(&alloc->base, &tbm_allocator_iface,
- DS_BUFFER_CAP_DATA_PTR);
-
- ds_inf("TBM allocator(%p) created", alloc);
-
- return &alloc->base;
-}
-
-WL_EXPORT void *
-ds_tbm_buffer_get_surface(struct ds_buffer *ds_buffer)
-{
- struct ds_tbm_buffer *buffer;
-
- buffer = tbm_buffer_from_buffer(ds_buffer);
- if (!buffer)
- return NULL;
-
- return buffer->surface;
-}
-
-static struct ds_tbm_allocator *
-tbm_allocator_from_allocator(struct ds_allocator *ds_allocator)
-{
- assert(ds_allocator->iface == &tbm_allocator_iface);
- return (struct ds_tbm_allocator *)ds_allocator;
-}
-
-static const struct ds_buffer_interface tbm_buffer_iface;
-
-static struct ds_tbm_buffer *
-tbm_buffer_from_buffer(struct ds_buffer *buffer)
-{
- assert(buffer->iface == &tbm_buffer_iface);
- return (struct ds_tbm_buffer *)buffer;
-}
-
-static void
-tbm_buffer_destroy(struct ds_buffer *ds_buffer)
-{
- struct ds_tbm_buffer *buffer;
-
- buffer = tbm_buffer_from_buffer(ds_buffer);
-
- ds_dbg("Destroy tbm buffer(%p)", buffer);
-
- tbm_surface_destroy(buffer->surface);
- free(buffer);
-}
-
-static bool
-tbm_buffer_begin_data_ptr_access(struct ds_buffer *ds_buffer, uint32_t flags,
- void **data, uint32_t *format, size_t *stride)
-{
- struct ds_tbm_buffer *buffer;
- tbm_surface_info_s info;
- int tbm_access_flags = 0;
- int ret;
-
- buffer = tbm_buffer_from_buffer(ds_buffer);
-
- if (flags & DS_BUFFER_DATA_PTR_ACCESS_READ)
- tbm_access_flags |= TBM_OPTION_READ;
- else if (flags & DS_BUFFER_DATA_PTR_ACCESS_WRITE)
- tbm_access_flags |= TBM_OPTION_WRITE;
-
- ret = tbm_surface_map(buffer->surface, tbm_access_flags, &info);
- if (ret != TBM_SURFACE_ERROR_NONE) {
- ds_err("Could not map tbm_surface of buffer(%p)", buffer);
- return false;
- }
-
- *data = info.planes[0].ptr;
- *format = info.format;
- *stride = info.planes[0].stride;
-
- return true;
-}
-
-static void
-tbm_buffer_end_data_ptr_access(struct ds_buffer *ds_buffer)
-{
- struct ds_tbm_buffer *buffer;
-
- buffer = tbm_buffer_from_buffer(ds_buffer);
-
- tbm_surface_unmap(buffer->surface);
-}
-
-static const struct ds_buffer_interface tbm_buffer_iface =
-{
- .destroy = tbm_buffer_destroy,
- .begin_data_ptr_access = tbm_buffer_begin_data_ptr_access,
- .end_data_ptr_access = tbm_buffer_end_data_ptr_access,
-};
-
-static void
-tbm_allocator_destroy(struct ds_allocator *ds_allocator)
-{
- struct ds_tbm_allocator *alloc;
-
- alloc = tbm_allocator_from_allocator(ds_allocator);
-
- ds_inf("Destroy TBM allocator(%p)", alloc);
-
- tbm_bufmgr_deinit(alloc->bufmgr);
- free(alloc);
-}
-
-static struct ds_buffer *
-tbm_allocator_create_buffer(struct ds_allocator *ds_allocator,
- int width, int height, uint32_t format)
-{
- static int num_buffers = 0;
- struct ds_tbm_buffer *buffer;
-
- buffer = calloc(1, sizeof *buffer);
- if (!buffer)
- return NULL;
-
- ds_buffer_init(&buffer->base, &tbm_buffer_iface, width, height);
-
- buffer->surface = tbm_surface_create(width, height, TBM_FORMAT_XRGB8888);
-
- ds_dbg("tbm buffer(%p) created: size(%dx%d) number of buffers: %d",
- buffer, width, height, ++num_buffers);
-
- return &buffer->base;
-}
-
-static const struct ds_allocator_interface tbm_allocator_iface =
-{
- .destroy = tbm_allocator_destroy,
- .create_buffer = tbm_allocator_create_buffer,
-};
-all_backends = ['tdm']
-backends = get_option('backends')
-if 'auto' in backends and get_option('auto_features').enabled()
- backends = all_backends
-elif 'auto' in backends and get_option('auto_features').disabled()
- backends = []
-endif
-
-foreach backend : all_backends
- if backend in backends or 'auto' in backends
- subdir(backend)
- endif
-endforeach
-
subdir('wayland')
+++ /dev/null
-#include <assert.h>
-#include <stdlib.h>
-
-#include "libds/log.h"
-
-#include "tdm.h"
-
-static const struct ds_backend_interface tdm_backend_iface;
-
-static void tdm_backend_handle_display_destroy(struct wl_listener *listener,
- void *data);
-static void tdm_backend_destroy(struct ds_tdm_backend *tdm);
-static int tdm_backend_handle_tdm_event(int fd, uint32_t mask, void *data);
-
-WL_EXPORT struct ds_backend *
-ds_tdm_backend_create(struct wl_display *display)
-{
- struct ds_tdm_backend *tdm;
- struct wl_event_loop *loop;
- tdm_error err;
-
- ds_inf("Initializing TDM backend");
-
- tdm = calloc(1, sizeof *tdm);
- if (!tdm)
- return NULL;
-
- ds_backend_init(&tdm->base, &tdm_backend_iface);
-
- tdm->wl_display = display;
- tdm->clock = CLOCK_MONOTONIC; // FIXME
-
- wl_list_init(&tdm->outputs);
- wl_list_init(&tdm->buffers);
-
- tdm->tdm_display = tdm_display_init(&err);
- if (err != TDM_ERROR_NONE) {
- ds_err("Could not initialize tdm_display");
- goto err_display;
- }
-
- err = tdm_display_get_fd(tdm->tdm_display, &tdm->fd);
- if (err != TDM_ERROR_NONE || tdm->fd < 0) {
- ds_err("Could not get fd from tdm_display: err(%d)", err);
- goto err_fd;
- }
-
- loop = wl_display_get_event_loop(display);
- tdm->tdm_event = wl_event_loop_add_fd(loop, tdm->fd, WL_EVENT_READABLE,
- tdm_backend_handle_tdm_event, tdm);
- if (!tdm->tdm_event) {
- ds_err("could not add fd event handler for tdm event");
- goto err_event;
- }
-
- tdm->display_destroy.notify = tdm_backend_handle_display_destroy;
- wl_display_add_destroy_listener(display, &tdm->display_destroy);
-
- return &tdm->base;
-
-err_event:
- close(tdm->fd);
-err_fd:
- tdm_display_deinit(tdm->tdm_display);
-err_display:
- free(tdm);
-
- return NULL;
-}
-
-struct ds_tdm_backend *
-tdm_backend_from_backend(struct ds_backend *backend)
-{
- assert(backend->iface == &tdm_backend_iface);
- return (struct ds_tdm_backend *)backend;
-}
-
-static void
-tdm_backend_destroy(struct ds_tdm_backend *tdm)
-{
- struct ds_tdm_output *output, *tmp_output;
- struct ds_tdm_buffer *buffer, *tmp_buffer;
-
- wl_list_for_each_safe(output, tmp_output, &tdm->outputs, link)
- ds_output_destroy(&output->base);
-
- wl_list_for_each_safe(buffer, tmp_buffer, &tdm->buffers, link)
- destroy_tdm_buffer(buffer);
-
- wl_list_remove(&tdm->display_destroy.link);
- wl_event_source_remove(tdm->tdm_event);
- close(tdm->fd);
- tdm_display_deinit(tdm->tdm_display);
- ds_backend_finish(&tdm->base);
- free(tdm);
-}
-
-static bool
-tdm_backend_scan_outputs(struct ds_tdm_backend *tdm)
-{
- struct ds_tdm_output *output;
- tdm_output *tdm_output;
- tdm_error err;
- int num_outputs, i;
-
- err = tdm_display_get_output_count(tdm->tdm_display, &num_outputs);
- if (err != TDM_ERROR_NONE) {
- ds_err("Could not get number of outputs: err(%d)", err);
- return false;
- }
-
- for (i = 0; i < num_outputs; i++) {
- tdm_output = tdm_display_get_output(tdm->tdm_display, i, &err);
- if (err != TDM_ERROR_NONE || !tdm_output) {
- ds_err("Could not get output from tdm_display: index(%d) err(%d)",
- i, err);
- continue;
- }
-
- output = create_tdm_output(tdm, tdm_output);
- if (!output) {
- ds_err("Could not create output: index(%d)", i);
- continue;
- }
-
- wl_list_insert(&tdm->outputs, &output->link);
-
- wl_signal_emit(&tdm->base.events.new_output, &output->base);
- }
-
- return true;
-}
-
-static bool
-tdm_backend_iface_start(struct ds_backend *backend)
-{
- struct ds_tdm_backend *tdm;
-
- tdm = tdm_backend_from_backend(backend);
- return tdm_backend_scan_outputs(tdm);
-}
-
-static void
-tdm_backend_iface_destroy(struct ds_backend *backend)
-{
- struct ds_tdm_backend *tdm;
-
- tdm = tdm_backend_from_backend(backend);
- tdm_backend_destroy(tdm);
-}
-
-static const struct ds_backend_interface tdm_backend_iface =
-{
- .start = tdm_backend_iface_start,
- .destroy = tdm_backend_iface_destroy,
- .get_drm_fd = NULL,
-};
-
-static void
-tdm_backend_handle_display_destroy(struct wl_listener *listener, void *data)
-{
- struct ds_tdm_backend *tdm;
-
- tdm = wl_container_of(listener, tdm, display_destroy);
- tdm_backend_destroy(tdm);
-}
-
-static int
-tdm_backend_handle_tdm_event(int fd, uint32_t mask, void *data)
-{
- struct ds_tdm_backend *tdm = data;
-
- tdm_display_handle_events(tdm->tdm_display);
-
- return 0;
-}
+++ /dev/null
-msg = ['Required for TDM backend support.']
-if 'tdm' in backends
- msg += 'Install "libtdm" and "libtbm", or disable the tdm backend'
-endif
-
-libtdm = dependency(
- 'libtdm',
- required: 'tdm' in backends,
- not_found_message: '\n'.join(msg)
-)
-
-libtbm = dependency(
- 'libtbm',
- required: 'tdm' in backends,
- not_found_message: '\n'.join(msg)
-)
-
-if not libtdm.found() or not libtbm.found()
- subdir_done()
-endif
-
-libds_files += files(
- 'backend.c',
- 'output.c',
-)
-
-libds_deps += [
- libtdm,
- libtbm
-]
-
-features += { 'tdm-backend': true }
+++ /dev/null
-#include <assert.h>
-#include <stdlib.h>
-
-#include <tbm_surface.h>
-
-#include "libds/log.h"
-#include "libds/allocator/tbm.h"
-
-#include "tdm.h"
-
-static const struct ds_output_interface tdm_output_iface;
-static bool output_init_modes(struct ds_tdm_output *output);
-static void output_destroy(struct ds_tdm_output *output);
-static void output_init_hwc(struct ds_tdm_output *output);
-static bool output_update_mode(struct ds_tdm_output *output);
-static bool output_set_pending_fb(struct ds_tdm_output *output,
- struct ds_buffer *ds_buffer);
-static bool output_hwc_commit(struct ds_tdm_output *output);
-
-struct ds_tdm_output *
-create_tdm_output(struct ds_tdm_backend *tdm, tdm_output *tdm_output)
-{
- struct ds_tdm_output *output;
- tdm_output_conn_status conn;
- tdm_error err;
-
- output = calloc(1, sizeof *output);
- if (!output)
- return NULL;
-
- ds_output_init(&output->base, &tdm->base, &tdm_output_iface,
- tdm->wl_display);
-
- output->backend = tdm;
- output->tdm.output = tdm_output;
-
- err = tdm_output_get_conn_status(tdm_output, &conn);
- if (err != TDM_ERROR_NONE) {
- ds_err("Could not get connection status of tdm output(%p): err(%d)",
- tdm_output, err);
- goto err_status;
- }
-
- if (conn == TDM_OUTPUT_CONN_STATUS_CONNECTED) {
- output->status = DS_TDM_OUTPUT_CONNECTED;
-
- if (!output_init_modes(output)) {
- ds_err("Could not initialize modes of tdm output(%p)",
- tdm_output);
- goto err_status;
- }
- }
- else if (conn == TDM_OUTPUT_CONN_STATUS_DISCONNECTED) {
- output->status = DS_TDM_OUTPUT_DISCONNECTED;
- }
-
- if (tdm_output_get_hwc(output->tdm.output, NULL) != NULL)
- output_init_hwc(output);
-
- ds_inf("TDM output(%p) created: hwc(%p)", output, output->tdm.hwc);
-
- return output;
-
-err_status:
- free(output);
-
- return NULL;
-}
-
-static struct ds_tdm_output *
-tdm_output_from_output(struct ds_output *ds_output)
-{
- assert(ds_output->iface == &tdm_output_iface);
- return (struct ds_tdm_output *)ds_output;
-}
-
-static void
-output_iface_destroy(struct ds_output *ds_output)
-{
- struct ds_tdm_output *output;
-
- output = tdm_output_from_output(ds_output);
- output_destroy(output);
-}
-
-void
-destroy_tdm_buffer(struct ds_tdm_buffer *buffer)
-{
- if (buffer == NULL)
- return;
-
- wl_list_remove(&buffer->buffer_destroy.link);
- wl_list_remove(&buffer->link);
- free(buffer);
-}
-
-static void
-buffer_handle_buffer_destroy(struct wl_listener *listener, void *data)
-{
- struct ds_tdm_buffer *buffer;
-
- buffer = wl_container_of(listener, buffer, buffer_destroy);
- destroy_tdm_buffer(buffer);
-}
-
-static struct ds_tdm_buffer *
-create_tdm_buffer(struct ds_tdm_backend *backend, struct ds_buffer *ds_buffer)
-{
- struct ds_tdm_buffer *buffer;
- tbm_surface_h surface;
-
- surface = ds_tbm_buffer_get_surface(ds_buffer);
- if (!surface) {
- ds_err("Could not get tbm_surface_h");
- return NULL;
- }
-
- buffer = calloc(1, sizeof *buffer);
- if (!buffer)
- return NULL;
-
- buffer->surface = surface;
- buffer->buffer = ds_buffer_lock(ds_buffer);
- wl_list_insert(&backend->buffers, &buffer->link);
-
- buffer->buffer_destroy.notify = buffer_handle_buffer_destroy;
- ds_buffer_add_destroy_listener(ds_buffer, &buffer->buffer_destroy);
-
- return buffer;
-}
-
-static struct ds_tdm_buffer *
-get_or_create_tdm_buffer(struct ds_tdm_backend *backend,
- struct ds_buffer *ds_buffer)
-{
- struct ds_tdm_buffer *buffer;
-
- wl_list_for_each(buffer, &backend->buffers, link) {
- if (buffer->buffer == ds_buffer && buffer->released) {
- buffer->released = false;
- ds_buffer_lock(buffer->buffer);
- return buffer;
- }
- }
-
- return create_tdm_buffer(backend, ds_buffer);
-}
-
-static void
-tdm_buffer_release(struct ds_tdm_buffer *buffer)
-{
- buffer->released = true;
- ds_buffer_unlock(buffer->buffer);
-}
-
-static void
-output_update_front_buffer(struct ds_tdm_output *output)
-{
- if (output->front_buffer)
- tdm_buffer_release(output->front_buffer);
- output->front_buffer = output->back_buffer;
- output->back_buffer = NULL;
-}
-
-static void
-output_attach_back_buffer(struct ds_tdm_output *output,
- struct ds_tdm_buffer *buffer)
-{
- if (output->back_buffer)
- tdm_buffer_release(output->back_buffer);
- output->back_buffer = buffer;
-}
-
-static bool
-output_iface_commit(struct ds_output *ds_output)
-{
- struct ds_tdm_output *output;
-
- output = tdm_output_from_output(ds_output);
-
- if (ds_output->pending.committed & DS_OUTPUT_STATE_MODE) {
- if (!output_update_mode(output)) {
- ds_err("Could not update TDM mode");
- return false;
- }
- }
-
- if (ds_output->pending.committed & DS_OUTPUT_STATE_BUFFER) {
- if (!output_set_pending_fb(output, ds_output->pending.buffer))
- ds_err("Could not update buffer");
- }
-
- if (!output_hwc_commit(output)) {
- ds_err("Could not commit tdm output");
- if (output->back_buffer) {
- tdm_buffer_release(output->back_buffer);
- }
- }
-
- return true;
-}
-
-static const struct ds_output_interface tdm_output_iface =
-{
- .destroy = output_iface_destroy,
- .commit = output_iface_commit,
-};
-
-static void
-output_destroy(struct ds_tdm_output *output)
-{
- struct ds_tdm_output_mode *mode, *mode_tmp;
-
- wl_list_for_each_safe(mode, mode_tmp, &output->base.modes, base.link) {
- wl_list_remove(&mode->base.link);
- free(mode);
- }
-
- if (output->back_buffer)
- ds_buffer_unlock(output->back_buffer->buffer);
-
- if (output->front_buffer)
- ds_buffer_unlock(output->front_buffer->buffer);
-
- free(output);
-}
-
-static bool
-output_init_modes(struct ds_tdm_output *output)
-{
- struct ds_tdm_output_mode *mode;
- const tdm_output_mode *tdm_modes, *tdm_mode;
- tdm_error err;
- int num_modes, i;
-
- err = tdm_output_get_available_modes(output->tdm.output, &tdm_modes,
- &num_modes);
- if (err != TDM_ERROR_NONE) {
- ds_err("Could not get available modes: output(%p)", output);
- return false;
- }
-
- ds_dbg("Detected modes:");
-
- for (i = 0; i < num_modes; i++) {
- tdm_mode = &tdm_modes[i];
-
- mode = calloc(1, sizeof *mode);
- if (!mode) {
- ds_err("Could not allocate memory");
- continue;
- }
-
- mode->tdm_mode = tdm_mode;
- mode->base.width = tdm_mode->hdisplay;
- mode->base.height = tdm_mode->vdisplay;
- mode->base.refresh = (int32_t)tdm_mode->vrefresh; // FIXME
-
- if (tdm_mode->type & TDM_OUTPUT_MODE_TYPE_PREFERRED)
- mode->base.preferred = true;
-
- ds_dbg(" %dx%d@%d %s", mode->base.width, mode->base.height,
- mode->base.refresh,
- mode->base.preferred ? "(preferred)" : "");
-
- if (tdm_mode->type & TDM_OUTPUT_MODE_TYPE_DEFAULT)
- wl_list_insert(&output->base.modes, &mode->base.link);
- else
- wl_list_insert(output->base.modes.prev, &mode->base.link);
- }
-
- return true;
-}
-
-static void
-output_init_hwc(struct ds_tdm_output *output)
-{
- tdm_error err;
-
- output->tdm.hwc = tdm_output_get_hwc(output->tdm.output, &err);
- if (err != TDM_ERROR_NONE || !output->tdm.hwc) {
- ds_err("Could not get tdm_hwc: output(%p)", output);
- return;
- }
-}
-
-static bool
-output_update_mode(struct ds_tdm_output *output)
-{
- const struct ds_tdm_output_mode *mode;
- tdm_error err;
-
- mode = (struct ds_tdm_output_mode *)output->base.pending.mode;
-
- ds_inf("TDM output(%p) set mode %dx%d %d mHz", output,
- mode->base.width, mode->base.height, mode->base.refresh);
-
- err = tdm_output_set_mode(output->tdm.output, mode->tdm_mode);
- if (err != TDM_ERROR_NONE)
- return false;
-
- return true;
-}
-
-static bool
-output_set_pending_fb(struct ds_tdm_output *output,
- struct ds_buffer *ds_buffer)
-{
- struct ds_tdm_buffer *buffer;
- tdm_region fb_damage;
- tdm_error err;
-
- buffer = get_or_create_tdm_buffer(output->backend, ds_buffer);
- if (!buffer)
- return false;
-
- memset(&fb_damage, 0, sizeof(fb_damage));
- err = tdm_hwc_set_client_target_buffer(output->tdm.hwc,
- buffer->surface, fb_damage);
- if (err != TDM_ERROR_NONE) {
- ds_err("Could not set hwc client target buffer");
- ds_buffer_unlock(buffer->buffer);
- return false;
- }
-
- output_attach_back_buffer(output, buffer);
-
- return true;
-}
-
-static void
-output_hwc_commit_handler(tdm_hwc *hwc, unsigned int sequence,
- unsigned int tv_sec, unsigned int tv_usec, void *user_data)
-{
- struct ds_tdm_output *output = user_data;
-
- output_update_front_buffer(output);
-
- wl_signal_emit(&output->base.events.frame, &output->base);
-}
-
-static bool
-output_hwc_commit(struct ds_tdm_output *output)
-{
- tdm_error err;
- uint32_t num_changes;
-
- err = tdm_hwc_validate(output->tdm.hwc, NULL, 0, &num_changes);
- if (err != TDM_ERROR_NONE) {
- ds_err("Could not hwc validate");
- return false;
- }
-
- err = tdm_hwc_accept_validation(output->tdm.hwc);
- if (err != TDM_ERROR_NONE) {
- ds_err("Could not hwc accept validation");
- return false;
- }
-
- err = tdm_hwc_commit(output->tdm.hwc, 0, output_hwc_commit_handler,
- output);
- if (err != TDM_ERROR_NONE) {
- ds_err("Could not hwc commit");
- return false;
- }
-
- return true;
-}
+++ /dev/null
-#ifndef DS_BACKEND_TDM_H
-#define DS_BACKEND_TDM_H
-
-#include <time.h>
-
-#include <tdm.h>
-
-#include "libds/interfaces/backend.h"
-#include "libds/interfaces/output.h"
-
-enum ds_tdm_output_status {
- DS_TDM_OUTPUT_DISCONNECTED,
- DS_TDM_OUTPUT_CONNECTED,
-};
-
-struct ds_tdm_output_mode {
- struct ds_output_mode base;
- const tdm_output_mode *tdm_mode;
-};
-
-struct ds_tdm_backend
-{
- struct ds_backend base;
-
- tdm_display *tdm_display;
- struct wl_display *wl_display;
- struct wl_event_source *tdm_event;
-
- struct wl_list outputs; // ds_tdm_output.link
- struct wl_list buffers; // ds_tdm_buffer.link
-
- struct wl_listener display_destroy;
-
- clockid_t clock;
- int fd;
-};
-
-struct ds_tdm_output
-{
- struct ds_output base;
-
- struct ds_tdm_backend *backend;
- struct ds_tdm_buffer *front_buffer, *back_buffer;
-
- struct {
- tdm_output *output;
- tdm_hwc *hwc;
- } tdm;
-
- struct wl_list link;
-
- enum ds_tdm_output_status status;
-};
-
-struct ds_tdm_buffer
-{
- struct ds_buffer *buffer;
- tbm_surface_h surface;
- struct wl_list link; // ds_wl_backend.buffers
- struct wl_listener buffer_destroy;
-
- bool released;
-};
-
-struct ds_tdm_backend *tdm_backend_from_backend(struct ds_backend *backend);
-
-struct ds_tdm_output *create_tdm_output(struct ds_tdm_backend *tdm,
- tdm_output *tdm_output);
-
-void destroy_tdm_buffer(struct ds_tdm_buffer *buffer);
-
-
-#endif
install: true
)
-ds_vars = {}
-foreach name, have : features
- ds_vars += { 'have_' + name.underscorify(): have.to_string() }
-endforeach
-
dep_libds = declare_dependency(
link_with: lib_libds,
dependencies: libds_deps,
include_directories: [ common_inc, include_directories('.') ],
- variables: ds_vars,
)
pkgconfig = import('pkgconfig')
filebase: meson.project_name(),
name: meson.project_name(),
description: 'Wayland compositor library',
- variables: ds_vars,
)
)
subdir('libds')
+if get_option('tizen')
+ subdir('libds-tizen')
+endif
subdir('tests')
subdir('examples')
subdir('clients')