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_query_hw.h"
|
||||||
#include "freedreno_util.h"
|
#include "freedreno_util.h"
|
||||||
|
|
||||||
|
#include <drm_fourcc.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
/* XXX this should go away, needed for 'struct winsys_handle' */
|
/* 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.
|
* Create a new texture object, using the given template info.
|
||||||
*/
|
*/
|
||||||
static struct pipe_resource *
|
static struct pipe_resource *
|
||||||
fd_resource_create(struct pipe_screen *pscreen,
|
fd_resource_create_with_modifiers(struct pipe_screen *pscreen,
|
||||||
const struct pipe_resource *tmpl)
|
const struct pipe_resource *tmpl,
|
||||||
|
const uint64_t *modifiers, int count)
|
||||||
{
|
{
|
||||||
struct fd_screen *screen = fd_screen(pscreen);
|
struct fd_screen *screen = fd_screen(pscreen);
|
||||||
struct fd_resource *rsc = CALLOC_STRUCT(fd_resource);
|
struct fd_resource *rsc = CALLOC_STRUCT(fd_resource);
|
||||||
@@ -840,10 +855,25 @@ fd_resource_create(struct pipe_screen *pscreen,
|
|||||||
PIPE_BIND_LINEAR | \
|
PIPE_BIND_LINEAR | \
|
||||||
PIPE_BIND_DISPLAY_TARGET)
|
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 &&
|
if (screen->tile_mode &&
|
||||||
(tmpl->target != PIPE_BUFFER) &&
|
(tmpl->target != PIPE_BUFFER) &&
|
||||||
(tmpl->bind & PIPE_BIND_SAMPLER_VIEW) &&
|
!linear) {
|
||||||
!(tmpl->bind & LINEAR)) {
|
|
||||||
rsc->tile_mode = screen->tile_mode(tmpl);
|
rsc->tile_mode = screen->tile_mode(tmpl);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -888,6 +918,9 @@ fd_resource_create(struct pipe_screen *pscreen,
|
|||||||
|
|
||||||
size = screen->setup_slices(rsc);
|
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
|
/* special case for hw-query buffer, which we need to allocate before we
|
||||||
* know the size:
|
* know the size:
|
||||||
*/
|
*/
|
||||||
@@ -912,6 +945,34 @@ fail:
|
|||||||
return NULL;
|
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
|
* Create a texture from a winsys_handle. The handle is often created in
|
||||||
* another process by first creating a pipe texture and then calling
|
* 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,
|
const struct pipe_resource *tmpl,
|
||||||
struct winsys_handle *handle, unsigned usage)
|
struct winsys_handle *handle, unsigned usage)
|
||||||
{
|
{
|
||||||
|
struct fd_screen *screen = fd_screen(pscreen);
|
||||||
struct fd_resource *rsc = CALLOC_STRUCT(fd_resource);
|
struct fd_resource *rsc = CALLOC_STRUCT(fd_resource);
|
||||||
struct fd_resource_slice *slice = &rsc->slices[0];
|
struct fd_resource_slice *slice = &rsc->slices[0];
|
||||||
struct pipe_resource *prsc = &rsc->base;
|
struct pipe_resource *prsc = &rsc->base;
|
||||||
@@ -960,6 +1022,19 @@ fd_resource_from_handle(struct pipe_screen *pscreen,
|
|||||||
(slice->pitch & (pitchalign - 1)))
|
(slice->pitch & (pitchalign - 1)))
|
||||||
goto fail;
|
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);
|
assert(rsc->cpp);
|
||||||
|
|
||||||
return prsc;
|
return prsc;
|
||||||
@@ -1131,6 +1206,10 @@ fd_resource_screen_init(struct pipe_screen *pscreen)
|
|||||||
bool fake_rgtc = screen->gpu_id < 400;
|
bool fake_rgtc = screen->gpu_id < 400;
|
||||||
|
|
||||||
pscreen->resource_create = u_transfer_helper_resource_create;
|
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_from_handle = fd_resource_from_handle;
|
||||||
pscreen->resource_get_handle = fd_resource_get_handle;
|
pscreen->resource_get_handle = fd_resource_get_handle;
|
||||||
pscreen->resource_destroy = u_transfer_helper_resource_destroy;
|
pscreen->resource_destroy = u_transfer_helper_resource_destroy;
|
||||||
|
@@ -87,6 +87,7 @@ struct fd_screen {
|
|||||||
*/
|
*/
|
||||||
struct fd_pipe *pipe;
|
struct fd_pipe *pipe;
|
||||||
|
|
||||||
|
uint32_t (*fill_ubwc_buffer_sizes)(struct fd_resource *rsc);
|
||||||
uint32_t (*setup_slices)(struct fd_resource *rsc);
|
uint32_t (*setup_slices)(struct fd_resource *rsc);
|
||||||
unsigned (*tile_mode)(const struct pipe_resource *prsc);
|
unsigned (*tile_mode)(const struct pipe_resource *prsc);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user