1 /* 2 * Copyright (C) 2012 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 "CpuConsumer_test" 18 //#define LOG_NDEBUG 0 19 //#define LOG_NNDEBUG 0 20 21 #ifdef LOG_NNDEBUG 22 #define ALOGVV(...) ALOGV(__VA_ARGS__) 23 #else 24 #define ALOGVV(...) ((void)0) 25 #endif 26 27 #include <gtest/gtest.h> 28 #include <gui/CpuConsumer.h> 29 #include <gui/SurfaceTextureClient.h> 30 #include <ui/GraphicBuffer.h> 31 #include <utils/String8.h> 32 #include <utils/Thread.h> 33 #include <utils/Mutex.h> 34 #include <utils/Condition.h> 35 36 #include <ui/FramebufferNativeWindow.h> 37 38 namespace android { 39 40 struct CpuConsumerTestParams { 41 uint32_t width; 42 uint32_t height; 43 int maxLockedBuffers; 44 PixelFormat format; 45 }; 46 47 ::std::ostream& operator<<(::std::ostream& os, const CpuConsumerTestParams& p) { 48 return os << "[ (" << p.width << ", " << p.height << "), B:" 49 << p.maxLockedBuffers << ", F:0x" 50 << ::std::hex << p.format << "]"; 51 } 52 53 class CpuConsumerTest : public ::testing::TestWithParam<CpuConsumerTestParams> { 54 protected: 55 56 virtual void SetUp() { 57 const ::testing::TestInfo* const test_info = 58 ::testing::UnitTest::GetInstance()->current_test_info(); 59 CpuConsumerTestParams params = GetParam(); 60 ALOGV("** Starting test %s (%d x %d, %d, 0x%x)", 61 test_info->name(), 62 params.width, params.height, 63 params.maxLockedBuffers, params.format); 64 mCC = new CpuConsumer(params.maxLockedBuffers); 65 String8 name("CpuConsumer_Under_Test"); 66 mCC->setName(name); 67 mSTC = new SurfaceTextureClient(mCC->getProducerInterface()); 68 mANW = mSTC; 69 } 70 71 virtual void TearDown() { 72 mANW.clear(); 73 mSTC.clear(); 74 mCC.clear(); 75 } 76 77 class FrameWaiter : public CpuConsumer::FrameAvailableListener { 78 public: 79 FrameWaiter(): 80 mPendingFrames(0) { 81 } 82 83 void waitForFrame() { 84 Mutex::Autolock lock(mMutex); 85 while (mPendingFrames == 0) { 86 mCondition.wait(mMutex); 87 } 88 mPendingFrames--; 89 } 90 91 virtual void onFrameAvailable() { 92 Mutex::Autolock lock(mMutex); 93 mPendingFrames++; 94 mCondition.signal(); 95 } 96 97 int mPendingFrames; 98 Mutex mMutex; 99 Condition mCondition; 100 }; 101 102 // Note that SurfaceTexture will lose the notifications 103 // onBuffersReleased and onFrameAvailable as there is currently 104 // no way to forward the events. This DisconnectWaiter will not let the 105 // disconnect finish until finishDisconnect() is called. It will 106 // also block until a disconnect is called 107 class DisconnectWaiter : public BufferQueue::ConsumerListener { 108 public: 109 DisconnectWaiter () : 110 mWaitForDisconnect(false), 111 mPendingFrames(0) { 112 } 113 114 void waitForFrame() { 115 Mutex::Autolock lock(mMutex); 116 while (mPendingFrames == 0) { 117 mFrameCondition.wait(mMutex); 118 } 119 mPendingFrames--; 120 } 121 122 virtual void onFrameAvailable() { 123 Mutex::Autolock lock(mMutex); 124 mPendingFrames++; 125 mFrameCondition.signal(); 126 } 127 128 virtual void onBuffersReleased() { 129 Mutex::Autolock lock(mMutex); 130 while (!mWaitForDisconnect) { 131 mDisconnectCondition.wait(mMutex); 132 } 133 } 134 135 void finishDisconnect() { 136 Mutex::Autolock lock(mMutex); 137 mWaitForDisconnect = true; 138 mDisconnectCondition.signal(); 139 } 140 141 private: 142 Mutex mMutex; 143 144 bool mWaitForDisconnect; 145 Condition mDisconnectCondition; 146 147 int mPendingFrames; 148 Condition mFrameCondition; 149 }; 150 151 sp<CpuConsumer> mCC; 152 sp<SurfaceTextureClient> mSTC; 153 sp<ANativeWindow> mANW; 154 }; 155 156 #define ASSERT_NO_ERROR(err, msg) \ 157 ASSERT_EQ(NO_ERROR, err) << msg << strerror(-err) 158 159 void checkPixel(const CpuConsumer::LockedBuffer &buf, 160 uint32_t x, uint32_t y, uint32_t r, uint32_t g, uint32_t b) { 161 // Ignores components that don't exist for given pixel 162 switch(buf.format) { 163 case HAL_PIXEL_FORMAT_RAW_SENSOR: { 164 String8 msg; 165 uint16_t *bPtr = (uint16_t*)buf.data; 166 bPtr += y * buf.stride + x; 167 // GRBG Bayer mosaic; only check the matching channel 168 switch( ((y & 1) << 1) | (x & 1) ) { 169 case 0: // G 170 case 3: // G 171 EXPECT_EQ(g, *bPtr); 172 break; 173 case 1: // R 174 EXPECT_EQ(r, *bPtr); 175 break; 176 case 2: // B 177 EXPECT_EQ(b, *bPtr); 178 break; 179 } 180 break; 181 } 182 default: { 183 ADD_FAILURE() << "Unknown format for check:" << buf.format; 184 break; 185 } 186 } 187 } 188 189 // Fill a YV12 buffer with a multi-colored checkerboard pattern 190 void fillYV12Buffer(uint8_t* buf, int w, int h, int stride); 191 192 // Fill a RAW sensor buffer with a multi-colored checkerboard pattern. 193 // Assumes GRBG mosaic ordering. Result should be a grid in a 2x2 pattern 194 // of [ R, B; G, W] 195 void fillBayerRawBuffer(uint8_t* buf, int w, int h, int stride) { 196 ALOGVV("fillBayerRawBuffer: %p with %d x %d, stride %d", buf, w, h ,stride); 197 // Blocks need to be even-width/height, aim for 8-wide otherwise 198 const int blockWidth = (w > 16 ? w / 8 : 2) & ~0x1; 199 const int blockHeight = (h > 16 ? h / 8 : 2) & ~0x1; 200 for (int y = 0; y < h; y+=2) { 201 uint16_t *bPtr1 = ((uint16_t*)buf) + stride*y; 202 uint16_t *bPtr2 = bPtr1 + stride; 203 for (int x = 0; x < w; x+=2) { 204 int blockX = (x / blockWidth ) & 1; 205 int blockY = (y / blockHeight) & 1; 206 unsigned short r = (blockX == blockY) ? 1000 : 200; 207 unsigned short g = blockY ? 1000: 200; 208 unsigned short b = blockX ? 1000: 200; 209 // GR row 210 *bPtr1++ = g; 211 *bPtr1++ = r; 212 // BG row 213 *bPtr2++ = b; 214 *bPtr2++ = g; 215 } 216 } 217 218 } 219 220 void checkBayerRawBuffer(const CpuConsumer::LockedBuffer &buf) { 221 uint32_t w = buf.width; 222 uint32_t h = buf.height; 223 const int blockWidth = (w > 16 ? w / 8 : 2) & ~0x1; 224 const int blockHeight = (h > 16 ? h / 8 : 2) & ~0x1; 225 const int blockRows = h / blockHeight; 226 const int blockCols = w / blockWidth; 227 228 // Top-left square is red 229 checkPixel(buf, 0, 0, 1000, 200, 200); 230 checkPixel(buf, 1, 0, 1000, 200, 200); 231 checkPixel(buf, 0, 1, 1000, 200, 200); 232 checkPixel(buf, 1, 1, 1000, 200, 200); 233 234 // One-right square is blue 235 checkPixel(buf, blockWidth, 0, 200, 200, 1000); 236 checkPixel(buf, blockWidth + 1, 0, 200, 200, 1000); 237 checkPixel(buf, blockWidth, 1, 200, 200, 1000); 238 checkPixel(buf, blockWidth + 1, 1, 200, 200, 1000); 239 240 // One-down square is green 241 checkPixel(buf, 0, blockHeight, 200, 1000, 200); 242 checkPixel(buf, 1, blockHeight, 200, 1000, 200); 243 checkPixel(buf, 0, blockHeight + 1, 200, 1000, 200); 244 checkPixel(buf, 1, blockHeight + 1, 200, 1000, 200); 245 246 // One-diag square is white 247 checkPixel(buf, blockWidth, blockHeight, 1000, 1000, 1000); 248 checkPixel(buf, blockWidth + 1, blockHeight, 1000, 1000, 1000); 249 checkPixel(buf, blockWidth, blockHeight + 1, 1000, 1000, 1000); 250 checkPixel(buf, blockWidth + 1, blockHeight + 1, 1000, 1000, 1000); 251 252 // Test bottom-right pixel 253 const int maxBlockX = ((w-1) / blockWidth) & 0x1; 254 const int maxBlockY = ((w-1) / blockHeight) & 0x1; 255 unsigned short maxR = (maxBlockX == maxBlockY) ? 1000 : 200; 256 unsigned short maxG = maxBlockY ? 1000: 200; 257 unsigned short maxB = maxBlockX ? 1000: 200; 258 checkPixel(buf, w-1, h-1, maxR, maxG, maxB); 259 } 260 261 void fillYV12BufferRect(uint8_t* buf, int w, int h, int stride, 262 const android_native_rect_t& rect); 263 264 void fillRGBA8Buffer(uint8_t* buf, int w, int h, int stride); 265 266 void fillRGBA8BufferSolid(uint8_t* buf, int w, int h, int stride, uint8_t r, 267 uint8_t g, uint8_t b, uint8_t a); 268 269 // Configures the ANativeWindow producer-side interface based on test parameters 270 void configureANW(const sp<ANativeWindow>& anw, 271 const CpuConsumerTestParams& params, 272 int maxBufferSlack) { 273 status_t err; 274 err = native_window_set_buffers_geometry(anw.get(), 275 params.width, params.height, params.format); 276 ASSERT_NO_ERROR(err, "set_buffers_geometry error: "); 277 278 err = native_window_set_usage(anw.get(), 279 GRALLOC_USAGE_SW_WRITE_OFTEN); 280 ASSERT_NO_ERROR(err, "set_usage error: "); 281 282 int minUndequeuedBuffers; 283 err = anw.get()->query(anw.get(), 284 NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, 285 &minUndequeuedBuffers); 286 ASSERT_NO_ERROR(err, "query error: "); 287 288 ALOGVV("Setting buffer count to %d", 289 maxBufferSlack + 1 + minUndequeuedBuffers); 290 err = native_window_set_buffer_count(anw.get(), 291 maxBufferSlack + 1 + minUndequeuedBuffers); 292 ASSERT_NO_ERROR(err, "set_buffer_count error: "); 293 294 } 295 296 // Produce one frame of image data; assumes format and resolution configuration 297 // is already done. 298 void produceOneFrame(const sp<ANativeWindow>& anw, 299 const CpuConsumerTestParams& params, 300 int64_t timestamp, uint32_t *stride) { 301 status_t err; 302 ANativeWindowBuffer* anb; 303 ALOGVV("Dequeue buffer from %p", anw.get()); 304 err = native_window_dequeue_buffer_and_wait(anw.get(), &anb); 305 ASSERT_NO_ERROR(err, "dequeueBuffer error: "); 306 307 ASSERT_TRUE(anb != NULL); 308 309 sp<GraphicBuffer> buf(new GraphicBuffer(anb, false)); 310 311 *stride = buf->getStride(); 312 uint8_t* img = NULL; 313 314 ALOGVV("Lock buffer from %p for write", anw.get()); 315 err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); 316 ASSERT_NO_ERROR(err, "lock error: "); 317 318 switch (params.format) { 319 case HAL_PIXEL_FORMAT_YV12: 320 fillYV12Buffer(img, params.width, params.height, *stride); 321 break; 322 case HAL_PIXEL_FORMAT_RAW_SENSOR: 323 fillBayerRawBuffer(img, params.width, params.height, buf->getStride()); 324 break; 325 default: 326 FAIL() << "Unknown pixel format under test!"; 327 break; 328 } 329 ALOGVV("Unlock buffer from %p", anw.get()); 330 err = buf->unlock(); 331 ASSERT_NO_ERROR(err, "unlock error: "); 332 333 ALOGVV("Set timestamp to %p", anw.get()); 334 err = native_window_set_buffers_timestamp(anw.get(), timestamp); 335 ASSERT_NO_ERROR(err, "set_buffers_timestamp error: "); 336 337 ALOGVV("Queue buffer to %p", anw.get()); 338 err = anw->queueBuffer(anw.get(), buf->getNativeBuffer(), -1); 339 ASSERT_NO_ERROR(err, "queueBuffer error:"); 340 }; 341 342 // This test is disabled because the HAL_PIXEL_FORMAT_RAW_SENSOR format is not 343 // supported on all devices. 344 TEST_P(CpuConsumerTest, DISABLED_FromCpuSingle) { 345 status_t err; 346 CpuConsumerTestParams params = GetParam(); 347 348 // Set up 349 350 ASSERT_NO_FATAL_FAILURE(configureANW(mANW, params, 1)); 351 352 // Produce 353 354 const int64_t time = 12345678L; 355 uint32_t stride; 356 ASSERT_NO_FATAL_FAILURE(produceOneFrame(mANW, params, time, 357 &stride)); 358 359 // Consume 360 361 CpuConsumer::LockedBuffer b; 362 err = mCC->lockNextBuffer(&b); 363 ASSERT_NO_ERROR(err, "getNextBuffer error: "); 364 365 ASSERT_TRUE(b.data != NULL); 366 EXPECT_EQ(params.width, b.width); 367 EXPECT_EQ(params.height, b.height); 368 EXPECT_EQ(params.format, b.format); 369 EXPECT_EQ(stride, b.stride); 370 EXPECT_EQ(time, b.timestamp); 371 372 checkBayerRawBuffer(b); 373 mCC->unlockBuffer(b); 374 } 375 376 // This test is disabled because the HAL_PIXEL_FORMAT_RAW_SENSOR format is not 377 // supported on all devices. 378 TEST_P(CpuConsumerTest, DISABLED_FromCpuManyInQueue) { 379 status_t err; 380 CpuConsumerTestParams params = GetParam(); 381 382 const int numInQueue = 5; 383 // Set up 384 385 ASSERT_NO_FATAL_FAILURE(configureANW(mANW, params, numInQueue)); 386 387 // Produce 388 389 const int64_t time[numInQueue] = { 1L, 2L, 3L, 4L, 5L}; 390 uint32_t stride[numInQueue]; 391 392 for (int i = 0; i < numInQueue; i++) { 393 ALOGV("Producing frame %d", i); 394 ASSERT_NO_FATAL_FAILURE(produceOneFrame(mANW, params, time[i], 395 &stride[i])); 396 } 397 398 // Consume 399 400 for (int i = 0; i < numInQueue; i++) { 401 ALOGV("Consuming frame %d", i); 402 CpuConsumer::LockedBuffer b; 403 err = mCC->lockNextBuffer(&b); 404 ASSERT_NO_ERROR(err, "getNextBuffer error: "); 405 406 ASSERT_TRUE(b.data != NULL); 407 EXPECT_EQ(params.width, b.width); 408 EXPECT_EQ(params.height, b.height); 409 EXPECT_EQ(params.format, b.format); 410 EXPECT_EQ(stride[i], b.stride); 411 EXPECT_EQ(time[i], b.timestamp); 412 413 checkBayerRawBuffer(b); 414 415 mCC->unlockBuffer(b); 416 } 417 } 418 419 // This test is disabled because the HAL_PIXEL_FORMAT_RAW_SENSOR format is not 420 // supported on all devices. 421 TEST_P(CpuConsumerTest, DISABLED_FromCpuLockMax) { 422 status_t err; 423 CpuConsumerTestParams params = GetParam(); 424 425 // Set up 426 427 ASSERT_NO_FATAL_FAILURE(configureANW(mANW, params, params.maxLockedBuffers + 1)); 428 429 // Produce 430 431 const int64_t time = 1234L; 432 uint32_t stride; 433 434 for (int i = 0; i < params.maxLockedBuffers + 1; i++) { 435 ALOGV("Producing frame %d", i); 436 ASSERT_NO_FATAL_FAILURE(produceOneFrame(mANW, params, time, 437 &stride)); 438 } 439 440 // Consume 441 442 CpuConsumer::LockedBuffer *b = new CpuConsumer::LockedBuffer[params.maxLockedBuffers]; 443 for (int i = 0; i < params.maxLockedBuffers; i++) { 444 ALOGV("Locking frame %d", i); 445 err = mCC->lockNextBuffer(&b[i]); 446 ASSERT_NO_ERROR(err, "getNextBuffer error: "); 447 448 ASSERT_TRUE(b[i].data != NULL); 449 EXPECT_EQ(params.width, b[i].width); 450 EXPECT_EQ(params.height, b[i].height); 451 EXPECT_EQ(params.format, b[i].format); 452 EXPECT_EQ(stride, b[i].stride); 453 EXPECT_EQ(time, b[i].timestamp); 454 455 checkBayerRawBuffer(b[i]); 456 } 457 458 ALOGV("Locking frame %d (too many)", params.maxLockedBuffers); 459 CpuConsumer::LockedBuffer bTooMuch; 460 err = mCC->lockNextBuffer(&bTooMuch); 461 ASSERT_TRUE(err == INVALID_OPERATION) << "Allowing too many locks"; 462 463 ALOGV("Unlocking frame 0"); 464 err = mCC->unlockBuffer(b[0]); 465 ASSERT_NO_ERROR(err, "Could not unlock buffer 0: "); 466 467 ALOGV("Locking frame %d (should work now)", params.maxLockedBuffers); 468 err = mCC->lockNextBuffer(&bTooMuch); 469 ASSERT_NO_ERROR(err, "Did not allow new lock after unlock"); 470 471 ASSERT_TRUE(bTooMuch.data != NULL); 472 EXPECT_EQ(params.width, bTooMuch.width); 473 EXPECT_EQ(params.height, bTooMuch.height); 474 EXPECT_EQ(params.format, bTooMuch.format); 475 EXPECT_EQ(stride, bTooMuch.stride); 476 EXPECT_EQ(time, bTooMuch.timestamp); 477 478 checkBayerRawBuffer(bTooMuch); 479 480 ALOGV("Unlocking extra buffer"); 481 err = mCC->unlockBuffer(bTooMuch); 482 ASSERT_NO_ERROR(err, "Could not unlock extra buffer: "); 483 484 ALOGV("Locking frame %d (no more available)", params.maxLockedBuffers + 1); 485 err = mCC->lockNextBuffer(&b[0]); 486 ASSERT_EQ(BAD_VALUE, err) << "Not out of buffers somehow"; 487 488 for (int i = 1; i < params.maxLockedBuffers; i++) { 489 mCC->unlockBuffer(b[i]); 490 } 491 492 delete[] b; 493 494 } 495 496 CpuConsumerTestParams rawTestSets[] = { 497 { 512, 512, 1, HAL_PIXEL_FORMAT_RAW_SENSOR}, 498 { 512, 512, 3, HAL_PIXEL_FORMAT_RAW_SENSOR}, 499 { 2608, 1960, 1, HAL_PIXEL_FORMAT_RAW_SENSOR}, 500 { 2608, 1960, 3, HAL_PIXEL_FORMAT_RAW_SENSOR}, 501 { 100, 100, 1, HAL_PIXEL_FORMAT_RAW_SENSOR}, 502 { 100, 100, 3, HAL_PIXEL_FORMAT_RAW_SENSOR} 503 }; 504 505 INSTANTIATE_TEST_CASE_P(RawTests, 506 CpuConsumerTest, 507 ::testing::ValuesIn(rawTestSets)); 508 509 } // namespace android 510