freedreno: core buffer modifier support
Split out of a patch from Fritz Koenig to decouple from a6xx UBWC enablement, and added fd_resource_create_with_modifiers().
This commit is contained in:
@@ -43,6 +43,7 @@
|
||||
#include "freedreno_query_hw.h"
|
||||
#include "freedreno_util.h"
|
||||
|
||||
#include <drm_fourcc.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* XXX this should go away, needed for 'struct winsys_handle' */
|
||||
@@ -810,12 +811,26 @@ has_depth(enum pipe_format format)
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
find_modifier(uint64_t needle, const uint64_t *haystack, int count)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (haystack[i] == needle)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new texture object, using the given template info.
|
||||
*/
|
||||
static struct pipe_resource *
|
||||
fd_resource_create(struct pipe_screen *pscreen,
|
||||
const struct pipe_resource *tmpl)
|
||||
fd_resource_create_with_modifiers(struct pipe_screen *pscreen,
|
||||
const struct pipe_resource *tmpl,
|
||||
const uint64_t *modifiers, int count)
|
||||
{
|
||||
struct fd_screen *screen = fd_screen(pscreen);
|
||||
struct fd_resource *rsc = CALLOC_STRUCT(fd_resource);
|
||||
@@ -840,10 +855,25 @@ fd_resource_create(struct pipe_screen *pscreen,
|
||||
PIPE_BIND_LINEAR | \
|
||||
PIPE_BIND_DISPLAY_TARGET)
|
||||
|
||||
bool linear = find_modifier(DRM_FORMAT_MOD_LINEAR, modifiers, count);
|
||||
if (tmpl->bind & LINEAR)
|
||||
linear = true;
|
||||
|
||||
/* Normally, for non-shared buffers, allow buffer compression if
|
||||
* not shared, otherwise only allow if QCOM_COMPRESSED modifier
|
||||
* is requested:
|
||||
*
|
||||
* TODO we should probably also limit tiled in a similar way,
|
||||
* except we don't have a format modifier for tiled. (We probably
|
||||
* should.)
|
||||
*/
|
||||
bool allow_ubwc = find_modifier(DRM_FORMAT_MOD_INVALID, modifiers, count);
|
||||
if (tmpl->bind & PIPE_BIND_SHARED)
|
||||
allow_ubwc = find_modifier(DRM_FORMAT_MOD_QCOM_COMPRESSED, modifiers, count);
|
||||
|
||||
if (screen->tile_mode &&
|
||||
(tmpl->target != PIPE_BUFFER) &&
|
||||
(tmpl->bind & PIPE_BIND_SAMPLER_VIEW) &&
|
||||
!(tmpl->bind & LINEAR)) {
|
||||
!linear) {
|
||||
rsc->tile_mode = screen->tile_mode(tmpl);
|
||||
}
|
||||
|
||||
@@ -888,6 +918,9 @@ fd_resource_create(struct pipe_screen *pscreen,
|
||||
|
||||
size = screen->setup_slices(rsc);
|
||||
|
||||
if (allow_ubwc && screen->fill_ubwc_buffer_sizes && rsc->tile_mode)
|
||||
size += screen->fill_ubwc_buffer_sizes(rsc);
|
||||
|
||||
/* special case for hw-query buffer, which we need to allocate before we
|
||||
* know the size:
|
||||
*/
|
||||
@@ -912,6 +945,34 @@ fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct pipe_resource *
|
||||
fd_resource_create(struct pipe_screen *pscreen,
|
||||
const struct pipe_resource *tmpl)
|
||||
{
|
||||
const uint64_t mod = DRM_FORMAT_MOD_INVALID;
|
||||
return fd_resource_create_with_modifiers(pscreen, tmpl, &mod, 1);
|
||||
}
|
||||
|
||||
static bool
|
||||
is_supported_modifier(struct pipe_screen *pscreen, enum pipe_format pfmt,
|
||||
uint64_t mod)
|
||||
{
|
||||
int count;
|
||||
|
||||
/* Get the count of supported modifiers: */
|
||||
pscreen->query_dmabuf_modifiers(pscreen, pfmt, 0, NULL, NULL, &count);
|
||||
|
||||
/* Get the supported modifiers: */
|
||||
uint64_t modifiers[count];
|
||||
pscreen->query_dmabuf_modifiers(pscreen, pfmt, 0, modifiers, NULL, &count);
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
if (modifiers[i] == mod)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a texture from a winsys_handle. The handle is often created in
|
||||
* another process by first creating a pipe texture and then calling
|
||||
@@ -922,6 +983,7 @@ fd_resource_from_handle(struct pipe_screen *pscreen,
|
||||
const struct pipe_resource *tmpl,
|
||||
struct winsys_handle *handle, unsigned usage)
|
||||
{
|
||||
struct fd_screen *screen = fd_screen(pscreen);
|
||||
struct fd_resource *rsc = CALLOC_STRUCT(fd_resource);
|
||||
struct fd_resource_slice *slice = &rsc->slices[0];
|
||||
struct pipe_resource *prsc = &rsc->base;
|
||||
@@ -960,6 +1022,19 @@ fd_resource_from_handle(struct pipe_screen *pscreen,
|
||||
(slice->pitch & (pitchalign - 1)))
|
||||
goto fail;
|
||||
|
||||
if (handle->modifier == DRM_FORMAT_MOD_QCOM_COMPRESSED) {
|
||||
if (!is_supported_modifier(pscreen, tmpl->format,
|
||||
DRM_FORMAT_MOD_QCOM_COMPRESSED)) {
|
||||
DBG("bad modifier: %lx", handle->modifier);
|
||||
goto fail;
|
||||
}
|
||||
debug_assert(screen->fill_ubwc_buffer_sizes);
|
||||
screen->fill_ubwc_buffer_sizes(rsc);
|
||||
} else if (handle->modifier &&
|
||||
(handle->modifier != DRM_FORMAT_MOD_INVALID)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
assert(rsc->cpp);
|
||||
|
||||
return prsc;
|
||||
@@ -1131,6 +1206,10 @@ fd_resource_screen_init(struct pipe_screen *pscreen)
|
||||
bool fake_rgtc = screen->gpu_id < 400;
|
||||
|
||||
pscreen->resource_create = u_transfer_helper_resource_create;
|
||||
/* NOTE: u_transfer_helper does not yet support the _with_modifiers()
|
||||
* variant:
|
||||
*/
|
||||
pscreen->resource_create_with_modifiers = fd_resource_create_with_modifiers;
|
||||
pscreen->resource_from_handle = fd_resource_from_handle;
|
||||
pscreen->resource_get_handle = fd_resource_get_handle;
|
||||
pscreen->resource_destroy = u_transfer_helper_resource_destroy;
|
||||
|
@@ -87,6 +87,7 @@ struct fd_screen {
|
||||
*/
|
||||
struct fd_pipe *pipe;
|
||||
|
||||
uint32_t (*fill_ubwc_buffer_sizes)(struct fd_resource *rsc);
|
||||
uint32_t (*setup_slices)(struct fd_resource *rsc);
|
||||
unsigned (*tile_mode)(const struct pipe_resource *prsc);
|
||||
|
||||
|
Reference in New Issue
Block a user