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