-/*
-Copyright (C) 2015 Samsung Electronics co., Ltd. All Rights Reserved.
-
-Contact:
- SooChan Lim <sc1.lim@samsung.com>,
- Sangjin Lee <lsj119@samsung.com>,
- Boram Park <boram1288.park@samsung.com>,
- Changyeon Lee <cyeon.lee@samsung.com>
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-the rights to use, copy, modify, merge, publish, distribute, sublicense,
-and/or sell copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice (including the next
-paragraph) shall be included in all copies or substantial portions of the
-Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.
-*/
-
-#define WL_HIDE_DEPRECATED
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stddef.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-#include <tbm_surface.h>
-#include <tbm_surface_internal.h>
-#include <wayland-server.h>
-
-#include "wayland-tbm-server.h"
-#include "wayland-tbm-server-protocol.h"
-
-#include "wayland-tbm-int.h"
-
-#define WL_TBM_SERVER_DEBUG
-
-#define MIN(x,y) (((x)<(y))?(x):(y))
-
-struct wayland_tbm_server {
- struct wl_display *display;
- struct wl_global *wl_tbm_global;
-
- struct wl_list client_resource_list;
-
- tbm_bufmgr bufmgr;
-
- /*Scanout*/
- struct wl_list queue_list;
- struct wl_list server_queue_list;
-};
-
-struct wl_tbm_buffer {
- struct wl_resource *resource;
- tbm_surface_h tbm_surface;
- tbm_surface_queue_h tbm_queue;
- int flags;
-};
-
-struct wayland_tbm_client_resource {
- struct wl_resource *resource;
- pid_t pid;
- char *app_name;
- struct wl_list link;
-};
-
-struct wayland_tbm_server_queue {
- struct wl_list link;
- struct wayland_tbm_server *tbm_srv;
- tbm_surface_queue_h tbm_queue;
- uint32_t flags;
-
- struct wl_tbm_queue *client_queue;
-};
-
-struct wl_tbm_queue {
- struct wl_list link;
-
- struct wl_resource *resource;
- struct wl_resource *wl_tbm;
- struct wl_resource *surface;
- struct wayland_tbm_server_queue *server_queue;
-
- int num_attached;
-};
-
-static const int key_wl_tbm_queue;
-#define KEY_WL_TBM_QUEUE ((unsigned long)&key_wl_tbm_queue)
-
-const static int key_wl_tbm_buffer;
-#define KEY_WL_TBM_BUFFER ((unsigned long)&key_wl_tbm_buffer)
-
-static void _create_tbm_queue(struct wl_client *client,
- struct wl_resource *resource,
- uint32_t surface_queue,
- struct wl_resource *surface);
-
-static void _destory_tbm_queue(struct wl_resource *resource);
-
-static void _buffer_destroy(struct wl_client *client,
- struct wl_resource *resource);
-
-static const struct wl_buffer_interface _wayland_tbm_buffer_impementation = {
- _buffer_destroy
-};
-
-static void
-_destroy_buffer(struct wl_resource *resource)
-{
- struct wl_tbm_buffer *buffer = wl_resource_get_user_data(resource);
-
- tbm_surface_internal_delete_user_data(buffer->tbm_surface, KEY_WL_TBM_BUFFER);
-
- if (buffer->tbm_queue) {
- tbm_surface_queue_release(buffer->tbm_queue, buffer->tbm_surface);
- WL_TBM_S_LOG("Release to queue(%p), tbm_surface:%p\n", buffer->tbm_queue,
- buffer->tbm_surface);
- }
-
- tbm_surface_destroy(buffer->tbm_surface);
-
- free(buffer);
-}
-
-static void
-_buffer_destroy(struct wl_client *client, struct wl_resource *resource)
-{
- wl_resource_destroy(resource);
-}
-
-static struct wl_tbm_buffer *
-_create_wl_buffer(struct wl_client *client, struct wl_resource *resource,
- uint id, tbm_surface_h tbm_buffer, int flags)
-{
- struct wayland_tbm_server *tbm_srv = wl_resource_get_user_data(resource);
- struct wayland_tbm_client_resource *c_res = NULL, *tmp_res = NULL;
- struct wl_tbm_buffer *buffer;
-
- buffer = calloc(1, sizeof * buffer);
- if (buffer == NULL) {
- wl_resource_post_no_memory(resource);
- return NULL;
- }
-
- buffer->flags = flags;
- buffer->tbm_surface = (void *)tbm_buffer;
- if (buffer->tbm_surface == NULL) {
- wl_resource_post_error(resource,
- WL_TBM_ERROR_INVALID_NAME,
- "tbm_surface is NULL");
- free(buffer);
- return NULL;
- }
-
- /* set the debug_pid to the surface for debugging */
- if (!wl_list_empty(&tbm_srv->client_resource_list)) {
- wl_list_for_each_safe(c_res, tmp_res, &tbm_srv->client_resource_list, link) {
- if (c_res->resource == resource) {
- tbm_surface_internal_set_debug_pid(tbm_buffer, c_res->pid);
- break;
- }
- }
- }
-
- buffer->resource = wl_resource_create(client, &wl_buffer_interface, 1, id);
- if (!buffer->resource) {
- wl_resource_post_no_memory(resource);
- free(buffer);
- return NULL;
- }
-
- wl_resource_set_implementation(buffer->resource,
- (void (* *)(void)) &_wayland_tbm_buffer_impementation,
- buffer, _destroy_buffer);
- tbm_surface_internal_add_user_data(tbm_buffer, KEY_WL_TBM_BUFFER, NULL);
- tbm_surface_internal_set_user_data(tbm_buffer, KEY_WL_TBM_BUFFER,
- (void *)buffer);
-
- return buffer;
-}
-
-static void
-_create_buffer(struct wl_client *client, struct wl_resource *resource,
- uint32_t id,
- tbm_surface_info_s *info,
- int32_t is_fd, int32_t *names, int32_t num_name, uint32_t flags)
-{
- struct wayland_tbm_server *tbm_srv = wl_resource_get_user_data(resource);
- struct wl_tbm_buffer *buffer;
- tbm_surface_h surface;
- tbm_bo bos[TBM_SURF_PLANE_MAX];
- int i;
-
- for (i = 0; i < num_name; i++) {
- if (is_fd) {
- bos[i] = tbm_bo_import_fd(tbm_srv->bufmgr, names[i]);
- } else {
- bos[i] = tbm_bo_import(tbm_srv->bufmgr, names[i]);
- }
- }
-
- surface = tbm_surface_internal_create_with_bos(info, bos, num_name);
- for (i = 0; i < num_name; i++)
- tbm_bo_unref(bos[i]);
-
- buffer = _create_wl_buffer(client, resource, id, surface, flags);
- if (!buffer) {
- WL_TBM_S_LOG("failed to create wl_buffer id:%d\n", id);
- tbm_surface_destroy(surface);
- return;
- }
-
- return;
-}
-
-static void
-_wayland_tbm_server_impl_request_tbm_monitor(struct wl_client *client,
- struct wl_resource *resource,
- int32_t command,
- int32_t trace_command,
- int32_t target,
- int32_t pid)
-{
- struct wayland_tbm_server *tbm_srv = wl_resource_get_user_data(resource);
- struct wayland_tbm_client_resource *c_res = NULL, *tmp_res = NULL;
- int i = 0;
-
-#ifdef WL_TBM_SERVER_DEBUG
- WL_TBM_LOG("[%s]: command=%d, trace_command=%d, target=%d, pid=%d.\n", __func__,
- command, trace_command, target, pid);
-#endif
-
- if (command == WL_TBM_MONITOR_COMMAND_LIST) {
- WL_TBM_DEBUG("================== app list =======================\n");
- WL_TBM_DEBUG("no pid app_name\n");
-
- if (!wl_list_empty(&tbm_srv->client_resource_list)) {
- wl_list_for_each_safe(c_res, tmp_res, &tbm_srv->client_resource_list, link) {
- /* skip the requestor (wayland-tbm-monitor */
- if (c_res->resource == resource)
- continue;
-
- if (!c_res->app_name) {
- c_res->app_name = (char *) calloc(1, 255 * sizeof(char));
-
- _wayland_tbm_util_get_appname_from_pid(c_res->pid, c_res->app_name);
- _wayland_tbm_util_get_appname_brief(c_res->app_name);
- }
-
- WL_TBM_DEBUG("%-3d%-5d%s\n", ++i, c_res->pid, c_res->app_name);
- }
- }
-
- WL_TBM_DEBUG("======================================================\n");
-
- return;
- }
-
- if (target == WL_TBM_MONITOR_TARGET_CLIENT) {
- if (pid < 1) {
- wl_resource_post_error(resource, WL_TBM_ERROR_INVALID_FORMAT, "invalid format");
- return;
- }
- /* send the events to all client containing wl_tbm resource except for the wayland-tbm-monitor(requestor). */
- if (!wl_list_empty(&tbm_srv->client_resource_list)) {
- wl_list_for_each_safe(c_res, tmp_res, &tbm_srv->client_resource_list, link) {
- /* skip the requestor (wayland-tbm-monitor */
- if (c_res->resource == resource)
- continue;
-
- wl_tbm_send_monitor_client_tbm_bo(c_res->resource, command, trace_command,
- target, pid);
- }
- }
- } else if (target == WL_TBM_MONITOR_TARGET_SERVER) {
- if (command == WL_TBM_MONITOR_COMMAND_SHOW) {
- tbm_bufmgr_debug_show(tbm_srv->bufmgr);
- } else if (command == WL_TBM_MONITOR_COMMAND_TRACE) {
- WL_TBM_LOG("[%s]: TRACE NOT IMPLEMENTED.\n", __func__);
- } else
- wl_resource_post_error(resource, WL_TBM_ERROR_INVALID_FORMAT,
- "invalid format");
- } else if (target == WL_TBM_MONITOR_TARGET_ALL) {
- if (command == WL_TBM_MONITOR_COMMAND_SHOW) {
- /* send the events to all client containing wl_tbm resource except for the wayland-tbm-monitor(requestor). */
- if (!wl_list_empty(&tbm_srv->client_resource_list)) {
- wl_list_for_each_safe(c_res, tmp_res, &tbm_srv->client_resource_list, link) {
- /* skip the requestor (wayland-tbm-monitor */
- if (c_res->resource == resource)
- continue;
-
- wl_tbm_send_monitor_client_tbm_bo(c_res->resource, command, trace_command,
- target, pid);
- }
- }
- tbm_bufmgr_debug_show(tbm_srv->bufmgr);
- } else if (command == WL_TBM_MONITOR_COMMAND_TRACE) {
- wl_tbm_send_monitor_client_tbm_bo(resource, command, trace_command, target,
- pid);
- WL_TBM_LOG("[%s]: TRACE NOT IMPLEMENTED.\n", __func__);
- } else
- wl_resource_post_error(resource, WL_TBM_ERROR_INVALID_FORMAT,
- "invalid format");
- } else
- wl_resource_post_error(resource, WL_TBM_ERROR_INVALID_FORMAT,
- "invalid format");
-
-}
-
-
-static void
-_wayland_tbm_server_impl_create_buffer(struct wl_client *client,
- struct wl_resource *resource,
- uint32_t id,
- int32_t width, int32_t height, uint32_t format, int32_t num_plane,
- int32_t buf_idx0, int32_t offset0, int32_t stride0,
- int32_t buf_idx1, int32_t offset1, int32_t stride1,
- int32_t buf_idx2, int32_t offset2, int32_t stride2,
- uint32_t flags,
- int32_t num_buf, uint32_t buf0, uint32_t buf1, uint32_t buf2)
-{
- int32_t names[TBM_SURF_PLANE_MAX] = { -1, -1, -1, -1};
- tbm_surface_info_s info;
- int bpp;
- int numPlane, numName = 0;
-
-#ifdef WL_TBM_SERVER_DEBUG
- WL_TBM_LOG("[%s]: trying.\n", __func__);
-#endif
-
- bpp = tbm_surface_internal_get_bpp(format);
- numPlane = tbm_surface_internal_get_num_planes(format);
- if (numPlane != num_plane) {
- wl_resource_post_error(resource, WL_TBM_ERROR_INVALID_FORMAT,
- "invalid format");
- return;
- }
-
- memset(&info, 0x0, sizeof(tbm_surface_info_s));
-
- info.width = width;
- info.height = height;
- info.format = format;
- info.bpp = bpp;
- info.num_planes = numPlane;
-
- /*Fill plane info*/
- if (numPlane > 0) {
- info.planes[0].offset = offset0;
- info.planes[0].stride = stride0;
- numPlane--;
- }
-
- if (numPlane > 0) {
- info.planes[1].offset = offset1;
- info.planes[1].stride = stride1;
- numPlane--;
- }
-
- if (numPlane > 0) {
- info.planes[2].offset = offset2;
- info.planes[2].stride = stride2;
- numPlane--;
- }
-
- /*Fill buffer*/
- numName = num_buf;
- names[0] = buf0;
- names[1] = buf1;
- names[2] = buf2;
-
- _create_buffer(client, resource, id, &info, 0, names, numName, flags);
-}
-
-static void
-_wayland_tbm_server_impl_create_buffer_with_fd(struct wl_client *client,
- struct wl_resource *resource,
- uint32_t id,
- int32_t width, int32_t height, uint32_t format, int num_plane,
- int32_t buf_idx0, int32_t offset0, int32_t stride0,
- int32_t buf_idx1, int32_t offset1, int32_t stride1,
- int32_t buf_idx2, int32_t offset2, int32_t stride2,
- uint32_t flags,
- int32_t num_buf, int32_t buf0, int32_t buf1, int32_t buf2)
-{
- int32_t names[TBM_SURF_PLANE_MAX] = {0, 0, 0, 0};
- tbm_surface_info_s info;
- int bpp;
- int numPlane, numName = 0;
-
-#ifdef WL_TBM_SERVER_DEBUG
- WL_TBM_LOG("[%s]: trying.\n", __func__);
-#endif
-
- bpp = tbm_surface_internal_get_bpp(format);
- numPlane = tbm_surface_internal_get_num_planes(format);
- if (numPlane != num_plane) {
- wl_resource_post_error(resource, WL_TBM_ERROR_INVALID_FORMAT,
- "invalid format");
- return;
- }
-
- memset(&info, 0x0, sizeof(tbm_surface_info_s));
-
- info.width = width;
- info.height = height;
- info.format = format;
- info.bpp = bpp;
- info.num_planes = numPlane;
-
- /*Fill plane info*/
- if (numPlane > 0) {
- info.planes[0].offset = offset0;
- info.planes[0].stride = stride0;
- numPlane--;
- }
-
- if (numPlane > 0) {
- info.planes[1].offset = offset1;
- info.planes[1].stride = stride1;
- numPlane--;
- }
-
- if (numPlane > 0) {
- info.planes[2].offset = offset2;
- info.planes[2].stride = stride2;
- numPlane--;
- }
-
- /*Fill buffer*/
- numName = num_buf;
- names[0] = buf0;
- names[1] = buf1;
- names[2] = buf2;
-
- _create_buffer(client, resource, id, &info, 1, names, numName, flags);
-
- close(buf0);
- close(buf1);
- close(buf2);
-}
-
-static void
-_wayland_tbm_server_impl_create_surface_queue(struct wl_client *client,
- struct wl_resource *resource,
- uint32_t surface_queue,
- struct wl_resource *surface)
-{
- _create_tbm_queue(client, resource, surface_queue, surface);
-}
-
-static const struct wl_tbm_interface _wayland_tbm_server_implementation = {
- _wayland_tbm_server_impl_create_buffer,
- _wayland_tbm_server_impl_create_buffer_with_fd,
- _wayland_tbm_server_impl_request_tbm_monitor,
- _wayland_tbm_server_impl_create_surface_queue,
-};
-
-static void
-_wayland_tbm_server_destroy_resource (struct wl_resource *resource)
-{
- struct wayland_tbm_server *tbm_srv = NULL;
- struct wayland_tbm_client_resource *c_res = NULL, *tmp_res;
-
- /* remove the client resources to the list */
- tbm_srv = wl_resource_get_user_data(resource);
- if (!wl_list_empty(&tbm_srv->client_resource_list)) {
- wl_list_for_each_safe(c_res, tmp_res, &tbm_srv->client_resource_list, link) {
- if (c_res->resource == resource) {
-#ifdef WL_TBM_SERVER_DEBUG
- WL_TBM_LOG("[%s]: resource,%p pid,%d \n", __func__, c_res->resource,
- c_res->pid);
-#endif
- wl_list_remove(&c_res->link);
- if (c_res->app_name)
- free(c_res->app_name);
- free(c_res);
- break;
- }
- }
- }
-}
-
-static void
-_wayland_tbm_server_bind_cb(struct wl_client *client, void *data,
- uint32_t version,
- uint32_t id)
-{
- struct wayland_tbm_server *tbm_srv = NULL;
- struct wayland_tbm_client_resource *c_res = NULL;
-
- struct wl_resource *resource;
- pid_t pid = 0;
- uid_t uid = 0;
- gid_t gid = 0;
-
-
- resource = wl_resource_create(client, &wl_tbm_interface, MIN(version, 1), id);
- if (!resource) {
- wl_client_post_no_memory(client);
- return;
- }
-
- wl_resource_set_implementation(resource,
- &_wayland_tbm_server_implementation,
- data,
- _wayland_tbm_server_destroy_resource);
-
- /* add the client resources to the list */
- tbm_srv = wl_resource_get_user_data(resource);
- wl_client_get_credentials(client, &pid, &uid, &gid);
-
-#ifdef WL_TBM_SERVER_DEBUG
- WL_TBM_LOG("[%s]: resource,%p pid,%d \n", __func__, resource, pid);
-#endif
-
- c_res = calloc (1, sizeof(struct wayland_tbm_client_resource));
- c_res->pid = pid;
- c_res->resource = resource;
- wl_list_insert(&tbm_srv->client_resource_list, &c_res->link);
-}
-
-struct wayland_tbm_server *
-wayland_tbm_server_init(struct wl_display *display, const char *device_name,
- int fd,
- uint32_t flags)
-{
- struct wayland_tbm_server *tbm_srv;
-
- tbm_srv = calloc(1, sizeof(struct wayland_tbm_server));
- WL_TBM_RETURN_VAL_IF_FAIL(tbm_srv != NULL, NULL);
-
- tbm_srv->display = display;
-
- /* init the client resource list */
- wl_list_init(&tbm_srv->client_resource_list);
- wl_list_init(&tbm_srv->server_queue_list);
-
- //init bufmgr
- tbm_srv->bufmgr = tbm_bufmgr_init(-1);
- if (!tbm_srv->bufmgr) {
- free(tbm_srv);
- return NULL;
- }
-
- if (!getenv("WL_TBM_EMBEDDED_SERVER")) {
- WL_TBM_S_LOG("Bind start\n");
- tbm_bufmgr_bind_native_display(tbm_srv->bufmgr, (void *)display);
- }
- tbm_srv->wl_tbm_global = wl_global_create(display, &wl_tbm_interface, 1,
- tbm_srv, _wayland_tbm_server_bind_cb);
-
- //init wl_tbm_queue
- wl_list_init(&tbm_srv->queue_list);
-
- return tbm_srv;
-}
-
-void
-wayland_tbm_server_deinit(struct wayland_tbm_server *tbm_srv)
-{
- wl_global_destroy(tbm_srv->wl_tbm_global);
-
- tbm_bufmgr_deinit(tbm_srv->bufmgr);
-
- free(tbm_srv);
-}
-
-tbm_surface_h
-wayland_tbm_server_get_surface(struct wayland_tbm_server *tbm_srv,
- struct wl_resource *resource)
-{
- struct wl_tbm_buffer *wl_buffer;
-
- if (resource == NULL)
- return NULL;
-
- if (wl_resource_instance_of(resource, &wl_buffer_interface,
- &_wayland_tbm_buffer_impementation)) {
- wl_buffer = wl_resource_get_user_data(resource);
- return wl_buffer->tbm_surface;
- }
-
- return NULL;
-}
-
-struct wl_resource *
-wayland_tbm_server_get_resource(struct wayland_tbm_server *tbm_srv,
- tbm_surface_h surface)
-{
- struct wl_tbm_buffer *wl_buffer = NULL;
-
- tbm_surface_internal_get_user_data(surface, KEY_WL_TBM_BUFFER,
- (void **)&wl_buffer);
- if (wl_buffer)
- return wl_buffer->resource;
-
- return NULL;
-}
-
-uint32_t
-wayland_tbm_server_get_flags(struct wayland_tbm_server *tbm_srv,
- struct wl_resource *resource)
-{
- struct wl_tbm_buffer *wl_buffer;
-
- if (resource == NULL)
- return 0;
-
- if (wl_resource_instance_of(resource, &wl_buffer_interface,
- &_wayland_tbm_buffer_impementation)) {
- wl_buffer = wl_resource_get_user_data(resource);
- return wl_buffer->flags;
- }
-
- return 0;
-}
-
-void *
-wayland_tbm_server_get_bufmgr(struct wayland_tbm_server *tbm_srv)
-{
- if (tbm_srv == NULL)
- return NULL;
-
- return (void *)tbm_srv->bufmgr;
-}
-
-static void
-_wayland_tbm_queue_impl_destroy(struct wl_client *client,
- struct wl_resource *resource)
-{
- _destory_tbm_queue(resource);
-}
-
-static void
-_wayland_tbm_queue_impl_detach_buffer(struct wl_client *client,
- struct wl_resource *resource,
- struct wl_resource *buffer)
-{
-}
-
-static const struct wl_tbm_queue_interface _wayland_tbm_queue_impementation = {
- _wayland_tbm_queue_impl_destroy,
- _wayland_tbm_queue_impl_detach_buffer,
-};
-
-struct wl_tbm_queue *
-_find_tbm_queue(struct wayland_tbm_server *tbm_srv, struct wl_resource *surface)
-{
- struct wl_tbm_queue *queue = NULL;
-
- wl_list_for_each(queue, &tbm_srv->queue_list, link) {
- if (queue && queue->surface == surface)
- return queue;
- }
-
- return NULL;
-}
-
-static void
-_destory_tbm_queue(struct wl_resource *resource)
-{
- struct wl_tbm_queue *queue = wl_resource_get_user_data(resource);
-
- wl_list_remove(&queue->link);
-
- free(queue);
-}
-
-static void
-_create_tbm_queue(struct wl_client *client,
- struct wl_resource *resource,
- uint32_t surface_queue,
- struct wl_resource *surface)
-{
- struct wayland_tbm_server *tbm_srv = wl_resource_get_user_data(resource);
- struct wl_tbm_queue *queue;
-
- queue = calloc(1, sizeof * queue);
- if (queue == NULL) {
- wl_resource_post_no_memory(resource);
- return;
- }
-
- wl_list_init(&queue->link);
- queue->wl_tbm = resource;
- queue->surface = surface;
- queue->resource = wl_resource_create(client, &wl_tbm_queue_interface, 1,
- surface_queue);
- if (!queue->resource) {
- wl_resource_post_no_memory(resource);
- free(queue);
- return;
- }
-
- wl_resource_set_implementation(queue->resource,
- (void (* *)(void)) &_wayland_tbm_queue_impementation,
- queue, _destory_tbm_queue);
- wl_list_insert(&tbm_srv->queue_list, &queue->link);
-}
-
-static void
-_server_queue_buffer_attach(struct wl_tbm_queue *client_queue,
- tbm_surface_h buffer)
-{
- struct wl_tbm_buffer *wl_tbm_buffer = NULL;
- tbm_surface_info_s info;
- int num_buf;
- int bufs[TBM_SURF_PLANE_MAX] = { -1, -1, -1, -1};
- int is_fd = -1;
- int ret = -1, i;
- uint32_t flags;
-
- flags = client_queue->server_queue->flags;
- wl_tbm_buffer = _create_wl_buffer(wl_resource_get_client(client_queue->wl_tbm),
- client_queue->wl_tbm,
- 0, buffer, flags);
- WL_TBM_RETURN_IF_FAIL(wl_tbm_buffer != NULL);
- tbm_surface_internal_ref(buffer);
-
- ret = tbm_surface_get_info(buffer, &info);
- if (ret != TBM_SURFACE_ERROR_NONE) {
- WL_TBM_S_LOG("Failed to create buffer from surface\n");
- _destroy_buffer(wl_tbm_buffer->resource);
- return;
- }
-
- if (info.num_planes > 3) {
- WL_TBM_S_LOG("invalid num_planes(%d)\n", info.num_planes);
- _destroy_buffer(wl_tbm_buffer->resource);
- return;
- }
-
- num_buf = tbm_surface_internal_get_num_bos(buffer);
- if (num_buf == 0) {
- WL_TBM_S_LOG("surface doesn't have any bo.\n");
- _destroy_buffer(wl_tbm_buffer->resource);
- goto err;
- }
-
- for (i = 0; i < num_buf; i++) {
- tbm_bo bo = tbm_surface_internal_get_bo(buffer, i);
- if (bo == NULL) {
- WL_TBM_S_LOG("Failed to get bo from surface\n");
- goto err;
- }
-
- /* try to get fd first */
- if (is_fd == -1 || is_fd == 1) {
- bufs[i] = tbm_bo_export_fd(bo);
- if (bufs[i] >= 0)
- is_fd = 1;
- }
-
- /* if fail to get fd, try to get name second */
- if (is_fd == -1 || is_fd == 0) {
- bufs[i] = tbm_bo_export(bo);
- if (bufs[i] > 0)
- is_fd = 0;
- }
-
- if (is_fd == -1 ||
- (is_fd == 1 && bufs[i] < 0) ||
- (is_fd == 0 && bufs[i] <= 0)) {
- WL_TBM_S_LOG("Failed to export(is_fd:%d, bufs:%d)\n", is_fd, bufs[i]);
- goto err;
- }
- }
-
- if (is_fd == 1)
- wl_tbm_queue_send_buffer_attached_with_fd(client_queue->resource,
- wl_tbm_buffer->resource,
- info.width, info.height, info.format, info.num_planes,
- tbm_surface_internal_get_plane_bo_idx(buffer, 0),
- info.planes[0].offset, info.planes[0].stride,
- tbm_surface_internal_get_plane_bo_idx(buffer, 1),
- info.planes[1].offset, info.planes[1].stride,
- tbm_surface_internal_get_plane_bo_idx(buffer, 2),
- info.planes[2].offset, info.planes[2].stride,
- flags, num_buf, bufs[0],
- (bufs[1] == -1) ? bufs[0] : bufs[1],
- (bufs[2] == -1) ? bufs[0] : bufs[2]);
- else
- wl_tbm_queue_send_buffer_attached_with_fd(client_queue->resource,
- wl_tbm_buffer->resource,
- info.width, info.height, info.format, info.num_planes,
- tbm_surface_internal_get_plane_bo_idx(buffer, 0),
- info.planes[0].offset, info.planes[0].stride,
- tbm_surface_internal_get_plane_bo_idx(buffer, 1),
- info.planes[1].offset, info.planes[1].stride,
- tbm_surface_internal_get_plane_bo_idx(buffer, 2),
- info.planes[2].offset, info.planes[2].stride,
- flags, num_buf, bufs[0],
- (bufs[1] == -1) ? bufs[0] : bufs[1],
- (bufs[2] == -1) ? bufs[0] : bufs[2]);
-
-
- for (i = 0; i < TBM_SURF_PLANE_MAX; i++) {
- if (is_fd == 1 && (bufs[i] >= 0))
- close(bufs[i]);
- }
-
- wl_tbm_buffer->tbm_queue = client_queue->server_queue->tbm_queue;
- return;
-err:
- for (i = 0; i < TBM_SURF_PLANE_MAX; i++) {
- if (is_fd == 1 && (bufs[i] >= 0))
- close(bufs[i]);
- }
-
- if (wl_tbm_buffer) {
- _destroy_buffer(wl_tbm_buffer->resource);
- tbm_surface_internal_unref(buffer);
- }
-
- return;
-}
-
-static void
-_server_queue_buffer_attach_free_queue(struct wl_tbm_queue *client_queue)
-{
- tbm_surface_queue_h queue;
- tbm_surface_h buffer;
- struct wl_resource *wl_buffer;
-
- queue = client_queue->server_queue->tbm_queue;
- while (tbm_surface_queue_can_dequeue(queue, 0)) {
- tbm_surface_queue_dequeue(queue, &buffer);
-
- wl_buffer = wayland_tbm_server_get_resource(NULL, buffer);
- if (wl_buffer) {
- wl_buffer_send_release(wl_buffer);
- continue;
- }
-
- _server_queue_buffer_attach(client_queue, buffer);
- }
-}
-
-static void
-_server_queue_dequeuable_cb(tbm_surface_queue_h surface_queue,
- void *data)
-{
- struct wl_tbm_queue *client_queue = data;
- struct wl_resource *wl_buffer;
- tbm_surface_h buffer = NULL;
-
- tbm_surface_queue_dequeue(surface_queue, &buffer);
- WL_TBM_RETURN_IF_FAIL(buffer != NULL);
-
- wl_buffer = wayland_tbm_server_get_resource(NULL, buffer);
- if (wl_buffer) {
- wl_buffer_send_release(wl_buffer);
- return;
- }
-
- _server_queue_buffer_attach(client_queue, buffer);
-}
-
-struct wayland_tbm_server_queue *
-wayland_tbm_server_create_queue(struct wayland_tbm_server *tbm_srv,
- tbm_surface_queue_h queue, uint32_t flags)
-{
- struct wayland_tbm_server_queue *server_queue = NULL;
-
- WL_TBM_RETURN_VAL_IF_FAIL(tbm_srv != NULL, NULL);
- WL_TBM_RETURN_VAL_IF_FAIL(queue != NULL, NULL);
-
- server_queue = calloc(1, sizeof(struct wayland_tbm_server_queue));
- WL_TBM_RETURN_VAL_IF_FAIL(server_queue != NULL, NULL);
-
- server_queue->tbm_srv = tbm_srv;
- server_queue->tbm_queue = queue;
- server_queue->flags = flags;
- wl_list_insert(&tbm_srv->server_queue_list, &server_queue->link);
-
- return server_queue;
-}
-
-int
-wayland_tbm_server_queue_set_surface(struct wayland_tbm_server_queue *server_queue,
- struct wl_resource *surface, uint32_t usage)
-{
- struct wl_tbm_queue *client_queue = NULL;
-
- WL_TBM_RETURN_VAL_IF_FAIL(server_queue != NULL, 0);
-
- if (surface) {
- client_queue = _find_tbm_queue(server_queue->tbm_srv, surface);
- WL_TBM_RETURN_VAL_IF_FAIL(client_queue != NULL, 0);
- }
-
- if (client_queue == server_queue->client_queue)
- return 1;
-
- if (server_queue->client_queue) {
- //Send deactivate;
- server_queue->client_queue->server_queue = NULL;
-
- tbm_surface_queue_remove_dequeuable_cb(server_queue->tbm_queue,
- _server_queue_dequeuable_cb,
- server_queue->client_queue);
- wl_tbm_queue_send_deactive(server_queue->client_queue->resource);
- }
-
- if (client_queue) {
- //Send activate and attach free buffer;
- client_queue->server_queue = server_queue;
-
- wl_tbm_queue_send_active(client_queue->resource, usage);
- wl_tbm_queue_send_info(client_queue->resource,
- tbm_surface_queue_get_width(server_queue->tbm_queue),
- tbm_surface_queue_get_height(server_queue->tbm_queue),
- tbm_surface_queue_get_format(server_queue->tbm_queue),
- TBM_BO_SCANOUT,
- tbm_surface_queue_get_size(server_queue->tbm_queue));
-
- _server_queue_buffer_attach_free_queue(client_queue);
- tbm_surface_queue_add_dequeuable_cb(server_queue->tbm_queue,
- _server_queue_dequeuable_cb, client_queue);
- }
-
- server_queue->client_queue = client_queue;
-
- return 1;
-}
-
-
+/*\r
+Copyright (C) 2015 Samsung Electronics co., Ltd. All Rights Reserved.\r
+\r
+Contact:\r
+ SooChan Lim <sc1.lim@samsung.com>,\r
+ Sangjin Lee <lsj119@samsung.com>,\r
+ Boram Park <boram1288.park@samsung.com>,\r
+ Changyeon Lee <cyeon.lee@samsung.com>\r
+\r
+Permission is hereby granted, free of charge, to any person obtaining a\r
+copy of this software and associated documentation files (the "Software"),\r
+to deal in the Software without restriction, including without limitation\r
+the rights to use, copy, modify, merge, publish, distribute, sublicense,\r
+and/or sell copies of the Software, and to permit persons to whom the\r
+Software is furnished to do so, subject to the following conditions:\r
+\r
+The above copyright notice and this permission notice (including the next\r
+paragraph) shall be included in all copies or substantial portions of the\r
+Software.\r
+\r
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\r
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\r
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\r
+DEALINGS IN THE SOFTWARE.\r
+*/\r
+\r
+#define WL_HIDE_DEPRECATED\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <stddef.h>\r
+#include <unistd.h>\r
+#include <fcntl.h>\r
+\r
+#include <tbm_surface.h>\r
+#include <tbm_surface_internal.h>\r
+#include <wayland-server.h>\r
+\r
+#include "wayland-tbm-server.h"\r
+#include "wayland-tbm-server-protocol.h"\r
+\r
+#include "wayland-tbm-int.h"\r
+\r
+#define WL_TBM_SERVER_DEBUG\r
+\r
+#define MIN(x,y) (((x)<(y))?(x):(y))\r
+\r
+struct wayland_tbm_server {\r
+ struct wl_display *display;\r
+ struct wl_global *wl_tbm_global;\r
+\r
+ tbm_bufmgr bufmgr;\r
+\r
+ struct wl_list cqueue_list; /* for scanout buffer */\r
+ struct wl_list cresource_list; /* for tbm monitor */\r
+};\r
+\r
+struct wayland_tbm_buffer {\r
+ struct wl_resource *wl_buffer;\r
+ tbm_surface_h surface;\r
+ int flags;\r
+ struct wl_client *client;\r
+\r
+ wayland_tbm_server_surface_destroy_cb destroy_cb;\r
+ void *user_data;\r
+};\r
+\r
+struct wayland_tbm_client_resource {\r
+ struct wl_resource *resource;\r
+ pid_t pid;\r
+ char *app_name;\r
+\r
+ struct wl_list link;\r
+};\r
+\r
+struct wayland_tbm_client_queue {\r
+ struct wl_resource *wl_tbm;\r
+ struct wl_resource *wl_tbm_queue;\r
+ struct wl_resource *wl_surface;\r
+\r
+ struct wl_list link;\r
+};\r
+\r
+static const int key_wl_tbm_queue;\r
+#define KEY_WL_TBM_QUEUE ((unsigned long)&key_wl_tbm_queue)\r
+\r
+const static int key_tbm_buffer;\r
+#define KEY_TBM_BUFFER ((unsigned long)&key_tbm_buffer)\r
+\r
+static void _wayland_tbm_server_tbm_buffer_destroy(struct wayland_tbm_buffer *tbm_buffer);\r
+\r
+static void\r
+_tbm_buffer_destroy(struct wl_resource *wl_buffer)\r
+{\r
+ struct wayland_tbm_buffer *tbm_buffer = wl_resource_get_user_data(wl_buffer);\r
+\r
+ _wayland_tbm_server_tbm_buffer_destroy(tbm_buffer);\r
+}\r
+\r
+static void\r
+_wayland_tbm_server_tbm_buffer_impl_destroy(struct wl_client *client, struct wl_resource *wl_buffer)\r
+{\r
+ wl_resource_destroy(wl_buffer);\r
+}\r
+\r
+static const struct wl_buffer_interface _wayland_tbm_buffer_impementation = {\r
+ _wayland_tbm_server_tbm_buffer_impl_destroy\r
+};\r
+\r
+static void\r
+_wayland_tbm_server_tbm_buffer_destroy(struct wayland_tbm_buffer *tbm_buffer)\r
+{\r
+ if (tbm_buffer->destroy_cb)\r
+ tbm_buffer->destroy_cb(tbm_buffer->surface, tbm_buffer->user_data);\r
+\r
+ tbm_surface_internal_delete_user_data(tbm_buffer->surface, KEY_TBM_BUFFER);\r
+ tbm_surface_destroy(tbm_buffer->surface);\r
+\r
+ free(tbm_buffer);\r
+}\r
+\r
+static struct wayland_tbm_buffer *\r
+_wayland_tbm_server_tbm_buffer_create(struct wl_resource *wl_tbm,\r
+ struct wl_client *client, tbm_surface_h surface, uint id, int flags)\r
+{\r
+ struct wayland_tbm_server *tbm_srv = wl_resource_get_user_data(wl_tbm);\r
+ struct wayland_tbm_client_resource *c_res = NULL, *tmp_res = NULL;\r
+ struct wayland_tbm_buffer *tbm_buffer;\r
+\r
+ tbm_buffer = calloc(1, sizeof * tbm_buffer);\r
+ if (tbm_buffer == NULL) {\r
+ WL_TBM_S_LOG("Error. fail to allocate a tbm_buffer.\n");\r
+ return NULL;\r
+ }\r
+\r
+ /* create a wl_buffer resource */\r
+ tbm_buffer->wl_buffer = wl_resource_create(client, &wl_buffer_interface, 1, id);\r
+ if (!tbm_buffer->wl_buffer) {\r
+ WL_TBM_S_LOG("Error. fail to create wl_buffer resource.\n");\r
+ free(tbm_buffer);\r
+ return NULL;\r
+ }\r
+\r
+ wl_resource_set_implementation(tbm_buffer->wl_buffer,\r
+ (void (* *)(void)) &_wayland_tbm_buffer_impementation,\r
+ tbm_buffer, _tbm_buffer_destroy);\r
+\r
+ tbm_buffer->flags = flags;\r
+ tbm_buffer->surface = surface;\r
+ tbm_buffer->client = client;\r
+\r
+ tbm_surface_internal_add_user_data(surface, KEY_TBM_BUFFER, NULL);\r
+ tbm_surface_internal_set_user_data(surface, KEY_TBM_BUFFER,\r
+ (void *)tbm_buffer);\r
+\r
+ /* set the debug_pid to the surface for debugging */\r
+ if (!wl_list_empty(&tbm_srv->cresource_list)) {\r
+ wl_list_for_each_safe(c_res, tmp_res, &tbm_srv->cresource_list, link) {\r
+ if (c_res->resource == wl_tbm) {\r
+ tbm_surface_internal_set_debug_pid(surface, c_res->pid);\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ return tbm_buffer;\r
+}\r
+\r
+static void\r
+_destroy_tbm_queue(struct wl_resource *wl_tbm_queue)\r
+{\r
+ struct wayland_tbm_client_queue *cqueue = wl_resource_get_user_data(wl_tbm_queue);\r
+\r
+ if (cqueue) {\r
+ wl_list_remove(&cqueue->link);\r
+ free(cqueue);\r
+\r
+ wl_resource_set_user_data(wl_tbm_queue, NULL);\r
+ }\r
+}\r
+\r
+static void\r
+_wayland_tbm_server_queue_impl_destroy(struct wl_client *client,\r
+ struct wl_resource *wl_tbm_queue)\r
+{\r
+ wl_resource_destroy(wl_tbm_queue);\r
+}\r
+\r
+static void\r
+_wayland_tbm_server_queue_impl_detach_buffer(struct wl_client *client,\r
+ struct wl_resource *wl_tbm_queue,\r
+ struct wl_resource *wl_buffer)\r
+{\r
+}\r
+\r
+static const struct wl_tbm_queue_interface _wayland_tbm_queue_impementation = {\r
+ _wayland_tbm_server_queue_impl_destroy,\r
+ _wayland_tbm_server_queue_impl_detach_buffer,\r
+};\r
+\r
+static void\r
+_wayland_tbm_server_impl_request_tbm_monitor(struct wl_client *client,\r
+ struct wl_resource *resource,\r
+ int32_t command,\r
+ int32_t trace_command,\r
+ int32_t target,\r
+ int32_t pid)\r
+{\r
+ struct wayland_tbm_server *tbm_srv = wl_resource_get_user_data(resource);\r
+ struct wayland_tbm_client_resource *c_res = NULL, *tmp_res = NULL;\r
+ int i = 0;\r
+\r
+#ifdef WL_TBM_SERVER_DEBUG\r
+ WL_TBM_LOG("[%s]: command=%d, trace_command=%d, target=%d, pid=%d.\n", __func__,\r
+ command, trace_command, target, pid);\r
+#endif\r
+\r
+ if (command == WL_TBM_MONITOR_COMMAND_LIST) {\r
+ WL_TBM_DEBUG("================== app list =======================\n");\r
+ WL_TBM_DEBUG("no pid app_name\n");\r
+\r
+ if (!wl_list_empty(&tbm_srv->cresource_list)) {\r
+ wl_list_for_each_safe(c_res, tmp_res, &tbm_srv->cresource_list, link) {\r
+ /* skip the requestor (wayland-tbm-monitor */\r
+ if (c_res->resource == resource)\r
+ continue;\r
+\r
+ if (!c_res->app_name) {\r
+ c_res->app_name = (char *) calloc(1, 255 * sizeof(char));\r
+\r
+ _wayland_tbm_util_get_appname_from_pid(c_res->pid, c_res->app_name);\r
+ _wayland_tbm_util_get_appname_brief(c_res->app_name);\r
+ }\r
+\r
+ WL_TBM_DEBUG("%-3d%-5d%s\n", ++i, c_res->pid, c_res->app_name);\r
+ }\r
+ }\r
+\r
+ WL_TBM_DEBUG("======================================================\n");\r
+\r
+ return;\r
+ }\r
+\r
+ if (target == WL_TBM_MONITOR_TARGET_CLIENT) {\r
+ if (pid < 1) {\r
+ wl_resource_post_error(resource, WL_TBM_ERROR_INVALID_FORMAT, "invalid format");\r
+ return;\r
+ }\r
+ /* send the events to all client containing wl_tbm resource except for the wayland-tbm-monitor(requestor). */\r
+ if (!wl_list_empty(&tbm_srv->cresource_list)) {\r
+ wl_list_for_each_safe(c_res, tmp_res, &tbm_srv->cresource_list, link) {\r
+ /* skip the requestor (wayland-tbm-monitor */\r
+ if (c_res->resource == resource)\r
+ continue;\r
+\r
+ wl_tbm_send_monitor_client_tbm_bo(c_res->resource, command, trace_command,\r
+ target, pid);\r
+ }\r
+ }\r
+ } else if (target == WL_TBM_MONITOR_TARGET_SERVER) {\r
+ if (command == WL_TBM_MONITOR_COMMAND_SHOW) {\r
+ tbm_bufmgr_debug_show(tbm_srv->bufmgr);\r
+ } else if (command == WL_TBM_MONITOR_COMMAND_TRACE) {\r
+ WL_TBM_LOG("[%s]: TRACE NOT IMPLEMENTED.\n", __func__);\r
+ } else\r
+ wl_resource_post_error(resource, WL_TBM_ERROR_INVALID_FORMAT,\r
+ "invalid format");\r
+ } else if (target == WL_TBM_MONITOR_TARGET_ALL) {\r
+ if (command == WL_TBM_MONITOR_COMMAND_SHOW) {\r
+ /* send the events to all client containing wl_tbm resource except for the wayland-tbm-monitor(requestor). */\r
+ if (!wl_list_empty(&tbm_srv->cresource_list)) {\r
+ wl_list_for_each_safe(c_res, tmp_res, &tbm_srv->cresource_list, link) {\r
+ /* skip the requestor (wayland-tbm-monitor */\r
+ if (c_res->resource == resource)\r
+ continue;\r
+\r
+ wl_tbm_send_monitor_client_tbm_bo(c_res->resource, command, trace_command,\r
+ target, pid);\r
+ }\r
+ }\r
+ tbm_bufmgr_debug_show(tbm_srv->bufmgr);\r
+ } else if (command == WL_TBM_MONITOR_COMMAND_TRACE) {\r
+ wl_tbm_send_monitor_client_tbm_bo(resource, command, trace_command, target,\r
+ pid);\r
+ WL_TBM_LOG("[%s]: TRACE NOT IMPLEMENTED.\n", __func__);\r
+ } else\r
+ wl_resource_post_error(resource, WL_TBM_ERROR_INVALID_FORMAT,\r
+ "invalid format");\r
+ } else\r
+ wl_resource_post_error(resource, WL_TBM_ERROR_INVALID_FORMAT,\r
+ "invalid format");\r
+\r
+}\r
+\r
+\r
+static void\r
+_wayland_tbm_server_impl_create_buffer(struct wl_client *client,\r
+ struct wl_resource *wl_tbm,\r
+ uint32_t id,\r
+ int32_t width, int32_t height, uint32_t format, int32_t num_plane,\r
+ int32_t buf_idx0, int32_t offset0, int32_t stride0,\r
+ int32_t buf_idx1, int32_t offset1, int32_t stride1,\r
+ int32_t buf_idx2, int32_t offset2, int32_t stride2,\r
+ uint32_t flags,\r
+ int32_t num_buf, uint32_t buf0, uint32_t buf1, uint32_t buf2)\r
+{\r
+ struct wayland_tbm_server *tbm_srv = wl_resource_get_user_data(wl_tbm);\r
+ struct wayland_tbm_buffer *tbm_buffer = NULL;\r
+ tbm_surface_h surface = NULL;\r
+ tbm_surface_info_s info;\r
+ tbm_bo bos[TBM_SURF_PLANE_MAX];\r
+ int32_t names[TBM_SURF_PLANE_MAX] = { -1, -1, -1, -1};\r
+ int bpp;\r
+ int numPlane;\r
+ int i;\r
+\r
+#ifdef WL_TBM_SERVER_DEBUG\r
+ WL_TBM_LOG("[%s]: trying.\n", __func__);\r
+#endif\r
+\r
+ bpp = tbm_surface_internal_get_bpp(format);\r
+ numPlane = tbm_surface_internal_get_num_planes(format);\r
+ if (numPlane != num_plane) {\r
+ wl_resource_post_error(wl_tbm, WL_TBM_ERROR_INVALID_FORMAT,\r
+ "invalid format");\r
+ return;\r
+ }\r
+\r
+ memset(&info, 0x0, sizeof(tbm_surface_info_s));\r
+\r
+ info.width = width;\r
+ info.height = height;\r
+ info.format = format;\r
+ info.bpp = bpp;\r
+ info.num_planes = numPlane;\r
+\r
+ /*Fill plane info*/\r
+ if (numPlane > 0) {\r
+ info.planes[0].offset = offset0;\r
+ info.planes[0].stride = stride0;\r
+ numPlane--;\r
+ }\r
+\r
+ if (numPlane > 0) {\r
+ info.planes[1].offset = offset1;\r
+ info.planes[1].stride = stride1;\r
+ numPlane--;\r
+ }\r
+\r
+ if (numPlane > 0) {\r
+ info.planes[2].offset = offset2;\r
+ info.planes[2].stride = stride2;\r
+ numPlane--;\r
+ }\r
+\r
+ /*Fill buffer*/\r
+ names[0] = buf0;\r
+ names[1] = buf1;\r
+ names[2] = buf2;\r
+\r
+ for (i = 0; i < num_buf; i++) {\r
+ bos[i] = tbm_bo_import(tbm_srv->bufmgr, names[i]);\r
+ }\r
+\r
+ surface = tbm_surface_internal_create_with_bos(&info, bos, num_buf);\r
+ for (i = 0; i < num_buf; i++)\r
+ tbm_bo_unref(bos[i]);\r
+\r
+ tbm_buffer = _wayland_tbm_server_tbm_buffer_create(wl_tbm, client, surface, id, flags);\r
+ if (tbm_buffer == NULL) {\r
+ tbm_surface_destroy(surface);\r
+ wl_resource_post_no_memory(wl_tbm);\r
+ return;\r
+ }\r
+\r
+}\r
+\r
+static void\r
+_wayland_tbm_server_impl_create_buffer_with_fd(struct wl_client *client,\r
+ struct wl_resource *wl_tbm,\r
+ uint32_t id,\r
+ int32_t width, int32_t height, uint32_t format, int num_plane,\r
+ int32_t buf_idx0, int32_t offset0, int32_t stride0,\r
+ int32_t buf_idx1, int32_t offset1, int32_t stride1,\r
+ int32_t buf_idx2, int32_t offset2, int32_t stride2,\r
+ uint32_t flags,\r
+ int32_t num_buf, int32_t buf0, int32_t buf1, int32_t buf2)\r
+{\r
+ struct wayland_tbm_server *tbm_srv = wl_resource_get_user_data(wl_tbm);\r
+ struct wayland_tbm_buffer *tbm_buffer = NULL;\r
+ tbm_surface_h surface = NULL;\r
+ tbm_surface_info_s info;\r
+ tbm_bo bos[TBM_SURF_PLANE_MAX];\r
+ int32_t names[TBM_SURF_PLANE_MAX] = { -1, -1, -1, -1};\r
+ int bpp;\r
+ int numPlane;\r
+ int i;\r
+\r
+#ifdef WL_TBM_SERVER_DEBUG\r
+ WL_TBM_LOG("[%s]: trying.\n", __func__);\r
+#endif\r
+\r
+ bpp = tbm_surface_internal_get_bpp(format);\r
+ numPlane = tbm_surface_internal_get_num_planes(format);\r
+ if (numPlane != num_plane) {\r
+ wl_resource_post_error(wl_tbm, WL_TBM_ERROR_INVALID_FORMAT,\r
+ "invalid format");\r
+ return;\r
+ }\r
+\r
+ memset(&info, 0x0, sizeof(tbm_surface_info_s));\r
+\r
+ info.width = width;\r
+ info.height = height;\r
+ info.format = format;\r
+ info.bpp = bpp;\r
+ info.num_planes = numPlane;\r
+\r
+ /*Fill plane info*/\r
+ if (numPlane > 0) {\r
+ info.planes[0].offset = offset0;\r
+ info.planes[0].stride = stride0;\r
+ numPlane--;\r
+ }\r
+\r
+ if (numPlane > 0) {\r
+ info.planes[1].offset = offset1;\r
+ info.planes[1].stride = stride1;\r
+ numPlane--;\r
+ }\r
+\r
+ if (numPlane > 0) {\r
+ info.planes[2].offset = offset2;\r
+ info.planes[2].stride = stride2;\r
+ numPlane--;\r
+ }\r
+\r
+ /*Fill buffer*/\r
+ names[0] = buf0;\r
+ names[1] = buf1;\r
+ names[2] = buf2;\r
+\r
+ for (i = 0; i < num_buf; i++) {\r
+ bos[i] = tbm_bo_import_fd(tbm_srv->bufmgr, names[i]);\r
+ }\r
+\r
+ surface = tbm_surface_internal_create_with_bos(&info, bos, num_buf);\r
+ for (i = 0; i < num_buf; i++)\r
+ tbm_bo_unref(bos[i]);\r
+\r
+ tbm_buffer = _wayland_tbm_server_tbm_buffer_create(wl_tbm, client, surface, id, flags);\r
+ if (tbm_buffer == NULL) {\r
+ tbm_surface_destroy(surface);\r
+ wl_resource_post_no_memory(wl_tbm);\r
+ return;\r
+ }\r
+\r
+ close(buf0);\r
+ close(buf1);\r
+ close(buf2);\r
+}\r
+\r
+static void\r
+_wayland_tbm_server_impl_create_surface_queue(struct wl_client *client,\r
+ struct wl_resource *wl_tbm,\r
+ uint32_t surface_queue,\r
+ struct wl_resource *wl_surface)\r
+{\r
+ struct wayland_tbm_server *tbm_srv = wl_resource_get_user_data(wl_tbm);\r
+ struct wayland_tbm_client_queue *cqueue = NULL;\r
+\r
+ cqueue = calloc(1, sizeof(struct wayland_tbm_client_queue));\r
+ if (!cqueue) {\r
+ wl_resource_post_no_memory(wl_tbm);\r
+ return;\r
+ }\r
+\r
+ cqueue->wl_tbm = wl_tbm;\r
+ cqueue->wl_surface = wl_surface;\r
+ cqueue->wl_tbm_queue = wl_resource_create(client, &wl_tbm_queue_interface, 1,\r
+ surface_queue);\r
+ if (!cqueue->wl_tbm_queue) {\r
+ wl_resource_post_no_memory(wl_tbm);\r
+ free(cqueue);\r
+ return;\r
+ }\r
+\r
+ wl_resource_set_implementation(cqueue->wl_tbm_queue,\r
+ (void (* *)(void)) &_wayland_tbm_queue_impementation,\r
+ cqueue, _destroy_tbm_queue);\r
+\r
+ wl_list_init(&cqueue->link);\r
+\r
+ /* add a cqueue to the list */\r
+ wl_list_insert(&tbm_srv->cqueue_list, &cqueue->link);\r
+}\r
+\r
+static const struct wl_tbm_interface _wayland_tbm_server_implementation = {\r
+ _wayland_tbm_server_impl_create_buffer,\r
+ _wayland_tbm_server_impl_create_buffer_with_fd,\r
+ _wayland_tbm_server_impl_request_tbm_monitor,\r
+ _wayland_tbm_server_impl_create_surface_queue,\r
+};\r
+\r
+static void\r
+_wayland_tbm_server_destroy_resource(struct wl_resource *wl_tbm)\r
+{\r
+ struct wayland_tbm_server *tbm_srv = NULL;\r
+ struct wayland_tbm_client_resource *c_res = NULL, *tmp_res;\r
+\r
+ /* remove the client resources to the list */\r
+ tbm_srv = wl_resource_get_user_data(wl_tbm);\r
+ if (!wl_list_empty(&tbm_srv->cresource_list)) {\r
+ wl_list_for_each_safe(c_res, tmp_res, &tbm_srv->cresource_list, link) {\r
+ if (c_res->resource == wl_tbm) {\r
+#ifdef WL_TBM_SERVER_DEBUG\r
+ WL_TBM_LOG("[%s]: resource,%p pid,%d \n", __func__, c_res->resource,\r
+ c_res->pid);\r
+#endif\r
+ wl_list_remove(&c_res->link);\r
+ if (c_res->app_name)\r
+ free(c_res->app_name);\r
+ free(c_res);\r
+ break;\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+static void\r
+_wayland_tbm_server_bind_cb(struct wl_client *client, void *data,\r
+ uint32_t version,\r
+ uint32_t id)\r
+{\r
+ struct wayland_tbm_server *tbm_srv = NULL;\r
+ struct wayland_tbm_client_resource *c_res = NULL;\r
+ struct wl_resource *wl_tbm;\r
+\r
+ pid_t pid = 0;\r
+ uid_t uid = 0;\r
+ gid_t gid = 0;\r
+\r
+ wl_tbm = wl_resource_create(client, &wl_tbm_interface, MIN(version, 1), id);\r
+ if (!wl_tbm) {\r
+ wl_client_post_no_memory(client);\r
+ return;\r
+ }\r
+\r
+ wl_resource_set_implementation(wl_tbm,\r
+ &_wayland_tbm_server_implementation,\r
+ data,\r
+ _wayland_tbm_server_destroy_resource);\r
+\r
+ /* add the client resources to the list */\r
+ tbm_srv = wl_resource_get_user_data(wl_tbm);\r
+ wl_client_get_credentials(client, &pid, &uid, &gid);\r
+\r
+#ifdef WL_TBM_SERVER_DEBUG\r
+ WL_TBM_LOG("[%s]: resource,%p pid,%d \n", __func__, wl_tbm, pid);\r
+#endif\r
+\r
+ c_res = calloc (1, sizeof(struct wayland_tbm_client_resource));\r
+ c_res->pid = pid;\r
+ c_res->resource = wl_tbm;\r
+ wl_list_insert(&tbm_srv->cresource_list, &c_res->link);\r
+}\r
+\r
+struct wayland_tbm_server *\r
+wayland_tbm_server_init(struct wl_display *display, const char *device_name,\r
+ int fd,\r
+ uint32_t flags)\r
+{\r
+ struct wayland_tbm_server *tbm_srv;\r
+\r
+ tbm_srv = calloc(1, sizeof(struct wayland_tbm_server));\r
+ WL_TBM_RETURN_VAL_IF_FAIL(tbm_srv != NULL, NULL);\r
+\r
+ tbm_srv->display = display;\r
+\r
+ //init bufmgr\r
+ tbm_srv->bufmgr = tbm_bufmgr_init(-1);\r
+ if (!tbm_srv->bufmgr) {\r
+ free(tbm_srv);\r
+ return NULL;\r
+ }\r
+\r
+ if (!getenv("WL_TBM_EMBEDDED_SERVER")) {\r
+ WL_TBM_S_LOG("Bind start\n");\r
+ tbm_bufmgr_bind_native_display(tbm_srv->bufmgr, (void *)display);\r
+ }\r
+ tbm_srv->wl_tbm_global = wl_global_create(display, &wl_tbm_interface, 1,\r
+ tbm_srv, _wayland_tbm_server_bind_cb);\r
+\r
+\r
+ //init wayland_tbm_client_queue\r
+ wl_list_init(&tbm_srv->cqueue_list);\r
+\r
+ /* init the client resource list */\r
+ wl_list_init(&tbm_srv->cresource_list);\r
+\r
+\r
+ return tbm_srv;\r
+}\r
+\r
+void\r
+wayland_tbm_server_deinit(struct wayland_tbm_server *tbm_srv)\r
+{\r
+ WL_TBM_RETURN_IF_FAIL(tbm_srv != NULL);\r
+\r
+ wl_global_destroy(tbm_srv->wl_tbm_global);\r
+\r
+ tbm_bufmgr_deinit(tbm_srv->bufmgr);\r
+\r
+ free(tbm_srv);\r
+}\r
+\r
+tbm_surface_h\r
+wayland_tbm_server_get_surface(struct wayland_tbm_server *tbm_srv,\r
+ struct wl_resource *wl_buffer)\r
+{\r
+ struct wayland_tbm_buffer *tbm_buffer = NULL;\r
+\r
+// WL_TBM_RETURN_VAL_IF_FAIL(tbm_srv != NULL, NULL);\r
+ WL_TBM_RETURN_VAL_IF_FAIL(wl_buffer != NULL, NULL);\r
+\r
+ if (wl_resource_instance_of(wl_buffer, &wl_buffer_interface,\r
+ &_wayland_tbm_buffer_impementation)) {\r
+ tbm_buffer = wl_resource_get_user_data(wl_buffer);\r
+ return tbm_buffer->surface;\r
+ }\r
+\r
+ return NULL;\r
+}\r
+\r
+void *\r
+wayland_tbm_server_get_bufmgr(struct wayland_tbm_server *tbm_srv)\r
+{\r
+ WL_TBM_RETURN_VAL_IF_FAIL(tbm_srv != NULL, NULL);\r
+\r
+ return (void *)tbm_srv->bufmgr;\r
+}\r
+\r
+uint32_t\r
+wayland_tbm_server_get_buffer_flags(struct wayland_tbm_server *tbm_srv,\r
+ struct wl_resource *wl_buffer)\r
+{\r
+ struct wayland_tbm_buffer *tbm_buffer = NULL;\r
+\r
+ WL_TBM_RETURN_VAL_IF_FAIL(wl_buffer != NULL, 0);\r
+\r
+ if (wl_resource_instance_of(wl_buffer, &wl_buffer_interface,\r
+ &_wayland_tbm_buffer_impementation)) {\r
+ tbm_buffer = wl_resource_get_user_data(wl_buffer);\r
+ return tbm_buffer->flags;\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+struct wayland_tbm_client_queue *\r
+wayland_tbm_server_client_queue_get(struct wayland_tbm_server *tbm_srv, struct wl_resource *wl_surface)\r
+{\r
+ struct wayland_tbm_client_queue *cqueue = NULL;\r
+ WL_TBM_RETURN_VAL_IF_FAIL(tbm_srv != NULL, NULL);\r
+ WL_TBM_RETURN_VAL_IF_FAIL(wl_surface != NULL, NULL);\r
+\r
+ wl_list_for_each(cqueue, &tbm_srv->cqueue_list, link) {\r
+ if (cqueue && cqueue->wl_surface == wl_surface)\r
+ return cqueue;\r
+ }\r
+\r
+ return NULL;\r
+}\r
+\r
+void\r
+wayland_tbm_server_client_queue_activate(struct wayland_tbm_client_queue *cqueue, uint32_t usage)\r
+{\r
+ WL_TBM_RETURN_IF_FAIL(cqueue != NULL);\r
+ WL_TBM_RETURN_IF_FAIL(cqueue->wl_tbm_queue != NULL);\r
+\r
+ wl_tbm_queue_send_active(cqueue->wl_tbm_queue, usage);\r
+}\r
+\r
+void\r
+wayland_tbm_server_client_queue_deactivate(struct wayland_tbm_client_queue *cqueue)\r
+{\r
+ WL_TBM_RETURN_IF_FAIL(cqueue != NULL);\r
+ WL_TBM_RETURN_IF_FAIL(cqueue->wl_tbm_queue != NULL);\r
+\r
+ wl_tbm_queue_send_deactive(cqueue->wl_tbm_queue);\r
+}\r
+\r
+\r
+int\r
+_wayland_tbm_server_wl_tbm_queue_send_surface(struct wl_resource *wl_tbm_queue,\r
+ struct wl_resource *wl_buffer, tbm_surface_h surface,\r
+ uint32_t flags)\r
+{\r
+ tbm_surface_info_s info;\r
+ int num_buf;\r
+ int bufs[TBM_SURF_PLANE_MAX] = { -1, -1, -1, -1};\r
+ int is_fd = -1;\r
+ int ret = -1, i;\r
+\r
+ ret = tbm_surface_get_info(surface, &info);\r
+ if (ret != TBM_SURFACE_ERROR_NONE) {\r
+ WL_TBM_S_LOG("Failed to create buffer from surface\n");\r
+ return 0;\r
+ }\r
+\r
+ if (info.num_planes > 3) {\r
+ WL_TBM_S_LOG("invalid num_planes(%d)\n", info.num_planes);\r
+ return 0;\r
+ }\r
+\r
+ num_buf = tbm_surface_internal_get_num_bos(surface);\r
+ if (num_buf == 0) {\r
+ WL_TBM_S_LOG("surface doesn't have any bo.\n");\r
+ goto err;\r
+ }\r
+\r
+ for (i = 0; i < num_buf; i++) {\r
+ tbm_bo bo = tbm_surface_internal_get_bo(surface, i);\r
+ if (bo == NULL) {\r
+ goto err;\r
+ }\r
+\r
+ /* try to get fd first */\r
+ if (is_fd == -1 || is_fd == 1) {\r
+ bufs[i] = tbm_bo_export_fd(bo);\r
+ if (bufs[i] >= 0)\r
+ is_fd = 1;\r
+ }\r
+\r
+ /* if fail to get fd, try to get name second */\r
+ if (is_fd == -1 || is_fd == 0) {\r
+ bufs[i] = tbm_bo_export(bo);\r
+ if (bufs[i] > 0)\r
+ is_fd = 0;\r
+ }\r
+\r
+ if (is_fd == -1 ||\r
+ (is_fd == 1 && bufs[i] < 0) ||\r
+ (is_fd == 0 && bufs[i] <= 0)) {\r
+ WL_TBM_S_LOG("Failed to export(is_fd:%d, bufs:%d)\n", is_fd, bufs[i]);\r
+ goto err;\r
+ }\r
+ }\r
+\r
+ if (is_fd == 1)\r
+ wl_tbm_queue_send_buffer_attached_with_fd(wl_tbm_queue,\r
+ wl_buffer,\r
+ info.width, info.height, info.format, info.num_planes,\r
+ tbm_surface_internal_get_plane_bo_idx(surface, 0),\r
+ info.planes[0].offset, info.planes[0].stride,\r
+ tbm_surface_internal_get_plane_bo_idx(surface, 1),\r
+ info.planes[1].offset, info.planes[1].stride,\r
+ tbm_surface_internal_get_plane_bo_idx(surface, 2),\r
+ info.planes[2].offset, info.planes[2].stride,\r
+ flags, num_buf, bufs[0],\r
+ (bufs[1] == -1) ? bufs[0] : bufs[1],\r
+ (bufs[2] == -1) ? bufs[0] : bufs[2]);\r
+ else\r
+ wl_tbm_queue_send_buffer_attached_with_fd(wl_tbm_queue,\r
+ wl_buffer,\r
+ info.width, info.height, info.format, info.num_planes,\r
+ tbm_surface_internal_get_plane_bo_idx(surface, 0),\r
+ info.planes[0].offset, info.planes[0].stride,\r
+ tbm_surface_internal_get_plane_bo_idx(surface, 1),\r
+ info.planes[1].offset, info.planes[1].stride,\r
+ tbm_surface_internal_get_plane_bo_idx(surface, 2),\r
+ info.planes[2].offset, info.planes[2].stride,\r
+ flags, num_buf, bufs[0],\r
+ (bufs[1] == -1) ? bufs[0] : bufs[1],\r
+ (bufs[2] == -1) ? bufs[0] : bufs[2]);\r
+\r
+\r
+ for (i = 0; i < TBM_SURF_PLANE_MAX; i++) {\r
+ if (is_fd == 1 && (bufs[i] >= 0))\r
+ close(bufs[i]);\r
+ }\r
+\r
+ WL_TBM_S_LOG("Release wl_tbm_queue tbm_surface(%p).\n", surface);\r
+\r
+ return 1;\r
+err:\r
+ for (i = 0; i < TBM_SURF_PLANE_MAX; i++) {\r
+ if (is_fd == 1 && (bufs[i] >= 0))\r
+ close(bufs[i]);\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+int\r
+wayland_tbm_server_client_queue_export_buffer(struct wayland_tbm_client_queue *cqueue,\r
+ tbm_surface_h surface, uint32_t flags,\r
+ wayland_tbm_server_surface_destroy_cb destroy_cb, void *user_data)\r
+{\r
+ struct wl_resource *wl_tbm = NULL;\r
+ struct wayland_tbm_buffer *tbm_buffer = NULL;\r
+ struct wl_client *client = NULL;\r
+ void *data = NULL;\r
+\r
+ WL_TBM_RETURN_VAL_IF_FAIL(cqueue != NULL, 0);\r
+ WL_TBM_RETURN_VAL_IF_FAIL(cqueue->wl_tbm_queue != NULL, 0);\r
+ WL_TBM_RETURN_VAL_IF_FAIL(surface != NULL, 0);\r
+\r
+ /* return if the surface is already exported to the client on the cqueue */\r
+ tbm_surface_internal_get_user_data(surface, KEY_TBM_BUFFER, &data);\r
+ if (data != NULL) {\r
+ WL_TBM_S_LOG("WARNING...surface(%p) is already export\n", surface);\r
+ return 0;\r
+ }\r
+\r
+ wl_tbm = cqueue->wl_tbm;\r
+ client = wl_resource_get_client(cqueue->wl_tbm_queue);\r
+\r
+ tbm_surface_internal_ref(surface);\r
+ tbm_buffer = _wayland_tbm_server_tbm_buffer_create(wl_tbm, client, surface, 0, flags);\r
+ if (tbm_buffer == NULL) {\r
+ tbm_surface_internal_unref(surface);\r
+ return 0;\r
+ }\r
+\r
+ tbm_buffer->destroy_cb = destroy_cb;\r
+ tbm_buffer->user_data = user_data;\r
+\r
+ if(!_wayland_tbm_server_wl_tbm_queue_send_surface(cqueue->wl_tbm_queue,\r
+ tbm_buffer->wl_buffer, surface, flags)) {\r
+ WL_TBM_S_LOG("Failed to send the surface to the wl_tbm_queue\n");\r
+ _wayland_tbm_server_tbm_buffer_destroy(tbm_buffer);\r
+ tbm_surface_internal_unref(surface);\r
+ return 0;\r
+ }\r
+\r
+ return 1;\r
+}\r
+\r