~ubuntu-branches/ubuntu/utopic/mir/utopic-proposed

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): Ubuntu daily release
  • Date: 2014-03-10 19:28:46 UTC
  • mto: This revision was merged to the branch mainline in revision 63.
  • Revision ID: package-import@ubuntu.com-20140310192846-rq9qm3ec26yrelo2
Tags: upstream-0.1.6+14.04.20140310
ImportĀ upstreamĀ versionĀ 0.1.6+14.04.20140310

Show diffs side-by-side

added added

removed removed

Lines of Context:
103
103
    MirOrientation rot,
104
104
    EGLContext shared_context)
105
105
    : last_flipped_bufobj{nullptr},
 
106
      scheduled_bufobj{nullptr},
106
107
      platform(platform),
107
108
      listener(listener),
108
109
      drm(platform->drm),
110
111
      surface_gbm{std::move(surface_gbm_param)},
111
112
      area(area),
112
113
      rotation(rot),
113
 
      needs_set_crtc{false}
 
114
      needs_set_crtc{false},
 
115
      page_flips_pending{false}
114
116
{
115
117
    uint32_t area_width = area.size.width.as_uint32_t();
116
118
    uint32_t area_height = area.size.height.as_uint32_t();
142
144
 
143
145
    listener->report_successful_egl_buffer_swap_on_construction();
144
146
 
145
 
    last_flipped_bufobj = get_front_buffer_object();
146
 
    if (!last_flipped_bufobj)
 
147
    scheduled_bufobj = get_front_buffer_object();
 
148
    if (!scheduled_bufobj)
147
149
        BOOST_THROW_EXCEPTION(std::runtime_error("Failed to get frontbuffer"));
148
150
 
149
151
    for (auto& output : outputs)
150
152
    {
151
 
        if (!output->set_crtc(last_flipped_bufobj->get_drm_fb_id()))
 
153
        if (!output->set_crtc(scheduled_bufobj->get_drm_fb_id()))
152
154
            BOOST_THROW_EXCEPTION(std::runtime_error("Failed to set DRM crtc"));
153
155
    }
154
156
 
171
173
     */
172
174
    if (last_flipped_bufobj)
173
175
        last_flipped_bufobj->release();
 
176
 
 
177
    if (scheduled_bufobj)
 
178
        scheduled_bufobj->release();
174
179
}
175
180
 
176
181
geom::Rectangle mgm::DisplayBuffer::view_area() const
206
211
    std::shared_ptr<graphics::Buffer> bypass_buf)
207
212
{
208
213
    /*
 
214
     * If the last frame was composited then we haven't waited for the
 
215
     * page flips yet. This is good because it maximizes the time available
 
216
     * to spend rendering each frame. However we have to wait here, because
 
217
     * it will be unsafe to swap_buffers before guaranteeing the previous
 
218
     * page flip finished.
 
219
     */
 
220
    wait_for_page_flip();
 
221
 
 
222
    /*
 
223
     * Switching from bypass to compositing? Now is the earliest safe time
 
224
     * we can unreference the bypass buffer...
 
225
     */
 
226
    if (scheduled_bufobj)
 
227
        last_flipped_bypass_buf = nullptr;
 
228
    /*
 
229
     * Release the last flipped buffer object (which is not displayed anymore)
 
230
     * to make it available for future rendering.
 
231
     */
 
232
    if (last_flipped_bufobj)
 
233
        last_flipped_bufobj->release();
 
234
 
 
235
    last_flipped_bufobj = scheduled_bufobj;
 
236
    scheduled_bufobj = nullptr;
 
237
 
 
238
    /*
209
239
     * Bring the back buffer to the front and get the buffer object
210
240
     * corresponding to the front buffer.
211
241
     */
234
264
     * If the flip fails, release the buffer object to make it available
235
265
     * for future rendering.
236
266
     */
237
 
    if (!needs_set_crtc && !schedule_and_wait_for_page_flip(bufobj))
 
267
    if (!needs_set_crtc && !schedule_page_flip(bufobj))
238
268
    {
239
269
        if (!bypass_buf)
240
270
            bufobj->release();
250
280
        needs_set_crtc = false;
251
281
    }
252
282
 
253
 
    /*
254
 
     * Release the last flipped buffer object (which is not displayed anymore)
255
 
     * to make it available for future rendering.
256
 
     */
257
 
    if (last_flipped_bufobj)
258
 
        last_flipped_bufobj->release();
259
 
 
260
 
    last_flipped_bufobj = bypass_buf ? nullptr : bufobj;
261
 
 
262
 
    /*
263
 
     * Keep a reference to the buffer being bypassed for the entire duration
264
 
     * of the frame. This ensures the buffer doesn't get reused by the client
265
 
     * prematurely, which would be seen as tearing.
266
 
     * If not bypassing, then bypass_buf will be nullptr.
267
 
     */
268
 
    last_flipped_bypass_buf = bypass_buf;
 
283
    if (bypass_buf)
 
284
    {
 
285
        /*
 
286
         * For composited frames we defer wait_for_page_flip till just before
 
287
         * the next frame, but not for bypass frames. Deferring the flip of
 
288
         * bypass frames would increase the time we held
 
289
         * last_flipped_bypass_buf unacceptably, resulting in client stuttering
 
290
         * unless we allocate quad-buffers (which I'm trying to avoid).
 
291
         * Also, bypass does not need the deferred page flip because it has
 
292
         * no compositing/rendering step for which to save time for.
 
293
         */
 
294
        wait_for_page_flip();
 
295
        scheduled_bufobj = nullptr;
 
296
 
 
297
        /*
 
298
         * Keep a reference to the buffer being bypassed for the entire
 
299
         * duration of the frame. This ensures the buffer doesn't get reused by
 
300
         * the client while its on-screen, which would be seen as tearing or
 
301
         * worse.
 
302
         */
 
303
        last_flipped_bypass_buf = bypass_buf;
 
304
    }
 
305
    else
 
306
    {
 
307
        scheduled_bufobj = bufobj;
 
308
    }
269
309
}
270
310
 
271
311
mgm::BufferObject* mgm::DisplayBuffer::get_front_buffer_object()
311
351
}
312
352
 
313
353
 
314
 
bool mgm::DisplayBuffer::schedule_and_wait_for_page_flip(BufferObject* bufobj)
 
354
bool mgm::DisplayBuffer::schedule_page_flip(BufferObject* bufobj)
315
355
{
316
 
    int page_flips_pending{0};
317
 
 
318
356
    /*
319
357
     * Schedule the current front buffer object for display. Note that
320
358
     * the page flip is asynchronous and synchronized with vertical refresh.
322
360
    for (auto& output : outputs)
323
361
    {
324
362
        if (output->schedule_page_flip(bufobj->get_drm_fb_id()))
325
 
            ++page_flips_pending;
 
363
            page_flips_pending = true;
326
364
    }
327
365
 
328
 
    if (page_flips_pending == 0)
329
 
        return false;
 
366
    return page_flips_pending;
 
367
}
330
368
 
331
 
    for (auto& output : outputs)
 
369
void mgm::DisplayBuffer::wait_for_page_flip()
 
370
{
 
371
    if (page_flips_pending)
332
372
    {
333
 
        output->wait_for_page_flip();
 
373
        for (auto& output : outputs)
 
374
            output->wait_for_page_flip();
 
375
 
 
376
        page_flips_pending = false;
334
377
    }
335
 
 
336
 
    return true;
337
378
}
338
379
 
339
380
void mgm::DisplayBuffer::make_current()