From 319a588238b4c0c58f8f8807e1143ad79cd8f698 Mon Sep 17 00:00:00 2001 From: Zack Rusin Date: Fri, 9 Oct 2009 09:52:17 -0400 Subject: st/xorg: lots of rendering and xv changes extract all the rendering code to xorg_rendedrer, make both exa and xv share that code. in the process cleanup the rendering code and implement a lot more of the xv infrastructure. --- src/gallium/state_trackers/xorg/SConscript | 1 + src/gallium/state_trackers/xorg/xorg_composite.c | 746 +--------------------- src/gallium/state_trackers/xorg/xorg_composite.h | 5 - src/gallium/state_trackers/xorg/xorg_exa.c | 50 +- src/gallium/state_trackers/xorg/xorg_exa.h | 12 +- src/gallium/state_trackers/xorg/xorg_exa_tgsi.c | 14 +- src/gallium/state_trackers/xorg/xorg_exa_tgsi.h | 4 +- src/gallium/state_trackers/xorg/xorg_renderer.c | 748 +++++++++++++++++++++++ src/gallium/state_trackers/xorg/xorg_renderer.h | 53 ++ src/gallium/state_trackers/xorg/xorg_tracker.h | 4 +- src/gallium/state_trackers/xorg/xorg_xv.c | 319 +++++++++- 11 files changed, 1170 insertions(+), 786 deletions(-) create mode 100644 src/gallium/state_trackers/xorg/xorg_renderer.c create mode 100644 src/gallium/state_trackers/xorg/xorg_renderer.h (limited to 'src') diff --git a/src/gallium/state_trackers/xorg/SConscript b/src/gallium/state_trackers/xorg/SConscript index 65f55ea378a..6165bae7a4b 100644 --- a/src/gallium/state_trackers/xorg/SConscript +++ b/src/gallium/state_trackers/xorg/SConscript @@ -22,6 +22,7 @@ if 'xorg' in env['statetrackers']: 'xorg_exa.c', 'xorg_exa_tgsi.c', 'xorg_output.c', + 'xorg_xv.c', ] ) Export('st_xorg') diff --git a/src/gallium/state_trackers/xorg/xorg_composite.c b/src/gallium/state_trackers/xorg/xorg_composite.c index 98e9933f72d..54b9ecaba1a 100644 --- a/src/gallium/state_trackers/xorg/xorg_composite.c +++ b/src/gallium/state_trackers/xorg/xorg_composite.c @@ -1,5 +1,6 @@ #include "xorg_composite.h" +#include "xorg_renderer.h" #include "xorg_exa_tgsi.h" #include "cso_cache/cso_context.h" @@ -111,173 +112,6 @@ render_repeat_to_gallium(int mode) return PIPE_TEX_WRAP_REPEAT; } - -static INLINE void -setup_vertex0(float vertex[2][4], float x, float y, - float color[4]) -{ - vertex[0][0] = x; - vertex[0][1] = y; - vertex[0][2] = 0.f; /*z*/ - vertex[0][3] = 1.f; /*w*/ - - vertex[1][0] = color[0]; /*r*/ - vertex[1][1] = color[1]; /*g*/ - vertex[1][2] = color[2]; /*b*/ - vertex[1][3] = color[3]; /*a*/ -} - -static struct pipe_buffer * -setup_vertex_data0(struct exa_context *ctx, - int srcX, int srcY, int maskX, int maskY, - int dstX, int dstY, int width, int height) -{ - /* 1st vertex */ - setup_vertex0(ctx->vertices2[0], dstX, dstY, - ctx->solid_color); - /* 2nd vertex */ - setup_vertex0(ctx->vertices2[1], dstX + width, dstY, - ctx->solid_color); - /* 3rd vertex */ - setup_vertex0(ctx->vertices2[2], dstX + width, dstY + height, - ctx->solid_color); - /* 4th vertex */ - setup_vertex0(ctx->vertices2[3], dstX, dstY + height, - ctx->solid_color); - - return pipe_user_buffer_create(ctx->pipe->screen, - ctx->vertices2, - sizeof(ctx->vertices2)); -} - -static INLINE void -setup_vertex1(float vertex[2][4], float x, float y, float s, float t) -{ - vertex[0][0] = x; - vertex[0][1] = y; - vertex[0][2] = 0.f; /*z*/ - vertex[0][3] = 1.f; /*w*/ - - vertex[1][0] = s; /*s*/ - vertex[1][1] = t; /*t*/ - vertex[1][2] = 0.f; /*r*/ - vertex[1][3] = 1.f; /*q*/ -} - -static struct pipe_buffer * -setup_vertex_data1(struct exa_context *ctx, - int srcX, int srcY, int maskX, int maskY, - int dstX, int dstY, int width, int height) -{ - float s0, t0, s1, t1; - struct pipe_texture *src = ctx->bound_textures[0]; - - s0 = srcX / src->width[0]; - s1 = srcX + width / src->width[0]; - t0 = srcY / src->height[0]; - t1 = srcY + height / src->height[0]; - - /* 1st vertex */ - setup_vertex1(ctx->vertices2[0], dstX, dstY, - s0, t0); - /* 2nd vertex */ - setup_vertex1(ctx->vertices2[1], dstX + width, dstY, - s1, t0); - /* 3rd vertex */ - setup_vertex1(ctx->vertices2[2], dstX + width, dstY + height, - s1, t1); - /* 4th vertex */ - setup_vertex1(ctx->vertices2[3], dstX, dstY + height, - s0, t1); - - return pipe_user_buffer_create(ctx->pipe->screen, - ctx->vertices2, - sizeof(ctx->vertices2)); -} - -static struct pipe_buffer * -setup_vertex_data_tex(struct exa_context *ctx, - float x0, float y0, float x1, float y1, - float s0, float t0, float s1, float t1, - float z) -{ - /* 1st vertex */ - setup_vertex1(ctx->vertices2[0], x0, y0, - s0, t0); - /* 2nd vertex */ - setup_vertex1(ctx->vertices2[1], x1, y0, - s1, t0); - /* 3rd vertex */ - setup_vertex1(ctx->vertices2[2], x1, y1, - s1, t1); - /* 4th vertex */ - setup_vertex1(ctx->vertices2[3], x0, y1, - s0, t1); - - return pipe_user_buffer_create(ctx->pipe->screen, - ctx->vertices2, - sizeof(ctx->vertices2)); -} - - - -static INLINE void -setup_vertex2(float vertex[3][4], float x, float y, - float s0, float t0, float s1, float t1) -{ - vertex[0][0] = x; - vertex[0][1] = y; - vertex[0][2] = 0.f; /*z*/ - vertex[0][3] = 1.f; /*w*/ - - vertex[1][0] = s0; /*s*/ - vertex[1][1] = t0; /*t*/ - vertex[1][2] = 0.f; /*r*/ - vertex[1][3] = 1.f; /*q*/ - - vertex[2][0] = s1; /*s*/ - vertex[2][1] = t1; /*t*/ - vertex[2][2] = 0.f; /*r*/ - vertex[2][3] = 1.f; /*q*/ -} - -static struct pipe_buffer * -setup_vertex_data2(struct exa_context *ctx, - int srcX, int srcY, int maskX, int maskY, - int dstX, int dstY, int width, int height) -{ - float st0[4], st1[4]; - struct pipe_texture *src = ctx->bound_textures[0]; - struct pipe_texture *mask = ctx->bound_textures[0]; - - st0[0] = srcX / src->width[0]; - st0[1] = srcY / src->height[0]; - st0[2] = srcX + width / src->width[0]; - st0[3] = srcY + height / src->height[0]; - - st1[0] = maskX / mask->width[0]; - st1[1] = maskY / mask->height[0]; - st1[2] = maskX + width / mask->width[0]; - st1[3] = maskY + height / mask->height[0]; - - /* 1st vertex */ - setup_vertex2(ctx->vertices3[0], dstX, dstY, - st0[0], st0[1], st1[0], st1[1]); - /* 2nd vertex */ - setup_vertex2(ctx->vertices3[1], dstX + width, dstY, - st0[2], st0[1], st1[2], st1[1]); - /* 3rd vertex */ - setup_vertex2(ctx->vertices3[2], dstX + width, dstY + height, - st0[2], st0[3], st1[2], st1[3]); - /* 4th vertex */ - setup_vertex2(ctx->vertices3[3], dstX, dstY + height, - st0[0], st0[3], st1[0], st1[3]); - - return pipe_user_buffer_create(ctx->pipe->screen, - ctx->vertices3, - sizeof(ctx->vertices3)); -} - boolean xorg_composite_accelerated(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, @@ -316,71 +150,6 @@ boolean xorg_composite_accelerated(int op, XORG_FALLBACK("unsupported operation"); } -static void -bind_clip_state(struct exa_context *exa) -{ -} - -static void -bind_framebuffer_state(struct exa_context *exa, struct exa_pixmap_priv *pDst) -{ - unsigned i; - struct pipe_framebuffer_state state; - struct pipe_surface *surface = exa_gpu_surface(exa, pDst); - memset(&state, 0, sizeof(struct pipe_framebuffer_state)); - - state.width = pDst->tex->width[0]; - state.height = pDst->tex->height[0]; - - state.nr_cbufs = 1; - state.cbufs[0] = surface; - for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i) - state.cbufs[i] = 0; - - /* currently we don't use depth/stencil */ - state.zsbuf = 0; - - cso_set_framebuffer(exa->cso, &state); - - /* we do fire and forget for the framebuffer, this is the forget part */ - pipe_surface_reference(&surface, NULL); -} - -enum AxisOrientation { - Y0_BOTTOM, - Y0_TOP -}; - -static void -set_viewport(struct exa_context *exa, int width, int height, - enum AxisOrientation orientation) -{ - struct pipe_viewport_state viewport; - float y_scale = (orientation == Y0_BOTTOM) ? -2.f : 2.f; - - viewport.scale[0] = width / 2.f; - viewport.scale[1] = height / y_scale; - viewport.scale[2] = 1.0; - viewport.scale[3] = 1.0; - viewport.translate[0] = width / 2.f; - viewport.translate[1] = height / 2.f; - viewport.translate[2] = 0.0; - viewport.translate[3] = 0.0; - - cso_set_viewport(exa->cso, &viewport); -} - -static void -bind_viewport_state(struct exa_context *exa, struct exa_pixmap_priv *pDst) -{ - int width = pDst->tex->width[0]; - int height = pDst->tex->height[0]; - - /*debug_printf("Bind viewport (%d, %d)\n", width, height);*/ - - set_viewport(exa, width, height, Y0_TOP); -} - static void bind_blend_state(struct exa_context *exa, int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture) @@ -402,17 +171,9 @@ bind_blend_state(struct exa_context *exa, int op, blend.rgb_dst_factor = blend_opt.rgb_dst_factor; blend.alpha_dst_factor = blend_opt.alpha_dst_factor; - cso_set_blend(exa->cso, &blend); + cso_set_blend(exa->renderer->cso, &blend); } -static void -bind_rasterizer_state(struct exa_context *exa) -{ - struct pipe_rasterizer_state raster; - memset(&raster, 0, sizeof(struct pipe_rasterizer_state)); - raster.gl_rasterization_rules = 1; - cso_set_rasterizer(exa->cso, &raster); -} static void bind_shaders(struct exa_context *exa, int op, @@ -446,9 +207,9 @@ bind_shaders(struct exa_context *exa, int op, fs_traits |= FS_MASK; } - shader = xorg_shaders_get(exa->shaders, vs_traits, fs_traits); - cso_set_vertex_shader_handle(exa->cso, shader.vs); - cso_set_fragment_shader_handle(exa->cso, shader.fs); + shader = xorg_shaders_get(exa->renderer->shaders, vs_traits, fs_traits); + cso_set_vertex_shader_handle(exa->renderer->cso, shader.vs); + cso_set_fragment_shader_handle(exa->renderer->cso, shader.fs); } @@ -500,9 +261,9 @@ bind_samplers(struct exa_context *exa, int op, ++exa->num_bound_samplers; } - cso_set_samplers(exa->cso, exa->num_bound_samplers, + cso_set_samplers(exa->renderer->cso, exa->num_bound_samplers, (const struct pipe_sampler_state **)samplers); - cso_set_sampler_textures(exa->cso, exa->num_bound_samplers, + cso_set_sampler_textures(exa->renderer->cso, exa->num_bound_samplers, exa->bound_textures); } @@ -515,18 +276,8 @@ setup_vs_constant_buffer(struct exa_context *exa, 2.f/width, 2.f/height, 1, 1, -1, -1, 0, 0 }; - struct pipe_constant_buffer *cbuf = &exa->vs_const_buffer; - - pipe_buffer_reference(&cbuf->buffer, NULL); - cbuf->buffer = pipe_buffer_create(exa->pipe->screen, 16, - PIPE_BUFFER_USAGE_CONSTANT, - param_bytes); - - if (cbuf->buffer) { - pipe_buffer_write(exa->pipe->screen, cbuf->buffer, - 0, param_bytes, vs_consts); - } - exa->pipe->set_constant_buffer(exa->pipe, PIPE_SHADER_VERTEX, 0, cbuf); + renderer_set_constants(exa->renderer, PIPE_SHADER_VERTEX, + vs_consts, param_bytes); } @@ -534,21 +285,11 @@ static void setup_fs_constant_buffer(struct exa_context *exa) { const int param_bytes = 4 * sizeof(float); - float fs_consts[8] = { + const float fs_consts[8] = { 0, 0, 0, 1, }; - struct pipe_constant_buffer *cbuf = &exa->fs_const_buffer; - - pipe_buffer_reference(&cbuf->buffer, NULL); - cbuf->buffer = pipe_buffer_create(exa->pipe->screen, 16, - PIPE_BUFFER_USAGE_CONSTANT, - param_bytes); - - if (cbuf->buffer) { - pipe_buffer_write(exa->pipe->screen, cbuf->buffer, - 0, param_bytes, fs_consts); - } - exa->pipe->set_constant_buffer(exa->pipe, PIPE_SHADER_FRAGMENT, 0, cbuf); + renderer_set_constants(exa->renderer, PIPE_SHADER_FRAGMENT, + fs_consts, param_bytes); } static void @@ -570,14 +311,13 @@ boolean xorg_composite_bind_state(struct exa_context *exa, struct exa_pixmap_priv *pMask, struct exa_pixmap_priv *pDst) { - bind_framebuffer_state(exa, pDst); - bind_viewport_state(exa, pDst); + renderer_bind_framebuffer(exa->renderer, pDst); + renderer_bind_viewport(exa->renderer, pDst); bind_blend_state(exa, op, pSrcPicture, pMaskPicture); - bind_rasterizer_state(exa); + renderer_bind_rasterizer(exa->renderer); bind_shaders(exa, op, pSrcPicture, pMaskPicture); bind_samplers(exa, op, pSrcPicture, pMaskPicture, pDstPicture, pSrc, pMask, pDst); - bind_clip_state(exa); setup_constant_buffers(exa, pDst); return FALSE; @@ -588,42 +328,16 @@ void xorg_composite(struct exa_context *exa, int srcX, int srcY, int maskX, int maskY, int dstX, int dstY, int width, int height) { - struct pipe_context *pipe = exa->pipe; - struct pipe_buffer *buf = 0; - if (exa->num_bound_samplers == 0 ) { /* solid fill */ - buf = setup_vertex_data0(exa, - srcX, srcY, maskX, maskY, - dstX, dstY, width, height); - } else if (exa->num_bound_samplers == 1 ) /* src */ - buf = setup_vertex_data1(exa, - srcX, srcY, maskX, maskY, - dstX, dstY, width, height); - else if (exa->num_bound_samplers == 2) /* src + mask */ - buf = setup_vertex_data2(exa, - srcX, srcY, maskX, maskY, - dstX, dstY, width, height); - else if (exa->num_bound_samplers == 3) { /* src + mask + dst */ - debug_assert(!"src/mask/dst not handled right now"); -#if 0 - buf = setup_vertex_data2(exa, - srcX, srcY, maskX, maskY, - dstX, dstY, width, height); -#endif - } - - if (buf) { - int num_attribs = 1; /*pos*/ - num_attribs += exa->num_bound_samplers; - if (exa->has_solid_color) - ++num_attribs; - - util_draw_vertex_buffer(pipe, buf, 0, - PIPE_PRIM_TRIANGLE_FAN, - 4, /* verts */ - num_attribs); /* attribs/vert */ - - pipe_buffer_reference(&buf, NULL); + renderer_draw_solid_rect(exa->renderer, + dstX, dstY, dstX + width, dstY + height, + exa->solid_color); + } else { + int pos[6] = {srcX, srcY, maskX, maskY, dstX, dstY}; + renderer_draw_textures(exa->renderer, + pos, width, height, + exa->bound_textures, + exa->num_bound_samplers); } } @@ -650,16 +364,15 @@ boolean xorg_solid_bind_state(struct exa_context *exa, vs_traits = VS_SOLID_FILL; fs_traits = FS_SOLID_FILL; - bind_framebuffer_state(exa, pixmap); - bind_viewport_state(exa, pixmap); - bind_rasterizer_state(exa); + renderer_bind_framebuffer(exa->renderer, pixmap); + renderer_bind_viewport(exa->renderer, pixmap); + renderer_bind_rasterizer(exa->renderer); bind_blend_state(exa, PictOpSrc, NULL, NULL); setup_constant_buffers(exa, pixmap); - bind_clip_state(exa); - shader = xorg_shaders_get(exa->shaders, vs_traits, fs_traits); - cso_set_vertex_shader_handle(exa->cso, shader.vs); - cso_set_fragment_shader_handle(exa->cso, shader.fs); + shader = xorg_shaders_get(exa->renderer->shaders, vs_traits, fs_traits); + cso_set_vertex_shader_handle(exa->renderer->cso, shader.vs); + cso_set_fragment_shader_handle(exa->renderer->cso, shader.fs); return TRUE; } @@ -668,402 +381,7 @@ void xorg_solid(struct exa_context *exa, struct exa_pixmap_priv *pixmap, int x0, int y0, int x1, int y1) { - struct pipe_context *pipe = exa->pipe; - struct pipe_buffer *buf = 0; - - /* 1st vertex */ - setup_vertex0(exa->vertices2[0], x0, y0, - exa->solid_color); - /* 2nd vertex */ - setup_vertex0(exa->vertices2[1], x1, y0, - exa->solid_color); - /* 3rd vertex */ - setup_vertex0(exa->vertices2[2], x1, y1, - exa->solid_color); - /* 4th vertex */ - setup_vertex0(exa->vertices2[3], x0, y1, - exa->solid_color); - - buf = pipe_user_buffer_create(exa->pipe->screen, - exa->vertices2, - sizeof(exa->vertices2)); - - - if (buf) { - util_draw_vertex_buffer(pipe, buf, 0, - PIPE_PRIM_TRIANGLE_FAN, - 4, /* verts */ - 2); /* attribs/vert */ - - pipe_buffer_reference(&buf, NULL); - } -} - - -static INLINE void shift_rectx(float coords[4], - const float *bounds, - const float shift) -{ - coords[0] += shift; - coords[2] -= shift; - if (bounds) { - coords[2] = MIN2(coords[2], bounds[2]); - /* bound x/y + width/height */ - if ((coords[0] + coords[2]) > (bounds[0] + bounds[2])) { - coords[2] = (bounds[0] + bounds[2]) - coords[0]; - } - } -} - -static INLINE void shift_recty(float coords[4], - const float *bounds, - const float shift) -{ - coords[1] += shift; - coords[3] -= shift; - if (bounds) { - coords[3] = MIN2(coords[3], bounds[3]); - if ((coords[1] + coords[3]) > (bounds[1] + bounds[3])) { - coords[3] = (bounds[1] + bounds[3]) - coords[1]; - } - } -} - -static INLINE void bound_rect(float coords[4], - const float bounds[4], - float shift[4]) -{ - /* if outside the bounds */ - if (coords[0] > (bounds[0] + bounds[2]) || - coords[1] > (bounds[1] + bounds[3]) || - (coords[0] + coords[2]) < bounds[0] || - (coords[1] + coords[3]) < bounds[1]) { - coords[0] = 0.f; - coords[1] = 0.f; - coords[2] = 0.f; - coords[3] = 0.f; - shift[0] = 0.f; - shift[1] = 0.f; - return; - } - - /* bound x */ - if (coords[0] < bounds[0]) { - shift[0] = bounds[0] - coords[0]; - coords[2] -= shift[0]; - coords[0] = bounds[0]; - } else - shift[0] = 0.f; - - /* bound y */ - if (coords[1] < bounds[1]) { - shift[1] = bounds[1] - coords[1]; - coords[3] -= shift[1]; - coords[1] = bounds[1]; - } else - shift[1] = 0.f; - - shift[2] = bounds[2] - coords[2]; - shift[3] = bounds[3] - coords[3]; - /* bound width/height */ - coords[2] = MIN2(coords[2], bounds[2]); - coords[3] = MIN2(coords[3], bounds[3]); - - /* bound x/y + width/height */ - if ((coords[0] + coords[2]) > (bounds[0] + bounds[2])) { - coords[2] = (bounds[0] + bounds[2]) - coords[0]; - } - if ((coords[1] + coords[3]) > (bounds[1] + bounds[3])) { - coords[3] = (bounds[1] + bounds[3]) - coords[1]; - } - - /* if outside the bounds */ - if ((coords[0] + coords[2]) < bounds[0] || - (coords[1] + coords[3]) < bounds[1]) { - coords[0] = 0.f; - coords[1] = 0.f; - coords[2] = 0.f; - coords[3] = 0.f; - return; - } -} - -static INLINE void sync_size(float *src_loc, float *dst_loc) -{ - src_loc[2] = MIN2(src_loc[2], dst_loc[2]); - src_loc[3] = MIN2(src_loc[3], dst_loc[3]); - dst_loc[2] = src_loc[2]; - dst_loc[3] = src_loc[3]; -} - - -static void renderer_copy_texture(struct exa_context *exa, - struct pipe_texture *src, - float sx1, float sy1, - float sx2, float sy2, - struct pipe_texture *dst, - float dx1, float dy1, - float dx2, float dy2) -{ - struct pipe_context *pipe = exa->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); - struct pipe_framebuffer_state fb; - 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, - PIPE_TEXTURE_2D, - PIPE_TEXTURE_USAGE_RENDER_TARGET, - 0)); - - /* save state (restored below) */ - cso_save_blend(exa->cso); - cso_save_samplers(exa->cso); - cso_save_sampler_textures(exa->cso); - cso_save_framebuffer(exa->cso); - cso_save_fragment_shader(exa->cso); - cso_save_vertex_shader(exa->cso); - - cso_save_viewport(exa->cso); - - - /* set misc state we care about */ - { - struct pipe_blend_state blend; - memset(&blend, 0, sizeof(blend)); - blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE; - blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE; - blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; - blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; - blend.colormask = PIPE_MASK_RGBA; - cso_set_blend(exa->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(exa->cso, 0, &sampler); - cso_single_sampler_done(exa->cso); - } - - set_viewport(exa, dst_surf->width, dst_surf->height, Y0_TOP); - - /* texture */ - cso_set_sampler_textures(exa->cso, 1, &src); - - bind_rasterizer_state(exa); - - /* shaders */ - shader = xorg_shaders_get(exa->shaders, - VS_COMPOSITE, - FS_COMPOSITE); - cso_set_vertex_shader_handle(exa->cso, shader.vs); - cso_set_fragment_shader_handle(exa->cso, shader.fs); - - /* drawing dest */ - memset(&fb, 0, sizeof(fb)); - fb.width = dst_surf->width; - fb.height = dst_surf->height; - fb.nr_cbufs = 1; - fb.cbufs[0] = dst_surf; - { - int i; - for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i) - fb.cbufs[i] = 0; - } - cso_set_framebuffer(exa->cso, &fb); - setup_vs_constant_buffer(exa, fb.width, fb.height); - setup_fs_constant_buffer(exa); - - /* draw quad */ - buf = setup_vertex_data_tex(exa, - dx1, dy1, - dx2, dy2, - s0, t0, s1, t1, - 0.0f); - - if (buf) { - util_draw_vertex_buffer(exa->pipe, buf, 0, - PIPE_PRIM_TRIANGLE_FAN, - 4, /* verts */ - 2); /* attribs/vert */ - - pipe_buffer_reference(&buf, NULL); - } - - /* restore state we changed */ - cso_restore_blend(exa->cso); - cso_restore_samplers(exa->cso); - cso_restore_sampler_textures(exa->cso); - cso_restore_framebuffer(exa->cso); - cso_restore_vertex_shader(exa->cso); - cso_restore_fragment_shader(exa->cso); - cso_restore_viewport(exa->cso); - - pipe_surface_reference(&dst_surf, NULL); -} - - -static struct pipe_texture * -create_sampler_texture(struct exa_context *ctx, - struct pipe_texture *src) -{ - enum pipe_format format; - struct pipe_context *pipe = ctx->pipe; - struct pipe_screen *screen = pipe->screen; - struct pipe_texture *pt; - struct pipe_texture templ; - - 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, - PIPE_TEXTURE_2D, - PIPE_TEXTURE_USAGE_SAMPLER, 0)); - - format = src->format; - - memset(&templ, 0, sizeof(templ)); - templ.target = PIPE_TEXTURE_2D; - templ.format = format; - templ.last_level = 0; - templ.width[0] = src->width[0]; - templ.height[0] = src->height[0]; - templ.depth[0] = 1; - pf_get_block(format, &templ.block); - templ.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER; - - pt = screen->texture_create(screen, &templ); - - debug_assert(!pt || pipe_is_referenced(&pt->reference)); - - if (!pt) - return NULL; - - { - /* copy source framebuffer surface into texture */ - struct pipe_surface *ps_read = screen->get_tex_surface( - screen, src, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ); - struct pipe_surface *ps_tex = screen->get_tex_surface( - screen, pt, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE ); - pipe->surface_copy(pipe, - ps_tex, /* dest */ - 0, 0, /* destx/y */ - ps_read, - 0, 0, src->width[0], src->height[0]); - pipe_surface_reference(&ps_read, NULL); - pipe_surface_reference(&ps_tex, NULL); - } - - return pt; -} - -void xorg_copy_pixmap(struct exa_context *ctx, - struct exa_pixmap_priv *dst_priv, int dx, int dy, - struct exa_pixmap_priv *src_priv, int sx, int sy, - int width, int height) -{ - float dst_loc[4], src_loc[4]; - float dst_bounds[4], src_bounds[4]; - float src_shift[4], dst_shift[4], shift[4]; - struct pipe_texture *dst = dst_priv->tex; - struct pipe_texture *src = src_priv->tex; - - if (ctx->pipe->is_texture_referenced(ctx->pipe, src, 0, 0) & - PIPE_REFERENCED_FOR_WRITE) - ctx->pipe->flush(ctx->pipe, PIPE_FLUSH_RENDER_CACHE, NULL); - - dst_loc[0] = dx; - dst_loc[1] = dy; - dst_loc[2] = width; - dst_loc[3] = height; - dst_bounds[0] = 0.f; - dst_bounds[1] = 0.f; - dst_bounds[2] = dst->width[0]; - dst_bounds[3] = dst->height[0]; - - src_loc[0] = sx; - src_loc[1] = sy; - src_loc[2] = width; - src_loc[3] = height; - src_bounds[0] = 0.f; - src_bounds[1] = 0.f; - src_bounds[2] = src->width[0]; - src_bounds[3] = src->height[0]; - - bound_rect(src_loc, src_bounds, src_shift); - bound_rect(dst_loc, dst_bounds, dst_shift); - shift[0] = src_shift[0] - dst_shift[0]; - shift[1] = src_shift[1] - dst_shift[1]; - - if (shift[0] < 0) - shift_rectx(src_loc, src_bounds, -shift[0]); - else - shift_rectx(dst_loc, dst_bounds, shift[0]); - - if (shift[1] < 0) - shift_recty(src_loc, src_bounds, -shift[1]); - else - shift_recty(dst_loc, dst_bounds, shift[1]); - - sync_size(src_loc, dst_loc); - - 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(ctx, src); - - renderer_copy_texture(ctx, - 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); - } + renderer_draw_solid_rect(exa->renderer, + x0, y0, x1, y1, exa->solid_color); } diff --git a/src/gallium/state_trackers/xorg/xorg_composite.h b/src/gallium/state_trackers/xorg/xorg_composite.h index e73f1c704a8..236addf1ce4 100644 --- a/src/gallium/state_trackers/xorg/xorg_composite.h +++ b/src/gallium/state_trackers/xorg/xorg_composite.h @@ -29,9 +29,4 @@ void xorg_solid(struct exa_context *exa, struct exa_pixmap_priv *pixmap, int x0, int y0, int x1, int y1); -void xorg_copy_pixmap(struct exa_context *ctx, - struct exa_pixmap_priv *dst, int dx, int dy, - struct exa_pixmap_priv *src, int sx, int sy, - int width, int height); - #endif diff --git a/src/gallium/state_trackers/xorg/xorg_exa.c b/src/gallium/state_trackers/xorg/xorg_exa.c index 2633e8caaf5..29785c0040c 100644 --- a/src/gallium/state_trackers/xorg/xorg_exa.c +++ b/src/gallium/state_trackers/xorg/xorg_exa.c @@ -43,8 +43,6 @@ #include "pipe/p_state.h" #include "pipe/p_inlines.h" -#include "cso_cache/cso_context.h" - #include "util/u_rect.h" #define DEBUG_PRINT 0 @@ -89,16 +87,6 @@ exa_get_pipe_format(int depth, enum pipe_format *format, int *bbp) } } -static void -xorg_exa_init_state(struct exa_context *exa) -{ - struct pipe_depth_stencil_alpha_state dsa; - - /* set common initial clip state */ - memset(&dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state)); - cso_set_depth_stencil_alpha(exa->cso, &dsa); -} - static void xorg_exa_common_done(struct exa_context *exa) { @@ -444,9 +432,9 @@ ExaCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY, debug_assert(priv == exa->copy.dst); - xorg_copy_pixmap(exa, exa->copy.dst, dstX, dstY, - exa->copy.src, srcX, srcY, - width, height); + renderer_copy_pixmap(exa->renderer, exa->copy.dst, dstX, dstY, + exa->copy.src, srcX, srcY, + width, height); } static Bool @@ -701,7 +689,7 @@ ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, dst_surf = exa->scrn->get_tex_surface( exa->scrn, texture, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE); - src_surf = exa_gpu_surface(exa, priv); + src_surf = xorg_gpu_surface(exa->pipe->screen, priv); exa->pipe->surface_copy(exa->pipe, dst_surf, 0, 0, src_surf, 0, 0, min(width, texture->width[0]), min(height, texture->height[0])); @@ -731,23 +719,8 @@ xorg_exa_close(ScrnInfoPtr pScrn) { modesettingPtr ms = modesettingPTR(pScrn); struct exa_context *exa = ms->exa; - struct pipe_constant_buffer *vsbuf = &exa->vs_const_buffer; - struct pipe_constant_buffer *fsbuf = &exa->fs_const_buffer; - if (exa->shaders) { - xorg_shaders_destroy(exa->shaders); - } - - if (vsbuf && vsbuf->buffer) - pipe_buffer_reference(&vsbuf->buffer, NULL); - - if (fsbuf && fsbuf->buffer) - pipe_buffer_reference(&fsbuf->buffer, NULL); - - if (exa->cso) { - cso_release_all(exa->cso); - cso_destroy_context(exa->cso); - } + renderer_destroy(exa->renderer); if (exa->pipe) exa->pipe->destroy(exa->pipe); @@ -822,10 +795,7 @@ xorg_exa_init(ScrnInfoPtr pScrn) /* Share context with DRI */ ms->ctx = exa->pipe; - exa->cso = cso_create_context(exa->pipe); - exa->shaders = xorg_shaders_create(exa); - - xorg_exa_init_state(exa); + exa->renderer = renderer_create(exa->pipe); return (void *)exa; @@ -836,11 +806,11 @@ out_err: } struct pipe_surface * -exa_gpu_surface(struct exa_context *exa, struct exa_pixmap_priv *priv) +xorg_gpu_surface(struct pipe_screen *scrn, struct exa_pixmap_priv *priv) { - return exa->scrn->get_tex_surface(exa->scrn, priv->tex, 0, 0, 0, - PIPE_BUFFER_USAGE_GPU_READ | - PIPE_BUFFER_USAGE_GPU_WRITE); + return scrn->get_tex_surface(scrn, priv->tex, 0, 0, 0, + PIPE_BUFFER_USAGE_GPU_READ | + PIPE_BUFFER_USAGE_GPU_WRITE); } diff --git a/src/gallium/state_trackers/xorg/xorg_exa.h b/src/gallium/state_trackers/xorg/xorg_exa.h index 28834e3ef50..292f964cec6 100644 --- a/src/gallium/state_trackers/xorg/xorg_exa.h +++ b/src/gallium/state_trackers/xorg/xorg_exa.h @@ -16,11 +16,7 @@ struct exa_context ExaDriverPtr pExa; struct pipe_context *pipe; struct pipe_screen *scrn; - struct cso_context *cso; - struct xorg_shaders *shaders; - - struct pipe_constant_buffer vs_const_buffer; - struct pipe_constant_buffer fs_const_buffer; + struct xorg_renderer *renderer; struct pipe_texture *bound_textures[MAX_EXA_SAMPLERS]; int num_bound_samplers; @@ -32,10 +28,6 @@ struct exa_context struct exa_pixmap_priv *src; struct exa_pixmap_priv *dst; } copy; - - /* we should combine these two */ - float vertices2[4][2][4]; - float vertices3[4][3][4]; }; struct exa_pixmap_priv @@ -60,7 +52,7 @@ do { \ } while(0) struct pipe_surface * -exa_gpu_surface(struct exa_context *exa, struct exa_pixmap_priv *priv); +xorg_gpu_surface(struct pipe_screen *scrn, struct exa_pixmap_priv *priv); void xorg_exa_flush(struct exa_context *exa, uint pipeFlushFlags, struct pipe_fence_handle **fence); diff --git a/src/gallium/state_trackers/xorg/xorg_exa_tgsi.c b/src/gallium/state_trackers/xorg/xorg_exa_tgsi.c index bb5a42af37e..8ce06e374a9 100644 --- a/src/gallium/state_trackers/xorg/xorg_exa_tgsi.c +++ b/src/gallium/state_trackers/xorg/xorg_exa_tgsi.c @@ -44,7 +44,7 @@ */ struct xorg_shaders { - struct exa_context *exa; + struct xorg_renderer *r; struct cso_hash *vs_hash; struct cso_hash *fs_hash; @@ -400,11 +400,11 @@ create_fs(struct pipe_context *pipe, return ureg_create_shader_and_destroy(ureg, pipe); } -struct xorg_shaders * xorg_shaders_create(struct exa_context *exa) +struct xorg_shaders * xorg_shaders_create(struct xorg_renderer *r) { struct xorg_shaders *sc = CALLOC_STRUCT(xorg_shaders); - sc->exa = exa; + sc->r = r; sc->vs_hash = cso_hash_create(); sc->fs_hash = cso_hash_create(); @@ -431,9 +431,9 @@ cache_destroy(struct cso_context *cso, void xorg_shaders_destroy(struct xorg_shaders *sc) { - cache_destroy(sc->exa->cso, sc->vs_hash, + cache_destroy(sc->r->cso, sc->vs_hash, PIPE_SHADER_VERTEX); - cache_destroy(sc->exa->cso, sc->fs_hash, + cache_destroy(sc->r->cso, sc->fs_hash, PIPE_SHADER_FRAGMENT); free(sc); @@ -468,9 +468,9 @@ struct xorg_shader xorg_shaders_get(struct xorg_shaders *sc, struct xorg_shader shader = { NULL, NULL }; void *vs, *fs; - vs = shader_from_cache(sc->exa->pipe, PIPE_SHADER_VERTEX, + vs = shader_from_cache(sc->r->pipe, PIPE_SHADER_VERTEX, sc->vs_hash, vs_traits); - fs = shader_from_cache(sc->exa->pipe, PIPE_SHADER_FRAGMENT, + fs = shader_from_cache(sc->r->pipe, PIPE_SHADER_FRAGMENT, sc->fs_hash, fs_traits); debug_assert(vs && fs); diff --git a/src/gallium/state_trackers/xorg/xorg_exa_tgsi.h b/src/gallium/state_trackers/xorg/xorg_exa_tgsi.h index 1535a0c8c30..33c272070b8 100644 --- a/src/gallium/state_trackers/xorg/xorg_exa_tgsi.h +++ b/src/gallium/state_trackers/xorg/xorg_exa_tgsi.h @@ -1,7 +1,7 @@ #ifndef XORG_EXA_TGSI_H #define XORG_EXA_TGSI_H -#include "xorg_exa.h" +#include "xorg_renderer.h" enum xorg_vs_traits { VS_COMPOSITE = 1 << 0, @@ -33,7 +33,7 @@ struct xorg_shader { struct xorg_shaders; -struct xorg_shaders *xorg_shaders_create(struct exa_context *exa); +struct xorg_shaders *xorg_shaders_create(struct xorg_renderer *renderer); void xorg_shaders_destroy(struct xorg_shaders *shaders); struct xorg_shader xorg_shaders_get(struct xorg_shaders *shaders, diff --git a/src/gallium/state_trackers/xorg/xorg_renderer.c b/src/gallium/state_trackers/xorg/xorg_renderer.c new file mode 100644 index 00000000000..362fb6f4f13 --- /dev/null +++ b/src/gallium/state_trackers/xorg/xorg_renderer.c @@ -0,0 +1,748 @@ +#include "xorg_exa.h" +#include "xorg_renderer.h" + +#include "xorg_exa_tgsi.h" + +#include "cso_cache/cso_context.h" +#include "util/u_draw_quad.h" +#include "util/u_math.h" +#include "util/u_memory.h" + +#include "pipe/p_inlines.h" + +enum AxisOrientation { + Y0_BOTTOM, + Y0_TOP +}; + +static void +renderer_init_state(struct xorg_renderer *r) +{ + struct pipe_depth_stencil_alpha_state dsa; + + /* set common initial clip state */ + memset(&dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state)); + cso_set_depth_stencil_alpha(r->cso, &dsa); +} + + +static INLINE void +setup_vertex0(float vertex[2][4], float x, float y, + float color[4]) +{ + vertex[0][0] = x; + vertex[0][1] = y; + vertex[0][2] = 0.f; /*z*/ + vertex[0][3] = 1.f; /*w*/ + + vertex[1][0] = color[0]; /*r*/ + vertex[1][1] = color[1]; /*g*/ + vertex[1][2] = color[2]; /*b*/ + vertex[1][3] = color[3]; /*a*/ +} + +static INLINE void +setup_vertex1(float vertex[2][4], float x, float y, float s, float t) +{ + vertex[0][0] = x; + vertex[0][1] = y; + vertex[0][2] = 0.f; /*z*/ + vertex[0][3] = 1.f; /*w*/ + + vertex[1][0] = s; /*s*/ + vertex[1][1] = t; /*t*/ + vertex[1][2] = 0.f; /*r*/ + vertex[1][3] = 1.f; /*q*/ +} + +static struct pipe_buffer * +setup_vertex_data1(struct xorg_renderer *r, + int srcX, int srcY, int dstX, int dstY, + int width, int height, + struct pipe_texture *src) +{ + float s0, t0, s1, t1; + + s0 = srcX / src->width[0]; + s1 = srcX + width / src->width[0]; + t0 = srcY / src->height[0]; + t1 = srcY + height / src->height[0]; + + /* 1st vertex */ + setup_vertex1(r->vertices2[0], dstX, dstY, s0, t0); + /* 2nd vertex */ + setup_vertex1(r->vertices2[1], dstX + width, dstY, s1, t0); + /* 3rd vertex */ + setup_vertex1(r->vertices2[2], dstX + width, dstY + height, s1, t1); + /* 4th vertex */ + setup_vertex1(r->vertices2[3], dstX, dstY + height, s0, t1); + + return pipe_user_buffer_create(r->pipe->screen, + r->vertices2, + sizeof(r->vertices2)); +} + +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 */ + setup_vertex1(r->vertices2[0], x0, y0, s0, t0); + /* 2nd vertex */ + setup_vertex1(r->vertices2[1], x1, y0, s1, t0); + /* 3rd vertex */ + setup_vertex1(r->vertices2[2], x1, y1, s1, t1); + /* 4th vertex */ + setup_vertex1(r->vertices2[3], x0, y1, s0, t1); + + return pipe_user_buffer_create(r->pipe->screen, + r->vertices2, + sizeof(r->vertices2)); +} + +static INLINE void +setup_vertex2(float vertex[3][4], float x, float y, + float s0, float t0, float s1, float t1) +{ + vertex[0][0] = x; + vertex[0][1] = y; + vertex[0][2] = 0.f; /*z*/ + vertex[0][3] = 1.f; /*w*/ + + vertex[1][0] = s0; /*s*/ + vertex[1][1] = t0; /*t*/ + vertex[1][2] = 0.f; /*r*/ + vertex[1][3] = 1.f; /*q*/ + + vertex[2][0] = s1; /*s*/ + vertex[2][1] = t1; /*t*/ + vertex[2][2] = 0.f; /*r*/ + vertex[2][3] = 1.f; /*q*/ +} + +static struct pipe_buffer * +setup_vertex_data2(struct xorg_renderer *r, + int srcX, int srcY, int maskX, int maskY, + int dstX, int dstY, int width, int height, + struct pipe_texture *src, + struct pipe_texture *mask) +{ + float st0[4], st1[4]; + + st0[0] = srcX / src->width[0]; + st0[1] = srcY / src->height[0]; + st0[2] = srcX + width / src->width[0]; + st0[3] = srcY + height / src->height[0]; + + st1[0] = maskX / mask->width[0]; + st1[1] = maskY / mask->height[0]; + st1[2] = maskX + width / mask->width[0]; + st1[3] = maskY + height / mask->height[0]; + + /* 1st vertex */ + setup_vertex2(r->vertices3[0], dstX, dstY, + st0[0], st0[1], st1[0], st1[1]); + /* 2nd vertex */ + setup_vertex2(r->vertices3[1], dstX + width, dstY, + st0[2], st0[1], st1[2], st1[1]); + /* 3rd vertex */ + setup_vertex2(r->vertices3[2], dstX + width, dstY + height, + st0[2], st0[3], st1[2], st1[3]); + /* 4th vertex */ + setup_vertex2(r->vertices3[3], dstX, dstY + height, + st0[0], st0[3], st1[0], st1[3]); + + return pipe_user_buffer_create(r->pipe->screen, + r->vertices3, + sizeof(r->vertices3)); +} + + + +static void +set_viewport(struct xorg_renderer *r, int width, int height, + enum AxisOrientation orientation) +{ + struct pipe_viewport_state viewport; + float y_scale = (orientation == Y0_BOTTOM) ? -2.f : 2.f; + + viewport.scale[0] = width / 2.f; + viewport.scale[1] = height / y_scale; + viewport.scale[2] = 1.0; + viewport.scale[3] = 1.0; + viewport.translate[0] = width / 2.f; + viewport.translate[1] = height / 2.f; + viewport.translate[2] = 0.0; + viewport.translate[3] = 0.0; + + cso_set_viewport(r->cso, &viewport); +} + + + +struct xorg_renderer * renderer_create(struct pipe_context *pipe) +{ + struct xorg_renderer *renderer = CALLOC_STRUCT(xorg_renderer); + + renderer->cso = cso_create_context(pipe); + renderer->shaders = xorg_shaders_create(renderer); + + renderer_init_state(renderer); + + return renderer; +} + +void renderer_destroy(struct xorg_renderer *r) +{ + struct pipe_constant_buffer *vsbuf = &r->vs_const_buffer; + struct pipe_constant_buffer *fsbuf = &r->fs_const_buffer; + + if (vsbuf && vsbuf->buffer) + pipe_buffer_reference(&vsbuf->buffer, NULL); + + if (fsbuf && fsbuf->buffer) + pipe_buffer_reference(&fsbuf->buffer, NULL); + + if (r->cso) { + cso_release_all(r->cso); + cso_destroy_context(r->cso); + } + + if (r->shaders) { + xorg_shaders_destroy(r->shaders); + } +} + +void renderer_bind_framebuffer(struct xorg_renderer *r, + struct exa_pixmap_priv *priv) +{ + unsigned i; + struct pipe_framebuffer_state state; + struct pipe_surface *surface = xorg_gpu_surface(r->pipe->screen, priv); + memset(&state, 0, sizeof(struct pipe_framebuffer_state)); + + state.width = priv->tex->width[0]; + state.height = priv->tex->height[0]; + + state.nr_cbufs = 1; + state.cbufs[0] = surface; + for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i) + state.cbufs[i] = 0; + + /* currently we don't use depth/stencil */ + state.zsbuf = 0; + + cso_set_framebuffer(r->cso, &state); + + /* we do fire and forget for the framebuffer, this is the forget part */ + pipe_surface_reference(&surface, NULL); +} + +void renderer_bind_viewport(struct xorg_renderer *r, + struct exa_pixmap_priv *dst) +{ + int width = dst->tex->width[0]; + int height = dst->tex->height[0]; + + /*debug_printf("Bind viewport (%d, %d)\n", width, height);*/ + + set_viewport(r, width, height, Y0_TOP); +} + +void renderer_bind_rasterizer(struct xorg_renderer *r) +{ + struct pipe_rasterizer_state raster; + + /* XXX: move to renderer_init_state? */ + memset(&raster, 0, sizeof(struct pipe_rasterizer_state)); + raster.gl_rasterization_rules = 1; + cso_set_rasterizer(r->cso, &raster); +} + +void renderer_set_constants(struct xorg_renderer *r, + int shader_type, + const float *params, + int param_bytes) +{ + struct pipe_constant_buffer *cbuf = + (shader_type == PIPE_SHADER_VERTEX) ? &r->vs_const_buffer : + &r->fs_const_buffer; + + pipe_buffer_reference(&cbuf->buffer, NULL); + cbuf->buffer = pipe_buffer_create(r->pipe->screen, 16, + PIPE_BUFFER_USAGE_CONSTANT, + param_bytes); + + if (cbuf->buffer) { + pipe_buffer_write(r->pipe->screen, cbuf->buffer, + 0, param_bytes, params); + } + r->pipe->set_constant_buffer(r->pipe, shader_type, 0, cbuf); +} + +static void +setup_vs_constant_buffer(struct xorg_renderer *r, + int width, int height) +{ + const int param_bytes = 8 * sizeof(float); + float vs_consts[8] = { + 2.f/width, 2.f/height, 1, 1, + -1, -1, 0, 0 + }; + renderer_set_constants(r, PIPE_SHADER_VERTEX, + vs_consts, param_bytes); +} + +static void +setup_fs_constant_buffer(struct xorg_renderer *r) +{ + const int param_bytes = 4 * sizeof(float); + const float fs_consts[8] = { + 0, 0, 0, 1, + }; + renderer_set_constants(r, PIPE_SHADER_FRAGMENT, + fs_consts, param_bytes); +} + +static INLINE void shift_rectx(float coords[4], + const float *bounds, + const float shift) +{ + coords[0] += shift; + coords[2] -= shift; + if (bounds) { + coords[2] = MIN2(coords[2], bounds[2]); + /* bound x/y + width/height */ + if ((coords[0] + coords[2]) > (bounds[0] + bounds[2])) { + coords[2] = (bounds[0] + bounds[2]) - coords[0]; + } + } +} + +static INLINE void shift_recty(float coords[4], + const float *bounds, + const float shift) +{ + coords[1] += shift; + coords[3] -= shift; + if (bounds) { + coords[3] = MIN2(coords[3], bounds[3]); + if ((coords[1] + coords[3]) > (bounds[1] + bounds[3])) { + coords[3] = (bounds[1] + bounds[3]) - coords[1]; + } + } +} + +static INLINE void bound_rect(float coords[4], + const float bounds[4], + float shift[4]) +{ + /* if outside the bounds */ + if (coords[0] > (bounds[0] + bounds[2]) || + coords[1] > (bounds[1] + bounds[3]) || + (coords[0] + coords[2]) < bounds[0] || + (coords[1] + coords[3]) < bounds[1]) { + coords[0] = 0.f; + coords[1] = 0.f; + coords[2] = 0.f; + coords[3] = 0.f; + shift[0] = 0.f; + shift[1] = 0.f; + return; + } + + /* bound x */ + if (coords[0] < bounds[0]) { + shift[0] = bounds[0] - coords[0]; + coords[2] -= shift[0]; + coords[0] = bounds[0]; + } else + shift[0] = 0.f; + + /* bound y */ + if (coords[1] < bounds[1]) { + shift[1] = bounds[1] - coords[1]; + coords[3] -= shift[1]; + coords[1] = bounds[1]; + } else + shift[1] = 0.f; + + shift[2] = bounds[2] - coords[2]; + shift[3] = bounds[3] - coords[3]; + /* bound width/height */ + coords[2] = MIN2(coords[2], bounds[2]); + coords[3] = MIN2(coords[3], bounds[3]); + + /* bound x/y + width/height */ + if ((coords[0] + coords[2]) > (bounds[0] + bounds[2])) { + coords[2] = (bounds[0] + bounds[2]) - coords[0]; + } + if ((coords[1] + coords[3]) > (bounds[1] + bounds[3])) { + coords[3] = (bounds[1] + bounds[3]) - coords[1]; + } + + /* if outside the bounds */ + if ((coords[0] + coords[2]) < bounds[0] || + (coords[1] + coords[3]) < bounds[1]) { + coords[0] = 0.f; + coords[1] = 0.f; + coords[2] = 0.f; + coords[3] = 0.f; + return; + } +} + +static INLINE void sync_size(float *src_loc, float *dst_loc) +{ + src_loc[2] = MIN2(src_loc[2], dst_loc[2]); + src_loc[3] = MIN2(src_loc[3], dst_loc[3]); + dst_loc[2] = src_loc[2]; + dst_loc[3] = src_loc[3]; +} + +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) +{ + 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); + struct pipe_framebuffer_state fb; + 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, + PIPE_TEXTURE_2D, + PIPE_TEXTURE_USAGE_RENDER_TARGET, + 0)); + + /* save state (restored below) */ + cso_save_blend(r->cso); + cso_save_samplers(r->cso); + cso_save_sampler_textures(r->cso); + cso_save_framebuffer(r->cso); + cso_save_fragment_shader(r->cso); + cso_save_vertex_shader(r->cso); + + cso_save_viewport(r->cso); + + + /* set misc state we care about */ + { + struct pipe_blend_state blend; + memset(&blend, 0, sizeof(blend)); + blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE; + blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend.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); + } + + set_viewport(r, dst_surf->width, dst_surf->height, Y0_TOP); + + /* texture */ + cso_set_sampler_textures(r->cso, 1, &src); + + renderer_bind_rasterizer(r); + + /* 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); + + /* drawing dest */ + memset(&fb, 0, sizeof(fb)); + fb.width = dst_surf->width; + fb.height = dst_surf->height; + fb.nr_cbufs = 1; + fb.cbufs[0] = dst_surf; + { + int i; + for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i) + fb.cbufs[i] = 0; + } + cso_set_framebuffer(r->cso, &fb); + setup_vs_constant_buffer(r, fb.width, fb.height); + setup_fs_constant_buffer(r); + + /* 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_TRIANGLE_FAN, + 4, /* verts */ + 2); /* attribs/vert */ + + pipe_buffer_reference(&buf, NULL); + } + + /* restore state we changed */ + cso_restore_blend(r->cso); + cso_restore_samplers(r->cso); + cso_restore_sampler_textures(r->cso); + cso_restore_framebuffer(r->cso); + cso_restore_vertex_shader(r->cso); + cso_restore_fragment_shader(r->cso); + cso_restore_viewport(r->cso); + + pipe_surface_reference(&dst_surf, NULL); +} + +static struct pipe_texture * +create_sampler_texture(struct xorg_renderer *r, + struct pipe_texture *src) +{ + enum pipe_format format; + struct pipe_context *pipe = r->pipe; + struct pipe_screen *screen = pipe->screen; + struct pipe_texture *pt; + struct pipe_texture templ; + + 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, + PIPE_TEXTURE_2D, + PIPE_TEXTURE_USAGE_SAMPLER, 0)); + + format = src->format; + + memset(&templ, 0, sizeof(templ)); + templ.target = PIPE_TEXTURE_2D; + templ.format = format; + templ.last_level = 0; + templ.width[0] = src->width[0]; + templ.height[0] = src->height[0]; + templ.depth[0] = 1; + pf_get_block(format, &templ.block); + templ.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER; + + pt = screen->texture_create(screen, &templ); + + debug_assert(!pt || pipe_is_referenced(&pt->reference)); + + if (!pt) + return NULL; + + { + /* copy source framebuffer surface into texture */ + struct pipe_surface *ps_read = screen->get_tex_surface( + screen, src, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ); + struct pipe_surface *ps_tex = screen->get_tex_surface( + screen, pt, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE ); + pipe->surface_copy(pipe, + ps_tex, /* dest */ + 0, 0, /* destx/y */ + ps_read, + 0, 0, src->width[0], src->height[0]); + pipe_surface_reference(&ps_read, NULL); + pipe_surface_reference(&ps_tex, NULL); + } + + return pt; +} + + +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) +{ + float dst_loc[4], src_loc[4]; + float dst_bounds[4], src_bounds[4]; + float src_shift[4], dst_shift[4], shift[4]; + struct pipe_texture *dst = dst_priv->tex; + struct pipe_texture *src = src_priv->tex; + + 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; + dst_bounds[0] = 0.f; + dst_bounds[1] = 0.f; + dst_bounds[2] = dst->width[0]; + dst_bounds[3] = dst->height[0]; + + src_loc[0] = sx; + src_loc[1] = sy; + src_loc[2] = width; + src_loc[3] = height; + src_bounds[0] = 0.f; + src_bounds[1] = 0.f; + src_bounds[2] = src->width[0]; + src_bounds[3] = src->height[0]; + + bound_rect(src_loc, src_bounds, src_shift); + bound_rect(dst_loc, dst_bounds, dst_shift); + shift[0] = src_shift[0] - dst_shift[0]; + shift[1] = src_shift[1] - dst_shift[1]; + + if (shift[0] < 0) + shift_rectx(src_loc, src_bounds, -shift[0]); + else + shift_rectx(dst_loc, dst_bounds, shift[0]); + + if (shift[1] < 0) + shift_recty(src_loc, src_bounds, -shift[1]); + else + shift_recty(dst_loc, dst_bounds, shift[1]); + + sync_size(src_loc, dst_loc); + + 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); + } +} + +void renderer_draw_solid_rect(struct xorg_renderer *r, + int x0, int y0, + int x1, int y1, + float *color) +{ + struct pipe_context *pipe = r->pipe; + struct pipe_buffer *buf = 0; + + /* 1st vertex */ + setup_vertex0(r->vertices2[0], x0, y0, color); + /* 2nd vertex */ + setup_vertex0(r->vertices2[1], x1, y0, color); + /* 3rd vertex */ + setup_vertex0(r->vertices2[2], x1, y1, color); + /* 4th vertex */ + setup_vertex0(r->vertices2[3], x0, y1, color); + + buf = pipe_user_buffer_create(pipe->screen, + r->vertices2, + sizeof(r->vertices2)); + + + if (buf) { + util_draw_vertex_buffer(pipe, buf, 0, + PIPE_PRIM_TRIANGLE_FAN, + 4, /* verts */ + 2); /* attribs/vert */ + + pipe_buffer_reference(&buf, NULL); + } +} + +void renderer_draw_textures(struct xorg_renderer *r, + int *pos, + int width, int height, + struct pipe_texture **textures, + int num_textures) +{ + struct pipe_context *pipe = r->pipe; + struct pipe_buffer *buf = 0; + + switch(num_textures) { + case 1: + buf = setup_vertex_data1(r, + pos[0], pos[1], /* src */ + pos[4], pos[5], /* dst */ + width, height, + textures[0]); + break; + case 2: + buf = setup_vertex_data2(r, + pos[0], pos[1], /* src */ + pos[2], pos[3], /* mask */ + pos[4], pos[5], /* dst */ + width, height, + textures[0], textures[1]); + break; + default: + debug_assert(!"Unsupported number of textures"); + break; + } + + if (buf) { + int num_attribs = 1; /*pos*/ + num_attribs += num_textures; + + util_draw_vertex_buffer(pipe, buf, 0, + PIPE_PRIM_TRIANGLE_FAN, + 4, /* verts */ + num_attribs); /* attribs/vert */ + + pipe_buffer_reference(&buf, NULL); + } +} diff --git a/src/gallium/state_trackers/xorg/xorg_renderer.h b/src/gallium/state_trackers/xorg/xorg_renderer.h new file mode 100644 index 00000000000..b6296d5fd6b --- /dev/null +++ b/src/gallium/state_trackers/xorg/xorg_renderer.h @@ -0,0 +1,53 @@ +#ifndef XORG_RENDERER_H +#define XORG_RENDERER_H + +#include "pipe/p_context.h" +#include "pipe/p_state.h" + +struct xorg_shaders; +struct exa_pixmap_priv; + +struct xorg_renderer { + struct pipe_context *pipe; + + struct cso_context *cso; + struct xorg_shaders *shaders; + + struct pipe_constant_buffer vs_const_buffer; + struct pipe_constant_buffer fs_const_buffer; + + /* we should combine these two */ + float vertices2[4][2][4]; + float vertices3[4][3][4]; +}; + +struct xorg_renderer *renderer_create(struct pipe_context *pipe); +void renderer_destroy(struct xorg_renderer *renderer); + +void renderer_bind_framebuffer(struct xorg_renderer *r, + struct exa_pixmap_priv *priv); +void renderer_bind_viewport(struct xorg_renderer *r, + struct exa_pixmap_priv *dst); +void renderer_bind_rasterizer(struct xorg_renderer *r); +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_solid_rect(struct xorg_renderer *r, + int x0, int y0, + int x1, int y1, + float *color); + +void renderer_draw_textures(struct xorg_renderer *r, + int *pos, + int width, int height, + struct pipe_texture **textures, + int num_textures); + + +#endif diff --git a/src/gallium/state_trackers/xorg/xorg_tracker.h b/src/gallium/state_trackers/xorg/xorg_tracker.h index db2f16f63ea..24e1a4928ee 100644 --- a/src/gallium/state_trackers/xorg/xorg_tracker.h +++ b/src/gallium/state_trackers/xorg/xorg_tracker.h @@ -51,6 +51,8 @@ #define DRV_ERROR(msg) xf86DrvMsg(pScrn->scrnIndex, X_ERROR, msg); +struct exa_context; + typedef struct { int lastInstance; @@ -92,7 +94,7 @@ typedef struct _modesettingRec boolean ds_depth_bits_last; /* exa */ - void *exa; + struct exa_context *exa; Bool noEvict; Bool debug_fallback; diff --git a/src/gallium/state_trackers/xorg/xorg_xv.c b/src/gallium/state_trackers/xorg/xorg_xv.c index 27d52700ec7..efac9275b26 100644 --- a/src/gallium/state_trackers/xorg/xorg_xv.c +++ b/src/gallium/state_trackers/xorg/xorg_xv.c @@ -4,10 +4,34 @@ #include #include +#include "xorg_exa.h" +#include "xorg_renderer.h" + +#include "pipe/p_screen.h" +#include "pipe/p_inlines.h" + /*XXX get these from pipe's texture limits */ #define IMAGE_MAX_WIDTH 2048 #define IMAGE_MAX_HEIGHT 2048 +#define RES_720P_X 1280 +#define RES_720P_Y 720 + + +/* The ITU-R BT.601 conversion matrix for SDTV. */ +static const float bt_601[] = { + 1.0, 0.0, 1.4075, + 1.0, -0.3455, -0.7169, + 1.0, 1.7790, 0. +}; + +/* The ITU-R BT.709 conversion matrix for HDTV. */ +static const float bt_709[] = { + 1.0, 0.0, 1.581, + 1.0, -0.1881, -0.47, + 1.0, 1.8629, 0. +}; + #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) static Atom xvBrightness, xvContrast; @@ -39,10 +63,17 @@ static XF86ImageRec Images[NUM_IMAGES] = { }; struct xorg_xv_port_priv { + struct xorg_renderer *r; + RegionRec clip; int brightness; int contrast; + + int current_set; + /* juggle two sets of seperate Y, U and V + * textures */ + struct pipe_texture *yuv[2][3]; }; @@ -106,6 +137,225 @@ query_best_size(ScrnInfoPtr pScrn, *p_h = drw_h; } +static INLINE struct pipe_texture * +create_component_texture(struct pipe_context *pipe, + int width, int height) +{ + struct pipe_screen *screen = pipe->screen; + struct pipe_texture *tex = 0; + struct pipe_texture templ; + + memset(&templ, 0, sizeof(templ)); + templ.target = PIPE_TEXTURE_2D; + templ.format = PIPE_FORMAT_L8_UNORM; + templ.last_level = 0; + templ.width[0] = width; + templ.height[0] = height; + templ.depth[0] = 1; + pf_get_block(PIPE_FORMAT_L8_UNORM, &templ.block); + templ.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER; + + tex = screen->texture_create(screen, &templ); + + return tex; +} + +static int +check_yuv_textures(struct xorg_xv_port_priv *priv, int width, int height) +{ + struct pipe_texture **dst = priv->yuv[priv->current_set]; + if (!dst[0] || + dst[0]->width[0] != width || + dst[0]->height[0] != height) { + pipe_texture_reference(&dst[0], NULL); + } + if (!dst[1] || + dst[1]->width[0] != width || + dst[1]->height[0] != height) { + pipe_texture_reference(&dst[1], NULL); + } + if (!dst[2] || + dst[2]->width[0] != width || + dst[2]->height[0] != height) { + pipe_texture_reference(&dst[2], NULL); + } + + if (!dst[0]) + dst[0] = create_component_texture(priv->r->pipe, width, height); + + if (!dst[1]) + dst[1] = create_component_texture(priv->r->pipe, width, height); + + if (!dst[2]) + dst[2] = create_component_texture(priv->r->pipe, width, height); + + if (!dst[0] || !dst[1] || !dst[2]) + return BadAlloc; + + return Success; +} + +static void +copy_packed_data(ScrnInfoPtr pScrn, + struct xorg_xv_port_priv *port, + int id, + unsigned char *buf, + int srcPitch, + int left, + int top, + int w, int h) +{ + unsigned char *src; + int i, j; + struct pipe_texture **dst = port->yuv[port->current_set]; + struct pipe_transfer *ytrans, *utrans, *vtrans; + struct pipe_screen *screen = port->r->pipe->screen; + char *ymap, *vmap, *umap; + unsigned char y1, y2, u, v; + int yidx, uidx, vidx; + + src = buf + (top * srcPitch) + (left << 1); + + ytrans = screen->get_tex_transfer(screen, dst[0], + 0, 0, 0, + PIPE_TRANSFER_WRITE, + left, top, w, h); + utrans = screen->get_tex_transfer(screen, dst[1], + 0, 0, 0, + PIPE_TRANSFER_WRITE, + left, top, w, h); + vtrans = screen->get_tex_transfer(screen, dst[2], + 0, 0, 0, + PIPE_TRANSFER_WRITE, + left, top, w, h); + + ymap = screen->transfer_map(screen, ytrans); + umap = screen->transfer_map(screen, utrans); + vmap = screen->transfer_map(screen, vtrans); + + switch (id) { + case FOURCC_YV12: { + int y_array_size = w * h; + for (i = 0; i < w; ++i) { + for (j = 0; i < h; ++j) { + /*XXX use src? */ + y1 = buf[j*w + i]; + u = buf[(j/2) * (w/2) + i/2 + y_array_size]; + v = buf[(j/2) * (w/2) + i/2 + y_array_size + y_array_size/4]; + ymap[yidx++] = y1; + umap[uidx++] = u; + vmap[vidx++] = v; + } + } + } + break; + case FOURCC_YUY2: + for (j = 0; j < h; ++j) { + for (i = 0; i < w; ++i) { + /* extracting two pixels */ + y1 = buf[0]; + u = buf[1]; + y2 = buf[2]; + v = buf[3]; + + ymap[yidx++] = y1; + ymap[yidx++] = y2; + umap[uidx++] = u; + umap[uidx++] = u; + vmap[vidx++] = v; + vmap[vidx++] = v; + } + } + break; + default: + debug_assert(!"Unsupported yuv format!"); + break; + } + + screen->transfer_unmap(screen, ytrans); + screen->transfer_unmap(screen, utrans); + screen->transfer_unmap(screen, vtrans); + screen->tex_transfer_destroy(ytrans); + screen->tex_transfer_destroy(utrans); + screen->tex_transfer_destroy(vtrans); +} + +static void +setup_video_constants(struct xorg_renderer *r, boolean hdtv) +{ + struct pipe_context *pipe = r->pipe; + const int param_bytes = 9 * sizeof(float); + struct pipe_constant_buffer *cbuf = &r->vs_const_buffer; + + pipe_buffer_reference(&cbuf->buffer, NULL); + cbuf->buffer = pipe_buffer_create(pipe->screen, 16, + PIPE_BUFFER_USAGE_CONSTANT, + param_bytes); + + if (cbuf->buffer) { + const float *video_constants = (hdtv) ? bt_709 : bt_601; + + pipe_buffer_write(pipe->screen, cbuf->buffer, + 0, param_bytes, video_constants); + } + pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, 0, cbuf); +} + +static int +display_video(ScrnInfoPtr pScrn, struct xorg_xv_port_priv *pPriv, int id, + RegionPtr dstRegion, + short width, short height, + int x1, int y1, int x2, int y2, + short src_w, short src_h, short drw_w, short drw_h, + PixmapPtr pPixmap) +{ + BoxPtr pbox; + int nbox; + int dxo, dyo; + Bool hdtv; + float tc0[2], tc1[2], tc2[2]; + + hdtv = ((src_w >= RES_720P_X) && (src_h >= RES_720P_Y)); + setup_video_constants(pPriv->r, hdtv); + + REGION_TRANSLATE(pScrn->pScreen, dstRegion, -pPixmap->screen_x, + -pPixmap->screen_y); + + dxo = dstRegion->extents.x1; + dyo = dstRegion->extents.y1; + + pbox = REGION_RECTS(dstRegion); + nbox = REGION_NUM_RECTS(dstRegion); + + while (nbox--) { + int box_x1 = pbox->x1; + int box_y1 = pbox->y1; + int box_x2 = pbox->x2; + int box_y2 = pbox->y2; + + tc0[0] = (double) (box_x1 - dxo) / (double) drw_w; /* u0 */ + tc0[1] = (double) (box_y1 - dyo) / (double) drw_h; /* v0 */ + tc1[0] = (double) (box_x2 - dxo) / (double) drw_w; /* u1 */ + tc1[1] = tc0[1]; + tc2[0] = tc0[0]; + tc2[1] = (double) (box_y2 - dyo) / (double) drw_h; /* v1 */ + +#if 0 + x = box_x1; + y = box_y1; + w = box_x2 - box_x1; + h = box_y2 - box_y1; + + pbox++; + draw_yuv(pScrn, x, y, w, h, &src, 1, FALSE, + 0, tc0, tc1, tc2, 1, + pPriv->conversionData); +#endif + } + DamageDamageRegion(&pPixmap->drawable, dstRegion); + return TRUE; +} + static int put_image(ScrnInfoPtr pScrn, short src_x, short src_y, @@ -117,7 +367,57 @@ put_image(ScrnInfoPtr pScrn, Bool sync, RegionPtr clipBoxes, pointer data, DrawablePtr pDraw) { - return 0; + struct xorg_xv_port_priv *pPriv = (struct xorg_xv_port_priv *) data; + ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex]; + PixmapPtr pPixmap; + INT32 x1, x2, y1, y2; + int srcPitch; + BoxRec dstBox; + int ret; + + /* Clip */ + x1 = src_x; + x2 = src_x + src_w; + y1 = src_y; + y2 = src_y + src_h; + + dstBox.x1 = drw_x; + dstBox.x2 = drw_x + drw_w; + dstBox.y1 = drw_y; + dstBox.y2 = drw_y + drw_h; + + if (!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes, + width, height)) + return Success; + + switch (id) { + case FOURCC_UYVY: + case FOURCC_YUY2: + default: + srcPitch = width << 1; + break; + } + + ret = check_yuv_textures(pPriv, width, height); + + if (ret) + return ret; + + copy_packed_data(pScrn, pPriv, id, buf, srcPitch, + src_x, src_y, width, height); + + if (pDraw->type == DRAWABLE_WINDOW) { + pPixmap = (*pScreen->GetWindowPixmap)((WindowPtr)pDraw); + } else { + pPixmap = (PixmapPtr)pDraw; + } + + display_video(pScrn, pPriv, id, clipBoxes, width, height, + x1, y1, x2, y2, + src_w, src_h, drw_w, drw_h, pPixmap); + + pPriv->current_set = (pPriv->current_set + 1) & 1; + return Success; } static int @@ -152,10 +452,8 @@ query_image_attributes(ScrnInfoPtr pScrn, } static struct xorg_xv_port_priv * -port_priv_create(ScreenPtr pScreen) +port_priv_create(struct xorg_renderer *r) { - /*ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];*/ - /*modesettingPtr ms = modesettingPTR(pScrn);*/ struct xorg_xv_port_priv *priv = NULL; priv = calloc(1, sizeof(struct xorg_xv_port_priv)); @@ -163,16 +461,20 @@ port_priv_create(ScreenPtr pScreen) if (!priv) return NULL; + priv->r = r; + REGION_NULL(pScreen, &priv->clip); + debug_assert(priv && priv->r); + return priv; } static XF86VideoAdaptorPtr xorg_setup_textured_adapter(ScreenPtr pScreen) { - /*ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];*/ - /*modesettingPtr ms = modesettingPTR(pScrn);*/ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + modesettingPtr ms = modesettingPTR(pScrn); XF86VideoAdaptorPtr adapt; XF86AttributePtr attrs; DevUnion *dev_unions; @@ -181,6 +483,9 @@ xorg_setup_textured_adapter(ScreenPtr pScreen) nattributes = NUM_TEXTURED_ATTRIBUTES; + debug_assert(ms->exa); + debug_assert(ms->exa->renderer); + adapt = calloc(1, sizeof(XF86VideoAdaptorRec)); dev_unions = calloc(nports, sizeof(DevUnion)); attrs = calloc(nattributes, sizeof(XF86AttributeRec)); @@ -218,7 +523,7 @@ xorg_setup_textured_adapter(ScreenPtr pScreen) for (i = 0; i < nports; i++) { struct xorg_xv_port_priv *priv = - port_priv_create(pScreen); + port_priv_create(ms->exa->renderer); adapt->pPortPrivates[i].ptr = (pointer) (priv); adapt->nPorts++; -- cgit v1.2.3