~vanvugt/mir/frame-skip

« back to all changes in this revision

Viewing changes to src/platform/graphics/mesa/kms_page_flipper.cpp

  • Committer: Daniel van Vugt
  • Date: 2014-11-21 09:01:43 UTC
  • Revision ID: daniel.van.vugt@canonical.com-20141121090143-qf1k2us60vc9h0rh
Prototype frame skip detection

Show diffs side-by-side

added added

removed removed

Lines of Context:
32
32
namespace
33
33
{
34
34
 
35
 
void page_flip_handler(int /*fd*/, unsigned int /*frame*/,
 
35
void page_flip_handler(int /*fd*/, unsigned int seq,
36
36
                       unsigned int /*sec*/, unsigned int /*usec*/,
37
37
                       void* data)
38
38
{
39
39
    auto page_flip_data = static_cast<mgm::PageFlipEventData*>(data);
40
 
    page_flip_data->pending->erase(page_flip_data->crtc_id);
 
40
    page_flip_data->done = true;
 
41
    page_flip_data->seq = seq;
41
42
}
42
43
 
43
44
}
56
57
    if (pending_page_flips.find(crtc_id) != pending_page_flips.end())
57
58
        BOOST_THROW_EXCEPTION(std::logic_error("Page flip for crtc_id is already scheduled"));
58
59
 
59
 
    pending_page_flips[crtc_id] = PageFlipEventData{&pending_page_flips, crtc_id};
 
60
    pending_page_flips[crtc_id] = PageFlipEventData{false, 0};
60
61
 
61
62
    auto ret = drmModePageFlip(drm_fd, crtc_id, fb_id,
62
63
                               DRM_MODE_PAGE_FLIP_EVENT,
68
69
    return (ret == 0);
69
70
}
70
71
 
71
 
void mgm::KMSPageFlipper::wait_for_flip(uint32_t crtc_id)
 
72
unsigned int mgm::KMSPageFlipper::wait_for_flip(uint32_t crtc_id)
72
73
{
73
74
    static drmEventContext evctx =
74
75
    {
77
78
        page_flip_handler  /* .page_flip_handler */
78
79
    };
79
80
    static std::thread::id const invalid_tid;
 
81
    unsigned int seq = 0;
80
82
 
81
83
    {
82
84
        std::unique_lock<std::mutex> lock{pf_mutex};
85
87
         * While another thread is the worker (it is controlling the
86
88
         * page flip event loop) and our event has not arrived, wait.
87
89
         */
88
 
        while (worker_tid != invalid_tid && !page_flip_is_done(crtc_id))
 
90
        while (worker_tid != invalid_tid && !page_flip_is_done(crtc_id, seq))
89
91
            pf_cv.wait(lock);
90
92
 
91
93
        /* If the page flip we are waiting for has arrived we are done. */
92
 
        if (page_flip_is_done(crtc_id))
93
 
            return;
 
94
        bool done = page_flip_is_done(crtc_id, seq);
 
95
        if (done)
 
96
            return seq;
94
97
 
95
98
        /* ...otherwise we become the worker */
96
99
        worker_tid = std::this_thread::get_id();
97
100
    }
98
101
 
 
102
    bool done = false;
 
103
 
99
104
    /* Only the worker thread reaches this point */
100
 
    bool done{false};
101
 
 
102
105
    while (!done)
103
106
    {
104
107
        fd_set fds;
127
130
                        std::runtime_error(msg)) << boost::errinfo_errno(errno));
128
131
            }
129
132
 
130
 
            done = page_flip_is_done(crtc_id);
 
133
            done = page_flip_is_done(crtc_id, seq);
131
134
            /* Give up loop control if we are done */
132
135
            if (done)
133
136
                worker_tid = invalid_tid;
140
143
         */
141
144
        pf_cv.notify_all();
142
145
    }
 
146
    return seq;
143
147
}
144
148
 
145
149
std::thread::id mgm::KMSPageFlipper::debug_get_worker_tid()
150
154
}
151
155
 
152
156
/* This method should be called with the 'pf_mutex' locked */
153
 
bool mgm::KMSPageFlipper::page_flip_is_done(uint32_t crtc_id)
 
157
bool mgm::KMSPageFlipper::page_flip_is_done(uint32_t crtc_id, unsigned int& seq)
154
158
{
155
 
    return pending_page_flips.find(crtc_id) == pending_page_flips.end();
 
159
    auto i = pending_page_flips.find(crtc_id);
 
160
    if (i == pending_page_flips.end())
 
161
        return true;
 
162
 
 
163
    seq = i->second.seq;
 
164
    if (i->second.done)
 
165
        pending_page_flips.erase(i);
 
166
 
 
167
    return seq;
156
168
}