~ubuntu-branches/ubuntu/raring/cairo/raring

« back to all changes in this revision

Viewing changes to src/cairo-xlib-surface-shm.c

  • Committer: Package Import Robot
  • Author(s): Chris Coulson
  • Date: 2013-01-23 21:19:34 UTC
  • mfrom: (1.3.11) (28.1.7 experimental)
  • Revision ID: package-import@ubuntu.com-20130123211934-q9qb538ujcmkliic
Tags: 1.12.10-1ubuntu1
* Merge from Debian, remaining changes:
* debian/patches/server_side_gradients.patch:
  - Don't use server side gradients, most drivers don't handle those and
    are really slow
* debian/control: Add missing libxext-dev dependency to libcairo2-dev.
  Spotted by autopkgtest.
* debian/patches/git_evince_rendering_fix.patch:
  Backport GIT commit to fix a rendering bug in evince
* debian/control, debian/libcairo2.symbols, debian/rules:
  - Disable GL backend due to LP: #725434

Show diffs side-by-side

added added

removed removed

Lines of Context:
206
206
    int event;
207
207
 
208
208
    Window window;
 
209
    unsigned long last_request;
 
210
    unsigned long last_event;
209
211
 
210
212
    cairo_list_t surfaces;
211
213
 
216
218
static inline cairo_bool_t
217
219
seqno_passed (unsigned long a, unsigned long b)
218
220
{
219
 
    return (long)(b - a) > 0;
 
221
    return (long)(b - a) >= 0;
220
222
}
221
223
 
222
224
static inline cairo_status_t
421
423
    free (pool);
422
424
}
423
425
 
 
426
static void send_event(cairo_xlib_display_t *display,
 
427
                       cairo_xlib_shm_info_t *info,
 
428
                       unsigned long seqno)
 
429
{
 
430
    XShmCompletionEvent ev;
 
431
 
 
432
    if (seqno_passed (seqno, display->shm->last_event))
 
433
        return;
 
434
 
 
435
    ev.type = display->shm->event;
 
436
    ev.send_event = 1; /* XXX or lie? */
 
437
    ev.serial = NextRequest (display->display);
 
438
    ev.drawable = display->shm->window;
 
439
    ev.major_code = display->shm->opcode;
 
440
    ev.minor_code = X_ShmPutImage;
 
441
    ev.shmseg = info->pool->shm.shmid;
 
442
    ev.offset = (char *)info->mem - (char *)info->pool->shm.shmaddr;
 
443
 
 
444
    XSendEvent (display->display, ev.drawable, False, 0, (XEvent *)&ev);
 
445
 
 
446
    display->shm->last_event = ev.serial;
 
447
}
 
448
 
 
449
static void sync (cairo_xlib_display_t *display)
 
450
{
 
451
    cairo_xlib_shm_info_t *info;
 
452
    struct pqueue *pq = &display->shm->info;
 
453
 
 
454
    XSync (display->display, False);
 
455
 
 
456
    while ((info = PQ_TOP(pq))) {
 
457
        _cairo_mempool_free (&info->pool->mem, info->mem);
 
458
        _pqueue_pop (&display->shm->info);
 
459
        free (info);
 
460
    }
 
461
}
 
462
 
424
463
static void
425
464
_cairo_xlib_shm_info_cleanup (cairo_xlib_display_t *display)
426
465
{
437
476
 
438
477
    info = PQ_TOP(pq);
439
478
    do {
440
 
        if (! seqno_passed (info->last_request, processed))
441
 
            break;
 
479
        if (! seqno_passed (info->last_request, processed)) {
 
480
            send_event (display, info, display->shm->last_request);
 
481
            return;
 
482
        }
442
483
 
443
484
        _cairo_mempool_free (&info->pool->mem, info->mem);
444
485
        _pqueue_pop (&display->shm->info);
446
487
    } while ((info = PQ_TOP(pq)));
447
488
}
448
489
 
449
 
static cairo_xlib_shm_info_t *
450
 
_cairo_xlib_shm_info_find (cairo_xlib_display_t *display,
451
 
                           size_t size, unsigned long *last_request)
 
490
static cairo_xlib_shm_t *
 
491
_cairo_xlib_shm_info_find (cairo_xlib_display_t *display, size_t size,
 
492
                           void **ptr, unsigned long *last_request)
452
493
{
453
494
    cairo_xlib_shm_info_t *info;
454
495
    struct pqueue *pq = &display->shm->info;
458
499
 
459
500
    info = PQ_TOP(pq);
460
501
    do {
461
 
        _pqueue_pop (&display->shm->info);
462
 
 
463
 
        if (info->size >= size && size <= 2*info->size)
464
 
            return info;
 
502
        cairo_xlib_shm_t *pool = info->pool;
465
503
 
466
504
        *last_request = info->last_request;
 
505
 
 
506
        _pqueue_pop (&display->shm->info);
467
507
        _cairo_mempool_free (&info->pool->mem, info->mem);
468
508
        free (info);
 
509
 
 
510
        if (pool->mem.free_bytes >= size) {
 
511
            void *mem = _cairo_mempool_alloc (&pool->mem, size);
 
512
            if (mem != NULL) {
 
513
                *ptr = mem;
 
514
                return pool;
 
515
            }
 
516
        }
469
517
    } while ((info = PQ_TOP(pq)));
470
518
 
471
519
    return NULL;
582
630
    unsigned long last_request = 0;
583
631
    void *mem = NULL;
584
632
 
585
 
    if (will_sync) {
586
 
        info = _cairo_xlib_shm_info_find (display, size, &last_request);
587
 
        if (info)
588
 
            return info;
589
 
    }
590
 
 
591
633
    _cairo_xlib_shm_info_cleanup (display);
592
634
    pool = _cairo_xlib_shm_pool_find (display, size, &mem);
593
635
    _cairo_xlib_shm_pool_cleanup (display);
 
636
 
 
637
    if (pool == NULL && will_sync)
 
638
        pool = _cairo_xlib_shm_info_find (display, size, &mem, &last_request);
594
639
    if (pool == NULL)
595
640
        pool = _cairo_xlib_shm_pool_create (display, size, &mem);
596
641
    if (pool == NULL)
617
662
{
618
663
    cairo_xlib_shm_surface_t *shm = abstract_surface;
619
664
    cairo_xlib_display_t *display;
 
665
    Display *dpy;
620
666
    cairo_status_t status;
621
667
 
622
668
    if (shm->active == 0)
634
680
    if (unlikely (status))
635
681
        return status;
636
682
 
637
 
    XEventsQueued (display->display, QueuedAfterReading);
638
 
    if (!seqno_passed (shm->active,
639
 
                       LastKnownRequestProcessed (display->display)))
640
 
        XSync (display->display, False);
 
683
    send_event (display, shm->info, shm->active);
 
684
 
 
685
    dpy = display->display;
 
686
    XEventsQueued (dpy, QueuedAfterReading);
 
687
    while (! seqno_passed (shm->active, LastKnownRequestProcessed (dpy))) {
 
688
        LockDisplay(dpy);
 
689
        _XReadEvents(dpy);
 
690
        UnlockDisplay(dpy);
 
691
    }
641
692
 
642
693
    cairo_device_release (&display->base);
643
694
    shm->active = 0;
649
700
active (cairo_xlib_shm_surface_t *shm, Display *dpy)
650
701
{
651
702
    return (shm->active &&
652
 
            !seqno_passed (shm->active, LastKnownRequestProcessed (dpy)));
 
703
            ! seqno_passed (shm->active, LastKnownRequestProcessed (dpy)));
653
704
}
654
705
 
655
706
static cairo_status_t
659
710
    cairo_xlib_display_t *display;
660
711
    cairo_status_t status;
661
712
 
 
713
    if (shm->image.base.damage) {
 
714
        _cairo_damage_destroy (shm->image.base.damage);
 
715
        shm->image.base.damage = _cairo_damage_create_in_error (CAIRO_STATUS_SURFACE_FINISHED);
 
716
    }
 
717
 
662
718
    status = _cairo_xlib_display_acquire (shm->image.base.device, &display);
663
719
    if (unlikely (status))
664
720
        return status;
669
725
    if (active (shm, display->display)) {
670
726
        shm->info->last_request = shm->active;
671
727
        _pqueue_push (&display->shm->info, shm->info);
 
728
        if (! seqno_passed (display->shm->last_request, shm->active))
 
729
            display->shm->last_request = shm->active;
672
730
    } else {
673
731
        _cairo_mempool_free (&shm->info->pool->mem, shm->info->mem);
674
732
        free (shm->info);
679
737
    cairo_list_del (&shm->link);
680
738
 
681
739
    cairo_device_release (&display->base);
682
 
    return CAIRO_STATUS_SUCCESS;
 
740
    return _cairo_image_surface_finish (abstract_surface);
683
741
}
684
742
 
685
743
static const cairo_surface_backend_t cairo_xlib_shm_surface_backend = {
884
942
        XChangeGC (display->display, gc, GCSubwindowMode, &gcv);
885
943
    }
886
944
 
887
 
    XSync (display->display, False);
 
945
    sync (display);
888
946
    shm->active = 0;
889
947
    shm->idle--;
890
948
 
1013
1071
        damage = _cairo_damage_reduce (shm->image.base.damage);
1014
1072
        shm->image.base.damage = _cairo_damage_create ();
1015
1073
 
1016
 
        status = _cairo_xlib_surface_get_gc (display, surface, &gc);
1017
 
        if (unlikely (status))
1018
 
            goto out;
1019
 
 
1020
1074
        TRACE ((stderr, "%s: flushing damage x %d\n", __FUNCTION__,
1021
1075
                damage->region ? cairo_region_num_rectangles (damage->region) : 0));
1022
1076
        if (damage->status == CAIRO_STATUS_SUCCESS && damage->region) {
1026
1080
            int n_rects, i;
1027
1081
 
1028
1082
            n_rects = cairo_region_num_rectangles (damage->region);
1029
 
            if (n_rects == 0) {
1030
 
            } else if (n_rects == 1) {
 
1083
            if (n_rects == 0)
 
1084
                goto out;
 
1085
 
 
1086
            status = _cairo_xlib_surface_get_gc (display, surface, &gc);
 
1087
            if (unlikely (status))
 
1088
                goto out;
 
1089
 
 
1090
            if (n_rects == 1) {
1031
1091
                cairo_region_get_rectangle (damage->region, 0, &r);
 
1092
                _cairo_xlib_shm_surface_mark_active (surface->shm);
1032
1093
                XCopyArea (display->display,
1033
1094
                           shm->pixmap, surface->drawable, gc,
1034
1095
                           r.x, r.y,
1039
1100
                    rects = _cairo_malloc_ab (n_rects, sizeof (XRectangle));
1040
1101
                    if (unlikely (rects == NULL)) {
1041
1102
                        status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
1103
                        _cairo_xlib_surface_put_gc (display, surface, gc);
1042
1104
                        goto out;
1043
1105
                    }
1044
1106
                }
1052
1114
                }
1053
1115
                XSetClipRectangles (display->display, gc, 0, 0, rects, i, YXBanded);
1054
1116
 
 
1117
                _cairo_xlib_shm_surface_mark_active (surface->shm);
1055
1118
                XCopyArea (display->display,
1056
1119
                           shm->pixmap, surface->drawable, gc,
1057
1120
                           0, 0,
1061
1124
                if (damage->status == CAIRO_STATUS_SUCCESS && damage->region)
1062
1125
                    XSetClipMask (display->display, gc, None);
1063
1126
            }
 
1127
 
 
1128
            _cairo_xlib_surface_put_gc (display, surface, gc);
1064
1129
        }
 
1130
 
 
1131
out:
1065
1132
        _cairo_damage_destroy (damage);
1066
 
 
1067
 
        _cairo_xlib_shm_surface_mark_active (surface->shm);
1068
 
        _cairo_xlib_surface_put_gc (display, surface, gc);
1069
 
out:
1070
1133
        cairo_device_release (&display->base);
1071
1134
    }
1072
1135
 
1082
1145
 
1083
1146
    surface = NULL;
1084
1147
    if (has_shm (other))
1085
 
        surface = &_cairo_xlib_shm_surface_create (other, format,
1086
 
                                                   width, height, FALSE,
1087
 
                                                   has_shm_pixmaps (other))->image.base;
 
1148
        surface = &_cairo_xlib_shm_surface_create (other, format, width, height,
 
1149
                                                   FALSE, has_shm_pixmaps (other))->image.base;
1088
1150
 
1089
1151
    return surface;
1090
1152
}
1097
1159
    if (! has_shm(surface))
1098
1160
        return NULL;
1099
1161
 
1100
 
    return &_cairo_xlib_shm_surface_create (surface, format,
1101
 
                                            surface->width, surface->height,
 
1162
    return &_cairo_xlib_shm_surface_create (surface, format, width, height,
1102
1163
                                            TRUE, 0)->image.base;
1103
1164
}
1104
1165
 
1130
1191
{
1131
1192
    cairo_xlib_shm_surface_t *shm = (cairo_xlib_shm_surface_t *) _shm;
1132
1193
    cairo_xlib_display_t *display = (cairo_xlib_display_t *) _shm->device;
1133
 
    XShmCompletionEvent ev;
1134
 
 
1135
 
    ev.type = display->shm->event;
1136
 
    ev.drawable = display->shm->window;
1137
 
    ev.major_code = display->shm->opcode;
1138
 
    ev.minor_code = X_ShmPutImage;
1139
 
    ev.shmseg = shm->info->pool->shm.shmid;
1140
 
    ev.offset = (char *)shm->info->mem - (char *)shm->info->pool->shm.shmaddr;
1141
1194
 
1142
1195
    shm->active = NextRequest (display->display);
1143
 
    XSendEvent (display->display, ev.drawable, False, 0, (XEvent *)&ev);
1144
1196
}
1145
1197
 
1146
1198
void
1259
1311
    }
1260
1312
 
1261
1313
    ev.type = shm->event;
 
1314
    ev.send_event = 1;
 
1315
    ev.serial = 1;
1262
1316
    ev.drawable = shm->window;
1263
1317
    ev.major_code = shm->opcode;
1264
1318
    ev.minor_code = X_ShmPutImage;
1352
1406
                                 InputOutput,
1353
1407
                                 DefaultVisual (display->display, scr),
1354
1408
                                 CWOverrideRedirect, &attr);
 
1409
    shm->last_event = 0;
 
1410
    shm->last_request = 0;
1355
1411
 
1356
1412
    if (xorg_has_buggy_send_shm_completion_event(display, shm))
1357
1413
        has_pixmap = 0;