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_batch.h"
34 #include "iris_context.h"
35 #include "iris_resource.h"
36 #include "iris_screen.h"
37 #include "intel/common/gen_debug.h"
38 #include "drm-uapi/drm_fourcc.h"
39 #include "drm-uapi/i915_drm.h"
41 enum modifier_priority
{
42 MODIFIER_PRIORITY_INVALID
= 0,
43 MODIFIER_PRIORITY_LINEAR
,
46 MODIFIER_PRIORITY_Y_CCS
,
49 static const uint64_t priority_to_modifier
[] = {
50 [MODIFIER_PRIORITY_INVALID
] = DRM_FORMAT_MOD_INVALID
,
51 [MODIFIER_PRIORITY_LINEAR
] = DRM_FORMAT_MOD_LINEAR
,
52 [MODIFIER_PRIORITY_X
] = I915_FORMAT_MOD_X_TILED
,
53 [MODIFIER_PRIORITY_Y
] = I915_FORMAT_MOD_Y_TILED
,
54 [MODIFIER_PRIORITY_Y_CCS
] = I915_FORMAT_MOD_Y_TILED_CCS
,
58 modifier_is_supported(const struct gen_device_info
*devinfo
,
61 /* XXX: do something real */
63 case I915_FORMAT_MOD_Y_TILED
:
64 case I915_FORMAT_MOD_X_TILED
:
65 case DRM_FORMAT_MOD_LINEAR
:
67 case I915_FORMAT_MOD_Y_TILED_CCS
:
68 case DRM_FORMAT_MOD_INVALID
:
75 select_best_modifier(struct gen_device_info
*devinfo
,
76 const uint64_t *modifiers
,
79 enum modifier_priority prio
= MODIFIER_PRIORITY_INVALID
;
81 for (int i
= 0; i
< count
; i
++) {
82 if (!modifier_is_supported(devinfo
, modifiers
[i
]))
85 switch (modifiers
[i
]) {
86 case I915_FORMAT_MOD_Y_TILED_CCS
:
87 prio
= MAX2(prio
, MODIFIER_PRIORITY_Y_CCS
);
89 case I915_FORMAT_MOD_Y_TILED
:
90 prio
= MAX2(prio
, MODIFIER_PRIORITY_Y
);
92 case I915_FORMAT_MOD_X_TILED
:
93 prio
= MAX2(prio
, MODIFIER_PRIORITY_X
);
95 case DRM_FORMAT_MOD_LINEAR
:
96 prio
= MAX2(prio
, MODIFIER_PRIORITY_LINEAR
);
98 case DRM_FORMAT_MOD_INVALID
:
104 return priority_to_modifier
[prio
];
107 static enum isl_surf_dim
108 target_to_isl_surf_dim(enum pipe_texture_target target
)
112 case PIPE_TEXTURE_1D
:
113 case PIPE_TEXTURE_1D_ARRAY
:
114 return ISL_SURF_DIM_1D
;
115 case PIPE_TEXTURE_2D
:
116 case PIPE_TEXTURE_CUBE
:
117 case PIPE_TEXTURE_RECT
:
118 case PIPE_TEXTURE_2D_ARRAY
:
119 case PIPE_TEXTURE_CUBE_ARRAY
:
120 return ISL_SURF_DIM_2D
;
121 case PIPE_TEXTURE_3D
:
122 return ISL_SURF_DIM_3D
;
123 case PIPE_MAX_TEXTURE_TYPES
:
126 unreachable("invalid texture type");
129 static isl_surf_usage_flags_t
130 pipe_bind_to_isl_usage(unsigned bindings
)
132 isl_surf_usage_flags_t usage
= 0;
134 if (bindings
& PIPE_BIND_DEPTH_STENCIL
)
135 usage
|= ISL_SURF_USAGE_DEPTH_BIT
| ISL_SURF_USAGE_STENCIL_BIT
;
137 if (bindings
& PIPE_BIND_RENDER_TARGET
)
138 usage
|= ISL_SURF_USAGE_RENDER_TARGET_BIT
;
140 if (bindings
& PIPE_BIND_SHADER_IMAGE
)
141 usage
|= ISL_SURF_USAGE_STORAGE_BIT
;
143 if (bindings
& PIPE_BIND_DISPLAY_TARGET
)
144 usage
|= ISL_SURF_USAGE_DISPLAY_BIT
;
146 /* XXX: what to do with these? */
147 if (bindings
& PIPE_BIND_BLENDABLE
)
149 if (bindings
& PIPE_BIND_SAMPLER_VIEW
)
151 if (bindings
& PIPE_BIND_VERTEX_BUFFER
)
153 if (bindings
& PIPE_BIND_INDEX_BUFFER
)
155 if (bindings
& PIPE_BIND_CONSTANT_BUFFER
)
158 if (bindings
& PIPE_BIND_STREAM_OUTPUT
)
160 if (bindings
& PIPE_BIND_CURSOR
)
162 if (bindings
& PIPE_BIND_CUSTOM
)
165 if (bindings
& PIPE_BIND_GLOBAL
)
167 if (bindings
& PIPE_BIND_SHADER_BUFFER
)
169 if (bindings
& PIPE_BIND_COMPUTE_RESOURCE
)
171 if (bindings
& PIPE_BIND_COMMAND_ARGS_BUFFER
)
173 if (bindings
& PIPE_BIND_QUERY_BUFFER
)
180 iris_resource_destroy(struct pipe_screen
*screen
,
181 struct pipe_resource
*resource
)
183 struct iris_resource
*res
= (struct iris_resource
*)resource
;
185 iris_bo_unreference(res
->bo
);
188 static struct iris_resource
*
189 iris_alloc_resource(struct pipe_screen
*pscreen
,
190 const struct pipe_resource
*templ
)
192 struct iris_resource
*res
= calloc(1, sizeof(struct iris_resource
));
197 res
->base
.screen
= pscreen
;
198 pipe_reference_init(&res
->base
.reference
, 1);
203 static struct pipe_resource
*
204 iris_resource_create_with_modifiers(struct pipe_screen
*pscreen
,
205 const struct pipe_resource
*templ
,
206 const uint64_t *modifiers
,
209 struct iris_screen
*screen
= (struct iris_screen
*)pscreen
;
210 struct gen_device_info
*devinfo
= &screen
->devinfo
;
211 struct iris_resource
*res
= iris_alloc_resource(pscreen
, templ
);
215 uint64_t modifier
= DRM_FORMAT_MOD_INVALID
;
217 if (modifiers_count
== 0) {
218 /* Display is X-tiled for historical reasons. */
219 modifier
= (templ
->bind
& PIPE_BIND_DISPLAY_TARGET
) ?
220 I915_FORMAT_MOD_X_TILED
: I915_FORMAT_MOD_Y_TILED
;
221 /* XXX: make sure this doesn't do stupid things for internal textures */
224 if (templ
->target
== PIPE_BUFFER
)
225 modifier
= DRM_FORMAT_MOD_LINEAR
;
227 if (templ
->bind
& (PIPE_BIND_LINEAR
| PIPE_BIND_CURSOR
))
228 modifier
= DRM_FORMAT_MOD_LINEAR
;
230 if (modifier
== DRM_FORMAT_MOD_INVALID
) {
231 /* User requested specific modifiers */
232 modifier
= select_best_modifier(devinfo
, modifiers
, modifiers_count
);
233 if (modifier
== DRM_FORMAT_MOD_INVALID
)
237 const struct isl_drm_modifier_info
*mod_info
=
238 isl_drm_modifier_get_info(modifier
);
240 isl_surf_usage_flags_t usage
= pipe_bind_to_isl_usage(templ
->bind
);
242 if (templ
->target
== PIPE_TEXTURE_CUBE
)
243 usage
|= ISL_SURF_USAGE_CUBE_BIT
;
245 isl_surf_init(&screen
->isl_dev
, &res
->surf
,
246 .dim
= target_to_isl_surf_dim(templ
->target
),
247 .format
= iris_isl_format_for_pipe_format(templ
->format
),
248 .width
= templ
->width0
,
249 .height
= templ
->height0
,
250 .depth
= templ
->depth0
,
251 .levels
= templ
->last_level
+ 1,
252 .array_len
= templ
->array_size
,
253 .samples
= MAX2(templ
->nr_samples
, 1),
254 .min_alignment_B
= 0,
257 .tiling_flags
= 1 << mod_info
->tiling
);
259 res
->bo
= iris_bo_alloc_tiled(screen
->bufmgr
, "resource", res
->surf
.size_B
,
260 isl_tiling_to_i915_tiling(res
->surf
.tiling
),
261 res
->surf
.row_pitch_B
, 0);
265 if (templ
->flags
& IRIS_RESOURCE_FLAG_INSTRUCTION_CACHE
) {
266 res
->bo
->kflags
= EXEC_OBJECT_PINNED
;
267 res
->bo
->name
= "instruction cache";
268 // XXX: p_atomic_add is backwards :(
269 res
->bo
->gtt_offset
= __atomic_fetch_add(&screen
->next_instruction_address
, res
->bo
->size
, __ATOMIC_ACQ_REL
);
275 iris_resource_destroy(pscreen
, &res
->base
);
279 static struct pipe_resource
*
280 iris_resource_create(struct pipe_screen
*pscreen
,
281 const struct pipe_resource
*templ
)
283 return iris_resource_create_with_modifiers(pscreen
, templ
, NULL
, 0);
286 static struct pipe_resource
*
287 iris_resource_from_handle(struct pipe_screen
*pscreen
,
288 const struct pipe_resource
*templ
,
289 struct winsys_handle
*whandle
,
292 struct iris_screen
*screen
= (struct iris_screen
*)pscreen
;
293 struct iris_bufmgr
*bufmgr
= screen
->bufmgr
;
294 struct iris_resource
*res
= iris_alloc_resource(pscreen
, templ
);
298 if (whandle
->offset
!= 0) {
299 dbg_printf("Attempt to import unsupported winsys offset %u\n",
304 switch (whandle
->type
) {
305 case WINSYS_HANDLE_TYPE_SHARED
:
306 res
->bo
= iris_bo_import_dmabuf(bufmgr
, whandle
->handle
);
308 case WINSYS_HANDLE_TYPE_FD
:
309 res
->bo
= iris_bo_gem_create_from_name(bufmgr
, "winsys image",
313 unreachable("invalid winsys handle type");
316 const struct isl_drm_modifier_info
*mod_info
=
317 isl_drm_modifier_get_info(whandle
->modifier
);
320 isl_surf_usage_flags_t isl_usage
= ISL_SURF_USAGE_DISPLAY_BIT
;
322 isl_surf_init(&screen
->isl_dev
, &res
->surf
,
323 .dim
= target_to_isl_surf_dim(templ
->target
),
324 .format
= iris_isl_format_for_pipe_format(templ
->format
),
325 .width
= templ
->width0
,
326 .height
= templ
->height0
,
327 .depth
= templ
->depth0
,
328 .levels
= templ
->last_level
+ 1,
329 .array_len
= templ
->array_size
,
330 .samples
= MAX2(templ
->nr_samples
, 1),
331 .min_alignment_B
= 0,
334 .tiling_flags
= 1 << mod_info
->tiling
);
336 assert(res
->bo
->tiling_mode
== isl_tiling_to_i915_tiling(res
->surf
.tiling
));
341 iris_resource_destroy(pscreen
, &res
->base
);
346 iris_resource_get_handle(struct pipe_screen
*pscreen
,
347 struct pipe_context
*ctx
,
348 struct pipe_resource
*resource
,
349 struct winsys_handle
*whandle
,
352 struct iris_resource
*res
= (struct iris_resource
*)resource
;
354 whandle
->stride
= res
->surf
.row_pitch_B
;
356 switch (whandle
->type
) {
357 case WINSYS_HANDLE_TYPE_SHARED
:
358 return iris_bo_flink(res
->bo
, &whandle
->handle
) == 0;
359 case WINSYS_HANDLE_TYPE_KMS
:
360 return iris_bo_export_gem_handle(res
->bo
) == 0;
361 case WINSYS_HANDLE_TYPE_FD
:
362 return iris_bo_export_dmabuf(res
->bo
, (int *) &whandle
->handle
) == 0;
369 iris_transfer_map(struct pipe_context
*ctx
,
370 struct pipe_resource
*resource
,
372 enum pipe_transfer_usage usage
,
373 const struct pipe_box
*box
,
374 struct pipe_transfer
**ptransfer
)
376 struct iris_context
*ice
= (struct iris_context
*)ctx
;
377 struct iris_resource
*res
= (struct iris_resource
*)resource
;
378 struct pipe_transfer
*transfer
;
380 // PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE
381 // PIPE_TRANSFER_DISCARD_RANGE
382 // PIPE_TRANSFER_MAP_DIRECTLY
384 transfer
= calloc(1, sizeof(struct pipe_transfer
));
388 pipe_resource_reference(&transfer
->resource
, resource
);
389 transfer
->level
= level
;
390 transfer
->usage
= usage
;
391 transfer
->box
= *box
;
392 transfer
->stride
= 1;
393 transfer
->layer_stride
= 1;
394 *ptransfer
= transfer
;
396 if (!(usage
& PIPE_TRANSFER_UNSYNCHRONIZED
) &&
397 iris_batch_references(&ice
->render_batch
, res
->bo
)) {
398 iris_batch_flush(&ice
->render_batch
);
401 if ((usage
& PIPE_TRANSFER_DONTBLOCK
) && iris_bo_busy(res
->bo
))
404 usage
&= (PIPE_TRANSFER_READ
|
405 PIPE_TRANSFER_WRITE
|
406 PIPE_TRANSFER_UNSYNCHRONIZED
|
407 PIPE_TRANSFER_PERSISTENT
|
408 PIPE_TRANSFER_COHERENT
);
410 return iris_bo_map(&ice
->dbg
, res
->bo
, usage
);
414 iris_transfer_flush_region(struct pipe_context
*pipe
,
415 struct pipe_transfer
*transfer
,
416 const struct pipe_box
*box
)
421 iris_transfer_unmap(struct pipe_context
*pipe
,
422 struct pipe_transfer
*transfer
)
424 pipe_resource_reference(&transfer
->resource
, NULL
);
429 iris_buffer_subdata(struct pipe_context
*pipe
,
430 struct pipe_resource
*resource
,
431 unsigned usage
, unsigned offset
,
432 unsigned size
, const void *data
)
437 iris_texture_subdata(struct pipe_context
*pipe
,
438 struct pipe_resource
*resource
,
441 const struct pipe_box
*box
,
444 unsigned layer_stride
)
450 iris_resource_copy_region(struct pipe_context
*ctx
,
451 struct pipe_resource
*dst
,
453 unsigned dstx
, unsigned dsty
, unsigned dstz
,
454 struct pipe_resource
*src
,
456 const struct pipe_box
*src_box
)
461 iris_flush_resource(struct pipe_context
*ctx
, struct pipe_resource
*resource
)
466 iris_generate_mipmap(struct pipe_context
*ctx
,
467 struct pipe_resource
*resource
,
468 enum pipe_format format
,
471 unsigned first_layer
,
478 iris_init_screen_resource_functions(struct pipe_screen
*pscreen
)
480 pscreen
->resource_create_with_modifiers
=
481 iris_resource_create_with_modifiers
;
482 pscreen
->resource_create
= iris_resource_create
;
483 pscreen
->resource_from_handle
= iris_resource_from_handle
;
484 pscreen
->resource_get_handle
= iris_resource_get_handle
;
485 pscreen
->resource_destroy
= iris_resource_destroy
;
489 iris_init_resource_functions(struct pipe_context
*ctx
)
491 ctx
->flush_resource
= iris_flush_resource
;
492 ctx
->transfer_map
= iris_transfer_map
;
493 ctx
->transfer_flush_region
= iris_transfer_flush_region
;
494 ctx
->transfer_unmap
= iris_transfer_unmap
;
495 ctx
->buffer_subdata
= iris_buffer_subdata
;
496 ctx
->texture_subdata
= iris_texture_subdata
;
497 ctx
->resource_copy_region
= iris_resource_copy_region
;