diff options
Diffstat (limited to 'widget/gonk/nativewindow')
39 files changed, 0 insertions, 11650 deletions
diff --git a/widget/gonk/nativewindow/FakeSurfaceComposer.cpp b/widget/gonk/nativewindow/FakeSurfaceComposer.cpp deleted file mode 100644 index 7e4a2a9d8..000000000 --- a/widget/gonk/nativewindow/FakeSurfaceComposer.cpp +++ /dev/null @@ -1,703 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * Copyright (C) 2013 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "FakeSurfaceComposer" -//#define LOG_NDEBUG 0 - -#include <stdint.h> -#include <sys/types.h> -#include <errno.h> -#include <cutils/atomic.h> -#include <cutils/log.h> -#include <cutils/properties.h> -#include <private/android_filesystem_config.h> - -#include <gui/IDisplayEventConnection.h> -#include <gui/GraphicBufferAlloc.h> -#include <gui/Surface.h> -#include <ui/DisplayInfo.h> - -#if ANDROID_VERSION >= 21 -#include <ui/Rect.h> -#endif - -#include "../libdisplay/GonkDisplay.h" -#include "../nsScreenManagerGonk.h" -#include "FakeSurfaceComposer.h" -#include "gfxPrefs.h" -#include "MainThreadUtils.h" -#include "mozilla/Assertions.h" -#include "mozilla/layers/CompositorBridgeParent.h" -#include "mozilla/layers/CompositorThread.h" -#include "nsProxyRelease.h" -#include "nsThreadUtils.h" - -using namespace mozilla; - -namespace android { - -/* static */ -void FakeSurfaceComposer::instantiate() { - defaultServiceManager()->addService( - String16("SurfaceFlinger"), new FakeSurfaceComposer()); -} - -FakeSurfaceComposer::FakeSurfaceComposer() - : BnSurfaceComposer() -{ -} - -FakeSurfaceComposer::~FakeSurfaceComposer() -{ -} - -status_t FakeSurfaceComposer::onTransact(uint32_t code, const Parcel& data, - Parcel* reply, uint32_t flags) -{ - switch (code) { - case CREATE_CONNECTION: - case CREATE_DISPLAY: - case SET_TRANSACTION_STATE: - case CAPTURE_SCREEN: - { - // codes that require permission check - IPCThreadState* ipc = IPCThreadState::self(); - const int pid = ipc->getCallingPid(); - const int uid = ipc->getCallingUid(); - // Accept request only when uid is root. - if (uid != AID_ROOT) { - ALOGE("Permission Denial: " - "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid); - return PERMISSION_DENIED; - } - break; - } - } - - return BnSurfaceComposer::onTransact(code, data, reply, flags); -} - -sp<ISurfaceComposerClient> FakeSurfaceComposer::createConnection() -{ - return nullptr; -} - -sp<IGraphicBufferAlloc> FakeSurfaceComposer::createGraphicBufferAlloc() -{ - sp<GraphicBufferAlloc> gba(new GraphicBufferAlloc()); - return gba; -} - -class DestroyDisplayRunnable : public Runnable { -public: - DestroyDisplayRunnable(FakeSurfaceComposer* aComposer, ssize_t aIndex) - : mComposer(aComposer), mIndex(aIndex) { } - NS_IMETHOD Run() override { - MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread."); - Mutex::Autolock _l(mComposer->mStateLock); - RefPtr<nsScreenManagerGonk> screenManager = - nsScreenManagerGonk::GetInstance(); - screenManager->RemoveScreen(GonkDisplay::DISPLAY_VIRTUAL); - mComposer->mDisplays.removeItemsAt(mIndex); - return NS_OK; - } - sp<FakeSurfaceComposer> mComposer; - ssize_t mIndex; -}; - -sp<IBinder> FakeSurfaceComposer::createDisplay(const String8& displayName, - bool secure) -{ -#if ANDROID_VERSION >= 19 - class DisplayToken : public BBinder { - sp<FakeSurfaceComposer> composer; - virtual ~DisplayToken() { - MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread."); - // no more references, this display must be terminated - Mutex::Autolock _l(composer->mStateLock); - ssize_t idx = composer->mDisplays.indexOfKey(this); - if (idx >= 0) { - nsCOMPtr<nsIRunnable> task(new DestroyDisplayRunnable(composer.get(), idx)); - NS_DispatchToMainThread(task); - } - } - public: - DisplayToken(const sp<FakeSurfaceComposer>& composer) - : composer(composer) { - } - }; - - sp<BBinder> token = new DisplayToken(this); - - Mutex::Autolock _l(mStateLock); - DisplayDeviceState info(HWC_DISPLAY_VIRTUAL); - info.displayName = displayName; - info.displayId = GonkDisplay::DISPLAY_VIRTUAL; - info.isSecure = secure; - mDisplays.add(token, info); - return token; -#else - return nullptr; -#endif -} - -#if ANDROID_VERSION >= 19 -void FakeSurfaceComposer::destroyDisplay(const sp<IBinder>& display) -{ - Mutex::Autolock _l(mStateLock); - - ssize_t idx = mDisplays.indexOfKey(display); - if (idx < 0) { - ALOGW("destroyDisplay: invalid display token"); - return; - } - - nsCOMPtr<nsIRunnable> task(new DestroyDisplayRunnable(this, idx)); - NS_DispatchToMainThread(task); -} -#endif - -sp<IBinder> FakeSurfaceComposer::getBuiltInDisplay(int32_t id) -{ - // support only primary display - if (uint32_t(id) != HWC_DISPLAY_PRIMARY) { - return NULL; - } - - if (!mPrimaryDisplay.get()) { - mPrimaryDisplay = new BBinder(); - } - return mPrimaryDisplay; -} - -void FakeSurfaceComposer::setTransactionState( - const Vector<ComposerState>& state, - const Vector<DisplayState>& displays, - uint32_t flags) -{ - Mutex::Autolock _l(mStateLock); - size_t count = displays.size(); - for (size_t i=0 ; i<count ; i++) { - const DisplayState& s(displays[i]); - setDisplayStateLocked(s); - } -} - -uint32_t FakeSurfaceComposer::setDisplayStateLocked(const DisplayState& s) -{ - ssize_t dpyIdx = mDisplays.indexOfKey(s.token); - if (dpyIdx < 0) { - return 0; - } - - uint32_t flags = 0; - DisplayDeviceState& disp(mDisplays.editValueAt(dpyIdx)); - - if (!disp.isValid()) { - return 0; - } - - const uint32_t what = s.what; - if (what & DisplayState::eSurfaceChanged) { - if (disp.surface->asBinder() != s.surface->asBinder()) { - disp.surface = s.surface; - flags |= eDisplayTransactionNeeded; - } - } - if (what & DisplayState::eLayerStackChanged) { - if (disp.layerStack != s.layerStack) { - disp.layerStack = s.layerStack; - flags |= eDisplayTransactionNeeded; - } - } - if (what & DisplayState::eDisplayProjectionChanged) { - if (disp.orientation != s.orientation) { - disp.orientation = s.orientation; - flags |= eDisplayTransactionNeeded; - } - if (disp.frame != s.frame) { - disp.frame = s.frame; - flags |= eDisplayTransactionNeeded; - } - if (disp.viewport != s.viewport) { - disp.viewport = s.viewport; - flags |= eDisplayTransactionNeeded; - } - } -#if ANDROID_VERSION >= 21 - if (what & DisplayState::eDisplaySizeChanged) { - if (disp.width != s.width) { - disp.width = s.width; - flags |= eDisplayTransactionNeeded; - } - if (disp.height != s.height) { - disp.height = s.height; - flags |= eDisplayTransactionNeeded; - } - } -#endif - - if (what & DisplayState::eSurfaceChanged) { - nsCOMPtr<nsIRunnable> runnable = - NS_NewRunnableFunction([&]() { - MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread."); - RefPtr<nsScreenManagerGonk> screenManager = nsScreenManagerGonk::GetInstance(); - screenManager->AddScreen(GonkDisplay::DISPLAY_VIRTUAL, disp.surface.get()); - }); - NS_DispatchToMainThread(runnable, NS_DISPATCH_SYNC); - } - - return flags; -} - -void FakeSurfaceComposer::bootFinished() -{ -} - -bool FakeSurfaceComposer::authenticateSurfaceTexture( - const sp<IGraphicBufferProducer>& bufferProducer) const { - return false; -} - -sp<IDisplayEventConnection> FakeSurfaceComposer::createDisplayEventConnection() { - return nullptr; -} - -// --------------------------------------------------------------------------- -// Capture screen into an IGraphiBufferProducer -// --------------------------------------------------------------------------- - -class Barrier { -public: - inline Barrier() : state(CLOSED) { } - inline ~Barrier() { } - - // Release any threads waiting at the Barrier. - // Provides release semantics: preceding loads and stores will be visible - // to other threads before they wake up. - void open() { - Mutex::Autolock _l(lock); - state = OPENED; - cv.broadcast(); - } - - // Reset the Barrier, so wait() will block until open() has been called. - void close() { - Mutex::Autolock _l(lock); - state = CLOSED; - } - - // Wait until the Barrier is OPEN. - // Provides acquire semantics: no subsequent loads or stores will occur - // until wait() returns. - void wait() const { - Mutex::Autolock _l(lock); - while (state == CLOSED) { - cv.wait(lock); - } - } -private: - enum { OPENED, CLOSED }; - mutable Mutex lock; - mutable Condition cv; - volatile int state; -}; - -/* The code below is here to handle b/8734824 - * - * We create a IGraphicBufferProducer wrapper that forwards all calls - * to the calling binder thread, where they are executed. This allows - * the calling thread to be reused (on the other side) and not - * depend on having "enough" binder threads to handle the requests. - * - */ - -class GraphicProducerWrapper : public BBinder, public MessageHandler { - sp<IGraphicBufferProducer> impl; - sp<Looper> looper; - status_t result; - bool exitPending; - bool exitRequested; - mutable Barrier barrier; - volatile int32_t memoryBarrier; - uint32_t code; - Parcel const* data; - Parcel* reply; - - enum { - MSG_API_CALL, - MSG_EXIT - }; - - /* - * this is called by our "fake" BpGraphicBufferProducer. We package the - * data and reply Parcel and forward them to the calling thread. - */ - virtual status_t transact(uint32_t code, - const Parcel& data, Parcel* reply, uint32_t flags) { - this->code = code; - this->data = &data; - this->reply = reply; - android_atomic_acquire_store(0, &memoryBarrier); - if (exitPending) { - // if we've exited, we run the message synchronously right here - handleMessage(Message(MSG_API_CALL)); - } else { - barrier.close(); - looper->sendMessage(this, Message(MSG_API_CALL)); - barrier.wait(); - } - return NO_ERROR; - } - - /* - * here we run on the binder calling thread. All we've got to do is - * call the real BpGraphicBufferProducer. - */ - virtual void handleMessage(const Message& message) { - android_atomic_release_load(&memoryBarrier); - if (message.what == MSG_API_CALL) { - impl->asBinder()->transact(code, data[0], reply); - barrier.open(); - } else if (message.what == MSG_EXIT) { - exitRequested = true; - } - } - -public: - GraphicProducerWrapper(const sp<IGraphicBufferProducer>& impl) : - impl(impl), looper(new Looper(true)), result(NO_ERROR), - exitPending(false), exitRequested(false) { - } - - status_t waitForResponse() { - do { - looper->pollOnce(-1); - } while (!exitRequested); - return result; - } - - void exit(status_t result) { - this->result = result; - exitPending = true; - looper->sendMessage(this, Message(MSG_EXIT)); - } -}; - -status_t -FakeSurfaceComposer::captureScreen(const sp<IBinder>& display - , const sp<IGraphicBufferProducer>& producer -#if ANDROID_VERSION >= 21 - , Rect sourceCrop -#endif - , uint32_t reqWidth - , uint32_t reqHeight - , uint32_t minLayerZ - , uint32_t maxLayerZ -#if ANDROID_VERSION >= 21 - , bool useIdentityTransform - , Rotation rotation -#elif ANDROID_VERSION < 19 - , bool isCpuConsumer -#endif - ) -{ - if (display == 0 || producer == 0) { - return BAD_VALUE; - } - - // Limit only to primary display - if (display != mPrimaryDisplay) { - return BAD_VALUE; - } - - // this creates a "fake" BBinder which will serve as a "fake" remote - // binder to receive the marshaled calls and forward them to the - // real remote (a BpGraphicBufferProducer) - sp<GraphicProducerWrapper> wrapper = new GraphicProducerWrapper(producer); - // the asInterface() call below creates our "fake" BpGraphicBufferProducer - // which does the marshaling work forwards to our "fake remote" above. - sp<IGraphicBufferProducer> fakeProducer = IGraphicBufferProducer::asInterface(wrapper); - - nsCOMPtr<nsIRunnable> runnable = - NS_NewRunnableFunction([&]() { - captureScreenImp(fakeProducer, reqWidth, reqHeight, wrapper.get()); - }); - NS_DispatchToMainThread(runnable); - - status_t result = wrapper->waitForResponse(); - - return result; -} - -class RunnableCallTask final : public Runnable -{ -public: - explicit RunnableCallTask(nsIRunnable* aRunnable) - : mRunnable(aRunnable) {} - - NS_IMETHOD Run() override - { - return mRunnable->Run(); - } -protected: - nsCOMPtr<nsIRunnable> mRunnable; -}; - -void -FakeSurfaceComposer::captureScreenImp(const sp<IGraphicBufferProducer>& producer, - uint32_t reqWidth, - uint32_t reqHeight, - const sp<GraphicProducerWrapper>& wrapper) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(wrapper.get()); - - RefPtr<nsScreenGonk> screen = nsScreenManagerGonk::GetPrimaryScreen(); - - // get screen geometry - nsIntRect screenBounds = screen->GetNaturalBounds().ToUnknownRect(); - const uint32_t hw_w = screenBounds.width; - const uint32_t hw_h = screenBounds.height; - - if (reqWidth > hw_w || reqHeight > hw_h) { - ALOGE("size mismatch (%d, %d) > (%d, %d)", - reqWidth, reqHeight, hw_w, hw_h); - static_cast<GraphicProducerWrapper*>(producer->asBinder().get())->exit(BAD_VALUE); - return; - } - - reqWidth = (!reqWidth) ? hw_w : reqWidth; - reqHeight = (!reqHeight) ? hw_h : reqHeight; - - nsCOMPtr<nsIRunnable> runnable = - NS_NewRunnableFunction([screen, reqWidth, reqHeight, producer, wrapper]() { - // create a surface (because we're a producer, and we need to - // dequeue/queue a buffer) - sp<Surface> sur = new Surface(producer); - ANativeWindow* window = sur.get(); - // The closure makes screen const and we can't call forget() on it. - RefPtr<nsScreenGonk> screenAlias = screen; - - if (native_window_api_connect(window, NATIVE_WINDOW_API_EGL) != NO_ERROR) { - static_cast<GraphicProducerWrapper*>(producer->asBinder().get())->exit(BAD_VALUE); - NS_ReleaseOnMainThread(screenAlias.forget()); - return; - } - uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN | - GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE; - - int err = 0; - err = native_window_set_buffers_dimensions(window, reqWidth, reqHeight); - err |= native_window_set_scaling_mode(window, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); - err |= native_window_set_buffers_format(window, HAL_PIXEL_FORMAT_RGBA_8888); - err |= native_window_set_usage(window, usage); - - status_t result = NO_ERROR; - if (err == NO_ERROR) { - ANativeWindowBuffer* buffer; - result = native_window_dequeue_buffer_and_wait(window, &buffer); - if (result == NO_ERROR) { - nsresult rv = screen->MakeSnapshot(buffer); - if (rv != NS_OK) { - result = INVALID_OPERATION; - } - window->queueBuffer(window, buffer, -1); - } - } else { - result = BAD_VALUE; - } - native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); - static_cast<GraphicProducerWrapper*>(producer->asBinder().get())->exit(result); - NS_ReleaseOnMainThread(screenAlias.forget()); - }); - - layers::CompositorThreadHolder::Loop()->PostTask( - MakeAndAddRef<RunnableCallTask>(runnable)); -} - -#if ANDROID_VERSION >= 21 -void -FakeSurfaceComposer::setPowerMode(const sp<IBinder>& display, int mode) -{ -} - -status_t -FakeSurfaceComposer::getDisplayConfigs(const sp<IBinder>& display, Vector<DisplayInfo>* configs) -{ - if (configs == NULL) { - return BAD_VALUE; - } - - // Limit DisplayConfigs only to primary display - if (!display.get() || display != mPrimaryDisplay) { - return NAME_NOT_FOUND; - } - - configs->clear(); - DisplayInfo info = DisplayInfo(); - - nsCOMPtr<nsIRunnable> runnable = - NS_NewRunnableFunction([&]() { - MOZ_ASSERT(NS_IsMainThread()); - getPrimaryDisplayInfo(&info); - }); - NS_DispatchToMainThread(runnable, NS_DISPATCH_SYNC); - - configs->push_back(info); - return NO_ERROR; -} - -status_t -FakeSurfaceComposer::getDisplayStats(const sp<IBinder>& display, DisplayStatInfo* stats) -{ - return INVALID_OPERATION; -} - -int -FakeSurfaceComposer::getActiveConfig(const sp<IBinder>& display) -{ - // Only support primary display. - if (display.get() && (display == mPrimaryDisplay)) { - return 0; - } - return INVALID_OPERATION; -} - -status_t -FakeSurfaceComposer::setActiveConfig(const sp<IBinder>& display, int id) -{ - return INVALID_OPERATION; -} - -status_t -FakeSurfaceComposer::clearAnimationFrameStats() -{ - return INVALID_OPERATION; -} - -status_t -FakeSurfaceComposer::getAnimationFrameStats(FrameStats* outStats) const -{ - return INVALID_OPERATION; -} -#else -void -FakeSurfaceComposer::blank(const sp<IBinder>& display) -{ -} - -void -FakeSurfaceComposer::unblank(const sp<IBinder>& display) -{ -} - -status_t -FakeSurfaceComposer::getDisplayInfo(const sp<IBinder>& display, DisplayInfo* info) -{ - if (info == NULL) { - return BAD_VALUE; - } - - // Limit DisplayConfigs only to primary display - if (!display.get() || display != mPrimaryDisplay) { - return NAME_NOT_FOUND; - } - - nsCOMPtr<nsIRunnable> runnable = - NS_NewRunnableFunction([&]() { - MOZ_ASSERT(NS_IsMainThread()); - getPrimaryDisplayInfo(info); - }); - NS_DispatchToMainThread(runnable, NS_DISPATCH_SYNC); - - return NO_ERROR; -} -#endif - -#define VSYNC_EVENT_PHASE_OFFSET_NS 0 -#define SF_VSYNC_EVENT_PHASE_OFFSET_NS 0 - -void -FakeSurfaceComposer::getPrimaryDisplayInfo(DisplayInfo* info) -{ - MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread."); - - // Implementation mimic android SurfaceFlinger::getDisplayConfigs(). - - class Density { - static int getDensityFromProperty(char const* propName) { - char property[PROPERTY_VALUE_MAX]; - int density = 0; - if (property_get(propName, property, NULL) > 0) { - density = atoi(property); - } - return density; - } - public: - static int getEmuDensity() { - return getDensityFromProperty("qemu.sf.lcd_density"); } - static int getBuildDensity() { - return getDensityFromProperty("ro.sf.lcd_density"); } - }; - - RefPtr<nsScreenGonk> screen = nsScreenManagerGonk::GetPrimaryScreen(); - - float xdpi = screen->GetDpi(); - float ydpi = screen->GetDpi(); - int fps = 60; // XXX set a value from hwc hal - nsIntRect screenBounds = screen->GetNaturalBounds().ToUnknownRect(); - - // The density of the device is provided by a build property - float density = Density::getBuildDensity() / 160.0f; - if (density == 0) { - // the build doesn't provide a density -- this is wrong! - // use xdpi instead - ALOGE("ro.sf.lcd_density must be defined as a build property"); - density = xdpi / 160.0f; - } - info->density = density; - info->orientation = screen->EffectiveScreenRotation(); - - info->w = screenBounds.width; - info->h = screenBounds.height; - info->xdpi = xdpi; - info->ydpi = ydpi; - info->fps = fps; -#if ANDROID_VERSION >= 21 - info->appVsyncOffset = VSYNC_EVENT_PHASE_OFFSET_NS; - - // This is how far in advance a buffer must be queued for - // presentation at a given time. If you want a buffer to appear - // on the screen at time N, you must submit the buffer before - // (N - presentationDeadline). - // - // Normally it's one full refresh period (to give SF a chance to - // latch the buffer), but this can be reduced by configuring a - // DispSync offset. Any additional delays introduced by the hardware - // composer or panel must be accounted for here. - // - // We add an additional 1ms to allow for processing time and - // differences between the ideal and actual refresh rate. - info->presentationDeadline = - (1e9 / fps) - SF_VSYNC_EVENT_PHASE_OFFSET_NS + 1000000; -#endif - // All non-virtual displays are currently considered secure. - info->secure = true; -} - -}; // namespace android diff --git a/widget/gonk/nativewindow/FakeSurfaceComposer.h b/widget/gonk/nativewindow/FakeSurfaceComposer.h deleted file mode 100644 index 97a717444..000000000 --- a/widget/gonk/nativewindow/FakeSurfaceComposer.h +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * Copyright (C) 2013 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef NATIVEWINDOW_FAKE_SURFACE_COMPOSER_H -#define NATIVEWINDOW_FAKE_SURFACE_COMPOSER_H - -#include <stdint.h> -#include <sys/types.h> - -#include <utils/Errors.h> -#include <utils/Looper.h> - -#include <binder/BinderService.h> - -#include <gui/IGraphicBufferProducer.h> -#include <gui/ISurfaceComposer.h> -#include <gui/ISurfaceComposerClient.h> -#include <hardware/hwcomposer.h> -#include <private/gui/LayerState.h> -#include <utils/KeyedVector.h> - -class nsIWidget; - -namespace android { - -// --------------------------------------------------------------------------- - -class GraphicProducerWrapper; -class IGraphicBufferAlloc; - -enum { - eTransactionNeeded = 0x01, - eTraversalNeeded = 0x02, - eDisplayTransactionNeeded = 0x04, - eTransactionMask = 0x07 -}; - -class FakeSurfaceComposer : public BinderService<FakeSurfaceComposer>, - public BnSurfaceComposer -{ -public: - static char const* getServiceName() { - return "FakeSurfaceComposer"; - } - - // Instantiate FakeSurfaceComposer and register to service manager. - // If service manager is not present, wait until service manager becomes present. - static void instantiate(); - -#if ANDROID_VERSION >= 19 - virtual void destroyDisplay(const sp<android::IBinder>& display); -#endif - -#if ANDROID_VERSION >= 21 - virtual status_t captureScreen(const sp<IBinder>& display, - const sp<IGraphicBufferProducer>& producer, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - uint32_t minLayerZ, uint32_t maxLayerZ, - bool useIdentityTransform, - Rotation rotation = eRotateNone); -#elif ANDROID_VERSION >= 19 - virtual status_t captureScreen(const sp<IBinder>& display, - const sp<IGraphicBufferProducer>& producer, - uint32_t reqWidth, uint32_t reqHeight, - uint32_t minLayerZ, uint32_t maxLayerZ); -#else - virtual status_t captureScreen(const sp<IBinder>& display, - const sp<IGraphicBufferProducer>& producer, - uint32_t reqWidth, uint32_t reqHeight, - uint32_t minLayerZ, uint32_t maxLayerZ, bool isCpuConsumer); -#endif - -private: - FakeSurfaceComposer(); - // We're reference counted, never destroy FakeSurfaceComposer directly - virtual ~FakeSurfaceComposer(); - - /* ------------------------------------------------------------------------ - * IBinder interface - */ - virtual status_t onTransact(uint32_t code, const Parcel& data, - Parcel* reply, uint32_t flags); - - /* ------------------------------------------------------------------------ - * ISurfaceComposer interface - */ - virtual sp<ISurfaceComposerClient> createConnection(); - virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc(); - virtual sp<IBinder> createDisplay(const String8& displayName, bool secure); - virtual sp<IBinder> getBuiltInDisplay(int32_t id); - virtual void setTransactionState(const Vector<ComposerState>& state, - const Vector<DisplayState>& displays, uint32_t flags); - virtual void bootFinished(); - virtual bool authenticateSurfaceTexture( - const sp<IGraphicBufferProducer>& bufferProducer) const; - virtual sp<IDisplayEventConnection> createDisplayEventConnection(); -#if ANDROID_VERSION >= 21 - virtual void setPowerMode(const sp<IBinder>& display, int mode); - virtual status_t getDisplayConfigs(const sp<IBinder>& display, Vector<DisplayInfo>* configs); - virtual status_t getDisplayStats(const sp<IBinder>& display, DisplayStatInfo* stats); - virtual int getActiveConfig(const sp<IBinder>& display); - virtual status_t setActiveConfig(const sp<IBinder>& display, int id); - virtual status_t clearAnimationFrameStats(); - virtual status_t getAnimationFrameStats(FrameStats* outStats) const; -#elif ANDROID_VERSION >= 17 - // called when screen needs to turn off - virtual void blank(const sp<IBinder>& display); - // called when screen is turning back on - virtual void unblank(const sp<IBinder>& display); - virtual status_t getDisplayInfo(const sp<IBinder>& display, DisplayInfo* info); -#endif - void getPrimaryDisplayInfo(DisplayInfo* info); - - /* ------------------------------------------------------------------------ - * Transactions - */ - uint32_t setDisplayStateLocked(const DisplayState& s); - - void captureScreenImp(const sp<IGraphicBufferProducer>& producer, - uint32_t reqWidth, - uint32_t reqHeight, - const sp<GraphicProducerWrapper>& wrapper); - - sp<IBinder> mPrimaryDisplay; - - struct DisplayDeviceState { - enum { - NO_LAYER_STACK = 0xFFFFFFFF, - }; - DisplayDeviceState() - : type(-1), displayId(-1), width(0), height(0) { - } - DisplayDeviceState(int type) - : type(type), displayId(-1), layerStack(NO_LAYER_STACK), orientation(0), width(0), height(0) { - viewport.makeInvalid(); - frame.makeInvalid(); - } - bool isValid() const { return type >= 0; } - int type; - int displayId; - sp<IGraphicBufferProducer> surface; - uint32_t layerStack; - Rect viewport; - Rect frame; - uint8_t orientation; - uint32_t width, height; - String8 displayName; - bool isSecure; - }; - - // access must be protected by mStateLock - mutable Mutex mStateLock; - DefaultKeyedVector<wp<IBinder>, DisplayDeviceState> mDisplays; - - friend class DestroyDisplayRunnable; -}; - -// --------------------------------------------------------------------------- -}; // namespace android - -#endif // NATIVEWINDOW_FAKE_SURFACE_COMPOSER_H diff --git a/widget/gonk/nativewindow/GonkBufferQueue.h b/widget/gonk/nativewindow/GonkBufferQueue.h deleted file mode 100644 index defdb0ae2..000000000 --- a/widget/gonk/nativewindow/GonkBufferQueue.h +++ /dev/null @@ -1,22 +0,0 @@ -/* Copyright 2013 Mozilla Foundation and Mozilla contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 21 -# include "GonkBufferQueueLL.h" -#elif defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 19 -# include "GonkBufferQueueKK.h" -#elif defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17 -# include "GonkBufferQueueJB.h" -#endif diff --git a/widget/gonk/nativewindow/GonkBufferQueueJB.cpp b/widget/gonk/nativewindow/GonkBufferQueueJB.cpp deleted file mode 100644 index 81502f81e..000000000 --- a/widget/gonk/nativewindow/GonkBufferQueueJB.cpp +++ /dev/null @@ -1,1036 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * Copyright (C) 2012 The Android Open Source Project - * Copyright (C) 2013 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "GonkBufferQueue" -#define ATRACE_TAG ATRACE_TAG_GRAPHICS -#define LOG_NDEBUG 0 - -#define GL_GLEXT_PROTOTYPES -#define EGL_EGLEXT_PROTOTYPES - -#include <utils/Log.h> - -#include "mozilla/layers/GrallocTextureClient.h" -#include "mozilla/layers/ImageBridgeChild.h" - -#include "GonkBufferQueueJB.h" - -// Macros for including the GonkBufferQueue name in log messages -#define ST_LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__) -#define ST_LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) -#define ST_LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) -#define ST_LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__) -#define ST_LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) - -#define ATRACE_BUFFER_INDEX(index) - -using namespace mozilla; -using namespace mozilla::gfx; -using namespace mozilla::layers; - -namespace android { - -// Get an ID that's unique within this process. -static int32_t createProcessUniqueId() { - static volatile int32_t globalCounter = 0; - return android_atomic_inc(&globalCounter); -} - -static const char* scalingModeName(int scalingMode) { - switch (scalingMode) { - case NATIVE_WINDOW_SCALING_MODE_FREEZE: return "FREEZE"; - case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: return "SCALE_TO_WINDOW"; - case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP: return "SCALE_CROP"; - default: return "Unknown"; - } -} - -GonkBufferQueue::GonkBufferQueue(bool allowSynchronousMode, - const sp<IGraphicBufferAlloc>& allocator) : - mDefaultWidth(1), - mDefaultHeight(1), - mMaxAcquiredBufferCount(1), - mDefaultMaxBufferCount(2), - mOverrideMaxBufferCount(0), - mSynchronousMode(true), - mAllowSynchronousMode(allowSynchronousMode), - mConnectedApi(NO_CONNECTED_API), - mAbandoned(false), - mFrameCounter(0), - mBufferHasBeenQueued(false), - mDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888), - mConsumerUsageBits(0), - mTransformHint(0) -{ - // Choose a name using the PID and a process-unique ID. - mConsumerName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId()); - - ST_LOGV("GonkBufferQueue"); -} - -GonkBufferQueue::~GonkBufferQueue() { - ST_LOGV("~GonkBufferQueue"); -} - -status_t GonkBufferQueue::setDefaultMaxBufferCountLocked(int count) { - if (count < 2 || count > NUM_BUFFER_SLOTS) - return BAD_VALUE; - - mDefaultMaxBufferCount = count; - mDequeueCondition.broadcast(); - - return NO_ERROR; -} - -bool GonkBufferQueue::isSynchronousMode() const { - Mutex::Autolock lock(mMutex); - return mSynchronousMode; -} - -void GonkBufferQueue::setConsumerName(const String8& name) { - Mutex::Autolock lock(mMutex); - mConsumerName = name; -} - -status_t GonkBufferQueue::setDefaultBufferFormat(uint32_t defaultFormat) { - Mutex::Autolock lock(mMutex); - mDefaultBufferFormat = defaultFormat; - return NO_ERROR; -} - -status_t GonkBufferQueue::setConsumerUsageBits(uint32_t usage) { - Mutex::Autolock lock(mMutex); - mConsumerUsageBits = usage; - return NO_ERROR; -} - -status_t GonkBufferQueue::setTransformHint(uint32_t hint) { - ST_LOGV("setTransformHint: %02x", hint); - Mutex::Autolock lock(mMutex); - mTransformHint = hint; - return NO_ERROR; -} - -already_AddRefed<TextureClient> -GonkBufferQueue::getTextureClientFromBuffer(ANativeWindowBuffer* buffer) -{ - Mutex::Autolock _l(mMutex); - if (buffer == NULL) { - ST_LOGE("getSlotFromBufferLocked: encountered NULL buffer"); - return nullptr; - } - - for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { - if (mSlots[i].mGraphicBuffer != NULL && mSlots[i].mGraphicBuffer->handle == buffer->handle) { - RefPtr<TextureClient> client(mSlots[i].mTextureClient); - return client.forget(); - } - } - ST_LOGE("getSlotFromBufferLocked: unknown buffer: %p", buffer->handle); - return nullptr; -} - -int GonkBufferQueue::getSlotFromTextureClientLocked( - TextureClient* client) const -{ - if (client == NULL) { - ST_LOGE("getSlotFromBufferLocked: encountered NULL buffer"); - return BAD_VALUE; - } - - for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { - if (mSlots[i].mTextureClient == client) { - return i; - } - } - ST_LOGE("getSlotFromBufferLocked: unknown TextureClient: %p", client); - return BAD_VALUE; -} - - -status_t GonkBufferQueue::setBufferCount(int bufferCount) { - ST_LOGV("setBufferCount: count=%d", bufferCount); - - sp<ConsumerListener> listener; - { - Mutex::Autolock lock(mMutex); - - if (mAbandoned) { - ST_LOGE("setBufferCount: GonkBufferQueue has been abandoned!"); - return NO_INIT; - } - if (bufferCount > NUM_BUFFER_SLOTS) { - ST_LOGE("setBufferCount: bufferCount too large (max %d)", - NUM_BUFFER_SLOTS); - return BAD_VALUE; - } - - // Error out if the user has dequeued buffers - int maxBufferCount = getMaxBufferCountLocked(); - for (int i=0 ; i<maxBufferCount; i++) { - if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) { - ST_LOGE("setBufferCount: client owns some buffers"); - return -EINVAL; - } - } - - const int minBufferSlots = getMinMaxBufferCountLocked(); - if (bufferCount == 0) { - mOverrideMaxBufferCount = 0; - mDequeueCondition.broadcast(); - return NO_ERROR; - } - - if (bufferCount < minBufferSlots) { - ST_LOGE("setBufferCount: requested buffer count (%d) is less than " - "minimum (%d)", bufferCount, minBufferSlots); - return BAD_VALUE; - } - - // here we're guaranteed that the client doesn't have dequeued buffers - // and will release all of its buffer references. - // - // XXX: Should this use drainQueueAndFreeBuffersLocked instead? - freeAllBuffersLocked(); - mOverrideMaxBufferCount = bufferCount; - mBufferHasBeenQueued = false; - mDequeueCondition.broadcast(); - listener = mConsumerListener; - } // scope for lock - - if (listener != NULL) { - listener->onBuffersReleased(); - } - - return NO_ERROR; -} - -int GonkBufferQueue::query(int what, int* outValue) -{ - Mutex::Autolock lock(mMutex); - - if (mAbandoned) { - ST_LOGE("query: GonkBufferQueue has been abandoned!"); - return NO_INIT; - } - - int value; - switch (what) { - case NATIVE_WINDOW_WIDTH: - value = mDefaultWidth; - break; - case NATIVE_WINDOW_HEIGHT: - value = mDefaultHeight; - break; - case NATIVE_WINDOW_FORMAT: - value = mDefaultBufferFormat; - break; - case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS: - value = getMinUndequeuedBufferCountLocked(); - break; - case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND: - value = (mQueue.size() >= 2); - break; - default: - return BAD_VALUE; - } - outValue[0] = value; - return NO_ERROR; -} - -status_t GonkBufferQueue::requestBuffer(int slot, sp<GraphicBuffer>* buf) { - ST_LOGV("requestBuffer: slot=%d", slot); - Mutex::Autolock lock(mMutex); - if (mAbandoned) { - ST_LOGE("requestBuffer: GonkBufferQueue has been abandoned!"); - return NO_INIT; - } - int maxBufferCount = getMaxBufferCountLocked(); - if (slot < 0 || maxBufferCount <= slot) { - ST_LOGE("requestBuffer: slot index out of range [0, %d]: %d", - maxBufferCount, slot); - return BAD_VALUE; - } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) { - // XXX: I vaguely recall there was some reason this can be valid, but - // for the life of me I can't recall under what circumstances that's - // the case. - ST_LOGE("requestBuffer: slot %d is not owned by the client (state=%d)", - slot, mSlots[slot].mBufferState); - return BAD_VALUE; - } - mSlots[slot].mRequestBufferCalled = true; - *buf = mSlots[slot].mGraphicBuffer; - return NO_ERROR; -} - -status_t GonkBufferQueue::dequeueBuffer(int *outBuf, sp<Fence>* outFence, - uint32_t w, uint32_t h, uint32_t format, uint32_t usage) { - ST_LOGV("dequeueBuffer: w=%d h=%d fmt=%#x usage=%#x", w, h, format, usage); - - if ((w && !h) || (!w && h)) { - ST_LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h); - return BAD_VALUE; - } - - status_t returnFlags(OK); - int buf = INVALID_BUFFER_SLOT; - - { // Scope for the lock - Mutex::Autolock lock(mMutex); - - if (format == 0) { - format = mDefaultBufferFormat; - } - // turn on usage bits the consumer requested - usage |= mConsumerUsageBits; - - int found = -1; - int dequeuedCount = 0; - bool tryAgain = true; - while (tryAgain) { - if (mAbandoned) { - ST_LOGE("dequeueBuffer: GonkBufferQueue has been abandoned!"); - return NO_INIT; - } - - const int maxBufferCount = getMaxBufferCountLocked(); - - // Free up any buffers that are in slots beyond the max buffer - // count. - //for (int i = maxBufferCount; i < NUM_BUFFER_SLOTS; i++) { - // assert(mSlots[i].mBufferState == BufferSlot::FREE); - // if (mSlots[i].mGraphicBuffer != NULL) { - // freeBufferLocked(i); - // returnFlags |= IGraphicBufferProducer::RELEASE_ALL_BUFFERS; - // } - //} - - // look for a free buffer to give to the client - found = INVALID_BUFFER_SLOT; - dequeuedCount = 0; - for (int i = 0; i < maxBufferCount; i++) { - const int state = mSlots[i].mBufferState; - if (state == BufferSlot::DEQUEUED) { - dequeuedCount++; - } - - if (state == BufferSlot::FREE) { - /* We return the oldest of the free buffers to avoid - * stalling the producer if possible. This is because - * the consumer may still have pending reads of the - * buffers in flight. - */ - if ((found < 0) || - mSlots[i].mFrameNumber < mSlots[found].mFrameNumber) { - found = i; - } - } - } - - // clients are not allowed to dequeue more than one buffer - // if they didn't set a buffer count. - if (!mOverrideMaxBufferCount && dequeuedCount) { - ST_LOGE("dequeueBuffer: can't dequeue multiple buffers without " - "setting the buffer count"); - return -EINVAL; - } - - // See whether a buffer has been queued since the last - // setBufferCount so we know whether to perform the min undequeued - // buffers check below. - if (mBufferHasBeenQueued) { - // make sure the client is not trying to dequeue more buffers - // than allowed. - const int newUndequeuedCount = maxBufferCount - (dequeuedCount+1); - const int minUndequeuedCount = getMinUndequeuedBufferCountLocked(); - if (newUndequeuedCount < minUndequeuedCount) { - ST_LOGE("dequeueBuffer: min undequeued buffer count (%d) " - "exceeded (dequeued=%d undequeudCount=%d)", - minUndequeuedCount, dequeuedCount, - newUndequeuedCount); - return -EBUSY; - } - } - - // If no buffer is found, wait for a buffer to be released or for - // the max buffer count to change. - tryAgain = found == INVALID_BUFFER_SLOT; - if (tryAgain) { - mDequeueCondition.wait(mMutex); - } - } - - - if (found == INVALID_BUFFER_SLOT) { - // This should not happen. - ST_LOGE("dequeueBuffer: no available buffer slots"); - return -EBUSY; - } - - buf = found; - *outBuf = found; - - const bool useDefaultSize = !w && !h; - if (useDefaultSize) { - // use the default size - w = mDefaultWidth; - h = mDefaultHeight; - } - - mSlots[buf].mBufferState = BufferSlot::DEQUEUED; - - const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer); - if ((buffer == NULL) || - (uint32_t(buffer->width) != w) || - (uint32_t(buffer->height) != h) || - (uint32_t(buffer->format) != format) || - ((uint32_t(buffer->usage) & usage) != usage)) - { - mSlots[buf].mAcquireCalled = false; - mSlots[buf].mGraphicBuffer = NULL; - mSlots[buf].mRequestBufferCalled = false; - mSlots[buf].mFence = Fence::NO_FENCE; - if (mSlots[buf].mTextureClient) { - mSlots[buf].mTextureClient->ClearRecycleCallback(); - // release TextureClient in ImageBridge thread - RefPtr<TextureClientReleaseTask> task = - MakeAndAddRef<TextureClientReleaseTask>(mSlots[buf].mTextureClient); - mSlots[buf].mTextureClient = NULL; - ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask(task.forget()); - } - returnFlags |= IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION; - } - - *outFence = mSlots[buf].mFence; - mSlots[buf].mFence = Fence::NO_FENCE; - } // end lock scope - - sp<GraphicBuffer> graphicBuffer; - if (returnFlags & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) { - - usage |= GraphicBuffer::USAGE_HW_TEXTURE; - RefPtr<LayersIPCChannel> allocator = ImageBridgeChild::GetSingleton(); - GrallocTextureData* texData = GrallocTextureData::Create(IntSize(w,h), format, - gfx::BackendType::NONE, usage, - allocator); - if (!texData) { - ST_LOGE("dequeueBuffer: failed to alloc gralloc buffer"); - return -ENOMEM; - } - RefPtr<TextureClient> textureClient = new TextureClient(texData, TextureFlags::RECYCLE | TextureFlags::DEALLOCATE_CLIENT, allocator); - sp<GraphicBuffer> graphicBuffer = texData->GetGraphicBuffer(); - - { // Scope for the lock - Mutex::Autolock lock(mMutex); - - if (mAbandoned) { - ST_LOGE("dequeueBuffer: SurfaceTexture has been abandoned!"); - return NO_INIT; - } - - mSlots[buf].mGraphicBuffer = graphicBuffer; - mSlots[buf].mTextureClient = textureClient; - ST_LOGD("dequeueBuffer: returning slot=%d buf=%p ", buf, - mSlots[buf].mGraphicBuffer->handle); - //mSlots[*outBuf].mGraphicBuffer = graphicBuffer; - } - } - - ST_LOGV("dequeueBuffer: returning slot=%d buf=%p flags=%#x", *outBuf, - mSlots[*outBuf].mGraphicBuffer->handle, returnFlags); - - return returnFlags; -} - -status_t GonkBufferQueue::setSynchronousMode(bool enabled) { - ST_LOGV("setSynchronousMode: enabled=%d", enabled); - Mutex::Autolock lock(mMutex); - - if (mAbandoned) { - ST_LOGE("setSynchronousMode: BufferQueue has been abandoned!"); - return NO_INIT; - } - - if (mSynchronousMode != enabled) { - mSynchronousMode = enabled; - mDequeueCondition.broadcast(); - } - return OK; -} - -status_t GonkBufferQueue::queueBuffer(int buf, - const QueueBufferInput& input, QueueBufferOutput* output) { - - Rect crop; - uint32_t transform; - int scalingMode; - int64_t timestamp; - sp<Fence> fence; - - input.deflate(×tamp, &crop, &scalingMode, &transform, &fence); - -#if ANDROID_VERSION >= 18 - if (fence == NULL) { - ST_LOGE("queueBuffer: fence is NULL"); - return BAD_VALUE; - } -#endif - - ST_LOGV("queueBuffer: slot=%d time=%#llx crop=[%d,%d,%d,%d] tr=%#x " - "scale=%s", - buf, timestamp, crop.left, crop.top, crop.right, crop.bottom, - transform, scalingModeName(scalingMode)); - - sp<ConsumerListener> listener; - - { // scope for the lock - Mutex::Autolock lock(mMutex); - if (mAbandoned) { - ST_LOGE("queueBuffer: GonkBufferQueue has been abandoned!"); - return NO_INIT; - } - int maxBufferCount = getMaxBufferCountLocked(); - if (buf < 0 || buf >= maxBufferCount) { - ST_LOGE("queueBuffer: slot index out of range [0, %d]: %d", - maxBufferCount, buf); - return -EINVAL; - } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) { - ST_LOGE("queueBuffer: slot %d is not owned by the client " - "(state=%d)", buf, mSlots[buf].mBufferState); - return -EINVAL; - } else if (!mSlots[buf].mRequestBufferCalled) { - ST_LOGE("queueBuffer: slot %d was enqueued without requesting a " - "buffer", buf); - return -EINVAL; - } - - const sp<GraphicBuffer>& graphicBuffer(mSlots[buf].mGraphicBuffer); - Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight()); - Rect croppedCrop; - crop.intersect(bufferRect, &croppedCrop); - if (croppedCrop != crop) { - ST_LOGE("queueBuffer: crop rect is not contained within the " - "buffer in slot %d", buf); - return -EINVAL; - } - - if (mSynchronousMode) { - // In synchronous mode we queue all buffers in a FIFO. - mQueue.push_back(buf); - } else { - // In asynchronous mode we only keep the most recent buffer. - if (mQueue.empty()) { - mQueue.push_back(buf); - } else { - Fifo::iterator front(mQueue.begin()); - // buffer currently queued is freed - mSlots[*front].mBufferState = BufferSlot::FREE; - // and we record the new buffer index in the queued list - *front = buf; - } - } - // always signals that an additional frame should be consumed - // to handle max acquired buffer count reached case. - listener = mConsumerListener; - - mSlots[buf].mTimestamp = timestamp; - mSlots[buf].mCrop = crop; - mSlots[buf].mTransform = transform; - mSlots[buf].mFence = fence; - - switch (scalingMode) { - case NATIVE_WINDOW_SCALING_MODE_FREEZE: - case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: - case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP: - break; - default: - ST_LOGE("unknown scaling mode: %d (ignoring)", scalingMode); - scalingMode = mSlots[buf].mScalingMode; - break; - } - - mSlots[buf].mBufferState = BufferSlot::QUEUED; - mSlots[buf].mScalingMode = scalingMode; - mFrameCounter++; - mSlots[buf].mFrameNumber = mFrameCounter; - - mBufferHasBeenQueued = true; - mDequeueCondition.broadcast(); - - output->inflate(mDefaultWidth, mDefaultHeight, mTransformHint, - mQueue.size()); - } // scope for the lock - - // call back without lock held - if (listener != 0) { - listener->onFrameAvailable(); - } - return NO_ERROR; -} - -#if ANDROID_VERSION == 17 -void GonkBufferQueue::cancelBuffer(int buf, sp<Fence> fence) { -#else -void GonkBufferQueue::cancelBuffer(int buf, const sp<Fence>& fence) { -#endif - - ST_LOGV("cancelBuffer: slot=%d", buf); - Mutex::Autolock lock(mMutex); - - if (mAbandoned) { - ST_LOGW("cancelBuffer: GonkBufferQueue has been abandoned!"); - return; - } - - int maxBufferCount = getMaxBufferCountLocked(); - if (buf < 0 || buf >= maxBufferCount) { - ST_LOGE("cancelBuffer: slot index out of range [0, %d]: %d", - maxBufferCount, buf); - return; - } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) { - ST_LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)", - buf, mSlots[buf].mBufferState); - return; -#if ANDROID_VERSION >= 18 - } else if (fence == NULL) { - ST_LOGE("cancelBuffer: fence is NULL"); - return; -#endif - } - mSlots[buf].mBufferState = BufferSlot::FREE; - mSlots[buf].mFrameNumber = 0; - mSlots[buf].mFence = fence; - mDequeueCondition.broadcast(); -} - -status_t GonkBufferQueue::connect(int api, QueueBufferOutput* output) { - ST_LOGV("connect: api=%d", api); - Mutex::Autolock lock(mMutex); - - if (mAbandoned) { - ST_LOGE("connect: GonkBufferQueue has been abandoned!"); - return NO_INIT; - } - - if (mConsumerListener == NULL) { - ST_LOGE("connect: GonkBufferQueue has no consumer!"); - return NO_INIT; - } - - int err = NO_ERROR; - switch (api) { - case NATIVE_WINDOW_API_EGL: - case NATIVE_WINDOW_API_CPU: - case NATIVE_WINDOW_API_MEDIA: - case NATIVE_WINDOW_API_CAMERA: - if (mConnectedApi != NO_CONNECTED_API) { - ST_LOGE("connect: already connected (cur=%d, req=%d)", - mConnectedApi, api); - err = -EINVAL; - } else { - mConnectedApi = api; - output->inflate(mDefaultWidth, mDefaultHeight, mTransformHint, - mQueue.size()); - } - break; - default: - err = -EINVAL; - break; - } - - mBufferHasBeenQueued = false; - - return err; -} - -status_t GonkBufferQueue::disconnect(int api) { - ST_LOGV("disconnect: api=%d", api); - - int err = NO_ERROR; - sp<ConsumerListener> listener; - - { // Scope for the lock - Mutex::Autolock lock(mMutex); - - if (mAbandoned) { - // it is not really an error to disconnect after the surface - // has been abandoned, it should just be a no-op. - return NO_ERROR; - } - - switch (api) { - case NATIVE_WINDOW_API_EGL: - case NATIVE_WINDOW_API_CPU: - case NATIVE_WINDOW_API_MEDIA: - case NATIVE_WINDOW_API_CAMERA: - if (mConnectedApi == api) { - freeAllBuffersLocked(); - mConnectedApi = NO_CONNECTED_API; - mDequeueCondition.broadcast(); - listener = mConsumerListener; - } else { - ST_LOGE("disconnect: connected to another api (cur=%d, req=%d)", - mConnectedApi, api); - err = -EINVAL; - } - break; - default: - ST_LOGE("disconnect: unknown API %d", api); - err = -EINVAL; - break; - } - } - - if (listener != NULL) { - listener->onBuffersReleased(); - } - - return err; -} - -void GonkBufferQueue::dumpToString(String8& result) const -{ - char buffer[1024]; - GonkBufferQueue::dumpToString(result, "", buffer, 1024); -} - -void GonkBufferQueue::dumpToString(String8& result, const char* prefix, - char* buffer, size_t SIZE) const -{ - Mutex::Autolock _l(mMutex); - - String8 fifo; - int fifoSize = 0; - Fifo::const_iterator i(mQueue.begin()); - while (i != mQueue.end()) { - snprintf(buffer, SIZE, "%02d ", *i++); - fifoSize++; - fifo.append(buffer); - } - - int maxBufferCount = getMaxBufferCountLocked(); - - snprintf(buffer, SIZE, - "%s-BufferQueue maxBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], " - "default-format=%d, transform-hint=%02x, FIFO(%d)={%s}\n", - prefix, maxBufferCount, mSynchronousMode, mDefaultWidth, - mDefaultHeight, mDefaultBufferFormat, mTransformHint, - fifoSize, fifo.string()); - result.append(buffer); - - - struct { - const char * operator()(int state) const { - switch (state) { - case BufferSlot::DEQUEUED: return "DEQUEUED"; - case BufferSlot::QUEUED: return "QUEUED"; - case BufferSlot::FREE: return "FREE"; - case BufferSlot::ACQUIRED: return "ACQUIRED"; - default: return "Unknown"; - } - } - } stateName; - - for (int i=0 ; i<maxBufferCount ; i++) { - const BufferSlot& slot(mSlots[i]); - snprintf(buffer, SIZE, - "%s%s[%02d] " - "state=%-8s, crop=[%d,%d,%d,%d], " - "xform=0x%02x, time=%#llx, scale=%s", - prefix, (slot.mBufferState == BufferSlot::ACQUIRED)?">":" ", i, - stateName(slot.mBufferState), - slot.mCrop.left, slot.mCrop.top, slot.mCrop.right, - slot.mCrop.bottom, slot.mTransform, slot.mTimestamp, - scalingModeName(slot.mScalingMode) - ); - result.append(buffer); - - const sp<GraphicBuffer>& buf(slot.mGraphicBuffer); - if (buf != NULL) { - snprintf(buffer, SIZE, - ", %p [%4ux%4u:%4u,%3X]", - buf->handle, buf->width, buf->height, buf->stride, - buf->format); - result.append(buffer); - } - result.append("\n"); - } -} - -void GonkBufferQueue::freeAllBuffersLocked() -{ - ALOGW_IF(!mQueue.isEmpty(), - "freeAllBuffersLocked called but mQueue is not empty"); - mQueue.clear(); - mBufferHasBeenQueued = false; - for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { - mSlots[i].mGraphicBuffer = 0; - if (mSlots[i].mTextureClient) { - mSlots[i].mTextureClient->ClearRecycleCallback(); - // release TextureClient in ImageBridge thread - RefPtr<TextureClientReleaseTask> task = - MakeAndAddRef<TextureClientReleaseTask>(mSlots[i].mTextureClient); - mSlots[i].mTextureClient = NULL; - ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask(task.forget()); - } - if (mSlots[i].mBufferState == BufferSlot::ACQUIRED) { - mSlots[i].mNeedsCleanupOnRelease = true; - } - mSlots[i].mBufferState = BufferSlot::FREE; - mSlots[i].mFrameNumber = 0; - mSlots[i].mAcquireCalled = false; - // destroy fence as GonkBufferQueue now takes ownership - mSlots[i].mFence = Fence::NO_FENCE; - } -} - -status_t GonkBufferQueue::acquireBuffer(BufferItem *buffer) { - Mutex::Autolock _l(mMutex); - - // Check that the consumer doesn't currently have the maximum number of - // buffers acquired. We allow the max buffer count to be exceeded by one - // buffer, so that the consumer can successfully set up the newly acquired - // buffer before releasing the old one. - int numAcquiredBuffers = 0; - for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { - if (mSlots[i].mBufferState == BufferSlot::ACQUIRED) { - numAcquiredBuffers++; - } - } - if (numAcquiredBuffers >= mMaxAcquiredBufferCount+1) { - ST_LOGE("acquireBuffer: max acquired buffer count reached: %d (max=%d)", - numAcquiredBuffers, mMaxAcquiredBufferCount); - return INVALID_OPERATION; - } - - // check if queue is empty - // In asynchronous mode the list is guaranteed to be one buffer - // deep, while in synchronous mode we use the oldest buffer. - if (!mQueue.empty()) { - Fifo::iterator front(mQueue.begin()); - int buf = *front; - - // In android, when the buffer is aquired by BufferConsumer, - // BufferQueue releases a reference to the buffer and - // it's ownership moves to the BufferConsumer. - // In b2g, GonkBufferQueue continues to have a buffer ownership. - // It is necessary to free buffer via ImageBridgeChild. - - //if (mSlots[buf].mAcquireCalled) { - // buffer->mGraphicBuffer = NULL; - //} else { - // buffer->mGraphicBuffer = mSlots[buf].mGraphicBuffer; - //} - buffer->mGraphicBuffer = mSlots[buf].mGraphicBuffer; - buffer->mCrop = mSlots[buf].mCrop; - buffer->mTransform = mSlots[buf].mTransform; - buffer->mScalingMode = mSlots[buf].mScalingMode; - buffer->mFrameNumber = mSlots[buf].mFrameNumber; - buffer->mTimestamp = mSlots[buf].mTimestamp; - buffer->mBuf = buf; - buffer->mFence = mSlots[buf].mFence; - - mSlots[buf].mAcquireCalled = true; - mSlots[buf].mNeedsCleanupOnRelease = false; - mSlots[buf].mBufferState = BufferSlot::ACQUIRED; - mSlots[buf].mFence = Fence::NO_FENCE; - - mQueue.erase(front); - mDequeueCondition.broadcast(); - } else { - return NO_BUFFER_AVAILABLE; - } - - return NO_ERROR; -} - -status_t GonkBufferQueue::releaseBuffer(int buf, const sp<Fence>& fence) { - Mutex::Autolock _l(mMutex); - -#if ANDROID_VERSION == 17 - if (buf == INVALID_BUFFER_SLOT) { -#else - if (buf == INVALID_BUFFER_SLOT || fence == NULL) { -#endif - return BAD_VALUE; - } - - mSlots[buf].mFence = fence; - - // The buffer can now only be released if its in the acquired state - if (mSlots[buf].mBufferState == BufferSlot::ACQUIRED) { - mSlots[buf].mBufferState = BufferSlot::FREE; - } else if (mSlots[buf].mNeedsCleanupOnRelease) { - ST_LOGV("releasing a stale buf %d its state was %d", buf, mSlots[buf].mBufferState); - mSlots[buf].mNeedsCleanupOnRelease = false; - return STALE_BUFFER_SLOT; - } else { - ST_LOGE("attempted to release buf %d but its state was %d", buf, mSlots[buf].mBufferState); - return -EINVAL; - } - - mDequeueCondition.broadcast(); - return NO_ERROR; -} - -status_t GonkBufferQueue::consumerConnect(const sp<ConsumerListener>& consumerListener) { - ST_LOGV("consumerConnect"); - Mutex::Autolock lock(mMutex); - - if (mAbandoned) { - ST_LOGE("consumerConnect: GonkBufferQueue has been abandoned!"); - return NO_INIT; - } - if (consumerListener == NULL) { - ST_LOGE("consumerConnect: consumerListener may not be NULL"); - return BAD_VALUE; - } - - mConsumerListener = consumerListener; - - return NO_ERROR; -} - -status_t GonkBufferQueue::consumerDisconnect() { - ST_LOGV("consumerDisconnect"); - Mutex::Autolock lock(mMutex); - - if (mConsumerListener == NULL) { - ST_LOGE("consumerDisconnect: No consumer is connected!"); - return -EINVAL; - } - - mAbandoned = true; - mConsumerListener = NULL; - mQueue.clear(); - freeAllBuffersLocked(); - mDequeueCondition.broadcast(); - return NO_ERROR; -} - -status_t GonkBufferQueue::getReleasedBuffers(uint32_t* slotMask) { - ST_LOGV("getReleasedBuffers"); - Mutex::Autolock lock(mMutex); - - if (mAbandoned) { - ST_LOGE("getReleasedBuffers: GonkBufferQueue has been abandoned!"); - return NO_INIT; - } - - uint32_t mask = 0; - for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { - if (!mSlots[i].mAcquireCalled) { - mask |= 1 << i; - } - } - *slotMask = mask; - - ST_LOGV("getReleasedBuffers: returning mask %#x", mask); - return NO_ERROR; -} - -status_t GonkBufferQueue::setDefaultBufferSize(uint32_t w, uint32_t h) -{ - ST_LOGV("setDefaultBufferSize: w=%d, h=%d", w, h); - if (!w || !h) { - ST_LOGE("setDefaultBufferSize: dimensions cannot be 0 (w=%d, h=%d)", - w, h); - return BAD_VALUE; - } - - Mutex::Autolock lock(mMutex); - mDefaultWidth = w; - mDefaultHeight = h; - return NO_ERROR; -} - -status_t GonkBufferQueue::setDefaultMaxBufferCount(int bufferCount) { - Mutex::Autolock lock(mMutex); - return setDefaultMaxBufferCountLocked(bufferCount); -} - -status_t GonkBufferQueue::setMaxAcquiredBufferCount(int maxAcquiredBuffers) { - Mutex::Autolock lock(mMutex); - if (maxAcquiredBuffers < 1 || maxAcquiredBuffers > MAX_MAX_ACQUIRED_BUFFERS) { - ST_LOGE("setMaxAcquiredBufferCount: invalid count specified: %d", - maxAcquiredBuffers); - return BAD_VALUE; - } - if (mConnectedApi != NO_CONNECTED_API) { - return INVALID_OPERATION; - } - mMaxAcquiredBufferCount = maxAcquiredBuffers; - return NO_ERROR; -} - -int GonkBufferQueue::getMinMaxBufferCountLocked() const { - return getMinUndequeuedBufferCountLocked() + 1; -} - -int GonkBufferQueue::getMinUndequeuedBufferCountLocked() const { - return mSynchronousMode ? mMaxAcquiredBufferCount : - mMaxAcquiredBufferCount + 1; -} - -int GonkBufferQueue::getMaxBufferCountLocked() const { - int minMaxBufferCount = getMinMaxBufferCountLocked(); - - int maxBufferCount = mDefaultMaxBufferCount; - if (maxBufferCount < minMaxBufferCount) { - maxBufferCount = minMaxBufferCount; - } - if (mOverrideMaxBufferCount != 0) { - assert(mOverrideMaxBufferCount >= minMaxBufferCount); - maxBufferCount = mOverrideMaxBufferCount; - } - - // Any buffers that are dequeued by the producer or sitting in the queue - // waiting to be consumed need to have their slots preserved. Such - // buffers will temporarily keep the max buffer count up until the slots - // no longer need to be preserved. - for (int i = maxBufferCount; i < NUM_BUFFER_SLOTS; i++) { - BufferSlot::BufferState state = mSlots[i].mBufferState; - if (state == BufferSlot::QUEUED || state == BufferSlot::DEQUEUED) { - maxBufferCount = i + 1; - } - } - - return maxBufferCount; -} - -GonkBufferQueue::ProxyConsumerListener::ProxyConsumerListener( - const wp<GonkBufferQueue::ConsumerListener>& consumerListener): - mConsumerListener(consumerListener) {} - -GonkBufferQueue::ProxyConsumerListener::~ProxyConsumerListener() {} - -void GonkBufferQueue::ProxyConsumerListener::onFrameAvailable() { - sp<GonkBufferQueue::ConsumerListener> listener(mConsumerListener.promote()); - if (listener != NULL) { - listener->onFrameAvailable(); - } -} - -void GonkBufferQueue::ProxyConsumerListener::onBuffersReleased() { - sp<GonkBufferQueue::ConsumerListener> listener(mConsumerListener.promote()); - if (listener != NULL) { - listener->onBuffersReleased(); - } -} - -}; // namespace android diff --git a/widget/gonk/nativewindow/GonkBufferQueueJB.h b/widget/gonk/nativewindow/GonkBufferQueueJB.h deleted file mode 100644 index df0c4599f..000000000 --- a/widget/gonk/nativewindow/GonkBufferQueueJB.h +++ /dev/null @@ -1,653 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * Copyright (C) 2013 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef NATIVEWINDOW_GONKBUFFERQUEUE_JB_H -#define NATIVEWINDOW_GONKBUFFERQUEUE_JB_H - -#include <gui/IGraphicBufferAlloc.h> -#if ANDROID_VERSION == 17 -#include <gui/ISurfaceTexture.h> -#else -#include <gui/IGraphicBufferProducer.h> -#endif - -#include <ui/Fence.h> -#include <ui/GraphicBuffer.h> - -#include <utils/String8.h> -#include <utils/Vector.h> -#include <utils/threads.h> - -#include "mozilla/layers/LayersSurfaces.h" -#include "mozilla/layers/TextureClient.h" - -#if ANDROID_VERSION == 17 -#define IGraphicBufferProducer ISurfaceTexture -#endif - -namespace android { -// ---------------------------------------------------------------------------- - -#if ANDROID_VERSION == 17 -class GonkBufferQueue : public BnSurfaceTexture { -#else -class GonkBufferQueue : public BnGraphicBufferProducer { -#endif - typedef mozilla::layers::TextureClient TextureClient; - -public: - enum { MIN_UNDEQUEUED_BUFFERS = 2 }; - enum { NUM_BUFFER_SLOTS = 32 }; - enum { NO_CONNECTED_API = 0 }; - enum { INVALID_BUFFER_SLOT = -1 }; - enum { STALE_BUFFER_SLOT = 1, NO_BUFFER_AVAILABLE }; - - // When in async mode we reserve two slots in order to guarantee that the - // producer and consumer can run asynchronously. - enum { MAX_MAX_ACQUIRED_BUFFERS = NUM_BUFFER_SLOTS - 2 }; - - // ConsumerListener is the interface through which the GonkBufferQueue notifies - // the consumer of events that the consumer may wish to react to. Because - // the consumer will generally have a mutex that is locked during calls from - // the consumer to the GonkBufferQueue, these calls from the GonkBufferQueue to the - // consumer *MUST* be called only when the GonkBufferQueue mutex is NOT locked. - struct ConsumerListener : public virtual RefBase { - // onFrameAvailable is called from queueBuffer each time an additional - // frame becomes available for consumption. This means that frames that - // are queued while in asynchronous mode only trigger the callback if no - // previous frames are pending. Frames queued while in synchronous mode - // always trigger the callback. - // - // This is called without any lock held and can be called concurrently - // by multiple threads. - virtual void onFrameAvailable() = 0; - - // onBuffersReleased is called to notify the buffer consumer that the - // GonkBufferQueue has released its references to one or more GraphicBuffers - // contained in its slots. The buffer consumer should then call - // GonkBufferQueue::getReleasedBuffers to retrieve the list of buffers - // - // This is called without any lock held and can be called concurrently - // by multiple threads. - virtual void onBuffersReleased() = 0; - }; - - // ProxyConsumerListener is a ConsumerListener implementation that keeps a weak - // reference to the actual consumer object. It forwards all calls to that - // consumer object so long as it exists. - // - // This class exists to avoid having a circular reference between the - // GonkBufferQueue object and the consumer object. The reason this can't be a weak - // reference in the GonkBufferQueue class is because we're planning to expose the - // consumer side of a GonkBufferQueue as a binder interface, which doesn't support - // weak references. - class ProxyConsumerListener : public GonkBufferQueue::ConsumerListener { - public: - - ProxyConsumerListener(const wp<GonkBufferQueue::ConsumerListener>& consumerListener); - virtual ~ProxyConsumerListener(); - virtual void onFrameAvailable(); - virtual void onBuffersReleased(); - - private: - - // mConsumerListener is a weak reference to the ConsumerListener. This is - // the raison d'etre of ProxyConsumerListener. - wp<GonkBufferQueue::ConsumerListener> mConsumerListener; - }; - - - // GonkBufferQueue manages a pool of gralloc memory slots to be used by - // producers and consumers. allowSynchronousMode specifies whether or not - // synchronous mode can be enabled by the producer. allocator is used to - // allocate all the needed gralloc buffers. - GonkBufferQueue(bool allowSynchronousMode = true, - const sp<IGraphicBufferAlloc>& allocator = NULL); - virtual ~GonkBufferQueue(); - - // Query native window attributes. The "what" values are enumerated in - // window.h (e.g. NATIVE_WINDOW_FORMAT). - virtual int query(int what, int* value); - - // setBufferCount updates the number of available buffer slots. If this - // method succeeds, buffer slots will be both unallocated and owned by - // the GonkBufferQueue object (i.e. they are not owned by the producer or - // consumer). - // - // This will fail if the producer has dequeued any buffers, or if - // bufferCount is invalid. bufferCount must generally be a value - // between the minimum undequeued buffer count and NUM_BUFFER_SLOTS - // (inclusive). It may also be set to zero (the default) to indicate - // that the producer does not wish to set a value. The minimum value - // can be obtained by calling query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, - // ...). - // - // This may only be called by the producer. The consumer will be told - // to discard buffers through the onBuffersReleased callback. - virtual status_t setBufferCount(int bufferCount); - - // requestBuffer returns the GraphicBuffer for slot N. - // - // In normal operation, this is called the first time slot N is returned - // by dequeueBuffer. It must be called again if dequeueBuffer returns - // flags indicating that previously-returned buffers are no longer valid. - virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf); - - // dequeueBuffer gets the next buffer slot index for the producer to use. - // If a buffer slot is available then that slot index is written to the - // location pointed to by the buf argument and a status of OK is returned. - // If no slot is available then a status of -EBUSY is returned and buf is - // unmodified. - // - // The fence parameter will be updated to hold the fence associated with - // the buffer. The contents of the buffer must not be overwritten until the - // fence signals. If the fence is Fence::NO_FENCE, the buffer may be - // written immediately. - // - // The width and height parameters must be no greater than the minimum of - // GL_MAX_VIEWPORT_DIMS and GL_MAX_TEXTURE_SIZE (see: glGetIntegerv). - // An error due to invalid dimensions might not be reported until - // updateTexImage() is called. If width and height are both zero, the - // default values specified by setDefaultBufferSize() are used instead. - // - // The pixel formats are enumerated in graphics.h, e.g. - // HAL_PIXEL_FORMAT_RGBA_8888. If the format is 0, the default format - // will be used. - // - // The usage argument specifies gralloc buffer usage flags. The values - // are enumerated in gralloc.h, e.g. GRALLOC_USAGE_HW_RENDER. These - // will be merged with the usage flags specified by setConsumerUsageBits. - // - // The return value may be a negative error value or a non-negative - // collection of flags. If the flags are set, the return values are - // valid, but additional actions must be performed. - // - // If IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION is set, the - // producer must discard cached GraphicBuffer references for the slot - // returned in buf. - // If IGraphicBufferProducer::RELEASE_ALL_BUFFERS is set, the producer - // must discard cached GraphicBuffer references for all slots. - // - // In both cases, the producer will need to call requestBuffer to get a - // GraphicBuffer handle for the returned slot. -#if ANDROID_VERSION == 17 - virtual status_t dequeueBuffer(int *buf, sp<Fence>& fence, - uint32_t width, uint32_t height, uint32_t format, uint32_t usage) { - return dequeueBuffer(buf, &fence, width, height, format, usage); - } -#endif - - virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence, - uint32_t width, uint32_t height, uint32_t format, uint32_t usage); - - // queueBuffer returns a filled buffer to the GonkBufferQueue. - // - // Additional data is provided in the QueueBufferInput struct. Notably, - // a timestamp must be provided for the buffer. The timestamp is in - // nanoseconds, and must be monotonically increasing. Its other semantics - // (zero point, etc) are producer-specific and should be documented by the - // producer. - // - // The caller may provide a fence that signals when all rendering - // operations have completed. Alternatively, NO_FENCE may be used, - // indicating that the buffer is ready immediately. - // - // Some values are returned in the output struct: the current settings - // for default width and height, the current transform hint, and the - // number of queued buffers. - virtual status_t queueBuffer(int buf, - const QueueBufferInput& input, QueueBufferOutput* output); - - // cancelBuffer returns a dequeued buffer to the GonkBufferQueue, but doesn't - // queue it for use by the consumer. - // - // The buffer will not be overwritten until the fence signals. The fence - // will usually be the one obtained from dequeueBuffer. -#if ANDROID_VERSION == 17 - virtual void cancelBuffer(int buf, sp<Fence> fence); -#else - virtual void cancelBuffer(int buf, const sp<Fence>& fence); -#endif - - // setSynchronousMode sets whether dequeueBuffer is synchronous or - // asynchronous. In synchronous mode, dequeueBuffer blocks until - // a buffer is available, the currently bound buffer can be dequeued and - // queued buffers will be acquired in order. In asynchronous mode, - // a queued buffer may be replaced by a subsequently queued buffer. - // - // The default mode is synchronous. - // This should be called only during initialization. - virtual status_t setSynchronousMode(bool enabled); - - // connect attempts to connect a producer API to the GonkBufferQueue. This - // must be called before any other IGraphicBufferProducer methods are - // called except for getAllocator. A consumer must already be connected. - // - // This method will fail if connect was previously called on the - // GonkBufferQueue and no corresponding disconnect call was made (i.e. if - // it's still connected to a producer). - // - // APIs are enumerated in window.h (e.g. NATIVE_WINDOW_API_CPU). - virtual status_t connect(int api, QueueBufferOutput* output); - - // disconnect attempts to disconnect a producer API from the GonkBufferQueue. - // Calling this method will cause any subsequent calls to other - // IGraphicBufferProducer methods to fail except for getAllocator and connect. - // Successfully calling connect after this will allow the other methods to - // succeed again. - // - // This method will fail if the the GonkBufferQueue is not currently - // connected to the specified producer API. - virtual status_t disconnect(int api); - - // dump our state in a String - virtual void dumpToString(String8& result) const; - virtual void dumpToString(String8& result, const char* prefix, char* buffer, size_t SIZE) const; - - // public facing structure for BufferSlot - struct BufferItem { - - BufferItem() - : - mTransform(0), - mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE), - mTimestamp(0), - mFrameNumber(0), - mBuf(INVALID_BUFFER_SLOT) { - mCrop.makeInvalid(); - } - // mGraphicBuffer points to the buffer allocated for this slot, or is NULL - // if the buffer in this slot has been acquired in the past (see - // BufferSlot.mAcquireCalled). - sp<GraphicBuffer> mGraphicBuffer; - - // mCrop is the current crop rectangle for this buffer slot. - Rect mCrop; - - // mTransform is the current transform flags for this buffer slot. - uint32_t mTransform; - - // mScalingMode is the current scaling mode for this buffer slot. - uint32_t mScalingMode; - - // mTimestamp is the current timestamp for this buffer slot. This gets - // to set by queueBuffer each time this slot is queued. - int64_t mTimestamp; - - // mFrameNumber is the number of the queued frame for this slot. - uint64_t mFrameNumber; - - // mBuf is the slot index of this buffer - int mBuf; - - // mFence is a fence that will signal when the buffer is idle. - sp<Fence> mFence; - }; - - // The following public functions are the consumer-facing interface - - // acquireBuffer attempts to acquire ownership of the next pending buffer in - // the GonkBufferQueue. If no buffer is pending then it returns -EINVAL. If a - // buffer is successfully acquired, the information about the buffer is - // returned in BufferItem. If the buffer returned had previously been - // acquired then the BufferItem::mGraphicBuffer field of buffer is set to - // NULL and it is assumed that the consumer still holds a reference to the - // buffer. - status_t acquireBuffer(BufferItem *buffer); - - // releaseBuffer releases a buffer slot from the consumer back to the - // GonkBufferQueue. This may be done while the buffer's contents are still - // being accessed. The fence will signal when the buffer is no longer - // in use. - // - // If releaseBuffer returns STALE_BUFFER_SLOT, then the consumer must free - // any references to the just-released buffer that it might have, as if it - // had received a onBuffersReleased() call with a mask set for the released - // buffer. - // - // Note that the dependencies on EGL will be removed once we switch to using - // the Android HW Sync HAL. - status_t releaseBuffer(int buf, const sp<Fence>& releaseFence); - - // consumerConnect connects a consumer to the GonkBufferQueue. Only one - // consumer may be connected, and when that consumer disconnects the - // GonkBufferQueue is placed into the "abandoned" state, causing most - // interactions with the GonkBufferQueue by the producer to fail. - // - // consumer may not be NULL. - status_t consumerConnect(const sp<ConsumerListener>& consumer); - - // consumerDisconnect disconnects a consumer from the GonkBufferQueue. All - // buffers will be freed and the GonkBufferQueue is placed in the "abandoned" - // state, causing most interactions with the GonkBufferQueue by the producer to - // fail. - status_t consumerDisconnect(); - - // getReleasedBuffers sets the value pointed to by slotMask to a bit mask - // indicating which buffer slots have been released by the GonkBufferQueue - // but have not yet been released by the consumer. - // - // This should be called from the onBuffersReleased() callback. - status_t getReleasedBuffers(uint32_t* slotMask); - - // setDefaultBufferSize is used to set the size of buffers returned by - // dequeueBuffer when a width and height of zero is requested. Default - // is 1x1. - status_t setDefaultBufferSize(uint32_t w, uint32_t h); - - // setDefaultMaxBufferCount sets the default value for the maximum buffer - // count (the initial default is 2). If the producer has requested a - // buffer count using setBufferCount, the default buffer count will only - // take effect if the producer sets the count back to zero. - // - // The count must be between 2 and NUM_BUFFER_SLOTS, inclusive. - status_t setDefaultMaxBufferCount(int bufferCount); - - // setMaxAcquiredBufferCount sets the maximum number of buffers that can - // be acquired by the consumer at one time (default 1). This call will - // fail if a producer is connected to the GonkBufferQueue. - status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers); - - // isSynchronousMode returns whether the GonkBufferQueue is currently in - // synchronous mode. - bool isSynchronousMode() const; - - // setConsumerName sets the name used in logging - void setConsumerName(const String8& name); - - // setDefaultBufferFormat allows the GonkBufferQueue to create - // GraphicBuffers of a defaultFormat if no format is specified - // in dequeueBuffer. Formats are enumerated in graphics.h; the - // initial default is HAL_PIXEL_FORMAT_RGBA_8888. - status_t setDefaultBufferFormat(uint32_t defaultFormat); - - // setConsumerUsageBits will turn on additional usage bits for dequeueBuffer. - // These are merged with the bits passed to dequeueBuffer. The values are - // enumerated in gralloc.h, e.g. GRALLOC_USAGE_HW_RENDER; the default is 0. - status_t setConsumerUsageBits(uint32_t usage); - - // setTransformHint bakes in rotation to buffers so overlays can be used. - // The values are enumerated in window.h, e.g. - // NATIVE_WINDOW_TRANSFORM_ROT_90. The default is 0 (no transform). - status_t setTransformHint(uint32_t hint); - - already_AddRefed<TextureClient> getTextureClientFromBuffer(ANativeWindowBuffer* buffer); - - int getSlotFromTextureClientLocked(TextureClient* client) const; - -private: - // freeBufferLocked frees the GraphicBuffer and sync resources for the - // given slot. - //void freeBufferLocked(int index); - - // freeAllBuffersLocked frees the GraphicBuffer and sync resources for - // all slots. - //void freeAllBuffersLocked(); - void freeAllBuffersLocked(); - - // setDefaultMaxBufferCountLocked sets the maximum number of buffer slots - // that will be used if the producer does not override the buffer slot - // count. The count must be between 2 and NUM_BUFFER_SLOTS, inclusive. - // The initial default is 2. - status_t setDefaultMaxBufferCountLocked(int count); - - // getMinBufferCountLocked returns the minimum number of buffers allowed - // given the current GonkBufferQueue state. - int getMinMaxBufferCountLocked() const; - - // getMinUndequeuedBufferCountLocked returns the minimum number of buffers - // that must remain in a state other than DEQUEUED. - int getMinUndequeuedBufferCountLocked() const; - - // getMaxBufferCountLocked returns the maximum number of buffers that can - // be allocated at once. This value depends upon the following member - // variables: - // - // mSynchronousMode - // mMaxAcquiredBufferCount - // mDefaultMaxBufferCount - // mOverrideMaxBufferCount - // - // Any time one of these member variables is changed while a producer is - // connected, mDequeueCondition must be broadcast. - int getMaxBufferCountLocked() const; - - struct BufferSlot { - - BufferSlot() - : mBufferState(BufferSlot::FREE), - mRequestBufferCalled(false), - mTransform(0), - mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE), - mTimestamp(0), - mFrameNumber(0), - mAcquireCalled(false), - mNeedsCleanupOnRelease(false) { - mCrop.makeInvalid(); - } - - // mGraphicBuffer points to the buffer allocated for this slot or is NULL - // if no buffer has been allocated. - sp<GraphicBuffer> mGraphicBuffer; - - // mTextureClient is a thin abstraction over remotely allocated GraphicBuffer. - RefPtr<TextureClient> mTextureClient; - - // BufferState represents the different states in which a buffer slot - // can be. All slots are initially FREE. - enum BufferState { - // FREE indicates that the buffer is available to be dequeued - // by the producer. The buffer may be in use by the consumer for - // a finite time, so the buffer must not be modified until the - // associated fence is signaled. - // - // The slot is "owned" by GonkBufferQueue. It transitions to DEQUEUED - // when dequeueBuffer is called. - FREE = 0, - - // DEQUEUED indicates that the buffer has been dequeued by the - // producer, but has not yet been queued or canceled. The - // producer may modify the buffer's contents as soon as the - // associated ready fence is signaled. - // - // The slot is "owned" by the producer. It can transition to - // QUEUED (via queueBuffer) or back to FREE (via cancelBuffer). - DEQUEUED = 1, - - // QUEUED indicates that the buffer has been filled by the - // producer and queued for use by the consumer. The buffer - // contents may continue to be modified for a finite time, so - // the contents must not be accessed until the associated fence - // is signaled. - // - // The slot is "owned" by GonkBufferQueue. It can transition to - // ACQUIRED (via acquireBuffer) or to FREE (if another buffer is - // queued in asynchronous mode). - QUEUED = 2, - - // ACQUIRED indicates that the buffer has been acquired by the - // consumer. As with QUEUED, the contents must not be accessed - // by the consumer until the fence is signaled. - // - // The slot is "owned" by the consumer. It transitions to FREE - // when releaseBuffer is called. - ACQUIRED = 3 - }; - - // mBufferState is the current state of this buffer slot. - BufferState mBufferState; - - // mRequestBufferCalled is used for validating that the producer did - // call requestBuffer() when told to do so. Technically this is not - // needed but useful for debugging and catching producer bugs. - bool mRequestBufferCalled; - - // mCrop is the current crop rectangle for this buffer slot. - Rect mCrop; - - // mTransform is the current transform flags for this buffer slot. - // (example: NATIVE_WINDOW_TRANSFORM_ROT_90) - uint32_t mTransform; - - // mScalingMode is the current scaling mode for this buffer slot. - // (example: NATIVE_WINDOW_SCALING_MODE_FREEZE) - uint32_t mScalingMode; - - // mTimestamp is the current timestamp for this buffer slot. This gets - // to set by queueBuffer each time this slot is queued. - int64_t mTimestamp; - - // mFrameNumber is the number of the queued frame for this slot. This - // is used to dequeue buffers in LRU order (useful because buffers - // may be released before their release fence is signaled). - uint64_t mFrameNumber; - - // mEglFence is the EGL sync object that must signal before the buffer - // associated with this buffer slot may be dequeued. It is initialized - // to EGL_NO_SYNC_KHR when the buffer is created and may be set to a - // new sync object in releaseBuffer. (This is deprecated in favor of - // mFence, below.) - //EGLSyncKHR mEglFence; - - // mFence is a fence which will signal when work initiated by the - // previous owner of the buffer is finished. When the buffer is FREE, - // the fence indicates when the consumer has finished reading - // from the buffer, or when the producer has finished writing if it - // called cancelBuffer after queueing some writes. When the buffer is - // QUEUED, it indicates when the producer has finished filling the - // buffer. When the buffer is DEQUEUED or ACQUIRED, the fence has been - // passed to the consumer or producer along with ownership of the - // buffer, and mFence is set to NO_FENCE. - sp<Fence> mFence; - - // Indicates whether this buffer has been seen by a consumer yet - bool mAcquireCalled; - - // Indicates whether this buffer needs to be cleaned up by the - // consumer. This is set when a buffer in ACQUIRED state is freed. - // It causes releaseBuffer to return STALE_BUFFER_SLOT. - bool mNeedsCleanupOnRelease; - }; - - // mSlots is the array of buffer slots that must be mirrored on the - // producer side. This allows buffer ownership to be transferred between - // the producer and consumer without sending a GraphicBuffer over binder. - // The entire array is initialized to NULL at construction time, and - // buffers are allocated for a slot when requestBuffer is called with - // that slot's index. - BufferSlot mSlots[NUM_BUFFER_SLOTS]; - - // mDefaultWidth holds the default width of allocated buffers. It is used - // in dequeueBuffer() if a width and height of zero is specified. - uint32_t mDefaultWidth; - - // mDefaultHeight holds the default height of allocated buffers. It is used - // in dequeueBuffer() if a width and height of zero is specified. - uint32_t mDefaultHeight; - - // mMaxAcquiredBufferCount is the number of buffers that the consumer may - // acquire at one time. It defaults to 1 and can be changed by the - // consumer via the setMaxAcquiredBufferCount method, but this may only be - // done when no producer is connected to the GonkBufferQueue. - // - // This value is used to derive the value returned for the - // MIN_UNDEQUEUED_BUFFERS query by the producer. - int mMaxAcquiredBufferCount; - - // mDefaultMaxBufferCount is the default limit on the number of buffers - // that will be allocated at one time. This default limit is set by the - // consumer. The limit (as opposed to the default limit) may be - // overridden by the producer. - int mDefaultMaxBufferCount; - - // mOverrideMaxBufferCount is the limit on the number of buffers that will - // be allocated at one time. This value is set by the image producer by - // calling setBufferCount. The default is zero, which means the producer - // doesn't care about the number of buffers in the pool. In that case - // mDefaultMaxBufferCount is used as the limit. - int mOverrideMaxBufferCount; - - // mGraphicBufferAlloc is the connection to SurfaceFlinger that is used to - // allocate new GraphicBuffer objects. - sp<IGraphicBufferAlloc> mGraphicBufferAlloc; - - // mConsumerListener is used to notify the connected consumer of - // asynchronous events that it may wish to react to. It is initially set - // to NULL and is written by consumerConnect and consumerDisconnect. - sp<ConsumerListener> mConsumerListener; - - // mSynchronousMode whether we're in synchronous mode or not - bool mSynchronousMode; - - // mAllowSynchronousMode whether we allow synchronous mode or not. Set - // when the GonkBufferQueue is created (by the consumer). - const bool mAllowSynchronousMode; - - // mConnectedApi indicates the producer API that is currently connected - // to this GonkBufferQueue. It defaults to NO_CONNECTED_API (= 0), and gets - // updated by the connect and disconnect methods. - int mConnectedApi; - - // mDequeueCondition condition used for dequeueBuffer in synchronous mode - mutable Condition mDequeueCondition; - - // mQueue is a FIFO of queued buffers used in synchronous mode - typedef Vector<int> Fifo; - Fifo mQueue; - - // mAbandoned indicates that the GonkBufferQueue will no longer be used to - // consume image buffers pushed to it using the IGraphicBufferProducer - // interface. It is initialized to false, and set to true in the - // consumerDisconnect method. A GonkBufferQueue that has been abandoned will - // return the NO_INIT error from all IGraphicBufferProducer methods - // capable of returning an error. - bool mAbandoned; - - // mConsumerName is a string used to identify the GonkBufferQueue in log - // messages. It is set by the setConsumerName method. - String8 mConsumerName; - - // mMutex is the mutex used to prevent concurrent access to the member - // variables of GonkBufferQueue objects. It must be locked whenever the - // member variables are accessed. - mutable Mutex mMutex; - - // mFrameCounter is the free running counter, incremented on every - // successful queueBuffer call. - uint64_t mFrameCounter; - - // mBufferHasBeenQueued is true once a buffer has been queued. It is - // reset when something causes all buffers to be freed (e.g. changing the - // buffer count). - bool mBufferHasBeenQueued; - - // mDefaultBufferFormat can be set so it will override - // the buffer format when it isn't specified in dequeueBuffer - uint32_t mDefaultBufferFormat; - - // mConsumerUsageBits contains flags the consumer wants for GraphicBuffers - uint32_t mConsumerUsageBits; - - // mTransformHint is used to optimize for screen rotations - uint32_t mTransformHint; - -}; - -// ---------------------------------------------------------------------------- -}; // namespace android - -#endif // ANDROID_GUI_BUFFERQUEUE_H diff --git a/widget/gonk/nativewindow/GonkBufferQueueKK.cpp b/widget/gonk/nativewindow/GonkBufferQueueKK.cpp deleted file mode 100644 index 0c5cdfeb9..000000000 --- a/widget/gonk/nativewindow/GonkBufferQueueKK.cpp +++ /dev/null @@ -1,1265 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * Copyright (C) 2012 The Android Open Source Project - * Copyright (C) 2013 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "GonkBufferQueue" -#define ATRACE_TAG ATRACE_TAG_GRAPHICS -//#define LOG_NDEBUG 0 - -#define GL_GLEXT_PROTOTYPES -#define EGL_EGLEXT_PROTOTYPES - -#include <utils/Log.h> -#include <utils/Trace.h> -#include <utils/CallStack.h> -#include <cutils/compiler.h> - -#include "mozilla/layers/GrallocTextureClient.h" -#include "mozilla/layers/ImageBridgeChild.h" -#include "GonkBufferQueueKK.h" - -#define ATRACE_BUFFER_INDEX(index) - -using namespace mozilla; -using namespace mozilla::gfx; -using namespace mozilla::layers; - -namespace android { - -// Get an ID that's unique within this process. -static int32_t createProcessUniqueId() { - static volatile int32_t globalCounter = 0; - return android_atomic_inc(&globalCounter); -} - -static const char* scalingModeName(int scalingMode) { - switch (scalingMode) { - case NATIVE_WINDOW_SCALING_MODE_FREEZE: return "FREEZE"; - case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: return "SCALE_TO_WINDOW"; - case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP: return "SCALE_CROP"; - default: return "Unknown"; - } -} - -GonkBufferQueue::GonkBufferQueue(bool allowSynchronousMode, - const sp<IGraphicBufferAlloc>& allocator) : - mDefaultWidth(1), - mDefaultHeight(1), - mMaxAcquiredBufferCount(1), - mDefaultMaxBufferCount(2), - mOverrideMaxBufferCount(0), - mSynchronousMode(true), - mConsumerControlledByApp(false), - mDequeueBufferCannotBlock(false), - mUseAsyncBuffer(true), - mConnectedApi(NO_CONNECTED_API), - mAbandoned(false), - mFrameCounter(0), - mBufferHasBeenQueued(false), - mDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888), - mConsumerUsageBits(0), - mTransformHint(0) -{ - // Choose a name using the PID and a process-unique ID. - mConsumerName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId()); - - ALOGV("GonkBufferQueue"); -} - -GonkBufferQueue::~GonkBufferQueue() { - ALOGV("~GonkBufferQueue"); -} - -status_t GonkBufferQueue::setDefaultMaxBufferCountLocked(int count) { - if (count < 2 || count > NUM_BUFFER_SLOTS) - return BAD_VALUE; - - mDefaultMaxBufferCount = count; - mDequeueCondition.broadcast(); - - return NO_ERROR; -} - -void GonkBufferQueue::setConsumerName(const String8& name) { - Mutex::Autolock lock(mMutex); - mConsumerName = name; -} - -status_t GonkBufferQueue::setDefaultBufferFormat(uint32_t defaultFormat) { - Mutex::Autolock lock(mMutex); - mDefaultBufferFormat = defaultFormat; - return NO_ERROR; -} - -status_t GonkBufferQueue::setConsumerUsageBits(uint32_t usage) { - Mutex::Autolock lock(mMutex); - mConsumerUsageBits = usage; - return NO_ERROR; -} - -status_t GonkBufferQueue::setTransformHint(uint32_t hint) { - ALOGV("setTransformHint: %02x", hint); - Mutex::Autolock lock(mMutex); - mTransformHint = hint; - return NO_ERROR; -} - -already_AddRefed<TextureClient> -GonkBufferQueue::getTextureClientFromBuffer(ANativeWindowBuffer* buffer) -{ - Mutex::Autolock _l(mMutex); - if (buffer == NULL) { - ALOGE("getSlotFromBufferLocked: encountered NULL buffer"); - return nullptr; - } - - for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { - if (mSlots[i].mGraphicBuffer != NULL && mSlots[i].mGraphicBuffer->handle == buffer->handle) { - RefPtr<TextureClient> client(mSlots[i].mTextureClient); - return client.forget(); - } - } - ALOGE("getSlotFromBufferLocked: unknown buffer: %p", buffer->handle); - return nullptr; -} - -int GonkBufferQueue::getSlotFromTextureClientLocked( - TextureClient* client) const -{ - if (client == NULL) { - ALOGE("getSlotFromBufferLocked: encountered NULL buffer"); - return BAD_VALUE; - } - - for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { - if (mSlots[i].mTextureClient == client) { - return i; - } - } - ALOGE("getSlotFromBufferLocked: unknown TextureClient: %p", client); - return BAD_VALUE; -} - -status_t GonkBufferQueue::setBufferCount(int bufferCount) { - ALOGV("setBufferCount: count=%d", bufferCount); - - sp<IConsumerListener> listener; - { - Mutex::Autolock lock(mMutex); - - if (mAbandoned) { - ALOGE("setBufferCount: GonkBufferQueue has been abandoned!"); - return NO_INIT; - } - if (bufferCount > NUM_BUFFER_SLOTS) { - ALOGE("setBufferCount: bufferCount too large (max %d)", - NUM_BUFFER_SLOTS); - return BAD_VALUE; - } - - // Error out if the user has dequeued buffers - for (int i=0 ; i<NUM_BUFFER_SLOTS; i++) { - if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) { - ALOGE("setBufferCount: client owns some buffers"); - return -EINVAL; - } - } - - if (bufferCount == 0) { - mOverrideMaxBufferCount = 0; - mDequeueCondition.broadcast(); - return NO_ERROR; - } - - // fine to assume async to false before we're setting the buffer count - const int minBufferSlots = getMinMaxBufferCountLocked(false); - if (bufferCount < minBufferSlots) { - ALOGE("setBufferCount: requested buffer count (%d) is less than " - "minimum (%d)", bufferCount, minBufferSlots); - return BAD_VALUE; - } - - // here we're guaranteed that the client doesn't have dequeued buffers - // and will release all of its buffer references. We don't clear the - // queue, however, so currently queued buffers still get displayed. - // XXX: Should this use drainQueueAndFreeBuffersLocked instead? - freeAllBuffersLocked(); - mOverrideMaxBufferCount = bufferCount; - mDequeueCondition.broadcast(); - listener = mConsumerListener; - } // scope for lock - - if (listener != NULL) { - listener->onBuffersReleased(); - } - - return NO_ERROR; -} - -int GonkBufferQueue::query(int what, int* outValue) -{ - ATRACE_CALL(); - Mutex::Autolock lock(mMutex); - - if (mAbandoned) { - ALOGE("query: GonkBufferQueue has been abandoned!"); - return NO_INIT; - } - - int value; - switch (what) { - case NATIVE_WINDOW_WIDTH: - value = mDefaultWidth; - break; - case NATIVE_WINDOW_HEIGHT: - value = mDefaultHeight; - break; - case NATIVE_WINDOW_FORMAT: - value = mDefaultBufferFormat; - break; - case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS: - value = getMinUndequeuedBufferCount(false); - break; - case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND: - value = (mQueue.size() >= 2); - break; - case NATIVE_WINDOW_CONSUMER_USAGE_BITS: - value = mConsumerUsageBits; - break; - default: - return BAD_VALUE; - } - outValue[0] = value; - return NO_ERROR; -} - -status_t GonkBufferQueue::requestBuffer(int slot, sp<GraphicBuffer>* buf) { - ATRACE_CALL(); - ALOGV("requestBuffer: slot=%d", slot); - Mutex::Autolock lock(mMutex); - if (mAbandoned) { - ALOGE("requestBuffer: GonkBufferQueue has been abandoned!"); - return NO_INIT; - } - if (slot < 0 || slot >= NUM_BUFFER_SLOTS) { - ALOGE("requestBuffer: slot index out of range [0, %d]: %d", - NUM_BUFFER_SLOTS, slot); - return BAD_VALUE; - } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) { - ALOGE("requestBuffer: slot %d is not owned by the client (state=%d)", - slot, mSlots[slot].mBufferState); - return BAD_VALUE; - } - mSlots[slot].mRequestBufferCalled = true; - *buf = mSlots[slot].mGraphicBuffer; - return NO_ERROR; -} - -status_t GonkBufferQueue::dequeueBuffer(int *outBuf, sp<Fence>* outFence, bool async, - uint32_t w, uint32_t h, uint32_t format, uint32_t usage) { - ATRACE_CALL(); - ALOGV("dequeueBuffer: w=%d h=%d fmt=%#x usage=%#x", w, h, format, usage); - - if ((w && !h) || (!w && h)) { - ALOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h); - return BAD_VALUE; - } - - status_t returnFlags(OK); - int buf = INVALID_BUFFER_SLOT; - - { // Scope for the lock - Mutex::Autolock lock(mMutex); - - if (format == 0) { - format = mDefaultBufferFormat; - } - // turn on usage bits the consumer requested - usage |= mConsumerUsageBits; - - int found = -1; - bool tryAgain = true; - while (tryAgain) { - if (mAbandoned) { - ALOGE("dequeueBuffer: GonkBufferQueue has been abandoned!"); - return NO_INIT; - } - - const int maxBufferCount = getMaxBufferCountLocked(async); - if (async && mOverrideMaxBufferCount) { - // FIXME: some drivers are manually setting the buffer-count (which they - // shouldn't), so we do this extra test here to handle that case. - // This is TEMPORARY, until we get this fixed. - if (mOverrideMaxBufferCount < maxBufferCount) { - ALOGE("dequeueBuffer: async mode is invalid with buffercount override"); - return BAD_VALUE; - } - } - - // Free up any buffers that are in slots beyond the max buffer - // count. - //for (int i = maxBufferCount; i < NUM_BUFFER_SLOTS; i++) { - // assert(mSlots[i].mBufferState == BufferSlot::FREE); - // if (mSlots[i].mGraphicBuffer != NULL) { - // freeBufferLocked(i); - // returnFlags |= IGraphicBufferProducer::RELEASE_ALL_BUFFERS; - // } - //} - - // look for a free buffer to give to the client - found = INVALID_BUFFER_SLOT; - int dequeuedCount = 0; - int acquiredCount = 0; - for (int i = 0; i < maxBufferCount; i++) { - const int state = mSlots[i].mBufferState; - switch (state) { - case BufferSlot::DEQUEUED: - dequeuedCount++; - break; - case BufferSlot::ACQUIRED: - acquiredCount++; - break; - case BufferSlot::FREE: - /* We return the oldest of the free buffers to avoid - * stalling the producer if possible. This is because - * the consumer may still have pending reads of the - * buffers in flight. - */ - if ((found < 0) || - mSlots[i].mFrameNumber < mSlots[found].mFrameNumber) { - found = i; - } - break; - } - } - - // clients are not allowed to dequeue more than one buffer - // if they didn't set a buffer count. - if (!mOverrideMaxBufferCount && dequeuedCount) { - ALOGE("dequeueBuffer: can't dequeue multiple buffers without " - "setting the buffer count"); - return -EINVAL; - } - - // See whether a buffer has been queued since the last - // setBufferCount so we know whether to perform the min undequeued - // buffers check below. - if (mBufferHasBeenQueued) { - // make sure the client is not trying to dequeue more buffers - // than allowed. - const int newUndequeuedCount = maxBufferCount - (dequeuedCount+1); - const int minUndequeuedCount = getMinUndequeuedBufferCount(async); - if (newUndequeuedCount < minUndequeuedCount) { - ALOGE("dequeueBuffer: min undequeued buffer count (%d) " - "exceeded (dequeued=%d undequeudCount=%d)", - minUndequeuedCount, dequeuedCount, - newUndequeuedCount); - return -EBUSY; - } - } - - // If no buffer is found, wait for a buffer to be released or for - // the max buffer count to change. - tryAgain = found == INVALID_BUFFER_SLOT; - if (tryAgain) { - // return an error if we're in "cannot block" mode (producer and consumer - // are controlled by the application) -- however, the consumer is allowed - // to acquire briefly an extra buffer (which could cause us to have to wait here) - // and that's okay because we know the wait will be brief (it happens - // if we dequeue a buffer while the consumer has acquired one but not released - // the old one yet -- for e.g.: see GLConsumer::updateTexImage()). - if (mDequeueBufferCannotBlock && (acquiredCount <= mMaxAcquiredBufferCount)) { - ALOGE("dequeueBuffer: would block! returning an error instead."); - return WOULD_BLOCK; - } - mDequeueCondition.wait(mMutex); - } - } - - - if (found == INVALID_BUFFER_SLOT) { - // This should not happen. - ALOGE("dequeueBuffer: no available buffer slots"); - return -EBUSY; - } - - buf = found; - *outBuf = found; - - const bool useDefaultSize = !w && !h; - if (useDefaultSize) { - // use the default size - w = mDefaultWidth; - h = mDefaultHeight; - } - - mSlots[buf].mBufferState = BufferSlot::DEQUEUED; - - const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer); - if ((buffer == NULL) || - (uint32_t(buffer->width) != w) || - (uint32_t(buffer->height) != h) || - (uint32_t(buffer->format) != format) || - ((uint32_t(buffer->usage) & usage) != usage)) - { - mSlots[buf].mAcquireCalled = false; - mSlots[buf].mGraphicBuffer = NULL; - mSlots[buf].mRequestBufferCalled = false; - mSlots[buf].mFence = Fence::NO_FENCE; - if (mSlots[buf].mTextureClient) { - mSlots[buf].mTextureClient->ClearRecycleCallback(); - // release TextureClient in ImageBridge thread - RefPtr<TextureClientReleaseTask> task = - MakeAndAddRef<TextureClientReleaseTask>(mSlots[buf].mTextureClient); - mSlots[buf].mTextureClient = NULL; - ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask(task.forget()); - } - returnFlags |= IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION; - } - - - if (CC_UNLIKELY(mSlots[buf].mFence == NULL)) { - ALOGE("dequeueBuffer: about to return a NULL fence from mSlot. " - "buf=%d, w=%d, h=%d, format=%d", - buf, buffer->width, buffer->height, buffer->format); - } - *outFence = mSlots[buf].mFence; - mSlots[buf].mFence = Fence::NO_FENCE; - } // end lock scope - - if (returnFlags & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) { - - RefPtr<LayersIPCChannel> allocator = ImageBridgeChild::GetSingleton(); - usage |= GraphicBuffer::USAGE_HW_TEXTURE; - GrallocTextureData* texData = GrallocTextureData::Create(IntSize(w, h), format, - gfx::BackendType::NONE, usage, - allocator); - if (!texData) { - return -ENOMEM; - } - - RefPtr<TextureClient> textureClient = new TextureClient(texData, TextureFlags::RECYCLE | TextureFlags::DEALLOCATE_CLIENT, allocator); - - { // Scope for the lock - Mutex::Autolock lock(mMutex); - - if (mAbandoned) { - ALOGE("dequeueBuffer: SurfaceTexture has been abandoned!"); - return NO_INIT; - } - - mSlots[buf].mGraphicBuffer = texData->GetGraphicBuffer(); - mSlots[buf].mTextureClient = textureClient; - ALOGD("dequeueBuffer: returning slot=%d buf=%p ", buf, - mSlots[buf].mGraphicBuffer->handle); - - } - - } - - ALOGV("dequeueBuffer: returning slot=%d/%llu buf=%p flags=%#x", *outBuf, - mSlots[*outBuf].mFrameNumber, - mSlots[*outBuf].mGraphicBuffer->handle, returnFlags); - - return returnFlags; -} - -status_t GonkBufferQueue::setSynchronousMode(bool enabled) { - ALOGV("setSynchronousMode: enabled=%d", enabled); - Mutex::Autolock lock(mMutex); - - if (mAbandoned) { - ALOGE("setSynchronousMode: BufferQueue has been abandoned!"); - return NO_INIT; - } - - if (mSynchronousMode != enabled) { - mSynchronousMode = enabled; - mDequeueCondition.broadcast(); - } - return OK; -} - -status_t GonkBufferQueue::queueBuffer(int buf, - const QueueBufferInput& input, QueueBufferOutput* output) { - ATRACE_CALL(); - - Rect crop; - uint32_t transform; - int scalingMode; - int64_t timestamp; - bool isAutoTimestamp; - bool async; - sp<Fence> fence; - - input.deflate(×tamp, &isAutoTimestamp, &crop, &scalingMode, &transform, - &async, &fence); - - if (fence == NULL) { - ALOGE("queueBuffer: fence is NULL"); - return BAD_VALUE; - } - - ALOGV("queueBuffer: slot=%d time=%#llx crop=[%d,%d,%d,%d] tr=%#x " - "scale=%s", - buf, timestamp, crop.left, crop.top, crop.right, crop.bottom, - transform, scalingModeName(scalingMode)); - - switch (scalingMode) { - case NATIVE_WINDOW_SCALING_MODE_FREEZE: - case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: - case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP: - case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP: - break; - default: - ALOGE("unknown scaling mode: %d", scalingMode); - return -EINVAL; - } - - sp<IConsumerListener> listener; - - { // scope for the lock - Mutex::Autolock lock(mMutex); - - if (mAbandoned) { - ALOGE("queueBuffer: GonkBufferQueue has been abandoned!"); - return NO_INIT; - } - - const int maxBufferCount = getMaxBufferCountLocked(async); - if (async && mOverrideMaxBufferCount) { - // FIXME: some drivers are manually setting the buffer-count (which they - // shouldn't), so we do this extra test here to handle that case. - // This is TEMPORARY, until we get this fixed. - if (mOverrideMaxBufferCount < maxBufferCount) { - ALOGE("queueBuffer: async mode is invalid with buffercount override"); - return BAD_VALUE; - } - } - if (buf < 0 || buf >= maxBufferCount) { - ALOGE("queueBuffer: slot index out of range [0, %d]: %d", - maxBufferCount, buf); - return -EINVAL; - } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) { - ALOGE("queueBuffer: slot %d is not owned by the client " - "(state=%d)", buf, mSlots[buf].mBufferState); - return -EINVAL; - } else if (!mSlots[buf].mRequestBufferCalled) { - ALOGE("queueBuffer: slot %d was enqueued without requesting a " - "buffer", buf); - return -EINVAL; - } - - ALOGV("queueBuffer: slot=%d/%llu time=%#llx crop=[%d,%d,%d,%d] " - "tr=%#x scale=%s", - buf, mFrameCounter + 1, timestamp, - crop.left, crop.top, crop.right, crop.bottom, - transform, scalingModeName(scalingMode)); - - const sp<GraphicBuffer>& graphicBuffer(mSlots[buf].mGraphicBuffer); - Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight()); - Rect croppedCrop; - crop.intersect(bufferRect, &croppedCrop); - if (croppedCrop != crop) { - ALOGE("queueBuffer: crop rect is not contained within the " - "buffer in slot %d", buf); - return -EINVAL; - } - - mSlots[buf].mFence = fence; - mSlots[buf].mBufferState = BufferSlot::QUEUED; - mFrameCounter++; - mSlots[buf].mFrameNumber = mFrameCounter; - - BufferItem item; - item.mAcquireCalled = mSlots[buf].mAcquireCalled; - item.mGraphicBuffer = mSlots[buf].mGraphicBuffer; - item.mCrop = crop; - item.mTransform = transform & ~NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY; - item.mTransformToDisplayInverse = bool(transform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY); - item.mScalingMode = scalingMode; - item.mTimestamp = timestamp; - item.mIsAutoTimestamp = isAutoTimestamp; - item.mFrameNumber = mFrameCounter; - item.mBuf = buf; - item.mFence = fence; - item.mIsDroppable = mDequeueBufferCannotBlock || async; - - if (mQueue.empty()) { - // when the queue is empty, we can ignore "mDequeueBufferCannotBlock", and - // simply queue this buffer. - mQueue.push_back(item); - } else { - // when the queue is not empty, we need to look at the front buffer - // state and see if we need to replace it. - Fifo::iterator front(mQueue.begin()); - if (front->mIsDroppable || !mSynchronousMode) { - // buffer slot currently queued is marked free if still tracked - if (stillTracking(front)) { - mSlots[front->mBuf].mBufferState = BufferSlot::FREE; - // reset the frame number of the freed buffer so that it is the first in - // line to be dequeued again. - mSlots[front->mBuf].mFrameNumber = 0; - } - // and we record the new buffer in the queued list - *front = item; - } else { - mQueue.push_back(item); - } - } - // always signals that an additional frame should be consumed - // to handle max acquired buffer count reached case. - listener = mConsumerListener; - - mBufferHasBeenQueued = true; - mDequeueCondition.broadcast(); - - output->inflate(mDefaultWidth, mDefaultHeight, mTransformHint, - mQueue.size()); - - } // scope for the lock - - // call back without lock held - if (listener != 0) { - listener->onFrameAvailable(); - } - return NO_ERROR; -} - -void GonkBufferQueue::cancelBuffer(int buf, const sp<Fence>& fence) { - ATRACE_CALL(); - ALOGV("cancelBuffer: slot=%d", buf); - Mutex::Autolock lock(mMutex); - - if (mAbandoned) { - ALOGW("cancelBuffer: GonkBufferQueue has been abandoned!"); - return; - } - - if (buf < 0 || buf >= NUM_BUFFER_SLOTS) { - ALOGE("cancelBuffer: slot index out of range [0, %d]: %d", - NUM_BUFFER_SLOTS, buf); - return; - } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) { - ALOGE("cancelBuffer: slot %d is not owned by the client (state=%d)", - buf, mSlots[buf].mBufferState); - return; - } else if (fence == NULL) { - ALOGE("cancelBuffer: fence is NULL"); - return; - } - mSlots[buf].mBufferState = BufferSlot::FREE; - mSlots[buf].mFrameNumber = 0; - mSlots[buf].mFence = fence; - mDequeueCondition.broadcast(); -} - - -status_t GonkBufferQueue::connect(const sp<IBinder>& token, - int api, bool producerControlledByApp, QueueBufferOutput* output) { - ATRACE_CALL(); - ALOGV("connect: api=%d producerControlledByApp=%s", api, - producerControlledByApp ? "true" : "false"); - Mutex::Autolock lock(mMutex); - -retry: - if (mAbandoned) { - ALOGE("connect: GonkBufferQueue has been abandoned!"); - return NO_INIT; - } - - if (mConsumerListener == NULL) { - ALOGE("connect: GonkBufferQueue has no consumer!"); - return NO_INIT; - } - - if (mConnectedApi != NO_CONNECTED_API) { - ALOGE("connect: already connected (cur=%d, req=%d)", - mConnectedApi, api); - return -EINVAL; - } - - // If we disconnect and reconnect quickly, we can be in a state where our slots are - // empty but we have many buffers in the queue. This can cause us to run out of - // memory if we outrun the consumer. Wait here if it looks like we have too many - // buffers queued up. - int maxBufferCount = getMaxBufferCountLocked(false); // worst-case, i.e. largest value - if (mQueue.size() > (size_t) maxBufferCount) { - // TODO: make this bound tighter? - ALOGV("queue size is %d, waiting", mQueue.size()); - mDequeueCondition.wait(mMutex); - goto retry; - } - - int err = NO_ERROR; - switch (api) { - case NATIVE_WINDOW_API_EGL: - case NATIVE_WINDOW_API_CPU: - case NATIVE_WINDOW_API_MEDIA: - case NATIVE_WINDOW_API_CAMERA: - mConnectedApi = api; - output->inflate(mDefaultWidth, mDefaultHeight, mTransformHint, mQueue.size()); - - // set-up a death notification so that we can disconnect - // automatically when/if the remote producer dies. - if (token != NULL && token->remoteBinder() != NULL) { - status_t err = token->linkToDeath(static_cast<IBinder::DeathRecipient*>(this)); - if (err == NO_ERROR) { - mConnectedProducerToken = token; - } else { - ALOGE("linkToDeath failed: %s (%d)", strerror(-err), err); - } - } - break; - default: - err = -EINVAL; - break; - } - - mBufferHasBeenQueued = false; - mDequeueBufferCannotBlock = mConsumerControlledByApp && producerControlledByApp; - - return err; -} - -void GonkBufferQueue::binderDied(const wp<IBinder>& who) { - // If we're here, it means that a producer we were connected to died. - // We're GUARANTEED that we still are connected to it because it has no other way - // to get disconnected -- or -- we wouldn't be here because we're removing this - // callback upon disconnect. Therefore, it's okay to read mConnectedApi without - // synchronization here. - int api = mConnectedApi; - this->disconnect(api); -} - -status_t GonkBufferQueue::disconnect(int api) { - ATRACE_CALL(); - ALOGV("disconnect: api=%d", api); - - int err = NO_ERROR; - sp<IConsumerListener> listener; - - { // Scope for the lock - Mutex::Autolock lock(mMutex); - - if (mAbandoned) { - // it is not really an error to disconnect after the surface - // has been abandoned, it should just be a no-op. - return NO_ERROR; - } - - switch (api) { - case NATIVE_WINDOW_API_EGL: - case NATIVE_WINDOW_API_CPU: - case NATIVE_WINDOW_API_MEDIA: - case NATIVE_WINDOW_API_CAMERA: - if (mConnectedApi == api) { - freeAllBuffersLocked(); - mConnectedApi = NO_CONNECTED_API; - mDequeueCondition.broadcast(); - listener = mConsumerListener; - } else { - ALOGE("disconnect: connected to another api (cur=%d, req=%d)", - mConnectedApi, api); - err = -EINVAL; - } - break; - default: - ALOGE("disconnect: unknown API %d", api); - err = -EINVAL; - break; - } - } - - if (listener != NULL) { - listener->onBuffersReleased(); - } - - return err; -} - -void GonkBufferQueue::dumpToString(String8& result, const char* prefix) const { - Mutex::Autolock _l(mMutex); - - String8 fifo; - int fifoSize = 0; - Fifo::const_iterator i(mQueue.begin()); - while (i != mQueue.end()) { - fifo.appendFormat("%02d:%p crop=[%d,%d,%d,%d], " - "xform=0x%02x, time=%#llx, scale=%s\n", - i->mBuf, i->mGraphicBuffer.get(), - i->mCrop.left, i->mCrop.top, i->mCrop.right, - i->mCrop.bottom, i->mTransform, i->mTimestamp, - scalingModeName(i->mScalingMode) - ); - i++; - fifoSize++; - } - - - result.appendFormat( - "%s-BufferQueue mMaxAcquiredBufferCount=%d, mDequeueBufferCannotBlock=%d, default-size=[%dx%d], " - "default-format=%d, transform-hint=%02x, FIFO(%d)={%s}\n", - prefix, mMaxAcquiredBufferCount, mDequeueBufferCannotBlock, mDefaultWidth, - mDefaultHeight, mDefaultBufferFormat, mTransformHint, - fifoSize, fifo.string()); - - struct { - const char * operator()(int state) const { - switch (state) { - case BufferSlot::DEQUEUED: return "DEQUEUED"; - case BufferSlot::QUEUED: return "QUEUED"; - case BufferSlot::FREE: return "FREE"; - case BufferSlot::ACQUIRED: return "ACQUIRED"; - default: return "Unknown"; - } - } - } stateName; - - // just trim the free buffers to not spam the dump - int maxBufferCount = 0; - for (int i=NUM_BUFFER_SLOTS-1 ; i>=0 ; i--) { - const BufferSlot& slot(mSlots[i]); - if ((slot.mBufferState != BufferSlot::FREE) || (slot.mGraphicBuffer != NULL)) { - maxBufferCount = i+1; - break; - } - } - - for (int i=0 ; i<maxBufferCount ; i++) { - const BufferSlot& slot(mSlots[i]); - const sp<GraphicBuffer>& buf(slot.mGraphicBuffer); - result.appendFormat( - "%s%s[%02d:%p] state=%-8s", - prefix, (slot.mBufferState == BufferSlot::ACQUIRED)?">":" ", i, buf.get(), - stateName(slot.mBufferState) - ); - - if (buf != NULL) { - result.appendFormat( - ", %p [%4ux%4u:%4u,%3X]", - buf->handle, buf->width, buf->height, buf->stride, - buf->format); - } - result.append("\n"); - } -} - -void GonkBufferQueue::freeAllBuffersLocked() -{ - ALOGW_IF(!mQueue.isEmpty(), - "freeAllBuffersLocked called but mQueue is not empty"); - mQueue.clear(); - mBufferHasBeenQueued = false; - for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { - mSlots[i].mGraphicBuffer = 0; - if (mSlots[i].mTextureClient) { - mSlots[i].mTextureClient->ClearRecycleCallback(); - // release TextureClient in ImageBridge thread - RefPtr<TextureClientReleaseTask> task = - MakeAndAddRef<TextureClientReleaseTask>(mSlots[i].mTextureClient); - mSlots[i].mTextureClient = NULL; - ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask(task.forget()); - } - if (mSlots[i].mBufferState == BufferSlot::ACQUIRED) { - mSlots[i].mNeedsCleanupOnRelease = true; - } - mSlots[i].mBufferState = BufferSlot::FREE; - mSlots[i].mFrameNumber = 0; - mSlots[i].mAcquireCalled = false; - // destroy fence as GonkBufferQueue now takes ownership - mSlots[i].mFence = Fence::NO_FENCE; - } -} - -status_t GonkBufferQueue::acquireBuffer(BufferItem *buffer, nsecs_t expectedPresent) { - ATRACE_CALL(); - Mutex::Autolock _l(mMutex); - - // Check that the consumer doesn't currently have the maximum number of - // buffers acquired. We allow the max buffer count to be exceeded by one - // buffer, so that the consumer can successfully set up the newly acquired - // buffer before releasing the old one. - int numAcquiredBuffers = 0; - for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { - if (mSlots[i].mBufferState == BufferSlot::ACQUIRED) { - numAcquiredBuffers++; - } - } - if (numAcquiredBuffers >= mMaxAcquiredBufferCount+1) { - ALOGE("acquireBuffer: max acquired buffer count reached: %d (max=%d)", - numAcquiredBuffers, mMaxAcquiredBufferCount); - return INVALID_OPERATION; - } - - // check if queue is empty - // In asynchronous mode the list is guaranteed to be one buffer - // deep, while in synchronous mode we use the oldest buffer. - if (mQueue.empty()) { - return NO_BUFFER_AVAILABLE; - } - - Fifo::iterator front(mQueue.begin()); - - // If expectedPresent is specified, we may not want to return a buffer yet. - // If it's specified and there's more than one buffer queued, we may - // want to drop a buffer. - if (expectedPresent != 0) { - const int MAX_REASONABLE_NSEC = 1000000000ULL; // 1 second - - // The "expectedPresent" argument indicates when the buffer is expected - // to be presented on-screen. If the buffer's desired-present time - // is earlier (less) than expectedPresent, meaning it'll be displayed - // on time or possibly late if we show it ASAP, we acquire and return - // it. If we don't want to display it until after the expectedPresent - // time, we return PRESENT_LATER without acquiring it. - // - // To be safe, we don't defer acquisition if expectedPresent is - // more than one second in the future beyond the desired present time - // (i.e. we'd be holding the buffer for a long time). - // - // NOTE: code assumes monotonic time values from the system clock are - // positive. - - // Start by checking to see if we can drop frames. We skip this check - // if the timestamps are being auto-generated by Surface -- if the - // app isn't generating timestamps explicitly, they probably don't - // want frames to be discarded based on them. - while (mQueue.size() > 1 && !mQueue[0].mIsAutoTimestamp) { - // If entry[1] is timely, drop entry[0] (and repeat). We apply - // an additional criteria here: we only drop the earlier buffer if - // our desiredPresent falls within +/- 1 second of the expected - // present. Otherwise, bogus desiredPresent times (e.g. 0 or - // a small relative timestamp), which normally mean "ignore the - // timestamp and acquire immediately", would cause us to drop - // frames. - // - // We may want to add an additional criteria: don't drop the - // earlier buffer if entry[1]'s fence hasn't signaled yet. - // - // (Vector front is [0], back is [size()-1]) - const BufferItem& bi(mQueue[1]); - nsecs_t desiredPresent = bi.mTimestamp; - if (desiredPresent < expectedPresent - MAX_REASONABLE_NSEC || - desiredPresent > expectedPresent) { - // This buffer is set to display in the near future, or - // desiredPresent is garbage. Either way we don't want to - // drop the previous buffer just to get this on screen sooner. - ALOGV("pts nodrop: des=%lld expect=%lld (%lld) now=%lld", - desiredPresent, expectedPresent, desiredPresent - expectedPresent, - systemTime(CLOCK_MONOTONIC)); - break; - } - ALOGV("pts drop: queue1des=%lld expect=%lld size=%d", - desiredPresent, expectedPresent, mQueue.size()); - if (stillTracking(front)) { - // front buffer is still in mSlots, so mark the slot as free - mSlots[front->mBuf].mBufferState = BufferSlot::FREE; - } - mQueue.erase(front); - front = mQueue.begin(); - } - - // See if the front buffer is due. - nsecs_t desiredPresent = front->mTimestamp; - if (desiredPresent > expectedPresent && - desiredPresent < expectedPresent + MAX_REASONABLE_NSEC) { - ALOGV("pts defer: des=%lld expect=%lld (%lld) now=%lld", - desiredPresent, expectedPresent, desiredPresent - expectedPresent, - systemTime(CLOCK_MONOTONIC)); - return PRESENT_LATER; - } - - ALOGV("pts accept: des=%lld expect=%lld (%lld) now=%lld", - desiredPresent, expectedPresent, desiredPresent - expectedPresent, - systemTime(CLOCK_MONOTONIC)); - } - - int buf = front->mBuf; - buffer->mGraphicBuffer = mSlots[buf].mGraphicBuffer; - buffer->mFrameNumber = mSlots[buf].mFrameNumber; - buffer->mBuf = buf; - buffer->mFence = mSlots[buf].mFence; - ATRACE_BUFFER_INDEX(buf); - - ALOGV("acquireBuffer: acquiring { slot=%d/%llu, buffer=%p }", - front->mBuf, front->mFrameNumber, - front->mGraphicBuffer->handle); - // if front buffer still being tracked update slot state - if (stillTracking(front)) { - mSlots[buf].mAcquireCalled = true; - mSlots[buf].mNeedsCleanupOnRelease = false; - mSlots[buf].mBufferState = BufferSlot::ACQUIRED; - mSlots[buf].mFence = Fence::NO_FENCE; - } - - // If the buffer has previously been acquired by the consumer, set - // mGraphicBuffer to NULL to avoid unnecessarily remapping this - // buffer on the consumer side. - //if (buffer->mAcquireCalled) { - // buffer->mGraphicBuffer = NULL; - //} - - mQueue.erase(front); - mDequeueCondition.broadcast(); - - return NO_ERROR; -} - -status_t GonkBufferQueue::releaseBuffer(int buf, uint64_t frameNumber, const sp<Fence>& fence) { - ATRACE_CALL(); - - if (buf == INVALID_BUFFER_SLOT || fence == NULL) { - return BAD_VALUE; - } - - Mutex::Autolock _l(mMutex); - - // If the frame number has changed because buffer has been reallocated, - // we can ignore this releaseBuffer for the old buffer. - //if (frameNumber != mSlots[buf].mFrameNumber) { - // return STALE_BUFFER_SLOT; - //} - - - // Internal state consistency checks: - // Make sure this buffers hasn't been queued while we were owning it (acquired) - Fifo::iterator front(mQueue.begin()); - Fifo::const_iterator const end(mQueue.end()); - while (front != end) { - if (front->mBuf == buf) { - LOG_ALWAYS_FATAL("[%s] received new buffer(#%lld) on slot #%d that has not yet been " - "acquired", mConsumerName.string(), frameNumber, buf); - break; // never reached - } - front++; - } - - // The buffer can now only be released if its in the acquired state - if (mSlots[buf].mBufferState == BufferSlot::ACQUIRED) { - mSlots[buf].mFence = fence; - mSlots[buf].mBufferState = BufferSlot::FREE; - } else if (mSlots[buf].mNeedsCleanupOnRelease) { - ALOGV("releasing a stale buf %d its state was %d", buf, mSlots[buf].mBufferState); - mSlots[buf].mNeedsCleanupOnRelease = false; - return STALE_BUFFER_SLOT; - } else { - ALOGE("attempted to release buf %d but its state was %d", buf, mSlots[buf].mBufferState); - return -EINVAL; - } - - mDequeueCondition.broadcast(); - return NO_ERROR; -} - -status_t GonkBufferQueue::consumerConnect(const sp<IConsumerListener>& consumerListener, - bool controlledByApp) { - ALOGV("consumerConnect controlledByApp=%s", - controlledByApp ? "true" : "false"); - Mutex::Autolock lock(mMutex); - - if (mAbandoned) { - ALOGE("consumerConnect: GonkBufferQueue has been abandoned!"); - return NO_INIT; - } - if (consumerListener == NULL) { - ALOGE("consumerConnect: consumerListener may not be NULL"); - return BAD_VALUE; - } - - mConsumerListener = consumerListener; - mConsumerControlledByApp = controlledByApp; - - return NO_ERROR; -} - -status_t GonkBufferQueue::consumerDisconnect() { - ALOGV("consumerDisconnect"); - Mutex::Autolock lock(mMutex); - - if (mConsumerListener == NULL) { - ALOGE("consumerDisconnect: No consumer is connected!"); - return -EINVAL; - } - - mAbandoned = true; - mConsumerListener = NULL; - mQueue.clear(); - freeAllBuffersLocked(); - mDequeueCondition.broadcast(); - return NO_ERROR; -} - -status_t GonkBufferQueue::getReleasedBuffers(uint32_t* slotMask) { - ALOGV("getReleasedBuffers"); - Mutex::Autolock lock(mMutex); - - if (mAbandoned) { - ALOGE("getReleasedBuffers: GonkBufferQueue has been abandoned!"); - return NO_INIT; - } - - uint32_t mask = 0; - for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { - if (!mSlots[i].mAcquireCalled) { - mask |= 1 << i; - } - } - - // Remove buffers in flight (on the queue) from the mask where acquire has - // been called, as the consumer will not receive the buffer address, so - // it should not free these slots. - Fifo::iterator front(mQueue.begin()); - while (front != mQueue.end()) { - if (front->mAcquireCalled) - mask &= ~(1 << front->mBuf); - front++; - } - - *slotMask = mask; - - ALOGV("getReleasedBuffers: returning mask %#x", mask); - return NO_ERROR; -} - -status_t GonkBufferQueue::setDefaultBufferSize(uint32_t w, uint32_t h) { - ALOGV("setDefaultBufferSize: w=%d, h=%d", w, h); - if (!w || !h) { - ALOGE("setDefaultBufferSize: dimensions cannot be 0 (w=%d, h=%d)", - w, h); - return BAD_VALUE; - } - - Mutex::Autolock lock(mMutex); - mDefaultWidth = w; - mDefaultHeight = h; - return NO_ERROR; -} - -status_t GonkBufferQueue::setDefaultMaxBufferCount(int bufferCount) { - ATRACE_CALL(); - Mutex::Autolock lock(mMutex); - return setDefaultMaxBufferCountLocked(bufferCount); -} - -status_t GonkBufferQueue::disableAsyncBuffer() { - ATRACE_CALL(); - Mutex::Autolock lock(mMutex); - if (mConsumerListener != NULL) { - ALOGE("disableAsyncBuffer: consumer already connected!"); - return INVALID_OPERATION; - } - mUseAsyncBuffer = false; - return NO_ERROR; -} - -status_t GonkBufferQueue::setMaxAcquiredBufferCount(int maxAcquiredBuffers) { - ATRACE_CALL(); - Mutex::Autolock lock(mMutex); - if (maxAcquiredBuffers < 1 || maxAcquiredBuffers > MAX_MAX_ACQUIRED_BUFFERS) { - ALOGE("setMaxAcquiredBufferCount: invalid count specified: %d", - maxAcquiredBuffers); - return BAD_VALUE; - } - if (mConnectedApi != NO_CONNECTED_API) { - return INVALID_OPERATION; - } - mMaxAcquiredBufferCount = maxAcquiredBuffers; - return NO_ERROR; -} - -int GonkBufferQueue::getMinUndequeuedBufferCount(bool async) const { - // if dequeueBuffer is allowed to error out, we don't have to - // add an extra buffer. - if (!mUseAsyncBuffer) - return mMaxAcquiredBufferCount; - - // we're in async mode, or we want to prevent the app to - // deadlock itself, we throw-in an extra buffer to guarantee it. - if (mDequeueBufferCannotBlock || async || !mSynchronousMode) - return mMaxAcquiredBufferCount + 1; - - return mMaxAcquiredBufferCount; -} - -int GonkBufferQueue::getMinMaxBufferCountLocked(bool async) const { - return getMinUndequeuedBufferCount(async) + 1; -} - -int GonkBufferQueue::getMaxBufferCountLocked(bool async) const { - int minMaxBufferCount = getMinMaxBufferCountLocked(async); - - int maxBufferCount = mDefaultMaxBufferCount; - if (maxBufferCount < minMaxBufferCount) { - maxBufferCount = minMaxBufferCount; - } - if (mOverrideMaxBufferCount != 0) { - assert(mOverrideMaxBufferCount >= minMaxBufferCount); - maxBufferCount = mOverrideMaxBufferCount; - } - - // Any buffers that are dequeued by the producer or sitting in the queue - // waiting to be consumed need to have their slots preserved. Such - // buffers will temporarily keep the max buffer count up until the slots - // no longer need to be preserved. - for (int i = maxBufferCount; i < NUM_BUFFER_SLOTS; i++) { - BufferSlot::BufferState state = mSlots[i].mBufferState; - if (state == BufferSlot::QUEUED || state == BufferSlot::DEQUEUED) { - maxBufferCount = i + 1; - } - } - - return maxBufferCount; -} - -bool GonkBufferQueue::stillTracking(const BufferItem *item) const { - const BufferSlot &slot = mSlots[item->mBuf]; - - ALOGV("stillTracking?: item: { slot=%d/%llu, buffer=%p }, " - "slot: { slot=%d/%llu, buffer=%p }", - item->mBuf, item->mFrameNumber, - (item->mGraphicBuffer.get() ? item->mGraphicBuffer->handle : 0), - item->mBuf, slot.mFrameNumber, - (slot.mGraphicBuffer.get() ? slot.mGraphicBuffer->handle : 0)); - - // Compare item with its original buffer slot. We can check the slot - // as the buffer would not be moved to a different slot by the producer. - return (slot.mGraphicBuffer != NULL && - item->mGraphicBuffer->handle == slot.mGraphicBuffer->handle); -} - -GonkBufferQueue::ProxyConsumerListener::ProxyConsumerListener( - const wp<ConsumerListener>& consumerListener): - mConsumerListener(consumerListener) {} - -GonkBufferQueue::ProxyConsumerListener::~ProxyConsumerListener() {} - -void GonkBufferQueue::ProxyConsumerListener::onFrameAvailable() { - sp<ConsumerListener> listener(mConsumerListener.promote()); - if (listener != NULL) { - listener->onFrameAvailable(); - } -} - -void GonkBufferQueue::ProxyConsumerListener::onBuffersReleased() { - sp<ConsumerListener> listener(mConsumerListener.promote()); - if (listener != NULL) { - listener->onBuffersReleased(); - } -} - -}; // namespace android diff --git a/widget/gonk/nativewindow/GonkBufferQueueKK.h b/widget/gonk/nativewindow/GonkBufferQueueKK.h deleted file mode 100644 index 01905427d..000000000 --- a/widget/gonk/nativewindow/GonkBufferQueueKK.h +++ /dev/null @@ -1,583 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * Copyright (C) 2013 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef NATIVEWINDOW_GONKBUFFERQUEUE_KK_H -#define NATIVEWINDOW_GONKBUFFERQUEUE_KK_H - -#include <gui/IConsumerListener.h> -#include <gui/IGraphicBufferAlloc.h> -#include <gui/IGraphicBufferProducer.h> -#include "IGonkGraphicBufferConsumer.h" - -#include <ui/Fence.h> -#include <ui/GraphicBuffer.h> - -#include <utils/String8.h> -#include <utils/Vector.h> -#include <utils/threads.h> - -#include "mozilla/layers/LayersSurfaces.h" -#include "mozilla/layers/TextureClient.h" - -namespace android { -// ---------------------------------------------------------------------------- - -class GonkBufferQueue : public BnGraphicBufferProducer, - public BnGonkGraphicBufferConsumer, - private IBinder::DeathRecipient -{ - typedef mozilla::layers::TextureClient TextureClient; - -public: - enum { MIN_UNDEQUEUED_BUFFERS = 2 }; - enum { NUM_BUFFER_SLOTS = 32 }; - enum { NO_CONNECTED_API = 0 }; - enum { INVALID_BUFFER_SLOT = -1 }; - enum { STALE_BUFFER_SLOT = 1, NO_BUFFER_AVAILABLE, PRESENT_LATER }; - - // When in async mode we reserve two slots in order to guarantee that the - // producer and consumer can run asynchronously. - enum { MAX_MAX_ACQUIRED_BUFFERS = NUM_BUFFER_SLOTS - 2 }; - - // for backward source compatibility - typedef ::android::ConsumerListener ConsumerListener; - - // ProxyConsumerListener is a ConsumerListener implementation that keeps a weak - // reference to the actual consumer object. It forwards all calls to that - // consumer object so long as it exists. - // - // This class exists to avoid having a circular reference between the - // GonkBufferQueue object and the consumer object. The reason this can't be a weak - // reference in the GonkBufferQueue class is because we're planning to expose the - // consumer side of a GonkBufferQueue as a binder interface, which doesn't support - // weak references. - class ProxyConsumerListener : public BnConsumerListener { - public: - ProxyConsumerListener(const wp<ConsumerListener>& consumerListener); - virtual ~ProxyConsumerListener(); - virtual void onFrameAvailable(); - virtual void onBuffersReleased(); - private: - // mConsumerListener is a weak reference to the IConsumerListener. This is - // the raison d'etre of ProxyConsumerListener. - wp<ConsumerListener> mConsumerListener; - }; - - - // BufferQueue manages a pool of gralloc memory slots to be used by - // producers and consumers. allocator is used to allocate all the - // needed gralloc buffers. - GonkBufferQueue(bool allowSynchronousMode = true, - const sp<IGraphicBufferAlloc>& allocator = NULL); - virtual ~GonkBufferQueue(); - - /* - * IBinder::DeathRecipient interface - */ - - virtual void binderDied(const wp<IBinder>& who); - - /* - * IGraphicBufferProducer interface - */ - - // Query native window attributes. The "what" values are enumerated in - // window.h (e.g. NATIVE_WINDOW_FORMAT). - virtual int query(int what, int* value); - - // setBufferCount updates the number of available buffer slots. If this - // method succeeds, buffer slots will be both unallocated and owned by - // the GonkBufferQueue object (i.e. they are not owned by the producer or - // consumer). - // - // This will fail if the producer has dequeued any buffers, or if - // bufferCount is invalid. bufferCount must generally be a value - // between the minimum undequeued buffer count and NUM_BUFFER_SLOTS - // (inclusive). It may also be set to zero (the default) to indicate - // that the producer does not wish to set a value. The minimum value - // can be obtained by calling query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, - // ...). - // - // This may only be called by the producer. The consumer will be told - // to discard buffers through the onBuffersReleased callback. - virtual status_t setBufferCount(int bufferCount); - - // requestBuffer returns the GraphicBuffer for slot N. - // - // In normal operation, this is called the first time slot N is returned - // by dequeueBuffer. It must be called again if dequeueBuffer returns - // flags indicating that previously-returned buffers are no longer valid. - virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf); - - // dequeueBuffer gets the next buffer slot index for the producer to use. - // If a buffer slot is available then that slot index is written to the - // location pointed to by the buf argument and a status of OK is returned. - // If no slot is available then a status of -EBUSY is returned and buf is - // unmodified. - // - // The fence parameter will be updated to hold the fence associated with - // the buffer. The contents of the buffer must not be overwritten until the - // fence signals. If the fence is Fence::NO_FENCE, the buffer may be - // written immediately. - // - // The width and height parameters must be no greater than the minimum of - // GL_MAX_VIEWPORT_DIMS and GL_MAX_TEXTURE_SIZE (see: glGetIntegerv). - // An error due to invalid dimensions might not be reported until - // updateTexImage() is called. If width and height are both zero, the - // default values specified by setDefaultBufferSize() are used instead. - // - // The pixel formats are enumerated in graphics.h, e.g. - // HAL_PIXEL_FORMAT_RGBA_8888. If the format is 0, the default format - // will be used. - // - // The usage argument specifies gralloc buffer usage flags. The values - // are enumerated in gralloc.h, e.g. GRALLOC_USAGE_HW_RENDER. These - // will be merged with the usage flags specified by setConsumerUsageBits. - // - // The return value may be a negative error value or a non-negative - // collection of flags. If the flags are set, the return values are - // valid, but additional actions must be performed. - // - // If IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION is set, the - // producer must discard cached GraphicBuffer references for the slot - // returned in buf. - // If IGraphicBufferProducer::RELEASE_ALL_BUFFERS is set, the producer - // must discard cached GraphicBuffer references for all slots. - // - // In both cases, the producer will need to call requestBuffer to get a - // GraphicBuffer handle for the returned slot. - virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence, bool async, - uint32_t width, uint32_t height, uint32_t format, uint32_t usage); - - // queueBuffer returns a filled buffer to the GonkBufferQueue. - // - // Additional data is provided in the QueueBufferInput struct. Notably, - // a timestamp must be provided for the buffer. The timestamp is in - // nanoseconds, and must be monotonically increasing. Its other semantics - // (zero point, etc) are producer-specific and should be documented by the - // producer. - // - // The caller may provide a fence that signals when all rendering - // operations have completed. Alternatively, NO_FENCE may be used, - // indicating that the buffer is ready immediately. - // - // Some values are returned in the output struct: the current settings - // for default width and height, the current transform hint, and the - // number of queued buffers. - virtual status_t queueBuffer(int buf, - const QueueBufferInput& input, QueueBufferOutput* output); - - // cancelBuffer returns a dequeued buffer to the GonkBufferQueue, but doesn't - // queue it for use by the consumer. - // - // The buffer will not be overwritten until the fence signals. The fence - // will usually be the one obtained from dequeueBuffer. - virtual void cancelBuffer(int buf, const sp<Fence>& fence); - - // setSynchronousMode sets whether dequeueBuffer is synchronous or - // asynchronous. In synchronous mode, dequeueBuffer blocks until - // a buffer is available, the currently bound buffer can be dequeued and - // queued buffers will be acquired in order. In asynchronous mode, - // a queued buffer may be replaced by a subsequently queued buffer. - // - // The default mode is synchronous. - // This should be called only during initialization. - virtual status_t setSynchronousMode(bool enabled); - - // connect attempts to connect a producer API to the GonkBufferQueue. This - // must be called before any other IGraphicBufferProducer methods are - // called except for getAllocator. A consumer must already be connected. - // - // This method will fail if connect was previously called on the - // GonkBufferQueue and no corresponding disconnect call was made (i.e. if - // it's still connected to a producer). - // - // APIs are enumerated in window.h (e.g. NATIVE_WINDOW_API_CPU). - virtual status_t connect(const sp<IBinder>& token, - int api, bool producerControlledByApp, QueueBufferOutput* output); - - // disconnect attempts to disconnect a producer API from the GonkBufferQueue. - // Calling this method will cause any subsequent calls to other - // IGraphicBufferProducer methods to fail except for getAllocator and connect. - // Successfully calling connect after this will allow the other methods to - // succeed again. - // - // This method will fail if the the GonkBufferQueue is not currently - // connected to the specified producer API. - virtual status_t disconnect(int api); - - /* - * IGraphicBufferConsumer interface - */ - - // acquireBuffer attempts to acquire ownership of the next pending buffer in - // the GonkBufferQueue. If no buffer is pending then it returns -EINVAL. If a - // buffer is successfully acquired, the information about the buffer is - // returned in BufferItem. If the buffer returned had previously been - // acquired then the BufferItem::mGraphicBuffer field of buffer is set to - // NULL and it is assumed that the consumer still holds a reference to the - // buffer. - // - // If presentWhen is nonzero, it indicates the time when the buffer will - // be displayed on screen. If the buffer's timestamp is farther in the - // future, the buffer won't be acquired, and PRESENT_LATER will be - // returned. The presentation time is in nanoseconds, and the time base - // is CLOCK_MONOTONIC. - virtual status_t acquireBuffer(BufferItem *buffer, nsecs_t presentWhen); - - // releaseBuffer releases a buffer slot from the consumer back to the - // GonkBufferQueue. This may be done while the buffer's contents are still - // being accessed. The fence will signal when the buffer is no longer - // in use. frameNumber is used to indentify the exact buffer returned. - // - // If releaseBuffer returns STALE_BUFFER_SLOT, then the consumer must free - // any references to the just-released buffer that it might have, as if it - // had received a onBuffersReleased() call with a mask set for the released - // buffer. - // - // Note that the dependencies on EGL will be removed once we switch to using - // the Android HW Sync HAL. - virtual status_t releaseBuffer(int buf, uint64_t frameNumber, - const sp<Fence>& releaseFence); - - // consumerConnect connects a consumer to the GonkBufferQueue. Only one - // consumer may be connected, and when that consumer disconnects the - // GonkBufferQueue is placed into the "abandoned" state, causing most - // interactions with the GonkBufferQueue by the producer to fail. - // controlledByApp indicates whether the consumer is controlled by - // the application. - // - // consumer may not be NULL. - virtual status_t consumerConnect(const sp<IConsumerListener>& consumer, bool controlledByApp); - - // consumerDisconnect disconnects a consumer from the GonkBufferQueue. All - // buffers will be freed and the GonkBufferQueue is placed in the "abandoned" - // state, causing most interactions with the GonkBufferQueue by the producer to - // fail. - virtual status_t consumerDisconnect(); - - // getReleasedBuffers sets the value pointed to by slotMask to a bit mask - // indicating which buffer slots have been released by the GonkBufferQueue - // but have not yet been released by the consumer. - // - // This should be called from the onBuffersReleased() callback. - virtual status_t getReleasedBuffers(uint32_t* slotMask); - - // setDefaultBufferSize is used to set the size of buffers returned by - // dequeueBuffer when a width and height of zero is requested. Default - // is 1x1. - virtual status_t setDefaultBufferSize(uint32_t w, uint32_t h); - - // setDefaultMaxBufferCount sets the default value for the maximum buffer - // count (the initial default is 2). If the producer has requested a - // buffer count using setBufferCount, the default buffer count will only - // take effect if the producer sets the count back to zero. - // - // The count must be between 2 and NUM_BUFFER_SLOTS, inclusive. - virtual status_t setDefaultMaxBufferCount(int bufferCount); - - // disableAsyncBuffer disables the extra buffer used in async mode - // (when both producer and consumer have set their "isControlledByApp" - // flag) and has dequeueBuffer() return WOULD_BLOCK instead. - // - // This can only be called before consumerConnect(). - virtual status_t disableAsyncBuffer(); - - // setMaxAcquiredBufferCount sets the maximum number of buffers that can - // be acquired by the consumer at one time (default 1). This call will - // fail if a producer is connected to the GonkBufferQueue. - virtual status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers); - - // setConsumerName sets the name used in logging - virtual void setConsumerName(const String8& name); - - // setDefaultBufferFormat allows the GonkBufferQueue to create - // GraphicBuffers of a defaultFormat if no format is specified - // in dequeueBuffer. Formats are enumerated in graphics.h; the - // initial default is HAL_PIXEL_FORMAT_RGBA_8888. - virtual status_t setDefaultBufferFormat(uint32_t defaultFormat); - - // setConsumerUsageBits will turn on additional usage bits for dequeueBuffer. - // These are merged with the bits passed to dequeueBuffer. The values are - // enumerated in gralloc.h, e.g. GRALLOC_USAGE_HW_RENDER; the default is 0. - virtual status_t setConsumerUsageBits(uint32_t usage); - - // setTransformHint bakes in rotation to buffers so overlays can be used. - // The values are enumerated in window.h, e.g. - // NATIVE_WINDOW_TRANSFORM_ROT_90. The default is 0 (no transform). - virtual status_t setTransformHint(uint32_t hint); - - // dump our state in a String - virtual void dumpToString(String8& result, const char* prefix) const; - - already_AddRefed<TextureClient> getTextureClientFromBuffer(ANativeWindowBuffer* buffer); - - int getSlotFromTextureClientLocked(TextureClient* client) const; - -private: - // freeBufferLocked frees the GraphicBuffer and sync resources for the - // given slot. - //void freeBufferLocked(int index); - - // freeAllBuffersLocked frees the GraphicBuffer and sync resources for - // all slots. - void freeAllBuffersLocked(); - - // setDefaultMaxBufferCountLocked sets the maximum number of buffer slots - // that will be used if the producer does not override the buffer slot - // count. The count must be between 2 and NUM_BUFFER_SLOTS, inclusive. - // The initial default is 2. - status_t setDefaultMaxBufferCountLocked(int count); - - // getMinUndequeuedBufferCount returns the minimum number of buffers - // that must remain in a state other than DEQUEUED. - // The async parameter tells whether we're in asynchronous mode. - int getMinUndequeuedBufferCount(bool async) const; - - // getMinBufferCountLocked returns the minimum number of buffers allowed - // given the current GonkBufferQueue state. - // The async parameter tells whether we're in asynchronous mode. - int getMinMaxBufferCountLocked(bool async) const; - - // getMaxBufferCountLocked returns the maximum number of buffers that can - // be allocated at once. This value depends upon the following member - // variables: - // - // mDequeueBufferCannotBlock - // mMaxAcquiredBufferCount - // mDefaultMaxBufferCount - // mOverrideMaxBufferCount - // async parameter - // - // Any time one of these member variables is changed while a producer is - // connected, mDequeueCondition must be broadcast. - int getMaxBufferCountLocked(bool async) const; - - // stillTracking returns true iff the buffer item is still being tracked - // in one of the slots. - bool stillTracking(const BufferItem *item) const; - - struct BufferSlot { - - BufferSlot() - : mBufferState(BufferSlot::FREE), - mRequestBufferCalled(false), - mFrameNumber(0), - mAcquireCalled(false), - mNeedsCleanupOnRelease(false) { - } - - // mGraphicBuffer points to the buffer allocated for this slot or is NULL - // if no buffer has been allocated. - sp<GraphicBuffer> mGraphicBuffer; - - // mTextureClient is a thin abstraction over remotely allocated GraphicBuffer. - RefPtr<TextureClient> mTextureClient; - - // BufferState represents the different states in which a buffer slot - // can be. All slots are initially FREE. - enum BufferState { - // FREE indicates that the buffer is available to be dequeued - // by the producer. The buffer may be in use by the consumer for - // a finite time, so the buffer must not be modified until the - // associated fence is signaled. - // - // The slot is "owned" by GonkBufferQueue. It transitions to DEQUEUED - // when dequeueBuffer is called. - FREE = 0, - - // DEQUEUED indicates that the buffer has been dequeued by the - // producer, but has not yet been queued or canceled. The - // producer may modify the buffer's contents as soon as the - // associated ready fence is signaled. - // - // The slot is "owned" by the producer. It can transition to - // QUEUED (via queueBuffer) or back to FREE (via cancelBuffer). - DEQUEUED = 1, - - // QUEUED indicates that the buffer has been filled by the - // producer and queued for use by the consumer. The buffer - // contents may continue to be modified for a finite time, so - // the contents must not be accessed until the associated fence - // is signaled. - // - // The slot is "owned" by GonkBufferQueue. It can transition to - // ACQUIRED (via acquireBuffer) or to FREE (if another buffer is - // queued in asynchronous mode). - QUEUED = 2, - - // ACQUIRED indicates that the buffer has been acquired by the - // consumer. As with QUEUED, the contents must not be accessed - // by the consumer until the fence is signaled. - // - // The slot is "owned" by the consumer. It transitions to FREE - // when releaseBuffer is called. - ACQUIRED = 3 - }; - - // mBufferState is the current state of this buffer slot. - BufferState mBufferState; - - // mRequestBufferCalled is used for validating that the producer did - // call requestBuffer() when told to do so. Technically this is not - // needed but useful for debugging and catching producer bugs. - bool mRequestBufferCalled; - - // mFrameNumber is the number of the queued frame for this slot. This - // is used to dequeue buffers in LRU order (useful because buffers - // may be released before their release fence is signaled). - uint64_t mFrameNumber; - - // mFence is a fence which will signal when work initiated by the - // previous owner of the buffer is finished. When the buffer is FREE, - // the fence indicates when the consumer has finished reading - // from the buffer, or when the producer has finished writing if it - // called cancelBuffer after queueing some writes. When the buffer is - // QUEUED, it indicates when the producer has finished filling the - // buffer. When the buffer is DEQUEUED or ACQUIRED, the fence has been - // passed to the consumer or producer along with ownership of the - // buffer, and mFence is set to NO_FENCE. - sp<Fence> mFence; - - // Indicates whether this buffer has been seen by a consumer yet - bool mAcquireCalled; - - // Indicates whether this buffer needs to be cleaned up by the - // consumer. This is set when a buffer in ACQUIRED state is freed. - // It causes releaseBuffer to return STALE_BUFFER_SLOT. - bool mNeedsCleanupOnRelease; - }; - - // mSlots is the array of buffer slots that must be mirrored on the - // producer side. This allows buffer ownership to be transferred between - // the producer and consumer without sending a GraphicBuffer over binder. - // The entire array is initialized to NULL at construction time, and - // buffers are allocated for a slot when requestBuffer is called with - // that slot's index. - BufferSlot mSlots[NUM_BUFFER_SLOTS]; - - // mDefaultWidth holds the default width of allocated buffers. It is used - // in dequeueBuffer() if a width and height of zero is specified. - uint32_t mDefaultWidth; - - // mDefaultHeight holds the default height of allocated buffers. It is used - // in dequeueBuffer() if a width and height of zero is specified. - uint32_t mDefaultHeight; - - // mMaxAcquiredBufferCount is the number of buffers that the consumer may - // acquire at one time. It defaults to 1 and can be changed by the - // consumer via the setMaxAcquiredBufferCount method, but this may only be - // done when no producer is connected to the GonkBufferQueue. - // - // This value is used to derive the value returned for the - // MIN_UNDEQUEUED_BUFFERS query by the producer. - int mMaxAcquiredBufferCount; - - // mDefaultMaxBufferCount is the default limit on the number of buffers - // that will be allocated at one time. This default limit is set by the - // consumer. The limit (as opposed to the default limit) may be - // overridden by the producer. - int mDefaultMaxBufferCount; - - // mOverrideMaxBufferCount is the limit on the number of buffers that will - // be allocated at one time. This value is set by the image producer by - // calling setBufferCount. The default is zero, which means the producer - // doesn't care about the number of buffers in the pool. In that case - // mDefaultMaxBufferCount is used as the limit. - int mOverrideMaxBufferCount; - - // mGraphicBufferAlloc is the connection to SurfaceFlinger that is used to - // allocate new GraphicBuffer objects. - sp<IGraphicBufferAlloc> mGraphicBufferAlloc; - - // mConsumerListener is used to notify the connected consumer of - // asynchronous events that it may wish to react to. It is initially set - // to NULL and is written by consumerConnect and consumerDisconnect. - sp<IConsumerListener> mConsumerListener; - - // mSynchronousMode whether we're in synchronous mode or not - bool mSynchronousMode; - - // mConsumerControlledByApp whether the connected consumer is controlled by the - // application. - bool mConsumerControlledByApp; - - // mDequeueBufferCannotBlock whether dequeueBuffer() isn't allowed to block. - // this flag is set during connect() when both consumer and producer are controlled - // by the application. - bool mDequeueBufferCannotBlock; - - // mUseAsyncBuffer whether an extra buffer is used in async mode to prevent - // dequeueBuffer() from ever blocking. - bool mUseAsyncBuffer; - - // mConnectedApi indicates the producer API that is currently connected - // to this GonkBufferQueue. It defaults to NO_CONNECTED_API (= 0), and gets - // updated by the connect and disconnect methods. - int mConnectedApi; - - // mDequeueCondition condition used for dequeueBuffer in synchronous mode - mutable Condition mDequeueCondition; - - // mQueue is a FIFO of queued buffers used in synchronous mode - typedef Vector<BufferItem> Fifo; - Fifo mQueue; - - // mAbandoned indicates that the GonkBufferQueue will no longer be used to - // consume image buffers pushed to it using the IGraphicBufferProducer - // interface. It is initialized to false, and set to true in the - // consumerDisconnect method. A GonkBufferQueue that has been abandoned will - // return the NO_INIT error from all IGraphicBufferProducer methods - // capable of returning an error. - bool mAbandoned; - - // mConsumerName is a string used to identify the GonkBufferQueue in log - // messages. It is set by the setConsumerName method. - String8 mConsumerName; - - // mMutex is the mutex used to prevent concurrent access to the member - // variables of GonkBufferQueue objects. It must be locked whenever the - // member variables are accessed. - mutable Mutex mMutex; - - // mFrameCounter is the free running counter, incremented on every - // successful queueBuffer call, and buffer allocation. - uint64_t mFrameCounter; - - // mBufferHasBeenQueued is true once a buffer has been queued. It is - // reset when something causes all buffers to be freed (e.g. changing the - // buffer count). - bool mBufferHasBeenQueued; - - // mDefaultBufferFormat can be set so it will override - // the buffer format when it isn't specified in dequeueBuffer - uint32_t mDefaultBufferFormat; - - // mConsumerUsageBits contains flags the consumer wants for GraphicBuffers - uint32_t mConsumerUsageBits; - - // mTransformHint is used to optimize for screen rotations - uint32_t mTransformHint; - - // mConnectedProducerToken is used to set a binder death notification on the producer - sp<IBinder> mConnectedProducerToken; -}; - -// ---------------------------------------------------------------------------- -}; // namespace android - -#endif // ANDROID_GUI_BUFFERQUEUE_H diff --git a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferItem.cpp b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferItem.cpp deleted file mode 100644 index 7df72bf68..000000000 --- a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferItem.cpp +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright 2014 The Android Open Source Project - * Copyright (C) 2014 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "GonkBufferItem.h" - -#include <ui/Fence.h> -#include <ui/GraphicBuffer.h> - -#include <system/window.h> - -namespace android { - -GonkBufferItem::GonkBufferItem() : - mTransform(0), - mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE), - mTimestamp(0), - mIsAutoTimestamp(false), - mFrameNumber(0), - mSlot(INVALID_BUFFER_SLOT), - mIsDroppable(false), - mAcquireCalled(false), - mTransformToDisplayInverse(false) { - mCrop.makeInvalid(); -} - -GonkBufferItem::operator IGonkGraphicBufferConsumer::BufferItem() const { - IGonkGraphicBufferConsumer::BufferItem bufferItem; - bufferItem.mGraphicBuffer = mGraphicBuffer; - bufferItem.mFence = mFence; - bufferItem.mCrop = mCrop; - bufferItem.mTransform = mTransform; - bufferItem.mScalingMode = mScalingMode; - bufferItem.mTimestamp = mTimestamp; - bufferItem.mIsAutoTimestamp = mIsAutoTimestamp; - bufferItem.mFrameNumber = mFrameNumber; - bufferItem.mBuf = mSlot; - bufferItem.mIsDroppable = mIsDroppable; - bufferItem.mAcquireCalled = mAcquireCalled; - bufferItem.mTransformToDisplayInverse = mTransformToDisplayInverse; - return bufferItem; -} - -size_t GonkBufferItem::getPodSize() const { - size_t c = sizeof(mCrop) + - sizeof(mTransform) + - sizeof(mScalingMode) + - sizeof(mTimestamp) + - sizeof(mIsAutoTimestamp) + - sizeof(mFrameNumber) + - sizeof(mSlot) + - sizeof(mIsDroppable) + - sizeof(mAcquireCalled) + - sizeof(mTransformToDisplayInverse); - return c; -} - -size_t GonkBufferItem::getFlattenedSize() const { - size_t c = 0; - if (mGraphicBuffer != 0) { - c += mGraphicBuffer->getFlattenedSize(); - FlattenableUtils::align<4>(c); - } - if (mFence != 0) { - c += mFence->getFlattenedSize(); - FlattenableUtils::align<4>(c); - } - return sizeof(int32_t) + c + getPodSize(); -} - -size_t GonkBufferItem::getFdCount() const { - size_t c = 0; - if (mGraphicBuffer != 0) { - c += mGraphicBuffer->getFdCount(); - } - if (mFence != 0) { - c += mFence->getFdCount(); - } - return c; -} - -status_t GonkBufferItem::flatten( - void*& buffer, size_t& size, int*& fds, size_t& count) const { - - // make sure we have enough space - if (count < GonkBufferItem::getFlattenedSize()) { - return NO_MEMORY; - } - - // content flags are stored first - uint32_t& flags = *static_cast<uint32_t*>(buffer); - - // advance the pointer - FlattenableUtils::advance(buffer, size, sizeof(uint32_t)); - - flags = 0; - if (mGraphicBuffer != 0) { - status_t err = mGraphicBuffer->flatten(buffer, size, fds, count); - if (err) return err; - size -= FlattenableUtils::align<4>(buffer); - flags |= 1; - } - if (mFence != 0) { - status_t err = mFence->flatten(buffer, size, fds, count); - if (err) return err; - size -= FlattenableUtils::align<4>(buffer); - flags |= 2; - } - - // check we have enough space (in case flattening the fence/graphicbuffer lied to us) - if (size < getPodSize()) { - return NO_MEMORY; - } - - FlattenableUtils::write(buffer, size, mCrop); - FlattenableUtils::write(buffer, size, mTransform); - FlattenableUtils::write(buffer, size, mScalingMode); - FlattenableUtils::write(buffer, size, mTimestamp); - FlattenableUtils::write(buffer, size, mIsAutoTimestamp); - FlattenableUtils::write(buffer, size, mFrameNumber); - FlattenableUtils::write(buffer, size, mSlot); - FlattenableUtils::write(buffer, size, mIsDroppable); - FlattenableUtils::write(buffer, size, mAcquireCalled); - FlattenableUtils::write(buffer, size, mTransformToDisplayInverse); - - return NO_ERROR; -} - -status_t GonkBufferItem::unflatten( - void const*& buffer, size_t& size, int const*& fds, size_t& count) { - - if (size < sizeof(uint32_t)) - return NO_MEMORY; - - uint32_t flags = 0; - FlattenableUtils::read(buffer, size, flags); - - if (flags & 1) { - mGraphicBuffer = new GraphicBuffer(); - status_t err = mGraphicBuffer->unflatten(buffer, size, fds, count); - if (err) return err; - size -= FlattenableUtils::align<4>(buffer); - } - - if (flags & 2) { - mFence = new Fence(); - status_t err = mFence->unflatten(buffer, size, fds, count); - if (err) return err; - size -= FlattenableUtils::align<4>(buffer); - } - - // check we have enough space - if (size < getPodSize()) { - return NO_MEMORY; - } - - FlattenableUtils::read(buffer, size, mCrop); - FlattenableUtils::read(buffer, size, mTransform); - FlattenableUtils::read(buffer, size, mScalingMode); - FlattenableUtils::read(buffer, size, mTimestamp); - FlattenableUtils::read(buffer, size, mIsAutoTimestamp); - FlattenableUtils::read(buffer, size, mFrameNumber); - FlattenableUtils::read(buffer, size, mSlot); - FlattenableUtils::read(buffer, size, mIsDroppable); - FlattenableUtils::read(buffer, size, mAcquireCalled); - FlattenableUtils::read(buffer, size, mTransformToDisplayInverse); - - return NO_ERROR; -} - -const char* GonkBufferItem::scalingModeName(uint32_t scalingMode) { - switch (scalingMode) { - case NATIVE_WINDOW_SCALING_MODE_FREEZE: return "FREEZE"; - case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: return "SCALE_TO_WINDOW"; - case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP: return "SCALE_CROP"; - default: return "Unknown"; - } -} - -} // namespace android diff --git a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferItem.h b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferItem.h deleted file mode 100644 index b2d6d3068..000000000 --- a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferItem.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2014 The Android Open Source Project - * Copyright (C) 2014 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef NATIVEWINDOW_GONKBUFFERITEM_LL_H -#define NATIVEWINDOW_GONKBUFFERITEM_LL_H - -#include "IGonkGraphicBufferConsumerLL.h" - -#include <ui/Rect.h> - -#include <utils/Flattenable.h> -#include <utils/StrongPointer.h> - -namespace android { - -class Fence; -class GraphicBuffer; - -class GonkBufferItem : public Flattenable<GonkBufferItem> { - friend class Flattenable<GonkBufferItem>; - size_t getPodSize() const; - size_t getFlattenedSize() const; - size_t getFdCount() const; - status_t flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const; - status_t unflatten(void const*& buffer, size_t& size, int const*& fds, size_t& count); - - public: - // The default value of mBuf, used to indicate this doesn't correspond to a slot. - enum { INVALID_BUFFER_SLOT = -1 }; - GonkBufferItem(); - operator IGonkGraphicBufferConsumer::BufferItem() const; - - static const char* scalingModeName(uint32_t scalingMode); - - // mGraphicBuffer points to the buffer allocated for this slot, or is NULL - // if the buffer in this slot has been acquired in the past (see - // BufferSlot.mAcquireCalled). - sp<GraphicBuffer> mGraphicBuffer; - - // mFence is a fence that will signal when the buffer is idle. - sp<Fence> mFence; - - // mCrop is the current crop rectangle for this buffer slot. - Rect mCrop; - - // mTransform is the current transform flags for this buffer slot. - // refer to NATIVE_WINDOW_TRANSFORM_* in <window.h> - uint32_t mTransform; - - // mScalingMode is the current scaling mode for this buffer slot. - // refer to NATIVE_WINDOW_SCALING_* in <window.h> - uint32_t mScalingMode; - - // mTimestamp is the current timestamp for this buffer slot. This gets - // to set by queueBuffer each time this slot is queued. This value - // is guaranteed to be monotonically increasing for each newly - // acquired buffer. - int64_t mTimestamp; - - // mIsAutoTimestamp indicates whether mTimestamp was generated - // automatically when the buffer was queued. - bool mIsAutoTimestamp; - - // mFrameNumber is the number of the queued frame for this slot. - uint64_t mFrameNumber; - - // mSlot is the slot index of this buffer (default INVALID_BUFFER_SLOT). - int mSlot; - - // mIsDroppable whether this buffer was queued with the - // property that it can be replaced by a new buffer for the purpose of - // making sure dequeueBuffer() won't block. - // i.e.: was the BufferQueue in "mDequeueBufferCannotBlock" when this buffer - // was queued. - bool mIsDroppable; - - // Indicates whether this buffer has been seen by a consumer yet - bool mAcquireCalled; - - // Indicates this buffer must be transformed by the inverse transform of the screen - // it is displayed onto. This is applied after mTransform. - bool mTransformToDisplayInverse; -}; - -} // namespace android - -#endif diff --git a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueConsumer.cpp b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueConsumer.cpp deleted file mode 100644 index 1d7eb2702..000000000 --- a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueConsumer.cpp +++ /dev/null @@ -1,559 +0,0 @@ -/* - * Copyright 2014 The Android Open Source Project - * Copyright (C) 2014 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <inttypes.h> - -#define LOG_TAG "GonkBufferQueueConsumer" -#define ATRACE_TAG ATRACE_TAG_GRAPHICS -//#define LOG_NDEBUG 0 - -#include "GonkBufferItem.h" -#include "GonkBufferQueueConsumer.h" -#include "GonkBufferQueueCore.h" -#include <gui/IConsumerListener.h> -#include <gui/IProducerListener.h> - -namespace android { - -GonkBufferQueueConsumer::GonkBufferQueueConsumer(const sp<GonkBufferQueueCore>& core) : - mCore(core), - mSlots(core->mSlots), - mConsumerName() {} - -GonkBufferQueueConsumer::~GonkBufferQueueConsumer() {} - -status_t GonkBufferQueueConsumer::acquireBuffer(BufferItem* outBuffer, - nsecs_t expectedPresent) { - ATRACE_CALL(); - Mutex::Autolock lock(mCore->mMutex); - - // Check that the consumer doesn't currently have the maximum number of - // buffers acquired. We allow the max buffer count to be exceeded by one - // buffer so that the consumer can successfully set up the newly acquired - // buffer before releasing the old one. - int numAcquiredBuffers = 0; - for (int s = 0; s < GonkBufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { - if (mSlots[s].mBufferState == GonkBufferSlot::ACQUIRED) { - ++numAcquiredBuffers; - } - } - if (numAcquiredBuffers >= mCore->mMaxAcquiredBufferCount + 1) { - ALOGE("acquireBuffer: max acquired buffer count reached: %d (max %d)", - numAcquiredBuffers, mCore->mMaxAcquiredBufferCount); - return INVALID_OPERATION; - } - - // Check if the queue is empty. - // In asynchronous mode the list is guaranteed to be one buffer deep, - // while in synchronous mode we use the oldest buffer. - if (mCore->mQueue.empty()) { - return NO_BUFFER_AVAILABLE; - } - - GonkBufferQueueCore::Fifo::iterator front(mCore->mQueue.begin()); - - // If expectedPresent is specified, we may not want to return a buffer yet. - // If it's specified and there's more than one buffer queued, we may want - // to drop a buffer. - if (expectedPresent != 0) { - const int MAX_REASONABLE_NSEC = 1000000000ULL; // 1 second - - // The 'expectedPresent' argument indicates when the buffer is expected - // to be presented on-screen. If the buffer's desired present time is - // earlier (less) than expectedPresent -- meaning it will be displayed - // on time or possibly late if we show it as soon as possible -- we - // acquire and return it. If we don't want to display it until after the - // expectedPresent time, we return PRESENT_LATER without acquiring it. - // - // To be safe, we don't defer acquisition if expectedPresent is more - // than one second in the future beyond the desired present time - // (i.e., we'd be holding the buffer for a long time). - // - // NOTE: Code assumes monotonic time values from the system clock - // are positive. - - // Start by checking to see if we can drop frames. We skip this check if - // the timestamps are being auto-generated by Surface. If the app isn't - // generating timestamps explicitly, it probably doesn't want frames to - // be discarded based on them. - while (mCore->mQueue.size() > 1 && !mCore->mQueue[0].mIsAutoTimestamp) { - // If entry[1] is timely, drop entry[0] (and repeat). We apply an - // additional criterion here: we only drop the earlier buffer if our - // desiredPresent falls within +/- 1 second of the expected present. - // Otherwise, bogus desiredPresent times (e.g., 0 or a small - // relative timestamp), which normally mean "ignore the timestamp - // and acquire immediately", would cause us to drop frames. - // - // We may want to add an additional criterion: don't drop the - // earlier buffer if entry[1]'s fence hasn't signaled yet. - const BufferItem& bufferItem(mCore->mQueue[1]); - nsecs_t desiredPresent = bufferItem.mTimestamp; - if (desiredPresent < expectedPresent - MAX_REASONABLE_NSEC || - desiredPresent > expectedPresent) { - // This buffer is set to display in the near future, or - // desiredPresent is garbage. Either way we don't want to drop - // the previous buffer just to get this on the screen sooner. - ALOGV("acquireBuffer: nodrop desire=%" PRId64 " expect=%" - PRId64 " (%" PRId64 ") now=%" PRId64, - desiredPresent, expectedPresent, - desiredPresent - expectedPresent, - systemTime(CLOCK_MONOTONIC)); - break; - } - - ALOGV("acquireBuffer: drop desire=%" PRId64 " expect=%" PRId64 - " size=%zu", - desiredPresent, expectedPresent, mCore->mQueue.size()); - if (mCore->stillTracking(front)) { - // Front buffer is still in mSlots, so mark the slot as free - mSlots[front->mSlot].mBufferState = GonkBufferSlot::FREE; - } - mCore->mQueue.erase(front); - front = mCore->mQueue.begin(); - } - - // See if the front buffer is due - nsecs_t desiredPresent = front->mTimestamp; - if (desiredPresent > expectedPresent && - desiredPresent < expectedPresent + MAX_REASONABLE_NSEC) { - ALOGV("acquireBuffer: defer desire=%" PRId64 " expect=%" PRId64 - " (%" PRId64 ") now=%" PRId64, - desiredPresent, expectedPresent, - desiredPresent - expectedPresent, - systemTime(CLOCK_MONOTONIC)); - return PRESENT_LATER; - } - - ALOGV("acquireBuffer: accept desire=%" PRId64 " expect=%" PRId64 " " - "(%" PRId64 ") now=%" PRId64, desiredPresent, expectedPresent, - desiredPresent - expectedPresent, - systemTime(CLOCK_MONOTONIC)); - } - - int slot = front->mSlot; - //*outBuffer = *front; - outBuffer->mGraphicBuffer = mSlots[slot].mGraphicBuffer; - outBuffer->mFrameNumber = mSlots[slot].mFrameNumber; - outBuffer->mBuf = slot; - outBuffer->mFence = mSlots[slot].mFence; - - ATRACE_BUFFER_INDEX(slot); - - ALOGV("acquireBuffer: acquiring { slot=%d/%" PRIu64 " buffer=%p }", - slot, front->mFrameNumber, front->mGraphicBuffer->handle); - // If the front buffer is still being tracked, update its slot state - if (mCore->stillTracking(front)) { - mSlots[slot].mAcquireCalled = true; - mSlots[slot].mNeedsCleanupOnRelease = false; - mSlots[slot].mBufferState = GonkBufferSlot::ACQUIRED; - mSlots[slot].mFence = Fence::NO_FENCE; - } - - // If the buffer has previously been acquired by the consumer, set - // mGraphicBuffer to NULL to avoid unnecessarily remapping this buffer - // on the consumer side - //if (outBuffer->mAcquireCalled) { - // outBuffer->mGraphicBuffer = NULL; - //} - - mCore->mQueue.erase(front); - - // We might have freed a slot while dropping old buffers, or the producer - // may be blocked waiting for the number of buffers in the queue to - // decrease. - mCore->mDequeueCondition.broadcast(); - - return NO_ERROR; -} - -status_t GonkBufferQueueConsumer::detachBuffer(int slot) { - ATRACE_CALL(); - ATRACE_BUFFER_INDEX(slot); - ALOGV("detachBuffer(C): slot %d", slot); - Mutex::Autolock lock(mCore->mMutex); - - if (mCore->mIsAbandoned) { - ALOGE("detachBuffer(C): GonkBufferQueue has been abandoned"); - return NO_INIT; - } - - if (slot < 0 || slot >= GonkBufferQueueDefs::NUM_BUFFER_SLOTS) { - ALOGE("detachBuffer(C): slot index %d out of range [0, %d)", - slot, GonkBufferQueueDefs::NUM_BUFFER_SLOTS); - return BAD_VALUE; - } else if (mSlots[slot].mBufferState != GonkBufferSlot::ACQUIRED) { - ALOGE("detachBuffer(C): slot %d is not owned by the consumer " - "(state = %d)", slot, mSlots[slot].mBufferState); - return BAD_VALUE; - } - - mCore->freeBufferLocked(slot); - mCore->mDequeueCondition.broadcast(); - - return NO_ERROR; -} - -status_t GonkBufferQueueConsumer::attachBuffer(int* outSlot, - const sp<android::GraphicBuffer>& buffer) { - ATRACE_CALL(); - - if (outSlot == NULL) { - ALOGE("attachBuffer(P): outSlot must not be NULL"); - return BAD_VALUE; - } else if (buffer == NULL) { - ALOGE("attachBuffer(P): cannot attach NULL buffer"); - return BAD_VALUE; - } - - Mutex::Autolock lock(mCore->mMutex); - - // Make sure we don't have too many acquired buffers and find a free slot - // to put the buffer into (the oldest if there are multiple). - int numAcquiredBuffers = 0; - int found = GonkBufferQueueCore::INVALID_BUFFER_SLOT; - for (int s = 0; s < GonkBufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { - if (mSlots[s].mBufferState == GonkBufferSlot::ACQUIRED) { - ++numAcquiredBuffers; - } else if (mSlots[s].mBufferState == GonkBufferSlot::FREE) { - if (found == GonkBufferQueueCore::INVALID_BUFFER_SLOT || - mSlots[s].mFrameNumber < mSlots[found].mFrameNumber) { - found = s; - } - } - } - - if (numAcquiredBuffers >= mCore->mMaxAcquiredBufferCount + 1) { - ALOGE("attachBuffer(P): max acquired buffer count reached: %d " - "(max %d)", numAcquiredBuffers, - mCore->mMaxAcquiredBufferCount); - return INVALID_OPERATION; - } - if (found == GonkBufferQueueCore::INVALID_BUFFER_SLOT) { - ALOGE("attachBuffer(P): could not find free buffer slot"); - return NO_MEMORY; - } - - *outSlot = found; - ATRACE_BUFFER_INDEX(*outSlot); - ALOGV("attachBuffer(C): returning slot %d", *outSlot); - - mSlots[*outSlot].mGraphicBuffer = buffer; - mSlots[*outSlot].mBufferState = GonkBufferSlot::ACQUIRED; - mSlots[*outSlot].mAttachedByConsumer = true; - mSlots[*outSlot].mNeedsCleanupOnRelease = false; - mSlots[*outSlot].mFence = Fence::NO_FENCE; - mSlots[*outSlot].mFrameNumber = 0; - - // mAcquireCalled tells GonkBufferQueue that it doesn't need to send a valid - // GraphicBuffer pointer on the next acquireBuffer call, which decreases - // Binder traffic by not un/flattening the GraphicBuffer. However, it - // requires that the consumer maintain a cached copy of the slot <--> buffer - // mappings, which is why the consumer doesn't need the valid pointer on - // acquire. - // - // The StreamSplitter is one of the primary users of the attach/detach - // logic, and while it is running, all buffers it acquires are immediately - // detached, and all buffers it eventually releases are ones that were - // attached (as opposed to having been obtained from acquireBuffer), so it - // doesn't make sense to maintain the slot/buffer mappings, which would - // become invalid for every buffer during detach/attach. By setting this to - // false, the valid GraphicBuffer pointer will always be sent with acquire - // for attached buffers. - mSlots[*outSlot].mAcquireCalled = false; - - return NO_ERROR; -} - -status_t GonkBufferQueueConsumer::releaseBuffer(int slot, uint64_t frameNumber, - const sp<Fence>& releaseFence) { - ATRACE_CALL(); - - if (slot < 0 || slot >= GonkBufferQueueDefs::NUM_BUFFER_SLOTS || - releaseFence == NULL) { - return BAD_VALUE; - } - - sp<IProducerListener> listener; - { // Autolock scope - Mutex::Autolock lock(mCore->mMutex); - - // If the frame number has changed because the buffer has been reallocated, - // we can ignore this releaseBuffer for the old buffer - //if (frameNumber != mSlots[slot].mFrameNumber) { - // return STALE_BUFFER_SLOT; - //} - - // Make sure this buffer hasn't been queued while acquired by the consumer - GonkBufferQueueCore::Fifo::iterator current(mCore->mQueue.begin()); - while (current != mCore->mQueue.end()) { - if (current->mSlot == slot) { - ALOGE("releaseBuffer: buffer slot %d pending release is " - "currently queued", slot); - return BAD_VALUE; - } - ++current; - } - - if (mSlots[slot].mBufferState == GonkBufferSlot::ACQUIRED) { - mSlots[slot].mFence = releaseFence; - mSlots[slot].mBufferState = GonkBufferSlot::FREE; - listener = mCore->mConnectedProducerListener; - ALOGV("releaseBuffer: releasing slot %d", slot); - } else if (mSlots[slot].mNeedsCleanupOnRelease) { - ALOGV("releaseBuffer: releasing a stale buffer slot %d " - "(state = %d)", slot, mSlots[slot].mBufferState); - mSlots[slot].mNeedsCleanupOnRelease = false; - return STALE_BUFFER_SLOT; - } else { - ALOGV("releaseBuffer: attempted to release buffer slot %d " - "but its state was %d", slot, mSlots[slot].mBufferState); - return BAD_VALUE; - } - - mCore->mDequeueCondition.broadcast(); - } // Autolock scope - - // Call back without lock held - if (listener != NULL) { - listener->onBufferReleased(); - } - - return NO_ERROR; -} - -status_t GonkBufferQueueConsumer::connect( - const sp<IConsumerListener>& consumerListener, bool controlledByApp) { - ATRACE_CALL(); - - if (consumerListener == NULL) { - ALOGE("connect(C): consumerListener may not be NULL"); - return BAD_VALUE; - } - - ALOGV("connect(C): controlledByApp=%s", - controlledByApp ? "true" : "false"); - - Mutex::Autolock lock(mCore->mMutex); - - if (mCore->mIsAbandoned) { - ALOGE("connect(C): GonkBufferQueue has been abandoned"); - return NO_INIT; - } - - mCore->mConsumerListener = consumerListener; - mCore->mConsumerControlledByApp = controlledByApp; - - return NO_ERROR; -} - -status_t GonkBufferQueueConsumer::disconnect() { - ATRACE_CALL(); - - ALOGV("disconnect(C)"); - - Mutex::Autolock lock(mCore->mMutex); - - if (mCore->mConsumerListener == NULL) { - ALOGE("disconnect(C): no consumer is connected"); - return BAD_VALUE; - } - - mCore->mIsAbandoned = true; - mCore->mConsumerListener = NULL; - mCore->mQueue.clear(); - mCore->freeAllBuffersLocked(); - mCore->mDequeueCondition.broadcast(); - return NO_ERROR; -} - -status_t GonkBufferQueueConsumer::getReleasedBuffers(uint64_t *outSlotMask) { - ATRACE_CALL(); - - if (outSlotMask == NULL) { - ALOGE("getReleasedBuffers: outSlotMask may not be NULL"); - return BAD_VALUE; - } - - Mutex::Autolock lock(mCore->mMutex); - - if (mCore->mIsAbandoned) { - ALOGE("getReleasedBuffers: GonkBufferQueue has been abandoned"); - return NO_INIT; - } - - uint64_t mask = 0; - for (int s = 0; s < GonkBufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { - if (!mSlots[s].mAcquireCalled) { - mask |= (1ULL << s); - } - } - - // Remove from the mask queued buffers for which acquire has been called, - // since the consumer will not receive their buffer addresses and so must - // retain their cached information - GonkBufferQueueCore::Fifo::iterator current(mCore->mQueue.begin()); - while (current != mCore->mQueue.end()) { - if (current->mAcquireCalled) { - mask &= ~(1ULL << current->mSlot); - } - ++current; - } - - ALOGV("getReleasedBuffers: returning mask %#" PRIx64, mask); - *outSlotMask = mask; - return NO_ERROR; -} - -status_t GonkBufferQueueConsumer::setDefaultBufferSize(uint32_t width, - uint32_t height) { - ATRACE_CALL(); - - if (width == 0 || height == 0) { - ALOGV("setDefaultBufferSize: dimensions cannot be 0 (width=%u " - "height=%u)", width, height); - return BAD_VALUE; - } - - ALOGV("setDefaultBufferSize: width=%u height=%u", width, height); - - Mutex::Autolock lock(mCore->mMutex); - mCore->mDefaultWidth = width; - mCore->mDefaultHeight = height; - return NO_ERROR; -} - -status_t GonkBufferQueueConsumer::setDefaultMaxBufferCount(int bufferCount) { - ATRACE_CALL(); - Mutex::Autolock lock(mCore->mMutex); - return mCore->setDefaultMaxBufferCountLocked(bufferCount); -} - -status_t GonkBufferQueueConsumer::disableAsyncBuffer() { - ATRACE_CALL(); - - Mutex::Autolock lock(mCore->mMutex); - - if (mCore->mConsumerListener != NULL) { - ALOGE("disableAsyncBuffer: consumer already connected"); - return INVALID_OPERATION; - } - - ALOGV("disableAsyncBuffer"); - mCore->mUseAsyncBuffer = false; - return NO_ERROR; -} - -status_t GonkBufferQueueConsumer::setMaxAcquiredBufferCount( - int maxAcquiredBuffers) { - ATRACE_CALL(); - - if (maxAcquiredBuffers < 1 || - maxAcquiredBuffers > GonkBufferQueueCore::MAX_MAX_ACQUIRED_BUFFERS) { - ALOGE("setMaxAcquiredBufferCount: invalid count %d", - maxAcquiredBuffers); - return BAD_VALUE; - } - - Mutex::Autolock lock(mCore->mMutex); - - if (mCore->mConnectedApi != GonkBufferQueueCore::NO_CONNECTED_API) { - ALOGE("setMaxAcquiredBufferCount: producer is already connected"); - return INVALID_OPERATION; - } - - ALOGV("setMaxAcquiredBufferCount: %d", maxAcquiredBuffers); - mCore->mMaxAcquiredBufferCount = maxAcquiredBuffers; - return NO_ERROR; -} - -void GonkBufferQueueConsumer::setConsumerName(const String8& name) { - ATRACE_CALL(); - ALOGV("setConsumerName: '%s'", name.string()); - Mutex::Autolock lock(mCore->mMutex); - mCore->mConsumerName = name; - mConsumerName = name; -} - -status_t GonkBufferQueueConsumer::setDefaultBufferFormat(uint32_t defaultFormat) { - ATRACE_CALL(); - ALOGV("setDefaultBufferFormat: %u", defaultFormat); - Mutex::Autolock lock(mCore->mMutex); - mCore->mDefaultBufferFormat = defaultFormat; - return NO_ERROR; -} - -status_t GonkBufferQueueConsumer::setConsumerUsageBits(uint32_t usage) { - ATRACE_CALL(); - ALOGV("setConsumerUsageBits: %#x", usage); - Mutex::Autolock lock(mCore->mMutex); - mCore->mConsumerUsageBits = usage; - return NO_ERROR; -} - -status_t GonkBufferQueueConsumer::setTransformHint(uint32_t hint) { - ATRACE_CALL(); - ALOGV("setTransformHint: %#x", hint); - Mutex::Autolock lock(mCore->mMutex); - mCore->mTransformHint = hint; - return NO_ERROR; -} - -sp<NativeHandle> GonkBufferQueueConsumer::getSidebandStream() const { - return mCore->mSidebandStream; -} - -void GonkBufferQueueConsumer::dumpToString(String8& result, const char* prefix) const { - mCore->dump(result, prefix); -} - -already_AddRefed<GonkBufferSlot::TextureClient> -GonkBufferQueueConsumer::getTextureClientFromBuffer(ANativeWindowBuffer* buffer) -{ - Mutex::Autolock _l(mCore->mMutex); - if (buffer == NULL) { - ALOGE("getSlotFromBufferLocked: encountered NULL buffer"); - return nullptr; - } - - for (int i = 0; i < GonkBufferQueueDefs::NUM_BUFFER_SLOTS; i++) { - if (mSlots[i].mGraphicBuffer != NULL && mSlots[i].mGraphicBuffer->handle == buffer->handle) { - RefPtr<TextureClient> client(mSlots[i].mTextureClient); - return client.forget(); - } - } - ALOGE("getSlotFromBufferLocked: unknown buffer: %p", buffer->handle); - return nullptr; -} - -int -GonkBufferQueueConsumer::getSlotFromTextureClientLocked(GonkBufferSlot::TextureClient* client) const -{ - if (client == NULL) { - ALOGE("getSlotFromBufferLocked: encountered NULL buffer"); - return BAD_VALUE; - } - - for (int i = 0; i < GonkBufferQueueDefs::NUM_BUFFER_SLOTS; i++) { - if (mSlots[i].mTextureClient == client) { - return i; - } - } - ALOGE("getSlotFromBufferLocked: unknown TextureClient: %p", client); - return BAD_VALUE; -} - -} // namespace android diff --git a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueConsumer.h b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueConsumer.h deleted file mode 100644 index a97cfab42..000000000 --- a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueConsumer.h +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright 2014 The Android Open Source Project - * Copyright (C) 2014 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef NATIVEWINDOW_GONKBUFFERQUEUECONSUMER_LL_H -#define NATIVEWINDOW_GONKBUFFERQUEUECONSUMER_LL_H - -#include "GonkBufferQueueDefs.h" -#include "IGonkGraphicBufferConsumerLL.h" - -namespace android { - -class GonkBufferQueueCore; - -class GonkBufferQueueConsumer : public BnGonkGraphicBufferConsumer { - -public: - GonkBufferQueueConsumer(const sp<GonkBufferQueueCore>& core); - virtual ~GonkBufferQueueConsumer(); - - // acquireBuffer attempts to acquire ownership of the next pending buffer in - // the GonkBufferQueue. If no buffer is pending then it returns - // NO_BUFFER_AVAILABLE. If a buffer is successfully acquired, the - // information about the buffer is returned in BufferItem. If the buffer - // returned had previously been acquired then the BufferItem::mGraphicBuffer - // field of buffer is set to NULL and it is assumed that the consumer still - // holds a reference to the buffer. - // - // If expectedPresent is nonzero, it indicates the time when the buffer - // will be displayed on screen. If the buffer's timestamp is farther in the - // future, the buffer won't be acquired, and PRESENT_LATER will be - // returned. The presentation time is in nanoseconds, and the time base - // is CLOCK_MONOTONIC. - virtual status_t acquireBuffer(BufferItem* outBuffer, - nsecs_t expectedPresent); - - // See IGonkGraphicBufferConsumer::detachBuffer - virtual status_t detachBuffer(int slot); - - // See IGonkGraphicBufferConsumer::attachBuffer - virtual status_t attachBuffer(int* slot, const sp<GraphicBuffer>& buffer); - - // releaseBuffer releases a buffer slot from the consumer back to the - // GonkBufferQueue. This may be done while the buffer's contents are still - // being accessed. The fence will signal when the buffer is no longer - // in use. frameNumber is used to indentify the exact buffer returned. - // - // If releaseBuffer returns STALE_BUFFER_SLOT, then the consumer must free - // any references to the just-released buffer that it might have, as if it - // had received a onBuffersReleased() call with a mask set for the released - // buffer. - virtual status_t releaseBuffer(int slot, uint64_t frameNumber, - const sp<Fence>& releaseFence); - - // connect connects a consumer to the GonkBufferQueue. Only one - // consumer may be connected, and when that consumer disconnects the - // GonkBufferQueue is placed into the "abandoned" state, causing most - // interactions with the GonkBufferQueue by the producer to fail. - // controlledByApp indicates whether the consumer is controlled by - // the application. - // - // consumerListener may not be NULL. - virtual status_t connect(const sp<IConsumerListener>& consumerListener, - bool controlledByApp); - - // disconnect disconnects a consumer from the GonkBufferQueue. All - // buffers will be freed and the GonkBufferQueue is placed in the "abandoned" - // state, causing most interactions with the GonkBufferQueue by the producer to - // fail. - virtual status_t disconnect(); - - // getReleasedBuffers sets the value pointed to by outSlotMask to a bit mask - // indicating which buffer slots have been released by the GonkBufferQueue - // but have not yet been released by the consumer. - // - // This should be called from the onBuffersReleased() callback. - virtual status_t getReleasedBuffers(uint64_t* outSlotMask); - - // setDefaultBufferSize is used to set the size of buffers returned by - // dequeueBuffer when a width and height of zero is requested. Default - // is 1x1. - virtual status_t setDefaultBufferSize(uint32_t width, uint32_t height); - - // setDefaultMaxBufferCount sets the default value for the maximum buffer - // count (the initial default is 2). If the producer has requested a - // buffer count using setBufferCount, the default buffer count will only - // take effect if the producer sets the count back to zero. - // - // The count must be between 2 and NUM_BUFFER_SLOTS, inclusive. - virtual status_t setDefaultMaxBufferCount(int bufferCount); - - // disableAsyncBuffer disables the extra buffer used in async mode - // (when both producer and consumer have set their "isControlledByApp" - // flag) and has dequeueBuffer() return WOULD_BLOCK instead. - // - // This can only be called before connect(). - virtual status_t disableAsyncBuffer(); - - // setMaxAcquiredBufferCount sets the maximum number of buffers that can - // be acquired by the consumer at one time (default 1). This call will - // fail if a producer is connected to the GonkBufferQueue. - virtual status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers); - - // setConsumerName sets the name used in logging - virtual void setConsumerName(const String8& name); - - // setDefaultBufferFormat allows the GonkBufferQueue to create - // GraphicBuffers of a defaultFormat if no format is specified - // in dequeueBuffer. Formats are enumerated in graphics.h; the - // initial default is HAL_PIXEL_FORMAT_RGBA_8888. - virtual status_t setDefaultBufferFormat(uint32_t defaultFormat); - - // setConsumerUsageBits will turn on additional usage bits for dequeueBuffer. - // These are merged with the bits passed to dequeueBuffer. The values are - // enumerated in gralloc.h, e.g. GRALLOC_USAGE_HW_RENDER; the default is 0. - virtual status_t setConsumerUsageBits(uint32_t usage); - - // setTransformHint bakes in rotation to buffers so overlays can be used. - // The values are enumerated in window.h, e.g. - // NATIVE_WINDOW_TRANSFORM_ROT_90. The default is 0 (no transform). - virtual status_t setTransformHint(uint32_t hint); - - // Retrieve the sideband buffer stream, if any. - virtual sp<NativeHandle> getSidebandStream() const; - - // dump our state in a String - virtual void dumpToString(String8& result, const char* prefix) const; - - // Added by mozilla - virtual already_AddRefed<GonkBufferSlot::TextureClient> getTextureClientFromBuffer(ANativeWindowBuffer* buffer); - - virtual int getSlotFromTextureClientLocked(GonkBufferSlot::TextureClient* client) const; - - // Functions required for backwards compatibility. - // These will be modified/renamed in IGonkGraphicBufferConsumer and will be - // removed from this class at that time. See b/13306289. - virtual status_t consumerConnect(const sp<IConsumerListener>& consumer, - bool controlledByApp) { - return connect(consumer, controlledByApp); - } - - virtual status_t consumerDisconnect() { return disconnect(); } - - // End functions required for backwards compatibility - -private: - sp<GonkBufferQueueCore> mCore; - - // This references mCore->mSlots. Lock mCore->mMutex while accessing. - GonkBufferQueueDefs::SlotsType& mSlots; - - // This is a cached copy of the name stored in the GonkBufferQueueCore. - // It's updated during setConsumerName. - String8 mConsumerName; - -}; // class GonkBufferQueueConsumer - -} // namespace android - -#endif diff --git a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueCore.cpp b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueCore.cpp deleted file mode 100644 index 9e8e337f6..000000000 --- a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueCore.cpp +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright 2014 The Android Open Source Project - * Copyright (C) 2014 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "GonkBufferQueueCore" -#define ATRACE_TAG ATRACE_TAG_GRAPHICS -//#define LOG_NDEBUG 0 - -#include <inttypes.h> - -#include "GonkBufferItem.h" -#include "GonkBufferQueueCore.h" -#include <gui/IConsumerListener.h> -#include <gui/IGraphicBufferAlloc.h> -#include <gui/IProducerListener.h> -#include <gui/ISurfaceComposer.h> -#include <private/gui/ComposerService.h> - -#include <cutils/compiler.h> -#include "mozilla/layers/GrallocTextureClient.h" -#include "mozilla/layers/ImageBridgeChild.h" - -template <typename T> -static inline T max(T a, T b) { return a > b ? a : b; } - -namespace android { - -static String8 getUniqueName() { - static volatile int32_t counter = 0; - return String8::format("unnamed-%d-%d", getpid(), - android_atomic_inc(&counter)); -} - -GonkBufferQueueCore::GonkBufferQueueCore(const sp<IGraphicBufferAlloc>& allocator) : - mAllocator(allocator), - mMutex(), - mIsAbandoned(false), - mConsumerControlledByApp(false), - mConsumerName(getUniqueName()), - mConsumerListener(), - mConsumerUsageBits(0), - mConnectedApi(NO_CONNECTED_API), - mConnectedProducerListener(), - mSlots(), - mQueue(), - mOverrideMaxBufferCount(0), - mDequeueCondition(), - mUseAsyncBuffer(true), - mDequeueBufferCannotBlock(false), - mDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888), - mDefaultWidth(1), - mDefaultHeight(1), - mDefaultMaxBufferCount(2), - mMaxAcquiredBufferCount(1), - mBufferHasBeenQueued(false), - mFrameCounter(0), - mTransformHint(0), - mIsAllocating(false), - mIsAllocatingCondition() -{ - ALOGV("GonkBufferQueueCore"); -} - -GonkBufferQueueCore::~GonkBufferQueueCore() {} - -void GonkBufferQueueCore::dump(String8& result, const char* prefix) const { - Mutex::Autolock lock(mMutex); - - String8 fifo; - Fifo::const_iterator current(mQueue.begin()); - while (current != mQueue.end()) { - fifo.appendFormat("%02d:%p crop=[%d,%d,%d,%d], " - "xform=0x%02x, time=%#" PRIx64 ", scale=%s\n", - current->mSlot, current->mGraphicBuffer.get(), - current->mCrop.left, current->mCrop.top, current->mCrop.right, - current->mCrop.bottom, current->mTransform, current->mTimestamp, - GonkBufferItem::scalingModeName(current->mScalingMode)); - ++current; - } - - result.appendFormat("%s-GonkBufferQueue mMaxAcquiredBufferCount=%d, " - "mDequeueBufferCannotBlock=%d, default-size=[%dx%d], " - "default-format=%d, transform-hint=%02x, FIFO(%zu)={%s}\n", - prefix, mMaxAcquiredBufferCount, mDequeueBufferCannotBlock, - mDefaultWidth, mDefaultHeight, mDefaultBufferFormat, mTransformHint, - mQueue.size(), fifo.string()); - - // Trim the free buffers so as to not spam the dump - int maxBufferCount = 0; - for (int s = GonkBufferQueueDefs::NUM_BUFFER_SLOTS - 1; s >= 0; --s) { - const GonkBufferSlot& slot(mSlots[s]); - if (slot.mBufferState != GonkBufferSlot::FREE || - slot.mGraphicBuffer != NULL) { - maxBufferCount = s + 1; - break; - } - } - - for (int s = 0; s < maxBufferCount; ++s) { - const GonkBufferSlot& slot(mSlots[s]); - const sp<GraphicBuffer>& buffer(slot.mGraphicBuffer); - result.appendFormat("%s%s[%02d:%p] state=%-8s", prefix, - (slot.mBufferState == GonkBufferSlot::ACQUIRED) ? ">" : " ", - s, buffer.get(), - GonkBufferSlot::bufferStateName(slot.mBufferState)); - - if (buffer != NULL) { - result.appendFormat(", %p [%4ux%4u:%4u,%3X]", buffer->handle, - buffer->width, buffer->height, buffer->stride, - buffer->format); - } - - result.append("\n"); - } -} - -int GonkBufferQueueCore::getMinUndequeuedBufferCountLocked(bool async) const { - // If dequeueBuffer is allowed to error out, we don't have to add an - // extra buffer. - if (!mUseAsyncBuffer) { - return mMaxAcquiredBufferCount; - } - - if (mDequeueBufferCannotBlock || async) { - return mMaxAcquiredBufferCount + 1; - } - - return mMaxAcquiredBufferCount; -} - -int GonkBufferQueueCore::getMinMaxBufferCountLocked(bool async) const { - return getMinUndequeuedBufferCountLocked(async) + 1; -} - -int GonkBufferQueueCore::getMaxBufferCountLocked(bool async) const { - int minMaxBufferCount = getMinMaxBufferCountLocked(async); - - int maxBufferCount = max(mDefaultMaxBufferCount, minMaxBufferCount); - if (mOverrideMaxBufferCount != 0) { - assert(mOverrideMaxBufferCount >= minMaxBufferCount); - maxBufferCount = mOverrideMaxBufferCount; - } - - // Any buffers that are dequeued by the producer or sitting in the queue - // waiting to be consumed need to have their slots preserved. Such buffers - // will temporarily keep the max buffer count up until the slots no longer - // need to be preserved. - for (int s = maxBufferCount; s < GonkBufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { - GonkBufferSlot::BufferState state = mSlots[s].mBufferState; - if (state == GonkBufferSlot::QUEUED || state == GonkBufferSlot::DEQUEUED) { - maxBufferCount = s + 1; - } - } - - return maxBufferCount; -} - -status_t GonkBufferQueueCore::setDefaultMaxBufferCountLocked(int count) { - const int minBufferCount = 2; - if (count < minBufferCount || count > GonkBufferQueueDefs::NUM_BUFFER_SLOTS) { - ALOGV("setDefaultMaxBufferCount: invalid count %d, should be in " - "[%d, %d]", - count, minBufferCount, GonkBufferQueueDefs::NUM_BUFFER_SLOTS); - return BAD_VALUE; - } - - ALOGV("setDefaultMaxBufferCount: setting count to %d", count); - mDefaultMaxBufferCount = count; - mDequeueCondition.broadcast(); - - return NO_ERROR; -} - -void GonkBufferQueueCore::freeBufferLocked(int slot) { - ALOGV("freeBufferLocked: slot %d", slot); - - if (mSlots[slot].mTextureClient) { - mSlots[slot].mTextureClient->ClearRecycleCallback(); - // release TextureClient in ImageBridge thread - RefPtr<TextureClientReleaseTask> task = - MakeAndAddRef<TextureClientReleaseTask>(mSlots[slot].mTextureClient); - mSlots[slot].mTextureClient = NULL; - ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask(task.forget()); - } - mSlots[slot].mGraphicBuffer.clear(); - if (mSlots[slot].mBufferState == GonkBufferSlot::ACQUIRED) { - mSlots[slot].mNeedsCleanupOnRelease = true; - } - mSlots[slot].mBufferState = GonkBufferSlot::FREE; - mSlots[slot].mFrameNumber = UINT32_MAX; - mSlots[slot].mAcquireCalled = false; - - // Destroy fence as GonkBufferQueue now takes ownership - mSlots[slot].mFence = Fence::NO_FENCE; -} - -void GonkBufferQueueCore::freeAllBuffersLocked() { - ALOGW_IF(!mQueue.isEmpty(), - "freeAllBuffersLocked called but mQueue is not empty"); - mQueue.clear(); - mBufferHasBeenQueued = false; - for (int s = 0; s < GonkBufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { - freeBufferLocked(s); - } -} - -bool GonkBufferQueueCore::stillTracking(const GonkBufferItem* item) const { - const GonkBufferSlot& slot = mSlots[item->mSlot]; - - ALOGV("stillTracking: item { slot=%d/%" PRIu64 " buffer=%p } " - "slot { slot=%d/%" PRIu64 " buffer=%p }", - item->mSlot, item->mFrameNumber, - (item->mGraphicBuffer.get() ? item->mGraphicBuffer->handle : 0), - item->mSlot, slot.mFrameNumber, - (slot.mGraphicBuffer.get() ? slot.mGraphicBuffer->handle : 0)); - - // Compare item with its original buffer slot. We can check the slot as - // the buffer would not be moved to a different slot by the producer. - return (slot.mGraphicBuffer != NULL) && - (item->mGraphicBuffer->handle == slot.mGraphicBuffer->handle); -} - -void GonkBufferQueueCore::waitWhileAllocatingLocked() const { - ATRACE_CALL(); - while (mIsAllocating) { - mIsAllocatingCondition.wait(mMutex); - } -} - -} // namespace android diff --git a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueCore.h b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueCore.h deleted file mode 100644 index 936e11686..000000000 --- a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueCore.h +++ /dev/null @@ -1,251 +0,0 @@ -/* - * Copyright 2014 The Android Open Source Project - * Copyright (C) 2014 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef NATIVEWINDOW_GONKBUFFERQUEUECORE_LL_H -#define NATIVEWINDOW_GONKBUFFERQUEUECORE_LL_H - -#include "GonkBufferQueueDefs.h" -#include "GonkBufferSlot.h" - -#include <utils/Condition.h> -#include <utils/Mutex.h> -#include <utils/NativeHandle.h> -#include <utils/RefBase.h> -#include <utils/String8.h> -#include <utils/StrongPointer.h> -#include <utils/Trace.h> -#include <utils/Vector.h> - -#include "mozilla/layers/TextureClient.h" - -#define ATRACE_BUFFER_INDEX(index) - -using namespace mozilla; -using namespace mozilla::gfx; -using namespace mozilla::layers; - -namespace android { - -class GonkBufferItem; -class IConsumerListener; -class IGraphicBufferAlloc; -class IProducerListener; - -class GonkBufferQueueCore : public virtual RefBase { - - friend class GonkBufferQueueProducer; - friend class GonkBufferQueueConsumer; - -public: - // Used as a placeholder slot number when the value isn't pointing to an - // existing buffer. - enum { INVALID_BUFFER_SLOT = -1 }; // TODO: Extract from IGBC::BufferItem - - // We reserve two slots in order to guarantee that the producer and - // consumer can run asynchronously. - enum { MAX_MAX_ACQUIRED_BUFFERS = GonkBufferQueueDefs::NUM_BUFFER_SLOTS - 2 }; - - // The default API number used to indicate that no producer is connected - enum { NO_CONNECTED_API = 0 }; - - typedef Vector<GonkBufferItem> Fifo; - typedef mozilla::layers::TextureClient TextureClient; - - // GonkBufferQueueCore manages a pool of gralloc memory slots to be used by - // producers and consumers. allocator is used to allocate all the needed - // gralloc buffers. - GonkBufferQueueCore(const sp<IGraphicBufferAlloc>& allocator = NULL); - virtual ~GonkBufferQueueCore(); - -private: - // Dump our state in a string - void dump(String8& result, const char* prefix) const; - - int getSlotFromTextureClientLocked(TextureClient* client) const; - - // getMinUndequeuedBufferCountLocked returns the minimum number of buffers - // that must remain in a state other than DEQUEUED. The async parameter - // tells whether we're in asynchronous mode. - int getMinUndequeuedBufferCountLocked(bool async) const; - - // getMinMaxBufferCountLocked returns the minimum number of buffers allowed - // given the current GonkBufferQueue state. The async parameter tells whether - // we're in asynchonous mode. - int getMinMaxBufferCountLocked(bool async) const; - - // getMaxBufferCountLocked returns the maximum number of buffers that can be - // allocated at once. This value depends on the following member variables: - // - // mDequeueBufferCannotBlock - // mMaxAcquiredBufferCount - // mDefaultMaxBufferCount - // mOverrideMaxBufferCount - // async parameter - // - // Any time one of these member variables is changed while a producer is - // connected, mDequeueCondition must be broadcast. - int getMaxBufferCountLocked(bool async) const; - - // setDefaultMaxBufferCountLocked sets the maximum number of buffer slots - // that will be used if the producer does not override the buffer slot - // count. The count must be between 2 and NUM_BUFFER_SLOTS, inclusive. The - // initial default is 2. - status_t setDefaultMaxBufferCountLocked(int count); - - // freeBufferLocked frees the GraphicBuffer and sync resources for the - // given slot. - void freeBufferLocked(int slot); - - // freeAllBuffersLocked frees the GraphicBuffer and sync resources for - // all slots. - void freeAllBuffersLocked(); - - // stillTracking returns true iff the buffer item is still being tracked - // in one of the slots. - bool stillTracking(const GonkBufferItem* item) const; - - // waitWhileAllocatingLocked blocks until mIsAllocating is false. - void waitWhileAllocatingLocked() const; - - // mAllocator is the connection to SurfaceFlinger that is used to allocate - // new GraphicBuffer objects. - sp<IGraphicBufferAlloc> mAllocator; - - // mMutex is the mutex used to prevent concurrent access to the member - // variables of GonkBufferQueueCore objects. It must be locked whenever any - // member variable is accessed. - mutable Mutex mMutex; - - // mIsAbandoned indicates that the GonkBufferQueue will no longer be used to - // consume image buffers pushed to it using the IGraphicBufferProducer - // interface. It is initialized to false, and set to true in the - // consumerDisconnect method. A GonkBufferQueue that is abandoned will return - // the NO_INIT error from all IGraphicBufferProducer methods capable of - // returning an error. - bool mIsAbandoned; - - // mConsumerControlledByApp indicates whether the connected consumer is - // controlled by the application. - bool mConsumerControlledByApp; - - // mConsumerName is a string used to identify the GonkBufferQueue in log - // messages. It is set by the IGraphicBufferConsumer::setConsumerName - // method. - String8 mConsumerName; - - // mConsumerListener is used to notify the connected consumer of - // asynchronous events that it may wish to react to. It is initially - // set to NULL and is written by consumerConnect and consumerDisconnect. - sp<IConsumerListener> mConsumerListener; - - // mConsumerUsageBits contains flags that the consumer wants for - // GraphicBuffers. - uint32_t mConsumerUsageBits; - - // mConnectedApi indicates the producer API that is currently connected - // to this GonkBufferQueue. It defaults to NO_CONNECTED_API, and gets updated - // by the connect and disconnect methods. - int mConnectedApi; - - // mConnectedProducerToken is used to set a binder death notification on - // the producer. - sp<IProducerListener> mConnectedProducerListener; - - // mSlots is an array of buffer slots that must be mirrored on the producer - // side. This allows buffer ownership to be transferred between the producer - // and consumer without sending a GraphicBuffer over Binder. The entire - // array is initialized to NULL at construction time, and buffers are - // allocated for a slot when requestBuffer is called with that slot's index. - GonkBufferQueueDefs::SlotsType mSlots; - - // mQueue is a FIFO of queued buffers used in synchronous mode. - Fifo mQueue; - - // mOverrideMaxBufferCount is the limit on the number of buffers that will - // be allocated at one time. This value is set by the producer by calling - // setBufferCount. The default is 0, which means that the producer doesn't - // care about the number of buffers in the pool. In that case, - // mDefaultMaxBufferCount is used as the limit. - int mOverrideMaxBufferCount; - - // mDequeueCondition is a condition variable used for dequeueBuffer in - // synchronous mode. - mutable Condition mDequeueCondition; - - // mUseAsyncBuffer indicates whether an extra buffer is used in async mode - // to prevent dequeueBuffer from blocking. - bool mUseAsyncBuffer; - - // mDequeueBufferCannotBlock indicates whether dequeueBuffer is allowed to - // block. This flag is set during connect when both the producer and - // consumer are controlled by the application. - bool mDequeueBufferCannotBlock; - - // mDefaultBufferFormat can be set so it will override the buffer format - // when it isn't specified in dequeueBuffer. - uint32_t mDefaultBufferFormat; - - // mDefaultWidth holds the default width of allocated buffers. It is used - // in dequeueBuffer if a width and height of 0 are specified. - int mDefaultWidth; - - // mDefaultHeight holds the default height of allocated buffers. It is used - // in dequeueBuffer if a width and height of 0 are specified. - int mDefaultHeight; - - // mDefaultMaxBufferCount is the default limit on the number of buffers that - // will be allocated at one time. This default limit is set by the consumer. - // The limit (as opposed to the default limit) may be overriden by the - // producer. - int mDefaultMaxBufferCount; - - // mMaxAcquiredBufferCount is the number of buffers that the consumer may - // acquire at one time. It defaults to 1, and can be changed by the consumer - // via setMaxAcquiredBufferCount, but this may only be done while no - // producer is connected to the GonkBufferQueue. This value is used to derive - // the value returned for the MIN_UNDEQUEUED_BUFFERS query to the producer. - int mMaxAcquiredBufferCount; - - // mBufferHasBeenQueued is true once a buffer has been queued. It is reset - // when something causes all buffers to be freed (e.g., changing the buffer - // count). - bool mBufferHasBeenQueued; - - // mFrameCounter is the free running counter, incremented on every - // successful queueBuffer call and buffer allocation. - uint64_t mFrameCounter; - - // mTransformHint is used to optimize for screen rotations. - uint32_t mTransformHint; - - // mSidebandStream is a handle to the sideband buffer stream, if any - sp<NativeHandle> mSidebandStream; - - // mIsAllocating indicates whether a producer is currently trying to allocate buffers (which - // releases mMutex while doing the allocation proper). Producers should not modify any of the - // FREE slots while this is true. mIsAllocatingCondition is signaled when this value changes to - // false. - bool mIsAllocating; - - // mIsAllocatingCondition is a condition variable used by producers to wait until mIsAllocating - // becomes false. - mutable Condition mIsAllocatingCondition; -}; // class GonkBufferQueueCore - -} // namespace android - -#endif diff --git a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueDefs.h b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueDefs.h deleted file mode 100644 index 60085706f..000000000 --- a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueDefs.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2014 The Android Open Source Project - * Copyright (C) 2014 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef NATIVEWINDOW_BUFFERQUEUECOREDEFS_H -#define NATIVEWINDOW_BUFFERQUEUECOREDEFS_H - -#include "GonkBufferSlot.h" - -namespace android { - class GonkBufferQueueCore; - - namespace GonkBufferQueueDefs { - // GonkBufferQueue will keep track of at most this value of buffers. - // Attempts at runtime to increase the number of buffers past this - // will fail. - enum { NUM_BUFFER_SLOTS = 64 }; - - typedef GonkBufferSlot SlotsType[NUM_BUFFER_SLOTS]; - } // namespace GonkBufferQueueDefs -} // namespace android - -#endif diff --git a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueLL.cpp b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueLL.cpp deleted file mode 100644 index 649d06bee..000000000 --- a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueLL.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * Copyright (C) 2014 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "GonkBufferQueue" -#define ATRACE_TAG ATRACE_TAG_GRAPHICS -#define LOG_NDEBUG 0 - -#include "GonkBufferQueue.h" -#include "GonkBufferQueueConsumer.h" -#include "GonkBufferQueueCore.h" -#include "GonkBufferQueueProducer.h" - -namespace android { - -GonkBufferQueue::ProxyConsumerListener::ProxyConsumerListener( - const wp<ConsumerListener>& consumerListener): - mConsumerListener(consumerListener) {} - -GonkBufferQueue::ProxyConsumerListener::~ProxyConsumerListener() {} - -#if ANDROID_VERSION == 21 -void GonkBufferQueue::ProxyConsumerListener::onFrameAvailable() { - sp<ConsumerListener> listener(mConsumerListener.promote()); - if (listener != NULL) { - listener->onFrameAvailable(); - } -} -#else -void GonkBufferQueue::ProxyConsumerListener::onFrameAvailable(const ::android::BufferItem& item) { - sp<ConsumerListener> listener(mConsumerListener.promote()); - if (listener != NULL) { - listener->onFrameAvailable(item); - } -} - -void GonkBufferQueue::ProxyConsumerListener::onFrameReplaced(const ::android::BufferItem& item) { - sp<ConsumerListener> listener(mConsumerListener.promote()); - if (listener != NULL) { - listener->onFrameReplaced(item); - } -} -#endif - -void GonkBufferQueue::ProxyConsumerListener::onBuffersReleased() { - sp<ConsumerListener> listener(mConsumerListener.promote()); - if (listener != NULL) { - listener->onBuffersReleased(); - } -} - -void GonkBufferQueue::ProxyConsumerListener::onSidebandStreamChanged() { - sp<ConsumerListener> listener(mConsumerListener.promote()); - if (listener != NULL) { - listener->onSidebandStreamChanged(); - } -} - -void GonkBufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer, - sp<IGonkGraphicBufferConsumer>* outConsumer, - const sp<IGraphicBufferAlloc>& allocator) { - LOG_ALWAYS_FATAL_IF(outProducer == NULL, - "GonkBufferQueue: outProducer must not be NULL"); - LOG_ALWAYS_FATAL_IF(outConsumer == NULL, - "GonkBufferQueue: outConsumer must not be NULL"); - - sp<GonkBufferQueueCore> core(new GonkBufferQueueCore(allocator)); - LOG_ALWAYS_FATAL_IF(core == NULL, - "GonkBufferQueue: failed to create GonkBufferQueueCore"); - - sp<IGraphicBufferProducer> producer(new GonkBufferQueueProducer(core)); - LOG_ALWAYS_FATAL_IF(producer == NULL, - "GonkBufferQueue: failed to create GonkBufferQueueProducer"); - - sp<IGonkGraphicBufferConsumer> consumer(new GonkBufferQueueConsumer(core)); - LOG_ALWAYS_FATAL_IF(consumer == NULL, - "GonkBufferQueue: failed to create GonkBufferQueueConsumer"); - - *outProducer = producer; - *outConsumer = consumer; -} - -}; // namespace android diff --git a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueLL.h b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueLL.h deleted file mode 100644 index b1b4e06b5..000000000 --- a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueLL.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * Copyright (C) 2014 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef NATIVEWINDOW_GONKBUFFERQUEUE_LL_H -#define NATIVEWINDOW_GONKBUFFERQUEUE_LL_H - -#include "GonkBufferQueueDefs.h" -#include "IGonkGraphicBufferConsumerLL.h" -#include <gui/IGraphicBufferProducer.h> -#include <gui/IConsumerListener.h> - -// These are only required to keep other parts of the framework with incomplete -// dependencies building successfully -#include <gui/IGraphicBufferAlloc.h> - -namespace android { - -class GonkBufferQueue { -public: - // GonkBufferQueue will keep track of at most this value of buffers. - // Attempts at runtime to increase the number of buffers past this will fail. - enum { NUM_BUFFER_SLOTS = GonkBufferQueueDefs::NUM_BUFFER_SLOTS }; - // Used as a placeholder slot# when the value isn't pointing to an existing buffer. - enum { INVALID_BUFFER_SLOT = IGonkGraphicBufferConsumer::BufferItem::INVALID_BUFFER_SLOT }; - // Alias to <IGonkGraphicBufferConsumer.h> -- please scope from there in future code! - enum { - NO_BUFFER_AVAILABLE = IGonkGraphicBufferConsumer::NO_BUFFER_AVAILABLE, - PRESENT_LATER = IGonkGraphicBufferConsumer::PRESENT_LATER, - }; - - // When in async mode we reserve two slots in order to guarantee that the - // producer and consumer can run asynchronously. - enum { MAX_MAX_ACQUIRED_BUFFERS = NUM_BUFFER_SLOTS - 2 }; - - // for backward source compatibility - typedef ::android::ConsumerListener ConsumerListener; - typedef IGonkGraphicBufferConsumer::BufferItem BufferItem; - - // ProxyConsumerListener is a ConsumerListener implementation that keeps a weak - // reference to the actual consumer object. It forwards all calls to that - // consumer object so long as it exists. - // - // This class exists to avoid having a circular reference between the - // GonkBufferQueue object and the consumer object. The reason this can't be a weak - // reference in the GonkBufferQueue class is because we're planning to expose the - // consumer side of a GonkBufferQueue as a binder interface, which doesn't support - // weak references. - class ProxyConsumerListener : public BnConsumerListener { - public: - ProxyConsumerListener(const wp<ConsumerListener>& consumerListener); - virtual ~ProxyConsumerListener(); -#if ANDROID_VERSION == 21 - virtual void onFrameAvailable(); -#else - virtual void onFrameAvailable(const ::android::BufferItem& item); - virtual void onFrameReplaced(const ::android::BufferItem& item); -#endif - virtual void onBuffersReleased(); - virtual void onSidebandStreamChanged(); - private: - // mConsumerListener is a weak reference to the IConsumerListener. This is - // the raison d'etre of ProxyConsumerListener. - wp<ConsumerListener> mConsumerListener; - }; - - // GonkBufferQueue manages a pool of gralloc memory slots to be used by - // producers and consumers. allocator is used to allocate all the - // needed gralloc buffers. - static void createBufferQueue(sp<IGraphicBufferProducer>* outProducer, - sp<IGonkGraphicBufferConsumer>* outConsumer, - const sp<IGraphicBufferAlloc>& allocator = NULL); - -private: - GonkBufferQueue(); // Create through createBufferQueue -}; - -// ---------------------------------------------------------------------------- -}; // namespace android - -#endif // NATIVEWINDOW_GONKBUFFERQUEUE_LL_H diff --git a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueProducer.cpp b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueProducer.cpp deleted file mode 100644 index d3436756f..000000000 --- a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueProducer.cpp +++ /dev/null @@ -1,886 +0,0 @@ -/* - * Copyright 2014 The Android Open Source Project - * Copyright (C) 2014 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <inttypes.h> - -#define LOG_TAG "GonkBufferQueueProducer" -#define ATRACE_TAG ATRACE_TAG_GRAPHICS -//#define LOG_NDEBUG 0 - -#include "GonkBufferItem.h" -#include "GonkBufferQueueCore.h" -#include "GonkBufferQueueProducer.h" -#include <gui/IConsumerListener.h> -#include <gui/IGraphicBufferAlloc.h> -#include <gui/IProducerListener.h> - -#include <cutils/compiler.h> -#include <utils/Log.h> -#include <utils/Trace.h> - -#include "mozilla/layers/GrallocTextureClient.h" -#include "mozilla/layers/ImageBridgeChild.h" -#include "mozilla/layers/TextureClient.h" - -namespace android { - -GonkBufferQueueProducer::GonkBufferQueueProducer(const sp<GonkBufferQueueCore>& core) : - mCore(core), - mSlots(core->mSlots), - mConsumerName(), - mSynchronousMode(true), - mStickyTransform(0) {} - -GonkBufferQueueProducer::~GonkBufferQueueProducer() {} - -status_t GonkBufferQueueProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) { - ATRACE_CALL(); - ALOGV("requestBuffer: slot %d", slot); - Mutex::Autolock lock(mCore->mMutex); - - if (mCore->mIsAbandoned) { - ALOGE("requestBuffer: GonkBufferQueue has been abandoned"); - return NO_INIT; - } - - if (slot < 0 || slot >= GonkBufferQueueDefs::NUM_BUFFER_SLOTS) { - ALOGE("requestBuffer: slot index %d out of range [0, %d)", - slot, GonkBufferQueueDefs::NUM_BUFFER_SLOTS); - return BAD_VALUE; - } else if (mSlots[slot].mBufferState != GonkBufferSlot::DEQUEUED) { - ALOGE("requestBuffer: slot %d is not owned by the producer " - "(state = %d)", slot, mSlots[slot].mBufferState); - return BAD_VALUE; - } - - mSlots[slot].mRequestBufferCalled = true; - *buf = mSlots[slot].mGraphicBuffer; - return NO_ERROR; -} - -status_t GonkBufferQueueProducer::setBufferCount(int bufferCount) { - ATRACE_CALL(); - ALOGV("setBufferCount: count = %d", bufferCount); - - sp<IConsumerListener> listener; - { // Autolock scope - Mutex::Autolock lock(mCore->mMutex); - mCore->waitWhileAllocatingLocked(); - - if (mCore->mIsAbandoned) { - ALOGE("setBufferCount: GonkBufferQueue has been abandoned"); - return NO_INIT; - } - - if (bufferCount > GonkBufferQueueDefs::NUM_BUFFER_SLOTS) { - ALOGE("setBufferCount: bufferCount %d too large (max %d)", - bufferCount, GonkBufferQueueDefs::NUM_BUFFER_SLOTS); - return BAD_VALUE; - } - - // There must be no dequeued buffers when changing the buffer count. - for (int s = 0; s < GonkBufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { - if (mSlots[s].mBufferState == GonkBufferSlot::DEQUEUED) { - ALOGE("setBufferCount: buffer owned by producer"); - return BAD_VALUE; - } - } - - if (bufferCount == 0) { - mCore->mOverrideMaxBufferCount = 0; - mCore->mDequeueCondition.broadcast(); - return NO_ERROR; - } - - const int minBufferSlots = mCore->getMinMaxBufferCountLocked(false); - if (bufferCount < minBufferSlots) { - ALOGE("setBufferCount: requested buffer count %d is less than " - "minimum %d", bufferCount, minBufferSlots); - return BAD_VALUE; - } - - // Here we are guaranteed that the producer doesn't have any dequeued - // buffers and will release all of its buffer references. We don't - // clear the queue, however, so that currently queued buffers still - // get displayed. - mCore->freeAllBuffersLocked(); - mCore->mOverrideMaxBufferCount = bufferCount; - mCore->mDequeueCondition.broadcast(); - listener = mCore->mConsumerListener; - } // Autolock scope - - // Call back without lock held - if (listener != NULL) { - listener->onBuffersReleased(); - } - - return NO_ERROR; -} - -status_t GonkBufferQueueProducer::waitForFreeSlotThenRelock(const char* caller, - bool async, int* found, status_t* returnFlags) const { - bool tryAgain = true; - while (tryAgain) { - if (mCore->mIsAbandoned) { - ALOGE("%s: GonkBufferQueue has been abandoned", caller); - return NO_INIT; - } - - const int maxBufferCount = mCore->getMaxBufferCountLocked(async); - if (async && mCore->mOverrideMaxBufferCount) { - // FIXME: Some drivers are manually setting the buffer count - // (which they shouldn't), so we do this extra test here to - // handle that case. This is TEMPORARY until we get this fixed. - if (mCore->mOverrideMaxBufferCount < maxBufferCount) { - ALOGE("%s: async mode is invalid with buffer count override", - caller); - return BAD_VALUE; - } - } - - // Free up any buffers that are in slots beyond the max buffer count - //for (int s = maxBufferCount; s < GonkBufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { - // assert(mSlots[s].mBufferState == GonkBufferSlot::FREE); - // if (mSlots[s].mGraphicBuffer != NULL) { - // mCore->freeBufferLocked(s); - // *returnFlags |= RELEASE_ALL_BUFFERS; - // } - //} - - // Look for a free buffer to give to the client - *found = GonkBufferQueueCore::INVALID_BUFFER_SLOT; - int dequeuedCount = 0; - int acquiredCount = 0; - for (int s = 0; s < maxBufferCount; ++s) { - switch (mSlots[s].mBufferState) { - case GonkBufferSlot::DEQUEUED: - ++dequeuedCount; - break; - case GonkBufferSlot::ACQUIRED: - ++acquiredCount; - break; - case GonkBufferSlot::FREE: - // We return the oldest of the free buffers to avoid - // stalling the producer if possible, since the consumer - // may still have pending reads of in-flight buffers - if (*found == GonkBufferQueueCore::INVALID_BUFFER_SLOT || - mSlots[s].mFrameNumber < mSlots[*found].mFrameNumber) { - *found = s; - } - break; - default: - break; - } - } - - // Producers are not allowed to dequeue more than one buffer if they - // did not set a buffer count - if (!mCore->mOverrideMaxBufferCount && dequeuedCount) { - ALOGE("%s: can't dequeue multiple buffers without setting the " - "buffer count", caller); - return INVALID_OPERATION; - } - - // See whether a buffer has been queued since the last - // setBufferCount so we know whether to perform the min undequeued - // buffers check below - if (mCore->mBufferHasBeenQueued) { - // Make sure the producer is not trying to dequeue more buffers - // than allowed - const int newUndequeuedCount = - maxBufferCount - (dequeuedCount + 1); - const int minUndequeuedCount = - mCore->getMinUndequeuedBufferCountLocked(async); - if (newUndequeuedCount < minUndequeuedCount) { - ALOGE("%s: min undequeued buffer count (%d) exceeded " - "(dequeued=%d undequeued=%d)", - caller, minUndequeuedCount, - dequeuedCount, newUndequeuedCount); - return INVALID_OPERATION; - } - } - - // If we disconnect and reconnect quickly, we can be in a state where - // our slots are empty but we have many buffers in the queue. This can - // cause us to run out of memory if we outrun the consumer. Wait here if - // it looks like we have too many buffers queued up. - bool tooManyBuffers = mCore->mQueue.size() - > static_cast<size_t>(maxBufferCount); - if (tooManyBuffers) { - ALOGV("%s: queue size is %zu, waiting", caller, - mCore->mQueue.size()); - } - - // If no buffer is found, or if the queue has too many buffers - // outstanding, wait for a buffer to be acquired or released, or for the - // max buffer count to change. - tryAgain = (*found == GonkBufferQueueCore::INVALID_BUFFER_SLOT) || - tooManyBuffers; - if (tryAgain) { - // Return an error if we're in non-blocking mode (producer and - // consumer are controlled by the application). - // However, the consumer is allowed to briefly acquire an extra - // buffer (which could cause us to have to wait here), which is - // okay, since it is only used to implement an atomic acquire + - // release (e.g., in GLConsumer::updateTexImage()) - if (mCore->mDequeueBufferCannotBlock && - (acquiredCount <= mCore->mMaxAcquiredBufferCount)) { - return WOULD_BLOCK; - } - mCore->mDequeueCondition.wait(mCore->mMutex); - } - } // while (tryAgain) - - return NO_ERROR; -} - -status_t GonkBufferQueueProducer::dequeueBuffer(int *outSlot, - sp<android::Fence> *outFence, bool async, - uint32_t width, uint32_t height, uint32_t format, uint32_t usage) { - ATRACE_CALL(); - { // Autolock scope - Mutex::Autolock lock(mCore->mMutex); - mConsumerName = mCore->mConsumerName; - } // Autolock scope - - ALOGV("dequeueBuffer: async=%s w=%u h=%u format=%#x, usage=%#x", - async ? "true" : "false", width, height, format, usage); - - if ((width && !height) || (!width && height)) { - ALOGE("dequeueBuffer: invalid size: w=%u h=%u", width, height); - return BAD_VALUE; - } - - status_t returnFlags = NO_ERROR; - // Reset slot - *outSlot = GonkBufferQueueCore::INVALID_BUFFER_SLOT; - - bool attachedByConsumer = false; - - { // Autolock scope - Mutex::Autolock lock(mCore->mMutex); - mCore->waitWhileAllocatingLocked(); - - if (format == 0) { - format = mCore->mDefaultBufferFormat; - } - - // Enable the usage bits the consumer requested - usage |= mCore->mConsumerUsageBits; - - int found; - status_t status = waitForFreeSlotThenRelock("dequeueBuffer", async, - &found, &returnFlags); - if (status != NO_ERROR) { - return status; - } - - // This should not happen - if (found == GonkBufferQueueCore::INVALID_BUFFER_SLOT) { - ALOGE("dequeueBuffer: no available buffer slots"); - return -EBUSY; - } - - *outSlot = found; - - attachedByConsumer = mSlots[found].mAttachedByConsumer; - - const bool useDefaultSize = !width && !height; - if (useDefaultSize) { - width = mCore->mDefaultWidth; - height = mCore->mDefaultHeight; - } - - mSlots[found].mBufferState = GonkBufferSlot::DEQUEUED; - - const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer); - if ((buffer == NULL) || - (static_cast<uint32_t>(buffer->width) != width) || - (static_cast<uint32_t>(buffer->height) != height) || - (static_cast<uint32_t>(buffer->format) != format) || - ((static_cast<uint32_t>(buffer->usage) & usage) != usage)) - { - mSlots[found].mAcquireCalled = false; - mSlots[found].mGraphicBuffer = NULL; - mSlots[found].mRequestBufferCalled = false; - mSlots[found].mFence = Fence::NO_FENCE; - - if (mSlots[found].mTextureClient) { - mSlots[found].mTextureClient->ClearRecycleCallback(); - // release TextureClient in ImageBridge thread - RefPtr<TextureClientReleaseTask> task = - MakeAndAddRef<TextureClientReleaseTask>(mSlots[found].mTextureClient); - mSlots[found].mTextureClient = NULL; - ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask(task.forget()); - } - - returnFlags |= BUFFER_NEEDS_REALLOCATION; - } - - if (CC_UNLIKELY(mSlots[found].mFence == NULL)) { - ALOGE("dequeueBuffer: about to return a NULL fence - " - "slot=%d w=%d h=%d format=%u", - found, buffer->width, buffer->height, buffer->format); - } - - *outFence = mSlots[found].mFence; - mSlots[found].mFence = Fence::NO_FENCE; - } // Autolock scope - - if (returnFlags & BUFFER_NEEDS_REALLOCATION) { - RefPtr<LayersIPCChannel> allocator = ImageBridgeChild::GetSingleton(); - usage |= GraphicBuffer::USAGE_HW_TEXTURE; - GrallocTextureData* texData = GrallocTextureData::Create(IntSize(width,height), format, - gfx::BackendType::NONE, - usage, allocator); - if (!texData) { - ALOGE("dequeueBuffer: failed to alloc gralloc buffer"); - return -ENOMEM; - } - RefPtr<TextureClient> textureClient = TextureClient::CreateWithData( - texData, TextureFlags::RECYCLE | TextureFlags::DEALLOCATE_CLIENT, allocator); - - sp<GraphicBuffer> graphicBuffer = texData->GetGraphicBuffer(); - - { // Autolock scope - Mutex::Autolock lock(mCore->mMutex); - - if (mCore->mIsAbandoned) { - ALOGE("dequeueBuffer: GonkBufferQueue has been abandoned"); - return NO_INIT; - } - - mSlots[*outSlot].mFrameNumber = UINT32_MAX; - mSlots[*outSlot].mGraphicBuffer = graphicBuffer; - mSlots[*outSlot].mTextureClient = textureClient; - } // Autolock scope - } - - if (attachedByConsumer) { - returnFlags |= BUFFER_NEEDS_REALLOCATION; - } - - ALOGV("dequeueBuffer: returning slot=%d/%" PRIu64 " buf=%p flags=%#x", - *outSlot, - mSlots[*outSlot].mFrameNumber, - mSlots[*outSlot].mGraphicBuffer->handle, returnFlags); - - return returnFlags; -} - -status_t GonkBufferQueueProducer::detachBuffer(int slot) { - ATRACE_CALL(); - ATRACE_BUFFER_INDEX(slot); - ALOGV("detachBuffer(P): slot %d", slot); - Mutex::Autolock lock(mCore->mMutex); - - if (mCore->mIsAbandoned) { - ALOGE("detachBuffer(P): GonkBufferQueue has been abandoned"); - return NO_INIT; - } - - if (slot < 0 || slot >= GonkBufferQueueDefs::NUM_BUFFER_SLOTS) { - ALOGE("detachBuffer(P): slot index %d out of range [0, %d)", - slot, GonkBufferQueueDefs::NUM_BUFFER_SLOTS); - return BAD_VALUE; - } else if (mSlots[slot].mBufferState != GonkBufferSlot::DEQUEUED) { - ALOGE("detachBuffer(P): slot %d is not owned by the producer " - "(state = %d)", slot, mSlots[slot].mBufferState); - return BAD_VALUE; - } else if (!mSlots[slot].mRequestBufferCalled) { - ALOGE("detachBuffer(P): buffer in slot %d has not been requested", - slot); - return BAD_VALUE; - } - - mCore->freeBufferLocked(slot); - mCore->mDequeueCondition.broadcast(); - - return NO_ERROR; -} - -status_t GonkBufferQueueProducer::detachNextBuffer(sp<GraphicBuffer>* outBuffer, - sp<Fence>* outFence) { - ATRACE_CALL(); - - if (outBuffer == NULL) { - ALOGE("detachNextBuffer: outBuffer must not be NULL"); - return BAD_VALUE; - } else if (outFence == NULL) { - ALOGE("detachNextBuffer: outFence must not be NULL"); - return BAD_VALUE; - } - - Mutex::Autolock lock(mCore->mMutex); - mCore->waitWhileAllocatingLocked(); - - if (mCore->mIsAbandoned) { - ALOGE("detachNextBuffer: GonkBufferQueue has been abandoned"); - return NO_INIT; - } - - // Find the oldest valid slot - int found = GonkBufferQueueCore::INVALID_BUFFER_SLOT; - for (int s = 0; s < GonkBufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { - if (mSlots[s].mBufferState == GonkBufferSlot::FREE && - mSlots[s].mGraphicBuffer != NULL) { - if (found == GonkBufferQueueCore::INVALID_BUFFER_SLOT || - mSlots[s].mFrameNumber < mSlots[found].mFrameNumber) { - found = s; - } - } - } - - if (found == GonkBufferQueueCore::INVALID_BUFFER_SLOT) { - return NO_MEMORY; - } - - ALOGV("detachNextBuffer detached slot %d", found); - - *outBuffer = mSlots[found].mGraphicBuffer; - *outFence = mSlots[found].mFence; - mCore->freeBufferLocked(found); - - return NO_ERROR; -} - -status_t GonkBufferQueueProducer::attachBuffer(int* outSlot, - const sp<android::GraphicBuffer>& buffer) { - ATRACE_CALL(); - - if (outSlot == NULL) { - ALOGE("attachBuffer(P): outSlot must not be NULL"); - return BAD_VALUE; - } else if (buffer == NULL) { - ALOGE("attachBuffer(P): cannot attach NULL buffer"); - return BAD_VALUE; - } - - Mutex::Autolock lock(mCore->mMutex); - mCore->waitWhileAllocatingLocked(); - - status_t returnFlags = NO_ERROR; - int found; - // TODO: Should we provide an async flag to attachBuffer? It seems - // unlikely that buffers which we are attaching to a GonkBufferQueue will - // be asynchronous (droppable), but it may not be impossible. - status_t status = waitForFreeSlotThenRelock("attachBuffer(P)", false, - &found, &returnFlags); - if (status != NO_ERROR) { - return status; - } - - // This should not happen - if (found == GonkBufferQueueCore::INVALID_BUFFER_SLOT) { - ALOGE("attachBuffer(P): no available buffer slots"); - return -EBUSY; - } - - *outSlot = found; - ATRACE_BUFFER_INDEX(*outSlot); - ALOGV("attachBuffer(P): returning slot %d flags=%#x", - *outSlot, returnFlags); - - mSlots[*outSlot].mGraphicBuffer = buffer; - mSlots[*outSlot].mBufferState = GonkBufferSlot::DEQUEUED; - mSlots[*outSlot].mFence = Fence::NO_FENCE; - mSlots[*outSlot].mRequestBufferCalled = true; - - return returnFlags; -} - -status_t GonkBufferQueueProducer::setSynchronousMode(bool enabled) { - ALOGV("setSynchronousMode: enabled=%d", enabled); - Mutex::Autolock lock(mCore->mMutex); - - if (mCore->mIsAbandoned) { - ALOGE("setSynchronousMode: BufferQueue has been abandoned!"); - return NO_INIT; - } - - if (mSynchronousMode != enabled) { - mSynchronousMode = enabled; - mCore->mDequeueCondition.broadcast(); - } - return OK; -} - -status_t GonkBufferQueueProducer::queueBuffer(int slot, - const QueueBufferInput &input, QueueBufferOutput *output) { - ATRACE_CALL(); - - int64_t timestamp; - bool isAutoTimestamp; - Rect crop; - int scalingMode; - uint32_t transform; - uint32_t stickyTransform; - bool async; - sp<Fence> fence; - input.deflate(×tamp, &isAutoTimestamp, &crop, &scalingMode, &transform, - &async, &fence, &stickyTransform); - - if (fence == NULL) { - ALOGE("queueBuffer: fence is NULL"); - // Temporary workaround for b/17946343: soldier-on instead of returning an error. This - // prevents the client from dying, at the risk of visible corruption due to hwcomposer - // reading the buffer before the producer is done rendering it. Unless the buffer is the - // last frame of an animation, the corruption will be transient. - fence = Fence::NO_FENCE; - // return BAD_VALUE; - } - - switch (scalingMode) { - case NATIVE_WINDOW_SCALING_MODE_FREEZE: - case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: - case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP: - case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP: - break; - default: - ALOGE("queueBuffer: unknown scaling mode %d", scalingMode); - return BAD_VALUE; - } - - GonkBufferItem item; - sp<IConsumerListener> listener; - { // Autolock scope - Mutex::Autolock lock(mCore->mMutex); - - if (mCore->mIsAbandoned) { - ALOGE("queueBuffer: GonkBufferQueue has been abandoned"); - return NO_INIT; - } - - const int maxBufferCount = mCore->getMaxBufferCountLocked(async); - if (async && mCore->mOverrideMaxBufferCount) { - // FIXME: Some drivers are manually setting the buffer count - // (which they shouldn't), so we do this extra test here to - // handle that case. This is TEMPORARY until we get this fixed. - if (mCore->mOverrideMaxBufferCount < maxBufferCount) { - ALOGE("queueBuffer: async mode is invalid with " - "buffer count override"); - return BAD_VALUE; - } - } - - if (slot < 0 || slot >= maxBufferCount) { - ALOGE("queueBuffer: slot index %d out of range [0, %d)", - slot, maxBufferCount); - return BAD_VALUE; - } else if (mSlots[slot].mBufferState != GonkBufferSlot::DEQUEUED) { - ALOGE("queueBuffer: slot %d is not owned by the producer " - "(state = %d)", slot, mSlots[slot].mBufferState); - return BAD_VALUE; - } else if (!mSlots[slot].mRequestBufferCalled) { - ALOGE("queueBuffer: slot %d was queued without requesting " - "a buffer", slot); - return BAD_VALUE; - } - - ALOGV("queueBuffer: slot=%d/%" PRIu64 " time=%" PRIu64 - " crop=[%d,%d,%d,%d] transform=%#x scale=%s", - slot, mCore->mFrameCounter + 1, timestamp, - crop.left, crop.top, crop.right, crop.bottom, - transform, GonkBufferItem::scalingModeName(scalingMode)); - - const sp<GraphicBuffer>& graphicBuffer(mSlots[slot].mGraphicBuffer); - Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight()); - Rect croppedRect; - crop.intersect(bufferRect, &croppedRect); - if (croppedRect != crop) { - ALOGE("queueBuffer: crop rect is not contained within the " - "buffer in slot %d", slot); - return BAD_VALUE; - } - - mSlots[slot].mFence = fence; - mSlots[slot].mBufferState = GonkBufferSlot::QUEUED; - ++mCore->mFrameCounter; - mSlots[slot].mFrameNumber = mCore->mFrameCounter; - - item.mAcquireCalled = mSlots[slot].mAcquireCalled; - item.mGraphicBuffer = mSlots[slot].mGraphicBuffer; - item.mCrop = crop; - item.mTransform = transform & ~NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY; - item.mTransformToDisplayInverse = - bool(transform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY); - item.mScalingMode = scalingMode; - item.mTimestamp = timestamp; - item.mIsAutoTimestamp = isAutoTimestamp; - item.mFrameNumber = mCore->mFrameCounter; - item.mSlot = slot; - item.mFence = fence; - item.mIsDroppable = mCore->mDequeueBufferCannotBlock || async; - - mStickyTransform = stickyTransform; - - if (mCore->mQueue.empty()) { - // When the queue is empty, we can ignore mDequeueBufferCannotBlock - // and simply queue this buffer - mCore->mQueue.push_back(item); - listener = mCore->mConsumerListener; - } else { - // When the queue is not empty, we need to look at the front buffer - // state to see if we need to replace it - GonkBufferQueueCore::Fifo::iterator front(mCore->mQueue.begin()); - if (front->mIsDroppable || !mSynchronousMode) { - // If the front queued buffer is still being tracked, we first - // mark it as freed - if (mCore->stillTracking(front)) { - mSlots[front->mSlot].mBufferState = GonkBufferSlot::FREE; - // Reset the frame number of the freed buffer so that it is - // the first in line to be dequeued again - mSlots[front->mSlot].mFrameNumber = 0; - } - // Overwrite the droppable buffer with the incoming one - *front = item; - listener = mCore->mConsumerListener; - } else { - mCore->mQueue.push_back(item); - listener = mCore->mConsumerListener; - } - } - - mCore->mBufferHasBeenQueued = true; - mCore->mDequeueCondition.broadcast(); - - output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight, - mCore->mTransformHint, mCore->mQueue.size()); - - item.mGraphicBuffer.clear(); - item.mSlot = GonkBufferItem::INVALID_BUFFER_SLOT; - } // Autolock scope - - // Call back without lock held - if (listener != NULL) { -#if ANDROID_VERSION == 21 - listener->onFrameAvailable(); -#else - listener->onFrameAvailable(reinterpret_cast<::android::BufferItem&>(item)); -#endif - } - - return NO_ERROR; -} - -void GonkBufferQueueProducer::cancelBuffer(int slot, const sp<Fence>& fence) { - ATRACE_CALL(); - ALOGV("cancelBuffer: slot %d", slot); - Mutex::Autolock lock(mCore->mMutex); - - if (mCore->mIsAbandoned) { - ALOGE("cancelBuffer: GonkBufferQueue has been abandoned"); - return; - } - - if (slot < 0 || slot >= GonkBufferQueueDefs::NUM_BUFFER_SLOTS) { - ALOGE("cancelBuffer: slot index %d out of range [0, %d)", - slot, GonkBufferQueueDefs::NUM_BUFFER_SLOTS); - return; - } else if (mSlots[slot].mBufferState != GonkBufferSlot::DEQUEUED) { - ALOGE("cancelBuffer: slot %d is not owned by the producer " - "(state = %d)", slot, mSlots[slot].mBufferState); - return; - } else if (fence == NULL) { - ALOGE("cancelBuffer: fence is NULL"); - return; - } - - mSlots[slot].mBufferState = GonkBufferSlot::FREE; - mSlots[slot].mFrameNumber = 0; - mSlots[slot].mFence = fence; - mCore->mDequeueCondition.broadcast(); -} - -int GonkBufferQueueProducer::query(int what, int *outValue) { - ATRACE_CALL(); - Mutex::Autolock lock(mCore->mMutex); - - if (outValue == NULL) { - ALOGE("query: outValue was NULL"); - return BAD_VALUE; - } - - if (mCore->mIsAbandoned) { - ALOGE("query: GonkBufferQueue has been abandoned"); - return NO_INIT; - } - - int value; - switch (what) { - case NATIVE_WINDOW_WIDTH: - value = mCore->mDefaultWidth; - break; - case NATIVE_WINDOW_HEIGHT: - value = mCore->mDefaultHeight; - break; - case NATIVE_WINDOW_FORMAT: - value = mCore->mDefaultBufferFormat; - break; - case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS: - value = mCore->getMinUndequeuedBufferCountLocked(false); - break; - case NATIVE_WINDOW_STICKY_TRANSFORM: - value = static_cast<int>(mStickyTransform); - break; - case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND: - value = (mCore->mQueue.size() > 1); - break; - case NATIVE_WINDOW_CONSUMER_USAGE_BITS: - value = mCore->mConsumerUsageBits; - break; - default: - return BAD_VALUE; - } - - ALOGV("query: %d? %d", what, value); - *outValue = value; - return NO_ERROR; -} - -status_t GonkBufferQueueProducer::connect(const sp<IProducerListener>& listener, - int api, bool producerControlledByApp, QueueBufferOutput *output) { - ATRACE_CALL(); - Mutex::Autolock lock(mCore->mMutex); - mConsumerName = mCore->mConsumerName; - ALOGV("connect(P): api=%d producerControlledByApp=%s", api, - producerControlledByApp ? "true" : "false"); - - if (mCore->mIsAbandoned) { - ALOGE("connect(P): GonkBufferQueue has been abandoned"); - return NO_INIT; - } - - if (mCore->mConsumerListener == NULL) { - ALOGE("connect(P): GonkBufferQueue has no consumer"); - return NO_INIT; - } - - if (output == NULL) { - ALOGE("connect(P): output was NULL"); - return BAD_VALUE; - } - - if (mCore->mConnectedApi != GonkBufferQueueCore::NO_CONNECTED_API) { - ALOGE("connect(P): already connected (cur=%d req=%d)", mCore->mConnectedApi, - api); - return BAD_VALUE; - } - - int status = NO_ERROR; - switch (api) { - case NATIVE_WINDOW_API_EGL: - case NATIVE_WINDOW_API_CPU: - case NATIVE_WINDOW_API_MEDIA: - case NATIVE_WINDOW_API_CAMERA: - mCore->mConnectedApi = api; - output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight, - mCore->mTransformHint, mCore->mQueue.size()); - - // Set up a death notification so that we can disconnect - // automatically if the remote producer dies - if (listener != NULL && - listener->asBinder()->remoteBinder() != NULL) { - status = listener->asBinder()->linkToDeath( - static_cast<IBinder::DeathRecipient*>(this)); - if (status != NO_ERROR) { - ALOGE("connect(P): linkToDeath failed: %s (%d)", - strerror(-status), status); - } - } - mCore->mConnectedProducerListener = listener; - break; - default: - ALOGE("connect(P): unknown API %d", api); - status = BAD_VALUE; - break; - } - - mCore->mBufferHasBeenQueued = false; - mCore->mDequeueBufferCannotBlock = - mCore->mConsumerControlledByApp && producerControlledByApp; - - return status; -} - -status_t GonkBufferQueueProducer::disconnect(int api) { - ATRACE_CALL(); - ALOGV("disconnect(P): api %d", api); - - int status = NO_ERROR; - sp<IConsumerListener> listener; - { // Autolock scope - Mutex::Autolock lock(mCore->mMutex); - mCore->waitWhileAllocatingLocked(); - - if (mCore->mIsAbandoned) { - // It's not really an error to disconnect after the surface has - // been abandoned; it should just be a no-op. - return NO_ERROR; - } - - switch (api) { - case NATIVE_WINDOW_API_EGL: - case NATIVE_WINDOW_API_CPU: - case NATIVE_WINDOW_API_MEDIA: - case NATIVE_WINDOW_API_CAMERA: - if (mCore->mConnectedApi == api) { - mCore->freeAllBuffersLocked(); - mCore->mConnectedApi = GonkBufferQueueCore::NO_CONNECTED_API; - mCore->mSidebandStream.clear(); - mCore->mDequeueCondition.broadcast(); - listener = mCore->mConsumerListener; - } else { - ALOGE("disconnect(P): connected to another API " - "(cur=%d req=%d)", mCore->mConnectedApi, api); - status = BAD_VALUE; - } - break; - default: - ALOGE("disconnect(P): unknown API %d", api); - status = BAD_VALUE; - break; - } - } // Autolock scope - - // Call back without lock held - if (listener != NULL) { - listener->onBuffersReleased(); - } - - return status; -} - -status_t GonkBufferQueueProducer::setSidebandStream(const sp<NativeHandle>& stream) { - return INVALID_OPERATION; -} - -void GonkBufferQueueProducer::allocateBuffers(bool async, uint32_t width, - uint32_t height, uint32_t format, uint32_t usage) { - ALOGE("allocateBuffers: no op"); -} - -void GonkBufferQueueProducer::binderDied(const wp<android::IBinder>& /* who */) { - // If we're here, it means that a producer we were connected to died. - // We're guaranteed that we are still connected to it because we remove - // this callback upon disconnect. It's therefore safe to read mConnectedApi - // without synchronization here. - int api = mCore->mConnectedApi; - disconnect(api); -} - -} // namespace android diff --git a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueProducer.h b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueProducer.h deleted file mode 100644 index a1a22416a..000000000 --- a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueProducer.h +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright 2014 The Android Open Source Project - * Copyright (C) 2014 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef NATIVEWINDOW_GONKBUFFERQUEUEPRODUCER_LL_H -#define NATIVEWINDOW_GONKBUFFERQUEUEPRODUCER_LL_H - -#include "GonkBufferQueueDefs.h" -#include <gui/IGraphicBufferProducer.h> - -namespace android { - -class GonkBufferQueueProducer : public BnGraphicBufferProducer, - private IBinder::DeathRecipient { -public: - friend class GonkBufferQueue; // Needed to access binderDied - - GonkBufferQueueProducer(const sp<GonkBufferQueueCore>& core); - virtual ~GonkBufferQueueProducer(); - - // requestBuffer returns the GraphicBuffer for slot N. - // - // In normal operation, this is called the first time slot N is returned - // by dequeueBuffer. It must be called again if dequeueBuffer returns - // flags indicating that previously-returned buffers are no longer valid. - virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf); - - // setBufferCount updates the number of available buffer slots. If this - // method succeeds, buffer slots will be both unallocated and owned by - // the GonkBufferQueue object (i.e. they are not owned by the producer or - // consumer). - // - // This will fail if the producer has dequeued any buffers, or if - // bufferCount is invalid. bufferCount must generally be a value - // between the minimum undequeued buffer count (exclusive) and NUM_BUFFER_SLOTS - // (inclusive). It may also be set to zero (the default) to indicate - // that the producer does not wish to set a value. The minimum value - // can be obtained by calling query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, - // ...). - // - // This may only be called by the producer. The consumer will be told - // to discard buffers through the onBuffersReleased callback. - virtual status_t setBufferCount(int bufferCount); - - // dequeueBuffer gets the next buffer slot index for the producer to use. - // If a buffer slot is available then that slot index is written to the - // location pointed to by the buf argument and a status of OK is returned. - // If no slot is available then a status of -EBUSY is returned and buf is - // unmodified. - // - // The outFence parameter will be updated to hold the fence associated with - // the buffer. The contents of the buffer must not be overwritten until the - // fence signals. If the fence is Fence::NO_FENCE, the buffer may be - // written immediately. - // - // The width and height parameters must be no greater than the minimum of - // GL_MAX_VIEWPORT_DIMS and GL_MAX_TEXTURE_SIZE (see: glGetIntegerv). - // An error due to invalid dimensions might not be reported until - // updateTexImage() is called. If width and height are both zero, the - // default values specified by setDefaultBufferSize() are used instead. - // - // The pixel formats are enumerated in graphics.h, e.g. - // HAL_PIXEL_FORMAT_RGBA_8888. If the format is 0, the default format - // will be used. - // - // The usage argument specifies gralloc buffer usage flags. The values - // are enumerated in gralloc.h, e.g. GRALLOC_USAGE_HW_RENDER. These - // will be merged with the usage flags specified by setConsumerUsageBits. - // - // The return value may be a negative error value or a non-negative - // collection of flags. If the flags are set, the return values are - // valid, but additional actions must be performed. - // - // If IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION is set, the - // producer must discard cached GraphicBuffer references for the slot - // returned in buf. - // If IGraphicBufferProducer::RELEASE_ALL_BUFFERS is set, the producer - // must discard cached GraphicBuffer references for all slots. - // - // In both cases, the producer will need to call requestBuffer to get a - // GraphicBuffer handle for the returned slot. - virtual status_t dequeueBuffer(int *outSlot, sp<Fence>* outFence, bool async, - uint32_t width, uint32_t height, uint32_t format, uint32_t usage); - - // See IGraphicBufferProducer::detachBuffer - virtual status_t detachBuffer(int slot); - - // See IGraphicBufferProducer::detachNextBuffer - virtual status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer, - sp<Fence>* outFence); - - // See IGraphicBufferProducer::attachBuffer - virtual status_t attachBuffer(int* outSlot, const sp<GraphicBuffer>& buffer); - - // queueBuffer returns a filled buffer to the GonkBufferQueue. - // - // Additional data is provided in the QueueBufferInput struct. Notably, - // a timestamp must be provided for the buffer. The timestamp is in - // nanoseconds, and must be monotonically increasing. Its other semantics - // (zero point, etc) are producer-specific and should be documented by the - // producer. - // - // The caller may provide a fence that signals when all rendering - // operations have completed. Alternatively, NO_FENCE may be used, - // indicating that the buffer is ready immediately. - // - // Some values are returned in the output struct: the current settings - // for default width and height, the current transform hint, and the - // number of queued buffers. - virtual status_t queueBuffer(int slot, - const QueueBufferInput& input, QueueBufferOutput* output); - - // cancelBuffer returns a dequeued buffer to the GonkBufferQueue, but doesn't - // queue it for use by the consumer. - // - // The buffer will not be overwritten until the fence signals. The fence - // will usually be the one obtained from dequeueBuffer. - virtual void cancelBuffer(int slot, const sp<Fence>& fence); - - // Query native window attributes. The "what" values are enumerated in - // window.h (e.g. NATIVE_WINDOW_FORMAT). - virtual int query(int what, int* outValue); - - // connect attempts to connect a producer API to the GonkBufferQueue. This - // must be called before any other IGraphicBufferProducer methods are - // called except for getAllocator. A consumer must already be connected. - // - // This method will fail if connect was previously called on the - // GonkBufferQueue and no corresponding disconnect call was made (i.e. if - // it's still connected to a producer). - // - // APIs are enumerated in window.h (e.g. NATIVE_WINDOW_API_CPU). - virtual status_t connect(const sp<IProducerListener>& listener, - int api, bool producerControlledByApp, QueueBufferOutput* output); - - // disconnect attempts to disconnect a producer API from the GonkBufferQueue. - // Calling this method will cause any subsequent calls to other - // IGraphicBufferProducer methods to fail except for getAllocator and connect. - // Successfully calling connect after this will allow the other methods to - // succeed again. - // - // This method will fail if the the GonkBufferQueue is not currently - // connected to the specified producer API. - virtual status_t disconnect(int api); - - // Attaches a sideband buffer stream to the IGraphicBufferProducer. - // - // A sideband stream is a device-specific mechanism for passing buffers - // from the producer to the consumer without using dequeueBuffer/ - // queueBuffer. If a sideband stream is present, the consumer can choose - // whether to acquire buffers from the sideband stream or from the queued - // buffers. - // - // Passing NULL or a different stream handle will detach the previous - // handle if any. - virtual status_t setSidebandStream(const sp<NativeHandle>& stream); - - // See IGraphicBufferProducer::allocateBuffers - virtual void allocateBuffers(bool async, uint32_t width, uint32_t height, - uint32_t format, uint32_t usage); - - // setSynchronousMode sets whether dequeueBuffer is synchronous or - // asynchronous. In synchronous mode, dequeueBuffer blocks until - // a buffer is available, the currently bound buffer can be dequeued and - // queued buffers will be acquired in order. In asynchronous mode, - // a queued buffer may be replaced by a subsequently queued buffer. - // - // The default mode is synchronous. - // This should be called only during initialization. - virtual status_t setSynchronousMode(bool enabled); - -private: - // This is required by the IBinder::DeathRecipient interface - virtual void binderDied(const wp<IBinder>& who); - - // waitForFreeSlotThenRelock finds the oldest slot in the FREE state. It may - // block if there are no available slots and we are not in non-blocking - // mode (producer and consumer controlled by the application). If it blocks, - // it will release mCore->mMutex while blocked so that other operations on - // the GonkBufferQueue may succeed. - status_t waitForFreeSlotThenRelock(const char* caller, bool async, - int* found, status_t* returnFlags) const; - - sp<GonkBufferQueueCore> mCore; - - // This references mCore->mSlots. Lock mCore->mMutex while accessing. - GonkBufferQueueDefs::SlotsType& mSlots; - - // This is a cached copy of the name stored in the GonkBufferQueueCore. - // It's updated during connect and dequeueBuffer (which should catch - // most updates). - String8 mConsumerName; - - // mSynchronousMode whether we're in synchronous mode or not - bool mSynchronousMode; - - uint32_t mStickyTransform; - -}; // class GonkBufferQueueProducer - -} // namespace android - -#endif diff --git a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferSlot.cpp b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferSlot.cpp deleted file mode 100644 index 9e4a424a9..000000000 --- a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferSlot.cpp +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2014 The Android Open Source Project - * Copyright (C) 2014 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "GonkBufferSlot.h" - -namespace android { - -const char* GonkBufferSlot::bufferStateName(BufferState state) { - switch (state) { - case GonkBufferSlot::DEQUEUED: return "DEQUEUED"; - case GonkBufferSlot::QUEUED: return "QUEUED"; - case GonkBufferSlot::FREE: return "FREE"; - case GonkBufferSlot::ACQUIRED: return "ACQUIRED"; - default: return "Unknown"; - } -} - -} // namespace android diff --git a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferSlot.h b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferSlot.h deleted file mode 100644 index 759bb7b23..000000000 --- a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferSlot.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright 2014 The Android Open Source Project - * Copyright (C) 2014 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef NATIVEWINDOW_GONKBUFFERSLOT_LL_H -#define NATIVEWINDOW_GONKBUFFERSLOT_LL_H - -#include <ui/Fence.h> -#include <ui/GraphicBuffer.h> - -#include <utils/StrongPointer.h> - -#include "mozilla/layers/TextureClient.h" - -namespace android { - -struct GonkBufferSlot { - typedef mozilla::layers::TextureClient TextureClient; - - GonkBufferSlot() - : mBufferState(GonkBufferSlot::FREE), - mRequestBufferCalled(false), - mFrameNumber(0), - mAcquireCalled(false), - mNeedsCleanupOnRelease(false), - mAttachedByConsumer(false) { - } - - // mGraphicBuffer points to the buffer allocated for this slot or is NULL - // if no buffer has been allocated. - sp<GraphicBuffer> mGraphicBuffer; - - // BufferState represents the different states in which a buffer slot - // can be. All slots are initially FREE. - enum BufferState { - // FREE indicates that the buffer is available to be dequeued - // by the producer. The buffer may be in use by the consumer for - // a finite time, so the buffer must not be modified until the - // associated fence is signaled. - // - // The slot is "owned" by BufferQueue. It transitions to DEQUEUED - // when dequeueBuffer is called. - FREE = 0, - - // DEQUEUED indicates that the buffer has been dequeued by the - // producer, but has not yet been queued or canceled. The - // producer may modify the buffer's contents as soon as the - // associated ready fence is signaled. - // - // The slot is "owned" by the producer. It can transition to - // QUEUED (via queueBuffer) or back to FREE (via cancelBuffer). - DEQUEUED = 1, - - // QUEUED indicates that the buffer has been filled by the - // producer and queued for use by the consumer. The buffer - // contents may continue to be modified for a finite time, so - // the contents must not be accessed until the associated fence - // is signaled. - // - // The slot is "owned" by BufferQueue. It can transition to - // ACQUIRED (via acquireBuffer) or to FREE (if another buffer is - // queued in asynchronous mode). - QUEUED = 2, - - // ACQUIRED indicates that the buffer has been acquired by the - // consumer. As with QUEUED, the contents must not be accessed - // by the consumer until the fence is signaled. - // - // The slot is "owned" by the consumer. It transitions to FREE - // when releaseBuffer is called. - ACQUIRED = 3 - }; - - static const char* bufferStateName(BufferState state); - - // mBufferState is the current state of this buffer slot. - BufferState mBufferState; - - // mRequestBufferCalled is used for validating that the producer did - // call requestBuffer() when told to do so. Technically this is not - // needed but useful for debugging and catching producer bugs. - bool mRequestBufferCalled; - - // mFrameNumber is the number of the queued frame for this slot. This - // is used to dequeue buffers in LRU order (useful because buffers - // may be released before their release fence is signaled). - uint64_t mFrameNumber; - - // mFence is a fence which will signal when work initiated by the - // previous owner of the buffer is finished. When the buffer is FREE, - // the fence indicates when the consumer has finished reading - // from the buffer, or when the producer has finished writing if it - // called cancelBuffer after queueing some writes. When the buffer is - // QUEUED, it indicates when the producer has finished filling the - // buffer. When the buffer is DEQUEUED or ACQUIRED, the fence has been - // passed to the consumer or producer along with ownership of the - // buffer, and mFence is set to NO_FENCE. - sp<Fence> mFence; - - // Indicates whether this buffer has been seen by a consumer yet - bool mAcquireCalled; - - // Indicates whether this buffer needs to be cleaned up by the - // consumer. This is set when a buffer in ACQUIRED state is freed. - // It causes releaseBuffer to return STALE_BUFFER_SLOT. - bool mNeedsCleanupOnRelease; - - // Indicates whether the buffer was attached on the consumer side. - // If so, it needs to set the BUFFER_NEEDS_REALLOCATION flag when dequeued - // to prevent the producer from using a stale cached buffer. - bool mAttachedByConsumer; - - // mTextureClient is a thin abstraction over remotely allocated GraphicBuffer. - RefPtr<TextureClient> mTextureClient; -}; - -} // namespace android - -#endif diff --git a/widget/gonk/nativewindow/GonkConsumerBaseJB.cpp b/widget/gonk/nativewindow/GonkConsumerBaseJB.cpp deleted file mode 100644 index 1ee37e4e2..000000000 --- a/widget/gonk/nativewindow/GonkConsumerBaseJB.cpp +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * Copyright (C) 2013 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "GonkConsumerBase" -#define ATRACE_TAG ATRACE_TAG_GRAPHICS -//#define LOG_NDEBUG 0 - -#define EGL_EGLEXT_PROTOTYPES - -#include <hardware/hardware.h> - -#include <gui/IGraphicBufferAlloc.h> -#include <utils/Log.h> -#include <utils/String8.h> - -#include "GonkConsumerBaseJB.h" - -// Macros for including the GonkConsumerBase name in log messages -#define CB_LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__) -#define CB_LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) -#define CB_LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) -#define CB_LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__) -#define CB_LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) - -namespace android { - -// Get an ID that's unique within this process. -static int32_t createProcessUniqueId() { - static volatile int32_t globalCounter = 0; - return android_atomic_inc(&globalCounter); -} - -GonkConsumerBase::GonkConsumerBase(const sp<GonkBufferQueue>& bufferQueue) : - mAbandoned(false), - mBufferQueue(bufferQueue) { - // Choose a name using the PID and a process-unique ID. - mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId()); - - // Note that we can't create an sp<...>(this) in a ctor that will not keep a - // reference once the ctor ends, as that would cause the refcount of 'this' - // dropping to 0 at the end of the ctor. Since all we need is a wp<...> - // that's what we create. - wp<GonkBufferQueue::ConsumerListener> listener; - sp<GonkBufferQueue::ConsumerListener> proxy; - listener = static_cast<GonkBufferQueue::ConsumerListener*>(this); - proxy = new GonkBufferQueue::ProxyConsumerListener(listener); - - status_t err = mBufferQueue->consumerConnect(proxy); - if (err != NO_ERROR) { - CB_LOGE("GonkConsumerBase: error connecting to GonkBufferQueue: %s (%d)", - strerror(-err), err); - } else { - mBufferQueue->setConsumerName(mName); - } -} - -GonkConsumerBase::~GonkConsumerBase() { - CB_LOGV("~GonkConsumerBase"); - Mutex::Autolock lock(mMutex); - - // Verify that abandon() has been called before we get here. This should - // be done by GonkConsumerBase::onLastStrongRef(), but it's possible for a - // derived class to override that method and not call - // GonkConsumerBase::onLastStrongRef(). - LOG_ALWAYS_FATAL_IF(!mAbandoned, "[%s] ~GonkConsumerBase was called, but the " - "consumer is not abandoned!", mName.string()); -} - -void GonkConsumerBase::onLastStrongRef(const void* id) { - abandon(); -} - -void GonkConsumerBase::freeBufferLocked(int slotIndex) { - CB_LOGV("freeBufferLocked: slotIndex=%d", slotIndex); - mSlots[slotIndex].mGraphicBuffer = 0; - mSlots[slotIndex].mFence = Fence::NO_FENCE; -} - -// Used for refactoring, should not be in final interface -sp<GonkBufferQueue> GonkConsumerBase::getBufferQueue() const { - Mutex::Autolock lock(mMutex); - return mBufferQueue; -} - -void GonkConsumerBase::onFrameAvailable() { - CB_LOGV("onFrameAvailable"); - - sp<FrameAvailableListener> listener; - { // scope for the lock - Mutex::Autolock lock(mMutex); -#if ANDROID_VERSION == 17 - listener = mFrameAvailableListener; -#else - listener = mFrameAvailableListener.promote(); -#endif - } - - if (listener != NULL) { - CB_LOGV("actually calling onFrameAvailable"); - listener->onFrameAvailable(); - } -} - -void GonkConsumerBase::onBuffersReleased() { - Mutex::Autolock lock(mMutex); - - CB_LOGV("onBuffersReleased"); - - if (mAbandoned) { - // Nothing to do if we're already abandoned. - return; - } - - uint32_t mask = 0; - mBufferQueue->getReleasedBuffers(&mask); - for (int i = 0; i < GonkBufferQueue::NUM_BUFFER_SLOTS; i++) { - if (mask & (1 << i)) { - freeBufferLocked(i); - } - } -} - -void GonkConsumerBase::abandon() { - CB_LOGV("abandon"); - Mutex::Autolock lock(mMutex); - - if (!mAbandoned) { - abandonLocked(); - mAbandoned = true; - } -} - -void GonkConsumerBase::abandonLocked() { - CB_LOGV("abandonLocked"); - for (int i =0; i < GonkBufferQueue::NUM_BUFFER_SLOTS; i++) { - freeBufferLocked(i); - } - // disconnect from the GonkBufferQueue - mBufferQueue->consumerDisconnect(); - mBufferQueue.clear(); -} - -void GonkConsumerBase::setFrameAvailableListener( -#if ANDROID_VERSION == 17 - const sp<FrameAvailableListener>& listener) { -#else - const wp<FrameAvailableListener>& listener) { -#endif - CB_LOGV("setFrameAvailableListener"); - Mutex::Autolock lock(mMutex); - mFrameAvailableListener = listener; -} - -void GonkConsumerBase::dump(String8& result) const { - char buffer[1024]; - dump(result, "", buffer, 1024); -} - -void GonkConsumerBase::dump(String8& result, const char* prefix, - char* buffer, size_t size) const { - Mutex::Autolock _l(mMutex); - dumpLocked(result, prefix, buffer, size); -} - -void GonkConsumerBase::dumpLocked(String8& result, const char* prefix, - char* buffer, size_t SIZE) const { - snprintf(buffer, SIZE, "%smAbandoned=%d\n", prefix, int(mAbandoned)); - result.append(buffer); - - if (!mAbandoned) { - mBufferQueue->dumpToString(result, prefix, buffer, SIZE); - } -} - -status_t GonkConsumerBase::acquireBufferLocked(GonkBufferQueue::BufferItem *item) { - status_t err = mBufferQueue->acquireBuffer(item); - if (err != NO_ERROR) { - return err; - } - - if (item->mGraphicBuffer != NULL) { - mSlots[item->mBuf].mGraphicBuffer = item->mGraphicBuffer; - } - - mSlots[item->mBuf].mFence = item->mFence; - - CB_LOGV("acquireBufferLocked: -> slot=%d", item->mBuf); - - return OK; -} - -status_t GonkConsumerBase::addReleaseFence(int slot, const sp<Fence>& fence) { - Mutex::Autolock lock(mMutex); - return addReleaseFenceLocked(slot, fence); -} - -status_t GonkConsumerBase::addReleaseFenceLocked(int slot, const sp<Fence>& fence) { - CB_LOGV("addReleaseFenceLocked: slot=%d", slot); - - if (!mSlots[slot].mFence.get()) { - mSlots[slot].mFence = fence; - } else { - sp<Fence> mergedFence = Fence::merge( - String8::format("%.28s:%d", mName.string(), slot), - mSlots[slot].mFence, fence); - if (!mergedFence.get()) { - CB_LOGE("failed to merge release fences"); - // synchronization is broken, the best we can do is hope fences - // signal in order so the new fence will act like a union - mSlots[slot].mFence = fence; - return BAD_VALUE; - } - mSlots[slot].mFence = mergedFence; - } - - return OK; -} - -status_t GonkConsumerBase::releaseBufferLocked(int slot) { - CB_LOGV("releaseBufferLocked: slot=%d", slot); - status_t err = mBufferQueue->releaseBuffer(slot, mSlots[slot].mFence); - if (err == GonkBufferQueue::STALE_BUFFER_SLOT) { - freeBufferLocked(slot); - } - - mSlots[slot].mFence = Fence::NO_FENCE; - - return err; -} - -} // namespace android diff --git a/widget/gonk/nativewindow/GonkConsumerBaseJB.h b/widget/gonk/nativewindow/GonkConsumerBaseJB.h deleted file mode 100644 index 8f523af37..000000000 --- a/widget/gonk/nativewindow/GonkConsumerBaseJB.h +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * Copyright (C) 2013 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef NATIVEWINDOW_GONKCONSUMERBASE_JB_H -#define NATIVEWINDOW_GONKCONSUMERBASE_JB_H - -#include <ui/GraphicBuffer.h> - -#include <utils/String8.h> -#include <utils/Vector.h> -#include <utils/threads.h> - -#include "GonkBufferQueueJB.h" - -namespace android { -// ---------------------------------------------------------------------------- - -class String8; - -// GonkConsumerBase is a base class for GonkBufferQueue consumer end-points. It -// handles common tasks like management of the connection to the GonkBufferQueue -// and the buffer pool. -class GonkConsumerBase : public virtual RefBase, - protected GonkBufferQueue::ConsumerListener { -public: - struct FrameAvailableListener : public virtual RefBase { - // onFrameAvailable() is called each time an additional frame becomes - // available for consumption. This means that frames that are queued - // while in asynchronous mode only trigger the callback if no previous - // frames are pending. Frames queued while in synchronous mode always - // trigger the callback. - // - // This is called without any lock held and can be called concurrently - // by multiple threads. - virtual void onFrameAvailable() = 0; - }; - - virtual ~GonkConsumerBase(); - - // abandon frees all the buffers and puts the GonkConsumerBase into the - // 'abandoned' state. Once put in this state the GonkConsumerBase can never - // leave it. When in the 'abandoned' state, all methods of the - // IGraphicBufferProducer interface will fail with the NO_INIT error. - // - // Note that while calling this method causes all the buffers to be freed - // from the perspective of the the GonkConsumerBase, if there are additional - // references on the buffers (e.g. if a buffer is referenced by a client - // or by OpenGL ES as a texture) then those buffer will remain allocated. - void abandon(); - - // set the name of the GonkConsumerBase that will be used to identify it in - // log messages. - void setName(const String8& name); - - // getBufferQueue returns the GonkBufferQueue object to which this - // GonkConsumerBase is connected. - sp<GonkBufferQueue> getBufferQueue() const; - - // dump writes the current state to a string. Child classes should add - // their state to the dump by overriding the dumpLocked method, which is - // called by these methods after locking the mutex. - void dump(String8& result) const; - void dump(String8& result, const char* prefix, char* buffer, size_t SIZE) const; - - // setFrameAvailableListener sets the listener object that will be notified - // when a new frame becomes available. -#if ANDROID_VERSION == 17 - void setFrameAvailableListener(const sp<FrameAvailableListener>& listener); -#else - void setFrameAvailableListener(const wp<FrameAvailableListener>& listener); -#endif - -private: - GonkConsumerBase(const GonkConsumerBase&); - void operator=(const GonkConsumerBase&); - -protected: - - // GonkConsumerBase constructs a new GonkConsumerBase object to consume image - // buffers from the given GonkBufferQueue. - GonkConsumerBase(const sp<GonkBufferQueue> &bufferQueue); - - // onLastStrongRef gets called by RefBase just before the dtor of the most - // derived class. It is used to clean up the buffers so that GonkConsumerBase - // can coordinate the clean-up by calling into virtual methods implemented - // by the derived classes. This would not be possible from the - // ConsuemrBase dtor because by the time that gets called the derived - // classes have already been destructed. - // - // This methods should not need to be overridden by derived classes, but - // if they are overridden the GonkConsumerBase implementation must be called - // from the derived class. - virtual void onLastStrongRef(const void* id); - - // Implementation of the GonkBufferQueue::ConsumerListener interface. These - // calls are used to notify the GonkConsumerBase of asynchronous events in the - // GonkBufferQueue. These methods should not need to be overridden by derived - // classes, but if they are overridden the GonkConsumerBase implementation - // must be called from the derived class. - virtual void onFrameAvailable(); - virtual void onBuffersReleased(); - - // freeBufferLocked frees up the given buffer slot. If the slot has been - // initialized this will release the reference to the GraphicBuffer in that - // slot. Otherwise it has no effect. - // - // Derived classes should override this method to clean up any state they - // keep per slot. If it is overridden, the derived class's implementation - // must call GonkConsumerBase::freeBufferLocked. - // - // This method must be called with mMutex locked. - virtual void freeBufferLocked(int slotIndex); - - // abandonLocked puts the GonkBufferQueue into the abandoned state, causing - // all future operations on it to fail. This method rather than the public - // abandon method should be overridden by child classes to add abandon- - // time behavior. - // - // Derived classes should override this method to clean up any object - // state they keep (as opposed to per-slot state). If it is overridden, - // the derived class's implementation must call GonkConsumerBase::abandonLocked. - // - // This method must be called with mMutex locked. - virtual void abandonLocked(); - - // dumpLocked dumps the current state of the GonkConsumerBase object to the - // result string. Each line is prefixed with the string pointed to by the - // prefix argument. The buffer argument points to a buffer that may be - // used for intermediate formatting data, and the size of that buffer is - // indicated by the size argument. - // - // Derived classes should override this method to dump their internal - // state. If this method is overridden the derived class's implementation - // should call GonkConsumerBase::dumpLocked. - // - // This method must be called with mMutex locked. - virtual void dumpLocked(String8& result, const char* prefix, char* buffer, - size_t size) const; - - // acquireBufferLocked fetches the next buffer from the GonkBufferQueue and - // updates the buffer slot for the buffer returned. - // - // Derived classes should override this method to perform any - // initialization that must take place the first time a buffer is assigned - // to a slot. If it is overridden the derived class's implementation must - // call GonkConsumerBase::acquireBufferLocked. - virtual status_t acquireBufferLocked(GonkBufferQueue::BufferItem *item); - - // releaseBufferLocked relinquishes control over a buffer, returning that - // control to the GonkBufferQueue. - // - // Derived classes should override this method to perform any cleanup that - // must take place when a buffer is released back to the GonkBufferQueue. If - // it is overridden the derived class's implementation must call - // GonkConsumerBase::releaseBufferLocked. - virtual status_t releaseBufferLocked(int buf); - - // addReleaseFence* adds the sync points associated with a fence to the set - // of sync points that must be reached before the buffer in the given slot - // may be used after the slot has been released. This should be called by - // derived classes each time some asynchronous work is kicked off that - // references the buffer. - status_t addReleaseFence(int slot, const sp<Fence>& fence); - status_t addReleaseFenceLocked(int slot, const sp<Fence>& fence); - - // Slot contains the information and object references that - // GonkConsumerBase maintains about a GonkBufferQueue buffer slot. - struct Slot { - // mGraphicBuffer is the Gralloc buffer store in the slot or NULL if - // no Gralloc buffer is in the slot. - sp<GraphicBuffer> mGraphicBuffer; - - // mFence is a fence which will signal when the buffer associated with - // this buffer slot is no longer being used by the consumer and can be - // overwritten. The buffer can be dequeued before the fence signals; - // the producer is responsible for delaying writes until it signals. - sp<Fence> mFence; - }; - - // mSlots stores the buffers that have been allocated by the GonkBufferQueue - // for each buffer slot. It is initialized to null pointers, and gets - // filled in with the result of GonkBufferQueue::acquire when the - // client dequeues a buffer from a - // slot that has not yet been used. The buffer allocated to a slot will also - // be replaced if the requested buffer usage or geometry differs from that - // of the buffer allocated to a slot. - Slot mSlots[GonkBufferQueue::NUM_BUFFER_SLOTS]; - - // mAbandoned indicates that the GonkBufferQueue will no longer be used to - // consume images buffers pushed to it using the IGraphicBufferProducer - // interface. It is initialized to false, and set to true in the abandon - // method. A GonkBufferQueue that has been abandoned will return the NO_INIT - // error from all IGonkConsumerBase methods capable of returning an error. - bool mAbandoned; - - // mName is a string used to identify the GonkConsumerBase in log messages. - // It can be set by the setName method. - String8 mName; - - // mFrameAvailableListener is the listener object that will be called when a - // new frame becomes available. If it is not NULL it will be called from - // queueBuffer. -#if ANDROID_VERSION == 17 - sp<FrameAvailableListener> mFrameAvailableListener; -#else - wp<FrameAvailableListener> mFrameAvailableListener; -#endif - - // The GonkConsumerBase has-a GonkBufferQueue and is responsible for creating this object - // if none is supplied - sp<GonkBufferQueue> mBufferQueue; - - // mMutex is the mutex used to prevent concurrent access to the member - // variables of GonkConsumerBase objects. It must be locked whenever the - // member variables are accessed or when any of the *Locked methods are - // called. - // - // This mutex is intended to be locked by derived classes. - mutable Mutex mMutex; -}; - -// ---------------------------------------------------------------------------- -}; // namespace android - -#endif // NATIVEWINDOW_GONKCONSUMERBASE_H diff --git a/widget/gonk/nativewindow/GonkConsumerBaseKK.cpp b/widget/gonk/nativewindow/GonkConsumerBaseKK.cpp deleted file mode 100644 index 3fc9fc16c..000000000 --- a/widget/gonk/nativewindow/GonkConsumerBaseKK.cpp +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * Copyright (C) 2013 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "GonkConsumerBase" -#define ATRACE_TAG ATRACE_TAG_GRAPHICS -//#define LOG_NDEBUG 0 - -#define EGL_EGLEXT_PROTOTYPES - -#include <hardware/hardware.h> - -#include <gui/IGraphicBufferAlloc.h> -#include <utils/Log.h> -#include <utils/String8.h> - -#include "GonkConsumerBaseKK.h" - -namespace android { - -// Get an ID that's unique within this process. -static int32_t createProcessUniqueId() { - static volatile int32_t globalCounter = 0; - return android_atomic_inc(&globalCounter); -} - -GonkConsumerBase::GonkConsumerBase(const sp<GonkBufferQueue>& bufferQueue, bool controlledByApp) : - mAbandoned(false), - mConsumer(bufferQueue) { - // Choose a name using the PID and a process-unique ID. - mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId()); - - // Note that we can't create an sp<...>(this) in a ctor that will not keep a - // reference once the ctor ends, as that would cause the refcount of 'this' - // dropping to 0 at the end of the ctor. Since all we need is a wp<...> - // that's what we create. - wp<ConsumerListener> listener = static_cast<ConsumerListener*>(this); - sp<IConsumerListener> proxy = new GonkBufferQueue::ProxyConsumerListener(listener); - - status_t err = mConsumer->consumerConnect(proxy, controlledByApp); - if (err != NO_ERROR) { - ALOGE("GonkConsumerBase: error connecting to GonkBufferQueue: %s (%d)", - strerror(-err), err); - } else { - mConsumer->setConsumerName(mName); - } -} - -GonkConsumerBase::~GonkConsumerBase() { - ALOGV("~GonkConsumerBase"); - Mutex::Autolock lock(mMutex); - - // Verify that abandon() has been called before we get here. This should - // be done by GonkConsumerBase::onLastStrongRef(), but it's possible for a - // derived class to override that method and not call - // GonkConsumerBase::onLastStrongRef(). - LOG_ALWAYS_FATAL_IF(!mAbandoned, "[%s] ~GonkConsumerBase was called, but the " - "consumer is not abandoned!", mName.string()); -} - -void GonkConsumerBase::onLastStrongRef(const void* id) { - abandon(); -} - -void GonkConsumerBase::freeBufferLocked(int slotIndex) { - ALOGV("freeBufferLocked: slotIndex=%d", slotIndex); - mSlots[slotIndex].mGraphicBuffer = 0; - mSlots[slotIndex].mFence = Fence::NO_FENCE; - mSlots[slotIndex].mFrameNumber = 0; -} - -// Used for refactoring, should not be in final interface -sp<GonkBufferQueue> GonkConsumerBase::getBufferQueue() const { - Mutex::Autolock lock(mMutex); - return mConsumer; -} - -void GonkConsumerBase::onFrameAvailable() { - ALOGV("onFrameAvailable"); - - sp<FrameAvailableListener> listener; - { // scope for the lock - Mutex::Autolock lock(mMutex); - listener = mFrameAvailableListener.promote(); - } - - if (listener != NULL) { - ALOGV("actually calling onFrameAvailable"); - listener->onFrameAvailable(); - } -} - -void GonkConsumerBase::onBuffersReleased() { - Mutex::Autolock lock(mMutex); - - ALOGV("onBuffersReleased"); - - if (mAbandoned) { - // Nothing to do if we're already abandoned. - return; - } - - uint32_t mask = 0; - mConsumer->getReleasedBuffers(&mask); - for (int i = 0; i < GonkBufferQueue::NUM_BUFFER_SLOTS; i++) { - if (mask & (1 << i)) { - freeBufferLocked(i); - } - } -} - -void GonkConsumerBase::abandon() { - ALOGV("abandon"); - Mutex::Autolock lock(mMutex); - - if (!mAbandoned) { - abandonLocked(); - mAbandoned = true; - } -} - -void GonkConsumerBase::abandonLocked() { - ALOGV("abandonLocked"); - for (int i =0; i < GonkBufferQueue::NUM_BUFFER_SLOTS; i++) { - freeBufferLocked(i); - } - // disconnect from the BufferQueue - mConsumer->consumerDisconnect(); - mConsumer.clear(); -} - -void GonkConsumerBase::setFrameAvailableListener( - const wp<FrameAvailableListener>& listener) { - ALOGV("setFrameAvailableListener"); - Mutex::Autolock lock(mMutex); - mFrameAvailableListener = listener; -} - -void GonkConsumerBase::dump(String8& result) const { - dump(result, ""); -} - -void GonkConsumerBase::dump(String8& result, const char* prefix) const { - Mutex::Autolock _l(mMutex); - dumpLocked(result, prefix); -} - -void GonkConsumerBase::dumpLocked(String8& result, const char* prefix) const { - result.appendFormat("%smAbandoned=%d\n", prefix, int(mAbandoned)); - - if (!mAbandoned) { - mConsumer->dumpToString(result, prefix); - } -} - -status_t GonkConsumerBase::acquireBufferLocked(IGonkGraphicBufferConsumer::BufferItem *item, - nsecs_t presentWhen) { - status_t err = mConsumer->acquireBuffer(item, presentWhen); - if (err != NO_ERROR) { - return err; - } - - if (item->mGraphicBuffer != NULL) { - mSlots[item->mBuf].mGraphicBuffer = item->mGraphicBuffer; - } - - mSlots[item->mBuf].mFrameNumber = item->mFrameNumber; - mSlots[item->mBuf].mFence = item->mFence; - - ALOGV("acquireBufferLocked: -> slot=%d", item->mBuf); - - return OK; -} - -status_t GonkConsumerBase::addReleaseFence(int slot, - const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence) { - Mutex::Autolock lock(mMutex); - return addReleaseFenceLocked(slot, graphicBuffer, fence); -} - -status_t GonkConsumerBase::addReleaseFenceLocked(int slot, - const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence) { - ALOGV("addReleaseFenceLocked: slot=%d", slot); - - // If consumer no longer tracks this graphicBuffer, we can safely - // drop this fence, as it will never be received by the producer. - if (!stillTracking(slot, graphicBuffer)) { - return OK; - } - - if (!mSlots[slot].mFence.get()) { - mSlots[slot].mFence = fence; - } else { - sp<Fence> mergedFence = Fence::merge( - String8::format("%.28s:%d", mName.string(), slot), - mSlots[slot].mFence, fence); - if (!mergedFence.get()) { - ALOGE("failed to merge release fences"); - // synchronization is broken, the best we can do is hope fences - // signal in order so the new fence will act like a union - mSlots[slot].mFence = fence; - return BAD_VALUE; - } - mSlots[slot].mFence = mergedFence; - } - - return OK; -} - -status_t GonkConsumerBase::releaseBufferLocked(int slot, const sp<GraphicBuffer> graphicBuffer) { - // If consumer no longer tracks this graphicBuffer (we received a new - // buffer on the same slot), the buffer producer is definitely no longer - // tracking it. - if (!stillTracking(slot, graphicBuffer)) { - return OK; - } - - ALOGV("releaseBufferLocked: slot=%d/%llu", - slot, mSlots[slot].mFrameNumber); - status_t err = mConsumer->releaseBuffer(slot, mSlots[slot].mFrameNumber, mSlots[slot].mFence); - if (err == GonkBufferQueue::STALE_BUFFER_SLOT) { - freeBufferLocked(slot); - } - - mSlots[slot].mFence = Fence::NO_FENCE; - - return err; -} - -bool GonkConsumerBase::stillTracking(int slot, - const sp<GraphicBuffer> graphicBuffer) { - if (slot < 0 || slot >= GonkBufferQueue::NUM_BUFFER_SLOTS) { - return false; - } - return (mSlots[slot].mGraphicBuffer != NULL && - mSlots[slot].mGraphicBuffer->handle == graphicBuffer->handle); -} - -} // namespace android diff --git a/widget/gonk/nativewindow/GonkConsumerBaseKK.h b/widget/gonk/nativewindow/GonkConsumerBaseKK.h deleted file mode 100644 index e198ad843..000000000 --- a/widget/gonk/nativewindow/GonkConsumerBaseKK.h +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * Copyright (C) 2013 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef NATIVEWINDOW_GONKCONSUMERBASE_KK_H -#define NATIVEWINDOW_GONKCONSUMERBASE_KK_H - -#include <ui/GraphicBuffer.h> - -#include <utils/String8.h> -#include <utils/Vector.h> -#include <utils/threads.h> -#include <gui/IConsumerListener.h> - -#include "GonkBufferQueueKK.h" - -namespace android { -// ---------------------------------------------------------------------------- - -class String8; - -// GonkConsumerBase is a base class for GonkBufferQueue consumer end-points. It -// handles common tasks like management of the connection to the GonkBufferQueue -// and the buffer pool. -class GonkConsumerBase : public virtual RefBase, - protected ConsumerListener { -public: - struct FrameAvailableListener : public virtual RefBase { - // onFrameAvailable() is called each time an additional frame becomes - // available for consumption. This means that frames that are queued - // while in asynchronous mode only trigger the callback if no previous - // frames are pending. Frames queued while in synchronous mode always - // trigger the callback. - // - // This is called without any lock held and can be called concurrently - // by multiple threads. - virtual void onFrameAvailable() = 0; - }; - - virtual ~GonkConsumerBase(); - - // abandon frees all the buffers and puts the GonkConsumerBase into the - // 'abandoned' state. Once put in this state the GonkConsumerBase can never - // leave it. When in the 'abandoned' state, all methods of the - // IGraphicBufferProducer interface will fail with the NO_INIT error. - // - // Note that while calling this method causes all the buffers to be freed - // from the perspective of the the GonkConsumerBase, if there are additional - // references on the buffers (e.g. if a buffer is referenced by a client - // or by OpenGL ES as a texture) then those buffer will remain allocated. - void abandon(); - - // set the name of the GonkConsumerBase that will be used to identify it in - // log messages. - void setName(const String8& name); - - // getBufferQueue returns the GonkBufferQueue object to which this - // GonkConsumerBase is connected. - sp<GonkBufferQueue> getBufferQueue() const; - - // dump writes the current state to a string. Child classes should add - // their state to the dump by overriding the dumpLocked method, which is - // called by these methods after locking the mutex. - void dump(String8& result) const; - void dump(String8& result, const char* prefix) const; - - // setFrameAvailableListener sets the listener object that will be notified - // when a new frame becomes available. - void setFrameAvailableListener(const wp<FrameAvailableListener>& listener); - -private: - GonkConsumerBase(const GonkConsumerBase&); - void operator=(const GonkConsumerBase&); - -protected: - - // GonkConsumerBase constructs a new GonkConsumerBase object to consume image - // buffers from the given GonkBufferQueue. - GonkConsumerBase(const sp<GonkBufferQueue>& bufferQueue, bool controlledByApp = false); - - // onLastStrongRef gets called by RefBase just before the dtor of the most - // derived class. It is used to clean up the buffers so that GonkConsumerBase - // can coordinate the clean-up by calling into virtual methods implemented - // by the derived classes. This would not be possible from the - // ConsuemrBase dtor because by the time that gets called the derived - // classes have already been destructed. - // - // This methods should not need to be overridden by derived classes, but - // if they are overridden the GonkConsumerBase implementation must be called - // from the derived class. - virtual void onLastStrongRef(const void* id); - - // Implementation of the GonkBufferQueue::ConsumerListener interface. These - // calls are used to notify the GonkConsumerBase of asynchronous events in the - // GonkBufferQueue. These methods should not need to be overridden by derived - // classes, but if they are overridden the GonkConsumerBase implementation - // must be called from the derived class. - virtual void onFrameAvailable(); - virtual void onBuffersReleased(); - - // freeBufferLocked frees up the given buffer slot. If the slot has been - // initialized this will release the reference to the GraphicBuffer in that - // slot. Otherwise it has no effect. - // - // Derived classes should override this method to clean up any state they - // keep per slot. If it is overridden, the derived class's implementation - // must call GonkConsumerBase::freeBufferLocked. - // - // This method must be called with mMutex locked. - virtual void freeBufferLocked(int slotIndex); - - // abandonLocked puts the GonkBufferQueue into the abandoned state, causing - // all future operations on it to fail. This method rather than the public - // abandon method should be overridden by child classes to add abandon- - // time behavior. - // - // Derived classes should override this method to clean up any object - // state they keep (as opposed to per-slot state). If it is overridden, - // the derived class's implementation must call GonkConsumerBase::abandonLocked. - // - // This method must be called with mMutex locked. - virtual void abandonLocked(); - - // dumpLocked dumps the current state of the GonkConsumerBase object to the - // result string. Each line is prefixed with the string pointed to by the - // prefix argument. The buffer argument points to a buffer that may be - // used for intermediate formatting data, and the size of that buffer is - // indicated by the size argument. - // - // Derived classes should override this method to dump their internal - // state. If this method is overridden the derived class's implementation - // should call GonkConsumerBase::dumpLocked. - // - // This method must be called with mMutex locked. - virtual void dumpLocked(String8& result, const char* prefix) const; - - // acquireBufferLocked fetches the next buffer from the GonkBufferQueue and - // updates the buffer slot for the buffer returned. - // - // Derived classes should override this method to perform any - // initialization that must take place the first time a buffer is assigned - // to a slot. If it is overridden the derived class's implementation must - // call GonkConsumerBase::acquireBufferLocked. - virtual status_t acquireBufferLocked(IGonkGraphicBufferConsumer::BufferItem *item, - nsecs_t presentWhen); - - // releaseBufferLocked relinquishes control over a buffer, returning that - // control to the GonkBufferQueue. - // - // Derived classes should override this method to perform any cleanup that - // must take place when a buffer is released back to the GonkBufferQueue. If - // it is overridden the derived class's implementation must call - // GonkConsumerBase::releaseBufferLocked. - virtual status_t releaseBufferLocked(int slot, const sp<GraphicBuffer> graphicBuffer); - - // returns true iff the slot still has the graphicBuffer in it. - bool stillTracking(int slot, const sp<GraphicBuffer> graphicBuffer); - - // addReleaseFence* adds the sync points associated with a fence to the set - // of sync points that must be reached before the buffer in the given slot - // may be used after the slot has been released. This should be called by - // derived classes each time some asynchronous work is kicked off that - // references the buffer. - status_t addReleaseFence(int slot, - const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence); - status_t addReleaseFenceLocked(int slot, - const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence); - - // Slot contains the information and object references that - // GonkConsumerBase maintains about a GonkBufferQueue buffer slot. - struct Slot { - // mGraphicBuffer is the Gralloc buffer store in the slot or NULL if - // no Gralloc buffer is in the slot. - sp<GraphicBuffer> mGraphicBuffer; - - // mFence is a fence which will signal when the buffer associated with - // this buffer slot is no longer being used by the consumer and can be - // overwritten. The buffer can be dequeued before the fence signals; - // the producer is responsible for delaying writes until it signals. - sp<Fence> mFence; - - // the frame number of the last acquired frame for this slot - uint64_t mFrameNumber; - }; - - // mSlots stores the buffers that have been allocated by the GonkBufferQueue - // for each buffer slot. It is initialized to null pointers, and gets - // filled in with the result of GonkBufferQueue::acquire when the - // client dequeues a buffer from a - // slot that has not yet been used. The buffer allocated to a slot will also - // be replaced if the requested buffer usage or geometry differs from that - // of the buffer allocated to a slot. - Slot mSlots[GonkBufferQueue::NUM_BUFFER_SLOTS]; - - // mAbandoned indicates that the GonkBufferQueue will no longer be used to - // consume images buffers pushed to it using the IGraphicBufferProducer - // interface. It is initialized to false, and set to true in the abandon - // method. A GonkBufferQueue that has been abandoned will return the NO_INIT - // error from all IGonkConsumerBase methods capable of returning an error. - bool mAbandoned; - - // mName is a string used to identify the GonkConsumerBase in log messages. - // It can be set by the setName method. - String8 mName; - - // mFrameAvailableListener is the listener object that will be called when a - // new frame becomes available. If it is not NULL it will be called from - // queueBuffer. - wp<FrameAvailableListener> mFrameAvailableListener; - - // The GonkConsumerBase has-a GonkBufferQueue and is responsible for creating this object - // if none is supplied - sp<GonkBufferQueue> mConsumer; - - // mMutex is the mutex used to prevent concurrent access to the member - // variables of GonkConsumerBase objects. It must be locked whenever the - // member variables are accessed or when any of the *Locked methods are - // called. - // - // This mutex is intended to be locked by derived classes. - mutable Mutex mMutex; -}; - -// ---------------------------------------------------------------------------- -}; // namespace android - -#endif // NATIVEWINDOW_GONKCONSUMERBASE_H diff --git a/widget/gonk/nativewindow/GonkConsumerBaseLL.cpp b/widget/gonk/nativewindow/GonkConsumerBaseLL.cpp deleted file mode 100644 index 5b1166b57..000000000 --- a/widget/gonk/nativewindow/GonkConsumerBaseLL.cpp +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * Copyright (C) 2014 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <inttypes.h> - -#define LOG_TAG "GonkConsumerBase" -#define ATRACE_TAG ATRACE_TAG_GRAPHICS -//#define LOG_NDEBUG 0 - -#define EGL_EGLEXT_PROTOTYPES - -#include <hardware/hardware.h> - -#include <gui/IGraphicBufferAlloc.h> - -#include <utils/Log.h> -#include <utils/String8.h> - -#include "GonkConsumerBaseLL.h" - -namespace android { - -// Get an ID that's unique within this process. -static int32_t createProcessUniqueId() { - static volatile int32_t globalCounter = 0; - return android_atomic_inc(&globalCounter); -} - -GonkConsumerBase::GonkConsumerBase(const sp<IGonkGraphicBufferConsumer>& bufferQueue, bool controlledByApp) : - mAbandoned(false), - mConsumer(bufferQueue) { - // Choose a name using the PID and a process-unique ID. - mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId()); - - // Note that we can't create an sp<...>(this) in a ctor that will not keep a - // reference once the ctor ends, as that would cause the refcount of 'this' - // dropping to 0 at the end of the ctor. Since all we need is a wp<...> - // that's what we create. - wp<ConsumerListener> listener = static_cast<ConsumerListener*>(this); - sp<IConsumerListener> proxy = new GonkBufferQueue::ProxyConsumerListener(listener); - - status_t err = mConsumer->consumerConnect(proxy, controlledByApp); - if (err != NO_ERROR) { - ALOGE("GonkConsumerBase: error connecting to GonkBufferQueue: %s (%d)", - strerror(-err), err); - } else { - mConsumer->setConsumerName(mName); - } -} - -GonkConsumerBase::~GonkConsumerBase() { - ALOGV("~GonkConsumerBase"); - Mutex::Autolock lock(mMutex); - - // Verify that abandon() has been called before we get here. This should - // be done by GonkConsumerBase::onLastStrongRef(), but it's possible for a - // derived class to override that method and not call - // GonkConsumerBase::onLastStrongRef(). - LOG_ALWAYS_FATAL_IF(!mAbandoned, "[%s] ~GonkConsumerBase was called, but the " - "consumer is not abandoned!", mName.string()); -} - -void GonkConsumerBase::onLastStrongRef(const void* id __attribute__((unused))) { - abandon(); -} - -void GonkConsumerBase::freeBufferLocked(int slotIndex) { - ALOGV("freeBufferLocked: slotIndex=%d", slotIndex); - mSlots[slotIndex].mGraphicBuffer = 0; - mSlots[slotIndex].mFence = Fence::NO_FENCE; - mSlots[slotIndex].mFrameNumber = 0; -} - -#if ANDROID_VERSION == 21 -void GonkConsumerBase::onFrameAvailable() { -#else -void GonkConsumerBase::onFrameAvailable(const ::android::BufferItem& item) { -#endif - ALOGV("onFrameAvailable"); - - sp<FrameAvailableListener> listener; - { // scope for the lock - Mutex::Autolock lock(mMutex); - listener = mFrameAvailableListener.promote(); - } - - if (listener != NULL) { - ALOGV("actually calling onFrameAvailable"); - listener->onFrameAvailable(); - } -} - -void GonkConsumerBase::onBuffersReleased() { - Mutex::Autolock lock(mMutex); - - ALOGV("onBuffersReleased"); - - if (mAbandoned) { - // Nothing to do if we're already abandoned. - return; - } - - uint64_t mask = 0; - mConsumer->getReleasedBuffers(&mask); - for (int i = 0; i < GonkBufferQueue::NUM_BUFFER_SLOTS; i++) { - if (mask & (1ULL << i)) { - freeBufferLocked(i); - } - } -} - -void GonkConsumerBase::onSidebandStreamChanged() { -} - -void GonkConsumerBase::abandon() { - ALOGV("abandon"); - Mutex::Autolock lock(mMutex); - - if (!mAbandoned) { - abandonLocked(); - mAbandoned = true; - } -} - -void GonkConsumerBase::abandonLocked() { - ALOGV("abandonLocked"); - for (int i =0; i < GonkBufferQueue::NUM_BUFFER_SLOTS; i++) { - freeBufferLocked(i); - } - // disconnect from the BufferQueue - mConsumer->consumerDisconnect(); - mConsumer.clear(); -} - -void GonkConsumerBase::setFrameAvailableListener( - const wp<FrameAvailableListener>& listener) { - ALOGV("setFrameAvailableListener"); - Mutex::Autolock lock(mMutex); - mFrameAvailableListener = listener; -} - -void GonkConsumerBase::dump(String8& result) const { - dump(result, ""); -} - -void GonkConsumerBase::dump(String8& result, const char* prefix) const { - Mutex::Autolock _l(mMutex); - dumpLocked(result, prefix); -} - -void GonkConsumerBase::dumpLocked(String8& result, const char* prefix) const { - result.appendFormat("%smAbandoned=%d\n", prefix, int(mAbandoned)); - - if (!mAbandoned) { - mConsumer->dumpToString(result, prefix); - } -} - -status_t GonkConsumerBase::acquireBufferLocked(GonkBufferQueue::BufferItem *item, - nsecs_t presentWhen) { - status_t err = mConsumer->acquireBuffer(item, presentWhen); - if (err != NO_ERROR) { - return err; - } - - if (item->mGraphicBuffer != NULL) { - mSlots[item->mBuf].mGraphicBuffer = item->mGraphicBuffer; - } - - mSlots[item->mBuf].mFrameNumber = item->mFrameNumber; - mSlots[item->mBuf].mFence = item->mFence; - - ALOGV("acquireBufferLocked: -> slot=%d/%" PRIu64, - item->mBuf, item->mFrameNumber); - - return OK; -} - -status_t GonkConsumerBase::addReleaseFence(int slot, - const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence) { - Mutex::Autolock lock(mMutex); - return addReleaseFenceLocked(slot, graphicBuffer, fence); -} - -status_t GonkConsumerBase::addReleaseFenceLocked(int slot, - const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence) { - ALOGV("addReleaseFenceLocked: slot=%d", slot); - - // If consumer no longer tracks this graphicBuffer, we can safely - // drop this fence, as it will never be received by the producer. - if (!stillTracking(slot, graphicBuffer)) { - return OK; - } - - if (!mSlots[slot].mFence.get()) { - mSlots[slot].mFence = fence; - } else { - sp<Fence> mergedFence = Fence::merge( - String8::format("%.28s:%d", mName.string(), slot), - mSlots[slot].mFence, fence); - if (!mergedFence.get()) { - ALOGE("failed to merge release fences"); - // synchronization is broken, the best we can do is hope fences - // signal in order so the new fence will act like a union - mSlots[slot].mFence = fence; - return BAD_VALUE; - } - mSlots[slot].mFence = mergedFence; - } - - return OK; -} - -status_t GonkConsumerBase::releaseBufferLocked(int slot, const sp<GraphicBuffer> graphicBuffer) { - // If consumer no longer tracks this graphicBuffer (we received a new - // buffer on the same slot), the buffer producer is definitely no longer - // tracking it. - if (!stillTracking(slot, graphicBuffer)) { - return OK; - } - - ALOGV("releaseBufferLocked: slot=%d/%" PRIu64, - slot, mSlots[slot].mFrameNumber); - status_t err = mConsumer->releaseBuffer(slot, mSlots[slot].mFrameNumber, mSlots[slot].mFence); - if (err == IGonkGraphicBufferConsumer::STALE_BUFFER_SLOT) { - freeBufferLocked(slot); - } - - mSlots[slot].mFence = Fence::NO_FENCE; - - return err; -} - -bool GonkConsumerBase::stillTracking(int slot, - const sp<GraphicBuffer> graphicBuffer) { - if (slot < 0 || slot >= GonkBufferQueue::NUM_BUFFER_SLOTS) { - return false; - } - return (mSlots[slot].mGraphicBuffer != NULL && - mSlots[slot].mGraphicBuffer->handle == graphicBuffer->handle); -} - -} // namespace android diff --git a/widget/gonk/nativewindow/GonkConsumerBaseLL.h b/widget/gonk/nativewindow/GonkConsumerBaseLL.h deleted file mode 100644 index 0b2c2d166..000000000 --- a/widget/gonk/nativewindow/GonkConsumerBaseLL.h +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * Copyright (C) 2014 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef NATIVEWINDOW_GONKCONSUMERBASE_LL_H -#define NATIVEWINDOW_GONKCONSUMERBASE_LL_H - -#include <ui/GraphicBuffer.h> - -#include <utils/String8.h> -#include <utils/Vector.h> -#include <utils/threads.h> -#include <gui/IConsumerListener.h> - -#include "GonkBufferQueueLL.h" - -namespace android { -// ---------------------------------------------------------------------------- - -class String8; - -// GonkConsumerBase is a base class for GonkBufferQueue consumer end-points. It -// handles common tasks like management of the connection to the GonkBufferQueue -// and the buffer pool. -class GonkConsumerBase : public virtual RefBase, - protected ConsumerListener { -public: - struct FrameAvailableListener : public virtual RefBase { - // onFrameAvailable() is called each time an additional frame becomes - // available for consumption. This means that frames that are queued - // while in asynchronous mode only trigger the callback if no previous - // frames are pending. Frames queued while in synchronous mode always - // trigger the callback. - // - // This is called without any lock held and can be called concurrently - // by multiple threads. - virtual void onFrameAvailable() = 0; - }; - - virtual ~GonkConsumerBase(); - - // abandon frees all the buffers and puts the GonkConsumerBase into the - // 'abandoned' state. Once put in this state the GonkConsumerBase can never - // leave it. When in the 'abandoned' state, all methods of the - // IGraphicBufferProducer interface will fail with the NO_INIT error. - // - // Note that while calling this method causes all the buffers to be freed - // from the perspective of the the GonkConsumerBase, if there are additional - // references on the buffers (e.g. if a buffer is referenced by a client - // or by OpenGL ES as a texture) then those buffer will remain allocated. - void abandon(); - - // set the name of the GonkConsumerBase that will be used to identify it in - // log messages. - void setName(const String8& name); - - // dump writes the current state to a string. Child classes should add - // their state to the dump by overriding the dumpLocked method, which is - // called by these methods after locking the mutex. - void dump(String8& result) const; - void dump(String8& result, const char* prefix) const; - - // setFrameAvailableListener sets the listener object that will be notified - // when a new frame becomes available. - void setFrameAvailableListener(const wp<FrameAvailableListener>& listener); - -private: - GonkConsumerBase(const GonkConsumerBase&); - void operator=(const GonkConsumerBase&); - -protected: - // GonkConsumerBase constructs a new GonkConsumerBase object to consume image - // buffers from the given IGonkGraphicBufferConsumer. - // The controlledByApp flag indicates that this consumer is under the application's - // control. - GonkConsumerBase(const sp<IGonkGraphicBufferConsumer>& consumer, bool controlledByApp = false); - - // onLastStrongRef gets called by RefBase just before the dtor of the most - // derived class. It is used to clean up the buffers so that GonkConsumerBase - // can coordinate the clean-up by calling into virtual methods implemented - // by the derived classes. This would not be possible from the - // ConsuemrBase dtor because by the time that gets called the derived - // classes have already been destructed. - // - // This methods should not need to be overridden by derived classes, but - // if they are overridden the GonkConsumerBase implementation must be called - // from the derived class. - virtual void onLastStrongRef(const void* id); - - // Implementation of the IConsumerListener interface. These - // calls are used to notify the GonkConsumerBase of asynchronous events in the - // GonkBufferQueue. The onFrameAvailable and onBuffersReleased methods should - // not need to be overridden by derived classes, but if they are overridden - // the GonkConsumerBase implementation must be called from the derived class. - // The GonkConsumerBase version of onSidebandStreamChanged does nothing and can - // be overriden by derived classes if they want the notification. -#if ANDROID_VERSION == 21 - virtual void onFrameAvailable(); -#else - virtual void onFrameAvailable(const ::android::BufferItem& item); - virtual void onFrameReplaced(const ::android::BufferItem& item) {}; -#endif - virtual void onBuffersReleased(); - virtual void onSidebandStreamChanged(); - - // freeBufferLocked frees up the given buffer slot. If the slot has been - // initialized this will release the reference to the GraphicBuffer in that - // slot. Otherwise it has no effect. - // - // Derived classes should override this method to clean up any state they - // keep per slot. If it is overridden, the derived class's implementation - // must call GonkConsumerBase::freeBufferLocked. - // - // This method must be called with mMutex locked. - virtual void freeBufferLocked(int slotIndex); - - // abandonLocked puts the GonkBufferQueue into the abandoned state, causing - // all future operations on it to fail. This method rather than the public - // abandon method should be overridden by child classes to add abandon- - // time behavior. - // - // Derived classes should override this method to clean up any object - // state they keep (as opposed to per-slot state). If it is overridden, - // the derived class's implementation must call GonkConsumerBase::abandonLocked. - // - // This method must be called with mMutex locked. - virtual void abandonLocked(); - - // dumpLocked dumps the current state of the GonkConsumerBase object to the - // result string. Each line is prefixed with the string pointed to by the - // prefix argument. The buffer argument points to a buffer that may be - // used for intermediate formatting data, and the size of that buffer is - // indicated by the size argument. - // - // Derived classes should override this method to dump their internal - // state. If this method is overridden the derived class's implementation - // should call GonkConsumerBase::dumpLocked. - // - // This method must be called with mMutex locked. - virtual void dumpLocked(String8& result, const char* prefix) const; - - // acquireBufferLocked fetches the next buffer from the GonkBufferQueue and - // updates the buffer slot for the buffer returned. - // - // Derived classes should override this method to perform any - // initialization that must take place the first time a buffer is assigned - // to a slot. If it is overridden the derived class's implementation must - // call GonkConsumerBase::acquireBufferLocked. - virtual status_t acquireBufferLocked(IGonkGraphicBufferConsumer::BufferItem *item, - nsecs_t presentWhen); - - // releaseBufferLocked relinquishes control over a buffer, returning that - // control to the GonkBufferQueue. - // - // Derived classes should override this method to perform any cleanup that - // must take place when a buffer is released back to the GonkBufferQueue. If - // it is overridden the derived class's implementation must call - // GonkConsumerBase::releaseBufferLocked. - virtual status_t releaseBufferLocked(int slot, const sp<GraphicBuffer> graphicBuffer); - - // returns true iff the slot still has the graphicBuffer in it. - bool stillTracking(int slot, const sp<GraphicBuffer> graphicBuffer); - - // addReleaseFence* adds the sync points associated with a fence to the set - // of sync points that must be reached before the buffer in the given slot - // may be used after the slot has been released. This should be called by - // derived classes each time some asynchronous work is kicked off that - // references the buffer. - status_t addReleaseFence(int slot, - const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence); - status_t addReleaseFenceLocked(int slot, - const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence); - - // Slot contains the information and object references that - // GonkConsumerBase maintains about a GonkBufferQueue buffer slot. - struct Slot { - // mGraphicBuffer is the Gralloc buffer store in the slot or NULL if - // no Gralloc buffer is in the slot. - sp<GraphicBuffer> mGraphicBuffer; - - // mFence is a fence which will signal when the buffer associated with - // this buffer slot is no longer being used by the consumer and can be - // overwritten. The buffer can be dequeued before the fence signals; - // the producer is responsible for delaying writes until it signals. - sp<Fence> mFence; - - // the frame number of the last acquired frame for this slot - uint64_t mFrameNumber; - }; - - // mSlots stores the buffers that have been allocated by the GonkBufferQueue - // for each buffer slot. It is initialized to null pointers, and gets - // filled in with the result of GonkBufferQueue::acquire when the - // client dequeues a buffer from a - // slot that has not yet been used. The buffer allocated to a slot will also - // be replaced if the requested buffer usage or geometry differs from that - // of the buffer allocated to a slot. - Slot mSlots[GonkBufferQueue::NUM_BUFFER_SLOTS]; - - // mAbandoned indicates that the GonkBufferQueue will no longer be used to - // consume images buffers pushed to it using the IGraphicBufferProducer - // interface. It is initialized to false, and set to true in the abandon - // method. A GonkBufferQueue that has been abandoned will return the NO_INIT - // error from all IConsumerBase methods capable of returning an error. - bool mAbandoned; - - // mName is a string used to identify the GonkConsumerBase in log messages. - // It can be set by the setName method. - String8 mName; - - // mFrameAvailableListener is the listener object that will be called when a - // new frame becomes available. If it is not NULL it will be called from - // queueBuffer. - wp<FrameAvailableListener> mFrameAvailableListener; - - // The GonkConsumerBase has-a GonkBufferQueue and is responsible for creating this object - // if none is supplied - sp<IGonkGraphicBufferConsumer> mConsumer; - - // mMutex is the mutex used to prevent concurrent access to the member - // variables of GonkConsumerBase objects. It must be locked whenever the - // member variables are accessed or when any of the *Locked methods are - // called. - // - // This mutex is intended to be locked by derived classes. - mutable Mutex mMutex; -}; - -// ---------------------------------------------------------------------------- -}; // namespace android - -#endif // NATIVEWINDOW_GONKCONSUMERBASE_LL_H diff --git a/widget/gonk/nativewindow/GonkNativeWindow.h b/widget/gonk/nativewindow/GonkNativeWindow.h deleted file mode 100644 index 61b6780b8..000000000 --- a/widget/gonk/nativewindow/GonkNativeWindow.h +++ /dev/null @@ -1,22 +0,0 @@ -/* Copyright 2013 Mozilla Foundation and Mozilla contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 21 -# include "GonkNativeWindowLL.h" -#elif defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 19 -# include "GonkNativeWindowKK.h" -#elif defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17 -# include "GonkNativeWindowJB.h" -#endif diff --git a/widget/gonk/nativewindow/GonkNativeWindowJB.cpp b/widget/gonk/nativewindow/GonkNativeWindowJB.cpp deleted file mode 100644 index e38642009..000000000 --- a/widget/gonk/nativewindow/GonkNativeWindowJB.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * Copyright (C) 2013 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -//#define LOG_NDEBUG 0 -#define LOG_TAG "GonkNativeWindow" -#define ATRACE_TAG ATRACE_TAG_GRAPHICS -#include <utils/Log.h> - -#include "GonkNativeWindowJB.h" -#include "GrallocImages.h" -#include "mozilla/layers/ImageBridgeChild.h" -#include "mozilla/RefPtr.h" - -#define BI_LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__) -#define BI_LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) -#define BI_LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) -#define BI_LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__) -#define BI_LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) - -using namespace mozilla; -using namespace mozilla::layers; - -namespace android { - -GonkNativeWindow::GonkNativeWindow(int bufferCount) : - GonkConsumerBase(new GonkBufferQueue(true) ), - mNewFrameCallback(nullptr) -{ - mBufferQueue->setMaxAcquiredBufferCount(bufferCount); -} - -GonkNativeWindow::~GonkNativeWindow() { -} - -void GonkNativeWindow::setName(const String8& name) { - Mutex::Autolock _l(mMutex); - mName = name; - mBufferQueue->setConsumerName(name); -} -#if ANDROID_VERSION >= 18 -status_t GonkNativeWindow::acquireBuffer(BufferItem *item, bool waitForFence) { - status_t err; - - if (!item) return BAD_VALUE; - - Mutex::Autolock _l(mMutex); - - err = acquireBufferLocked(item); - if (err != OK) { - if (err != NO_BUFFER_AVAILABLE) { - BI_LOGE("Error acquiring buffer: %s (%d)", strerror(err), err); - } - return err; - } - - if (waitForFence) { - err = item->mFence->waitForever("GonkNativeWindow::acquireBuffer"); - if (err != OK) { - BI_LOGE("Failed to wait for fence of acquired buffer: %s (%d)", - strerror(-err), err); - return err; - } - } - - item->mGraphicBuffer = mSlots[item->mBuf].mGraphicBuffer; - - return OK; -} - -status_t GonkNativeWindow::releaseBuffer(const BufferItem &item, - const sp<Fence>& releaseFence) { - status_t err; - - Mutex::Autolock _l(mMutex); - - err = addReleaseFenceLocked(item.mBuf, releaseFence); - - err = releaseBufferLocked(item.mBuf); - if (err != OK) { - BI_LOGE("Failed to release buffer: %s (%d)", - strerror(-err), err); - } - return err; -} -#endif - -status_t GonkNativeWindow::setDefaultBufferSize(uint32_t w, uint32_t h) { - Mutex::Autolock _l(mMutex); - return mBufferQueue->setDefaultBufferSize(w, h); -} - -status_t GonkNativeWindow::setDefaultBufferFormat(uint32_t defaultFormat) { - Mutex::Autolock _l(mMutex); - return mBufferQueue->setDefaultBufferFormat(defaultFormat); -} - -already_AddRefed<TextureClient> -GonkNativeWindow::getCurrentBuffer() { - Mutex::Autolock _l(mMutex); - GonkBufferQueue::BufferItem item; - - // In asynchronous mode the list is guaranteed to be one buffer - // deep, while in synchronous mode we use the oldest buffer. - status_t err = acquireBufferLocked(&item); - if (err != NO_ERROR) { - return NULL; - } - - RefPtr<TextureClient> textureClient = - mBufferQueue->getTextureClientFromBuffer(item.mGraphicBuffer.get()); - if (!textureClient) { - return NULL; - } - textureClient->SetRecycleCallback(GonkNativeWindow::RecycleCallback, this); - return textureClient.forget(); -} - -/* static */ void -GonkNativeWindow::RecycleCallback(TextureClient* client, void* closure) { - GonkNativeWindow* nativeWindow = - static_cast<GonkNativeWindow*>(closure); - - MOZ_ASSERT(client && !client->IsDead()); - client->ClearRecycleCallback(); - nativeWindow->returnBuffer(client); -} - -void GonkNativeWindow::returnBuffer(TextureClient* client) { - BI_LOGD("GonkNativeWindow::returnBuffer"); - Mutex::Autolock lock(mMutex); - - int index = mBufferQueue->getSlotFromTextureClientLocked(client); - if (index < 0) { - } - - FenceHandle handle = client->GetAndResetReleaseFenceHandle(); - RefPtr<FenceHandle::FdObj> fdObj = handle.GetAndResetFdObj(); - sp<Fence> fence = new Fence(fdObj->GetAndResetFd()); - - addReleaseFenceLocked(index, fence); - - releaseBufferLocked(index); -} - -already_AddRefed<TextureClient> -GonkNativeWindow::getTextureClientFromBuffer(ANativeWindowBuffer* buffer) { - Mutex::Autolock lock(mMutex); - return mBufferQueue->getTextureClientFromBuffer(buffer); -} - -void GonkNativeWindow::setNewFrameCallback( - GonkNativeWindowNewFrameCallback* callback) { - BI_LOGD("setNewFrameCallback"); - Mutex::Autolock lock(mMutex); - mNewFrameCallback = callback; -} - -void GonkNativeWindow::onFrameAvailable() { - GonkConsumerBase::onFrameAvailable(); - - if (mNewFrameCallback) { - mNewFrameCallback->OnNewFrame(); - } -} - -} // namespace android diff --git a/widget/gonk/nativewindow/GonkNativeWindowJB.h b/widget/gonk/nativewindow/GonkNativeWindowJB.h deleted file mode 100644 index e63a7527d..000000000 --- a/widget/gonk/nativewindow/GonkNativeWindowJB.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * Copyright (C) 2013 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef NATIVEWINDOW_GONKNATIVEWINDOW_JB_H -#define NATIVEWINDOW_GONKNATIVEWINDOW_JB_H - -#include <ui/GraphicBuffer.h> -#include <utils/String8.h> -#include <utils/Vector.h> -#include <utils/threads.h> - -#include "GonkConsumerBaseJB.h" -#include "GrallocImages.h" -#include "mozilla/layers/LayersSurfaces.h" - -namespace mozilla { -namespace layers { - class PGrallocBufferChild; -} -} - -namespace android { - -// The user of GonkNativeWindow who wants to receive notification of -// new frames should implement this interface. -class GonkNativeWindowNewFrameCallback { -public: - virtual void OnNewFrame() = 0; -}; - -/** - * GonkNativeWindow is a GonkBufferQueue consumer endpoint that allows clients - * access to the whole BufferItem entry from GonkBufferQueue. Multiple buffers may - * be acquired at once, to be used concurrently by the client. This consumer can - * operate either in synchronous or asynchronous mode. - */ -class GonkNativeWindow: public GonkConsumerBase -{ - typedef mozilla::layers::TextureClient TextureClient; - public: - typedef GonkConsumerBase::FrameAvailableListener FrameAvailableListener; - - typedef GonkBufferQueue::BufferItem BufferItem; - - enum { INVALID_BUFFER_SLOT = GonkBufferQueue::INVALID_BUFFER_SLOT }; - enum { NO_BUFFER_AVAILABLE = GonkBufferQueue::NO_BUFFER_AVAILABLE }; - - // Create a new buffer item consumer. The consumerUsage parameter determines - // the consumer usage flags passed to the graphics allocator. The - // bufferCount parameter specifies how many buffers can be locked for user - // access at the same time. - GonkNativeWindow(int bufferCount = GonkBufferQueue::MIN_UNDEQUEUED_BUFFERS); - - virtual ~GonkNativeWindow(); - - // set the name of the GonkNativeWindow that will be used to identify it in - // log messages. - void setName(const String8& name); - - // Gets the next graphics buffer from the producer, filling out the - // passed-in BufferItem structure. Returns NO_BUFFER_AVAILABLE if the queue - // of buffers is empty, and INVALID_OPERATION if the maximum number of - // buffers is already acquired. - // - // Only a fixed number of buffers can be acquired at a time, determined by - // the construction-time bufferCount parameter. If INVALID_OPERATION is - // returned by acquireBuffer, then old buffers must be returned to the - // queue by calling releaseBuffer before more buffers can be acquired. - // - // If waitForFence is true, and the acquired BufferItem has a valid fence object, - // acquireBuffer will wait on the fence with no timeout before returning. -#if ANDROID_VERSION >= 18 - status_t acquireBuffer(BufferItem *item, bool waitForFence = true); -#endif - // Returns an acquired buffer to the queue, allowing it to be reused. Since - // only a fixed number of buffers may be acquired at a time, old buffers - // must be released by calling releaseBuffer to ensure new buffers can be - // acquired by acquireBuffer. Once a BufferItem is released, the caller must - // not access any members of the BufferItem, and should immediately remove - // all of its references to the BufferItem itself. -#if ANDROID_VERSION >= 18 - status_t releaseBuffer(const BufferItem &item, - const sp<Fence>& releaseFence = Fence::NO_FENCE); -#endif - - sp<IGraphicBufferProducer> getProducerInterface() const { return getBufferQueue(); } - - // setDefaultBufferSize is used to set the size of buffers returned by - // requestBuffers when a with and height of zero is requested. - status_t setDefaultBufferSize(uint32_t w, uint32_t h); - - // setDefaultBufferFormat allows the BufferQueue to create - // GraphicBuffers of a defaultFormat if no format is specified - // in dequeueBuffer - status_t setDefaultBufferFormat(uint32_t defaultFormat); - - // Get next frame from the queue, caller owns the returned buffer. - already_AddRefed<TextureClient> getCurrentBuffer(); - - // Return the buffer to the queue and mark it as FREE. After that - // the buffer is useable again for the decoder. - void returnBuffer(TextureClient* client); - - already_AddRefed<TextureClient> getTextureClientFromBuffer(ANativeWindowBuffer* buffer); - - void setNewFrameCallback(GonkNativeWindowNewFrameCallback* callback); - - static void RecycleCallback(TextureClient* client, void* closure); - -protected: - virtual void onFrameAvailable(); - -private: - GonkNativeWindowNewFrameCallback* mNewFrameCallback; -}; - -} // namespace android - -#endif // NATIVEWINDOW_GONKNATIVEWINDOW_JB_H diff --git a/widget/gonk/nativewindow/GonkNativeWindowKK.cpp b/widget/gonk/nativewindow/GonkNativeWindowKK.cpp deleted file mode 100644 index cf34d6539..000000000 --- a/widget/gonk/nativewindow/GonkNativeWindowKK.cpp +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * Copyright (C) 2013 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -//#define LOG_NDEBUG 0 -#define LOG_TAG "GonkNativeWindow" -#define ATRACE_TAG ATRACE_TAG_GRAPHICS -#include <utils/Log.h> - -#include "GonkNativeWindowKK.h" -#include "GrallocImages.h" - -using namespace mozilla; -using namespace mozilla::layers; - -namespace android { - -GonkNativeWindow::GonkNativeWindow(int bufferCount) : - GonkConsumerBase(new GonkBufferQueue(true), false), - mNewFrameCallback(nullptr) -{ - mConsumer->setMaxAcquiredBufferCount(bufferCount); -} - -GonkNativeWindow::GonkNativeWindow(const sp<GonkBufferQueue>& bq, - uint32_t consumerUsage, int bufferCount, bool controlledByApp) : - GonkConsumerBase(bq, controlledByApp) -{ - mConsumer->setConsumerUsageBits(consumerUsage); - mConsumer->setMaxAcquiredBufferCount(bufferCount); -} - -GonkNativeWindow::~GonkNativeWindow() { -} - -void GonkNativeWindow::setName(const String8& name) { - Mutex::Autolock _l(mMutex); - mName = name; - mConsumer->setConsumerName(name); -} - -status_t GonkNativeWindow::acquireBuffer(BufferItem *item, - nsecs_t presentWhen, bool waitForFence) { - status_t err; - - if (!item) return BAD_VALUE; - - Mutex::Autolock _l(mMutex); - - err = acquireBufferLocked(item, presentWhen); - if (err != OK) { - if (err != NO_BUFFER_AVAILABLE) { - ALOGE("Error acquiring buffer: %s (%d)", strerror(err), err); - } - return err; - } - - if (waitForFence) { - err = item->mFence->waitForever("GonkNativeWindow::acquireBuffer"); - if (err != OK) { - ALOGE("Failed to wait for fence of acquired buffer: %s (%d)", - strerror(-err), err); - return err; - } - } - - item->mGraphicBuffer = mSlots[item->mBuf].mGraphicBuffer; - - return OK; -} - -status_t GonkNativeWindow::releaseBuffer(const BufferItem &item, - const sp<Fence>& releaseFence) { - status_t err; - - Mutex::Autolock _l(mMutex); - - err = addReleaseFenceLocked(item.mBuf, item.mGraphicBuffer, releaseFence); - - err = releaseBufferLocked(item.mBuf, item.mGraphicBuffer); - if (err != OK) { - ALOGE("Failed to release buffer: %s (%d)", - strerror(-err), err); - } - return err; -} - -status_t GonkNativeWindow::setDefaultBufferSize(uint32_t w, uint32_t h) { - Mutex::Autolock _l(mMutex); - return mConsumer->setDefaultBufferSize(w, h); -} - -status_t GonkNativeWindow::setDefaultBufferFormat(uint32_t defaultFormat) { - Mutex::Autolock _l(mMutex); - return mConsumer->setDefaultBufferFormat(defaultFormat); -} - -already_AddRefed<TextureClient> -GonkNativeWindow::getCurrentBuffer() { - Mutex::Autolock _l(mMutex); - BufferItem item; - - // In asynchronous mode the list is guaranteed to be one buffer - // deep, while in synchronous mode we use the oldest buffer. - status_t err = acquireBufferLocked(&item, 0); //??? - if (err != NO_ERROR) { - return NULL; - } - - RefPtr<TextureClient> textureClient = - mConsumer->getTextureClientFromBuffer(item.mGraphicBuffer.get()); - if (!textureClient) { - return NULL; - } - textureClient->SetRecycleCallback(GonkNativeWindow::RecycleCallback, this); - return textureClient.forget(); -} - -/* static */ void -GonkNativeWindow::RecycleCallback(TextureClient* client, void* closure) { - GonkNativeWindow* nativeWindow = - static_cast<GonkNativeWindow*>(closure); - - MOZ_ASSERT(client && !client->IsDead()); - client->ClearRecycleCallback(); - nativeWindow->returnBuffer(client); -} - -void GonkNativeWindow::returnBuffer(TextureClient* client) { - ALOGD("GonkNativeWindow::returnBuffer"); - Mutex::Autolock lock(mMutex); - - int index = mConsumer->getSlotFromTextureClientLocked(client); - if (index < 0) { - } - - FenceHandle handle = client->GetAndResetReleaseFenceHandle(); - RefPtr<FenceHandle::FdObj> fdObj = handle.GetAndResetFdObj(); - sp<Fence> fence = new Fence(fdObj->GetAndResetFd()); - - addReleaseFenceLocked(index, - mSlots[index].mGraphicBuffer, - fence); - - releaseBufferLocked(index, mSlots[index].mGraphicBuffer); -} - -already_AddRefed<TextureClient> -GonkNativeWindow::getTextureClientFromBuffer(ANativeWindowBuffer* buffer) { - Mutex::Autolock lock(mMutex); - return mConsumer->getTextureClientFromBuffer(buffer); -} - -void GonkNativeWindow::setNewFrameCallback( - GonkNativeWindowNewFrameCallback* callback) { - ALOGD("setNewFrameCallback"); - Mutex::Autolock lock(mMutex); - mNewFrameCallback = callback; -} - -void GonkNativeWindow::onFrameAvailable() { - GonkConsumerBase::onFrameAvailable(); - - if (mNewFrameCallback) { - mNewFrameCallback->OnNewFrame(); - } -} - -} // namespace android diff --git a/widget/gonk/nativewindow/GonkNativeWindowKK.h b/widget/gonk/nativewindow/GonkNativeWindowKK.h deleted file mode 100644 index e36788b41..000000000 --- a/widget/gonk/nativewindow/GonkNativeWindowKK.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * Copyright (C) 2013 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef NATIVEWINDOW_GONKNATIVEWINDOW_KK_H -#define NATIVEWINDOW_GONKNATIVEWINDOW_KK_H - -#include <ui/GraphicBuffer.h> -#include <utils/String8.h> -#include <utils/Vector.h> -#include <utils/threads.h> - -#include "GonkConsumerBaseKK.h" -#include "GrallocImages.h" -#include "IGonkGraphicBufferConsumer.h" -#include "mozilla/layers/ImageBridgeChild.h" -#include "mozilla/layers/LayersSurfaces.h" - -namespace mozilla { -namespace layers { - class PGrallocBufferChild; -} -} - -namespace android { - -// The user of GonkNativeWindow who wants to receive notification of -// new frames should implement this interface. -class GonkNativeWindowNewFrameCallback { -public: - virtual void OnNewFrame() = 0; -}; - -/** - * GonkNativeWindow is a GonkBufferQueue consumer endpoint that allows clients - * access to the whole BufferItem entry from GonkBufferQueue. Multiple buffers may - * be acquired at once, to be used concurrently by the client. This consumer can - * operate either in synchronous or asynchronous mode. - */ -class GonkNativeWindow: public GonkConsumerBase -{ - typedef mozilla::layers::TextureClient TextureClient; - public: - typedef GonkConsumerBase::FrameAvailableListener FrameAvailableListener; - typedef IGonkGraphicBufferConsumer::BufferItem BufferItem; - - enum { INVALID_BUFFER_SLOT = GonkBufferQueue::INVALID_BUFFER_SLOT }; - enum { NO_BUFFER_AVAILABLE = GonkBufferQueue::NO_BUFFER_AVAILABLE }; - - // Create a new buffer item consumer. The consumerUsage parameter determines - // the consumer usage flags passed to the graphics allocator. The - // bufferCount parameter specifies how many buffers can be locked for user - // access at the same time. - // controlledByApp tells whether this consumer is controlled by the - // application. - GonkNativeWindow(int bufferCount = GonkBufferQueue::MIN_UNDEQUEUED_BUFFERS); - GonkNativeWindow(const sp<GonkBufferQueue>& bq, uint32_t consumerUsage, - int bufferCount = GonkBufferQueue::MIN_UNDEQUEUED_BUFFERS, - bool controlledByApp = false); - - virtual ~GonkNativeWindow(); - - // set the name of the GonkNativeWindow that will be used to identify it in - // log messages. - void setName(const String8& name); - - // Gets the next graphics buffer from the producer, filling out the - // passed-in BufferItem structure. Returns NO_BUFFER_AVAILABLE if the queue - // of buffers is empty, and INVALID_OPERATION if the maximum number of - // buffers is already acquired. - // - // Only a fixed number of buffers can be acquired at a time, determined by - // the construction-time bufferCount parameter. If INVALID_OPERATION is - // returned by acquireBuffer, then old buffers must be returned to the - // queue by calling releaseBuffer before more buffers can be acquired. - // - // If waitForFence is true, and the acquired BufferItem has a valid fence object, - // acquireBuffer will wait on the fence with no timeout before returning. - status_t acquireBuffer(BufferItem *item, nsecs_t presentWhen, - bool waitForFence = true); - - // Returns an acquired buffer to the queue, allowing it to be reused. Since - // only a fixed number of buffers may be acquired at a time, old buffers - // must be released by calling releaseBuffer to ensure new buffers can be - // acquired by acquireBuffer. Once a BufferItem is released, the caller must - // not access any members of the BufferItem, and should immediately remove - // all of its references to the BufferItem itself. - status_t releaseBuffer(const BufferItem &item, - const sp<Fence>& releaseFence = Fence::NO_FENCE); - - // setDefaultBufferSize is used to set the size of buffers returned by - // requestBuffers when a with and height of zero is requested. - status_t setDefaultBufferSize(uint32_t w, uint32_t h); - - // setDefaultBufferFormat allows the BufferQueue to create - // GraphicBuffers of a defaultFormat if no format is specified - // in dequeueBuffer - status_t setDefaultBufferFormat(uint32_t defaultFormat); - - // Get next frame from the queue, caller owns the returned buffer. - already_AddRefed<TextureClient> getCurrentBuffer(); - - // Return the buffer to the queue and mark it as FREE. After that - // the buffer is useable again for the decoder. - void returnBuffer(TextureClient* client); - - already_AddRefed<TextureClient> getTextureClientFromBuffer(ANativeWindowBuffer* buffer); - - void setNewFrameCallback(GonkNativeWindowNewFrameCallback* callback); - - static void RecycleCallback(TextureClient* client, void* closure); - -protected: - virtual void onFrameAvailable(); - -private: - GonkNativeWindowNewFrameCallback* mNewFrameCallback; -}; - -} // namespace android - -#endif // NATIVEWINDOW_GONKNATIVEWINDOW_JB_H diff --git a/widget/gonk/nativewindow/GonkNativeWindowLL.cpp b/widget/gonk/nativewindow/GonkNativeWindowLL.cpp deleted file mode 100644 index 48644a22f..000000000 --- a/widget/gonk/nativewindow/GonkNativeWindowLL.cpp +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * Copyright (C) 2014 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -//#define LOG_NDEBUG 0 -#define LOG_TAG "GonkNativeWindow" -#define ATRACE_TAG ATRACE_TAG_GRAPHICS -#include <utils/Log.h> - -#include "GonkNativeWindowLL.h" - -using namespace mozilla; -using namespace mozilla::layers; - -namespace android { - -GonkNativeWindow::GonkNativeWindow( - const sp<IGonkGraphicBufferConsumer>& consumer, int bufferCount) : - GonkConsumerBase(consumer, false), - mNewFrameCallback(nullptr) -{ - if (bufferCount != DEFAULT_MAX_BUFFERS) { - status_t err = mConsumer->setMaxAcquiredBufferCount(bufferCount); - LOG_ALWAYS_FATAL_IF(err != OK, - "Failed to set max acquired buffer count to %d", bufferCount); - } -} - -GonkNativeWindow::GonkNativeWindow( - const sp<IGonkGraphicBufferConsumer>& consumer, uint32_t consumerUsage, - int bufferCount, bool controlledByApp) : - GonkConsumerBase(consumer, controlledByApp) -{ - status_t err = mConsumer->setConsumerUsageBits(consumerUsage); - LOG_ALWAYS_FATAL_IF(err != OK, - "Failed to set consumer usage bits to %#x", consumerUsage); - if (bufferCount != DEFAULT_MAX_BUFFERS) { - err = mConsumer->setMaxAcquiredBufferCount(bufferCount); - LOG_ALWAYS_FATAL_IF(err != OK, - "Failed to set max acquired buffer count to %d", bufferCount); - } -} - -GonkNativeWindow::~GonkNativeWindow() { -} - -void GonkNativeWindow::setName(const String8& name) { - Mutex::Autolock _l(mMutex); - mName = name; - mConsumer->setConsumerName(name); -} - -status_t GonkNativeWindow::acquireBuffer(BufferItem *item, - nsecs_t presentWhen, bool waitForFence) { - status_t err; - - if (!item) return BAD_VALUE; - - Mutex::Autolock _l(mMutex); - - err = acquireBufferLocked(item, presentWhen); - if (err != OK) { - if (err != NO_BUFFER_AVAILABLE) { - ALOGE("Error acquiring buffer: %s (%d)", strerror(err), err); - } - return err; - } - - if (waitForFence) { - err = item->mFence->waitForever("GonkNativeWindow::acquireBuffer"); - if (err != OK) { - ALOGE("Failed to wait for fence of acquired buffer: %s (%d)", - strerror(-err), err); - return err; - } - } - - item->mGraphicBuffer = mSlots[item->mBuf].mGraphicBuffer; - - return OK; -} - -status_t GonkNativeWindow::releaseBuffer(const BufferItem &item, - const sp<Fence>& releaseFence) { - status_t err; - - Mutex::Autolock _l(mMutex); - - err = addReleaseFenceLocked(item.mBuf, item.mGraphicBuffer, releaseFence); - - err = releaseBufferLocked(item.mBuf, item.mGraphicBuffer); - if (err != OK) { - ALOGE("Failed to release buffer: %s (%d)", - strerror(-err), err); - } - return err; -} - -status_t GonkNativeWindow::setDefaultBufferSize(uint32_t w, uint32_t h) { - Mutex::Autolock _l(mMutex); - return mConsumer->setDefaultBufferSize(w, h); -} - -status_t GonkNativeWindow::setDefaultBufferFormat(uint32_t defaultFormat) { - Mutex::Autolock _l(mMutex); - return mConsumer->setDefaultBufferFormat(defaultFormat); -} - -already_AddRefed<TextureClient> -GonkNativeWindow::getCurrentBuffer() { - Mutex::Autolock _l(mMutex); - BufferItem item; - - // In asynchronous mode the list is guaranteed to be one buffer - // deep, while in synchronous mode we use the oldest buffer. - status_t err = acquireBufferLocked(&item, 0); //??? - if (err != NO_ERROR) { - return NULL; - } - - RefPtr<TextureClient> textureClient = - mConsumer->getTextureClientFromBuffer(item.mGraphicBuffer.get()); - if (!textureClient) { - return NULL; - } - textureClient->SetRecycleCallback(GonkNativeWindow::RecycleCallback, this); - return textureClient.forget(); -} - -/* static */ void -GonkNativeWindow::RecycleCallback(TextureClient* client, void* closure) { - GonkNativeWindow* nativeWindow = - static_cast<GonkNativeWindow*>(closure); - - MOZ_ASSERT(client && !client->IsDead()); - client->ClearRecycleCallback(); - nativeWindow->returnBuffer(client); -} - -void GonkNativeWindow::returnBuffer(TextureClient* client) { - ALOGD("GonkNativeWindow::returnBuffer"); - Mutex::Autolock lock(mMutex); - - int index = mConsumer->getSlotFromTextureClientLocked(client); - if (index < 0) { - return; - } - - FenceHandle handle = client->GetAndResetReleaseFenceHandle(); - RefPtr<FenceHandle::FdObj> fdObj = handle.GetAndResetFdObj(); - sp<Fence> fence = new Fence(fdObj->GetAndResetFd()); - - status_t err; - err = addReleaseFenceLocked(index, - mSlots[index].mGraphicBuffer, - fence); - - err = releaseBufferLocked(index, mSlots[index].mGraphicBuffer); - - if (err != OK) { - ALOGE("Failed to return buffer: %s (%d)", strerror(-err), err); - } -} - -already_AddRefed<TextureClient> -GonkNativeWindow::getTextureClientFromBuffer(ANativeWindowBuffer* buffer) { - Mutex::Autolock lock(mMutex); - return mConsumer->getTextureClientFromBuffer(buffer); -} - -void GonkNativeWindow::setNewFrameCallback( - GonkNativeWindowNewFrameCallback* callback) { - ALOGD("setNewFrameCallback"); - Mutex::Autolock lock(mMutex); - mNewFrameCallback = callback; -} - -#if ANDROID_VERSION == 21 -void GonkNativeWindow::onFrameAvailable() { - GonkConsumerBase::onFrameAvailable(); -#else -void GonkNativeWindow::onFrameAvailable(const ::android::BufferItem &item) { - GonkConsumerBase::onFrameAvailable(item); -#endif - - if (mNewFrameCallback) { - mNewFrameCallback->OnNewFrame(); - } -} - -} // namespace android diff --git a/widget/gonk/nativewindow/GonkNativeWindowLL.h b/widget/gonk/nativewindow/GonkNativeWindowLL.h deleted file mode 100644 index 64cd6482d..000000000 --- a/widget/gonk/nativewindow/GonkNativeWindowLL.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * Copyright (C) 2014 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef NATIVEWINDOW_GONKNATIVEWINDOW_LL_H -#define NATIVEWINDOW_GONKNATIVEWINDOW_LL_H - -#include <ui/GraphicBuffer.h> - -#include <utils/String8.h> -#include <utils/Vector.h> -#include <utils/threads.h> - -#include "GonkConsumerBaseLL.h" -#include "IGonkGraphicBufferConsumerLL.h" - -namespace android { - -// The user of GonkNativeWindow who wants to receive notification of -// new frames should implement this interface. -class GonkNativeWindowNewFrameCallback { -public: - virtual void OnNewFrame() = 0; -}; - -/** - * GonkNativeWindow is a GonkBufferQueue consumer endpoint that allows clients - * access to the whole BufferItem entry from GonkBufferQueue. Multiple buffers may - * be acquired at once, to be used concurrently by the client. This consumer can - * operate either in synchronous or asynchronous mode. - */ -class GonkNativeWindow: public GonkConsumerBase -{ - typedef mozilla::layers::TextureClient TextureClient; - public: - typedef GonkConsumerBase::FrameAvailableListener FrameAvailableListener; - typedef GonkBufferQueue::BufferItem BufferItem; - - enum { DEFAULT_MAX_BUFFERS = -1 }; - enum { INVALID_BUFFER_SLOT = GonkBufferQueue::INVALID_BUFFER_SLOT }; - enum { NO_BUFFER_AVAILABLE = GonkBufferQueue::NO_BUFFER_AVAILABLE }; - - // Create a new buffer item consumer. The consumerUsage parameter determines - // the consumer usage flags passed to the graphics allocator. The - // bufferCount parameter specifies how many buffers can be locked for user - // access at the same time. - // controlledByApp tells whether this consumer is controlled by the - // application. - GonkNativeWindow(const sp<IGonkGraphicBufferConsumer>& consumer, - int bufferCount = DEFAULT_MAX_BUFFERS); - GonkNativeWindow(const sp<IGonkGraphicBufferConsumer>& consumer, - uint32_t consumerUsage, int bufferCount = DEFAULT_MAX_BUFFERS, - bool controlledByApp = false); - - virtual ~GonkNativeWindow(); - - // set the name of the GonkNativeWindow that will be used to identify it in - // log messages. - void setName(const String8& name); - - // Gets the next graphics buffer from the producer, filling out the - // passed-in BufferItem structure. Returns NO_BUFFER_AVAILABLE if the queue - // of buffers is empty, and INVALID_OPERATION if the maximum number of - // buffers is already acquired. - // - // Only a fixed number of buffers can be acquired at a time, determined by - // the construction-time bufferCount parameter. If INVALID_OPERATION is - // returned by acquireBuffer, then old buffers must be returned to the - // queue by calling releaseBuffer before more buffers can be acquired. - // - // If waitForFence is true, and the acquired BufferItem has a valid fence object, - // acquireBuffer will wait on the fence with no timeout before returning. - status_t acquireBuffer(BufferItem *item, nsecs_t presentWhen, - bool waitForFence = true); - - // Returns an acquired buffer to the queue, allowing it to be reused. Since - // only a fixed number of buffers may be acquired at a time, old buffers - // must be released by calling releaseBuffer to ensure new buffers can be - // acquired by acquireBuffer. Once a BufferItem is released, the caller must - // not access any members of the BufferItem, and should immediately remove - // all of its references to the BufferItem itself. - status_t releaseBuffer(const BufferItem &item, - const sp<Fence>& releaseFence = Fence::NO_FENCE); - - // setDefaultBufferSize is used to set the size of buffers returned by - // requestBuffers when a with and height of zero is requested. - status_t setDefaultBufferSize(uint32_t w, uint32_t h); - - // setDefaultBufferFormat allows the GonkBufferQueue to create - // GraphicBuffers of a defaultFormat if no format is specified - // in dequeueBuffer - status_t setDefaultBufferFormat(uint32_t defaultFormat); - - // Get next frame from the queue, caller owns the returned buffer. - already_AddRefed<TextureClient> getCurrentBuffer(); - - // Return the buffer to the queue and mark it as FREE. After that - // the buffer is useable again for the decoder. - void returnBuffer(TextureClient* client); - - already_AddRefed<TextureClient> getTextureClientFromBuffer(ANativeWindowBuffer* buffer); - - void setNewFrameCallback(GonkNativeWindowNewFrameCallback* callback); - - static void RecycleCallback(TextureClient* client, void* closure); - -protected: -#if ANDROID_VERSION == 21 - virtual void onFrameAvailable(); -#else - virtual void onFrameAvailable(const ::android::BufferItem &item); -#endif - -private: - GonkNativeWindowNewFrameCallback* mNewFrameCallback; -}; - -} // namespace android - -#endif // NATIVEWINDOW_GONKNATIVEWINDOW_LL_H diff --git a/widget/gonk/nativewindow/IGonkGraphicBufferConsumer.h b/widget/gonk/nativewindow/IGonkGraphicBufferConsumer.h deleted file mode 100644 index 14541c9b4..000000000 --- a/widget/gonk/nativewindow/IGonkGraphicBufferConsumer.h +++ /dev/null @@ -1,20 +0,0 @@ -/* Copyright 2013 Mozilla Foundation and Mozilla contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 21 -# include "IGonkGraphicBufferConsumerLL.h" -#elif defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 19 -# include "IGonkGraphicBufferConsumerKK.h" -#endif diff --git a/widget/gonk/nativewindow/IGonkGraphicBufferConsumerKK.cpp b/widget/gonk/nativewindow/IGonkGraphicBufferConsumerKK.cpp deleted file mode 100644 index c4c9f6578..000000000 --- a/widget/gonk/nativewindow/IGonkGraphicBufferConsumerKK.cpp +++ /dev/null @@ -1,480 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define EGL_EGLEXT_PROTOTYPES - -#include <stdint.h> -#include <sys/types.h> - -#include <utils/Errors.h> - -#include <binder/Parcel.h> -#include <binder/IInterface.h> - -#include <gui/IConsumerListener.h> -#include "IGonkGraphicBufferConsumerKK.h" - -#include <ui/GraphicBuffer.h> -#include <ui/Fence.h> - -#include <system/window.h> - -namespace android { -// --------------------------------------------------------------------------- - -IGonkGraphicBufferConsumer::BufferItem::BufferItem() : - mTransform(0), - mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE), - mTimestamp(0), - mIsAutoTimestamp(false), - mFrameNumber(0), - mBuf(INVALID_BUFFER_SLOT), - mIsDroppable(false), - mAcquireCalled(false), - mTransformToDisplayInverse(false) { - mCrop.makeInvalid(); -} - -size_t IGonkGraphicBufferConsumer::BufferItem::getPodSize() const { - size_t c = sizeof(mCrop) + - sizeof(mTransform) + - sizeof(mScalingMode) + - sizeof(mTimestamp) + - sizeof(mIsAutoTimestamp) + - sizeof(mFrameNumber) + - sizeof(mBuf) + - sizeof(mIsDroppable) + - sizeof(mAcquireCalled) + - sizeof(mTransformToDisplayInverse); - return c; -} - -size_t IGonkGraphicBufferConsumer::BufferItem::getFlattenedSize() const { - size_t c = 0; - if (mGraphicBuffer != 0) { - c += mGraphicBuffer->getFlattenedSize(); - FlattenableUtils::align<4>(c); - } - if (mFence != 0) { - c += mFence->getFlattenedSize(); - FlattenableUtils::align<4>(c); - } - return sizeof(int32_t) + c + getPodSize(); -} - -size_t IGonkGraphicBufferConsumer::BufferItem::getFdCount() const { - size_t c = 0; - if (mGraphicBuffer != 0) { - c += mGraphicBuffer->getFdCount(); - } - if (mFence != 0) { - c += mFence->getFdCount(); - } - return c; -} - -status_t IGonkGraphicBufferConsumer::BufferItem::flatten( - void*& buffer, size_t& size, int*& fds, size_t& count) const { - - // make sure we have enough space - if (count < BufferItem::getFlattenedSize()) { - return NO_MEMORY; - } - - // content flags are stored first - uint32_t& flags = *static_cast<uint32_t*>(buffer); - - // advance the pointer - FlattenableUtils::advance(buffer, size, sizeof(uint32_t)); - - flags = 0; - if (mGraphicBuffer != 0) { - status_t err = mGraphicBuffer->flatten(buffer, size, fds, count); - if (err) return err; - size -= FlattenableUtils::align<4>(buffer); - flags |= 1; - } - if (mFence != 0) { - status_t err = mFence->flatten(buffer, size, fds, count); - if (err) return err; - size -= FlattenableUtils::align<4>(buffer); - flags |= 2; - } - - // check we have enough space (in case flattening the fence/graphicbuffer lied to us) - if (size < getPodSize()) { - return NO_MEMORY; - } - - FlattenableUtils::write(buffer, size, mCrop); - FlattenableUtils::write(buffer, size, mTransform); - FlattenableUtils::write(buffer, size, mScalingMode); - FlattenableUtils::write(buffer, size, mTimestamp); - FlattenableUtils::write(buffer, size, mIsAutoTimestamp); - FlattenableUtils::write(buffer, size, mFrameNumber); - FlattenableUtils::write(buffer, size, mBuf); - FlattenableUtils::write(buffer, size, mIsDroppable); - FlattenableUtils::write(buffer, size, mAcquireCalled); - FlattenableUtils::write(buffer, size, mTransformToDisplayInverse); - - return NO_ERROR; -} - -status_t IGonkGraphicBufferConsumer::BufferItem::unflatten( - void const*& buffer, size_t& size, int const*& fds, size_t& count) { - - if (size < sizeof(uint32_t)) - return NO_MEMORY; - - uint32_t flags = 0; - FlattenableUtils::read(buffer, size, flags); - - if (flags & 1) { - mGraphicBuffer = new GraphicBuffer(); - status_t err = mGraphicBuffer->unflatten(buffer, size, fds, count); - if (err) return err; - size -= FlattenableUtils::align<4>(buffer); - } - - if (flags & 2) { - mFence = new Fence(); - status_t err = mFence->unflatten(buffer, size, fds, count); - if (err) return err; - size -= FlattenableUtils::align<4>(buffer); - } - - // check we have enough space - if (size < getPodSize()) { - return NO_MEMORY; - } - - FlattenableUtils::read(buffer, size, mCrop); - FlattenableUtils::read(buffer, size, mTransform); - FlattenableUtils::read(buffer, size, mScalingMode); - FlattenableUtils::read(buffer, size, mTimestamp); - FlattenableUtils::read(buffer, size, mIsAutoTimestamp); - FlattenableUtils::read(buffer, size, mFrameNumber); - FlattenableUtils::read(buffer, size, mBuf); - FlattenableUtils::read(buffer, size, mIsDroppable); - FlattenableUtils::read(buffer, size, mAcquireCalled); - FlattenableUtils::read(buffer, size, mTransformToDisplayInverse); - - return NO_ERROR; -} - -// --------------------------------------------------------------------------- - -enum { - ACQUIRE_BUFFER = IBinder::FIRST_CALL_TRANSACTION, - RELEASE_BUFFER, - CONSUMER_CONNECT, - CONSUMER_DISCONNECT, - GET_RELEASED_BUFFERS, - SET_DEFAULT_BUFFER_SIZE, - SET_DEFAULT_MAX_BUFFER_COUNT, - DISABLE_ASYNC_BUFFER, - SET_MAX_ACQUIRED_BUFFER_COUNT, - SET_CONSUMER_NAME, - SET_DEFAULT_BUFFER_FORMAT, - SET_CONSUMER_USAGE_BITS, - SET_TRANSFORM_HINT, - DUMP, -}; - -class BpGonkGraphicBufferConsumer : public BpInterface<IGonkGraphicBufferConsumer> -{ -public: - BpGonkGraphicBufferConsumer(const sp<IBinder>& impl) - : BpInterface<IGonkGraphicBufferConsumer>(impl) - { - } - - virtual status_t acquireBuffer(BufferItem *buffer, nsecs_t presentWhen) { - Parcel data, reply; - data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor()); - data.writeInt64(presentWhen); - status_t result = remote()->transact(ACQUIRE_BUFFER, data, &reply); - if (result != NO_ERROR) { - return result; - } - result = reply.read(*buffer); - if (result != NO_ERROR) { - return result; - } - return reply.readInt32(); - } - - virtual status_t releaseBuffer(int buf, uint64_t frameNumber, - const sp<Fence>& releaseFence) { - Parcel data, reply; - data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor()); - data.writeInt32(buf); - data.writeInt64(frameNumber); - data.write(*releaseFence); - status_t result = remote()->transact(RELEASE_BUFFER, data, &reply); - if (result != NO_ERROR) { - return result; - } - return reply.readInt32(); - } - - virtual status_t consumerConnect(const sp<IConsumerListener>& consumer, bool controlledByApp) { - Parcel data, reply; - data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor()); - data.writeStrongBinder(consumer->asBinder()); - data.writeInt32(controlledByApp); - status_t result = remote()->transact(CONSUMER_CONNECT, data, &reply); - if (result != NO_ERROR) { - return result; - } - return reply.readInt32(); - } - - virtual status_t consumerDisconnect() { - Parcel data, reply; - data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor()); - status_t result = remote()->transact(CONSUMER_DISCONNECT, data, &reply); - if (result != NO_ERROR) { - return result; - } - return reply.readInt32(); - } - - virtual status_t getReleasedBuffers(uint32_t* slotMask) { - Parcel data, reply; - data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor()); - status_t result = remote()->transact(GET_RELEASED_BUFFERS, data, &reply); - if (result != NO_ERROR) { - return result; - } - *slotMask = reply.readInt32(); - return reply.readInt32(); - } - - virtual status_t setDefaultBufferSize(uint32_t w, uint32_t h) { - Parcel data, reply; - data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor()); - data.writeInt32(w); - data.writeInt32(h); - status_t result = remote()->transact(SET_DEFAULT_BUFFER_SIZE, data, &reply); - if (result != NO_ERROR) { - return result; - } - return reply.readInt32(); - } - - virtual status_t setDefaultMaxBufferCount(int bufferCount) { - Parcel data, reply; - data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor()); - data.writeInt32(bufferCount); - status_t result = remote()->transact(SET_DEFAULT_MAX_BUFFER_COUNT, data, &reply); - if (result != NO_ERROR) { - return result; - } - return reply.readInt32(); - } - - virtual status_t disableAsyncBuffer() { - Parcel data, reply; - data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor()); - status_t result = remote()->transact(DISABLE_ASYNC_BUFFER, data, &reply); - if (result != NO_ERROR) { - return result; - } - return reply.readInt32(); - } - - virtual status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers) { - Parcel data, reply; - data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor()); - data.writeInt32(maxAcquiredBuffers); - status_t result = remote()->transact(SET_MAX_ACQUIRED_BUFFER_COUNT, data, &reply); - if (result != NO_ERROR) { - return result; - } - return reply.readInt32(); - } - - virtual void setConsumerName(const String8& name) { - Parcel data, reply; - data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor()); - data.writeString8(name); - remote()->transact(SET_CONSUMER_NAME, data, &reply); - } - - virtual status_t setDefaultBufferFormat(uint32_t defaultFormat) { - Parcel data, reply; - data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor()); - data.writeInt32(defaultFormat); - status_t result = remote()->transact(SET_DEFAULT_BUFFER_FORMAT, data, &reply); - if (result != NO_ERROR) { - return result; - } - return reply.readInt32(); - } - - virtual status_t setConsumerUsageBits(uint32_t usage) { - Parcel data, reply; - data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor()); - data.writeInt32(usage); - status_t result = remote()->transact(SET_CONSUMER_USAGE_BITS, data, &reply); - if (result != NO_ERROR) { - return result; - } - return reply.readInt32(); - } - - virtual status_t setTransformHint(uint32_t hint) { - Parcel data, reply; - data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor()); - data.writeInt32(hint); - status_t result = remote()->transact(SET_TRANSFORM_HINT, data, &reply); - if (result != NO_ERROR) { - return result; - } - return reply.readInt32(); - } - - virtual void dumpToString(String8& result, const char* prefix) const { - Parcel data, reply; - data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor()); - data.writeString8(result); - data.writeString8(String8(prefix ? prefix : "")); - remote()->transact(DUMP, data, &reply); - reply.readString8(); - } -}; - -IMPLEMENT_META_INTERFACE(GonkGraphicBufferConsumer, "android.gui.IGonkGraphicBufferConsumer"); -// ---------------------------------------------------------------------- - -status_t BnGonkGraphicBufferConsumer::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - switch(code) { - case ACQUIRE_BUFFER: { - CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply); - BufferItem item; - int64_t presentWhen = data.readInt64(); - status_t result = acquireBuffer(&item, presentWhen); - status_t err = reply->write(item); - if (err) return err; - reply->writeInt32(result); - return NO_ERROR; - } break; - case RELEASE_BUFFER: { - CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply); - int buf = data.readInt32(); - uint64_t frameNumber = data.readInt64(); - sp<Fence> releaseFence = new Fence(); - status_t err = data.read(*releaseFence); - if (err) return err; - status_t result = releaseBuffer(buf, frameNumber, releaseFence); - reply->writeInt32(result); - return NO_ERROR; - } break; - - case CONSUMER_CONNECT: { - CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply); - sp<IConsumerListener> consumer = IConsumerListener::asInterface( data.readStrongBinder() ); - bool controlledByApp = data.readInt32(); - status_t result = consumerConnect(consumer, controlledByApp); - reply->writeInt32(result); - return NO_ERROR; - } break; - - case CONSUMER_DISCONNECT: { - CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply); - status_t result = consumerDisconnect(); - reply->writeInt32(result); - return NO_ERROR; - } break; - case GET_RELEASED_BUFFERS: { - CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply); - uint32_t slotMask; - status_t result = getReleasedBuffers(&slotMask); - reply->writeInt32(slotMask); - reply->writeInt32(result); - return NO_ERROR; - } break; - case SET_DEFAULT_BUFFER_SIZE: { - CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply); - uint32_t w = data.readInt32(); - uint32_t h = data.readInt32(); - status_t result = setDefaultBufferSize(w, h); - reply->writeInt32(result); - return NO_ERROR; - } break; - case SET_DEFAULT_MAX_BUFFER_COUNT: { - CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply); - uint32_t bufferCount = data.readInt32(); - status_t result = setDefaultMaxBufferCount(bufferCount); - reply->writeInt32(result); - return NO_ERROR; - } break; - case DISABLE_ASYNC_BUFFER: { - CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply); - status_t result = disableAsyncBuffer(); - reply->writeInt32(result); - return NO_ERROR; - } break; - case SET_MAX_ACQUIRED_BUFFER_COUNT: { - CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply); - uint32_t maxAcquiredBuffers = data.readInt32(); - status_t result = setMaxAcquiredBufferCount(maxAcquiredBuffers); - reply->writeInt32(result); - return NO_ERROR; - } break; - case SET_CONSUMER_NAME: { - CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply); - setConsumerName( data.readString8() ); - return NO_ERROR; - } break; - case SET_DEFAULT_BUFFER_FORMAT: { - CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply); - uint32_t defaultFormat = data.readInt32(); - status_t result = setDefaultBufferFormat(defaultFormat); - reply->writeInt32(result); - return NO_ERROR; - } break; - case SET_CONSUMER_USAGE_BITS: { - CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply); - uint32_t usage = data.readInt32(); - status_t result = setConsumerUsageBits(usage); - reply->writeInt32(result); - return NO_ERROR; - } break; - case SET_TRANSFORM_HINT: { - CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply); - uint32_t hint = data.readInt32(); - status_t result = setTransformHint(hint); - reply->writeInt32(result); - return NO_ERROR; - } break; - - case DUMP: { - CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply); - String8 result = data.readString8(); - String8 prefix = data.readString8(); - static_cast<IGonkGraphicBufferConsumer*>(this)->dumpToString(result, prefix); - reply->writeString8(result); - return NO_ERROR; - } - } - return BBinder::onTransact(code, data, reply, flags); -} - -}; // namespace android diff --git a/widget/gonk/nativewindow/IGonkGraphicBufferConsumerKK.h b/widget/gonk/nativewindow/IGonkGraphicBufferConsumerKK.h deleted file mode 100644 index ce51e1ef2..000000000 --- a/widget/gonk/nativewindow/IGonkGraphicBufferConsumerKK.h +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef NATIVEWINDOW_IGONKGRAPHICBUFFERCONSUMER_KK_H -#define NATIVEWINDOW_IGONKGRAPHICBUFFERCONSUMER_KK_H - -#include <stdint.h> -#include <sys/types.h> - -#include <utils/Errors.h> -#include <utils/RefBase.h> -#include <utils/Timers.h> - -#include <binder/IInterface.h> -#include <ui/Rect.h> - -#include "mozilla/Types.h" -#include "mozilla/layers/LayersSurfaces.h" - -namespace mozilla { - -namespace layers { -class TextureClient; -} -} - -namespace android { -// ---------------------------------------------------------------------------- - -class MOZ_EXPORT IConsumerListener; -class MOZ_EXPORT GraphicBuffer; -class MOZ_EXPORT Fence; - -class IGonkGraphicBufferConsumer : public IInterface { - typedef mozilla::layers::TextureClient TextureClient; -public: - - // public facing structure for BufferSlot - class BufferItem : public Flattenable<BufferItem> { - friend class Flattenable<BufferItem>; - size_t getPodSize() const; - size_t getFlattenedSize() const; - size_t getFdCount() const; - status_t flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const; - status_t unflatten(void const*& buffer, size_t& size, int const*& fds, size_t& count); - - public: - enum { INVALID_BUFFER_SLOT = -1 }; - BufferItem(); - - // mGraphicBuffer points to the buffer allocated for this slot, or is NULL - // if the buffer in this slot has been acquired in the past (see - // BufferSlot.mAcquireCalled). - sp<GraphicBuffer> mGraphicBuffer; - - // mFence is a fence that will signal when the buffer is idle. - sp<Fence> mFence; - - // mCrop is the current crop rectangle for this buffer slot. - Rect mCrop; - - // mTransform is the current transform flags for this buffer slot. - uint32_t mTransform; - - // mScalingMode is the current scaling mode for this buffer slot. - uint32_t mScalingMode; - - // mTimestamp is the current timestamp for this buffer slot. This gets - // to set by queueBuffer each time this slot is queued. - int64_t mTimestamp; - - // mIsAutoTimestamp indicates whether mTimestamp was generated - // automatically when the buffer was queued. - bool mIsAutoTimestamp; - - // mFrameNumber is the number of the queued frame for this slot. - uint64_t mFrameNumber; - - // mBuf is the slot index of this buffer - int mBuf; - - // mIsDroppable whether this buffer was queued with the - // property that it can be replaced by a new buffer for the purpose of - // making sure dequeueBuffer() won't block. - // i.e.: was the BufferQueue in "mDequeueBufferCannotBlock" when this buffer - // was queued. - bool mIsDroppable; - - // Indicates whether this buffer has been seen by a consumer yet - bool mAcquireCalled; - - // Indicates this buffer must be transformed by the inverse transform of the screen - // it is displayed onto. This is applied after mTransform. - bool mTransformToDisplayInverse; - }; - - - // acquireBuffer attempts to acquire ownership of the next pending buffer in - // the BufferQueue. If no buffer is pending then it returns -EINVAL. If a - // buffer is successfully acquired, the information about the buffer is - // returned in BufferItem. If the buffer returned had previously been - // acquired then the BufferItem::mGraphicBuffer field of buffer is set to - // NULL and it is assumed that the consumer still holds a reference to the - // buffer. - // - // If presentWhen is nonzero, it indicates the time when the buffer will - // be displayed on screen. If the buffer's timestamp is farther in the - // future, the buffer won't be acquired, and PRESENT_LATER will be - // returned. The presentation time is in nanoseconds, and the time base - // is CLOCK_MONOTONIC. - virtual status_t acquireBuffer(BufferItem *buffer, nsecs_t presentWhen) = 0; - - // releaseBuffer releases a buffer slot from the consumer back to the - // BufferQueue. This may be done while the buffer's contents are still - // being accessed. The fence will signal when the buffer is no longer - // in use. frameNumber is used to indentify the exact buffer returned. - // - // If releaseBuffer returns STALE_BUFFER_SLOT, then the consumer must free - // any references to the just-released buffer that it might have, as if it - // had received a onBuffersReleased() call with a mask set for the released - // buffer. - // - // Note that the dependencies on EGL will be removed once we switch to using - // the Android HW Sync HAL. - virtual status_t releaseBuffer(int buf, uint64_t frameNumber, const sp<Fence>& releaseFence) = 0; - - // consumerConnect connects a consumer to the BufferQueue. Only one - // consumer may be connected, and when that consumer disconnects the - // BufferQueue is placed into the "abandoned" state, causing most - // interactions with the BufferQueue by the producer to fail. - // controlledByApp indicates whether the consumer is controlled by - // the application. - // - // consumer may not be NULL. - virtual status_t consumerConnect(const sp<IConsumerListener>& consumer, bool controlledByApp) = 0; - - // consumerDisconnect disconnects a consumer from the BufferQueue. All - // buffers will be freed and the BufferQueue is placed in the "abandoned" - // state, causing most interactions with the BufferQueue by the producer to - // fail. - virtual status_t consumerDisconnect() = 0; - - // getReleasedBuffers sets the value pointed to by slotMask to a bit mask - // indicating which buffer slots have been released by the BufferQueue - // but have not yet been released by the consumer. - // - // This should be called from the onBuffersReleased() callback. - virtual status_t getReleasedBuffers(uint32_t* slotMask) = 0; - - // setDefaultBufferSize is used to set the size of buffers returned by - // dequeueBuffer when a width and height of zero is requested. Default - // is 1x1. - virtual status_t setDefaultBufferSize(uint32_t w, uint32_t h) = 0; - - // setDefaultMaxBufferCount sets the default value for the maximum buffer - // count (the initial default is 2). If the producer has requested a - // buffer count using setBufferCount, the default buffer count will only - // take effect if the producer sets the count back to zero. - // - // The count must be between 2 and NUM_BUFFER_SLOTS, inclusive. - virtual status_t setDefaultMaxBufferCount(int bufferCount) = 0; - - // disableAsyncBuffer disables the extra buffer used in async mode - // (when both producer and consumer have set their "isControlledByApp" - // flag) and has dequeueBuffer() return WOULD_BLOCK instead. - // - // This can only be called before consumerConnect(). - virtual status_t disableAsyncBuffer() = 0; - - // setMaxAcquiredBufferCount sets the maximum number of buffers that can - // be acquired by the consumer at one time (default 1). This call will - // fail if a producer is connected to the BufferQueue. - virtual status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers) = 0; - - // setConsumerName sets the name used in logging - virtual void setConsumerName(const String8& name) = 0; - - // setDefaultBufferFormat allows the BufferQueue to create - // GraphicBuffers of a defaultFormat if no format is specified - // in dequeueBuffer. Formats are enumerated in graphics.h; the - // initial default is HAL_PIXEL_FORMAT_RGBA_8888. - virtual status_t setDefaultBufferFormat(uint32_t defaultFormat) = 0; - - // setConsumerUsageBits will turn on additional usage bits for dequeueBuffer. - // These are merged with the bits passed to dequeueBuffer. The values are - // enumerated in gralloc.h, e.g. GRALLOC_USAGE_HW_RENDER; the default is 0. - virtual status_t setConsumerUsageBits(uint32_t usage) = 0; - - // setTransformHint bakes in rotation to buffers so overlays can be used. - // The values are enumerated in window.h, e.g. - // NATIVE_WINDOW_TRANSFORM_ROT_90. The default is 0 (no transform). - virtual status_t setTransformHint(uint32_t hint) = 0; - - // dump state into a string - virtual void dumpToString(String8& result, const char* prefix) const = 0; - -public: - DECLARE_META_INTERFACE(GonkGraphicBufferConsumer); -}; - -// ---------------------------------------------------------------------------- - -class BnGonkGraphicBufferConsumer : public BnInterface<IGonkGraphicBufferConsumer> -{ -public: - virtual status_t onTransact( uint32_t code, - const Parcel& data, - Parcel* reply, - uint32_t flags = 0); -}; - -// ---------------------------------------------------------------------------- -}; // namespace android - -#endif // ANDROID_GUI_IGRAPHICBUFFERCONSUMER_H diff --git a/widget/gonk/nativewindow/IGonkGraphicBufferConsumerLL.cpp b/widget/gonk/nativewindow/IGonkGraphicBufferConsumerLL.cpp deleted file mode 100644 index 729ed6736..000000000 --- a/widget/gonk/nativewindow/IGonkGraphicBufferConsumerLL.cpp +++ /dev/null @@ -1,565 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <stdint.h> -#include <sys/types.h> - -#include <utils/Errors.h> -#include <utils/NativeHandle.h> - -#include <binder/Parcel.h> -#include <binder/IInterface.h> - -#include <gui/IConsumerListener.h> -#include "IGonkGraphicBufferConsumerLL.h" - -#include <ui/GraphicBuffer.h> -#include <ui/Fence.h> - -#include <system/window.h> - -#include "mozilla/layers/TextureClient.h" - -namespace android { -// --------------------------------------------------------------------------- - -IGonkGraphicBufferConsumer::BufferItem::BufferItem() : - mTransform(0), - mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE), - mTimestamp(0), - mIsAutoTimestamp(false), - mFrameNumber(0), - mBuf(INVALID_BUFFER_SLOT), - mIsDroppable(false), - mAcquireCalled(false), - mTransformToDisplayInverse(false) { - mCrop.makeInvalid(); -} - -size_t IGonkGraphicBufferConsumer::BufferItem::getPodSize() const { - size_t c = sizeof(mCrop) + - sizeof(mTransform) + - sizeof(mScalingMode) + - sizeof(mTimestamp) + - sizeof(mIsAutoTimestamp) + - sizeof(mFrameNumber) + - sizeof(mBuf) + - sizeof(mIsDroppable) + - sizeof(mAcquireCalled) + - sizeof(mTransformToDisplayInverse); - return c; -} - -size_t IGonkGraphicBufferConsumer::BufferItem::getFlattenedSize() const { - size_t c = 0; - if (mGraphicBuffer != 0) { - c += mGraphicBuffer->getFlattenedSize(); - c = FlattenableUtils::align<4>(c); - } - if (mFence != 0) { - c += mFence->getFlattenedSize(); - c = FlattenableUtils::align<4>(c); - } - return sizeof(int32_t) + c + getPodSize(); -} - -size_t IGonkGraphicBufferConsumer::BufferItem::getFdCount() const { - size_t c = 0; - if (mGraphicBuffer != 0) { - c += mGraphicBuffer->getFdCount(); - } - if (mFence != 0) { - c += mFence->getFdCount(); - } - return c; -} - -static void writeBoolAsInt(void*& buffer, size_t& size, bool b) { - FlattenableUtils::write(buffer, size, static_cast<int32_t>(b)); -} - -static bool readBoolFromInt(void const*& buffer, size_t& size) { - int32_t i; - FlattenableUtils::read(buffer, size, i); - return static_cast<bool>(i); -} - -status_t IGonkGraphicBufferConsumer::BufferItem::flatten( - void*& buffer, size_t& size, int*& fds, size_t& count) const { - - // make sure we have enough space - if (size < BufferItem::getFlattenedSize()) { - return NO_MEMORY; - } - - // content flags are stored first - uint32_t& flags = *static_cast<uint32_t*>(buffer); - - // advance the pointer - FlattenableUtils::advance(buffer, size, sizeof(uint32_t)); - - flags = 0; - if (mGraphicBuffer != 0) { - status_t err = mGraphicBuffer->flatten(buffer, size, fds, count); - if (err) return err; - size -= FlattenableUtils::align<4>(buffer); - flags |= 1; - } - if (mFence != 0) { - status_t err = mFence->flatten(buffer, size, fds, count); - if (err) return err; - size -= FlattenableUtils::align<4>(buffer); - flags |= 2; - } - - // check we have enough space (in case flattening the fence/graphicbuffer lied to us) - if (size < getPodSize()) { - return NO_MEMORY; - } - - FlattenableUtils::write(buffer, size, mCrop); - FlattenableUtils::write(buffer, size, mTransform); - FlattenableUtils::write(buffer, size, mScalingMode); - FlattenableUtils::write(buffer, size, mTimestamp); - writeBoolAsInt(buffer, size, mIsAutoTimestamp); - FlattenableUtils::write(buffer, size, mFrameNumber); - FlattenableUtils::write(buffer, size, mBuf); - writeBoolAsInt(buffer, size, mIsDroppable); - writeBoolAsInt(buffer, size, mAcquireCalled); - writeBoolAsInt(buffer, size, mTransformToDisplayInverse); - - return NO_ERROR; -} - -status_t IGonkGraphicBufferConsumer::BufferItem::unflatten( - void const*& buffer, size_t& size, int const*& fds, size_t& count) { - - if (size < sizeof(uint32_t)) - return NO_MEMORY; - - uint32_t flags = 0; - FlattenableUtils::read(buffer, size, flags); - - if (flags & 1) { - mGraphicBuffer = new GraphicBuffer(); - status_t err = mGraphicBuffer->unflatten(buffer, size, fds, count); - if (err) return err; - size -= FlattenableUtils::align<4>(buffer); - } - - if (flags & 2) { - mFence = new Fence(); - status_t err = mFence->unflatten(buffer, size, fds, count); - if (err) return err; - size -= FlattenableUtils::align<4>(buffer); - } - - // check we have enough space - if (size < getPodSize()) { - return NO_MEMORY; - } - - FlattenableUtils::read(buffer, size, mCrop); - FlattenableUtils::read(buffer, size, mTransform); - FlattenableUtils::read(buffer, size, mScalingMode); - FlattenableUtils::read(buffer, size, mTimestamp); - mIsAutoTimestamp = readBoolFromInt(buffer, size); - FlattenableUtils::read(buffer, size, mFrameNumber); - FlattenableUtils::read(buffer, size, mBuf); - mIsDroppable = readBoolFromInt(buffer, size); - mAcquireCalled = readBoolFromInt(buffer, size); - mTransformToDisplayInverse = readBoolFromInt(buffer, size); - - return NO_ERROR; -} - -// --------------------------------------------------------------------------- - -enum { - ACQUIRE_BUFFER = IBinder::FIRST_CALL_TRANSACTION, - DETACH_BUFFER, - ATTACH_BUFFER, - RELEASE_BUFFER, - CONSUMER_CONNECT, - CONSUMER_DISCONNECT, - GET_RELEASED_BUFFERS, - SET_DEFAULT_BUFFER_SIZE, - SET_DEFAULT_MAX_BUFFER_COUNT, - DISABLE_ASYNC_BUFFER, - SET_MAX_ACQUIRED_BUFFER_COUNT, - SET_CONSUMER_NAME, - SET_DEFAULT_BUFFER_FORMAT, - SET_CONSUMER_USAGE_BITS, - SET_TRANSFORM_HINT, - GET_SIDEBAND_STREAM, - DUMP, -}; - - -class BpGonkGraphicBufferConsumer : public BpInterface<IGonkGraphicBufferConsumer> -{ -public: - BpGonkGraphicBufferConsumer(const sp<IBinder>& impl) - : BpInterface<IGonkGraphicBufferConsumer>(impl) - { - } - - virtual status_t acquireBuffer(BufferItem *buffer, nsecs_t presentWhen) { - Parcel data, reply; - data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor()); - data.writeInt64(presentWhen); - status_t result = remote()->transact(ACQUIRE_BUFFER, data, &reply); - if (result != NO_ERROR) { - return result; - } - result = reply.read(*buffer); - if (result != NO_ERROR) { - return result; - } - return reply.readInt32(); - } - - virtual status_t detachBuffer(int slot) { - Parcel data, reply; - data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor()); - data.writeInt32(slot); - status_t result = remote()->transact(DETACH_BUFFER, data, &reply); - if (result != NO_ERROR) { - return result; - } - result = reply.readInt32(); - return result; - } - - virtual status_t attachBuffer(int* slot, const sp<GraphicBuffer>& buffer) { - Parcel data, reply; - data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor()); - data.write(*buffer.get()); - status_t result = remote()->transact(ATTACH_BUFFER, data, &reply); - if (result != NO_ERROR) { - return result; - } - *slot = reply.readInt32(); - result = reply.readInt32(); - return result; - } - - virtual status_t releaseBuffer(int buf, uint64_t frameNumber, const sp<Fence>& releaseFence) { - Parcel data, reply; - data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor()); - data.writeInt32(buf); - data.writeInt64(frameNumber); - data.write(*releaseFence); - status_t result = remote()->transact(RELEASE_BUFFER, data, &reply); - if (result != NO_ERROR) { - return result; - } - return reply.readInt32(); - } - - virtual status_t consumerConnect(const sp<IConsumerListener>& consumer, bool controlledByApp) { - Parcel data, reply; - data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor()); - data.writeStrongBinder(consumer->asBinder()); - data.writeInt32(controlledByApp); - status_t result = remote()->transact(CONSUMER_CONNECT, data, &reply); - if (result != NO_ERROR) { - return result; - } - return reply.readInt32(); - } - - virtual status_t consumerDisconnect() { - Parcel data, reply; - data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor()); - status_t result = remote()->transact(CONSUMER_DISCONNECT, data, &reply); - if (result != NO_ERROR) { - return result; - } - return reply.readInt32(); - } - - virtual status_t getReleasedBuffers(uint64_t* slotMask) { - Parcel data, reply; - if (slotMask == NULL) { - ALOGE("getReleasedBuffers: slotMask must not be NULL"); - return BAD_VALUE; - } - data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor()); - status_t result = remote()->transact(GET_RELEASED_BUFFERS, data, &reply); - if (result != NO_ERROR) { - return result; - } - *slotMask = reply.readInt64(); - return reply.readInt32(); - } - - virtual status_t setDefaultBufferSize(uint32_t w, uint32_t h) { - Parcel data, reply; - data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor()); - data.writeInt32(w); - data.writeInt32(h); - status_t result = remote()->transact(SET_DEFAULT_BUFFER_SIZE, data, &reply); - if (result != NO_ERROR) { - return result; - } - return reply.readInt32(); - } - - virtual status_t setDefaultMaxBufferCount(int bufferCount) { - Parcel data, reply; - data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor()); - data.writeInt32(bufferCount); - status_t result = remote()->transact(SET_DEFAULT_MAX_BUFFER_COUNT, data, &reply); - if (result != NO_ERROR) { - return result; - } - return reply.readInt32(); - } - - virtual status_t disableAsyncBuffer() { - Parcel data, reply; - data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor()); - status_t result = remote()->transact(DISABLE_ASYNC_BUFFER, data, &reply); - if (result != NO_ERROR) { - return result; - } - return reply.readInt32(); - } - - virtual status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers) { - Parcel data, reply; - data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor()); - data.writeInt32(maxAcquiredBuffers); - status_t result = remote()->transact(SET_MAX_ACQUIRED_BUFFER_COUNT, data, &reply); - if (result != NO_ERROR) { - return result; - } - return reply.readInt32(); - } - - virtual void setConsumerName(const String8& name) { - Parcel data, reply; - data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor()); - data.writeString8(name); - remote()->transact(SET_CONSUMER_NAME, data, &reply); - } - - virtual status_t setDefaultBufferFormat(uint32_t defaultFormat) { - Parcel data, reply; - data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor()); - data.writeInt32(defaultFormat); - status_t result = remote()->transact(SET_DEFAULT_BUFFER_FORMAT, data, &reply); - if (result != NO_ERROR) { - return result; - } - return reply.readInt32(); - } - - virtual status_t setConsumerUsageBits(uint32_t usage) { - Parcel data, reply; - data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor()); - data.writeInt32(usage); - status_t result = remote()->transact(SET_CONSUMER_USAGE_BITS, data, &reply); - if (result != NO_ERROR) { - return result; - } - return reply.readInt32(); - } - - virtual status_t setTransformHint(uint32_t hint) { - Parcel data, reply; - data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor()); - data.writeInt32(hint); - status_t result = remote()->transact(SET_TRANSFORM_HINT, data, &reply); - if (result != NO_ERROR) { - return result; - } - return reply.readInt32(); - } - - virtual sp<NativeHandle> getSidebandStream() const { - Parcel data, reply; - status_t err; - data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor()); - if ((err = remote()->transact(GET_SIDEBAND_STREAM, data, &reply)) != NO_ERROR) { - return NULL; - } - sp<NativeHandle> stream; - if (reply.readInt32()) { - stream = NativeHandle::create(reply.readNativeHandle(), true); - } - return stream; - } - - virtual void dumpToString(String8& result, const char* prefix) const { - Parcel data, reply; - data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor()); - data.writeString8(result); - data.writeString8(String8(prefix ? prefix : "")); - remote()->transact(DUMP, data, &reply); - reply.readString8(); - } - - // Added by mozilla - virtual already_AddRefed<mozilla::layers::TextureClient> - getTextureClientFromBuffer(ANativeWindowBuffer* buffer) - { - return nullptr; - } - - virtual int - getSlotFromTextureClientLocked(mozilla::layers::TextureClient* client) const - { - return BAD_VALUE; - } -}; - -IMPLEMENT_META_INTERFACE(GonkGraphicBufferConsumer, "android.gui.IGonkGraphicBufferConsumer"); - -// ---------------------------------------------------------------------- - -status_t BnGonkGraphicBufferConsumer::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - switch(code) { - case ACQUIRE_BUFFER: { - CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply); - BufferItem item; - int64_t presentWhen = data.readInt64(); - status_t result = acquireBuffer(&item, presentWhen); - status_t err = reply->write(item); - if (err) return err; - reply->writeInt32(result); - return NO_ERROR; - } break; - case DETACH_BUFFER: { - CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply); - int slot = data.readInt32(); - int result = detachBuffer(slot); - reply->writeInt32(result); - return NO_ERROR; - } break; - case ATTACH_BUFFER: { - CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply); - sp<GraphicBuffer> buffer = new GraphicBuffer(); - data.read(*buffer.get()); - int slot; - int result = attachBuffer(&slot, buffer); - reply->writeInt32(slot); - reply->writeInt32(result); - return NO_ERROR; - } break; - case RELEASE_BUFFER: { - CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply); - int buf = data.readInt32(); - uint64_t frameNumber = data.readInt64(); - sp<Fence> releaseFence = new Fence(); - status_t err = data.read(*releaseFence); - if (err) return err; - status_t result = releaseBuffer(buf, frameNumber, releaseFence); - reply->writeInt32(result); - return NO_ERROR; - } break; - case CONSUMER_CONNECT: { - CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply); - sp<IConsumerListener> consumer = IConsumerListener::asInterface( data.readStrongBinder() ); - bool controlledByApp = data.readInt32(); - status_t result = consumerConnect(consumer, controlledByApp); - reply->writeInt32(result); - return NO_ERROR; - } break; - case CONSUMER_DISCONNECT: { - CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply); - status_t result = consumerDisconnect(); - reply->writeInt32(result); - return NO_ERROR; - } break; - case GET_RELEASED_BUFFERS: { - CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply); - uint64_t slotMask; - status_t result = getReleasedBuffers(&slotMask); - reply->writeInt64(slotMask); - reply->writeInt32(result); - return NO_ERROR; - } break; - case SET_DEFAULT_BUFFER_SIZE: { - CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply); - uint32_t w = data.readInt32(); - uint32_t h = data.readInt32(); - status_t result = setDefaultBufferSize(w, h); - reply->writeInt32(result); - return NO_ERROR; - } break; - case SET_DEFAULT_MAX_BUFFER_COUNT: { - CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply); - uint32_t bufferCount = data.readInt32(); - status_t result = setDefaultMaxBufferCount(bufferCount); - reply->writeInt32(result); - return NO_ERROR; - } break; - case DISABLE_ASYNC_BUFFER: { - CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply); - status_t result = disableAsyncBuffer(); - reply->writeInt32(result); - return NO_ERROR; - } break; - case SET_MAX_ACQUIRED_BUFFER_COUNT: { - CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply); - uint32_t maxAcquiredBuffers = data.readInt32(); - status_t result = setMaxAcquiredBufferCount(maxAcquiredBuffers); - reply->writeInt32(result); - return NO_ERROR; - } break; - case SET_CONSUMER_NAME: { - CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply); - setConsumerName( data.readString8() ); - return NO_ERROR; - } break; - case SET_DEFAULT_BUFFER_FORMAT: { - CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply); - uint32_t defaultFormat = data.readInt32(); - status_t result = setDefaultBufferFormat(defaultFormat); - reply->writeInt32(result); - return NO_ERROR; - } break; - case SET_CONSUMER_USAGE_BITS: { - CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply); - uint32_t usage = data.readInt32(); - status_t result = setConsumerUsageBits(usage); - reply->writeInt32(result); - return NO_ERROR; - } break; - case SET_TRANSFORM_HINT: { - CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply); - uint32_t hint = data.readInt32(); - status_t result = setTransformHint(hint); - reply->writeInt32(result); - return NO_ERROR; - } break; - case DUMP: { - CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply); - String8 result = data.readString8(); - String8 prefix = data.readString8(); - static_cast<IGonkGraphicBufferConsumer*>(this)->dumpToString(result, prefix); - reply->writeString8(result); - return NO_ERROR; - } - } - return BBinder::onTransact(code, data, reply, flags); -} - -}; // namespace android diff --git a/widget/gonk/nativewindow/IGonkGraphicBufferConsumerLL.h b/widget/gonk/nativewindow/IGonkGraphicBufferConsumerLL.h deleted file mode 100644 index 8a93a0849..000000000 --- a/widget/gonk/nativewindow/IGonkGraphicBufferConsumerLL.h +++ /dev/null @@ -1,337 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef NATIVEWINDOW_IGONKGRAPHICBUFFERCONSUMER_LL_H -#define NATIVEWINDOW_IGONKGRAPHICBUFFERCONSUMER_LL_H - -#include <stdint.h> -#include <sys/types.h> - -#include <utils/Errors.h> -#include <utils/RefBase.h> -#include <utils/Timers.h> - -#include <binder/IInterface.h> -#include <ui/Rect.h> - -#include "mozilla/RefPtr.h" - -class ANativeWindowBuffer; - -namespace mozilla { -namespace layers { -class TextureClient; -} -} - -namespace android { -// ---------------------------------------------------------------------------- - -class Fence; -class GraphicBuffer; -class IConsumerListener; -class NativeHandle; - -class IGonkGraphicBufferConsumer : public IInterface { -public: - - // public facing structure for BufferSlot - class BufferItem : public Flattenable<BufferItem> { - friend class Flattenable<BufferItem>; - size_t getPodSize() const; - size_t getFlattenedSize() const; - size_t getFdCount() const; - status_t flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const; - status_t unflatten(void const*& buffer, size_t& size, int const*& fds, size_t& count); - - public: - // The default value of mBuf, used to indicate this doesn't correspond to a slot. - enum { INVALID_BUFFER_SLOT = -1 }; - BufferItem(); - - // mGraphicBuffer points to the buffer allocated for this slot, or is NULL - // if the buffer in this slot has been acquired in the past (see - // BufferSlot.mAcquireCalled). - sp<GraphicBuffer> mGraphicBuffer; - - // mFence is a fence that will signal when the buffer is idle. - sp<Fence> mFence; - - // mCrop is the current crop rectangle for this buffer slot. - Rect mCrop; - - // mTransform is the current transform flags for this buffer slot. - // refer to NATIVE_WINDOW_TRANSFORM_* in <window.h> - uint32_t mTransform; - - // mScalingMode is the current scaling mode for this buffer slot. - // refer to NATIVE_WINDOW_SCALING_* in <window.h> - uint32_t mScalingMode; - - // mTimestamp is the current timestamp for this buffer slot. This gets - // to set by queueBuffer each time this slot is queued. This value - // is guaranteed to be monotonically increasing for each newly - // acquired buffer. - int64_t mTimestamp; - - // mIsAutoTimestamp indicates whether mTimestamp was generated - // automatically when the buffer was queued. - bool mIsAutoTimestamp; - - // mFrameNumber is the number of the queued frame for this slot. - uint64_t mFrameNumber; - - // mBuf is the slot index of this buffer (default INVALID_BUFFER_SLOT). - int mBuf; - - // mIsDroppable whether this buffer was queued with the - // property that it can be replaced by a new buffer for the purpose of - // making sure dequeueBuffer() won't block. - // i.e.: was the BufferQueue in "mDequeueBufferCannotBlock" when this buffer - // was queued. - bool mIsDroppable; - - // Indicates whether this buffer has been seen by a consumer yet - bool mAcquireCalled; - - // Indicates this buffer must be transformed by the inverse transform of the screen - // it is displayed onto. This is applied after mTransform. - bool mTransformToDisplayInverse; - }; - - enum { - // Returned by releaseBuffer, after which the consumer must - // free any references to the just-released buffer that it might have. - STALE_BUFFER_SLOT = 1, - // Returned by dequeueBuffer if there are no pending buffers available. - NO_BUFFER_AVAILABLE, - // Returned by dequeueBuffer if it's too early for the buffer to be acquired. - PRESENT_LATER, - }; - - // acquireBuffer attempts to acquire ownership of the next pending buffer in - // the BufferQueue. If no buffer is pending then it returns - // NO_BUFFER_AVAILABLE. If a buffer is successfully acquired, the - // information about the buffer is returned in BufferItem. - // - // If the buffer returned had previously been - // acquired then the BufferItem::mGraphicBuffer field of buffer is set to - // NULL and it is assumed that the consumer still holds a reference to the - // buffer. - // - // If presentWhen is non-zero, it indicates the time when the buffer will - // be displayed on screen. If the buffer's timestamp is farther in the - // future, the buffer won't be acquired, and PRESENT_LATER will be - // returned. The presentation time is in nanoseconds, and the time base - // is CLOCK_MONOTONIC. - // - // Return of NO_ERROR means the operation completed as normal. - // - // Return of a positive value means the operation could not be completed - // at this time, but the user should try again later: - // * NO_BUFFER_AVAILABLE - no buffer is pending (nothing queued by producer) - // * PRESENT_LATER - the buffer's timestamp is farther in the future - // - // Return of a negative value means an error has occurred: - // * INVALID_OPERATION - too many buffers have been acquired - virtual status_t acquireBuffer(BufferItem* buffer, nsecs_t presentWhen) = 0; - - // detachBuffer attempts to remove all ownership of the buffer in the given - // slot from the buffer queue. If this call succeeds, the slot will be - // freed, and there will be no way to obtain the buffer from this interface. - // The freed slot will remain unallocated until either it is selected to - // hold a freshly allocated buffer in dequeueBuffer or a buffer is attached - // to the slot. The buffer must have already been acquired. - // - // Return of a value other than NO_ERROR means an error has occurred: - // * BAD_VALUE - the given slot number is invalid, either because it is - // out of the range [0, NUM_BUFFER_SLOTS) or because the slot - // it refers to is not currently acquired. - virtual status_t detachBuffer(int slot) = 0; - - // attachBuffer attempts to transfer ownership of a buffer to the buffer - // queue. If this call succeeds, it will be as if this buffer was acquired - // from the returned slot number. As such, this call will fail if attaching - // this buffer would cause too many buffers to be simultaneously acquired. - // - // If the buffer is successfully attached, its frameNumber is initialized - // to 0. This must be passed into the releaseBuffer call or else the buffer - // will be deallocated as stale. - // - // Return of a value other than NO_ERROR means an error has occurred: - // * BAD_VALUE - outSlot or buffer were NULL - // * INVALID_OPERATION - cannot attach the buffer because it would cause too - // many buffers to be acquired. - // * NO_MEMORY - no free slots available - virtual status_t attachBuffer(int *outSlot, - const sp<GraphicBuffer>& buffer) = 0; - - // releaseBuffer releases a buffer slot from the consumer back to the - // BufferQueue. This may be done while the buffer's contents are still - // being accessed. The fence will signal when the buffer is no longer - // in use. frameNumber is used to indentify the exact buffer returned. - // - // If releaseBuffer returns STALE_BUFFER_SLOT, then the consumer must free - // any references to the just-released buffer that it might have, as if it - // had received a onBuffersReleased() call with a mask set for the released - // buffer. - // - // Note that the dependencies on EGL will be removed once we switch to using - // the Android HW Sync HAL. - // - // Return of NO_ERROR means the operation completed as normal. - // - // Return of a positive value means the operation could not be completed - // at this time, but the user should try again later: - // * STALE_BUFFER_SLOT - see above (second paragraph) - // - // Return of a negative value means an error has occurred: - // * BAD_VALUE - one of the following could've happened: - // * the buffer slot was invalid - // * the fence was NULL - // * the buffer slot specified is not in the acquired state - virtual status_t releaseBuffer(int buf, uint64_t frameNumber, const sp<Fence>& releaseFence) = 0; - - // consumerConnect connects a consumer to the BufferQueue. Only one - // consumer may be connected, and when that consumer disconnects the - // BufferQueue is placed into the "abandoned" state, causing most - // interactions with the BufferQueue by the producer to fail. - // controlledByApp indicates whether the consumer is controlled by - // the application. - // - // consumer may not be NULL. - // - // Return of a value other than NO_ERROR means an error has occurred: - // * NO_INIT - the buffer queue has been abandoned - // * BAD_VALUE - a NULL consumer was provided - virtual status_t consumerConnect(const sp<IConsumerListener>& consumer, bool controlledByApp) = 0; - - // consumerDisconnect disconnects a consumer from the BufferQueue. All - // buffers will be freed and the BufferQueue is placed in the "abandoned" - // state, causing most interactions with the BufferQueue by the producer to - // fail. - // - // Return of a value other than NO_ERROR means an error has occurred: - // * BAD_VALUE - no consumer is currently connected - virtual status_t consumerDisconnect() = 0; - - // getReleasedBuffers sets the value pointed to by slotMask to a bit set. - // Each bit index with a 1 corresponds to a released buffer slot with that - // index value. In particular, a released buffer is one that has - // been released by the BufferQueue but have not yet been released by the consumer. - // - // This should be called from the onBuffersReleased() callback. - // - // Return of a value other than NO_ERROR means an error has occurred: - // * NO_INIT - the buffer queue has been abandoned. - virtual status_t getReleasedBuffers(uint64_t* slotMask) = 0; - - // setDefaultBufferSize is used to set the size of buffers returned by - // dequeueBuffer when a width and height of zero is requested. Default - // is 1x1. - // - // Return of a value other than NO_ERROR means an error has occurred: - // * BAD_VALUE - either w or h was zero - virtual status_t setDefaultBufferSize(uint32_t w, uint32_t h) = 0; - - // setDefaultMaxBufferCount sets the default value for the maximum buffer - // count (the initial default is 2). If the producer has requested a - // buffer count using setBufferCount, the default buffer count will only - // take effect if the producer sets the count back to zero. - // - // The count must be between 2 and NUM_BUFFER_SLOTS, inclusive. - // - // Return of a value other than NO_ERROR means an error has occurred: - // * BAD_VALUE - bufferCount was out of range (see above). - virtual status_t setDefaultMaxBufferCount(int bufferCount) = 0; - - // disableAsyncBuffer disables the extra buffer used in async mode - // (when both producer and consumer have set their "isControlledByApp" - // flag) and has dequeueBuffer() return WOULD_BLOCK instead. - // - // This can only be called before consumerConnect(). - // - // Return of a value other than NO_ERROR means an error has occurred: - // * INVALID_OPERATION - attempting to call this after consumerConnect. - virtual status_t disableAsyncBuffer() = 0; - - // setMaxAcquiredBufferCount sets the maximum number of buffers that can - // be acquired by the consumer at one time (default 1). This call will - // fail if a producer is connected to the BufferQueue. - // - // maxAcquiredBuffers must be (inclusive) between 1 and MAX_MAX_ACQUIRED_BUFFERS. - // - // Return of a value other than NO_ERROR means an error has occurred: - // * BAD_VALUE - maxAcquiredBuffers was out of range (see above). - // * INVALID_OPERATION - attempting to call this after a producer connected. - virtual status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers) = 0; - - // setConsumerName sets the name used in logging - virtual void setConsumerName(const String8& name) = 0; - - // setDefaultBufferFormat allows the BufferQueue to create - // GraphicBuffers of a defaultFormat if no format is specified - // in dequeueBuffer. Formats are enumerated in graphics.h; the - // initial default is HAL_PIXEL_FORMAT_RGBA_8888. - // - // Return of a value other than NO_ERROR means an unknown error has occurred. - virtual status_t setDefaultBufferFormat(uint32_t defaultFormat) = 0; - - // setConsumerUsageBits will turn on additional usage bits for dequeueBuffer. - // These are merged with the bits passed to dequeueBuffer. The values are - // enumerated in gralloc.h, e.g. GRALLOC_USAGE_HW_RENDER; the default is 0. - // - // Return of a value other than NO_ERROR means an unknown error has occurred. - virtual status_t setConsumerUsageBits(uint32_t usage) = 0; - - // setTransformHint bakes in rotation to buffers so overlays can be used. - // The values are enumerated in window.h, e.g. - // NATIVE_WINDOW_TRANSFORM_ROT_90. The default is 0 (no transform). - // - // Return of a value other than NO_ERROR means an unknown error has occurred. - virtual status_t setTransformHint(uint32_t hint) = 0; - - // Retrieve the sideband buffer stream, if any. - virtual sp<NativeHandle> getSidebandStream() const = 0; - - // dump state into a string - virtual void dumpToString(String8& result, const char* prefix) const = 0; - - // Added by mozilla - virtual already_AddRefed<mozilla::layers::TextureClient> - getTextureClientFromBuffer(ANativeWindowBuffer* buffer) = 0; - - virtual int getSlotFromTextureClientLocked(mozilla::layers::TextureClient* client) const = 0; - -public: - DECLARE_META_INTERFACE(GonkGraphicBufferConsumer); -}; - -// ---------------------------------------------------------------------------- - -class BnGonkGraphicBufferConsumer : public BnInterface<IGonkGraphicBufferConsumer> -{ -public: - virtual status_t onTransact( uint32_t code, - const Parcel& data, - Parcel* reply, - uint32_t flags = 0); -}; - -// ---------------------------------------------------------------------------- -}; // namespace android - -#endif // ANDROID_GUI_IGONKGRAPHICBUFFERCONSUMER_H diff --git a/widget/gonk/nativewindow/moz.build b/widget/gonk/nativewindow/moz.build deleted file mode 100644 index fbcee601c..000000000 --- a/widget/gonk/nativewindow/moz.build +++ /dev/null @@ -1,104 +0,0 @@ -# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- -# vim: set filetype=python: -# Copyright 2013 Mozilla Foundation and Mozilla contributors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -EXPORTS += [ - 'GonkBufferQueue.h', - 'GonkNativeWindow.h', -] - -if CONFIG['ANDROID_VERSION'] >= '19': - EXPORTS += [ - 'IGonkGraphicBufferConsumer.h', - ] - -if CONFIG['ANDROID_VERSION'] >= '21': - EXPORTS += [ - 'GonkBufferQueueLL/GonkBufferQueueDefs.h', - 'GonkBufferQueueLL/GonkBufferQueueLL.h', - 'GonkBufferQueueLL/GonkBufferQueueProducer.h', - 'GonkBufferQueueLL/GonkBufferSlot.h', - 'GonkConsumerBaseLL.h', - 'GonkNativeWindowLL.h', - 'IGonkGraphicBufferConsumerLL.h', - ] -elif CONFIG['ANDROID_VERSION'] >= '19': - EXPORTS += [ - 'GonkBufferQueueKK.h', - 'GonkConsumerBaseKK.h', - 'GonkNativeWindowKK.h', - 'IGonkGraphicBufferConsumerKK.h', - ] -elif CONFIG['ANDROID_VERSION'] in ('17', '18'): - EXPORTS += [ - 'GonkBufferQueueJB.h', - 'GonkConsumerBaseJB.h', - 'GonkNativeWindowJB.h', - ] - -if CONFIG['MOZ_WEBRTC']: - if CONFIG['ANDROID_VERSION'] >= '21': - SOURCES += [ - 'GonkBufferQueueLL/GonkBufferItem.cpp', - 'GonkBufferQueueLL/GonkBufferQueueConsumer.cpp', - 'GonkBufferQueueLL/GonkBufferQueueCore.cpp', - 'GonkBufferQueueLL/GonkBufferQueueLL.cpp', - 'GonkBufferQueueLL/GonkBufferQueueProducer.cpp', - 'GonkBufferQueueLL/GonkBufferSlot.cpp', - 'GonkConsumerBaseLL.cpp', - 'GonkNativeWindowLL.cpp', - 'IGonkGraphicBufferConsumerLL.cpp', - ] - elif CONFIG['ANDROID_VERSION'] >= '19': - SOURCES += [ - 'GonkBufferQueueKK.cpp', - 'GonkConsumerBaseKK.cpp', - 'GonkNativeWindowKK.cpp', - 'IGonkGraphicBufferConsumerKK.cpp', - ] - elif CONFIG['ANDROID_VERSION'] in ('17', '18'): - SOURCES += [ - 'GonkBufferQueueJB.cpp', - 'GonkConsumerBaseJB.cpp', - 'GonkNativeWindowJB.cpp', - ] - -if CONFIG['ANDROID_VERSION'] >= '18': - SOURCES += [ - 'FakeSurfaceComposer.cpp', - ] - -include('/ipc/chromium/chromium-config.mozbuild') - -if CONFIG['ANDROID_VERSION'] >= '18': - LOCAL_INCLUDES += [ - '%' + '%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [ - 'frameworks/native/opengl/include', - ] - ] - -DEFINES['HAVE_ANDROID_OS'] = True - -# Suppress some GCC warnings being treated as errors: -# - about attributes on forward declarations for types that are already -# defined, which complains about an important MOZ_EXPORT for android::AString -if CONFIG['GNU_CC']: - CXXFLAGS += ['-Wno-error=attributes', '-Wno-overloaded-virtual'] - -FINAL_LIBRARY = 'xul' - -DISABLE_STL_WRAPPING = True - -NO_VISIBILITY_FLAGS = True |