diff options
Diffstat (limited to 'services/surfaceflinger/SurfaceFlinger.cpp')
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 305 |
1 files changed, 262 insertions, 43 deletions
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index fdc3650..40e5da1 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +//#define LOG_NDEBUG 0 #define ATRACE_TAG ATRACE_TAG_GRAPHICS #include <stdint.h> @@ -27,6 +28,7 @@ #include <EGL/egl.h> #include <cutils/log.h> +#include <cutils/iosched_policy.h> #include <cutils/properties.h> #include <binder/IPCThreadState.h> @@ -67,6 +69,7 @@ #include "EventThread.h" #include "Layer.h" #include "LayerDim.h" +#include "LayerBlur.h" #include "SurfaceFlinger.h" #include "DisplayHardware/FramebufferSurface.h" @@ -77,6 +80,7 @@ #include "RenderEngine/RenderEngine.h" #include <cutils/compiler.h> +#include "DisplayUtils.h" #define DISPLAY_COUNT 1 @@ -122,6 +126,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() @@ -150,10 +156,12 @@ SurfaceFlinger::SurfaceFlinger() mHWVsyncAvailable(false), mDaltonize(false), mHasColorMatrix(false), + mHasSecondaryColorMatrix(false), mHasPoweredOff(false), mFrameBuckets(), mTotalTime(0), - mLastSwapTime(0) + mLastSwapTime(0), + mActiveFrameSequence(0) { ALOGI("SurfaceFlinger is starting"); @@ -446,17 +454,24 @@ void SurfaceFlinger::init() { eglInitialize(mEGLDisplay, NULL, NULL); // start the EventThread - sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync, - vsyncPhaseOffsetNs, true, "app"); - mEventThread = new EventThread(vsyncSrc); - sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync, - sfVsyncPhaseOffsetNs, true, "sf"); - mSFEventThread = new EventThread(sfVsyncSrc); - mEventQueue.setEventThread(mSFEventThread); + if (vsyncPhaseOffsetNs != sfVsyncPhaseOffsetNs) { + sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync, + vsyncPhaseOffsetNs, true, "app"); + mEventThread = new EventThread(vsyncSrc); + sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync, + sfVsyncPhaseOffsetNs, true, "sf"); + mSFEventThread = new EventThread(sfVsyncSrc); + mEventQueue.setEventThread(mSFEventThread); + } else { + sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync, + vsyncPhaseOffsetNs, true, "sf-app"); + mEventThread = new EventThread(vsyncSrc); + mEventQueue.setEventThread(mEventThread); + } // 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 +512,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 +529,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) { @@ -626,10 +649,21 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& display, info.orientation = 0; } - info.w = hwConfig.width; - info.h = hwConfig.height; - info.xdpi = xdpi; - info.ydpi = ydpi; + char value[PROPERTY_VALUE_MAX]; + property_get("ro.sf.hwrotation", value, "0"); + int additionalRot = atoi(value) / 90; + if ((type == DisplayDevice::DISPLAY_PRIMARY) && (additionalRot & DisplayState::eOrientationSwapMask)) { + info.h = hwConfig.width; + info.w = hwConfig.height; + info.xdpi = ydpi; + info.ydpi = xdpi; + } + else { + info.w = hwConfig.width; + info.h = hwConfig.height; + info.xdpi = xdpi; + info.ydpi = ydpi; + } info.fps = float(1e9 / hwConfig.refresh); info.appVsyncOffset = VSYNC_EVENT_PHASE_OFFSET_NS; info.colorTransform = hwConfig.colorTransform; @@ -695,8 +729,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 +905,7 @@ void SurfaceFlinger::onHotplugReceived(int type, bool connected) { } else { mCurrentState.displays.removeItem(mBuiltinDisplays[type]); mBuiltinDisplays[type].clear(); + updateVisibleRegionsDirty(); } setTransactionFlags(eDisplayTransactionNeeded); @@ -1045,6 +1082,8 @@ void SurfaceFlinger::postComposition() mAnimFrameTracker.advanceFrame(); } + dumpDrawCycle(false); + if (hw->getPowerMode() == HWC_POWER_MODE_OFF) { return; } @@ -1067,6 +1106,7 @@ void SurfaceFlinger::postComposition() } void SurfaceFlinger::rebuildLayerStacks() { + updateExtendedMode(); // rebuild the visible layer list per screen if (CC_UNLIKELY(mVisibleRegionsDirty)) { ATRACE_CALL(); @@ -1082,14 +1122,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); @@ -1155,7 +1194,7 @@ void SurfaceFlinger::setUpHWComposer() { for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) { const sp<Layer>& layer(currentLayers[i]); layer->setGeometry(hw, *cur); - if (mDebugDisableHWC || mDebugRegion || mDaltonize || mHasColorMatrix) { + if (mDebugDisableHWC || mDebugRegion || mDaltonize || mHasColorMatrix || mHasSecondaryColorMatrix) { cur->setSkip(true); } } @@ -1169,6 +1208,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 +1222,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; + } } } } @@ -1205,6 +1251,8 @@ void SurfaceFlinger::setUpHWComposer() { } } + dumpDrawCycle(true); + status_t err = hwc.prepare(); ALOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err)); @@ -1227,6 +1275,8 @@ void SurfaceFlinger::doComposition() { // repaint the framebuffer (if needed) doDisplayComposition(hw, dirtyRegion); + ++mActiveFrameSequence; + hw->dirtyRegion.clear(); hw->flip(hw->swapRegion); hw->swapRegion.clear(); @@ -1287,6 +1337,7 @@ void SurfaceFlinger::postFramebuffer() if (flipCount % LOG_FRAME_STATS_PERIOD == 0) { logFrameStats(); } + ALOGV_IF(mFrameRateHelper.update(), "FPS: %d", mFrameRateHelper.get()); } void SurfaceFlinger::handleTransaction(uint32_t transactionFlags) @@ -1439,6 +1490,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) if (state.surface != NULL) { int width = 0; + DisplayUtils* displayUtils = DisplayUtils::getInstance(); int status = state.surface->query( NATIVE_WINDOW_WIDTH, &width); ALOGE_IF(status != NO_ERROR, @@ -1451,15 +1503,21 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) if (MAX_VIRTUAL_DISPLAY_DIMENSION == 0 || (width <= MAX_VIRTUAL_DISPLAY_DIMENSION && height <= MAX_VIRTUAL_DISPLAY_DIMENSION)) { - hwcDisplayId = allocateHwcDisplayId(state.type); + int usage = 0; + status = state.surface->query( + NATIVE_WINDOW_CONSUMER_USAGE_BITS, &usage); + ALOGW_IF(status != NO_ERROR, + "Unable to query usage (%d)", status); + if ( (status == NO_ERROR) && + displayUtils->canAllocateHwcDisplayIdForVDS(usage)) { + hwcDisplayId = allocateHwcDisplayId(state.type); + } } - sp<VirtualDisplaySurface> vds = new VirtualDisplaySurface( - *mHwc, hwcDisplayId, state.surface, - bqProducer, bqConsumer, state.displayName); + displayUtils->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 +1533,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 +1543,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 +1711,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 +1722,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 +1733,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; /* @@ -1887,11 +1959,14 @@ void SurfaceFlinger::doDisplayComposition(const sp<const DisplayDevice>& hw, } } - if (CC_LIKELY(!mDaltonize && !mHasColorMatrix)) { + if (CC_LIKELY(!mDaltonize && !mHasColorMatrix && !mHasSecondaryColorMatrix)) { if (!doComposeSurfaces(hw, dirtyRegion)) return; } else { RenderEngine& engine(getRenderEngine()); mat4 colorMatrix = mColorMatrix; + if (mHasSecondaryColorMatrix) { + colorMatrix = mHasColorMatrix ? (colorMatrix * mSecondaryColorMatrix) : mSecondaryColorMatrix; + } if (mDaltonize) { colorMatrix = colorMatrix * mDaltonizer(); } @@ -1954,7 +2029,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 +2171,8 @@ void SurfaceFlinger::setTransactionState( uint32_t flags) { ATRACE_CALL(); + + delayDPTransactionIfNeeded(displays); Mutex::Autolock _l(mStateLock); uint32_t transactionFlags = 0; @@ -2241,6 +2318,41 @@ uint32_t SurfaceFlinger::setClientStateLocked( flags |= eTransactionNeeded|eTraversalNeeded; } } + if (what & layer_state_t::eBlurChanged) { + ALOGV("eBlurChanged"); + if (layer->setBlur(uint8_t(255.0f*s.blur+0.5f))) { + flags |= eTraversalNeeded; + } + } + if (what & layer_state_t::eBlurMaskSurfaceChanged) { + ALOGV("eBlurMaskSurfaceChanged"); + sp<Layer> maskLayer = 0; + if (s.blurMaskSurface != 0) { + maskLayer = client->getLayerUser(s.blurMaskSurface); + } + if (maskLayer == 0) { + ALOGV("eBlurMaskSurfaceChanged. maskLayer == 0"); + } else { + ALOGV("eBlurMaskSurfaceChagned. maskLayer.z == %d", maskLayer->getCurrentState().z); + if (maskLayer->isBlurLayer()) { + ALOGE("Blur layer can not be used as blur mask surface"); + maskLayer = 0; + } + } + if (layer->setBlurMaskLayer(maskLayer)) { + flags |= eTraversalNeeded; + } + } + if (what & layer_state_t::eBlurMaskSamplingChanged) { + if (layer->setBlurMaskSampling(s.blurMaskSampling)) { + flags |= eTraversalNeeded; + } + } + if (what & layer_state_t::eBlurMaskAlphaThresholdChanged) { + if (layer->setBlurMaskAlphaThreshold(s.blurMaskAlphaThreshold)) { + flags |= eTraversalNeeded; + } + } if (what & layer_state_t::eSizeChanged) { if (layer->setSize(s.w, s.h)) { flags |= eTraversalNeeded; @@ -2309,6 +2421,11 @@ status_t SurfaceFlinger::createLayer( name, w, h, flags, handle, gbp, &layer); break; + case ISurfaceComposerClient::eFXSurfaceBlur: + result = createBlurLayer(client, + name, w, h, flags, + handle, gbp, &layer); + break; default: result = BAD_VALUE; break; @@ -2342,7 +2459,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(); @@ -2363,6 +2480,16 @@ status_t SurfaceFlinger::createDimLayer(const sp<Client>& client, return NO_ERROR; } +status_t SurfaceFlinger::createBlurLayer(const sp<Client>& client, + const String8& name, uint32_t w, uint32_t h, uint32_t flags, + sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer) +{ + *outLayer = new LayerBlur(this, client, name, w, h, flags); + *handle = (*outLayer)->getHandle(); + *gbp = (*outLayer)->getProducer(); + return NO_ERROR; +} + status_t SurfaceFlinger::onLayerRemoved(const sp<Client>& client, const sp<IBinder>& handle) { // called by the window manager when it wants to remove a Layer @@ -2605,14 +2732,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); + } } } @@ -2820,7 +2952,8 @@ void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index, result.appendFormat(" h/w composer %s and %s\n", hwc.initCheck()==NO_ERROR ? "present" : "not present", (mDebugDisableHWC || mDebugRegion || mDaltonize - || mHasColorMatrix) ? "disabled" : "enabled"); + || mHasColorMatrix + || mHasSecondaryColorMatrix) ? "disabled" : "enabled"); hwc.dump(result); /* @@ -2841,7 +2974,7 @@ SurfaceFlinger::getLayerSortedByZForHwcDisplay(int id) { } } if (dpy == NULL) { - ALOGE("getLayerSortedByZForHwcDisplay: invalid hwc display id %d", id); + ALOGW("getLayerSortedByZForHwcDisplay: invalid hwc display id %d", id); // Just use the primary display so we have something to return dpy = getBuiltInDisplay(DisplayDevice::DISPLAY_PRIMARY); } @@ -3020,14 +3153,38 @@ status_t SurfaceFlinger::onTransact( } case 1018: { // Modify Choreographer's phase offset n = data.readInt32(); - mEventThread->setPhaseOffset(static_cast<nsecs_t>(n)); + if (mEventThread != NULL) + mEventThread->setPhaseOffset(static_cast<nsecs_t>(n)); return NO_ERROR; } case 1019: { // Modify SurfaceFlinger's phase offset n = data.readInt32(); - mSFEventThread->setPhaseOffset(static_cast<nsecs_t>(n)); + if (mSFEventThread != NULL) + mSFEventThread->setPhaseOffset(static_cast<nsecs_t>(n)); return NO_ERROR; } + case 1030: { + // apply a secondary color matrix + // this will be combined with any other transformations + n = data.readInt32(); + mHasSecondaryColorMatrix = n ? 1 : 0; + if (n) { + // color matrix is sent as mat3 matrix followed by vec3 + // offset, then packed into a mat4 where the last row is + // the offset and extra values are 0 + for (size_t i = 0 ; i < 4; i++) { + for (size_t j = 0; j < 4; j++) { + mSecondaryColorMatrix[i][j] = data.readFloat(); + } + } + } else { + mSecondaryColorMatrix = mat4(); + } + invalidateHwcGeometry(); + repaintEverything(); + return NO_ERROR; + } + } } return err; @@ -3155,7 +3312,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 +3363,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 +3371,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 +3388,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 +3414,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 +3463,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 +3484,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 +3504,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(); @@ -3354,6 +3523,8 @@ status_t SurfaceFlinger::captureScreenImplLocked( return BAD_VALUE; } + ++mActiveFrameSequence; + reqWidth = (!reqWidth) ? hw_w : reqWidth; reqHeight = (!reqHeight) ? hw_h : reqHeight; @@ -3388,7 +3559,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 +3607,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 +3673,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() { |