int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) { ATRACE_CALL(); ALOGV("Surface::queueBuffer"); Mutex::Autolock lock(mMutex); int64_t timestamp; bool isAutoTimestamp = false; if (mTimestamp == NATIVE_WINDOW_TIMESTAMP_AUTO) { timestamp = systemTime(SYSTEM_TIME_MONOTONIC); isAutoTimestamp = true; ALOGV("Surface::queueBuffer making up timestamp: %.2f ms", timestamp / 1000000.f); } else { timestamp = mTimestamp; } int i = getSlotFromBufferLocked(buffer); if (i < 0) { return i; } // Make sure the crop rectangle is entirely inside the buffer. Rect crop; mCrop.intersect(Rect(buffer->width, buffer->height), &crop); #ifdef QCOM_BSP Rect dirtyRect = mDirtyRect; if(dirtyRect.isEmpty()) { int drWidth = mUserWidth ? mUserWidth : mDefaultWidth; int drHeight = mUserHeight ? mUserHeight : mDefaultHeight; dirtyRect = Rect(drWidth, drHeight); } #endif sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE); IGraphicBufferProducer::QueueBufferOutput output; IGraphicBufferProducer::QueueBufferInput input(timestamp, isAutoTimestamp, crop, #ifdef QCOM_BSP dirtyRect, #endif mScalingMode, mTransform, mSwapIntervalZero,fence); status_t err = mGraphicBufferProducer->queueBuffer(i, input, &output); if (err != OK) { ALOGE("queueBuffer: error queuing buffer to SurfaceTexture, %d", err); } uint32_t numPendingBuffers = 0; output.deflate(&mDefaultWidth, &mDefaultHeight, &mTransformHint, &numPendingBuffers); mConsumerRunningBehind = (numPendingBuffers >= 2); #ifdef QCOM_BSP mDirtyRect.clear(); #endif return err; }
// TODO: queue under more complicated situations not involving just a single buffer TEST_F(IGraphicBufferProducerTest, Queue_Succeeds) { ASSERT_NO_FATAL_FAILURE(ConnectProducer()); int dequeuedSlot = -1; sp<Fence> dequeuedFence; ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION & (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence, DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT, TEST_PRODUCER_USAGE_BITS))); EXPECT_LE(0, dequeuedSlot); EXPECT_GT(BufferQueue::NUM_BUFFER_SLOTS, dequeuedSlot); // Request the buffer (pre-requisite for queueing) sp<GraphicBuffer> dequeuedBuffer; ASSERT_OK(mProducer->requestBuffer(dequeuedSlot, &dequeuedBuffer)); // A generic "valid" input IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput(); IGraphicBufferProducer::QueueBufferOutput output; // Queue the buffer back into the BQ ASSERT_OK(mProducer->queueBuffer(dequeuedSlot, input, &output)); { uint32_t width; uint32_t height; uint32_t transformHint; uint32_t numPendingBuffers; output.deflate(&width, &height, &transformHint, &numPendingBuffers); EXPECT_EQ(DEFAULT_WIDTH, width); EXPECT_EQ(DEFAULT_HEIGHT, height); EXPECT_EQ(DEFAULT_TRANSFORM_HINT, transformHint); EXPECT_EQ(1u, numPendingBuffers); // since queueBuffer was called exactly once } // Buffer was not in the dequeued state EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(dequeuedSlot, input, &output)); }