psb_xrandr.c revision 643778eb83b8dfe3bbf433855b311d4fefa95e21
1#include "psb_xrandr.h"
2#include "psb_x11.h"
3
4psb_xrandr_info_p psb_xrandr_info;
5static psb_xrandr_crtc_p crtc_head, crtc_tail;
6static psb_xrandr_output_p output_head, output_tail;
7static pthread_mutex_t psb_extvideo_mutex;
8static XRRScreenResources *res;
9Display *dpy;
10Window root;
11int screen;
12
13#define USE_XRANDR_THREAD
14//#undef USE_XRANDR_THREAD
15
16#define MWM_HINTS_DECORATIONS (1L << 1)
17typedef struct
18{
19        int flags;
20        int functions;
21        int decorations;
22        int input_mode;
23        int status;
24} MWMHints;
25
26static char* location2string(psb_xrandr_location location)
27{
28    switch (location)
29    {
30	case ABOVE:
31	    return "ABOVE";
32	    break;
33	case BELOW:
34	    return "BELOW";
35	    break;
36	case LEFT_OF:
37	    return "LEFT_OF";
38	    break;
39	case RIGHT_OF:
40	    return "RIGHT_OF";
41	    break;
42	default:
43	    return "NORMAL";
44	    break;
45    }
46}
47
48static psb_xrandr_output_p get_output_by_id(RROutput output_id)
49{
50    psb_xrandr_output_p p_output;
51    for (p_output = output_head; p_output; p_output = p_output->next) {
52	if (p_output->output_id == output_id)
53	    return p_output;
54    }
55    return NULL;
56}
57
58static psb_xrandr_crtc_p get_crtc_by_id(RRCrtc crtc_id)
59{
60    psb_xrandr_crtc_p p_crtc;
61    for (p_crtc = crtc_head; p_crtc; p_crtc = p_crtc->next)
62	if (p_crtc->crtc_id == crtc_id)
63	    return p_crtc;
64    return NULL;
65}
66
67static void psb_extvideo_prop()
68{
69    psb_xrandr_crtc_p p_crtc;
70    psb_xrandr_output_p p_output;
71#if 0
72    int i, j, nprop, actual_format;
73    unsigned long nitems, bytes_after;
74    Atom *props;
75    Atom actual_type;
76    unsigned char* prop;
77    unsigned char* prop_name;
78#endif
79    psb_xrandr_info->output_changed = 1;
80    if (psb_xrandr_info->nconnected_output == 1)
81    {
82	for (p_output = output_head; p_output; p_output = p_output->next)
83	    if (p_output->connection == RR_Connected)
84		psb_xrandr_info->primary_output = p_output;
85
86	for (p_crtc = crtc_head; p_crtc; p_crtc = p_crtc->next)
87	{
88	    if (p_crtc->noutput == 0)
89		continue;
90	    else
91		psb_xrandr_info->primary_crtc = p_crtc;
92	}
93
94	psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode = SINGLE;
95    }
96    else if (psb_xrandr_info->nconnected_output >= 2)
97    {
98	for (p_output = output_head; p_output; p_output = p_output->next)
99	{
100	    if (p_output->connection != RR_Connected)
101		continue;
102
103	    if (!strcmp(p_output->name, "MIPI0"))
104	    {
105		psb_xrandr_info->primary_output = p_output;
106		psb_xrandr_info->primary_crtc = p_output->crtc;
107	    }
108	    else if (!strcmp(p_output->name, "MIPI1"))
109	    {
110                psb_xrandr_info->mipi1_connected = 1;
111		psb_xrandr_info->extend_output = p_output;
112		psb_xrandr_info->extend_crtc = p_output->crtc;
113	    }
114	    else if (!strcmp(p_output->name, "TMDS0-1"))
115	    {
116	        psb_xrandr_info->hdmi_connected = 1;
117		psb_xrandr_info->extend_output = p_output;
118		psb_xrandr_info->extend_crtc = p_output->crtc;
119	    }
120	}
121
122	if (!psb_xrandr_info->primary_crtc || !psb_xrandr_info->extend_crtc || !psb_xrandr_info->primary_output || !psb_xrandr_info->extend_output)
123	{
124	    psb__error_message("failed to get primary/extend crtc/output\n");
125	    return;
126	}
127
128	if (psb_xrandr_info->primary_crtc->x == 0 && psb_xrandr_info->primary_crtc->y == 0 \
129	    && psb_xrandr_info->extend_crtc->x == 0 && psb_xrandr_info->extend_crtc->y == 0)
130	    psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode = CLONE;
131	else {
132	    psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode = EXTENDED;
133
134	    if (psb_xrandr_info->primary_crtc->y == psb_xrandr_info->extend_crtc->height)
135		psb_xrandr_info->extend_crtc->location = ABOVE;
136	    else if (psb_xrandr_info->extend_crtc->y == psb_xrandr_info->primary_crtc->height)
137		psb_xrandr_info->extend_crtc->location = BELOW;
138	    else if (psb_xrandr_info->primary_crtc->x == psb_xrandr_info->extend_crtc->width)
139		psb_xrandr_info->extend_crtc->location = LEFT_OF;
140	    else if (psb_xrandr_info->extend_crtc->x == psb_xrandr_info->primary_crtc->width)
141		psb_xrandr_info->extend_crtc->location = RIGHT_OF;
142	}
143#if 0
144	props = XRRListOutputProperties(dpy, psb_xrandr_info->extend_output->output_id, &nprop);
145	for (i = 0; i < nprop; i++) {
146	    XRRGetOutputProperty(dpy, psb_xrandr_info->extend_output->output_id, props[i],
147				 0, 100, False, False, AnyPropertyType, &actual_type, &actual_format,
148				 &nitems, &bytes_after, &prop);
149
150	    XRRQueryOutputProperty(dpy, psb_xrandr_info->extend_output->output_id, props[i]);
151	    prop_name = XGetAtomName(dpy, props[i]);
152
153	    if (!strcmp(prop_name, "ExtVideoMode"))
154		for (j = 0; j < nitems; j++)
155		    psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode = (int)((INT32*)prop)[j];
156	    else if (!strcmp(prop_name, "ExtVideoMode_XRes"))
157		for (j = 0; j < nitems; j++)
158		    psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_XRes = (int)((INT32*)prop)[j];
159	    else if (!strcmp(prop_name, "ExtVideoMode_YRes"))
160		for (j = 0; j < nitems; j++)
161		    psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_YRes = (int)((INT32*)prop)[j];
162	    else if (!strcmp(prop_name, "ExtVideoMode_X_Offset"))
163		for (j = 0; j < nitems; j++)
164		    psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_X_Offset = (int)((INT32*)prop)[j];
165	    else if (!strcmp(prop_name, "ExtVideoMode_Y_Offset"))
166		for (j = 0; j < nitems; j++)
167		    psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_Y_Offset = (int)((INT32*)prop)[j];
168	    else if (!strcmp(prop_name, "ExtVideoMode_Center"))
169		for (j = 0; j < nitems; j++)
170		    psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_Center = (int)((INT32*)prop)[j];
171	    else if (!strcmp(prop_name, "ExtVideoMode_SubTitle"))
172		for (j = 0; j < nitems; j++)
173		    psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_SubTitle = (int)((INT32*)prop)[j];
174	}
175
176	if (psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode == CLONE)
177	    psb_xrandr_info->extend_crtc->location = NORMAL;
178	else if (psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode == EXTENDED) {
179	    if (psb_xrandr_info->primary_crtc->y == psb_xrandr_info->extend_crtc->height)
180		psb_xrandr_info->extend_crtc->location = ABOVE;
181	    else if (psb_xrandr_info->extend_crtc->y == psb_xrandr_info->primary_crtc->height)
182		psb_xrandr_info->extend_crtc->location = BELOW;
183	    else if (psb_xrandr_info->primary_crtc->x == psb_xrandr_info->extend_crtc->width)
184		psb_xrandr_info->extend_crtc->location = LEFT_OF;
185	    else if (psb_xrandr_info->extend_crtc->x == psb_xrandr_info->primary_crtc->width)
186		psb_xrandr_info->extend_crtc->location = RIGHT_OF;
187	}
188#if 0
189	else if (psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode == EXTENDEDVIDEO) {
190	    if (psb_xrandr_info->primary_crtc->y == psb_xrandr_info->extend_crtc->height)
191		psb_xrandr_info->extend_crtc->location = ABOVE;
192	    else if (psb_xrandr_info->extend_crtc->y == psb_xrandr_info->primary_crtc->height)
193		psb_xrandr_info->extend_crtc->location = BELOW;
194	    else if (psb_xrandr_info->primary_crtc->x == psb_xrandr_info->extend_crtc->width)
195		psb_xrandr_info->extend_crtc->location = LEFT_OF;
196	    else if (psb_xrandr_info->extend_crtc->x == psb_xrandr_info->primary_crtc->width)
197		psb_xrandr_info->extend_crtc->location = RIGHT_OF;
198	}
199#endif
200#endif
201    }
202}
203
204void psb_xrandr_refresh()
205{
206    int i, j;
207
208    XRROutputInfo *output_info;
209    XRRCrtcInfo *crtc_info;
210
211    psb_xrandr_crtc_p p_crtc;
212    psb_xrandr_output_p p_output;
213
214    pthread_mutex_lock(&psb_extvideo_mutex);
215
216    if (psb_xrandr_info)
217    {
218	if (psb_xrandr_info->hdmi_extvideo_prop)
219	    free(psb_xrandr_info->hdmi_extvideo_prop);
220
221 	free(psb_xrandr_info);
222
223	psb_xrandr_info = NULL;
224    }
225
226    psb_xrandr_info = (psb_xrandr_info_p)calloc(1, sizeof(psb_xrandr_info_s));
227    memset(psb_xrandr_info, 0, sizeof(psb_xrandr_info_s));
228
229    psb_xrandr_info->hdmi_extvideo_prop = (psb_extvideo_prop_p)calloc(1, sizeof(psb_extvideo_prop_s));
230    memset(psb_xrandr_info->hdmi_extvideo_prop, 0, sizeof(psb_extvideo_prop_s));
231
232    //deinit crtc
233    if (crtc_head)
234    {
235	while (crtc_head)
236	{
237	    crtc_tail = crtc_head->next;
238
239	    free(crtc_head->output);
240	    free(crtc_head);
241
242	    crtc_head = crtc_tail;
243	}
244	crtc_head = crtc_tail = NULL;
245    }
246
247    for (i = 0; i < res->ncrtc; i++)
248    {
249	crtc_info = XRRGetCrtcInfo (dpy, res, res->crtcs[i]);
250	if (crtc_info)
251	{
252	    p_crtc = (psb_xrandr_crtc_p)calloc(1, sizeof(psb_xrandr_crtc_s));
253	    if (!p_crtc)
254		psb__error_message("output of memory\n");
255
256	    if (i == 0)
257		crtc_head = crtc_tail = p_crtc;
258
259	    p_crtc->crtc_id = res->crtcs[i];
260	    p_crtc->x = crtc_info->x;
261	    p_crtc->y = crtc_info->y;
262	    p_crtc->width = crtc_info->width;
263	    p_crtc->height = crtc_info->height;
264	    p_crtc->crtc_mode = crtc_info->mode;
265	    p_crtc->noutput = crtc_info->noutput;
266
267	    crtc_tail->next = p_crtc;
268	    p_crtc->next = NULL;
269	    crtc_tail = p_crtc;
270	}
271	else{
272	    psb__error_message("failed to get crtc_info\n");
273            pthread_mutex_unlock(&psb_extvideo_mutex);
274	    return;
275	}
276    }
277
278    //deinit output
279    if (output_head)
280    {
281	while (output_head)
282	{
283	    output_tail = output_head->next;
284
285	    free(output_head);
286
287	    output_head = output_tail;
288	}
289	output_head = output_tail = NULL;
290    }
291
292    for (i = 0; i < res->noutput; i++)
293    {
294	output_info = XRRGetOutputInfo(dpy, res, res->outputs[i]);
295	if (output_info)
296	{
297	    p_output = (psb_xrandr_output_p)calloc(1, sizeof(psb_xrandr_output_s));
298	    if (!output_info)
299		psb__error_message("output of memory\n");
300
301	    if (i == 0)
302		output_head = output_tail = p_output;
303
304	    p_output->output_id = res->outputs[i];
305
306	    p_output->connection = output_info->connection;
307	    if (p_output->connection == RR_Connected)
308		psb_xrandr_info->nconnected_output++;
309
310	    p_output->mm_width = output_info->mm_width;
311	    p_output->mm_height = output_info->mm_height;
312
313	    strcpy(p_output->name, output_info->name);
314
315	    if (output_info->crtc)
316		p_output->crtc = get_crtc_by_id(output_info->crtc);
317	    else
318		p_output->crtc = NULL;
319
320
321	    output_tail->next = p_output;
322	    p_output->next = NULL;
323	    output_tail = p_output;
324	}
325	else
326	{
327	    psb__error_message("failed to get output_info\n");
328	    pthread_mutex_unlock(&psb_extvideo_mutex);
329	    return;
330	}
331    }
332
333    for (p_crtc = crtc_head; p_crtc; p_crtc = p_crtc->next)
334    {
335	crtc_info = XRRGetCrtcInfo (dpy, res, p_crtc->crtc_id);
336
337	p_crtc->output = (psb_xrandr_output_p)calloc(p_crtc->noutput, sizeof(psb_xrandr_output_s));
338
339	for (j = 0; j < crtc_info->noutput; j++)
340	{
341	    p_output = get_output_by_id(crtc_info->outputs[j]);
342	    if (p_output)
343		p_crtc->output[j] = p_output;
344	    else
345		p_crtc->output[j] = NULL;
346	}
347    }
348
349    psb_extvideo_prop();
350    pthread_mutex_unlock(&psb_extvideo_mutex);
351}
352
353static void psb_xrandr_exit_thread()
354{
355    pthread_mutex_lock(&psb_extvideo_mutex);
356
357    //free crtc
358    if (crtc_head)
359    {
360	while (crtc_head)
361	{
362	    crtc_tail = crtc_head->next;
363
364	    free(crtc_head);
365
366	    crtc_head = crtc_tail;
367	}
368	crtc_head = crtc_tail = NULL;
369    }
370
371    //free output
372    if (output_head)
373    {
374	while (output_head)
375	{
376	    output_tail = output_head->next;
377
378	    free(output_head);
379
380	    output_head = output_tail;
381	}
382	output_head = output_tail = NULL;
383    }
384
385    if (psb_xrandr_info->hdmi_extvideo_prop)
386	free(psb_xrandr_info->hdmi_extvideo_prop);
387
388    if (psb_xrandr_info)
389	free(psb_xrandr_info);
390
391    pthread_mutex_unlock(&psb_extvideo_mutex);
392    pthread_mutex_destroy(&psb_extvideo_mutex);
393
394    psb__information_message("xrandr thread exit safely\n");
395    pthread_exit(NULL);
396}
397
398void psb_xrandr_thread()
399{
400    int event_base, error_base;
401    XEvent event;
402    XRRQueryExtension(dpy, &event_base, &error_base);
403    XRRSelectInput(dpy, root, RRScreenChangeNotifyMask | RRCrtcChangeNotifyMask | RROutputChangeNotifyMask | RROutputPropertyNotifyMask);
404
405    psb__information_message("psb xrandr thread start\n");
406
407    while (1)
408    {
409	XNextEvent(dpy, (XEvent *)&event);
410	if (event.type == ClientMessage) {
411	    psb__information_message("receive ClientMessage event, thread should exit\n");
412	    XClientMessageEvent *evt;
413	    evt = (XClientMessageEvent*)&event;
414	    if (evt->message_type == psb_exit_atom)
415		psb_xrandr_exit_thread();
416	}
417	switch (event.type - event_base) {
418	    case RRNotify_OutputChange:
419		XRRUpdateConfiguration (&event);
420		psb__information_message("receive RRNotify_OutputChange event, refresh output/crtc info\n");
421		psb_xrandr_refresh();
422		break;
423	    default:
424		break;
425        }
426    }
427}
428
429Window psb_xrandr_create_full_screen_window()
430{
431    int x, y, width, height;
432    Window win;
433
434    x = psb_xrandr_info->extend_crtc->x;
435    y = psb_xrandr_info->extend_crtc->y;
436    width = psb_xrandr_info->extend_crtc->width;
437    height = psb_xrandr_info->extend_crtc->height;
438
439    win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), x, y, width, height, 0, 0, 0);
440
441    MWMHints mwmhints;
442    Atom MOTIF_WM_HINTS;
443
444    mwmhints.flags = MWM_HINTS_DECORATIONS;
445    mwmhints.decorations = 0; /* MWM_DECOR_BORDER */
446    MOTIF_WM_HINTS = XInternAtom(dpy, "_MOTIF_WM_HINTS", False);
447    XChangeProperty(dpy, win, MOTIF_WM_HINTS, MOTIF_WM_HINTS, sizeof(long)*8,
448		    PropModeReplace, (unsigned char*) &mwmhints, sizeof(mwmhints)/sizeof(long));
449
450    XSetWindowAttributes attributes;
451    attributes.override_redirect = 1;
452    unsigned long valuemask;
453    valuemask = CWOverrideRedirect ;
454    XChangeWindowAttributes(dpy, win, valuemask, &attributes);
455
456    XMapWindow(dpy, win);
457    XFlush(dpy);
458    return win;
459}
460
461#if 0
462void show_current()
463{
464    int i, ret;
465    int x, y, widht, height;
466    psb_xrandr_location location;
467
468    ret = pthread_mutex_trylock(&psb_extvideo_mutex);
469    if (ret != 0)
470    {
471	printf("mutex busy, should not read\n");
472	return;
473    }
474
475    if (psb_xrandr_single_mode())
476    {
477	printf("single mode\n");
478	printf("primary crtc info:\n");
479
480	ret = psb_xrandr_primary_crtc_coordinate(&x, &y, &widht, &height);
481
482	if (!ret)
483	    printf("failed to get primary crtc info\n");
484	else
485	{
486	    printf("\tx = %d, y = %d, widht = %d, height = %d\n", x, y, widht, height);
487	    printf("\tcrtc id: %08x, crtc mode: %08x, ", psb_xrandr_info->primary_crtc->crtc_id, psb_xrandr_info->primary_crtc->crtc_mode);
488	    for (i = 0; i < psb_xrandr_info->primary_crtc->noutput; i++)
489	    printf("output: %08x\n", psb_xrandr_info->primary_crtc->output[i]->output_id);
490	}
491    }
492    else if (psb_xrandr_clone_mode())
493    {
494	printf("clone mode\n");
495
496	ret = psb_xrandr_primary_crtc_coordinate(&x, &y, &widht, &height);
497
498	if (!ret)
499	    printf("failed to get primary crtc info\n");
500	else
501	{
502	    printf("primary crtc info:\n");
503	    printf("\tx = %d, y = %d, widht = %d, height = %d\n", x, y, widht, height);
504	    printf("\tcrtc id: %08x, crtc mode: %08x, ", psb_xrandr_info->primary_crtc->crtc_id, psb_xrandr_info->primary_crtc->crtc_mode);
505	    for (i = 0; i < psb_xrandr_info->primary_crtc->noutput; i++)
506	    printf("output: %08x\n", psb_xrandr_info->primary_crtc->output[i]->output_id);
507	}
508
509	ret = psb_xrandr_extend_crtc_coordinate(&x, &y, &widht, &height, &location);
510
511	if (!ret)
512	    printf("failed to get clone crtc info\n");
513	else
514	{
515	    printf("clone crtc info:\n");
516	    printf("\tx = %d, y = %d, widht = %d, height = %d, location = %s\n", x, y, widht, height, location2string(location));
517	    printf("\tcrtc id: %08x, crtc mode: %08x, ", psb_xrandr_info->extend_crtc->crtc_id, psb_xrandr_info->extend_crtc->crtc_mode);
518	    for (i = 0; i < psb_xrandr_info->extend_crtc->noutput; i++)
519	    printf("output: %08x\n", psb_xrandr_info->extend_crtc->output[i]->output_id);
520	}
521    }
522    else if (psb_xrandr_extend_mode())
523    {
524	printf("extend mode\n");
525	ret = psb_xrandr_primary_crtc_coordinate(&x, &y, &widht, &height);
526
527	if (!ret)
528	    printf("failed to get primary crtc info\n");
529	else
530	{
531	    printf("primary crtc info:\n");
532	    printf("\tx = %d, y = %d, widht = %d, height = %d\n", x, y, widht, height);
533	    printf("\tcrtc id: %08x, crtc mode: %08x, ", psb_xrandr_info->primary_crtc->crtc_id, psb_xrandr_info->primary_crtc->crtc_mode);
534	    for (i = 0; i < psb_xrandr_info->primary_crtc->noutput; i++)
535	    printf("output: %08x\n", psb_xrandr_info->primary_crtc->output[i]->output_id);
536	}
537
538	ret = psb_xrandr_extend_crtc_coordinate(&x, &y, &widht, &height, &location);
539
540	if (!ret)
541	    printf("failed to get extend crtc info\n");
542	else
543	{
544	    printf("extend crtc info:\n");
545	    printf("\tx = %d, y = %d, widht = %d, height = %d, location = %s\n", x, y, widht, height, location2string(location));
546	    printf("\tcrtc id: %08x, crtc mode: %08x, ", psb_xrandr_info->extend_crtc->crtc_id, psb_xrandr_info->extend_crtc->crtc_mode);
547	    for (i = 0; i < psb_xrandr_info->extend_crtc->noutput; i++)
548	    printf("output: %08x\n", psb_xrandr_info->extend_crtc->output[i]->output_id);
549	}
550    }
551    else if (psb_xrandr_extvideo_mode())
552	printf("extvideo mode\n");
553
554    pthread_mutex_unlock(&psb_extvideo_mutex);
555}
556#endif
557int psb_xrandr_hdmi_connected()
558{
559    int ret;
560    pthread_mutex_lock(&psb_extvideo_mutex);
561    ret = psb_xrandr_info->hdmi_connected;
562    pthread_mutex_unlock(&psb_extvideo_mutex);
563    return ret;
564}
565
566int psb_xrandr_mipi1_connected()
567{
568    int ret;
569    pthread_mutex_lock(&psb_extvideo_mutex);
570    ret = psb_xrandr_info->mipi1_connected;
571    pthread_mutex_unlock(&psb_extvideo_mutex);
572    return ret;
573}
574
575int psb_xrandr_single_mode()
576{
577    int ret;
578    pthread_mutex_lock(&psb_extvideo_mutex);
579    ret = (psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode == SINGLE) ? 1 : 0;
580    pthread_mutex_unlock(&psb_extvideo_mutex);
581    return ret;
582}
583
584int psb_xrandr_clone_mode()
585{
586    int ret;
587    pthread_mutex_lock(&psb_extvideo_mutex);
588    ret = (psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode == CLONE) ? 1 : 0;
589    pthread_mutex_unlock(&psb_extvideo_mutex);
590    return ret;
591}
592
593int psb_xrandr_extend_mode()
594{
595    int ret;
596    pthread_mutex_lock(&psb_extvideo_mutex);
597    ret = (psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode == EXTENDED) ? 1 : 0;
598    pthread_mutex_unlock(&psb_extvideo_mutex);
599    return ret;
600}
601
602int psb_xrandr_extvideo_mode()
603{
604    int ret;
605    pthread_mutex_lock(&psb_extvideo_mutex);
606    ret = (psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode == EXTENDEDVIDEO) ? 1 : 0;
607    pthread_mutex_unlock(&psb_extvideo_mutex);
608    return ret;
609}
610
611int psb_xrandr_outputchanged()
612{
613    int ret;
614    pthread_mutex_lock(&psb_extvideo_mutex);
615    if (psb_xrandr_info->output_changed){
616        psb_xrandr_info->output_changed = 0;
617        ret = 1;
618    } else
619        ret = 0;
620    pthread_mutex_unlock(&psb_extvideo_mutex);
621    return ret;
622}
623
624VAStatus psb_xrandr_extvideo_mode_prop(unsigned int *xres, unsigned int *yres, unsigned int *xoffset,
625			      unsigned int *yoffset, psb_extvideo_center *center, psb_extvideo_subtitle *subtitle)
626{
627    pthread_mutex_lock(&psb_extvideo_mutex);
628
629    if (psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode != EXTENDEDVIDEO){
630        pthread_mutex_unlock(&psb_extvideo_mutex);
631	return VA_STATUS_ERROR_UNKNOWN;
632    }
633
634    *xres = psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_XRes;
635    *yres = psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_YRes;
636    *xoffset = psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_X_Offset;
637    *yoffset = psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_Y_Offset;
638    *center = psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_Center;
639    *subtitle = psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_SubTitle;
640
641    pthread_mutex_unlock(&psb_extvideo_mutex);
642    return VA_STATUS_SUCCESS;
643}
644
645VAStatus psb_xrandr_primary_crtc_coordinate(int *x, int *y, int *width, int *height)
646{
647    pthread_mutex_lock(&psb_extvideo_mutex);
648    psb_xrandr_crtc_p crtc = psb_xrandr_info->primary_crtc;;
649    if (crtc) {
650	*x = crtc->x;
651	*y = crtc->y;
652	*width = crtc->width - 1;
653	*height = crtc->height - 1;
654	pthread_mutex_unlock(&psb_extvideo_mutex);
655	psb__information_message("crtc %08x coordinate: x = %d, y = %d, widht = %d, height = %d\n",
656				  psb_xrandr_info->primary_crtc->crtc_id, x, y, width, height);
657	return VA_STATUS_SUCCESS;
658    }
659    pthread_mutex_unlock(&psb_extvideo_mutex);
660    return VA_STATUS_ERROR_UNKNOWN;
661}
662
663VAStatus psb_xrandr_extend_crtc_coordinate(int *x, int *y, int *width, int *height, psb_xrandr_location *location)
664{
665    pthread_mutex_lock(&psb_extvideo_mutex);
666
667    if (psb_xrandr_info->nconnected_output == 1 || !psb_xrandr_info->extend_crtc){
668	pthread_mutex_unlock(&psb_extvideo_mutex);
669	return VA_STATUS_ERROR_UNKNOWN;
670    }
671
672    *x = psb_xrandr_info->extend_crtc->x;
673    *y = psb_xrandr_info->extend_crtc->y;
674    *width = psb_xrandr_info->extend_crtc->width - 1;
675    *height = psb_xrandr_info->extend_crtc->height - 1;
676    *location = psb_xrandr_info->extend_crtc->location;
677
678    pthread_mutex_unlock(&psb_extvideo_mutex);
679    psb__information_message("crtc %08x coordinate: x = %d, y = %d, widht = %d, height = %d, location = %s\n",
680			     psb_xrandr_info->extend_crtc->crtc_id, x, y, width, height, location2string(psb_xrandr_info->extend_crtc->location));
681    return VA_STATUS_SUCCESS;
682}
683
684VAStatus psb_xrandr_deinit(Drawable draw)
685{
686#ifdef USE_XRANDR_THREAD
687    int ret;
688    XSelectInput(dpy, draw, StructureNotifyMask);
689    XClientMessageEvent xevent;
690    xevent.type = ClientMessage;
691    xevent.message_type = psb_exit_atom;
692    xevent.window = draw;
693    xevent.format = 32;
694    ret = XSendEvent(dpy, draw, 0, 0, (XEvent*)&xevent);
695    XFlush(dpy);
696    if (ret == 0) {
697	psb__information_message("send thread exit event to drawable: %08x\n success", draw);
698	return VA_STATUS_SUCCESS;
699    }
700    else {
701	psb__information_message("send thread exit event to drawable: %08x failed\n", draw);
702	return VA_STATUS_ERROR_UNKNOWN;
703    }
704#else
705    //free crtc
706    if (crtc_head)
707    {
708	while (crtc_head)
709	{
710	    crtc_tail = crtc_head->next;
711
712	    free(crtc_head);
713
714	    crtc_head = crtc_tail;
715	}
716	crtc_head = crtc_tail = NULL;
717    }
718
719    //free output
720    if (output_head)
721    {
722	while (output_head)
723	{
724	    output_tail = output_head->next;
725
726	    free(output_head);
727
728	    output_head = output_tail;
729	}
730	output_head = output_tail = NULL;
731    }
732
733    if (psb_xrandr_info->hdmi_extvideo_prop)
734	free(psb_xrandr_info->hdmi_extvideo_prop);
735
736    if (psb_xrandr_info)
737	free(psb_xrandr_info);
738
739    pthread_mutex_destroy(&psb_extvideo_mutex);
740#endif
741}
742
743VAStatus psb_xrandr_init (VADriverContextP ctx)
744{
745    int	major, minor;
746    pthread_t id;
747
748    dpy = (Display *)ctx->native_dpy;
749    screen = DefaultScreen (dpy);
750    psb_exit_atom = XInternAtom(dpy, "psb_exit_atom", 0);
751
752    if (screen >= ScreenCount (dpy)) {
753	psb__error_message("Invalid screen number %d (display has %d)\n",
754			    screen, ScreenCount (dpy));
755	return VA_STATUS_ERROR_UNKNOWN;
756    }
757
758    root = RootWindow (dpy, screen);
759
760    if (!XRRQueryVersion (dpy, &major, &minor))
761    {
762	psb__error_message("RandR extension missing\n");
763	return VA_STATUS_ERROR_UNKNOWN;
764    }
765
766    res = XRRGetScreenResources (dpy, root);
767    if (!res)
768	psb__error_message("failed to get screen resources\n");
769
770    pthread_mutex_init(&psb_extvideo_mutex, NULL);
771
772    psb_xrandr_refresh();
773#ifdef USE_XRANDR_THREAD
774    pthread_create(&id, NULL, (void*)psb_xrandr_thread, NULL);
775#endif
776    /*while(1) { sleep(1);
777	show_current();
778    }*/
779
780    return 0;
781}
782