diff options
Diffstat (limited to 'services/surfaceflinger/SurfaceFlinger.cpp')
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 133 |
1 files changed, 100 insertions, 33 deletions
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 80d3cc2..df4ac2e 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -145,6 +145,7 @@ SurfaceFlinger::SurfaceFlinger() mDebugInTransaction(0), mLastTransactionTime(0), mBootFinished(false), + mForceFullDamage(false), mPrimaryHWVsyncEnabled(false), mHWVsyncAvailable(false), mDaltonize(false), @@ -319,17 +320,20 @@ public: DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync, const char* label) : mValue(0), - mPhaseOffset(phaseOffset), mTraceVsync(traceVsync), mVsyncOnLabel(String8::format("VsyncOn-%s", label)), mVsyncEventLabel(String8::format("VSYNC-%s", label)), - mDispSync(dispSync) {} + mDispSync(dispSync), + mCallbackMutex(), + mCallback(), + mVsyncMutex(), + mPhaseOffset(phaseOffset), + mEnabled(false) {} virtual ~DispSyncSource() {} virtual void setVSyncEnabled(bool enable) { - // Do NOT lock the mutex here so as to avoid any mutex ordering issues - // with locking it in the onDispSyncEvent callback. + Mutex::Autolock lock(mVsyncMutex); if (enable) { status_t err = mDispSync->addEventListener(mPhaseOffset, static_cast<DispSync::Callback*>(this)); @@ -347,18 +351,54 @@ public: } //ATRACE_INT(mVsyncOnLabel.string(), 0); } + mEnabled = enable; } virtual void setCallback(const sp<VSyncSource::Callback>& callback) { - Mutex::Autolock lock(mMutex); + Mutex::Autolock lock(mCallbackMutex); mCallback = callback; } + virtual void setPhaseOffset(nsecs_t phaseOffset) { + Mutex::Autolock lock(mVsyncMutex); + + // Normalize phaseOffset to [0, period) + auto period = mDispSync->getPeriod(); + phaseOffset %= period; + if (phaseOffset < 0) { + // If we're here, then phaseOffset is in (-period, 0). After this + // operation, it will be in (0, period) + phaseOffset += period; + } + mPhaseOffset = phaseOffset; + + // If we're not enabled, we don't need to mess with the listeners + if (!mEnabled) { + return; + } + + // Remove the listener with the old offset + status_t err = mDispSync->removeEventListener( + static_cast<DispSync::Callback*>(this)); + if (err != NO_ERROR) { + ALOGE("error unregistering vsync callback: %s (%d)", + strerror(-err), err); + } + + // Add a listener with the new offset + err = mDispSync->addEventListener(mPhaseOffset, + static_cast<DispSync::Callback*>(this)); + if (err != NO_ERROR) { + ALOGE("error registering vsync callback: %s (%d)", + strerror(-err), err); + } + } + private: virtual void onDispSyncEvent(nsecs_t when) { sp<VSyncSource::Callback> callback; { - Mutex::Autolock lock(mMutex); + Mutex::Autolock lock(mCallbackMutex); callback = mCallback; if (mTraceVsync) { @@ -374,21 +414,24 @@ private: int mValue; - const nsecs_t mPhaseOffset; const bool mTraceVsync; const String8 mVsyncOnLabel; const String8 mVsyncEventLabel; DispSync* mDispSync; + + Mutex mCallbackMutex; // Protects the following sp<VSyncSource::Callback> mCallback; - Mutex mMutex; + + Mutex mVsyncMutex; // Protects the following + nsecs_t mPhaseOffset; + bool mEnabled; }; void SurfaceFlinger::init() { ALOGI( "SurfaceFlinger's main thread ready to run. " "Initializing graphics H/W..."); - status_t err; Mutex::Autolock _l(mStateLock); // initialize EGL for the default display @@ -497,7 +540,7 @@ size_t SurfaceFlinger::getMaxViewportDims() const { bool SurfaceFlinger::authenticateSurfaceTexture( const sp<IGraphicBufferProducer>& bufferProducer) const { Mutex::Autolock _l(mStateLock); - sp<IBinder> surfaceTextureBinder(bufferProducer->asBinder()); + sp<IBinder> surfaceTextureBinder(IInterface::asBinder(bufferProducer)); return mGraphicBufferProducerList.indexOf(surfaceTextureBinder) >= 0; } @@ -607,7 +650,7 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& display, return NO_ERROR; } -status_t SurfaceFlinger::getDisplayStats(const sp<IBinder>& display, +status_t SurfaceFlinger::getDisplayStats(const sp<IBinder>& /* display */, DisplayStatInfo* stats) { if (stats == NULL) { return BAD_VALUE; @@ -621,7 +664,11 @@ status_t SurfaceFlinger::getDisplayStats(const sp<IBinder>& display, } int SurfaceFlinger::getActiveConfig(const sp<IBinder>& display) { - return getDisplayDevice(display)->getActiveConfig(); + sp<DisplayDevice> device(getDisplayDevice(display)); + if (device != NULL) { + return device->getActiveConfig(); + } + return BAD_VALUE; } void SurfaceFlinger::setActiveConfigInternal(const sp<DisplayDevice>& hw, int mode) { @@ -1288,7 +1335,9 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) // this display is in both lists. see if something changed. const DisplayDeviceState& state(curr[j]); const wp<IBinder>& display(curr.keyAt(j)); - if (state.surface->asBinder() != draw[i].surface->asBinder()) { + const sp<IBinder> state_binder = IInterface::asBinder(state.surface); + const sp<IBinder> draw_binder = IInterface::asBinder(draw[i].surface); + if (state_binder != draw_binder) { // changing the surface is like destroying and // recreating the DisplayDevice, so we just remove it // from the drawing state, so that it get re-added @@ -1720,12 +1769,17 @@ bool SurfaceFlinger::handlePageFlip() frameQueued = true; if (layer->shouldPresentNow(mPrimaryDispSync)) { layersWithQueuedFrames.push_back(layer.get()); + } else { + layer->useEmptyDamage(); } + } else { + layer->useEmptyDamage(); } } for (size_t i = 0, count = layersWithQueuedFrames.size() ; i<count ; i++) { Layer* layer = layersWithQueuedFrames[i]; const Region dirty(layer->latchBuffer(visibleRegions)); + layer->useSurfaceDamage(); const Layer::State& s(layer->getDrawingState()); invalidateLayerStack(s.layerStack, dirty); } @@ -1951,7 +2005,7 @@ void SurfaceFlinger::addClientLayer(const sp<Client>& client, // add this layer to the current state list Mutex::Autolock _l(mStateLock); mCurrentState.layersSortedByZ.add(lbc); - mGraphicBufferProducerList.add(gbc->asBinder()); + mGraphicBufferProducerList.add(IInterface::asBinder(gbc)); } status_t SurfaceFlinger::removeLayer(const sp<Layer>& layer) { @@ -2024,7 +2078,7 @@ void SurfaceFlinger::setTransactionState( // NOTE: it would be better to use RTTI as we could directly check // that we have a Client*. however, RTTI is disabled in Android. if (s.client != NULL) { - sp<IBinder> binder = s.client->asBinder(); + sp<IBinder> binder = IInterface::asBinder(s.client); if (binder != NULL) { String16 desc(binder->getInterfaceDescriptor()); if (desc == ISurfaceComposerClient::descriptor) { @@ -2071,7 +2125,7 @@ uint32_t SurfaceFlinger::setDisplayStateLocked(const DisplayState& s) if (disp.isValid()) { const uint32_t what = s.what; if (what & DisplayState::eSurfaceChanged) { - if (disp.surface->asBinder() != s.surface->asBinder()) { + if (IInterface::asBinder(disp.surface) != IInterface::asBinder(s.surface)) { disp.surface = s.surface; flags |= eDisplayTransactionNeeded; } @@ -2402,18 +2456,15 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args) result.appendFormat("Permission Denial: " "can't dump SurfaceFlinger from pid=%d, uid=%d\n", pid, uid); } else { - // Try to get the main lock, but don't insist if we can't + // Try to get the main lock, but give up after one second // (this would indicate SF is stuck, but we want to be able to // print something in dumpsys). - int retry = 3; - while (mStateLock.tryLock()<0 && --retry>=0) { - usleep(1000000); - } - const bool locked(retry >= 0); + status_t err = mStateLock.timedLock(s2ns(1)); + bool locked = (err == NO_ERROR); if (!locked) { - result.append( - "SurfaceFlinger appears to be unresponsive, " - "dumping anyways (no locks held)\n"); + result.appendFormat( + "SurfaceFlinger appears to be unresponsive (%s [%d]), " + "dumping anyways (no locks held)\n", strerror(-err), err); } bool dumpAll = true; @@ -2874,6 +2925,21 @@ status_t SurfaceFlinger::onTransact( mPrimaryDispSync.setRefreshSkipCount(n); return NO_ERROR; } + case 1017: { + n = data.readInt32(); + mForceFullDamage = static_cast<bool>(n); + return NO_ERROR; + } + case 1018: { // Modify Choreographer's phase offset + n = data.readInt32(); + 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)); + return NO_ERROR; + } } } return err; @@ -2962,7 +3028,7 @@ class GraphicProducerWrapper : public BBinder, public MessageHandler { // Prevent reads below from happening before the read from Message atomic_thread_fence(memory_order_acquire); if (what == MSG_API_CALL) { - result = impl->asBinder()->transact(code, data[0], reply); + result = IInterface::asBinder(impl)->transact(code, data[0], reply); barrier.open(); } else if (what == MSG_EXIT) { exitRequested = true; @@ -3012,7 +3078,7 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display, // if we have secure windows on this display, never allow the screen capture // unless the producer interface is local (i.e.: we can take a screenshot for // ourselves). - if (!producer->asBinder()->localBinder()) { + if (!IInterface::asBinder(producer)->localBinder()) { Mutex::Autolock _l(mStateLock); sp<const DisplayDevice> hw(getDisplayDevice(display)); if (hw->getSecureLayerVisible()) { @@ -3076,7 +3142,7 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display, result = flinger->captureScreenImplLocked(hw, producer, sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform, rotation); - static_cast<GraphicProducerWrapper*>(producer->asBinder().get())->exit(result); + static_cast<GraphicProducerWrapper*>(IInterface::asBinder(producer).get())->exit(result); return true; } }; @@ -3118,9 +3184,10 @@ void SurfaceFlinger::renderScreenImplLocked( RenderEngine& engine(getRenderEngine()); // get screen geometry - const uint32_t hw_w = hw->getWidth(); - const uint32_t hw_h = hw->getHeight(); - const bool filtering = reqWidth != hw_w || reqWidth != hw_h; + const int32_t hw_w = hw->getWidth(); + const int32_t hw_h = hw->getHeight(); + const bool filtering = static_cast<int32_t>(reqWidth) != hw_w || + static_cast<int32_t>(reqHeight) != hw_h; // if a default or invalid sourceCrop is passed in, set reasonable values if (sourceCrop.width() == 0 || sourceCrop.height() == 0 || @@ -3133,13 +3200,13 @@ void SurfaceFlinger::renderScreenImplLocked( if (sourceCrop.left < 0) { ALOGE("Invalid crop rect: l = %d (< 0)", sourceCrop.left); } - if (static_cast<uint32_t>(sourceCrop.right) > hw_w) { + if (sourceCrop.right > hw_w) { ALOGE("Invalid crop rect: r = %d (> %d)", sourceCrop.right, hw_w); } if (sourceCrop.top < 0) { ALOGE("Invalid crop rect: t = %d (< 0)", sourceCrop.top); } - if (static_cast<uint32_t>(sourceCrop.bottom) > hw_h) { + if (sourceCrop.bottom > hw_h) { ALOGE("Invalid crop rect: b = %d (> %d)", sourceCrop.bottom, hw_h); } |