Subversion Repositories Kolibri OS

Rev

Rev 4358 | 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.         struct wl_buffer_interface buffer_interface;
  49. };
  50.  
  51. static void
  52. destroy_buffer(struct wl_resource *resource)
  53. {
  54.         struct wl_drm_buffer *buffer = resource->data;
  55.         struct wl_drm *drm = buffer->drm;
  56.  
  57.         drm->callbacks->release_buffer(drm->user_data, buffer);
  58.         free(buffer);
  59. }
  60.  
  61. static void
  62. buffer_destroy(struct wl_client *client, struct wl_resource *resource)
  63. {
  64.         wl_resource_destroy(resource);
  65. }
  66.  
  67. static void
  68. create_buffer(struct wl_client *client, struct wl_resource *resource,
  69.               uint32_t id, uint32_t name, int fd,
  70.               int32_t width, int32_t height,
  71.               uint32_t format,
  72.               int32_t offset0, int32_t stride0,
  73.               int32_t offset1, int32_t stride1,
  74.               int32_t offset2, int32_t stride2)
  75. {
  76.         struct wl_drm *drm = resource->data;
  77.         struct wl_drm_buffer *buffer;
  78.  
  79.         buffer = calloc(1, sizeof *buffer);
  80.         if (buffer == NULL) {
  81.                 wl_resource_post_no_memory(resource);
  82.                 return;
  83.         }
  84.  
  85.         buffer->drm = drm;
  86.         buffer->buffer.width = width;
  87.         buffer->buffer.height = height;
  88.         buffer->format = format;
  89.         buffer->offset[0] = offset0;
  90.         buffer->stride[0] = stride0;
  91.         buffer->offset[1] = offset1;
  92.         buffer->stride[1] = stride1;
  93.         buffer->offset[2] = offset2;
  94.         buffer->stride[2] = stride2;
  95.  
  96.         drm->callbacks->reference_buffer(drm->user_data, name, fd, buffer);
  97.         if (buffer->driver_buffer == NULL) {
  98.                 wl_resource_post_error(resource,
  99.                                        WL_DRM_ERROR_INVALID_NAME,
  100.                                        "invalid name");
  101.                 return;
  102.         }
  103.  
  104.         buffer->buffer.resource.object.id = id;
  105.         buffer->buffer.resource.object.interface = &wl_buffer_interface;
  106.         buffer->buffer.resource.object.implementation =
  107.                 (void (**)(void)) &drm->buffer_interface;
  108.         buffer->buffer.resource.data = buffer;
  109.  
  110.         buffer->buffer.resource.destroy = destroy_buffer;
  111.         buffer->buffer.resource.client = resource->client;
  112.  
  113.         wl_client_add_resource(resource->client, &buffer->buffer.resource);
  114. }
  115.  
  116. static void
  117. drm_create_buffer(struct wl_client *client, struct wl_resource *resource,
  118.                   uint32_t id, uint32_t name, int32_t width, int32_t height,
  119.                   uint32_t stride, uint32_t format)
  120. {
  121.         switch (format) {
  122.         case WL_DRM_FORMAT_ARGB8888:
  123.         case WL_DRM_FORMAT_XRGB8888:
  124.         case WL_DRM_FORMAT_YUYV:
  125.                 break;
  126.         default:
  127.                 wl_resource_post_error(resource,
  128.                                        WL_DRM_ERROR_INVALID_FORMAT,
  129.                                        "invalid format");
  130.            return;
  131.         }
  132.  
  133.         create_buffer(client, resource, id,
  134.                       name, -1, width, height, format, 0, stride, 0, 0, 0, 0);
  135. }
  136.  
  137. static void
  138. drm_create_planar_buffer(struct wl_client *client,
  139.                          struct wl_resource *resource,
  140.                          uint32_t id, uint32_t name,
  141.                          int32_t width, int32_t height, uint32_t format,
  142.                          int32_t offset0, int32_t stride0,
  143.                          int32_t offset1, int32_t stride1,
  144.                          int32_t offset2, int32_t stride2)
  145. {
  146.         switch (format) {
  147.         case WL_DRM_FORMAT_YUV410:
  148.         case WL_DRM_FORMAT_YUV411:
  149.         case WL_DRM_FORMAT_YUV420:
  150.         case WL_DRM_FORMAT_YUV422:
  151.         case WL_DRM_FORMAT_YUV444:
  152.         case WL_DRM_FORMAT_NV12:
  153.         case WL_DRM_FORMAT_NV16:
  154.                 break;
  155.         default:
  156.                 wl_resource_post_error(resource,
  157.                                        WL_DRM_ERROR_INVALID_FORMAT,
  158.                                        "invalid format");
  159.            return;
  160.         }
  161.  
  162.         create_buffer(client, resource, id, name, -1, width, height, format,
  163.                       offset0, stride0, offset1, stride1, offset2, stride2);
  164. }
  165.  
  166. static void
  167. drm_create_prime_buffer(struct wl_client *client,
  168.                         struct wl_resource *resource,
  169.                         uint32_t id, int fd,
  170.                         int32_t width, int32_t height, uint32_t format,
  171.                         int32_t offset0, int32_t stride0,
  172.                         int32_t offset1, int32_t stride1,
  173.                         int32_t offset2, int32_t stride2)
  174. {
  175.         create_buffer(client, resource, id, 0, fd, width, height, format,
  176.                       offset0, stride0, offset1, stride1, offset2, stride2);
  177.         close(fd);
  178. }
  179.  
  180. static void
  181. drm_authenticate(struct wl_client *client,
  182.                  struct wl_resource *resource, uint32_t id)
  183. {
  184.         struct wl_drm *drm = resource->data;
  185.  
  186.         if (drm->callbacks->authenticate(drm->user_data, id) < 0)
  187.                 wl_resource_post_error(resource,
  188.                                        WL_DRM_ERROR_AUTHENTICATE_FAIL,
  189.                                        "authenicate failed");
  190.         else
  191.                 wl_resource_post_event(resource, WL_DRM_AUTHENTICATED);
  192. }
  193.  
  194. const static struct wl_drm_interface drm_interface = {
  195.         drm_authenticate,
  196.         drm_create_buffer,
  197.         drm_create_planar_buffer,
  198.         drm_create_prime_buffer
  199. };
  200.  
  201. static void
  202. bind_drm(struct wl_client *client, void *data, uint32_t version, uint32_t id)
  203. {
  204.         struct wl_drm *drm = data;
  205.         struct wl_resource *resource;
  206.         uint32_t capabilities;
  207.  
  208.         resource = wl_client_add_object(client, &wl_drm_interface,
  209.                                         &drm_interface, id, data);
  210.         wl_resource_post_event(resource, WL_DRM_DEVICE, drm->device_name);
  211.         wl_resource_post_event(resource, WL_DRM_FORMAT,
  212.                                WL_DRM_FORMAT_ARGB8888);
  213.         wl_resource_post_event(resource, WL_DRM_FORMAT,
  214.                                WL_DRM_FORMAT_XRGB8888);
  215.         wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_YUV410);
  216.         wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_YUV411);
  217.         wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_YUV420);
  218.         wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_YUV422);
  219.         wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_YUV444);
  220.         wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_NV12);
  221.         wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_NV16);
  222.         wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_YUYV);
  223.  
  224.         capabilities = 0;
  225.         if (drm->flags & WAYLAND_DRM_PRIME)
  226.            capabilities |= WL_DRM_CAPABILITY_PRIME;
  227.  
  228.         if (version >= 2)
  229.            wl_resource_post_event(resource, WL_DRM_CAPABILITIES, capabilities);
  230. }
  231.  
  232. struct wl_drm *
  233. wayland_drm_init(struct wl_display *display, char *device_name,
  234.                  struct wayland_drm_callbacks *callbacks, void *user_data,
  235.                  uint32_t flags)
  236. {
  237.         struct wl_drm *drm;
  238.  
  239.         drm = malloc(sizeof *drm);
  240.  
  241.         drm->display = display;
  242.         drm->device_name = strdup(device_name);
  243.         drm->callbacks = callbacks;
  244.         drm->user_data = user_data;
  245.         drm->flags = flags;
  246.         drm->buffer_interface.destroy = buffer_destroy;
  247.  
  248.         wl_display_add_global(display, &wl_drm_interface, drm, bind_drm);
  249.  
  250.         return drm;
  251. }
  252.  
  253. void
  254. wayland_drm_uninit(struct wl_drm *drm)
  255. {
  256.         free(drm->device_name);
  257.  
  258.         /* FIXME: need wl_display_del_{object,global} */
  259.  
  260.         free(drm);
  261. }
  262.  
  263. int
  264. wayland_buffer_is_drm(struct wl_drm *drm, struct wl_buffer *buffer)
  265. {
  266.         return buffer->resource.object.implementation ==
  267.                 (void (**)(void)) &drm->buffer_interface;
  268. }
  269.  
  270. uint32_t
  271. wayland_drm_buffer_get_format(struct wl_buffer *buffer_base)
  272. {
  273.         struct wl_drm_buffer *buffer = (struct wl_drm_buffer *) buffer_base;
  274.  
  275.         return buffer->format;
  276. }
  277.  
  278. void *
  279. wayland_drm_buffer_get_buffer(struct wl_buffer *buffer_base)
  280. {
  281.         struct wl_drm_buffer *buffer = (struct wl_drm_buffer *) buffer_base;
  282.  
  283.         return buffer->driver_buffer;
  284. }
  285.