Path: blob/21.2-virgl/src/egl/wayland/wayland-drm/wayland-drm.c
4561 views
/*1* Copyright © 2011 Kristian Høgsberg2* Copyright © 2011 Benjamin Franzke3*4* Permission is hereby granted, free of charge, to any person obtaining a5* copy of this software and associated documentation files (the "Software"),6* to deal in the Software without restriction, including without limitation7* the rights to use, copy, modify, merge, publish, distribute, sublicense,8* and/or sell copies of the Software, and to permit persons to whom the9* Software is furnished to do so, subject to the following conditions:10*11* The above copyright notice and this permission notice (including the next12* paragraph) shall be included in all copies or substantial portions of the13* Software.14*15* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,16* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF17* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND18* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT19* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,20* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,21* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER22* DEALINGS IN THE SOFTWARE.23*24* Authors:25* Kristian Høgsberg <[email protected]>26* Benjamin Franzke <[email protected]>27*/2829#include <stdio.h>30#include <stdlib.h>31#include <string.h>32#include <stddef.h>33#include <unistd.h>3435#include <wayland-server.h>36#include "wayland-drm.h"37#include "wayland-drm-server-protocol.h"3839#define MIN(x,y) (((x)<(y))?(x):(y))4041static void42destroy_buffer(struct wl_resource *resource)43{44struct wl_drm_buffer *buffer = wl_resource_get_user_data(resource);45struct wl_drm *drm = buffer->drm;4647drm->callbacks.release_buffer(drm->user_data, buffer);48free(buffer);49}5051static void52buffer_destroy(struct wl_client *client, struct wl_resource *resource)53{54wl_resource_destroy(resource);55}5657static void58create_buffer(struct wl_client *client, struct wl_resource *resource,59uint32_t id, uint32_t name, int fd,60int32_t width, int32_t height,61uint32_t format,62int32_t offset0, int32_t stride0,63int32_t offset1, int32_t stride1,64int32_t offset2, int32_t stride2)65{66struct wl_drm *drm = wl_resource_get_user_data(resource);67struct wl_drm_buffer *buffer;6869buffer = calloc(1, sizeof *buffer);70if (buffer == NULL) {71wl_resource_post_no_memory(resource);72return;73}7475buffer->drm = drm;76buffer->width = width;77buffer->height = height;78buffer->format = format;79buffer->offset[0] = offset0;80buffer->stride[0] = stride0;81buffer->offset[1] = offset1;82buffer->stride[1] = stride1;83buffer->offset[2] = offset2;84buffer->stride[2] = stride2;8586drm->callbacks.reference_buffer(drm->user_data, name, fd, buffer);87if (buffer->driver_buffer == NULL) {88wl_resource_post_error(resource,89WL_DRM_ERROR_INVALID_NAME,90"invalid name");91return;92}9394buffer->resource =95wl_resource_create(client, &wl_buffer_interface, 1, id);96if (!buffer->resource) {97wl_resource_post_no_memory(resource);98free(buffer);99return;100}101102wl_resource_set_implementation(buffer->resource,103(void (**)(void)) &drm->buffer_interface,104buffer, destroy_buffer);105}106107static void108drm_create_buffer(struct wl_client *client, struct wl_resource *resource,109uint32_t id, uint32_t name, int32_t width, int32_t height,110uint32_t stride, uint32_t format)111{112switch (format) {113case WL_DRM_FORMAT_ABGR2101010:114case WL_DRM_FORMAT_XBGR2101010:115case WL_DRM_FORMAT_ARGB2101010:116case WL_DRM_FORMAT_XRGB2101010:117case WL_DRM_FORMAT_ARGB8888:118case WL_DRM_FORMAT_XRGB8888:119case WL_DRM_FORMAT_YUYV:120case WL_DRM_FORMAT_RGB565:121break;122default:123wl_resource_post_error(resource,124WL_DRM_ERROR_INVALID_FORMAT,125"invalid format");126return;127}128129create_buffer(client, resource, id,130name, -1, width, height, format, 0, stride, 0, 0, 0, 0);131}132133static void134drm_create_planar_buffer(struct wl_client *client,135struct wl_resource *resource,136uint32_t id, uint32_t name,137int32_t width, int32_t height, uint32_t format,138int32_t offset0, int32_t stride0,139int32_t offset1, int32_t stride1,140int32_t offset2, int32_t stride2)141{142switch (format) {143case WL_DRM_FORMAT_YUV410:144case WL_DRM_FORMAT_YUV411:145case WL_DRM_FORMAT_YUV420:146case WL_DRM_FORMAT_YUV422:147case WL_DRM_FORMAT_YUV444:148case WL_DRM_FORMAT_NV12:149case WL_DRM_FORMAT_NV16:150break;151default:152wl_resource_post_error(resource,153WL_DRM_ERROR_INVALID_FORMAT,154"invalid format");155return;156}157158create_buffer(client, resource, id, name, -1, width, height, format,159offset0, stride0, offset1, stride1, offset2, stride2);160}161162static void163drm_create_prime_buffer(struct wl_client *client,164struct wl_resource *resource,165uint32_t id, int fd,166int32_t width, int32_t height, uint32_t format,167int32_t offset0, int32_t stride0,168int32_t offset1, int32_t stride1,169int32_t offset2, int32_t stride2)170{171create_buffer(client, resource, id, 0, fd, width, height, format,172offset0, stride0, offset1, stride1, offset2, stride2);173close(fd);174}175176static void177drm_authenticate(struct wl_client *client,178struct wl_resource *resource, uint32_t id)179{180struct wl_drm *drm = wl_resource_get_user_data(resource);181182if (!drm->callbacks.authenticate ||183drm->callbacks.authenticate(drm->user_data, id) < 0)184wl_resource_post_error(resource,185WL_DRM_ERROR_AUTHENTICATE_FAIL,186"authenticate failed");187else188wl_resource_post_event(resource, WL_DRM_AUTHENTICATED);189}190191static const struct wl_drm_interface drm_interface = {192drm_authenticate,193drm_create_buffer,194drm_create_planar_buffer,195drm_create_prime_buffer196};197198static void199bind_drm(struct wl_client *client, void *data, uint32_t version, uint32_t id)200{201struct wl_drm *drm = data;202struct wl_resource *resource;203uint32_t capabilities;204205resource = wl_resource_create(client, &wl_drm_interface,206MIN(version, 2), id);207if (!resource) {208wl_client_post_no_memory(client);209return;210}211212wl_resource_set_implementation(resource, &drm_interface, data, NULL);213214wl_resource_post_event(resource, WL_DRM_DEVICE, drm->device_name);215216if (drm->callbacks.is_format_supported(drm->user_data,217WL_DRM_FORMAT_ARGB2101010)) {218wl_resource_post_event(resource, WL_DRM_FORMAT,219WL_DRM_FORMAT_ARGB2101010);220}221222if (drm->callbacks.is_format_supported(drm->user_data,223WL_DRM_FORMAT_XRGB2101010)) {224wl_resource_post_event(resource, WL_DRM_FORMAT,225WL_DRM_FORMAT_XRGB2101010);226}227228if (drm->callbacks.is_format_supported(drm->user_data,229WL_DRM_FORMAT_ABGR2101010)) {230wl_resource_post_event(resource, WL_DRM_FORMAT,231WL_DRM_FORMAT_ABGR2101010);232}233234if (drm->callbacks.is_format_supported(drm->user_data,235WL_DRM_FORMAT_XBGR2101010)) {236wl_resource_post_event(resource, WL_DRM_FORMAT,237WL_DRM_FORMAT_XBGR2101010);238}239240wl_resource_post_event(resource, WL_DRM_FORMAT,241WL_DRM_FORMAT_ARGB8888);242wl_resource_post_event(resource, WL_DRM_FORMAT,243WL_DRM_FORMAT_XRGB8888);244wl_resource_post_event(resource, WL_DRM_FORMAT,245WL_DRM_FORMAT_RGB565);246wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_YUV410);247wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_YUV411);248wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_YUV420);249wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_YUV422);250wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_YUV444);251wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_NV12);252wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_NV16);253wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_YUYV);254255capabilities = 0;256if (drm->flags & WAYLAND_DRM_PRIME)257capabilities |= WL_DRM_CAPABILITY_PRIME;258259if (version >= 2)260wl_resource_post_event(resource, WL_DRM_CAPABILITIES, capabilities);261}262263struct wl_drm *264wayland_drm_init(struct wl_display *display, char *device_name,265const struct wayland_drm_callbacks *callbacks, void *user_data,266uint32_t flags)267{268struct wl_drm *drm;269270drm = malloc(sizeof *drm);271if (!drm)272return NULL;273274drm->display = display;275drm->device_name = strdup(device_name);276drm->callbacks = *callbacks;277drm->user_data = user_data;278drm->flags = flags;279280drm->buffer_interface.destroy = buffer_destroy;281282drm->wl_drm_global =283wl_global_create(display, &wl_drm_interface, 2,284drm, bind_drm);285286return drm;287}288289void290wayland_drm_uninit(struct wl_drm *drm)291{292free(drm->device_name);293294wl_global_destroy(drm->wl_drm_global);295296free(drm);297}298299300