101e04c3fSmrg/* 201e04c3fSmrg * Copyright (C) 2016 Christian Gmeiner <christian.gmeiner@gmail.com> 301e04c3fSmrg * 401e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a 501e04c3fSmrg * copy of this software and associated documentation files (the "Software"), 601e04c3fSmrg * to deal in the Software without restriction, including without limitation 701e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 801e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the 901e04c3fSmrg * Software is furnished to do so, subject to the following conditions: 1001e04c3fSmrg * 1101e04c3fSmrg * The above copyright notice and this permission notice (including the next 1201e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the 1301e04c3fSmrg * Software. 1401e04c3fSmrg * 1501e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1601e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1701e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1801e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1901e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 2001e04c3fSmrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 2101e04c3fSmrg * SOFTWARE. 2201e04c3fSmrg * 2301e04c3fSmrg * Authors: 2401e04c3fSmrg * Christian Gmeiner <christian.gmeiner@gmail.com> 2501e04c3fSmrg */ 2601e04c3fSmrg 2701e04c3fSmrg#include "renderonly/renderonly.h" 2801e04c3fSmrg 2901e04c3fSmrg#include <errno.h> 3001e04c3fSmrg#include <fcntl.h> 3101e04c3fSmrg#include <stdio.h> 3201e04c3fSmrg#include <xf86drm.h> 3301e04c3fSmrg 347ec681f3Smrg#include "frontend/drm_driver.h" 3501e04c3fSmrg#include "pipe/p_screen.h" 367ec681f3Smrg#include "util/format/u_format.h" 3701e04c3fSmrg#include "util/u_inlines.h" 3801e04c3fSmrg#include "util/u_memory.h" 3901e04c3fSmrg 4001e04c3fSmrgvoid 4101e04c3fSmrgrenderonly_scanout_destroy(struct renderonly_scanout *scanout, 4201e04c3fSmrg struct renderonly *ro) 4301e04c3fSmrg{ 447ec681f3Smrg struct drm_mode_destroy_dumb destroy_dumb = {0}; 4501e04c3fSmrg 4601e04c3fSmrg if (ro->kms_fd != -1) { 4701e04c3fSmrg destroy_dumb.handle = scanout->handle; 4801e04c3fSmrg drmIoctl(ro->kms_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_dumb); 4901e04c3fSmrg } 5001e04c3fSmrg FREE(scanout); 5101e04c3fSmrg} 5201e04c3fSmrg 5301e04c3fSmrgstruct renderonly_scanout * 5401e04c3fSmrgrenderonly_create_kms_dumb_buffer_for_resource(struct pipe_resource *rsc, 5501e04c3fSmrg struct renderonly *ro, 5601e04c3fSmrg struct winsys_handle *out_handle) 5701e04c3fSmrg{ 5801e04c3fSmrg struct renderonly_scanout *scanout; 5901e04c3fSmrg int err; 6001e04c3fSmrg struct drm_mode_create_dumb create_dumb = { 6101e04c3fSmrg .width = rsc->width0, 6201e04c3fSmrg .height = rsc->height0, 6301e04c3fSmrg .bpp = util_format_get_blocksizebits(rsc->format), 6401e04c3fSmrg }; 657ec681f3Smrg struct drm_mode_destroy_dumb destroy_dumb = {0}; 6601e04c3fSmrg 6701e04c3fSmrg scanout = CALLOC_STRUCT(renderonly_scanout); 6801e04c3fSmrg if (!scanout) 6901e04c3fSmrg return NULL; 7001e04c3fSmrg 7101e04c3fSmrg /* create dumb buffer at scanout GPU */ 7201e04c3fSmrg err = drmIoctl(ro->kms_fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_dumb); 7301e04c3fSmrg if (err < 0) { 7401e04c3fSmrg fprintf(stderr, "DRM_IOCTL_MODE_CREATE_DUMB failed: %s\n", 7501e04c3fSmrg strerror(errno)); 7601e04c3fSmrg goto free_scanout; 7701e04c3fSmrg } 7801e04c3fSmrg 7901e04c3fSmrg scanout->handle = create_dumb.handle; 8001e04c3fSmrg scanout->stride = create_dumb.pitch; 8101e04c3fSmrg 8201e04c3fSmrg if (!out_handle) 8301e04c3fSmrg return scanout; 8401e04c3fSmrg 8501e04c3fSmrg /* fill in winsys handle */ 8601e04c3fSmrg memset(out_handle, 0, sizeof(*out_handle)); 8701e04c3fSmrg out_handle->type = WINSYS_HANDLE_TYPE_FD; 8801e04c3fSmrg out_handle->stride = create_dumb.pitch; 8901e04c3fSmrg 9001e04c3fSmrg err = drmPrimeHandleToFD(ro->kms_fd, create_dumb.handle, O_CLOEXEC, 9101e04c3fSmrg (int *)&out_handle->handle); 9201e04c3fSmrg if (err < 0) { 9301e04c3fSmrg fprintf(stderr, "failed to export dumb buffer: %s\n", strerror(errno)); 9401e04c3fSmrg goto free_dumb; 9501e04c3fSmrg } 9601e04c3fSmrg 9701e04c3fSmrg return scanout; 9801e04c3fSmrg 9901e04c3fSmrgfree_dumb: 10001e04c3fSmrg destroy_dumb.handle = scanout->handle; 10101e04c3fSmrg drmIoctl(ro->kms_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_dumb); 10201e04c3fSmrg 10301e04c3fSmrgfree_scanout: 10401e04c3fSmrg FREE(scanout); 10501e04c3fSmrg 10601e04c3fSmrg return NULL; 10701e04c3fSmrg} 10801e04c3fSmrg 10901e04c3fSmrgstruct renderonly_scanout * 11001e04c3fSmrgrenderonly_create_gpu_import_for_resource(struct pipe_resource *rsc, 11101e04c3fSmrg struct renderonly *ro, 11201e04c3fSmrg struct winsys_handle *out_handle) 11301e04c3fSmrg{ 11401e04c3fSmrg struct pipe_screen *screen = rsc->screen; 11501e04c3fSmrg struct renderonly_scanout *scanout; 11601e04c3fSmrg boolean status; 11701e04c3fSmrg int fd, err; 11801e04c3fSmrg struct winsys_handle handle = { 11901e04c3fSmrg .type = WINSYS_HANDLE_TYPE_FD 12001e04c3fSmrg }; 12101e04c3fSmrg 12201e04c3fSmrg scanout = CALLOC_STRUCT(renderonly_scanout); 12301e04c3fSmrg if (!scanout) 12401e04c3fSmrg return NULL; 12501e04c3fSmrg 12601e04c3fSmrg status = screen->resource_get_handle(screen, NULL, rsc, &handle, 12701e04c3fSmrg PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE); 12801e04c3fSmrg if (!status) 12901e04c3fSmrg goto free_scanout; 13001e04c3fSmrg 13101e04c3fSmrg scanout->stride = handle.stride; 13201e04c3fSmrg fd = handle.handle; 13301e04c3fSmrg 13401e04c3fSmrg err = drmPrimeFDToHandle(ro->kms_fd, fd, &scanout->handle); 13501e04c3fSmrg close(fd); 13601e04c3fSmrg 1377ec681f3Smrg if (err < 0) 13801e04c3fSmrg goto free_scanout; 13901e04c3fSmrg 14001e04c3fSmrg return scanout; 14101e04c3fSmrg 14201e04c3fSmrgfree_scanout: 14301e04c3fSmrg FREE(scanout); 14401e04c3fSmrg 14501e04c3fSmrg return NULL; 14601e04c3fSmrg} 14701e04c3fSmrg 148