Skip to content
Snippets Groups Projects
Commit 76d6a64d authored by Michel Dänzer's avatar Michel Dänzer
Browse files

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.
parent 0201c7d0
No related branches found
No related tags found
No related merge requests found
......@@ -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");
}
......
......@@ -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;
};
......
......@@ -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,
......
......@@ -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
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment