diff options
author | Erik Faye-Lund <[email protected]> | 2019-04-04 11:55:24 +0200 |
---|---|---|
committer | Erik Faye-Lund <[email protected]> | 2019-04-17 07:27:08 +0000 |
commit | 3fdacf1c390b5281c9adb4fbfdacd2757023941c (patch) | |
tree | a1865dd1c26d704f06983aaece94f28f7373cd0f /src/gallium/drivers/virgl/virgl_texture.c | |
parent | 9e9d9b352e7a87f42f4fb9117faaf8a350953a0c (diff) |
virgl: do color-conversion during when mapping transfer
When running on OpenGL ES, we can't just map any format for reading,
because of limitations on glReadPixels. So let's fall back to the
blit code-path, and translate the pixels to the correct format in the
end.
This fixes the remaining failures of KHR-GL32.packed_pixels.* apart
from the sRGB tests.
Signed-off-by: Erik Faye-Lund <[email protected]>
Reviewed-by: Gurchetan Singh <[email protected]>
Diffstat (limited to 'src/gallium/drivers/virgl/virgl_texture.c')
-rw-r--r-- | src/gallium/drivers/virgl/virgl_texture.c | 80 |
1 files changed, 70 insertions, 10 deletions
diff --git a/src/gallium/drivers/virgl/virgl_texture.c b/src/gallium/drivers/virgl/virgl_texture.c index 471fe6c7b9a..bbda3f2406e 100644 --- a/src/gallium/drivers/virgl/virgl_texture.c +++ b/src/gallium/drivers/virgl/virgl_texture.c @@ -79,11 +79,12 @@ static unsigned temp_bind(unsigned orig) static void virgl_init_temp_resource_from_box(struct pipe_resource *res, struct pipe_resource *orig, const struct pipe_box *box, - unsigned level, unsigned flags) + unsigned level, unsigned flags, + enum pipe_format fmt) { memset(res, 0, sizeof(*res)); res->bind = temp_bind(orig->bind); - res->format = orig->format; + res->format = fmt; res->width0 = box->width; res->height0 = box->height; res->depth0 = 1; @@ -160,16 +161,29 @@ static void *texture_transfer_map_resolve(struct pipe_context *ctx, struct pipe_transfer **transfer) { struct virgl_context *vctx = virgl_context(ctx); + struct virgl_resource *vtex = virgl_resource(resource); struct pipe_resource templ, *resolve_tmp; struct virgl_transfer *trans; trans = virgl_resource_create_transfer(&vctx->transfer_pool, resource, - &virgl_resource(resource)->metadata, - level, usage, box); + &vtex->metadata, level, usage, box); if (!trans) return NULL; - virgl_init_temp_resource_from_box(&templ, resource, box, level, 0); + enum pipe_format fmt = resource->format; + if (!virgl_has_readback_format(ctx->screen, fmt)) { + if (util_format_fits_8unorm(util_format_description(fmt))) + fmt = PIPE_FORMAT_R8G8B8A8_UNORM; + else if (util_format_is_pure_sint(fmt)) + fmt = PIPE_FORMAT_R32G32B32A32_SINT; + else if (util_format_is_pure_uint(fmt)) + fmt = PIPE_FORMAT_R32G32B32A32_UINT; + else + fmt = PIPE_FORMAT_R32G32B32A32_FLOAT; + assert(virgl_has_readback_format(ctx->screen, fmt)); + } + + virgl_init_temp_resource_from_box(&templ, resource, box, level, 0, fmt); resolve_tmp = ctx->screen->resource_create(ctx->screen, &templ); if (!resolve_tmp) @@ -190,9 +204,41 @@ static void *texture_transfer_map_resolve(struct pipe_context *ctx, goto fail; *transfer = &trans->base; - trans->base.stride = trans->resolve_transfer->stride; - trans->base.layer_stride = trans->resolve_transfer->layer_stride; - return ptr; + if (fmt == resource->format) { + trans->base.stride = trans->resolve_transfer->stride; + trans->base.layer_stride = trans->resolve_transfer->layer_stride; + return ptr; + } else { + if (usage & PIPE_TRANSFER_READ) { + struct virgl_winsys *vws = virgl_screen(ctx->screen)->vws; + void *src = ptr; + ptr = vws->resource_map(vws, vtex->hw_res); + if (!ptr) + goto fail; + + if (!util_format_translate_3d(resource->format, + ptr, + trans->base.stride, + trans->base.layer_stride, + box->x, box->y, box->z, + fmt, + src, + trans->resolve_transfer->stride, + trans->resolve_transfer->layer_stride, + 0, 0, 0, + box->width, box->height, box->depth)) { + debug_printf("failed to translate format %s to %s\n", + util_format_short_name(fmt), + util_format_short_name(resource->format)); + goto fail; + } + } + + if ((usage & PIPE_TRANSFER_WRITE) == 0) + pipe_resource_reference(&trans->resolve_transfer->resource, NULL); + + return ptr + trans->offset; + } fail: pipe_resource_reference(&resolve_tmp, NULL); @@ -200,6 +246,19 @@ fail: return NULL; } +static bool needs_resolve(struct pipe_screen *screen, + struct pipe_resource *resource, unsigned usage) +{ + if (resource->nr_samples > 1) + return true; + + if (usage & PIPE_TRANSFER_READ) + return !util_format_is_depth_or_stencil(resource->format) && + !virgl_has_readback_format(screen, resource->format); + + return false; +} + static void *virgl_texture_transfer_map(struct pipe_context *ctx, struct pipe_resource *resource, unsigned level, @@ -207,7 +266,7 @@ static void *virgl_texture_transfer_map(struct pipe_context *ctx, const struct pipe_box *box, struct pipe_transfer **transfer) { - if (resource->nr_samples > 1) + if (needs_resolve(ctx->screen, resource, usage)) return texture_transfer_map_resolve(ctx, resource, level, usage, box, transfer); @@ -234,7 +293,8 @@ static void virgl_texture_transfer_unmap(struct pipe_context *ctx, if (transfer->usage & PIPE_TRANSFER_WRITE && (transfer->usage & PIPE_TRANSFER_FLUSH_EXPLICIT) == 0) { - if (trans->resolve_transfer) { + if (trans->resolve_transfer && (trans->base.resource->format == + trans->resolve_transfer->resource->format)) { flush_data(ctx, virgl_transfer(trans->resolve_transfer), &trans->resolve_transfer->box); |