Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright © 2011 Kristian Høgsberg
  3.  * Copyright © 2011 Benjamin Franzke
  4.  *
  5.  * Permission is hereby granted, free of charge, to any person obtaining a
  6.  * copy of this software and associated documentation files (the "Software"),
  7.  * to deal in the Software without restriction, including without limitation
  8.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  9.  * and/or sell copies of the Software, and to permit persons to whom the
  10.  * Software is furnished to do so, subject to the following conditions:
  11.  *
  12.  * The above copyright notice and this permission notice (including the next
  13.  * paragraph) shall be included in all copies or substantial portions of the
  14.  * Software.
  15.  *
  16.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  17.  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  18.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  19.  * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  20.  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  21.  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22.  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  23.  * DEALINGS IN THE SOFTWARE.
  24.  *
  25.  * Authors:
  26.  *    Kristian Høgsberg <krh@bitplanet.net>
  27.  *    Benjamin Franzke <benjaminfranzke@googlemail.com>
  28.  */
  29.  
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <string.h>
  33. #include <stddef.h>
  34. #include <unistd.h>
  35.  
  36. #include <wayland-server.h>
  37. #include "wayland-drm.h"
  38. #include "wayland-drm-server-protocol.h"
  39.  
  40. struct wl_drm {
  41.         struct wl_display *display;
  42.  
  43.         void *user_data;
  44.         char *device_name;
  45.         uint32_t flags;
  46.  
  47.         struct wayland_drm_callbacks *callbacks;
  48. };
  49.  
  50. static void
  51. destroy_buffer(struct wl_resource *resource)
  52. {
  53.         struct wl_drm_buffer *buffer = resource->data;
  54.         struct wl_drm *drm = buffer->drm;
  55.  
  56.         drm->callbacks->release_buffer(drm->user_data, buffer);
  57.         free(buffer);
  58. }
  59.  
  60. static void
  61. buffer_destroy(struct wl_client *client, struct wl_resource *resource)
  62. {
  63.         wl_resource_destroy(resource);
  64. }
  65.  
  66. const static struct wl_buffer_interface drm_buffer_interface = {
  67.         buffer_destroy
  68. };
  69.  
  70. static void
  71. create_buffer(struct wl_client *client, struct wl_resource *resource,
  72.               uint32_t id, uint32_t name, int fd,
  73.               int32_t width, int32_t height,
  74.               uint32_t format,
  75.               int32_t offset0, int32_t stride0,
  76.               int32_t offset1, int32_t stride1,
  77.               int32_t offset2, int32_t stride2)
  78. {
  79.         struct wl_drm *drm = resource->data;
  80.         struct wl_drm_buffer *buffer;
  81.  
  82.         buffer = calloc(1, sizeof *buffer);
  83.         if (buffer == NULL) {
  84.                 wl_resource_post_no_memory(resource);
  85.                 return;
  86.         }
  87.  
  88.         buffer->drm = drm;
  89.         buffer->buffer.width = width;
  90.         buffer->buffer.height = height;
  91.         buffer->format = format;
  92.         buffer->offset[0] = offset0;
  93.         buffer->stride[0] = stride0;
  94.         buffer->offset[1] = offset1;
  95.         buffer->stride[1] = stride1;
  96.         buffer->offset[2] = offset2;
  97.         buffer->stride[2] = stride2;
  98.  
  99.         drm->callbacks->reference_buffer(drm->user_data, name, fd, buffer);
  100.         if (buffer->driver_buffer == NULL) {
  101.                 wl_resource_post_error(resource,
  102.                                        WL_DRM_ERROR_INVALID_NAME,
  103.                                        "invalid name");
  104.                 return;
  105.         }
  106.  
  107.         buffer->buffer.resource.object.id = id;
  108.         buffer->buffer.resource.object.interface = &wl_buffer_interface;
  109.         buffer->buffer.resource.object.implementation =
  110.                 (void (**)(void)) &drm_buffer_interface;
  111.         buffer->buffer.resource.data = buffer;
  112.  
  113.         buffer->buffer.resource.destroy = destroy_buffer;
  114.         buffer->buffer.resource.client = resource->client;
  115.  
  116.         wl_client_add_resource(resource->client, &buffer->buffer.resource);
  117. }
  118.  
  119. static void
  120. drm_create_buffer(struct wl_client *client, struct wl_resource *resource,
  121.                   uint32_t id, uint32_t name, int32_t width, int32_t height,
  122.                   uint32_t stride, uint32_t format)
  123. {
  124.         switch (format) {
  125.         case WL_DRM_FORMAT_ARGB8888:
  126.         case WL_DRM_FORMAT_XRGB8888:
  127.         case WL_DRM_FORMAT_YUYV:
  128.                 break;
  129.         default:
  130.                 wl_resource_post_error(resource,
  131.                                        WL_DRM_ERROR_INVALID_FORMAT,
  132.                                        "invalid format");
  133.            return;
  134.         }
  135.  
  136.         create_buffer(client, resource, id,
  137.                       name, -1, width, height, format, 0, stride, 0, 0, 0, 0);
  138. }
  139.  
  140. static void
  141. drm_create_planar_buffer(struct wl_client *client,
  142.                          struct wl_resource *resource,
  143.                          uint32_t id, uint32_t name,
  144.                          int32_t width, int32_t height, uint32_t format,
  145.                          int32_t offset0, int32_t stride0,
  146.                          int32_t offset1, int32_t stride1,
  147.                          int32_t offset2, int32_t stride2)
  148. {
  149.         switch (format) {
  150.         case WL_DRM_FORMAT_YUV410:
  151.         case WL_DRM_FORMAT_YUV411:
  152.         case WL_DRM_FORMAT_YUV420:
  153.         case WL_DRM_FORMAT_YUV422:
  154.         case WL_DRM_FORMAT_YUV444:
  155.         case WL_DRM_FORMAT_NV12:
  156.         case WL_DRM_FORMAT_NV16:
  157.                 break;
  158.         default:
  159.                 wl_resource_post_error(resource,
  160.                                        WL_DRM_ERROR_INVALID_FORMAT,
  161.                                        "invalid format");
  162.            return;
  163.         }
  164.  
  165.         create_buffer(client, resource, id, name, -1, width, height, format,
  166.                       offset0, stride0, offset1, stride1, offset2, stride2);
  167. }
  168.  
  169. static void
  170. drm_create_prime_buffer(struct wl_client *client,
  171.                         struct wl_resource *resource,
  172.                         uint32_t id, int fd,
  173.                         int32_t width, int32_t height, uint32_t format,
  174.                         int32_t offset0, int32_t stride0,
  175.                         int32_t offset1, int32_t stride1,
  176.                         int32_t offset2, int32_t stride2)
  177. {
  178.         create_buffer(client, resource, id, 0, fd, width, height, format,
  179.                       offset0, stride0, offset1, stride1, offset2, stride2);
  180.         close(fd);
  181. }
  182.  
  183. static void
  184. drm_authenticate(struct wl_client *client,
  185.                  struct wl_resource *resource, uint32_t id)
  186. {
  187.         struct wl_drm *drm = resource->data;
  188.  
  189.         if (drm->callbacks->authenticate(drm->user_data, id) < 0)
  190.                 wl_resource_post_error(resource,
  191.                                        WL_DRM_ERROR_AUTHENTICATE_FAIL,
  192.                                        "authenicate failed");
  193.         else
  194.                 wl_resource_post_event(resource, WL_DRM_AUTHENTICATED);
  195. }
  196.  
  197. const static struct wl_drm_interface drm_interface = {
  198.         drm_authenticate,
  199.         drm_create_buffer,
  200.         drm_create_planar_buffer,
  201.         drm_create_prime_buffer
  202. };
  203.  
  204. static void
  205. bind_drm(struct wl_client *client, void *data, uint32_t version, uint32_t id)
  206. {
  207.         struct wl_drm *drm = data;
  208.         struct wl_resource *resource;
  209.         uint32_t capabilities;
  210.  
  211.         resource = wl_client_add_object(client, &wl_drm_interface,
  212.                                         &drm_interface, id, data);
  213.         wl_resource_post_event(resource, WL_DRM_DEVICE, drm->device_name);
  214.         wl_resource_post_event(resource, WL_DRM_FORMAT,
  215.                                WL_DRM_FORMAT_ARGB8888);
  216.         wl_resource_post_event(resource, WL_DRM_FORMAT,
  217.                                WL_DRM_FORMAT_XRGB8888);
  218.         wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_YUV410);
  219.         wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_YUV411);
  220.         wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_YUV420);
  221.         wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_YUV422);
  222.         wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_YUV444);
  223.         wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_NV12);
  224.         wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_NV16);
  225.         wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_YUYV);
  226.  
  227.         capabilities = 0;
  228.         if (drm->flags & WAYLAND_DRM_PRIME)
  229.            capabilities |= WL_DRM_CAPABILITY_PRIME;
  230.  
  231.         if (version >= 2)
  232.            wl_resource_post_event(resource, WL_DRM_CAPABILITIES, capabilities);
  233. }
  234.  
  235. struct wl_drm *
  236. wayland_drm_init(struct wl_display *display, char *device_name,
  237.                  struct wayland_drm_callbacks *callbacks, void *user_data,
  238.                  uint32_t flags)
  239. {
  240.         struct wl_drm *drm;
  241.  
  242.         drm = malloc(sizeof *drm);
  243.  
  244.         drm->display = display;
  245.         drm->device_name = strdup(device_name);
  246.         drm->callbacks = callbacks;
  247.         drm->user_data = user_data;
  248.         drm->flags = flags;
  249.  
  250.         wl_display_add_global(display, &wl_drm_interface, drm, bind_drm);
  251.  
  252.         return drm;
  253. }
  254.  
  255. void
  256. wayland_drm_uninit(struct wl_drm *drm)
  257. {
  258.         free(drm->device_name);
  259.  
  260.         /* FIXME: need wl_display_del_{object,global} */
  261.  
  262.         free(drm);
  263. }
  264.  
  265. int
  266. wayland_buffer_is_drm(struct wl_buffer *buffer)
  267. {
  268.         return buffer->resource.object.implementation ==
  269.                 (void (**)(void)) &drm_buffer_interface;
  270. }
  271.  
  272. uint32_t
  273. wayland_drm_buffer_get_format(struct wl_buffer *buffer_base)
  274. {
  275.         struct wl_drm_buffer *buffer = (struct wl_drm_buffer *) buffer_base;
  276.  
  277.         return buffer->format;
  278. }
  279.  
  280. void *
  281. wayland_drm_buffer_get_buffer(struct wl_buffer *buffer_base)
  282. {
  283.         struct wl_drm_buffer *buffer = (struct wl_drm_buffer *) buffer_base;
  284.  
  285.         return buffer->driver_buffer;
  286. }
  287.