1 /*
2 * Copyright (c) 2011 Intel Corporation. All Rights Reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sub license, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
14 * of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
19 * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
20 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 * Jason Hu <jason.hu@intel.com>
26 * Zhaohan Ren <zhaohan.ren@intel.com>
27 *
28 */
29
30 #include <unistd.h>
31 #include "psb_xrandr.h"
32 #include "psb_x11.h"
33 #include "psb_drv_debug.h"
34
35 /* Global variable for xrandr */
36 psb_xrandr_info_p psb_xrandr_info;
37
38 #define INIT_DRIVER_DATA psb_driver_data_p driver_data = (psb_driver_data_p) ctx->pDriverData
39 #define INIT_OUTPUT_PRIV psb_x11_output_p output = (psb_x11_output_p)(((psb_driver_data_p)ctx->pDriverData)->ws_priv)
40
41 #define MWM_HINTS_DECORATIONS (1L << 1)
42 typedef struct {
43 int flags;
44 int functions;
45 int decorations;
46 int input_mode;
47 int status;
48 } MWMHints;
49
location2string(psb_xrandr_location location)50 char* location2string(psb_xrandr_location location)
51 {
52 switch (location) {
53 case ABOVE:
54 return "ABOVE";
55 break;
56 case BELOW:
57 return "BELOW";
58 break;
59 case LEFT_OF:
60 return "LEFT_OF";
61 break;
62 case RIGHT_OF:
63 return "RIGHT_OF";
64 break;
65 default:
66 return "NORMAL";
67 break;
68 }
69 }
70
RRrotation2VArotation(Rotation rotation)71 static int RRrotation2VArotation(Rotation rotation)
72 {
73 switch (rotation) {
74 case RR_Rotate_0:
75 return VA_ROTATION_NONE;
76 case RR_Rotate_90:
77 return VA_ROTATION_270;
78 case RR_Rotate_180:
79 return VA_ROTATION_180;
80 case RR_Rotate_270:
81 return VA_ROTATION_90;
82 }
83
84 return 0;
85 }
get_crtc_by_id(RRCrtc crtc_id)86 static psb_xrandr_crtc_p get_crtc_by_id(RRCrtc crtc_id)
87 {
88 psb_xrandr_crtc_p p_crtc;
89 for (p_crtc = psb_xrandr_info->crtc_head; p_crtc; p_crtc = p_crtc->next)
90 if (p_crtc->crtc_id == crtc_id)
91 return p_crtc;
92 return NULL;
93 }
94
psb_xrandr_hdmi_property(VADriverContextP ctx)95 static void psb_xrandr_hdmi_property(VADriverContextP ctx)
96 {
97 INIT_DRIVER_DATA;
98 Atom *props;
99 Atom actual_type;
100 XRRPropertyInfo *propinfo;
101 int i, nprop, actual_format;
102 unsigned long nitems, bytes_after;
103 char* prop_name;
104 unsigned char* prop;
105
106 /* Check HDMI properties */
107 props = XRRListOutputProperties(psb_xrandr_info->dpy, psb_xrandr_info->extend_output->output_id, &nprop);
108 if (!props) {
109 drv_debug_msg(VIDEO_DEBUG_ERROR, "Xrandr: XRRListOutputProperties failed\n", psb_xrandr_info->extend_output->output_id);
110 return;
111 }
112
113 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: extend output %08x has %d properties\n", psb_xrandr_info->extend_output->output_id, nprop);
114
115 for (i = 0; i < nprop; i++) {
116 XRRGetOutputProperty(psb_xrandr_info->dpy, psb_xrandr_info->extend_output->output_id, props[i],
117 0, 100, False, False, AnyPropertyType, &actual_type, &actual_format,
118 &nitems, &bytes_after, &prop);
119
120 propinfo = XRRQueryOutputProperty(psb_xrandr_info->dpy, psb_xrandr_info->extend_output->output_id, props[i]);
121 if (!propinfo) {
122 drv_debug_msg(VIDEO_DEBUG_ERROR, "Xrandr: get output %08x prop %08x failed\n", psb_xrandr_info->extend_output->output_id, props[i]);
123 return;
124 }
125
126 prop_name = XGetAtomName(psb_xrandr_info->dpy, props[i]);
127
128 /* Currently all properties are XA_INTEGER, 32 */
129 if (!strcmp(prop_name, "ExtVideoMode")) {
130 psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode = (int)((INT32*)prop)[0];
131 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: ExtVideoMode (%08x)\n", psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode);
132 } else if (!strcmp(prop_name, "ExtVideoMode_Xres")) {
133 psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_XRes = (int)((INT32*)prop)[0];
134 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: ExtVideoMode_XRes (%08x)\n", psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_XRes);
135 } else if (!strcmp(prop_name, "ExtVideoMode_Yres")) {
136 psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_YRes = (int)((INT32*)prop)[0];
137 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: ExtVideoMode_YRes (%08x)\n", psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_YRes);
138 } else if (!strcmp(prop_name, "ExtVideoMode_X_Offset")) {
139 psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_X_Offset = (int)((INT32*)prop)[0];
140 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: ExtVideoMode_X_Offset (%08x)\n", psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_X_Offset);
141 } else if (!strcmp(prop_name, "ExtVideoMode_Y_Offset")) {
142 psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_Y_Offset = (int)((INT32*)prop)[0];
143 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: ExtVideoMode_Y_Offset (%08x)\n", psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_Y_Offset);
144 } else if (!strcmp(prop_name, "ExtVideoMode_Center")) {
145 psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_Center = (int)((INT32*)prop)[0];
146 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: ExtVideoMode_Center (%08x)\n", psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_Center);
147 } else if (!strcmp(prop_name, "ExtVideoMode_SubTitle")) {
148 psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_SubTitle = (int)((INT32*)prop)[0];
149 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: ExtVideoMode_SubTitle (%08x)\n", psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_SubTitle);
150 } else if (!strcmp(prop_name, "ExtDesktopMode")) {
151 if ((psb_xrandr_info->hdmi_extvideo_prop->ExtDesktopMode != EXTENDEDVIDEO) &&
152 ((int)((INT32*)prop)[0] == EXTENDEDVIDEO)) {
153 driver_data->xrandr_dirty |= PSB_NEW_EXTVIDEO;
154 }
155 psb_xrandr_info->hdmi_extvideo_prop->ExtDesktopMode = (int)((INT32*)prop)[0];
156 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: ExtDesktopMode (%08x)\n", psb_xrandr_info->hdmi_extvideo_prop->ExtDesktopMode);
157 } else if (!strcmp(prop_name, "OverscanMode")) {
158 psb_xrandr_info->hdmi_extvideo_prop->OverscanMode = (int)((INT32*)prop)[0];
159 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: OverscanMode (%08x)\n", psb_xrandr_info->hdmi_extvideo_prop->OverscanMode);
160 } else if (!strcmp(prop_name, "PANELFITTING")) {
161 psb_xrandr_info->hdmi_extvideo_prop->PANELFITTING = (int)((INT32*)prop)[0];
162 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: PANELFITTING (%08x)\n", psb_xrandr_info->hdmi_extvideo_prop->PANELFITTING);
163 }
164 }
165 }
166
psb_xrandr_mipi_location_init(psb_output_device_mode output_device_mode)167 static void psb_xrandr_mipi_location_init(psb_output_device_mode output_device_mode)
168 {
169 psb_xrandr_crtc_p local_crtc = NULL, extend_crtc = NULL;
170
171 switch (output_device_mode) {
172 case SINGLE_MIPI0:
173 psb_xrandr_info->hdmi_extvideo_prop->ExtDesktopMode = SINGLE;
174 psb_xrandr_info->local_crtc[0]->location = NORMAL;
175 return;
176 case SINGLE_MIPI1:
177 psb_xrandr_info->hdmi_extvideo_prop->ExtDesktopMode = SINGLE;
178 psb_xrandr_info->local_crtc[1]->location = NORMAL;
179 return;
180 case MIPI0_MIPI1:
181 local_crtc = psb_xrandr_info->local_crtc[0];
182 extend_crtc = psb_xrandr_info->local_crtc[1];
183 break;
184 default:
185 break;
186 }
187
188 if (!local_crtc || !extend_crtc) {
189 drv_debug_msg(VIDEO_DEBUG_ERROR, "Failed to get crtc info\n");
190 return;
191 }
192
193 /* MIPI1 clone MIPI0 */
194 if (local_crtc->x == 0 && local_crtc->y == 0 &&
195 extend_crtc->x == 0 && extend_crtc->y == 0) {
196 psb_xrandr_info->hdmi_extvideo_prop->ExtDesktopMode = CLONE;
197 extend_crtc->location = NORMAL;
198 } else {
199 /* MIPI1 entend MIPI0 */
200 psb_xrandr_info->hdmi_extvideo_prop->ExtDesktopMode = EXTENDED;
201 if (local_crtc->y == extend_crtc->height)
202 extend_crtc->location = ABOVE;
203 else if (extend_crtc->y == local_crtc->height)
204 extend_crtc->location = BELOW;
205 else if (local_crtc->x == extend_crtc->width)
206 extend_crtc->location = LEFT_OF;
207 else if (extend_crtc->x == local_crtc->width)
208 extend_crtc->location = RIGHT_OF;
209 }
210 }
211
psb_xrandr_hdmi_location_init(psb_output_device_mode output_device_mode)212 static void psb_xrandr_hdmi_location_init(psb_output_device_mode output_device_mode)
213 {
214 psb_xrandr_crtc_p local_crtc = NULL, extend_crtc = NULL;
215
216 switch (output_device_mode) {
217 case SINGLE_HDMI:
218 psb_xrandr_info->hdmi_extvideo_prop->ExtDesktopMode = SINGLE;
219 psb_xrandr_info->extend_crtc->location = NORMAL;
220 return;
221 case MIPI0_HDMI:
222 case MIPI0_MIPI1_HDMI:
223 local_crtc = psb_xrandr_info->local_crtc[0];
224 extend_crtc = psb_xrandr_info->extend_crtc;
225 break;
226 case MIPI1_HDMI:
227 local_crtc = psb_xrandr_info->local_crtc[1];
228 extend_crtc = psb_xrandr_info->extend_crtc;
229 break;
230 default:
231 break;
232 }
233
234 if (!local_crtc || !extend_crtc) {
235 drv_debug_msg(VIDEO_DEBUG_ERROR, "Failed to get crtc info\n");
236 return;
237 }
238
239 if (psb_xrandr_info->hdmi_extvideo_prop->ExtDesktopMode == CLONE)
240 psb_xrandr_info->extend_crtc->location = NORMAL;
241
242 if (psb_xrandr_info->hdmi_extvideo_prop->ExtDesktopMode == EXTENDED
243 || psb_xrandr_info->hdmi_extvideo_prop->ExtDesktopMode == EXTENDEDVIDEO) {
244 if (local_crtc->y == extend_crtc->height)
245 psb_xrandr_info->extend_crtc->location = ABOVE;
246 else if (extend_crtc->y == local_crtc->height)
247 psb_xrandr_info->extend_crtc->location = BELOW;
248 else if (local_crtc->x == extend_crtc->width)
249 psb_xrandr_info->extend_crtc->location = LEFT_OF;
250 else if (extend_crtc->x == local_crtc->width)
251 psb_xrandr_info->extend_crtc->location = RIGHT_OF;
252 }
253 }
254
psb_xrandr_coordinate_init(VADriverContextP ctx)255 static void psb_xrandr_coordinate_init(VADriverContextP ctx)
256 {
257 INIT_DRIVER_DATA;
258 psb_xrandr_output_p p_output;
259
260 psb_xrandr_info->output_changed = 1;
261
262 for (p_output = psb_xrandr_info->output_head; p_output; p_output = p_output->next) {
263 if (p_output->connection == RR_Connected) {
264 if (!strcmp(p_output->name, "MIPI0")) {
265 if (p_output->crtc) {
266 psb_xrandr_info->mipi0_enabled = 1;
267 psb_xrandr_info->local_output[0] = p_output;
268 psb_xrandr_info->local_crtc[0] = p_output->crtc;
269 if (psb_xrandr_info->mipi0_rotation != p_output->crtc->rotation) {
270 psb_xrandr_info->mipi0_rotation = p_output->crtc->rotation;
271 driver_data->mipi0_rotation = RRrotation2VArotation(psb_xrandr_info->mipi0_rotation);
272 driver_data->xrandr_dirty |= PSB_NEW_ROTATION;
273 }
274 } else {
275 psb_xrandr_info->mipi0_enabled = 0;
276 psb_xrandr_info->local_output[0] = NULL;
277 psb_xrandr_info->local_crtc[0] = NULL;
278 }
279 } else if (!strcmp(p_output->name, "MIPI1")) {
280 if (p_output->crtc) {
281 psb_xrandr_info->mipi1_enabled = 1;
282 psb_xrandr_info->local_output[1] = p_output;
283 psb_xrandr_info->local_crtc[1] = p_output->crtc;
284 if (psb_xrandr_info->mipi1_rotation != p_output->crtc->rotation) {
285 psb_xrandr_info->mipi1_rotation = p_output->crtc->rotation;
286 driver_data->mipi1_rotation = RRrotation2VArotation(psb_xrandr_info->mipi1_rotation);
287 driver_data->xrandr_dirty |= PSB_NEW_ROTATION;
288 }
289 } else {
290 psb_xrandr_info->mipi1_enabled = 0;
291 psb_xrandr_info->local_output[1] = NULL;
292 psb_xrandr_info->local_crtc[1] = NULL;
293 }
294 } else if (!strcmp(p_output->name, "TMDS0-1")) {
295 if (p_output->crtc) {
296 psb_xrandr_info->hdmi_enabled = 1;
297 psb_xrandr_info->extend_output = p_output;
298 psb_xrandr_info->extend_crtc = p_output->crtc;
299 if (psb_xrandr_info->hdmi_rotation != p_output->crtc->rotation) {
300 psb_xrandr_info->hdmi_rotation = p_output->crtc->rotation;
301 driver_data->hdmi_rotation = RRrotation2VArotation(psb_xrandr_info->hdmi_rotation);
302 driver_data->xrandr_dirty |= PSB_NEW_ROTATION;
303 }
304 } else {
305 psb_xrandr_info->hdmi_enabled = 0;
306 psb_xrandr_info->extend_output = NULL;
307 psb_xrandr_info->extend_crtc = NULL;
308 }
309 } else if (!strcmp(p_output->name, "LVDS0") && IS_MRST(driver_data)) {
310 if (p_output->crtc) {
311 psb_xrandr_info->lvds0_enabled = 1;
312 psb_xrandr_info->local_output[0] = p_output;
313 psb_xrandr_info->local_crtc[0] = p_output->crtc;
314 } else {
315 psb_xrandr_info->lvds0_enabled = 0;
316 psb_xrandr_info->local_output[0] = NULL;
317 psb_xrandr_info->local_crtc[0] = NULL;
318 }
319 }
320 }
321 }
322
323 /* for MRST */
324 if (IS_MRST(driver_data) && psb_xrandr_info->lvds0_enabled) {
325 psb_xrandr_info->hdmi_extvideo_prop->ExtDesktopMode = SINGLE;
326 psb_xrandr_info->output_device_mode = SINGLE_LVDS0;
327 psb_xrandr_info->local_crtc[0]->location = NORMAL;
328 return;
329 }
330
331 /* HDMI + either MIPI0 or MIPI1 */
332 if (psb_xrandr_info->hdmi_enabled) {
333
334 /* Get HDMI properties if it is enabled*/
335 psb_xrandr_hdmi_property(ctx);
336
337 /* Only HDMI */
338 if (!psb_xrandr_info->mipi0_enabled && !psb_xrandr_info->mipi1_enabled)
339 psb_xrandr_info->output_device_mode = SINGLE_HDMI;
340
341 /* HDMI + MIPI0 */
342 if (psb_xrandr_info->mipi0_enabled && !psb_xrandr_info->mipi1_enabled)
343 psb_xrandr_info->output_device_mode = MIPI0_HDMI;
344
345 /* HDMI + MIPI1 */
346 if (!psb_xrandr_info->mipi0_enabled && psb_xrandr_info->mipi1_enabled)
347 psb_xrandr_info->output_device_mode = MIPI1_HDMI;
348
349 /* HDMI + MIPI0 + MIPI1 */
350 if (psb_xrandr_info->mipi0_enabled && psb_xrandr_info->mipi1_enabled)
351 psb_xrandr_info->output_device_mode = MIPI0_MIPI1_HDMI;
352
353 psb_xrandr_hdmi_location_init(psb_xrandr_info->output_device_mode);
354 } else {
355 /* MIPI0 + MIPI1 */
356 if (psb_xrandr_info->mipi0_enabled && psb_xrandr_info->mipi1_enabled) {
357 psb_xrandr_info->output_device_mode = MIPI0_MIPI1;
358 } else {
359 /* MIPI0/MIPI1 */
360 if (psb_xrandr_info->mipi0_enabled)
361 psb_xrandr_info->output_device_mode = SINGLE_MIPI0;
362 else if (psb_xrandr_info->mipi1_enabled)
363 psb_xrandr_info->output_device_mode = SINGLE_MIPI1;
364 }
365
366 psb_xrandr_mipi_location_init(psb_xrandr_info->output_device_mode);
367 }
368 }
369
psb_xrandr_refresh(VADriverContextP ctx)370 void psb_xrandr_refresh(VADriverContextP ctx)
371 {
372 int i;
373
374 XRROutputInfo *output_info;
375 XRRCrtcInfo *crtc_info;
376
377 psb_xrandr_crtc_p p_crtc;
378 psb_xrandr_output_p p_output;
379
380 pthread_mutex_lock(&psb_xrandr_info->psb_extvideo_mutex);
381
382 //deinit crtc
383 if (psb_xrandr_info->crtc_head) {
384 while (psb_xrandr_info->crtc_head) {
385 psb_xrandr_info->crtc_tail = psb_xrandr_info->crtc_head->next;
386
387 free(psb_xrandr_info->crtc_head);
388
389 psb_xrandr_info->crtc_head = psb_xrandr_info->crtc_tail;
390 }
391 psb_xrandr_info->crtc_head = psb_xrandr_info->crtc_tail = NULL;
392 }
393
394 for (i = 0; i < psb_xrandr_info->res->ncrtc; i++) {
395 crtc_info = XRRGetCrtcInfo(psb_xrandr_info->dpy, psb_xrandr_info->res, psb_xrandr_info->res->crtcs[i]);
396 if (crtc_info) {
397 p_crtc = (psb_xrandr_crtc_p)calloc(1, sizeof(psb_xrandr_crtc_s));
398 if (!p_crtc) {
399 drv_debug_msg(VIDEO_DEBUG_ERROR, "output of memory\n");
400 return;
401 }
402
403 if (i == 0)
404 psb_xrandr_info->crtc_head = psb_xrandr_info->crtc_tail = p_crtc;
405
406 p_crtc->crtc_id = psb_xrandr_info->res->crtcs[i];
407 p_crtc->x = crtc_info->x;
408 p_crtc->y = crtc_info->y;
409 p_crtc->width = crtc_info->width;
410 p_crtc->height = crtc_info->height;
411 p_crtc->crtc_mode = crtc_info->mode;
412 p_crtc->noutput = crtc_info->noutput;
413 p_crtc->rotation = crtc_info->rotation;
414
415 psb_xrandr_info->crtc_tail->next = p_crtc;
416 p_crtc->next = NULL;
417 psb_xrandr_info->crtc_tail = p_crtc;
418 } else {
419 drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to get crtc_info\n");
420 pthread_mutex_unlock(&psb_xrandr_info->psb_extvideo_mutex);
421 return;
422 }
423 }
424
425 //deinit output
426 if (psb_xrandr_info->output_head) {
427 while (psb_xrandr_info->output_head) {
428 psb_xrandr_info->output_tail = psb_xrandr_info->output_head->next;
429
430 free(psb_xrandr_info->output_head);
431
432 psb_xrandr_info->output_head = psb_xrandr_info->output_tail;
433 }
434 psb_xrandr_info->output_head = psb_xrandr_info->output_tail = NULL;
435 }
436 #if 0
437 //destroy the full-screen window
438 //FIXME: commited out for X Error message: BadDrawable, need more investigation
439 if (va_output) {
440 if (va_output->extend_drawable) {
441 XDestroyWindow(ctx->native_dpy, va_output->extend_drawable);
442 va_output->extend_drawable = 0;
443 texture_priv->extend_dri_init_flag = 0;
444 }
445 }
446 #endif
447 for (i = 0; i < psb_xrandr_info->res->noutput; i++) {
448 output_info = XRRGetOutputInfo(psb_xrandr_info->dpy, psb_xrandr_info->res, psb_xrandr_info->res->outputs[i]);
449 if (output_info) {
450 p_output = (psb_xrandr_output_p)calloc(1, sizeof(psb_xrandr_output_s));
451 if (!p_output) {
452 drv_debug_msg(VIDEO_DEBUG_ERROR, "output of memory\n");
453 return;
454 }
455
456 if (i == 0)
457 psb_xrandr_info->output_head = psb_xrandr_info->output_tail = p_output;
458
459 p_output->output_id = psb_xrandr_info->res->outputs[i];
460
461 p_output->connection = output_info->connection;
462 if (p_output->connection == RR_Connected)
463 psb_xrandr_info->nconnected_output++;
464
465 strcpy(p_output->name, output_info->name);
466
467 if (output_info->crtc)
468 p_output->crtc = get_crtc_by_id(output_info->crtc);
469 else
470 p_output->crtc = NULL;
471
472 psb_xrandr_info->output_tail->next = p_output;
473 p_output->next = NULL;
474 psb_xrandr_info->output_tail = p_output;
475 } else {
476 drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to get output_info\n");
477 pthread_mutex_unlock(&psb_xrandr_info->psb_extvideo_mutex);
478 return;
479 }
480 }
481
482 psb_xrandr_coordinate_init(ctx);
483
484 psb_RecalcRotate(ctx);
485 pthread_mutex_unlock(&psb_xrandr_info->psb_extvideo_mutex);
486 }
487
488 static Bool
outputChangePredicate(Display * display,XEvent * event,char * args)489 outputChangePredicate(Display *display, XEvent *event, char *args)
490 {
491 int event_base, error_base;
492
493 XRRQueryExtension(psb_xrandr_info->dpy, &event_base, &error_base);
494 return ((event->type == event_base + RRNotify_OutputChange) ||
495 ((event->type == ClientMessage) &&
496 (((XClientMessageEvent*)event)->message_type == psb_xrandr_info->psb_exit_atom)));
497 }
498
psb_xrandr_thread(void * arg)499 void psb_xrandr_thread(void* arg)
500 {
501 VADriverContextP ctx = (VADriverContextP)arg;
502 INIT_DRIVER_DATA;
503 int event_base, error_base;
504 XEvent event;
505 XRRQueryExtension(psb_xrandr_info->dpy, &event_base, &error_base);
506 XRRSelectInput(psb_xrandr_info->dpy, psb_xrandr_info->root, RRScreenChangeNotifyMask | RRCrtcChangeNotifyMask | RROutputChangeNotifyMask | RROutputPropertyNotifyMask);
507 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: psb xrandr thread start\n");
508
509 while (1) {
510 if (XCheckIfEvent(psb_xrandr_info->dpy, (XEvent *)&event, outputChangePredicate, NULL)) {
511 if (event.type == ClientMessage) {
512 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: receive ClientMessage event, thread should exit\n");
513 XClientMessageEvent *evt;
514 evt = (XClientMessageEvent*) & event;
515 if (evt->message_type == psb_xrandr_info->psb_exit_atom) {
516 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: xrandr thread exit safely\n");
517 pthread_exit(NULL);
518 }
519 }
520 switch (event.type - event_base) {
521 case RRNotify_OutputChange:
522 XRRUpdateConfiguration(&event);
523 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: receive RRNotify_OutputChange event, refresh output/crtc info\n");
524 driver_data->xrandr_update = 1;
525 psb_xrandr_refresh(ctx);
526 break;
527 default:
528 break;
529 }
530 }
531 usleep(200000);
532 }
533 }
534
psb_xrandr_create_full_screen_window(unsigned int destx,unsigned int desty,unsigned int destw,unsigned int desth)535 Window psb_xrandr_create_full_screen_window(unsigned int destx, unsigned int desty, unsigned int destw, unsigned int desth)
536 {
537 int x, y, width, height;
538 Window win;
539
540 x = psb_xrandr_info->extend_crtc->x;
541 y = psb_xrandr_info->extend_crtc->y;
542 width = psb_xrandr_info->extend_crtc->width;
543 height = psb_xrandr_info->extend_crtc->height;
544
545 if (destw == 0 || desth == 0) {
546 destw = width;
547 desth = height;
548 }
549 win = XCreateSimpleWindow(psb_xrandr_info->dpy, DefaultRootWindow(psb_xrandr_info->dpy), destx, desty, destw, desth, 0, 0, 0);
550
551 MWMHints mwmhints;
552 Atom MOTIF_WM_HINTS;
553
554 mwmhints.flags = MWM_HINTS_DECORATIONS;
555 mwmhints.decorations = 0; /* MWM_DECOR_BORDER */
556 MOTIF_WM_HINTS = XInternAtom(psb_xrandr_info->dpy, "_MOTIF_WM_HINTS", False);
557 XChangeProperty(psb_xrandr_info->dpy, win, MOTIF_WM_HINTS, MOTIF_WM_HINTS, sizeof(long) * 8,
558 PropModeReplace, (unsigned char*) &mwmhints, sizeof(mwmhints) / sizeof(long));
559
560 XSetWindowAttributes attributes;
561 attributes.override_redirect = 1;
562 unsigned long valuemask;
563 valuemask = CWOverrideRedirect ;
564 XChangeWindowAttributes(psb_xrandr_info->dpy, win, valuemask, &attributes);
565
566 XMapWindow(psb_xrandr_info->dpy, win);
567 XFlush(psb_xrandr_info->dpy);
568 return win;
569 }
570
psb_xrandr_hdmi_enabled()571 int psb_xrandr_hdmi_enabled()
572 {
573 int ret;
574 pthread_mutex_lock(&psb_xrandr_info->psb_extvideo_mutex);
575 ret = psb_xrandr_info->hdmi_enabled;
576 pthread_mutex_unlock(&psb_xrandr_info->psb_extvideo_mutex);
577 return ret;
578 }
579
psb_xrandr_mipi0_enabled()580 int psb_xrandr_mipi0_enabled()
581 {
582 int ret;
583 pthread_mutex_lock(&psb_xrandr_info->psb_extvideo_mutex);
584 ret = psb_xrandr_info->mipi0_enabled;
585 pthread_mutex_unlock(&psb_xrandr_info->psb_extvideo_mutex);
586 return ret;
587 }
588
psb_xrandr_mipi1_enabled()589 int psb_xrandr_mipi1_enabled()
590 {
591 int ret;
592 pthread_mutex_lock(&psb_xrandr_info->psb_extvideo_mutex);
593 ret = psb_xrandr_info->mipi1_enabled;
594 pthread_mutex_unlock(&psb_xrandr_info->psb_extvideo_mutex);
595 return ret;
596 }
597
psb_xrandr_single_mode()598 int psb_xrandr_single_mode()
599 {
600 int ret;
601 pthread_mutex_lock(&psb_xrandr_info->psb_extvideo_mutex);
602 ret = (psb_xrandr_info->hdmi_extvideo_prop->ExtDesktopMode == SINGLE) ? 1 : 0;
603 pthread_mutex_unlock(&psb_xrandr_info->psb_extvideo_mutex);
604 return ret;
605 }
606
psb_xrandr_clone_mode()607 int psb_xrandr_clone_mode()
608 {
609 int ret;
610 pthread_mutex_lock(&psb_xrandr_info->psb_extvideo_mutex);
611 ret = (psb_xrandr_info->hdmi_extvideo_prop->ExtDesktopMode == CLONE) ? 1 : 0;
612 pthread_mutex_unlock(&psb_xrandr_info->psb_extvideo_mutex);
613 return ret;
614 }
615
psb_xrandr_extend_mode()616 int psb_xrandr_extend_mode()
617 {
618 int ret;
619 pthread_mutex_lock(&psb_xrandr_info->psb_extvideo_mutex);
620 ret = (psb_xrandr_info->hdmi_extvideo_prop->ExtDesktopMode == EXTENDED) ? 1 : 0;
621 pthread_mutex_unlock(&psb_xrandr_info->psb_extvideo_mutex);
622 return ret;
623 }
624
psb_xrandr_extvideo_mode()625 int psb_xrandr_extvideo_mode()
626 {
627 int ret;
628 pthread_mutex_lock(&psb_xrandr_info->psb_extvideo_mutex);
629 ret = (psb_xrandr_info->hdmi_extvideo_prop->ExtDesktopMode == EXTENDEDVIDEO) ? 1 : 0;
630 pthread_mutex_unlock(&psb_xrandr_info->psb_extvideo_mutex);
631 return ret;
632 }
633
psb_xrandr_outputchanged()634 int psb_xrandr_outputchanged()
635 {
636 int ret;
637 pthread_mutex_lock(&psb_xrandr_info->psb_extvideo_mutex);
638 if (psb_xrandr_info->output_changed) {
639 psb_xrandr_info->output_changed = 0;
640 ret = 1;
641 } else
642 ret = 0;
643 pthread_mutex_unlock(&psb_xrandr_info->psb_extvideo_mutex);
644 return ret;
645 }
646
psb_xrandr_extvideo_prop(unsigned int * xres,unsigned int * yres,unsigned int * xoffset,unsigned int * yoffset,psb_extvideo_center * center,psb_extvideo_subtitle * subtitle,unsigned int * overscanmode,unsigned int * pannelfitting)647 VAStatus psb_xrandr_extvideo_prop(unsigned int *xres, unsigned int *yres, unsigned int *xoffset,
648 unsigned int *yoffset, psb_extvideo_center *center, psb_extvideo_subtitle *subtitle,
649 unsigned int *overscanmode, unsigned int *pannelfitting)
650 {
651 pthread_mutex_lock(&psb_xrandr_info->psb_extvideo_mutex);
652
653 if (psb_xrandr_info->hdmi_extvideo_prop->ExtDesktopMode != EXTENDEDVIDEO) {
654 pthread_mutex_unlock(&psb_xrandr_info->psb_extvideo_mutex);
655 return VA_STATUS_ERROR_UNKNOWN;
656 }
657
658 *xres = psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_XRes;
659 *yres = psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_YRes;
660 *xoffset = psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_X_Offset;
661 *yoffset = psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_Y_Offset;
662 *center = psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_Center;
663 *subtitle = psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_SubTitle;
664 *pannelfitting = psb_xrandr_info->hdmi_extvideo_prop->PANELFITTING;
665 *overscanmode = psb_xrandr_info->hdmi_extvideo_prop->OverscanMode;
666
667 pthread_mutex_unlock(&psb_xrandr_info->psb_extvideo_mutex);
668 return VA_STATUS_SUCCESS;
669 }
670
psb_xrandr_local_crtc_coordinate(psb_output_device * local_device_enabled,int * x,int * y,int * width,int * height,Rotation * rotation)671 VAStatus psb_xrandr_local_crtc_coordinate(psb_output_device *local_device_enabled, int *x, int *y, int *width, int *height, Rotation *rotation)
672 {
673 psb_xrandr_crtc_p p_crtc;
674 pthread_mutex_lock(&psb_xrandr_info->psb_extvideo_mutex);
675
676 switch (psb_xrandr_info->output_device_mode) {
677 case SINGLE_LVDS0:
678 *local_device_enabled = LVDS0;
679 p_crtc = psb_xrandr_info->local_crtc[0];
680 break;
681 case SINGLE_MIPI0:
682 case MIPI0_MIPI1:
683 case MIPI0_HDMI:
684 case MIPI0_MIPI1_HDMI:
685 *local_device_enabled = MIPI0;
686 p_crtc = psb_xrandr_info->local_crtc[0];
687 break;
688 case SINGLE_MIPI1:
689 case MIPI1_HDMI:
690 *local_device_enabled = MIPI1;
691 p_crtc = psb_xrandr_info->local_crtc[1];
692 break;
693 case SINGLE_HDMI:
694 *local_device_enabled = HDMI;
695 p_crtc = psb_xrandr_info->extend_crtc;
696 break;
697 default:
698 drv_debug_msg(VIDEO_DEBUG_ERROR, "Xrandr: Unknown statue\n");
699 pthread_mutex_unlock(&psb_xrandr_info->psb_extvideo_mutex);
700 return VA_STATUS_ERROR_UNKNOWN;
701 break;
702 }
703
704 if (p_crtc) {
705 *x = p_crtc->x;
706 *y = p_crtc->y;
707 *width = p_crtc->width;
708 *height = p_crtc->height;
709 *rotation = p_crtc->rotation;
710 pthread_mutex_unlock(&psb_xrandr_info->psb_extvideo_mutex);
711 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: device %08x enabled, crtc %08x coordinate: x = %d, y = %d, widht = %d, height = %d, rotate = %08x\n",
712 *local_device_enabled, p_crtc->crtc_id, *x, *y, *width + 1, *height + 1, *rotation);
713 return VA_STATUS_SUCCESS;
714 } else {
715 drv_debug_msg(VIDEO_DEBUG_ERROR, "Xrandr: local device is not available\n");
716 pthread_mutex_unlock(&psb_xrandr_info->psb_extvideo_mutex);
717 return VA_STATUS_ERROR_UNKNOWN;
718 }
719 }
720
psb_xrandr_extend_crtc_coordinate(psb_output_device * extend_device_enabled,int * x,int * y,int * width,int * height,psb_xrandr_location * location,Rotation * rotation)721 VAStatus psb_xrandr_extend_crtc_coordinate(psb_output_device *extend_device_enabled, int *x, int *y, int *width, int *height, psb_xrandr_location *location, Rotation *rotation)
722 {
723 psb_xrandr_crtc_p p_crtc;
724
725 pthread_mutex_lock(&psb_xrandr_info->psb_extvideo_mutex);
726
727 switch (psb_xrandr_info->output_device_mode) {
728 case MIPI0_MIPI1:
729 *extend_device_enabled = MIPI1;
730 p_crtc = psb_xrandr_info->local_crtc[1];
731 break;
732 case MIPI0_HDMI:
733 case MIPI0_MIPI1_HDMI:
734 case MIPI1_HDMI:
735 *extend_device_enabled = HDMI;
736 p_crtc = psb_xrandr_info->extend_crtc;
737 break;
738 default:
739 drv_debug_msg(VIDEO_DEBUG_ERROR, "Xrandr: Unknown status, may be extend device is not available\n");
740 pthread_mutex_unlock(&psb_xrandr_info->psb_extvideo_mutex);
741 return VA_STATUS_ERROR_UNKNOWN;
742 break;
743 }
744
745 if (p_crtc) {
746 *x = p_crtc->x;
747 *y = p_crtc->y;
748 *width = p_crtc->width;
749 *height = p_crtc->height;
750 *location = p_crtc->location;
751 *rotation = p_crtc->rotation;
752 pthread_mutex_unlock(&psb_xrandr_info->psb_extvideo_mutex);
753 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: extend device %08x enabled, crtc %08x coordinate: x = %d, y = %d, widht = %d, height = %d, location = %s, rotation = %08x\n",
754 *extend_device_enabled, p_crtc->crtc_id, *x, *y, *width + 1, *height + 1, location2string(p_crtc->location), *rotation);
755 } else {
756 drv_debug_msg(VIDEO_DEBUG_ERROR, "Xrandr: extend device is not available\n");
757 pthread_mutex_unlock(&psb_xrandr_info->psb_extvideo_mutex);
758 return VA_STATUS_ERROR_UNKNOWN;
759 }
760
761 return VA_STATUS_SUCCESS;
762 }
763
psb_xrandr_thread_exit()764 VAStatus psb_xrandr_thread_exit()
765 {
766 int ret;
767
768 XSelectInput(psb_xrandr_info->dpy, psb_xrandr_info->root, StructureNotifyMask);
769 XClientMessageEvent xevent;
770 xevent.type = ClientMessage;
771 xevent.message_type = psb_xrandr_info->psb_exit_atom;
772 xevent.window = psb_xrandr_info->root;
773 xevent.format = 32;
774 ret = XSendEvent(psb_xrandr_info->dpy, psb_xrandr_info->root, 0, StructureNotifyMask, (XEvent*) & xevent);
775 XFlush(psb_xrandr_info->dpy);
776 if (!ret) {
777 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: send thread exit event to drawable: failed\n");
778 return VA_STATUS_ERROR_UNKNOWN;
779 } else {
780 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: send thread exit event to drawable: success\n");
781 return VA_STATUS_SUCCESS;
782 }
783 }
784
psb_xrandr_thread_create(VADriverContextP ctx)785 VAStatus psb_xrandr_thread_create(VADriverContextP ctx)
786 {
787 pthread_t id;
788 INIT_DRIVER_DATA;
789
790 psb_xrandr_info->psb_exit_atom = XInternAtom(psb_xrandr_info->dpy, "psb_exit_atom", 0);
791 pthread_create(&id, NULL, (void*)psb_xrandr_thread, ctx);
792 driver_data->xrandr_thread_id = id;
793 return VA_STATUS_SUCCESS;
794 }
795
psb_xrandr_deinit()796 VAStatus psb_xrandr_deinit()
797 {
798 #ifdef _FOR_FPGA_
799 return VA_STATUS_SUCCESS;
800 #endif
801 pthread_mutex_lock(&psb_xrandr_info->psb_extvideo_mutex);
802 //free crtc
803 if (psb_xrandr_info->crtc_head) {
804 while (psb_xrandr_info->crtc_head) {
805 psb_xrandr_info->crtc_tail = psb_xrandr_info->crtc_head->next;
806
807 free(psb_xrandr_info->crtc_head);
808
809 psb_xrandr_info->crtc_head = psb_xrandr_info->crtc_tail;
810 }
811 psb_xrandr_info->crtc_head = psb_xrandr_info->crtc_tail = NULL;
812 }
813
814 //free output
815 if (psb_xrandr_info->output_head) {
816 while (psb_xrandr_info->output_head) {
817 psb_xrandr_info->output_tail = psb_xrandr_info->output_head->next;
818
819 free(psb_xrandr_info->output_head);
820
821 psb_xrandr_info->output_head = psb_xrandr_info->output_tail;
822 }
823 psb_xrandr_info->output_head = psb_xrandr_info->output_tail = NULL;
824 }
825
826 if (psb_xrandr_info->hdmi_extvideo_prop) {
827 free(psb_xrandr_info->hdmi_extvideo_prop);
828 }
829
830 pthread_mutex_unlock(&psb_xrandr_info->psb_extvideo_mutex);
831 pthread_mutex_destroy(&psb_xrandr_info->psb_extvideo_mutex);
832
833 free(psb_xrandr_info);
834 return VA_STATUS_SUCCESS;
835 }
836
psb_xrandr_init(VADriverContextP ctx)837 VAStatus psb_xrandr_init(VADriverContextP ctx)
838 {
839 int major, minor;
840 int screen;
841
842 psb_xrandr_info = (psb_xrandr_info_p)calloc(1, sizeof(psb_xrandr_info_s));
843
844 if (!psb_xrandr_info) {
845 drv_debug_msg(VIDEO_DEBUG_ERROR, "output of memory\n");
846 return VA_STATUS_ERROR_UNKNOWN;
847 }
848 memset(psb_xrandr_info, 0, sizeof(psb_xrandr_info_s));
849 psb_xrandr_info->mipi0_rotation = RR_Rotate_0;
850 psb_xrandr_info->mipi1_rotation = RR_Rotate_0;
851 psb_xrandr_info->hdmi_rotation = RR_Rotate_0;
852
853 psb_xrandr_info->hdmi_extvideo_prop = (psb_extvideo_prop_p)calloc(1, sizeof(psb_extvideo_prop_s));
854 if (!psb_xrandr_info->hdmi_extvideo_prop) {
855 drv_debug_msg(VIDEO_DEBUG_ERROR, "output of memory\n");
856 return VA_STATUS_ERROR_ALLOCATION_FAILED;
857 }
858 memset(psb_xrandr_info->hdmi_extvideo_prop, 0, sizeof(psb_extvideo_prop_s));
859
860 psb_xrandr_info->dpy = (Display *)ctx->native_dpy;
861 screen = DefaultScreen(psb_xrandr_info->dpy);
862
863 if (screen >= ScreenCount(psb_xrandr_info->dpy)) {
864 drv_debug_msg(VIDEO_DEBUG_ERROR, "Xrandr: Invalid screen number %d (display has %d)\n",
865 screen, ScreenCount(psb_xrandr_info->dpy));
866 return VA_STATUS_ERROR_UNKNOWN;
867 }
868
869 psb_xrandr_info->root = RootWindow(psb_xrandr_info->dpy, screen);
870
871 if (!XRRQueryVersion(psb_xrandr_info->dpy, &major, &minor)) {
872 drv_debug_msg(VIDEO_DEBUG_ERROR, "Xrandr: RandR extension missing\n");
873 return VA_STATUS_ERROR_UNKNOWN;
874 }
875
876 psb_xrandr_info->res = XRRGetScreenResources(psb_xrandr_info->dpy, psb_xrandr_info->root);
877 if (!psb_xrandr_info->res)
878 drv_debug_msg(VIDEO_DEBUG_ERROR, "Xrandr: failed to get screen resources\n");
879
880 pthread_mutex_init(&psb_xrandr_info->psb_extvideo_mutex, NULL);
881
882 psb_xrandr_refresh(ctx);
883
884 return VA_STATUS_SUCCESS;
885 }
886