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