1b8e80941Smrg/* 2b8e80941Smrg * Copyright © 2014-2018 NVIDIA Corporation 3b8e80941Smrg * 4b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5b8e80941Smrg * copy of this software and associated documentation files (the "Software"), 6b8e80941Smrg * to deal in the Software without restriction, including without limitation 7b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the 9b8e80941Smrg * Software is furnished to do so, subject to the following conditions: 10b8e80941Smrg * 11b8e80941Smrg * The above copyright notice and this permission notice (including the next 12b8e80941Smrg * paragraph) shall be included in all copies or substantial portions of the 13b8e80941Smrg * Software. 14b8e80941Smrg * 15b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18b8e80941Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19b8e80941Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20b8e80941Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21b8e80941Smrg * IN THE SOFTWARE. 22b8e80941Smrg */ 23b8e80941Smrg 24b8e80941Smrg#include <errno.h> 25b8e80941Smrg#include <fcntl.h> 26b8e80941Smrg#include <inttypes.h> 27b8e80941Smrg#include <stdio.h> 28b8e80941Smrg 29b8e80941Smrg#include <sys/stat.h> 30b8e80941Smrg 31b8e80941Smrg#include "drm-uapi/drm_fourcc.h" 32b8e80941Smrg#include "drm-uapi/tegra_drm.h" 33b8e80941Smrg#include <xf86drm.h> 34b8e80941Smrg 35b8e80941Smrg#include "loader/loader.h" 36b8e80941Smrg#include "pipe/p_state.h" 37b8e80941Smrg#include "util/u_debug.h" 38b8e80941Smrg#include "util/u_inlines.h" 39b8e80941Smrg 40b8e80941Smrg#include "state_tracker/drm_driver.h" 41b8e80941Smrg 42b8e80941Smrg#include "nouveau/drm/nouveau_drm_public.h" 43b8e80941Smrg 44b8e80941Smrg#include "tegra_context.h" 45b8e80941Smrg#include "tegra_resource.h" 46b8e80941Smrg#include "tegra_screen.h" 47b8e80941Smrg 48b8e80941Smrgstatic void tegra_screen_destroy(struct pipe_screen *pscreen) 49b8e80941Smrg{ 50b8e80941Smrg struct tegra_screen *screen = to_tegra_screen(pscreen); 51b8e80941Smrg 52b8e80941Smrg screen->gpu->destroy(screen->gpu); 53b8e80941Smrg free(pscreen); 54b8e80941Smrg} 55b8e80941Smrg 56b8e80941Smrgstatic const char * 57b8e80941Smrgtegra_screen_get_name(struct pipe_screen *pscreen) 58b8e80941Smrg{ 59b8e80941Smrg return "tegra"; 60b8e80941Smrg} 61b8e80941Smrg 62b8e80941Smrgstatic const char * 63b8e80941Smrgtegra_screen_get_vendor(struct pipe_screen *pscreen) 64b8e80941Smrg{ 65b8e80941Smrg return "NVIDIA"; 66b8e80941Smrg} 67b8e80941Smrg 68b8e80941Smrgstatic const char * 69b8e80941Smrgtegra_screen_get_device_vendor(struct pipe_screen *pscreen) 70b8e80941Smrg{ 71b8e80941Smrg return "NVIDIA"; 72b8e80941Smrg} 73b8e80941Smrg 74b8e80941Smrgstatic int 75b8e80941Smrgtegra_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) 76b8e80941Smrg{ 77b8e80941Smrg struct tegra_screen *screen = to_tegra_screen(pscreen); 78b8e80941Smrg 79b8e80941Smrg return screen->gpu->get_param(screen->gpu, param); 80b8e80941Smrg} 81b8e80941Smrg 82b8e80941Smrgstatic float 83b8e80941Smrgtegra_screen_get_paramf(struct pipe_screen *pscreen, enum pipe_capf param) 84b8e80941Smrg{ 85b8e80941Smrg struct tegra_screen *screen = to_tegra_screen(pscreen); 86b8e80941Smrg 87b8e80941Smrg return screen->gpu->get_paramf(screen->gpu, param); 88b8e80941Smrg} 89b8e80941Smrg 90b8e80941Smrgstatic int 91b8e80941Smrgtegra_screen_get_shader_param(struct pipe_screen *pscreen, unsigned shader, 92b8e80941Smrg enum pipe_shader_cap param) 93b8e80941Smrg{ 94b8e80941Smrg struct tegra_screen *screen = to_tegra_screen(pscreen); 95b8e80941Smrg 96b8e80941Smrg return screen->gpu->get_shader_param(screen->gpu, shader, param); 97b8e80941Smrg} 98b8e80941Smrg 99b8e80941Smrgstatic int 100b8e80941Smrgtegra_screen_get_video_param(struct pipe_screen *pscreen, 101b8e80941Smrg enum pipe_video_profile profile, 102b8e80941Smrg enum pipe_video_entrypoint entrypoint, 103b8e80941Smrg enum pipe_video_cap param) 104b8e80941Smrg{ 105b8e80941Smrg struct tegra_screen *screen = to_tegra_screen(pscreen); 106b8e80941Smrg 107b8e80941Smrg return screen->gpu->get_video_param(screen->gpu, profile, entrypoint, 108b8e80941Smrg param); 109b8e80941Smrg} 110b8e80941Smrg 111b8e80941Smrgstatic int 112b8e80941Smrgtegra_screen_get_compute_param(struct pipe_screen *pscreen, 113b8e80941Smrg enum pipe_shader_ir ir_type, 114b8e80941Smrg enum pipe_compute_cap param, 115b8e80941Smrg void *retp) 116b8e80941Smrg{ 117b8e80941Smrg struct tegra_screen *screen = to_tegra_screen(pscreen); 118b8e80941Smrg 119b8e80941Smrg return screen->gpu->get_compute_param(screen->gpu, ir_type, param, 120b8e80941Smrg retp); 121b8e80941Smrg} 122b8e80941Smrg 123b8e80941Smrgstatic uint64_t 124b8e80941Smrgtegra_screen_get_timestamp(struct pipe_screen *pscreen) 125b8e80941Smrg{ 126b8e80941Smrg struct tegra_screen *screen = to_tegra_screen(pscreen); 127b8e80941Smrg 128b8e80941Smrg return screen->gpu->get_timestamp(screen->gpu); 129b8e80941Smrg} 130b8e80941Smrg 131b8e80941Smrgstatic boolean 132b8e80941Smrgtegra_screen_is_format_supported(struct pipe_screen *pscreen, 133b8e80941Smrg enum pipe_format format, 134b8e80941Smrg enum pipe_texture_target target, 135b8e80941Smrg unsigned sample_count, 136b8e80941Smrg unsigned storage_sample_count, 137b8e80941Smrg unsigned usage) 138b8e80941Smrg{ 139b8e80941Smrg struct tegra_screen *screen = to_tegra_screen(pscreen); 140b8e80941Smrg 141b8e80941Smrg return screen->gpu->is_format_supported(screen->gpu, format, target, 142b8e80941Smrg sample_count, storage_sample_count, 143b8e80941Smrg usage); 144b8e80941Smrg} 145b8e80941Smrg 146b8e80941Smrgstatic boolean 147b8e80941Smrgtegra_screen_is_video_format_supported(struct pipe_screen *pscreen, 148b8e80941Smrg enum pipe_format format, 149b8e80941Smrg enum pipe_video_profile profile, 150b8e80941Smrg enum pipe_video_entrypoint entrypoint) 151b8e80941Smrg{ 152b8e80941Smrg struct tegra_screen *screen = to_tegra_screen(pscreen); 153b8e80941Smrg 154b8e80941Smrg return screen->gpu->is_video_format_supported(screen->gpu, format, profile, 155b8e80941Smrg entrypoint); 156b8e80941Smrg} 157b8e80941Smrg 158b8e80941Smrgstatic boolean 159b8e80941Smrgtegra_screen_can_create_resource(struct pipe_screen *pscreen, 160b8e80941Smrg const struct pipe_resource *template) 161b8e80941Smrg{ 162b8e80941Smrg struct tegra_screen *screen = to_tegra_screen(pscreen); 163b8e80941Smrg 164b8e80941Smrg return screen->gpu->can_create_resource(screen->gpu, template); 165b8e80941Smrg} 166b8e80941Smrg 167b8e80941Smrgstatic int tegra_screen_import_resource(struct tegra_screen *screen, 168b8e80941Smrg struct tegra_resource *resource) 169b8e80941Smrg{ 170b8e80941Smrg struct winsys_handle handle; 171b8e80941Smrg boolean status; 172b8e80941Smrg int fd, err; 173b8e80941Smrg 174b8e80941Smrg memset(&handle, 0, sizeof(handle)); 175b8e80941Smrg handle.modifier = DRM_FORMAT_MOD_INVALID; 176b8e80941Smrg handle.type = WINSYS_HANDLE_TYPE_FD; 177b8e80941Smrg 178b8e80941Smrg status = screen->gpu->resource_get_handle(screen->gpu, NULL, resource->gpu, 179b8e80941Smrg &handle, 0); 180b8e80941Smrg if (!status) 181b8e80941Smrg return -EINVAL; 182b8e80941Smrg 183b8e80941Smrg assert(handle.modifier != DRM_FORMAT_MOD_INVALID); 184b8e80941Smrg 185b8e80941Smrg if (handle.modifier == DRM_FORMAT_MOD_INVALID) { 186b8e80941Smrg close(handle.handle); 187b8e80941Smrg return -EINVAL; 188b8e80941Smrg } 189b8e80941Smrg 190b8e80941Smrg resource->modifier = handle.modifier; 191b8e80941Smrg resource->stride = handle.stride; 192b8e80941Smrg fd = handle.handle; 193b8e80941Smrg 194b8e80941Smrg err = drmPrimeFDToHandle(screen->fd, fd, &resource->handle); 195b8e80941Smrg if (err < 0) 196b8e80941Smrg err = -errno; 197b8e80941Smrg 198b8e80941Smrg close(fd); 199b8e80941Smrg 200b8e80941Smrg return err; 201b8e80941Smrg} 202b8e80941Smrg 203b8e80941Smrgstatic struct pipe_resource * 204b8e80941Smrgtegra_screen_resource_create(struct pipe_screen *pscreen, 205b8e80941Smrg const struct pipe_resource *template) 206b8e80941Smrg{ 207b8e80941Smrg struct tegra_screen *screen = to_tegra_screen(pscreen); 208b8e80941Smrg uint64_t modifier = DRM_FORMAT_MOD_INVALID; 209b8e80941Smrg struct tegra_resource *resource; 210b8e80941Smrg int err; 211b8e80941Smrg 212b8e80941Smrg resource = calloc(1, sizeof(*resource)); 213b8e80941Smrg if (!resource) 214b8e80941Smrg return NULL; 215b8e80941Smrg 216b8e80941Smrg /* 217b8e80941Smrg * Applications that create scanout resources without modifiers are very 218b8e80941Smrg * unlikely to support modifiers at all. In that case the resources need 219b8e80941Smrg * to be created with a pitch-linear layout so that they can be properly 220b8e80941Smrg * shared with scanout hardware. 221b8e80941Smrg * 222b8e80941Smrg * Technically it is possible for applications to create resources without 223b8e80941Smrg * specifying a modifier but still query the modifier associated with the 224b8e80941Smrg * resource (e.g. using gbm_bo_get_modifier()) before handing it to the 225b8e80941Smrg * framebuffer creation API (such as the DRM_IOCTL_MODE_ADDFB2 IOCTL). 226b8e80941Smrg */ 227b8e80941Smrg if (template->bind & PIPE_BIND_SCANOUT) 228b8e80941Smrg modifier = DRM_FORMAT_MOD_LINEAR; 229b8e80941Smrg 230b8e80941Smrg resource->gpu = screen->gpu->resource_create_with_modifiers(screen->gpu, 231b8e80941Smrg template, 232b8e80941Smrg &modifier, 1); 233b8e80941Smrg if (!resource->gpu) 234b8e80941Smrg goto free; 235b8e80941Smrg 236b8e80941Smrg /* import scanout buffers for display */ 237b8e80941Smrg if (template->bind & PIPE_BIND_SCANOUT) { 238b8e80941Smrg err = tegra_screen_import_resource(screen, resource); 239b8e80941Smrg if (err < 0) 240b8e80941Smrg goto destroy; 241b8e80941Smrg } 242b8e80941Smrg 243b8e80941Smrg memcpy(&resource->base, resource->gpu, sizeof(*resource->gpu)); 244b8e80941Smrg pipe_reference_init(&resource->base.reference, 1); 245b8e80941Smrg resource->base.screen = &screen->base; 246b8e80941Smrg 247b8e80941Smrg return &resource->base; 248b8e80941Smrg 249b8e80941Smrgdestroy: 250b8e80941Smrg screen->gpu->resource_destroy(screen->gpu, resource->gpu); 251b8e80941Smrgfree: 252b8e80941Smrg free(resource); 253b8e80941Smrg return NULL; 254b8e80941Smrg} 255b8e80941Smrg 256b8e80941Smrg/* XXX */ 257b8e80941Smrgstatic struct pipe_resource * 258b8e80941Smrgtegra_screen_resource_create_front(struct pipe_screen *pscreen, 259b8e80941Smrg const struct pipe_resource *template, 260b8e80941Smrg const void *map_front_private) 261b8e80941Smrg{ 262b8e80941Smrg struct tegra_screen *screen = to_tegra_screen(pscreen); 263b8e80941Smrg struct pipe_resource *resource; 264b8e80941Smrg 265b8e80941Smrg resource = screen->gpu->resource_create_front(screen->gpu, template, 266b8e80941Smrg map_front_private); 267b8e80941Smrg if (resource) 268b8e80941Smrg resource->screen = pscreen; 269b8e80941Smrg 270b8e80941Smrg return resource; 271b8e80941Smrg} 272b8e80941Smrg 273b8e80941Smrgstatic struct pipe_resource * 274b8e80941Smrgtegra_screen_resource_from_handle(struct pipe_screen *pscreen, 275b8e80941Smrg const struct pipe_resource *template, 276b8e80941Smrg struct winsys_handle *handle, 277b8e80941Smrg unsigned usage) 278b8e80941Smrg{ 279b8e80941Smrg struct tegra_screen *screen = to_tegra_screen(pscreen); 280b8e80941Smrg struct tegra_resource *resource; 281b8e80941Smrg 282b8e80941Smrg resource = calloc(1, sizeof(*resource)); 283b8e80941Smrg if (!resource) 284b8e80941Smrg return NULL; 285b8e80941Smrg 286b8e80941Smrg resource->gpu = screen->gpu->resource_from_handle(screen->gpu, template, 287b8e80941Smrg handle, usage); 288b8e80941Smrg if (!resource->gpu) { 289b8e80941Smrg free(resource); 290b8e80941Smrg return NULL; 291b8e80941Smrg } 292b8e80941Smrg 293b8e80941Smrg memcpy(&resource->base, resource->gpu, sizeof(*resource->gpu)); 294b8e80941Smrg pipe_reference_init(&resource->base.reference, 1); 295b8e80941Smrg resource->base.screen = &screen->base; 296b8e80941Smrg 297b8e80941Smrg return &resource->base; 298b8e80941Smrg} 299b8e80941Smrg 300b8e80941Smrg/* XXX */ 301b8e80941Smrgstatic struct pipe_resource * 302b8e80941Smrgtegra_screen_resource_from_user_memory(struct pipe_screen *pscreen, 303b8e80941Smrg const struct pipe_resource *template, 304b8e80941Smrg void *buffer) 305b8e80941Smrg{ 306b8e80941Smrg struct tegra_screen *screen = to_tegra_screen(pscreen); 307b8e80941Smrg struct pipe_resource *resource; 308b8e80941Smrg 309b8e80941Smrg resource = screen->gpu->resource_from_user_memory(screen->gpu, template, 310b8e80941Smrg buffer); 311b8e80941Smrg if (resource) 312b8e80941Smrg resource->screen = pscreen; 313b8e80941Smrg 314b8e80941Smrg return resource; 315b8e80941Smrg} 316b8e80941Smrg 317b8e80941Smrgstatic boolean 318b8e80941Smrgtegra_screen_resource_get_handle(struct pipe_screen *pscreen, 319b8e80941Smrg struct pipe_context *pcontext, 320b8e80941Smrg struct pipe_resource *presource, 321b8e80941Smrg struct winsys_handle *handle, 322b8e80941Smrg unsigned usage) 323b8e80941Smrg{ 324b8e80941Smrg struct tegra_resource *resource = to_tegra_resource(presource); 325b8e80941Smrg struct tegra_context *context = to_tegra_context(pcontext); 326b8e80941Smrg struct tegra_screen *screen = to_tegra_screen(pscreen); 327b8e80941Smrg boolean ret = TRUE; 328b8e80941Smrg 329b8e80941Smrg /* 330b8e80941Smrg * Assume that KMS handles for scanout resources will only ever be used 331b8e80941Smrg * to pass buffers into Tegra DRM for display. In all other cases, return 332b8e80941Smrg * the Nouveau handle, assuming they will be used for sharing in DRI2/3. 333b8e80941Smrg */ 334b8e80941Smrg if (handle->type == WINSYS_HANDLE_TYPE_KMS && 335b8e80941Smrg presource->bind & PIPE_BIND_SCANOUT) { 336b8e80941Smrg handle->modifier = resource->modifier; 337b8e80941Smrg handle->handle = resource->handle; 338b8e80941Smrg handle->stride = resource->stride; 339b8e80941Smrg } else { 340b8e80941Smrg ret = screen->gpu->resource_get_handle(screen->gpu, 341b8e80941Smrg context ? context->gpu : NULL, 342b8e80941Smrg resource->gpu, handle, usage); 343b8e80941Smrg } 344b8e80941Smrg 345b8e80941Smrg return ret; 346b8e80941Smrg} 347b8e80941Smrg 348b8e80941Smrgstatic void 349b8e80941Smrgtegra_screen_resource_destroy(struct pipe_screen *pscreen, 350b8e80941Smrg struct pipe_resource *presource) 351b8e80941Smrg{ 352b8e80941Smrg struct tegra_resource *resource = to_tegra_resource(presource); 353b8e80941Smrg 354b8e80941Smrg pipe_resource_reference(&resource->gpu, NULL); 355b8e80941Smrg free(resource); 356b8e80941Smrg} 357b8e80941Smrg 358b8e80941Smrgstatic void 359b8e80941Smrgtegra_screen_flush_frontbuffer(struct pipe_screen *pscreen, 360b8e80941Smrg struct pipe_resource *resource, 361b8e80941Smrg unsigned int level, 362b8e80941Smrg unsigned int layer, 363b8e80941Smrg void *winsys_drawable_handle, 364b8e80941Smrg struct pipe_box *box) 365b8e80941Smrg{ 366b8e80941Smrg struct tegra_screen *screen = to_tegra_screen(pscreen); 367b8e80941Smrg 368b8e80941Smrg screen->gpu->flush_frontbuffer(screen->gpu, resource, level, layer, 369b8e80941Smrg winsys_drawable_handle, box); 370b8e80941Smrg} 371b8e80941Smrg 372b8e80941Smrgstatic void 373b8e80941Smrgtegra_screen_fence_reference(struct pipe_screen *pscreen, 374b8e80941Smrg struct pipe_fence_handle **ptr, 375b8e80941Smrg struct pipe_fence_handle *fence) 376b8e80941Smrg{ 377b8e80941Smrg struct tegra_screen *screen = to_tegra_screen(pscreen); 378b8e80941Smrg 379b8e80941Smrg screen->gpu->fence_reference(screen->gpu, ptr, fence); 380b8e80941Smrg} 381b8e80941Smrg 382b8e80941Smrgstatic boolean 383b8e80941Smrgtegra_screen_fence_finish(struct pipe_screen *pscreen, 384b8e80941Smrg struct pipe_context *pcontext, 385b8e80941Smrg struct pipe_fence_handle *fence, 386b8e80941Smrg uint64_t timeout) 387b8e80941Smrg{ 388b8e80941Smrg struct tegra_context *context = to_tegra_context(pcontext); 389b8e80941Smrg struct tegra_screen *screen = to_tegra_screen(pscreen); 390b8e80941Smrg 391b8e80941Smrg return screen->gpu->fence_finish(screen->gpu, 392b8e80941Smrg context ? context->gpu : NULL, 393b8e80941Smrg fence, timeout); 394b8e80941Smrg} 395b8e80941Smrg 396b8e80941Smrgstatic int 397b8e80941Smrgtegra_screen_fence_get_fd(struct pipe_screen *pscreen, 398b8e80941Smrg struct pipe_fence_handle *fence) 399b8e80941Smrg{ 400b8e80941Smrg struct tegra_screen *screen = to_tegra_screen(pscreen); 401b8e80941Smrg 402b8e80941Smrg return screen->gpu->fence_get_fd(screen->gpu, fence); 403b8e80941Smrg} 404b8e80941Smrg 405b8e80941Smrgstatic int 406b8e80941Smrgtegra_screen_get_driver_query_info(struct pipe_screen *pscreen, 407b8e80941Smrg unsigned int index, 408b8e80941Smrg struct pipe_driver_query_info *info) 409b8e80941Smrg{ 410b8e80941Smrg struct tegra_screen *screen = to_tegra_screen(pscreen); 411b8e80941Smrg 412b8e80941Smrg return screen->gpu->get_driver_query_info(screen->gpu, index, info); 413b8e80941Smrg} 414b8e80941Smrg 415b8e80941Smrgstatic int 416b8e80941Smrgtegra_screen_get_driver_query_group_info(struct pipe_screen *pscreen, 417b8e80941Smrg unsigned int index, 418b8e80941Smrg struct pipe_driver_query_group_info *info) 419b8e80941Smrg{ 420b8e80941Smrg struct tegra_screen *screen = to_tegra_screen(pscreen); 421b8e80941Smrg 422b8e80941Smrg return screen->gpu->get_driver_query_group_info(screen->gpu, index, info); 423b8e80941Smrg} 424b8e80941Smrg 425b8e80941Smrgstatic void 426b8e80941Smrgtegra_screen_query_memory_info(struct pipe_screen *pscreen, 427b8e80941Smrg struct pipe_memory_info *info) 428b8e80941Smrg{ 429b8e80941Smrg struct tegra_screen *screen = to_tegra_screen(pscreen); 430b8e80941Smrg 431b8e80941Smrg screen->gpu->query_memory_info(screen->gpu, info); 432b8e80941Smrg} 433b8e80941Smrg 434b8e80941Smrgstatic const void * 435b8e80941Smrgtegra_screen_get_compiler_options(struct pipe_screen *pscreen, 436b8e80941Smrg enum pipe_shader_ir ir, 437b8e80941Smrg unsigned int shader) 438b8e80941Smrg{ 439b8e80941Smrg struct tegra_screen *screen = to_tegra_screen(pscreen); 440b8e80941Smrg const void *options = NULL; 441b8e80941Smrg 442b8e80941Smrg if (screen->gpu->get_compiler_options) 443b8e80941Smrg options = screen->gpu->get_compiler_options(screen->gpu, ir, shader); 444b8e80941Smrg 445b8e80941Smrg return options; 446b8e80941Smrg} 447b8e80941Smrg 448b8e80941Smrgstatic struct disk_cache * 449b8e80941Smrgtegra_screen_get_disk_shader_cache(struct pipe_screen *pscreen) 450b8e80941Smrg{ 451b8e80941Smrg struct tegra_screen *screen = to_tegra_screen(pscreen); 452b8e80941Smrg 453b8e80941Smrg return screen->gpu->get_disk_shader_cache(screen->gpu); 454b8e80941Smrg} 455b8e80941Smrg 456b8e80941Smrgstatic struct pipe_resource * 457b8e80941Smrgtegra_screen_resource_create_with_modifiers(struct pipe_screen *pscreen, 458b8e80941Smrg const struct pipe_resource *template, 459b8e80941Smrg const uint64_t *modifiers, 460b8e80941Smrg int count) 461b8e80941Smrg{ 462b8e80941Smrg struct tegra_screen *screen = to_tegra_screen(pscreen); 463b8e80941Smrg struct pipe_resource tmpl = *template; 464b8e80941Smrg struct tegra_resource *resource; 465b8e80941Smrg int err; 466b8e80941Smrg 467b8e80941Smrg resource = calloc(1, sizeof(*resource)); 468b8e80941Smrg if (!resource) 469b8e80941Smrg return NULL; 470b8e80941Smrg 471b8e80941Smrg /* 472b8e80941Smrg * Assume that resources created with modifiers will always be used for 473b8e80941Smrg * scanout. This is necessary because some of the APIs that are used to 474b8e80941Smrg * create resources with modifiers (e.g. gbm_bo_create_with_modifiers()) 475b8e80941Smrg * can't pass along usage information. Adding that capability might be 476b8e80941Smrg * worth adding to remove this ambiguity. Not all future use-cases that 477b8e80941Smrg * involve modifiers may always be targetting scanout hardware. 478b8e80941Smrg */ 479b8e80941Smrg tmpl.bind |= PIPE_BIND_SCANOUT; 480b8e80941Smrg 481b8e80941Smrg resource->gpu = screen->gpu->resource_create_with_modifiers(screen->gpu, 482b8e80941Smrg &tmpl, 483b8e80941Smrg modifiers, 484b8e80941Smrg count); 485b8e80941Smrg if (!resource->gpu) 486b8e80941Smrg goto free; 487b8e80941Smrg 488b8e80941Smrg err = tegra_screen_import_resource(screen, resource); 489b8e80941Smrg if (err < 0) 490b8e80941Smrg goto destroy; 491b8e80941Smrg 492b8e80941Smrg memcpy(&resource->base, resource->gpu, sizeof(*resource->gpu)); 493b8e80941Smrg pipe_reference_init(&resource->base.reference, 1); 494b8e80941Smrg resource->base.screen = &screen->base; 495b8e80941Smrg 496b8e80941Smrg return &resource->base; 497b8e80941Smrg 498b8e80941Smrgdestroy: 499b8e80941Smrg screen->gpu->resource_destroy(screen->gpu, resource->gpu); 500b8e80941Smrgfree: 501b8e80941Smrg free(resource); 502b8e80941Smrg return NULL; 503b8e80941Smrg} 504b8e80941Smrg 505b8e80941Smrgstatic void tegra_screen_query_dmabuf_modifiers(struct pipe_screen *pscreen, 506b8e80941Smrg enum pipe_format format, 507b8e80941Smrg int max, uint64_t *modifiers, 508b8e80941Smrg unsigned int *external_only, 509b8e80941Smrg int *count) 510b8e80941Smrg{ 511b8e80941Smrg struct tegra_screen *screen = to_tegra_screen(pscreen); 512b8e80941Smrg 513b8e80941Smrg screen->gpu->query_dmabuf_modifiers(screen->gpu, format, max, modifiers, 514b8e80941Smrg external_only, count); 515b8e80941Smrg} 516b8e80941Smrg 517b8e80941Smrgstatic struct pipe_memory_object * 518b8e80941Smrgtegra_screen_memobj_create_from_handle(struct pipe_screen *pscreen, 519b8e80941Smrg struct winsys_handle *handle, 520b8e80941Smrg bool dedicated) 521b8e80941Smrg{ 522b8e80941Smrg struct tegra_screen *screen = to_tegra_screen(pscreen); 523b8e80941Smrg 524b8e80941Smrg return screen->gpu->memobj_create_from_handle(screen->gpu, handle, 525b8e80941Smrg dedicated); 526b8e80941Smrg} 527b8e80941Smrg 528b8e80941Smrgstruct pipe_screen * 529b8e80941Smrgtegra_screen_create(int fd) 530b8e80941Smrg{ 531b8e80941Smrg struct tegra_screen *screen; 532b8e80941Smrg 533b8e80941Smrg screen = calloc(1, sizeof(*screen)); 534b8e80941Smrg if (!screen) 535b8e80941Smrg return NULL; 536b8e80941Smrg 537b8e80941Smrg screen->fd = fd; 538b8e80941Smrg 539b8e80941Smrg screen->gpu_fd = loader_open_render_node("nouveau"); 540b8e80941Smrg if (screen->gpu_fd < 0) { 541b8e80941Smrg if (errno != ENOENT) 542b8e80941Smrg fprintf(stderr, "failed to open GPU device: %s\n", strerror(errno)); 543b8e80941Smrg 544b8e80941Smrg free(screen); 545b8e80941Smrg return NULL; 546b8e80941Smrg } 547b8e80941Smrg 548b8e80941Smrg screen->gpu = nouveau_drm_screen_create(screen->gpu_fd); 549b8e80941Smrg if (!screen->gpu) { 550b8e80941Smrg fprintf(stderr, "failed to create GPU screen\n"); 551b8e80941Smrg close(screen->gpu_fd); 552b8e80941Smrg free(screen); 553b8e80941Smrg return NULL; 554b8e80941Smrg } 555b8e80941Smrg 556b8e80941Smrg screen->base.destroy = tegra_screen_destroy; 557b8e80941Smrg screen->base.get_name = tegra_screen_get_name; 558b8e80941Smrg screen->base.get_vendor = tegra_screen_get_vendor; 559b8e80941Smrg screen->base.get_device_vendor = tegra_screen_get_device_vendor; 560b8e80941Smrg screen->base.get_param = tegra_screen_get_param; 561b8e80941Smrg screen->base.get_paramf = tegra_screen_get_paramf; 562b8e80941Smrg screen->base.get_shader_param = tegra_screen_get_shader_param; 563b8e80941Smrg screen->base.get_video_param = tegra_screen_get_video_param; 564b8e80941Smrg screen->base.get_compute_param = tegra_screen_get_compute_param; 565b8e80941Smrg screen->base.get_timestamp = tegra_screen_get_timestamp; 566b8e80941Smrg screen->base.context_create = tegra_screen_context_create; 567b8e80941Smrg screen->base.is_format_supported = tegra_screen_is_format_supported; 568b8e80941Smrg screen->base.is_video_format_supported = tegra_screen_is_video_format_supported; 569b8e80941Smrg 570b8e80941Smrg /* allow fallback implementation if GPU driver doesn't implement it */ 571b8e80941Smrg if (screen->gpu->can_create_resource) 572b8e80941Smrg screen->base.can_create_resource = tegra_screen_can_create_resource; 573b8e80941Smrg 574b8e80941Smrg screen->base.resource_create = tegra_screen_resource_create; 575b8e80941Smrg screen->base.resource_create_front = tegra_screen_resource_create_front; 576b8e80941Smrg screen->base.resource_from_handle = tegra_screen_resource_from_handle; 577b8e80941Smrg screen->base.resource_from_user_memory = tegra_screen_resource_from_user_memory; 578b8e80941Smrg screen->base.resource_get_handle = tegra_screen_resource_get_handle; 579b8e80941Smrg screen->base.resource_destroy = tegra_screen_resource_destroy; 580b8e80941Smrg 581b8e80941Smrg screen->base.flush_frontbuffer = tegra_screen_flush_frontbuffer; 582b8e80941Smrg screen->base.fence_reference = tegra_screen_fence_reference; 583b8e80941Smrg screen->base.fence_finish = tegra_screen_fence_finish; 584b8e80941Smrg screen->base.fence_get_fd = tegra_screen_fence_get_fd; 585b8e80941Smrg 586b8e80941Smrg screen->base.get_driver_query_info = tegra_screen_get_driver_query_info; 587b8e80941Smrg screen->base.get_driver_query_group_info = tegra_screen_get_driver_query_group_info; 588b8e80941Smrg screen->base.query_memory_info = tegra_screen_query_memory_info; 589b8e80941Smrg 590b8e80941Smrg screen->base.get_compiler_options = tegra_screen_get_compiler_options; 591b8e80941Smrg screen->base.get_disk_shader_cache = tegra_screen_get_disk_shader_cache; 592b8e80941Smrg 593b8e80941Smrg screen->base.resource_create_with_modifiers = tegra_screen_resource_create_with_modifiers; 594b8e80941Smrg screen->base.query_dmabuf_modifiers = tegra_screen_query_dmabuf_modifiers; 595b8e80941Smrg screen->base.memobj_create_from_handle = tegra_screen_memobj_create_from_handle; 596b8e80941Smrg 597b8e80941Smrg return &screen->base; 598b8e80941Smrg} 599