2 * Copyright © 2017 Intel 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 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the 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 NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE.
25 #include "pipe/p_defines.h"
26 #include "pipe/p_state.h"
27 #include "pipe/p_context.h"
28 #include "pipe/p_screen.h"
29 #include "util/u_inlines.h"
30 #include "util/u_format.h"
31 #include "util/u_upload_mgr.h"
32 #include "util/ralloc.h"
33 #include "iris_resource.h"
34 #include "iris_screen.h"
35 #include "intel/common/gen_debug.h"
36 #include "drm-uapi/drm_fourcc.h"
37 #include "drm-uapi/i915_drm.h"
39 enum modifier_priority
{
40 MODIFIER_PRIORITY_INVALID
= 0,
41 MODIFIER_PRIORITY_LINEAR
,
44 MODIFIER_PRIORITY_Y_CCS
,
47 static const uint64_t priority_to_modifier
[] = {
48 [MODIFIER_PRIORITY_INVALID
] = DRM_FORMAT_MOD_INVALID
,
49 [MODIFIER_PRIORITY_LINEAR
] = DRM_FORMAT_MOD_LINEAR
,
50 [MODIFIER_PRIORITY_X
] = I915_FORMAT_MOD_X_TILED
,
51 [MODIFIER_PRIORITY_Y
] = I915_FORMAT_MOD_Y_TILED
,
52 [MODIFIER_PRIORITY_Y_CCS
] = I915_FORMAT_MOD_Y_TILED_CCS
,
56 modifier_is_supported(const struct gen_device_info
*devinfo
,
59 /* XXX: do something real */
61 case I915_FORMAT_MOD_Y_TILED
:
62 case I915_FORMAT_MOD_X_TILED
:
63 case DRM_FORMAT_MOD_LINEAR
:
65 case I915_FORMAT_MOD_Y_TILED_CCS
:
66 case DRM_FORMAT_MOD_INVALID
:
73 select_best_modifier(struct gen_device_info
*devinfo
,
74 const uint64_t *modifiers
,
77 enum modifier_priority prio
= MODIFIER_PRIORITY_INVALID
;
79 for (int i
= 0; i
< count
; i
++) {
80 if (!modifier_is_supported(devinfo
, modifiers
[i
]))
83 switch (modifiers
[i
]) {
84 case I915_FORMAT_MOD_Y_TILED_CCS
:
85 prio
= MAX2(prio
, MODIFIER_PRIORITY_Y_CCS
);
87 case I915_FORMAT_MOD_Y_TILED
:
88 prio
= MAX2(prio
, MODIFIER_PRIORITY_Y
);
90 case I915_FORMAT_MOD_X_TILED
:
91 prio
= MAX2(prio
, MODIFIER_PRIORITY_X
);
93 case DRM_FORMAT_MOD_LINEAR
:
94 prio
= MAX2(prio
, MODIFIER_PRIORITY_LINEAR
);
96 case DRM_FORMAT_MOD_INVALID
:
102 return priority_to_modifier
[prio
];
105 static enum isl_surf_dim
106 target_to_isl_surf_dim(enum pipe_texture_target target
)
110 case PIPE_TEXTURE_1D
:
111 case PIPE_TEXTURE_1D_ARRAY
:
112 return ISL_SURF_DIM_1D
;
113 case PIPE_TEXTURE_2D
:
114 case PIPE_TEXTURE_CUBE
:
115 case PIPE_TEXTURE_RECT
:
116 case PIPE_TEXTURE_2D_ARRAY
:
117 case PIPE_TEXTURE_CUBE_ARRAY
:
118 return ISL_SURF_DIM_2D
;
119 case PIPE_TEXTURE_3D
:
120 return ISL_SURF_DIM_3D
;
121 case PIPE_MAX_TEXTURE_TYPES
:
124 unreachable("invalid texture type");
127 static isl_surf_usage_flags_t
128 pipe_bind_to_isl_usage(unsigned bindings
)
130 isl_surf_usage_flags_t usage
= 0;
132 if (bindings
& PIPE_BIND_DEPTH_STENCIL
)
133 usage
|= ISL_SURF_USAGE_DEPTH_BIT
| ISL_SURF_USAGE_STENCIL_BIT
;
135 if (bindings
& PIPE_BIND_RENDER_TARGET
)
136 usage
|= ISL_SURF_USAGE_RENDER_TARGET_BIT
;
138 if (bindings
& PIPE_BIND_SHADER_IMAGE
)
139 usage
|= ISL_SURF_USAGE_STORAGE_BIT
;
141 if (bindings
& PIPE_BIND_DISPLAY_TARGET
)
142 usage
|= ISL_SURF_USAGE_DISPLAY_BIT
;
144 /* XXX: what to do with these? */
145 if (bindings
& PIPE_BIND_BLENDABLE
)
147 if (bindings
& PIPE_BIND_SAMPLER_VIEW
)
149 if (bindings
& PIPE_BIND_VERTEX_BUFFER
)
151 if (bindings
& PIPE_BIND_INDEX_BUFFER
)
153 if (bindings
& PIPE_BIND_CONSTANT_BUFFER
)
156 if (bindings
& PIPE_BIND_STREAM_OUTPUT
)
158 if (bindings
& PIPE_BIND_CURSOR
)
160 if (bindings
& PIPE_BIND_CUSTOM
)
163 if (bindings
& PIPE_BIND_GLOBAL
)
165 if (bindings
& PIPE_BIND_SHADER_BUFFER
)
167 if (bindings
& PIPE_BIND_COMPUTE_RESOURCE
)
169 if (bindings
& PIPE_BIND_COMMAND_ARGS_BUFFER
)
171 if (bindings
& PIPE_BIND_QUERY_BUFFER
)
178 iris_resource_destroy(struct pipe_screen
*screen
,
179 struct pipe_resource
*resource
)
181 struct iris_resource
*res
= (struct iris_resource
*)resource
;
183 iris_bo_unreference(res
->bo
);
186 static struct iris_resource
*
187 iris_alloc_resource(struct pipe_screen
*pscreen
,
188 const struct pipe_resource
*templ
)
190 struct iris_resource
*res
= calloc(1, sizeof(struct iris_resource
));
195 res
->base
.screen
= pscreen
;
196 pipe_reference_init(&res
->base
.reference
, 1);
201 static struct pipe_resource
*
202 iris_resource_create_with_modifiers(struct pipe_screen
*pscreen
,
203 const struct pipe_resource
*templ
,
204 const uint64_t *modifiers
,
207 struct iris_screen
*screen
= (struct iris_screen
*)pscreen
;
208 struct gen_device_info
*devinfo
= &screen
->devinfo
;
209 struct iris_resource
*res
= iris_alloc_resource(pscreen
, templ
);
213 uint64_t modifier
= DRM_FORMAT_MOD_INVALID
;
215 if (templ
->target
== PIPE_BUFFER
)
216 modifier
= DRM_FORMAT_MOD_LINEAR
;
218 if (templ
->bind
& (PIPE_BIND_LINEAR
| PIPE_BIND_CURSOR
))
219 modifier
= DRM_FORMAT_MOD_LINEAR
;
221 if (modifiers_count
== 0) {
222 /* Display is X-tiled for historical reasons. */
223 modifier
= (templ
->bind
& PIPE_BIND_DISPLAY_TARGET
) ?
224 I915_FORMAT_MOD_X_TILED
: I915_FORMAT_MOD_Y_TILED
;
225 /* XXX: make sure this doesn't do stupid things for internal textures */
228 if (modifier
== DRM_FORMAT_MOD_INVALID
) {
229 /* User requested specific modifiers */
230 modifier
= select_best_modifier(devinfo
, modifiers
, modifiers_count
);
231 if (modifier
== DRM_FORMAT_MOD_INVALID
)
235 const struct isl_drm_modifier_info
*mod_info
=
236 isl_drm_modifier_get_info(modifier
);
238 isl_surf_usage_flags_t usage
= pipe_bind_to_isl_usage(templ
->bind
);
240 if (templ
->target
== PIPE_TEXTURE_CUBE
)
241 usage
|= ISL_SURF_USAGE_CUBE_BIT
;
243 isl_surf_init(&screen
->isl_dev
, &res
->surf
,
244 .dim
= target_to_isl_surf_dim(templ
->target
),
245 .format
= iris_isl_format_for_pipe_format(templ
->format
),
246 .width
= templ
->width0
,
247 .height
= templ
->height0
,
248 .depth
= templ
->depth0
,
249 .levels
= templ
->last_level
+ 1,
250 .array_len
= templ
->array_size
,
251 .samples
= MAX2(templ
->nr_samples
, 1),
252 .min_alignment_B
= 0,
255 .tiling_flags
= 1 << mod_info
->tiling
);
257 res
->bo
= iris_bo_alloc_tiled(screen
->bufmgr
, "resource", res
->surf
.size_B
,
258 isl_tiling_to_i915_tiling(res
->surf
.tiling
),
259 res
->surf
.row_pitch_B
, 0);
266 iris_resource_destroy(pscreen
, &res
->base
);
270 static struct pipe_resource
*
271 iris_resource_create(struct pipe_screen
*pscreen
,
272 const struct pipe_resource
*templ
)
274 return iris_resource_create_with_modifiers(pscreen
, templ
, NULL
, 0);
277 static struct pipe_resource
*
278 iris_resource_from_handle(struct pipe_screen
*pscreen
,
279 const struct pipe_resource
*templ
,
280 struct winsys_handle
*whandle
,
283 struct iris_screen
*screen
= (struct iris_screen
*)pscreen
;
284 struct iris_bufmgr
*bufmgr
= screen
->bufmgr
;
285 struct iris_resource
*res
= iris_alloc_resource(pscreen
, templ
);
289 if (whandle
->offset
!= 0) {
290 dbg_printf("Attempt to import unsupported winsys offset %u\n",
295 switch (whandle
->type
) {
296 case WINSYS_HANDLE_TYPE_SHARED
:
297 res
->bo
= iris_bo_import_dmabuf(bufmgr
, whandle
->handle
);
299 case WINSYS_HANDLE_TYPE_FD
:
300 res
->bo
= iris_bo_gem_create_from_name(bufmgr
, "winsys image",
304 unreachable("invalid winsys handle type");
307 const struct isl_drm_modifier_info
*mod_info
=
308 isl_drm_modifier_get_info(whandle
->modifier
);
311 isl_surf_usage_flags_t isl_usage
= ISL_SURF_USAGE_DISPLAY_BIT
;
313 isl_surf_init(&screen
->isl_dev
, &res
->surf
,
314 .dim
= target_to_isl_surf_dim(templ
->target
),
315 .format
= iris_isl_format_for_pipe_format(templ
->format
),
316 .width
= templ
->width0
,
317 .height
= templ
->height0
,
318 .depth
= templ
->depth0
,
319 .levels
= templ
->last_level
+ 1,
320 .array_len
= templ
->array_size
,
321 .samples
= MAX2(templ
->nr_samples
, 1),
322 .min_alignment_B
= 0,
325 .tiling_flags
= 1 << mod_info
->tiling
);
327 assert(res
->bo
->tiling_mode
== isl_tiling_to_i915_tiling(res
->surf
.tiling
));
332 iris_resource_destroy(pscreen
, &res
->base
);
337 iris_resource_get_handle(struct pipe_screen
*pscreen
,
338 struct pipe_context
*ctx
,
339 struct pipe_resource
*resource
,
340 struct winsys_handle
*whandle
,
343 struct iris_resource
*res
= (struct iris_resource
*)resource
;
345 whandle
->stride
= res
->surf
.row_pitch_B
;
347 switch (whandle
->type
) {
348 case WINSYS_HANDLE_TYPE_SHARED
:
349 return iris_bo_flink(res
->bo
, &whandle
->handle
) > 0;
350 case WINSYS_HANDLE_TYPE_KMS
:
351 return iris_bo_export_gem_handle(res
->bo
);
352 case WINSYS_HANDLE_TYPE_FD
:
353 return iris_bo_export_dmabuf(res
->bo
, (int *) &whandle
->handle
) > 0;
360 iris_init_screen_resource_functions(struct pipe_screen
*pscreen
)
362 pscreen
->resource_create_with_modifiers
=
363 iris_resource_create_with_modifiers
;
364 pscreen
->resource_create
= iris_resource_create
;
365 pscreen
->resource_from_handle
= iris_resource_from_handle
;
366 pscreen
->resource_get_handle
= iris_resource_get_handle
;
367 pscreen
->resource_destroy
= iris_resource_destroy
;