asahi: Make resource creation code modifier-aware
Needed for WSI. Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/19606>
This commit is contained in:
@@ -259,9 +259,6 @@ agx_resource_get_handle(struct pipe_screen *pscreen,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Linear textures require specifying their strides explicitly, which only
|
|
||||||
* works for 2D textures. Rectangle textures are a special case of 2D.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
agx_resource_get_param(struct pipe_screen *pscreen,
|
agx_resource_get_param(struct pipe_screen *pscreen,
|
||||||
@@ -303,24 +300,78 @@ agx_is_2d(enum pipe_texture_target target)
|
|||||||
return (target == PIPE_TEXTURE_2D || target == PIPE_TEXTURE_RECT);
|
return (target == PIPE_TEXTURE_2D || target == PIPE_TEXTURE_RECT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t
|
static bool
|
||||||
agx_select_modifier(const struct agx_resource *pres)
|
agx_linear_allowed(const struct agx_resource *pres)
|
||||||
{
|
{
|
||||||
/* Buffers are always linear */
|
/* Mipmapping not allowed with linear */
|
||||||
if (pres->base.target == PIPE_BUFFER)
|
if (pres->base.last_level != 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
switch (pres->base.target) {
|
||||||
|
/* 1D is always linear */
|
||||||
|
case PIPE_BUFFER:
|
||||||
|
case PIPE_TEXTURE_1D:
|
||||||
|
|
||||||
|
/* Linear textures require specifying their strides explicitly, which only
|
||||||
|
* works for 2D textures. Rectangle textures are a special case of 2D.
|
||||||
|
*/
|
||||||
|
case PIPE_TEXTURE_2D:
|
||||||
|
case PIPE_TEXTURE_RECT:
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* No other texture type can specify a stride */
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
agx_twiddled_allowed(const struct agx_resource *pres)
|
||||||
|
{
|
||||||
|
/* Certain binds force linear */
|
||||||
|
if (pres->base.bind & (PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_SCANOUT | PIPE_BIND_LINEAR))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* Buffers must be linear, and it does not make sense to twiddle 1D */
|
||||||
|
if (pres->base.target == PIPE_BUFFER || pres->base.target == PIPE_TEXTURE_1D)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* Anything else may be twiddled */
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64_t
|
||||||
|
agx_select_modifier_from_list(const struct agx_resource *pres,
|
||||||
|
const uint64_t *modifiers, int count)
|
||||||
|
{
|
||||||
|
if (agx_twiddled_allowed(pres) &&
|
||||||
|
drm_find_modifier(DRM_FORMAT_MOD_APPLE_TWIDDLED, modifiers, count))
|
||||||
|
return DRM_FORMAT_MOD_APPLE_TWIDDLED;
|
||||||
|
|
||||||
|
if (agx_linear_allowed(pres) &&
|
||||||
|
drm_find_modifier(DRM_FORMAT_MOD_LINEAR, modifiers, count))
|
||||||
return DRM_FORMAT_MOD_LINEAR;
|
return DRM_FORMAT_MOD_LINEAR;
|
||||||
|
|
||||||
/* Optimize streaming textures */
|
/* We didn't find anything */
|
||||||
if (pres->base.usage == PIPE_USAGE_STREAM && agx_is_2d(pres->base.target))
|
return DRM_FORMAT_MOD_INVALID;
|
||||||
return DRM_FORMAT_MOD_LINEAR;
|
}
|
||||||
|
|
||||||
/* Default to tiled */
|
static uint64_t
|
||||||
return DRM_FORMAT_MOD_APPLE_TWIDDLED;
|
agx_select_best_modifier(const struct agx_resource *pres)
|
||||||
|
{
|
||||||
|
if (agx_twiddled_allowed(pres))
|
||||||
|
return DRM_FORMAT_MOD_APPLE_TWIDDLED;
|
||||||
|
|
||||||
|
assert(agx_linear_allowed(pres));
|
||||||
|
return DRM_FORMAT_MOD_LINEAR;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct pipe_resource *
|
static struct pipe_resource *
|
||||||
agx_resource_create(struct pipe_screen *screen,
|
agx_resource_create_with_modifiers(struct pipe_screen *screen,
|
||||||
const struct pipe_resource *templ)
|
const struct pipe_resource *templ,
|
||||||
|
const uint64_t *modifiers, int count)
|
||||||
{
|
{
|
||||||
struct agx_device *dev = agx_device(screen);
|
struct agx_device *dev = agx_device(screen);
|
||||||
struct agx_resource *nresource;
|
struct agx_resource *nresource;
|
||||||
@@ -332,30 +383,73 @@ agx_resource_create(struct pipe_screen *screen,
|
|||||||
nresource->base = *templ;
|
nresource->base = *templ;
|
||||||
nresource->base.screen = screen;
|
nresource->base.screen = screen;
|
||||||
|
|
||||||
nresource->modifier = agx_select_modifier(nresource);
|
if (modifiers) {
|
||||||
|
nresource->modifier = agx_select_modifier_from_list(nresource, modifiers, count);
|
||||||
|
|
||||||
|
/* There may not be a matching modifier, bail if so */
|
||||||
|
if (nresource->modifier == DRM_FORMAT_MOD_INVALID)
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
nresource->modifier = agx_select_best_modifier(nresource);
|
||||||
|
|
||||||
|
assert(nresource->modifier != DRM_FORMAT_MOD_INVALID);
|
||||||
|
}
|
||||||
|
|
||||||
nresource->mipmapped = (templ->last_level > 0);
|
nresource->mipmapped = (templ->last_level > 0);
|
||||||
|
|
||||||
assert(templ->format != PIPE_FORMAT_Z24X8_UNORM &&
|
assert(templ->format != PIPE_FORMAT_Z24X8_UNORM &&
|
||||||
templ->format != PIPE_FORMAT_Z24_UNORM_S8_UINT &&
|
templ->format != PIPE_FORMAT_Z24_UNORM_S8_UINT &&
|
||||||
"u_transfer_helper should have lowered");
|
"u_transfer_helper should have lowered");
|
||||||
|
|
||||||
nresource->layout = (struct ail_layout) {
|
agx_resource_setup(dev, nresource);
|
||||||
.tiling = (nresource->modifier == DRM_FORMAT_MOD_LINEAR) ?
|
|
||||||
AIL_TILING_LINEAR : AIL_TILING_TWIDDLED,
|
|
||||||
.format = templ->format,
|
|
||||||
.width_px = templ->width0,
|
|
||||||
.height_px = templ->height0,
|
|
||||||
.depth_px = templ->depth0 * templ->array_size,
|
|
||||||
.levels = templ->last_level + 1
|
|
||||||
};
|
|
||||||
|
|
||||||
pipe_reference_init(&nresource->base.reference, 1);
|
pipe_reference_init(&nresource->base.reference, 1);
|
||||||
|
|
||||||
struct sw_winsys *winsys = ((struct agx_screen *) screen)->winsys;
|
struct sw_winsys *winsys = ((struct agx_screen *) screen)->winsys;
|
||||||
|
|
||||||
if (templ->bind & (PIPE_BIND_DISPLAY_TARGET |
|
ail_make_miptree(&nresource->layout);
|
||||||
PIPE_BIND_SCANOUT |
|
|
||||||
PIPE_BIND_SHARED)) {
|
if (dev->ro && (templ->bind & PIPE_BIND_SCANOUT)) {
|
||||||
|
struct winsys_handle handle;
|
||||||
|
assert(util_format_get_blockwidth(templ->format) == 1);
|
||||||
|
assert(util_format_get_blockheight(templ->format) == 1);
|
||||||
|
|
||||||
|
unsigned width = templ->width0;
|
||||||
|
unsigned stride = templ->width0 * util_format_get_blocksize(templ->format);
|
||||||
|
unsigned size = nresource->layout.size_B;
|
||||||
|
unsigned effective_rows = DIV_ROUND_UP(size, stride);
|
||||||
|
|
||||||
|
struct pipe_resource scanout_tmpl = {
|
||||||
|
.target = nresource->base.target,
|
||||||
|
.format = templ->format,
|
||||||
|
.width0 = width,
|
||||||
|
.height0 = effective_rows,
|
||||||
|
.depth0 = 1,
|
||||||
|
.array_size = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
nresource->scanout = renderonly_scanout_for_resource(&scanout_tmpl,
|
||||||
|
dev->ro,
|
||||||
|
&handle);
|
||||||
|
|
||||||
|
if (!nresource->scanout) {
|
||||||
|
fprintf(stderr, "Failed to create scanout resource\n");
|
||||||
|
free(nresource);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
assert(handle.type == WINSYS_HANDLE_TYPE_FD);
|
||||||
|
nresource->bo = agx_bo_import(dev, handle.handle);
|
||||||
|
close(handle.handle);
|
||||||
|
|
||||||
|
if (!nresource->bo) {
|
||||||
|
free(nresource);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return &nresource->base;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (winsys && templ->bind & PIPE_BIND_DISPLAY_TARGET) {
|
||||||
unsigned width = templ->width0;
|
unsigned width = templ->width0;
|
||||||
unsigned height = templ->height0;
|
unsigned height = templ->height0;
|
||||||
|
|
||||||
@@ -382,7 +476,6 @@ agx_resource_create(struct pipe_screen *screen,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ail_make_miptree(&nresource->layout);
|
|
||||||
nresource->bo = agx_bo_create(dev, nresource->layout.size_B, AGX_MEMORY_TYPE_FRAMEBUFFER);
|
nresource->bo = agx_bo_create(dev, nresource->layout.size_B, AGX_MEMORY_TYPE_FRAMEBUFFER);
|
||||||
|
|
||||||
if (!nresource->bo) {
|
if (!nresource->bo) {
|
||||||
@@ -393,6 +486,13 @@ agx_resource_create(struct pipe_screen *screen,
|
|||||||
return &nresource->base;
|
return &nresource->base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct pipe_resource *
|
||||||
|
agx_resource_create(struct pipe_screen *screen,
|
||||||
|
const struct pipe_resource *templ)
|
||||||
|
{
|
||||||
|
return agx_resource_create_with_modifiers(screen, templ, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
agx_resource_destroy(struct pipe_screen *screen,
|
agx_resource_destroy(struct pipe_screen *screen,
|
||||||
struct pipe_resource *prsrc)
|
struct pipe_resource *prsrc)
|
||||||
@@ -1418,6 +1518,8 @@ agx_screen_create(int fd, struct renderonly *ro, struct sw_winsys *winsys)
|
|||||||
screen->context_create = agx_create_context;
|
screen->context_create = agx_create_context;
|
||||||
screen->resource_from_handle = agx_resource_from_handle;
|
screen->resource_from_handle = agx_resource_from_handle;
|
||||||
screen->resource_get_handle = agx_resource_get_handle;
|
screen->resource_get_handle = agx_resource_get_handle;
|
||||||
|
screen->resource_get_param = agx_resource_get_param;
|
||||||
|
screen->resource_create_with_modifiers = agx_resource_create_with_modifiers;
|
||||||
screen->flush_frontbuffer = agx_flush_frontbuffer;
|
screen->flush_frontbuffer = agx_flush_frontbuffer;
|
||||||
screen->get_timestamp = u_default_get_timestamp;
|
screen->get_timestamp = u_default_get_timestamp;
|
||||||
screen->fence_reference = agx_fence_reference;
|
screen->fence_reference = agx_fence_reference;
|
||||||
|
|||||||
Reference in New Issue
Block a user