1/* 2 * Copyright © 2017 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, 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 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 */ 23 24#include <unistd.h> 25#include <fcntl.h> 26#include <sys/stat.h> 27 28#include "c11/threads.h" 29#include "util/os_file.h" 30#include "util/u_hash_table.h" 31#include "util/u_pointer.h" 32#include "renderonly/renderonly.h" 33 34#include "lima_drm_public.h" 35 36#include "lima/lima_screen.h" 37 38static struct hash_table *fd_tab = NULL; 39static mtx_t lima_screen_mutex = _MTX_INITIALIZER_NP; 40 41static void 42lima_drm_screen_destroy(struct pipe_screen *pscreen) 43{ 44 struct lima_screen *screen = lima_screen(pscreen); 45 boolean destroy; 46 int fd = screen->fd; 47 48 mtx_lock(&lima_screen_mutex); 49 destroy = --screen->refcnt == 0; 50 if (destroy) { 51 _mesa_hash_table_remove_key(fd_tab, intptr_to_pointer(fd)); 52 53 if (!fd_tab->entries) { 54 _mesa_hash_table_destroy(fd_tab, NULL); 55 fd_tab = NULL; 56 } 57 } 58 mtx_unlock(&lima_screen_mutex); 59 60 if (destroy) { 61 pscreen->destroy = screen->winsys_priv; 62 pscreen->destroy(pscreen); 63 close(fd); 64 } 65} 66 67struct pipe_screen * 68lima_drm_screen_create(int fd) 69{ 70 struct pipe_screen *pscreen = NULL; 71 72 mtx_lock(&lima_screen_mutex); 73 if (!fd_tab) { 74 fd_tab = util_hash_table_create_fd_keys(); 75 if (!fd_tab) 76 goto unlock; 77 } 78 79 pscreen = util_hash_table_get(fd_tab, intptr_to_pointer(fd)); 80 if (pscreen) { 81 lima_screen(pscreen)->refcnt++; 82 } else { 83 int dup_fd = os_dupfd_cloexec(fd); 84 85 pscreen = lima_screen_create(dup_fd, NULL); 86 if (pscreen) { 87 _mesa_hash_table_insert(fd_tab, intptr_to_pointer(dup_fd), pscreen); 88 89 /* Bit of a hack, to avoid circular linkage dependency, 90 * ie. pipe driver having to call in to winsys, we 91 * override the pipe drivers screen->destroy(): 92 */ 93 lima_screen(pscreen)->winsys_priv = pscreen->destroy; 94 pscreen->destroy = lima_drm_screen_destroy; 95 } 96 } 97 98unlock: 99 mtx_unlock(&lima_screen_mutex); 100 return pscreen; 101} 102 103struct pipe_screen * 104lima_drm_screen_create_renderonly(struct renderonly *ro) 105{ 106 return lima_screen_create(os_dupfd_cloexec(ro->gpu_fd), ro); 107} 108