~vanvugt/compiz/fix-1028809

« back to all changes in this revision

Viewing changes to plugins/opengl/src/doublebuffer/tests/test-opengl-double-buffer.cpp

  • Committer: Tarmac
  • Author(s): Sam Spilsbury
  • Date: 2012-11-09 10:59:19 UTC
  • mfrom: (3378.2.27 compiz.fix_1051286)
  • Revision ID: tarmac-20121109105919-65qpmaoc0rhs8fd7
Refactored the vsync code to get it under test. DoubleBuffer now dispatches to two separate VSync strategies depending on what type of swap we are doing. It also makes the unthrottledFrames code a lot clearer by specifying that this is for detecting broken hardware framelimiting.. Approved by PS Jenkins bot, Daniel van Vugt, Sam Spilsbury.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#include <gtest/gtest.h>
2
2
#include <gmock/gmock.h>
3
3
 
 
4
#include <boost/function.hpp>
 
5
#include <boost/bind.hpp>
 
6
 
4
7
#include <opengl/doublebuffer.h>
5
8
 
6
9
using namespace compiz::opengl;
7
10
using testing::_;
8
11
using testing::StrictMock;
9
12
using testing::Return;
 
13
using testing::DoAll;
 
14
using testing::SetArgReferee;
 
15
using testing::SetArgPointee;
 
16
using testing::InSequence;
 
17
 
 
18
char programName[] = "compiz_test_opengl_double_buffer";
 
19
bool debugOutput = false;
10
20
 
11
21
class MockDoubleBuffer :
12
22
    public DoubleBuffer
13
23
{
14
24
    public:
15
25
 
 
26
        MockDoubleBuffer (const impl::GLXSwapIntervalEXTFunc  &swapIntervalFunc,
 
27
                          const impl::GLXWaitVideoSyncSGIFunc &waitVideoSyncFunc) :
 
28
            DoubleBuffer (swapIntervalFunc, waitVideoSyncFunc)
 
29
        {
 
30
        }
 
31
 
16
32
        MOCK_CONST_METHOD0 (swap, void ());
17
33
        MOCK_CONST_METHOD0 (blitAvailable, bool ());
18
34
        MOCK_CONST_METHOD1 (blit, void (const CompRegion &));
21
37
        MOCK_CONST_METHOD0 (copyFrontToBack, void ());
22
38
};
23
39
 
 
40
class MockVSyncDoubleBuffer :
 
41
    public MockDoubleBuffer
 
42
{
 
43
    public:
 
44
 
 
45
        static void stubSwapInterval (int) {}
 
46
        static int  stubWaitVideoSync (int, int, unsigned int *) { return 1; }
 
47
 
 
48
        MockVSyncDoubleBuffer () :
 
49
            MockDoubleBuffer (boost::bind (stubSwapInterval, _1),
 
50
                              boost::bind (stubWaitVideoSync, _1, _2, _3))
 
51
        {
 
52
        }
 
53
 
 
54
        MOCK_METHOD2 (enableAsyncVideoSync, bool (FrontbufferRedrawType, FrameThrottleState &));
 
55
        MOCK_METHOD2 (enableBlockingVideoSync, bool (FrontbufferRedrawType, FrameThrottleState &));
 
56
        MOCK_METHOD0 (disableAsyncVideoSync, void ());
 
57
        MOCK_METHOD0 (disableBlockingVideoSync, void ());
 
58
};
 
59
 
24
60
class DoubleBufferTest :
25
61
    public ::testing::Test
26
62
{
27
63
    public:
28
64
 
29
 
        MockDoubleBuffer db;
30
 
        CompRegion       blitRegion;
 
65
        MockVSyncDoubleBuffer        db;
 
66
        CompRegion                   blitRegion;
31
67
 
32
68
};
33
69
 
39
75
TEST_F(DoubleBufferTest, TestPaintedFullAlwaysSwaps)
40
76
{
41
77
    EXPECT_CALL (db, swap ());
 
78
    EXPECT_CALL (db, enableAsyncVideoSync (DoubleBuffer::Swap, _))
 
79
            .WillOnce (Return (true));
42
80
    EXPECT_CALL (db, copyFrontToBack ()).Times (0);
43
81
 
44
82
    db.render (blitRegion, true);
48
86
{
49
87
    EXPECT_CALL (db, blitAvailable ()).WillOnce (Return (true));
50
88
    EXPECT_CALL (db, blit (_));
 
89
    EXPECT_CALL (db, enableAsyncVideoSync (DoubleBuffer::Blit, _))
 
90
            .WillOnce (Return (false));
 
91
    EXPECT_CALL (db, enableBlockingVideoSync (DoubleBuffer::Blit, _))
 
92
            .WillOnce (Return (true));
51
93
    EXPECT_CALL (db, copyFrontToBack ()).Times (0);
52
94
 
53
95
    db.render (blitRegion, false);
59
101
    db.set (DoubleBuffer::NEED_PERSISTENT_BACK_BUFFER, true);
60
102
 
61
103
    EXPECT_CALL (db, swap ());
 
104
    EXPECT_CALL (db, enableAsyncVideoSync (DoubleBuffer::Swap, _))
 
105
            .WillOnce (Return (true));
62
106
    EXPECT_CALL (db, copyFrontToBack ()).Times (1);
63
107
 
64
108
    db.render (blitRegion, true);
72
116
    EXPECT_CALL (db, blitAvailable ()).WillRepeatedly (Return (true));
73
117
    EXPECT_CALL (db, blit (_));
74
118
    EXPECT_CALL (db, swap ()).Times (0);
 
119
    EXPECT_CALL (db, enableAsyncVideoSync (DoubleBuffer::Blit, _))
 
120
            .WillOnce (Return (false));
 
121
    EXPECT_CALL (db, enableBlockingVideoSync (DoubleBuffer::Blit, _))
 
122
            .WillOnce (Return (true));
75
123
    EXPECT_CALL (db, copyFrontToBack ()).Times (0);
76
124
 
77
125
    db.render (blitRegion, false);
89
137
    CompRegion r3 (200, 200, 100, 100);
90
138
 
91
139
    EXPECT_CALL (db, blitAvailable ()).WillRepeatedly (Return (true));
 
140
    EXPECT_CALL (db, enableAsyncVideoSync (DoubleBuffer::Blit, _))
 
141
            .WillRepeatedly (Return (false));
 
142
    EXPECT_CALL (db, enableBlockingVideoSync (DoubleBuffer::Blit, _))
 
143
            .WillRepeatedly (Return (true));
92
144
 
93
145
    EXPECT_CALL (db, blit (r1));
94
146
    db.render (r1, false);
102
154
 
103
155
TEST_F(CompizOpenGLDoubleBufferDeathTest, TestNoPaintedFullscreenOrFBODoesNotBlitOrCopyIfNotSupportedAndDies)
104
156
{
105
 
    StrictMock <MockDoubleBuffer> dbStrict;
 
157
    StrictMock <MockVSyncDoubleBuffer> dbStrict;
106
158
 
107
159
    ON_CALL (dbStrict, blitAvailable ()).WillByDefault (Return (false));
108
160
    ON_CALL (dbStrict, fallbackBlitAvailable ()).WillByDefault (Return (false));
115
167
 
116
168
TEST_F(DoubleBufferTest, TestSubBufferCopyIfNoFBOAndNoSubBufferBlit)
117
169
{
118
 
    StrictMock <MockDoubleBuffer> dbStrict;
 
170
    StrictMock <MockVSyncDoubleBuffer> dbStrict;
119
171
 
120
172
    EXPECT_CALL (dbStrict, blitAvailable ()).WillOnce (Return (false));
121
173
    EXPECT_CALL (dbStrict, fallbackBlitAvailable ()).WillOnce (Return (true));
 
174
    EXPECT_CALL (dbStrict, enableAsyncVideoSync (DoubleBuffer::Blit, _))
 
175
            .WillOnce (Return (false));
 
176
    EXPECT_CALL (dbStrict, enableBlockingVideoSync (DoubleBuffer::Blit, _))
 
177
            .WillOnce (Return (true));
122
178
    EXPECT_CALL (dbStrict, fallbackBlit (blitRegion));
123
179
 
124
180
    dbStrict.render (blitRegion, false);
125
181
}
 
182
 
 
183
TEST_F(DoubleBufferTest, TestCallWorkingStrategy)
 
184
{
 
185
    EXPECT_CALL (db, enableAsyncVideoSync (DoubleBuffer::Swap, _))
 
186
            .WillOnce (Return (true));
 
187
 
 
188
    db.vsync (DoubleBuffer::Swap);
 
189
}
 
190
 
 
191
TEST_F(DoubleBufferTest, TestCallNextWorkingStrategy)
 
192
{
 
193
    /* This one fails */
 
194
    EXPECT_CALL (db, enableAsyncVideoSync (DoubleBuffer::Blit, _))
 
195
            .WillOnce (Return (false));
 
196
    /* Try the next one */
 
197
    EXPECT_CALL (db, enableBlockingVideoSync (DoubleBuffer::Blit, _))
 
198
            .WillOnce (Return (true));
 
199
 
 
200
    db.vsync (DoubleBuffer::Blit);
 
201
}
 
202
 
 
203
TEST_F(DoubleBufferTest, TestCallPrevCallNextPrevDeactivated)
 
204
{
 
205
    /* This one fails */
 
206
    EXPECT_CALL (db, enableAsyncVideoSync (DoubleBuffer::Blit, _))
 
207
            .WillOnce (Return (false));
 
208
    /* Try the next one */
 
209
    EXPECT_CALL (db, enableBlockingVideoSync (DoubleBuffer::Blit, _))
 
210
            .WillOnce (Return (true));
 
211
 
 
212
    db.vsync (DoubleBuffer::Blit);
 
213
 
 
214
    EXPECT_CALL (db, enableAsyncVideoSync (DoubleBuffer::Blit, _))
 
215
            .WillOnce (Return (true));
 
216
    /* Previous one must be deactivated */
 
217
    EXPECT_CALL (db, disableBlockingVideoSync ());
 
218
 
 
219
    db.vsync (DoubleBuffer::Blit);
 
220
}
 
221
 
 
222
TEST_F(DoubleBufferTest, TestReportNoHardwareVSyncIfMoreThan5UnthrottledFrames)
 
223
{
 
224
    /* This one succeeds but fails to throttle */
 
225
    for (unsigned int i = 0; i < 5; ++i)
 
226
    {
 
227
        EXPECT_CALL (db, enableAsyncVideoSync (DoubleBuffer::Blit, _))
 
228
                    .WillOnce (Return (false));
 
229
        EXPECT_CALL (db, enableBlockingVideoSync (DoubleBuffer::Blit, _))
 
230
            .WillOnce (DoAll (SetArgReferee <1> (DoubleBuffer::ExternalFrameThrottlingRequired),
 
231
                                      Return (true)));
 
232
 
 
233
        db.vsync (DoubleBuffer::Blit);
 
234
    }
 
235
 
 
236
    EXPECT_FALSE (db.hardwareVSyncFunctional ());
 
237
}
 
238
 
 
239
TEST_F(DoubleBufferTest, TestRestoreReportHardwareVSync)
 
240
{
 
241
    /* This one succeeds but fails to throttle */
 
242
    for (unsigned int i = 0; i < 5; ++i)
 
243
    {
 
244
        EXPECT_CALL (db, enableAsyncVideoSync (DoubleBuffer::Blit, _))
 
245
                    .WillOnce (Return (false));
 
246
        EXPECT_CALL (db, enableBlockingVideoSync (DoubleBuffer::Blit, _))
 
247
            .WillOnce (DoAll (SetArgReferee <1> (DoubleBuffer::ExternalFrameThrottlingRequired),
 
248
                                      Return (true)));
 
249
 
 
250
        EXPECT_TRUE (db.hardwareVSyncFunctional ());
 
251
 
 
252
        db.vsync (DoubleBuffer::Blit);
 
253
    }
 
254
 
 
255
    EXPECT_FALSE (db.hardwareVSyncFunctional ());
 
256
 
 
257
    /* It works again */
 
258
    EXPECT_CALL (db, enableAsyncVideoSync (DoubleBuffer::Blit, _))
 
259
            .WillOnce (Return (false));
 
260
    EXPECT_CALL (db, enableBlockingVideoSync (DoubleBuffer::Blit, _))
 
261
        .WillOnce (DoAll (SetArgReferee <1> (DoubleBuffer::FrameThrottledInternally),
 
262
                              Return (true)));
 
263
 
 
264
    db.vsync (DoubleBuffer::Blit);
 
265
 
 
266
    /* And should report to work for another 5 bad frames */
 
267
    for (unsigned int i = 0; i < 5; ++i)
 
268
    {
 
269
        EXPECT_CALL (db, enableAsyncVideoSync (DoubleBuffer::Blit, _))
 
270
                    .WillOnce (Return (false));
 
271
        EXPECT_CALL (db, enableBlockingVideoSync (DoubleBuffer::Blit, _))
 
272
            .WillOnce (DoAll (SetArgReferee <1> (DoubleBuffer::ExternalFrameThrottlingRequired),
 
273
                                      Return (true)));
 
274
 
 
275
        EXPECT_TRUE (db.hardwareVSyncFunctional ());
 
276
 
 
277
        db.vsync (DoubleBuffer::Blit);
 
278
    }
 
279
 
 
280
    EXPECT_FALSE (db.hardwareVSyncFunctional ());
 
281
}
 
282
 
 
283
namespace
 
284
{
 
285
class MockOpenGLFunctionsTable
 
286
{
 
287
    public:
 
288
 
 
289
        MOCK_METHOD3 (waitVideoSyncSGI, int (int, int, unsigned int *));
 
290
        MOCK_METHOD1 (swapIntervalEXT, void (int));
 
291
};
 
292
 
 
293
namespace cgl = compiz::opengl;
 
294
namespace cgli = compiz::opengl::impl;
 
295
 
 
296
cgli::GLXWaitVideoSyncSGIFunc
 
297
GetWaitVideoSyncFuncFromMock (MockOpenGLFunctionsTable &mock)
 
298
{
 
299
    return boost::bind (&MockOpenGLFunctionsTable::waitVideoSyncSGI, &mock, _1, _2, _3);
 
300
}
 
301
 
 
302
cgli::GLXSwapIntervalEXTFunc
 
303
GetSwapIntervalFuncFromMock (MockOpenGLFunctionsTable &mock)
 
304
{
 
305
    return boost::bind (&MockOpenGLFunctionsTable::swapIntervalEXT, &mock, _1);
 
306
}
 
307
}
 
308
 
 
309
class OpenGLVideoSyncTest :
 
310
    public ::testing::Test
 
311
{
 
312
    public:
 
313
 
 
314
        OpenGLVideoSyncTest () :
 
315
            doubleBuffer (GetSwapIntervalFuncFromMock (functions),
 
316
                          GetWaitVideoSyncFuncFromMock (functions))
 
317
        {
 
318
        }
 
319
 
 
320
        MockDoubleBuffer         doubleBuffer;
 
321
        MockOpenGLFunctionsTable functions;
 
322
};
 
323
 
 
324
TEST_F (OpenGLVideoSyncTest, TestCallSwapIntervalOnVSyncForFlip)
 
325
{
 
326
    EXPECT_CALL (functions, swapIntervalEXT (1));
 
327
    doubleBuffer.vsync (cgl::DoubleBuffer::Swap);
 
328
}
 
329
 
 
330
TEST_F (OpenGLVideoSyncTest, TestCallSwapIntervalOnEnableForFlipOnlyOnce)
 
331
{
 
332
    EXPECT_CALL (functions, swapIntervalEXT (1)).Times (1);
 
333
    doubleBuffer.vsync (cgl::DoubleBuffer::Swap);
 
334
    doubleBuffer.vsync (cgl::DoubleBuffer::Swap);
 
335
}
 
336
 
 
337
TEST_F (OpenGLVideoSyncTest, TestCallSwapIntervalOnEnableForFlipAndZeroForDisable)
 
338
{
 
339
    EXPECT_CALL (functions, swapIntervalEXT (1));
 
340
    doubleBuffer.vsync (cgl::DoubleBuffer::Swap);
 
341
    EXPECT_CALL (functions, swapIntervalEXT (0));
 
342
    EXPECT_CALL (functions, waitVideoSyncSGI (1, 0, _));
 
343
    doubleBuffer.vsync (cgl::DoubleBuffer::Blit);
 
344
}
 
345
 
 
346
TEST_F (OpenGLVideoSyncTest, TestCallSwapIntervalZeroForDisableOnce)
 
347
{
 
348
    /* Enable it */
 
349
    EXPECT_CALL (functions, swapIntervalEXT (1)).Times (1);
 
350
    doubleBuffer.vsync (cgl::DoubleBuffer::Swap);
 
351
 
 
352
    /* Disable it twice */
 
353
    EXPECT_CALL (functions, swapIntervalEXT (0)).Times (1);
 
354
    EXPECT_CALL (functions, waitVideoSyncSGI (1, 0, _)).Times (2);
 
355
    doubleBuffer.vsync (cgl::DoubleBuffer::Blit);
 
356
    doubleBuffer.vsync (cgl::DoubleBuffer::Blit);
 
357
}
 
358
 
 
359
TEST_F (OpenGLVideoSyncTest, TestCallSwapIntervalFailsToEnableForCopy)
 
360
{
 
361
    EXPECT_CALL (functions, swapIntervalEXT (1)).Times (0);
 
362
    EXPECT_CALL (functions, waitVideoSyncSGI (1, _, _));
 
363
    doubleBuffer.vsync (cgl::DoubleBuffer::Blit);
 
364
}
 
365
 
 
366
TEST_F (OpenGLVideoSyncTest, TestCallSwapIntervalUnthrottledWhereSuccess)
 
367
{
 
368
    EXPECT_CALL (functions, swapIntervalEXT (1));
 
369
 
 
370
    /* At the moment there's no way to test except for the general throttled method */
 
371
    doubleBuffer.vsync (cgl::DoubleBuffer::Swap);
 
372
 
 
373
    EXPECT_FALSE (doubleBuffer.hardwareVSyncFunctional ());
 
374
}
 
375
 
 
376
TEST_F (OpenGLVideoSyncTest, TestCallsGetVideoSyncAndWaitVideoSyncForCopy)
 
377
{
 
378
    EXPECT_CALL (functions, waitVideoSyncSGI (_, _, _));
 
379
    doubleBuffer.vsync (cgl::DoubleBuffer::Blit);
 
380
}
 
381
 
 
382
TEST_F (OpenGLVideoSyncTest, TestCallsWaitVideoSyncAndThrottled)
 
383
{
 
384
    /* Frames 1-5 */
 
385
    ON_CALL (functions, waitVideoSyncSGI (1, _, _)).WillByDefault (DoAll (SetArgPointee<2> (0),
 
386
                                                                          Return (0)));
 
387
    EXPECT_CALL (functions, waitVideoSyncSGI (1, _, _)).Times (5);
 
388
    /* Returned next frame, this frame was throttled */
 
389
    doubleBuffer.vsync (cgl::DoubleBuffer::Blit);
 
390
    doubleBuffer.vsync (cgl::DoubleBuffer::Blit);
 
391
    doubleBuffer.vsync (cgl::DoubleBuffer::Blit);
 
392
    doubleBuffer.vsync (cgl::DoubleBuffer::Blit);
 
393
    doubleBuffer.vsync (cgl::DoubleBuffer::Blit);
 
394
    EXPECT_FALSE (doubleBuffer.hardwareVSyncFunctional ());
 
395
}
 
396
 
 
397
TEST_F (OpenGLVideoSyncTest, TestCallsWaitVideoSyncAndThrottledEveryFrame)
 
398
{
 
399
    InSequence s;
 
400
 
 
401
    /* Frame 0 to frame 1 */
 
402
    EXPECT_CALL (functions, waitVideoSyncSGI (1, _, _)).WillOnce (DoAll (SetArgPointee<2> (1),
 
403
                                                                         Return (0)));
 
404
    /* Frame 1 to frame 2 */
 
405
    EXPECT_CALL (functions, waitVideoSyncSGI (1, _, _)).WillOnce (DoAll (SetArgPointee<2> (2),
 
406
                                                                         Return (0)));
 
407
    /* Frame 2 to frame 3 */
 
408
    EXPECT_CALL (functions, waitVideoSyncSGI (1, _, _)).WillOnce (DoAll (SetArgPointee<2> (3),
 
409
                                                                         Return (0)));
 
410
    /* Frame 3 to frame 4 */
 
411
    EXPECT_CALL (functions, waitVideoSyncSGI (1, _, _)).WillOnce (DoAll (SetArgPointee<2> (4),
 
412
                                                                         Return (0)));
 
413
    /* Frame 5 to frame 5 */
 
414
    EXPECT_CALL (functions, waitVideoSyncSGI (1, _, _)).WillOnce (DoAll (SetArgPointee<2> (5),
 
415
                                                                         Return (0)));
 
416
    /* Returned next frame, this frame was throttled */
 
417
    doubleBuffer.vsync (cgl::DoubleBuffer::Blit);
 
418
    doubleBuffer.vsync (cgl::DoubleBuffer::Blit);
 
419
    doubleBuffer.vsync (cgl::DoubleBuffer::Blit);
 
420
    doubleBuffer.vsync (cgl::DoubleBuffer::Blit);
 
421
    doubleBuffer.vsync (cgl::DoubleBuffer::Blit);
 
422
    EXPECT_TRUE (doubleBuffer.hardwareVSyncFunctional ());
 
423
}
 
424
 
 
425
TEST_F (OpenGLVideoSyncTest, TestCallsWaitVideoSyncAndUnthrottledDueToBrokenWaitVSync)
 
426
{
 
427
    /* Frames 0 to 5 */
 
428
    ON_CALL (functions, waitVideoSyncSGI (1, _, _)).WillByDefault (DoAll (SetArgPointee<2> (0),
 
429
                                                                          Return (0)));
 
430
    EXPECT_CALL (functions, waitVideoSyncSGI (1, _, _)).Times (5);
 
431
    /* Returned next frame, this frame was not throttled */
 
432
    doubleBuffer.vsync (cgl::DoubleBuffer::Blit);
 
433
    doubleBuffer.vsync (cgl::DoubleBuffer::Blit);
 
434
    doubleBuffer.vsync (cgl::DoubleBuffer::Blit);
 
435
    doubleBuffer.vsync (cgl::DoubleBuffer::Blit);
 
436
    doubleBuffer.vsync (cgl::DoubleBuffer::Blit);
 
437
    EXPECT_FALSE (doubleBuffer.hardwareVSyncFunctional ());
 
438
 
 
439
    InSequence s;
 
440
 
 
441
    /* Frame 0 to frame 1 */
 
442
    EXPECT_CALL (functions, waitVideoSyncSGI (1, _, _)).WillOnce (DoAll (SetArgPointee<2> (1),
 
443
                                                                         Return (0)));
 
444
    /* Frame 1 to frame 2 */
 
445
    EXPECT_CALL (functions, waitVideoSyncSGI (1, _, _)).WillOnce (DoAll (SetArgPointee<2> (2),
 
446
                                                                         Return (0)));
 
447
    /* Frame 2 to frame 3 */
 
448
    EXPECT_CALL (functions, waitVideoSyncSGI (1, _, _)).WillOnce (DoAll (SetArgPointee<2> (3),
 
449
                                                                         Return (0)));
 
450
    /* Frame 3 to frame 4 */
 
451
    EXPECT_CALL (functions, waitVideoSyncSGI (1, _, _)).WillOnce (DoAll (SetArgPointee<2> (4),
 
452
                                                                         Return (0)));
 
453
    /* Frame 5 to frame 5 (eg, working waitVideoSyncSGI) */
 
454
    EXPECT_CALL (functions, waitVideoSyncSGI (1, _, _)).WillOnce (DoAll (SetArgPointee<2> (5),
 
455
                                                                         Return (0)));
 
456
    /* Returned next frame, this frame was throttled */
 
457
    doubleBuffer.vsync (cgl::DoubleBuffer::Blit);
 
458
    doubleBuffer.vsync (cgl::DoubleBuffer::Blit);
 
459
    doubleBuffer.vsync (cgl::DoubleBuffer::Blit);
 
460
    doubleBuffer.vsync (cgl::DoubleBuffer::Blit);
 
461
    doubleBuffer.vsync (cgl::DoubleBuffer::Blit);
 
462
    EXPECT_TRUE (doubleBuffer.hardwareVSyncFunctional ());
 
463
}