101e04c3fSmrg/* 201e04c3fSmrg * Copyright © 2014-2018 NVIDIA Corporation 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 2001e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 2101e04c3fSmrg * IN THE SOFTWARE. 2201e04c3fSmrg */ 2301e04c3fSmrg 2401e04c3fSmrg#include <errno.h> 2501e04c3fSmrg#include <fcntl.h> 2601e04c3fSmrg#include <inttypes.h> 2701e04c3fSmrg#include <stdio.h> 2801e04c3fSmrg 2901e04c3fSmrg#include <sys/stat.h> 3001e04c3fSmrg 319f464c52Smaya#include "drm-uapi/drm_fourcc.h" 329f464c52Smaya#include "drm-uapi/tegra_drm.h" 3301e04c3fSmrg#include <xf86drm.h> 3401e04c3fSmrg 3501e04c3fSmrg#include "loader/loader.h" 3601e04c3fSmrg#include "pipe/p_state.h" 3701e04c3fSmrg#include "util/u_debug.h" 387ec681f3Smrg#include "util/format/u_format.h" 3901e04c3fSmrg#include "util/u_inlines.h" 4001e04c3fSmrg 417ec681f3Smrg#include "frontend/drm_driver.h" 4201e04c3fSmrg 4301e04c3fSmrg#include "nouveau/drm/nouveau_drm_public.h" 4401e04c3fSmrg 4501e04c3fSmrg#include "tegra_context.h" 4601e04c3fSmrg#include "tegra_resource.h" 4701e04c3fSmrg#include "tegra_screen.h" 4801e04c3fSmrg 4901e04c3fSmrgstatic void tegra_screen_destroy(struct pipe_screen *pscreen) 5001e04c3fSmrg{ 5101e04c3fSmrg struct tegra_screen *screen = to_tegra_screen(pscreen); 5201e04c3fSmrg 5301e04c3fSmrg screen->gpu->destroy(screen->gpu); 5401e04c3fSmrg free(pscreen); 5501e04c3fSmrg} 5601e04c3fSmrg 5701e04c3fSmrgstatic const char * 5801e04c3fSmrgtegra_screen_get_name(struct pipe_screen *pscreen) 5901e04c3fSmrg{ 6001e04c3fSmrg return "tegra"; 6101e04c3fSmrg} 6201e04c3fSmrg 6301e04c3fSmrgstatic const char * 6401e04c3fSmrgtegra_screen_get_vendor(struct pipe_screen *pscreen) 6501e04c3fSmrg{ 6601e04c3fSmrg return "NVIDIA"; 6701e04c3fSmrg} 6801e04c3fSmrg 6901e04c3fSmrgstatic const char * 7001e04c3fSmrgtegra_screen_get_device_vendor(struct pipe_screen *pscreen) 7101e04c3fSmrg{ 7201e04c3fSmrg return "NVIDIA"; 7301e04c3fSmrg} 7401e04c3fSmrg 7501e04c3fSmrgstatic int 7601e04c3fSmrgtegra_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) 7701e04c3fSmrg{ 7801e04c3fSmrg struct tegra_screen *screen = to_tegra_screen(pscreen); 7901e04c3fSmrg 8001e04c3fSmrg return screen->gpu->get_param(screen->gpu, param); 8101e04c3fSmrg} 8201e04c3fSmrg 8301e04c3fSmrgstatic float 8401e04c3fSmrgtegra_screen_get_paramf(struct pipe_screen *pscreen, enum pipe_capf param) 8501e04c3fSmrg{ 8601e04c3fSmrg struct tegra_screen *screen = to_tegra_screen(pscreen); 8701e04c3fSmrg 8801e04c3fSmrg return screen->gpu->get_paramf(screen->gpu, param); 8901e04c3fSmrg} 9001e04c3fSmrg 9101e04c3fSmrgstatic int 9201e04c3fSmrgtegra_screen_get_shader_param(struct pipe_screen *pscreen, unsigned shader, 9301e04c3fSmrg enum pipe_shader_cap param) 9401e04c3fSmrg{ 9501e04c3fSmrg struct tegra_screen *screen = to_tegra_screen(pscreen); 9601e04c3fSmrg 9701e04c3fSmrg return screen->gpu->get_shader_param(screen->gpu, shader, param); 9801e04c3fSmrg} 9901e04c3fSmrg 10001e04c3fSmrgstatic int 10101e04c3fSmrgtegra_screen_get_video_param(struct pipe_screen *pscreen, 10201e04c3fSmrg enum pipe_video_profile profile, 10301e04c3fSmrg enum pipe_video_entrypoint entrypoint, 10401e04c3fSmrg enum pipe_video_cap param) 10501e04c3fSmrg{ 10601e04c3fSmrg struct tegra_screen *screen = to_tegra_screen(pscreen); 10701e04c3fSmrg 10801e04c3fSmrg return screen->gpu->get_video_param(screen->gpu, profile, entrypoint, 10901e04c3fSmrg param); 11001e04c3fSmrg} 11101e04c3fSmrg 11201e04c3fSmrgstatic int 11301e04c3fSmrgtegra_screen_get_compute_param(struct pipe_screen *pscreen, 11401e04c3fSmrg enum pipe_shader_ir ir_type, 11501e04c3fSmrg enum pipe_compute_cap param, 11601e04c3fSmrg void *retp) 11701e04c3fSmrg{ 11801e04c3fSmrg struct tegra_screen *screen = to_tegra_screen(pscreen); 11901e04c3fSmrg 12001e04c3fSmrg return screen->gpu->get_compute_param(screen->gpu, ir_type, param, 12101e04c3fSmrg retp); 12201e04c3fSmrg} 12301e04c3fSmrg 12401e04c3fSmrgstatic uint64_t 12501e04c3fSmrgtegra_screen_get_timestamp(struct pipe_screen *pscreen) 12601e04c3fSmrg{ 12701e04c3fSmrg struct tegra_screen *screen = to_tegra_screen(pscreen); 12801e04c3fSmrg 12901e04c3fSmrg return screen->gpu->get_timestamp(screen->gpu); 13001e04c3fSmrg} 13101e04c3fSmrg 1327ec681f3Smrgstatic bool 13301e04c3fSmrgtegra_screen_is_format_supported(struct pipe_screen *pscreen, 13401e04c3fSmrg enum pipe_format format, 13501e04c3fSmrg enum pipe_texture_target target, 13601e04c3fSmrg unsigned sample_count, 13701e04c3fSmrg unsigned storage_sample_count, 13801e04c3fSmrg unsigned usage) 13901e04c3fSmrg{ 14001e04c3fSmrg struct tegra_screen *screen = to_tegra_screen(pscreen); 14101e04c3fSmrg 14201e04c3fSmrg return screen->gpu->is_format_supported(screen->gpu, format, target, 14301e04c3fSmrg sample_count, storage_sample_count, 14401e04c3fSmrg usage); 14501e04c3fSmrg} 14601e04c3fSmrg 1477ec681f3Smrgstatic bool 14801e04c3fSmrgtegra_screen_is_video_format_supported(struct pipe_screen *pscreen, 14901e04c3fSmrg enum pipe_format format, 15001e04c3fSmrg enum pipe_video_profile profile, 15101e04c3fSmrg enum pipe_video_entrypoint entrypoint) 15201e04c3fSmrg{ 15301e04c3fSmrg struct tegra_screen *screen = to_tegra_screen(pscreen); 15401e04c3fSmrg 15501e04c3fSmrg return screen->gpu->is_video_format_supported(screen->gpu, format, profile, 15601e04c3fSmrg entrypoint); 15701e04c3fSmrg} 15801e04c3fSmrg 1597ec681f3Smrgstatic bool 16001e04c3fSmrgtegra_screen_can_create_resource(struct pipe_screen *pscreen, 16101e04c3fSmrg const struct pipe_resource *template) 16201e04c3fSmrg{ 16301e04c3fSmrg struct tegra_screen *screen = to_tegra_screen(pscreen); 16401e04c3fSmrg 16501e04c3fSmrg return screen->gpu->can_create_resource(screen->gpu, template); 16601e04c3fSmrg} 16701e04c3fSmrg 16801e04c3fSmrgstatic int tegra_screen_import_resource(struct tegra_screen *screen, 16901e04c3fSmrg struct tegra_resource *resource) 17001e04c3fSmrg{ 17101e04c3fSmrg struct winsys_handle handle; 1727ec681f3Smrg bool status; 17301e04c3fSmrg int fd, err; 17401e04c3fSmrg 17501e04c3fSmrg memset(&handle, 0, sizeof(handle)); 17601e04c3fSmrg handle.modifier = DRM_FORMAT_MOD_INVALID; 17701e04c3fSmrg handle.type = WINSYS_HANDLE_TYPE_FD; 17801e04c3fSmrg 17901e04c3fSmrg status = screen->gpu->resource_get_handle(screen->gpu, NULL, resource->gpu, 18001e04c3fSmrg &handle, 0); 18101e04c3fSmrg if (!status) 18201e04c3fSmrg return -EINVAL; 18301e04c3fSmrg 18401e04c3fSmrg assert(handle.modifier != DRM_FORMAT_MOD_INVALID); 18501e04c3fSmrg 18601e04c3fSmrg if (handle.modifier == DRM_FORMAT_MOD_INVALID) { 18701e04c3fSmrg close(handle.handle); 18801e04c3fSmrg return -EINVAL; 18901e04c3fSmrg } 19001e04c3fSmrg 19101e04c3fSmrg resource->modifier = handle.modifier; 19201e04c3fSmrg resource->stride = handle.stride; 19301e04c3fSmrg fd = handle.handle; 19401e04c3fSmrg 19501e04c3fSmrg err = drmPrimeFDToHandle(screen->fd, fd, &resource->handle); 19601e04c3fSmrg if (err < 0) 19701e04c3fSmrg err = -errno; 19801e04c3fSmrg 19901e04c3fSmrg close(fd); 20001e04c3fSmrg 20101e04c3fSmrg return err; 20201e04c3fSmrg} 20301e04c3fSmrg 20401e04c3fSmrgstatic struct pipe_resource * 20501e04c3fSmrgtegra_screen_resource_create(struct pipe_screen *pscreen, 20601e04c3fSmrg const struct pipe_resource *template) 20701e04c3fSmrg{ 20801e04c3fSmrg struct tegra_screen *screen = to_tegra_screen(pscreen); 20901e04c3fSmrg uint64_t modifier = DRM_FORMAT_MOD_INVALID; 21001e04c3fSmrg struct tegra_resource *resource; 21101e04c3fSmrg int err; 21201e04c3fSmrg 21301e04c3fSmrg resource = calloc(1, sizeof(*resource)); 21401e04c3fSmrg if (!resource) 21501e04c3fSmrg return NULL; 21601e04c3fSmrg 21701e04c3fSmrg /* 21801e04c3fSmrg * Applications that create scanout resources without modifiers are very 21901e04c3fSmrg * unlikely to support modifiers at all. In that case the resources need 22001e04c3fSmrg * to be created with a pitch-linear layout so that they can be properly 22101e04c3fSmrg * shared with scanout hardware. 22201e04c3fSmrg * 22301e04c3fSmrg * Technically it is possible for applications to create resources without 22401e04c3fSmrg * specifying a modifier but still query the modifier associated with the 22501e04c3fSmrg * resource (e.g. using gbm_bo_get_modifier()) before handing it to the 22601e04c3fSmrg * framebuffer creation API (such as the DRM_IOCTL_MODE_ADDFB2 IOCTL). 22701e04c3fSmrg */ 22801e04c3fSmrg if (template->bind & PIPE_BIND_SCANOUT) 22901e04c3fSmrg modifier = DRM_FORMAT_MOD_LINEAR; 23001e04c3fSmrg 23101e04c3fSmrg resource->gpu = screen->gpu->resource_create_with_modifiers(screen->gpu, 23201e04c3fSmrg template, 23301e04c3fSmrg &modifier, 1); 23401e04c3fSmrg if (!resource->gpu) 23501e04c3fSmrg goto free; 23601e04c3fSmrg 23701e04c3fSmrg /* import scanout buffers for display */ 23801e04c3fSmrg if (template->bind & PIPE_BIND_SCANOUT) { 23901e04c3fSmrg err = tegra_screen_import_resource(screen, resource); 24001e04c3fSmrg if (err < 0) 24101e04c3fSmrg goto destroy; 24201e04c3fSmrg } 24301e04c3fSmrg 24401e04c3fSmrg memcpy(&resource->base, resource->gpu, sizeof(*resource->gpu)); 24501e04c3fSmrg pipe_reference_init(&resource->base.reference, 1); 24601e04c3fSmrg resource->base.screen = &screen->base; 24701e04c3fSmrg 2487ec681f3Smrg /* use private reference count for wrapped resources */ 2497ec681f3Smrg resource->gpu->reference.count += 100000000; 2507ec681f3Smrg resource->refcount = 100000000; 2517ec681f3Smrg 25201e04c3fSmrg return &resource->base; 25301e04c3fSmrg 25401e04c3fSmrgdestroy: 25501e04c3fSmrg screen->gpu->resource_destroy(screen->gpu, resource->gpu); 25601e04c3fSmrgfree: 25701e04c3fSmrg free(resource); 25801e04c3fSmrg return NULL; 25901e04c3fSmrg} 26001e04c3fSmrg 26101e04c3fSmrg/* XXX */ 26201e04c3fSmrgstatic struct pipe_resource * 26301e04c3fSmrgtegra_screen_resource_create_front(struct pipe_screen *pscreen, 26401e04c3fSmrg const struct pipe_resource *template, 26501e04c3fSmrg const void *map_front_private) 26601e04c3fSmrg{ 26701e04c3fSmrg struct tegra_screen *screen = to_tegra_screen(pscreen); 26801e04c3fSmrg struct pipe_resource *resource; 26901e04c3fSmrg 27001e04c3fSmrg resource = screen->gpu->resource_create_front(screen->gpu, template, 27101e04c3fSmrg map_front_private); 27201e04c3fSmrg if (resource) 27301e04c3fSmrg resource->screen = pscreen; 27401e04c3fSmrg 27501e04c3fSmrg return resource; 27601e04c3fSmrg} 27701e04c3fSmrg 27801e04c3fSmrgstatic struct pipe_resource * 27901e04c3fSmrgtegra_screen_resource_from_handle(struct pipe_screen *pscreen, 28001e04c3fSmrg const struct pipe_resource *template, 28101e04c3fSmrg struct winsys_handle *handle, 28201e04c3fSmrg unsigned usage) 28301e04c3fSmrg{ 28401e04c3fSmrg struct tegra_screen *screen = to_tegra_screen(pscreen); 28501e04c3fSmrg struct tegra_resource *resource; 28601e04c3fSmrg 28701e04c3fSmrg resource = calloc(1, sizeof(*resource)); 28801e04c3fSmrg if (!resource) 28901e04c3fSmrg return NULL; 29001e04c3fSmrg 29101e04c3fSmrg resource->gpu = screen->gpu->resource_from_handle(screen->gpu, template, 29201e04c3fSmrg handle, usage); 29301e04c3fSmrg if (!resource->gpu) { 29401e04c3fSmrg free(resource); 29501e04c3fSmrg return NULL; 29601e04c3fSmrg } 29701e04c3fSmrg 29801e04c3fSmrg memcpy(&resource->base, resource->gpu, sizeof(*resource->gpu)); 29901e04c3fSmrg pipe_reference_init(&resource->base.reference, 1); 30001e04c3fSmrg resource->base.screen = &screen->base; 30101e04c3fSmrg 30201e04c3fSmrg return &resource->base; 30301e04c3fSmrg} 30401e04c3fSmrg 30501e04c3fSmrg/* XXX */ 30601e04c3fSmrgstatic struct pipe_resource * 30701e04c3fSmrgtegra_screen_resource_from_user_memory(struct pipe_screen *pscreen, 30801e04c3fSmrg const struct pipe_resource *template, 30901e04c3fSmrg void *buffer) 31001e04c3fSmrg{ 31101e04c3fSmrg struct tegra_screen *screen = to_tegra_screen(pscreen); 31201e04c3fSmrg struct pipe_resource *resource; 31301e04c3fSmrg 31401e04c3fSmrg resource = screen->gpu->resource_from_user_memory(screen->gpu, template, 31501e04c3fSmrg buffer); 31601e04c3fSmrg if (resource) 31701e04c3fSmrg resource->screen = pscreen; 31801e04c3fSmrg 31901e04c3fSmrg return resource; 32001e04c3fSmrg} 32101e04c3fSmrg 3227ec681f3Smrgstatic bool 32301e04c3fSmrgtegra_screen_resource_get_handle(struct pipe_screen *pscreen, 32401e04c3fSmrg struct pipe_context *pcontext, 32501e04c3fSmrg struct pipe_resource *presource, 32601e04c3fSmrg struct winsys_handle *handle, 32701e04c3fSmrg unsigned usage) 32801e04c3fSmrg{ 32901e04c3fSmrg struct tegra_resource *resource = to_tegra_resource(presource); 33001e04c3fSmrg struct tegra_context *context = to_tegra_context(pcontext); 33101e04c3fSmrg struct tegra_screen *screen = to_tegra_screen(pscreen); 3327ec681f3Smrg bool ret = true; 33301e04c3fSmrg 33401e04c3fSmrg /* 33501e04c3fSmrg * Assume that KMS handles for scanout resources will only ever be used 33601e04c3fSmrg * to pass buffers into Tegra DRM for display. In all other cases, return 33701e04c3fSmrg * the Nouveau handle, assuming they will be used for sharing in DRI2/3. 33801e04c3fSmrg */ 33901e04c3fSmrg if (handle->type == WINSYS_HANDLE_TYPE_KMS && 34001e04c3fSmrg presource->bind & PIPE_BIND_SCANOUT) { 34101e04c3fSmrg handle->modifier = resource->modifier; 34201e04c3fSmrg handle->handle = resource->handle; 34301e04c3fSmrg handle->stride = resource->stride; 34401e04c3fSmrg } else { 34501e04c3fSmrg ret = screen->gpu->resource_get_handle(screen->gpu, 34601e04c3fSmrg context ? context->gpu : NULL, 34701e04c3fSmrg resource->gpu, handle, usage); 34801e04c3fSmrg } 34901e04c3fSmrg 35001e04c3fSmrg return ret; 35101e04c3fSmrg} 35201e04c3fSmrg 35301e04c3fSmrgstatic void 35401e04c3fSmrgtegra_screen_resource_destroy(struct pipe_screen *pscreen, 35501e04c3fSmrg struct pipe_resource *presource) 35601e04c3fSmrg{ 35701e04c3fSmrg struct tegra_resource *resource = to_tegra_resource(presource); 35801e04c3fSmrg 3597ec681f3Smrg /* adjust private reference count */ 3607ec681f3Smrg p_atomic_add(&resource->gpu->reference.count, -resource->refcount); 36101e04c3fSmrg pipe_resource_reference(&resource->gpu, NULL); 36201e04c3fSmrg free(resource); 36301e04c3fSmrg} 36401e04c3fSmrg 36501e04c3fSmrgstatic void 36601e04c3fSmrgtegra_screen_flush_frontbuffer(struct pipe_screen *pscreen, 3677ec681f3Smrg struct pipe_context *pcontext, 36801e04c3fSmrg struct pipe_resource *resource, 36901e04c3fSmrg unsigned int level, 37001e04c3fSmrg unsigned int layer, 37101e04c3fSmrg void *winsys_drawable_handle, 37201e04c3fSmrg struct pipe_box *box) 37301e04c3fSmrg{ 37401e04c3fSmrg struct tegra_screen *screen = to_tegra_screen(pscreen); 3757ec681f3Smrg struct tegra_context *context = to_tegra_context(pcontext); 37601e04c3fSmrg 3777ec681f3Smrg screen->gpu->flush_frontbuffer(screen->gpu, 3787ec681f3Smrg context ? context->gpu : NULL, 3797ec681f3Smrg resource, level, layer, 38001e04c3fSmrg winsys_drawable_handle, box); 38101e04c3fSmrg} 38201e04c3fSmrg 38301e04c3fSmrgstatic void 38401e04c3fSmrgtegra_screen_fence_reference(struct pipe_screen *pscreen, 38501e04c3fSmrg struct pipe_fence_handle **ptr, 38601e04c3fSmrg struct pipe_fence_handle *fence) 38701e04c3fSmrg{ 38801e04c3fSmrg struct tegra_screen *screen = to_tegra_screen(pscreen); 38901e04c3fSmrg 39001e04c3fSmrg screen->gpu->fence_reference(screen->gpu, ptr, fence); 39101e04c3fSmrg} 39201e04c3fSmrg 3937ec681f3Smrgstatic bool 39401e04c3fSmrgtegra_screen_fence_finish(struct pipe_screen *pscreen, 39501e04c3fSmrg struct pipe_context *pcontext, 39601e04c3fSmrg struct pipe_fence_handle *fence, 39701e04c3fSmrg uint64_t timeout) 39801e04c3fSmrg{ 39901e04c3fSmrg struct tegra_context *context = to_tegra_context(pcontext); 40001e04c3fSmrg struct tegra_screen *screen = to_tegra_screen(pscreen); 40101e04c3fSmrg 40201e04c3fSmrg return screen->gpu->fence_finish(screen->gpu, 40301e04c3fSmrg context ? context->gpu : NULL, 40401e04c3fSmrg fence, timeout); 40501e04c3fSmrg} 40601e04c3fSmrg 40701e04c3fSmrgstatic int 40801e04c3fSmrgtegra_screen_fence_get_fd(struct pipe_screen *pscreen, 40901e04c3fSmrg struct pipe_fence_handle *fence) 41001e04c3fSmrg{ 41101e04c3fSmrg struct tegra_screen *screen = to_tegra_screen(pscreen); 41201e04c3fSmrg 41301e04c3fSmrg return screen->gpu->fence_get_fd(screen->gpu, fence); 41401e04c3fSmrg} 41501e04c3fSmrg 41601e04c3fSmrgstatic int 41701e04c3fSmrgtegra_screen_get_driver_query_info(struct pipe_screen *pscreen, 41801e04c3fSmrg unsigned int index, 41901e04c3fSmrg struct pipe_driver_query_info *info) 42001e04c3fSmrg{ 42101e04c3fSmrg struct tegra_screen *screen = to_tegra_screen(pscreen); 42201e04c3fSmrg 42301e04c3fSmrg return screen->gpu->get_driver_query_info(screen->gpu, index, info); 42401e04c3fSmrg} 42501e04c3fSmrg 42601e04c3fSmrgstatic int 42701e04c3fSmrgtegra_screen_get_driver_query_group_info(struct pipe_screen *pscreen, 42801e04c3fSmrg unsigned int index, 42901e04c3fSmrg struct pipe_driver_query_group_info *info) 43001e04c3fSmrg{ 43101e04c3fSmrg struct tegra_screen *screen = to_tegra_screen(pscreen); 43201e04c3fSmrg 43301e04c3fSmrg return screen->gpu->get_driver_query_group_info(screen->gpu, index, info); 43401e04c3fSmrg} 43501e04c3fSmrg 43601e04c3fSmrgstatic void 43701e04c3fSmrgtegra_screen_query_memory_info(struct pipe_screen *pscreen, 43801e04c3fSmrg struct pipe_memory_info *info) 43901e04c3fSmrg{ 44001e04c3fSmrg struct tegra_screen *screen = to_tegra_screen(pscreen); 44101e04c3fSmrg 44201e04c3fSmrg screen->gpu->query_memory_info(screen->gpu, info); 44301e04c3fSmrg} 44401e04c3fSmrg 44501e04c3fSmrgstatic const void * 44601e04c3fSmrgtegra_screen_get_compiler_options(struct pipe_screen *pscreen, 44701e04c3fSmrg enum pipe_shader_ir ir, 44801e04c3fSmrg unsigned int shader) 44901e04c3fSmrg{ 45001e04c3fSmrg struct tegra_screen *screen = to_tegra_screen(pscreen); 45101e04c3fSmrg const void *options = NULL; 45201e04c3fSmrg 45301e04c3fSmrg if (screen->gpu->get_compiler_options) 45401e04c3fSmrg options = screen->gpu->get_compiler_options(screen->gpu, ir, shader); 45501e04c3fSmrg 45601e04c3fSmrg return options; 45701e04c3fSmrg} 45801e04c3fSmrg 45901e04c3fSmrgstatic struct disk_cache * 46001e04c3fSmrgtegra_screen_get_disk_shader_cache(struct pipe_screen *pscreen) 46101e04c3fSmrg{ 46201e04c3fSmrg struct tegra_screen *screen = to_tegra_screen(pscreen); 46301e04c3fSmrg 46401e04c3fSmrg return screen->gpu->get_disk_shader_cache(screen->gpu); 46501e04c3fSmrg} 46601e04c3fSmrg 46701e04c3fSmrgstatic struct pipe_resource * 46801e04c3fSmrgtegra_screen_resource_create_with_modifiers(struct pipe_screen *pscreen, 46901e04c3fSmrg const struct pipe_resource *template, 47001e04c3fSmrg const uint64_t *modifiers, 47101e04c3fSmrg int count) 47201e04c3fSmrg{ 47301e04c3fSmrg struct tegra_screen *screen = to_tegra_screen(pscreen); 47401e04c3fSmrg struct pipe_resource tmpl = *template; 47501e04c3fSmrg struct tegra_resource *resource; 47601e04c3fSmrg int err; 47701e04c3fSmrg 47801e04c3fSmrg resource = calloc(1, sizeof(*resource)); 47901e04c3fSmrg if (!resource) 48001e04c3fSmrg return NULL; 48101e04c3fSmrg 48201e04c3fSmrg /* 48301e04c3fSmrg * Assume that resources created with modifiers will always be used for 48401e04c3fSmrg * scanout. This is necessary because some of the APIs that are used to 48501e04c3fSmrg * create resources with modifiers (e.g. gbm_bo_create_with_modifiers()) 48601e04c3fSmrg * can't pass along usage information. Adding that capability might be 48701e04c3fSmrg * worth adding to remove this ambiguity. Not all future use-cases that 48801e04c3fSmrg * involve modifiers may always be targetting scanout hardware. 48901e04c3fSmrg */ 49001e04c3fSmrg tmpl.bind |= PIPE_BIND_SCANOUT; 49101e04c3fSmrg 49201e04c3fSmrg resource->gpu = screen->gpu->resource_create_with_modifiers(screen->gpu, 49301e04c3fSmrg &tmpl, 49401e04c3fSmrg modifiers, 49501e04c3fSmrg count); 49601e04c3fSmrg if (!resource->gpu) 49701e04c3fSmrg goto free; 49801e04c3fSmrg 49901e04c3fSmrg err = tegra_screen_import_resource(screen, resource); 50001e04c3fSmrg if (err < 0) 50101e04c3fSmrg goto destroy; 50201e04c3fSmrg 50301e04c3fSmrg memcpy(&resource->base, resource->gpu, sizeof(*resource->gpu)); 50401e04c3fSmrg pipe_reference_init(&resource->base.reference, 1); 50501e04c3fSmrg resource->base.screen = &screen->base; 50601e04c3fSmrg 50701e04c3fSmrg return &resource->base; 50801e04c3fSmrg 50901e04c3fSmrgdestroy: 51001e04c3fSmrg screen->gpu->resource_destroy(screen->gpu, resource->gpu); 51101e04c3fSmrgfree: 51201e04c3fSmrg free(resource); 51301e04c3fSmrg return NULL; 51401e04c3fSmrg} 51501e04c3fSmrg 51601e04c3fSmrgstatic void tegra_screen_query_dmabuf_modifiers(struct pipe_screen *pscreen, 51701e04c3fSmrg enum pipe_format format, 51801e04c3fSmrg int max, uint64_t *modifiers, 51901e04c3fSmrg unsigned int *external_only, 52001e04c3fSmrg int *count) 52101e04c3fSmrg{ 52201e04c3fSmrg struct tegra_screen *screen = to_tegra_screen(pscreen); 52301e04c3fSmrg 52401e04c3fSmrg screen->gpu->query_dmabuf_modifiers(screen->gpu, format, max, modifiers, 52501e04c3fSmrg external_only, count); 52601e04c3fSmrg} 52701e04c3fSmrg 5287ec681f3Smrgstatic bool 5297ec681f3Smrgtegra_screen_is_dmabuf_modifier_supported(struct pipe_screen *pscreen, 5307ec681f3Smrg uint64_t modifier, 5317ec681f3Smrg enum pipe_format format, 5327ec681f3Smrg bool *external_only) 5337ec681f3Smrg{ 5347ec681f3Smrg struct tegra_screen *screen = to_tegra_screen(pscreen); 5357ec681f3Smrg 5367ec681f3Smrg return screen->gpu->is_dmabuf_modifier_supported(screen->gpu, modifier, 5377ec681f3Smrg format, external_only); 5387ec681f3Smrg} 5397ec681f3Smrg 5407ec681f3Smrgstatic unsigned int 5417ec681f3Smrgtegra_screen_get_dmabuf_modifier_planes(struct pipe_screen *pscreen, 5427ec681f3Smrg uint64_t modifier, 5437ec681f3Smrg enum pipe_format format) 5447ec681f3Smrg{ 5457ec681f3Smrg struct tegra_screen *screen = to_tegra_screen(pscreen); 5467ec681f3Smrg 5477ec681f3Smrg return screen->gpu->get_dmabuf_modifier_planes ? 5487ec681f3Smrg screen->gpu->get_dmabuf_modifier_planes(screen->gpu, modifier, format) : 5497ec681f3Smrg util_format_get_num_planes(format); 5507ec681f3Smrg} 5517ec681f3Smrg 55201e04c3fSmrgstatic struct pipe_memory_object * 55301e04c3fSmrgtegra_screen_memobj_create_from_handle(struct pipe_screen *pscreen, 55401e04c3fSmrg struct winsys_handle *handle, 55501e04c3fSmrg bool dedicated) 55601e04c3fSmrg{ 55701e04c3fSmrg struct tegra_screen *screen = to_tegra_screen(pscreen); 55801e04c3fSmrg 55901e04c3fSmrg return screen->gpu->memobj_create_from_handle(screen->gpu, handle, 56001e04c3fSmrg dedicated); 56101e04c3fSmrg} 56201e04c3fSmrg 56301e04c3fSmrgstruct pipe_screen * 56401e04c3fSmrgtegra_screen_create(int fd) 56501e04c3fSmrg{ 56601e04c3fSmrg struct tegra_screen *screen; 56701e04c3fSmrg 56801e04c3fSmrg screen = calloc(1, sizeof(*screen)); 56901e04c3fSmrg if (!screen) 57001e04c3fSmrg return NULL; 57101e04c3fSmrg 57201e04c3fSmrg screen->fd = fd; 57301e04c3fSmrg 57401e04c3fSmrg screen->gpu_fd = loader_open_render_node("nouveau"); 57501e04c3fSmrg if (screen->gpu_fd < 0) { 57601e04c3fSmrg if (errno != ENOENT) 57701e04c3fSmrg fprintf(stderr, "failed to open GPU device: %s\n", strerror(errno)); 57801e04c3fSmrg 57901e04c3fSmrg free(screen); 58001e04c3fSmrg return NULL; 58101e04c3fSmrg } 58201e04c3fSmrg 58301e04c3fSmrg screen->gpu = nouveau_drm_screen_create(screen->gpu_fd); 58401e04c3fSmrg if (!screen->gpu) { 58501e04c3fSmrg fprintf(stderr, "failed to create GPU screen\n"); 58601e04c3fSmrg close(screen->gpu_fd); 58701e04c3fSmrg free(screen); 58801e04c3fSmrg return NULL; 58901e04c3fSmrg } 59001e04c3fSmrg 59101e04c3fSmrg screen->base.destroy = tegra_screen_destroy; 59201e04c3fSmrg screen->base.get_name = tegra_screen_get_name; 59301e04c3fSmrg screen->base.get_vendor = tegra_screen_get_vendor; 59401e04c3fSmrg screen->base.get_device_vendor = tegra_screen_get_device_vendor; 59501e04c3fSmrg screen->base.get_param = tegra_screen_get_param; 59601e04c3fSmrg screen->base.get_paramf = tegra_screen_get_paramf; 59701e04c3fSmrg screen->base.get_shader_param = tegra_screen_get_shader_param; 59801e04c3fSmrg screen->base.get_video_param = tegra_screen_get_video_param; 59901e04c3fSmrg screen->base.get_compute_param = tegra_screen_get_compute_param; 60001e04c3fSmrg screen->base.get_timestamp = tegra_screen_get_timestamp; 60101e04c3fSmrg screen->base.context_create = tegra_screen_context_create; 60201e04c3fSmrg screen->base.is_format_supported = tegra_screen_is_format_supported; 60301e04c3fSmrg screen->base.is_video_format_supported = tegra_screen_is_video_format_supported; 60401e04c3fSmrg 60501e04c3fSmrg /* allow fallback implementation if GPU driver doesn't implement it */ 60601e04c3fSmrg if (screen->gpu->can_create_resource) 60701e04c3fSmrg screen->base.can_create_resource = tegra_screen_can_create_resource; 60801e04c3fSmrg 60901e04c3fSmrg screen->base.resource_create = tegra_screen_resource_create; 61001e04c3fSmrg screen->base.resource_create_front = tegra_screen_resource_create_front; 61101e04c3fSmrg screen->base.resource_from_handle = tegra_screen_resource_from_handle; 61201e04c3fSmrg screen->base.resource_from_user_memory = tegra_screen_resource_from_user_memory; 61301e04c3fSmrg screen->base.resource_get_handle = tegra_screen_resource_get_handle; 61401e04c3fSmrg screen->base.resource_destroy = tegra_screen_resource_destroy; 61501e04c3fSmrg 61601e04c3fSmrg screen->base.flush_frontbuffer = tegra_screen_flush_frontbuffer; 61701e04c3fSmrg screen->base.fence_reference = tegra_screen_fence_reference; 61801e04c3fSmrg screen->base.fence_finish = tegra_screen_fence_finish; 61901e04c3fSmrg screen->base.fence_get_fd = tegra_screen_fence_get_fd; 62001e04c3fSmrg 62101e04c3fSmrg screen->base.get_driver_query_info = tegra_screen_get_driver_query_info; 62201e04c3fSmrg screen->base.get_driver_query_group_info = tegra_screen_get_driver_query_group_info; 62301e04c3fSmrg screen->base.query_memory_info = tegra_screen_query_memory_info; 62401e04c3fSmrg 62501e04c3fSmrg screen->base.get_compiler_options = tegra_screen_get_compiler_options; 62601e04c3fSmrg screen->base.get_disk_shader_cache = tegra_screen_get_disk_shader_cache; 62701e04c3fSmrg 62801e04c3fSmrg screen->base.resource_create_with_modifiers = tegra_screen_resource_create_with_modifiers; 62901e04c3fSmrg screen->base.query_dmabuf_modifiers = tegra_screen_query_dmabuf_modifiers; 6307ec681f3Smrg screen->base.is_dmabuf_modifier_supported = tegra_screen_is_dmabuf_modifier_supported; 6317ec681f3Smrg screen->base.get_dmabuf_modifier_planes = tegra_screen_get_dmabuf_modifier_planes; 63201e04c3fSmrg screen->base.memobj_create_from_handle = tegra_screen_memobj_create_from_handle; 63301e04c3fSmrg 63401e04c3fSmrg return &screen->base; 63501e04c3fSmrg} 636