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