1/* 2 * Copyright (c) 2018-2019 Lima Project 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, sub license, 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 12 * next paragraph) shall be included in all copies or substantial portions 13 * of the 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 NON-INFRINGEMENT. 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 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 * 23 */ 24 25#include <fcntl.h> 26#include <libsync.h> 27 28#include <util/u_memory.h> 29#include <util/u_inlines.h> 30 31#include "drm-uapi/lima_drm.h" 32 33#include "lima_screen.h" 34#include "lima_context.h" 35#include "lima_fence.h" 36#include "lima_submit.h" 37 38struct pipe_fence_handle { 39 struct pipe_reference reference; 40 int fd; 41}; 42 43static void 44lima_create_fence_fd(struct pipe_context *pctx, 45 struct pipe_fence_handle **fence, 46 int fd, enum pipe_fd_type type) 47{ 48 assert(type == PIPE_FD_TYPE_NATIVE_SYNC); 49 *fence = lima_fence_create(fcntl(fd, F_DUPFD_CLOEXEC, 3)); 50} 51 52static void 53lima_fence_server_sync(struct pipe_context *pctx, 54 struct pipe_fence_handle *fence) 55{ 56 struct lima_context *ctx = lima_context(pctx); 57 58 lima_submit_add_in_sync(ctx->gp_submit, fence->fd); 59} 60 61void lima_fence_context_init(struct lima_context *ctx) 62{ 63 ctx->base.create_fence_fd = lima_create_fence_fd; 64 ctx->base.fence_server_sync = lima_fence_server_sync; 65} 66 67struct pipe_fence_handle * 68lima_fence_create(int fd) 69{ 70 struct pipe_fence_handle *fence; 71 72 fence = CALLOC_STRUCT(pipe_fence_handle); 73 if (!fence) 74 return NULL; 75 76 pipe_reference_init(&fence->reference, 1); 77 fence->fd = fd; 78 79 return fence; 80} 81 82static int 83lima_fence_get_fd(struct pipe_screen *pscreen, 84 struct pipe_fence_handle *fence) 85{ 86 return fcntl(fence->fd, F_DUPFD_CLOEXEC, 3); 87} 88 89static void 90lima_fence_destroy(struct pipe_fence_handle *fence) 91{ 92 if (fence->fd >= 0) 93 close(fence->fd); 94 FREE(fence); 95} 96 97static void 98lima_fence_reference(struct pipe_screen *pscreen, 99 struct pipe_fence_handle **ptr, 100 struct pipe_fence_handle *fence) 101{ 102 if (pipe_reference(&(*ptr)->reference, &fence->reference)) 103 lima_fence_destroy(*ptr); 104 *ptr = fence; 105} 106 107static boolean 108lima_fence_finish(struct pipe_screen *pscreen, struct pipe_context *pctx, 109 struct pipe_fence_handle *fence, uint64_t timeout) 110{ 111 return !sync_wait(fence->fd, timeout / 1000000); 112} 113 114void 115lima_fence_screen_init(struct lima_screen *screen) 116{ 117 screen->base.fence_reference = lima_fence_reference; 118 screen->base.fence_finish = lima_fence_finish; 119 screen->base.fence_get_fd = lima_fence_get_fd; 120} 121