#include "xorg_exa.h"
#include "xorg_renderer.h"
+#include "xorg_exa_tgsi.h"
+
+#include "cso_cache/cso_context.h"
#include "pipe/p_screen.h"
#include "pipe/p_inlines.h"
/* The ITU-R BT.601 conversion matrix for SDTV. */
+/* original, matrix, but we transpose it to
+ * make the shader easier
static const float bt_601[] = {
- 1.0, 0.0, 1.4075, 0,
+ 1.0, 0.0, 1.4075, ,
1.0, -0.3455, -0.7169, 0,
1.0, 1.7790, 0., 0,
+};*/
+static const float bt_601[] = {
+ 1.0, 1.0, 1.0, 0.5,
+ 0.0, -0.3455, 1.7790, 0,
+ 1.4075, -0.7169, 0., 0,
};
/* The ITU-R BT.709 conversion matrix for HDTV. */
+/* original, but we transpose to make the conversion
+ * in the shader easier
static const float bt_709[] = {
1.0, 0.0, 1.581, 0,
1.0, -0.1881, -0.47, 0,
1.0, 1.8629, 0., 0,
+};*/
+static const float bt_709[] = {
+ 1.0, 1.0, 1.0, 0.5,
+ 0.0, -0.1881, 1.8629, 0,
+ 1.581,-0.47 , 0.0, 0,
};
#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
char *ymap, *vmap, *umap;
unsigned char y1, y2, u, v;
int yidx, uidx, vidx;
+ int y_array_size = w * h;
src = buf + (top * srcPitch) + (left << 1);
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);
+ ymap = (char*)screen->transfer_map(screen, ytrans);
+ umap = (char*)screen->transfer_map(screen, utrans);
+ vmap = (char*)screen->transfer_map(screen, vtrans);
+
+ yidx = uidx = vidx = 0;
switch (id) {
case FOURCC_YV12: {
- int y_array_size = w * h;
for (i = 0; i < w; ++i) {
- for (j = 0; i < h; ++j) {
+ for (j = 0; j < h; ++j) {
/*XXX use src? */
y1 = buf[j*w + i];
u = buf[(j/2) * (w/2) + i/2 + y_array_size];
}
}
break;
+ case FOURCC_UYVY:
+ for (i = 0; i < y_array_size; i +=2 ) {
+ /* extracting two pixels */
+ u = buf[0];
+ y1 = buf[1];
+ v = buf[2];
+ y2 = buf[3];
+ buf += 4;
+
+ ymap[yidx++] = y1;
+ ymap[yidx++] = y2;
+ umap[uidx++] = u;
+ umap[uidx++] = u;
+ vmap[vidx++] = v;
+ 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;
- }
+ for (i = 0; i < y_array_size; i +=2 ) {
+ /* extracting two pixels */
+ y1 = buf[0];
+ u = buf[1];
+ y2 = buf[2];
+ v = buf[3];
+
+ buf += 4;
+
+ ymap[yidx++] = y1;
+ ymap[yidx++] = y2;
+ umap[uidx++] = u;
+ umap[uidx++] = u;
+ vmap[vidx++] = v;
+ vmap[vidx++] = v;
}
break;
default:
screen->tex_transfer_destroy(vtrans);
}
+
static void
-setup_video_constants(struct xorg_renderer *r, boolean hdtv)
+setup_fs_video_constants(struct xorg_renderer *r, boolean hdtv)
{
- struct pipe_context *pipe = r->pipe;
const int param_bytes = 12 * sizeof(float);
- struct pipe_constant_buffer *cbuf = &r->fs_const_buffer;
+ const float *video_constants = (hdtv) ? bt_709 : bt_601;
- pipe_buffer_reference(&cbuf->buffer, NULL);
- cbuf->buffer = pipe_buffer_create(pipe->screen, 16,
- PIPE_BUFFER_USAGE_CONSTANT,
- param_bytes);
+ renderer_set_constants(r, PIPE_SHADER_FRAGMENT,
+ video_constants, param_bytes);
+}
+
+static void
+draw_yuv(struct xorg_xv_port_priv *port,
+ int src_x, int src_y, int src_w, int src_h,
+ int dst_x, int dst_y, int dst_w, int dst_h)
+{
+ struct pipe_texture **textures = port->yuv[port->current_set];
- if (cbuf->buffer) {
- const float *video_constants = (hdtv) ? bt_709 : bt_601;
+ renderer_draw_yuv(port->r,
+ src_x, src_y, src_w, src_h,
+ dst_x, dst_y, dst_w, dst_h,
+ textures);
+}
+
+static void
+bind_blend_state(struct xorg_xv_port_priv *port)
+{
+ struct pipe_blend_state blend;
- pipe_buffer_write(pipe->screen, cbuf->buffer,
- 0, param_bytes, video_constants);
+ memset(&blend, 0, sizeof(struct pipe_blend_state));
+ blend.blend_enable = 1;
+ blend.colormask |= PIPE_MASK_RGBA;
+
+ /* porter&duff src */
+ 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;
+
+ cso_set_blend(port->r->cso, &blend);
+}
+
+
+static void
+bind_shaders(struct xorg_xv_port_priv *port)
+{
+ unsigned vs_traits = 0, fs_traits = 0;
+ struct xorg_shader shader;
+
+ vs_traits |= VS_YUV;
+ fs_traits |= FS_YUV;
+
+ shader = xorg_shaders_get(port->r->shaders, vs_traits, fs_traits);
+ cso_set_vertex_shader_handle(port->r->cso, shader.vs);
+ cso_set_fragment_shader_handle(port->r->cso, shader.fs);
+}
+
+static INLINE void
+conditional_flush(struct pipe_context *pipe, struct pipe_texture **tex,
+ int num)
+{
+ int i;
+ for (i = 0; i < num; ++i) {
+ if (tex[i] && pipe->is_texture_referenced(pipe, tex[i], 0, 0) &
+ PIPE_REFERENCED_FOR_WRITE) {
+ pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
+ return;
+ }
}
- pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, 0, cbuf);
+}
+
+static void
+bind_samplers(struct xorg_xv_port_priv *port)
+{
+ struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
+ struct pipe_sampler_state sampler;
+ struct pipe_texture **dst = port->yuv[port->current_set];
+
+ memset(&sampler, 0, sizeof(struct pipe_sampler_state));
+
+ conditional_flush(port->r->pipe, dst, 3);
+
+ sampler.wrap_s = PIPE_TEX_WRAP_CLAMP;
+ sampler.wrap_t = PIPE_TEX_WRAP_CLAMP;
+ sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR;
+ sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR;
+ sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST;
+ sampler.normalized_coords = 1;
+
+ samplers[0] = &sampler;
+ samplers[1] = &sampler;
+ samplers[2] = &sampler;
+
+
+ cso_set_samplers(port->r->cso, 3,
+ (const struct pipe_sampler_state **)samplers);
+ cso_set_sampler_textures(port->r->cso, 3,
+ dst);
}
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,
+ int src_x, int src_y, int src_w, int src_h,
+ int dstX, int dstY, int dst_w, int dst_h,
PixmapPtr pPixmap)
{
+ modesettingPtr ms = modesettingPTR(pScrn);
BoxPtr pbox;
int nbox;
int dxo, dyo;
Bool hdtv;
- float tc0[2], tc1[2], tc2[2];
+ int x, y, w, h;
+ struct exa_pixmap_priv *dst = exaGetPixmapDriverPrivate(pPixmap);
+ struct pipe_surface *dst_surf = xorg_gpu_surface(pPriv->r->pipe->screen, dst);
+
+ if (dst && !dst->tex) {
+ xorg_exa_set_shared_usage(pPixmap);
+ pScrn->pScreen->ModifyPixmapHeader(pPixmap, 0, 0, 0, 0, 0, NULL);
+ }
+
+ if (!dst || !dst->tex)
+ XORG_FALLBACK("Xv destination %s", !dst ? "!dst" : "!dst->tex");
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);
pbox = REGION_RECTS(dstRegion);
nbox = REGION_NUM_RECTS(dstRegion);
+ renderer_bind_destination(pPriv->r, dst_surf);
+ bind_blend_state(pPriv);
+ bind_shaders(pPriv);
+ bind_samplers(pPriv);
+ setup_fs_video_constants(pPriv->r, hdtv);
+
+ exaMoveInPixmap(pPixmap);
+ DamageDamageRegion(&pPixmap->drawable, dstRegion);
+
while (nbox--) {
int box_x1 = pbox->x1;
int box_y1 = pbox->y1;
int box_x2 = pbox->x2;
int box_y2 = pbox->y2;
+ float diff_x = (float)src_w / (float)dst_w;
+ float diff_y = (float)src_h / (float)dst_h;
+ int offset_x = box_x1 - dstX + pPixmap->screen_x;
+ int offset_y = box_y1 - dstY + pPixmap->screen_y;
+ int offset_w;
+ int offset_h;
- 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;
+ offset_w = dst_w - w;
+ offset_h = dst_h - h;
+
+ draw_yuv(pPriv, src_x + offset_x*diff_x, src_y + offset_y*diff_y,
+ src_w - offset_w*diff_x, src_h - offset_h*diff_x,
+ x, y, w, h);
+
pbox++;
- draw_yuv(pScrn, x, y, w, h, &src, 1, FALSE,
- 0, tc0, tc1, tc2, 1,
- pPriv->conversionData);
-#endif
}
- DamageDamageRegion(&pPixmap->drawable, dstRegion);
+ DamageRegionProcessPending(&pPixmap->drawable);
+
return TRUE;
}
pPixmap = (PixmapPtr)pDraw;
}
- display_video(pScrn, pPriv, id, clipBoxes, width, height,
- x1, y1, x2, y2,
- src_w, src_h, drw_w, drw_h, pPixmap);
+ display_video(pScrn, pPriv, id, clipBoxes,
+ src_x, src_y, src_w, src_h,
+ drw_x, drw_y,
+ drw_w, drw_h, pPixmap);
pPriv->current_set = (pPriv->current_set + 1) & 1;
return Success;
}
void
-xorg_init_video(ScreenPtr pScreen)
+xorg_xv_init(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
/*modesettingPtr ms = modesettingPTR(pScrn);*/