1848b8605Smrg/* 2848b8605Smrg * Copyright © 2011 Kristian Høgsberg 3848b8605Smrg * Copyright © 2011 Benjamin Franzke 4848b8605Smrg * 5848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 6848b8605Smrg * copy of this software and associated documentation files (the "Software"), 7848b8605Smrg * to deal in the Software without restriction, including without limitation 8848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 10848b8605Smrg * Software is furnished to do so, subject to the following conditions: 11848b8605Smrg * 12848b8605Smrg * The above copyright notice and this permission notice (including the next 13848b8605Smrg * paragraph) shall be included in all copies or substantial portions of the 14848b8605Smrg * Software. 15848b8605Smrg * 16848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17848b8605Smrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18848b8605Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19848b8605Smrg * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 20848b8605Smrg * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21848b8605Smrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22848b8605Smrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23848b8605Smrg * DEALINGS IN THE SOFTWARE. 24848b8605Smrg * 25848b8605Smrg * Authors: 26848b8605Smrg * Kristian Høgsberg <krh@bitplanet.net> 27848b8605Smrg * Benjamin Franzke <benjaminfranzke@googlemail.com> 28848b8605Smrg */ 29848b8605Smrg 30848b8605Smrg#include <stdio.h> 31848b8605Smrg#include <stdlib.h> 32848b8605Smrg#include <string.h> 33848b8605Smrg#include <stddef.h> 34848b8605Smrg#include <unistd.h> 35848b8605Smrg 36848b8605Smrg#include <wayland-server.h> 37848b8605Smrg#include "wayland-drm.h" 38848b8605Smrg#include "wayland-drm-server-protocol.h" 39848b8605Smrg 40848b8605Smrg#define MIN(x,y) (((x)<(y))?(x):(y)) 41848b8605Smrg 42848b8605Smrgstatic void 43848b8605Smrgdestroy_buffer(struct wl_resource *resource) 44848b8605Smrg{ 45b8e80941Smrg struct wl_drm_buffer *buffer = wl_resource_get_user_data(resource); 46848b8605Smrg struct wl_drm *drm = buffer->drm; 47848b8605Smrg 48b8e80941Smrg drm->callbacks.release_buffer(drm->user_data, buffer); 49848b8605Smrg free(buffer); 50848b8605Smrg} 51848b8605Smrg 52848b8605Smrgstatic void 53848b8605Smrgbuffer_destroy(struct wl_client *client, struct wl_resource *resource) 54848b8605Smrg{ 55848b8605Smrg wl_resource_destroy(resource); 56848b8605Smrg} 57848b8605Smrg 58848b8605Smrgstatic void 59848b8605Smrgcreate_buffer(struct wl_client *client, struct wl_resource *resource, 60848b8605Smrg uint32_t id, uint32_t name, int fd, 61848b8605Smrg int32_t width, int32_t height, 62848b8605Smrg uint32_t format, 63848b8605Smrg int32_t offset0, int32_t stride0, 64848b8605Smrg int32_t offset1, int32_t stride1, 65848b8605Smrg int32_t offset2, int32_t stride2) 66848b8605Smrg{ 67b8e80941Smrg struct wl_drm *drm = wl_resource_get_user_data(resource); 68848b8605Smrg struct wl_drm_buffer *buffer; 69848b8605Smrg 70848b8605Smrg buffer = calloc(1, sizeof *buffer); 71848b8605Smrg if (buffer == NULL) { 72848b8605Smrg wl_resource_post_no_memory(resource); 73848b8605Smrg return; 74848b8605Smrg } 75848b8605Smrg 76848b8605Smrg buffer->drm = drm; 77848b8605Smrg buffer->width = width; 78848b8605Smrg buffer->height = height; 79848b8605Smrg buffer->format = format; 80848b8605Smrg buffer->offset[0] = offset0; 81848b8605Smrg buffer->stride[0] = stride0; 82848b8605Smrg buffer->offset[1] = offset1; 83848b8605Smrg buffer->stride[1] = stride1; 84848b8605Smrg buffer->offset[2] = offset2; 85848b8605Smrg buffer->stride[2] = stride2; 86848b8605Smrg 87b8e80941Smrg drm->callbacks.reference_buffer(drm->user_data, name, fd, buffer); 88848b8605Smrg if (buffer->driver_buffer == NULL) { 89848b8605Smrg wl_resource_post_error(resource, 90848b8605Smrg WL_DRM_ERROR_INVALID_NAME, 91848b8605Smrg "invalid name"); 92848b8605Smrg return; 93848b8605Smrg } 94848b8605Smrg 95848b8605Smrg buffer->resource = 96848b8605Smrg wl_resource_create(client, &wl_buffer_interface, 1, id); 97848b8605Smrg if (!buffer->resource) { 98848b8605Smrg wl_resource_post_no_memory(resource); 99848b8605Smrg free(buffer); 100848b8605Smrg return; 101848b8605Smrg } 102848b8605Smrg 103848b8605Smrg wl_resource_set_implementation(buffer->resource, 104848b8605Smrg (void (**)(void)) &drm->buffer_interface, 105848b8605Smrg buffer, destroy_buffer); 106848b8605Smrg} 107848b8605Smrg 108848b8605Smrgstatic void 109848b8605Smrgdrm_create_buffer(struct wl_client *client, struct wl_resource *resource, 110848b8605Smrg uint32_t id, uint32_t name, int32_t width, int32_t height, 111848b8605Smrg uint32_t stride, uint32_t format) 112848b8605Smrg{ 113848b8605Smrg switch (format) { 114b8e80941Smrg case WL_DRM_FORMAT_ABGR2101010: 115b8e80941Smrg case WL_DRM_FORMAT_XBGR2101010: 116b8e80941Smrg case WL_DRM_FORMAT_ARGB2101010: 117b8e80941Smrg case WL_DRM_FORMAT_XRGB2101010: 118848b8605Smrg case WL_DRM_FORMAT_ARGB8888: 119848b8605Smrg case WL_DRM_FORMAT_XRGB8888: 120848b8605Smrg case WL_DRM_FORMAT_YUYV: 121848b8605Smrg case WL_DRM_FORMAT_RGB565: 122848b8605Smrg break; 123848b8605Smrg default: 124848b8605Smrg wl_resource_post_error(resource, 125848b8605Smrg WL_DRM_ERROR_INVALID_FORMAT, 126848b8605Smrg "invalid format"); 127848b8605Smrg return; 128848b8605Smrg } 129848b8605Smrg 130848b8605Smrg create_buffer(client, resource, id, 131848b8605Smrg name, -1, width, height, format, 0, stride, 0, 0, 0, 0); 132848b8605Smrg} 133848b8605Smrg 134848b8605Smrgstatic void 135848b8605Smrgdrm_create_planar_buffer(struct wl_client *client, 136848b8605Smrg struct wl_resource *resource, 137848b8605Smrg uint32_t id, uint32_t name, 138848b8605Smrg int32_t width, int32_t height, uint32_t format, 139848b8605Smrg int32_t offset0, int32_t stride0, 140848b8605Smrg int32_t offset1, int32_t stride1, 141848b8605Smrg int32_t offset2, int32_t stride2) 142848b8605Smrg{ 143848b8605Smrg switch (format) { 144848b8605Smrg case WL_DRM_FORMAT_YUV410: 145848b8605Smrg case WL_DRM_FORMAT_YUV411: 146848b8605Smrg case WL_DRM_FORMAT_YUV420: 147848b8605Smrg case WL_DRM_FORMAT_YUV422: 148848b8605Smrg case WL_DRM_FORMAT_YUV444: 149848b8605Smrg case WL_DRM_FORMAT_NV12: 150848b8605Smrg case WL_DRM_FORMAT_NV16: 151848b8605Smrg break; 152848b8605Smrg default: 153848b8605Smrg wl_resource_post_error(resource, 154848b8605Smrg WL_DRM_ERROR_INVALID_FORMAT, 155848b8605Smrg "invalid format"); 156848b8605Smrg return; 157848b8605Smrg } 158848b8605Smrg 159848b8605Smrg create_buffer(client, resource, id, name, -1, width, height, format, 160848b8605Smrg offset0, stride0, offset1, stride1, offset2, stride2); 161848b8605Smrg} 162848b8605Smrg 163848b8605Smrgstatic void 164848b8605Smrgdrm_create_prime_buffer(struct wl_client *client, 165848b8605Smrg struct wl_resource *resource, 166848b8605Smrg uint32_t id, int fd, 167848b8605Smrg int32_t width, int32_t height, uint32_t format, 168848b8605Smrg int32_t offset0, int32_t stride0, 169848b8605Smrg int32_t offset1, int32_t stride1, 170848b8605Smrg int32_t offset2, int32_t stride2) 171848b8605Smrg{ 172848b8605Smrg create_buffer(client, resource, id, 0, fd, width, height, format, 173848b8605Smrg offset0, stride0, offset1, stride1, offset2, stride2); 174848b8605Smrg close(fd); 175848b8605Smrg} 176848b8605Smrg 177848b8605Smrgstatic void 178848b8605Smrgdrm_authenticate(struct wl_client *client, 179848b8605Smrg struct wl_resource *resource, uint32_t id) 180848b8605Smrg{ 181b8e80941Smrg struct wl_drm *drm = wl_resource_get_user_data(resource); 182848b8605Smrg 183b8e80941Smrg if (drm->callbacks.authenticate(drm->user_data, id) < 0) 184848b8605Smrg wl_resource_post_error(resource, 185848b8605Smrg WL_DRM_ERROR_AUTHENTICATE_FAIL, 186848b8605Smrg "authenicate failed"); 187848b8605Smrg else 188848b8605Smrg wl_resource_post_event(resource, WL_DRM_AUTHENTICATED); 189848b8605Smrg} 190848b8605Smrg 191b8e80941Smrgstatic const struct wl_drm_interface drm_interface = { 192848b8605Smrg drm_authenticate, 193848b8605Smrg drm_create_buffer, 194848b8605Smrg drm_create_planar_buffer, 195848b8605Smrg drm_create_prime_buffer 196848b8605Smrg}; 197848b8605Smrg 198848b8605Smrgstatic void 199848b8605Smrgbind_drm(struct wl_client *client, void *data, uint32_t version, uint32_t id) 200848b8605Smrg{ 201848b8605Smrg struct wl_drm *drm = data; 202848b8605Smrg struct wl_resource *resource; 203848b8605Smrg uint32_t capabilities; 204848b8605Smrg 205848b8605Smrg resource = wl_resource_create(client, &wl_drm_interface, 206848b8605Smrg MIN(version, 2), id); 207848b8605Smrg if (!resource) { 208848b8605Smrg wl_client_post_no_memory(client); 209848b8605Smrg return; 210848b8605Smrg } 211848b8605Smrg 212848b8605Smrg wl_resource_set_implementation(resource, &drm_interface, data, NULL); 213848b8605Smrg 214848b8605Smrg wl_resource_post_event(resource, WL_DRM_DEVICE, drm->device_name); 215b8e80941Smrg 216b8e80941Smrg if (drm->callbacks.is_format_supported(drm->user_data, 217b8e80941Smrg WL_DRM_FORMAT_ARGB2101010)) { 218b8e80941Smrg wl_resource_post_event(resource, WL_DRM_FORMAT, 219b8e80941Smrg WL_DRM_FORMAT_ARGB2101010); 220b8e80941Smrg } 221b8e80941Smrg 222b8e80941Smrg if (drm->callbacks.is_format_supported(drm->user_data, 223b8e80941Smrg WL_DRM_FORMAT_XRGB2101010)) { 224b8e80941Smrg wl_resource_post_event(resource, WL_DRM_FORMAT, 225b8e80941Smrg WL_DRM_FORMAT_XRGB2101010); 226b8e80941Smrg } 227b8e80941Smrg 228b8e80941Smrg if (drm->callbacks.is_format_supported(drm->user_data, 229b8e80941Smrg WL_DRM_FORMAT_ABGR2101010)) { 230b8e80941Smrg wl_resource_post_event(resource, WL_DRM_FORMAT, 231b8e80941Smrg WL_DRM_FORMAT_ABGR2101010); 232b8e80941Smrg } 233b8e80941Smrg 234b8e80941Smrg if (drm->callbacks.is_format_supported(drm->user_data, 235b8e80941Smrg WL_DRM_FORMAT_XBGR2101010)) { 236b8e80941Smrg wl_resource_post_event(resource, WL_DRM_FORMAT, 237b8e80941Smrg WL_DRM_FORMAT_XBGR2101010); 238b8e80941Smrg } 239b8e80941Smrg 240848b8605Smrg wl_resource_post_event(resource, WL_DRM_FORMAT, 241848b8605Smrg WL_DRM_FORMAT_ARGB8888); 242848b8605Smrg wl_resource_post_event(resource, WL_DRM_FORMAT, 243848b8605Smrg WL_DRM_FORMAT_XRGB8888); 244848b8605Smrg wl_resource_post_event(resource, WL_DRM_FORMAT, 245848b8605Smrg WL_DRM_FORMAT_RGB565); 246848b8605Smrg wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_YUV410); 247848b8605Smrg wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_YUV411); 248848b8605Smrg wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_YUV420); 249848b8605Smrg wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_YUV422); 250848b8605Smrg wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_YUV444); 251848b8605Smrg wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_NV12); 252848b8605Smrg wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_NV16); 253848b8605Smrg wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_YUYV); 254848b8605Smrg 255848b8605Smrg capabilities = 0; 256848b8605Smrg if (drm->flags & WAYLAND_DRM_PRIME) 257848b8605Smrg capabilities |= WL_DRM_CAPABILITY_PRIME; 258848b8605Smrg 259848b8605Smrg if (version >= 2) 260848b8605Smrg wl_resource_post_event(resource, WL_DRM_CAPABILITIES, capabilities); 261848b8605Smrg} 262848b8605Smrg 263848b8605Smrgstruct wl_drm * 264848b8605Smrgwayland_drm_init(struct wl_display *display, char *device_name, 265b8e80941Smrg const struct wayland_drm_callbacks *callbacks, void *user_data, 266848b8605Smrg uint32_t flags) 267848b8605Smrg{ 268848b8605Smrg struct wl_drm *drm; 269848b8605Smrg 270848b8605Smrg drm = malloc(sizeof *drm); 271b8e80941Smrg if (!drm) 272b8e80941Smrg return NULL; 273848b8605Smrg 274848b8605Smrg drm->display = display; 275848b8605Smrg drm->device_name = strdup(device_name); 276b8e80941Smrg drm->callbacks = *callbacks; 277848b8605Smrg drm->user_data = user_data; 278848b8605Smrg drm->flags = flags; 279848b8605Smrg 280848b8605Smrg drm->buffer_interface.destroy = buffer_destroy; 281848b8605Smrg 282848b8605Smrg drm->wl_drm_global = 283848b8605Smrg wl_global_create(display, &wl_drm_interface, 2, 284848b8605Smrg drm, bind_drm); 285848b8605Smrg 286848b8605Smrg return drm; 287848b8605Smrg} 288848b8605Smrg 289848b8605Smrgvoid 290848b8605Smrgwayland_drm_uninit(struct wl_drm *drm) 291848b8605Smrg{ 292848b8605Smrg free(drm->device_name); 293848b8605Smrg 294848b8605Smrg wl_global_destroy(drm->wl_drm_global); 295848b8605Smrg 296848b8605Smrg free(drm); 297848b8605Smrg} 298