Merge branch 'mesa_7_7_branch'
[mesa.git] / src / gallium / state_trackers / xorg / xorg_xv.c
1 #include "xorg_tracker.h"
2
3 #include <xf86xv.h>
4 #include <X11/extensions/Xv.h>
5 #include <fourcc.h>
6
7 #include "xorg_exa.h"
8 #include "xorg_renderer.h"
9 #include "xorg_exa_tgsi.h"
10
11 #include "cso_cache/cso_context.h"
12
13 #include "pipe/p_screen.h"
14
15 #include "util/u_format.h"
16
17 /*XXX get these from pipe's texture limits */
18 #define IMAGE_MAX_WIDTH 2048
19 #define IMAGE_MAX_HEIGHT 2048
20
21 #define RES_720P_X 1280
22 #define RES_720P_Y 720
23
24
25 /* The ITU-R BT.601 conversion matrix for SDTV. */
26 /* original, matrix, but we transpose it to
27 * make the shader easier
28 static const float bt_601[] = {
29 1.0, 0.0, 1.4075, ,
30 1.0, -0.3455, -0.7169, 0,
31 1.0, 1.7790, 0., 0,
32 };*/
33 static const float bt_601[] = {
34 1.0, 1.0, 1.0, 0.5,
35 0.0, -0.3455, 1.7790, 0,
36 1.4075, -0.7169, 0., 0,
37 };
38
39 /* The ITU-R BT.709 conversion matrix for HDTV. */
40 /* original, but we transpose to make the conversion
41 * in the shader easier
42 static const float bt_709[] = {
43 1.0, 0.0, 1.581, 0,
44 1.0, -0.1881, -0.47, 0,
45 1.0, 1.8629, 0., 0,
46 };*/
47 static const float bt_709[] = {
48 1.0, 1.0, 1.0, 0.5,
49 0.0, -0.1881, 1.8629, 0,
50 1.581,-0.47 , 0.0, 0,
51 };
52
53 #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
54
55 static Atom xvBrightness, xvContrast;
56
57 #define NUM_TEXTURED_ATTRIBUTES 2
58 static XF86AttributeRec TexturedAttributes[NUM_TEXTURED_ATTRIBUTES] = {
59 {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"},
60 {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"}
61 };
62
63 #define NUM_FORMATS 3
64 static XF86VideoFormatRec Formats[NUM_FORMATS] = {
65 {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
66 };
67
68 static XF86VideoEncodingRec DummyEncoding[1] = {
69 {
70 0,
71 "XV_IMAGE",
72 IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT,
73 {1, 1}
74 }
75 };
76
77 #define NUM_IMAGES 3
78 static XF86ImageRec Images[NUM_IMAGES] = {
79 XVIMAGE_UYVY,
80 XVIMAGE_YUY2,
81 XVIMAGE_YV12,
82 };
83
84 struct xorg_xv_port_priv {
85 struct xorg_renderer *r;
86
87 RegionRec clip;
88
89 int brightness;
90 int contrast;
91
92 int current_set;
93 /* juggle two sets of seperate Y, U and V
94 * textures */
95 struct pipe_texture *yuv[2][3];
96 };
97
98
99 static void
100 stop_video(ScrnInfoPtr pScrn, pointer data, Bool shutdown)
101 {
102 struct xorg_xv_port_priv *priv = (struct xorg_xv_port_priv *)data;
103
104 REGION_EMPTY(pScrn->pScreen, &priv->clip);
105 }
106
107 static int
108 set_port_attribute(ScrnInfoPtr pScrn,
109 Atom attribute, INT32 value, pointer data)
110 {
111 struct xorg_xv_port_priv *priv = (struct xorg_xv_port_priv *)data;
112
113 if (attribute == xvBrightness) {
114 if ((value < -128) || (value > 127))
115 return BadValue;
116 priv->brightness = value;
117 } else if (attribute == xvContrast) {
118 if ((value < 0) || (value > 255))
119 return BadValue;
120 priv->contrast = value;
121 } else
122 return BadMatch;
123
124 return Success;
125 }
126
127 static int
128 get_port_attribute(ScrnInfoPtr pScrn,
129 Atom attribute, INT32 * value, pointer data)
130 {
131 struct xorg_xv_port_priv *priv = (struct xorg_xv_port_priv *)data;
132
133 if (attribute == xvBrightness)
134 *value = priv->brightness;
135 else if (attribute == xvContrast)
136 *value = priv->contrast;
137 else
138 return BadMatch;
139
140 return Success;
141 }
142
143 static void
144 query_best_size(ScrnInfoPtr pScrn,
145 Bool motion,
146 short vid_w, short vid_h,
147 short drw_w, short drw_h,
148 unsigned int *p_w, unsigned int *p_h, pointer data)
149 {
150 if (vid_w > (drw_w << 1))
151 drw_w = vid_w >> 1;
152 if (vid_h > (drw_h << 1))
153 drw_h = vid_h >> 1;
154
155 *p_w = drw_w;
156 *p_h = drw_h;
157 }
158
159 static INLINE struct pipe_texture *
160 create_component_texture(struct pipe_context *pipe,
161 int width, int height)
162 {
163 struct pipe_screen *screen = pipe->screen;
164 struct pipe_texture *tex = 0;
165 struct pipe_texture templ;
166
167 memset(&templ, 0, sizeof(templ));
168 templ.target = PIPE_TEXTURE_2D;
169 templ.format = PIPE_FORMAT_L8_UNORM;
170 templ.last_level = 0;
171 templ.width0 = width;
172 templ.height0 = height;
173 templ.depth0 = 1;
174 templ.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER;
175
176 tex = screen->texture_create(screen, &templ);
177
178 return tex;
179 }
180
181 static int
182 check_yuv_textures(struct xorg_xv_port_priv *priv, int width, int height)
183 {
184 struct pipe_texture **dst = priv->yuv[priv->current_set];
185 if (!dst[0] ||
186 dst[0]->width0 != width ||
187 dst[0]->height0 != height) {
188 pipe_texture_reference(&dst[0], NULL);
189 }
190 if (!dst[1] ||
191 dst[1]->width0 != width ||
192 dst[1]->height0 != height) {
193 pipe_texture_reference(&dst[1], NULL);
194 }
195 if (!dst[2] ||
196 dst[2]->width0 != width ||
197 dst[2]->height0 != height) {
198 pipe_texture_reference(&dst[2], NULL);
199 }
200
201 if (!dst[0])
202 dst[0] = create_component_texture(priv->r->pipe, width, height);
203
204 if (!dst[1])
205 dst[1] = create_component_texture(priv->r->pipe, width, height);
206
207 if (!dst[2])
208 dst[2] = create_component_texture(priv->r->pipe, width, height);
209
210 if (!dst[0] || !dst[1] || !dst[2])
211 return BadAlloc;
212
213 return Success;
214 }
215
216 static int
217 query_image_attributes(ScrnInfoPtr pScrn,
218 int id,
219 unsigned short *w, unsigned short *h,
220 int *pitches, int *offsets)
221 {
222 int size, tmp;
223
224 if (*w > IMAGE_MAX_WIDTH)
225 *w = IMAGE_MAX_WIDTH;
226 if (*h > IMAGE_MAX_HEIGHT)
227 *h = IMAGE_MAX_HEIGHT;
228
229 *w = (*w + 1) & ~1;
230 if (offsets)
231 offsets[0] = 0;
232
233 switch (id) {
234 case FOURCC_YV12:
235 *h = (*h + 1) & ~1;
236 size = (*w + 3) & ~3;
237 if (pitches) {
238 pitches[0] = size;
239 }
240 size *= *h;
241 if (offsets) {
242 offsets[1] = size;
243 }
244 tmp = ((*w >> 1) + 3) & ~3;
245 if (pitches) {
246 pitches[1] = pitches[2] = tmp;
247 }
248 tmp *= (*h >> 1);
249 size += tmp;
250 if (offsets) {
251 offsets[2] = size;
252 }
253 size += tmp;
254 break;
255 case FOURCC_UYVY:
256 case FOURCC_YUY2:
257 default:
258 size = *w << 1;
259 if (pitches)
260 pitches[0] = size;
261 size *= *h;
262 break;
263 }
264
265 return size;
266 }
267
268 static void
269 copy_packed_data(ScrnInfoPtr pScrn,
270 struct xorg_xv_port_priv *port,
271 int id,
272 unsigned char *buf,
273 int left,
274 int top,
275 unsigned short w, unsigned short h)
276 {
277 int i, j;
278 struct pipe_texture **dst = port->yuv[port->current_set];
279 struct pipe_transfer *ytrans, *utrans, *vtrans;
280 struct pipe_screen *screen = port->r->pipe->screen;
281 char *ymap, *vmap, *umap;
282 unsigned char y1, y2, u, v;
283 int yidx, uidx, vidx;
284 int y_array_size = w * h;
285
286 ytrans = screen->get_tex_transfer(screen, dst[0],
287 0, 0, 0,
288 PIPE_TRANSFER_WRITE,
289 left, top, w, h);
290 utrans = screen->get_tex_transfer(screen, dst[1],
291 0, 0, 0,
292 PIPE_TRANSFER_WRITE,
293 left, top, w, h);
294 vtrans = screen->get_tex_transfer(screen, dst[2],
295 0, 0, 0,
296 PIPE_TRANSFER_WRITE,
297 left, top, w, h);
298
299 ymap = (char*)screen->transfer_map(screen, ytrans);
300 umap = (char*)screen->transfer_map(screen, utrans);
301 vmap = (char*)screen->transfer_map(screen, vtrans);
302
303 yidx = uidx = vidx = 0;
304
305 switch (id) {
306 case FOURCC_YV12: {
307 int pitches[3], offsets[3];
308 unsigned char *y, *u, *v;
309 query_image_attributes(pScrn, FOURCC_YV12,
310 &w, &h, pitches, offsets);
311
312 y = buf + offsets[0];
313 v = buf + offsets[1];
314 u = buf + offsets[2];
315 for (i = 0; i < h; ++i) {
316 for (j = 0; j < w; ++j) {
317 int yoffset = (w*i+j);
318 int ii = (i|1), jj = (j|1);
319 int vuoffset = (w/2)*(ii/2) + (jj/2);
320 ymap[yidx++] = y[yoffset];
321 umap[uidx++] = u[vuoffset];
322 vmap[vidx++] = v[vuoffset];
323 }
324 }
325 }
326 break;
327 case FOURCC_UYVY:
328 for (i = 0; i < y_array_size; i +=2 ) {
329 /* extracting two pixels */
330 u = buf[0];
331 y1 = buf[1];
332 v = buf[2];
333 y2 = buf[3];
334 buf += 4;
335
336 ymap[yidx++] = y1;
337 ymap[yidx++] = y2;
338 umap[uidx++] = u;
339 umap[uidx++] = u;
340 vmap[vidx++] = v;
341 vmap[vidx++] = v;
342 }
343 break;
344 case FOURCC_YUY2:
345 for (i = 0; i < y_array_size; i +=2 ) {
346 /* extracting two pixels */
347 y1 = buf[0];
348 u = buf[1];
349 y2 = buf[2];
350 v = buf[3];
351
352 buf += 4;
353
354 ymap[yidx++] = y1;
355 ymap[yidx++] = y2;
356 umap[uidx++] = u;
357 umap[uidx++] = u;
358 vmap[vidx++] = v;
359 vmap[vidx++] = v;
360 }
361 break;
362 default:
363 debug_assert(!"Unsupported yuv format!");
364 break;
365 }
366
367 screen->transfer_unmap(screen, ytrans);
368 screen->transfer_unmap(screen, utrans);
369 screen->transfer_unmap(screen, vtrans);
370 screen->tex_transfer_destroy(ytrans);
371 screen->tex_transfer_destroy(utrans);
372 screen->tex_transfer_destroy(vtrans);
373 }
374
375
376 static void
377 setup_fs_video_constants(struct xorg_renderer *r, boolean hdtv)
378 {
379 const int param_bytes = 12 * sizeof(float);
380 const float *video_constants = (hdtv) ? bt_709 : bt_601;
381
382 renderer_set_constants(r, PIPE_SHADER_FRAGMENT,
383 video_constants, param_bytes);
384 }
385
386 static void
387 draw_yuv(struct xorg_xv_port_priv *port,
388 int src_x, int src_y, int src_w, int src_h,
389 int dst_x, int dst_y, int dst_w, int dst_h)
390 {
391 struct pipe_texture **textures = port->yuv[port->current_set];
392
393 renderer_draw_yuv(port->r,
394 src_x, src_y, src_w, src_h,
395 dst_x, dst_y, dst_w, dst_h,
396 textures);
397 }
398
399 static void
400 bind_blend_state(struct xorg_xv_port_priv *port)
401 {
402 struct pipe_blend_state blend;
403
404 memset(&blend, 0, sizeof(struct pipe_blend_state));
405 blend.blend_enable = 1;
406 blend.colormask |= PIPE_MASK_RGBA;
407
408 /* porter&duff src */
409 blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
410 blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
411 blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
412 blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
413
414 cso_set_blend(port->r->cso, &blend);
415 }
416
417
418 static void
419 bind_shaders(struct xorg_xv_port_priv *port)
420 {
421 unsigned vs_traits = 0, fs_traits = 0;
422 struct xorg_shader shader;
423
424 vs_traits |= VS_YUV;
425 fs_traits |= FS_YUV;
426
427 shader = xorg_shaders_get(port->r->shaders, vs_traits, fs_traits);
428 cso_set_vertex_shader_handle(port->r->cso, shader.vs);
429 cso_set_fragment_shader_handle(port->r->cso, shader.fs);
430 }
431
432 static INLINE void
433 conditional_flush(struct pipe_context *pipe, struct pipe_texture **tex,
434 int num)
435 {
436 int i;
437 for (i = 0; i < num; ++i) {
438 if (tex[i] && pipe->is_texture_referenced(pipe, tex[i], 0, 0) &
439 PIPE_REFERENCED_FOR_WRITE) {
440 pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
441 return;
442 }
443 }
444 }
445
446 static void
447 bind_samplers(struct xorg_xv_port_priv *port)
448 {
449 struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
450 struct pipe_sampler_state sampler;
451 struct pipe_texture **dst = port->yuv[port->current_set];
452
453 memset(&sampler, 0, sizeof(struct pipe_sampler_state));
454
455 conditional_flush(port->r->pipe, dst, 3);
456
457 sampler.wrap_s = PIPE_TEX_WRAP_CLAMP;
458 sampler.wrap_t = PIPE_TEX_WRAP_CLAMP;
459 sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR;
460 sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR;
461 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST;
462 sampler.normalized_coords = 1;
463
464 samplers[0] = &sampler;
465 samplers[1] = &sampler;
466 samplers[2] = &sampler;
467
468
469 cso_set_samplers(port->r->cso, 3,
470 (const struct pipe_sampler_state **)samplers);
471 cso_set_sampler_textures(port->r->cso, 3,
472 dst);
473 }
474
475 static int
476 display_video(ScrnInfoPtr pScrn, struct xorg_xv_port_priv *pPriv, int id,
477 RegionPtr dstRegion,
478 int src_x, int src_y, int src_w, int src_h,
479 int dstX, int dstY, int dst_w, int dst_h,
480 PixmapPtr pPixmap)
481 {
482 modesettingPtr ms = modesettingPTR(pScrn);
483 BoxPtr pbox;
484 int nbox;
485 int dxo, dyo;
486 Bool hdtv;
487 int x, y, w, h;
488 struct exa_pixmap_priv *dst;
489 struct pipe_surface *dst_surf = NULL;
490
491 exaMoveInPixmap(pPixmap);
492 dst = exaGetPixmapDriverPrivate(pPixmap);
493
494 if (dst && !dst->tex) {
495 xorg_exa_set_shared_usage(pPixmap);
496 pScrn->pScreen->ModifyPixmapHeader(pPixmap, 0, 0, 0, 0, 0, NULL);
497 }
498
499 if (!dst || !dst->tex)
500 XORG_FALLBACK("Xv destination %s", !dst ? "!dst" : "!dst->tex");
501
502 dst_surf = xorg_gpu_surface(pPriv->r->pipe->screen, dst);
503 hdtv = ((src_w >= RES_720P_X) && (src_h >= RES_720P_Y));
504
505 REGION_TRANSLATE(pScrn->pScreen, dstRegion, -pPixmap->screen_x,
506 -pPixmap->screen_y);
507
508 dxo = dstRegion->extents.x1;
509 dyo = dstRegion->extents.y1;
510
511 pbox = REGION_RECTS(dstRegion);
512 nbox = REGION_NUM_RECTS(dstRegion);
513
514 renderer_bind_destination(pPriv->r, dst_surf,
515 dst_surf->width, dst_surf->height);
516
517 bind_blend_state(pPriv);
518 bind_shaders(pPriv);
519 bind_samplers(pPriv);
520 setup_fs_video_constants(pPriv->r, hdtv);
521
522 DamageDamageRegion(&pPixmap->drawable, dstRegion);
523
524 while (nbox--) {
525 int box_x1 = pbox->x1;
526 int box_y1 = pbox->y1;
527 int box_x2 = pbox->x2;
528 int box_y2 = pbox->y2;
529 float diff_x = (float)src_w / (float)dst_w;
530 float diff_y = (float)src_h / (float)dst_h;
531 int offset_x = box_x1 - dstX + pPixmap->screen_x;
532 int offset_y = box_y1 - dstY + pPixmap->screen_y;
533 int offset_w;
534 int offset_h;
535
536 x = box_x1;
537 y = box_y1;
538 w = box_x2 - box_x1;
539 h = box_y2 - box_y1;
540
541 offset_w = dst_w - w;
542 offset_h = dst_h - h;
543
544 draw_yuv(pPriv, src_x + offset_x*diff_x, src_y + offset_y*diff_y,
545 src_w - offset_w*diff_x, src_h - offset_h*diff_x,
546 x, y, w, h);
547
548 pbox++;
549 }
550 DamageRegionProcessPending(&pPixmap->drawable);
551
552 pipe_surface_reference(&dst_surf, NULL);
553
554 return TRUE;
555 }
556
557 static int
558 put_image(ScrnInfoPtr pScrn,
559 short src_x, short src_y,
560 short drw_x, short drw_y,
561 short src_w, short src_h,
562 short drw_w, short drw_h,
563 int id, unsigned char *buf,
564 short width, short height,
565 Bool sync, RegionPtr clipBoxes, pointer data,
566 DrawablePtr pDraw)
567 {
568 struct xorg_xv_port_priv *pPriv = (struct xorg_xv_port_priv *) data;
569 ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
570 PixmapPtr pPixmap;
571 INT32 x1, x2, y1, y2;
572 BoxRec dstBox;
573 int ret;
574
575 /* Clip */
576 x1 = src_x;
577 x2 = src_x + src_w;
578 y1 = src_y;
579 y2 = src_y + src_h;
580
581 dstBox.x1 = drw_x;
582 dstBox.x2 = drw_x + drw_w;
583 dstBox.y1 = drw_y;
584 dstBox.y2 = drw_y + drw_h;
585
586 if (!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes,
587 width, height))
588 return Success;
589
590 ret = check_yuv_textures(pPriv, width, height);
591
592 if (ret)
593 return ret;
594
595 copy_packed_data(pScrn, pPriv, id, buf,
596 src_x, src_y, width, height);
597
598 if (pDraw->type == DRAWABLE_WINDOW) {
599 pPixmap = (*pScreen->GetWindowPixmap)((WindowPtr)pDraw);
600 } else {
601 pPixmap = (PixmapPtr)pDraw;
602 }
603
604 display_video(pScrn, pPriv, id, clipBoxes,
605 src_x, src_y, src_w, src_h,
606 drw_x, drw_y,
607 drw_w, drw_h, pPixmap);
608
609 pPriv->current_set = (pPriv->current_set + 1) & 1;
610 return Success;
611 }
612
613 static struct xorg_xv_port_priv *
614 port_priv_create(struct xorg_renderer *r)
615 {
616 struct xorg_xv_port_priv *priv = NULL;
617
618 priv = calloc(1, sizeof(struct xorg_xv_port_priv));
619
620 if (!priv)
621 return NULL;
622
623 priv->r = r;
624
625 REGION_NULL(pScreen, &priv->clip);
626
627 debug_assert(priv && priv->r);
628
629 return priv;
630 }
631
632 static XF86VideoAdaptorPtr
633 xorg_setup_textured_adapter(ScreenPtr pScreen)
634 {
635 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
636 modesettingPtr ms = modesettingPTR(pScrn);
637 XF86VideoAdaptorPtr adapt;
638 XF86AttributePtr attrs;
639 DevUnion *dev_unions;
640 int nports = 16, i;
641 int nattributes;
642
643 nattributes = NUM_TEXTURED_ATTRIBUTES;
644
645 debug_assert(ms->exa);
646 debug_assert(ms->exa->renderer);
647
648 adapt = calloc(1, sizeof(XF86VideoAdaptorRec));
649 dev_unions = calloc(nports, sizeof(DevUnion));
650 attrs = calloc(nattributes, sizeof(XF86AttributeRec));
651 if (adapt == NULL || dev_unions == NULL || attrs == NULL) {
652 free(adapt);
653 free(dev_unions);
654 free(attrs);
655 return NULL;
656 }
657
658 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
659 adapt->flags = 0;
660 adapt->name = "Gallium3D Textured Video";
661 adapt->nEncodings = 1;
662 adapt->pEncodings = DummyEncoding;
663 adapt->nFormats = NUM_FORMATS;
664 adapt->pFormats = Formats;
665 adapt->nPorts = 0;
666 adapt->pPortPrivates = dev_unions;
667 adapt->nAttributes = nattributes;
668 adapt->pAttributes = attrs;
669 memcpy(attrs, TexturedAttributes, nattributes * sizeof(XF86AttributeRec));
670 adapt->nImages = NUM_IMAGES;
671 adapt->pImages = Images;
672 adapt->PutVideo = NULL;
673 adapt->PutStill = NULL;
674 adapt->GetVideo = NULL;
675 adapt->GetStill = NULL;
676 adapt->StopVideo = stop_video;
677 adapt->SetPortAttribute = set_port_attribute;
678 adapt->GetPortAttribute = get_port_attribute;
679 adapt->QueryBestSize = query_best_size;
680 adapt->PutImage = put_image;
681 adapt->QueryImageAttributes = query_image_attributes;
682
683 for (i = 0; i < nports; i++) {
684 struct xorg_xv_port_priv *priv =
685 port_priv_create(ms->exa->renderer);
686
687 adapt->pPortPrivates[i].ptr = (pointer) (priv);
688 adapt->nPorts++;
689 }
690
691 return adapt;
692 }
693
694 void
695 xorg_xv_init(ScreenPtr pScreen)
696 {
697 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
698 /*modesettingPtr ms = modesettingPTR(pScrn);*/
699 XF86VideoAdaptorPtr *adaptors, *new_adaptors = NULL;
700 XF86VideoAdaptorPtr textured_adapter;
701 int num_adaptors;
702
703 num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
704 new_adaptors = malloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr *));
705 if (new_adaptors == NULL)
706 return;
707
708 memcpy(new_adaptors, adaptors, num_adaptors * sizeof(XF86VideoAdaptorPtr));
709 adaptors = new_adaptors;
710
711 /* Add the adaptors supported by our hardware. First, set up the atoms
712 * that will be used by both output adaptors.
713 */
714 xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
715 xvContrast = MAKE_ATOM("XV_CONTRAST");
716
717 textured_adapter = xorg_setup_textured_adapter(pScreen);
718
719 debug_assert(textured_adapter);
720
721 if (textured_adapter) {
722 adaptors[num_adaptors++] = textured_adapter;
723 }
724
725 if (num_adaptors) {
726 xf86XVScreenInit(pScreen, adaptors, num_adaptors);
727 } else {
728 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
729 "Disabling Xv because no adaptors could be initialized.\n");
730 }
731
732 free(adaptors);
733 }