summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers
diff options
context:
space:
mode:
authorRob Clark <[email protected]>2019-01-21 10:50:13 -0500
committerRob Clark <[email protected]>2019-01-22 16:33:27 -0500
commit1ce5d757d04ab91423d757811c712ab098a35ccc (patch)
treee93069ccedacadf9fcb4a224db979c696833133b /src/gallium/drivers
parentc56fe4118a2dd991ff1b2a532c0f234eddd435e9 (diff)
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().
Diffstat (limited to 'src/gallium/drivers')
-rw-r--r--src/gallium/drivers/freedreno/freedreno_resource.c87
-rw-r--r--src/gallium/drivers/freedreno/freedreno_screen.h1
2 files changed, 84 insertions, 4 deletions
diff --git a/src/gallium/drivers/freedreno/freedreno_resource.c b/src/gallium/drivers/freedreno/freedreno_resource.c
index 14751074ace..ccd4f7f118d 100644
--- a/src/gallium/drivers/freedreno/freedreno_resource.c
+++ b/src/gallium/drivers/freedreno/freedreno_resource.c
@@ -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;
diff --git a/src/gallium/drivers/freedreno/freedreno_screen.h b/src/gallium/drivers/freedreno/freedreno_screen.h
index 243770ffd90..1060f4609f6 100644
--- a/src/gallium/drivers/freedreno/freedreno_screen.h
+++ b/src/gallium/drivers/freedreno/freedreno_screen.h
@@ -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);