Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
1 /*
2 * Copyright (C) 2012 The Android Open Source Project
3 * Copyright (C) 2013 Mozilla Foundation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
18 #define LOG_TAG "GonkBufferQueue"
19 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
20 #define LOG_NDEBUG 0
22 #define GL_GLEXT_PROTOTYPES
23 #define EGL_EGLEXT_PROTOTYPES
25 #include <utils/Log.h>
27 #include "mozilla/layers/GrallocTextureClient.h"
28 #include "mozilla/layers/ImageBridgeChild.h"
30 #include "GonkBufferQueueJB.h"
32 // Macros for including the GonkBufferQueue name in log messages
33 #define ST_LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
34 #define ST_LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
35 #define ST_LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
36 #define ST_LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
37 #define ST_LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
39 #define ATRACE_BUFFER_INDEX(index)
41 using namespace mozilla;
42 using namespace mozilla::gfx;
43 using namespace mozilla::layers;
45 namespace android {
47 // Get an ID that's unique within this process.
48 static int32_t createProcessUniqueId() {
49 static volatile int32_t globalCounter = 0;
50 return android_atomic_inc(&globalCounter);
51 }
53 static const char* scalingModeName(int scalingMode) {
54 switch (scalingMode) {
55 case NATIVE_WINDOW_SCALING_MODE_FREEZE: return "FREEZE";
56 case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: return "SCALE_TO_WINDOW";
57 case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP: return "SCALE_CROP";
58 default: return "Unknown";
59 }
60 }
62 class nsProxyReleaseTask : public Task
63 {
64 public:
65 nsProxyReleaseTask(TextureClient* aClient)
66 : mTextureClient(aClient) {
67 }
69 virtual void Run() MOZ_OVERRIDE
70 {
71 mTextureClient = nullptr;
72 }
74 private:
75 mozilla::RefPtr<TextureClient> mTextureClient;
76 };
78 GonkBufferQueue::GonkBufferQueue(bool allowSynchronousMode,
79 const sp<IGraphicBufferAlloc>& allocator) :
80 mDefaultWidth(1),
81 mDefaultHeight(1),
82 mMaxAcquiredBufferCount(1),
83 mDefaultMaxBufferCount(2),
84 mOverrideMaxBufferCount(0),
85 mSynchronousMode(true), // GonkBufferQueue always works in sync mode.
86 mAllowSynchronousMode(allowSynchronousMode),
87 mConnectedApi(NO_CONNECTED_API),
88 mAbandoned(false),
89 mFrameCounter(0),
90 mBufferHasBeenQueued(false),
91 mDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888),
92 mConsumerUsageBits(0),
93 mTransformHint(0)
94 {
95 // Choose a name using the PID and a process-unique ID.
96 mConsumerName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
98 ST_LOGV("GonkBufferQueue");
99 }
101 GonkBufferQueue::~GonkBufferQueue() {
102 ST_LOGV("~GonkBufferQueue");
103 }
105 status_t GonkBufferQueue::setDefaultMaxBufferCountLocked(int count) {
106 if (count < 2 || count > NUM_BUFFER_SLOTS)
107 return BAD_VALUE;
109 mDefaultMaxBufferCount = count;
110 mDequeueCondition.broadcast();
112 return NO_ERROR;
113 }
115 bool GonkBufferQueue::isSynchronousMode() const {
116 Mutex::Autolock lock(mMutex);
117 return mSynchronousMode;
118 }
120 void GonkBufferQueue::setConsumerName(const String8& name) {
121 Mutex::Autolock lock(mMutex);
122 mConsumerName = name;
123 }
125 status_t GonkBufferQueue::setDefaultBufferFormat(uint32_t defaultFormat) {
126 Mutex::Autolock lock(mMutex);
127 mDefaultBufferFormat = defaultFormat;
128 return NO_ERROR;
129 }
131 status_t GonkBufferQueue::setConsumerUsageBits(uint32_t usage) {
132 Mutex::Autolock lock(mMutex);
133 mConsumerUsageBits = usage;
134 return NO_ERROR;
135 }
137 status_t GonkBufferQueue::setTransformHint(uint32_t hint) {
138 ST_LOGV("setTransformHint: %02x", hint);
139 Mutex::Autolock lock(mMutex);
140 mTransformHint = hint;
141 return NO_ERROR;
142 }
144 TemporaryRef<TextureClient>
145 GonkBufferQueue::getTextureClientFromBuffer(ANativeWindowBuffer* buffer)
146 {
147 Mutex::Autolock _l(mMutex);
148 if (buffer == NULL) {
149 ST_LOGE("getSlotFromBufferLocked: encountered NULL buffer");
150 return nullptr;
151 }
153 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
154 if (mSlots[i].mGraphicBuffer != NULL && mSlots[i].mGraphicBuffer->handle == buffer->handle) {
155 return mSlots[i].mTextureClient;
156 }
157 }
158 ST_LOGE("getSlotFromBufferLocked: unknown buffer: %p", buffer->handle);
159 return nullptr;
160 }
162 int GonkBufferQueue::getSlotFromTextureClientLocked(
163 TextureClient* client) const
164 {
165 if (client == NULL) {
166 ST_LOGE("getSlotFromBufferLocked: encountered NULL buffer");
167 return BAD_VALUE;
168 }
170 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
171 if (mSlots[i].mTextureClient == client) {
172 return i;
173 }
174 }
175 ST_LOGE("getSlotFromBufferLocked: unknown TextureClient: %p", client);
176 return BAD_VALUE;
177 }
180 status_t GonkBufferQueue::setBufferCount(int bufferCount) {
181 ST_LOGV("setBufferCount: count=%d", bufferCount);
183 sp<ConsumerListener> listener;
184 {
185 Mutex::Autolock lock(mMutex);
187 if (mAbandoned) {
188 ST_LOGE("setBufferCount: GonkBufferQueue has been abandoned!");
189 return NO_INIT;
190 }
191 if (bufferCount > NUM_BUFFER_SLOTS) {
192 ST_LOGE("setBufferCount: bufferCount too large (max %d)",
193 NUM_BUFFER_SLOTS);
194 return BAD_VALUE;
195 }
197 // Error out if the user has dequeued buffers
198 int maxBufferCount = getMaxBufferCountLocked();
199 for (int i=0 ; i<maxBufferCount; i++) {
200 if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) {
201 ST_LOGE("setBufferCount: client owns some buffers");
202 return -EINVAL;
203 }
204 }
206 const int minBufferSlots = getMinMaxBufferCountLocked();
207 if (bufferCount == 0) {
208 mOverrideMaxBufferCount = 0;
209 mDequeueCondition.broadcast();
210 return NO_ERROR;
211 }
213 if (bufferCount < minBufferSlots) {
214 ST_LOGE("setBufferCount: requested buffer count (%d) is less than "
215 "minimum (%d)", bufferCount, minBufferSlots);
216 return BAD_VALUE;
217 }
219 // here we're guaranteed that the client doesn't have dequeued buffers
220 // and will release all of its buffer references.
221 //
222 // XXX: Should this use drainQueueAndFreeBuffersLocked instead?
223 freeAllBuffersLocked();
224 mOverrideMaxBufferCount = bufferCount;
225 mBufferHasBeenQueued = false;
226 mDequeueCondition.broadcast();
227 listener = mConsumerListener;
228 } // scope for lock
230 if (listener != NULL) {
231 listener->onBuffersReleased();
232 }
234 return NO_ERROR;
235 }
237 int GonkBufferQueue::query(int what, int* outValue)
238 {
239 Mutex::Autolock lock(mMutex);
241 if (mAbandoned) {
242 ST_LOGE("query: GonkBufferQueue has been abandoned!");
243 return NO_INIT;
244 }
246 int value;
247 switch (what) {
248 case NATIVE_WINDOW_WIDTH:
249 value = mDefaultWidth;
250 break;
251 case NATIVE_WINDOW_HEIGHT:
252 value = mDefaultHeight;
253 break;
254 case NATIVE_WINDOW_FORMAT:
255 value = mDefaultBufferFormat;
256 break;
257 case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
258 value = getMinUndequeuedBufferCountLocked();
259 break;
260 case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND:
261 value = (mQueue.size() >= 2);
262 break;
263 default:
264 return BAD_VALUE;
265 }
266 outValue[0] = value;
267 return NO_ERROR;
268 }
270 status_t GonkBufferQueue::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
271 ST_LOGV("requestBuffer: slot=%d", slot);
272 Mutex::Autolock lock(mMutex);
273 if (mAbandoned) {
274 ST_LOGE("requestBuffer: GonkBufferQueue has been abandoned!");
275 return NO_INIT;
276 }
277 int maxBufferCount = getMaxBufferCountLocked();
278 if (slot < 0 || maxBufferCount <= slot) {
279 ST_LOGE("requestBuffer: slot index out of range [0, %d]: %d",
280 maxBufferCount, slot);
281 return BAD_VALUE;
282 } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
283 // XXX: I vaguely recall there was some reason this can be valid, but
284 // for the life of me I can't recall under what circumstances that's
285 // the case.
286 ST_LOGE("requestBuffer: slot %d is not owned by the client (state=%d)",
287 slot, mSlots[slot].mBufferState);
288 return BAD_VALUE;
289 }
290 mSlots[slot].mRequestBufferCalled = true;
291 *buf = mSlots[slot].mGraphicBuffer;
292 return NO_ERROR;
293 }
295 status_t GonkBufferQueue::dequeueBuffer(int *outBuf, sp<Fence>* outFence,
296 uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
297 ST_LOGV("dequeueBuffer: w=%d h=%d fmt=%#x usage=%#x", w, h, format, usage);
299 if ((w && !h) || (!w && h)) {
300 ST_LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h);
301 return BAD_VALUE;
302 }
304 status_t returnFlags(OK);
305 int buf = INVALID_BUFFER_SLOT;
307 { // Scope for the lock
308 Mutex::Autolock lock(mMutex);
310 if (format == 0) {
311 format = mDefaultBufferFormat;
312 }
313 // turn on usage bits the consumer requested
314 usage |= mConsumerUsageBits;
316 int found = -1;
317 int dequeuedCount = 0;
318 bool tryAgain = true;
319 while (tryAgain) {
320 if (mAbandoned) {
321 ST_LOGE("dequeueBuffer: GonkBufferQueue has been abandoned!");
322 return NO_INIT;
323 }
325 const int maxBufferCount = getMaxBufferCountLocked();
327 // Free up any buffers that are in slots beyond the max buffer
328 // count.
329 //for (int i = maxBufferCount; i < NUM_BUFFER_SLOTS; i++) {
330 // assert(mSlots[i].mBufferState == BufferSlot::FREE);
331 // if (mSlots[i].mGraphicBuffer != NULL) {
332 // freeBufferLocked(i);
333 // returnFlags |= IGraphicBufferProducer::RELEASE_ALL_BUFFERS;
334 // }
335 //}
337 // look for a free buffer to give to the client
338 found = INVALID_BUFFER_SLOT;
339 dequeuedCount = 0;
340 for (int i = 0; i < maxBufferCount; i++) {
341 const int state = mSlots[i].mBufferState;
342 if (state == BufferSlot::DEQUEUED) {
343 dequeuedCount++;
344 }
346 if (state == BufferSlot::FREE) {
347 /* We return the oldest of the free buffers to avoid
348 * stalling the producer if possible. This is because
349 * the consumer may still have pending reads of the
350 * buffers in flight.
351 */
352 if ((found < 0) ||
353 mSlots[i].mFrameNumber < mSlots[found].mFrameNumber) {
354 found = i;
355 }
356 }
357 }
359 // clients are not allowed to dequeue more than one buffer
360 // if they didn't set a buffer count.
361 if (!mOverrideMaxBufferCount && dequeuedCount) {
362 ST_LOGE("dequeueBuffer: can't dequeue multiple buffers without "
363 "setting the buffer count");
364 return -EINVAL;
365 }
367 // See whether a buffer has been queued since the last
368 // setBufferCount so we know whether to perform the min undequeued
369 // buffers check below.
370 if (mBufferHasBeenQueued) {
371 // make sure the client is not trying to dequeue more buffers
372 // than allowed.
373 const int newUndequeuedCount = maxBufferCount - (dequeuedCount+1);
374 const int minUndequeuedCount = getMinUndequeuedBufferCountLocked();
375 if (newUndequeuedCount < minUndequeuedCount) {
376 ST_LOGE("dequeueBuffer: min undequeued buffer count (%d) "
377 "exceeded (dequeued=%d undequeudCount=%d)",
378 minUndequeuedCount, dequeuedCount,
379 newUndequeuedCount);
380 return -EBUSY;
381 }
382 }
384 // If no buffer is found, wait for a buffer to be released or for
385 // the max buffer count to change.
386 tryAgain = found == INVALID_BUFFER_SLOT;
387 if (tryAgain) {
388 mDequeueCondition.wait(mMutex);
389 }
390 }
393 if (found == INVALID_BUFFER_SLOT) {
394 // This should not happen.
395 ST_LOGE("dequeueBuffer: no available buffer slots");
396 return -EBUSY;
397 }
399 buf = found;
400 *outBuf = found;
402 const bool useDefaultSize = !w && !h;
403 if (useDefaultSize) {
404 // use the default size
405 w = mDefaultWidth;
406 h = mDefaultHeight;
407 }
409 mSlots[buf].mBufferState = BufferSlot::DEQUEUED;
411 const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer);
412 if ((buffer == NULL) ||
413 (uint32_t(buffer->width) != w) ||
414 (uint32_t(buffer->height) != h) ||
415 (uint32_t(buffer->format) != format) ||
416 ((uint32_t(buffer->usage) & usage) != usage))
417 {
418 mSlots[buf].mAcquireCalled = false;
419 mSlots[buf].mGraphicBuffer = NULL;
420 mSlots[buf].mRequestBufferCalled = false;
421 mSlots[buf].mFence = Fence::NO_FENCE;
422 if (mSlots[buf].mTextureClient) {
423 mSlots[buf].mTextureClient->ClearRecycleCallback();
424 // release TextureClient in ImageBridge thread
425 nsProxyReleaseTask* task = new nsProxyReleaseTask(mSlots[buf].mTextureClient);
426 mSlots[buf].mTextureClient = NULL;
427 ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask(FROM_HERE, task);
428 }
429 returnFlags |= IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION;
430 }
432 *outFence = mSlots[buf].mFence;
433 mSlots[buf].mFence = Fence::NO_FENCE;
434 } // end lock scope
436 sp<GraphicBuffer> graphicBuffer;
437 if (returnFlags & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) {
438 RefPtr<GrallocTextureClientOGL> textureClient =
439 new GrallocTextureClientOGL(ImageBridgeChild::GetSingleton(),
440 gfx::SurfaceFormat::UNKNOWN,
441 gfx::BackendType::NONE,
442 TEXTURE_DEALLOCATE_CLIENT);
443 usage |= GraphicBuffer::USAGE_HW_TEXTURE;
444 bool result = textureClient->AllocateGralloc(IntSize(w, h), format, usage);
445 sp<GraphicBuffer> graphicBuffer = textureClient->GetGraphicBuffer();
446 if (!result || !graphicBuffer.get()) {
447 ST_LOGE("dequeueBuffer: failed to alloc gralloc buffer");
448 return -ENOMEM;
449 }
451 { // Scope for the lock
452 Mutex::Autolock lock(mMutex);
454 if (mAbandoned) {
455 ST_LOGE("dequeueBuffer: SurfaceTexture has been abandoned!");
456 return NO_INIT;
457 }
459 mSlots[buf].mGraphicBuffer = graphicBuffer;
460 mSlots[buf].mTextureClient = textureClient;
461 ST_LOGD("dequeueBuffer: returning slot=%d buf=%p ", buf,
462 mSlots[buf].mGraphicBuffer->handle);
463 //mSlots[*outBuf].mGraphicBuffer = graphicBuffer;
464 }
465 }
467 ST_LOGV("dequeueBuffer: returning slot=%d buf=%p flags=%#x", *outBuf,
468 mSlots[*outBuf].mGraphicBuffer->handle, returnFlags);
470 return returnFlags;
471 }
473 status_t GonkBufferQueue::setSynchronousMode(bool enabled) {
474 return NO_ERROR;
475 }
477 status_t GonkBufferQueue::queueBuffer(int buf,
478 const QueueBufferInput& input, QueueBufferOutput* output) {
480 Rect crop;
481 uint32_t transform;
482 int scalingMode;
483 int64_t timestamp;
484 sp<Fence> fence;
486 input.deflate(×tamp, &crop, &scalingMode, &transform, &fence);
488 #if ANDROID_VERSION >= 18
489 if (fence == NULL) {
490 ST_LOGE("queueBuffer: fence is NULL");
491 return BAD_VALUE;
492 }
493 #endif
495 ST_LOGV("queueBuffer: slot=%d time=%#llx crop=[%d,%d,%d,%d] tr=%#x "
496 "scale=%s",
497 buf, timestamp, crop.left, crop.top, crop.right, crop.bottom,
498 transform, scalingModeName(scalingMode));
500 sp<ConsumerListener> listener;
502 { // scope for the lock
503 Mutex::Autolock lock(mMutex);
504 if (mAbandoned) {
505 ST_LOGE("queueBuffer: GonkBufferQueue has been abandoned!");
506 return NO_INIT;
507 }
508 int maxBufferCount = getMaxBufferCountLocked();
509 if (buf < 0 || buf >= maxBufferCount) {
510 ST_LOGE("queueBuffer: slot index out of range [0, %d]: %d",
511 maxBufferCount, buf);
512 return -EINVAL;
513 } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
514 ST_LOGE("queueBuffer: slot %d is not owned by the client "
515 "(state=%d)", buf, mSlots[buf].mBufferState);
516 return -EINVAL;
517 } else if (!mSlots[buf].mRequestBufferCalled) {
518 ST_LOGE("queueBuffer: slot %d was enqueued without requesting a "
519 "buffer", buf);
520 return -EINVAL;
521 }
523 const sp<GraphicBuffer>& graphicBuffer(mSlots[buf].mGraphicBuffer);
524 Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight());
525 Rect croppedCrop;
526 crop.intersect(bufferRect, &croppedCrop);
527 if (croppedCrop != crop) {
528 ST_LOGE("queueBuffer: crop rect is not contained within the "
529 "buffer in slot %d", buf);
530 return -EINVAL;
531 }
533 if (mSynchronousMode) {
534 // In synchronous mode we queue all buffers in a FIFO.
535 mQueue.push_back(buf);
537 // Synchronous mode always signals that an additional frame should
538 // be consumed.
539 listener = mConsumerListener;
540 } else {
541 // In asynchronous mode we only keep the most recent buffer.
542 if (mQueue.empty()) {
543 mQueue.push_back(buf);
545 // Asynchronous mode only signals that a frame should be
546 // consumed if no previous frame was pending. If a frame were
547 // pending then the consumer would have already been notified.
548 listener = mConsumerListener;
549 } else {
550 Fifo::iterator front(mQueue.begin());
551 // buffer currently queued is freed
552 mSlots[*front].mBufferState = BufferSlot::FREE;
553 // and we record the new buffer index in the queued list
554 *front = buf;
555 }
556 }
558 mSlots[buf].mTimestamp = timestamp;
559 mSlots[buf].mCrop = crop;
560 mSlots[buf].mTransform = transform;
561 mSlots[buf].mFence = fence;
563 switch (scalingMode) {
564 case NATIVE_WINDOW_SCALING_MODE_FREEZE:
565 case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
566 case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
567 break;
568 default:
569 ST_LOGE("unknown scaling mode: %d (ignoring)", scalingMode);
570 scalingMode = mSlots[buf].mScalingMode;
571 break;
572 }
574 mSlots[buf].mBufferState = BufferSlot::QUEUED;
575 mSlots[buf].mScalingMode = scalingMode;
576 mFrameCounter++;
577 mSlots[buf].mFrameNumber = mFrameCounter;
579 mBufferHasBeenQueued = true;
580 mDequeueCondition.broadcast();
582 output->inflate(mDefaultWidth, mDefaultHeight, mTransformHint,
583 mQueue.size());
584 } // scope for the lock
586 // call back without lock held
587 if (listener != 0) {
588 listener->onFrameAvailable();
589 }
590 return NO_ERROR;
591 }
593 #if ANDROID_VERSION == 17
594 void GonkBufferQueue::cancelBuffer(int buf, sp<Fence> fence) {
595 #else
596 void GonkBufferQueue::cancelBuffer(int buf, const sp<Fence>& fence) {
597 #endif
599 ST_LOGV("cancelBuffer: slot=%d", buf);
600 Mutex::Autolock lock(mMutex);
602 if (mAbandoned) {
603 ST_LOGW("cancelBuffer: GonkBufferQueue has been abandoned!");
604 return;
605 }
607 int maxBufferCount = getMaxBufferCountLocked();
608 if (buf < 0 || buf >= maxBufferCount) {
609 ST_LOGE("cancelBuffer: slot index out of range [0, %d]: %d",
610 maxBufferCount, buf);
611 return;
612 } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
613 ST_LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)",
614 buf, mSlots[buf].mBufferState);
615 return;
616 #if ANDROID_VERSION >= 18
617 } else if (fence == NULL) {
618 ST_LOGE("cancelBuffer: fence is NULL");
619 return;
620 #endif
621 }
622 mSlots[buf].mBufferState = BufferSlot::FREE;
623 mSlots[buf].mFrameNumber = 0;
624 mSlots[buf].mFence = fence;
625 mDequeueCondition.broadcast();
626 }
628 status_t GonkBufferQueue::connect(int api, QueueBufferOutput* output) {
629 ST_LOGV("connect: api=%d", api);
630 Mutex::Autolock lock(mMutex);
632 if (mAbandoned) {
633 ST_LOGE("connect: GonkBufferQueue has been abandoned!");
634 return NO_INIT;
635 }
637 if (mConsumerListener == NULL) {
638 ST_LOGE("connect: GonkBufferQueue has no consumer!");
639 return NO_INIT;
640 }
642 int err = NO_ERROR;
643 switch (api) {
644 case NATIVE_WINDOW_API_EGL:
645 case NATIVE_WINDOW_API_CPU:
646 case NATIVE_WINDOW_API_MEDIA:
647 case NATIVE_WINDOW_API_CAMERA:
648 if (mConnectedApi != NO_CONNECTED_API) {
649 ST_LOGE("connect: already connected (cur=%d, req=%d)",
650 mConnectedApi, api);
651 err = -EINVAL;
652 } else {
653 mConnectedApi = api;
654 output->inflate(mDefaultWidth, mDefaultHeight, mTransformHint,
655 mQueue.size());
656 }
657 break;
658 default:
659 err = -EINVAL;
660 break;
661 }
663 mBufferHasBeenQueued = false;
665 return err;
666 }
668 status_t GonkBufferQueue::disconnect(int api) {
669 ST_LOGV("disconnect: api=%d", api);
671 int err = NO_ERROR;
672 sp<ConsumerListener> listener;
674 { // Scope for the lock
675 Mutex::Autolock lock(mMutex);
677 if (mAbandoned) {
678 // it is not really an error to disconnect after the surface
679 // has been abandoned, it should just be a no-op.
680 return NO_ERROR;
681 }
683 switch (api) {
684 case NATIVE_WINDOW_API_EGL:
685 case NATIVE_WINDOW_API_CPU:
686 case NATIVE_WINDOW_API_MEDIA:
687 case NATIVE_WINDOW_API_CAMERA:
688 if (mConnectedApi == api) {
689 freeAllBuffersLocked();
690 mConnectedApi = NO_CONNECTED_API;
691 mDequeueCondition.broadcast();
692 listener = mConsumerListener;
693 } else {
694 ST_LOGE("disconnect: connected to another api (cur=%d, req=%d)",
695 mConnectedApi, api);
696 err = -EINVAL;
697 }
698 break;
699 default:
700 ST_LOGE("disconnect: unknown API %d", api);
701 err = -EINVAL;
702 break;
703 }
704 }
706 if (listener != NULL) {
707 listener->onBuffersReleased();
708 }
710 return err;
711 }
713 void GonkBufferQueue::dump(String8& result) const
714 {
715 char buffer[1024];
716 GonkBufferQueue::dump(result, "", buffer, 1024);
717 }
719 void GonkBufferQueue::dump(String8& result, const char* prefix,
720 char* buffer, size_t SIZE) const
721 {
722 Mutex::Autolock _l(mMutex);
724 String8 fifo;
725 int fifoSize = 0;
726 Fifo::const_iterator i(mQueue.begin());
727 while (i != mQueue.end()) {
728 snprintf(buffer, SIZE, "%02d ", *i++);
729 fifoSize++;
730 fifo.append(buffer);
731 }
733 int maxBufferCount = getMaxBufferCountLocked();
735 snprintf(buffer, SIZE,
736 "%s-BufferQueue maxBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], "
737 "default-format=%d, transform-hint=%02x, FIFO(%d)={%s}\n",
738 prefix, maxBufferCount, mSynchronousMode, mDefaultWidth,
739 mDefaultHeight, mDefaultBufferFormat, mTransformHint,
740 fifoSize, fifo.string());
741 result.append(buffer);
744 struct {
745 const char * operator()(int state) const {
746 switch (state) {
747 case BufferSlot::DEQUEUED: return "DEQUEUED";
748 case BufferSlot::QUEUED: return "QUEUED";
749 case BufferSlot::FREE: return "FREE";
750 case BufferSlot::ACQUIRED: return "ACQUIRED";
751 default: return "Unknown";
752 }
753 }
754 } stateName;
756 for (int i=0 ; i<maxBufferCount ; i++) {
757 const BufferSlot& slot(mSlots[i]);
758 snprintf(buffer, SIZE,
759 "%s%s[%02d] "
760 "state=%-8s, crop=[%d,%d,%d,%d], "
761 "xform=0x%02x, time=%#llx, scale=%s",
762 prefix, (slot.mBufferState == BufferSlot::ACQUIRED)?">":" ", i,
763 stateName(slot.mBufferState),
764 slot.mCrop.left, slot.mCrop.top, slot.mCrop.right,
765 slot.mCrop.bottom, slot.mTransform, slot.mTimestamp,
766 scalingModeName(slot.mScalingMode)
767 );
768 result.append(buffer);
770 const sp<GraphicBuffer>& buf(slot.mGraphicBuffer);
771 if (buf != NULL) {
772 snprintf(buffer, SIZE,
773 ", %p [%4ux%4u:%4u,%3X]",
774 buf->handle, buf->width, buf->height, buf->stride,
775 buf->format);
776 result.append(buffer);
777 }
778 result.append("\n");
779 }
780 }
782 void GonkBufferQueue::freeAllBuffersLocked()
783 {
784 ALOGW_IF(!mQueue.isEmpty(),
785 "freeAllBuffersLocked called but mQueue is not empty");
786 mQueue.clear();
787 mBufferHasBeenQueued = false;
788 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
789 mSlots[i].mGraphicBuffer = 0;
790 if (mSlots[i].mTextureClient) {
791 mSlots[i].mTextureClient->ClearRecycleCallback();
792 // release TextureClient in ImageBridge thread
793 nsProxyReleaseTask* task = new nsProxyReleaseTask(mSlots[i].mTextureClient);
794 mSlots[i].mTextureClient = NULL;
795 ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask(FROM_HERE, task);
796 }
797 if (mSlots[i].mBufferState == BufferSlot::ACQUIRED) {
798 mSlots[i].mNeedsCleanupOnRelease = true;
799 }
800 mSlots[i].mBufferState = BufferSlot::FREE;
801 mSlots[i].mFrameNumber = 0;
802 mSlots[i].mAcquireCalled = false;
803 // destroy fence as GonkBufferQueue now takes ownership
804 mSlots[i].mFence = Fence::NO_FENCE;
805 }
806 }
808 status_t GonkBufferQueue::acquireBuffer(BufferItem *buffer) {
809 Mutex::Autolock _l(mMutex);
811 // Check that the consumer doesn't currently have the maximum number of
812 // buffers acquired. We allow the max buffer count to be exceeded by one
813 // buffer, so that the consumer can successfully set up the newly acquired
814 // buffer before releasing the old one.
815 int numAcquiredBuffers = 0;
816 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
817 if (mSlots[i].mBufferState == BufferSlot::ACQUIRED) {
818 numAcquiredBuffers++;
819 }
820 }
821 if (numAcquiredBuffers >= mMaxAcquiredBufferCount+1) {
822 ST_LOGE("acquireBuffer: max acquired buffer count reached: %d (max=%d)",
823 numAcquiredBuffers, mMaxAcquiredBufferCount);
824 return INVALID_OPERATION;
825 }
827 // check if queue is empty
828 // In asynchronous mode the list is guaranteed to be one buffer
829 // deep, while in synchronous mode we use the oldest buffer.
830 if (!mQueue.empty()) {
831 Fifo::iterator front(mQueue.begin());
832 int buf = *front;
834 // In android, when the buffer is aquired by BufferConsumer,
835 // BufferQueue releases a reference to the buffer and
836 // it's ownership moves to the BufferConsumer.
837 // In b2g, GonkBufferQueue continues to have a buffer ownership.
838 // It is necessary to free buffer via ImageBridgeChild.
840 //if (mSlots[buf].mAcquireCalled) {
841 // buffer->mGraphicBuffer = NULL;
842 //} else {
843 // buffer->mGraphicBuffer = mSlots[buf].mGraphicBuffer;
844 //}
845 buffer->mGraphicBuffer = mSlots[buf].mGraphicBuffer;
846 buffer->mCrop = mSlots[buf].mCrop;
847 buffer->mTransform = mSlots[buf].mTransform;
848 buffer->mScalingMode = mSlots[buf].mScalingMode;
849 buffer->mFrameNumber = mSlots[buf].mFrameNumber;
850 buffer->mTimestamp = mSlots[buf].mTimestamp;
851 buffer->mBuf = buf;
852 buffer->mFence = mSlots[buf].mFence;
854 mSlots[buf].mAcquireCalled = true;
855 mSlots[buf].mNeedsCleanupOnRelease = false;
856 mSlots[buf].mBufferState = BufferSlot::ACQUIRED;
857 mSlots[buf].mFence = Fence::NO_FENCE;
859 mQueue.erase(front);
860 mDequeueCondition.broadcast();
861 } else {
862 return NO_BUFFER_AVAILABLE;
863 }
865 return NO_ERROR;
866 }
868 status_t GonkBufferQueue::releaseBuffer(int buf, const sp<Fence>& fence) {
869 Mutex::Autolock _l(mMutex);
871 #if ANDROID_VERSION == 17
872 if (buf == INVALID_BUFFER_SLOT) {
873 #else
874 if (buf == INVALID_BUFFER_SLOT || fence == NULL) {
875 #endif
876 return BAD_VALUE;
877 }
879 mSlots[buf].mFence = fence;
881 // The buffer can now only be released if its in the acquired state
882 if (mSlots[buf].mBufferState == BufferSlot::ACQUIRED) {
883 mSlots[buf].mBufferState = BufferSlot::FREE;
884 } else if (mSlots[buf].mNeedsCleanupOnRelease) {
885 ST_LOGV("releasing a stale buf %d its state was %d", buf, mSlots[buf].mBufferState);
886 mSlots[buf].mNeedsCleanupOnRelease = false;
887 return STALE_BUFFER_SLOT;
888 } else {
889 ST_LOGE("attempted to release buf %d but its state was %d", buf, mSlots[buf].mBufferState);
890 return -EINVAL;
891 }
893 mDequeueCondition.broadcast();
894 return NO_ERROR;
895 }
897 status_t GonkBufferQueue::consumerConnect(const sp<ConsumerListener>& consumerListener) {
898 ST_LOGV("consumerConnect");
899 Mutex::Autolock lock(mMutex);
901 if (mAbandoned) {
902 ST_LOGE("consumerConnect: GonkBufferQueue has been abandoned!");
903 return NO_INIT;
904 }
905 if (consumerListener == NULL) {
906 ST_LOGE("consumerConnect: consumerListener may not be NULL");
907 return BAD_VALUE;
908 }
910 mConsumerListener = consumerListener;
912 return NO_ERROR;
913 }
915 status_t GonkBufferQueue::consumerDisconnect() {
916 ST_LOGV("consumerDisconnect");
917 Mutex::Autolock lock(mMutex);
919 if (mConsumerListener == NULL) {
920 ST_LOGE("consumerDisconnect: No consumer is connected!");
921 return -EINVAL;
922 }
924 mAbandoned = true;
925 mConsumerListener = NULL;
926 mQueue.clear();
927 freeAllBuffersLocked();
928 mDequeueCondition.broadcast();
929 return NO_ERROR;
930 }
932 status_t GonkBufferQueue::getReleasedBuffers(uint32_t* slotMask) {
933 ST_LOGV("getReleasedBuffers");
934 Mutex::Autolock lock(mMutex);
936 if (mAbandoned) {
937 ST_LOGE("getReleasedBuffers: GonkBufferQueue has been abandoned!");
938 return NO_INIT;
939 }
941 uint32_t mask = 0;
942 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
943 if (!mSlots[i].mAcquireCalled) {
944 mask |= 1 << i;
945 }
946 }
947 *slotMask = mask;
949 ST_LOGV("getReleasedBuffers: returning mask %#x", mask);
950 return NO_ERROR;
951 }
953 status_t GonkBufferQueue::setDefaultBufferSize(uint32_t w, uint32_t h)
954 {
955 ST_LOGV("setDefaultBufferSize: w=%d, h=%d", w, h);
956 if (!w || !h) {
957 ST_LOGE("setDefaultBufferSize: dimensions cannot be 0 (w=%d, h=%d)",
958 w, h);
959 return BAD_VALUE;
960 }
962 Mutex::Autolock lock(mMutex);
963 mDefaultWidth = w;
964 mDefaultHeight = h;
965 return NO_ERROR;
966 }
968 status_t GonkBufferQueue::setDefaultMaxBufferCount(int bufferCount) {
969 Mutex::Autolock lock(mMutex);
970 return setDefaultMaxBufferCountLocked(bufferCount);
971 }
973 status_t GonkBufferQueue::setMaxAcquiredBufferCount(int maxAcquiredBuffers) {
974 Mutex::Autolock lock(mMutex);
975 if (maxAcquiredBuffers < 1 || maxAcquiredBuffers > MAX_MAX_ACQUIRED_BUFFERS) {
976 ST_LOGE("setMaxAcquiredBufferCount: invalid count specified: %d",
977 maxAcquiredBuffers);
978 return BAD_VALUE;
979 }
980 if (mConnectedApi != NO_CONNECTED_API) {
981 return INVALID_OPERATION;
982 }
983 mMaxAcquiredBufferCount = maxAcquiredBuffers;
984 return NO_ERROR;
985 }
987 int GonkBufferQueue::getMinMaxBufferCountLocked() const {
988 return getMinUndequeuedBufferCountLocked() + 1;
989 }
991 int GonkBufferQueue::getMinUndequeuedBufferCountLocked() const {
992 return mSynchronousMode ? mMaxAcquiredBufferCount :
993 mMaxAcquiredBufferCount + 1;
994 }
996 int GonkBufferQueue::getMaxBufferCountLocked() const {
997 int minMaxBufferCount = getMinMaxBufferCountLocked();
999 int maxBufferCount = mDefaultMaxBufferCount;
1000 if (maxBufferCount < minMaxBufferCount) {
1001 maxBufferCount = minMaxBufferCount;
1002 }
1003 if (mOverrideMaxBufferCount != 0) {
1004 assert(mOverrideMaxBufferCount >= minMaxBufferCount);
1005 maxBufferCount = mOverrideMaxBufferCount;
1006 }
1008 // Any buffers that are dequeued by the producer or sitting in the queue
1009 // waiting to be consumed need to have their slots preserved. Such
1010 // buffers will temporarily keep the max buffer count up until the slots
1011 // no longer need to be preserved.
1012 for (int i = maxBufferCount; i < NUM_BUFFER_SLOTS; i++) {
1013 BufferSlot::BufferState state = mSlots[i].mBufferState;
1014 if (state == BufferSlot::QUEUED || state == BufferSlot::DEQUEUED) {
1015 maxBufferCount = i + 1;
1016 }
1017 }
1019 return maxBufferCount;
1020 }
1022 GonkBufferQueue::ProxyConsumerListener::ProxyConsumerListener(
1023 const wp<GonkBufferQueue::ConsumerListener>& consumerListener):
1024 mConsumerListener(consumerListener) {}
1026 GonkBufferQueue::ProxyConsumerListener::~ProxyConsumerListener() {}
1028 void GonkBufferQueue::ProxyConsumerListener::onFrameAvailable() {
1029 sp<GonkBufferQueue::ConsumerListener> listener(mConsumerListener.promote());
1030 if (listener != NULL) {
1031 listener->onFrameAvailable();
1032 }
1033 }
1035 void GonkBufferQueue::ProxyConsumerListener::onBuffersReleased() {
1036 sp<GonkBufferQueue::ConsumerListener> listener(mConsumerListener.promote());
1037 if (listener != NULL) {
1038 listener->onBuffersReleased();
1039 }
1040 }
1042 }; // namespace android