summaryrefslogtreecommitdiffstats
path: root/src/gallium
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium')
-rw-r--r--src/gallium/auxiliary/renderonly/renderonly.c52
-rw-r--r--src/gallium/auxiliary/renderonly/renderonly.h20
-rw-r--r--src/gallium/drivers/etnaviv/etnaviv_clear_blit.c8
-rw-r--r--src/gallium/drivers/etnaviv/etnaviv_resource.c34
-rw-r--r--src/gallium/drivers/etnaviv/etnaviv_resource.h5
-rw-r--r--src/gallium/drivers/vc4/vc4_resource.c5
6 files changed, 62 insertions, 62 deletions
diff --git a/src/gallium/auxiliary/renderonly/renderonly.c b/src/gallium/auxiliary/renderonly/renderonly.c
index d3ed214f4e4..da91f12b2ea 100644
--- a/src/gallium/auxiliary/renderonly/renderonly.c
+++ b/src/gallium/auxiliary/renderonly/renderonly.c
@@ -50,27 +50,12 @@ renderonly_dup(const struct renderonly *ro)
return copy;
}
-struct renderonly_scanout *
-renderonly_scanout_for_prime(struct pipe_resource *rsc, struct renderonly *ro)
-{
- struct renderonly_scanout *scanout;
-
- scanout = CALLOC_STRUCT(renderonly_scanout);
- if (!scanout)
- return NULL;
-
- scanout->prime = rsc;
-
- return scanout;
-}
-
void
renderonly_scanout_destroy(struct renderonly_scanout *scanout,
struct renderonly *ro)
{
struct drm_mode_destroy_dumb destroy_dumb = { };
- pipe_resource_reference(&scanout->prime, NULL);
if (ro->kms_fd != -1) {
destroy_dumb.handle = scanout->handle;
drmIoctl(ro->kms_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_dumb);
@@ -80,12 +65,11 @@ renderonly_scanout_destroy(struct renderonly_scanout *scanout,
struct renderonly_scanout *
renderonly_create_kms_dumb_buffer_for_resource(struct pipe_resource *rsc,
- struct renderonly *ro)
+ struct renderonly *ro,
+ struct winsys_handle *out_handle)
{
- struct pipe_screen *screen = rsc->screen;
struct renderonly_scanout *scanout;
- struct winsys_handle handle;
- int prime_fd, err;
+ int err;
struct drm_mode_create_dumb create_dumb = {
.width = rsc->width0,
.height = rsc->height0,
@@ -108,30 +92,21 @@ renderonly_create_kms_dumb_buffer_for_resource(struct pipe_resource *rsc,
scanout->handle = create_dumb.handle;
scanout->stride = create_dumb.pitch;
- /* export dumb buffer */
+ if (!out_handle)
+ return scanout;
+
+ /* fill in winsys handle */
+ memset(out_handle, 0, sizeof(*out_handle));
+ out_handle->type = DRM_API_HANDLE_TYPE_FD;
+ out_handle->stride = create_dumb.pitch;
+
err = drmPrimeHandleToFD(ro->kms_fd, create_dumb.handle, O_CLOEXEC,
- &prime_fd);
+ (int *)&out_handle->handle);
if (err < 0) {
fprintf(stderr, "failed to export dumb buffer: %s\n", strerror(errno));
goto free_dumb;
}
- /* import dumb buffer */
- memset(&handle, 0, sizeof(handle));
- handle.type = DRM_API_HANDLE_TYPE_FD;
- handle.handle = prime_fd;
- handle.stride = create_dumb.pitch;
-
- scanout->prime = screen->resource_from_handle(screen, rsc,
- &handle, PIPE_HANDLE_USAGE_READ_WRITE);
-
- close(prime_fd);
-
- if (!scanout->prime) {
- fprintf(stderr, "failed to create resource_from_handle: %s\n", strerror(errno));
- goto free_dumb;
- }
-
return scanout;
free_dumb:
@@ -146,7 +121,8 @@ free_scanout:
struct renderonly_scanout *
renderonly_create_gpu_import_for_resource(struct pipe_resource *rsc,
- struct renderonly *ro)
+ struct renderonly *ro,
+ struct winsys_handle *out_handle)
{
struct pipe_screen *screen = rsc->screen;
struct renderonly_scanout *scanout;
diff --git a/src/gallium/auxiliary/renderonly/renderonly.h b/src/gallium/auxiliary/renderonly/renderonly.h
index 70641c45878..6a89c29e2ef 100644
--- a/src/gallium/auxiliary/renderonly/renderonly.h
+++ b/src/gallium/auxiliary/renderonly/renderonly.h
@@ -34,8 +34,6 @@
struct renderonly_scanout {
uint32_t handle;
uint32_t stride;
-
- struct pipe_resource *prime;
};
struct renderonly {
@@ -59,7 +57,8 @@ struct renderonly {
* to be done in flush_resource(..) like a resolve to linear.
*/
struct renderonly_scanout *(*create_for_resource)(struct pipe_resource *rsc,
- struct renderonly *ro);
+ struct renderonly *ro,
+ struct winsys_handle *out_handle);
int kms_fd;
int gpu_fd;
};
@@ -68,14 +67,13 @@ struct renderonly *
renderonly_dup(const struct renderonly *ro);
static inline struct renderonly_scanout *
-renderonly_scanout_for_resource(struct pipe_resource *rsc, struct renderonly *ro)
+renderonly_scanout_for_resource(struct pipe_resource *rsc,
+ struct renderonly *ro,
+ struct winsys_handle *out_handle)
{
- return ro->create_for_resource(rsc, ro);
+ return ro->create_for_resource(rsc, ro, out_handle);
}
-struct renderonly_scanout *
-renderonly_scanout_for_prime(struct pipe_resource *rsc, struct renderonly *ro);
-
void
renderonly_scanout_destroy(struct renderonly_scanout *scanout,
struct renderonly *ro);
@@ -99,13 +97,15 @@ renderonly_get_handle(struct renderonly_scanout *scanout,
*/
struct renderonly_scanout *
renderonly_create_kms_dumb_buffer_for_resource(struct pipe_resource *rsc,
- struct renderonly *ro);
+ struct renderonly *ro,
+ struct winsys_handle *out_handle);
/**
* Import GPU resource into scanout hw.
*/
struct renderonly_scanout *
renderonly_create_gpu_import_for_resource(struct pipe_resource *rsc,
- struct renderonly *ro);
+ struct renderonly *ro,
+ struct winsys_handle *out_handle);
#endif /* RENDERONLY_H_ */
diff --git a/src/gallium/drivers/etnaviv/etnaviv_clear_blit.c b/src/gallium/drivers/etnaviv/etnaviv_clear_blit.c
index d9ff9624fa4..b832dd8f263 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_clear_blit.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_clear_blit.c
@@ -610,10 +610,10 @@ etna_flush_resource(struct pipe_context *pctx, struct pipe_resource *prsc)
{
struct etna_resource *rsc = etna_resource(prsc);
- if (rsc->scanout) {
- if (etna_resource_older(etna_resource(rsc->scanout->prime), rsc)) {
- etna_copy_resource(pctx, rsc->scanout->prime, prsc, 0, 0);
- etna_resource(rsc->scanout->prime)->seqno = rsc->seqno;
+ if (rsc->external) {
+ if (etna_resource_older(etna_resource(rsc->external), rsc)) {
+ etna_copy_resource(pctx, rsc->external, prsc, 0, 0);
+ etna_resource(rsc->external)->seqno = rsc->seqno;
}
} else if (etna_resource_needs_flush(rsc)) {
etna_copy_resource(pctx, prsc, prsc, 0, 0);
diff --git a/src/gallium/drivers/etnaviv/etnaviv_resource.c b/src/gallium/drivers/etnaviv/etnaviv_resource.c
index a709482c1b6..8d96baf2a04 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_resource.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_resource.c
@@ -214,8 +214,20 @@ etna_resource_alloc(struct pipe_screen *pscreen, unsigned layout,
rsc->bo = bo;
rsc->ts_bo = 0; /* TS is only created when first bound to surface */
- if (templat->bind & PIPE_BIND_SCANOUT)
- rsc->scanout = renderonly_scanout_for_resource(&rsc->base, screen->ro);
+ if (templat->bind & PIPE_BIND_SCANOUT) {
+ struct winsys_handle handle;
+ rsc->scanout = renderonly_scanout_for_resource(&rsc->base, screen->ro,
+ &handle);
+ if (!rsc->scanout)
+ goto free_rsc;
+
+ rsc->external = pscreen->resource_from_handle(pscreen, &rsc->base,
+ &handle,
+ PIPE_HANDLE_USAGE_WRITE);
+ close(handle.handle);
+ if (!rsc->external)
+ goto free_rsc;
+ }
if (DBG_ENABLED(ETNA_DBG_ZERO)) {
void *map = etna_bo_map(bo);
@@ -310,6 +322,7 @@ etna_resource_destroy(struct pipe_screen *pscreen, struct pipe_resource *prsc)
list_delinit(&rsc->list);
pipe_resource_reference(&rsc->texture, NULL);
+ pipe_resource_reference(&rsc->external, NULL);
FREE(rsc);
}
@@ -379,16 +392,12 @@ etna_resource_from_handle(struct pipe_screen *pscreen,
/* Render targets are linear in Xorg but must be tiled
* here. It would be nice if dri_drawable_get_format()
* set scanout for these buffers too. */
- struct etna_resource *tiled;
ptiled = etna_resource_create(pscreen, tmpl);
if (!ptiled)
goto fail;
- tiled = etna_resource(ptiled);
- tiled->scanout = renderonly_scanout_for_prime(prsc, screen->ro);
- if (!tiled->scanout)
- goto fail;
+ etna_resource(ptiled)->external = prsc;
return ptiled;
}
@@ -410,9 +419,18 @@ etna_resource_get_handle(struct pipe_screen *pscreen,
struct winsys_handle *handle, unsigned usage)
{
struct etna_resource *rsc = etna_resource(prsc);
+ /* Scanout is always attached to the base resource */
+ struct renderonly_scanout *scanout = rsc->scanout;
+
+ /*
+ * External resources are preferred, so a import->export chain of
+ * render/sampler incompatible buffers yield the same handle.
+ */
+ if (rsc->external)
+ rsc = etna_resource(rsc->external);
if (handle->type == DRM_API_HANDLE_TYPE_KMS &&
- renderonly_get_handle(rsc->scanout, handle))
+ renderonly_get_handle(scanout, handle))
return TRUE;
return etna_screen_bo_get_handle(pscreen, rsc->bo, rsc->levels[0].stride,
diff --git a/src/gallium/drivers/etnaviv/etnaviv_resource.h b/src/gallium/drivers/etnaviv/etnaviv_resource.h
index 3507e5ccecb..5f563c06adc 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_resource.h
+++ b/src/gallium/drivers/etnaviv/etnaviv_resource.h
@@ -75,6 +75,11 @@ struct etna_resource {
/* When we are rendering to a texture, we need a differently tiled resource */
struct pipe_resource *texture;
+ /*
+ * If imported resources have an render/sampler incompatible tiling, we keep
+ * them as an external resource, which is blitted as needed.
+ */
+ struct pipe_resource *external;
enum etna_resource_status status;
diff --git a/src/gallium/drivers/vc4/vc4_resource.c b/src/gallium/drivers/vc4/vc4_resource.c
index 94301bd4114..2018dc36d93 100644
--- a/src/gallium/drivers/vc4/vc4_resource.c
+++ b/src/gallium/drivers/vc4/vc4_resource.c
@@ -671,7 +671,7 @@ vc4_resource_create_with_modifiers(struct pipe_screen *pscreen,
if (screen->ro && tmpl->bind & PIPE_BIND_SCANOUT) {
rsc->scanout =
- renderonly_scanout_for_resource(prsc, screen->ro);
+ renderonly_scanout_for_resource(prsc, screen->ro, NULL);
if (!rsc->scanout)
goto fail;
}
@@ -769,7 +769,8 @@ vc4_resource_from_handle(struct pipe_screen *pscreen,
*/
rsc->scanout =
renderonly_create_gpu_import_for_resource(prsc,
- screen->ro);
+ screen->ro,
+ NULL);
if (!rsc->scanout)
goto fail;
}