From 76d6a64de30dc3af66c5aec855f1fc6560d85a89 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Michel=20D=C3=A4nzer?= Date: Wed, 16 May 2012 17:45:10 +0200 Subject: [PATCH] st/xorg: Better handling of EXA copies. Always use the resource_copy_region hook. If a source and destination rectangle overlap, copy to/from a temporary pixmap. --- src/gallium/state_trackers/xorg/xorg_exa.c | 94 +++++------ src/gallium/state_trackers/xorg/xorg_exa.h | 7 +- .../state_trackers/xorg/xorg_renderer.c | 150 ------------------ .../state_trackers/xorg/xorg_renderer.h | 15 -- 4 files changed, 41 insertions(+), 225 deletions(-) diff --git a/src/gallium/state_trackers/xorg/xorg_exa.c b/src/gallium/state_trackers/xorg/xorg_exa.c index db0167ba4c4..fa84298855e 100644 --- a/src/gallium/state_trackers/xorg/xorg_exa.c +++ b/src/gallium/state_trackers/xorg/xorg_exa.c @@ -462,41 +462,6 @@ ExaPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir, exa->copy.src = src_priv; exa->copy.dst = priv; - /* XXX this used to use resource_copy_region for same-surface copies, - * but they were redefined to not allow overlaps (some of the util code - * always assumed this anyway). - * Drivers should implement accelerated resource_copy_region or it will - * be slow - disable for now. - */ - if (0 && exa->copy.src != exa->copy.dst) { - exa->copy.use_surface_copy = TRUE; - } - else { - struct pipe_surface surf_tmpl; - exa->copy.use_surface_copy = FALSE; - - if (exa->copy.dst == exa->copy.src) - exa->copy.src_texture = renderer_clone_texture( exa->renderer, - exa->copy.src->tex ); - else - pipe_resource_reference(&exa->copy.src_texture, - exa->copy.src->tex); - - memset(&surf_tmpl, 0, sizeof(surf_tmpl)); - u_surface_default_template(&surf_tmpl, exa->copy.dst->tex, - PIPE_BIND_RENDER_TARGET); - exa->copy.dst_surface = - exa->pipe->create_surface(exa->pipe, - exa->copy.dst->tex, - &surf_tmpl); - - - renderer_copy_prepare(exa->renderer, - exa->copy.dst_surface, - exa->copy.src_texture ); - } - - return TRUE; } @@ -507,32 +472,53 @@ ExaCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY, ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; modesettingPtr ms = modesettingPTR(pScrn); struct exa_context *exa = ms->exa; - struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap); + struct pipe_box src_box; exa_debug_printf("\tExaCopy(srcx=%d, srcy=%d, dstX=%d, dstY=%d, w=%d, h=%d)\n", srcX, srcY, dstX, dstY, width, height); - debug_assert(priv == exa->copy.dst); - (void) priv; + debug_assert(exaGetPixmapDriverPrivate(pDstPixmap) == exa->copy.dst); + + u_box_2d(srcX, srcY, width, height, &src_box); + + /* If source and destination overlap, we have to copy to/from a scratch + * pixmap. + */ + if (exa->copy.dst == exa->copy.src && + !((dstX + width) < srcX || dstX > (srcX + width) || + (dstY + height) < srcY || dstY > (srcY + height))) { + struct exa_pixmap_priv *tmp_priv; + + if (!exa->copy.tmp_pix) { + exa->copy.tmp_pix = pScrn->pScreen->CreatePixmap(pScrn->pScreen, + pDstPixmap->drawable.width, + pDstPixmap->drawable.height, + pDstPixmap->drawable.depth, + pDstPixmap->drawable.width); + exaMoveInPixmap(exa->copy.tmp_pix); + } + + tmp_priv = exaGetPixmapDriverPrivate(exa->copy.tmp_pix); - if (exa->copy.use_surface_copy) { - struct pipe_box src_box; - u_box_2d(srcX, srcY, width, height, &src_box); + exa->pipe->resource_copy_region( exa->pipe, + tmp_priv->tex, + 0, + srcX, srcY, 0, + exa->copy.src->tex, + 0, &src_box); + exa->pipe->resource_copy_region( exa->pipe, + exa->copy.dst->tex, + 0, + dstX, dstY, 0, + tmp_priv->tex, + 0, &src_box); + } else exa->pipe->resource_copy_region( exa->pipe, exa->copy.dst->tex, 0, dstX, dstY, 0, exa->copy.src->tex, 0, &src_box); - } - else { - renderer_copy_pixmap(exa->renderer, - dstX, dstY, - srcX, srcY, - width, height, - exa->copy.src_texture->width0, - exa->copy.src_texture->height0); - } } static void @@ -548,12 +534,12 @@ ExaDoneCopy(PixmapPtr pPixmap) exa_debug_printf("ExaDoneCopy\n"); - renderer_draw_flush(exa->renderer); - + if (exa->copy.tmp_pix) { + pScrn->pScreen->DestroyPixmap(exa->copy.tmp_pix); + exa->copy.tmp_pix = NULL; + } exa->copy.src = NULL; exa->copy.dst = NULL; - pipe_surface_reference(&exa->copy.dst_surface, NULL); - pipe_resource_reference(&exa->copy.src_texture, NULL); exa_debug_printf("ExaDoneCopy done\n"); } diff --git a/src/gallium/state_trackers/xorg/xorg_exa.h b/src/gallium/state_trackers/xorg/xorg_exa.h index 47501f9affe..e8f7c9f66fc 100644 --- a/src/gallium/state_trackers/xorg/xorg_exa.h +++ b/src/gallium/state_trackers/xorg/xorg_exa.h @@ -35,14 +35,9 @@ struct exa_context } transform; struct { - boolean use_surface_copy; - struct exa_pixmap_priv *src; struct exa_pixmap_priv *dst; - - struct pipe_surface *dst_surface; - - struct pipe_resource *src_texture; + PixmapPtr tmp_pix; } copy; }; diff --git a/src/gallium/state_trackers/xorg/xorg_renderer.c b/src/gallium/state_trackers/xorg/xorg_renderer.c index ca25b0912f1..bf2d5b75dd7 100644 --- a/src/gallium/state_trackers/xorg/xorg_renderer.c +++ b/src/gallium/state_trackers/xorg/xorg_renderer.c @@ -414,156 +414,6 @@ void renderer_set_constants(struct xorg_renderer *r, } -void renderer_copy_prepare(struct xorg_renderer *r, - struct pipe_surface *dst_surface, - struct pipe_resource *src_texture) -{ - struct pipe_context *pipe = r->pipe; - struct pipe_screen *screen = pipe->screen; - struct xorg_shader shader; - - assert(screen->is_format_supported(screen, dst_surface->format, - PIPE_TEXTURE_2D, 0, - PIPE_BIND_RENDER_TARGET)); - (void) screen; - - - /* set misc state we care about */ - { - struct pipe_blend_state blend; - memset(&blend, 0, sizeof(blend)); - blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; - blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; - blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; - blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; - blend.rt[0].colormask = PIPE_MASK_RGBA; - cso_set_blend(r->cso, &blend); - } - - /* sampler */ - { - struct pipe_sampler_state sampler; - memset(&sampler, 0, sizeof(sampler)); - sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; - sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; - sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; - sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; - sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; - sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; - sampler.normalized_coords = 1; - cso_single_sampler(r->cso, 0, &sampler); - cso_single_sampler_done(r->cso); - } - - renderer_bind_destination(r, dst_surface, - dst_surface->width, - dst_surface->height); - - /* texture/sampler view */ - { - struct pipe_sampler_view templ; - struct pipe_sampler_view *src_view; - u_sampler_view_default_template(&templ, - src_texture, - src_texture->format); - src_view = pipe->create_sampler_view(pipe, src_texture, &templ); - cso_set_fragment_sampler_views(r->cso, 1, &src_view); - pipe_sampler_view_reference(&src_view, NULL); - } - - /* shaders */ - shader = xorg_shaders_get(r->shaders, - VS_COMPOSITE, - FS_COMPOSITE); - cso_set_vertex_shader_handle(r->cso, shader.vs); - cso_set_fragment_shader_handle(r->cso, shader.fs); - - r->buffer_size = 0; - r->attrs_per_vertex = 2; -} - -struct pipe_resource * -renderer_clone_texture(struct xorg_renderer *r, - struct pipe_resource *src) -{ - enum pipe_format format; - struct pipe_context *pipe = r->pipe; - struct pipe_screen *screen = pipe->screen; - struct pipe_resource *pt; - struct pipe_resource templ; - - /* the coming in texture should already have that invariance */ - debug_assert(screen->is_format_supported(screen, src->format, - PIPE_TEXTURE_2D, 0, - PIPE_BIND_SAMPLER_VIEW)); - - format = src->format; - - memset(&templ, 0, sizeof(templ)); - templ.target = PIPE_TEXTURE_2D; - templ.format = format; - templ.last_level = 0; - templ.width0 = src->width0; - templ.height0 = src->height0; - templ.depth0 = 1; - templ.array_size = 1; - templ.bind = PIPE_BIND_SAMPLER_VIEW; - - pt = screen->resource_create(screen, &templ); - - debug_assert(!pt || pipe_is_referenced(&pt->reference)); - - if (!pt) - return NULL; - - { - /* copy source framebuffer surface into texture */ - struct pipe_box src_box; - u_box_origin_2d(src->width0, src->height0, &src_box); - - pipe->resource_copy_region(pipe, - pt, /* dest */ - 0, /* dest_level */ - 0, 0, 0, /* destx/y/z */ - src, - 0, &src_box); - } - - return pt; -} - - -void renderer_copy_pixmap(struct xorg_renderer *r, - int dx, int dy, - int sx, int sy, - int width, int height, - float src_width, - float src_height) -{ - float s0, t0, s1, t1; - float x0, y0, x1, y1; - - - /* XXX: could put the texcoord scaling calculation into the vertex - * shader. - */ - s0 = sx / src_width; - s1 = (sx + width) / src_width; - t0 = sy / src_height; - t1 = (sy + height) / src_height; - - x0 = dx; - x1 = dx + width; - y0 = dy; - y1 = dy + height; - - /* draw quad */ - renderer_draw_conditional(r, 4*8); - add_vertex_1tex(r, x0, y0, s0, t0); - add_vertex_1tex(r, x1, y0, s1, t0); - add_vertex_1tex(r, x1, y1, s1, t1); - add_vertex_1tex(r, x0, y1, s0, t1); -} void renderer_draw_yuv(struct xorg_renderer *r, float src_x, float src_y, float src_w, float src_h, diff --git a/src/gallium/state_trackers/xorg/xorg_renderer.h b/src/gallium/state_trackers/xorg/xorg_renderer.h index fb09fabe156..b652aeb7d0c 100644 --- a/src/gallium/state_trackers/xorg/xorg_renderer.h +++ b/src/gallium/state_trackers/xorg/xorg_renderer.h @@ -77,20 +77,5 @@ void renderer_texture(struct xorg_renderer *r, void renderer_draw_flush(struct xorg_renderer *r); -struct pipe_resource * -renderer_clone_texture(struct xorg_renderer *r, - struct pipe_resource *src); - -void renderer_copy_prepare(struct xorg_renderer *r, - struct pipe_surface *dst_surface, - struct pipe_resource *src_texture); - -void renderer_copy_pixmap(struct xorg_renderer *r, - int dx, int dy, - int sx, int sy, - int width, int height, - float src_width, - float src_height); - #endif -- 2.30.2