summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichel Dänzer <[email protected]>2012-05-16 17:45:10 +0200
committerMichel Dänzer <[email protected]>2012-05-16 18:30:39 +0200
commit76d6a64de30dc3af66c5aec855f1fc6560d85a89 (patch)
tree9bea9ad484c1345e81a211c74121dea2d3d3e2da
parent0201c7d0af8424a8b8fd44243e3487898c11f96e (diff)
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.
-rw-r--r--src/gallium/state_trackers/xorg/xorg_exa.c94
-rw-r--r--src/gallium/state_trackers/xorg/xorg_exa.h7
-rw-r--r--src/gallium/state_trackers/xorg/xorg_renderer.c150
-rw-r--r--src/gallium/state_trackers/xorg/xorg_renderer.h15
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