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