Path: blob/21.2-virgl/src/gallium/winsys/etnaviv/drm/etnaviv_drm_winsys.c
4573 views
/*1* Copyright (c) 2015 Etnaviv Project2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sub license,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the11* next paragraph) shall be included in all copies or substantial portions12* of the Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING19* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER20* DEALINGS IN THE SOFTWARE.21*22* Authors:23* Christian Gmeiner <[email protected]>24*/2526#include <sys/stat.h>2728#include "util/os_file.h"29#include "util/u_hash_table.h"30#include "util/u_memory.h"31#include "util/u_pointer.h"3233#include "etnaviv/etnaviv_screen.h"34#include "etnaviv/hw/common.xml.h"35#include "etnaviv_drm_public.h"3637#include <stdio.h>3839static uint32_t hash_file_description(const void *key)40{41int fd = pointer_to_intptr(key);42struct stat stat;4344// File descriptions can't be hashed, but it should be safe to assume45// that the same file description will always refer to he same file46if(fstat(fd, &stat) == -1)47return ~0; // Make sure fstat failing won't result in a random hash4849return stat.st_dev ^ stat.st_ino ^ stat.st_rdev;50}515253static bool equal_file_description(const void *key1, const void *key2)54{55int ret;56int fd1 = pointer_to_intptr(key1);57int fd2 = pointer_to_intptr(key2);58struct stat stat1, stat2;5960// If the file descriptors are the same, the file description will be too61// This will also catch sentinels, such as -162if (fd1 == fd2)63return true;6465ret = os_same_file_description(fd1, fd2);66if (ret >= 0)67return (ret == 0);6869{70static bool has_warned;71if (!has_warned)72fprintf(stderr, "os_same_file_description couldn't determine if "73"two DRM fds reference the same file description. (%s)\n"74"Let's just assume that file descriptors for the same file probably"75"share the file description instead. This may cause problems when"76"that isn't the case.\n", strerror(errno));77has_warned = true;78}7980// Let's at least check that it's the same file, different files can't81// have the same file descriptions82fstat(fd1, &stat1);83fstat(fd2, &stat2);8485return stat1.st_dev == stat2.st_dev &&86stat1.st_ino == stat2.st_ino &&87stat1.st_rdev == stat2.st_rdev;88}899091static struct hash_table *92hash_table_create_file_description_keys(void)93{94return _mesa_hash_table_create(NULL, hash_file_description, equal_file_description);95}9697static struct pipe_screen *98screen_create(struct renderonly *ro)99{100struct etna_device *dev;101struct etna_gpu *gpu;102uint64_t val;103int i;104105dev = etna_device_new_dup(ro->gpu_fd);106if (!dev) {107fprintf(stderr, "Error creating device\n");108return NULL;109}110111for (i = 0;; i++) {112gpu = etna_gpu_new(dev, i);113if (!gpu) {114fprintf(stderr, "Error creating gpu\n");115return NULL;116}117118/* Look for a 3D capable GPU */119int ret = etna_gpu_get_param(gpu, ETNA_GPU_FEATURES_0, &val);120if (ret == 0 && (val & chipFeatures_PIPE_3D))121break;122123etna_gpu_del(gpu);124}125126return etna_screen_create(dev, gpu, ro);127}128129static struct hash_table *etna_tab = NULL;130131static mtx_t etna_screen_mutex = _MTX_INITIALIZER_NP;132133static void134etna_drm_screen_destroy(struct pipe_screen *pscreen)135{136struct etna_screen *screen = etna_screen(pscreen);137boolean destroy;138139mtx_lock(&etna_screen_mutex);140destroy = --screen->refcnt == 0;141if (destroy) {142int fd = etna_device_fd(screen->dev);143_mesa_hash_table_remove_key(etna_tab, intptr_to_pointer(fd));144}145mtx_unlock(&etna_screen_mutex);146147if (destroy) {148pscreen->destroy = screen->winsys_priv;149pscreen->destroy(pscreen);150}151}152153struct pipe_screen *154etna_drm_screen_create_renderonly(struct renderonly *ro)155{156struct pipe_screen *pscreen = NULL;157158mtx_lock(&etna_screen_mutex);159if (!etna_tab) {160etna_tab = hash_table_create_file_description_keys();161if (!etna_tab)162goto unlock;163}164165pscreen = util_hash_table_get(etna_tab, intptr_to_pointer(ro->gpu_fd));166if (pscreen) {167etna_screen(pscreen)->refcnt++;168} else {169pscreen = screen_create(ro);170if (pscreen) {171int fd = etna_device_fd(etna_screen(pscreen)->dev);172_mesa_hash_table_insert(etna_tab, intptr_to_pointer(fd), pscreen);173174/* Bit of a hack, to avoid circular linkage dependency,175* ie. pipe driver having to call in to winsys, we176* override the pipe drivers screen->destroy() */177etna_screen(pscreen)->winsys_priv = pscreen->destroy;178pscreen->destroy = etna_drm_screen_destroy;179}180}181182unlock:183mtx_unlock(&etna_screen_mutex);184return pscreen;185}186187static void etnaviv_ro_destroy(struct renderonly *ro)188{189FREE(ro);190}191192struct pipe_screen *193etna_drm_screen_create(int fd)194{195196struct renderonly *ro = CALLOC_STRUCT(renderonly);197struct pipe_screen *screen;198199if (!ro)200return NULL;201202ro->create_for_resource = renderonly_create_gpu_import_for_resource;203ro->destroy = etnaviv_ro_destroy;204ro->kms_fd = -1;205ro->gpu_fd = fd;206207screen = etna_drm_screen_create_renderonly(ro);208if (!screen)209FREE(ro);210211return screen;212}213214215