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:
Rob Clark
2019-01-21 10:50:13 -05:00
parent c56fe4118a
commit 1ce5d757d0
2 changed files with 84 additions and 4 deletions

View File

@@ -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;

View File

@@ -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);