~noskcaj/ubuntu/trusty/cogl/1.16.2

« back to all changes in this revision

Viewing changes to cogl/cogl-xlib-renderer.c

  • Committer: Package Import Robot
  • Author(s): Jeremy Bicha, Jeremy Bicha, Rico Tzschichholz
  • Date: 2013-02-26 16:43:25 UTC
  • mfrom: (1.1.10)
  • Revision ID: package-import@ubuntu.com-20130226164325-t4z9rylpa20v0p6q
Tags: 1.13.4-0ubuntu1
[ Jeremy Bicha ]
* New upstream release
  - soname bump
* debian/control.in:
  - Bump minimum glib to 2.32
  - Drop obsolete breaks/replaces
  - Bump libclutter-1.0-dev breaks for soname transition
* debian/libcogl-dev.install:
  - Add some missing files

[ Rico Tzschichholz ]
* debian/control.in:
  - Build-depend on libxrandr-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
30
30
 
31
31
#include "cogl-xlib-renderer.h"
32
32
#include "cogl-util.h"
33
 
#include "cogl-internal.h"
34
33
#include "cogl-object.h"
35
34
 
 
35
#include "cogl-output-private.h"
36
36
#include "cogl-renderer-private.h"
37
37
#include "cogl-xlib-renderer-private.h"
38
38
#include "cogl-x11-renderer-private.h"
39
39
#include "cogl-winsys-private.h"
 
40
#include "cogl-error-private.h"
40
41
 
41
42
#include <X11/Xlib.h>
42
43
#include <X11/extensions/Xdamage.h>
 
44
#include <X11/extensions/Xrandr.h>
43
45
 
44
46
#include <stdlib.h>
 
47
#include <string.h>
45
48
 
46
49
static char *_cogl_x11_display_name = NULL;
47
50
static GList *_cogl_xlib_renderers = NULL;
164
167
}
165
168
 
166
169
static Display *
167
 
assert_xlib_display (CoglRenderer *renderer, GError **error)
 
170
assert_xlib_display (CoglRenderer *renderer, CoglError **error)
168
171
{
169
172
  Display *xdpy = cogl_xlib_renderer_get_foreign_display (renderer);
170
173
  CoglXlibRenderer *xlib_renderer = _cogl_xlib_renderer_get_data (renderer);
179
182
  xdpy = XOpenDisplay (_cogl_x11_display_name);
180
183
  if (xdpy == NULL)
181
184
    {
182
 
      g_set_error (error,
 
185
      _cogl_set_error (error,
183
186
                   COGL_RENDERER_ERROR,
184
187
                   COGL_RENDERER_ERROR_XLIB_DISPLAY_OPEN,
185
188
                   "Failed to open X Display %s", _cogl_x11_display_name);
190
193
  return xdpy;
191
194
}
192
195
 
 
196
static int
 
197
compare_outputs (CoglOutput *a,
 
198
                 CoglOutput *b)
 
199
{
 
200
  return strcmp (a->name, b->name);
 
201
}
 
202
 
 
203
#define CSO(X) COGL_SUBPIXEL_ORDER_ ## X
 
204
static CoglSubpixelOrder subpixel_map[6][6] = {
 
205
  { CSO(UNKNOWN), CSO(NONE), CSO(HORIZONTAL_RGB), CSO(HORIZONTAL_BGR),
 
206
    CSO(VERTICAL_RGB),   CSO(VERTICAL_BGR) },   /* 0 */
 
207
  { CSO(UNKNOWN), CSO(NONE), CSO(VERTICAL_RGB),   CSO(VERTICAL_BGR),
 
208
    CSO(HORIZONTAL_BGR), CSO(HORIZONTAL_RGB) }, /* 90 */
 
209
  { CSO(UNKNOWN), CSO(NONE), CSO(HORIZONTAL_BGR), CSO(HORIZONTAL_RGB),
 
210
    CSO(VERTICAL_BGR),   CSO(VERTICAL_RGB) },   /* 180 */
 
211
  { CSO(UNKNOWN), CSO(NONE), CSO(VERTICAL_BGR),   CSO(VERTICAL_RGB),
 
212
    CSO(HORIZONTAL_RGB), CSO(HORIZONTAL_BGR) }, /* 270 */
 
213
  { CSO(UNKNOWN), CSO(NONE), CSO(HORIZONTAL_BGR), CSO(HORIZONTAL_RGB),
 
214
    CSO(VERTICAL_RGB),   CSO(VERTICAL_BGR) },   /* Reflect_X */
 
215
  { CSO(UNKNOWN), CSO(NONE), CSO(HORIZONTAL_RGB), CSO(HORIZONTAL_BGR),
 
216
    CSO(VERTICAL_BGR),   CSO(VERTICAL_RGB) },   /* Reflect_Y */
 
217
};
 
218
#undef CSO
 
219
 
 
220
static void
 
221
update_outputs (CoglRenderer *renderer,
 
222
                CoglBool notify)
 
223
{
 
224
  CoglXlibRenderer *xlib_renderer =
 
225
    _cogl_xlib_renderer_get_data (renderer);
 
226
  XRRScreenResources *resources;
 
227
  CoglXlibTrapState state;
 
228
  CoglBool error = FALSE;
 
229
  GList *new_outputs = NULL;
 
230
  GList *l, *m;
 
231
  CoglBool changed = FALSE;
 
232
  int i;
 
233
 
 
234
  xlib_renderer->outputs_update_serial = XNextRequest (xlib_renderer->xdpy);
 
235
 
 
236
  resources = XRRGetScreenResources (xlib_renderer->xdpy,
 
237
                                     DefaultRootWindow (xlib_renderer->xdpy));
 
238
 
 
239
  _cogl_xlib_renderer_trap_errors (renderer, &state);
 
240
 
 
241
  for (i = 0; i < resources->ncrtc && !error; i++)
 
242
    {
 
243
      XRRCrtcInfo *crtc_info = NULL;
 
244
      XRROutputInfo *output_info = NULL;
 
245
      CoglOutput *output;
 
246
      float refresh_rate = 0;
 
247
      int j;
 
248
 
 
249
      crtc_info = XRRGetCrtcInfo (xlib_renderer->xdpy,
 
250
                                  resources, resources->crtcs[i]);
 
251
      if (crtc_info == NULL)
 
252
        {
 
253
          error = TRUE;
 
254
          goto next;
 
255
        }
 
256
 
 
257
      if (crtc_info->mode == None)
 
258
        goto next;
 
259
 
 
260
      for (j = 0; j < resources->nmode; j++)
 
261
        {
 
262
          if (resources->modes[j].id == crtc_info->mode)
 
263
            refresh_rate = (resources->modes[j].dotClock /
 
264
                            ((float)resources->modes[j].hTotal *
 
265
                             resources->modes[j].vTotal));
 
266
        }
 
267
 
 
268
      output_info = XRRGetOutputInfo (xlib_renderer->xdpy,
 
269
                                      resources,
 
270
                                      crtc_info->outputs[0]);
 
271
      if (output_info == NULL)
 
272
        {
 
273
          error = TRUE;
 
274
          goto next;
 
275
        }
 
276
 
 
277
      output = _cogl_output_new (output_info->name);
 
278
      output->x = crtc_info->x;
 
279
      output->y = crtc_info->y;
 
280
      output->width = crtc_info->width;
 
281
      output->height = crtc_info->height;
 
282
      if ((crtc_info->rotation & (RR_Rotate_90 | RR_Rotate_270)) != 0)
 
283
        {
 
284
          output->mm_width = output_info->mm_height;
 
285
          output->mm_height = output_info->mm_width;
 
286
        }
 
287
      else
 
288
        {
 
289
          output->mm_width = output_info->mm_width;
 
290
          output->mm_height = output_info->mm_height;
 
291
        }
 
292
 
 
293
      output->refresh_rate = refresh_rate;
 
294
 
 
295
      switch (output_info->subpixel_order)
 
296
        {
 
297
        case SubPixelUnknown:
 
298
        default:
 
299
          output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
 
300
          break;
 
301
        case SubPixelNone:
 
302
          output->subpixel_order = COGL_SUBPIXEL_ORDER_NONE;
 
303
          break;
 
304
        case SubPixelHorizontalRGB:
 
305
          output->subpixel_order = COGL_SUBPIXEL_ORDER_HORIZONTAL_RGB;
 
306
          break;
 
307
        case SubPixelHorizontalBGR:
 
308
          output->subpixel_order = COGL_SUBPIXEL_ORDER_HORIZONTAL_BGR;
 
309
          break;
 
310
        case SubPixelVerticalRGB:
 
311
          output->subpixel_order = COGL_SUBPIXEL_ORDER_VERTICAL_RGB;
 
312
          break;
 
313
        case SubPixelVerticalBGR:
 
314
          output->subpixel_order = COGL_SUBPIXEL_ORDER_VERTICAL_BGR;
 
315
          break;
 
316
        }
 
317
 
 
318
      output->subpixel_order = COGL_SUBPIXEL_ORDER_HORIZONTAL_RGB;
 
319
 
 
320
      /* Handle the effect of rotation and reflection on subpixel order (ugh) */
 
321
      for (j = 0; j < 6; j++)
 
322
        {
 
323
          if ((crtc_info->rotation & (1 << j)) != 0)
 
324
            output->subpixel_order = subpixel_map[j][output->subpixel_order];
 
325
        }
 
326
 
 
327
      new_outputs = g_list_prepend (new_outputs, output);
 
328
 
 
329
    next:
 
330
      if (crtc_info != NULL)
 
331
        XFree (crtc_info);
 
332
 
 
333
      if (output_info != NULL)
 
334
        XFree (output_info);
 
335
    }
 
336
 
 
337
  XFree (resources);
 
338
 
 
339
  if (!error)
 
340
    {
 
341
      new_outputs = g_list_sort (new_outputs, (GCompareFunc)compare_outputs);
 
342
 
 
343
      l = new_outputs;
 
344
      m = renderer->outputs;
 
345
 
 
346
      while (l || m)
 
347
        {
 
348
          int cmp;
 
349
          CoglOutput *output_l = l ? (CoglOutput *)l->data : NULL;
 
350
          CoglOutput *output_m = m ? (CoglOutput *)m->data : NULL;
 
351
 
 
352
          if (l && m)
 
353
            cmp = compare_outputs (output_l, output_m);
 
354
          else if (l)
 
355
            cmp = -1;
 
356
          else
 
357
            cmp = 1;
 
358
 
 
359
          if (cmp == 0)
 
360
            {
 
361
              GList *m_next = m->next;
 
362
 
 
363
              if (!_cogl_output_values_equal (output_l, output_m))
 
364
                {
 
365
                  renderer->outputs = g_list_remove_link (renderer->outputs, m);
 
366
                  renderer->outputs = g_list_insert_before (renderer->outputs,
 
367
                                                            m_next, output_l);
 
368
                  cogl_object_ref (output_l);
 
369
 
 
370
                  changed = TRUE;
 
371
                }
 
372
 
 
373
              l = l->next;
 
374
              m = m_next;
 
375
            }
 
376
          else if (cmp < 0)
 
377
            {
 
378
              renderer->outputs =
 
379
                g_list_insert_before (renderer->outputs, m, output_l);
 
380
              cogl_object_ref (output_l);
 
381
              changed = TRUE;
 
382
              l = l->next;
 
383
            }
 
384
          else
 
385
            {
 
386
              GList *m_next = m->next;
 
387
              renderer->outputs = g_list_remove_link (renderer->outputs, m);
 
388
              changed = TRUE;
 
389
              m = m_next;
 
390
            }
 
391
        }
 
392
    }
 
393
 
 
394
  g_list_free_full (new_outputs, (GDestroyNotify)cogl_object_unref);
 
395
  _cogl_xlib_renderer_untrap_errors (renderer, &state);
 
396
 
 
397
  if (changed)
 
398
    {
 
399
      const CoglWinsysVtable *winsys = renderer->winsys_vtable;
 
400
 
 
401
      if (notify)
 
402
        COGL_NOTE (WINSYS, "Outputs changed:");
 
403
      else
 
404
        COGL_NOTE (WINSYS, "Outputs:");
 
405
 
 
406
      for (l = renderer->outputs; l; l = l->next)
 
407
        {
 
408
          CoglOutput *output = l->data;
 
409
          const char *subpixel_string;
 
410
 
 
411
          switch (output->subpixel_order)
 
412
            {
 
413
            case COGL_SUBPIXEL_ORDER_UNKNOWN:
 
414
            default:
 
415
              subpixel_string = "unknown";
 
416
              break;
 
417
            case COGL_SUBPIXEL_ORDER_NONE:
 
418
              subpixel_string = "none";
 
419
              break;
 
420
            case COGL_SUBPIXEL_ORDER_HORIZONTAL_RGB:
 
421
              subpixel_string = "horizontal_rgb";
 
422
              break;
 
423
            case COGL_SUBPIXEL_ORDER_HORIZONTAL_BGR:
 
424
              subpixel_string = "horizontal_bgr";
 
425
              break;
 
426
            case COGL_SUBPIXEL_ORDER_VERTICAL_RGB:
 
427
              subpixel_string = "vertical_rgb";
 
428
              break;
 
429
            case COGL_SUBPIXEL_ORDER_VERTICAL_BGR:
 
430
              subpixel_string = "vertical_bgr";
 
431
              break;
 
432
            }
 
433
 
 
434
          COGL_NOTE (WINSYS,
 
435
                     " %10s: +%d+%dx%dx%d mm=%dx%d dpi=%.1fx%.1f "
 
436
                     "subpixel_order=%s refresh_rate=%.3f",
 
437
                     output->name,
 
438
                     output->x, output->y, output->width, output->height,
 
439
                     output->mm_width, output->mm_height,
 
440
                     output->width / (output->mm_width / 25.4),
 
441
                     output->height / (output->mm_height / 25.4),
 
442
                     subpixel_string,
 
443
                     output->refresh_rate);
 
444
        }
 
445
 
 
446
      if (notify && winsys->renderer_outputs_changed != NULL)
 
447
        winsys->renderer_outputs_changed (renderer);
 
448
    }
 
449
}
 
450
 
 
451
static CoglFilterReturn
 
452
randr_filter (XEvent *event,
 
453
              void   *data)
 
454
{
 
455
  CoglRenderer *renderer = data;
 
456
  CoglXlibRenderer *xlib_renderer =
 
457
    _cogl_xlib_renderer_get_data (renderer);
 
458
  CoglX11Renderer *x11_renderer =
 
459
    (CoglX11Renderer *) xlib_renderer;
 
460
 
 
461
  if (x11_renderer->randr_base != -1 &&
 
462
      (event->xany.type == x11_renderer->randr_base + RRScreenChangeNotify ||
 
463
       event->xany.type == x11_renderer->randr_base + RRNotify) &&
 
464
      event->xany.serial >= xlib_renderer->outputs_update_serial)
 
465
    update_outputs (renderer, TRUE);
 
466
 
 
467
  return COGL_FILTER_CONTINUE;
 
468
}
 
469
 
193
470
CoglBool
194
 
_cogl_xlib_renderer_connect (CoglRenderer *renderer, GError **error)
 
471
_cogl_xlib_renderer_connect (CoglRenderer *renderer, CoglError **error)
195
472
{
196
473
  CoglXlibRenderer *xlib_renderer =
197
474
    _cogl_xlib_renderer_get_data (renderer);
198
475
  CoglX11Renderer *x11_renderer =
199
476
    (CoglX11Renderer *) xlib_renderer;
200
477
  int damage_error;
 
478
  int randr_error;
201
479
 
202
480
  if (!assert_xlib_display (renderer, error))
203
481
    return FALSE;
211
489
                              &damage_error))
212
490
    x11_renderer->damage_base = -1;
213
491
 
 
492
  /* Check whether randr is supported on this display */
 
493
  if (!XRRQueryExtension (xlib_renderer->xdpy,
 
494
                          &x11_renderer->randr_base,
 
495
                          &randr_error))
 
496
    x11_renderer->randr_base = -1;
 
497
 
214
498
  xlib_renderer->trap_state = NULL;
215
499
 
216
500
  xlib_renderer->poll_fd.fd = ConnectionNumber (xlib_renderer->xdpy);
217
501
  xlib_renderer->poll_fd.events = COGL_POLL_FD_EVENT_IN;
218
502
 
 
503
  XRRSelectInput(xlib_renderer->xdpy,
 
504
                 DefaultRootWindow (xlib_renderer->xdpy),
 
505
                 RRScreenChangeNotifyMask
 
506
                 | RRCrtcChangeNotifyMask
 
507
                 | RROutputPropertyNotifyMask);
 
508
  update_outputs (renderer, FALSE);
 
509
 
219
510
  register_xlib_renderer (renderer);
220
511
 
 
512
  cogl_xlib_renderer_add_filter (renderer,
 
513
                                 randr_filter,
 
514
                                 renderer);
 
515
 
221
516
  return TRUE;
222
517
}
223
518
 
227
522
  CoglXlibRenderer *xlib_renderer =
228
523
    _cogl_xlib_renderer_get_data (renderer);
229
524
 
 
525
  g_list_free_full (renderer->outputs, (GDestroyNotify)cogl_object_unref);
 
526
  renderer->outputs = NULL;
 
527
 
230
528
  if (!renderer->foreign_xdpy && xlib_renderer->xdpy)
231
529
    XCloseDisplay (xlib_renderer->xdpy);
232
530
 
312
610
        cogl_xlib_renderer_handle_event (renderer, &xevent);
313
611
      }
314
612
}
 
613
 
 
614
CoglOutput *
 
615
_cogl_xlib_renderer_output_for_rectangle (CoglRenderer *renderer,
 
616
                                          int x,
 
617
                                          int y,
 
618
                                          int width,
 
619
                                          int height)
 
620
{
 
621
  int max_overlap = 0;
 
622
  CoglOutput *max_overlapped = NULL;
 
623
  GList *l;
 
624
  int xa1 = x, xa2 = x + width;
 
625
  int ya1 = y, ya2 = y + height;
 
626
 
 
627
  for (l = renderer->outputs; l; l = l->next)
 
628
    {
 
629
      CoglOutput *output = l->data;
 
630
      int xb1 = output->x, xb2 = output->x + output->width;
 
631
      int yb1 = output->y, yb2 = output->y + output->height;
 
632
 
 
633
      int overlap_x = MIN(xa2, xb2) - MAX(xa1, xb1);
 
634
      int overlap_y = MIN(ya2, yb2) - MAX(ya1, yb1);
 
635
 
 
636
      if (overlap_x > 0 && overlap_y > 0)
 
637
        {
 
638
          int overlap = overlap_x * overlap_y;
 
639
          if (overlap > max_overlap)
 
640
            {
 
641
              max_overlap = overlap;
 
642
              max_overlapped = output;
 
643
            }
 
644
        }
 
645
    }
 
646
 
 
647
  return max_overlapped;
 
648
}