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
,
137 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
139 return screen
->gpu
->is_format_supported(screen
->gpu
, format
, target
,
140 sample_count
, usage
);
144 tegra_screen_is_video_format_supported(struct pipe_screen
*pscreen
,
145 enum pipe_format format
,
146 enum pipe_video_profile profile
,
147 enum pipe_video_entrypoint entrypoint
)
149 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
151 return screen
->gpu
->is_video_format_supported(screen
->gpu
, format
, profile
,
156 tegra_screen_can_create_resource(struct pipe_screen
*pscreen
,
157 const struct pipe_resource
*template)
159 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
161 return screen
->gpu
->can_create_resource(screen
->gpu
, template);
164 static int tegra_open_render_node(void)
166 drmDevicePtr
*devices
, device
;
167 int err
, render
= -ENOENT
, fd
;
170 err
= drmGetDevices2(0, NULL
, 0);
176 devices
= calloc(num
, sizeof(*devices
));
180 err
= drmGetDevices2(0, devices
, num
);
186 for (i
= 0; i
< num
; i
++) {
189 if ((device
->available_nodes
& (1 << DRM_NODE_RENDER
)) &&
190 (device
->bustype
== DRM_BUS_PLATFORM
)) {
191 drmVersionPtr version
;
193 fd
= open(device
->nodes
[DRM_NODE_RENDER
], O_RDWR
| O_CLOEXEC
);
197 version
= drmGetVersion(fd
);
203 if (strcmp(version
->name
, "nouveau") != 0) {
208 drmFreeVersion(version
);
214 drmFreeDevices(devices
, num
);
221 static int tegra_screen_import_resource(struct tegra_screen
*screen
,
222 struct tegra_resource
*resource
)
224 unsigned usage
= PIPE_HANDLE_USAGE_READ
;
225 struct winsys_handle handle
;
229 memset(&handle
, 0, sizeof(handle
));
230 handle
.modifier
= DRM_FORMAT_MOD_INVALID
;
231 handle
.type
= DRM_API_HANDLE_TYPE_FD
;
233 status
= screen
->gpu
->resource_get_handle(screen
->gpu
, NULL
, resource
->gpu
,
238 assert(handle
.modifier
!= DRM_FORMAT_MOD_INVALID
);
240 if (handle
.modifier
== DRM_FORMAT_MOD_INVALID
) {
241 close(handle
.handle
);
245 resource
->modifier
= handle
.modifier
;
246 resource
->stride
= handle
.stride
;
249 err
= drmPrimeFDToHandle(screen
->fd
, fd
, &resource
->handle
);
258 static struct pipe_resource
*
259 tegra_screen_resource_create(struct pipe_screen
*pscreen
,
260 const struct pipe_resource
*template)
262 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
263 struct tegra_resource
*resource
;
266 resource
= calloc(1, sizeof(*resource
));
270 resource
->gpu
= screen
->gpu
->resource_create(screen
->gpu
, template);
274 /* import scanout buffers for display */
275 if (template->bind
& PIPE_BIND_SCANOUT
) {
276 err
= tegra_screen_import_resource(screen
, resource
);
281 memcpy(&resource
->base
, resource
->gpu
, sizeof(*resource
->gpu
));
282 pipe_reference_init(&resource
->base
.reference
, 1);
283 resource
->base
.screen
= &screen
->base
;
285 return &resource
->base
;
288 screen
->gpu
->resource_destroy(screen
->gpu
, resource
->gpu
);
295 static struct pipe_resource
*
296 tegra_screen_resource_create_front(struct pipe_screen
*pscreen
,
297 const struct pipe_resource
*template,
298 const void *map_front_private
)
300 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
301 struct pipe_resource
*resource
;
303 resource
= screen
->gpu
->resource_create_front(screen
->gpu
, template,
306 resource
->screen
= pscreen
;
311 static struct pipe_resource
*
312 tegra_screen_resource_from_handle(struct pipe_screen
*pscreen
,
313 const struct pipe_resource
*template,
314 struct winsys_handle
*handle
,
317 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
318 struct tegra_resource
*resource
;
320 resource
= calloc(1, sizeof(*resource
));
324 resource
->gpu
= screen
->gpu
->resource_from_handle(screen
->gpu
, template,
326 if (!resource
->gpu
) {
331 memcpy(&resource
->base
, resource
->gpu
, sizeof(*resource
->gpu
));
332 pipe_reference_init(&resource
->base
.reference
, 1);
333 resource
->base
.screen
= &screen
->base
;
335 return &resource
->base
;
339 static struct pipe_resource
*
340 tegra_screen_resource_from_user_memory(struct pipe_screen
*pscreen
,
341 const struct pipe_resource
*template,
344 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
345 struct pipe_resource
*resource
;
347 resource
= screen
->gpu
->resource_from_user_memory(screen
->gpu
, template,
350 resource
->screen
= pscreen
;
356 tegra_screen_resource_get_handle(struct pipe_screen
*pscreen
,
357 struct pipe_context
*pcontext
,
358 struct pipe_resource
*presource
,
359 struct winsys_handle
*handle
,
362 struct tegra_resource
*resource
= to_tegra_resource(presource
);
363 struct tegra_context
*context
= to_tegra_context(pcontext
);
364 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
368 * Assume that KMS handles for scanout resources will only ever be used
369 * to pass buffers into Tegra DRM for display. In all other cases, return
370 * the Nouveau handle, assuming they will be used for sharing in DRI2/3.
372 if (handle
->type
== DRM_API_HANDLE_TYPE_KMS
&&
373 presource
->bind
& PIPE_BIND_SCANOUT
) {
374 handle
->modifier
= resource
->modifier
;
375 handle
->handle
= resource
->handle
;
376 handle
->stride
= resource
->stride
;
378 ret
= screen
->gpu
->resource_get_handle(screen
->gpu
,
379 context
? context
->gpu
: NULL
,
380 resource
->gpu
, handle
, usage
);
387 tegra_screen_resource_destroy(struct pipe_screen
*pscreen
,
388 struct pipe_resource
*presource
)
390 struct tegra_resource
*resource
= to_tegra_resource(presource
);
392 pipe_resource_reference(&resource
->gpu
, NULL
);
397 tegra_screen_flush_frontbuffer(struct pipe_screen
*pscreen
,
398 struct pipe_resource
*resource
,
401 void *winsys_drawable_handle
,
402 struct pipe_box
*box
)
404 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
406 screen
->gpu
->flush_frontbuffer(screen
->gpu
, resource
, level
, layer
,
407 winsys_drawable_handle
, box
);
411 tegra_screen_fence_reference(struct pipe_screen
*pscreen
,
412 struct pipe_fence_handle
**ptr
,
413 struct pipe_fence_handle
*fence
)
415 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
417 screen
->gpu
->fence_reference(screen
->gpu
, ptr
, fence
);
421 tegra_screen_fence_finish(struct pipe_screen
*pscreen
,
422 struct pipe_context
*pcontext
,
423 struct pipe_fence_handle
*fence
,
426 struct tegra_context
*context
= to_tegra_context(pcontext
);
427 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
429 return screen
->gpu
->fence_finish(screen
->gpu
,
430 context
? context
->gpu
: NULL
,
435 tegra_screen_fence_get_fd(struct pipe_screen
*pscreen
,
436 struct pipe_fence_handle
*fence
)
438 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
440 return screen
->gpu
->fence_get_fd(screen
->gpu
, fence
);
444 tegra_screen_get_driver_query_info(struct pipe_screen
*pscreen
,
446 struct pipe_driver_query_info
*info
)
448 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
450 return screen
->gpu
->get_driver_query_info(screen
->gpu
, index
, info
);
454 tegra_screen_get_driver_query_group_info(struct pipe_screen
*pscreen
,
456 struct pipe_driver_query_group_info
*info
)
458 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
460 return screen
->gpu
->get_driver_query_group_info(screen
->gpu
, index
, info
);
464 tegra_screen_query_memory_info(struct pipe_screen
*pscreen
,
465 struct pipe_memory_info
*info
)
467 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
469 screen
->gpu
->query_memory_info(screen
->gpu
, info
);
473 tegra_screen_get_compiler_options(struct pipe_screen
*pscreen
,
474 enum pipe_shader_ir ir
,
477 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
478 const void *options
= NULL
;
480 if (screen
->gpu
->get_compiler_options
)
481 options
= screen
->gpu
->get_compiler_options(screen
->gpu
, ir
, shader
);
486 static struct disk_cache
*
487 tegra_screen_get_disk_shader_cache(struct pipe_screen
*pscreen
)
489 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
491 return screen
->gpu
->get_disk_shader_cache(screen
->gpu
);
494 static struct pipe_resource
*
495 tegra_screen_resource_create_with_modifiers(struct pipe_screen
*pscreen
,
496 const struct pipe_resource
*template,
497 const uint64_t *modifiers
,
500 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
501 struct tegra_resource
*resource
;
504 resource
= calloc(1, sizeof(*resource
));
508 resource
->gpu
= screen
->gpu
->resource_create_with_modifiers(screen
->gpu
,
515 err
= tegra_screen_import_resource(screen
, resource
);
519 memcpy(&resource
->base
, resource
->gpu
, sizeof(*resource
->gpu
));
520 pipe_reference_init(&resource
->base
.reference
, 1);
521 resource
->base
.screen
= &screen
->base
;
523 return &resource
->base
;
526 screen
->gpu
->resource_destroy(screen
->gpu
, resource
->gpu
);
532 static void tegra_screen_query_dmabuf_modifiers(struct pipe_screen
*pscreen
,
533 enum pipe_format format
,
534 int max
, uint64_t *modifiers
,
535 unsigned int *external_only
,
538 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
540 screen
->gpu
->query_dmabuf_modifiers(screen
->gpu
, format
, max
, modifiers
,
541 external_only
, count
);
544 static struct pipe_memory_object
*
545 tegra_screen_memobj_create_from_handle(struct pipe_screen
*pscreen
,
546 struct winsys_handle
*handle
,
549 struct tegra_screen
*screen
= to_tegra_screen(pscreen
);
551 return screen
->gpu
->memobj_create_from_handle(screen
->gpu
, handle
,
556 tegra_screen_create(int fd
)
558 struct tegra_screen
*screen
;
560 screen
= calloc(1, sizeof(*screen
));
566 screen
->gpu_fd
= tegra_open_render_node();
567 if (screen
->gpu_fd
< 0) {
569 fprintf(stderr
, "failed to open GPU device: %s\n", strerror(errno
));
575 screen
->gpu
= nouveau_drm_screen_create(screen
->gpu_fd
);
577 fprintf(stderr
, "failed to create GPU screen\n");
578 close(screen
->gpu_fd
);
583 screen
->base
.destroy
= tegra_screen_destroy
;
584 screen
->base
.get_name
= tegra_screen_get_name
;
585 screen
->base
.get_vendor
= tegra_screen_get_vendor
;
586 screen
->base
.get_device_vendor
= tegra_screen_get_device_vendor
;
587 screen
->base
.get_param
= tegra_screen_get_param
;
588 screen
->base
.get_paramf
= tegra_screen_get_paramf
;
589 screen
->base
.get_shader_param
= tegra_screen_get_shader_param
;
590 screen
->base
.get_video_param
= tegra_screen_get_video_param
;
591 screen
->base
.get_compute_param
= tegra_screen_get_compute_param
;
592 screen
->base
.get_timestamp
= tegra_screen_get_timestamp
;
593 screen
->base
.context_create
= tegra_screen_context_create
;
594 screen
->base
.is_format_supported
= tegra_screen_is_format_supported
;
595 screen
->base
.is_video_format_supported
= tegra_screen_is_video_format_supported
;
597 /* allow fallback implementation if GPU driver doesn't implement it */
598 if (screen
->gpu
->can_create_resource
)
599 screen
->base
.can_create_resource
= tegra_screen_can_create_resource
;
601 screen
->base
.resource_create
= tegra_screen_resource_create
;
602 screen
->base
.resource_create_front
= tegra_screen_resource_create_front
;
603 screen
->base
.resource_from_handle
= tegra_screen_resource_from_handle
;
604 screen
->base
.resource_from_user_memory
= tegra_screen_resource_from_user_memory
;
605 screen
->base
.resource_get_handle
= tegra_screen_resource_get_handle
;
606 screen
->base
.resource_destroy
= tegra_screen_resource_destroy
;
608 screen
->base
.flush_frontbuffer
= tegra_screen_flush_frontbuffer
;
609 screen
->base
.fence_reference
= tegra_screen_fence_reference
;
610 screen
->base
.fence_finish
= tegra_screen_fence_finish
;
611 screen
->base
.fence_get_fd
= tegra_screen_fence_get_fd
;
613 screen
->base
.get_driver_query_info
= tegra_screen_get_driver_query_info
;
614 screen
->base
.get_driver_query_group_info
= tegra_screen_get_driver_query_group_info
;
615 screen
->base
.query_memory_info
= tegra_screen_query_memory_info
;
617 screen
->base
.get_compiler_options
= tegra_screen_get_compiler_options
;
618 screen
->base
.get_disk_shader_cache
= tegra_screen_get_disk_shader_cache
;
620 screen
->base
.resource_create_with_modifiers
= tegra_screen_resource_create_with_modifiers
;
621 screen
->base
.query_dmabuf_modifiers
= tegra_screen_query_dmabuf_modifiers
;
622 screen
->base
.memobj_create_from_handle
= tegra_screen_memobj_create_from_handle
;
624 return &screen
->base
;