diff options
Diffstat (limited to 'services/surfaceflinger')
25 files changed, 660 insertions, 85 deletions
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index 1eb2361..276a242 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -34,8 +34,8 @@ LOCAL_SRC_FILES := \ RenderEngine/Texture.cpp \ RenderEngine/GLES10RenderEngine.cpp \ RenderEngine/GLES11RenderEngine.cpp \ - RenderEngine/GLES20RenderEngine.cpp - + RenderEngine/GLES20RenderEngine.cpp \ + DisplayUtils.cpp LOCAL_CFLAGS := -DLOG_TAG=\"SurfaceFlinger\" LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES @@ -106,6 +106,17 @@ LOCAL_SHARED_LIBRARIES := \ libgui \ libpowermanager + +ifeq ($(TARGET_USES_QCOM_BSP), true) + LOCAL_WHOLE_STATIC_LIBRARIES += libexsurfaceflinger + LOCAL_C_INCLUDES += vendor/qcom/opensource/display-frameworks/native/services/surfaceflinger + LOCAL_C_INCLUDES += vendor/qcom/opensource/display-frameworks/include + LOCAL_C_INCLUDES += $(call project-path-for,qcom-display)/libgralloc + LOCAL_C_INCLUDES += $(call project-path-for,qcom-display)/libqdutils + LOCAL_SHARED_LIBRARIES += libqdutils + LOCAL_CFLAGS += -DQTI_BSP +endif + LOCAL_MODULE := libsurfaceflinger LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code diff --git a/services/surfaceflinger/DispSync.cpp b/services/surfaceflinger/DispSync.cpp index 3738a55..73b3897 100644 --- a/services/surfaceflinger/DispSync.cpp +++ b/services/surfaceflinger/DispSync.cpp @@ -21,6 +21,7 @@ #include <math.h> +#include <cutils/iosched_policy.h> #include <cutils/log.h> #include <ui/Fence.h> @@ -292,6 +293,7 @@ DispSync::DispSync() : mThread(new DispSyncThread()) { mThread->run("DispSync", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE); + android_set_rt_ioprio(mThread->getTid(), 1); reset(); beginResync(); diff --git a/services/surfaceflinger/DispSync.h b/services/surfaceflinger/DispSync.h index 67142b6..ebe19a5 100644 --- a/services/surfaceflinger/DispSync.h +++ b/services/surfaceflinger/DispSync.h @@ -26,11 +26,8 @@ namespace android { // Ignore present (retire) fences if the device doesn't have support for the -// sync framework, or if all phase offsets are zero. The latter is useful -// because it allows us to avoid resync bursts on devices that don't need -// phase-offset VSYNC events. -#if defined(RUNNING_WITHOUT_SYNC_FRAMEWORK) || \ - (VSYNC_EVENT_PHASE_OFFSET_NS == 0 && SF_VSYNC_EVENT_PHASE_OFFSET_NS == 0) +// sync framework. +#if defined(RUNNING_WITHOUT_SYNC_FRAMEWORK) static const bool kIgnorePresentFences = true; #else static const bool kIgnorePresentFences = false; diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 13d44f3..baff5ba 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -90,6 +90,7 @@ DisplayDevice::DisplayDevice( { mNativeWindow = new Surface(producer, false); ANativeWindow* const window = mNativeWindow.get(); + char property[PROPERTY_VALUE_MAX]; /* * Create our display's surface @@ -140,6 +141,11 @@ DisplayDevice::DisplayDevice( break; } + mPanelInverseMounted = false; + // Check if panel is inverse mounted (contents show up HV flipped) + property_get("persist.panel.inversemounted", property, "0"); + mPanelInverseMounted = !!atoi(property); + // initialize the display orientation transform. setProjection(DisplayState::eOrientationDefault, mViewport, mFrame); } @@ -402,6 +408,11 @@ status_t DisplayDevice::orientationToTransfrom( default: return BAD_VALUE; } + + if (DISPLAY_PRIMARY == mHwcDisplayId && isPanelInverseMounted()) { + flags = flags ^ Transform::ROT_180; + } + tr->set(flags, w, h); return NO_ERROR; } diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index 8695a44..f492a42 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -126,6 +126,10 @@ public: int32_t getHwcDisplayId() const { return mHwcDisplayId; } const wp<IBinder>& getDisplayToken() const { return mDisplayToken; } + bool isPanelInverseMounted() const { + return mPanelInverseMounted; + } + // We pass in mustRecompose so we can keep VirtualDisplaySurface's state // machine happy without actually queueing a buffer if nothing has changed status_t beginFrame(bool mustRecompose) const; @@ -209,7 +213,7 @@ private: /* * Transaction state */ - static status_t orientationToTransfrom(int orientation, + status_t orientationToTransfrom(int orientation, int w, int h, Transform* tr); uint32_t mLayerStack; @@ -226,6 +230,8 @@ private: int mPowerMode; // Current active config int mActiveConfig; + // Panel is inverse mounted + int mPanelInverseMounted; }; }; // namespace android diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 0859149..c57dd5f 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -190,6 +190,11 @@ HWComposer::HWComposer( // we don't have VSYNC support, we need to fake it mVSyncThread = new VSyncThread(*this); } + + mDimComp = 0; + if (mHwc) { + mHwc->query(mHwc, HWC_BACKGROUND_LAYER_SUPPORTED, &mDimComp); + } } HWComposer::~HWComposer() { @@ -368,7 +373,12 @@ status_t HWComposer::queryDisplayProperties(int disp) { return err; } - mDisplayData[disp].currentConfig = 0; + int currentConfig = getActiveConfig(disp); + if (currentConfig < 0 || currentConfig > static_cast<int>((numConfigs-1))) { + ALOGE("%s: Invalid display config! %d", __FUNCTION__, currentConfig); + currentConfig = 0; + } + mDisplayData[disp].currentConfig = currentConfig; for (size_t c = 0; c < numConfigs; ++c) { err = mHwc->getDisplayAttributes(mHwc, disp, configs[c], DISPLAY_ATTRIBUTES, values); @@ -716,6 +726,9 @@ status_t HWComposer::prepare() { if (l.compositionType == HWC_OVERLAY) { disp.hasOvComp = true; } + if (isCompositionTypeBlit(l.compositionType)) { + disp.hasFbComp = true; + } if (l.compositionType == HWC_CURSOR_OVERLAY) { disp.hasOvComp = true; } @@ -816,15 +829,31 @@ status_t HWComposer::setPowerMode(int disp, int mode) { status_t HWComposer::setActiveConfig(int disp, int mode) { LOG_FATAL_IF(disp >= VIRTUAL_DISPLAY_ID_BASE); DisplayData& dd(mDisplayData[disp]); - dd.currentConfig = mode; if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_4)) { - return (status_t)mHwc->setActiveConfig(mHwc, disp, mode); + status_t status = static_cast<status_t>( + mHwc->setActiveConfig(mHwc, disp, mode)); + if (status == NO_ERROR) { + dd.currentConfig = mode; + } else { + ALOGE("%s Failed to set new config (%d) for display (%d)", + __FUNCTION__, mode, disp); + } + return status; } else { LOG_FATAL_IF(mode != 0); } return NO_ERROR; } +int HWComposer::getActiveConfig(int disp) const { + LOG_FATAL_IF(disp >= VIRTUAL_DISPLAY_ID_BASE); + if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_4)) { + return mHwc->getActiveConfig(mHwc, disp); + } else { + return 0; + } +} + void HWComposer::disconnectDisplay(int disp) { LOG_ALWAYS_FATAL_IF(disp < 0 || disp == HWC_DISPLAY_PRIMARY); DisplayData& dd(mDisplayData[disp]); @@ -998,6 +1027,10 @@ public: getLayer()->flags &= ~HWC_SKIP_LAYER; } } + virtual void setDim() { + setSkip(false); + getLayer()->flags |= 0x80000000; + } virtual void setIsCursorLayerHint(bool isCursor) { if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_4)) { if (isCursor) { @@ -1233,7 +1266,7 @@ void HWComposer::dump(String8& result) const { if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) { result.appendFormat( " %9s | %08" PRIxPTR " | %04x | %04x | %02x | %04x | %-11s |%7.1f,%7.1f,%7.1f,%7.1f |%5d,%5d,%5d,%5d | %s\n", - compositionTypeName[type], + (isCompositionTypeBlit(l.compositionType)) ? "HWC_BLIT" : compositionTypeName[type], intptr_t(l.handle), l.hints, l.flags, l.transform, l.blending, formatStr.string(), l.sourceCropf.left, l.sourceCropf.top, l.sourceCropf.right, l.sourceCropf.bottom, l.displayFrame.left, l.displayFrame.top, l.displayFrame.right, l.displayFrame.bottom, @@ -1241,7 +1274,7 @@ void HWComposer::dump(String8& result) const { } else { result.appendFormat( " %9s | %08" PRIxPTR " | %04x | %04x | %02x | %04x | %-11s |%7d,%7d,%7d,%7d |%5d,%5d,%5d,%5d | %s\n", - compositionTypeName[type], + (isCompositionTypeBlit(l.compositionType)) ? "HWC_BLIT" : compositionTypeName[type], intptr_t(l.handle), l.hints, l.flags, l.transform, l.blending, formatStr.string(), l.sourceCrop.left, l.sourceCrop.top, l.sourceCrop.right, l.sourceCrop.bottom, l.displayFrame.left, l.displayFrame.top, l.displayFrame.right, l.displayFrame.bottom, diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index 5e0b3d8..862288f 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -74,7 +74,7 @@ public: const sp<SurfaceFlinger>& flinger, EventHandler& handler); - ~HWComposer(); + virtual ~HWComposer(); status_t initCheck() const; @@ -103,6 +103,9 @@ public: // set active config status_t setActiveConfig(int disp, int mode); + // get active config + int getActiveConfig(int disp) const; + // reset state when an external, non-virtual display is disconnected void disconnectDisplay(int disp); @@ -117,6 +120,9 @@ public: // does this display have layers handled by GLES bool hasGlesComposition(int32_t id) const; + // does this display support dim layer composition + bool hasDimComposition() const { return (mDimComp == 1); } + // get the releaseFence file descriptor for a display's framebuffer layer. // the release fence is only valid after commit() sp<Fence> getAndResetReleaseFence(int32_t id); @@ -162,6 +168,7 @@ public: virtual sp<Fence> getAndResetReleaseFence() = 0; virtual void setDefaultState() = 0; virtual void setSkip(bool skip) = 0; + virtual void setDim() = 0; virtual void setIsCursorLayerHint(bool isCursor = true) = 0; virtual void setBlending(uint32_t blending) = 0; virtual void setTransform(uint32_t transform) = 0; @@ -302,6 +309,14 @@ public: // for debugging ---------------------------------------------------------- void dump(String8& out) const; + /* ------------------------------------------------------------------------ + * Extensions + */ + virtual inline bool isVDSEnabled() const { return true; }; + virtual inline bool isCompositionTypeBlit(const int32_t /*compType*/) const { + return false; + }; + private: void loadHwcModule(); int loadFbHalModule(); @@ -372,6 +387,8 @@ private: // thread-safe mutable Mutex mEventControlLock; + + int mDimComp; }; // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp index ba4c198..1e4f907 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp @@ -152,7 +152,7 @@ status_t VirtualDisplaySurface::prepareFrame(CompositionType compositionType) { // format/usage and get a new buffer when the GLES driver calls // dequeueBuffer(). mOutputFormat = mDefaultOutputFormat; - mOutputUsage = GRALLOC_USAGE_HW_COMPOSER; + setOutputUsage(GRALLOC_USAGE_HW_COMPOSER); refreshOutputBuffer(); } @@ -377,7 +377,7 @@ status_t VirtualDisplaySurface::dequeueBuffer(int* pslot, sp<Fence>* fence, bool mSinkBufferWidth, mSinkBufferHeight, buf->getPixelFormat(), buf->getUsage()); mOutputFormat = format; - mOutputUsage = usage; + setOutputUsage(usage); result = refreshOutputBuffer(); if (result < 0) return result; @@ -616,6 +616,10 @@ const char* VirtualDisplaySurface::dbgSourceStr(Source s) { } } +void VirtualDisplaySurface::setOutputUsage(uint32_t usage) { + mOutputUsage = usage; +} + // --------------------------------------------------------------------------- } // namespace android // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h index 6298751..3d0e412 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h @@ -72,6 +72,10 @@ class VirtualDisplaySurface : public DisplaySurface, public BnGraphicBufferProducer, private ConsumerBase { public: +#ifdef QTI_BSP + friend class ExVirtualDisplaySurface; +#endif + VirtualDisplaySurface(HWComposer& hwc, int32_t dispId, const sp<IGraphicBufferProducer>& sink, const sp<IGraphicBufferProducer>& bqProducer, @@ -118,6 +122,7 @@ private: virtual status_t allowAllocation(bool allow); virtual status_t setGenerationNumber(uint32_t generationNumber); virtual String8 getConsumerName() const override; + virtual void setOutputUsage(uint32_t flag); // // Utility methods diff --git a/services/surfaceflinger/DisplayUtils.cpp b/services/surfaceflinger/DisplayUtils.cpp new file mode 100644 index 0000000..1f4c21c --- /dev/null +++ b/services/surfaceflinger/DisplayUtils.cpp @@ -0,0 +1,173 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdlib.h> +#include <stdint.h> +#include <sys/types.h> + +#include <utils/Errors.h> +#include <utils/Log.h> + +#include <gui/Surface.h> +#include <ui/GraphicBuffer.h> + +#include "RenderEngine/RenderEngine.h" +#include "DisplayHardware/FramebufferSurface.h" +#include "DisplayUtils.h" +#ifdef QTI_BSP +#include <ExSurfaceFlinger.h> +#include <ExLayer.h> +#include <DisplayHardware/ExHWComposer.h> +#include <DisplayHardware/ExVirtualDisplaySurface.h> +#endif +#include <dlfcn.h> +#include <cutils/properties.h> + +namespace android { + +DisplayUtils* DisplayUtils::sDisplayUtils = NULL; +bool DisplayUtils::sUseExtendedImpls = false; + +DisplayUtils::DisplayUtils() { +#ifdef QTI_BSP + sUseExtendedImpls = true; +#endif +} + +DisplayUtils* DisplayUtils::getInstance() { + if(sDisplayUtils == NULL) { + sDisplayUtils = new DisplayUtils(); + } + return sDisplayUtils; +} + +SurfaceFlinger* DisplayUtils::getSFInstance() { +#ifdef QTI_BSP + if(sUseExtendedImpls) { + return new ExSurfaceFlinger(); + } +#endif + return new SurfaceFlinger(); +} + +Layer* DisplayUtils::getLayerInstance(SurfaceFlinger* flinger, + const sp<Client>& client, const String8& name, + uint32_t w, uint32_t h, uint32_t flags) { +#ifdef QTI_BSP + if(sUseExtendedImpls) { + return new ExLayer(flinger, client, name, w, h, flags); + } +#endif + return new Layer(flinger, client, name, w, h, flags); +} + +HWComposer* DisplayUtils::getHWCInstance( + const sp<SurfaceFlinger>& flinger, + HWComposer::EventHandler& handler) { +#ifdef QTI_BSP + if(sUseExtendedImpls) { + return new ExHWComposer(flinger, handler); + } +#endif + return new HWComposer(flinger,handler); +} + +void DisplayUtils::initVDSInstance(HWComposer* hwc, int32_t hwcDisplayId, + sp<IGraphicBufferProducer> currentStateSurface, sp<DisplaySurface> &dispSurface, + sp<IGraphicBufferProducer> &producer, sp<IGraphicBufferProducer> bqProducer, + sp<IGraphicBufferConsumer> bqConsumer, String8 currentStateDisplayName, + bool currentStateIsSecure, int currentStateType) +{ +#ifdef QTI_BSP + if(sUseExtendedImpls) { + if(hwc->isVDSEnabled()) { + VirtualDisplaySurface* vds = new ExVirtualDisplaySurface(*hwc, hwcDisplayId, + currentStateSurface, bqProducer, bqConsumer, currentStateDisplayName, + currentStateIsSecure); + dispSurface = vds; + producer = vds; + } else if(!createV4L2BasedVirtualDisplay(hwc, hwcDisplayId, dispSurface, producer, + currentStateSurface, bqProducer, bqConsumer, currentStateType)) { + VirtualDisplaySurface* vds = new VirtualDisplaySurface(*hwc, hwcDisplayId, + currentStateSurface, bqProducer, bqConsumer, currentStateDisplayName); + dispSurface = vds; + producer = vds; + } + } else { +#endif + (void)currentStateIsSecure; + (void)currentStateType; + VirtualDisplaySurface* vds = new VirtualDisplaySurface(*hwc, hwcDisplayId, + currentStateSurface, bqProducer, bqConsumer, currentStateDisplayName); + dispSurface = vds; + producer = vds; +#ifdef QTI_BSP + } +#endif +} + +bool DisplayUtils::createV4L2BasedVirtualDisplay(HWComposer* hwc, int32_t &hwcDisplayId, + sp<DisplaySurface> &dispSurface, sp<IGraphicBufferProducer> &producer, + sp<IGraphicBufferProducer> currentStateSurface, + sp<IGraphicBufferProducer> bqProducer, sp<IGraphicBufferConsumer> bqConsumer, + int currentStateType) { + char value[PROPERTY_VALUE_MAX]; + property_get("persist.sys.wfd.virtual", value, "0"); + int wfdVirtual = atoi(value); + if(wfdVirtual && hwcDisplayId > 0) { + //Read virtual display properties and create a + //rendering surface for it inorder to be handled + //by hwc. + + sp<ANativeWindow> mNativeWindow = new Surface(currentStateSurface); + ANativeWindow* const window = mNativeWindow.get(); + + int format; + window->query(window, NATIVE_WINDOW_FORMAT, &format); + EGLSurface surface; + EGLint w, h; + EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + // In M AOSP getEGLConfig() always returns EGL_NO_CONFIG as + // EGL_ANDROIDX_no_config_context active now. + EGLConfig config = RenderEngine::chooseEglConfig(display, format); + + surface = eglCreateWindowSurface(display, config, window, NULL); + eglQuerySurface(display, surface, EGL_WIDTH, &w); + eglQuerySurface(display, surface, EGL_HEIGHT, &h); + if(hwc->setVirtualDisplayProperties(hwcDisplayId, w, h, format) != NO_ERROR) + return false; + + dispSurface = new FramebufferSurface(*hwc, currentStateType, bqConsumer); + producer = bqProducer; + return true; + } + return false; +} + +}; // namespace android + diff --git a/services/surfaceflinger/DisplayUtils.h b/services/surfaceflinger/DisplayUtils.h new file mode 100644 index 0000000..cdf2b67 --- /dev/null +++ b/services/surfaceflinger/DisplayUtils.h @@ -0,0 +1,78 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ANDROID_DISPLAY_UTILS_H +#define ANDROID_DISPLAY_UTILS_H + +#include <stdint.h> +#include <sys/types.h> + +#include "Layer.h" +#include "SurfaceFlinger.h" +#include "DisplayHardware/HWComposer.h" +#include "DisplayHardware/VirtualDisplaySurface.h" + +// --------------------------------------------------------------------------- + +namespace android { + +class IGraphicBufferProducer; +class IGraphicBufferConsumer; +class DisplaySurface; + +/* Factory Classes */ + +class DisplayUtils { + public: + static DisplayUtils* getInstance() ANDROID_API; + SurfaceFlinger* getSFInstance() ANDROID_API; + Layer* getLayerInstance(SurfaceFlinger*, const sp<Client>&, + const String8&, uint32_t, + uint32_t, uint32_t); + HWComposer* getHWCInstance(const sp<SurfaceFlinger>& flinger, + HWComposer::EventHandler& handler); + void initVDSInstance(HWComposer* hwc, int32_t hwcDisplayId, + sp<IGraphicBufferProducer> currentStateSurface, sp<DisplaySurface> &dispSurface, + sp<IGraphicBufferProducer> &producer, sp<IGraphicBufferProducer> bqProducer, + sp<IGraphicBufferConsumer> bqConsumer, String8 currentStateDisplayName, + bool currentStateIsSecure, int currentStateType); + DisplayUtils(); + private: + static DisplayUtils* sDisplayUtils; + static bool sUseExtendedImpls; + + bool createV4L2BasedVirtualDisplay(HWComposer* hwc, int32_t &hwcDisplayId, + sp<DisplaySurface> &dispSurface, sp<IGraphicBufferProducer> &producer, + sp<IGraphicBufferProducer> currentStateSurface, + sp<IGraphicBufferProducer> bqProducer, + sp<IGraphicBufferConsumer> bqConsumer, int currentStateType); +}; + +}; // namespace android + +#endif // ANDROID_DISPLAY_UTILS_H diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp index f760200..973a8bc 100644 --- a/services/surfaceflinger/EventThread.cpp +++ b/services/surfaceflinger/EventThread.cpp @@ -20,6 +20,7 @@ #include <sys/types.h> #include <cutils/compiler.h> +#include <cutils/iosched_policy.h> #include <gui/BitTube.h> #include <gui/IDisplayEventConnection.h> @@ -91,6 +92,7 @@ void EventThread::sendVsyncHintOnLocked() { void EventThread::onFirstRef() { run("EventThread", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE); + android_set_rt_ioprio(getTid(), 1); } sp<EventThread::Connection> EventThread::createEventConnection() const { diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 5ff79a9..bcd5915 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -320,7 +320,7 @@ Rect Layer::getContentCrop() const { return crop; } -static Rect reduce(const Rect& win, const Region& exclude) { +Rect Layer::reduce(const Rect& win, const Region& exclude) const{ if (CC_LIKELY(exclude.isEmpty())) { return win; } @@ -494,6 +494,7 @@ void Layer::setGeometry( frame.intersect(hw->getViewport(), &frame); const Transform& tr(hw->getTransform()); layer.setFrame(tr.transform(frame)); + setPosition(hw, layer, s); layer.setCrop(computeCrop(hw)); layer.setPlaneAlpha(s.alpha); @@ -578,6 +579,7 @@ void Layer::setAcquireFence(const sp<const DisplayDevice>& /* hw */, } } } + setAcquiredFenceIfBlit(fenceFd, layer); layer.setAcquireFenceFd(fenceFd); } @@ -664,7 +666,7 @@ void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip, RenderEngine& engine(mFlinger->getRenderEngine()); - if (!blackOutLayer) { + if (!blackOutLayer || canAllowGPUForProtected()) { // TODO: we could be more subtle with isFixedSize() const bool useFiltering = getFiltering() || needsFiltering(hw) || isFixedSize(); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index c1e5e9f..c0c8bf5 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -71,6 +71,9 @@ class Layer : public SurfaceFlingerConsumer::ContentsChangedListener { static int32_t sSequence; public: +#ifdef QTI_BSP + friend class ExLayer; +#endif mutable bool contentDirty; // regions below are in window-manager space Region visibleRegion; @@ -204,7 +207,7 @@ public: void setGeometry(const sp<const DisplayDevice>& hw, HWComposer::HWCLayerInterface& layer); - void setPerFrameData(const sp<const DisplayDevice>& hw, + virtual void setPerFrameData(const sp<const DisplayDevice>& hw, HWComposer::HWCLayerInterface& layer); void setAcquireFence(const sp<const DisplayDevice>& hw, HWComposer::HWCLayerInterface& layer); @@ -285,6 +288,21 @@ public: // the current orientation of the display device. void updateTransformHint(const sp<const DisplayDevice>& hw) const; + /* ------------------------------------------------------------------------ + * Extensions + */ + virtual bool isExtOnly() const { return false; } + virtual bool isIntOnly() const { return false; } + virtual bool isSecureDisplay() const { return false; } + virtual bool isYuvLayer() const { return false; } + virtual void setPosition(const sp<const DisplayDevice>& /*hw*/, + HWComposer::HWCLayerInterface& /*layer*/, + const State& /*state*/) { } + virtual void setAcquiredFenceIfBlit(int& /*fenceFd */, + HWComposer::HWCLayerInterface& /*layer */) { } + virtual bool canAllowGPUForProtected() const { return false; } + + /* * returns the rectangle that crops the content of the layer and scales it * to the layer's size. @@ -336,6 +354,7 @@ protected: LayerCleaner(const sp<SurfaceFlinger>& flinger, const sp<Layer>& layer); }; + Rect reduce(const Rect& win, const Region& exclude) const; private: // Interface implementation for SurfaceFlingerConsumer::ContentsChangedListener diff --git a/services/surfaceflinger/LayerDim.cpp b/services/surfaceflinger/LayerDim.cpp index 14aa328..b8d549a 100644 --- a/services/surfaceflinger/LayerDim.cpp +++ b/services/surfaceflinger/LayerDim.cpp @@ -58,6 +58,15 @@ bool LayerDim::isVisible() const { return !(s.flags & layer_state_t::eLayerHidden) && s.alpha; } +void LayerDim::setPerFrameData(const sp<const DisplayDevice>& hw, + HWComposer::HWCLayerInterface& layer) { + HWComposer& hwc = mFlinger->getHwComposer(); + + Layer::setPerFrameData(hw, layer); + if (hwc.hasDimComposition()) { + layer.setDim(); + } +} // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/LayerDim.h b/services/surfaceflinger/LayerDim.h index a0cfca9..b66591b 100644 --- a/services/surfaceflinger/LayerDim.h +++ b/services/surfaceflinger/LayerDim.h @@ -40,6 +40,8 @@ public: virtual bool isSecure() const { return false; } virtual bool isFixedSize() const { return true; } virtual bool isVisible() const; + virtual void setPerFrameData(const sp<const DisplayDevice>& hw, + HWComposer::HWCLayerInterface& layer); }; // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp index 1a9f59b..853a4eb 100644 --- a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp @@ -92,14 +92,29 @@ void GLES11RenderEngine::setViewportAndProjection( case Transform::ROT_0: break; case Transform::ROT_90: - glRotatef(90, 0, 0, 1); + { + float x1 = (l+r)/2; + float y1 = (t+b)/2; + glTranslatef(x1-y1, x1+y1, 0); + glRotatef(270, 0, 0, 1); break; + } case Transform::ROT_180: + { + float x1 = (l+r)/2; + float y1 = (t+b)/2; + glTranslatef(x1*2, y1*2, 0); glRotatef(180, 0, 0, 1); break; + } case Transform::ROT_270: - glRotatef(270, 0, 0, 1); + { + float x1 = (l+r)/2; + float y1 = (t+b)/2; + glTranslatef(x1+y1, y1-x1, 0); + glRotatef(90, 0, 0, 1); break; + } default: break; } @@ -210,28 +225,46 @@ void GLES11RenderEngine::disableBlending() { } void GLES11RenderEngine::bindImageAsFramebuffer(EGLImageKHR image, - uint32_t* texName, uint32_t* fbName, uint32_t* status) { + uint32_t* texName, uint32_t* fbName, uint32_t* status, + bool useReadPixels, int reqWidth, int reqHeight) { GLuint tname, name; - // turn our EGLImage into a texture - glGenTextures(1, &tname); - glBindTexture(GL_TEXTURE_2D, tname); - glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image); - - // create a Framebuffer Object to render into - glGenFramebuffersOES(1, &name); - glBindFramebufferOES(GL_FRAMEBUFFER_OES, name); - glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, - GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, tname, 0); + if (!useReadPixels) { + // turn our EGLImage into a texture + glGenTextures(1, &tname); + glBindTexture(GL_TEXTURE_2D, tname); + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image); + + // create a Framebuffer Object to render into + glGenFramebuffersOES(1, &name); + glBindFramebufferOES(GL_FRAMEBUFFER_OES, name); + glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, + GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, tname, 0); + } else { + // since we're going to use glReadPixels() anyways, + // use an intermediate renderbuffer instead + glGenRenderbuffersOES(1, &tname); + glBindRenderbufferOES(GL_RENDERBUFFER_OES, tname); + glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_RGBA8_OES, reqWidth, reqHeight); + // create a FBO to render into + glGenFramebuffersOES(1, &name); + glBindFramebufferOES(GL_FRAMEBUFFER_OES, name); + glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, + GL_RENDERBUFFER_OES, tname); + } *status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES); *texName = tname; *fbName = name; } -void GLES11RenderEngine::unbindFramebuffer(uint32_t texName, uint32_t fbName) { +void GLES11RenderEngine::unbindFramebuffer(uint32_t texName, uint32_t fbName, + bool useReadPixels) { glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0); glDeleteFramebuffersOES(1, &fbName); - glDeleteTextures(1, &texName); + if (!useReadPixels) + glDeleteTextures(1, &texName); + else + glDeleteRenderbuffersOES(1, &texName); } void GLES11RenderEngine::setupFillWithColor(float r, float g, float b, float a) { diff --git a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h index 08de646..77824ce 100644 --- a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h @@ -40,8 +40,9 @@ class GLES11RenderEngine : public RenderEngine { GLint mMaxTextureSize; virtual void bindImageAsFramebuffer(EGLImageKHR image, - uint32_t* texName, uint32_t* fbName, uint32_t* status); - virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName); + uint32_t* texName, uint32_t* fbName, uint32_t* status, bool useReadPixels, + int reqWidth, int reqHeight); + virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName, bool useReadPixels); public: GLES11RenderEngine(); diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp index 1fabaf5..a35aa78 100644 --- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp @@ -185,27 +185,44 @@ void GLES20RenderEngine::disableBlending() { void GLES20RenderEngine::bindImageAsFramebuffer(EGLImageKHR image, - uint32_t* texName, uint32_t* fbName, uint32_t* status) { + uint32_t* texName, uint32_t* fbName, uint32_t* status, + bool useReadPixels, int reqWidth, int reqHeight) { GLuint tname, name; - // turn our EGLImage into a texture - glGenTextures(1, &tname); - glBindTexture(GL_TEXTURE_2D, tname); - glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image); - - // create a Framebuffer Object to render into - glGenFramebuffers(1, &name); - glBindFramebuffer(GL_FRAMEBUFFER, name); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tname, 0); + if (!useReadPixels) { + // turn our EGLImage into a texture + glGenTextures(1, &tname); + glBindTexture(GL_TEXTURE_2D, tname); + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image); + + // create a Framebuffer Object to render into + glGenFramebuffers(1, &name); + glBindFramebuffer(GL_FRAMEBUFFER, name); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tname, 0); + } else { + // since we're going to use glReadPixels() anyways, + // use an intermediate renderbuffer instead + glGenRenderbuffers(1, &tname); + glBindRenderbuffer(GL_RENDERBUFFER, tname); + glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8_OES, reqWidth, reqHeight); + // create a FBO to render into + glGenFramebuffers(1, &name); + glBindFramebuffer(GL_FRAMEBUFFER, name); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, tname); + } *status = glCheckFramebufferStatus(GL_FRAMEBUFFER); *texName = tname; *fbName = name; } -void GLES20RenderEngine::unbindFramebuffer(uint32_t texName, uint32_t fbName) { +void GLES20RenderEngine::unbindFramebuffer(uint32_t texName, uint32_t fbName, + bool useReadPixels) { glBindFramebuffer(GL_FRAMEBUFFER, 0); glDeleteFramebuffers(1, &fbName); - glDeleteTextures(1, &texName); + if (!useReadPixels) + glDeleteTextures(1, &texName); + else + glDeleteRenderbuffers(1, &texName); } void GLES20RenderEngine::setupFillWithColor(float r, float g, float b, float a) { diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h index 819356a..6074a3d 100644 --- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h @@ -55,8 +55,9 @@ class GLES20RenderEngine : public RenderEngine { Vector<Group> mGroupStack; virtual void bindImageAsFramebuffer(EGLImageKHR image, - uint32_t* texName, uint32_t* fbName, uint32_t* status); - virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName); + uint32_t* texName, uint32_t* fbName, uint32_t* status, + bool useReadPixels, int reqWidth, int reqHeight); + virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName, bool useReadPixels); public: GLES20RenderEngine(); diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp index 7cd42e4..cb1d14c 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp @@ -83,7 +83,6 @@ RenderEngine* RenderEngine::create(EGLDisplay display, int hwcFormat) { EGL_CONTEXT_CLIENT_VERSION, contextClientVersion, // MUST be first #ifdef EGL_IMG_context_priority #ifdef HAS_CONTEXT_PRIORITY -#warning "using EGL_IMG_context_priority" EGL_CONTEXT_PRIORITY_LEVEL_IMG, EGL_CONTEXT_PRIORITY_HIGH_IMG, #endif #endif @@ -262,9 +261,11 @@ void RenderEngine::dump(String8& result) { // --------------------------------------------------------------------------- RenderEngine::BindImageAsFramebuffer::BindImageAsFramebuffer( - RenderEngine& engine, EGLImageKHR image) : mEngine(engine) + RenderEngine& engine, EGLImageKHR image, bool useReadPixels, + int reqWidth, int reqHeight) : mEngine(engine), mUseReadPixels(useReadPixels) { - mEngine.bindImageAsFramebuffer(image, &mTexName, &mFbName, &mStatus); + mEngine.bindImageAsFramebuffer(image, &mTexName, &mFbName, &mStatus, + useReadPixels, reqWidth, reqHeight); ALOGE_IF(mStatus != GL_FRAMEBUFFER_COMPLETE_OES, "glCheckFramebufferStatusOES error %d", mStatus); @@ -272,7 +273,7 @@ RenderEngine::BindImageAsFramebuffer::BindImageAsFramebuffer( RenderEngine::BindImageAsFramebuffer::~BindImageAsFramebuffer() { // back to main framebuffer - mEngine.unbindFramebuffer(mTexName, mFbName); + mEngine.unbindFramebuffer(mTexName, mFbName, mUseReadPixels); } status_t RenderEngine::BindImageAsFramebuffer::getStatus() const { diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h index 31a961e..c9a043a 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/RenderEngine.h @@ -51,8 +51,11 @@ class RenderEngine { EGLContext mEGLContext; void setEGLHandles(EGLConfig config, EGLContext ctxt); - virtual void bindImageAsFramebuffer(EGLImageKHR image, uint32_t* texName, uint32_t* fbName, uint32_t* status) = 0; - virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName) = 0; + virtual void bindImageAsFramebuffer(EGLImageKHR image, uint32_t* texName, + uint32_t* fbName, uint32_t* status, bool useReadPixels, int reqWidth, + int reqHeight) = 0; + virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName, + bool useReadPixels) = 0; protected: RenderEngine(); @@ -83,8 +86,10 @@ public: RenderEngine& mEngine; uint32_t mTexName, mFbName; uint32_t mStatus; + bool mUseReadPixels; public: - BindImageAsFramebuffer(RenderEngine& engine, EGLImageKHR image); + BindImageAsFramebuffer(RenderEngine& engine, EGLImageKHR image, + bool useReadPixels, int reqWidth, int reqHeight); ~BindImageAsFramebuffer(); int getStatus() const; }; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index fdc3650..fc99fa0 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -27,6 +27,7 @@ #include <EGL/egl.h> #include <cutils/log.h> +#include <cutils/iosched_policy.h> #include <cutils/properties.h> #include <binder/IPCThreadState.h> @@ -77,6 +78,7 @@ #include "RenderEngine/RenderEngine.h" #include <cutils/compiler.h> +#include "DisplayUtils.h" #define DISPLAY_COUNT 1 @@ -122,6 +124,8 @@ const String16 sAccessSurfaceFlinger("android.permission.ACCESS_SURFACE_FLINGER" const String16 sReadFramebuffer("android.permission.READ_FRAME_BUFFER"); const String16 sDump("android.permission.DUMP"); +static sp<Layer> lastSurfaceViewLayer; + // --------------------------------------------------------------------------- SurfaceFlinger::SurfaceFlinger() @@ -456,7 +460,7 @@ void SurfaceFlinger::init() { // Initialize the H/W composer object. There may or may not be an // actual hardware composer underneath. - mHwc = new HWComposer(this, + mHwc = DisplayUtils::getInstance()->getHWCInstance(this, *static_cast<HWComposer::EventHandler *>(this)); // get a RenderEngine for the given display / config (can't fail) @@ -497,6 +501,13 @@ void SurfaceFlinger::init() { ALOGD("marking display %zu as acquired/unblanked", i); hw->setPowerMode(HWC_POWER_MODE_NORMAL); } + // When a non-virtual display device is added at boot time, + // update the active config by querying HWC otherwise the + // default config (config 0) will be used. + int activeConfig = mHwc->getActiveConfig(hwcId); + if (activeConfig >= 0) { + hw->setActiveConfig(activeConfig); + } mDisplays.add(token, hw); } } @@ -507,6 +518,7 @@ void SurfaceFlinger::init() { mEventControlThread = new EventControlThread(this); mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY); + android_set_rt_ioprio(mEventControlThread->getTid(), 1); // set a fake vsync period if there is no HWComposer if (mHwc->initCheck() != NO_ERROR) { @@ -695,8 +707,10 @@ void SurfaceFlinger::setActiveConfigInternal(const sp<DisplayDevice>& hw, int mo return; } - hw->setActiveConfig(mode); - getHwComposer().setActiveConfig(type, mode); + status_t status = getHwComposer().setActiveConfig(type, mode); + if (status == NO_ERROR) { + hw->setActiveConfig(mode); + } } status_t SurfaceFlinger::setActiveConfig(const sp<IBinder>& display, int mode) { @@ -869,6 +883,7 @@ void SurfaceFlinger::onHotplugReceived(int type, bool connected) { } else { mCurrentState.displays.removeItem(mBuiltinDisplays[type]); mBuiltinDisplays[type].clear(); + updateVisibleRegionsDirty(); } setTransactionFlags(eDisplayTransactionNeeded); @@ -1067,6 +1082,7 @@ void SurfaceFlinger::postComposition() } void SurfaceFlinger::rebuildLayerStacks() { + updateExtendedMode(); // rebuild the visible layer list per screen if (CC_UNLIKELY(mVisibleRegionsDirty)) { ATRACE_CALL(); @@ -1082,14 +1098,13 @@ void SurfaceFlinger::rebuildLayerStacks() { const Transform& tr(hw->getTransform()); const Rect bounds(hw->getBounds()); if (hw->isDisplayOn()) { - SurfaceFlinger::computeVisibleRegions(layers, + computeVisibleRegions(hw->getHwcDisplayId(), layers, hw->getLayerStack(), dirtyRegion, opaqueRegion); const size_t count = layers.size(); for (size_t i=0 ; i<count ; i++) { const sp<Layer>& layer(layers[i]); - const Layer::State& s(layer->getDrawingState()); - if (s.layerStack == hw->getLayerStack()) { + { Region drawRegion(tr.transform( layer->visibleNonTransparentRegion)); drawRegion.andSelf(bounds); @@ -1169,6 +1184,8 @@ void SurfaceFlinger::setUpHWComposer() { sp<const DisplayDevice> hw(mDisplays[dpy]); const int32_t id = hw->getHwcDisplayId(); if (id >= 0) { + bool freezeSurfacePresent = false; + isfreezeSurfacePresent(freezeSurfacePresent, hw, id); const Vector< sp<Layer> >& currentLayers( hw->getVisibleLayersSortedByZ()); const size_t count = currentLayers.size(); @@ -1181,6 +1198,11 @@ void SurfaceFlinger::setUpHWComposer() { */ const sp<Layer>& layer(currentLayers[i]); layer->setPerFrameData(hw, *cur); + setOrientationEventControl(freezeSurfacePresent,id); + if(!strncmp(layer->getName(), "SurfaceView", + 11)) { + lastSurfaceViewLayer = layer; + } } } } @@ -1454,12 +1476,10 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) hwcDisplayId = allocateHwcDisplayId(state.type); } - sp<VirtualDisplaySurface> vds = new VirtualDisplaySurface( - *mHwc, hwcDisplayId, state.surface, - bqProducer, bqConsumer, state.displayName); + DisplayUtils::getInstance()->initVDSInstance(mHwc, hwcDisplayId, + state.surface, dispSurface, producer, bqProducer, bqConsumer, + state.displayName, state.isSecure, state.type); - dispSurface = vds; - producer = vds; } } else { ALOGE_IF(state.surface!=NULL, @@ -1475,7 +1495,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) } const wp<IBinder>& display(curr.keyAt(i)); - if (dispSurface != NULL) { + if (dispSurface != NULL && producer != NULL) { sp<DisplayDevice> hw = new DisplayDevice(this, state.type, hwcDisplayId, mHwc->getFormat(hwcDisplayId), state.isSecure, @@ -1485,6 +1505,16 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) hw->setProjection(state.orientation, state.viewport, state.frame); hw->setDisplayName(state.displayName); + // When a new display device is added update the active + // config by querying HWC otherwise the default config + // (config 0) will be used. + if (hwcDisplayId >= DisplayDevice::DISPLAY_PRIMARY && + hwcDisplayId < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) { + int activeConfig = mHwc->getActiveConfig(hwcDisplayId); + if (activeConfig >= 0) { + hw->setActiveConfig(activeConfig); + } + } mDisplays.add(display, hw); if (state.isVirtualDisplay()) { if (hwcDisplayId >= 0) { @@ -1643,7 +1673,7 @@ void SurfaceFlinger::commitTransaction() mTransactionCV.broadcast(); } -void SurfaceFlinger::computeVisibleRegions( +void SurfaceFlinger::computeVisibleRegions(size_t dpy, const LayerVector& currentLayers, uint32_t layerStack, Region& outDirtyRegion, Region& outOpaqueRegion) { @@ -1654,6 +1684,9 @@ void SurfaceFlinger::computeVisibleRegions( Region dirty; outDirtyRegion.clear(); + bool bIgnoreLayers = false; + int indexLOI = -1; + getIndexLOI(dpy, currentLayers, bIgnoreLayers, indexLOI); size_t i = currentLayers.size(); while (i--) { @@ -1662,8 +1695,9 @@ void SurfaceFlinger::computeVisibleRegions( // start with the whole surface at its current location const Layer::State& s(layer->getDrawingState()); - // only consider the layers on the given layer stack - if (s.layerStack != layerStack) + if(updateLayerVisibleNonTransparentRegion(dpy, layer, + bIgnoreLayers, indexLOI, + layerStack, i)) continue; /* @@ -1954,7 +1988,7 @@ bool SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const // screen is already cleared here if (!region.isEmpty()) { // can happen with SurfaceView - drawWormhole(hw, region); + drawWormHoleIfRequired(cur, end, hw, region); } } @@ -2096,6 +2130,8 @@ void SurfaceFlinger::setTransactionState( uint32_t flags) { ATRACE_CALL(); + + delayDPTransactionIfNeeded(displays); Mutex::Autolock _l(mStateLock); uint32_t transactionFlags = 0; @@ -2342,7 +2378,7 @@ status_t SurfaceFlinger::createNormalLayer(const sp<Client>& client, break; } - *outLayer = new Layer(this, client, name, w, h, flags); + *outLayer = DisplayUtils::getInstance()->getLayerInstance(this, client, name, w, h, flags); status_t err = (*outLayer)->setBuffers(w, h, format, flags); if (err == NO_ERROR) { *handle = (*outLayer)->getHandle(); @@ -2605,14 +2641,19 @@ void SurfaceFlinger::dumpStatsLocked(const Vector<String16>& args, size_t& index if (name.isEmpty()) { mAnimFrameTracker.dumpStats(result); } else { + bool found = false; const LayerVector& currentLayers = mCurrentState.layersSortedByZ; const size_t count = currentLayers.size(); for (size_t i=0 ; i<count ; i++) { const sp<Layer>& layer(currentLayers[i]); if (name == layer->getName()) { + found = true; layer->dumpFrameStats(result); } } + if (!found && !strncmp(name.string(), "SurfaceView", 11)) { + lastSurfaceViewLayer->dumpFrameStats(result); + } } } @@ -3155,7 +3196,8 @@ status_t SurfaceFlinger::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, ISurfaceComposer::Rotation rotation) { + bool useIdentityTransform, ISurfaceComposer::Rotation rotation, + bool useReadPixels) { if (CC_UNLIKELY(display == 0)) return BAD_VALUE; @@ -3205,6 +3247,7 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display, uint32_t minLayerZ,maxLayerZ; bool useIdentityTransform; Transform::orientation_flags rotation; + bool useReadPixels; status_t result; public: MessageCaptureScreen(SurfaceFlinger* flinger, @@ -3212,12 +3255,14 @@ status_t SurfaceFlinger::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, Transform::orientation_flags rotation) + bool useIdentityTransform, Transform::orientation_flags rotation, + bool useReadPixels) : flinger(flinger), display(display), producer(producer), sourceCrop(sourceCrop), reqWidth(reqWidth), reqHeight(reqHeight), minLayerZ(minLayerZ), maxLayerZ(maxLayerZ), useIdentityTransform(useIdentityTransform), rotation(rotation), + useReadPixels(useReadPixels), result(PERMISSION_DENIED) { } @@ -3227,9 +3272,10 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display, virtual bool handler() { Mutex::Autolock _l(flinger->mStateLock); sp<const DisplayDevice> hw(flinger->getDisplayDevice(display)); + bool useReadPixels = this->useReadPixels && !flinger->mGpuToCpuSupported; result = flinger->captureScreenImplLocked(hw, producer, sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ, - useIdentityTransform, rotation); + useIdentityTransform, rotation, useReadPixels); static_cast<GraphicProducerWrapper*>(IInterface::asBinder(producer).get())->exit(result); return true; } @@ -3252,7 +3298,7 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display, sp<MessageBase> msg = new MessageCaptureScreen(this, display, IGraphicBufferProducer::asInterface( wrapper ), sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ, - useIdentityTransform, rotationFlags); + useIdentityTransform, rotationFlags, useReadPixels); status_t res = postMessageAsync(msg); if (res == NO_ERROR) { @@ -3301,6 +3347,12 @@ void SurfaceFlinger::renderScreenImplLocked( // make sure to clear all GL error flags engine.checkErrors(); + if (DisplayDevice::DISPLAY_PRIMARY == hw->getDisplayType() && + hw->isPanelInverseMounted()) { + rotation = (Transform::orientation_flags) + (rotation ^ Transform::ROT_180); + } + // set-up our viewport engine.setViewportAndProjection( reqWidth, reqHeight, sourceCrop, hw_h, yswap, rotation); @@ -3316,7 +3368,7 @@ void SurfaceFlinger::renderScreenImplLocked( const Layer::State& state(layer->getDrawingState()); if (state.layerStack == hw->getLayerStack()) { if (state.z >= minLayerZ && state.z <= maxLayerZ) { - if (layer->isVisible()) { + if (canDrawLayerinScreenShot(hw,layer)) { if (filtering) layer->setFiltering(true); layer->draw(hw, useIdentityTransform); if (filtering) layer->setFiltering(false); @@ -3336,7 +3388,8 @@ status_t SurfaceFlinger::captureScreenImplLocked( const sp<IGraphicBufferProducer>& producer, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ, - bool useIdentityTransform, Transform::orientation_flags rotation) + bool useIdentityTransform, Transform::orientation_flags rotation, + bool useReadPixels) { ATRACE_CALL(); @@ -3388,7 +3441,8 @@ status_t SurfaceFlinger::captureScreenImplLocked( if (image != EGL_NO_IMAGE_KHR) { // this binds the given EGLImage as a framebuffer for the // duration of this scope. - RenderEngine::BindImageAsFramebuffer imageBond(getRenderEngine(), image); + RenderEngine::BindImageAsFramebuffer imageBond(getRenderEngine(), image, + useReadPixels, reqWidth, reqHeight); if (imageBond.getStatus() == NO_ERROR) { // this will in fact render into our dequeued buffer // via an FBO, which means we didn't have to create @@ -3435,6 +3489,15 @@ status_t SurfaceFlinger::captureScreenImplLocked( ALOGW("captureScreen: error creating EGL fence: %#x", eglGetError()); } } + if (useReadPixels) { + sp<GraphicBuffer> buf = static_cast<GraphicBuffer*>(buffer); + void* vaddr; + if (buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, &vaddr) == NO_ERROR) { + getRenderEngine().readPixels(0, 0, buffer->stride, reqHeight, + (uint32_t *)vaddr); + buf->unlock(); + } + } if (DEBUG_SCREENSHOTS) { uint32_t* pixels = new uint32_t[reqWidth*reqHeight]; getRenderEngine().readPixels(0, 0, reqWidth, reqHeight, pixels); @@ -3492,6 +3555,44 @@ void SurfaceFlinger::checkScreenshot(size_t w, size_t s, size_t h, void const* v } } +/* ------------------------------------------------------------------------ + * Extensions + */ + +bool SurfaceFlinger::updateLayerVisibleNonTransparentRegion(const int& /*dpy*/, + const sp<Layer>& layer, bool& /*bIgnoreLayers*/, int& /*indexLOI*/, + uint32_t layerStack, const int& /*i*/) { + + const Layer::State& s(layer->getDrawingState()); + + // only consider the layers on the given layer stack + if (s.layerStack != layerStack) { + /* set the visible region as empty since we have removed the + * layerstack check in rebuildLayerStack() function + */ + Region visibleNonTransRegion; + visibleNonTransRegion.set(Rect(0,0)); + layer->setVisibleNonTransparentRegion(visibleNonTransRegion); + + return true; + } + + return false; +} + +bool SurfaceFlinger::canDrawLayerinScreenShot( + const sp<const DisplayDevice>& /*hw*/, + const sp<Layer>& layer) { + return layer->isVisible(); +} + +void SurfaceFlinger::drawWormHoleIfRequired(HWComposer::LayerListIterator& /*cur*/, + const HWComposer::LayerListIterator& /*end*/, + const sp<const DisplayDevice>& hw, + const Region& region) { + drawWormhole(hw, region); +} + // --------------------------------------------------------------------------- SurfaceFlinger::LayerVector::LayerVector() { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index b3baadd..4bbb1f4 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -84,6 +84,10 @@ class SurfaceFlinger : public BnSurfaceComposer, private HWComposer::EventHandler { public: +#ifdef QTI_BSP + friend class ExSurfaceFlinger; +#endif + static char const* getServiceName() ANDROID_API { return "SurfaceFlinger"; } @@ -138,6 +142,7 @@ private: friend class Client; friend class DisplayEventConnection; friend class Layer; + friend class LayerDim; friend class MonitoredProducer; // This value is specified in number of frames. Log frame stats at most @@ -207,7 +212,8 @@ private: const sp<IGraphicBufferProducer>& producer, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ, - bool useIdentityTransform, ISurfaceComposer::Rotation rotation); + bool useIdentityTransform, ISurfaceComposer::Rotation rotation, + bool isCpuConsumer); virtual status_t getDisplayStats(const sp<IBinder>& display, DisplayStatInfo* stats); virtual status_t getDisplayConfigs(const sp<IBinder>& display, @@ -235,6 +241,43 @@ private: virtual void onHotplugReceived(int disp, bool connected); /* ------------------------------------------------------------------------ + * Extensions + */ + virtual void updateExtendedMode() { } + + virtual void getIndexLOI(size_t /*dpy*/, + const LayerVector& /*currentLayers*/, + bool& /*bIgnoreLayers*/, + int& /*indexLOI*/) { } + + virtual bool updateLayerVisibleNonTransparentRegion( + const int& dpy, const sp<Layer>& layer, + bool& bIgnoreLayers, int& indexLOI, + uint32_t layerStack, const int& i); + + virtual void delayDPTransactionIfNeeded( + const Vector<DisplayState>& /*displays*/) { } + + virtual bool canDrawLayerinScreenShot( + const sp<const DisplayDevice>& hw, + const sp<Layer>& layer); + + virtual void isfreezeSurfacePresent( + bool& freezeSurfacePresent, + const sp<const DisplayDevice>& /*hw*/, + const int32_t& /*id*/) { freezeSurfacePresent = false; } + + virtual void setOrientationEventControl( + bool& /*freezeSurfacePresent*/, + const int32_t& /*id*/) { } + + virtual void updateVisibleRegionsDirty() { } + + virtual void drawWormHoleIfRequired(HWComposer::LayerListIterator &cur, + const HWComposer::LayerListIterator &end, + const sp<const DisplayDevice>& hw, + const Region& region); + /* ------------------------------------------------------------------------ * Message handling */ void waitForEvent(); @@ -329,7 +372,8 @@ private: const sp<IGraphicBufferProducer>& producer, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ, - bool useIdentityTransform, Transform::orientation_flags rotation); + bool useIdentityTransform, Transform::orientation_flags rotation, + bool useReadPixels); /* ------------------------------------------------------------------------ * EGL @@ -373,7 +417,7 @@ private: * Compositing */ void invalidateHwcGeometry(); - static void computeVisibleRegions( + void computeVisibleRegions(size_t dpy, const LayerVector& currentLayers, uint32_t layerStack, Region& dirtyRegion, Region& opaqueRegion); diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp index a74bc4c..6127cf6 100644 --- a/services/surfaceflinger/main_surfaceflinger.cpp +++ b/services/surfaceflinger/main_surfaceflinger.cpp @@ -22,6 +22,7 @@ #include <binder/ProcessState.h> #include <binder/IServiceManager.h> #include "SurfaceFlinger.h" +#include "DisplayUtils.h" using namespace android; @@ -35,7 +36,7 @@ int main(int, char**) { ps->startThreadPool(); // instantiate surfaceflinger - sp<SurfaceFlinger> flinger = new SurfaceFlinger(); + sp<SurfaceFlinger> flinger = DisplayUtils::getInstance()->getSFInstance(); setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY); |