1 /***************************************************************************
3 Copyright 2000 Intel Corporation. All Rights Reserved.
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:
13 The above copyright notice and this permission notice (including the
14 next paragraph) shall be included in all copies or substantial portions
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.
25 **************************************************************************/
28 * i830_video.c: i830/i845 Xv driver.
30 * Copyright © 2002 by Alan Hourihane and David Dawes
33 * Alan Hourihane <alanh@tungstengraphics.com>
34 * David Dawes <dawes@xfree86.org>
36 * Derived from i810 Xv driver:
38 * Authors of i810 code:
39 * Jonathan Bian <jonathan.bian@intel.com>
41 * Matt Sottek <matthew.j.sottek@intel.com>
45 * XXX Could support more formats.
59 #include "xf86_OSproc.h"
61 #include "xf86PciInfo.h"
63 #include "xf86fbman.h"
64 #include "regionstr.h"
66 #include "windowstr.h"
69 #include "intel_video.h"
72 #include <X11/extensions/Xv.h>
73 #include "dixstruct.h"
77 #define _INTEL_XVMC_SERVER_
78 #include "intel_hwmc.h"
81 #define OFF_DELAY 250 /* milliseconds */
83 #define OFF_TIMER 0x01
84 #define CLIENT_VIDEO_ON 0x02
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 *);
104 #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
106 static Atom xvBrightness, xvContrast, xvSaturation, xvColorKey, xvPipe;
107 static Atom xvGamma0, xvGamma1, xvGamma2, xvGamma3, xvGamma4, xvGamma5;
108 static Atom xvSyncToVblank;
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.
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
120 /* overlay debugging printf function */
122 #define OVERLAY_DEBUG ErrorF
124 #define OVERLAY_DEBUG if (0) ErrorF
127 /* client libraries expect an encoding */
128 static const XF86VideoEncodingRec DummyEncoding[1] = {
132 IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT,
137 #define NUM_FORMATS 3
139 static XF86VideoFormatRec Formats[NUM_FORMATS] = {
140 {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
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"}
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"},
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"}
177 static XF86ImageRec Images[NUM_IMAGES] = {
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.
193 0x00, 0x00, 0x00, 0x10, 0x80, 0x00, 0x00, 0xAA, 0x00,
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},
209 /* kernel modesetting overlay functions */
210 static Bool intel_has_overlay(intel_screen_private *intel)
212 struct drm_i915_getparam gp;
216 gp.param = I915_PARAM_HAS_OVERLAY;
217 gp.value = &has_overlay;
218 ret = drmCommandWriteRead(intel->drmSubFD, DRM_I915_GETPARAM, &gp, sizeof(gp));
220 return !! has_overlay;
223 static void intel_overlay_update_attrs(intel_screen_private *intel)
225 intel_adaptor_private *adaptor_priv = intel_get_adaptor_private(intel);
226 struct drm_intel_overlay_attrs attrs;
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;
241 ret = drmCommandWriteRead(intel->drmSubFD, DRM_I915_OVERLAY_ATTRS,
242 &attrs, sizeof(attrs));
245 static void intel_overlay_off(intel_screen_private *intel)
247 struct drm_intel_overlay_put_image request;
252 ret = drmCommandWrite(intel->drmSubFD, DRM_I915_OVERLAY_PUT_IMAGE,
253 &request, sizeof(request));
257 intel_overlay_put_image(intel_screen_private *intel,
259 int id, short width, short height,
260 int dstPitch, int dstPitch2,
261 BoxPtr dstBox, short src_w, short src_h, short drw_w,
264 intel_adaptor_private *adaptor_priv = intel_get_adaptor_private(intel);
265 struct drm_intel_overlay_put_image request;
267 int planar = is_planar_fourcc(id);
271 request.flags = I915_OVERLAY_ENABLE;
273 request.bo_handle = adaptor_priv->buf->handle;
275 request.stride_Y = dstPitch2;
276 request.stride_UV = dstPitch;
278 request.stride_Y = dstPitch;
279 request.stride_UV = 0;
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);
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;
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;
300 request.src_scan_height = 1;
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;
306 request.src_scan_width = 1;
309 request.flags |= I915_OVERLAY_YUV_PLANAR | I915_OVERLAY_YUV420;
311 request.flags |= I915_OVERLAY_YUV_PACKED | I915_OVERLAY_YUV422;
312 if (id == FOURCC_UYVY)
313 request.flags |= I915_OVERLAY_Y_SWAP;
316 ret = drmCommandWrite(intel->drmSubFD, DRM_I915_OVERLAY_PUT_IMAGE,
317 &request, sizeof(request));
321 if (!adaptor_priv->reusable) {
322 drm_intel_bo_unreference(adaptor_priv->buf);
323 adaptor_priv->buf = NULL;
324 adaptor_priv->reusable = TRUE;
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;
335 void I830InitVideo(ScreenPtr screen)
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;
343 num_adaptors = xf86XVListGenericAdaptors(scrn, &adaptors);
344 /* Give our adaptor list enough space for the overlay and/or texture video
348 malloc((num_adaptors + 2) * sizeof(XF86VideoAdaptorPtr *));
349 if (newAdaptors == NULL)
352 memcpy(newAdaptors, adaptors,
353 num_adaptors * sizeof(XF86VideoAdaptorPtr));
354 adaptors = newAdaptors;
356 /* Add the adaptors supported by our hardware. First, set up the atoms
357 * that will be used by both output adaptors.
359 xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
360 xvContrast = MAKE_ATOM("XV_CONTRAST");
362 /* Set up textured video if we can do it at this depth and we are on
363 * supported hardware.
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");
373 xf86DrvMsg(scrn->scrnIndex, X_ERROR,
374 "Failed to set up textured video\n");
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");
386 xf86DrvMsg(scrn->scrnIndex, X_ERROR,
387 "Failed to set up overlay video\n");
391 if (overlayAdaptor && intel->XvPreferOverlay)
392 adaptors[num_adaptors++] = overlayAdaptor;
395 adaptors[num_adaptors++] = texturedAdaptor;
397 if (overlayAdaptor && !intel->XvPreferOverlay)
398 adaptors[num_adaptors++] = overlayAdaptor;
401 xf86XVScreenInit(screen, adaptors, num_adaptors);
403 xf86DrvMsg(scrn->scrnIndex, X_WARNING,
404 "Disabling Xv because no adaptors could be initialized.\n");
405 intel->XvEnabled = FALSE;
410 intel_xvmc_adaptor_init(screen);
415 static XF86VideoAdaptorPtr I830SetupImageVideoOverlay(ScreenPtr screen)
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;
423 OVERLAY_DEBUG("I830SetupImageVideoOverlay\n");
425 if (!(adapt = calloc(1,
426 sizeof(XF86VideoAdaptorRec) +
427 sizeof(intel_adaptor_private) +
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;
441 adapt->nFormats = NUM_FORMATS;
442 adapt->pFormats = Formats;
444 adapt->pPortPrivates = (DevUnion *) (&adapt[1]);
446 adaptor_priv = (intel_adaptor_private *)&adapt->pPortPrivates[1];
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 */
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;
464 adapt->nImages = NUM_IMAGES - XVMC_IMAGE;
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;
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;
495 adaptor_priv->rotation = RR_Rotate_0;
497 /* gotta uninit this someplace */
498 REGION_NULL(screen, &adaptor_priv->clip);
500 intel->adaptor = adapt;
502 xvColorKey = MAKE_ATOM("XV_COLORKEY");
503 xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
504 xvContrast = MAKE_ATOM("XV_CONTRAST");
505 xvSaturation = MAKE_ATOM("XV_SATURATION");
507 /* Allow the pipe to be switched from pipe A to B when in clone mode */
508 xvPipe = MAKE_ATOM("XV_PIPE");
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");
519 intel_overlay_update_attrs(intel);
524 static XF86VideoAdaptorPtr I830SetupImageVideoTextured(ScreenPtr screen)
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;
535 OVERLAY_DEBUG("I830SetupImageVideoOverlay\n");
537 nAttributes = NUM_TEXTURED_ATTRIBUTES;
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 ||
552 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
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;
569 adapt->nImages = NUM_IMAGES;
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;
583 for (i = 0; i < nports; i++) {
584 intel_adaptor_private *adaptor_priv = &adaptor_privs[i];
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;
592 adaptor_priv->rotation = RR_Rotate_0;
593 adaptor_priv->SyncToVblank = 1;
595 /* gotta uninit this someplace, XXX: shouldn't be necessary for textured */
596 REGION_NULL(screen, &adaptor_priv->clip);
598 adapt->pPortPrivates[i].ptr = (pointer) (adaptor_priv);
601 xvSyncToVblank = MAKE_ATOM("XV_SYNC_TO_VBLANK");
606 static void intel_free_video_buffers(intel_adaptor_private *adaptor_priv)
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;
618 if (adaptor_priv->buf) {
619 drm_intel_bo_unreference(adaptor_priv->buf);
620 adaptor_priv->buf = NULL;
624 static void I830StopVideo(ScrnInfoPtr scrn, pointer data, Bool shutdown)
626 intel_adaptor_private *adaptor_priv = (intel_adaptor_private *) data;
628 if (adaptor_priv->textured)
631 OVERLAY_DEBUG("I830StopVideo\n");
633 REGION_EMPTY(scrn->pScreen, &adaptor_priv->clip);
636 if (adaptor_priv->videoStatus & CLIENT_VIDEO_ON)
637 intel_overlay_off(intel_get_screen_private(scrn));
639 intel_free_video_buffers(adaptor_priv);
640 adaptor_priv->videoStatus = 0;
642 if (adaptor_priv->videoStatus & CLIENT_VIDEO_ON) {
643 adaptor_priv->videoStatus |= OFF_TIMER;
644 adaptor_priv->offTime = currentTime.milliseconds + OFF_DELAY;
651 I830SetPortAttributeTextured(ScrnInfoPtr scrn,
652 Atom attribute, INT32 value, pointer data)
654 intel_adaptor_private *adaptor_priv = (intel_adaptor_private *) data;
656 if (attribute == xvBrightness) {
657 if ((value < -128) || (value > 127))
659 adaptor_priv->brightness = value;
661 } else if (attribute == xvContrast) {
662 if ((value < 0) || (value > 255))
664 adaptor_priv->contrast = value;
666 } else if (attribute == xvSyncToVblank) {
667 if ((value < -1) || (value > 1))
669 adaptor_priv->SyncToVblank = value;
677 I830SetPortAttributeOverlay(ScrnInfoPtr scrn,
678 Atom attribute, INT32 value, pointer data)
680 intel_adaptor_private *adaptor_priv = (intel_adaptor_private *) data;
681 intel_screen_private *intel = intel_get_screen_private(scrn);
683 if (attribute == xvBrightness) {
684 if ((value < -128) || (value > 127))
686 adaptor_priv->brightness = value;
687 OVERLAY_DEBUG("BRIGHTNESS\n");
688 } else if (attribute == xvContrast) {
689 if ((value < 0) || (value > 255))
691 adaptor_priv->contrast = value;
692 OVERLAY_DEBUG("CONTRAST\n");
693 } else if (attribute == xvSaturation) {
694 if ((value < 0) || (value > 1023))
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))
702 adaptor_priv->desired_crtc = NULL;
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");
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");
732 intel_overlay_update_attrs(intel);
734 if (attribute == xvColorKey)
735 REGION_EMPTY(scrn->pScreen, &adaptor_priv->clip);
741 I830GetPortAttribute(ScrnInfoPtr scrn,
742 Atom attribute, INT32 * value, pointer data)
744 intel_screen_private *intel = intel_get_screen_private(scrn);
745 intel_adaptor_private *adaptor_priv = (intel_adaptor_private *) data;
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) {
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)
759 if (c == xf86_config->num_crtc)
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;
785 I830QueryBestSize(ScrnInfoPtr scrn,
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)
791 if (vid_w > (drw_w << 1))
793 if (vid_h > (drw_h << 1))
801 I830CopyPackedData(intel_adaptor_private *adaptor_priv,
803 int srcPitch, int dstPitch, int top, int left, int h, int w)
805 unsigned char *src, *dst, *dst_base;
810 ErrorF("I830CopyPackedData: (%d,%d) (%d,%d)\n"
811 "srcPitch: %d, dstPitch: %d\n", top, left, h, w,
815 src = buf + (top * srcPitch) + (left << 1);
817 if (drm_intel_gem_bo_map_gtt(adaptor_priv->buf))
820 dst_base = adaptor_priv->buf->virtual;
822 dst = dst_base + adaptor_priv->YBufOffset;
824 switch (adaptor_priv->rotation) {
827 for (i = 0; i < h; i++) {
835 for (i = 0; i < h; i += 2) {
837 for (j = 0; j < w; j++) {
839 dst[(i + 0) + ((w - j - 1) * dstPitch)] = *s++;
845 src = buf + (top * srcPitch) + (left << 1);
846 for (i = 0; i < h; i += 2) {
847 for (j = 0; j < w; j += 2) {
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)];
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)];
863 for (i = 0; i < h; i++) {
865 for (j = 0; j < w; j += 4) {
866 dst[(w - j - 4) + ((h - i - 1) * dstPitch)] =
868 dst[(w - j - 3) + ((h - i - 1) * dstPitch)] =
870 dst[(w - j - 2) + ((h - i - 1) * dstPitch)] =
872 dst[(w - j - 1) + ((h - i - 1) * dstPitch)] =
880 for (i = 0; i < h; i += 2) {
882 for (j = 0; j < w; j++) {
884 dst[(h - i - 2) + (j * dstPitch)] = *s++;
890 src = buf + (top * srcPitch) + (left << 1);
891 for (i = 0; i < h; i += 2) {
892 for (j = 0; j < w; j += 2) {
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)];
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)];
910 drm_intel_gem_bo_unmap_gtt(adaptor_priv->buf);
914 static void intel_memcpy_plane(unsigned char *dst, unsigned char *src,
915 int height, int width,
916 int dstPitch, int srcPitch, Rotation rotation)
923 /* optimise for the case of no clipping */
924 if (srcPitch == dstPitch && srcPitch == width)
925 memcpy(dst, src, srcPitch * height);
927 for (i = 0; i < height; i++) {
928 memcpy(dst, src, width);
934 for (i = 0; i < height; i++) {
936 for (j = 0; j < width; j++) {
937 dst[(i) + ((width - j - 1) * dstPitch)] = *s++;
943 for (i = 0; i < height; i++) {
945 for (j = 0; j < width; j++) {
946 dst[(width - j - 1) +
947 ((height - i - 1) * dstPitch)] = *s++;
953 for (i = 0; i < height; i++) {
955 for (j = 0; j < width; j++) {
956 dst[(height - i - 1) + (j * dstPitch)] = *s++;
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)
971 unsigned char *src1, *src2, *src3, *dst_base, *dst1, *dst2, *dst3;
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);
980 src1 = buf + (top * srcPitch) + left;
982 ErrorF("src1 is %p, offset is %ld\n", src1,
983 (unsigned long)src1 - (unsigned long)buf);
986 if (drm_intel_gem_bo_map_gtt(adaptor_priv->buf))
989 dst_base = adaptor_priv->buf->virtual;
991 dst1 = dst_base + adaptor_priv->YBufOffset;
993 intel_memcpy_plane(dst1, src1, h, w, dstPitch2, srcPitch,
994 adaptor_priv->rotation);
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 */
1003 ErrorF("src2 is %p, offset is %ld\n", src2,
1004 (unsigned long)src2 - (unsigned long)buf);
1006 if (id == FOURCC_I420)
1007 dst2 = dst_base + adaptor_priv->UBufOffset;
1009 dst2 = dst_base + adaptor_priv->VBufOffset;
1011 intel_memcpy_plane(dst2, src2, h / 2, w / 2,
1012 dstPitch, srcPitch2, adaptor_priv->rotation);
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 */
1021 ErrorF("src3 is %p, offset is %ld\n", src3,
1022 (unsigned long)src3 - (unsigned long)buf);
1024 if (id == FOURCC_I420)
1025 dst3 = dst_base + adaptor_priv->VBufOffset;
1027 dst3 = dst_base + adaptor_priv->UBufOffset;
1029 intel_memcpy_plane(dst3, src3, h / 2, w / 2,
1030 dstPitch, srcPitch2, adaptor_priv->rotation);
1032 drm_intel_gem_bo_unmap_gtt(adaptor_priv->buf);
1036 static void intel_box_intersect(BoxPtr dest, BoxPtr a, BoxPtr b)
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;
1046 static void intel_crtc_box(xf86CrtcPtr crtc, BoxPtr crtc_box)
1048 if (crtc->enabled) {
1049 crtc_box->x1 = crtc->x;
1051 crtc->x + xf86ModeWidth(&crtc->mode, crtc->rotation);
1052 crtc_box->y1 = crtc->y;
1054 crtc->y + xf86ModeHeight(&crtc->mode, crtc->rotation);
1056 crtc_box->x1 = crtc_box->x2 = crtc_box->y1 = crtc_box->y2 = 0;
1059 static int intel_box_area(BoxPtr box)
1061 return (int)(box->x2 - box->x1) * (int)(box->y2 - box->y1);
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
1071 intel_covering_crtc(ScrnInfoPtr scrn,
1072 BoxPtr box, xf86CrtcPtr desired, BoxPtr crtc_box_ret)
1074 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
1075 xf86CrtcPtr crtc, best_crtc;
1076 int coverage, best_coverage;
1078 BoxRec crtc_box, cover_box;
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];
1089 /* If the CRTC is off, treat it as not covering */
1090 if (!intel_crtc_on(crtc))
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;
1100 if (coverage > best_coverage) {
1101 *crtc_box_ret = crtc_box;
1103 best_coverage = coverage;
1110 intel_update_dst_box_to_crtc_coords(ScrnInfoPtr scrn, xf86CrtcPtr crtc,
1115 /* for overlay, we should take it from crtc's screen
1116 * coordinate to current crtc's display mode.
1117 * yeah, a bit confusing.
1119 switch (crtc->rotation & 0xf) {
1121 dstBox->x1 -= crtc->x;
1122 dstBox->x2 -= crtc->x;
1123 dstBox->y1 -= crtc->y;
1124 dstBox->y2 -= crtc->y;
1128 dstBox->x1 = dstBox->y1 - crtc->x;
1129 dstBox->y1 = scrn->virtualX - tmp - crtc->y;
1131 dstBox->x2 = dstBox->y2 - crtc->x;
1132 dstBox->y2 = scrn->virtualX - tmp - crtc->y;
1134 dstBox->y1 = dstBox->y2;
1139 dstBox->x1 = scrn->virtualX - dstBox->x2 - crtc->x;
1140 dstBox->x2 = scrn->virtualX - tmp - crtc->x;
1142 dstBox->y1 = scrn->virtualY - dstBox->y2 - crtc->y;
1143 dstBox->y2 = scrn->virtualY - tmp - crtc->y;
1147 dstBox->x1 = scrn->virtualY - dstBox->y1 - crtc->x;
1148 dstBox->y1 = tmp - crtc->y;
1150 dstBox->x2 = scrn->virtualY - dstBox->y2 - crtc->x;
1151 dstBox->y2 = tmp - crtc->y;
1153 dstBox->x1 = dstBox->x2;
1161 int is_planar_fourcc(int id)
1174 ErrorF("Unknown format 0x%x\n", id);
1179 static int xvmc_passthrough(int id)
1182 return id == FOURCC_XVMC;
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,
1195 intel_screen_private *intel = intel_get_screen_private(scrn);
1198 OVERLAY_DEBUG("I830DisplayVideo: %dx%d (pitch %d)\n", width, height,
1202 * If the video isn't visible on any CRTC, turn it off
1205 intel_overlay_off(intel);
1209 intel_update_dst_box_to_crtc_coords(scrn, crtc, dstBox);
1211 if (crtc->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
1223 return intel_overlay_put_image(intel, crtc, id,
1225 dstPitch, dstPitch2, dstBox,
1226 src_w, src_h, drw_w, drw_h);
1230 intel_clip_video_helper(ScrnInfoPtr scrn,
1231 intel_adaptor_private *adaptor_priv,
1232 xf86CrtcPtr * crtc_ret,
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,
1239 int *top, int* left, int* npixels, int *nlines,
1240 RegionPtr reg, INT32 width, INT32 height)
1243 RegionRec crtc_region_local;
1244 RegionPtr crtc_region = reg;
1246 INT32 x1, x2, y1, y2;
1255 dst->x2 = drw_x + drw_w;
1257 dst->y2 = drw_y + drw_h;
1260 * For overlay video, compute the relevant CRTC and
1261 * clip video to that
1263 crtc = intel_covering_crtc(scrn, dst, adaptor_priv->desired_crtc,
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,
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);
1281 *left = (x1 >> 16) & ~1;
1282 *npixels = ALIGN(((x2 + 0xffff) >> 16), 2) - *left;
1283 if (is_planar_fourcc(id)) {
1285 *nlines = ALIGN(((y2 + 0xffff) >> 16), 2) - *top;
1287 *nlines = ((y2 + 0xffff) >> 16) - *top;
1293 intel_wait_for_scanline(ScrnInfoPtr scrn, PixmapPtr pixmap,
1294 xf86CrtcPtr crtc, RegionPtr clipBoxes)
1296 intel_screen_private *intel = intel_get_screen_private(scrn);
1297 pixman_box16_t box, crtc_box;
1303 if (pixmap_is_scanout(pixmap))
1304 pipe = intel_crtc_to_pipe(crtc);
1308 box = *REGION_EXTENTS(unused, clipBoxes);
1310 if (crtc->transform_in_use)
1311 pixman_f_transform_bounds(&crtc->f_framebuffer_to_crtc, &box);
1313 /* We could presume the clip was correctly computed... */
1314 intel_crtc_box(crtc, &crtc_box);
1315 intel_box_intersect(&box, &crtc_box, &box);
1318 * Make sure we don't wait for a scanline that will
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;
1327 full_height = FALSE;
1328 if (y1 == 0 && y2 == (crtc_box.y2 - crtc_box.y1))
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
1336 if (full_height && INTEL_INFO(intel)->gen < 40)
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;
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;
1351 if (crtc->mode.Flags & V_INTERLACE) {
1352 /* DSL count field lines */
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);
1369 intel_setup_video_buffer(ScrnInfoPtr scrn, intel_adaptor_private *adaptor_priv,
1370 int alloc_size, int id, unsigned char *buf)
1372 intel_screen_private *intel = intel_get_screen_private(scrn);
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);
1378 if (adaptor_priv->buf == NULL) {
1379 adaptor_priv->buf = drm_intel_bo_alloc(intel->bufmgr, "xv buffer",
1381 if (adaptor_priv->buf == NULL)
1384 adaptor_priv->reusable = TRUE;
1391 intel_setup_dst_params(ScrnInfoPtr scrn, intel_adaptor_private *adaptor_priv, short width,
1392 short height, int *dstPitch, int *dstPitch2, int *size,
1395 intel_screen_private *intel = intel_get_screen_private(scrn);
1398 /* Only needs to be DWORD-aligned for textured on i915, but overlay has
1399 * stricter requirements.
1401 if (adaptor_priv->textured) {
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. */
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.
1419 /* for i915 xvmc, hw requires 1kb aligned surfaces */
1420 if ((id == FOURCC_XVMC) && IS_GEN3(intel))
1424 /* Determine the desired destination pitch (representing the chroma's pitch,
1425 * in the planar case.
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;
1433 *dstPitch = ALIGN((width / 2), pitchAlign);
1434 *dstPitch2 = ALIGN(width, pitchAlign);
1435 *size = *dstPitch * height * 3;
1438 if (adaptor_priv->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
1439 *dstPitch = ALIGN((height << 1), pitchAlign);
1440 *size = *dstPitch * width;
1442 *dstPitch = ALIGN((width << 1), pitchAlign);
1443 *size = *dstPitch * height;
1448 ErrorF("srcPitch: %d, dstPitch: %d, size: %d\n", srcPitch, *dstPitch,
1452 adaptor_priv->YBufOffset = 0;
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);
1460 adaptor_priv->UBufOffset =
1461 adaptor_priv->YBufOffset + (*dstPitch2 * height);
1462 adaptor_priv->VBufOffset =
1463 adaptor_priv->UBufOffset + (*dstPitch * height / 2);
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)
1473 int srcPitch = 0, srcPitch2 = 0;
1476 if (is_planar_fourcc(id)) {
1477 srcPitch = ALIGN(width, 0x4);
1478 srcPitch2 = ALIGN((width >> 1), 0x4);
1480 srcPitch = width << 1;
1483 intel_setup_dst_params(scrn, adaptor_priv, width, height, dstPitch,
1484 dstPitch2, &size, id);
1486 if (!intel_setup_video_buffer(scrn, adaptor_priv, size, id, buf))
1490 if (is_planar_fourcc(id)) {
1491 return I830CopyPlanarData(adaptor_priv, buf, srcPitch, srcPitch2,
1492 *dstPitch, *dstPitch2,
1493 height, top, left, nlines,
1496 return I830CopyPackedData(adaptor_priv, buf, srcPitch, *dstPitch, top, left,
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.
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)
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;
1531 int top, left, npixels, nlines;
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);
1539 if (!intel_clip_video_helper(scrn,
1543 src_x, src_y, drw_x, drw_y,
1544 src_w, src_h, drw_w, drw_h,
1546 &top, &left, &npixels, &nlines, clipBoxes,
1550 if (xvmc_passthrough(id)) {
1551 uint32_t *gem_handle = (uint32_t *)buf;
1554 intel_setup_dst_params(scrn, adaptor_priv, width, height,
1555 &dstPitch, &dstPitch2, &size, id);
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 */
1563 if (adaptor_priv->buf)
1564 drm_intel_bo_unreference(adaptor_priv->buf);
1567 drm_intel_bo_gem_create_from_name(intel->bufmgr,
1570 if (adaptor_priv->buf == NULL)
1573 adaptor_priv->reusable = FALSE;
1575 if (!intel_copy_video_data(scrn, adaptor_priv, width, height,
1576 &dstPitch, &dstPitch2,
1577 top, left, npixels, nlines, id, buf))
1581 if (crtc && adaptor_priv->SyncToVblank != 0 && INTEL_INFO(intel)->gen < 60) {
1582 intel_wait_for_scanline(scrn, pixmap, crtc, clipBoxes);
1585 if (INTEL_INFO(intel)->gen >= 60) {
1586 Gen6DisplayVideoTextured(scrn, adaptor_priv, id, clipBoxes,
1587 width, height, dstPitch, dstPitch2,
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,
1594 drw_w, drw_h, pixmap);
1596 I915DisplayVideoTextured(scrn, adaptor_priv, id, clipBoxes,
1597 width, height, dstPitch, dstPitch2,
1598 src_w, src_h, drw_w, drw_h,
1602 DamageDamageRegion(drawable, clipBoxes);
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)
1618 intel_adaptor_private *adaptor_priv = (intel_adaptor_private *) data;
1619 int dstPitch, dstPitch2;
1622 int top, left, npixels, nlines;
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);
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))
1636 if (src_h >= (drw_h * 8))
1639 if (!intel_clip_video_helper(scrn,
1643 src_x, src_y, drw_x, drw_y,
1644 src_w, src_h, drw_w, drw_h,
1646 &top, &left, &npixels, &nlines, clipBoxes,
1650 /* overlay can't handle rotation natively, store it for the copy func */
1652 adaptor_priv->rotation = crtc->rotation;
1654 xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1655 "Fail to clip video to any crtc!\n");
1659 if (!intel_copy_video_data(scrn, adaptor_priv, width, height,
1660 &dstPitch, &dstPitch2,
1661 top, left, npixels, nlines, id, buf))
1664 if (!intel_display_overlay
1665 (scrn, crtc, id, width, height, dstPitch, dstPitch2,
1666 &dstBox, src_w, src_h, drw_w, drw_h))
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,
1677 adaptor_priv->videoStatus = CLIENT_VIDEO_ON;
1683 I830QueryImageAttributes(ScrnInfoPtr scrn,
1685 unsigned short *w, unsigned short *h,
1686 int *pitches, int *offsets)
1688 intel_screen_private *intel = intel_get_screen_private(scrn);
1692 ErrorF("I830QueryImageAttributes: w is %d, h is %d\n", *w, *h);
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;
1701 if (*w > IMAGE_MAX_WIDTH)
1702 *w = IMAGE_MAX_WIDTH;
1703 if (*h > IMAGE_MAX_HEIGHT)
1704 *h = IMAGE_MAX_HEIGHT;
1712 /* IA44 is for XvMC only */
1722 size = (*w + 3) & ~3;
1728 tmp = ((*w >> 1) + 3) & ~3;
1730 pitches[1] = pitches[2] = tmp;
1738 ErrorF("pitch 0 is %d, pitch 1 is %d, pitch 2 is %d\n",
1739 pitches[0], pitches[1], pitches[2]);
1741 ErrorF("offset 1 is %d, offset 2 is %d\n", offsets[1],
1744 ErrorF("size is %d\n", size);
1750 size = sizeof(struct intel_xvmc_command);
1769 intel_video_block_handler(intel_screen_private *intel)
1771 intel_adaptor_private *adaptor_priv;
1774 if (intel->adaptor == NULL)
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;