michael@0: /* michael@0: * Copyright (C) 2012 The Android Open Source Project michael@0: * Copyright (C) 2013 Mozilla Foundation michael@0: * michael@0: * Licensed under the Apache License, Version 2.0 (the "License"); michael@0: * you may not use this file except in compliance with the License. michael@0: * You may obtain a copy of the License at michael@0: * michael@0: * http://www.apache.org/licenses/LICENSE-2.0 michael@0: * michael@0: * Unless required by applicable law or agreed to in writing, software michael@0: * distributed under the License is distributed on an "AS IS" BASIS, michael@0: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. michael@0: * See the License for the specific language governing permissions and michael@0: * limitations under the License. michael@0: */ michael@0: michael@0: //#define LOG_NDEBUG 0 michael@0: #define LOG_TAG "GonkNativeWindow" michael@0: #define ATRACE_TAG ATRACE_TAG_GRAPHICS michael@0: #include michael@0: michael@0: #include "GonkNativeWindowKK.h" michael@0: #include "GrallocImages.h" michael@0: michael@0: #define BI_LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__) michael@0: #define BI_LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) michael@0: #define BI_LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) michael@0: #define BI_LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__) michael@0: #define BI_LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) michael@0: michael@0: using namespace mozilla; michael@0: using namespace mozilla::layers; michael@0: michael@0: namespace android { michael@0: michael@0: GonkNativeWindow::GonkNativeWindow() : michael@0: GonkConsumerBase(new GonkBufferQueue(true), false) michael@0: { michael@0: mConsumer->setMaxAcquiredBufferCount(GonkBufferQueue::MIN_UNDEQUEUED_BUFFERS); michael@0: } michael@0: michael@0: GonkNativeWindow::GonkNativeWindow(const sp& bq, michael@0: uint32_t consumerUsage, int bufferCount, bool controlledByApp) : michael@0: GonkConsumerBase(bq, controlledByApp) michael@0: { michael@0: mConsumer->setConsumerUsageBits(consumerUsage); michael@0: mConsumer->setMaxAcquiredBufferCount(bufferCount); michael@0: } michael@0: michael@0: GonkNativeWindow::~GonkNativeWindow() { michael@0: } michael@0: michael@0: void GonkNativeWindow::setName(const String8& name) { michael@0: Mutex::Autolock _l(mMutex); michael@0: mName = name; michael@0: mConsumer->setConsumerName(name); michael@0: } michael@0: michael@0: status_t GonkNativeWindow::acquireBuffer(BufferItem *item, michael@0: nsecs_t presentWhen, bool waitForFence) { michael@0: status_t err; michael@0: michael@0: if (!item) return BAD_VALUE; michael@0: michael@0: Mutex::Autolock _l(mMutex); michael@0: michael@0: err = acquireBufferLocked(item, presentWhen); michael@0: if (err != OK) { michael@0: if (err != NO_BUFFER_AVAILABLE) { michael@0: BI_LOGE("Error acquiring buffer: %s (%d)", strerror(err), err); michael@0: } michael@0: return err; michael@0: } michael@0: michael@0: if (waitForFence) { michael@0: err = item->mFence->waitForever("GonkNativeWindow::acquireBuffer"); michael@0: if (err != OK) { michael@0: BI_LOGE("Failed to wait for fence of acquired buffer: %s (%d)", michael@0: strerror(-err), err); michael@0: return err; michael@0: } michael@0: } michael@0: michael@0: item->mGraphicBuffer = mSlots[item->mBuf].mGraphicBuffer; michael@0: michael@0: return OK; michael@0: } michael@0: michael@0: status_t GonkNativeWindow::releaseBuffer(const BufferItem &item, michael@0: const sp& releaseFence) { michael@0: status_t err; michael@0: michael@0: Mutex::Autolock _l(mMutex); michael@0: michael@0: err = addReleaseFenceLocked(item.mBuf, item.mGraphicBuffer, releaseFence); michael@0: michael@0: err = releaseBufferLocked(item.mBuf, item.mGraphicBuffer); michael@0: if (err != OK) { michael@0: BI_LOGE("Failed to release buffer: %s (%d)", michael@0: strerror(-err), err); michael@0: } michael@0: return err; michael@0: } michael@0: michael@0: status_t GonkNativeWindow::setDefaultBufferSize(uint32_t w, uint32_t h) { michael@0: Mutex::Autolock _l(mMutex); michael@0: return mConsumer->setDefaultBufferSize(w, h); michael@0: } michael@0: michael@0: status_t GonkNativeWindow::setDefaultBufferFormat(uint32_t defaultFormat) { michael@0: Mutex::Autolock _l(mMutex); michael@0: return mConsumer->setDefaultBufferFormat(defaultFormat); michael@0: } michael@0: michael@0: TemporaryRef michael@0: GonkNativeWindow::getCurrentBuffer() { michael@0: Mutex::Autolock _l(mMutex); michael@0: BufferItem item; michael@0: michael@0: // In asynchronous mode the list is guaranteed to be one buffer michael@0: // deep, while in synchronous mode we use the oldest buffer. michael@0: status_t err = acquireBufferLocked(&item, 0); //??? michael@0: if (err != NO_ERROR) { michael@0: return NULL; michael@0: } michael@0: michael@0: RefPtr textureClient = michael@0: mConsumer->getTextureClientFromBuffer(item.mGraphicBuffer.get()); michael@0: if (!textureClient) { michael@0: return NULL; michael@0: } michael@0: textureClient->SetRecycleCallback(GonkNativeWindow::RecycleCallback, this); michael@0: return textureClient; michael@0: } michael@0: michael@0: /* static */ void michael@0: GonkNativeWindow::RecycleCallback(TextureClient* client, void* closure) { michael@0: GonkNativeWindow* nativeWindow = michael@0: static_cast(closure); michael@0: michael@0: client->ClearRecycleCallback(); michael@0: nativeWindow->returnBuffer(client); michael@0: } michael@0: michael@0: void GonkNativeWindow::returnBuffer(TextureClient* client) { michael@0: BI_LOGD("GonkNativeWindow::returnBuffer"); michael@0: Mutex::Autolock lock(mMutex); michael@0: michael@0: int index = mConsumer->getSlotFromTextureClientLocked(client); michael@0: if (index < 0) { michael@0: } michael@0: michael@0: sp fence = client->GetReleaseFenceHandle().mFence; michael@0: if (!fence.get()) { michael@0: fence = Fence::NO_FENCE; michael@0: } michael@0: michael@0: status_t err; michael@0: err = addReleaseFenceLocked(index, michael@0: mSlots[index].mGraphicBuffer, michael@0: fence); michael@0: michael@0: err = releaseBufferLocked(index, mSlots[index].mGraphicBuffer); michael@0: } michael@0: michael@0: TemporaryRef michael@0: GonkNativeWindow::getTextureClientFromBuffer(ANativeWindowBuffer* buffer) { michael@0: Mutex::Autolock lock(mMutex); michael@0: return mConsumer->getTextureClientFromBuffer(buffer); michael@0: } michael@0: michael@0: void GonkNativeWindow::setNewFrameCallback( michael@0: GonkNativeWindowNewFrameCallback* callback) { michael@0: BI_LOGD("setNewFrameCallback"); michael@0: Mutex::Autolock lock(mMutex); michael@0: mNewFrameCallback = callback; michael@0: } michael@0: michael@0: void GonkNativeWindow::onFrameAvailable() { michael@0: GonkConsumerBase::onFrameAvailable(); michael@0: michael@0: if (mNewFrameCallback) { michael@0: mNewFrameCallback->OnNewFrame(); michael@0: } michael@0: } michael@0: michael@0: } // namespace android