radeon_video.c revision 6322c902
1209ff23fSmrg
2209ff23fSmrg#ifdef HAVE_CONFIG_H
3209ff23fSmrg#include "config.h"
4209ff23fSmrg#endif
5209ff23fSmrg
6209ff23fSmrg#include <stdlib.h>
7209ff23fSmrg#include <string.h>
8209ff23fSmrg#include <stdio.h>
9209ff23fSmrg#include <math.h>
10209ff23fSmrg
11209ff23fSmrg#include "radeon.h"
126322c902Smrg#include "radeon_glamor.h"
13209ff23fSmrg#include "radeon_reg.h"
14209ff23fSmrg#include "radeon_probe.h"
15209ff23fSmrg#include "radeon_video.h"
16209ff23fSmrg
17209ff23fSmrg#include "xf86.h"
18209ff23fSmrg#include "dixstruct.h"
19209ff23fSmrg
2068105dcbSveego/* DPMS */
2168105dcbSveego#ifdef HAVE_XEXTPROTO_71
2268105dcbSveego#include <X11/extensions/dpmsconst.h>
2368105dcbSveego#else
2468105dcbSveego#define DPMS_SERVER
2568105dcbSveego#include <X11/extensions/dpms.h>
2668105dcbSveego#endif
2768105dcbSveego
28209ff23fSmrg#include <X11/extensions/Xv.h>
29209ff23fSmrg#include "fourcc.h"
30209ff23fSmrg
31209ff23fSmrg#define OFF_DELAY       250  /* milliseconds */
32209ff23fSmrg#define FREE_DELAY      15000
33209ff23fSmrg
34209ff23fSmrg#define OFF_TIMER       0x01
35209ff23fSmrg#define FREE_TIMER      0x02
36209ff23fSmrg#define CLIENT_VIDEO_ON 0x04
37209ff23fSmrg
38209ff23fSmrg#define GET_PORT_PRIVATE(pScrn) \
39209ff23fSmrg   (RADEONPortPrivPtr)((RADEONPTR(pScrn))->adaptor->pPortPrivates[0].ptr)
40209ff23fSmrg
41209ff23fSmrgstatic void
42209ff23fSmrgradeon_box_intersect(BoxPtr dest, BoxPtr a, BoxPtr b)
43209ff23fSmrg{
44209ff23fSmrg    dest->x1 = a->x1 > b->x1 ? a->x1 : b->x1;
45209ff23fSmrg    dest->x2 = a->x2 < b->x2 ? a->x2 : b->x2;
46209ff23fSmrg    dest->y1 = a->y1 > b->y1 ? a->y1 : b->y1;
47209ff23fSmrg    dest->y2 = a->y2 < b->y2 ? a->y2 : b->y2;
48209ff23fSmrg
49209ff23fSmrg    if (dest->x1 >= dest->x2 || dest->y1 >= dest->y2)
50209ff23fSmrg	dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0;
51209ff23fSmrg}
52209ff23fSmrg
53209ff23fSmrgstatic void
54209ff23fSmrgradeon_crtc_box(xf86CrtcPtr crtc, BoxPtr crtc_box)
55209ff23fSmrg{
56209ff23fSmrg    if (crtc->enabled) {
57209ff23fSmrg	crtc_box->x1 = crtc->x;
58209ff23fSmrg	crtc_box->x2 = crtc->x + xf86ModeWidth(&crtc->mode, crtc->rotation);
59209ff23fSmrg	crtc_box->y1 = crtc->y;
60209ff23fSmrg	crtc_box->y2 = crtc->y + xf86ModeHeight(&crtc->mode, crtc->rotation);
61209ff23fSmrg    } else
62209ff23fSmrg	crtc_box->x1 = crtc_box->x2 = crtc_box->y1 = crtc_box->y2 = 0;
63209ff23fSmrg}
64209ff23fSmrg
65209ff23fSmrgstatic int
66209ff23fSmrgradeon_box_area(BoxPtr box)
67209ff23fSmrg{
68209ff23fSmrg    return (int) (box->x2 - box->x1) * (int) (box->y2 - box->y1);
69209ff23fSmrg}
70209ff23fSmrg
716322c902SmrgBool radeon_crtc_is_enabled(xf86CrtcPtr crtc)
7268105dcbSveego{
736322c902Smrg    drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
746322c902Smrg    return drmmode_crtc->dpms_mode == DPMSModeOn;
7568105dcbSveego}
7668105dcbSveego
77b7e1c893Smrgxf86CrtcPtr
786322c902Smrgradeon_pick_best_crtc(ScrnInfoPtr pScrn, Bool consider_disabled,
79ad43ddacSmrg		      int x1, int x2, int y1, int y2)
80b7e1c893Smrg{
81b7e1c893Smrg    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
826322c902Smrg    int			coverage, best_coverage, c, cd;
83b7e1c893Smrg    BoxRec		box, crtc_box, cover_box;
8440732134Srjs    RROutputPtr         primary_output = NULL;
8540732134Srjs    xf86CrtcPtr         best_crtc = NULL, primary_crtc = NULL;
86b7e1c893Smrg
8768105dcbSveego    if (!pScrn->vtSema)
8868105dcbSveego	return NULL;
8968105dcbSveego
90b7e1c893Smrg    box.x1 = x1;
91b7e1c893Smrg    box.x2 = x2;
92b7e1c893Smrg    box.y1 = y1;
93b7e1c893Smrg    box.y2 = y2;
94b7e1c893Smrg    best_coverage = 0;
9540732134Srjs
9640732134Srjs    /* Prefer the CRTC of the primary output */
9768105dcbSveego    if (dixPrivateKeyRegistered(rrPrivKey))
9868105dcbSveego    {
9940732134Srjs	primary_output = RRFirstOutput(pScrn->pScreen);
10040732134Srjs    }
10140732134Srjs    if (primary_output && primary_output->crtc)
10240732134Srjs	primary_crtc = primary_output->crtc->devPrivate;
10340732134Srjs
1046322c902Smrg    /* first consider only enabled CRTCs
1056322c902Smrg     * then on second pass consider disabled ones
106209ff23fSmrg     */
1076322c902Smrg    for (cd = 0; cd < (consider_disabled ? 2 : 1); cd++) {
1086322c902Smrg	for (c = 0; c < xf86_config->num_crtc; c++) {
1096322c902Smrg	    xf86CrtcPtr crtc = xf86_config->crtc[c];
1106322c902Smrg
1116322c902Smrg	    if (!cd && !radeon_crtc_is_enabled(crtc))
1126322c902Smrg		continue;
1136322c902Smrg
1146322c902Smrg	    radeon_crtc_box(crtc, &crtc_box);
1156322c902Smrg	    radeon_box_intersect(&cover_box, &crtc_box, &box);
1166322c902Smrg	    coverage = radeon_box_area(&cover_box);
1176322c902Smrg	    if (coverage > best_coverage ||
1186322c902Smrg		(coverage == best_coverage &&
1196322c902Smrg		 crtc == primary_crtc)) {
1206322c902Smrg		best_crtc = crtc;
1216322c902Smrg		best_coverage = coverage;
1226322c902Smrg	    }
123209ff23fSmrg	}
1246322c902Smrg	if (best_crtc)
1256322c902Smrg	    break;
126209ff23fSmrg    }
127209ff23fSmrg
1286322c902Smrg    return best_crtc;
129209ff23fSmrg}
130209ff23fSmrg
131209ff23fSmrg
132209ff23fSmrgvoid RADEONInitVideo(ScreenPtr pScreen)
133209ff23fSmrg{
13468105dcbSveego    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
135209ff23fSmrg    RADEONInfoPtr    info = RADEONPTR(pScrn);
1362f39173dSmrg    RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
137209ff23fSmrg    XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
1386322c902Smrg    XF86VideoAdaptorPtr texturedAdaptor = NULL;
139209ff23fSmrg    int num_adaptors;
140209ff23fSmrg
1412f39173dSmrg    /* no overlay or 3D on RN50 */
1422f39173dSmrg    if (info->ChipFamily == CHIP_FAMILY_RV100 && !pRADEONEnt->HasCRTC2)
1432f39173dSmrg	    return;
144209ff23fSmrg
145209ff23fSmrg    num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
1466322c902Smrg    newAdaptors = malloc((num_adaptors + 2) * sizeof(*newAdaptors));
147209ff23fSmrg    if (newAdaptors == NULL)
148209ff23fSmrg	return;
149209ff23fSmrg
150209ff23fSmrg    memcpy(newAdaptors, adaptors, num_adaptors * sizeof(XF86VideoAdaptorPtr));
151209ff23fSmrg    adaptors = newAdaptors;
152209ff23fSmrg
1536322c902Smrg    if (info->use_glamor) {
1546322c902Smrg        texturedAdaptor = radeon_glamor_xv_init(pScreen, 16);
1556322c902Smrg	if (texturedAdaptor != NULL) {
1566322c902Smrg	    adaptors[num_adaptors++] = texturedAdaptor;
1576322c902Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Set up textured video (glamor)\n");
158209ff23fSmrg	} else
1596322c902Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to set up textured video (glamor)\n");
1606322c902Smrg    } else if ((info->ChipFamily < CHIP_FAMILY_RS400)
161b7e1c893Smrg	|| (info->directRenderingEnabled)
162b7e1c893Smrg	) {
163b7e1c893Smrg	texturedAdaptor = RADEONSetupImageTexturedVideo(pScreen);
164b7e1c893Smrg	if (texturedAdaptor != NULL) {
165b7e1c893Smrg	    adaptors[num_adaptors++] = texturedAdaptor;
166b7e1c893Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Set up textured video\n");
167209ff23fSmrg	} else
168b7e1c893Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to set up textured video\n");
169209ff23fSmrg    } else
170b7e1c893Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Textured video requires CP on R5xx/R6xx/R7xx/IGP\n");
171209ff23fSmrg
172209ff23fSmrg    if(num_adaptors)
173209ff23fSmrg	xf86XVScreenInit(pScreen, adaptors, num_adaptors);
174209ff23fSmrg
17540732134Srjs    if(texturedAdaptor) {
1766322c902Smrg	XF86MCAdaptorPtr xvmcAdaptor = RADEONCreateAdaptorXvMC(pScreen, (char *)texturedAdaptor->name);
17740732134Srjs	if(xvmcAdaptor) {
17840732134Srjs	    if(!xf86XvMCScreenInit(pScreen, 1, &xvmcAdaptor))
17940732134Srjs		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[XvMC] Failed to initialize extension.\n");
18040732134Srjs	    else
18140732134Srjs		xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[XvMC] Extension initialized.\n");
18240732134Srjs	}
18340732134Srjs    }
18440732134Srjs
185209ff23fSmrg    if(newAdaptors)
1862f39173dSmrg	free(newAdaptors);
187209ff23fSmrg
188209ff23fSmrg}
189209ff23fSmrg
1906322c902Smrgvoid
1916322c902SmrgRADEONCopyData(
1926322c902Smrg  ScrnInfoPtr pScrn,
1936322c902Smrg  unsigned char *src,
1946322c902Smrg  unsigned char *dst,
1956322c902Smrg  unsigned int srcPitch,
1966322c902Smrg  unsigned int dstPitch,
1976322c902Smrg  unsigned int h,
1986322c902Smrg  unsigned int w,
1996322c902Smrg  unsigned int bpp
2006322c902Smrg){
2016322c902Smrg    /* Get the byte-swapping right for big endian systems */
2026322c902Smrg    if ( bpp == 2 ) {
2036322c902Smrg	w *= 2;
2046322c902Smrg	bpp = 1;
205209ff23fSmrg    }
206209ff23fSmrg
207209ff23fSmrg    {
2086322c902Smrg	int swap = RADEON_HOST_DATA_SWAP_NONE;
209209ff23fSmrg
2106322c902Smrg#if X_BYTE_ORDER == X_BIG_ENDIAN
2116322c902Smrg	switch(bpp) {
2126322c902Smrg	case 2:
2136322c902Smrg	    swap = RADEON_HOST_DATA_SWAP_16BIT;
2146322c902Smrg	    break;
2156322c902Smrg	case 4:
2166322c902Smrg	    swap = RADEON_HOST_DATA_SWAP_32BIT;
2176322c902Smrg	    break;
2186322c902Smrg	}
2196322c902Smrg#endif
220209ff23fSmrg
2216322c902Smrg	w *= bpp;
222209ff23fSmrg
2236322c902Smrg	if (dstPitch == w && dstPitch == srcPitch)
2246322c902Smrg	    RADEONCopySwap(dst, src, h * dstPitch, swap);
2256322c902Smrg	else {
2266322c902Smrg	    while (h--) {
2276322c902Smrg		RADEONCopySwap(dst, src, w, swap);
2286322c902Smrg		src += srcPitch;
2296322c902Smrg		dst += dstPitch;
2306322c902Smrg	    }
2316322c902Smrg	}
232209ff23fSmrg    }
233209ff23fSmrg}
234209ff23fSmrg
235209ff23fSmrg
236209ff23fSmrgvoid
2376322c902SmrgRADEONCopyMungedData(
2386322c902Smrg   ScrnInfoPtr pScrn,
2396322c902Smrg   unsigned char *src1,
2406322c902Smrg   unsigned char *src2,
2416322c902Smrg   unsigned char *src3,
2426322c902Smrg   unsigned char *dst1,
2436322c902Smrg   unsigned int srcPitch,
2446322c902Smrg   unsigned int srcPitch2,
2456322c902Smrg   unsigned int dstPitch,
2466322c902Smrg   unsigned int h,
2476322c902Smrg   unsigned int w
2486322c902Smrg){
2496322c902Smrg    uint32_t *dst;
2506322c902Smrg    uint8_t *s1, *s2, *s3;
2516322c902Smrg    int i, j;
2526322c902Smrg
2536322c902Smrg    w /= 2;
2546322c902Smrg
2556322c902Smrg    for( j = 0; j < h; j++ ) {
2566322c902Smrg	dst = (pointer)dst1;
2576322c902Smrg	s1 = src1;  s2 = src2;  s3 = src3;
2586322c902Smrg	i = w;
2596322c902Smrg	while( i > 4 ) {
2606322c902Smrg	    dst[0] = cpu_to_le32(s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24));
2616322c902Smrg	    dst[1] = cpu_to_le32(s1[2] | (s1[3] << 16) | (s3[1] << 8) | (s2[1] << 24));
2626322c902Smrg	    dst[2] = cpu_to_le32(s1[4] | (s1[5] << 16) | (s3[2] << 8) | (s2[2] << 24));
2636322c902Smrg	    dst[3] = cpu_to_le32(s1[6] | (s1[7] << 16) | (s3[3] << 8) | (s2[3] << 24));
2646322c902Smrg	    dst += 4; s2 += 4; s3 += 4; s1 += 8;
2656322c902Smrg	    i -= 4;
266209ff23fSmrg	}
2676322c902Smrg	while( i-- ) {
2686322c902Smrg	    dst[0] = cpu_to_le32(s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24));
2696322c902Smrg	    dst++; s2++; s3++;
2706322c902Smrg	    s1 += 2;
271209ff23fSmrg	}
272209ff23fSmrg
2736322c902Smrg	dst1 += dstPitch;
2746322c902Smrg	src1 += srcPitch;
2756322c902Smrg	if( j & 1 ) {
2766322c902Smrg	    src2 += srcPitch2;
2776322c902Smrg	    src3 += srcPitch2;
2786322c902Smrg	}
279b7e1c893Smrg    }
280209ff23fSmrg}
281