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