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