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 enum iris_memory_zone memzone
= IRIS_MEMZONE_OTHER
;
260 const char *name
= "resource";
261 if (templ
->flags
& IRIS_RESOURCE_FLAG_INSTRUCTION_CACHE
) {
262 memzone
= IRIS_MEMZONE_SHADER
;
263 name
= "shader kernels";
266 res
->bo
= iris_bo_alloc_tiled(screen
->bufmgr
, name
, res
->surf
.size_B
,
268 isl_tiling_to_i915_tiling(res
->surf
.tiling
),
269 res
->surf
.row_pitch_B
, 0);
276 iris_resource_destroy(pscreen
, &res
->base
);
280 static struct pipe_resource
*
281 iris_resource_create(struct pipe_screen
*pscreen
,
282 const struct pipe_resource
*templ
)
284 return iris_resource_create_with_modifiers(pscreen
, templ
, NULL
, 0);
287 static struct pipe_resource
*
288 iris_resource_from_handle(struct pipe_screen
*pscreen
,
289 const struct pipe_resource
*templ
,
290 struct winsys_handle
*whandle
,
293 struct iris_screen
*screen
= (struct iris_screen
*)pscreen
;
294 struct iris_bufmgr
*bufmgr
= screen
->bufmgr
;
295 struct iris_resource
*res
= iris_alloc_resource(pscreen
, templ
);
299 if (whandle
->offset
!= 0) {
300 dbg_printf("Attempt to import unsupported winsys offset %u\n",
305 switch (whandle
->type
) {
306 case WINSYS_HANDLE_TYPE_SHARED
:
307 res
->bo
= iris_bo_import_dmabuf(bufmgr
, whandle
->handle
);
309 case WINSYS_HANDLE_TYPE_FD
:
310 res
->bo
= iris_bo_gem_create_from_name(bufmgr
, "winsys image",
314 unreachable("invalid winsys handle type");
317 const struct isl_drm_modifier_info
*mod_info
=
318 isl_drm_modifier_get_info(whandle
->modifier
);
321 isl_surf_usage_flags_t isl_usage
= ISL_SURF_USAGE_DISPLAY_BIT
;
323 isl_surf_init(&screen
->isl_dev
, &res
->surf
,
324 .dim
= target_to_isl_surf_dim(templ
->target
),
325 .format
= iris_isl_format_for_pipe_format(templ
->format
),
326 .width
= templ
->width0
,
327 .height
= templ
->height0
,
328 .depth
= templ
->depth0
,
329 .levels
= templ
->last_level
+ 1,
330 .array_len
= templ
->array_size
,
331 .samples
= MAX2(templ
->nr_samples
, 1),
332 .min_alignment_B
= 0,
335 .tiling_flags
= 1 << mod_info
->tiling
);
337 assert(res
->bo
->tiling_mode
== isl_tiling_to_i915_tiling(res
->surf
.tiling
));
342 iris_resource_destroy(pscreen
, &res
->base
);
347 iris_resource_get_handle(struct pipe_screen
*pscreen
,
348 struct pipe_context
*ctx
,
349 struct pipe_resource
*resource
,
350 struct winsys_handle
*whandle
,
353 struct iris_resource
*res
= (struct iris_resource
*)resource
;
355 whandle
->stride
= res
->surf
.row_pitch_B
;
357 switch (whandle
->type
) {
358 case WINSYS_HANDLE_TYPE_SHARED
:
359 return iris_bo_flink(res
->bo
, &whandle
->handle
) == 0;
360 case WINSYS_HANDLE_TYPE_KMS
:
361 return iris_bo_export_gem_handle(res
->bo
) != 0;
362 case WINSYS_HANDLE_TYPE_FD
:
363 return iris_bo_export_dmabuf(res
->bo
, (int *) &whandle
->handle
) == 0;
370 iris_transfer_map(struct pipe_context
*ctx
,
371 struct pipe_resource
*resource
,
373 enum pipe_transfer_usage usage
,
374 const struct pipe_box
*box
,
375 struct pipe_transfer
**ptransfer
)
377 struct iris_context
*ice
= (struct iris_context
*)ctx
;
378 struct iris_resource
*res
= (struct iris_resource
*)resource
;
379 struct pipe_transfer
*transfer
;
381 // PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE
382 // PIPE_TRANSFER_DISCARD_RANGE
383 // PIPE_TRANSFER_MAP_DIRECTLY
385 transfer
= calloc(1, sizeof(struct pipe_transfer
));
389 pipe_resource_reference(&transfer
->resource
, resource
);
390 transfer
->level
= level
;
391 transfer
->usage
= usage
;
392 transfer
->box
= *box
;
393 transfer
->stride
= isl_surf_get_row_pitch_B(&res
->surf
);
394 transfer
->layer_stride
= isl_surf_get_array_pitch(&res
->surf
);
395 *ptransfer
= transfer
;
397 if (!(usage
& PIPE_TRANSFER_UNSYNCHRONIZED
) &&
398 iris_batch_references(&ice
->render_batch
, res
->bo
)) {
399 iris_batch_flush(&ice
->render_batch
);
402 if ((usage
& PIPE_TRANSFER_DONTBLOCK
) && iris_bo_busy(res
->bo
))
405 usage
&= (PIPE_TRANSFER_READ
|
406 PIPE_TRANSFER_WRITE
|
407 PIPE_TRANSFER_UNSYNCHRONIZED
|
408 PIPE_TRANSFER_PERSISTENT
|
409 PIPE_TRANSFER_COHERENT
);
411 return iris_bo_map(&ice
->dbg
, res
->bo
, usage
);
415 iris_transfer_flush_region(struct pipe_context
*pipe
,
416 struct pipe_transfer
*transfer
,
417 const struct pipe_box
*box
)
422 iris_transfer_unmap(struct pipe_context
*pipe
,
423 struct pipe_transfer
*transfer
)
425 pipe_resource_reference(&transfer
->resource
, NULL
);
430 iris_buffer_subdata(struct pipe_context
*pipe
,
431 struct pipe_resource
*resource
,
432 unsigned usage
, unsigned offset
,
433 unsigned size
, const void *data
)
438 iris_texture_subdata(struct pipe_context
*pipe
,
439 struct pipe_resource
*resource
,
442 const struct pipe_box
*box
,
445 unsigned layer_stride
)
451 iris_resource_copy_region(struct pipe_context
*ctx
,
452 struct pipe_resource
*dst
,
454 unsigned dstx
, unsigned dsty
, unsigned dstz
,
455 struct pipe_resource
*src
,
457 const struct pipe_box
*src_box
)
462 iris_flush_resource(struct pipe_context
*ctx
, struct pipe_resource
*resource
)
467 iris_generate_mipmap(struct pipe_context
*ctx
,
468 struct pipe_resource
*resource
,
469 enum pipe_format format
,
472 unsigned first_layer
,
479 iris_init_screen_resource_functions(struct pipe_screen
*pscreen
)
481 pscreen
->resource_create_with_modifiers
=
482 iris_resource_create_with_modifiers
;
483 pscreen
->resource_create
= iris_resource_create
;
484 pscreen
->resource_from_handle
= iris_resource_from_handle
;
485 pscreen
->resource_get_handle
= iris_resource_get_handle
;
486 pscreen
->resource_destroy
= iris_resource_destroy
;
490 iris_init_resource_functions(struct pipe_context
*ctx
)
492 ctx
->flush_resource
= iris_flush_resource
;
493 ctx
->transfer_map
= iris_transfer_map
;
494 ctx
->transfer_flush_region
= iris_transfer_flush_region
;
495 ctx
->transfer_unmap
= iris_transfer_unmap
;
496 ctx
->buffer_subdata
= iris_buffer_subdata
;
497 ctx
->texture_subdata
= iris_texture_subdata
;
498 ctx
->resource_copy_region
= iris_resource_copy_region
;