Initial code release
[adaptation/xorg-x11-drv-intel.git] / src / intel_video.c
1 /***************************************************************************
2
3  Copyright 2000 Intel Corporation.  All Rights Reserved. 
4
5  Permission is hereby granted, free of charge, to any person obtaining a 
6  copy of this software and associated documentation files (the 
7  "Software"), to deal in the Software without restriction, including 
8  without limitation the rights to use, copy, modify, merge, publish, 
9  distribute, sub license, and/or sell copies of the Software, and to 
10  permit persons to whom the Software is furnished to do so, subject to 
11  the following conditions: 
12
13  The above copyright notice and this permission notice (including the 
14  next paragraph) shall be included in all copies or substantial portions 
15  of the Software. 
16
17  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 
18  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
19  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 
20  IN NO EVENT SHALL INTEL, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 
21  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 
22  OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 
23  THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
25  **************************************************************************/
26
27 /*
28  * i830_video.c: i830/i845 Xv driver. 
29  *
30  * Copyright © 2002 by Alan Hourihane and David Dawes
31  *
32  * Authors: 
33  *      Alan Hourihane <alanh@tungstengraphics.com>
34  *      David Dawes <dawes@xfree86.org>
35  *
36  * Derived from i810 Xv driver:
37  *
38  * Authors of i810 code:
39  *      Jonathan Bian <jonathan.bian@intel.com>
40  *      Offscreen Images:
41  *        Matt Sottek <matthew.j.sottek@intel.com>
42  */
43
44 /*
45  * XXX Could support more formats.
46  */
47
48 #ifdef HAVE_CONFIG_H
49 #include "config.h"
50 #endif
51
52 #include <inttypes.h>
53 #include <math.h>
54 #include <string.h>
55 #include <assert.h>
56 #include <errno.h>
57
58 #include "xf86.h"
59 #include "xf86_OSproc.h"
60 #include "compiler.h"
61 #include "xf86PciInfo.h"
62 #include "xf86Pci.h"
63 #include "xf86fbman.h"
64 #include "regionstr.h"
65 #include "randrstr.h"
66 #include "windowstr.h"
67 #include "damage.h"
68 #include "intel.h"
69 #include "intel_video.h"
70 #include "i830_reg.h"
71 #include "xf86xv.h"
72 #include <X11/extensions/Xv.h>
73 #include "dixstruct.h"
74 #include "fourcc.h"
75
76 #ifdef INTEL_XVMC
77 #define _INTEL_XVMC_SERVER_
78 #include "intel_hwmc.h"
79 #endif
80
81 #define OFF_DELAY       250     /* milliseconds */
82
83 #define OFF_TIMER       0x01
84 #define CLIENT_VIDEO_ON 0x02
85
86 static XF86VideoAdaptorPtr I830SetupImageVideoOverlay(ScreenPtr);
87 static XF86VideoAdaptorPtr I830SetupImageVideoTextured(ScreenPtr);
88 static void I830StopVideo(ScrnInfoPtr, pointer, Bool);
89 static int I830SetPortAttributeOverlay(ScrnInfoPtr, Atom, INT32, pointer);
90 static int I830SetPortAttributeTextured(ScrnInfoPtr, Atom, INT32, pointer);
91 static int I830GetPortAttribute(ScrnInfoPtr, Atom, INT32 *, pointer);
92 static void I830QueryBestSize(ScrnInfoPtr, Bool,
93                               short, short, short, short, unsigned int *,
94                               unsigned int *, pointer);
95 static int I830PutImageTextured(ScrnInfoPtr, short, short, short, short, short, short,
96                         short, short, int, unsigned char *, short, short,
97                         Bool, RegionPtr, pointer, DrawablePtr);
98 static int I830PutImageOverlay(ScrnInfoPtr, short, short, short, short, short, short,
99                         short, short, int, unsigned char *, short, short,
100                         Bool, RegionPtr, pointer, DrawablePtr);
101 static int I830QueryImageAttributes(ScrnInfoPtr, int, unsigned short *,
102                                     unsigned short *, int *, int *);
103
104 #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
105
106 static Atom xvBrightness, xvContrast, xvSaturation, xvColorKey, xvPipe;
107 static Atom xvGamma0, xvGamma1, xvGamma2, xvGamma3, xvGamma4, xvGamma5;
108 static Atom xvSyncToVblank;
109
110 /* Limits for the overlay/textured video source sizes.  The documented hardware
111  * limits are 2048x2048 or better for overlay and both of our textured video
112  * implementations.  Additionally, on the 830 and 845, larger sizes resulted in
113  * the card hanging, so we keep the limits lower there.
114  */
115 #define IMAGE_MAX_WIDTH         2048
116 #define IMAGE_MAX_HEIGHT        2048
117 #define IMAGE_MAX_WIDTH_LEGACY  1024
118 #define IMAGE_MAX_HEIGHT_LEGACY 1088
119
120 /* overlay debugging printf function */
121 #if 0
122 #define OVERLAY_DEBUG ErrorF
123 #else
124 #define OVERLAY_DEBUG if (0) ErrorF
125 #endif
126
127 /* client libraries expect an encoding */
128 static const XF86VideoEncodingRec DummyEncoding[1] = {
129         {
130          0,
131          "XV_IMAGE",
132          IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT,
133          {1, 1}
134          }
135 };
136
137 #define NUM_FORMATS 3
138
139 static XF86VideoFormatRec Formats[NUM_FORMATS] = {
140         {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
141 };
142
143 #define NUM_ATTRIBUTES 5
144 static XF86AttributeRec Attributes[NUM_ATTRIBUTES] = {
145         {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
146         {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"},
147         {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"},
148         {XvSettable | XvGettable, 0, 1023, "XV_SATURATION"},
149         {XvSettable | XvGettable, -1, 1, "XV_PIPE"}
150 };
151
152 #define NUM_TEXTURED_ATTRIBUTES 3
153 static XF86AttributeRec TexturedAttributes[NUM_TEXTURED_ATTRIBUTES] = {
154         {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"},
155         {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"},
156         {XvSettable | XvGettable, -1, 1, "XV_SYNC_TO_VBLANK"},
157 };
158
159 #define GAMMA_ATTRIBUTES 6
160 static XF86AttributeRec GammaAttributes[GAMMA_ATTRIBUTES] = {
161         {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA0"},
162         {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA1"},
163         {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA2"},
164         {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA3"},
165         {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA4"},
166         {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA5"}
167 };
168
169 #ifdef INTEL_XVMC
170 #define NUM_IMAGES 5
171 #define XVMC_IMAGE 1
172 #else
173 #define NUM_IMAGES 4
174 #define XVMC_IMAGE 0
175 #endif
176
177 static XF86ImageRec Images[NUM_IMAGES] = {
178         XVIMAGE_YUY2,
179         XVIMAGE_YV12,
180         XVIMAGE_I420,
181         XVIMAGE_UYVY,
182 #ifdef INTEL_XVMC
183         {
184          /*
185           * Below, a dummy picture type that is used in XvPutImage only to do
186           * an overlay update. Introduced for the XvMC client lib.
187           * Defined to have a zero data size.
188           */
189          FOURCC_XVMC,
190          XvYUV,
191          LSBFirst,
192          {'X', 'V', 'M', 'C',
193           0x00, 0x00, 0x00, 0x10, 0x80, 0x00, 0x00, 0xAA, 0x00,
194           0x38, 0x9B, 0x71},
195          12,
196          XvPlanar,
197          3,
198          0, 0, 0, 0,
199          8, 8, 8,
200          1, 2, 2,
201          1, 2, 2,
202          {'Y', 'V', 'U',
203           0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
204           0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
205          XvTopToBottom},
206 #endif
207 };
208
209 /* kernel modesetting overlay functions */
210 static Bool intel_has_overlay(intel_screen_private *intel)
211 {
212         struct drm_i915_getparam gp;
213         int has_overlay = 0;
214         int ret;
215
216         gp.param = I915_PARAM_HAS_OVERLAY;
217         gp.value = &has_overlay;
218         ret = drmCommandWriteRead(intel->drmSubFD, DRM_I915_GETPARAM, &gp, sizeof(gp));
219
220         return !! has_overlay;
221 }
222
223 static void intel_overlay_update_attrs(intel_screen_private *intel)
224 {
225         intel_adaptor_private *adaptor_priv = intel_get_adaptor_private(intel);
226         struct drm_intel_overlay_attrs attrs;
227         int ret;
228
229         attrs.flags = I915_OVERLAY_UPDATE_ATTRS;
230         attrs.brightness = adaptor_priv->brightness;
231         attrs.contrast = adaptor_priv->contrast;
232         attrs.saturation = adaptor_priv->saturation;
233         attrs.color_key = adaptor_priv->colorKey;
234         attrs.gamma0 = adaptor_priv->gamma0;
235         attrs.gamma1 = adaptor_priv->gamma1;
236         attrs.gamma2 = adaptor_priv->gamma2;
237         attrs.gamma3 = adaptor_priv->gamma3;
238         attrs.gamma4 = adaptor_priv->gamma4;
239         attrs.gamma5 = adaptor_priv->gamma5;
240
241         ret = drmCommandWriteRead(intel->drmSubFD, DRM_I915_OVERLAY_ATTRS,
242                                   &attrs, sizeof(attrs));
243 }
244
245 static void intel_overlay_off(intel_screen_private *intel)
246 {
247         struct drm_intel_overlay_put_image request;
248         int ret;
249
250         request.flags = 0;
251
252         ret = drmCommandWrite(intel->drmSubFD, DRM_I915_OVERLAY_PUT_IMAGE,
253                               &request, sizeof(request));
254 }
255
256 static Bool
257 intel_overlay_put_image(intel_screen_private *intel,
258                           xf86CrtcPtr crtc,
259                           int id, short width, short height,
260                           int dstPitch, int dstPitch2,
261                           BoxPtr dstBox, short src_w, short src_h, short drw_w,
262                           short drw_h)
263 {
264         intel_adaptor_private *adaptor_priv = intel_get_adaptor_private(intel);
265         struct drm_intel_overlay_put_image request;
266         int ret;
267         int planar = is_planar_fourcc(id);
268         float scale;
269         dri_bo *tmp;
270
271         request.flags = I915_OVERLAY_ENABLE;
272
273         request.bo_handle = adaptor_priv->buf->handle;
274         if (planar) {
275                 request.stride_Y = dstPitch2;
276                 request.stride_UV = dstPitch;
277         } else {
278                 request.stride_Y = dstPitch;
279                 request.stride_UV = 0;
280         }
281         request.offset_Y = adaptor_priv->YBufOffset;
282         request.offset_U = adaptor_priv->UBufOffset;
283         request.offset_V = adaptor_priv->VBufOffset;
284         OVERLAY_DEBUG("off_Y: %i, off_U: %i, off_V: %i\n", request.offset_Y,
285                       request.offset_U, request.offset_V);
286
287         request.crtc_id = intel_crtc_id(crtc);
288         request.dst_x = dstBox->x1;
289         request.dst_y = dstBox->y1;
290         request.dst_width = dstBox->x2 - dstBox->x1;
291         request.dst_height = dstBox->y2 - dstBox->y1;
292
293         request.src_width = width;
294         request.src_height = height;
295         /* adjust src dimensions */
296         if (request.dst_height > 1) {
297                 scale = ((float)request.dst_height - 1) / ((float)drw_h - 1);
298                 request.src_scan_height = src_h * scale;
299         } else
300                 request.src_scan_height = 1;
301
302         if (request.dst_width > 1) {
303                 scale = ((float)request.dst_width - 1) / ((float)drw_w - 1);
304                 request.src_scan_width = src_w * scale;
305         } else
306                 request.src_scan_width = 1;
307
308         if (planar) {
309                 request.flags |= I915_OVERLAY_YUV_PLANAR | I915_OVERLAY_YUV420;
310         } else {
311                 request.flags |= I915_OVERLAY_YUV_PACKED | I915_OVERLAY_YUV422;
312                 if (id == FOURCC_UYVY)
313                         request.flags |= I915_OVERLAY_Y_SWAP;
314         }
315
316         ret = drmCommandWrite(intel->drmSubFD, DRM_I915_OVERLAY_PUT_IMAGE,
317                               &request, sizeof(request));
318         if (ret)
319                 return FALSE;
320
321         if (!adaptor_priv->reusable) {
322                 drm_intel_bo_unreference(adaptor_priv->buf);
323                 adaptor_priv->buf = NULL;
324                 adaptor_priv->reusable = TRUE;
325         }
326
327         tmp = adaptor_priv->old_buf[1];
328         adaptor_priv->old_buf[1] = adaptor_priv->old_buf[0];
329         adaptor_priv->old_buf[0] = adaptor_priv->buf;
330         adaptor_priv->buf = tmp;
331
332         return TRUE;
333 }
334
335 void I830InitVideo(ScreenPtr screen)
336 {
337         ScrnInfoPtr scrn = xf86Screens[screen->myNum];
338         intel_screen_private *intel = intel_get_screen_private(scrn);
339         XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
340         XF86VideoAdaptorPtr overlayAdaptor = NULL, texturedAdaptor = NULL;
341         int num_adaptors;
342
343         num_adaptors = xf86XVListGenericAdaptors(scrn, &adaptors);
344         /* Give our adaptor list enough space for the overlay and/or texture video
345          * adaptors.
346          */
347         newAdaptors =
348             malloc((num_adaptors + 2) * sizeof(XF86VideoAdaptorPtr *));
349         if (newAdaptors == NULL)
350                 return;
351
352         memcpy(newAdaptors, adaptors,
353                num_adaptors * sizeof(XF86VideoAdaptorPtr));
354         adaptors = newAdaptors;
355
356         /* Add the adaptors supported by our hardware.  First, set up the atoms
357          * that will be used by both output adaptors.
358          */
359         xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
360         xvContrast = MAKE_ATOM("XV_CONTRAST");
361
362         /* Set up textured video if we can do it at this depth and we are on
363          * supported hardware.
364          */
365         if (scrn->bitsPerPixel >= 16 &&
366             INTEL_INFO(intel)->gen >= 30 &&
367             !intel->use_shadow) {
368                 texturedAdaptor = I830SetupImageVideoTextured(screen);
369                 if (texturedAdaptor != NULL) {
370                         xf86DrvMsg(scrn->scrnIndex, X_INFO,
371                                    "Set up textured video\n");
372                 } else {
373                         xf86DrvMsg(scrn->scrnIndex, X_ERROR,
374                                    "Failed to set up textured video\n");
375                 }
376         }
377
378         /* Set up overlay video if it is available */
379         intel->use_overlay = intel_has_overlay(intel);
380         if (intel->use_overlay) {
381                 overlayAdaptor = I830SetupImageVideoOverlay(screen);
382                 if (overlayAdaptor != NULL) {
383                         xf86DrvMsg(scrn->scrnIndex, X_INFO,
384                                    "Set up overlay video\n");
385                 } else {
386                         xf86DrvMsg(scrn->scrnIndex, X_ERROR,
387                                    "Failed to set up overlay video\n");
388                 }
389         }
390
391         if (overlayAdaptor && intel->XvPreferOverlay)
392                 adaptors[num_adaptors++] = overlayAdaptor;
393
394         if (texturedAdaptor)
395                 adaptors[num_adaptors++] = texturedAdaptor;
396
397         if (overlayAdaptor && !intel->XvPreferOverlay)
398                 adaptors[num_adaptors++] = overlayAdaptor;
399
400         if (num_adaptors) {
401                 xf86XVScreenInit(screen, adaptors, num_adaptors);
402         } else {
403                 xf86DrvMsg(scrn->scrnIndex, X_WARNING,
404                            "Disabling Xv because no adaptors could be initialized.\n");
405                 intel->XvEnabled = FALSE;
406         }
407
408 #ifdef INTEL_XVMC
409         if (texturedAdaptor)
410                 intel_xvmc_adaptor_init(screen);
411 #endif
412         free(adaptors);
413 }
414
415 static XF86VideoAdaptorPtr I830SetupImageVideoOverlay(ScreenPtr screen)
416 {
417         ScrnInfoPtr scrn = xf86Screens[screen->myNum];
418         intel_screen_private *intel = intel_get_screen_private(scrn);
419         XF86VideoAdaptorPtr adapt;
420         intel_adaptor_private *adaptor_priv;
421         XF86AttributePtr att;
422
423         OVERLAY_DEBUG("I830SetupImageVideoOverlay\n");
424
425         if (!(adapt = calloc(1,
426                              sizeof(XF86VideoAdaptorRec) +
427                              sizeof(intel_adaptor_private) +
428                              sizeof(DevUnion))))
429                 return NULL;
430
431         adapt->type = XvWindowMask | XvInputMask | XvImageMask;
432         adapt->flags = VIDEO_OVERLAID_IMAGES /*| VIDEO_CLIP_TO_VIEWPORT */ ;
433         adapt->name = "Intel(R) Video Overlay";
434         adapt->nEncodings = 1;
435         adapt->pEncodings = xnfalloc(sizeof(DummyEncoding));
436         memcpy(adapt->pEncodings, DummyEncoding, sizeof(DummyEncoding));
437         if (IS_845G(intel) || IS_I830(intel)) {
438                 adapt->pEncodings->width = IMAGE_MAX_WIDTH_LEGACY;
439                 adapt->pEncodings->height = IMAGE_MAX_HEIGHT_LEGACY;
440         }
441         adapt->nFormats = NUM_FORMATS;
442         adapt->pFormats = Formats;
443         adapt->nPorts = 1;
444         adapt->pPortPrivates = (DevUnion *) (&adapt[1]);
445
446         adaptor_priv = (intel_adaptor_private *)&adapt->pPortPrivates[1];
447
448         adapt->pPortPrivates[0].ptr = (pointer) (adaptor_priv);
449         adapt->nAttributes = NUM_ATTRIBUTES;
450         if (INTEL_INFO(intel)->gen >= 30)
451                 adapt->nAttributes += GAMMA_ATTRIBUTES; /* has gamma */
452         adapt->pAttributes =
453             xnfalloc(sizeof(XF86AttributeRec) * adapt->nAttributes);
454         /* Now copy the attributes */
455         att = adapt->pAttributes;
456         memcpy((char *)att, (char *)Attributes,
457                sizeof(XF86AttributeRec) * NUM_ATTRIBUTES);
458         att += NUM_ATTRIBUTES;
459         if (INTEL_INFO(intel)->gen >= 30) {
460                 memcpy((char *)att, (char *)GammaAttributes,
461                        sizeof(XF86AttributeRec) * GAMMA_ATTRIBUTES);
462                 att += GAMMA_ATTRIBUTES;
463         }
464         adapt->nImages = NUM_IMAGES - XVMC_IMAGE;
465
466         adapt->pImages = Images;
467         adapt->PutVideo = NULL;
468         adapt->PutStill = NULL;
469         adapt->GetVideo = NULL;
470         adapt->GetStill = NULL;
471         adapt->StopVideo = I830StopVideo;
472         adapt->SetPortAttribute = I830SetPortAttributeOverlay;
473         adapt->GetPortAttribute = I830GetPortAttribute;
474         adapt->QueryBestSize = I830QueryBestSize;
475         adapt->PutImage = I830PutImageOverlay;
476         adapt->QueryImageAttributes = I830QueryImageAttributes;
477
478         adaptor_priv->textured = FALSE;
479         adaptor_priv->colorKey = intel->colorKey & ((1 << scrn->depth) - 1);
480         adaptor_priv->videoStatus = 0;
481         adaptor_priv->brightness = -19; /* (255/219) * -16 */
482         adaptor_priv->contrast = 75;    /* 255/219 * 64 */
483         adaptor_priv->saturation = 146; /* 128/112 * 128 */
484         adaptor_priv->desired_crtc = NULL;
485         adaptor_priv->buf = NULL;
486         adaptor_priv->old_buf[0] = NULL;
487         adaptor_priv->old_buf[1] = NULL;
488         adaptor_priv->gamma5 = 0xc0c0c0;
489         adaptor_priv->gamma4 = 0x808080;
490         adaptor_priv->gamma3 = 0x404040;
491         adaptor_priv->gamma2 = 0x202020;
492         adaptor_priv->gamma1 = 0x101010;
493         adaptor_priv->gamma0 = 0x080808;
494
495         adaptor_priv->rotation = RR_Rotate_0;
496
497         /* gotta uninit this someplace */
498         REGION_NULL(screen, &adaptor_priv->clip);
499
500         intel->adaptor = adapt;
501
502         xvColorKey = MAKE_ATOM("XV_COLORKEY");
503         xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
504         xvContrast = MAKE_ATOM("XV_CONTRAST");
505         xvSaturation = MAKE_ATOM("XV_SATURATION");
506
507         /* Allow the pipe to be switched from pipe A to B when in clone mode */
508         xvPipe = MAKE_ATOM("XV_PIPE");
509
510         if (INTEL_INFO(intel)->gen >= 30) {
511                 xvGamma0 = MAKE_ATOM("XV_GAMMA0");
512                 xvGamma1 = MAKE_ATOM("XV_GAMMA1");
513                 xvGamma2 = MAKE_ATOM("XV_GAMMA2");
514                 xvGamma3 = MAKE_ATOM("XV_GAMMA3");
515                 xvGamma4 = MAKE_ATOM("XV_GAMMA4");
516                 xvGamma5 = MAKE_ATOM("XV_GAMMA5");
517         }
518
519         intel_overlay_update_attrs(intel);
520
521         return adapt;
522 }
523
524 static XF86VideoAdaptorPtr I830SetupImageVideoTextured(ScreenPtr screen)
525 {
526         ScrnInfoPtr scrn = xf86Screens[screen->myNum];
527         intel_screen_private *intel = intel_get_screen_private(scrn);
528         XF86VideoAdaptorPtr adapt;
529         XF86AttributePtr attrs;
530         intel_adaptor_private *adaptor_privs;
531         DevUnion *devUnions;
532         int nports = 16, i;
533         int nAttributes;
534
535         OVERLAY_DEBUG("I830SetupImageVideoOverlay\n");
536
537         nAttributes = NUM_TEXTURED_ATTRIBUTES;
538
539         adapt = calloc(1, sizeof(XF86VideoAdaptorRec));
540         adaptor_privs = calloc(nports, sizeof(intel_adaptor_private));
541         devUnions = calloc(nports, sizeof(DevUnion));
542         attrs = calloc(nAttributes, sizeof(XF86AttributeRec));
543         if (adapt == NULL || adaptor_privs == NULL || devUnions == NULL ||
544             attrs == NULL) {
545                 free(adapt);
546                 free(adaptor_privs);
547                 free(devUnions);
548                 free(attrs);
549                 return NULL;
550         }
551
552         adapt->type = XvWindowMask | XvInputMask | XvImageMask;
553         adapt->flags = 0;
554         adapt->name = "Intel(R) Textured Video";
555         adapt->nEncodings = 1;
556         adapt->pEncodings = xnfalloc(sizeof(DummyEncoding));
557         memcpy(adapt->pEncodings, DummyEncoding, sizeof(DummyEncoding));
558         adapt->nFormats = NUM_FORMATS;
559         adapt->pFormats = Formats;
560         adapt->nPorts = nports;
561         adapt->pPortPrivates = devUnions;
562         adapt->nAttributes = nAttributes;
563         adapt->pAttributes = attrs;
564         memcpy(attrs, TexturedAttributes,
565                nAttributes * sizeof(XF86AttributeRec));
566         if (IS_I915G(intel) || IS_I915GM(intel))
567                 adapt->nImages = NUM_IMAGES - XVMC_IMAGE;
568         else
569                 adapt->nImages = NUM_IMAGES;
570
571         adapt->pImages = Images;
572         adapt->PutVideo = NULL;
573         adapt->PutStill = NULL;
574         adapt->GetVideo = NULL;
575         adapt->GetStill = NULL;
576         adapt->StopVideo = I830StopVideo;
577         adapt->SetPortAttribute = I830SetPortAttributeTextured;
578         adapt->GetPortAttribute = I830GetPortAttribute;
579         adapt->QueryBestSize = I830QueryBestSize;
580         adapt->PutImage = I830PutImageTextured;
581         adapt->QueryImageAttributes = I830QueryImageAttributes;
582
583         for (i = 0; i < nports; i++) {
584                 intel_adaptor_private *adaptor_priv = &adaptor_privs[i];
585
586                 adaptor_priv->textured = TRUE;
587                 adaptor_priv->videoStatus = 0;
588                 adaptor_priv->buf = NULL;
589                 adaptor_priv->old_buf[0] = NULL;
590                 adaptor_priv->old_buf[1] = NULL;
591
592                 adaptor_priv->rotation = RR_Rotate_0;
593                 adaptor_priv->SyncToVblank = 1;
594
595                 /* gotta uninit this someplace, XXX: shouldn't be necessary for textured */
596                 REGION_NULL(screen, &adaptor_priv->clip);
597
598                 adapt->pPortPrivates[i].ptr = (pointer) (adaptor_priv);
599         }
600
601         xvSyncToVblank = MAKE_ATOM("XV_SYNC_TO_VBLANK");
602
603         return adapt;
604 }
605
606 static void intel_free_video_buffers(intel_adaptor_private *adaptor_priv)
607 {
608         int i;
609
610         for (i = 0; i < 2; i++) {
611                 if (adaptor_priv->old_buf[i]) {
612                         drm_intel_bo_disable_reuse(adaptor_priv->old_buf[i]);
613                         drm_intel_bo_unreference(adaptor_priv->old_buf[i]);
614                         adaptor_priv->old_buf[i] = NULL;
615                 }
616         }
617
618         if (adaptor_priv->buf) {
619                 drm_intel_bo_unreference(adaptor_priv->buf);
620                 adaptor_priv->buf = NULL;
621         }
622 }
623
624 static void I830StopVideo(ScrnInfoPtr scrn, pointer data, Bool shutdown)
625 {
626         intel_adaptor_private *adaptor_priv = (intel_adaptor_private *) data;
627
628         if (adaptor_priv->textured)
629                 return;
630
631         OVERLAY_DEBUG("I830StopVideo\n");
632
633         REGION_EMPTY(scrn->pScreen, &adaptor_priv->clip);
634
635         if (shutdown) {
636                 if (adaptor_priv->videoStatus & CLIENT_VIDEO_ON)
637                         intel_overlay_off(intel_get_screen_private(scrn));
638
639                 intel_free_video_buffers(adaptor_priv);
640                 adaptor_priv->videoStatus = 0;
641         } else {
642                 if (adaptor_priv->videoStatus & CLIENT_VIDEO_ON) {
643                         adaptor_priv->videoStatus |= OFF_TIMER;
644                         adaptor_priv->offTime = currentTime.milliseconds + OFF_DELAY;
645                 }
646         }
647
648 }
649
650 static int
651 I830SetPortAttributeTextured(ScrnInfoPtr scrn,
652                              Atom attribute, INT32 value, pointer data)
653 {
654         intel_adaptor_private *adaptor_priv = (intel_adaptor_private *) data;
655
656         if (attribute == xvBrightness) {
657                 if ((value < -128) || (value > 127))
658                         return BadValue;
659                 adaptor_priv->brightness = value;
660                 return Success;
661         } else if (attribute == xvContrast) {
662                 if ((value < 0) || (value > 255))
663                         return BadValue;
664                 adaptor_priv->contrast = value;
665                 return Success;
666         } else if (attribute == xvSyncToVblank) {
667                 if ((value < -1) || (value > 1))
668                         return BadValue;
669                 adaptor_priv->SyncToVblank = value;
670                 return Success;
671         } else {
672                 return BadMatch;
673         }
674 }
675
676 static int
677 I830SetPortAttributeOverlay(ScrnInfoPtr scrn,
678                             Atom attribute, INT32 value, pointer data)
679 {
680         intel_adaptor_private *adaptor_priv = (intel_adaptor_private *) data;
681         intel_screen_private *intel = intel_get_screen_private(scrn);
682
683         if (attribute == xvBrightness) {
684                 if ((value < -128) || (value > 127))
685                         return BadValue;
686                 adaptor_priv->brightness = value;
687                 OVERLAY_DEBUG("BRIGHTNESS\n");
688         } else if (attribute == xvContrast) {
689                 if ((value < 0) || (value > 255))
690                         return BadValue;
691                 adaptor_priv->contrast = value;
692                 OVERLAY_DEBUG("CONTRAST\n");
693         } else if (attribute == xvSaturation) {
694                 if ((value < 0) || (value > 1023))
695                         return BadValue;
696                 adaptor_priv->saturation = value;
697         } else if (attribute == xvPipe) {
698                 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
699                 if ((value < -1) || (value > xf86_config->num_crtc))
700                         return BadValue;
701                 if (value < 0)
702                         adaptor_priv->desired_crtc = NULL;
703                 else
704                         adaptor_priv->desired_crtc = xf86_config->crtc[value];
705         } else if (attribute == xvGamma0 && (INTEL_INFO(intel)->gen >= 30)) {
706                 adaptor_priv->gamma0 = value;
707         } else if (attribute == xvGamma1 && (INTEL_INFO(intel)->gen >= 30)) {
708                 adaptor_priv->gamma1 = value;
709         } else if (attribute == xvGamma2 && (INTEL_INFO(intel)->gen >= 30)) {
710                 adaptor_priv->gamma2 = value;
711         } else if (attribute == xvGamma3 && (INTEL_INFO(intel)->gen >= 30)) {
712                 adaptor_priv->gamma3 = value;
713         } else if (attribute == xvGamma4 && (INTEL_INFO(intel)->gen >= 30)) {
714                 adaptor_priv->gamma4 = value;
715         } else if (attribute == xvGamma5 && (INTEL_INFO(intel)->gen >= 30)) {
716                 adaptor_priv->gamma5 = value;
717         } else if (attribute == xvColorKey) {
718                 adaptor_priv->colorKey = value;
719                 OVERLAY_DEBUG("COLORKEY\n");
720         } else
721                 return BadMatch;
722
723         if ((attribute == xvGamma0 ||
724              attribute == xvGamma1 ||
725              attribute == xvGamma2 ||
726              attribute == xvGamma3 ||
727              attribute == xvGamma4 ||
728              attribute == xvGamma5) && (INTEL_INFO(intel)->gen >= 30)) {
729                 OVERLAY_DEBUG("GAMMA\n");
730         }
731
732         intel_overlay_update_attrs(intel);
733
734         if (attribute == xvColorKey)
735                 REGION_EMPTY(scrn->pScreen, &adaptor_priv->clip);
736
737         return Success;
738 }
739
740 static int
741 I830GetPortAttribute(ScrnInfoPtr scrn,
742                      Atom attribute, INT32 * value, pointer data)
743 {
744         intel_screen_private *intel = intel_get_screen_private(scrn);
745         intel_adaptor_private *adaptor_priv = (intel_adaptor_private *) data;
746
747         if (attribute == xvBrightness) {
748                 *value = adaptor_priv->brightness;
749         } else if (attribute == xvContrast) {
750                 *value = adaptor_priv->contrast;
751         } else if (attribute == xvSaturation) {
752                 *value = adaptor_priv->saturation;
753         } else if (attribute == xvPipe) {
754                 int c;
755                 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
756                 for (c = 0; c < xf86_config->num_crtc; c++)
757                         if (xf86_config->crtc[c] == adaptor_priv->desired_crtc)
758                                 break;
759                 if (c == xf86_config->num_crtc)
760                         c = -1;
761                 *value = c;
762         } else if (attribute == xvGamma0 && (INTEL_INFO(intel)->gen >= 30)) {
763                 *value = adaptor_priv->gamma0;
764         } else if (attribute == xvGamma1 && (INTEL_INFO(intel)->gen >= 30)) {
765                 *value = adaptor_priv->gamma1;
766         } else if (attribute == xvGamma2 && (INTEL_INFO(intel)->gen >= 30)) {
767                 *value = adaptor_priv->gamma2;
768         } else if (attribute == xvGamma3 && (INTEL_INFO(intel)->gen >= 30)) {
769                 *value = adaptor_priv->gamma3;
770         } else if (attribute == xvGamma4 && (INTEL_INFO(intel)->gen >= 30)) {
771                 *value = adaptor_priv->gamma4;
772         } else if (attribute == xvGamma5 && (INTEL_INFO(intel)->gen >= 30)) {
773                 *value = adaptor_priv->gamma5;
774         } else if (attribute == xvColorKey) {
775                 *value = adaptor_priv->colorKey;
776         } else if (attribute == xvSyncToVblank) {
777                 *value = adaptor_priv->SyncToVblank;
778         } else
779                 return BadMatch;
780
781         return Success;
782 }
783
784 static void
785 I830QueryBestSize(ScrnInfoPtr scrn,
786                   Bool motion,
787                   short vid_w, short vid_h,
788                   short drw_w, short drw_h,
789                   unsigned int *p_w, unsigned int *p_h, pointer data)
790 {
791         if (vid_w > (drw_w << 1))
792                 drw_w = vid_w >> 1;
793         if (vid_h > (drw_h << 1))
794                 drw_h = vid_h >> 1;
795
796         *p_w = drw_w;
797         *p_h = drw_h;
798 }
799
800 static Bool
801 I830CopyPackedData(intel_adaptor_private *adaptor_priv,
802                    unsigned char *buf,
803                    int srcPitch, int dstPitch, int top, int left, int h, int w)
804 {
805         unsigned char *src, *dst, *dst_base;
806         int i, j;
807         unsigned char *s;
808
809 #if 0
810         ErrorF("I830CopyPackedData: (%d,%d) (%d,%d)\n"
811                "srcPitch: %d, dstPitch: %d\n", top, left, h, w,
812                srcPitch, dstPitch);
813 #endif
814
815         src = buf + (top * srcPitch) + (left << 1);
816
817         if (drm_intel_gem_bo_map_gtt(adaptor_priv->buf))
818                 return FALSE;
819
820         dst_base = adaptor_priv->buf->virtual;
821
822         dst = dst_base + adaptor_priv->YBufOffset;
823
824         switch (adaptor_priv->rotation) {
825         case RR_Rotate_0:
826                 w <<= 1;
827                 for (i = 0; i < h; i++) {
828                         memcpy(dst, src, w);
829                         src += srcPitch;
830                         dst += dstPitch;
831                 }
832                 break;
833         case RR_Rotate_90:
834                 h <<= 1;
835                 for (i = 0; i < h; i += 2) {
836                         s = src;
837                         for (j = 0; j < w; j++) {
838                                 /* Copy Y */
839                                 dst[(i + 0) + ((w - j - 1) * dstPitch)] = *s++;
840                                 (void)*s++;
841                         }
842                         src += srcPitch;
843                 }
844                 h >>= 1;
845                 src = buf + (top * srcPitch) + (left << 1);
846                 for (i = 0; i < h; i += 2) {
847                         for (j = 0; j < w; j += 2) {
848                                 /* Copy U */
849                                 dst[((i * 2) + 1) + ((w - j - 1) * dstPitch)] =
850                                     src[(j * 2) + 1 + (i * srcPitch)];
851                                 dst[((i * 2) + 1) + ((w - j - 2) * dstPitch)] =
852                                     src[(j * 2) + 1 + ((i + 1) * srcPitch)];
853                                 /* Copy V */
854                                 dst[((i * 2) + 3) + ((w - j - 1) * dstPitch)] =
855                                     src[(j * 2) + 3 + (i * srcPitch)];
856                                 dst[((i * 2) + 3) + ((w - j - 2) * dstPitch)] =
857                                     src[(j * 2) + 3 + ((i + 1) * srcPitch)];
858                         }
859                 }
860                 break;
861         case RR_Rotate_180:
862                 w <<= 1;
863                 for (i = 0; i < h; i++) {
864                         s = src;
865                         for (j = 0; j < w; j += 4) {
866                                 dst[(w - j - 4) + ((h - i - 1) * dstPitch)] =
867                                     *s++;
868                                 dst[(w - j - 3) + ((h - i - 1) * dstPitch)] =
869                                     *s++;
870                                 dst[(w - j - 2) + ((h - i - 1) * dstPitch)] =
871                                     *s++;
872                                 dst[(w - j - 1) + ((h - i - 1) * dstPitch)] =
873                                     *s++;
874                         }
875                         src += srcPitch;
876                 }
877                 break;
878         case RR_Rotate_270:
879                 h <<= 1;
880                 for (i = 0; i < h; i += 2) {
881                         s = src;
882                         for (j = 0; j < w; j++) {
883                                 /* Copy Y */
884                                 dst[(h - i - 2) + (j * dstPitch)] = *s++;
885                                 (void)*s++;
886                         }
887                         src += srcPitch;
888                 }
889                 h >>= 1;
890                 src = buf + (top * srcPitch) + (left << 1);
891                 for (i = 0; i < h; i += 2) {
892                         for (j = 0; j < w; j += 2) {
893                                 /* Copy U */
894                                 dst[(((h - i) * 2) - 3) + (j * dstPitch)] =
895                                     src[(j * 2) + 1 + (i * srcPitch)];
896                                 dst[(((h - i) * 2) - 3) +
897                                     ((j + 1) * dstPitch)] =
898                                     src[(j * 2) + 1 + ((i + 1) * srcPitch)];
899                                 /* Copy V */
900                                 dst[(((h - i) * 2) - 1) + (j * dstPitch)] =
901                                     src[(j * 2) + 3 + (i * srcPitch)];
902                                 dst[(((h - i) * 2) - 1) +
903                                     ((j + 1) * dstPitch)] =
904                                     src[(j * 2) + 3 + ((i + 1) * srcPitch)];
905                         }
906                 }
907                 break;
908         }
909
910         drm_intel_gem_bo_unmap_gtt(adaptor_priv->buf);
911         return TRUE;
912 }
913
914 static void intel_memcpy_plane(unsigned char *dst, unsigned char *src,
915                                int height, int width,
916                                int dstPitch, int srcPitch, Rotation rotation)
917 {
918         int i, j = 0;
919         unsigned char *s;
920
921         switch (rotation) {
922         case RR_Rotate_0:
923                 /* optimise for the case of no clipping */
924                 if (srcPitch == dstPitch && srcPitch == width)
925                         memcpy(dst, src, srcPitch * height);
926                 else
927                         for (i = 0; i < height; i++) {
928                                 memcpy(dst, src, width);
929                                 src += srcPitch;
930                                 dst += dstPitch;
931                         }
932                 break;
933         case RR_Rotate_90:
934                 for (i = 0; i < height; i++) {
935                         s = src;
936                         for (j = 0; j < width; j++) {
937                                 dst[(i) + ((width - j - 1) * dstPitch)] = *s++;
938                         }
939                         src += srcPitch;
940                 }
941                 break;
942         case RR_Rotate_180:
943                 for (i = 0; i < height; i++) {
944                         s = src;
945                         for (j = 0; j < width; j++) {
946                                 dst[(width - j - 1) +
947                                     ((height - i - 1) * dstPitch)] = *s++;
948                         }
949                         src += srcPitch;
950                 }
951                 break;
952         case RR_Rotate_270:
953                 for (i = 0; i < height; i++) {
954                         s = src;
955                         for (j = 0; j < width; j++) {
956                                 dst[(height - i - 1) + (j * dstPitch)] = *s++;
957                         }
958                         src += srcPitch;
959                 }
960                 break;
961         }
962 }
963
964 static Bool
965 I830CopyPlanarData(intel_adaptor_private *adaptor_priv,
966                    unsigned char *buf, int srcPitch, int srcPitch2,
967                    int dstPitch, int dstPitch2,
968                    int srcH, int top, int left,
969                    int h, int w, int id)
970 {
971         unsigned char *src1, *src2, *src3, *dst_base, *dst1, *dst2, *dst3;
972
973 #if 0
974         ErrorF("I830CopyPlanarData: srcPitch %d, srcPitch %d, dstPitch %d\n"
975                "nlines %d, npixels %d, top %d, left %d\n",
976                srcPitch, srcPitch2, dstPitch, h, w, top, left);
977 #endif
978
979         /* Copy Y data */
980         src1 = buf + (top * srcPitch) + left;
981 #if 0
982         ErrorF("src1 is %p, offset is %ld\n", src1,
983                (unsigned long)src1 - (unsigned long)buf);
984 #endif
985
986         if (drm_intel_gem_bo_map_gtt(adaptor_priv->buf))
987                 return FALSE;
988
989         dst_base = adaptor_priv->buf->virtual;
990
991         dst1 = dst_base + adaptor_priv->YBufOffset;
992
993         intel_memcpy_plane(dst1, src1, h, w, dstPitch2, srcPitch,
994                           adaptor_priv->rotation);
995
996         /* Copy V data for YV12, or U data for I420 */
997         src2 = buf +            /* start of YUV data */
998             (srcH * srcPitch) + /* move over Luma plane */
999             ((top >> 1) * srcPitch2) +  /* move down from by top lines */
1000             (left >> 1);        /* move left by left pixels */
1001
1002 #if 0
1003         ErrorF("src2 is %p, offset is %ld\n", src2,
1004                (unsigned long)src2 - (unsigned long)buf);
1005 #endif
1006         if (id == FOURCC_I420)
1007                 dst2 = dst_base + adaptor_priv->UBufOffset;
1008         else
1009                 dst2 = dst_base + adaptor_priv->VBufOffset;
1010
1011         intel_memcpy_plane(dst2, src2, h / 2, w / 2,
1012                           dstPitch, srcPitch2, adaptor_priv->rotation);
1013
1014         /* Copy U data for YV12, or V data for I420 */
1015         src3 = buf +            /* start of YUV data */
1016             (srcH * srcPitch) + /* move over Luma plane */
1017             ((srcH >> 1) * srcPitch2) + /* move over Chroma plane */
1018             ((top >> 1) * srcPitch2) +  /* move down from by top lines */
1019             (left >> 1);        /* move left by left pixels */
1020 #if 0
1021         ErrorF("src3 is %p, offset is %ld\n", src3,
1022                (unsigned long)src3 - (unsigned long)buf);
1023 #endif
1024         if (id == FOURCC_I420)
1025                 dst3 = dst_base + adaptor_priv->VBufOffset;
1026         else
1027                 dst3 = dst_base + adaptor_priv->UBufOffset;
1028
1029         intel_memcpy_plane(dst3, src3, h / 2, w / 2,
1030                           dstPitch, srcPitch2, adaptor_priv->rotation);
1031
1032         drm_intel_gem_bo_unmap_gtt(adaptor_priv->buf);
1033         return TRUE;
1034 }
1035
1036 static void intel_box_intersect(BoxPtr dest, BoxPtr a, BoxPtr b)
1037 {
1038         dest->x1 = a->x1 > b->x1 ? a->x1 : b->x1;
1039         dest->x2 = a->x2 < b->x2 ? a->x2 : b->x2;
1040         dest->y1 = a->y1 > b->y1 ? a->y1 : b->y1;
1041         dest->y2 = a->y2 < b->y2 ? a->y2 : b->y2;
1042         if (dest->x1 >= dest->x2 || dest->y1 >= dest->y2)
1043                 dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0;
1044 }
1045
1046 static void intel_crtc_box(xf86CrtcPtr crtc, BoxPtr crtc_box)
1047 {
1048         if (crtc->enabled) {
1049                 crtc_box->x1 = crtc->x;
1050                 crtc_box->x2 =
1051                     crtc->x + xf86ModeWidth(&crtc->mode, crtc->rotation);
1052                 crtc_box->y1 = crtc->y;
1053                 crtc_box->y2 =
1054                     crtc->y + xf86ModeHeight(&crtc->mode, crtc->rotation);
1055         } else
1056                 crtc_box->x1 = crtc_box->x2 = crtc_box->y1 = crtc_box->y2 = 0;
1057 }
1058
1059 static int intel_box_area(BoxPtr box)
1060 {
1061         return (int)(box->x2 - box->x1) * (int)(box->y2 - box->y1);
1062 }
1063
1064 /*
1065  * Return the crtc covering 'box'. If two crtcs cover a portion of
1066  * 'box', then prefer 'desired'. If 'desired' is NULL, then prefer the crtc
1067  * with greater coverage
1068  */
1069
1070 xf86CrtcPtr
1071 intel_covering_crtc(ScrnInfoPtr scrn,
1072                     BoxPtr box, xf86CrtcPtr desired, BoxPtr crtc_box_ret)
1073 {
1074         xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
1075         xf86CrtcPtr crtc, best_crtc;
1076         int coverage, best_coverage;
1077         int c;
1078         BoxRec crtc_box, cover_box;
1079
1080         best_crtc = NULL;
1081         best_coverage = 0;
1082         crtc_box_ret->x1 = 0;
1083         crtc_box_ret->x2 = 0;
1084         crtc_box_ret->y1 = 0;
1085         crtc_box_ret->y2 = 0;
1086         for (c = 0; c < xf86_config->num_crtc; c++) {
1087                 crtc = xf86_config->crtc[c];
1088
1089                 /* If the CRTC is off, treat it as not covering */
1090                 if (!intel_crtc_on(crtc))
1091                         continue;
1092
1093                 intel_crtc_box(crtc, &crtc_box);
1094                 intel_box_intersect(&cover_box, &crtc_box, box);
1095                 coverage = intel_box_area(&cover_box);
1096                 if (coverage && crtc == desired) {
1097                         *crtc_box_ret = crtc_box;
1098                         return crtc;
1099                 }
1100                 if (coverage > best_coverage) {
1101                         *crtc_box_ret = crtc_box;
1102                         best_crtc = crtc;
1103                         best_coverage = coverage;
1104                 }
1105         }
1106         return best_crtc;
1107 }
1108
1109 static void
1110 intel_update_dst_box_to_crtc_coords(ScrnInfoPtr scrn, xf86CrtcPtr crtc,
1111                                     BoxPtr dstBox)
1112 {
1113         int tmp;
1114
1115         /* for overlay, we should take it from crtc's screen
1116          * coordinate to current crtc's display mode.
1117          * yeah, a bit confusing.
1118          */
1119         switch (crtc->rotation & 0xf) {
1120         case RR_Rotate_0:
1121                 dstBox->x1 -= crtc->x;
1122                 dstBox->x2 -= crtc->x;
1123                 dstBox->y1 -= crtc->y;
1124                 dstBox->y2 -= crtc->y;
1125                 break;
1126         case RR_Rotate_90:
1127                 tmp = dstBox->x1;
1128                 dstBox->x1 = dstBox->y1 - crtc->x;
1129                 dstBox->y1 = scrn->virtualX - tmp - crtc->y;
1130                 tmp = dstBox->x2;
1131                 dstBox->x2 = dstBox->y2 - crtc->x;
1132                 dstBox->y2 = scrn->virtualX - tmp - crtc->y;
1133                 tmp = dstBox->y1;
1134                 dstBox->y1 = dstBox->y2;
1135                 dstBox->y2 = tmp;
1136                 break;
1137         case RR_Rotate_180:
1138                 tmp = dstBox->x1;
1139                 dstBox->x1 = scrn->virtualX - dstBox->x2 - crtc->x;
1140                 dstBox->x2 = scrn->virtualX - tmp - crtc->x;
1141                 tmp = dstBox->y1;
1142                 dstBox->y1 = scrn->virtualY - dstBox->y2 - crtc->y;
1143                 dstBox->y2 = scrn->virtualY - tmp - crtc->y;
1144                 break;
1145         case RR_Rotate_270:
1146                 tmp = dstBox->x1;
1147                 dstBox->x1 = scrn->virtualY - dstBox->y1 - crtc->x;
1148                 dstBox->y1 = tmp - crtc->y;
1149                 tmp = dstBox->x2;
1150                 dstBox->x2 = scrn->virtualY - dstBox->y2 - crtc->x;
1151                 dstBox->y2 = tmp - crtc->y;
1152                 tmp = dstBox->x1;
1153                 dstBox->x1 = dstBox->x2;
1154                 dstBox->x2 = tmp;
1155                 break;
1156         }
1157
1158         return;
1159 }
1160
1161 int is_planar_fourcc(int id)
1162 {
1163         switch (id) {
1164         case FOURCC_YV12:
1165         case FOURCC_I420:
1166 #ifdef INTEL_XVMC
1167         case FOURCC_XVMC:
1168 #endif
1169                 return 1;
1170         case FOURCC_UYVY:
1171         case FOURCC_YUY2:
1172                 return 0;
1173         default:
1174                 ErrorF("Unknown format 0x%x\n", id);
1175                 return 0;
1176         }
1177 }
1178
1179 static int xvmc_passthrough(int id)
1180 {
1181 #ifdef INTEL_XVMC
1182         return id == FOURCC_XVMC;
1183 #else
1184         return 0;
1185 #endif
1186 }
1187
1188 static Bool
1189 intel_display_overlay(ScrnInfoPtr scrn, xf86CrtcPtr crtc,
1190                       int id, short width, short height,
1191                       int dstPitch, int dstPitch2,
1192                       BoxPtr dstBox, short src_w, short src_h, short drw_w,
1193                       short drw_h)
1194 {
1195         intel_screen_private *intel = intel_get_screen_private(scrn);
1196         int tmp;
1197
1198         OVERLAY_DEBUG("I830DisplayVideo: %dx%d (pitch %d)\n", width, height,
1199                       dstPitch);
1200
1201         /*
1202          * If the video isn't visible on any CRTC, turn it off
1203          */
1204         if (!crtc) {
1205                 intel_overlay_off(intel);
1206                 return TRUE;
1207         }
1208
1209         intel_update_dst_box_to_crtc_coords(scrn, crtc, dstBox);
1210
1211         if (crtc->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
1212                 tmp = width;
1213                 width = height;
1214                 height = tmp;
1215                 tmp = drw_w;
1216                 drw_w = drw_h;
1217                 drw_h = tmp;
1218                 tmp = src_w;
1219                 src_w = src_h;
1220                 src_h = tmp;
1221         }
1222
1223         return intel_overlay_put_image(intel, crtc, id,
1224                                          width, height,
1225                                          dstPitch, dstPitch2, dstBox,
1226                                          src_w, src_h, drw_w, drw_h);
1227 }
1228
1229 static Bool
1230 intel_clip_video_helper(ScrnInfoPtr scrn,
1231                         intel_adaptor_private *adaptor_priv,
1232                         xf86CrtcPtr * crtc_ret,
1233                         BoxPtr dst,
1234                         short src_x, short src_y,
1235                         short drw_x, short drw_y,
1236                         short src_w, short src_h,
1237                         short drw_w, short drw_h,
1238                         int id,
1239                         int *top, int* left, int* npixels, int *nlines,
1240                         RegionPtr reg, INT32 width, INT32 height)
1241 {
1242         Bool ret;
1243         RegionRec crtc_region_local;
1244         RegionPtr crtc_region = reg;
1245         BoxRec crtc_box;
1246         INT32 x1, x2, y1, y2;
1247         xf86CrtcPtr crtc;
1248
1249         x1 = src_x;
1250         x2 = src_x + src_w;
1251         y1 = src_y;
1252         y2 = src_y + src_h;
1253
1254         dst->x1 = drw_x;
1255         dst->x2 = drw_x + drw_w;
1256         dst->y1 = drw_y;
1257         dst->y2 = drw_y + drw_h;
1258
1259         /*
1260          * For overlay video, compute the relevant CRTC and
1261          * clip video to that
1262          */
1263         crtc = intel_covering_crtc(scrn, dst, adaptor_priv->desired_crtc,
1264                                    &crtc_box);
1265
1266         /* For textured video, we don't actually want to clip at all. */
1267         if (crtc && !adaptor_priv->textured) {
1268                 REGION_INIT(screen, &crtc_region_local, &crtc_box, 1);
1269                 crtc_region = &crtc_region_local;
1270                 REGION_INTERSECT(screen, crtc_region, crtc_region,
1271                                  reg);
1272         }
1273         *crtc_ret = crtc;
1274
1275         ret = xf86XVClipVideoHelper(dst, &x1, &x2, &y1, &y2,
1276                                     crtc_region, width, height);
1277         if (crtc_region != reg)
1278                 REGION_UNINIT(screen, &crtc_region_local);
1279
1280         *top = y1 >> 16;
1281         *left = (x1 >> 16) & ~1;
1282         *npixels = ALIGN(((x2 + 0xffff) >> 16), 2) - *left;
1283         if (is_planar_fourcc(id)) {
1284                 *top &= ~1;
1285                 *nlines = ALIGN(((y2 + 0xffff) >> 16), 2) - *top;
1286         } else
1287                 *nlines = ((y2 + 0xffff) >> 16) - *top;
1288
1289         return ret;
1290 }
1291
1292 static void
1293 intel_wait_for_scanline(ScrnInfoPtr scrn, PixmapPtr pixmap,
1294                         xf86CrtcPtr crtc, RegionPtr clipBoxes)
1295 {
1296         intel_screen_private *intel = intel_get_screen_private(scrn);
1297         pixman_box16_t box, crtc_box;
1298         int pipe, event;
1299         Bool full_height;
1300         int y1, y2;
1301
1302         pipe = -1;
1303         if (pixmap_is_scanout(pixmap))
1304                 pipe = intel_crtc_to_pipe(crtc);
1305         if (pipe < 0)
1306                 return;
1307
1308         box = *REGION_EXTENTS(unused, clipBoxes);
1309
1310         if (crtc->transform_in_use)
1311                 pixman_f_transform_bounds(&crtc->f_framebuffer_to_crtc, &box);
1312
1313         /* We could presume the clip was correctly computed... */
1314         intel_crtc_box(crtc, &crtc_box);
1315         intel_box_intersect(&box, &crtc_box, &box);
1316
1317         /*
1318          * Make sure we don't wait for a scanline that will
1319          * never occur
1320          */
1321         y1 = (crtc_box.y1 <= box.y1) ? box.y1 - crtc_box.y1 : 0;
1322         y2 = (box.y2 <= crtc_box.y2) ?
1323                 box.y2 - crtc_box.y1 : crtc_box.y2 - crtc_box.y1;
1324         if (y2 <= y1)
1325                 return;
1326
1327         full_height = FALSE;
1328         if (y1 == 0 && y2 == (crtc_box.y2 - crtc_box.y1))
1329                 full_height = TRUE;
1330
1331         /*
1332          * Pre-965 doesn't have SVBLANK, so we need a bit
1333          * of extra time for the blitter to start up and
1334          * do its job for a full height blit
1335          */
1336         if (full_height && INTEL_INFO(intel)->gen < 40)
1337                 y2 -= 2;
1338
1339         if (pipe == 0) {
1340                 pipe = MI_LOAD_SCAN_LINES_DISPLAY_PIPEA;
1341                 event = MI_WAIT_FOR_PIPEA_SCAN_LINE_WINDOW;
1342                 if (full_height && INTEL_INFO(intel)->gen >= 40)
1343                         event = MI_WAIT_FOR_PIPEA_SVBLANK;
1344         } else {
1345                 pipe = MI_LOAD_SCAN_LINES_DISPLAY_PIPEB;
1346                 event = MI_WAIT_FOR_PIPEB_SCAN_LINE_WINDOW;
1347                 if (full_height && INTEL_INFO(intel)->gen >= 40)
1348                         event = MI_WAIT_FOR_PIPEB_SVBLANK;
1349         }
1350
1351         if (crtc->mode.Flags & V_INTERLACE) {
1352                 /* DSL count field lines */
1353                 y1 /= 2;
1354                 y2 /= 2;
1355         }
1356
1357         BEGIN_BATCH(5);
1358         /* The documentation says that the LOAD_SCAN_LINES command
1359          * always comes in pairs. Don't ask me why. */
1360         OUT_BATCH(MI_LOAD_SCAN_LINES_INCL | pipe);
1361         OUT_BATCH((y1 << 16) | (y2-1));
1362         OUT_BATCH(MI_LOAD_SCAN_LINES_INCL | pipe);
1363         OUT_BATCH((y1 << 16) | (y2-1));
1364         OUT_BATCH(MI_WAIT_FOR_EVENT | event);
1365         ADVANCE_BATCH();
1366 }
1367
1368 static Bool
1369 intel_setup_video_buffer(ScrnInfoPtr scrn, intel_adaptor_private *adaptor_priv,
1370                          int alloc_size, int id, unsigned char *buf)
1371 {
1372         intel_screen_private *intel = intel_get_screen_private(scrn);
1373
1374         /* Free the current buffer if we're going to have to reallocate */
1375         if (adaptor_priv->buf && adaptor_priv->buf->size < alloc_size)
1376                 intel_free_video_buffers(adaptor_priv);
1377
1378         if (adaptor_priv->buf == NULL) {
1379                 adaptor_priv->buf = drm_intel_bo_alloc(intel->bufmgr, "xv buffer",
1380                                                        alloc_size, 4096);
1381                 if (adaptor_priv->buf == NULL)
1382                         return FALSE;
1383
1384                 adaptor_priv->reusable = TRUE;
1385         }
1386
1387         return TRUE;
1388 }
1389
1390 static void
1391 intel_setup_dst_params(ScrnInfoPtr scrn, intel_adaptor_private *adaptor_priv, short width,
1392                        short height, int *dstPitch, int *dstPitch2, int *size,
1393                        int id)
1394 {
1395         intel_screen_private *intel = intel_get_screen_private(scrn);
1396         int pitchAlign;
1397
1398         /* Only needs to be DWORD-aligned for textured on i915, but overlay has
1399          * stricter requirements.
1400          */
1401         if (adaptor_priv->textured) {
1402                 pitchAlign = 4;
1403         } else {
1404                 if (INTEL_INFO(intel)->gen >= 40)
1405                         /* Actually the alignment is 64 bytes, too. But the
1406                          * stride must be at least 512 bytes. Take the easy fix
1407                          * and align on 512 bytes unconditionally. */
1408                         pitchAlign = 512;
1409                 else if (IS_I830(intel) || IS_845G(intel))
1410                         /* Harsh, errata on these chipsets limit the stride to be
1411                          * a multiple of 256 bytes.
1412                          */
1413                         pitchAlign = 256;
1414                 else
1415                         pitchAlign = 64;
1416         }
1417
1418 #if INTEL_XVMC
1419         /* for i915 xvmc, hw requires 1kb aligned surfaces */
1420         if ((id == FOURCC_XVMC) && IS_GEN3(intel))
1421                 pitchAlign = 1024;
1422 #endif
1423
1424         /* Determine the desired destination pitch (representing the chroma's pitch,
1425          * in the planar case.
1426          */
1427         if (is_planar_fourcc(id)) {
1428                 if (adaptor_priv->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
1429                         *dstPitch = ALIGN((height / 2), pitchAlign);
1430                         *dstPitch2 = ALIGN(height, pitchAlign);
1431                         *size = *dstPitch * width * 3;
1432                 } else {
1433                         *dstPitch = ALIGN((width / 2), pitchAlign);
1434                         *dstPitch2 = ALIGN(width, pitchAlign);
1435                         *size = *dstPitch * height * 3;
1436                 }
1437         } else {
1438                 if (adaptor_priv->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
1439                         *dstPitch = ALIGN((height << 1), pitchAlign);
1440                         *size = *dstPitch * width;
1441                 } else {
1442                         *dstPitch = ALIGN((width << 1), pitchAlign);
1443                         *size = *dstPitch * height;
1444                 }
1445                 *dstPitch2 = 0;
1446         }
1447 #if 0
1448         ErrorF("srcPitch: %d, dstPitch: %d, size: %d\n", srcPitch, *dstPitch,
1449                size);
1450 #endif
1451
1452         adaptor_priv->YBufOffset = 0;
1453
1454         if (adaptor_priv->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
1455                 adaptor_priv->UBufOffset =
1456                     adaptor_priv->YBufOffset + (*dstPitch2 * width);
1457                 adaptor_priv->VBufOffset =
1458                     adaptor_priv->UBufOffset + (*dstPitch * width / 2);
1459         } else {
1460                 adaptor_priv->UBufOffset =
1461                     adaptor_priv->YBufOffset + (*dstPitch2 * height);
1462                 adaptor_priv->VBufOffset =
1463                     adaptor_priv->UBufOffset + (*dstPitch * height / 2);
1464         }
1465 }
1466
1467 static Bool
1468 intel_copy_video_data(ScrnInfoPtr scrn, intel_adaptor_private *adaptor_priv,
1469                      short width, short height, int *dstPitch, int *dstPitch2,
1470                      int top, int left, int npixels, int nlines,
1471                      int id, unsigned char *buf)
1472 {
1473         int srcPitch = 0, srcPitch2 = 0;
1474         int size;
1475
1476         if (is_planar_fourcc(id)) {
1477                 srcPitch = ALIGN(width, 0x4);
1478                 srcPitch2 = ALIGN((width >> 1), 0x4);
1479         } else {
1480                 srcPitch = width << 1;
1481         }
1482
1483         intel_setup_dst_params(scrn, adaptor_priv, width, height, dstPitch,
1484                                 dstPitch2, &size, id);
1485
1486         if (!intel_setup_video_buffer(scrn, adaptor_priv, size, id, buf))
1487                 return FALSE;
1488
1489         /* copy data */
1490         if (is_planar_fourcc(id)) {
1491                 return I830CopyPlanarData(adaptor_priv, buf, srcPitch, srcPitch2,
1492                                           *dstPitch, *dstPitch2,
1493                                           height, top, left, nlines,
1494                                           npixels, id);
1495         } else {
1496                 return I830CopyPackedData(adaptor_priv, buf, srcPitch, *dstPitch, top, left,
1497                                           nlines, npixels);
1498         }
1499 }
1500
1501 /*
1502  * The source rectangle of the video is defined by (src_x, src_y, src_w, src_h).
1503  * The dest rectangle of the video is defined by (drw_x, drw_y, drw_w, drw_h).
1504  * id is a fourcc code for the format of the video.
1505  * buf is the pointer to the source data in system memory.
1506  * width and height are the w/h of the source data.
1507  * If "sync" is TRUE, then we must be finished with *buf at the point of return
1508  * (which we always are).
1509  * clipBoxes is the clipping region in screen space.
1510  * data is a pointer to our port private.
1511  * drawable is some Drawable, which might not be the screen in the case of
1512  * compositing.  It's a new argument to the function in the 1.1 server.
1513  */
1514 static int
1515 I830PutImageTextured(ScrnInfoPtr scrn,
1516                      short src_x, short src_y,
1517                      short drw_x, short drw_y,
1518                      short src_w, short src_h,
1519                      short drw_w, short drw_h,
1520                      int id, unsigned char *buf,
1521                      short width, short height,
1522                      Bool sync, RegionPtr clipBoxes, pointer data,
1523                      DrawablePtr drawable)
1524 {
1525         intel_screen_private *intel = intel_get_screen_private(scrn);
1526         intel_adaptor_private *adaptor_priv = (intel_adaptor_private *) data;
1527         PixmapPtr pixmap = get_drawable_pixmap(drawable);
1528         int dstPitch, dstPitch2;
1529         BoxRec dstBox;
1530         xf86CrtcPtr crtc;
1531         int top, left, npixels, nlines;
1532
1533 #if 0
1534         ErrorF("I830PutImage: src: (%d,%d)(%d,%d), dst: (%d,%d)(%d,%d)\n"
1535                "width %d, height %d\n", src_x, src_y, src_w, src_h, drw_x,
1536                drw_y, drw_w, drw_h, width, height);
1537 #endif
1538
1539         if (!intel_clip_video_helper(scrn,
1540                                     adaptor_priv,
1541                                     &crtc,
1542                                     &dstBox,
1543                                     src_x, src_y, drw_x, drw_y,
1544                                     src_w, src_h, drw_w, drw_h,
1545                                     id,
1546                                     &top, &left, &npixels, &nlines, clipBoxes,
1547                                     width, height))
1548                 return Success;
1549
1550         if (xvmc_passthrough(id)) {
1551                 uint32_t *gem_handle = (uint32_t *)buf;
1552                 int size;
1553
1554                 intel_setup_dst_params(scrn, adaptor_priv, width, height,
1555                                 &dstPitch, &dstPitch2, &size, id);
1556
1557                 if (IS_I915G(intel) || IS_I915GM(intel)) {
1558                         /* XXX: i915 is not support and needs some
1559                          * serious care.  grep for KMS in i915_hwmc.c */
1560                         return BadAlloc;
1561                 }
1562
1563                 if (adaptor_priv->buf)
1564                         drm_intel_bo_unreference(adaptor_priv->buf);
1565
1566                 adaptor_priv->buf =
1567                         drm_intel_bo_gem_create_from_name(intel->bufmgr,
1568                                                           "xvmc surface",
1569                                                           *gem_handle);
1570                 if (adaptor_priv->buf == NULL)
1571                         return BadAlloc;
1572
1573                 adaptor_priv->reusable = FALSE;
1574         } else {
1575                 if (!intel_copy_video_data(scrn, adaptor_priv, width, height,
1576                                           &dstPitch, &dstPitch2,
1577                                           top, left, npixels, nlines, id, buf))
1578                         return BadAlloc;
1579         }
1580
1581         if (crtc && adaptor_priv->SyncToVblank != 0 && INTEL_INFO(intel)->gen < 60) {
1582                 intel_wait_for_scanline(scrn, pixmap, crtc, clipBoxes);
1583         }
1584
1585         if (INTEL_INFO(intel)->gen >= 60) {
1586                 Gen6DisplayVideoTextured(scrn, adaptor_priv, id, clipBoxes,
1587                                          width, height, dstPitch, dstPitch2,
1588                                          src_w, src_h,
1589                                          drw_w, drw_h, pixmap);
1590         } else if (INTEL_INFO(intel)->gen >= 40) {
1591                 I965DisplayVideoTextured(scrn, adaptor_priv, id, clipBoxes,
1592                                          width, height, dstPitch, dstPitch2,
1593                                          src_w, src_h,
1594                                          drw_w, drw_h, pixmap);
1595         } else {
1596                 I915DisplayVideoTextured(scrn, adaptor_priv, id, clipBoxes,
1597                                          width, height, dstPitch, dstPitch2,
1598                                          src_w, src_h, drw_w, drw_h,
1599                                          pixmap);
1600         }
1601
1602         DamageDamageRegion(drawable, clipBoxes);
1603
1604         return Success;
1605 }
1606
1607 static int
1608 I830PutImageOverlay(ScrnInfoPtr scrn,
1609              short src_x, short src_y,
1610              short drw_x, short drw_y,
1611              short src_w, short src_h,
1612              short drw_w, short drw_h,
1613              int id, unsigned char *buf,
1614              short width, short height,
1615              Bool sync, RegionPtr clipBoxes, pointer data,
1616              DrawablePtr drawable)
1617 {
1618         intel_adaptor_private *adaptor_priv = (intel_adaptor_private *) data;
1619         int dstPitch, dstPitch2;
1620         BoxRec dstBox;
1621         xf86CrtcPtr crtc;
1622         int top, left, npixels, nlines;
1623
1624 #if 0
1625         ErrorF("I830PutImage: src: (%d,%d)(%d,%d), dst: (%d,%d)(%d,%d)\n"
1626                "width %d, height %d\n", src_x, src_y, src_w, src_h, drw_x,
1627                drw_y, drw_w, drw_h, width, height);
1628 #endif
1629
1630         /* If dst width and height are less than 1/8th the src size, the
1631          * src/dst scale factor becomes larger than 8 and doesn't fit in
1632          * the scale register. */
1633         if (src_w >= (drw_w * 8))
1634                 drw_w = src_w / 7;
1635
1636         if (src_h >= (drw_h * 8))
1637                 drw_h = src_h / 7;
1638
1639         if (!intel_clip_video_helper(scrn,
1640                                     adaptor_priv,
1641                                     &crtc,
1642                                     &dstBox,
1643                                     src_x, src_y, drw_x, drw_y,
1644                                     src_w, src_h, drw_w, drw_h,
1645                                     id,
1646                                     &top, &left, &npixels, &nlines, clipBoxes,
1647                                     width, height))
1648                 return Success;
1649
1650         /* overlay can't handle rotation natively, store it for the copy func */
1651         if (crtc)
1652                 adaptor_priv->rotation = crtc->rotation;
1653         else {
1654                 xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1655                            "Fail to clip video to any crtc!\n");
1656                 return Success;
1657         }
1658
1659         if (!intel_copy_video_data(scrn, adaptor_priv, width, height,
1660                                   &dstPitch, &dstPitch2,
1661                                   top, left, npixels, nlines, id, buf))
1662                 return BadAlloc;
1663
1664         if (!intel_display_overlay
1665             (scrn, crtc, id, width, height, dstPitch, dstPitch2,
1666              &dstBox, src_w, src_h, drw_w, drw_h))
1667                 return BadAlloc;
1668
1669         /* update cliplist */
1670         if (!REGION_EQUAL(scrn->pScreen, &adaptor_priv->clip, clipBoxes)) {
1671                 REGION_COPY(scrn->pScreen, &adaptor_priv->clip, clipBoxes);
1672                 xf86XVFillKeyHelperDrawable(drawable,
1673                                             adaptor_priv->colorKey,
1674                                             clipBoxes);
1675         }
1676
1677         adaptor_priv->videoStatus = CLIENT_VIDEO_ON;
1678
1679         return Success;
1680 }
1681
1682 static int
1683 I830QueryImageAttributes(ScrnInfoPtr scrn,
1684                          int id,
1685                          unsigned short *w, unsigned short *h,
1686                          int *pitches, int *offsets)
1687 {
1688         intel_screen_private *intel = intel_get_screen_private(scrn);
1689         int size, tmp;
1690
1691 #if 0
1692         ErrorF("I830QueryImageAttributes: w is %d, h is %d\n", *w, *h);
1693 #endif
1694
1695         if (IS_845G(intel) || IS_I830(intel)) {
1696                 if (*w > IMAGE_MAX_WIDTH_LEGACY)
1697                         *w = IMAGE_MAX_WIDTH_LEGACY;
1698                 if (*h > IMAGE_MAX_HEIGHT_LEGACY)
1699                         *h = IMAGE_MAX_HEIGHT_LEGACY;
1700         } else {
1701                 if (*w > IMAGE_MAX_WIDTH)
1702                         *w = IMAGE_MAX_WIDTH;
1703                 if (*h > IMAGE_MAX_HEIGHT)
1704                         *h = IMAGE_MAX_HEIGHT;
1705         }
1706
1707         *w = (*w + 1) & ~1;
1708         if (offsets)
1709                 offsets[0] = 0;
1710
1711         switch (id) {
1712                 /* IA44 is for XvMC only */
1713         case FOURCC_IA44:
1714         case FOURCC_AI44:
1715                 if (pitches)
1716                         pitches[0] = *w;
1717                 size = *w * *h;
1718                 break;
1719         case FOURCC_YV12:
1720         case FOURCC_I420:
1721                 *h = (*h + 1) & ~1;
1722                 size = (*w + 3) & ~3;
1723                 if (pitches)
1724                         pitches[0] = size;
1725                 size *= *h;
1726                 if (offsets)
1727                         offsets[1] = size;
1728                 tmp = ((*w >> 1) + 3) & ~3;
1729                 if (pitches)
1730                         pitches[1] = pitches[2] = tmp;
1731                 tmp *= (*h >> 1);
1732                 size += tmp;
1733                 if (offsets)
1734                         offsets[2] = size;
1735                 size += tmp;
1736 #if 0
1737                 if (pitches)
1738                         ErrorF("pitch 0 is %d, pitch 1 is %d, pitch 2 is %d\n",
1739                                pitches[0], pitches[1], pitches[2]);
1740                 if (offsets)
1741                         ErrorF("offset 1 is %d, offset 2 is %d\n", offsets[1],
1742                                offsets[2]);
1743                 if (offsets)
1744                         ErrorF("size is %d\n", size);
1745 #endif
1746                 break;
1747 #ifdef INTEL_XVMC
1748         case FOURCC_XVMC:
1749                 *h = (*h + 1) & ~1;
1750                 size = sizeof(struct intel_xvmc_command);
1751                 if (pitches)
1752                         pitches[0] = size;
1753                 break;
1754 #endif
1755         case FOURCC_UYVY:
1756         case FOURCC_YUY2:
1757         default:
1758                 size = *w << 1;
1759                 if (pitches)
1760                         pitches[0] = size;
1761                 size *= *h;
1762                 break;
1763         }
1764
1765         return size;
1766 }
1767
1768 void
1769 intel_video_block_handler(intel_screen_private *intel)
1770 {
1771         intel_adaptor_private *adaptor_priv;
1772
1773         /* no overlay */
1774         if (intel->adaptor == NULL)
1775                 return;
1776
1777         adaptor_priv = intel_get_adaptor_private(intel);
1778         if (adaptor_priv->videoStatus & OFF_TIMER) {
1779                 Time now = currentTime.milliseconds;
1780                 if (adaptor_priv->offTime < now) {
1781                         /* Turn off the overlay */
1782                         intel_overlay_off(intel);
1783                         intel_free_video_buffers(adaptor_priv);
1784                         adaptor_priv->videoStatus = 0;
1785                 }
1786         }
1787 }