amdgpu_video.c revision e49c54bc
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 "amdgpu_drv.h" 12#include "amdgpu_glamor.h" 13#include "amdgpu_probe.h" 14#include "amdgpu_video.h" 15#include "amdgpu_pixmap.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 38static void amdgpu_box_intersect(BoxPtr dest, BoxPtr a, BoxPtr b) 39{ 40 dest->x1 = a->x1 > b->x1 ? a->x1 : b->x1; 41 dest->x2 = a->x2 < b->x2 ? a->x2 : b->x2; 42 if (dest->x1 >= dest->x2) { 43 dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0; 44 return; 45 } 46 47 dest->y1 = a->y1 > b->y1 ? a->y1 : b->y1; 48 dest->y2 = a->y2 < b->y2 ? a->y2 : b->y2; 49 if (dest->y1 >= dest->y2) 50 dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0; 51} 52 53static int amdgpu_box_area(BoxPtr box) 54{ 55 return (int)(box->x2 - box->x1) * (int)(box->y2 - box->y1); 56} 57 58Bool 59amdgpu_crtc_is_enabled(xf86CrtcPtr crtc) 60{ 61 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 62 63 return crtc->enabled && drmmode_crtc->dpms_mode == DPMSModeOn; 64} 65 66static void amdgpu_crtc_box(RRCrtcPtr crtc, BoxPtr crtc_box) 67{ 68 if (crtc->mode) { 69 crtc_box->x1 = crtc->x; 70 crtc_box->y1 = crtc->y; 71 switch (crtc->rotation) { 72 case RR_Rotate_0: 73 case RR_Rotate_180: 74 default: 75 crtc_box->x2 = crtc->x + crtc->mode->mode.width; 76 crtc_box->y2 = crtc->y + crtc->mode->mode.height; 77 break; 78 case RR_Rotate_90: 79 case RR_Rotate_270: 80 crtc_box->x2 = crtc->x + crtc->mode->mode.height; 81 crtc_box->y2 = crtc->y + crtc->mode->mode.width; 82 break; 83 } 84 } else 85 crtc_box->x1 = crtc_box->x2 = crtc_box->y1 = crtc_box->y2 = 0; 86} 87 88static Bool amdgpu_crtc_on(RRCrtcPtr crtc, Bool crtc_is_xf86_hint) 89{ 90 if (!crtc) { 91 return FALSE; 92 } 93 if (crtc_is_xf86_hint && crtc->devPrivate) { 94 return amdgpu_crtc_is_enabled(crtc->devPrivate); 95 } else { 96 return !!crtc->mode; 97 } 98} 99 100/* 101 * Return the crtc covering 'box'. If two crtcs cover a portion of 102 * 'box', then prefer the crtc with greater coverage. 103 */ 104static RRCrtcPtr 105amdgpu_crtc_covering_box(ScreenPtr pScreen, BoxPtr box, Bool screen_is_xf86_hint) 106{ 107 rrScrPrivPtr pScrPriv; 108 RRCrtcPtr crtc, best_crtc, primary_crtc; 109 int coverage, best_coverage; 110 int c; 111 BoxRec crtc_box, cover_box; 112 RROutputPtr primary_output; 113 114 best_crtc = NULL; 115 best_coverage = 0; 116 primary_crtc = NULL; 117 primary_output = NULL; 118 119 if (!dixPrivateKeyRegistered(rrPrivKey)) 120 return NULL; 121 122 pScrPriv = rrGetScrPriv(pScreen); 123 124 if (!pScrPriv) 125 return NULL; 126 127 primary_output = RRFirstOutput(pScreen); 128 if (primary_output && primary_output->crtc) 129 primary_crtc = primary_output->crtc; 130 131 for (c = 0; c < pScrPriv->numCrtcs; c++) { 132 crtc = pScrPriv->crtcs[c]; 133 134 /* If the CRTC is off, treat it as not covering */ 135 if (!amdgpu_crtc_on(crtc, screen_is_xf86_hint)) 136 continue; 137 138 amdgpu_crtc_box(crtc, &crtc_box); 139 amdgpu_box_intersect(&cover_box, &crtc_box, box); 140 coverage = amdgpu_box_area(&cover_box); 141 if (coverage > best_coverage || 142 (crtc == primary_crtc && coverage == best_coverage)) { 143 best_crtc = crtc; 144 best_coverage = coverage; 145 } 146 } 147 148 return best_crtc; 149} 150 151#if ABI_VIDEODRV_VERSION >= SET_ABI_VERSION(23, 0) 152static RRCrtcPtr 153amdgpu_crtc_covering_box_on_secondary(ScreenPtr pScreen, BoxPtr box) 154{ 155 if (!pScreen->isGPU) { 156 ScreenPtr secondary; 157 RRCrtcPtr crtc = NULL; 158 159 xorg_list_for_each_entry(secondary, &pScreen->secondary_list, secondary_head) { 160 if (!secondary->is_output_secondary) 161 continue; 162 163 crtc = amdgpu_crtc_covering_box(secondary, box, FALSE); 164 if (crtc) 165 return crtc; 166 } 167 } 168 169 return NULL; 170} 171#endif 172 173RRCrtcPtr 174amdgpu_randr_crtc_covering_drawable(DrawablePtr pDraw) 175{ 176 ScreenPtr pScreen = pDraw->pScreen; 177 RRCrtcPtr crtc = NULL; 178 BoxRec box; 179 180 box.x1 = pDraw->x; 181 box.y1 = pDraw->y; 182 box.x2 = box.x1 + pDraw->width; 183 box.y2 = box.y1 + pDraw->height; 184 185 crtc = amdgpu_crtc_covering_box(pScreen, &box, TRUE); 186#if ABI_VIDEODRV_VERSION >= SET_ABI_VERSION(23, 0) 187 if (!crtc) { 188 crtc = amdgpu_crtc_covering_box_on_secondary(pScreen, &box); 189 } 190#endif 191 return crtc; 192} 193 194xf86CrtcPtr 195amdgpu_pick_best_crtc(ScreenPtr pScreen, 196 int x1, int x2, int y1, int y2) 197{ 198 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 199 200 if (!pScrn->vtSema) 201 return NULL; 202 203 RRCrtcPtr crtc = NULL; 204 BoxRec box; 205 206 box.x1 = x1; 207 box.x2 = x2; 208 box.y1 = y1; 209 box.y2 = y2; 210 211 crtc = amdgpu_crtc_covering_box(pScreen, &box, TRUE); 212 if (crtc) { 213 return crtc->devPrivate; 214 } 215 return NULL; 216} 217 218void AMDGPUInitVideo(ScreenPtr pScreen) 219{ 220 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 221 AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 222 XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL; 223 XF86VideoAdaptorPtr texturedAdaptor = NULL; 224 int num_adaptors; 225 226 num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); 227 newAdaptors = 228 malloc((num_adaptors + 2) * sizeof(*newAdaptors)); 229 if (!newAdaptors) 230 return; 231 232 memcpy(newAdaptors, adaptors, 233 num_adaptors * sizeof(XF86VideoAdaptorPtr)); 234 adaptors = newAdaptors; 235 236 if (info->use_glamor) { 237 texturedAdaptor = amdgpu_glamor_xv_init(pScreen, 16); 238 if (texturedAdaptor != NULL) { 239 adaptors[num_adaptors++] = texturedAdaptor; 240 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 241 "Set up textured video (glamor)\n"); 242 } else 243 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 244 "Failed to set up textured video (glamor)\n"); 245 } 246 247 if (num_adaptors) 248 xf86XVScreenInit(pScreen, adaptors, num_adaptors); 249 250 if (newAdaptors) 251 free(newAdaptors); 252 253} 254