1 /*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define LOG_TAG "BLASTBufferQueue_test"
18
19 #include <gui/BLASTBufferQueue.h>
20
21 #include <android/hardware/graphics/common/1.2/types.h>
22 #include <gui/BufferQueueCore.h>
23 #include <gui/BufferQueueProducer.h>
24 #include <gui/FrameTimestamps.h>
25 #include <gui/IGraphicBufferProducer.h>
26 #include <gui/IProducerListener.h>
27 #include <gui/Surface.h>
28 #include <gui/SurfaceComposerClient.h>
29 #include <gui/SyncScreenCaptureListener.h>
30 #include <gui/test/CallbackUtils.h>
31 #include <private/gui/ComposerService.h>
32 #include <ui/DisplayMode.h>
33 #include <ui/GraphicBuffer.h>
34 #include <ui/GraphicTypes.h>
35 #include <ui/Transform.h>
36
37 #include <gtest/gtest.h>
38
39 using namespace std::chrono_literals;
40
41 namespace android {
42
43 using Transaction = SurfaceComposerClient::Transaction;
44 using android::hardware::graphics::common::V1_2::BufferUsage;
45
46 class CountProducerListener : public BnProducerListener {
47 public:
onBufferReleased()48 void onBufferReleased() override {
49 std::scoped_lock<std::mutex> lock(mMutex);
50 mNumReleased++;
51 mReleaseCallback.notify_one();
52 }
53
waitOnNumberReleased(int32_t expectedNumReleased)54 void waitOnNumberReleased(int32_t expectedNumReleased) {
55 std::unique_lock<std::mutex> lock(mMutex);
56 while (mNumReleased < expectedNumReleased) {
57 ASSERT_NE(mReleaseCallback.wait_for(lock, std::chrono::seconds(3)),
58 std::cv_status::timeout)
59 << "did not receive release";
60 }
61 }
62
63 private:
64 std::mutex mMutex;
65 std::condition_variable mReleaseCallback;
66 int32_t mNumReleased GUARDED_BY(mMutex) = 0;
67 };
68
69 class BLASTBufferQueueHelper {
70 public:
BLASTBufferQueueHelper(const sp<SurfaceControl> & sc,int width,int height)71 BLASTBufferQueueHelper(const sp<SurfaceControl>& sc, int width, int height) {
72 mBlastBufferQueueAdapter = new BLASTBufferQueue("TestBLASTBufferQueue", sc, width, height,
73 PIXEL_FORMAT_RGBA_8888);
74 }
75
update(const sp<SurfaceControl> & sc,int width,int height)76 void update(const sp<SurfaceControl>& sc, int width, int height) {
77 mBlastBufferQueueAdapter->update(sc, width, height, PIXEL_FORMAT_RGBA_8888);
78 }
79
setNextTransaction(Transaction * next)80 void setNextTransaction(Transaction* next) {
81 mBlastBufferQueueAdapter->setNextTransaction(next);
82 }
83
getWidth()84 int getWidth() { return mBlastBufferQueueAdapter->mSize.width; }
85
getHeight()86 int getHeight() { return mBlastBufferQueueAdapter->mSize.height; }
87
getNextTransaction()88 Transaction* getNextTransaction() { return mBlastBufferQueueAdapter->mNextTransaction; }
89
getIGraphicBufferProducer()90 sp<IGraphicBufferProducer> getIGraphicBufferProducer() {
91 return mBlastBufferQueueAdapter->getIGraphicBufferProducer();
92 }
93
getSurfaceControl()94 const sp<SurfaceControl> getSurfaceControl() {
95 return mBlastBufferQueueAdapter->mSurfaceControl;
96 }
97
getSurface()98 sp<Surface> getSurface() {
99 return mBlastBufferQueueAdapter->getSurface(false /* includeSurfaceControlHandle */);
100 }
101
waitForCallbacks()102 void waitForCallbacks() {
103 std::unique_lock lock{mBlastBufferQueueAdapter->mMutex};
104 // Wait until all but one of the submitted buffers have been released.
105 while (mBlastBufferQueueAdapter->mSubmitted.size() > 1) {
106 mBlastBufferQueueAdapter->mCallbackCV.wait(lock);
107 }
108 }
109
setTransactionCompleteCallback(int64_t frameNumber)110 void setTransactionCompleteCallback(int64_t frameNumber) {
111 mBlastBufferQueueAdapter->setTransactionCompleteCallback(frameNumber, [&](int64_t frame) {
112 std::unique_lock lock{mMutex};
113 mLastTransactionCompleteFrameNumber = frame;
114 mCallbackCV.notify_all();
115 });
116 }
117
waitForCallback(int64_t frameNumber)118 void waitForCallback(int64_t frameNumber) {
119 std::unique_lock lock{mMutex};
120 // Wait until all but one of the submitted buffers have been released.
121 while (mLastTransactionCompleteFrameNumber < frameNumber) {
122 mCallbackCV.wait(lock);
123 }
124 }
125
126 private:
127 sp<BLASTBufferQueue> mBlastBufferQueueAdapter;
128
129 std::mutex mMutex;
130 std::condition_variable mCallbackCV;
131 int64_t mLastTransactionCompleteFrameNumber = -1;
132 };
133
134 class BLASTBufferQueueTest : public ::testing::Test {
135 public:
136 protected:
BLASTBufferQueueTest()137 BLASTBufferQueueTest() {
138 const ::testing::TestInfo* const testInfo =
139 ::testing::UnitTest::GetInstance()->current_test_info();
140 ALOGV("Begin test: %s.%s", testInfo->test_case_name(), testInfo->name());
141 }
142
~BLASTBufferQueueTest()143 ~BLASTBufferQueueTest() {
144 const ::testing::TestInfo* const testInfo =
145 ::testing::UnitTest::GetInstance()->current_test_info();
146 ALOGV("End test: %s.%s", testInfo->test_case_name(), testInfo->name());
147 }
148
SetUp()149 void SetUp() {
150 mComposer = ComposerService::getComposerService();
151 mClient = new SurfaceComposerClient();
152 mDisplayToken = mClient->getInternalDisplayToken();
153 ASSERT_NE(nullptr, mDisplayToken.get());
154 Transaction t;
155 t.setDisplayLayerStack(mDisplayToken, 0);
156 t.apply();
157 t.clear();
158
159 ui::DisplayMode mode;
160 ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(mDisplayToken, &mode));
161 const ui::Size& resolution = mode.resolution;
162 mDisplayWidth = resolution.getWidth();
163 mDisplayHeight = resolution.getHeight();
164
165 mSurfaceControl = mClient->createSurface(String8("TestSurface"), mDisplayWidth,
166 mDisplayHeight, PIXEL_FORMAT_RGBA_8888,
167 ISurfaceComposerClient::eFXSurfaceBufferState,
168 /*parent*/ nullptr);
169 t.setLayerStack(mSurfaceControl, 0)
170 .setLayer(mSurfaceControl, std::numeric_limits<int32_t>::max())
171 .show(mSurfaceControl)
172 .setDataspace(mSurfaceControl, ui::Dataspace::V0_SRGB)
173 .apply();
174
175 mCaptureArgs.displayToken = mDisplayToken;
176 mCaptureArgs.dataspace = ui::Dataspace::V0_SRGB;
177 }
178
setUpProducer(BLASTBufferQueueHelper & adapter,sp<IGraphicBufferProducer> & producer,int32_t maxBufferCount=2)179 void setUpProducer(BLASTBufferQueueHelper& adapter, sp<IGraphicBufferProducer>& producer,
180 int32_t maxBufferCount = 2) {
181 producer = adapter.getIGraphicBufferProducer();
182 setUpProducer(producer, maxBufferCount);
183 }
184
setUpProducer(sp<IGraphicBufferProducer> & igbProducer,int32_t maxBufferCount)185 void setUpProducer(sp<IGraphicBufferProducer>& igbProducer, int32_t maxBufferCount) {
186 ASSERT_NE(nullptr, igbProducer.get());
187 ASSERT_EQ(NO_ERROR, igbProducer->setMaxDequeuedBufferCount(maxBufferCount));
188 IGraphicBufferProducer::QueueBufferOutput qbOutput;
189 mProducerListener = new CountProducerListener();
190 ASSERT_EQ(NO_ERROR,
191 igbProducer->connect(mProducerListener, NATIVE_WINDOW_API_CPU, false, &qbOutput));
192 ASSERT_NE(ui::Transform::ROT_INVALID, qbOutput.transformHint);
193 }
194
fillBuffer(uint32_t * bufData,Rect rect,uint32_t stride,uint8_t r,uint8_t g,uint8_t b)195 void fillBuffer(uint32_t* bufData, Rect rect, uint32_t stride, uint8_t r, uint8_t g,
196 uint8_t b) {
197 for (uint32_t row = rect.top; row < rect.bottom; row++) {
198 for (uint32_t col = rect.left; col < rect.right; col++) {
199 uint8_t* pixel = (uint8_t*)(bufData + (row * stride) + col);
200 *pixel = r;
201 *(pixel + 1) = g;
202 *(pixel + 2) = b;
203 *(pixel + 3) = 255;
204 }
205 }
206 }
207
fillQuadrants(sp<GraphicBuffer> & buf)208 void fillQuadrants(sp<GraphicBuffer>& buf) {
209 const auto bufWidth = buf->getWidth();
210 const auto bufHeight = buf->getHeight();
211 uint32_t* bufData;
212 buf->lock(static_cast<uint32_t>(GraphicBuffer::USAGE_SW_WRITE_OFTEN),
213 reinterpret_cast<void**>(&bufData));
214 fillBuffer(bufData, Rect(0, 0, bufWidth / 2, bufHeight / 2), buf->getStride(), 0, 0, 0);
215 fillBuffer(bufData, Rect(bufWidth / 2, 0, bufWidth, bufHeight / 2), buf->getStride(), 255,
216 0, 0);
217 fillBuffer(bufData, Rect(bufWidth / 2, bufHeight / 2, bufWidth, bufHeight),
218 buf->getStride(), 0, 255, 0);
219 fillBuffer(bufData, Rect(0, bufHeight / 2, bufWidth / 2, bufHeight), buf->getStride(), 0, 0,
220 255);
221 buf->unlock();
222 }
223
checkScreenCapture(uint8_t r,uint8_t g,uint8_t b,Rect region,int32_t border=0,bool outsideRegion=false)224 void checkScreenCapture(uint8_t r, uint8_t g, uint8_t b, Rect region, int32_t border = 0,
225 bool outsideRegion = false) {
226 sp<GraphicBuffer>& captureBuf = mCaptureResults.buffer;
227 const auto epsilon = 3;
228 const auto width = captureBuf->getWidth();
229 const auto height = captureBuf->getHeight();
230 const auto stride = captureBuf->getStride();
231
232 uint32_t* bufData;
233 captureBuf->lock(static_cast<uint32_t>(GraphicBuffer::USAGE_SW_READ_OFTEN),
234 reinterpret_cast<void**>(&bufData));
235
236 for (uint32_t row = 0; row < height; row++) {
237 for (uint32_t col = 0; col < width; col++) {
238 uint8_t* pixel = (uint8_t*)(bufData + (row * stride) + col);
239 ASSERT_NE(nullptr, pixel);
240 bool inRegion;
241 if (!outsideRegion) {
242 inRegion = row >= region.top + border && row < region.bottom - border &&
243 col >= region.left + border && col < region.right - border;
244 } else {
245 inRegion = row >= region.top - border && row < region.bottom + border &&
246 col >= region.left - border && col < region.right + border;
247 }
248 if (!outsideRegion && inRegion) {
249 ASSERT_GE(epsilon, abs(r - *(pixel)));
250 ASSERT_GE(epsilon, abs(g - *(pixel + 1)));
251 ASSERT_GE(epsilon, abs(b - *(pixel + 2)));
252 } else if (outsideRegion && !inRegion) {
253 ASSERT_GE(epsilon, abs(r - *(pixel)));
254 ASSERT_GE(epsilon, abs(g - *(pixel + 1)));
255 ASSERT_GE(epsilon, abs(b - *(pixel + 2)));
256 }
257 ASSERT_EQ(false, ::testing::Test::HasFailure());
258 }
259 }
260 captureBuf->unlock();
261 }
262
captureDisplay(DisplayCaptureArgs & captureArgs,ScreenCaptureResults & captureResults)263 static status_t captureDisplay(DisplayCaptureArgs& captureArgs,
264 ScreenCaptureResults& captureResults) {
265 const auto sf = ComposerService::getComposerService();
266 SurfaceComposerClient::Transaction().apply(true);
267
268 const sp<SyncScreenCaptureListener> captureListener = new SyncScreenCaptureListener();
269 status_t status = sf->captureDisplay(captureArgs, captureListener);
270 if (status != NO_ERROR) {
271 return status;
272 }
273 captureResults = captureListener->waitForResults();
274 return captureResults.result;
275 }
276
queueBuffer(sp<IGraphicBufferProducer> igbp,uint8_t r,uint8_t g,uint8_t b,nsecs_t presentTimeDelay)277 void queueBuffer(sp<IGraphicBufferProducer> igbp, uint8_t r, uint8_t g, uint8_t b,
278 nsecs_t presentTimeDelay) {
279 int slot;
280 sp<Fence> fence;
281 sp<GraphicBuffer> buf;
282 auto ret = igbp->dequeueBuffer(&slot, &fence, mDisplayWidth, mDisplayHeight,
283 PIXEL_FORMAT_RGBA_8888, GRALLOC_USAGE_SW_WRITE_OFTEN,
284 nullptr, nullptr);
285 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, ret);
286 ASSERT_EQ(OK, igbp->requestBuffer(slot, &buf));
287
288 uint32_t* bufData;
289 buf->lock(static_cast<uint32_t>(GraphicBuffer::USAGE_SW_WRITE_OFTEN),
290 reinterpret_cast<void**>(&bufData));
291 fillBuffer(bufData, Rect(buf->getWidth(), buf->getHeight() / 2), buf->getStride(), r, g, b);
292 buf->unlock();
293
294 IGraphicBufferProducer::QueueBufferOutput qbOutput;
295 nsecs_t timestampNanos = systemTime() + presentTimeDelay;
296 IGraphicBufferProducer::QueueBufferInput input(timestampNanos, false, HAL_DATASPACE_UNKNOWN,
297 Rect(mDisplayWidth, mDisplayHeight / 2),
298 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0,
299 Fence::NO_FENCE);
300 igbp->queueBuffer(slot, input, &qbOutput);
301 }
302
303 sp<SurfaceComposerClient> mClient;
304 sp<ISurfaceComposer> mComposer;
305
306 sp<IBinder> mDisplayToken;
307
308 sp<SurfaceControl> mSurfaceControl;
309
310 uint32_t mDisplayWidth;
311 uint32_t mDisplayHeight;
312
313 DisplayCaptureArgs mCaptureArgs;
314 ScreenCaptureResults mCaptureResults;
315 sp<CountProducerListener> mProducerListener;
316 };
317
TEST_F(BLASTBufferQueueTest,CreateBLASTBufferQueue)318 TEST_F(BLASTBufferQueueTest, CreateBLASTBufferQueue) {
319 // create BLASTBufferQueue adapter associated with this surface
320 BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
321 ASSERT_EQ(mSurfaceControl, adapter.getSurfaceControl());
322 ASSERT_EQ(mDisplayWidth, adapter.getWidth());
323 ASSERT_EQ(mDisplayHeight, adapter.getHeight());
324 ASSERT_EQ(nullptr, adapter.getNextTransaction());
325 }
326
TEST_F(BLASTBufferQueueTest,Update)327 TEST_F(BLASTBufferQueueTest, Update) {
328 BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
329 sp<SurfaceControl> updateSurface =
330 mClient->createSurface(String8("UpdateTest"), mDisplayWidth / 2, mDisplayHeight / 2,
331 PIXEL_FORMAT_RGBA_8888);
332 adapter.update(updateSurface, mDisplayWidth / 2, mDisplayHeight / 2);
333 ASSERT_EQ(updateSurface, adapter.getSurfaceControl());
334 sp<IGraphicBufferProducer> igbProducer;
335 setUpProducer(adapter, igbProducer);
336
337 int32_t width;
338 igbProducer->query(NATIVE_WINDOW_WIDTH, &width);
339 ASSERT_EQ(mDisplayWidth / 2, width);
340 int32_t height;
341 igbProducer->query(NATIVE_WINDOW_HEIGHT, &height);
342 ASSERT_EQ(mDisplayHeight / 2, height);
343 }
344
TEST_F(BLASTBufferQueueTest,SetNextTransaction)345 TEST_F(BLASTBufferQueueTest, SetNextTransaction) {
346 BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
347 Transaction next;
348 adapter.setNextTransaction(&next);
349 ASSERT_EQ(&next, adapter.getNextTransaction());
350 }
351
TEST_F(BLASTBufferQueueTest,DISABLED_onFrameAvailable_ApplyDesiredPresentTime)352 TEST_F(BLASTBufferQueueTest, DISABLED_onFrameAvailable_ApplyDesiredPresentTime) {
353 BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
354 sp<IGraphicBufferProducer> igbProducer;
355 setUpProducer(adapter, igbProducer);
356
357 int slot;
358 sp<Fence> fence;
359 sp<GraphicBuffer> buf;
360 auto ret = igbProducer->dequeueBuffer(&slot, &fence, mDisplayWidth, mDisplayHeight,
361 PIXEL_FORMAT_RGBA_8888, GRALLOC_USAGE_SW_WRITE_OFTEN,
362 nullptr, nullptr);
363 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, ret);
364 ASSERT_EQ(OK, igbProducer->requestBuffer(slot, &buf));
365
366 nsecs_t desiredPresentTime = systemTime() + nsecs_t(5 * 1e8);
367 IGraphicBufferProducer::QueueBufferOutput qbOutput;
368 IGraphicBufferProducer::QueueBufferInput input(desiredPresentTime, true /* autotimestamp */,
369 HAL_DATASPACE_UNKNOWN,
370 Rect(mDisplayWidth, mDisplayHeight),
371 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0,
372 Fence::NO_FENCE);
373 igbProducer->queueBuffer(slot, input, &qbOutput);
374 ASSERT_NE(ui::Transform::ROT_INVALID, qbOutput.transformHint);
375
376 adapter.waitForCallbacks();
377 ASSERT_GE(systemTime(), desiredPresentTime);
378 }
379
TEST_F(BLASTBufferQueueTest,onFrameAvailable_Apply)380 TEST_F(BLASTBufferQueueTest, onFrameAvailable_Apply) {
381 uint8_t r = 255;
382 uint8_t g = 0;
383 uint8_t b = 0;
384
385 BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
386 sp<IGraphicBufferProducer> igbProducer;
387 setUpProducer(adapter, igbProducer);
388
389 int slot;
390 sp<Fence> fence;
391 sp<GraphicBuffer> buf;
392 auto ret = igbProducer->dequeueBuffer(&slot, &fence, mDisplayWidth, mDisplayHeight,
393 PIXEL_FORMAT_RGBA_8888, GRALLOC_USAGE_SW_WRITE_OFTEN,
394 nullptr, nullptr);
395 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, ret);
396 ASSERT_EQ(OK, igbProducer->requestBuffer(slot, &buf));
397
398 uint32_t* bufData;
399 buf->lock(static_cast<uint32_t>(GraphicBuffer::USAGE_SW_WRITE_OFTEN),
400 reinterpret_cast<void**>(&bufData));
401 fillBuffer(bufData, Rect(buf->getWidth(), buf->getHeight()), buf->getStride(), r, g, b);
402 buf->unlock();
403
404 IGraphicBufferProducer::QueueBufferOutput qbOutput;
405 IGraphicBufferProducer::QueueBufferInput input(systemTime(), true /* autotimestamp */,
406 HAL_DATASPACE_UNKNOWN,
407 Rect(mDisplayWidth, mDisplayHeight),
408 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0,
409 Fence::NO_FENCE);
410 igbProducer->queueBuffer(slot, input, &qbOutput);
411 ASSERT_NE(ui::Transform::ROT_INVALID, qbOutput.transformHint);
412
413 adapter.waitForCallbacks();
414
415 // capture screen and verify that it is red
416 ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults));
417 ASSERT_NO_FATAL_FAILURE(
418 checkScreenCapture(r, g, b, {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight}));
419 }
420
TEST_F(BLASTBufferQueueTest,TripleBuffering)421 TEST_F(BLASTBufferQueueTest, TripleBuffering) {
422 BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
423 sp<IGraphicBufferProducer> igbProducer;
424 setUpProducer(adapter, igbProducer);
425
426 std::vector<std::pair<int, sp<Fence>>> allocated;
427 int minUndequeuedBuffers = 0;
428 ASSERT_EQ(OK, igbProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBuffers));
429 const auto bufferCount = minUndequeuedBuffers + 2;
430
431 for (int i = 0; i < bufferCount; i++) {
432 int slot;
433 sp<Fence> fence;
434 sp<GraphicBuffer> buf;
435 auto ret = igbProducer->dequeueBuffer(&slot, &fence, mDisplayWidth, mDisplayHeight,
436 PIXEL_FORMAT_RGBA_8888, GRALLOC_USAGE_SW_WRITE_OFTEN,
437 nullptr, nullptr);
438 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, ret);
439 ASSERT_EQ(OK, igbProducer->requestBuffer(slot, &buf));
440 allocated.push_back({slot, fence});
441 }
442 for (int i = 0; i < allocated.size(); i++) {
443 igbProducer->cancelBuffer(allocated[i].first, allocated[i].second);
444 }
445
446 for (int i = 0; i < 100; i++) {
447 int slot;
448 sp<Fence> fence;
449 sp<GraphicBuffer> buf;
450 auto ret = igbProducer->dequeueBuffer(&slot, &fence, mDisplayWidth, mDisplayHeight,
451 PIXEL_FORMAT_RGBA_8888, GRALLOC_USAGE_SW_WRITE_OFTEN,
452 nullptr, nullptr);
453 ASSERT_EQ(NO_ERROR, ret);
454 IGraphicBufferProducer::QueueBufferOutput qbOutput;
455 IGraphicBufferProducer::QueueBufferInput input(systemTime(), true /* autotimestamp */,
456 HAL_DATASPACE_UNKNOWN,
457 Rect(mDisplayWidth, mDisplayHeight),
458 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0,
459 Fence::NO_FENCE);
460 igbProducer->queueBuffer(slot, input, &qbOutput);
461 }
462 adapter.waitForCallbacks();
463 }
464
TEST_F(BLASTBufferQueueTest,SetCrop_Item)465 TEST_F(BLASTBufferQueueTest, SetCrop_Item) {
466 uint8_t r = 255;
467 uint8_t g = 0;
468 uint8_t b = 0;
469
470 BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
471 sp<IGraphicBufferProducer> igbProducer;
472 setUpProducer(adapter, igbProducer);
473 int slot;
474 sp<Fence> fence;
475 sp<GraphicBuffer> buf;
476 auto ret = igbProducer->dequeueBuffer(&slot, &fence, mDisplayWidth, mDisplayHeight,
477 PIXEL_FORMAT_RGBA_8888, GRALLOC_USAGE_SW_WRITE_OFTEN,
478 nullptr, nullptr);
479 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, ret);
480 ASSERT_EQ(OK, igbProducer->requestBuffer(slot, &buf));
481
482 uint32_t* bufData;
483 buf->lock(static_cast<uint32_t>(GraphicBuffer::USAGE_SW_WRITE_OFTEN),
484 reinterpret_cast<void**>(&bufData));
485 fillBuffer(bufData, Rect(buf->getWidth(), buf->getHeight() / 2), buf->getStride(), r, g, b);
486 buf->unlock();
487
488 IGraphicBufferProducer::QueueBufferOutput qbOutput;
489 IGraphicBufferProducer::QueueBufferInput input(systemTime(), true /* autotimestamp */,
490 HAL_DATASPACE_UNKNOWN,
491 Rect(mDisplayWidth, mDisplayHeight / 2),
492 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0,
493 Fence::NO_FENCE);
494 igbProducer->queueBuffer(slot, input, &qbOutput);
495 ASSERT_NE(ui::Transform::ROT_INVALID, qbOutput.transformHint);
496
497 adapter.waitForCallbacks();
498 // capture screen and verify that it is red
499 ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults));
500
501 ASSERT_NO_FATAL_FAILURE(
502 checkScreenCapture(r, g, b,
503 {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight / 2}));
504 }
505
TEST_F(BLASTBufferQueueTest,SetCrop_ScalingModeScaleCrop)506 TEST_F(BLASTBufferQueueTest, SetCrop_ScalingModeScaleCrop) {
507 uint8_t r = 255;
508 uint8_t g = 0;
509 uint8_t b = 0;
510
511 int32_t bufferSideLength =
512 (mDisplayWidth < mDisplayHeight) ? mDisplayWidth / 2 : mDisplayHeight / 2;
513 int32_t finalCropSideLength = bufferSideLength / 2;
514
515 auto bg = mClient->createSurface(String8("BGTest"), 0, 0, PIXEL_FORMAT_RGBA_8888,
516 ISurfaceComposerClient::eFXSurfaceEffect);
517 ASSERT_NE(nullptr, bg.get());
518 Transaction t;
519 t.setLayerStack(bg, 0)
520 .setCrop(bg, Rect(0, 0, mDisplayWidth, mDisplayHeight))
521 .setColor(bg, half3{0, 0, 0})
522 .setLayer(bg, 0)
523 .apply();
524
525 BLASTBufferQueueHelper adapter(mSurfaceControl, bufferSideLength, bufferSideLength);
526 sp<IGraphicBufferProducer> igbProducer;
527 setUpProducer(adapter, igbProducer);
528 int slot;
529 sp<Fence> fence;
530 sp<GraphicBuffer> buf;
531 auto ret = igbProducer->dequeueBuffer(&slot, &fence, bufferSideLength, bufferSideLength,
532 PIXEL_FORMAT_RGBA_8888, GRALLOC_USAGE_SW_WRITE_OFTEN,
533 nullptr, nullptr);
534 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, ret);
535 ASSERT_EQ(OK, igbProducer->requestBuffer(slot, &buf));
536
537 uint32_t* bufData;
538 buf->lock(static_cast<uint32_t>(GraphicBuffer::USAGE_SW_WRITE_OFTEN),
539 reinterpret_cast<void**>(&bufData));
540 fillBuffer(bufData, Rect(buf->getWidth(), buf->getHeight()), buf->getStride(), 0, 0, 0);
541 fillBuffer(bufData,
542 Rect(finalCropSideLength / 2, 0, buf->getWidth() - finalCropSideLength / 2,
543 buf->getHeight()),
544 buf->getStride(), r, g, b);
545 buf->unlock();
546
547 IGraphicBufferProducer::QueueBufferOutput qbOutput;
548 IGraphicBufferProducer::QueueBufferInput input(systemTime(), true /* autotimestamp */,
549 HAL_DATASPACE_UNKNOWN,
550 Rect(bufferSideLength, finalCropSideLength),
551 NATIVE_WINDOW_SCALING_MODE_SCALE_CROP, 0,
552 Fence::NO_FENCE);
553 igbProducer->queueBuffer(slot, input, &qbOutput);
554 ASSERT_NE(ui::Transform::ROT_INVALID, qbOutput.transformHint);
555
556 adapter.waitForCallbacks();
557 // capture screen and verify that it is red
558 ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults));
559 ASSERT_NO_FATAL_FAILURE(checkScreenCapture(r, g, b,
560 {10, 10, (int32_t)bufferSideLength - 10,
561 (int32_t)bufferSideLength - 10}));
562 ASSERT_NO_FATAL_FAILURE(
563 checkScreenCapture(0, 0, 0,
564 {0, 0, (int32_t)bufferSideLength, (int32_t)bufferSideLength},
565 /*border*/ 0, /*outsideRegion*/ true));
566 }
567
TEST_F(BLASTBufferQueueTest,ScaleCroppedBufferToBufferSize)568 TEST_F(BLASTBufferQueueTest, ScaleCroppedBufferToBufferSize) {
569 // add black background
570 auto bg = mClient->createSurface(String8("BGTest"), 0, 0, PIXEL_FORMAT_RGBA_8888,
571 ISurfaceComposerClient::eFXSurfaceEffect);
572 ASSERT_NE(nullptr, bg.get());
573 Transaction t;
574 t.setLayerStack(bg, 0)
575 .setCrop(bg, Rect(0, 0, mDisplayWidth, mDisplayHeight))
576 .setColor(bg, half3{0, 0, 0})
577 .setLayer(bg, 0)
578 .apply();
579
580 Rect windowSize(1000, 1000);
581 Rect bufferSize(windowSize);
582 Rect bufferCrop(200, 200, 700, 700);
583
584 BLASTBufferQueueHelper adapter(mSurfaceControl, windowSize.getWidth(), windowSize.getHeight());
585 sp<IGraphicBufferProducer> igbProducer;
586 setUpProducer(adapter, igbProducer);
587 int slot;
588 sp<Fence> fence;
589 sp<GraphicBuffer> buf;
590 auto ret = igbProducer->dequeueBuffer(&slot, &fence, bufferSize.getWidth(),
591 bufferSize.getHeight(), PIXEL_FORMAT_RGBA_8888,
592 GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr, nullptr);
593 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, ret);
594 ASSERT_EQ(OK, igbProducer->requestBuffer(slot, &buf));
595
596 uint32_t* bufData;
597 buf->lock(static_cast<uint32_t>(GraphicBuffer::USAGE_SW_WRITE_OFTEN),
598 reinterpret_cast<void**>(&bufData));
599 // fill buffer with grey
600 fillBuffer(bufData, bufferSize, buf->getStride(), 127, 127, 127);
601
602 // fill crop area with different colors so we can verify the cropped region has been scaled
603 // correctly.
604 fillBuffer(bufData, Rect(200, 200, 450, 450), buf->getStride(), /* rgb */ 255, 0, 0);
605 fillBuffer(bufData, Rect(200, 451, 450, 700), buf->getStride(), /* rgb */ 0, 255, 0);
606 fillBuffer(bufData, Rect(451, 200, 700, 450), buf->getStride(), /* rgb */ 0, 0, 255);
607 fillBuffer(bufData, Rect(451, 451, 700, 700), buf->getStride(), /* rgb */ 255, 0, 0);
608 buf->unlock();
609
610 IGraphicBufferProducer::QueueBufferOutput qbOutput;
611 IGraphicBufferProducer::QueueBufferInput input(systemTime(), true /* autotimestamp */,
612 HAL_DATASPACE_UNKNOWN,
613 bufferCrop /* Rect::INVALID_RECT */,
614 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW, 0,
615 Fence::NO_FENCE);
616 igbProducer->queueBuffer(slot, input, &qbOutput);
617 ASSERT_NE(ui::Transform::ROT_INVALID, qbOutput.transformHint);
618
619 adapter.waitForCallbacks();
620
621 ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults));
622
623 // Verify cropped region is scaled correctly.
624 ASSERT_NO_FATAL_FAILURE(checkScreenCapture(255, 0, 0, {10, 10, 490, 490}));
625 ASSERT_NO_FATAL_FAILURE(checkScreenCapture(0, 255, 0, {10, 510, 490, 990}));
626 ASSERT_NO_FATAL_FAILURE(checkScreenCapture(0, 0, 255, {510, 10, 990, 490}));
627 ASSERT_NO_FATAL_FAILURE(checkScreenCapture(255, 0, 0, {510, 510, 990, 990}));
628 // Verify outside region is black.
629 ASSERT_NO_FATAL_FAILURE(checkScreenCapture(0, 0, 0,
630 {0, 0, (int32_t)windowSize.getWidth(),
631 (int32_t)windowSize.getHeight()},
632 /*border*/ 0, /*outsideRegion*/ true));
633 }
634
TEST_F(BLASTBufferQueueTest,ScaleCroppedBufferToWindowSize)635 TEST_F(BLASTBufferQueueTest, ScaleCroppedBufferToWindowSize) {
636 // add black background
637 auto bg = mClient->createSurface(String8("BGTest"), 0, 0, PIXEL_FORMAT_RGBA_8888,
638 ISurfaceComposerClient::eFXSurfaceEffect);
639 ASSERT_NE(nullptr, bg.get());
640 Transaction t;
641 t.setLayerStack(bg, 0)
642 .setCrop(bg, Rect(0, 0, mDisplayWidth, mDisplayHeight))
643 .setColor(bg, half3{0, 0, 0})
644 .setLayer(bg, 0)
645 .apply();
646
647 Rect windowSize(1000, 1000);
648 Rect bufferSize(500, 500);
649 Rect bufferCrop(100, 100, 350, 350);
650
651 BLASTBufferQueueHelper adapter(mSurfaceControl, windowSize.getWidth(), windowSize.getHeight());
652 sp<IGraphicBufferProducer> igbProducer;
653 setUpProducer(adapter, igbProducer);
654 int slot;
655 sp<Fence> fence;
656 sp<GraphicBuffer> buf;
657 auto ret = igbProducer->dequeueBuffer(&slot, &fence, bufferSize.getWidth(),
658 bufferSize.getHeight(), PIXEL_FORMAT_RGBA_8888,
659 GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr, nullptr);
660 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, ret);
661 ASSERT_EQ(OK, igbProducer->requestBuffer(slot, &buf));
662
663 uint32_t* bufData;
664 buf->lock(static_cast<uint32_t>(GraphicBuffer::USAGE_SW_WRITE_OFTEN),
665 reinterpret_cast<void**>(&bufData));
666 // fill buffer with grey
667 fillBuffer(bufData, bufferSize, buf->getStride(), 127, 127, 127);
668
669 // fill crop area with different colors so we can verify the cropped region has been scaled
670 // correctly.
671 fillBuffer(bufData, Rect(100, 100, 225, 225), buf->getStride(), /* rgb */ 255, 0, 0);
672 fillBuffer(bufData, Rect(100, 226, 225, 350), buf->getStride(), /* rgb */ 0, 255, 0);
673 fillBuffer(bufData, Rect(226, 100, 350, 225), buf->getStride(), /* rgb */ 0, 0, 255);
674 fillBuffer(bufData, Rect(226, 226, 350, 350), buf->getStride(), /* rgb */ 255, 0, 0);
675 buf->unlock();
676
677 IGraphicBufferProducer::QueueBufferOutput qbOutput;
678 IGraphicBufferProducer::QueueBufferInput input(systemTime(), true /* autotimestamp */,
679 HAL_DATASPACE_UNKNOWN,
680 bufferCrop /* Rect::INVALID_RECT */,
681 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW, 0,
682 Fence::NO_FENCE);
683 igbProducer->queueBuffer(slot, input, &qbOutput);
684 ASSERT_NE(ui::Transform::ROT_INVALID, qbOutput.transformHint);
685
686 adapter.waitForCallbacks();
687
688 ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults));
689 // Verify cropped region is scaled correctly.
690 ASSERT_NO_FATAL_FAILURE(checkScreenCapture(255, 0, 0, {10, 10, 490, 490}));
691 ASSERT_NO_FATAL_FAILURE(checkScreenCapture(0, 255, 0, {10, 510, 490, 990}));
692 ASSERT_NO_FATAL_FAILURE(checkScreenCapture(0, 0, 255, {510, 10, 990, 490}));
693 ASSERT_NO_FATAL_FAILURE(checkScreenCapture(255, 0, 0, {510, 510, 990, 990}));
694 // Verify outside region is black.
695 ASSERT_NO_FATAL_FAILURE(checkScreenCapture(0, 0, 0,
696 {0, 0, (int32_t)windowSize.getWidth(),
697 (int32_t)windowSize.getHeight()},
698 /*border*/ 0, /*outsideRegion*/ true));
699 }
700
701 // b/196339769 verify we can can update the requested size while the in FREEZE scaling mode and
702 // scale the buffer properly when the mode changes to SCALE_TO_WINDOW
TEST_F(BLASTBufferQueueTest,ScalingModeChanges)703 TEST_F(BLASTBufferQueueTest, ScalingModeChanges) {
704 uint8_t r = 255;
705 uint8_t g = 0;
706 uint8_t b = 0;
707
708 BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight / 4);
709 sp<IGraphicBufferProducer> igbProducer;
710 setUpProducer(adapter, igbProducer);
711 {
712 int slot;
713 sp<Fence> fence;
714 sp<GraphicBuffer> buf;
715 auto ret = igbProducer->dequeueBuffer(&slot, &fence, mDisplayWidth, mDisplayHeight / 4,
716 PIXEL_FORMAT_RGBA_8888, GRALLOC_USAGE_SW_WRITE_OFTEN,
717 nullptr, nullptr);
718 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, ret);
719 ASSERT_EQ(OK, igbProducer->requestBuffer(slot, &buf));
720
721 uint32_t* bufData;
722 buf->lock(static_cast<uint32_t>(GraphicBuffer::USAGE_SW_WRITE_OFTEN),
723 reinterpret_cast<void**>(&bufData));
724 fillBuffer(bufData, Rect(buf->getWidth(), buf->getHeight()), buf->getStride(), r, g, b);
725 buf->unlock();
726
727 IGraphicBufferProducer::QueueBufferOutput qbOutput;
728 IGraphicBufferProducer::QueueBufferInput input(systemTime(), true /* autotimestamp */,
729 HAL_DATASPACE_UNKNOWN, {},
730 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0,
731 Fence::NO_FENCE);
732 igbProducer->queueBuffer(slot, input, &qbOutput);
733 adapter.waitForCallbacks();
734 }
735 // capture screen and verify that it is red
736 ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults));
737
738 ASSERT_NO_FATAL_FAILURE(
739 checkScreenCapture(r, g, b,
740 {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight / 4}));
741
742 // update the size to half the display and dequeue a buffer quarter of the display.
743 adapter.update(mSurfaceControl, mDisplayWidth, mDisplayHeight / 2);
744
745 {
746 int slot;
747 sp<Fence> fence;
748 sp<GraphicBuffer> buf;
749 auto ret = igbProducer->dequeueBuffer(&slot, &fence, mDisplayWidth, mDisplayHeight / 8,
750 PIXEL_FORMAT_RGBA_8888, GRALLOC_USAGE_SW_WRITE_OFTEN,
751 nullptr, nullptr);
752 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, ret);
753 ASSERT_EQ(OK, igbProducer->requestBuffer(slot, &buf));
754
755 uint32_t* bufData;
756 buf->lock(static_cast<uint32_t>(GraphicBuffer::USAGE_SW_WRITE_OFTEN),
757 reinterpret_cast<void**>(&bufData));
758 g = 255;
759 fillBuffer(bufData, Rect(buf->getWidth(), buf->getHeight()), buf->getStride(), r, g, b);
760 buf->unlock();
761
762 IGraphicBufferProducer::QueueBufferOutput qbOutput;
763 IGraphicBufferProducer::QueueBufferInput input(systemTime(), true /* autotimestamp */,
764 HAL_DATASPACE_UNKNOWN, {},
765 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW,
766 0, Fence::NO_FENCE);
767 igbProducer->queueBuffer(slot, input, &qbOutput);
768 adapter.waitForCallbacks();
769 }
770 // capture screen and verify that it is red
771 ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults));
772 // verify we still scale the buffer to the new size (half the screen height)
773 ASSERT_NO_FATAL_FAILURE(
774 checkScreenCapture(r, g, b,
775 {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight / 2}));
776 }
777
TEST_F(BLASTBufferQueueTest,SyncThenNoSync)778 TEST_F(BLASTBufferQueueTest, SyncThenNoSync) {
779 uint8_t r = 255;
780 uint8_t g = 0;
781 uint8_t b = 0;
782
783 BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
784
785 sp<IGraphicBufferProducer> igbProducer;
786 setUpProducer(adapter, igbProducer);
787
788 Transaction next;
789 adapter.setNextTransaction(&next);
790 queueBuffer(igbProducer, 0, 255, 0, 0);
791
792 // queue non sync buffer, so this one should get blocked
793 // Add a present delay to allow the first screenshot to get taken.
794 nsecs_t presentTimeDelay = std::chrono::nanoseconds(500ms).count();
795 queueBuffer(igbProducer, r, g, b, presentTimeDelay);
796
797 CallbackHelper transactionCallback;
798 next.addTransactionCompletedCallback(transactionCallback.function,
799 transactionCallback.getContext())
800 .apply();
801
802 CallbackData callbackData;
803 transactionCallback.getCallbackData(&callbackData);
804
805 // capture screen and verify that it is red
806 ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults));
807 ASSERT_NO_FATAL_FAILURE(
808 checkScreenCapture(0, 255, 0, {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight}));
809
810 mProducerListener->waitOnNumberReleased(1);
811 ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults));
812 ASSERT_NO_FATAL_FAILURE(
813 checkScreenCapture(r, g, b, {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight}));
814 }
815
TEST_F(BLASTBufferQueueTest,MultipleSyncTransactions)816 TEST_F(BLASTBufferQueueTest, MultipleSyncTransactions) {
817 uint8_t r = 255;
818 uint8_t g = 0;
819 uint8_t b = 0;
820
821 BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
822
823 sp<IGraphicBufferProducer> igbProducer;
824 setUpProducer(adapter, igbProducer);
825
826 Transaction mainTransaction;
827
828 Transaction next;
829 adapter.setNextTransaction(&next);
830 queueBuffer(igbProducer, 0, 255, 0, 0);
831
832 mainTransaction.merge(std::move(next));
833
834 adapter.setNextTransaction(&next);
835 queueBuffer(igbProducer, r, g, b, 0);
836
837 mainTransaction.merge(std::move(next));
838 // Expect 1 buffer to be released even before sending to SurfaceFlinger
839 mProducerListener->waitOnNumberReleased(1);
840
841 CallbackHelper transactionCallback;
842 mainTransaction
843 .addTransactionCompletedCallback(transactionCallback.function,
844 transactionCallback.getContext())
845 .apply();
846
847 CallbackData callbackData;
848 transactionCallback.getCallbackData(&callbackData);
849
850 // capture screen and verify that it is red
851 ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults));
852 ASSERT_NO_FATAL_FAILURE(
853 checkScreenCapture(r, g, b, {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight}));
854 }
855
TEST_F(BLASTBufferQueueTest,MultipleSyncTransactionWithNonSync)856 TEST_F(BLASTBufferQueueTest, MultipleSyncTransactionWithNonSync) {
857 uint8_t r = 255;
858 uint8_t g = 0;
859 uint8_t b = 0;
860
861 BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
862
863 sp<IGraphicBufferProducer> igbProducer;
864 setUpProducer(adapter, igbProducer);
865
866 Transaction mainTransaction;
867
868 Transaction next;
869 // queue a sync transaction
870 adapter.setNextTransaction(&next);
871 queueBuffer(igbProducer, 0, 255, 0, 0);
872
873 mainTransaction.merge(std::move(next));
874
875 // queue another buffer without setting next transaction
876 queueBuffer(igbProducer, 0, 0, 255, 0);
877
878 // queue another sync transaction
879 adapter.setNextTransaction(&next);
880 queueBuffer(igbProducer, r, g, b, 0);
881 // Expect 1 buffer to be released because the non sync transaction should merge
882 // with the sync
883 mProducerListener->waitOnNumberReleased(1);
884
885 mainTransaction.merge(std::move(next));
886 // Expect 2 buffers to be released due to merging the two syncs.
887 mProducerListener->waitOnNumberReleased(2);
888
889 CallbackHelper transactionCallback;
890 mainTransaction
891 .addTransactionCompletedCallback(transactionCallback.function,
892 transactionCallback.getContext())
893 .apply();
894
895 CallbackData callbackData;
896 transactionCallback.getCallbackData(&callbackData);
897
898 // capture screen and verify that it is red
899 ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults));
900 ASSERT_NO_FATAL_FAILURE(
901 checkScreenCapture(r, g, b, {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight}));
902 }
903
TEST_F(BLASTBufferQueueTest,MultipleSyncRunOutOfBuffers)904 TEST_F(BLASTBufferQueueTest, MultipleSyncRunOutOfBuffers) {
905 uint8_t r = 255;
906 uint8_t g = 0;
907 uint8_t b = 0;
908
909 BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
910
911 sp<IGraphicBufferProducer> igbProducer;
912 setUpProducer(adapter, igbProducer, 3);
913
914 Transaction mainTransaction;
915
916 Transaction next;
917 // queue a sync transaction
918 adapter.setNextTransaction(&next);
919 queueBuffer(igbProducer, 0, 255, 0, 0);
920
921 mainTransaction.merge(std::move(next));
922
923 // queue a few buffers without setting next transaction
924 queueBuffer(igbProducer, 0, 0, 255, 0);
925 queueBuffer(igbProducer, 0, 0, 255, 0);
926 queueBuffer(igbProducer, 0, 0, 255, 0);
927
928 // queue another sync transaction
929 adapter.setNextTransaction(&next);
930 queueBuffer(igbProducer, r, g, b, 0);
931 // Expect 3 buffers to be released because the non sync transactions should merge
932 // with the sync
933 mProducerListener->waitOnNumberReleased(3);
934
935 mainTransaction.merge(std::move(next));
936 // Expect 4 buffers to be released due to merging the two syncs.
937 mProducerListener->waitOnNumberReleased(4);
938
939 CallbackHelper transactionCallback;
940 mainTransaction
941 .addTransactionCompletedCallback(transactionCallback.function,
942 transactionCallback.getContext())
943 .apply();
944
945 CallbackData callbackData;
946 transactionCallback.getCallbackData(&callbackData);
947
948 // capture screen and verify that it is red
949 ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults));
950 ASSERT_NO_FATAL_FAILURE(
951 checkScreenCapture(r, g, b, {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight}));
952 }
953
954 // Tests BBQ with a sync transaction when the buffers acquired reaches max and the only way to
955 // continue processing is for a release callback from SurfaceFlinger.
956 // This is done by sending a buffer to SF so it can release the previous one and allow BBQ to
957 // continue acquiring buffers.
TEST_F(BLASTBufferQueueTest,RunOutOfBuffersWaitingOnSF)958 TEST_F(BLASTBufferQueueTest, RunOutOfBuffersWaitingOnSF) {
959 uint8_t r = 255;
960 uint8_t g = 0;
961 uint8_t b = 0;
962
963 BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
964
965 sp<IGraphicBufferProducer> igbProducer;
966 setUpProducer(adapter, igbProducer, 4);
967
968 Transaction mainTransaction;
969
970 // Send a buffer to SF
971 queueBuffer(igbProducer, 0, 255, 0, 0);
972
973 Transaction next;
974 // queue a sync transaction
975 adapter.setNextTransaction(&next);
976 queueBuffer(igbProducer, 0, 255, 0, 0);
977
978 mainTransaction.merge(std::move(next));
979
980 // queue a few buffers without setting next transaction
981 queueBuffer(igbProducer, 0, 0, 255, 0);
982 queueBuffer(igbProducer, 0, 0, 255, 0);
983 queueBuffer(igbProducer, 0, 0, 255, 0);
984
985 // apply the first synced buffer to ensure we have to wait on SF
986 mainTransaction.apply();
987
988 // queue another sync transaction
989 adapter.setNextTransaction(&next);
990 queueBuffer(igbProducer, r, g, b, 0);
991 // Expect 2 buffers to be released because the non sync transactions should merge
992 // with the sync
993 mProducerListener->waitOnNumberReleased(3);
994
995 mainTransaction.merge(std::move(next));
996
997 CallbackHelper transactionCallback;
998 mainTransaction
999 .addTransactionCompletedCallback(transactionCallback.function,
1000 transactionCallback.getContext())
1001 .apply();
1002
1003 CallbackData callbackData;
1004 transactionCallback.getCallbackData(&callbackData);
1005
1006 // capture screen and verify that it is red
1007 ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults));
1008 ASSERT_NO_FATAL_FAILURE(
1009 checkScreenCapture(r, g, b, {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight}));
1010 }
1011
1012 class TestProducerListener : public BnProducerListener {
1013 public:
1014 sp<IGraphicBufferProducer> mIgbp;
TestProducerListener(const sp<IGraphicBufferProducer> & igbp)1015 TestProducerListener(const sp<IGraphicBufferProducer>& igbp) : mIgbp(igbp) {}
onBufferReleased()1016 void onBufferReleased() override {
1017 sp<GraphicBuffer> buffer;
1018 sp<Fence> fence;
1019 mIgbp->detachNextBuffer(&buffer, &fence);
1020 }
1021 };
1022
TEST_F(BLASTBufferQueueTest,CustomProducerListener)1023 TEST_F(BLASTBufferQueueTest, CustomProducerListener) {
1024 BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
1025 sp<IGraphicBufferProducer> igbProducer = adapter.getIGraphicBufferProducer();
1026 ASSERT_NE(nullptr, igbProducer.get());
1027 ASSERT_EQ(NO_ERROR, igbProducer->setMaxDequeuedBufferCount(2));
1028 IGraphicBufferProducer::QueueBufferOutput qbOutput;
1029 ASSERT_EQ(NO_ERROR,
1030 igbProducer->connect(new TestProducerListener(igbProducer), NATIVE_WINDOW_API_CPU,
1031 false, &qbOutput));
1032 ASSERT_NE(ui::Transform::ROT_INVALID, qbOutput.transformHint);
1033 for (int i = 0; i < 3; i++) {
1034 int slot;
1035 sp<Fence> fence;
1036 sp<GraphicBuffer> buf;
1037 auto ret = igbProducer->dequeueBuffer(&slot, &fence, mDisplayWidth, mDisplayHeight,
1038 PIXEL_FORMAT_RGBA_8888, GRALLOC_USAGE_SW_WRITE_OFTEN,
1039 nullptr, nullptr);
1040 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, ret);
1041 ASSERT_EQ(OK, igbProducer->requestBuffer(slot, &buf));
1042 IGraphicBufferProducer::QueueBufferOutput qbOutput;
1043 IGraphicBufferProducer::QueueBufferInput input(systemTime(), true /* autotimestamp */,
1044 HAL_DATASPACE_UNKNOWN,
1045 Rect(mDisplayWidth, mDisplayHeight),
1046 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0,
1047 Fence::NO_FENCE);
1048 igbProducer->queueBuffer(slot, input, &qbOutput);
1049 }
1050 adapter.waitForCallbacks();
1051 }
1052
TEST_F(BLASTBufferQueueTest,QueryNativeWindowQueuesToWindowComposer)1053 TEST_F(BLASTBufferQueueTest, QueryNativeWindowQueuesToWindowComposer) {
1054 BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
1055
1056 sp<android::Surface> surface = new Surface(adapter.getIGraphicBufferProducer());
1057 ANativeWindow* nativeWindow = (ANativeWindow*)(surface.get());
1058 int queuesToNativeWindow = 0;
1059 int err = nativeWindow->query(nativeWindow, NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER,
1060 &queuesToNativeWindow);
1061 ASSERT_EQ(NO_ERROR, err);
1062 ASSERT_EQ(queuesToNativeWindow, 1);
1063 }
1064
1065 // Test a slow producer doesn't hold up a faster producer from the same client. Essentially tests
1066 // BBQ uses separate transaction queues.
TEST_F(BLASTBufferQueueTest,OutOfOrderTransactionTest)1067 TEST_F(BLASTBufferQueueTest, OutOfOrderTransactionTest) {
1068 sp<SurfaceControl> bgSurface =
1069 mClient->createSurface(String8("BGTest"), 0, 0, PIXEL_FORMAT_RGBA_8888,
1070 ISurfaceComposerClient::eFXSurfaceBufferState);
1071 ASSERT_NE(nullptr, bgSurface.get());
1072 Transaction t;
1073 t.setLayerStack(bgSurface, 0)
1074 .show(bgSurface)
1075 .setDataspace(bgSurface, ui::Dataspace::V0_SRGB)
1076 .setLayer(bgSurface, std::numeric_limits<int32_t>::max() - 1)
1077 .apply();
1078
1079 BLASTBufferQueueHelper slowAdapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
1080 sp<IGraphicBufferProducer> slowIgbProducer;
1081 setUpProducer(slowAdapter, slowIgbProducer);
1082 nsecs_t presentTimeDelay = std::chrono::nanoseconds(500ms).count();
1083 queueBuffer(slowIgbProducer, 0 /* r */, 255 /* g */, 0 /* b */, presentTimeDelay);
1084
1085 BLASTBufferQueueHelper fastAdapter(bgSurface, mDisplayWidth, mDisplayHeight);
1086 sp<IGraphicBufferProducer> fastIgbProducer;
1087 setUpProducer(fastAdapter, fastIgbProducer);
1088 uint8_t r = 255;
1089 uint8_t g = 0;
1090 uint8_t b = 0;
1091 queueBuffer(fastIgbProducer, r, g, b, 0 /* presentTimeDelay */);
1092 fastAdapter.waitForCallbacks();
1093
1094 // capture screen and verify that it is red
1095 ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults));
1096
1097 ASSERT_NO_FATAL_FAILURE(
1098 checkScreenCapture(r, g, b,
1099 {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight / 2}));
1100 }
1101
TEST_F(BLASTBufferQueueTest,TransformHint)1102 TEST_F(BLASTBufferQueueTest, TransformHint) {
1103 // Transform hint is provided to BBQ via the surface control passed by WM
1104 mSurfaceControl->setTransformHint(ui::Transform::ROT_90);
1105
1106 BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
1107 sp<IGraphicBufferProducer> igbProducer = adapter.getIGraphicBufferProducer();
1108 ASSERT_NE(nullptr, igbProducer.get());
1109 ASSERT_EQ(NO_ERROR, igbProducer->setMaxDequeuedBufferCount(2));
1110 sp<Surface> surface = adapter.getSurface();
1111
1112 // Before connecting to the surface, we do not get a valid transform hint
1113 int transformHint;
1114 surface->query(NATIVE_WINDOW_TRANSFORM_HINT, &transformHint);
1115 ASSERT_EQ(ui::Transform::ROT_0, transformHint);
1116
1117 ASSERT_EQ(NO_ERROR,
1118 surface->connect(NATIVE_WINDOW_API_CPU, new TestProducerListener(igbProducer)));
1119
1120 // After connecting to the surface, we should get the correct hint.
1121 surface->query(NATIVE_WINDOW_TRANSFORM_HINT, &transformHint);
1122 ASSERT_EQ(ui::Transform::ROT_90, transformHint);
1123
1124 ANativeWindow_Buffer buffer;
1125 surface->lock(&buffer, nullptr /* inOutDirtyBounds */);
1126
1127 // Transform hint is updated via callbacks or surface control updates
1128 mSurfaceControl->setTransformHint(ui::Transform::ROT_0);
1129 adapter.update(mSurfaceControl, mDisplayWidth, mDisplayHeight);
1130
1131 // The hint does not change and matches the value used when dequeueing the buffer.
1132 surface->query(NATIVE_WINDOW_TRANSFORM_HINT, &transformHint);
1133 ASSERT_EQ(ui::Transform::ROT_90, transformHint);
1134
1135 surface->unlockAndPost();
1136
1137 // After queuing the buffer, we get the updated transform hint
1138 surface->query(NATIVE_WINDOW_TRANSFORM_HINT, &transformHint);
1139 ASSERT_EQ(ui::Transform::ROT_0, transformHint);
1140
1141 adapter.waitForCallbacks();
1142 }
1143
1144 class BLASTBufferQueueTransformTest : public BLASTBufferQueueTest {
1145 public:
test(uint32_t tr)1146 void test(uint32_t tr) {
1147 BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
1148 sp<IGraphicBufferProducer> igbProducer;
1149 setUpProducer(adapter, igbProducer);
1150
1151 auto bufWidth = mDisplayWidth;
1152 auto bufHeight = mDisplayHeight;
1153 int slot;
1154 sp<Fence> fence;
1155 sp<GraphicBuffer> buf;
1156
1157 auto ret = igbProducer->dequeueBuffer(&slot, &fence, bufWidth, bufHeight,
1158 PIXEL_FORMAT_RGBA_8888, GRALLOC_USAGE_SW_WRITE_OFTEN,
1159 nullptr, nullptr);
1160 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, ret);
1161 ASSERT_EQ(OK, igbProducer->requestBuffer(slot, &buf));
1162
1163 fillQuadrants(buf);
1164
1165 IGraphicBufferProducer::QueueBufferOutput qbOutput;
1166 IGraphicBufferProducer::QueueBufferInput input(systemTime(), true /* autotimestamp */,
1167 HAL_DATASPACE_UNKNOWN,
1168 Rect(bufWidth, bufHeight),
1169 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW,
1170 tr, Fence::NO_FENCE);
1171 igbProducer->queueBuffer(slot, input, &qbOutput);
1172 ASSERT_NE(ui::Transform::ROT_INVALID, qbOutput.transformHint);
1173
1174 adapter.waitForCallbacks();
1175 ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults));
1176
1177 switch (tr) {
1178 case ui::Transform::ROT_0:
1179 ASSERT_NO_FATAL_FAILURE(checkScreenCapture(0, 0, 0,
1180 {0, 0, (int32_t)mDisplayWidth / 2,
1181 (int32_t)mDisplayHeight / 2},
1182 1));
1183 ASSERT_NO_FATAL_FAILURE(
1184 checkScreenCapture(255, 0, 0,
1185 {(int32_t)mDisplayWidth / 2, 0, (int32_t)mDisplayWidth,
1186 (int32_t)mDisplayHeight / 2},
1187 1));
1188 ASSERT_NO_FATAL_FAILURE(
1189 checkScreenCapture(0, 255, 0,
1190 {(int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight / 2,
1191 (int32_t)mDisplayWidth, (int32_t)mDisplayHeight},
1192 1));
1193 ASSERT_NO_FATAL_FAILURE(
1194 checkScreenCapture(0, 0, 255,
1195 {0, (int32_t)mDisplayHeight / 2,
1196 (int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight},
1197 1));
1198 break;
1199 case ui::Transform::FLIP_H:
1200 ASSERT_NO_FATAL_FAILURE(checkScreenCapture(255, 0, 0,
1201 {0, 0, (int32_t)mDisplayWidth / 2,
1202 (int32_t)mDisplayHeight / 2},
1203 1));
1204 ASSERT_NO_FATAL_FAILURE(
1205 checkScreenCapture(0, 0, 0,
1206 {(int32_t)mDisplayWidth / 2, 0, (int32_t)mDisplayWidth,
1207 (int32_t)mDisplayHeight / 2},
1208 1));
1209 ASSERT_NO_FATAL_FAILURE(
1210 checkScreenCapture(0, 0, 255,
1211 {(int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight / 2,
1212 (int32_t)mDisplayWidth, (int32_t)mDisplayHeight},
1213 1));
1214 ASSERT_NO_FATAL_FAILURE(
1215 checkScreenCapture(0, 255, 0,
1216 {0, (int32_t)mDisplayHeight / 2,
1217 (int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight},
1218 1));
1219 break;
1220 case ui::Transform::FLIP_V:
1221 ASSERT_NO_FATAL_FAILURE(checkScreenCapture(0, 0, 255,
1222 {0, 0, (int32_t)mDisplayWidth / 2,
1223 (int32_t)mDisplayHeight / 2},
1224 1));
1225 ASSERT_NO_FATAL_FAILURE(
1226 checkScreenCapture(0, 255, 0,
1227 {(int32_t)mDisplayWidth / 2, 0, (int32_t)mDisplayWidth,
1228 (int32_t)mDisplayHeight / 2},
1229 1));
1230 ASSERT_NO_FATAL_FAILURE(
1231 checkScreenCapture(255, 0, 0,
1232 {(int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight / 2,
1233 (int32_t)mDisplayWidth, (int32_t)mDisplayHeight},
1234 1));
1235 ASSERT_NO_FATAL_FAILURE(
1236 checkScreenCapture(0, 0, 0,
1237 {0, (int32_t)mDisplayHeight / 2,
1238 (int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight},
1239 1));
1240 break;
1241 case ui::Transform::ROT_90:
1242 ASSERT_NO_FATAL_FAILURE(checkScreenCapture(0, 0, 255,
1243 {0, 0, (int32_t)mDisplayWidth / 2,
1244 (int32_t)mDisplayHeight / 2},
1245 1));
1246 ASSERT_NO_FATAL_FAILURE(
1247 checkScreenCapture(0, 0, 0,
1248 {(int32_t)mDisplayWidth / 2, 0, (int32_t)mDisplayWidth,
1249 (int32_t)mDisplayHeight / 2},
1250 1));
1251 ASSERT_NO_FATAL_FAILURE(
1252 checkScreenCapture(255, 0, 0,
1253 {(int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight / 2,
1254 (int32_t)mDisplayWidth, (int32_t)mDisplayHeight},
1255 1));
1256 ASSERT_NO_FATAL_FAILURE(
1257 checkScreenCapture(0, 255, 0,
1258 {0, (int32_t)mDisplayHeight / 2,
1259 (int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight},
1260 1));
1261 break;
1262 case ui::Transform::ROT_180:
1263 ASSERT_NO_FATAL_FAILURE(checkScreenCapture(0, 255, 0,
1264 {0, 0, (int32_t)mDisplayWidth / 2,
1265 (int32_t)mDisplayHeight / 2},
1266 1));
1267 ASSERT_NO_FATAL_FAILURE(
1268 checkScreenCapture(0, 0, 255,
1269 {(int32_t)mDisplayWidth / 2, 0, (int32_t)mDisplayWidth,
1270 (int32_t)mDisplayHeight / 2},
1271 1));
1272 ASSERT_NO_FATAL_FAILURE(
1273 checkScreenCapture(0, 0, 0,
1274 {(int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight / 2,
1275 (int32_t)mDisplayWidth, (int32_t)mDisplayHeight},
1276 1));
1277 ASSERT_NO_FATAL_FAILURE(
1278 checkScreenCapture(255, 0, 0,
1279 {0, (int32_t)mDisplayHeight / 2,
1280 (int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight},
1281 1));
1282 break;
1283 case ui::Transform::ROT_270:
1284 ASSERT_NO_FATAL_FAILURE(checkScreenCapture(255, 0, 0,
1285 {0, 0, (int32_t)mDisplayWidth / 2,
1286 (int32_t)mDisplayHeight / 2},
1287 1));
1288 ASSERT_NO_FATAL_FAILURE(
1289 checkScreenCapture(0, 255, 0,
1290 {(int32_t)mDisplayWidth / 2, 0, (int32_t)mDisplayWidth,
1291 (int32_t)mDisplayHeight / 2},
1292 1));
1293 ASSERT_NO_FATAL_FAILURE(
1294 checkScreenCapture(0, 0, 255,
1295 {(int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight / 2,
1296 (int32_t)mDisplayWidth, (int32_t)mDisplayHeight},
1297 1));
1298 ASSERT_NO_FATAL_FAILURE(
1299 checkScreenCapture(0, 0, 0,
1300 {0, (int32_t)mDisplayHeight / 2,
1301 (int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight},
1302 1));
1303 }
1304 }
1305 };
1306
TEST_F(BLASTBufferQueueTransformTest,setTransform_ROT_0)1307 TEST_F(BLASTBufferQueueTransformTest, setTransform_ROT_0) {
1308 test(ui::Transform::ROT_0);
1309 }
1310
TEST_F(BLASTBufferQueueTransformTest,setTransform_FLIP_H)1311 TEST_F(BLASTBufferQueueTransformTest, setTransform_FLIP_H) {
1312 test(ui::Transform::FLIP_H);
1313 }
1314
TEST_F(BLASTBufferQueueTransformTest,setTransform_FLIP_V)1315 TEST_F(BLASTBufferQueueTransformTest, setTransform_FLIP_V) {
1316 test(ui::Transform::FLIP_V);
1317 }
1318
TEST_F(BLASTBufferQueueTransformTest,setTransform_ROT_90)1319 TEST_F(BLASTBufferQueueTransformTest, setTransform_ROT_90) {
1320 test(ui::Transform::ROT_90);
1321 }
1322
TEST_F(BLASTBufferQueueTransformTest,setTransform_ROT_180)1323 TEST_F(BLASTBufferQueueTransformTest, setTransform_ROT_180) {
1324 test(ui::Transform::ROT_180);
1325 }
1326
TEST_F(BLASTBufferQueueTransformTest,setTransform_ROT_270)1327 TEST_F(BLASTBufferQueueTransformTest, setTransform_ROT_270) {
1328 test(ui::Transform::ROT_270);
1329 }
1330
1331 class BLASTFrameEventHistoryTest : public BLASTBufferQueueTest {
1332 public:
setUpAndQueueBuffer(const sp<IGraphicBufferProducer> & igbProducer,nsecs_t * outRequestedPresentTime,nsecs_t * postedTime,IGraphicBufferProducer::QueueBufferOutput * qbOutput,bool getFrameTimestamps,nsecs_t requestedPresentTime=systemTime ())1333 void setUpAndQueueBuffer(const sp<IGraphicBufferProducer>& igbProducer,
1334 nsecs_t* outRequestedPresentTime, nsecs_t* postedTime,
1335 IGraphicBufferProducer::QueueBufferOutput* qbOutput,
1336 bool getFrameTimestamps, nsecs_t requestedPresentTime = systemTime()) {
1337 int slot;
1338 sp<Fence> fence;
1339 sp<GraphicBuffer> buf;
1340 auto ret = igbProducer->dequeueBuffer(&slot, &fence, mDisplayWidth, mDisplayHeight,
1341 PIXEL_FORMAT_RGBA_8888, GRALLOC_USAGE_SW_WRITE_OFTEN,
1342 nullptr, nullptr);
1343 if (IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION == ret) {
1344 ASSERT_EQ(OK, igbProducer->requestBuffer(slot, &buf));
1345 }
1346
1347 *outRequestedPresentTime = requestedPresentTime;
1348 IGraphicBufferProducer::QueueBufferInput input(requestedPresentTime, false,
1349 HAL_DATASPACE_UNKNOWN,
1350 Rect(mDisplayWidth, mDisplayHeight),
1351 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0,
1352 Fence::NO_FENCE, /*sticky*/ 0,
1353 getFrameTimestamps);
1354 if (postedTime) *postedTime = systemTime();
1355 igbProducer->queueBuffer(slot, input, qbOutput);
1356 }
1357 sp<SurfaceControl> mBufferQueueSurfaceControl;
1358 };
1359
TEST_F(BLASTFrameEventHistoryTest,FrameEventHistory_Basic)1360 TEST_F(BLASTFrameEventHistoryTest, FrameEventHistory_Basic) {
1361 BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
1362 sp<IGraphicBufferProducer> igbProducer;
1363 ProducerFrameEventHistory history;
1364 setUpProducer(adapter, igbProducer);
1365
1366 IGraphicBufferProducer::QueueBufferOutput qbOutput;
1367 nsecs_t requestedPresentTimeA = 0;
1368 nsecs_t postedTimeA = 0;
1369 adapter.setTransactionCompleteCallback(1);
1370 setUpAndQueueBuffer(igbProducer, &requestedPresentTimeA, &postedTimeA, &qbOutput, true);
1371 history.applyDelta(qbOutput.frameTimestamps);
1372
1373 FrameEvents* events = nullptr;
1374 events = history.getFrame(1);
1375 ASSERT_NE(nullptr, events);
1376 ASSERT_EQ(1, events->frameNumber);
1377 ASSERT_EQ(requestedPresentTimeA, events->requestedPresentTime);
1378 ASSERT_GE(events->postedTime, postedTimeA);
1379
1380 adapter.waitForCallback(1);
1381
1382 // queue another buffer so we query for frame event deltas
1383 nsecs_t requestedPresentTimeB = 0;
1384 nsecs_t postedTimeB = 0;
1385 setUpAndQueueBuffer(igbProducer, &requestedPresentTimeB, &postedTimeB, &qbOutput, true);
1386 history.applyDelta(qbOutput.frameTimestamps);
1387 events = history.getFrame(1);
1388 ASSERT_NE(nullptr, events);
1389
1390 // frame number, requestedPresentTime, and postTime should not have changed
1391 ASSERT_EQ(1, events->frameNumber);
1392 ASSERT_EQ(requestedPresentTimeA, events->requestedPresentTime);
1393 ASSERT_GE(events->postedTime, postedTimeA);
1394
1395 ASSERT_GE(events->latchTime, postedTimeA);
1396 ASSERT_GE(events->dequeueReadyTime, events->latchTime);
1397 ASSERT_NE(nullptr, events->gpuCompositionDoneFence);
1398 ASSERT_NE(nullptr, events->displayPresentFence);
1399 ASSERT_NE(nullptr, events->releaseFence);
1400
1401 // we should also have gotten the initial values for the next frame
1402 events = history.getFrame(2);
1403 ASSERT_NE(nullptr, events);
1404 ASSERT_EQ(2, events->frameNumber);
1405 ASSERT_EQ(requestedPresentTimeB, events->requestedPresentTime);
1406 ASSERT_GE(events->postedTime, postedTimeB);
1407
1408 // wait for any callbacks that have not been received
1409 adapter.waitForCallbacks();
1410 }
1411
TEST_F(BLASTFrameEventHistoryTest,FrameEventHistory_DroppedFrame)1412 TEST_F(BLASTFrameEventHistoryTest, FrameEventHistory_DroppedFrame) {
1413 BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
1414 sp<IGraphicBufferProducer> igbProducer;
1415 setUpProducer(adapter, igbProducer);
1416
1417 ProducerFrameEventHistory history;
1418 IGraphicBufferProducer::QueueBufferOutput qbOutput;
1419 nsecs_t requestedPresentTimeA = 0;
1420 nsecs_t postedTimeA = 0;
1421 // Present the frame sometime in the future so we can add two frames to the queue so the older
1422 // one will be dropped.
1423 nsecs_t presentTime = systemTime() + std::chrono::nanoseconds(500ms).count();
1424 setUpAndQueueBuffer(igbProducer, &requestedPresentTimeA, &postedTimeA, &qbOutput, true,
1425 presentTime);
1426 history.applyDelta(qbOutput.frameTimestamps);
1427
1428 FrameEvents* events = nullptr;
1429 events = history.getFrame(1);
1430 ASSERT_NE(nullptr, events);
1431 ASSERT_EQ(1, events->frameNumber);
1432 ASSERT_EQ(requestedPresentTimeA, events->requestedPresentTime);
1433 ASSERT_GE(events->postedTime, postedTimeA);
1434
1435 // queue another buffer so the first can be dropped
1436 nsecs_t requestedPresentTimeB = 0;
1437 nsecs_t postedTimeB = 0;
1438 adapter.setTransactionCompleteCallback(2);
1439 presentTime = systemTime() + std::chrono::nanoseconds(1ms).count();
1440 setUpAndQueueBuffer(igbProducer, &requestedPresentTimeB, &postedTimeB, &qbOutput, true,
1441 presentTime);
1442 history.applyDelta(qbOutput.frameTimestamps);
1443 events = history.getFrame(1);
1444 ASSERT_NE(nullptr, events);
1445
1446 // frame number, requestedPresentTime, and postTime should not have changed
1447 ASSERT_EQ(1, events->frameNumber);
1448 ASSERT_EQ(requestedPresentTimeA, events->requestedPresentTime);
1449 ASSERT_GE(events->postedTime, postedTimeA);
1450
1451 // a valid latchtime and pre and post composition info should not be set for the dropped frame
1452 ASSERT_FALSE(events->hasLatchInfo());
1453 ASSERT_FALSE(events->hasDequeueReadyInfo());
1454 ASSERT_FALSE(events->hasGpuCompositionDoneInfo());
1455 ASSERT_FALSE(events->hasDisplayPresentInfo());
1456 ASSERT_FALSE(events->hasReleaseInfo());
1457
1458 // wait for the last transaction to be completed.
1459 adapter.waitForCallback(2);
1460
1461 // queue another buffer so we query for frame event deltas
1462 nsecs_t requestedPresentTimeC = 0;
1463 nsecs_t postedTimeC = 0;
1464 setUpAndQueueBuffer(igbProducer, &requestedPresentTimeC, &postedTimeC, &qbOutput, true);
1465 history.applyDelta(qbOutput.frameTimestamps);
1466
1467 // frame number, requestedPresentTime, and postTime should not have changed
1468 ASSERT_EQ(1, events->frameNumber);
1469 ASSERT_EQ(requestedPresentTimeA, events->requestedPresentTime);
1470 ASSERT_GE(events->postedTime, postedTimeA);
1471
1472 // a valid latchtime and pre and post composition info should not be set for the dropped frame
1473 ASSERT_FALSE(events->hasLatchInfo());
1474 ASSERT_FALSE(events->hasDequeueReadyInfo());
1475 ASSERT_FALSE(events->hasGpuCompositionDoneInfo());
1476 ASSERT_FALSE(events->hasDisplayPresentInfo());
1477 ASSERT_FALSE(events->hasReleaseInfo());
1478
1479 // we should also have gotten values for the presented frame
1480 events = history.getFrame(2);
1481 ASSERT_NE(nullptr, events);
1482 ASSERT_EQ(2, events->frameNumber);
1483 ASSERT_EQ(requestedPresentTimeB, events->requestedPresentTime);
1484 ASSERT_GE(events->postedTime, postedTimeB);
1485 ASSERT_GE(events->latchTime, postedTimeB);
1486 ASSERT_GE(events->dequeueReadyTime, events->latchTime);
1487 ASSERT_NE(nullptr, events->gpuCompositionDoneFence);
1488 ASSERT_NE(nullptr, events->displayPresentFence);
1489 ASSERT_NE(nullptr, events->releaseFence);
1490
1491 // wait for any callbacks that have not been received
1492 adapter.waitForCallbacks();
1493 }
1494
TEST_F(BLASTFrameEventHistoryTest,FrameEventHistory_CompositorTimings)1495 TEST_F(BLASTFrameEventHistoryTest, FrameEventHistory_CompositorTimings) {
1496 BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
1497 sp<IGraphicBufferProducer> igbProducer;
1498 ProducerFrameEventHistory history;
1499 setUpProducer(adapter, igbProducer);
1500
1501 IGraphicBufferProducer::QueueBufferOutput qbOutput;
1502 nsecs_t requestedPresentTimeA = 0;
1503 nsecs_t postedTimeA = 0;
1504 adapter.setTransactionCompleteCallback(1);
1505 setUpAndQueueBuffer(igbProducer, &requestedPresentTimeA, &postedTimeA, &qbOutput, true);
1506 history.applyDelta(qbOutput.frameTimestamps);
1507 adapter.waitForCallback(1);
1508
1509 // queue another buffer so we query for frame event deltas
1510 nsecs_t requestedPresentTimeB = 0;
1511 nsecs_t postedTimeB = 0;
1512 setUpAndQueueBuffer(igbProducer, &requestedPresentTimeB, &postedTimeB, &qbOutput, true);
1513 history.applyDelta(qbOutput.frameTimestamps);
1514
1515 // check for a valid compositor deadline
1516 ASSERT_NE(0, history.getReportedCompositeDeadline());
1517
1518 // wait for any callbacks that have not been received
1519 adapter.waitForCallbacks();
1520 }
1521
1522 } // namespace android
1523