radeon_video.c revision 0d16fef4
1de2362d3Smrg
2de2362d3Smrg#ifdef HAVE_CONFIG_H
3de2362d3Smrg#include "config.h"
4de2362d3Smrg#endif
5de2362d3Smrg
6de2362d3Smrg#include <stdlib.h>
7de2362d3Smrg#include <string.h>
8de2362d3Smrg#include <stdio.h>
9de2362d3Smrg#include <math.h>
10de2362d3Smrg
11de2362d3Smrg#include "radeon.h"
120d16fef4Smrg#include "radeon_glamor.h"
13de2362d3Smrg#include "radeon_reg.h"
14de2362d3Smrg#include "radeon_probe.h"
15de2362d3Smrg#include "radeon_video.h"
16de2362d3Smrg
17de2362d3Smrg#include "xf86.h"
18de2362d3Smrg#include "dixstruct.h"
19de2362d3Smrg
20de2362d3Smrg/* DPMS */
21de2362d3Smrg#ifdef HAVE_XEXTPROTO_71
22de2362d3Smrg#include <X11/extensions/dpmsconst.h>
23de2362d3Smrg#else
24de2362d3Smrg#define DPMS_SERVER
25de2362d3Smrg#include <X11/extensions/dpms.h>
26de2362d3Smrg#endif
27de2362d3Smrg
28de2362d3Smrg#include <X11/extensions/Xv.h>
29de2362d3Smrg#include "fourcc.h"
30de2362d3Smrg
31de2362d3Smrg#define OFF_DELAY       250  /* milliseconds */
32de2362d3Smrg#define FREE_DELAY      15000
33de2362d3Smrg
34de2362d3Smrg#define OFF_TIMER       0x01
35de2362d3Smrg#define FREE_TIMER      0x02
36de2362d3Smrg#define CLIENT_VIDEO_ON 0x04
37de2362d3Smrg
38de2362d3Smrg#define GET_PORT_PRIVATE(pScrn) \
39de2362d3Smrg   (RADEONPortPrivPtr)((RADEONPTR(pScrn))->adaptor->pPortPrivates[0].ptr)
40de2362d3Smrg
41de2362d3Smrgstatic void
42de2362d3Smrgradeon_box_intersect(BoxPtr dest, BoxPtr a, BoxPtr b)
43de2362d3Smrg{
44de2362d3Smrg    dest->x1 = a->x1 > b->x1 ? a->x1 : b->x1;
45de2362d3Smrg    dest->x2 = a->x2 < b->x2 ? a->x2 : b->x2;
46de2362d3Smrg    dest->y1 = a->y1 > b->y1 ? a->y1 : b->y1;
47de2362d3Smrg    dest->y2 = a->y2 < b->y2 ? a->y2 : b->y2;
48de2362d3Smrg
49de2362d3Smrg    if (dest->x1 >= dest->x2 || dest->y1 >= dest->y2)
50de2362d3Smrg	dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0;
51de2362d3Smrg}
52de2362d3Smrg
53de2362d3Smrgstatic void
54de2362d3Smrgradeon_crtc_box(xf86CrtcPtr crtc, BoxPtr crtc_box)
55de2362d3Smrg{
56de2362d3Smrg    if (crtc->enabled) {
57de2362d3Smrg	crtc_box->x1 = crtc->x;
58de2362d3Smrg	crtc_box->x2 = crtc->x + xf86ModeWidth(&crtc->mode, crtc->rotation);
59de2362d3Smrg	crtc_box->y1 = crtc->y;
60de2362d3Smrg	crtc_box->y2 = crtc->y + xf86ModeHeight(&crtc->mode, crtc->rotation);
61de2362d3Smrg    } else
62de2362d3Smrg	crtc_box->x1 = crtc_box->x2 = crtc_box->y1 = crtc_box->y2 = 0;
63de2362d3Smrg}
64de2362d3Smrg
65de2362d3Smrgstatic int
66de2362d3Smrgradeon_box_area(BoxPtr box)
67de2362d3Smrg{
68de2362d3Smrg    return (int) (box->x2 - box->x1) * (int) (box->y2 - box->y1);
69de2362d3Smrg}
70de2362d3Smrg
71de2362d3SmrgBool radeon_crtc_is_enabled(xf86CrtcPtr crtc)
72de2362d3Smrg{
73de2362d3Smrg    drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
74de2362d3Smrg    return drmmode_crtc->dpms_mode == DPMSModeOn;
75de2362d3Smrg}
76de2362d3Smrg
77de2362d3Smrgxf86CrtcPtr
78de2362d3Smrgradeon_pick_best_crtc(ScrnInfoPtr pScrn, Bool consider_disabled,
79de2362d3Smrg		      int x1, int x2, int y1, int y2)
80de2362d3Smrg{
81de2362d3Smrg    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
820d16fef4Smrg    int			coverage, best_coverage, c, cd;
83de2362d3Smrg    BoxRec		box, crtc_box, cover_box;
84de2362d3Smrg    RROutputPtr         primary_output = NULL;
85de2362d3Smrg    xf86CrtcPtr         best_crtc = NULL, primary_crtc = NULL;
86de2362d3Smrg
87de2362d3Smrg    if (!pScrn->vtSema)
88de2362d3Smrg	return NULL;
89de2362d3Smrg
90de2362d3Smrg    box.x1 = x1;
91de2362d3Smrg    box.x2 = x2;
92de2362d3Smrg    box.y1 = y1;
93de2362d3Smrg    box.y2 = y2;
94de2362d3Smrg    best_coverage = 0;
95de2362d3Smrg
96de2362d3Smrg    /* Prefer the CRTC of the primary output */
97de2362d3Smrg    if (dixPrivateKeyRegistered(rrPrivKey))
98de2362d3Smrg    {
99de2362d3Smrg	primary_output = RRFirstOutput(pScrn->pScreen);
100de2362d3Smrg    }
101de2362d3Smrg    if (primary_output && primary_output->crtc)
102de2362d3Smrg	primary_crtc = primary_output->crtc->devPrivate;
103de2362d3Smrg
1040d16fef4Smrg    /* first consider only enabled CRTCs
1050d16fef4Smrg     * then on second pass consider disabled ones
1060d16fef4Smrg     */
1070d16fef4Smrg    for (cd = 0; cd < (consider_disabled ? 2 : 1); cd++) {
1080d16fef4Smrg	for (c = 0; c < xf86_config->num_crtc; c++) {
1090d16fef4Smrg	    xf86CrtcPtr crtc = xf86_config->crtc[c];
1100d16fef4Smrg
1110d16fef4Smrg	    if (!cd && !radeon_crtc_is_enabled(crtc))
1120d16fef4Smrg		continue;
1130d16fef4Smrg
1140d16fef4Smrg	    radeon_crtc_box(crtc, &crtc_box);
1150d16fef4Smrg	    radeon_box_intersect(&cover_box, &crtc_box, &box);
1160d16fef4Smrg	    coverage = radeon_box_area(&cover_box);
1170d16fef4Smrg	    if (coverage > best_coverage ||
1180d16fef4Smrg		(coverage == best_coverage &&
1190d16fef4Smrg		 crtc == primary_crtc)) {
1200d16fef4Smrg		best_crtc = crtc;
1210d16fef4Smrg		best_coverage = coverage;
1220d16fef4Smrg	    }
123de2362d3Smrg	}
1240d16fef4Smrg	if (best_crtc)
1250d16fef4Smrg	    break;
126de2362d3Smrg    }
1270d16fef4Smrg
128de2362d3Smrg    return best_crtc;
129de2362d3Smrg}
130de2362d3Smrg
131de2362d3Smrg
132de2362d3Smrgvoid RADEONInitVideo(ScreenPtr pScreen)
133de2362d3Smrg{
134de2362d3Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
135de2362d3Smrg    RADEONInfoPtr    info = RADEONPTR(pScrn);
136de2362d3Smrg    RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
137de2362d3Smrg    XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
138de2362d3Smrg    XF86VideoAdaptorPtr texturedAdaptor = NULL;
139de2362d3Smrg    int num_adaptors;
140de2362d3Smrg
141de2362d3Smrg    /* no overlay or 3D on RN50 */
142de2362d3Smrg    if (info->ChipFamily == CHIP_FAMILY_RV100 && !pRADEONEnt->HasCRTC2)
143de2362d3Smrg	    return;
144de2362d3Smrg
145de2362d3Smrg    num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
1460d16fef4Smrg    newAdaptors = malloc((num_adaptors + 2) * sizeof(*newAdaptors));
147de2362d3Smrg    if (newAdaptors == NULL)
148de2362d3Smrg	return;
149de2362d3Smrg
150de2362d3Smrg    memcpy(newAdaptors, adaptors, num_adaptors * sizeof(XF86VideoAdaptorPtr));
151de2362d3Smrg    adaptors = newAdaptors;
152de2362d3Smrg
153de2362d3Smrg    if (info->use_glamor) {
154de2362d3Smrg        texturedAdaptor = radeon_glamor_xv_init(pScreen, 16);
155de2362d3Smrg	if (texturedAdaptor != NULL) {
156de2362d3Smrg	    adaptors[num_adaptors++] = texturedAdaptor;
157de2362d3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Set up textured video (glamor)\n");
158de2362d3Smrg	} else
159de2362d3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to set up textured video (glamor)\n");
160de2362d3Smrg    } else if ((info->ChipFamily < CHIP_FAMILY_RS400)
161de2362d3Smrg	|| (info->directRenderingEnabled)
162de2362d3Smrg	) {
163de2362d3Smrg	texturedAdaptor = RADEONSetupImageTexturedVideo(pScreen);
164de2362d3Smrg	if (texturedAdaptor != NULL) {
165de2362d3Smrg	    adaptors[num_adaptors++] = texturedAdaptor;
166de2362d3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Set up textured video\n");
167de2362d3Smrg	} else
168de2362d3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to set up textured video\n");
169de2362d3Smrg    } else
170de2362d3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Textured video requires CP on R5xx/R6xx/R7xx/IGP\n");
171de2362d3Smrg
172de2362d3Smrg    if(num_adaptors)
173de2362d3Smrg	xf86XVScreenInit(pScreen, adaptors, num_adaptors);
174de2362d3Smrg
175de2362d3Smrg    if(texturedAdaptor) {
176de2362d3Smrg	XF86MCAdaptorPtr xvmcAdaptor = RADEONCreateAdaptorXvMC(pScreen, (char *)texturedAdaptor->name);
177de2362d3Smrg	if(xvmcAdaptor) {
178de2362d3Smrg	    if(!xf86XvMCScreenInit(pScreen, 1, &xvmcAdaptor))
179de2362d3Smrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[XvMC] Failed to initialize extension.\n");
180de2362d3Smrg	    else
181de2362d3Smrg		xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[XvMC] Extension initialized.\n");
182de2362d3Smrg	}
183de2362d3Smrg    }
184de2362d3Smrg
185de2362d3Smrg    if(newAdaptors)
186de2362d3Smrg	free(newAdaptors);
187de2362d3Smrg
188de2362d3Smrg}
189de2362d3Smrg
190de2362d3Smrgvoid
191de2362d3SmrgRADEONCopyData(
192de2362d3Smrg  ScrnInfoPtr pScrn,
193de2362d3Smrg  unsigned char *src,
194de2362d3Smrg  unsigned char *dst,
195de2362d3Smrg  unsigned int srcPitch,
196de2362d3Smrg  unsigned int dstPitch,
197de2362d3Smrg  unsigned int h,
198de2362d3Smrg  unsigned int w,
199de2362d3Smrg  unsigned int bpp
200de2362d3Smrg){
201de2362d3Smrg    /* Get the byte-swapping right for big endian systems */
202de2362d3Smrg    if ( bpp == 2 ) {
203de2362d3Smrg	w *= 2;
204de2362d3Smrg	bpp = 1;
205de2362d3Smrg    }
206de2362d3Smrg
207de2362d3Smrg    {
208de2362d3Smrg	int swap = RADEON_HOST_DATA_SWAP_NONE;
209de2362d3Smrg
210de2362d3Smrg#if X_BYTE_ORDER == X_BIG_ENDIAN
211de2362d3Smrg	switch(bpp) {
212de2362d3Smrg	case 2:
213de2362d3Smrg	    swap = RADEON_HOST_DATA_SWAP_16BIT;
214de2362d3Smrg	    break;
215de2362d3Smrg	case 4:
216de2362d3Smrg	    swap = RADEON_HOST_DATA_SWAP_32BIT;
217de2362d3Smrg	    break;
218de2362d3Smrg	}
219de2362d3Smrg#endif
220de2362d3Smrg
221de2362d3Smrg	w *= bpp;
222de2362d3Smrg
223de2362d3Smrg	if (dstPitch == w && dstPitch == srcPitch)
224de2362d3Smrg	    RADEONCopySwap(dst, src, h * dstPitch, swap);
225de2362d3Smrg	else {
226de2362d3Smrg	    while (h--) {
227de2362d3Smrg		RADEONCopySwap(dst, src, w, swap);
228de2362d3Smrg		src += srcPitch;
229de2362d3Smrg		dst += dstPitch;
230de2362d3Smrg	    }
231de2362d3Smrg	}
232de2362d3Smrg    }
233de2362d3Smrg}
234de2362d3Smrg
235de2362d3Smrg
236de2362d3Smrgvoid
237de2362d3SmrgRADEONCopyMungedData(
238de2362d3Smrg   ScrnInfoPtr pScrn,
239de2362d3Smrg   unsigned char *src1,
240de2362d3Smrg   unsigned char *src2,
241de2362d3Smrg   unsigned char *src3,
242de2362d3Smrg   unsigned char *dst1,
243de2362d3Smrg   unsigned int srcPitch,
244de2362d3Smrg   unsigned int srcPitch2,
245de2362d3Smrg   unsigned int dstPitch,
246de2362d3Smrg   unsigned int h,
247de2362d3Smrg   unsigned int w
248de2362d3Smrg){
249de2362d3Smrg    uint32_t *dst;
250de2362d3Smrg    uint8_t *s1, *s2, *s3;
251de2362d3Smrg    int i, j;
252de2362d3Smrg
253de2362d3Smrg    w /= 2;
254de2362d3Smrg
255de2362d3Smrg    for( j = 0; j < h; j++ ) {
256de2362d3Smrg	dst = (pointer)dst1;
257de2362d3Smrg	s1 = src1;  s2 = src2;  s3 = src3;
258de2362d3Smrg	i = w;
259de2362d3Smrg	while( i > 4 ) {
260de2362d3Smrg	    dst[0] = cpu_to_le32(s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24));
261de2362d3Smrg	    dst[1] = cpu_to_le32(s1[2] | (s1[3] << 16) | (s3[1] << 8) | (s2[1] << 24));
262de2362d3Smrg	    dst[2] = cpu_to_le32(s1[4] | (s1[5] << 16) | (s3[2] << 8) | (s2[2] << 24));
263de2362d3Smrg	    dst[3] = cpu_to_le32(s1[6] | (s1[7] << 16) | (s3[3] << 8) | (s2[3] << 24));
264de2362d3Smrg	    dst += 4; s2 += 4; s3 += 4; s1 += 8;
265de2362d3Smrg	    i -= 4;
266de2362d3Smrg	}
267de2362d3Smrg	while( i-- ) {
268de2362d3Smrg	    dst[0] = cpu_to_le32(s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24));
269de2362d3Smrg	    dst++; s2++; s3++;
270de2362d3Smrg	    s1 += 2;
271de2362d3Smrg	}
272de2362d3Smrg
273de2362d3Smrg	dst1 += dstPitch;
274de2362d3Smrg	src1 += srcPitch;
275de2362d3Smrg	if( j & 1 ) {
276de2362d3Smrg	    src2 += srcPitch2;
277de2362d3Smrg	    src3 += srcPitch2;
278de2362d3Smrg	}
279de2362d3Smrg    }
280de2362d3Smrg}
281