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