1/* 2 * Copyright 2017 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#include <gtest/gtest.h> 18 19#include <C2AllocatorIon.h> 20#include <C2AllocatorGralloc.h> 21#include <C2Buffer.h> 22#include <C2BufferPriv.h> 23#include <C2ParamDef.h> 24 25#include <system/graphics.h> 26 27namespace android { 28 29class C2BufferUtilsTest : public ::testing::Test { 30 static void StaticSegmentTest() { 31 // constructor 32 static_assert(C2Segment(123u, 456u).offset == 123, ""); 33 static_assert(C2Segment(123u, 456u).size == 456, ""); 34 35 // empty 36 static_assert(!C2Segment(123u, 456u).isEmpty(), ""); 37 static_assert(C2Segment(123u, 0u).isEmpty(), ""); 38 39 // valid 40 static_assert(C2Segment(123u, 456u).isValid(), ""); 41 static_assert(C2Segment(123u, ~123u).isValid(), ""); 42 static_assert(!C2Segment(123u, 1 + ~123u).isValid(), ""); 43 44 // bool() 45 static_assert(C2Segment(123u, 456u), ""); 46 static_assert((bool)C2Segment(123u, ~123u), ""); 47 static_assert(!bool(C2Segment(123u, 1 + ~123u)), ""); 48 static_assert(!bool(C2Segment(123u, 0)), ""); 49 50 // ! 51 static_assert(!!C2Segment(123u, 456u), ""); 52 static_assert(!!C2Segment(123u, ~123u), ""); 53 static_assert(!C2Segment(123u, 1 + ~123u), ""); 54 static_assert(!C2Segment(123u, 0), ""); 55 56 // contains 57 static_assert(C2Segment(123u, ~123u).contains(C2Segment(123u, 0)), ""); 58 static_assert(!C2Segment(123u, 1 + ~123u).contains(C2Segment(123u, 0)), ""); 59 static_assert(C2Segment(123u, ~123u).contains(C2Segment(123u, ~123u)), ""); 60 static_assert(!C2Segment(123u, ~123u).contains(C2Segment(123u, 1 + ~123u)), ""); 61 static_assert(!C2Segment(123u, 1 + ~123u).contains(C2Segment(123u, 1 + ~123u)), ""); 62 static_assert(!C2Segment(123u, ~123u).contains(C2Segment(122u, 2u)), ""); 63 static_assert(C2Segment(123u, ~123u).contains(C2Segment(123u, 2u)), ""); 64 static_assert(C2Segment(123u, 3u).contains(C2Segment(124u, 2u)), ""); 65 static_assert(!C2Segment(123u, 3u).contains(C2Segment(125u, 2u)), ""); 66 67 // == 68 static_assert(C2Segment(123u, 456u) == C2Segment(123u, 456u), ""); 69 static_assert(!(C2Segment(123u, 456u) == C2Segment(123u, 457u)), ""); 70 static_assert(!(C2Segment(123u, 456u) == C2Segment(123u, 455u)), ""); 71 static_assert(!(C2Segment(123u, 456u) == C2Segment(122u, 456u)), ""); 72 static_assert(!(C2Segment(123u, 456u) == C2Segment(124u, 456u)), ""); 73 static_assert(!(C2Segment(123u, 0u) == C2Segment(124u, 0u)), ""); 74 static_assert(C2Segment(123u, 0u) == C2Segment(123u, 0u), ""); 75 static_assert(C2Segment(123u, 1 + ~123u) == C2Segment(124u, 1 + ~124u), ""); 76 77 // != 78 static_assert(!(C2Segment(123u, 456u) != C2Segment(123u, 456u)), ""); 79 static_assert(C2Segment(123u, 456u) != C2Segment(123u, 457u), ""); 80 static_assert(C2Segment(123u, 456u) != C2Segment(123u, 455u), ""); 81 static_assert(C2Segment(123u, 456u) != C2Segment(122u, 456u), ""); 82 static_assert(C2Segment(123u, 456u) != C2Segment(124u, 456u), ""); 83 static_assert(C2Segment(123u, 0u) != C2Segment(124u, 0u), ""); 84 static_assert(!(C2Segment(123u, 0u) != C2Segment(123u, 0u)), ""); 85 static_assert(!(C2Segment(123u, 1 + ~123u) != C2Segment(124u, 1 + ~124u)), ""); 86 87 // <= 88 static_assert(C2Segment(123u, 456u) <= C2Segment(123u, 456u), ""); 89 static_assert(C2Segment(123u, 456u) <= C2Segment(123u, 457u), ""); 90 static_assert(C2Segment(123u, 456u) <= C2Segment(122u, 457u), ""); 91 static_assert(!(C2Segment(123u, 457u) <= C2Segment(123u, 456u)), ""); 92 static_assert(!(C2Segment(122u, 457u) <= C2Segment(123u, 456u)), ""); 93 static_assert(!(C2Segment(123u, 457u) <= C2Segment(124u, 457u)), ""); 94 static_assert(!(C2Segment(122u, 457u) <= C2Segment(123u, 457u)), ""); 95 static_assert(!(C2Segment(122u, 0u) <= C2Segment(123u, 0u)), ""); 96 static_assert(C2Segment(123u, 0u) <= C2Segment(122u, 1u), ""); 97 static_assert(C2Segment(122u, 0u) <= C2Segment(122u, 1u), ""); 98 static_assert(!(C2Segment(122u, ~122u) <= C2Segment(122u, 1 + ~122u)), ""); 99 static_assert(!(C2Segment(122u, 1 + ~122u) <= C2Segment(122u, ~122u)), ""); 100 static_assert(!(C2Segment(122u, 1 + ~122u) <= C2Segment(122u, 1 + ~122u)), ""); 101 102 // < 103 static_assert(!(C2Segment(123u, 456u) < C2Segment(123u, 456u)), ""); 104 static_assert(C2Segment(123u, 456u) < C2Segment(123u, 457u), ""); 105 static_assert(C2Segment(123u, 456u) < C2Segment(122u, 457u), ""); 106 static_assert(!(C2Segment(123u, 457u) < C2Segment(123u, 456u)), ""); 107 static_assert(!(C2Segment(122u, 457u) < C2Segment(123u, 456u)), ""); 108 static_assert(!(C2Segment(123u, 457u) < C2Segment(124u, 457u)), ""); 109 static_assert(!(C2Segment(122u, 457u) < C2Segment(123u, 457u)), ""); 110 static_assert(!(C2Segment(122u, 0u) < C2Segment(123u, 0u)), ""); 111 static_assert(C2Segment(123u, 0u) < C2Segment(122u, 1u), ""); 112 static_assert(C2Segment(122u, 0u) < C2Segment(122u, 1u), ""); 113 static_assert(!(C2Segment(122u, ~122u) < C2Segment(122u, 1 + ~122u)), ""); 114 static_assert(!(C2Segment(122u, 1 + ~122u) < C2Segment(122u, ~122u)), ""); 115 static_assert(!(C2Segment(122u, 1 + ~122u) < C2Segment(122u, 1 + ~122u)), ""); 116 117 // <= 118 static_assert(C2Segment(123u, 456u) >= C2Segment(123u, 456u), ""); 119 static_assert(C2Segment(123u, 457u) >= C2Segment(123u, 456u), ""); 120 static_assert(C2Segment(122u, 457u) >= C2Segment(123u, 456u), ""); 121 static_assert(!(C2Segment(123u, 456u) >= C2Segment(123u, 457u)), ""); 122 static_assert(!(C2Segment(123u, 456u) >= C2Segment(122u, 457u)), ""); 123 static_assert(!(C2Segment(124u, 457u) >= C2Segment(123u, 457u)), ""); 124 static_assert(!(C2Segment(123u, 457u) >= C2Segment(122u, 457u)), ""); 125 static_assert(!(C2Segment(123u, 0u) >= C2Segment(122u, 0u)), ""); 126 static_assert(C2Segment(122u, 1u) >= C2Segment(123u, 0u), ""); 127 static_assert(C2Segment(122u, 1u) >= C2Segment(122u, 0u), ""); 128 static_assert(!(C2Segment(122u, 1 + ~122u) >= C2Segment(122u, ~122u)), ""); 129 static_assert(!(C2Segment(122u, ~122u) >= C2Segment(122u, 1 + ~122u)), ""); 130 static_assert(!(C2Segment(122u, 1 + ~122u) >= C2Segment(122u, 1 + ~122u)), ""); 131 132 // < 133 static_assert(!(C2Segment(123u, 456u) > C2Segment(123u, 456u)), ""); 134 static_assert(C2Segment(123u, 457u) > C2Segment(123u, 456u), ""); 135 static_assert(C2Segment(122u, 457u) > C2Segment(123u, 456u), ""); 136 static_assert(!(C2Segment(123u, 456u) > C2Segment(123u, 457u)), ""); 137 static_assert(!(C2Segment(123u, 456u) > C2Segment(122u, 457u)), ""); 138 static_assert(!(C2Segment(124u, 457u) > C2Segment(123u, 457u)), ""); 139 static_assert(!(C2Segment(123u, 457u) > C2Segment(122u, 457u)), ""); 140 static_assert(!(C2Segment(123u, 0u) > C2Segment(122u, 0u)), ""); 141 static_assert(C2Segment(122u, 1u) > C2Segment(123u, 0u), ""); 142 static_assert(C2Segment(122u, 1u) > C2Segment(122u, 0u), ""); 143 static_assert(!(C2Segment(122u, 1 + ~122u) > C2Segment(122u, ~122u)), ""); 144 static_assert(!(C2Segment(122u, ~122u) > C2Segment(122u, 1 + ~122u)), ""); 145 static_assert(!(C2Segment(122u, 1 + ~122u) > C2Segment(122u, 1 + ~122u)), ""); 146 147 // end 148 static_assert(C2Segment(123u, 456u).end() == 579u, ""); 149 static_assert(C2Segment(123u, 0u).end() == 123u, ""); 150 static_assert(C2Segment(123u, ~123u).end() == 0xffffffffu, ""); 151 static_assert(C2Segment(123u, 1 + ~123u).end() == 0u, ""); 152 153 // intersect 154 static_assert(C2Segment(123u, 456u).intersect(C2Segment(123u, 456u)) == C2Segment(123u, 456u), ""); 155 static_assert(C2Segment(123u, 456u).intersect(C2Segment(123u, 460u)) == C2Segment(123u, 456u), ""); 156 static_assert(C2Segment(123u, 456u).intersect(C2Segment(124u, 460u)) == C2Segment(124u, 455u), ""); 157 static_assert(C2Segment(123u, 456u).intersect(C2Segment(579u, 460u)) == C2Segment(579u, 0u), ""); 158 static_assert(C2Segment(123u, 456u).intersect(C2Segment(589u, 460u)) == C2Segment(589u, ~9u /* -10 */), ""); 159 static_assert(C2Segment(123u, 456u).intersect(C2Segment(123u, 455u)) == C2Segment(123u, 455u), ""); 160 static_assert(C2Segment(123u, 456u).intersect(C2Segment(122u, 456u)) == C2Segment(123u, 455u), ""); 161 static_assert(C2Segment(123u, 456u).intersect(C2Segment(0u, 123u)) == C2Segment(123u, 0u), ""); 162 static_assert(C2Segment(123u, 456u).intersect(C2Segment(0u, 0u)) == C2Segment(123u, ~122u /* -123 */), ""); 163 164 // normalize (change invalid segments to empty segments) 165 static_assert(C2Segment(123u, 456u).normalize() == C2Segment(123u, 456u), ""); 166 static_assert(C2Segment(123u, ~123u).normalize() == C2Segment(123u, ~123u), ""); 167 static_assert(C2Segment(123u, 1 + ~123u).normalize() == C2Segment(123u, 0u), ""); 168 169 // note: normalize cannot be used to make this work 170 static_assert(C2Segment(123u, 456u).intersect(C2Segment(150u, ~150u)).normalize() == C2Segment(150u, 429u), ""); 171 static_assert(C2Segment(123u, 456u).intersect(C2Segment(150u, 1 + ~150u)).normalize() != C2Segment(150u, 429u), ""); 172 static_assert(C2Segment(123u, 456u).intersect(C2Segment(150u, 1 + ~150u)).normalize() == C2Segment(150u, 0u), ""); 173 174 // saturate (change invalid segments to full segments up to max) 175 static_assert(C2Segment(123u, 456u).saturate() == C2Segment(123u, 456u), ""); 176 static_assert(C2Segment(123u, ~123u).saturate() == C2Segment(123u, ~123u), ""); 177 static_assert(C2Segment(123u, 1 + ~123u).saturate() == C2Segment(123u, ~123u), ""); 178 179 // note: saturate can be used to make this work but only partially 180 static_assert(C2Segment(123u, 456u).intersect(C2Segment(150u, 1 + ~150u).saturate()).normalize() == C2Segment(150u, 429u), ""); 181 static_assert(C2Segment(123u, 456u).intersect(C2Segment(0u, 100u).saturate()).normalize() == C2Segment(123u, 0u), ""); 182 static_assert(C2Segment(123u, 456u).intersect(C2Segment(1000u, 100u).saturate()).normalize() != C2Segment(579u, 0u), ""); 183 static_assert(C2Segment(123u, 456u).intersect(C2Segment(1000u, 100u).saturate()).normalize() == C2Segment(1000u, 0u), ""); 184 185 } 186 187 static void StaticLinearRangeAndCapacityTest() { 188 class TestCapacity : public _C2LinearCapacityAspect { 189 using _C2LinearCapacityAspect::_C2LinearCapacityAspect; 190 friend class C2BufferUtilsTest; 191 }; 192 193 class TestRange : public _C2LinearRangeAspect { 194 using _C2LinearRangeAspect::_C2LinearRangeAspect; 195 friend class C2BufferUtilsTest; 196 }; 197 198 // _C2LinearCapacityAspect 199 static_assert(TestCapacity(0u).capacity() == 0u, ""); 200 constexpr TestCapacity cap(123u); 201 static_assert(TestCapacity(&cap).capacity() == 123u, ""); 202 static_assert(TestCapacity(nullptr).capacity() == 0u, ""); 203 204 // _C2LinearCapacityRange 205 static_assert(TestRange(&cap).capacity() == 123u, ""); 206 static_assert(TestRange(&cap).offset() == 0u, ""); 207 static_assert(TestRange(&cap).size() == 123u, ""); 208 static_assert(TestRange(&cap).endOffset() == 123u, ""); 209 210 constexpr TestRange range(&cap, 50u, 100u); 211 212 static_assert(range.capacity() == 123u, ""); 213 static_assert(range.offset() == 50u, ""); 214 static_assert(range.size() == 73u, ""); 215 static_assert(range.endOffset() == 123u, ""); 216 217 static_assert(TestRange(&cap, 20u, 30u).capacity() == 123u, ""); 218 static_assert(TestRange(&cap, 20u, 30u).offset() == 20u, ""); 219 static_assert(TestRange(&cap, 20u, 30u).size() == 30u, ""); 220 static_assert(TestRange(&cap, 20u, 30u).endOffset() == 50u, ""); 221 222 static_assert(TestRange(&cap, 200u, 30u).capacity() == 123u, ""); 223 static_assert(TestRange(&cap, 200u, 30u).offset() == 123u, ""); 224 static_assert(TestRange(&cap, 200u, 30u).size() == 0u, ""); 225 static_assert(TestRange(&cap, 200u, 30u).endOffset() == 123u, ""); 226 227 } 228 229}; 230 231 232class C2BufferTest : public ::testing::Test { 233public: 234 C2BufferTest() 235 : mBlockPoolId(C2BlockPool::PLATFORM_START), 236 mLinearAllocator(std::make_shared<C2AllocatorIon>('i')), 237 mSize(0u), 238 mAddr(nullptr), 239 mGraphicAllocator(std::make_shared<C2AllocatorGralloc>('g')) { 240 } 241 242 ~C2BufferTest() = default; 243 244 void allocateLinear(size_t capacity) { 245 c2_status_t err = mLinearAllocator->newLinearAllocation( 246 capacity, 247 { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE }, 248 &mLinearAllocation); 249 if (err != C2_OK) { 250 mLinearAllocation.reset(); 251 FAIL() << "C2Allocator::newLinearAllocation() failed: " << err; 252 } 253 } 254 255 void mapLinear(size_t offset, size_t size, uint8_t **addr) { 256 ASSERT_TRUE(mLinearAllocation); 257 c2_status_t err = mLinearAllocation->map( 258 offset, 259 size, 260 { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE }, 261 // TODO: fence 262 nullptr, 263 &mAddr); 264 if (err != C2_OK) { 265 mAddr = nullptr; 266 FAIL() << "C2LinearAllocation::map() failed: " << err; 267 } 268 ASSERT_NE(nullptr, mAddr); 269 mSize = size; 270 *addr = (uint8_t *)mAddr; 271 } 272 273 void unmapLinear() { 274 ASSERT_TRUE(mLinearAllocation); 275 ASSERT_NE(nullptr, mAddr); 276 ASSERT_NE(0u, mSize); 277 278 // TODO: fence 279 ASSERT_EQ(C2_OK, mLinearAllocation->unmap(mAddr, mSize, nullptr)); 280 mSize = 0u; 281 mAddr = nullptr; 282 } 283 284 std::shared_ptr<C2BlockPool> makeLinearBlockPool() { 285 return std::make_shared<C2PooledBlockPool>(mLinearAllocator, mBlockPoolId++); 286 } 287 288 void allocateGraphic(uint32_t width, uint32_t height) { 289 c2_status_t err = mGraphicAllocator->newGraphicAllocation( 290 width, 291 height, 292 HAL_PIXEL_FORMAT_YCBCR_420_888, 293 { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE }, 294 &mGraphicAllocation); 295 if (err != C2_OK) { 296 mGraphicAllocation.reset(); 297 FAIL() << "C2Allocator::newGraphicAllocation() failed: " << err; 298 } 299 } 300 301 void mapGraphic(C2Rect rect, C2PlanarLayout *layout, uint8_t **addr) { 302 ASSERT_TRUE(mGraphicAllocation); 303 c2_status_t err = mGraphicAllocation->map( 304 rect, 305 { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE }, 306 // TODO: fence 307 nullptr, 308 layout, 309 addr); 310 if (err != C2_OK) { 311 addr[C2PlanarLayout::PLANE_Y] = nullptr; 312 addr[C2PlanarLayout::PLANE_U] = nullptr; 313 addr[C2PlanarLayout::PLANE_V] = nullptr; 314 FAIL() << "C2GraphicAllocation::map() failed: " << err; 315 } 316 mMappedRect = rect; 317 memcpy(mAddrGraphic, addr, sizeof(uint8_t*) * C2PlanarLayout::MAX_NUM_PLANES); 318 } 319 320 void unmapGraphic() { 321 ASSERT_TRUE(mGraphicAllocation); 322 323 // TODO: fence 324 ASSERT_EQ(C2_OK, mGraphicAllocation->unmap(mAddrGraphic, mMappedRect, nullptr)); 325 } 326 327 std::shared_ptr<C2BlockPool> makeGraphicBlockPool() { 328 return std::make_shared<C2BasicGraphicBlockPool>(mGraphicAllocator); 329 } 330 331private: 332 C2BlockPool::local_id_t mBlockPoolId; 333 std::shared_ptr<C2Allocator> mLinearAllocator; 334 std::shared_ptr<C2LinearAllocation> mLinearAllocation; 335 size_t mSize; 336 void *mAddr; 337 C2Rect mMappedRect; 338 uint8_t* mAddrGraphic[C2PlanarLayout::MAX_NUM_PLANES]; 339 340 std::shared_ptr<C2Allocator> mGraphicAllocator; 341 std::shared_ptr<C2GraphicAllocation> mGraphicAllocation; 342}; 343 344TEST_F(C2BufferTest, LinearAllocationTest) { 345 constexpr size_t kCapacity = 1024u * 1024u; 346 347 allocateLinear(kCapacity); 348 349 uint8_t *addr = nullptr; 350 mapLinear(0u, kCapacity, &addr); 351 ASSERT_NE(nullptr, addr); 352 353 for (size_t i = 0; i < kCapacity; ++i) { 354 addr[i] = i % 100u; 355 } 356 357 unmapLinear(); 358 addr = nullptr; 359 360 mapLinear(kCapacity / 3, kCapacity / 3, &addr); 361 ASSERT_NE(nullptr, addr); 362 for (size_t i = 0; i < kCapacity / 3; ++i) { 363 ASSERT_EQ((i + kCapacity / 3) % 100, addr[i]) << " at i = " << i; 364 } 365} 366 367TEST_F(C2BufferTest, BlockPoolTest) { 368 constexpr size_t kCapacity = 1024u * 1024u; 369 370 std::shared_ptr<C2BlockPool> blockPool(makeLinearBlockPool()); 371 372 std::shared_ptr<C2LinearBlock> block; 373 ASSERT_EQ(C2_OK, blockPool->fetchLinearBlock( 374 kCapacity, 375 { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE }, 376 &block)); 377 ASSERT_TRUE(block); 378 379 C2Acquirable<C2WriteView> writeViewHolder = block->map(); 380 C2WriteView writeView = writeViewHolder.get(); 381 ASSERT_EQ(C2_OK, writeView.error()); 382 ASSERT_EQ(kCapacity, writeView.capacity()); 383 ASSERT_EQ(0u, writeView.offset()); 384 ASSERT_EQ(kCapacity, writeView.size()); 385 386 uint8_t *data = writeView.data(); 387 ASSERT_NE(nullptr, data); 388 for (size_t i = 0; i < writeView.size(); ++i) { 389 data[i] = i % 100u; 390 } 391 392 writeView.setOffset(kCapacity / 3); 393 data = writeView.data(); 394 ASSERT_NE(nullptr, data); 395 for (size_t i = 0; i < writeView.size(); ++i) { 396 ASSERT_EQ((i + kCapacity / 3) % 100u, data[i]) << " at i = " << i 397 << "; data = " << static_cast<void *>(data); 398 } 399 400 C2Fence fence; 401 C2ConstLinearBlock constBlock = block->share( 402 kCapacity / 3, kCapacity / 3, fence); 403 404 C2Acquirable<C2ReadView> readViewHolder = constBlock.map(); 405 C2ReadView readView = readViewHolder.get(); 406 ASSERT_EQ(C2_OK, readView.error()); 407 ASSERT_EQ(kCapacity / 3, readView.capacity()); 408 409 // TODO: fence 410 const uint8_t *constData = readView.data(); 411 ASSERT_NE(nullptr, constData); 412 for (size_t i = 0; i < readView.capacity(); ++i) { 413 ASSERT_EQ((i + kCapacity / 3) % 100u, constData[i]) << " at i = " << i 414 << "; data = " << static_cast<void *>(data) 415 << "; constData = " << static_cast<const void *>(constData); 416 } 417 418 readView = readView.subView(333u, 100u); 419 ASSERT_EQ(C2_OK, readView.error()); 420 ASSERT_EQ(100u, readView.capacity()); 421 422 constData = readView.data(); 423 ASSERT_NE(nullptr, constData); 424 for (size_t i = 0; i < readView.capacity(); ++i) { 425 ASSERT_EQ((i + 333u + kCapacity / 3) % 100u, constData[i]) << " at i = " << i; 426 } 427} 428 429void fillPlane(const C2Rect rect, const C2PlaneInfo info, uint8_t *addr, uint8_t value) { 430 for (uint32_t row = 0; row < rect.height / info.rowSampling; ++row) { 431 int32_t rowOffset = (row + rect.top / info.rowSampling) * info.rowInc; 432 for (uint32_t col = 0; col < rect.width / info.colSampling; ++col) { 433 int32_t colOffset = (col + rect.left / info.colSampling) * info.colInc; 434 addr[rowOffset + colOffset] = value; 435 } 436 } 437} 438 439bool verifyPlane(const C2Rect rect, const C2PlaneInfo info, const uint8_t *addr, uint8_t value) { 440 for (uint32_t row = 0; row < rect.height / info.rowSampling; ++row) { 441 int32_t rowOffset = (row + rect.top / info.rowSampling) * info.rowInc; 442 for (uint32_t col = 0; col < rect.width / info.colSampling; ++col) { 443 int32_t colOffset = (col + rect.left / info.colSampling) * info.colInc; 444 if (addr[rowOffset + colOffset] != value) { 445 return false; 446 } 447 } 448 } 449 return true; 450} 451 452TEST_F(C2BufferTest, GraphicAllocationTest) { 453 constexpr uint32_t kWidth = 320; 454 constexpr uint32_t kHeight = 240; 455 456 allocateGraphic(kWidth, kHeight); 457 458 uint8_t *addr[C2PlanarLayout::MAX_NUM_PLANES]; 459 C2Rect rect(kWidth, kHeight); 460 C2PlanarLayout layout; 461 mapGraphic(rect, &layout, addr); 462 ASSERT_NE(nullptr, addr[C2PlanarLayout::PLANE_Y]); 463 ASSERT_NE(nullptr, addr[C2PlanarLayout::PLANE_U]); 464 ASSERT_NE(nullptr, addr[C2PlanarLayout::PLANE_V]); 465 466 uint8_t *y = addr[C2PlanarLayout::PLANE_Y]; 467 C2PlaneInfo yInfo = layout.planes[C2PlanarLayout::PLANE_Y]; 468 uint8_t *u = addr[C2PlanarLayout::PLANE_U]; 469 C2PlaneInfo uInfo = layout.planes[C2PlanarLayout::PLANE_U]; 470 uint8_t *v = addr[C2PlanarLayout::PLANE_V]; 471 C2PlaneInfo vInfo = layout.planes[C2PlanarLayout::PLANE_V]; 472 473 fillPlane(rect, yInfo, y, 0); 474 fillPlane(rect, uInfo, u, 0); 475 fillPlane(rect, vInfo, v, 0); 476 fillPlane(C2Rect(kWidth / 2, kHeight / 2).at(kWidth / 4, kHeight / 4), yInfo, y, 0x12); 477 fillPlane(C2Rect(kWidth / 2, kHeight / 2).at(kWidth / 4, kHeight / 4), uInfo, u, 0x34); 478 fillPlane(C2Rect(kWidth / 2, kHeight / 2).at(kWidth / 4, kHeight / 4), vInfo, v, 0x56); 479 480 unmapGraphic(); 481 482 mapGraphic(rect, &layout, addr); 483 ASSERT_NE(nullptr, addr[C2PlanarLayout::PLANE_Y]); 484 ASSERT_NE(nullptr, addr[C2PlanarLayout::PLANE_U]); 485 ASSERT_NE(nullptr, addr[C2PlanarLayout::PLANE_V]); 486 487 y = addr[C2PlanarLayout::PLANE_Y]; 488 yInfo = layout.planes[C2PlanarLayout::PLANE_Y]; 489 u = addr[C2PlanarLayout::PLANE_U]; 490 uInfo = layout.planes[C2PlanarLayout::PLANE_U]; 491 v = addr[C2PlanarLayout::PLANE_V]; 492 vInfo = layout.planes[C2PlanarLayout::PLANE_V]; 493 494 ASSERT_TRUE(verifyPlane(C2Rect(kWidth / 2, kHeight / 2).at(kWidth / 4, kHeight / 4), yInfo, y, 0x12)); 495 ASSERT_TRUE(verifyPlane(C2Rect(kWidth / 2, kHeight / 2).at(kWidth / 4, kHeight / 4), uInfo, u, 0x34)); 496 ASSERT_TRUE(verifyPlane(C2Rect(kWidth / 2, kHeight / 2).at(kWidth / 4, kHeight / 4), vInfo, v, 0x56)); 497 ASSERT_TRUE(verifyPlane({ kWidth, kHeight / 4 }, yInfo, y, 0)); 498 ASSERT_TRUE(verifyPlane({ kWidth, kHeight / 4 }, uInfo, u, 0)); 499 ASSERT_TRUE(verifyPlane({ kWidth, kHeight / 4 }, vInfo, v, 0)); 500 ASSERT_TRUE(verifyPlane({ kWidth / 4, kHeight }, yInfo, y, 0)); 501 ASSERT_TRUE(verifyPlane({ kWidth / 4, kHeight }, uInfo, u, 0)); 502 ASSERT_TRUE(verifyPlane({ kWidth / 4, kHeight }, vInfo, v, 0)); 503} 504 505TEST_F(C2BufferTest, GraphicBlockPoolTest) { 506 constexpr uint32_t kWidth = 320; 507 constexpr uint32_t kHeight = 240; 508 509 std::shared_ptr<C2BlockPool> blockPool(makeGraphicBlockPool()); 510 511 std::shared_ptr<C2GraphicBlock> block; 512 ASSERT_EQ(C2_OK, blockPool->fetchGraphicBlock( 513 kWidth, 514 kHeight, 515 HAL_PIXEL_FORMAT_YCBCR_420_888, 516 { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE }, 517 &block)); 518 ASSERT_TRUE(block); 519 520 C2Acquirable<C2GraphicView> graphicViewHolder = block->map(); 521 C2GraphicView graphicView = graphicViewHolder.get(); 522 ASSERT_EQ(C2_OK, graphicView.error()); 523 ASSERT_EQ(kWidth, graphicView.width()); 524 ASSERT_EQ(kHeight, graphicView.height()); 525 526 uint8_t *const *data = graphicView.data(); 527 C2PlanarLayout layout = graphicView.layout(); 528 ASSERT_NE(nullptr, data); 529 530 uint8_t *y = data[C2PlanarLayout::PLANE_Y]; 531 C2PlaneInfo yInfo = layout.planes[C2PlanarLayout::PLANE_Y]; 532 uint8_t *u = data[C2PlanarLayout::PLANE_U]; 533 C2PlaneInfo uInfo = layout.planes[C2PlanarLayout::PLANE_U]; 534 uint8_t *v = data[C2PlanarLayout::PLANE_V]; 535 C2PlaneInfo vInfo = layout.planes[C2PlanarLayout::PLANE_V]; 536 537 fillPlane({ kWidth, kHeight }, yInfo, y, 0); 538 fillPlane({ kWidth, kHeight }, uInfo, u, 0); 539 fillPlane({ kWidth, kHeight }, vInfo, v, 0); 540 fillPlane(C2Rect(kWidth / 2, kHeight / 2).at(kWidth / 4, kHeight / 4), yInfo, y, 0x12); 541 fillPlane(C2Rect(kWidth / 2, kHeight / 2).at(kWidth / 4, kHeight / 4), uInfo, u, 0x34); 542 fillPlane(C2Rect(kWidth / 2, kHeight / 2).at(kWidth / 4, kHeight / 4), vInfo, v, 0x56); 543 544 C2Fence fence; 545 C2ConstGraphicBlock constBlock = block->share(C2Rect(kWidth, kHeight), fence); 546 block.reset(); 547 548 C2Acquirable<const C2GraphicView> constViewHolder = constBlock.map(); 549 const C2GraphicView constGraphicView = constViewHolder.get(); 550 ASSERT_EQ(C2_OK, constGraphicView.error()); 551 ASSERT_EQ(kWidth, constGraphicView.width()); 552 ASSERT_EQ(kHeight, constGraphicView.height()); 553 554 const uint8_t *const *constData = constGraphicView.data(); 555 layout = graphicView.layout(); 556 ASSERT_NE(nullptr, constData); 557 558 const uint8_t *cy = constData[C2PlanarLayout::PLANE_Y]; 559 yInfo = layout.planes[C2PlanarLayout::PLANE_Y]; 560 const uint8_t *cu = constData[C2PlanarLayout::PLANE_U]; 561 uInfo = layout.planes[C2PlanarLayout::PLANE_U]; 562 const uint8_t *cv = constData[C2PlanarLayout::PLANE_V]; 563 vInfo = layout.planes[C2PlanarLayout::PLANE_V]; 564 565 ASSERT_TRUE(verifyPlane(C2Rect(kWidth / 2, kHeight / 2).at(kWidth / 4, kHeight / 4), yInfo, cy, 0x12)); 566 ASSERT_TRUE(verifyPlane(C2Rect(kWidth / 2, kHeight / 2).at(kWidth / 4, kHeight / 4), uInfo, cu, 0x34)); 567 ASSERT_TRUE(verifyPlane(C2Rect(kWidth / 2, kHeight / 2).at(kWidth / 4, kHeight / 4), vInfo, cv, 0x56)); 568 ASSERT_TRUE(verifyPlane({ kWidth, kHeight / 4 }, yInfo, cy, 0)); 569 ASSERT_TRUE(verifyPlane({ kWidth, kHeight / 4 }, uInfo, cu, 0)); 570 ASSERT_TRUE(verifyPlane({ kWidth, kHeight / 4 }, vInfo, cv, 0)); 571 ASSERT_TRUE(verifyPlane({ kWidth / 4, kHeight }, yInfo, cy, 0)); 572 ASSERT_TRUE(verifyPlane({ kWidth / 4, kHeight }, uInfo, cu, 0)); 573 ASSERT_TRUE(verifyPlane({ kWidth / 4, kHeight }, vInfo, cv, 0)); 574} 575 576class BufferData : public C2BufferData { 577public: 578 explicit BufferData(const std::vector<C2ConstLinearBlock> &blocks) : C2BufferData(blocks) {} 579 explicit BufferData(const std::vector<C2ConstGraphicBlock> &blocks) : C2BufferData(blocks) {} 580}; 581 582class Buffer : public C2Buffer { 583public: 584 explicit Buffer(const std::vector<C2ConstLinearBlock> &blocks) : C2Buffer(blocks) {} 585 explicit Buffer(const std::vector<C2ConstGraphicBlock> &blocks) : C2Buffer(blocks) {} 586}; 587 588TEST_F(C2BufferTest, BufferDataTest) { 589 std::shared_ptr<C2BlockPool> linearBlockPool(makeLinearBlockPool()); 590 std::shared_ptr<C2BlockPool> graphicBlockPool(makeGraphicBlockPool()); 591 592 constexpr uint32_t kWidth1 = 320; 593 constexpr uint32_t kHeight1 = 240; 594 constexpr C2Rect kCrop1(kWidth1, kHeight1); 595 constexpr uint32_t kWidth2 = 176; 596 constexpr uint32_t kHeight2 = 144; 597 constexpr C2Rect kCrop2(kWidth2, kHeight2); 598 constexpr size_t kCapacity1 = 1024u; 599 constexpr size_t kCapacity2 = 2048u; 600 601 std::shared_ptr<C2LinearBlock> linearBlock1; 602 std::shared_ptr<C2LinearBlock> linearBlock2; 603 ASSERT_EQ(C2_OK, linearBlockPool->fetchLinearBlock( 604 kCapacity1, 605 { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE }, 606 &linearBlock1)); 607 ASSERT_EQ(C2_OK, linearBlockPool->fetchLinearBlock( 608 kCapacity2, 609 { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE }, 610 &linearBlock2)); 611 std::shared_ptr<C2GraphicBlock> graphicBlock1; 612 std::shared_ptr<C2GraphicBlock> graphicBlock2; 613 ASSERT_EQ(C2_OK, graphicBlockPool->fetchGraphicBlock( 614 kWidth1, 615 kHeight1, 616 HAL_PIXEL_FORMAT_YCBCR_420_888, 617 { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE }, 618 &graphicBlock1)); 619 ASSERT_EQ(C2_OK, graphicBlockPool->fetchGraphicBlock( 620 kWidth2, 621 kHeight2, 622 HAL_PIXEL_FORMAT_YCBCR_420_888, 623 { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE }, 624 &graphicBlock2)); 625 626 std::shared_ptr<C2BufferData> data(new BufferData({ linearBlock1->share(0, kCapacity1, C2Fence()) })); 627 EXPECT_EQ(C2BufferData::LINEAR, data->type()); 628 ASSERT_EQ(1u, data->linearBlocks().size()); 629 EXPECT_EQ(linearBlock1->handle(), data->linearBlocks().front().handle()); 630 EXPECT_TRUE(data->graphicBlocks().empty()); 631 632 data.reset(new BufferData({ 633 linearBlock1->share(0, kCapacity1, C2Fence()), 634 linearBlock2->share(0, kCapacity2, C2Fence()), 635 })); 636 EXPECT_EQ(C2BufferData::LINEAR_CHUNKS, data->type()); 637 ASSERT_EQ(2u, data->linearBlocks().size()); 638 EXPECT_EQ(linearBlock1->handle(), data->linearBlocks().front().handle()); 639 EXPECT_EQ(linearBlock2->handle(), data->linearBlocks().back().handle()); 640 EXPECT_TRUE(data->graphicBlocks().empty()); 641 642 data.reset(new BufferData({ graphicBlock1->share(kCrop1, C2Fence()) })); 643 EXPECT_EQ(C2BufferData::GRAPHIC, data->type()); 644 ASSERT_EQ(1u, data->graphicBlocks().size()); 645 EXPECT_EQ(graphicBlock1->handle(), data->graphicBlocks().front().handle()); 646 EXPECT_TRUE(data->linearBlocks().empty()); 647 648 data.reset(new BufferData({ 649 graphicBlock1->share(kCrop1, C2Fence()), 650 graphicBlock2->share(kCrop2, C2Fence()), 651 })); 652 EXPECT_EQ(C2BufferData::GRAPHIC_CHUNKS, data->type()); 653 ASSERT_EQ(2u, data->graphicBlocks().size()); 654 EXPECT_EQ(graphicBlock1->handle(), data->graphicBlocks().front().handle()); 655 EXPECT_EQ(graphicBlock2->handle(), data->graphicBlocks().back().handle()); 656 EXPECT_TRUE(data->linearBlocks().empty()); 657} 658 659void DestroyCallback(const C2Buffer * /* buf */, void *arg) { 660 std::function<void(void)> *cb = (std::function<void(void)> *)arg; 661 (*cb)(); 662} 663 664enum : uint32_t { 665 kParamIndexNumber1, 666 kParamIndexNumber2, 667}; 668 669typedef C2GlobalParam<C2Info, C2Int32Value, kParamIndexNumber1> C2Number1Info; 670typedef C2GlobalParam<C2Info, C2Int32Value, kParamIndexNumber2> C2Number2Info; 671 672TEST_F(C2BufferTest, BufferTest) { 673 std::shared_ptr<C2BlockPool> alloc(makeLinearBlockPool()); 674 constexpr size_t kCapacity = 1024u; 675 std::shared_ptr<C2LinearBlock> block; 676 677 ASSERT_EQ(C2_OK, alloc->fetchLinearBlock( 678 kCapacity, 679 { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE }, 680 &block)); 681 682 std::atomic_bool destroyed(false); 683 std::function<void(void)> arg = [&destroyed](){ destroyed = true; }; 684 685 std::shared_ptr<C2Buffer> buffer(new Buffer( { block->share(0, kCapacity, C2Fence()) })); 686 ASSERT_EQ(C2_OK, buffer->registerOnDestroyNotify(&DestroyCallback, &arg)); 687 EXPECT_FALSE(destroyed); 688 ASSERT_EQ(C2_DUPLICATE, buffer->registerOnDestroyNotify(&DestroyCallback, &arg)); 689 buffer.reset(); 690 EXPECT_TRUE(destroyed); 691 692 buffer.reset(new Buffer( { block->share(0, kCapacity, C2Fence()) })); 693 destroyed = false; 694 ASSERT_EQ(C2_OK, buffer->registerOnDestroyNotify(&DestroyCallback, &arg)); 695 EXPECT_FALSE(destroyed); 696 ASSERT_EQ(C2_NOT_FOUND, buffer->unregisterOnDestroyNotify(&DestroyCallback, nullptr)); 697 ASSERT_EQ(C2_OK, buffer->unregisterOnDestroyNotify(&DestroyCallback, &arg)); 698 EXPECT_FALSE(destroyed); 699 ASSERT_EQ(C2_NOT_FOUND, buffer->unregisterOnDestroyNotify(&DestroyCallback, &arg)); 700 buffer.reset(); 701 EXPECT_FALSE(destroyed); 702 703 std::shared_ptr<C2Info> info1(new C2Number1Info(1)); 704 std::shared_ptr<C2Info> info2(new C2Number2Info(2)); 705 buffer.reset(new Buffer( { block->share(0, kCapacity, C2Fence()) })); 706 EXPECT_TRUE(buffer->info().empty()); 707 EXPECT_FALSE(buffer->hasInfo(info1->type())); 708 EXPECT_FALSE(buffer->hasInfo(info2->type())); 709 710 ASSERT_EQ(C2_OK, buffer->setInfo(info1)); 711 EXPECT_EQ(1u, buffer->info().size()); 712 EXPECT_EQ(*info1, *buffer->info().front()); 713 EXPECT_TRUE(buffer->hasInfo(info1->type())); 714 EXPECT_FALSE(buffer->hasInfo(info2->type())); 715 716 ASSERT_EQ(C2_OK, buffer->setInfo(info2)); 717 EXPECT_EQ(2u, buffer->info().size()); 718 EXPECT_TRUE(buffer->hasInfo(info1->type())); 719 EXPECT_TRUE(buffer->hasInfo(info2->type())); 720 721 std::shared_ptr<C2Info> removed = buffer->removeInfo(info1->type()); 722 ASSERT_TRUE(removed); 723 EXPECT_EQ(*removed, *info1); 724 EXPECT_EQ(1u, buffer->info().size()); 725 EXPECT_EQ(*info2, *buffer->info().front()); 726 EXPECT_FALSE(buffer->hasInfo(info1->type())); 727 EXPECT_TRUE(buffer->hasInfo(info2->type())); 728 729 removed = buffer->removeInfo(info1->type()); 730 ASSERT_FALSE(removed); 731 EXPECT_EQ(1u, buffer->info().size()); 732 EXPECT_FALSE(buffer->hasInfo(info1->type())); 733 EXPECT_TRUE(buffer->hasInfo(info2->type())); 734 735 std::shared_ptr<C2Info> info3(new C2Number2Info(3)); 736 ASSERT_EQ(C2_OK, buffer->setInfo(info3)); 737 EXPECT_EQ(1u, buffer->info().size()); 738 EXPECT_FALSE(buffer->hasInfo(info1->type())); 739 EXPECT_TRUE(buffer->hasInfo(info2->type())); 740 741 removed = buffer->removeInfo(info2->type()); 742 ASSERT_TRUE(removed); 743 EXPECT_EQ(*info3, *removed); 744 EXPECT_TRUE(buffer->info().empty()); 745 EXPECT_FALSE(buffer->hasInfo(info1->type())); 746 EXPECT_FALSE(buffer->hasInfo(info2->type())); 747} 748 749TEST_F(C2BufferTest, MultipleLinearMapTest) { 750 std::shared_ptr<C2BlockPool> pool(makeLinearBlockPool()); 751 constexpr size_t kCapacity = 524288u; 752 for (int i = 0; i < 100; ++i) { 753 std::vector<C2WriteView> wViews; 754 std::vector<C2ReadView> rViews; 755 for (int j = 0; j < 16; ++j) { 756 std::shared_ptr<C2LinearBlock> block; 757 ASSERT_EQ(C2_OK, pool->fetchLinearBlock( 758 kCapacity, 759 { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE }, 760 &block)); 761 wViews.push_back(block->map().get()); 762 C2ConstLinearBlock cBlock = block->share(0, kCapacity / 2, C2Fence()); 763 rViews.push_back(cBlock.map().get()); 764 } 765 } 766} 767 768} // namespace android 769