1 #include "xorg_tracker.h"
4 #include <X11/extensions/Xv.h>
8 #include "xorg_renderer.h"
9 #include "xorg_exa_tgsi.h"
11 #include "cso_cache/cso_context.h"
13 #include "pipe/p_screen.h"
14 #include "pipe/p_inlines.h"
16 /*XXX get these from pipe's texture limits */
17 #define IMAGE_MAX_WIDTH 2048
18 #define IMAGE_MAX_HEIGHT 2048
20 #define RES_720P_X 1280
21 #define RES_720P_Y 720
24 /* The ITU-R BT.601 conversion matrix for SDTV. */
25 static const float bt_601
[] = {
27 1.0, -0.3455, -0.7169, 0,
31 /* The ITU-R BT.709 conversion matrix for HDTV. */
32 static const float bt_709
[] = {
34 1.0, -0.1881, -0.47, 0,
38 #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
40 static Atom xvBrightness
, xvContrast
;
42 #define NUM_TEXTURED_ATTRIBUTES 2
43 static XF86AttributeRec TexturedAttributes
[NUM_TEXTURED_ATTRIBUTES
] = {
44 {XvSettable
| XvGettable
, -128, 127, "XV_BRIGHTNESS"},
45 {XvSettable
| XvGettable
, 0, 255, "XV_CONTRAST"}
49 static XF86VideoFormatRec Formats
[NUM_FORMATS
] = {
50 {15, TrueColor
}, {16, TrueColor
}, {24, TrueColor
}
53 static XF86VideoEncodingRec DummyEncoding
[1] = {
57 IMAGE_MAX_WIDTH
, IMAGE_MAX_HEIGHT
,
63 static XF86ImageRec Images
[NUM_IMAGES
] = {
68 struct xorg_xv_port_priv
{
69 struct xorg_renderer
*r
;
77 /* juggle two sets of seperate Y, U and V
79 struct pipe_texture
*yuv
[2][3];
84 stop_video(ScrnInfoPtr pScrn
, pointer data
, Bool shutdown
)
86 struct xorg_xv_port_priv
*priv
= (struct xorg_xv_port_priv
*)data
;
88 REGION_EMPTY(pScrn
->pScreen
, &priv
->clip
);
92 set_port_attribute(ScrnInfoPtr pScrn
,
93 Atom attribute
, INT32 value
, pointer data
)
95 struct xorg_xv_port_priv
*priv
= (struct xorg_xv_port_priv
*)data
;
97 if (attribute
== xvBrightness
) {
98 if ((value
< -128) || (value
> 127))
100 priv
->brightness
= value
;
101 } else if (attribute
== xvContrast
) {
102 if ((value
< 0) || (value
> 255))
104 priv
->contrast
= value
;
112 get_port_attribute(ScrnInfoPtr pScrn
,
113 Atom attribute
, INT32
* value
, pointer data
)
115 struct xorg_xv_port_priv
*priv
= (struct xorg_xv_port_priv
*)data
;
117 if (attribute
== xvBrightness
)
118 *value
= priv
->brightness
;
119 else if (attribute
== xvContrast
)
120 *value
= priv
->contrast
;
128 query_best_size(ScrnInfoPtr pScrn
,
130 short vid_w
, short vid_h
,
131 short drw_w
, short drw_h
,
132 unsigned int *p_w
, unsigned int *p_h
, pointer data
)
134 if (vid_w
> (drw_w
<< 1))
136 if (vid_h
> (drw_h
<< 1))
143 static INLINE
struct pipe_texture
*
144 create_component_texture(struct pipe_context
*pipe
,
145 int width
, int height
)
147 struct pipe_screen
*screen
= pipe
->screen
;
148 struct pipe_texture
*tex
= 0;
149 struct pipe_texture templ
;
151 memset(&templ
, 0, sizeof(templ
));
152 templ
.target
= PIPE_TEXTURE_2D
;
153 templ
.format
= PIPE_FORMAT_L8_UNORM
;
154 templ
.last_level
= 0;
155 templ
.width
[0] = width
;
156 templ
.height
[0] = height
;
158 pf_get_block(PIPE_FORMAT_L8_UNORM
, &templ
.block
);
159 templ
.tex_usage
= PIPE_TEXTURE_USAGE_SAMPLER
;
161 tex
= screen
->texture_create(screen
, &templ
);
167 check_yuv_textures(struct xorg_xv_port_priv
*priv
, int width
, int height
)
169 struct pipe_texture
**dst
= priv
->yuv
[priv
->current_set
];
171 dst
[0]->width
[0] != width
||
172 dst
[0]->height
[0] != height
) {
173 pipe_texture_reference(&dst
[0], NULL
);
176 dst
[1]->width
[0] != width
||
177 dst
[1]->height
[0] != height
) {
178 pipe_texture_reference(&dst
[1], NULL
);
181 dst
[2]->width
[0] != width
||
182 dst
[2]->height
[0] != height
) {
183 pipe_texture_reference(&dst
[2], NULL
);
187 dst
[0] = create_component_texture(priv
->r
->pipe
, width
, height
);
190 dst
[1] = create_component_texture(priv
->r
->pipe
, width
, height
);
193 dst
[2] = create_component_texture(priv
->r
->pipe
, width
, height
);
195 if (!dst
[0] || !dst
[1] || !dst
[2])
202 copy_packed_data(ScrnInfoPtr pScrn
,
203 struct xorg_xv_port_priv
*port
,
213 struct pipe_texture
**dst
= port
->yuv
[port
->current_set
];
214 struct pipe_transfer
*ytrans
, *utrans
, *vtrans
;
215 struct pipe_screen
*screen
= port
->r
->pipe
->screen
;
216 char *ymap
, *vmap
, *umap
;
217 unsigned char y1
, y2
, u
, v
;
218 int yidx
, uidx
, vidx
;
219 int y_array_size
= w
* h
;
221 src
= buf
+ (top
* srcPitch
) + (left
<< 1);
223 ytrans
= screen
->get_tex_transfer(screen
, dst
[0],
227 utrans
= screen
->get_tex_transfer(screen
, dst
[1],
231 vtrans
= screen
->get_tex_transfer(screen
, dst
[2],
236 ymap
= (char*)screen
->transfer_map(screen
, ytrans
);
237 umap
= (char*)screen
->transfer_map(screen
, utrans
);
238 vmap
= (char*)screen
->transfer_map(screen
, vtrans
);
240 yidx
= uidx
= vidx
= 0;
244 for (i
= 0; i
< w
; ++i
) {
245 for (j
= 0; i
< h
; ++j
) {
248 u
= buf
[(j
/2) * (w
/2) + i
/2 + y_array_size
];
249 v
= buf
[(j
/2) * (w
/2) + i
/2 + y_array_size
+ y_array_size
/4];
258 for (i
= 0; i
< y_array_size
; i
+=2 ) {
259 /* extracting two pixels */
275 for (i
= 0; i
< y_array_size
; i
+=2 ) {
276 /* extracting two pixels */
293 debug_assert(!"Unsupported yuv format!");
297 screen
->transfer_unmap(screen
, ytrans
);
298 screen
->transfer_unmap(screen
, utrans
);
299 screen
->transfer_unmap(screen
, vtrans
);
300 screen
->tex_transfer_destroy(ytrans
);
301 screen
->tex_transfer_destroy(utrans
);
302 screen
->tex_transfer_destroy(vtrans
);
307 setup_vs_video_constants(struct xorg_renderer
*r
, struct exa_pixmap_priv
*dst
)
309 int width
= dst
->tex
->width
[0];
310 int height
= dst
->tex
->height
[0];
311 const int param_bytes
= 8 * sizeof(float);
312 float vs_consts
[8] = {
313 2.f
/width
, 2.f
/height
, 1, 1,
317 renderer_set_constants(r
, PIPE_SHADER_VERTEX
,
318 vs_consts
, param_bytes
);
322 setup_fs_video_constants(struct xorg_renderer
*r
, boolean hdtv
)
324 const int param_bytes
= 12 * sizeof(float);
325 const float *video_constants
= (hdtv
) ? bt_709
: bt_601
;
327 renderer_set_constants(r
, PIPE_SHADER_FRAGMENT
,
328 video_constants
, param_bytes
);
332 draw_yuv(struct xorg_xv_port_priv
*port
, int src_x
, int src_y
,
333 int dst_x
, int dst_y
,
336 int pos
[4] = {src_x
, src_y
,
338 struct pipe_texture
**textures
= port
->yuv
[port
->current_set
];
340 renderer_draw_textures(port
->r
,
343 3, /*bound samplers/textures */
344 NULL
, NULL
/* no transformations */);
348 bind_blend_state(struct xorg_xv_port_priv
*port
)
350 struct pipe_blend_state blend
;
352 memset(&blend
, 0, sizeof(struct pipe_blend_state
));
353 blend
.blend_enable
= 1;
354 blend
.colormask
|= PIPE_MASK_RGBA
;
356 /* porter&duff src */
357 blend
.rgb_src_factor
= PIPE_BLENDFACTOR_ONE
;
358 blend
.alpha_src_factor
= PIPE_BLENDFACTOR_ONE
;
359 blend
.rgb_dst_factor
= PIPE_BLENDFACTOR_ZERO
;
360 blend
.alpha_dst_factor
= PIPE_BLENDFACTOR_ZERO
;
362 cso_set_blend(port
->r
->cso
, &blend
);
367 bind_shaders(struct xorg_xv_port_priv
*port
)
369 unsigned vs_traits
= 0, fs_traits
= 0;
370 struct xorg_shader shader
;
375 shader
= xorg_shaders_get(port
->r
->shaders
, vs_traits
, fs_traits
);
376 cso_set_vertex_shader_handle(port
->r
->cso
, shader
.vs
);
377 cso_set_fragment_shader_handle(port
->r
->cso
, shader
.fs
);
381 conditional_flush(struct pipe_context
*pipe
, struct pipe_texture
**tex
,
385 for (i
= 0; i
< num
; ++i
) {
386 if (tex
[i
] && pipe
->is_texture_referenced(pipe
, tex
[i
], 0, 0) &
387 PIPE_REFERENCED_FOR_WRITE
) {
388 pipe
->flush(pipe
, PIPE_FLUSH_RENDER_CACHE
, NULL
);
395 bind_samplers(struct xorg_xv_port_priv
*port
)
397 struct pipe_sampler_state
*samplers
[PIPE_MAX_SAMPLERS
];
398 struct pipe_sampler_state sampler
;
399 struct pipe_texture
**dst
= port
->yuv
[port
->current_set
];
401 memset(&sampler
, 0, sizeof(struct pipe_sampler_state
));
403 conditional_flush(port
->r
->pipe
, dst
, 3);
405 sampler
.wrap_s
= PIPE_TEX_WRAP_CLAMP
;
406 sampler
.wrap_t
= PIPE_TEX_WRAP_CLAMP
;
407 sampler
.min_img_filter
= PIPE_TEX_FILTER_LINEAR
;
408 sampler
.mag_img_filter
= PIPE_TEX_FILTER_LINEAR
;
409 sampler
.min_mip_filter
= PIPE_TEX_MIPFILTER_NEAREST
;
410 sampler
.normalized_coords
= 1;
412 samplers
[0] = &sampler
;
413 samplers
[1] = &sampler
;
414 samplers
[2] = &sampler
;
417 cso_set_samplers(port
->r
->cso
, 3,
418 (const struct pipe_sampler_state
**)samplers
);
419 cso_set_sampler_textures(port
->r
->cso
, 3,
424 display_video(ScrnInfoPtr pScrn
, struct xorg_xv_port_priv
*pPriv
, int id
,
426 int src_x
, int src_y
, int src_w
, int src_h
,
428 short width
, short height
,
431 modesettingPtr ms
= modesettingPTR(pScrn
);
437 struct exa_pixmap_priv
*dst
= exaGetPixmapDriverPrivate(pPixmap
);
439 if (!dst
|| !dst
->tex
)
440 XORG_FALLBACK("Xv destination %s", !dst
? "!dst" : "!dst->tex");
442 hdtv
= ((src_w
>= RES_720P_X
) && (src_h
>= RES_720P_Y
));
444 REGION_TRANSLATE(pScrn
->pScreen
, dstRegion
, -pPixmap
->screen_x
,
447 dxo
= dstRegion
->extents
.x1
;
448 dyo
= dstRegion
->extents
.y1
;
450 pbox
= REGION_RECTS(dstRegion
);
451 nbox
= REGION_NUM_RECTS(dstRegion
);
453 renderer_bind_framebuffer(pPriv
->r
, dst
);
454 renderer_bind_viewport(pPriv
->r
, dst
);
455 bind_blend_state(pPriv
);
456 renderer_bind_rasterizer(pPriv
->r
);
458 bind_samplers(pPriv
);
459 setup_vs_video_constants(pPriv
->r
, dst
);
460 setup_fs_video_constants(pPriv
->r
, hdtv
);
463 int box_x1
= pbox
->x1
;
464 int box_y1
= pbox
->y1
;
465 int box_x2
= pbox
->x2
;
466 int box_y2
= pbox
->y2
;
473 draw_yuv(pPriv
, x
, y
, x
, y
, w
, h
);
477 DamageDamageRegion(&pPixmap
->drawable
, dstRegion
);
483 put_image(ScrnInfoPtr pScrn
,
484 short src_x
, short src_y
,
485 short drw_x
, short drw_y
,
486 short src_w
, short src_h
,
487 short drw_w
, short drw_h
,
488 int id
, unsigned char *buf
,
489 short width
, short height
,
490 Bool sync
, RegionPtr clipBoxes
, pointer data
,
493 struct xorg_xv_port_priv
*pPriv
= (struct xorg_xv_port_priv
*) data
;
494 ScreenPtr pScreen
= screenInfo
.screens
[pScrn
->scrnIndex
];
496 INT32 x1
, x2
, y1
, y2
;
508 dstBox
.x2
= drw_x
+ drw_w
;
510 dstBox
.y2
= drw_y
+ drw_h
;
512 if (!xf86XVClipVideoHelper(&dstBox
, &x1
, &x2
, &y1
, &y2
, clipBoxes
,
520 srcPitch
= width
<< 1;
524 ret
= check_yuv_textures(pPriv
, width
, height
);
529 copy_packed_data(pScrn
, pPriv
, id
, buf
, srcPitch
,
530 src_x
, src_y
, width
, height
);
532 if (pDraw
->type
== DRAWABLE_WINDOW
) {
533 pPixmap
= (*pScreen
->GetWindowPixmap
)((WindowPtr
)pDraw
);
535 pPixmap
= (PixmapPtr
)pDraw
;
538 display_video(pScrn
, pPriv
, id
, clipBoxes
,
539 src_x
, src_y
, src_w
, src_h
,
541 drw_w
, drw_h
, pPixmap
);
543 pPriv
->current_set
= (pPriv
->current_set
+ 1) & 1;
548 query_image_attributes(ScrnInfoPtr pScrn
,
550 unsigned short *w
, unsigned short *h
,
551 int *pitches
, int *offsets
)
555 if (*w
> IMAGE_MAX_WIDTH
)
556 *w
= IMAGE_MAX_WIDTH
;
557 if (*h
> IMAGE_MAX_HEIGHT
)
558 *h
= IMAGE_MAX_HEIGHT
;
578 static struct xorg_xv_port_priv
*
579 port_priv_create(struct xorg_renderer
*r
)
581 struct xorg_xv_port_priv
*priv
= NULL
;
583 priv
= calloc(1, sizeof(struct xorg_xv_port_priv
));
590 REGION_NULL(pScreen
, &priv
->clip
);
592 debug_assert(priv
&& priv
->r
);
597 static XF86VideoAdaptorPtr
598 xorg_setup_textured_adapter(ScreenPtr pScreen
)
600 ScrnInfoPtr pScrn
= xf86Screens
[pScreen
->myNum
];
601 modesettingPtr ms
= modesettingPTR(pScrn
);
602 XF86VideoAdaptorPtr adapt
;
603 XF86AttributePtr attrs
;
604 DevUnion
*dev_unions
;
608 nattributes
= NUM_TEXTURED_ATTRIBUTES
;
610 debug_assert(ms
->exa
);
611 debug_assert(ms
->exa
->renderer
);
613 adapt
= calloc(1, sizeof(XF86VideoAdaptorRec
));
614 dev_unions
= calloc(nports
, sizeof(DevUnion
));
615 attrs
= calloc(nattributes
, sizeof(XF86AttributeRec
));
616 if (adapt
== NULL
|| dev_unions
== NULL
|| attrs
== NULL
) {
623 adapt
->type
= XvWindowMask
| XvInputMask
| XvImageMask
;
625 adapt
->name
= "Gallium3D Textured Video";
626 adapt
->nEncodings
= 1;
627 adapt
->pEncodings
= DummyEncoding
;
628 adapt
->nFormats
= NUM_FORMATS
;
629 adapt
->pFormats
= Formats
;
631 adapt
->pPortPrivates
= dev_unions
;
632 adapt
->nAttributes
= nattributes
;
633 adapt
->pAttributes
= attrs
;
634 memcpy(attrs
, TexturedAttributes
, nattributes
* sizeof(XF86AttributeRec
));
635 adapt
->nImages
= NUM_IMAGES
;
636 adapt
->pImages
= Images
;
637 adapt
->PutVideo
= NULL
;
638 adapt
->PutStill
= NULL
;
639 adapt
->GetVideo
= NULL
;
640 adapt
->GetStill
= NULL
;
641 adapt
->StopVideo
= stop_video
;
642 adapt
->SetPortAttribute
= set_port_attribute
;
643 adapt
->GetPortAttribute
= get_port_attribute
;
644 adapt
->QueryBestSize
= query_best_size
;
645 adapt
->PutImage
= put_image
;
646 adapt
->QueryImageAttributes
= query_image_attributes
;
648 for (i
= 0; i
< nports
; i
++) {
649 struct xorg_xv_port_priv
*priv
=
650 port_priv_create(ms
->exa
->renderer
);
652 adapt
->pPortPrivates
[i
].ptr
= (pointer
) (priv
);
660 xorg_init_video(ScreenPtr pScreen
)
662 ScrnInfoPtr pScrn
= xf86Screens
[pScreen
->myNum
];
663 /*modesettingPtr ms = modesettingPTR(pScrn);*/
664 XF86VideoAdaptorPtr
*adaptors
, *new_adaptors
= NULL
;
665 XF86VideoAdaptorPtr textured_adapter
;
668 num_adaptors
= xf86XVListGenericAdaptors(pScrn
, &adaptors
);
669 new_adaptors
= malloc((num_adaptors
+ 1) * sizeof(XF86VideoAdaptorPtr
*));
670 if (new_adaptors
== NULL
)
673 memcpy(new_adaptors
, adaptors
, num_adaptors
* sizeof(XF86VideoAdaptorPtr
));
674 adaptors
= new_adaptors
;
676 /* Add the adaptors supported by our hardware. First, set up the atoms
677 * that will be used by both output adaptors.
679 xvBrightness
= MAKE_ATOM("XV_BRIGHTNESS");
680 xvContrast
= MAKE_ATOM("XV_CONTRAST");
682 textured_adapter
= xorg_setup_textured_adapter(pScreen
);
684 debug_assert(textured_adapter
);
686 if (textured_adapter
) {
687 adaptors
[num_adaptors
++] = textured_adapter
;
691 xf86XVScreenInit(pScreen
, adaptors
, num_adaptors
);
693 xf86DrvMsg(pScrn
->scrnIndex
, X_WARNING
,
694 "Disabling Xv because no adaptors could be initialized.\n");