mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-20 13:28:09 +02:00
Reviewed-by: Lars-Ivar Hesselberg Simonsen <lars-ivar.simonsen@arm.com> Acked-by: Boris Brezillon <boris.brezillon@collabora.com> Acked-by: Eric R. Smith <eric.smith@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/39759>
350 lines
9.9 KiB
C
350 lines
9.9 KiB
C
/*
|
|
* Copyright (C) 2008 VMware, Inc.
|
|
* Copyright (C) 2014 Broadcom
|
|
* Copyright (C) 2018-2019 Alyssa Rosenzweig
|
|
* Copyright (C) 2019-2020 Collabora, Ltd.
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
|
|
#ifndef __PAN_IMAGE_H
|
|
#define __PAN_IMAGE_H
|
|
|
|
#include "genxml/gen_macros.h"
|
|
|
|
#include <stdbool.h>
|
|
#include "util/format/u_format.h"
|
|
#include "pan_format.h"
|
|
#include "pan_layout.h"
|
|
#include "pan_mod.h"
|
|
#include "pan_props.h"
|
|
|
|
#include "kmod/pan_kmod.h"
|
|
|
|
#include "util/log.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
struct pan_mod_handler;
|
|
|
|
struct pan_image_plane {
|
|
struct pan_image_layout layout;
|
|
uint64_t base;
|
|
};
|
|
|
|
struct pan_image {
|
|
struct pan_image_props props;
|
|
const struct pan_mod_handler *mod_handler;
|
|
struct pan_image_plane *planes[MAX_IMAGE_PLANES];
|
|
};
|
|
|
|
struct pan_image_plane_ref {
|
|
struct pan_image *image;
|
|
uint32_t plane_idx;
|
|
};
|
|
|
|
struct pan_image_view {
|
|
/* Format, dimension and sample count of the view might differ from
|
|
* those of the image (2D view of a 3D image surface for instance).
|
|
*/
|
|
enum pipe_format format;
|
|
enum mali_texture_dimension dim;
|
|
unsigned first_level, last_level;
|
|
unsigned first_layer, last_layer;
|
|
float min_lod;
|
|
unsigned char swizzle[4];
|
|
|
|
/* planes 1 and 2 are NULL for single plane formats */
|
|
struct pan_image_plane_ref planes[MAX_IMAGE_PLANES];
|
|
|
|
/* If EXT_multisampled_render_to_texture is used, this may be
|
|
* greater than image->layout.nr_samples. */
|
|
unsigned nr_samples;
|
|
|
|
struct {
|
|
unsigned narrow;
|
|
unsigned hdr;
|
|
} astc;
|
|
};
|
|
|
|
static inline struct pan_image_plane_ref
|
|
pan_image_view_get_plane(const struct pan_image_view *iview, uint32_t idx)
|
|
{
|
|
if (idx >= ARRAY_SIZE(iview->planes))
|
|
return (struct pan_image_plane_ref){0};
|
|
|
|
return iview->planes[idx];
|
|
}
|
|
|
|
static inline unsigned
|
|
pan_image_view_get_plane_mask(const struct pan_image_view *iview)
|
|
{
|
|
unsigned mask = 0;
|
|
|
|
for (unsigned i = 0; i < ARRAY_SIZE(iview->planes); i++) {
|
|
if (iview->planes[i].image)
|
|
mask |= BITFIELD_BIT(i);
|
|
}
|
|
|
|
return mask;
|
|
}
|
|
|
|
static inline unsigned
|
|
pan_image_view_get_first_plane_idx(const struct pan_image_view *iview)
|
|
{
|
|
unsigned mask = pan_image_view_get_plane_mask(iview);
|
|
|
|
assert(mask);
|
|
return ffs(mask) - 1;
|
|
}
|
|
|
|
static inline struct pan_image_plane_ref
|
|
pan_image_view_get_first_plane(const struct pan_image_view *iview)
|
|
{
|
|
unsigned first_plane_idx = pan_image_view_get_first_plane_idx(iview);
|
|
return pan_image_view_get_plane(iview, first_plane_idx);
|
|
}
|
|
|
|
static inline uint32_t
|
|
pan_image_view_get_nr_samples(const struct pan_image_view *iview)
|
|
{
|
|
const struct pan_image_plane_ref pref = pan_image_view_get_first_plane(iview);
|
|
|
|
if (!pref.image)
|
|
return 0;
|
|
|
|
return pref.image->props.nr_samples;
|
|
}
|
|
|
|
static inline uint32_t
|
|
pan_image_view_get_layer_count(const struct pan_image_view *iview)
|
|
{
|
|
const struct pan_image_plane_ref pref = pan_image_view_get_first_plane(iview);
|
|
|
|
if (!pref.image)
|
|
return 0;
|
|
|
|
return iview->dim == MALI_TEXTURE_DIMENSION_3D
|
|
? pref.image->props.extent_px.depth
|
|
: iview->last_layer - iview->first_layer + 1;
|
|
}
|
|
|
|
static inline const struct pan_image_plane_ref
|
|
pan_image_view_get_color_plane(const struct pan_image_view *iview)
|
|
{
|
|
/* We only support rendering to plane 0 */
|
|
assert(pan_image_view_get_plane(iview, 1).image == NULL);
|
|
return pan_image_view_get_plane(iview, 0);
|
|
}
|
|
|
|
static inline bool
|
|
pan_image_view_has_crc(const struct pan_image_view *iview)
|
|
{
|
|
const struct pan_image_plane_ref p = pan_image_view_get_color_plane(iview);
|
|
|
|
if (!p.image)
|
|
return false;
|
|
|
|
return p.image->props.crc;
|
|
}
|
|
|
|
static inline struct pan_image_plane_ref
|
|
pan_image_view_get_s_plane(const struct pan_image_view *iview)
|
|
{
|
|
ASSERTED const struct util_format_description *fdesc =
|
|
util_format_description(iview->format);
|
|
assert(util_format_has_stencil(fdesc));
|
|
|
|
/* In case of multiplanar depth/stencil, the stencil is always on
|
|
* plane 1. Combined depth/stencil only has one plane, so depth
|
|
* will be on plane 0 in either case.
|
|
*/
|
|
const struct pan_image_plane_ref pref =
|
|
iview->planes[1].image ? iview->planes[1] : iview->planes[0];
|
|
|
|
assert(pref.image);
|
|
fdesc = util_format_description(pref.image->props.format);
|
|
assert(util_format_has_stencil(fdesc));
|
|
return pref;
|
|
}
|
|
|
|
static inline struct pan_image_plane_ref
|
|
pan_image_view_get_zs_plane(const struct pan_image_view *iview)
|
|
{
|
|
assert(util_format_is_depth_or_stencil(iview->format));
|
|
|
|
/* Depth or combined depth-stencil is always on plane 0. */
|
|
return pan_image_view_get_plane(iview, 0);
|
|
}
|
|
|
|
static inline void
|
|
pan_image_view_check(const struct pan_image_view *iview)
|
|
{
|
|
#ifndef NDEBUG
|
|
unsigned nplanes = util_format_get_num_planes(iview->format);
|
|
struct pan_image_plane_ref pref;
|
|
|
|
for (unsigned i = 0; i < nplanes; i++) {
|
|
if (util_format_is_depth_or_stencil(iview->format)) {
|
|
const struct util_format_description *fdesc =
|
|
util_format_description(iview->format);
|
|
|
|
if (util_format_has_stencil(fdesc))
|
|
pref = pan_image_view_get_s_plane(iview);
|
|
else
|
|
pref = pan_image_view_get_zs_plane(iview);
|
|
} else {
|
|
pref = iview->planes[i];
|
|
}
|
|
|
|
/* Make sure we have an image and the plane we point to exists. */
|
|
assert(pref.image);
|
|
assert(pref.plane_idx <
|
|
util_format_get_num_planes(pref.image->props.format));
|
|
|
|
enum pipe_format view_format =
|
|
util_format_get_plane_format(iview->format, i);
|
|
enum pipe_format img_format =
|
|
util_format_get_plane_format(pref.image->props.format, pref.plane_idx);
|
|
|
|
/* View-based pixel re-interpretation only allowed if the formats
|
|
* blocksize match. */
|
|
assert(util_format_get_blocksize(view_format) ==
|
|
util_format_get_blocksize(img_format));
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static inline uint64_t
|
|
pan_image_mip_level_size(const struct pan_image *image, unsigned plane_idx,
|
|
unsigned mip_level)
|
|
{
|
|
assert(plane_idx < ARRAY_SIZE(image->planes) &&
|
|
plane_idx < util_format_get_num_planes(image->props.format));
|
|
assert(mip_level < image->props.nr_slices);
|
|
assert(image->planes[plane_idx]);
|
|
|
|
uint64_t size = image->planes[plane_idx]->layout.slices[mip_level].size_B;
|
|
|
|
/* If this is an array, we need to cover the whole array. */
|
|
if (image->props.array_size > 1) {
|
|
size += image->planes[plane_idx]->layout.array_stride_B *
|
|
(image->props.array_size - 1);
|
|
}
|
|
|
|
return size;
|
|
}
|
|
|
|
static inline uint32_t
|
|
pan_image_get_wsi_row_pitch(const struct pan_image *image, unsigned plane_idx,
|
|
unsigned mip_level)
|
|
{
|
|
assert(image->mod_handler);
|
|
assert(image->mod_handler->get_wsi_row_pitch);
|
|
assert(plane_idx < ARRAY_SIZE(image->planes) &&
|
|
plane_idx < util_format_get_num_planes(image->props.format));
|
|
assert(image->planes[plane_idx]);
|
|
|
|
return image->mod_handler->get_wsi_row_pitch(image, plane_idx, mip_level);
|
|
}
|
|
|
|
static inline uint64_t
|
|
pan_image_get_wsi_offset(const struct pan_image *image, unsigned plane_idx,
|
|
unsigned mip_level)
|
|
{
|
|
assert(plane_idx < ARRAY_SIZE(image->planes) &&
|
|
plane_idx < util_format_get_num_planes(image->props.format));
|
|
assert(mip_level < image->props.nr_slices);
|
|
assert(image->planes[plane_idx]);
|
|
|
|
return image->planes[plane_idx]->layout.slices[mip_level].offset_B;
|
|
}
|
|
|
|
bool pan_image_layout_init(
|
|
unsigned arch, struct pan_image *image, unsigned plane_idx,
|
|
const struct pan_image_layout_constraints *explicit_layout_constraints);
|
|
|
|
struct pan_image_usage {
|
|
/* PAN_BIND_xxx flags. */
|
|
uint32_t bind;
|
|
|
|
/* Image needs to be mappable at standard sparse block granularity. */
|
|
bool standard_sparse_mapping_granularity;
|
|
|
|
/* Image filled directly from the CPU. */
|
|
bool host_copy;
|
|
|
|
/* Image frequently updated with host data. */
|
|
bool frequent_host_updates;
|
|
|
|
/* Legacy scanout image. */
|
|
bool legacy_scanout;
|
|
|
|
/* Image created by WSI. */
|
|
bool wsi;
|
|
};
|
|
|
|
static inline enum pan_mod_support
|
|
pan_image_test_props(const struct pan_kmod_dev_props *dprops,
|
|
const struct pan_image_props *iprops,
|
|
const struct pan_image_usage *iusage)
|
|
{
|
|
const unsigned arch = pan_arch(dprops->gpu_id);
|
|
struct pan_image image = {
|
|
.props = *iprops,
|
|
.mod_handler = pan_mod_get_handler(arch, iprops->modifier),
|
|
};
|
|
|
|
if (!image.mod_handler)
|
|
return PAN_MOD_NOT_SUPPORTED;
|
|
|
|
enum pan_mod_support ret =
|
|
image.mod_handler->test_props(dprops, &image.props, iusage);
|
|
if (ret == PAN_MOD_NOT_SUPPORTED)
|
|
return ret;
|
|
|
|
/* Now make sure the layout can be properly initialized on all planes. */
|
|
uint32_t plane_count = util_format_get_num_planes(image.props.format);
|
|
for (uint32_t p = 0; p < plane_count; p++) {
|
|
struct pan_image_plane plane;
|
|
|
|
memset(&plane, 0, sizeof(plane));
|
|
image.planes[p] = &plane;
|
|
|
|
if (!pan_image_layout_init(arch, &image, p, NULL))
|
|
return PAN_MOD_NOT_SUPPORTED;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static inline bool
|
|
pan_image_test_modifier_with_format(const struct pan_kmod_dev_props *dprops,
|
|
uint64_t modifier, enum pipe_format format)
|
|
{
|
|
/* To check if a <modifier,format> pair is supported, we define the smallest
|
|
* possible 2D image (or 3D image if this is a 3D compressed format). */
|
|
const struct pan_image_props iprops = {
|
|
.modifier = modifier,
|
|
.format = format,
|
|
.extent_px = {
|
|
.width = util_format_get_blockwidth(format),
|
|
.height = util_format_get_blockheight(format),
|
|
.depth = util_format_get_blockdepth(format),
|
|
},
|
|
.nr_samples = 1,
|
|
.dim = util_format_get_blockdepth(format) > 1 ? MALI_TEXTURE_DIMENSION_3D
|
|
: MALI_TEXTURE_DIMENSION_2D,
|
|
.nr_slices = 1,
|
|
.array_size = 1,
|
|
};
|
|
|
|
return pan_image_test_props(dprops, &iprops, NULL) != PAN_MOD_NOT_SUPPORTED;
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
} /* extern C */
|
|
#endif
|
|
|
|
#endif
|