amdgpu_video.c revision 35d5b7c7
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	dest->y1 = a->y1 > b->y1 ? a->y1 : b->y1;
43	dest->y2 = a->y2 < b->y2 ? a->y2 : b->y2;
44
45	if (dest->x1 >= dest->x2 || dest->y1 >= dest->y2)
46		dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0;
47}
48
49static void amdgpu_crtc_box(xf86CrtcPtr crtc, BoxPtr crtc_box)
50{
51	if (crtc->enabled) {
52		crtc_box->x1 = crtc->x;
53		crtc_box->x2 =
54		    crtc->x + xf86ModeWidth(&crtc->mode, crtc->rotation);
55		crtc_box->y1 = crtc->y;
56		crtc_box->y2 =
57		    crtc->y + xf86ModeHeight(&crtc->mode, crtc->rotation);
58	} else
59		crtc_box->x1 = crtc_box->x2 = crtc_box->y1 = crtc_box->y2 = 0;
60}
61
62static int amdgpu_box_area(BoxPtr box)
63{
64	return (int)(box->x2 - box->x1) * (int)(box->y2 - box->y1);
65}
66
67Bool amdgpu_crtc_is_enabled(xf86CrtcPtr crtc)
68{
69	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
70	return drmmode_crtc->dpms_mode == DPMSModeOn;
71}
72
73xf86CrtcPtr
74amdgpu_pick_best_crtc(ScrnInfoPtr pScrn, Bool consider_disabled,
75		      int x1, int x2, int y1, int y2)
76{
77	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
78	int coverage, best_coverage, c, cd;
79	BoxRec box, crtc_box, cover_box;
80	RROutputPtr primary_output = NULL;
81	xf86CrtcPtr best_crtc = NULL, primary_crtc = NULL;
82
83	if (!pScrn->vtSema)
84		return NULL;
85
86	box.x1 = x1;
87	box.x2 = x2;
88	box.y1 = y1;
89	box.y2 = y2;
90	best_coverage = 0;
91
92	/* Prefer the CRTC of the primary output */
93	if (dixPrivateKeyRegistered(rrPrivKey))
94	{
95		primary_output = RRFirstOutput(pScrn->pScreen);
96	}
97	if (primary_output && primary_output->crtc)
98		primary_crtc = primary_output->crtc->devPrivate;
99
100	/* first consider only enabled CRTCs
101	 * then on second pass consider disabled ones
102	 */
103	for (cd = 0; cd < (consider_disabled ? 2 : 1); cd++) {
104		for (c = 0; c < xf86_config->num_crtc; c++) {
105			xf86CrtcPtr crtc = xf86_config->crtc[c];
106
107			if (!cd && !amdgpu_crtc_is_enabled(crtc))
108				continue;
109
110			amdgpu_crtc_box(crtc, &crtc_box);
111			amdgpu_box_intersect(&cover_box, &crtc_box, &box);
112			coverage = amdgpu_box_area(&cover_box);
113			if (coverage > best_coverage ||
114			    (coverage == best_coverage &&
115			     crtc == primary_crtc)) {
116				best_crtc = crtc;
117				best_coverage = coverage;
118			}
119		}
120		if (best_crtc)
121			break;
122	}
123
124	return best_crtc;
125}
126
127void AMDGPUInitVideo(ScreenPtr pScreen)
128{
129	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
130	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
131	XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
132	XF86VideoAdaptorPtr texturedAdaptor = NULL;
133	int num_adaptors;
134
135	num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
136	newAdaptors =
137	    malloc((num_adaptors + 2) * sizeof(*newAdaptors));
138	if (!newAdaptors)
139		return;
140
141	memcpy(newAdaptors, adaptors,
142	       num_adaptors * sizeof(XF86VideoAdaptorPtr));
143	adaptors = newAdaptors;
144
145	if (info->use_glamor) {
146		texturedAdaptor = amdgpu_glamor_xv_init(pScreen, 16);
147		if (texturedAdaptor != NULL) {
148			adaptors[num_adaptors++] = texturedAdaptor;
149			xf86DrvMsg(pScrn->scrnIndex, X_INFO,
150				   "Set up textured video (glamor)\n");
151		} else
152			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
153				   "Failed to set up textured video (glamor)\n");
154	}
155
156	if (num_adaptors)
157		xf86XVScreenInit(pScreen, adaptors, num_adaptors);
158
159	if (newAdaptors)
160		free(newAdaptors);
161
162}
163