[virglrenderer-devel] [PATCH 2/3] vrend: If available use glCopyImageSubData to execute memcopy like blits
Gert Wollny
gert.wollny at collabora.com
Wed Jun 20 09:02:25 UTC 2018
When the host is gles >= 3.2, gl >= 4.3 or when the extension
GL_(ARB|EXT|OES)_copy_image is available, memcopy like blitting and region
copying can be done for many color format combinations by using
glCopyImageSubData.
This fixes a number of tests from the subset
dEQP-GLES31.functional.copy_image.non_compressed.viewclass_*
Signed-off-by: Gert Wollny <gert.wollny at collabora.com>
---
src/vrend_formats.c | 25 ++++++++++++++++++++++
src/vrend_renderer.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++--
src/vrend_renderer.h | 2 ++
3 files changed, 83 insertions(+), 2 deletions(-)
diff --git a/src/vrend_formats.c b/src/vrend_formats.c
index eb9f217..d1653a4 100644
--- a/src/vrend_formats.c
+++ b/src/vrend_formats.c
@@ -443,3 +443,28 @@ void vrend_build_format_list_gles(void)
*/
add_formats(gles_z32_format);
}
+
+bool vrend_is_canonical_format(enum pipe_format format)
+{
+ /* These are the canonical formats that are set by gallium */
+
+ switch (format) {
+ case PIPE_FORMAT_R32G32B32A32_UINT:
+ case PIPE_FORMAT_R32G32B32_UINT:
+ case PIPE_FORMAT_R32G32_UINT:
+ case PIPE_FORMAT_R16G16B16A16_UINT:
+ case PIPE_FORMAT_R16G16B16_UINT:
+ case PIPE_FORMAT_R8G8B8A8_UNORM:
+ case PIPE_FORMAT_A8B8G8R8_UNORM:
+ case PIPE_FORMAT_R16G16_UNORM:
+ case PIPE_FORMAT_R32_UINT:
+ case PIPE_FORMAT_R8G8B8_UINT:
+ case PIPE_FORMAT_G8R8_UNORM:
+ case PIPE_FORMAT_R8G8_UNORM:
+ case PIPE_FORMAT_R16_UINT:
+ case PIPE_FORMAT_R8_UINT:
+ return true;
+ default:
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c
index b769e8a..8690eb2 100644
--- a/src/vrend_renderer.c
+++ b/src/vrend_renderer.c
@@ -118,6 +118,7 @@ struct global_renderer_state {
bool have_polygon_offset_clamp;
bool have_texture_storage;
bool have_tessellation;
+ bool have_copy_image;
/* these appeared broken on at least one driver */
bool use_explicit_locations;
@@ -4449,6 +4450,12 @@ int vrend_renderer_init(struct vrend_if_cbs *cbs, uint32_t flags)
if (gl_ver >= 46 || epoxy_has_gl_extension("GL_ARB_polygon_offset_clamp"))
vrend_state.have_polygon_offset_clamp = true;
+ if (gl_ver >= 43 || (gles && gl_ver >= 32) ||
+ epoxy_has_gl_extension("GL_ARB_copy_image") ||
+ epoxy_has_gl_extension("GL_EXT_copy_image") ||
+ epoxy_has_gl_extension("GL_OES_copy_image"))
+ vrend_state.have_copy_image = true;
+
/* callbacks for when we are cleaning up the object table */
vrend_resource_set_destroy_callback(vrend_destroy_resource_object);
vrend_object_set_destroy_callback(VIRGL_OBJECT_QUERY, vrend_destroy_query_object);
@@ -6260,6 +6269,22 @@ static void vrend_resource_copy_fallback(struct vrend_context *ctx,
free(tptr);
}
+
+static inline void
+vrend_copy_sub_image(struct vrend_resource* src_res, struct vrend_resource * dst_res,
+ uint32_t src_level, const struct pipe_box *src_box,
+ uint32_t dst_level, uint32_t dstx, uint32_t dsty, uint32_t dstz)
+{
+ glCopyImageSubData(src_res->id,
+ tgsitargettogltarget(src_res->base.target, src_res->base.nr_samples),
+ src_level, src_box->x, src_box->y, src_box->z,
+ dst_res->id,
+ tgsitargettogltarget(dst_res->base.target, dst_res->base.nr_samples),
+ dst_level, dstx, dsty, dstz,
+ src_box->width, src_box->height,src_box->depth);
+}
+
+
void vrend_renderer_resource_copy_region(struct vrend_context *ctx,
uint32_t dst_handle, uint32_t dst_level,
uint32_t dstx, uint32_t dsty, uint32_t dstz,
@@ -6292,11 +6317,20 @@ void vrend_renderer_resource_copy_region(struct vrend_context *ctx,
return;
}
+ if (vrend_state.have_copy_image) {
+ const struct util_format_description *src_desc = util_format_description(src_res->base.format);
+ const struct util_format_description *dst_desc = util_format_description(dst_res->base.format);
+ if (util_is_format_compatible(src_desc,dst_desc)) {
+ vrend_copy_sub_image(src_res, dst_res, src_level, src_box,
+ dst_level, dstx, dsty, dstz);
+ return;
+ }
+ }
+
if (!vrend_format_can_render(src_res->base.format) ||
!vrend_format_can_render(dst_res->base.format)) {
vrend_resource_copy_fallback(ctx, src_res, dst_res, dst_level, dstx,
dsty, dstz, src_level, src_box);
-
return;
}
@@ -6568,7 +6602,27 @@ void vrend_renderer_blit(struct vrend_context *ctx,
if (info->render_condition_enable == false)
vrend_pause_render_condition(ctx, true);
- vrend_renderer_blit_int(ctx, src_res, dst_res, info);
+ /* The gallium blit function can be called for a general blit that may
+ * scale and convert the data or for a memcopy blit. In the latter case
+ * the info->formats are equal and set to one of the canonical formats.
+ * In addition some other restrictions apply. For this latter case use the
+ * glCopyImageSubData function.
+ */
+ if (vrend_state.have_copy_image &&
+ vrend_is_canonical_format(info->src.format) &&
+ (info->src.format == info->dst.format) &&
+ !info->scissor_enable && (info->filter == PIPE_TEX_FILTER_NEAREST) &&
+ !info->alpha_blend && (info->mask == PIPE_MASK_RGBA) &&
+ (src_res->base.nr_samples == dst_res->base.nr_samples) &&
+ info->src.box.width == info->dst.box.width &&
+ info->src.box.height == info->dst.box.height &&
+ info->src.box.depth == info->dst.box.depth) {
+ vrend_copy_sub_image(src_res, dst_res, info->src.level, &info->src.box,
+ info->dst.level, info->dst.box.x, info->dst.box.y,
+ info->dst.box.z);
+ } else {
+ vrend_renderer_blit_int(ctx, src_res, dst_res, info);
+ }
if (info->render_condition_enable == false)
vrend_pause_render_condition(ctx, false);
diff --git a/src/vrend_renderer.h b/src/vrend_renderer.h
index 258c439..badf2b1 100644
--- a/src/vrend_renderer.h
+++ b/src/vrend_renderer.h
@@ -323,6 +323,8 @@ GLint64 vrend_renderer_get_timestamp(void);
void vrend_build_format_list_common(void);
void vrend_build_format_list_gl(void);
void vrend_build_format_list_gles(void);
+bool vrend_is_canonical_format(enum pipe_format format);
+
int vrend_renderer_resource_attach_iov(int res_handle, struct iovec *iov,
int num_iovs);
--
2.16.4
More information about the virglrenderer-devel
mailing list