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