~alan-griffiths/mir/fix-1654023

« back to all changes in this revision

Viewing changes to src/platforms/mesa/server/display_buffer.cpp

  • Committer: Daniel van Vugt
  • Date: 2015-04-28 07:54:10 UTC
  • mfrom: (2517 development-branch)
  • mto: This revision was merged to the branch mainline in revision 2673.
  • Revision ID: daniel.van.vugt@canonical.com-20150428075410-rwskshfuar7voesp
Merge latest trunk and fix conflicts.

Show diffs side-by-side

added added

removed removed

Lines of Context:
96
96
    MirOrientation rot,
97
97
    GLConfig const& gl_config,
98
98
    EGLContext shared_context)
99
 
    : last_flipped_bufobj{nullptr},
100
 
      scheduled_bufobj{nullptr},
 
99
    : visible_composite_frame{nullptr},
 
100
      scheduled_composite_frame{nullptr},
101
101
      platform(platform),
102
102
      listener(listener),
103
103
      drm(*platform->drm),
139
139
 
140
140
    listener->report_successful_egl_buffer_swap_on_construction();
141
141
 
142
 
    scheduled_bufobj = get_front_buffer_object();
143
 
    if (!scheduled_bufobj)
 
142
    scheduled_composite_frame = get_front_buffer_object();
 
143
    if (!scheduled_composite_frame)
144
144
        fatal_error("Failed to get frontbuffer");
145
145
 
146
146
    for (auto& output : outputs)
147
147
    {
148
 
        if (!output->set_crtc(scheduled_bufobj->get_drm_fb_id()))
 
148
        if (!output->set_crtc(scheduled_composite_frame->get_drm_fb_id()))
149
149
            fatal_error("Failed to set DRM crtc");
150
150
    }
151
151
 
163
163
mgm::DisplayBuffer::~DisplayBuffer()
164
164
{
165
165
    /*
166
 
     * There is no need to destroy last_flipped_bufobj manually.
 
166
     * There is no need to destroy visible_composite_frame manually.
167
167
     * It will be destroyed when its gbm_surface gets destroyed.
168
168
     */
169
 
    if (last_flipped_bufobj)
170
 
        last_flipped_bufobj->release();
 
169
    if (visible_composite_frame)
 
170
        visible_composite_frame->release();
171
171
 
172
 
    if (scheduled_bufobj)
173
 
        scheduled_bufobj->release();
 
172
    if (scheduled_composite_frame)
 
173
        scheduled_composite_frame->release();
174
174
}
175
175
 
176
176
geom::Rectangle mgm::DisplayBuffer::view_area() const
204
204
        auto bypass_it = std::find_if(renderable_list.rbegin(), renderable_list.rend(), bypass_match);
205
205
        if (bypass_it != renderable_list.rend())
206
206
        {
207
 
            auto bypass_buf = (*bypass_it)->buffer();
208
 
            if ((bypass_buf->native_buffer_handle()->flags & mir_buffer_flag_can_scanout) &&
209
 
                bypass_buf->size() == geom::Size{fb_width,fb_height})
210
 
            {
211
 
                return flip(bypass_buf);
 
207
            auto bypass_buffer = (*bypass_it)->buffer();
 
208
            auto native = bypass_buffer->native_buffer_handle();
 
209
            auto gbm_native = static_cast<mgm::GBMNativeBuffer*>(native.get());
 
210
            auto bufobj = get_buffer_object(gbm_native->bo);
 
211
            if (bufobj &&
 
212
                native->flags & mir_buffer_flag_can_scanout &&
 
213
                bypass_buffer->size() == geom::Size{fb_width,fb_height})
 
214
            {
 
215
                bypass_buf = bypass_buffer;
 
216
                bypass_bufobj = bufobj;
 
217
                return true;
 
218
            }
 
219
            else
 
220
            {
 
221
                bypass_buf = nullptr;
 
222
                bypass_bufobj = nullptr;
212
223
            }
213
224
        }
214
225
    }
216
227
    return false;
217
228
}
218
229
 
219
 
void mgm::DisplayBuffer::flip()
 
230
void mgm::DisplayBuffer::for_each_display_buffer(
 
231
    std::function<void(graphics::DisplayBuffer&)> const& f)
220
232
{
221
 
    flip(nullptr);
 
233
    f(*this);
222
234
}
223
235
 
224
236
void mgm::DisplayBuffer::gl_swap_buffers()
225
237
{
226
238
    if (!egl.swap_buffers())
227
239
        fatal_error("Failed to perform buffer swap");
 
240
    bypass_buf = nullptr;
 
241
    bypass_bufobj = nullptr;
228
242
}
229
243
 
230
 
bool mgm::DisplayBuffer::flip(
231
 
    std::shared_ptr<graphics::Buffer> bypass_buf)
 
244
void mgm::DisplayBuffer::post()
232
245
{
233
246
    /*
234
247
     * We might not have waited for the previous frame to page flip yet.
242
255
     * Switching from bypass to compositing? Now is the earliest safe time
243
256
     * we can unreference the bypass buffer...
244
257
     */
245
 
    if (scheduled_bufobj)
246
 
        last_flipped_bypass_buf = nullptr;
 
258
    if (scheduled_composite_frame)
 
259
        visible_bypass_frame = nullptr;
247
260
    /*
248
261
     * Release the last flipped buffer object (which is not displayed anymore)
249
262
     * to make it available for future rendering.
250
263
     */
251
 
    if (last_flipped_bufobj)
252
 
        last_flipped_bufobj->release();
 
264
    if (visible_composite_frame)
 
265
        visible_composite_frame->release();
253
266
 
254
 
    last_flipped_bufobj = scheduled_bufobj;
255
 
    scheduled_bufobj = nullptr;
 
267
    visible_composite_frame = scheduled_composite_frame;
 
268
    scheduled_composite_frame = nullptr;
256
269
 
257
270
    mgm::BufferObject *bufobj;
258
271
    if (bypass_buf)
259
272
    {
260
 
        auto native = bypass_buf->native_buffer_handle();
261
 
        auto gbm_native = static_cast<mgm::GBMNativeBuffer*>(native.get());
262
 
        bufobj = get_buffer_object(gbm_native->bo);
263
 
        // If bypass fails, just fall back to compositing.
264
 
        if (!bufobj)
265
 
            return false;
 
273
        bufobj = bypass_bufobj;
266
274
    }
267
275
    else
268
276
    {
300
308
         * For composited frames we defer wait_for_page_flip till just before
301
309
         * the next frame, but not for bypass frames. Deferring the flip of
302
310
         * bypass frames would increase the time we held
303
 
         * last_flipped_bypass_buf unacceptably, resulting in client stuttering
 
311
         * visible_bypass_frame unacceptably, resulting in client stuttering
304
312
         * unless we allocate more buffers (which I'm trying to avoid).
305
313
         * Also, bypass does not need the deferred page flip because it has
306
314
         * no compositing/rendering step for which to save time for.
307
315
         */
308
316
        wait_for_page_flip();
309
 
        scheduled_bufobj = nullptr;
 
317
        scheduled_composite_frame = nullptr;
310
318
 
311
319
        /*
312
320
         * Keep a reference to the buffer being bypassed for the entire
314
322
         * the client while its on-screen, which would be seen as tearing or
315
323
         * worse.
316
324
         */
317
 
        last_flipped_bypass_buf = bypass_buf;
 
325
        visible_bypass_frame = bypass_buf;
318
326
    }
319
327
    else
320
328
    {
330
338
            /*
331
339
             * bufobj is now physically on screen. Release the old frame...
332
340
             */
333
 
            if (last_flipped_bufobj)
 
341
            if (visible_composite_frame)
334
342
            {
335
 
                last_flipped_bufobj->release();
336
 
                last_flipped_bufobj = nullptr;
 
343
                visible_composite_frame->release();
 
344
                visible_composite_frame = nullptr;
337
345
            }
338
346
 
339
347
            /*
340
 
             * last_flipped_bufobj will be set correctly on the next iteration
 
348
             * visible_composite_frame will be set correctly on the next iteration
341
349
             * Don't do it here or else bufobj would be released while still
342
350
             * on screen (hence tearing and artefacts).
343
351
             */
344
352
        }
345
353
 
346
 
        scheduled_bufobj = bufobj;
 
354
        scheduled_composite_frame = bufobj;
347
355
    }
348
 
 
349
 
    return true;
350
356
}
351
357
 
352
358
mgm::BufferObject* mgm::DisplayBuffer::get_front_buffer_object()