summaryrefslogtreecommitdiffstats
path: root/widget/gonk/nativewindow/FakeSurfaceComposer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'widget/gonk/nativewindow/FakeSurfaceComposer.cpp')
-rw-r--r--widget/gonk/nativewindow/FakeSurfaceComposer.cpp703
1 files changed, 0 insertions, 703 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