renderonly/etnaviv: stop importing resource from renderonly
The current way of importing the resource from renderonly after allocation is opaque and is taking away control from the driver, which it needs in order to implement more advanced scenarios than the simple linear scanout with matching stride alignments. Signed-off-by: Lucas Stach <l.stach@pengutronix.de> Reviewed-by: Christian Gmeiner <christian.gmeiner@gmail.com> Acked-by: Daniel Stone <daniels@collabora.com>
This commit is contained in:
parent
a9fad437f7
commit
c481880899
|
@ -50,27 +50,12 @@ renderonly_dup(const struct renderonly *ro)
|
||||||
return copy;
|
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
|
void
|
||||||
renderonly_scanout_destroy(struct renderonly_scanout *scanout,
|
renderonly_scanout_destroy(struct renderonly_scanout *scanout,
|
||||||
struct renderonly *ro)
|
struct renderonly *ro)
|
||||||
{
|
{
|
||||||
struct drm_mode_destroy_dumb destroy_dumb = { };
|
struct drm_mode_destroy_dumb destroy_dumb = { };
|
||||||
|
|
||||||
pipe_resource_reference(&scanout->prime, NULL);
|
|
||||||
if (ro->kms_fd != -1) {
|
if (ro->kms_fd != -1) {
|
||||||
destroy_dumb.handle = scanout->handle;
|
destroy_dumb.handle = scanout->handle;
|
||||||
drmIoctl(ro->kms_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_dumb);
|
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 *
|
struct renderonly_scanout *
|
||||||
renderonly_create_kms_dumb_buffer_for_resource(struct pipe_resource *rsc,
|
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 renderonly_scanout *scanout;
|
||||||
struct winsys_handle handle;
|
int err;
|
||||||
int prime_fd, err;
|
|
||||||
struct drm_mode_create_dumb create_dumb = {
|
struct drm_mode_create_dumb create_dumb = {
|
||||||
.width = rsc->width0,
|
.width = rsc->width0,
|
||||||
.height = rsc->height0,
|
.height = rsc->height0,
|
||||||
|
@ -108,30 +92,21 @@ renderonly_create_kms_dumb_buffer_for_resource(struct pipe_resource *rsc,
|
||||||
scanout->handle = create_dumb.handle;
|
scanout->handle = create_dumb.handle;
|
||||||
scanout->stride = create_dumb.pitch;
|
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,
|
err = drmPrimeHandleToFD(ro->kms_fd, create_dumb.handle, O_CLOEXEC,
|
||||||
&prime_fd);
|
(int *)&out_handle->handle);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
fprintf(stderr, "failed to export dumb buffer: %s\n", strerror(errno));
|
fprintf(stderr, "failed to export dumb buffer: %s\n", strerror(errno));
|
||||||
goto free_dumb;
|
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;
|
return scanout;
|
||||||
|
|
||||||
free_dumb:
|
free_dumb:
|
||||||
|
@ -146,7 +121,8 @@ free_scanout:
|
||||||
|
|
||||||
struct renderonly_scanout *
|
struct renderonly_scanout *
|
||||||
renderonly_create_gpu_import_for_resource(struct pipe_resource *rsc,
|
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 pipe_screen *screen = rsc->screen;
|
||||||
struct renderonly_scanout *scanout;
|
struct renderonly_scanout *scanout;
|
||||||
|
|
|
@ -34,8 +34,6 @@
|
||||||
struct renderonly_scanout {
|
struct renderonly_scanout {
|
||||||
uint32_t handle;
|
uint32_t handle;
|
||||||
uint32_t stride;
|
uint32_t stride;
|
||||||
|
|
||||||
struct pipe_resource *prime;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct renderonly {
|
struct renderonly {
|
||||||
|
@ -59,7 +57,8 @@ struct renderonly {
|
||||||
* to be done in flush_resource(..) like a resolve to linear.
|
* to be done in flush_resource(..) like a resolve to linear.
|
||||||
*/
|
*/
|
||||||
struct renderonly_scanout *(*create_for_resource)(struct pipe_resource *rsc,
|
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 kms_fd;
|
||||||
int gpu_fd;
|
int gpu_fd;
|
||||||
};
|
};
|
||||||
|
@ -68,14 +67,13 @@ struct renderonly *
|
||||||
renderonly_dup(const struct renderonly *ro);
|
renderonly_dup(const struct renderonly *ro);
|
||||||
|
|
||||||
static inline struct renderonly_scanout *
|
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
|
void
|
||||||
renderonly_scanout_destroy(struct renderonly_scanout *scanout,
|
renderonly_scanout_destroy(struct renderonly_scanout *scanout,
|
||||||
struct renderonly *ro);
|
struct renderonly *ro);
|
||||||
|
@ -99,13 +97,15 @@ renderonly_get_handle(struct renderonly_scanout *scanout,
|
||||||
*/
|
*/
|
||||||
struct renderonly_scanout *
|
struct renderonly_scanout *
|
||||||
renderonly_create_kms_dumb_buffer_for_resource(struct pipe_resource *rsc,
|
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.
|
* Import GPU resource into scanout hw.
|
||||||
*/
|
*/
|
||||||
struct renderonly_scanout *
|
struct renderonly_scanout *
|
||||||
renderonly_create_gpu_import_for_resource(struct pipe_resource *rsc,
|
renderonly_create_gpu_import_for_resource(struct pipe_resource *rsc,
|
||||||
struct renderonly *ro);
|
struct renderonly *ro,
|
||||||
|
struct winsys_handle *out_handle);
|
||||||
|
|
||||||
#endif /* RENDERONLY_H_ */
|
#endif /* RENDERONLY_H_ */
|
||||||
|
|
|
@ -610,10 +610,10 @@ etna_flush_resource(struct pipe_context *pctx, struct pipe_resource *prsc)
|
||||||
{
|
{
|
||||||
struct etna_resource *rsc = etna_resource(prsc);
|
struct etna_resource *rsc = etna_resource(prsc);
|
||||||
|
|
||||||
if (rsc->scanout) {
|
if (rsc->external) {
|
||||||
if (etna_resource_older(etna_resource(rsc->scanout->prime), rsc)) {
|
if (etna_resource_older(etna_resource(rsc->external), rsc)) {
|
||||||
etna_copy_resource(pctx, rsc->scanout->prime, prsc, 0, 0);
|
etna_copy_resource(pctx, rsc->external, prsc, 0, 0);
|
||||||
etna_resource(rsc->scanout->prime)->seqno = rsc->seqno;
|
etna_resource(rsc->external)->seqno = rsc->seqno;
|
||||||
}
|
}
|
||||||
} else if (etna_resource_needs_flush(rsc)) {
|
} else if (etna_resource_needs_flush(rsc)) {
|
||||||
etna_copy_resource(pctx, prsc, prsc, 0, 0);
|
etna_copy_resource(pctx, prsc, prsc, 0, 0);
|
||||||
|
|
|
@ -214,8 +214,20 @@ etna_resource_alloc(struct pipe_screen *pscreen, unsigned layout,
|
||||||
rsc->bo = bo;
|
rsc->bo = bo;
|
||||||
rsc->ts_bo = 0; /* TS is only created when first bound to surface */
|
rsc->ts_bo = 0; /* TS is only created when first bound to surface */
|
||||||
|
|
||||||
if (templat->bind & PIPE_BIND_SCANOUT)
|
if (templat->bind & PIPE_BIND_SCANOUT) {
|
||||||
rsc->scanout = renderonly_scanout_for_resource(&rsc->base, screen->ro);
|
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)) {
|
if (DBG_ENABLED(ETNA_DBG_ZERO)) {
|
||||||
void *map = etna_bo_map(bo);
|
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);
|
list_delinit(&rsc->list);
|
||||||
|
|
||||||
pipe_resource_reference(&rsc->texture, NULL);
|
pipe_resource_reference(&rsc->texture, NULL);
|
||||||
|
pipe_resource_reference(&rsc->external, NULL);
|
||||||
|
|
||||||
FREE(rsc);
|
FREE(rsc);
|
||||||
}
|
}
|
||||||
|
@ -379,16 +392,12 @@ etna_resource_from_handle(struct pipe_screen *pscreen,
|
||||||
/* Render targets are linear in Xorg but must be tiled
|
/* Render targets are linear in Xorg but must be tiled
|
||||||
* here. It would be nice if dri_drawable_get_format()
|
* here. It would be nice if dri_drawable_get_format()
|
||||||
* set scanout for these buffers too. */
|
* set scanout for these buffers too. */
|
||||||
struct etna_resource *tiled;
|
|
||||||
|
|
||||||
ptiled = etna_resource_create(pscreen, tmpl);
|
ptiled = etna_resource_create(pscreen, tmpl);
|
||||||
if (!ptiled)
|
if (!ptiled)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
tiled = etna_resource(ptiled);
|
etna_resource(ptiled)->external = prsc;
|
||||||
tiled->scanout = renderonly_scanout_for_prime(prsc, screen->ro);
|
|
||||||
if (!tiled->scanout)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
return ptiled;
|
return ptiled;
|
||||||
}
|
}
|
||||||
|
@ -410,9 +419,18 @@ etna_resource_get_handle(struct pipe_screen *pscreen,
|
||||||
struct winsys_handle *handle, unsigned usage)
|
struct winsys_handle *handle, unsigned usage)
|
||||||
{
|
{
|
||||||
struct etna_resource *rsc = etna_resource(prsc);
|
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 &&
|
if (handle->type == DRM_API_HANDLE_TYPE_KMS &&
|
||||||
renderonly_get_handle(rsc->scanout, handle))
|
renderonly_get_handle(scanout, handle))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
return etna_screen_bo_get_handle(pscreen, rsc->bo, rsc->levels[0].stride,
|
return etna_screen_bo_get_handle(pscreen, rsc->bo, rsc->levels[0].stride,
|
||||||
|
|
|
@ -75,6 +75,11 @@ struct etna_resource {
|
||||||
|
|
||||||
/* When we are rendering to a texture, we need a differently tiled resource */
|
/* When we are rendering to a texture, we need a differently tiled resource */
|
||||||
struct pipe_resource *texture;
|
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;
|
enum etna_resource_status status;
|
||||||
|
|
||||||
|
|
|
@ -671,7 +671,7 @@ vc4_resource_create_with_modifiers(struct pipe_screen *pscreen,
|
||||||
|
|
||||||
if (screen->ro && tmpl->bind & PIPE_BIND_SCANOUT) {
|
if (screen->ro && tmpl->bind & PIPE_BIND_SCANOUT) {
|
||||||
rsc->scanout =
|
rsc->scanout =
|
||||||
renderonly_scanout_for_resource(prsc, screen->ro);
|
renderonly_scanout_for_resource(prsc, screen->ro, NULL);
|
||||||
if (!rsc->scanout)
|
if (!rsc->scanout)
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
@ -769,7 +769,8 @@ vc4_resource_from_handle(struct pipe_screen *pscreen,
|
||||||
*/
|
*/
|
||||||
rsc->scanout =
|
rsc->scanout =
|
||||||
renderonly_create_gpu_import_for_resource(prsc,
|
renderonly_create_gpu_import_for_resource(prsc,
|
||||||
screen->ro);
|
screen->ro,
|
||||||
|
NULL);
|
||||||
if (!rsc->scanout)
|
if (!rsc->scanout)
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue