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.
This commit is contained in:
committed by
Michel Dänzer
parent
0201c7d0af
commit
76d6a64de3
@@ -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);
|
||||
|
||||
if (exa->copy.use_surface_copy) {
|
||||
struct pipe_box src_box;
|
||||
u_box_2d(srcX, srcY, width, height, &src_box);
|
||||
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);
|
||||
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user