1 #include "xorg_tracker.h"
4 #include <X11/extensions/Xv.h>
8 #include "xorg_renderer.h"
10 #include "pipe/p_screen.h"
11 #include "pipe/p_inlines.h"
13 /*XXX get these from pipe's texture limits */
14 #define IMAGE_MAX_WIDTH 2048
15 #define IMAGE_MAX_HEIGHT 2048
17 #define RES_720P_X 1280
18 #define RES_720P_Y 720
21 /* The ITU-R BT.601 conversion matrix for SDTV. */
22 static const float bt_601
[] = {
24 1.0, -0.3455, -0.7169,
28 /* The ITU-R BT.709 conversion matrix for HDTV. */
29 static const float bt_709
[] = {
35 #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
37 static Atom xvBrightness
, xvContrast
;
39 #define NUM_TEXTURED_ATTRIBUTES 2
40 static XF86AttributeRec TexturedAttributes
[NUM_TEXTURED_ATTRIBUTES
] = {
41 {XvSettable
| XvGettable
, -128, 127, "XV_BRIGHTNESS"},
42 {XvSettable
| XvGettable
, 0, 255, "XV_CONTRAST"}
46 static XF86VideoFormatRec Formats
[NUM_FORMATS
] = {
47 {15, TrueColor
}, {16, TrueColor
}, {24, TrueColor
}
50 static XF86VideoEncodingRec DummyEncoding
[1] = {
54 IMAGE_MAX_WIDTH
, IMAGE_MAX_HEIGHT
,
60 static XF86ImageRec Images
[NUM_IMAGES
] = {
65 struct xorg_xv_port_priv
{
66 struct xorg_renderer
*r
;
74 /* juggle two sets of seperate Y, U and V
76 struct pipe_texture
*yuv
[2][3];
81 stop_video(ScrnInfoPtr pScrn
, pointer data
, Bool shutdown
)
83 struct xorg_xv_port_priv
*priv
= (struct xorg_xv_port_priv
*)data
;
85 REGION_EMPTY(pScrn
->pScreen
, &priv
->clip
);
89 set_port_attribute(ScrnInfoPtr pScrn
,
90 Atom attribute
, INT32 value
, pointer data
)
92 struct xorg_xv_port_priv
*priv
= (struct xorg_xv_port_priv
*)data
;
94 if (attribute
== xvBrightness
) {
95 if ((value
< -128) || (value
> 127))
97 priv
->brightness
= value
;
98 } else if (attribute
== xvContrast
) {
99 if ((value
< 0) || (value
> 255))
101 priv
->contrast
= value
;
109 get_port_attribute(ScrnInfoPtr pScrn
,
110 Atom attribute
, INT32
* value
, pointer data
)
112 struct xorg_xv_port_priv
*priv
= (struct xorg_xv_port_priv
*)data
;
114 if (attribute
== xvBrightness
)
115 *value
= priv
->brightness
;
116 else if (attribute
== xvContrast
)
117 *value
= priv
->contrast
;
125 query_best_size(ScrnInfoPtr pScrn
,
127 short vid_w
, short vid_h
,
128 short drw_w
, short drw_h
,
129 unsigned int *p_w
, unsigned int *p_h
, pointer data
)
131 if (vid_w
> (drw_w
<< 1))
133 if (vid_h
> (drw_h
<< 1))
140 static INLINE
struct pipe_texture
*
141 create_component_texture(struct pipe_context
*pipe
,
142 int width
, int height
)
144 struct pipe_screen
*screen
= pipe
->screen
;
145 struct pipe_texture
*tex
= 0;
146 struct pipe_texture templ
;
148 memset(&templ
, 0, sizeof(templ
));
149 templ
.target
= PIPE_TEXTURE_2D
;
150 templ
.format
= PIPE_FORMAT_L8_UNORM
;
151 templ
.last_level
= 0;
152 templ
.width
[0] = width
;
153 templ
.height
[0] = height
;
155 pf_get_block(PIPE_FORMAT_L8_UNORM
, &templ
.block
);
156 templ
.tex_usage
= PIPE_TEXTURE_USAGE_SAMPLER
;
158 tex
= screen
->texture_create(screen
, &templ
);
164 check_yuv_textures(struct xorg_xv_port_priv
*priv
, int width
, int height
)
166 struct pipe_texture
**dst
= priv
->yuv
[priv
->current_set
];
168 dst
[0]->width
[0] != width
||
169 dst
[0]->height
[0] != height
) {
170 pipe_texture_reference(&dst
[0], NULL
);
173 dst
[1]->width
[0] != width
||
174 dst
[1]->height
[0] != height
) {
175 pipe_texture_reference(&dst
[1], NULL
);
178 dst
[2]->width
[0] != width
||
179 dst
[2]->height
[0] != height
) {
180 pipe_texture_reference(&dst
[2], NULL
);
184 dst
[0] = create_component_texture(priv
->r
->pipe
, width
, height
);
187 dst
[1] = create_component_texture(priv
->r
->pipe
, width
, height
);
190 dst
[2] = create_component_texture(priv
->r
->pipe
, width
, height
);
192 if (!dst
[0] || !dst
[1] || !dst
[2])
199 copy_packed_data(ScrnInfoPtr pScrn
,
200 struct xorg_xv_port_priv
*port
,
210 struct pipe_texture
**dst
= port
->yuv
[port
->current_set
];
211 struct pipe_transfer
*ytrans
, *utrans
, *vtrans
;
212 struct pipe_screen
*screen
= port
->r
->pipe
->screen
;
213 char *ymap
, *vmap
, *umap
;
214 unsigned char y1
, y2
, u
, v
;
215 int yidx
, uidx
, vidx
;
217 src
= buf
+ (top
* srcPitch
) + (left
<< 1);
219 ytrans
= screen
->get_tex_transfer(screen
, dst
[0],
223 utrans
= screen
->get_tex_transfer(screen
, dst
[1],
227 vtrans
= screen
->get_tex_transfer(screen
, dst
[2],
232 ymap
= screen
->transfer_map(screen
, ytrans
);
233 umap
= screen
->transfer_map(screen
, utrans
);
234 vmap
= screen
->transfer_map(screen
, vtrans
);
238 int y_array_size
= w
* h
;
239 for (i
= 0; i
< w
; ++i
) {
240 for (j
= 0; i
< h
; ++j
) {
243 u
= buf
[(j
/2) * (w
/2) + i
/2 + y_array_size
];
244 v
= buf
[(j
/2) * (w
/2) + i
/2 + y_array_size
+ y_array_size
/4];
253 for (j
= 0; j
< h
; ++j
) {
254 for (i
= 0; i
< w
; ++i
) {
255 /* extracting two pixels */
271 debug_assert(!"Unsupported yuv format!");
275 screen
->transfer_unmap(screen
, ytrans
);
276 screen
->transfer_unmap(screen
, utrans
);
277 screen
->transfer_unmap(screen
, vtrans
);
278 screen
->tex_transfer_destroy(ytrans
);
279 screen
->tex_transfer_destroy(utrans
);
280 screen
->tex_transfer_destroy(vtrans
);
284 setup_video_constants(struct xorg_renderer
*r
, boolean hdtv
)
286 struct pipe_context
*pipe
= r
->pipe
;
287 const int param_bytes
= 9 * sizeof(float);
288 struct pipe_constant_buffer
*cbuf
= &r
->vs_const_buffer
;
290 pipe_buffer_reference(&cbuf
->buffer
, NULL
);
291 cbuf
->buffer
= pipe_buffer_create(pipe
->screen
, 16,
292 PIPE_BUFFER_USAGE_CONSTANT
,
296 const float *video_constants
= (hdtv
) ? bt_709
: bt_601
;
298 pipe_buffer_write(pipe
->screen
, cbuf
->buffer
,
299 0, param_bytes
, video_constants
);
301 pipe
->set_constant_buffer(pipe
, PIPE_SHADER_FRAGMENT
, 0, cbuf
);
305 display_video(ScrnInfoPtr pScrn
, struct xorg_xv_port_priv
*pPriv
, int id
,
307 short width
, short height
,
308 int x1
, int y1
, int x2
, int y2
,
309 short src_w
, short src_h
, short drw_w
, short drw_h
,
316 float tc0
[2], tc1
[2], tc2
[2];
318 hdtv
= ((src_w
>= RES_720P_X
) && (src_h
>= RES_720P_Y
));
319 setup_video_constants(pPriv
->r
, hdtv
);
321 REGION_TRANSLATE(pScrn
->pScreen
, dstRegion
, -pPixmap
->screen_x
,
324 dxo
= dstRegion
->extents
.x1
;
325 dyo
= dstRegion
->extents
.y1
;
327 pbox
= REGION_RECTS(dstRegion
);
328 nbox
= REGION_NUM_RECTS(dstRegion
);
331 int box_x1
= pbox
->x1
;
332 int box_y1
= pbox
->y1
;
333 int box_x2
= pbox
->x2
;
334 int box_y2
= pbox
->y2
;
336 tc0
[0] = (double) (box_x1
- dxo
) / (double) drw_w
; /* u0 */
337 tc0
[1] = (double) (box_y1
- dyo
) / (double) drw_h
; /* v0 */
338 tc1
[0] = (double) (box_x2
- dxo
) / (double) drw_w
; /* u1 */
341 tc2
[1] = (double) (box_y2
- dyo
) / (double) drw_h
; /* v1 */
350 draw_yuv(pScrn
, x
, y
, w
, h
, &src
, 1, FALSE
,
352 pPriv
->conversionData
);
355 DamageDamageRegion(&pPixmap
->drawable
, dstRegion
);
360 put_image(ScrnInfoPtr pScrn
,
361 short src_x
, short src_y
,
362 short drw_x
, short drw_y
,
363 short src_w
, short src_h
,
364 short drw_w
, short drw_h
,
365 int id
, unsigned char *buf
,
366 short width
, short height
,
367 Bool sync
, RegionPtr clipBoxes
, pointer data
,
370 struct xorg_xv_port_priv
*pPriv
= (struct xorg_xv_port_priv
*) data
;
371 ScreenPtr pScreen
= screenInfo
.screens
[pScrn
->scrnIndex
];
373 INT32 x1
, x2
, y1
, y2
;
385 dstBox
.x2
= drw_x
+ drw_w
;
387 dstBox
.y2
= drw_y
+ drw_h
;
389 if (!xf86XVClipVideoHelper(&dstBox
, &x1
, &x2
, &y1
, &y2
, clipBoxes
,
397 srcPitch
= width
<< 1;
401 ret
= check_yuv_textures(pPriv
, width
, height
);
406 copy_packed_data(pScrn
, pPriv
, id
, buf
, srcPitch
,
407 src_x
, src_y
, width
, height
);
409 if (pDraw
->type
== DRAWABLE_WINDOW
) {
410 pPixmap
= (*pScreen
->GetWindowPixmap
)((WindowPtr
)pDraw
);
412 pPixmap
= (PixmapPtr
)pDraw
;
415 display_video(pScrn
, pPriv
, id
, clipBoxes
, width
, height
,
417 src_w
, src_h
, drw_w
, drw_h
, pPixmap
);
419 pPriv
->current_set
= (pPriv
->current_set
+ 1) & 1;
424 query_image_attributes(ScrnInfoPtr pScrn
,
426 unsigned short *w
, unsigned short *h
,
427 int *pitches
, int *offsets
)
431 if (*w
> IMAGE_MAX_WIDTH
)
432 *w
= IMAGE_MAX_WIDTH
;
433 if (*h
> IMAGE_MAX_HEIGHT
)
434 *h
= IMAGE_MAX_HEIGHT
;
454 static struct xorg_xv_port_priv
*
455 port_priv_create(struct xorg_renderer
*r
)
457 struct xorg_xv_port_priv
*priv
= NULL
;
459 priv
= calloc(1, sizeof(struct xorg_xv_port_priv
));
466 REGION_NULL(pScreen
, &priv
->clip
);
468 debug_assert(priv
&& priv
->r
);
473 static XF86VideoAdaptorPtr
474 xorg_setup_textured_adapter(ScreenPtr pScreen
)
476 ScrnInfoPtr pScrn
= xf86Screens
[pScreen
->myNum
];
477 modesettingPtr ms
= modesettingPTR(pScrn
);
478 XF86VideoAdaptorPtr adapt
;
479 XF86AttributePtr attrs
;
480 DevUnion
*dev_unions
;
484 nattributes
= NUM_TEXTURED_ATTRIBUTES
;
486 debug_assert(ms
->exa
);
487 debug_assert(ms
->exa
->renderer
);
489 adapt
= calloc(1, sizeof(XF86VideoAdaptorRec
));
490 dev_unions
= calloc(nports
, sizeof(DevUnion
));
491 attrs
= calloc(nattributes
, sizeof(XF86AttributeRec
));
492 if (adapt
== NULL
|| dev_unions
== NULL
|| attrs
== NULL
) {
499 adapt
->type
= XvWindowMask
| XvInputMask
| XvImageMask
;
501 adapt
->name
= "Gallium3D Textured Video";
502 adapt
->nEncodings
= 1;
503 adapt
->pEncodings
= DummyEncoding
;
504 adapt
->nFormats
= NUM_FORMATS
;
505 adapt
->pFormats
= Formats
;
507 adapt
->pPortPrivates
= dev_unions
;
508 adapt
->nAttributes
= nattributes
;
509 adapt
->pAttributes
= attrs
;
510 memcpy(attrs
, TexturedAttributes
, nattributes
* sizeof(XF86AttributeRec
));
511 adapt
->nImages
= NUM_IMAGES
;
512 adapt
->pImages
= Images
;
513 adapt
->PutVideo
= NULL
;
514 adapt
->PutStill
= NULL
;
515 adapt
->GetVideo
= NULL
;
516 adapt
->GetStill
= NULL
;
517 adapt
->StopVideo
= stop_video
;
518 adapt
->SetPortAttribute
= set_port_attribute
;
519 adapt
->GetPortAttribute
= get_port_attribute
;
520 adapt
->QueryBestSize
= query_best_size
;
521 adapt
->PutImage
= put_image
;
522 adapt
->QueryImageAttributes
= query_image_attributes
;
524 for (i
= 0; i
< nports
; i
++) {
525 struct xorg_xv_port_priv
*priv
=
526 port_priv_create(ms
->exa
->renderer
);
528 adapt
->pPortPrivates
[i
].ptr
= (pointer
) (priv
);
536 xorg_init_video(ScreenPtr pScreen
)
538 ScrnInfoPtr pScrn
= xf86Screens
[pScreen
->myNum
];
539 /*modesettingPtr ms = modesettingPTR(pScrn);*/
540 XF86VideoAdaptorPtr
*adaptors
, *new_adaptors
= NULL
;
541 XF86VideoAdaptorPtr textured_adapter
;
544 num_adaptors
= xf86XVListGenericAdaptors(pScrn
, &adaptors
);
545 new_adaptors
= malloc((num_adaptors
+ 1) * sizeof(XF86VideoAdaptorPtr
*));
546 if (new_adaptors
== NULL
)
549 memcpy(new_adaptors
, adaptors
, num_adaptors
* sizeof(XF86VideoAdaptorPtr
));
550 adaptors
= new_adaptors
;
552 /* Add the adaptors supported by our hardware. First, set up the atoms
553 * that will be used by both output adaptors.
555 xvBrightness
= MAKE_ATOM("XV_BRIGHTNESS");
556 xvContrast
= MAKE_ATOM("XV_CONTRAST");
558 textured_adapter
= xorg_setup_textured_adapter(pScreen
);
560 debug_assert(textured_adapter
);
562 if (textured_adapter
) {
563 adaptors
[num_adaptors
++] = textured_adapter
;
567 xf86XVScreenInit(pScreen
, adaptors
, num_adaptors
);
569 xf86DrvMsg(pScrn
->scrnIndex
, X_WARNING
,
570 "Disabling Xv because no adaptors could be initialized.\n");