Home | History | Annotate | Download | only in renderonly
      1 /*
      2  * Copyright (C) 2016 Christian Gmeiner <christian.gmeiner (at) gmail.com>
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8  * and/or sell copies of the Software, and to permit persons to whom the
      9  * Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice (including the next
     12  * paragraph) shall be included in all copies or substantial portions of the
     13  * Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     21  * SOFTWARE.
     22  *
     23  * Authors:
     24  *    Christian Gmeiner <christian.gmeiner (at) gmail.com>
     25  */
     26 
     27 #include "renderonly/renderonly.h"
     28 
     29 #include <errno.h>
     30 #include <fcntl.h>
     31 #include <stdio.h>
     32 #include <xf86drm.h>
     33 
     34 #include "state_tracker/drm_driver.h"
     35 #include "pipe/p_screen.h"
     36 #include "util/u_format.h"
     37 #include "util/u_inlines.h"
     38 #include "util/u_memory.h"
     39 
     40 struct renderonly *
     41 renderonly_dup(const struct renderonly *ro)
     42 {
     43    struct renderonly *copy;
     44 
     45    copy = CALLOC_STRUCT(renderonly);
     46    if (!copy)
     47       return NULL;
     48 
     49    memcpy(copy, ro, sizeof(*ro));
     50 
     51    return copy;
     52 }
     53 
     54 void
     55 renderonly_scanout_destroy(struct renderonly_scanout *scanout,
     56 			   struct renderonly *ro)
     57 {
     58    struct drm_mode_destroy_dumb destroy_dumb = { };
     59 
     60    if (ro->kms_fd != -1) {
     61       destroy_dumb.handle = scanout->handle;
     62       drmIoctl(ro->kms_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_dumb);
     63    }
     64    FREE(scanout);
     65 }
     66 
     67 struct renderonly_scanout *
     68 renderonly_create_kms_dumb_buffer_for_resource(struct pipe_resource *rsc,
     69                                                struct renderonly *ro,
     70                                                struct winsys_handle *out_handle)
     71 {
     72    struct renderonly_scanout *scanout;
     73    int err;
     74    struct drm_mode_create_dumb create_dumb = {
     75       .width = rsc->width0,
     76       .height = rsc->height0,
     77       .bpp = util_format_get_blocksizebits(rsc->format),
     78    };
     79    struct drm_mode_destroy_dumb destroy_dumb = { };
     80 
     81    scanout = CALLOC_STRUCT(renderonly_scanout);
     82    if (!scanout)
     83       return NULL;
     84 
     85    /* create dumb buffer at scanout GPU */
     86    err = drmIoctl(ro->kms_fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_dumb);
     87    if (err < 0) {
     88       fprintf(stderr, "DRM_IOCTL_MODE_CREATE_DUMB failed: %s\n",
     89             strerror(errno));
     90       goto free_scanout;
     91    }
     92 
     93    scanout->handle = create_dumb.handle;
     94    scanout->stride = create_dumb.pitch;
     95 
     96    if (!out_handle)
     97       return scanout;
     98 
     99    /* fill in winsys handle */
    100    memset(out_handle, 0, sizeof(*out_handle));
    101    out_handle->type = DRM_API_HANDLE_TYPE_FD;
    102    out_handle->stride = create_dumb.pitch;
    103 
    104    err = drmPrimeHandleToFD(ro->kms_fd, create_dumb.handle, O_CLOEXEC,
    105          (int *)&out_handle->handle);
    106    if (err < 0) {
    107       fprintf(stderr, "failed to export dumb buffer: %s\n", strerror(errno));
    108       goto free_dumb;
    109    }
    110 
    111    return scanout;
    112 
    113 free_dumb:
    114    destroy_dumb.handle = scanout->handle;
    115    drmIoctl(ro->kms_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_dumb);
    116 
    117 free_scanout:
    118    FREE(scanout);
    119 
    120    return NULL;
    121 }
    122 
    123 struct renderonly_scanout *
    124 renderonly_create_gpu_import_for_resource(struct pipe_resource *rsc,
    125                                           struct renderonly *ro,
    126                                           struct winsys_handle *out_handle)
    127 {
    128    struct pipe_screen *screen = rsc->screen;
    129    struct renderonly_scanout *scanout;
    130    boolean status;
    131    int fd, err;
    132    struct winsys_handle handle = {
    133       .type = DRM_API_HANDLE_TYPE_FD
    134    };
    135 
    136    scanout = CALLOC_STRUCT(renderonly_scanout);
    137    if (!scanout)
    138       return NULL;
    139 
    140    status = screen->resource_get_handle(screen, NULL, rsc, &handle,
    141          PIPE_HANDLE_USAGE_READ_WRITE);
    142    if (!status)
    143       goto free_scanout;
    144 
    145    scanout->stride = handle.stride;
    146    fd = handle.handle;
    147 
    148    err = drmPrimeFDToHandle(ro->kms_fd, fd, &scanout->handle);
    149    close(fd);
    150 
    151    if (err < 0) {
    152       fprintf(stderr, "drmPrimeFDToHandle() failed: %s\n", strerror(errno));
    153       goto free_scanout;
    154    }
    155 
    156    return scanout;
    157 
    158 free_scanout:
    159    FREE(scanout);
    160 
    161    return NULL;
    162 }
    163 
    164