Subversion Repositories Kolibri OS

Rev

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