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