st/xorg: split copy operation into prepare/copy/done phases

Any high-overhead one-off tasks are moved into the prepare hook.
This commit is contained in:
Keith Whitwell
2009-11-26 11:17:06 +00:00
parent 91a5131e6b
commit 8544c309d0
5 changed files with 99 additions and 125 deletions
+40 -6
View File
@@ -430,8 +430,17 @@ ExaPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir,
exa->copy.src = src_priv;
exa->copy.dst = priv;
if (0 && exa->pipe->surface_copy) {
/* For same-surface copies, the pipe->surface_copy path is clearly
* superior, providing it is implemented. In other cases it's not
* clear what the better path would be, and eventually we'd
* probably want to gather timings and choose dynamically.
*/
if (exa->pipe->surface_copy &&
exa->copy.src == exa->copy.dst) {
exa->copy.use_surface_copy = TRUE;
exa->copy.src_surface =
exa->scrn->get_tex_surface( exa->scrn,
exa->copy.src->tex,
@@ -444,6 +453,27 @@ ExaPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir,
0, 0, 0,
PIPE_BUFFER_USAGE_GPU_WRITE );
}
else {
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_texture_reference(&exa->copy.src_texture,
exa->copy.src->tex);
exa->copy.dst_surface =
exa->scrn->get_tex_surface(exa->scrn,
exa->copy.dst->tex,
0, 0, 0,
PIPE_BUFFER_USAGE_GPU_WRITE);
renderer_copy_prepare(exa->renderer,
exa->copy.dst_surface,
exa->copy.src_texture );
}
return exa->accel;
@@ -465,7 +495,7 @@ ExaCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY,
debug_assert(priv == exa->copy.dst);
if (exa->copy.src_surface && exa->copy.dst_surface) {
if (exa->copy.use_surface_copy) {
/* XXX: consider exposing >1 box in surface_copy interface.
*/
exa->pipe->surface_copy( exa->pipe,
@@ -476,9 +506,12 @@ ExaCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY,
width, height );
}
else {
renderer_copy_pixmap(exa->renderer, exa->copy.dst, dstX, dstY,
exa->copy.src, srcX, srcY,
width, height);
renderer_copy_pixmap(exa->renderer,
dstX, dstY,
srcX, srcY,
width, height,
exa->copy.src_texture->width[0],
exa->copy.src_texture->height[0]);
}
}
@@ -499,6 +532,7 @@ ExaDoneCopy(PixmapPtr pPixmap)
exa->copy.dst = NULL;
pipe_surface_reference(&exa->copy.src_surface, NULL);
pipe_surface_reference(&exa->copy.dst_surface, NULL);
pipe_texture_reference(&exa->copy.src_texture, NULL);
}
@@ -35,11 +35,15 @@ struct exa_context
} transform;
struct {
boolean use_surface_copy;
struct exa_pixmap_priv *src;
struct exa_pixmap_priv *dst;
struct pipe_surface *src_surface;
struct pipe_surface *dst_surface;
struct pipe_texture *src_texture;
} copy;
};
+40 -114
View File
@@ -195,23 +195,6 @@ add_vertex_data1(struct xorg_renderer *r,
add_vertex_1tex(r, dstX, dstY + height, s3, t3);
}
static struct pipe_buffer *
setup_vertex_data_tex(struct xorg_renderer *r,
float x0, float y0, float x1, float y1,
float s0, float t0, float s1, float t1,
float z)
{
/* 1st vertex */
add_vertex_1tex(r, x0, y0, s0, t0);
/* 2nd vertex */
add_vertex_1tex(r, x1, y0, s1, t0);
/* 3rd vertex */
add_vertex_1tex(r, x1, y1, s1, t1);
/* 4th vertex */
add_vertex_1tex(r, x0, y1, s0, t1);
return renderer_buffer_create(r);
}
static INLINE void
add_vertex_2tex(struct xorg_renderer *r,
@@ -442,47 +425,15 @@ void renderer_set_constants(struct xorg_renderer *r,
}
static void renderer_copy_texture(struct xorg_renderer *r,
struct pipe_texture *src,
float sx1, float sy1,
float sx2, float sy2,
struct pipe_texture *dst,
float dx1, float dy1,
float dx2, float dy2)
void renderer_copy_prepare(struct xorg_renderer *r,
struct pipe_surface *dst_surface,
struct pipe_texture *src_texture)
{
struct pipe_context *pipe = r->pipe;
struct pipe_screen *screen = pipe->screen;
struct pipe_buffer *buf;
struct pipe_surface *dst_surf = screen->get_tex_surface(
screen, dst, 0, 0, 0,
PIPE_BUFFER_USAGE_GPU_WRITE);
float s0, t0, s1, t1;
struct xorg_shader shader;
assert(src->width[0] != 0);
assert(src->height[0] != 0);
assert(dst->width[0] != 0);
assert(dst->height[0] != 0);
#if 1
s0 = sx1 / src->width[0];
s1 = sx2 / src->width[0];
t0 = sy1 / src->height[0];
t1 = sy2 / src->height[0];
#else
s0 = 0;
s1 = 1;
t0 = 0;
t1 = 1;
#endif
#if 0
debug_printf("copy texture src=[%f, %f, %f, %f], dst=[%f, %f, %f, %f], tex=[%f, %f, %f, %f]\n",
sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2,
s0, t0, s1, t1);
#endif
assert(screen->is_format_supported(screen, dst_surf->format,
assert(screen->is_format_supported(screen, dst_surface->format,
PIPE_TEXTURE_2D,
PIPE_TEXTURE_USAGE_RENDER_TARGET,
0));
@@ -515,10 +466,10 @@ static void renderer_copy_texture(struct xorg_renderer *r,
cso_single_sampler_done(r->cso);
}
renderer_bind_destination(r, dst_surf);
renderer_bind_destination(r, dst_surface);
/* texture */
cso_set_sampler_textures(r->cso, 1, &src);
cso_set_sampler_textures(r->cso, 1, &src_texture);
/* shaders */
shader = xorg_shaders_get(r->shaders,
@@ -527,27 +478,12 @@ static void renderer_copy_texture(struct xorg_renderer *r,
cso_set_vertex_shader_handle(r->cso, shader.vs);
cso_set_fragment_shader_handle(r->cso, shader.fs);
/* draw quad */
buf = setup_vertex_data_tex(r,
dx1, dy1,
dx2, dy2,
s0, t0, s1, t1,
0.0f);
if (buf) {
util_draw_vertex_buffer(r->pipe, buf, 0,
PIPE_PRIM_QUADS,
4, /* verts */
2); /* attribs/vert */
pipe_buffer_reference(&buf, NULL);
}
pipe_surface_reference(&dst_surf, NULL);
r->buffer_size = 0;
r->attrs_per_vertex = 2;
}
static struct pipe_texture *
create_sampler_texture(struct xorg_renderer *r,
struct pipe_texture *
renderer_clone_texture(struct xorg_renderer *r,
struct pipe_texture *src)
{
enum pipe_format format;
@@ -556,7 +492,9 @@ create_sampler_texture(struct xorg_renderer *r,
struct pipe_texture *pt;
struct pipe_texture templ;
pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
if (pipe->is_texture_referenced(pipe, src, 0, 0) &
PIPE_REFERENCED_FOR_WRITE)
pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
/* the coming in texture should already have that invariance */
debug_assert(screen->is_format_supported(screen, src->format,
@@ -610,52 +548,40 @@ create_sampler_texture(struct xorg_renderer *r,
void renderer_copy_pixmap(struct xorg_renderer *r,
struct exa_pixmap_priv *dst_priv, int dx, int dy,
struct exa_pixmap_priv *src_priv, int sx, int sy,
int width, int height)
int dx, int dy,
int sx, int sy,
int width, int height,
float src_width,
float src_height)
{
float dst_loc[4], src_loc[4];
struct pipe_texture *dst = dst_priv->tex;
struct pipe_texture *src = src_priv->tex;
float s0, t0, s1, t1;
float x0, y0, x1, y1;
if (r->pipe->is_texture_referenced(r->pipe, src, 0, 0) &
PIPE_REFERENCED_FOR_WRITE)
r->pipe->flush(r->pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
dst_loc[0] = dx;
dst_loc[1] = dy;
dst_loc[2] = width;
dst_loc[3] = height;
/* 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;
src_loc[0] = sx;
src_loc[1] = sy;
src_loc[2] = width;
src_loc[3] = height;
x0 = dx;
x1 = dx + width;
y0 = dy;
y1 = dy + height;
if (src_loc[2] >= 0 && src_loc[3] >= 0 &&
dst_loc[2] >= 0 && dst_loc[3] >= 0) {
struct pipe_texture *temp_src = src;
if (src == dst)
temp_src = create_sampler_texture(r, src);
renderer_copy_texture(r,
temp_src,
src_loc[0],
src_loc[1],
src_loc[0] + src_loc[2],
src_loc[1] + src_loc[3],
dst,
dst_loc[0],
dst_loc[1],
dst_loc[0] + dst_loc[2],
dst_loc[1] + dst_loc[3]);
if (src == dst)
pipe_texture_reference(&temp_src, NULL);
}
/* 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,
int src_x, int src_y, int src_w, int src_h,
int dst_x, int dst_y, int dst_w, int dst_h,
@@ -48,10 +48,6 @@ void renderer_set_constants(struct xorg_renderer *r,
int shader_type,
const float *buffer,
int size);
void renderer_copy_pixmap(struct xorg_renderer *r,
struct exa_pixmap_priv *dst_priv, int dx, int dy,
struct exa_pixmap_priv *src_priv, int sx, int sy,
int width, int height);
void renderer_draw_yuv(struct xorg_renderer *r,
@@ -78,5 +74,20 @@ void renderer_texture(struct xorg_renderer *r,
void renderer_draw_flush(struct xorg_renderer *r);
struct pipe_texture *
renderer_clone_texture(struct xorg_renderer *r,
struct pipe_texture *src);
void renderer_copy_prepare(struct xorg_renderer *r,
struct pipe_surface *dst_surface,
struct pipe_texture *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
@@ -453,7 +453,6 @@ display_video(ScrnInfoPtr pScrn, struct xorg_xv_port_priv *pPriv, int id,
renderer_bind_destination(pPriv->r, dst_surf);
bind_blend_state(pPriv);
renderer_bind_rasterizer(pPriv->r);
bind_shaders(pPriv);
bind_samplers(pPriv);
setup_fs_video_constants(pPriv->r, hdtv);