2 * Copyright © 2014-2018 NVIDIA Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
31 #include <drm_fourcc.h>
32 #include <tegra_drm.h>
35 #include "pipe/p_state.h"
36 #include "util/u_debug.h"
37 #include "util/u_inlines.h"
39 #include "state_tracker/drm_driver.h"
41 #include "nouveau/drm/nouveau_drm_public.h"
43 #include "tegra_context.h"
44 #include "tegra_resource.h"
45 #include "tegra_screen.h"
47 static void tegra_screen_destroy(struct pipe_screen
*pscreen
)
49 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
51 screen
->gpu
->destroy(screen
->gpu
);
56 tegra_screen_get_name(struct pipe_screen
*pscreen
)
62 tegra_screen_get_vendor(struct pipe_screen
*pscreen
)
68 tegra_screen_get_device_vendor(struct pipe_screen
*pscreen
)
74 tegra_screen_get_param(struct pipe_screen
*pscreen
, enum pipe_cap param
)
76 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
78 return screen
->gpu
->get_param(screen
->gpu
, param
);
82 tegra_screen_get_paramf(struct pipe_screen
*pscreen
, enum pipe_capf param
)
84 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
86 return screen
->gpu
->get_paramf(screen
->gpu
, param
);
90 tegra_screen_get_shader_param(struct pipe_screen
*pscreen
, unsigned shader
,
91 enum pipe_shader_cap param
)
93 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
95 return screen
->gpu
->get_shader_param(screen
->gpu
, shader
, param
);
99 tegra_screen_get_video_param(struct pipe_screen
*pscreen
,
100 enum pipe_video_profile profile
,
101 enum pipe_video_entrypoint entrypoint
,
102 enum pipe_video_cap param
)
104 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
106 return screen
->gpu
->get_video_param(screen
->gpu
, profile
, entrypoint
,
111 tegra_screen_get_compute_param(struct pipe_screen
*pscreen
,
112 enum pipe_shader_ir ir_type
,
113 enum pipe_compute_cap param
,
116 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
118 return screen
->gpu
->get_compute_param(screen
->gpu
, ir_type
, param
,
123 tegra_screen_get_timestamp(struct pipe_screen
*pscreen
)
125 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
127 return screen
->gpu
->get_timestamp(screen
->gpu
);
131 tegra_screen_is_format_supported(struct pipe_screen
*pscreen
,
132 enum pipe_format format
,
133 enum pipe_texture_target target
,
134 unsigned sample_count
,
135 unsigned storage_sample_count
,
138 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
140 return screen
->gpu
->is_format_supported(screen
->gpu
, format
, target
,
141 sample_count
, storage_sample_count
,
146 tegra_screen_is_video_format_supported(struct pipe_screen
*pscreen
,
147 enum pipe_format format
,
148 enum pipe_video_profile profile
,
149 enum pipe_video_entrypoint entrypoint
)
151 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
153 return screen
->gpu
->is_video_format_supported(screen
->gpu
, format
, profile
,
158 tegra_screen_can_create_resource(struct pipe_screen
*pscreen
,
159 const struct pipe_resource
*template)
161 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
163 return screen
->gpu
->can_create_resource(screen
->gpu
, template);
166 static int tegra_open_render_node(void)
168 drmDevicePtr
*devices
, device
;
169 int err
, render
= -ENOENT
, fd
;
172 err
= drmGetDevices2(0, NULL
, 0);
178 devices
= calloc(num
, sizeof(*devices
));
182 err
= drmGetDevices2(0, devices
, num
);
188 for (i
= 0; i
< num
; i
++) {
191 if ((device
->available_nodes
& (1 << DRM_NODE_RENDER
)) &&
192 (device
->bustype
== DRM_BUS_PLATFORM
)) {
193 drmVersionPtr version
;
195 fd
= open(device
->nodes
[DRM_NODE_RENDER
], O_RDWR
| O_CLOEXEC
);
199 version
= drmGetVersion(fd
);
205 if (strcmp(version
->name
, "nouveau") != 0) {
206 drmFreeVersion(version
);
211 drmFreeVersion(version
);
217 drmFreeDevices(devices
, num
);
224 static int tegra_screen_import_resource(struct tegra_screen
*screen
,
225 struct tegra_resource
*resource
)
227 unsigned usage
= PIPE_HANDLE_USAGE_READ
;
228 struct winsys_handle handle
;
232 memset(&handle
, 0, sizeof(handle
));
233 handle
.modifier
= DRM_FORMAT_MOD_INVALID
;
234 handle
.type
= WINSYS_HANDLE_TYPE_FD
;
236 status
= screen
->gpu
->resource_get_handle(screen
->gpu
, NULL
, resource
->gpu
,
241 assert(handle
.modifier
!= DRM_FORMAT_MOD_INVALID
);
243 if (handle
.modifier
== DRM_FORMAT_MOD_INVALID
) {
244 close(handle
.handle
);
248 resource
->modifier
= handle
.modifier
;
249 resource
->stride
= handle
.stride
;
252 err
= drmPrimeFDToHandle(screen
->fd
, fd
, &resource
->handle
);
261 static struct pipe_resource
*
262 tegra_screen_resource_create(struct pipe_screen
*pscreen
,
263 const struct pipe_resource
*template)
265 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
266 uint64_t modifier
= DRM_FORMAT_MOD_INVALID
;
267 struct tegra_resource
*resource
;
270 resource
= calloc(1, sizeof(*resource
));
275 * Applications that create scanout resources without modifiers are very
276 * unlikely to support modifiers at all. In that case the resources need
277 * to be created with a pitch-linear layout so that they can be properly
278 * shared with scanout hardware.
280 * Technically it is possible for applications to create resources without
281 * specifying a modifier but still query the modifier associated with the
282 * resource (e.g. using gbm_bo_get_modifier()) before handing it to the
283 * framebuffer creation API (such as the DRM_IOCTL_MODE_ADDFB2 IOCTL).
285 if (template->bind
& PIPE_BIND_SCANOUT
)
286 modifier
= DRM_FORMAT_MOD_LINEAR
;
288 resource
->gpu
= screen
->gpu
->resource_create_with_modifiers(screen
->gpu
,
294 /* import scanout buffers for display */
295 if (template->bind
& PIPE_BIND_SCANOUT
) {
296 err
= tegra_screen_import_resource(screen
, resource
);
301 memcpy(&resource
->base
, resource
->gpu
, sizeof(*resource
->gpu
));
302 pipe_reference_init(&resource
->base
.reference
, 1);
303 resource
->base
.screen
= &screen
->base
;
305 return &resource
->base
;
308 screen
->gpu
->resource_destroy(screen
->gpu
, resource
->gpu
);
315 static struct pipe_resource
*
316 tegra_screen_resource_create_front(struct pipe_screen
*pscreen
,
317 const struct pipe_resource
*template,
318 const void *map_front_private
)
320 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
321 struct pipe_resource
*resource
;
323 resource
= screen
->gpu
->resource_create_front(screen
->gpu
, template,
326 resource
->screen
= pscreen
;
331 static struct pipe_resource
*
332 tegra_screen_resource_from_handle(struct pipe_screen
*pscreen
,
333 const struct pipe_resource
*template,
334 struct winsys_handle
*handle
,
337 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
338 struct tegra_resource
*resource
;
340 resource
= calloc(1, sizeof(*resource
));
344 resource
->gpu
= screen
->gpu
->resource_from_handle(screen
->gpu
, template,
346 if (!resource
->gpu
) {
351 memcpy(&resource
->base
, resource
->gpu
, sizeof(*resource
->gpu
));
352 pipe_reference_init(&resource
->base
.reference
, 1);
353 resource
->base
.screen
= &screen
->base
;
355 return &resource
->base
;
359 static struct pipe_resource
*
360 tegra_screen_resource_from_user_memory(struct pipe_screen
*pscreen
,
361 const struct pipe_resource
*template,
364 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
365 struct pipe_resource
*resource
;
367 resource
= screen
->gpu
->resource_from_user_memory(screen
->gpu
, template,
370 resource
->screen
= pscreen
;
376 tegra_screen_resource_get_handle(struct pipe_screen
*pscreen
,
377 struct pipe_context
*pcontext
,
378 struct pipe_resource
*presource
,
379 struct winsys_handle
*handle
,
382 struct tegra_resource
*resource
= to_tegra_resource(presource
);
383 struct tegra_context
*context
= to_tegra_context(pcontext
);
384 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
388 * Assume that KMS handles for scanout resources will only ever be used
389 * to pass buffers into Tegra DRM for display. In all other cases, return
390 * the Nouveau handle, assuming they will be used for sharing in DRI2/3.
392 if (handle
->type
== WINSYS_HANDLE_TYPE_KMS
&&
393 presource
->bind
& PIPE_BIND_SCANOUT
) {
394 handle
->modifier
= resource
->modifier
;
395 handle
->handle
= resource
->handle
;
396 handle
->stride
= resource
->stride
;
398 ret
= screen
->gpu
->resource_get_handle(screen
->gpu
,
399 context
? context
->gpu
: NULL
,
400 resource
->gpu
, handle
, usage
);
407 tegra_screen_resource_destroy(struct pipe_screen
*pscreen
,
408 struct pipe_resource
*presource
)
410 struct tegra_resource
*resource
= to_tegra_resource(presource
);
412 pipe_resource_reference(&resource
->gpu
, NULL
);
417 tegra_screen_flush_frontbuffer(struct pipe_screen
*pscreen
,
418 struct pipe_resource
*resource
,
421 void *winsys_drawable_handle
,
422 struct pipe_box
*box
)
424 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
426 screen
->gpu
->flush_frontbuffer(screen
->gpu
, resource
, level
, layer
,
427 winsys_drawable_handle
, box
);
431 tegra_screen_fence_reference(struct pipe_screen
*pscreen
,
432 struct pipe_fence_handle
**ptr
,
433 struct pipe_fence_handle
*fence
)
435 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
437 screen
->gpu
->fence_reference(screen
->gpu
, ptr
, fence
);
441 tegra_screen_fence_finish(struct pipe_screen
*pscreen
,
442 struct pipe_context
*pcontext
,
443 struct pipe_fence_handle
*fence
,
446 struct tegra_context
*context
= to_tegra_context(pcontext
);
447 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
449 return screen
->gpu
->fence_finish(screen
->gpu
,
450 context
? context
->gpu
: NULL
,
455 tegra_screen_fence_get_fd(struct pipe_screen
*pscreen
,
456 struct pipe_fence_handle
*fence
)
458 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
460 return screen
->gpu
->fence_get_fd(screen
->gpu
, fence
);
464 tegra_screen_get_driver_query_info(struct pipe_screen
*pscreen
,
466 struct pipe_driver_query_info
*info
)
468 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
470 return screen
->gpu
->get_driver_query_info(screen
->gpu
, index
, info
);
474 tegra_screen_get_driver_query_group_info(struct pipe_screen
*pscreen
,
476 struct pipe_driver_query_group_info
*info
)
478 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
480 return screen
->gpu
->get_driver_query_group_info(screen
->gpu
, index
, info
);
484 tegra_screen_query_memory_info(struct pipe_screen
*pscreen
,
485 struct pipe_memory_info
*info
)
487 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
489 screen
->gpu
->query_memory_info(screen
->gpu
, info
);
493 tegra_screen_get_compiler_options(struct pipe_screen
*pscreen
,
494 enum pipe_shader_ir ir
,
497 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
498 const void *options
= NULL
;
500 if (screen
->gpu
->get_compiler_options
)
501 options
= screen
->gpu
->get_compiler_options(screen
->gpu
, ir
, shader
);
506 static struct disk_cache
*
507 tegra_screen_get_disk_shader_cache(struct pipe_screen
*pscreen
)
509 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
511 return screen
->gpu
->get_disk_shader_cache(screen
->gpu
);
514 static struct pipe_resource
*
515 tegra_screen_resource_create_with_modifiers(struct pipe_screen
*pscreen
,
516 const struct pipe_resource
*template,
517 const uint64_t *modifiers
,
520 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
521 struct pipe_resource tmpl
= *template;
522 struct tegra_resource
*resource
;
525 resource
= calloc(1, sizeof(*resource
));
530 * Assume that resources created with modifiers will always be used for
531 * scanout. This is necessary because some of the APIs that are used to
532 * create resources with modifiers (e.g. gbm_bo_create_with_modifiers())
533 * can't pass along usage information. Adding that capability might be
534 * worth adding to remove this ambiguity. Not all future use-cases that
535 * involve modifiers may always be targetting scanout hardware.
537 tmpl
.bind
|= PIPE_BIND_SCANOUT
;
539 resource
->gpu
= screen
->gpu
->resource_create_with_modifiers(screen
->gpu
,
546 err
= tegra_screen_import_resource(screen
, resource
);
550 memcpy(&resource
->base
, resource
->gpu
, sizeof(*resource
->gpu
));
551 pipe_reference_init(&resource
->base
.reference
, 1);
552 resource
->base
.screen
= &screen
->base
;
554 return &resource
->base
;
557 screen
->gpu
->resource_destroy(screen
->gpu
, resource
->gpu
);
563 static void tegra_screen_query_dmabuf_modifiers(struct pipe_screen
*pscreen
,
564 enum pipe_format format
,
565 int max
, uint64_t *modifiers
,
566 unsigned int *external_only
,
569 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
571 screen
->gpu
->query_dmabuf_modifiers(screen
->gpu
, format
, max
, modifiers
,
572 external_only
, count
);
575 static struct pipe_memory_object
*
576 tegra_screen_memobj_create_from_handle(struct pipe_screen
*pscreen
,
577 struct winsys_handle
*handle
,
580 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
582 return screen
->gpu
->memobj_create_from_handle(screen
->gpu
, handle
,
587 tegra_screen_create(int fd
)
589 struct tegra_screen
*screen
;
591 screen
= calloc(1, sizeof(*screen
));
597 screen
->gpu_fd
= tegra_open_render_node();
598 if (screen
->gpu_fd
< 0) {
600 fprintf(stderr
, "failed to open GPU device: %s\n", strerror(errno
));
606 screen
->gpu
= nouveau_drm_screen_create(screen
->gpu_fd
);
608 fprintf(stderr
, "failed to create GPU screen\n");
609 close(screen
->gpu_fd
);
614 screen
->base
.destroy
= tegra_screen_destroy
;
615 screen
->base
.get_name
= tegra_screen_get_name
;
616 screen
->base
.get_vendor
= tegra_screen_get_vendor
;
617 screen
->base
.get_device_vendor
= tegra_screen_get_device_vendor
;
618 screen
->base
.get_param
= tegra_screen_get_param
;
619 screen
->base
.get_paramf
= tegra_screen_get_paramf
;
620 screen
->base
.get_shader_param
= tegra_screen_get_shader_param
;
621 screen
->base
.get_video_param
= tegra_screen_get_video_param
;
622 screen
->base
.get_compute_param
= tegra_screen_get_compute_param
;
623 screen
->base
.get_timestamp
= tegra_screen_get_timestamp
;
624 screen
->base
.context_create
= tegra_screen_context_create
;
625 screen
->base
.is_format_supported
= tegra_screen_is_format_supported
;
626 screen
->base
.is_video_format_supported
= tegra_screen_is_video_format_supported
;
628 /* allow fallback implementation if GPU driver doesn't implement it */
629 if (screen
->gpu
->can_create_resource
)
630 screen
->base
.can_create_resource
= tegra_screen_can_create_resource
;
632 screen
->base
.resource_create
= tegra_screen_resource_create
;
633 screen
->base
.resource_create_front
= tegra_screen_resource_create_front
;
634 screen
->base
.resource_from_handle
= tegra_screen_resource_from_handle
;
635 screen
->base
.resource_from_user_memory
= tegra_screen_resource_from_user_memory
;
636 screen
->base
.resource_get_handle
= tegra_screen_resource_get_handle
;
637 screen
->base
.resource_destroy
= tegra_screen_resource_destroy
;
639 screen
->base
.flush_frontbuffer
= tegra_screen_flush_frontbuffer
;
640 screen
->base
.fence_reference
= tegra_screen_fence_reference
;
641 screen
->base
.fence_finish
= tegra_screen_fence_finish
;
642 screen
->base
.fence_get_fd
= tegra_screen_fence_get_fd
;
644 screen
->base
.get_driver_query_info
= tegra_screen_get_driver_query_info
;
645 screen
->base
.get_driver_query_group_info
= tegra_screen_get_driver_query_group_info
;
646 screen
->base
.query_memory_info
= tegra_screen_query_memory_info
;
648 screen
->base
.get_compiler_options
= tegra_screen_get_compiler_options
;
649 screen
->base
.get_disk_shader_cache
= tegra_screen_get_disk_shader_cache
;
651 screen
->base
.resource_create_with_modifiers
= tegra_screen_resource_create_with_modifiers
;
652 screen
->base
.query_dmabuf_modifiers
= tegra_screen_query_dmabuf_modifiers
;
653 screen
->base
.memobj_create_from_handle
= tegra_screen_memobj_create_from_handle
;
655 return &screen
->base
;