Skip to content
2 changes: 1 addition & 1 deletion libs/binder/BpBinder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -860,7 +860,7 @@ void BpBinder::onLastStrongRef(const void* /*id*/) {
Vector<Obituary>* obits = mObituaries;
if(obits != nullptr) {
if (!obits->isEmpty()) {
ALOGI("onLastStrongRef automatically unlinking death recipients for descriptor: '%s'",
ALOGV("onLastStrongRef automatically unlinking death recipients for descriptor: '%s'",
BPBINDER_BEST_DESCRIPTOR_LOCKED);
}

Expand Down
23 changes: 21 additions & 2 deletions libs/gui/BLASTBufferQueue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,25 @@ timespec timespecFromNanos(nsecs_t duration) {

} // namespace

inline int epoll_wait_with_timeout(int epfd, struct epoll_event* events, int maxevents,
const timespec* timeout) {
static bool useEpollWait = false;
if (!useEpollWait) {
int ret = epoll_pwait2(epfd, events, maxevents, timeout, nullptr);
if (ret == -1 && errno == ENOSYS) {
useEpollWait = true;
} else {
return ret;
}
}

int timeoutMs = -1;
if (timeout) {
timeoutMs = (timeout->tv_sec * 1000) + (timeout->tv_nsec / 1000000);
}
return epoll_wait(epfd, events, maxevents, timeoutMs);
}

namespace android {

// Macros to include adapter info in log messages
Expand Down Expand Up @@ -1467,8 +1486,8 @@ status_t BufferReleaseReader::readBlocking(ReleaseCallbackId& outId, sp<Fence>&
epoll_event event{};
int eventCount;
do {
eventCount = epoll_pwait2(mEpollFd.get(), &event, 1 /*maxevents*/,
timespec ? &(*timespec) : nullptr, nullptr /*sigmask*/);
eventCount = epoll_wait_with_timeout(mEpollFd.get(), &event, 1 /*maxevents*/,
timespec ? &(*timespec) : nullptr);
} while (eventCount == -1 && errno == EINTR);

if (eventCount == -1) {
Expand Down
7 changes: 7 additions & 0 deletions libs/gui/IProducerListener.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@ class HpProducerListener : public HpInterface<
virtual void onBuffersDiscarded(const std::vector<int32_t>& discardedSlots) override {
return mBase->onBuffersDiscarded(discardedSlots);
}

virtual void onBufferDetached(int slot) {
mBase->onBufferDetached(slot);
}
};

IMPLEMENT_HYBRID_META_INTERFACE(ProducerListener,
Expand Down Expand Up @@ -190,4 +194,7 @@ bool BnProducerListener::needsAttachNotify() {
}
#endif

void BnProducerListener::onBufferDetached(int slot) {
ALOGE("BnProducerListener::onBufferDetached slot: %d",slot);
}
} // namespace android
13 changes: 13 additions & 0 deletions libs/gui/Surface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2262,6 +2262,19 @@ int Surface::disconnect(int api, IGraphicBufferProducer::DisconnectMode mode) {
return err;
}

// MIUI ADD: START
void Surface::releaseSlot(int slot) {
Mutex::Autolock lock(mMutex);
if(mDequeuedSlots.count(slot) <= 0) {
ALOGV("Surface releaseSlot %d",slot);
if (mReportRemovedBuffers && (mSlots[slot].buffer != nullptr)) {
mRemovedBuffers.push_back(mSlots[slot].buffer);
}
mSlots[slot].buffer = nullptr;
}
}
// MIUI ADD: END

int Surface::detachNextBuffer(sp<GraphicBuffer>* outBuffer,
sp<Fence>* outFence) {
ATRACE_CALL();
Expand Down
3 changes: 3 additions & 0 deletions libs/gui/bufferqueue/1.0/WProducerListener.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,7 @@ bool LWProducerListener::needsReleaseNotify() {
void LWProducerListener::onBuffersDiscarded(const std::vector<int32_t>& /*slots*/) {
}

void LWProducerListener::onBufferDetached(int /*slot*/) {
}

} // namespace android
3 changes: 3 additions & 0 deletions libs/gui/bufferqueue/2.0/H2BProducerListener.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ bool H2BProducerListener::needsReleaseNotify() {
void H2BProducerListener::onBuffersDiscarded(const std::vector<int32_t>& /*slots*/) {
}

void H2BProducerListener::onBufferDetached(int /*slot*/) {
}

} // namespace utils
} // namespace V2_0
} // namespace bufferqueue
Expand Down
2 changes: 2 additions & 0 deletions libs/gui/include/gui/IProducerListener.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ class BnProducerListener : public BnInterface<IProducerListener>
Parcel* reply, uint32_t flags = 0);
virtual bool needsReleaseNotify();
virtual void onBuffersDiscarded(const std::vector<int32_t>& slots);
virtual void onBufferDetached(int slot);
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_CONSUMER_ATTACH_CALLBACK)
virtual bool needsAttachNotify();
#endif
Expand All @@ -106,6 +107,7 @@ class StubProducerListener : public BnProducerListener {
virtual ~StubProducerListener();
virtual void onBufferReleased() {}
virtual bool needsReleaseNotify() { return false; }
virtual void onBufferDetached(int /**slot**/) {}
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_CONSUMER_ATTACH_CALLBACK)
virtual bool needsAttachNotify() { return false; }
#endif
Expand Down
2 changes: 2 additions & 0 deletions libs/gui/include/gui/Surface.h
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,8 @@ class Surface
virtual int connect(int api, const sp<SurfaceListener>& listener,
bool reportBufferRemoval = false);
virtual int detachNextBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence);
// MIUI ADD
virtual void releaseSlot(int slot);
virtual int attachBuffer(ANativeWindowBuffer*);

virtual void destroy();
Expand Down
1 change: 1 addition & 0 deletions libs/gui/include/gui/bufferqueue/1.0/WProducerListener.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class LWProducerListener : public BnProducerListener {
void onBufferReleased() override;
bool needsReleaseNotify() override;
void onBuffersDiscarded(const std::vector<int32_t>& slots) override;
void onBufferDetached(int slot) override;
};

} // namespace android
Expand Down
1 change: 1 addition & 0 deletions libs/gui/include/gui/bufferqueue/2.0/H2BProducerListener.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class H2BProducerListener
virtual void onBufferReleased() override;
virtual bool needsReleaseNotify() override;
virtual void onBuffersDiscarded(const std::vector<int32_t>& slots) override;
virtual void onBufferDetached(int slot) override;
};

} // namespace utils
Expand Down
3 changes: 2 additions & 1 deletion libs/nativedisplay/include/surfacetexture/EGLConsumer.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <gui/BufferQueueDefs.h>
#include <ui/FenceTime.h>
#include <ui/GraphicBuffer.h>
#include <ui/GraphicTypes.h>
#include <utils/Mutex.h>

namespace android {
Expand Down Expand Up @@ -191,7 +192,7 @@ class EGLConsumer {

// mGraphicBuffer is the buffer that was used to create this image.
sp<GraphicBuffer> mGraphicBuffer;

ui::Dataspace mDataSpace;
// mEglImage is the EGLImage created from mGraphicBuffer.
EGLImageKHR mEglImage;

Expand Down
19 changes: 17 additions & 2 deletions libs/nativedisplay/surfacetexture/EGLConsumer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -616,7 +616,9 @@ void EGLConsumer::onAbandonLocked() {
}

EGLConsumer::EglImage::EglImage(sp<GraphicBuffer> graphicBuffer)
: mGraphicBuffer(graphicBuffer), mEglImage(EGL_NO_IMAGE_KHR), mEglDisplay(EGL_NO_DISPLAY) {}
: mGraphicBuffer(graphicBuffer), mEglImage(EGL_NO_IMAGE_KHR), mEglDisplay(EGL_NO_DISPLAY) {
mDataSpace = ui::Dataspace::UNKNOWN;
}

EGLConsumer::EglImage::~EglImage() {
if (mEglImage != EGL_NO_IMAGE_KHR) {
Expand All @@ -631,7 +633,16 @@ status_t EGLConsumer::EglImage::createIfNeeded(EGLDisplay eglDisplay, bool force
// If there's an image and it's no longer valid, destroy it.
bool haveImage = mEglImage != EGL_NO_IMAGE_KHR;
bool displayInvalid = mEglDisplay != eglDisplay;
if (haveImage && (displayInvalid || forceCreation)) {

ui::Dataspace dataspace;
bool dataspaceChanged = false;
if (mGraphicBuffer->getDataspace(&dataspace) == 0 ) {
dataspaceChanged = (mDataSpace != dataspace)? true:false;
if(dataspaceChanged)
ALOGI("createIfNeeded: Recreate new EGLImage since dataspace changed");
}

if (haveImage && (displayInvalid || forceCreation || dataspaceChanged)) {
if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) {
ALOGE("createIfNeeded: eglDestroyImageKHR failed");
}
Expand All @@ -655,6 +666,10 @@ status_t EGLConsumer::EglImage::createIfNeeded(EGLDisplay eglDisplay, bool force
buffer->getPixelFormat());
return UNKNOWN_ERROR;
}

if (dataspaceChanged) {
mDataSpace = dataspace;
}

return OK;
}
Expand Down
5 changes: 5 additions & 0 deletions libs/ui/include/ui/GraphicBuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include <ui/GraphicBufferMapper.h>
#include <ui/PixelFormat.h>
#include <ui/Rect.h>
#include <ui/GraphicTypes.h>
#include <utils/Flattenable.h>
#include <utils/RefBase.h>

Expand Down Expand Up @@ -168,6 +169,10 @@ class GraphicBuffer
Rect getBounds() const { return Rect(width, height); }
uint64_t getId() const { return mId; }

status_t getDataspace(ui::Dataspace* outDataspace){
return mBufferMapper.getDataspace(handle, outDataspace);
}

uint32_t getGenerationNumber() const { return mGenerationNumber; }
void setGenerationNumber(uint32_t generation) {
mGenerationNumber = generation;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ enum class Feature : std::uint8_t {
kBackpressureGpuComposition = 1 << 4,
kSmallDirtyContentDetection = 1 << 5,
kExpectedPresentTime = 1 << 6,
kPropagateBackpressure = 1 << 7,
};

using FeatureFlags = ftl::Flags<Feature>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,8 @@ class FrameTargeter final : private FrameTarget {
FrameTargeter(PhysicalDisplayId displayId, FeatureFlags flags)
: FrameTarget(to_string(displayId)),
mBackpressureGpuComposition(flags.test(Feature::kBackpressureGpuComposition)),
mSupportsExpectedPresentTime(flags.test(Feature::kExpectedPresentTime)) {}
mSupportsExpectedPresentTime(flags.test(Feature::kExpectedPresentTime)),
mPropagateBackpressure(flags.test(Feature::kPropagateBackpressure)) {}

const FrameTarget& target() const { return *this; }

Expand Down Expand Up @@ -169,6 +170,7 @@ class FrameTargeter final : private FrameTarget {

const bool mBackpressureGpuComposition;
const bool mSupportsExpectedPresentTime;
const bool mPropagateBackpressure;

TimePoint mScheduledPresentTime;
CompositionCoverageFlags mCompositionCoverage;
Expand Down
4 changes: 4 additions & 0 deletions services/surfaceflinger/Scheduler/src/FrameTargeter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,10 @@ void FrameTargeter::beginFrame(const BeginFrameArgs& args, const IVsyncSource& v
// In cases where the present fence is about to fire, give it a small grace period instead of
// giving up on the frame.
const int graceTimeForPresentFenceMs = [&] {
if (!mPropagateBackpressure) {
return 0;
}

const bool considerBackpressure =
mBackpressureGpuComposition || !mCompositionCoverage.test(CompositionCoverage::Gpu);

Expand Down
22 changes: 20 additions & 2 deletions services/surfaceflinger/SurfaceFlinger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,10 @@ SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipI

mDebugFlashDelay = base::GetUintProperty("debug.sf.showupdates"s, 0u);

property_get("debug.sf.disable_backpressure", value, "0");
mPropagateBackpressure = !atoi(value);
ALOGI_IF(!mPropagateBackpressure, "Disabling backpressure propagation");

mBackpressureGpuComposition = base::GetBoolProperty("debug.sf.enable_gl_backpressure"s, true);
ALOGI_IF(mBackpressureGpuComposition, "Enabling backpressure for GPU composition");

Expand Down Expand Up @@ -588,6 +592,9 @@ SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipI
}

LatchUnsignaledConfig SurfaceFlinger::getLatchUnsignaledConfig() {
if (base::GetBoolProperty("debug.sf.latch_unsignaled"s, false)) {
return LatchUnsignaledConfig::Always;
}
if (base::GetBoolProperty("debug.sf.auto_latch_unsignaled"s, true)) {
return LatchUnsignaledConfig::AutoSingleLayer;
}
Expand Down Expand Up @@ -2902,7 +2909,7 @@ bool SurfaceFlinger::commit(PhysicalDisplayId pacesetterId,
}

if (pacesetterFrameTarget.wouldBackpressureHwc()) {
if (mBackpressureGpuComposition || pacesetterFrameTarget.didMissHwcFrame()) {
if (mPropagateBackpressure && (mBackpressureGpuComposition || pacesetterFrameTarget.didMissHwcFrame())) {
mScheduler->getVsyncSchedule()->getTracker().onFrameMissed(
pacesetterFrameTarget.expectedPresentTime());
const Duration slack = TimePoint::now() - pacesetterFrameTarget.frameBeginTime();
Expand Down Expand Up @@ -4990,6 +4997,9 @@ void SurfaceFlinger::initScheduler(const sp<const DisplayDevice>& display) {
if (mBackpressureGpuComposition) {
features |= Feature::kBackpressureGpuComposition;
}
if (mPropagateBackpressure) {
features |= Feature::kPropagateBackpressure;
}
if (getHwComposer().getComposer()->isSupported(
Hwc2::Composer::OptionalFeature::ExpectedPresentTime)) {
features |= Feature::kExpectedPresentTime;
Expand Down Expand Up @@ -5247,10 +5257,13 @@ TransactionHandler::TransactionReadiness SurfaceFlinger::transactionReadyBufferC
return TraverseBuffersReturnValues::STOP_TRAVERSAL;
}

// ignore the acquire fence if LatchUnsignaledConfig::Always is set.
const bool checkAcquireFence =
enableLatchUnsignaledConfig != LatchUnsignaledConfig::Always;
const bool acquireFenceAvailable = s.bufferData &&
s.bufferData->flags.test(BufferData::BufferDataChange::fenceChanged) &&
s.bufferData->acquireFence;
const bool fenceSignaled = !acquireFenceAvailable ||
const bool fenceSignaled = !checkAcquireFence || !acquireFenceAvailable ||
s.bufferData->acquireFence->getStatus() != Fence::Status::Unsignaled;
if (!fenceSignaled) {
// check fence status
Expand Down Expand Up @@ -5358,6 +5371,11 @@ bool SurfaceFlinger::shouldLatchUnsignaled(const layer_state_t& state, size_t nu
return false;
}

if (enableLatchUnsignaledConfig == LatchUnsignaledConfig::Always) {
SFTRACE_FORMAT_INSTANT("%s: true (LatchUnsignaledConfig::Always)", __func__);
return true;
}

// We only want to latch unsignaled when a single layer is updated in this
// transaction (i.e. not a blast sync transaction).
if (numStates != 1) {
Expand Down
1 change: 1 addition & 0 deletions services/surfaceflinger/SurfaceFlinger.h
Original file line number Diff line number Diff line change
Expand Up @@ -1511,6 +1511,7 @@ class SurfaceFlinger : public BnSurfaceComposer,
std::atomic_bool mForceFullDamage = false;

bool mLayerCachingEnabled = false;
bool mPropagateBackpressure = true;
bool mBackpressureGpuComposition = false;

LayerTracing mLayerTracing;
Expand Down
4 changes: 4 additions & 0 deletions services/surfaceflinger/TransactionCallbackInvoker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,10 @@ void TransactionCallbackInvoker::sendCallbacks(bool onCommitOnly) {
mPresentFence.clear();
}

if (listenerStatsToSend.empty()) {
return;
}

BackgroundExecutor::getInstance().sendCallbacks(
{[listenerStatsToSend = std::move(listenerStatsToSend)]() {
SFTRACE_NAME("TransactionCallbackInvoker::sendCallbacks");
Expand Down