110
111
surface_gbm{std::move(surface_gbm_param)},
113
needs_set_crtc{false}
114
needs_set_crtc{false},
115
page_flips_pending{false}
115
117
uint32_t area_width = area.size.width.as_uint32_t();
116
118
uint32_t area_height = area.size.height.as_uint32_t();
143
145
listener->report_successful_egl_buffer_swap_on_construction();
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"));
149
151
for (auto& output : outputs)
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"));
206
211
std::shared_ptr<graphics::Buffer> bypass_buf)
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.
220
wait_for_page_flip();
223
* Switching from bypass to compositing? Now is the earliest safe time
224
* we can unreference the bypass buffer...
226
if (scheduled_bufobj)
227
last_flipped_bypass_buf = nullptr;
229
* Release the last flipped buffer object (which is not displayed anymore)
230
* to make it available for future rendering.
232
if (last_flipped_bufobj)
233
last_flipped_bufobj->release();
235
last_flipped_bufobj = scheduled_bufobj;
236
scheduled_bufobj = nullptr;
209
239
* Bring the back buffer to the front and get the buffer object
210
240
* corresponding to the front buffer.
250
280
needs_set_crtc = false;
254
* Release the last flipped buffer object (which is not displayed anymore)
255
* to make it available for future rendering.
257
if (last_flipped_bufobj)
258
last_flipped_bufobj->release();
260
last_flipped_bufobj = bypass_buf ? nullptr : bufobj;
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.
268
last_flipped_bypass_buf = bypass_buf;
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.
294
wait_for_page_flip();
295
scheduled_bufobj = nullptr;
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
303
last_flipped_bypass_buf = bypass_buf;
307
scheduled_bufobj = bufobj;
271
311
mgm::BufferObject* mgm::DisplayBuffer::get_front_buffer_object()
314
bool mgm::DisplayBuffer::schedule_and_wait_for_page_flip(BufferObject* bufobj)
354
bool mgm::DisplayBuffer::schedule_page_flip(BufferObject* bufobj)
316
int page_flips_pending{0};
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)
324
362
if (output->schedule_page_flip(bufobj->get_drm_fb_id()))
325
++page_flips_pending;
363
page_flips_pending = true;
328
if (page_flips_pending == 0)
366
return page_flips_pending;
331
for (auto& output : outputs)
369
void mgm::DisplayBuffer::wait_for_page_flip()
371
if (page_flips_pending)
333
output->wait_for_page_flip();
373
for (auto& output : outputs)
374
output->wait_for_page_flip();
376
page_flips_pending = false;
339
380
void mgm::DisplayBuffer::make_current()