GuiExtPoolItem::GuiExtPoolItem(const sp<IBinder>& token, bool isHwcNeeded, uint32_t poolId, uint32_t /*w*/, uint32_t /*h*/, DefaultKeyedVector< uint32_t, sp<DispInfo> >& dispList, sp<IBinder::DeathRecipient> observer) : mConsumerDeathListener(NULL) //, mGPUUsedBq(NULL) , mGPUUsedProducer(NULL) , mGPUUsedConsumer(NULL) #if !SUPPORT_MULTIBQ_FOR_HWC , mHwcUsedBq(NULL) #endif , mId(poolId) , mIsHwcNeeded(isHwcNeeded) , mGpuUsedBufNum(MAX_GLES_DEQUEUED_NUM) , mProducerPid(-1) , mProducerToken(token) , mProducerDeathObserver(observer) { GUIEXT_LOGV("GuiExtPoolItem ctor, poolId=%d, isHwcNeeded=%d, token=%p", poolId, isHwcNeeded, token.get()); //String8 name(szUsageName[0]); //name.appendFormat("_%d", poolId); //mGPUUsedBq = createBufferQueue(w, h, mGpuUsedBufNum, name); //createBufferQueue(w, h, mGpuUsedBufNum, name, &mGPUUsedProducer, &mGPUUsedConsumer); #ifdef CONFIG_FOR_SOURCE_PQ setOverlaySessionMode(true); #endif if (mIsHwcNeeded) { String8 name(szUsageName[1]); name.appendFormat("_%d", poolId); #if SUPPORT_MULTIBQ_FOR_HWC uint32_t disp_size = dispList.size(); for (uint32_t i = 0; i < disp_size; i++) { uint32_t type = dispList[i]->type; String8 extname(name); extname.appendFormat("_%d", type); sp<HwcBqSlot> slot = new HwcBqSlot(); //slot->bq = createBufferQueue(dispList[i]->w, dispList[i]->h, dispList[i]->bufNum, extname); createBufferQueue(dispList[i]->w, dispList[i]->h, dispList[i]->bufNum, extname, &slot->mProducer, &slot->mConsumer); slot->type = type; slot->bufNum = dispList[i]->bufNum; mHwcUsedBqList.add(type, slot); } #else mHwcUsedBq = createBufferQueue(dispList[0]->w, dispList[0]->h, dispList[i]->bufNum, name); #endif } mProducerPid = (NULL != token->localBinder()) ? getpid() : IPCThreadState::self()->getCallingPid(); for (uint32_t i = 0; i < GUI_EXT_USAGE_MAX; i++) mIsDisconnected[i] = true; }
TEST_F(BufferQueueTest, TestDisallowingAllocation) { createBufferQueue(); sp<DummyConsumer> dc(new DummyConsumer); ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true)); IGraphicBufferProducer::QueueBufferOutput output; ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener, NATIVE_WINDOW_API_CPU, true, &output)); static const uint32_t WIDTH = 320; static const uint32_t HEIGHT = 240; ASSERT_EQ(OK, mConsumer->setDefaultBufferSize(WIDTH, HEIGHT)); int slot; sp<Fence> fence; sp<GraphicBuffer> buffer; // This should return an error since it would require an allocation ASSERT_EQ(OK, mProducer->allowAllocation(false)); ASSERT_EQ(WOULD_BLOCK, mProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN)); // This should succeed, now that we've lifted the prohibition ASSERT_EQ(OK, mProducer->allowAllocation(true)); ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, mProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN)); // Release the previous buffer back to the BufferQueue mProducer->cancelBuffer(slot, fence); // This should fail since we're requesting a different size ASSERT_EQ(OK, mProducer->allowAllocation(false)); ASSERT_EQ(WOULD_BLOCK, mProducer->dequeueBuffer(&slot, &fence, false, WIDTH * 2, HEIGHT * 2, 0, GRALLOC_USAGE_SW_WRITE_OFTEN)); }
TEST_F(BufferQueueTest, AcquireBuffer_ExceedsMaxAcquireCount_Fails) { createBufferQueue(); sp<DummyConsumer> dc(new DummyConsumer); mConsumer->consumerConnect(dc, false); IGraphicBufferProducer::QueueBufferOutput qbo; mProducer->connect(new DummyProducerListener, NATIVE_WINDOW_API_CPU, false, &qbo); mProducer->setBufferCount(4); int slot; sp<Fence> fence; sp<GraphicBuffer> buf; IGraphicBufferProducer::QueueBufferInput qbi(0, false, HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1), NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, Fence::NO_FENCE); BufferItem item; for (int i = 0; i < 2; i++) { ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, mProducer->dequeueBuffer(&slot, &fence, false, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN)); ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf)); ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo)); ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0)); } ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, mProducer->dequeueBuffer(&slot, &fence, false, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN)); ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf)); ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo)); // Acquire the third buffer, which should fail. ASSERT_EQ(INVALID_OPERATION, mConsumer->acquireBuffer(&item, 0)); }
TEST_F(BufferQueueTest, DetachAndReattachOnConsumerSide) { createBufferQueue(); sp<DummyConsumer> dc(new DummyConsumer); ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false)); IGraphicBufferProducer::QueueBufferOutput output; ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener, NATIVE_WINDOW_API_CPU, false, &output)); int slot; sp<Fence> fence; sp<GraphicBuffer> buffer; ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, mProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN)); ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer)); IGraphicBufferProducer::QueueBufferInput input(0, false, HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1), NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, Fence::NO_FENCE); ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output)); ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(-1)); // Index too low ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer( BufferQueueDefs::NUM_BUFFER_SLOTS)); // Index too high ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(0)); // Not acquired BufferItem item; ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0))); ASSERT_EQ(OK, mConsumer->detachBuffer(item.mBuf)); ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(item.mBuf)); // Not acquired uint32_t* dataIn; ASSERT_EQ(OK, item.mGraphicBuffer->lock( GraphicBuffer::USAGE_SW_WRITE_OFTEN, reinterpret_cast<void**>(&dataIn))); *dataIn = TEST_DATA; ASSERT_EQ(OK, item.mGraphicBuffer->unlock()); int newSlot; sp<GraphicBuffer> safeToClobberBuffer; ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(NULL, safeToClobberBuffer)); ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(&newSlot, NULL)); ASSERT_EQ(OK, mConsumer->attachBuffer(&newSlot, item.mGraphicBuffer)); ASSERT_EQ(OK, mConsumer->releaseBuffer(newSlot, 0, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE)); ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, mProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN)); ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer)); uint32_t* dataOut; ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, reinterpret_cast<void**>(&dataOut))); ASSERT_EQ(*dataOut, TEST_DATA); ASSERT_EQ(OK, buffer->unlock()); }
TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithLegalValues_Succeeds) { createBufferQueue(); sp<DummyConsumer> dc(new DummyConsumer); mConsumer->consumerConnect(dc, false); int minBufferCount; ASSERT_NO_FATAL_FAILURE(GetMinUndequeuedBufferCount(&minBufferCount)); EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1)); EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(2)); EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(minBufferCount)); EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount( BufferQueue::MAX_MAX_ACQUIRED_BUFFERS)); }
TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithIllegalValues_ReturnsError) { createBufferQueue(); sp<DummyConsumer> dc(new DummyConsumer); mConsumer->consumerConnect(dc, false); int minBufferCount; ASSERT_NO_FATAL_FAILURE(GetMinUndequeuedBufferCount(&minBufferCount)); EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount( minBufferCount - 1)); EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(0)); EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(-3)); EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount( BufferQueue::MAX_MAX_ACQUIRED_BUFFERS+1)); EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(100)); }
TEST_F(BufferQueueTest, MoveFromConsumerToProducer) { createBufferQueue(); sp<DummyConsumer> dc(new DummyConsumer); ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false)); IGraphicBufferProducer::QueueBufferOutput output; ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener, NATIVE_WINDOW_API_CPU, false, &output)); int slot; sp<Fence> fence; sp<GraphicBuffer> buffer; ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, mProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN)); ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer)); uint32_t* dataIn; ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN, reinterpret_cast<void**>(&dataIn))); *dataIn = TEST_DATA; ASSERT_EQ(OK, buffer->unlock()); IGraphicBufferProducer::QueueBufferInput input(0, false, HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1), NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, Fence::NO_FENCE); ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output)); BufferItem item; ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0))); ASSERT_EQ(OK, mConsumer->detachBuffer(item.mBuf)); int newSlot; ASSERT_EQ(OK, mProducer->attachBuffer(&newSlot, item.mGraphicBuffer)); ASSERT_EQ(OK, mProducer->queueBuffer(newSlot, input, &output)); ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0))); uint32_t* dataOut; ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, reinterpret_cast<void**>(&dataOut))); ASSERT_EQ(*dataOut, TEST_DATA); ASSERT_EQ(OK, item.mGraphicBuffer->unlock()); }
TEST_F(BufferQueueTest, TestGenerationNumbers) { createBufferQueue(); sp<DummyConsumer> dc(new DummyConsumer); ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true)); IGraphicBufferProducer::QueueBufferOutput output; ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener, NATIVE_WINDOW_API_CPU, true, &output)); ASSERT_EQ(OK, mProducer->setGenerationNumber(1)); // Get one buffer to play with int slot; sp<Fence> fence; ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, mProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0, 0)); sp<GraphicBuffer> buffer; ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer)); // Ensure that the generation number we set propagates to allocated buffers ASSERT_EQ(1U, buffer->getGenerationNumber()); ASSERT_EQ(OK, mProducer->detachBuffer(slot)); ASSERT_EQ(OK, mProducer->setGenerationNumber(2)); // These should fail, since we've changed the generation number on the queue int outSlot; ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(&outSlot, buffer)); ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(&outSlot, buffer)); buffer->setGenerationNumber(2); // This should succeed now that we've changed the buffer's generation number ASSERT_EQ(OK, mProducer->attachBuffer(&outSlot, buffer)); ASSERT_EQ(OK, mProducer->detachBuffer(outSlot)); // This should also succeed with the new generation number ASSERT_EQ(OK, mConsumer->attachBuffer(&outSlot, buffer)); }