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-uapi/drm_fourcc.h"
32 #include "drm-uapi/tegra_drm.h"
35 #include "loader/loader.h"
36 #include "pipe/p_state.h"
37 #include "util/u_debug.h"
38 #include "util/u_inlines.h"
40 #include "state_tracker/drm_driver.h"
42 #include "nouveau/drm/nouveau_drm_public.h"
44 #include "tegra_context.h"
45 #include "tegra_resource.h"
46 #include "tegra_screen.h"
48 static void tegra_screen_destroy(struct pipe_screen
*pscreen
)
50 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
52 screen
->gpu
->destroy(screen
->gpu
);
57 tegra_screen_get_name(struct pipe_screen
*pscreen
)
63 tegra_screen_get_vendor(struct pipe_screen
*pscreen
)
69 tegra_screen_get_device_vendor(struct pipe_screen
*pscreen
)
75 tegra_screen_get_param(struct pipe_screen
*pscreen
, enum pipe_cap param
)
77 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
79 return screen
->gpu
->get_param(screen
->gpu
, param
);
83 tegra_screen_get_paramf(struct pipe_screen
*pscreen
, enum pipe_capf param
)
85 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
87 return screen
->gpu
->get_paramf(screen
->gpu
, param
);
91 tegra_screen_get_shader_param(struct pipe_screen
*pscreen
, unsigned shader
,
92 enum pipe_shader_cap param
)
94 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
96 return screen
->gpu
->get_shader_param(screen
->gpu
, shader
, param
);
100 tegra_screen_get_video_param(struct pipe_screen
*pscreen
,
101 enum pipe_video_profile profile
,
102 enum pipe_video_entrypoint entrypoint
,
103 enum pipe_video_cap param
)
105 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
107 return screen
->gpu
->get_video_param(screen
->gpu
, profile
, entrypoint
,
112 tegra_screen_get_compute_param(struct pipe_screen
*pscreen
,
113 enum pipe_shader_ir ir_type
,
114 enum pipe_compute_cap param
,
117 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
119 return screen
->gpu
->get_compute_param(screen
->gpu
, ir_type
, param
,
124 tegra_screen_get_timestamp(struct pipe_screen
*pscreen
)
126 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
128 return screen
->gpu
->get_timestamp(screen
->gpu
);
132 tegra_screen_is_format_supported(struct pipe_screen
*pscreen
,
133 enum pipe_format format
,
134 enum pipe_texture_target target
,
135 unsigned sample_count
,
136 unsigned storage_sample_count
,
139 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
141 return screen
->gpu
->is_format_supported(screen
->gpu
, format
, target
,
142 sample_count
, storage_sample_count
,
147 tegra_screen_is_video_format_supported(struct pipe_screen
*pscreen
,
148 enum pipe_format format
,
149 enum pipe_video_profile profile
,
150 enum pipe_video_entrypoint entrypoint
)
152 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
154 return screen
->gpu
->is_video_format_supported(screen
->gpu
, format
, profile
,
159 tegra_screen_can_create_resource(struct pipe_screen
*pscreen
,
160 const struct pipe_resource
*template)
162 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
164 return screen
->gpu
->can_create_resource(screen
->gpu
, template);
167 static int tegra_screen_import_resource(struct tegra_screen
*screen
,
168 struct tegra_resource
*resource
)
170 struct winsys_handle handle
;
174 memset(&handle
, 0, sizeof(handle
));
175 handle
.modifier
= DRM_FORMAT_MOD_INVALID
;
176 handle
.type
= WINSYS_HANDLE_TYPE_FD
;
178 status
= screen
->gpu
->resource_get_handle(screen
->gpu
, NULL
, resource
->gpu
,
183 assert(handle
.modifier
!= DRM_FORMAT_MOD_INVALID
);
185 if (handle
.modifier
== DRM_FORMAT_MOD_INVALID
) {
186 close(handle
.handle
);
190 resource
->modifier
= handle
.modifier
;
191 resource
->stride
= handle
.stride
;
194 err
= drmPrimeFDToHandle(screen
->fd
, fd
, &resource
->handle
);
203 static struct pipe_resource
*
204 tegra_screen_resource_create(struct pipe_screen
*pscreen
,
205 const struct pipe_resource
*template)
207 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
208 uint64_t modifier
= DRM_FORMAT_MOD_INVALID
;
209 struct tegra_resource
*resource
;
212 resource
= calloc(1, sizeof(*resource
));
217 * Applications that create scanout resources without modifiers are very
218 * unlikely to support modifiers at all. In that case the resources need
219 * to be created with a pitch-linear layout so that they can be properly
220 * shared with scanout hardware.
222 * Technically it is possible for applications to create resources without
223 * specifying a modifier but still query the modifier associated with the
224 * resource (e.g. using gbm_bo_get_modifier()) before handing it to the
225 * framebuffer creation API (such as the DRM_IOCTL_MODE_ADDFB2 IOCTL).
227 if (template->bind
& PIPE_BIND_SCANOUT
)
228 modifier
= DRM_FORMAT_MOD_LINEAR
;
230 resource
->gpu
= screen
->gpu
->resource_create_with_modifiers(screen
->gpu
,
236 /* import scanout buffers for display */
237 if (template->bind
& PIPE_BIND_SCANOUT
) {
238 err
= tegra_screen_import_resource(screen
, resource
);
243 memcpy(&resource
->base
, resource
->gpu
, sizeof(*resource
->gpu
));
244 pipe_reference_init(&resource
->base
.reference
, 1);
245 resource
->base
.screen
= &screen
->base
;
247 return &resource
->base
;
250 screen
->gpu
->resource_destroy(screen
->gpu
, resource
->gpu
);
257 static struct pipe_resource
*
258 tegra_screen_resource_create_front(struct pipe_screen
*pscreen
,
259 const struct pipe_resource
*template,
260 const void *map_front_private
)
262 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
263 struct pipe_resource
*resource
;
265 resource
= screen
->gpu
->resource_create_front(screen
->gpu
, template,
268 resource
->screen
= pscreen
;
273 static struct pipe_resource
*
274 tegra_screen_resource_from_handle(struct pipe_screen
*pscreen
,
275 const struct pipe_resource
*template,
276 struct winsys_handle
*handle
,
279 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
280 struct tegra_resource
*resource
;
282 resource
= calloc(1, sizeof(*resource
));
286 resource
->gpu
= screen
->gpu
->resource_from_handle(screen
->gpu
, template,
288 if (!resource
->gpu
) {
293 memcpy(&resource
->base
, resource
->gpu
, sizeof(*resource
->gpu
));
294 pipe_reference_init(&resource
->base
.reference
, 1);
295 resource
->base
.screen
= &screen
->base
;
297 return &resource
->base
;
301 static struct pipe_resource
*
302 tegra_screen_resource_from_user_memory(struct pipe_screen
*pscreen
,
303 const struct pipe_resource
*template,
306 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
307 struct pipe_resource
*resource
;
309 resource
= screen
->gpu
->resource_from_user_memory(screen
->gpu
, template,
312 resource
->screen
= pscreen
;
318 tegra_screen_resource_get_handle(struct pipe_screen
*pscreen
,
319 struct pipe_context
*pcontext
,
320 struct pipe_resource
*presource
,
321 struct winsys_handle
*handle
,
324 struct tegra_resource
*resource
= to_tegra_resource(presource
);
325 struct tegra_context
*context
= to_tegra_context(pcontext
);
326 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
330 * Assume that KMS handles for scanout resources will only ever be used
331 * to pass buffers into Tegra DRM for display. In all other cases, return
332 * the Nouveau handle, assuming they will be used for sharing in DRI2/3.
334 if (handle
->type
== WINSYS_HANDLE_TYPE_KMS
&&
335 presource
->bind
& PIPE_BIND_SCANOUT
) {
336 handle
->modifier
= resource
->modifier
;
337 handle
->handle
= resource
->handle
;
338 handle
->stride
= resource
->stride
;
340 ret
= screen
->gpu
->resource_get_handle(screen
->gpu
,
341 context
? context
->gpu
: NULL
,
342 resource
->gpu
, handle
, usage
);
349 tegra_screen_resource_destroy(struct pipe_screen
*pscreen
,
350 struct pipe_resource
*presource
)
352 struct tegra_resource
*resource
= to_tegra_resource(presource
);
354 pipe_resource_reference(&resource
->gpu
, NULL
);
359 tegra_screen_flush_frontbuffer(struct pipe_screen
*pscreen
,
360 struct pipe_resource
*resource
,
363 void *winsys_drawable_handle
,
364 struct pipe_box
*box
)
366 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
368 screen
->gpu
->flush_frontbuffer(screen
->gpu
, resource
, level
, layer
,
369 winsys_drawable_handle
, box
);
373 tegra_screen_fence_reference(struct pipe_screen
*pscreen
,
374 struct pipe_fence_handle
**ptr
,
375 struct pipe_fence_handle
*fence
)
377 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
379 screen
->gpu
->fence_reference(screen
->gpu
, ptr
, fence
);
383 tegra_screen_fence_finish(struct pipe_screen
*pscreen
,
384 struct pipe_context
*pcontext
,
385 struct pipe_fence_handle
*fence
,
388 struct tegra_context
*context
= to_tegra_context(pcontext
);
389 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
391 return screen
->gpu
->fence_finish(screen
->gpu
,
392 context
? context
->gpu
: NULL
,
397 tegra_screen_fence_get_fd(struct pipe_screen
*pscreen
,
398 struct pipe_fence_handle
*fence
)
400 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
402 return screen
->gpu
->fence_get_fd(screen
->gpu
, fence
);
406 tegra_screen_get_driver_query_info(struct pipe_screen
*pscreen
,
408 struct pipe_driver_query_info
*info
)
410 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
412 return screen
->gpu
->get_driver_query_info(screen
->gpu
, index
, info
);
416 tegra_screen_get_driver_query_group_info(struct pipe_screen
*pscreen
,
418 struct pipe_driver_query_group_info
*info
)
420 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
422 return screen
->gpu
->get_driver_query_group_info(screen
->gpu
, index
, info
);
426 tegra_screen_query_memory_info(struct pipe_screen
*pscreen
,
427 struct pipe_memory_info
*info
)
429 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
431 screen
->gpu
->query_memory_info(screen
->gpu
, info
);
435 tegra_screen_get_compiler_options(struct pipe_screen
*pscreen
,
436 enum pipe_shader_ir ir
,
439 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
440 const void *options
= NULL
;
442 if (screen
->gpu
->get_compiler_options
)
443 options
= screen
->gpu
->get_compiler_options(screen
->gpu
, ir
, shader
);
448 static struct disk_cache
*
449 tegra_screen_get_disk_shader_cache(struct pipe_screen
*pscreen
)
451 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
453 return screen
->gpu
->get_disk_shader_cache(screen
->gpu
);
456 static struct pipe_resource
*
457 tegra_screen_resource_create_with_modifiers(struct pipe_screen
*pscreen
,
458 const struct pipe_resource
*template,
459 const uint64_t *modifiers
,
462 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
463 struct pipe_resource tmpl
= *template;
464 struct tegra_resource
*resource
;
467 resource
= calloc(1, sizeof(*resource
));
472 * Assume that resources created with modifiers will always be used for
473 * scanout. This is necessary because some of the APIs that are used to
474 * create resources with modifiers (e.g. gbm_bo_create_with_modifiers())
475 * can't pass along usage information. Adding that capability might be
476 * worth adding to remove this ambiguity. Not all future use-cases that
477 * involve modifiers may always be targetting scanout hardware.
479 tmpl
.bind
|= PIPE_BIND_SCANOUT
;
481 resource
->gpu
= screen
->gpu
->resource_create_with_modifiers(screen
->gpu
,
488 err
= tegra_screen_import_resource(screen
, resource
);
492 memcpy(&resource
->base
, resource
->gpu
, sizeof(*resource
->gpu
));
493 pipe_reference_init(&resource
->base
.reference
, 1);
494 resource
->base
.screen
= &screen
->base
;
496 return &resource
->base
;
499 screen
->gpu
->resource_destroy(screen
->gpu
, resource
->gpu
);
505 static void tegra_screen_query_dmabuf_modifiers(struct pipe_screen
*pscreen
,
506 enum pipe_format format
,
507 int max
, uint64_t *modifiers
,
508 unsigned int *external_only
,
511 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
513 screen
->gpu
->query_dmabuf_modifiers(screen
->gpu
, format
, max
, modifiers
,
514 external_only
, count
);
517 static struct pipe_memory_object
*
518 tegra_screen_memobj_create_from_handle(struct pipe_screen
*pscreen
,
519 struct winsys_handle
*handle
,
522 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
524 return screen
->gpu
->memobj_create_from_handle(screen
->gpu
, handle
,
529 tegra_screen_create(int fd
)
531 struct tegra_screen
*screen
;
533 screen
= calloc(1, sizeof(*screen
));
539 screen
->gpu_fd
= loader_open_render_node("nouveau");
540 if (screen
->gpu_fd
< 0) {
542 fprintf(stderr
, "failed to open GPU device: %s\n", strerror(errno
));
548 screen
->gpu
= nouveau_drm_screen_create(screen
->gpu_fd
);
550 fprintf(stderr
, "failed to create GPU screen\n");
551 close(screen
->gpu_fd
);
556 screen
->base
.destroy
= tegra_screen_destroy
;
557 screen
->base
.get_name
= tegra_screen_get_name
;
558 screen
->base
.get_vendor
= tegra_screen_get_vendor
;
559 screen
->base
.get_device_vendor
= tegra_screen_get_device_vendor
;
560 screen
->base
.get_param
= tegra_screen_get_param
;
561 screen
->base
.get_paramf
= tegra_screen_get_paramf
;
562 screen
->base
.get_shader_param
= tegra_screen_get_shader_param
;
563 screen
->base
.get_video_param
= tegra_screen_get_video_param
;
564 screen
->base
.get_compute_param
= tegra_screen_get_compute_param
;
565 screen
->base
.get_timestamp
= tegra_screen_get_timestamp
;
566 screen
->base
.context_create
= tegra_screen_context_create
;
567 screen
->base
.is_format_supported
= tegra_screen_is_format_supported
;
568 screen
->base
.is_video_format_supported
= tegra_screen_is_video_format_supported
;
570 /* allow fallback implementation if GPU driver doesn't implement it */
571 if (screen
->gpu
->can_create_resource
)
572 screen
->base
.can_create_resource
= tegra_screen_can_create_resource
;
574 screen
->base
.resource_create
= tegra_screen_resource_create
;
575 screen
->base
.resource_create_front
= tegra_screen_resource_create_front
;
576 screen
->base
.resource_from_handle
= tegra_screen_resource_from_handle
;
577 screen
->base
.resource_from_user_memory
= tegra_screen_resource_from_user_memory
;
578 screen
->base
.resource_get_handle
= tegra_screen_resource_get_handle
;
579 screen
->base
.resource_destroy
= tegra_screen_resource_destroy
;
581 screen
->base
.flush_frontbuffer
= tegra_screen_flush_frontbuffer
;
582 screen
->base
.fence_reference
= tegra_screen_fence_reference
;
583 screen
->base
.fence_finish
= tegra_screen_fence_finish
;
584 screen
->base
.fence_get_fd
= tegra_screen_fence_get_fd
;
586 screen
->base
.get_driver_query_info
= tegra_screen_get_driver_query_info
;
587 screen
->base
.get_driver_query_group_info
= tegra_screen_get_driver_query_group_info
;
588 screen
->base
.query_memory_info
= tegra_screen_query_memory_info
;
590 screen
->base
.get_compiler_options
= tegra_screen_get_compiler_options
;
591 screen
->base
.get_disk_shader_cache
= tegra_screen_get_disk_shader_cache
;
593 screen
->base
.resource_create_with_modifiers
= tegra_screen_resource_create_with_modifiers
;
594 screen
->base
.query_dmabuf_modifiers
= tegra_screen_query_dmabuf_modifiers
;
595 screen
->base
.memobj_create_from_handle
= tegra_screen_memobj_create_from_handle
;
597 return &screen
->base
;