diff options
Diffstat (limited to 'libs/gui/Surface.cpp')
-rw-r--r-- | libs/gui/Surface.cpp | 220 |
1 files changed, 162 insertions, 58 deletions
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index 2de14c8846..e6eb327c6f 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -20,6 +20,11 @@ #include <gui/Surface.h> +#include <condition_variable> +#include <deque> +#include <mutex> +#include <thread> + #include <inttypes.h> #include <android/native_window.h> @@ -39,9 +44,6 @@ #include <gui/ISurfaceComposer.h> #include <private/gui/ComposerService.h> -#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h> -#include <configstore/Utils.h> - namespace android { using ui::ColorMode; @@ -156,7 +158,7 @@ status_t Surface::getDisplayRefreshCycleDuration(nsecs_t* outRefreshDuration) { ATRACE_CALL(); DisplayStatInfo stats; - status_t result = composerService()->getDisplayStats(NULL, &stats); + status_t result = composerService()->getDisplayStats(nullptr, &stats); if (result != NO_ERROR) { return result; } @@ -321,48 +323,27 @@ status_t Surface::getFrameTimestamps(uint64_t frameNumber, return NO_ERROR; } -using namespace android::hardware::configstore; -using namespace android::hardware::configstore::V1_0; - status_t Surface::getWideColorSupport(bool* supported) { ATRACE_CALL(); - sp<IBinder> display( - composerService()->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain)); - Vector<ColorMode> colorModes; - status_t err = - composerService()->getDisplayColorModes(display, &colorModes); - - if (err) - return err; - - bool wideColorBoardConfig = - getBool<ISurfaceFlingerConfigs, - &ISurfaceFlingerConfigs::hasWideColorDisplay>(false); - - *supported = false; - for (ColorMode colorMode : colorModes) { - switch (colorMode) { - case ColorMode::DISPLAY_P3: - case ColorMode::ADOBE_RGB: - case ColorMode::DCI_P3: - if (wideColorBoardConfig) { - *supported = true; - } - break; - default: - break; - } + const sp<IBinder> display = composerService()->getInternalDisplayToken(); + if (display == nullptr) { + return NAME_NOT_FOUND; } - return NO_ERROR; + *supported = false; + status_t error = composerService()->isWideColorDisplay(display, supported); + return error; } status_t Surface::getHdrSupport(bool* supported) { ATRACE_CALL(); - sp<IBinder> display( - composerService()->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain)); + const sp<IBinder> display = composerService()->getInternalDisplayToken(); + if (display == nullptr) { + return NAME_NOT_FOUND; + } + HdrCapabilities hdrCapabilities; status_t err = composerService()->getHdrCapabilities(display, &hdrCapabilities); @@ -474,6 +455,82 @@ int Surface::setSwapInterval(int interval) { return NO_ERROR; } +class FenceMonitor { +public: + explicit FenceMonitor(const char* name) : mName(name), mFencesQueued(0), mFencesSignaled(0) { + std::thread thread(&FenceMonitor::loop, this); + pthread_setname_np(thread.native_handle(), mName); + thread.detach(); + } + + void queueFence(const sp<Fence>& fence) { + char message[64]; + + std::lock_guard<std::mutex> lock(mMutex); + if (fence->getSignalTime() != Fence::SIGNAL_TIME_PENDING) { + snprintf(message, sizeof(message), "%s fence %u has signaled", mName, mFencesQueued); + ATRACE_NAME(message); + // Need an increment on both to make the trace number correct. + mFencesQueued++; + mFencesSignaled++; + return; + } + snprintf(message, sizeof(message), "Trace %s fence %u", mName, mFencesQueued); + ATRACE_NAME(message); + + mQueue.push_back(fence); + mCondition.notify_one(); + mFencesQueued++; + ATRACE_INT(mName, int32_t(mQueue.size())); + } + +private: +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wmissing-noreturn" + void loop() { + while (true) { + threadLoop(); + } + } +#pragma clang diagnostic pop + + void threadLoop() { + sp<Fence> fence; + uint32_t fenceNum; + { + std::unique_lock<std::mutex> lock(mMutex); + while (mQueue.empty()) { + mCondition.wait(lock); + } + fence = mQueue[0]; + fenceNum = mFencesSignaled; + } + { + char message[64]; + snprintf(message, sizeof(message), "waiting for %s %u", mName, fenceNum); + ATRACE_NAME(message); + + status_t result = fence->waitForever(message); + if (result != OK) { + ALOGE("Error waiting for fence: %d", result); + } + } + { + std::lock_guard<std::mutex> lock(mMutex); + mQueue.pop_front(); + mFencesSignaled++; + ATRACE_INT(mName, int32_t(mQueue.size())); + } + } + + const char* mName; + uint32_t mFencesQueued; + uint32_t mFencesSignaled; + std::deque<sp<Fence>> mQueue; + std::condition_variable mCondition; + std::mutex mMutex; +}; + int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) { ATRACE_CALL(); ALOGV("Surface::dequeueBuffer"); @@ -501,7 +558,7 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) { if (mSharedBufferMode && mAutoRefresh && mSharedBufferSlot != BufferItem::INVALID_BUFFER_SLOT) { sp<GraphicBuffer>& gbuf(mSlots[mSharedBufferSlot].buffer); - if (gbuf != NULL) { + if (gbuf != nullptr) { *buffer = gbuf.get(); *fenceFd = -1; return OK; @@ -541,7 +598,12 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) { sp<GraphicBuffer>& gbuf(mSlots[buf].buffer); // this should never happen - ALOGE_IF(fence == NULL, "Surface::dequeueBuffer: received null Fence! buf=%d", buf); + ALOGE_IF(fence == nullptr, "Surface::dequeueBuffer: received null Fence! buf=%d", buf); + + if (CC_UNLIKELY(atrace_is_tag_enabled(ATRACE_TAG_GRAPHICS))) { + static FenceMonitor hwcReleaseThread("HWC release"); + hwcReleaseThread.queueFence(fence); + } if (result & IGraphicBufferProducer::RELEASE_ALL_BUFFERS) { freeAllBuffers(); @@ -619,7 +681,7 @@ int Surface::cancelBuffer(android_native_buffer_t* buffer, int Surface::getSlotFromBufferLocked( android_native_buffer_t* buffer) const { for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { - if (mSlots[i].buffer != NULL && + if (mSlots[i].buffer != nullptr && mSlots[i].buffer->handle == buffer->handle) { return i; } @@ -754,7 +816,7 @@ int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) { // The consumer doesn't send it back to prevent us from having two // file descriptors of the same fence. mFrameEventHistory->updateAcquireFence(mNextFrameNumber, - std::make_shared<FenceTime>(std::move(fence))); + std::make_shared<FenceTime>(fence)); // Cache timestamps of signaled fences so we can close their file // descriptors. @@ -767,8 +829,9 @@ int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) { mDefaultHeight = output.height; mNextFrameNumber = output.nextFrameNumber; - // Disable transform hint if sticky transform is set. - if (mStickyTransform == 0) { + // Ignore transform hint if sticky transform is set or transform to display inverse flag is + // set. + if (mStickyTransform == 0 && !transformToDisplayInverse()) { mTransformHint = output.transformHint; } @@ -785,6 +848,11 @@ int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) { mQueueBufferCondition.broadcast(); + if (CC_UNLIKELY(atrace_is_tag_enabled(ATRACE_TAG_GRAPHICS))) { + static FenceMonitor gpuCompletionThread("GPU completion"); + gpuCompletionThread.queueFence(fence); + } + return err; } @@ -965,6 +1033,9 @@ int Surface::perform(int operation, va_list args) case NATIVE_WINDOW_SET_BUFFERS_CTA861_3_METADATA: res = dispatchSetBuffersCta8613Metadata(args); break; + case NATIVE_WINDOW_SET_BUFFERS_HDR10_PLUS_METADATA: + res = dispatchSetBuffersHdr10PlusMetadata(args); + break; case NATIVE_WINDOW_SET_SURFACE_DAMAGE: res = dispatchSetSurfaceDamage(args); break; @@ -1120,6 +1191,12 @@ int Surface::dispatchSetBuffersCta8613Metadata(va_list args) { return setBuffersCta8613Metadata(metadata); } +int Surface::dispatchSetBuffersHdr10PlusMetadata(va_list args) { + const size_t size = va_arg(args, size_t); + const uint8_t* metadata = va_arg(args, const uint8_t*); + return setBuffersHdr10PlusMetadata(size, metadata); +} + int Surface::dispatchSetSurfaceDamage(va_list args) { android_native_rect_t* rects = va_arg(args, android_native_rect_t*); size_t numRects = va_arg(args, size_t); @@ -1195,6 +1272,11 @@ int Surface::dispatchGetConsumerUsage64(va_list args) { return getConsumerUsage(usage); } +bool Surface::transformToDisplayInverse() { + return (mTransform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY) == + NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY; +} + int Surface::connect(int api) { static sp<IProducerListener> listener = new DummyProducerListener(); return connect(api, listener); @@ -1217,8 +1299,10 @@ int Surface::connect( mDefaultHeight = output.height; mNextFrameNumber = output.nextFrameNumber; - // Disable transform hint if sticky transform is set. - if (mStickyTransform == 0) { + // Ignore transform hint if sticky transform is set or transform to display inverse flag is + // set. Transform hint should be ignored if the client is expected to always submit buffers + // in the same orientation. + if (mStickyTransform == 0 && !transformToDisplayInverse()) { mTransformHint = output.transformHint; } @@ -1268,7 +1352,7 @@ int Surface::detachNextBuffer(sp<GraphicBuffer>* outBuffer, ATRACE_CALL(); ALOGV("Surface::detachNextBuffer"); - if (outBuffer == NULL || outFence == NULL) { + if (outBuffer == nullptr || outFence == nullptr) { return BAD_VALUE; } @@ -1277,8 +1361,8 @@ int Surface::detachNextBuffer(sp<GraphicBuffer>* outBuffer, mRemovedBuffers.clear(); } - sp<GraphicBuffer> buffer(NULL); - sp<Fence> fence(NULL); + sp<GraphicBuffer> buffer(nullptr); + sp<Fence> fence(nullptr); status_t result = mGraphicBufferProducer->detachNextBuffer( &buffer, &fence); if (result != NO_ERROR) { @@ -1286,19 +1370,19 @@ int Surface::detachNextBuffer(sp<GraphicBuffer>* outBuffer, } *outBuffer = buffer; - if (fence != NULL && fence->isValid()) { + if (fence != nullptr && fence->isValid()) { *outFence = fence; } else { *outFence = Fence::NO_FENCE; } for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { - if (mSlots[i].buffer != NULL && + if (mSlots[i].buffer != nullptr && mSlots[i].buffer->getId() == buffer->getId()) { if (mReportRemovedBuffers) { mRemovedBuffers.push_back(mSlots[i].buffer); } - mSlots[i].buffer = NULL; + mSlots[i].buffer = nullptr; } } @@ -1349,7 +1433,7 @@ int Surface::setCrop(Rect const* rect) ATRACE_CALL(); Rect realRect(Rect::EMPTY_RECT); - if (rect == NULL || rect->isEmpty()) { + if (rect == nullptr || rect->isEmpty()) { realRect.clear(); } else { realRect = *rect; @@ -1515,6 +1599,13 @@ int Surface::setBuffersTransform(uint32_t transform) ATRACE_CALL(); ALOGV("Surface::setBuffersTransform"); Mutex::Autolock lock(mMutex); + // Ensure NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY is sticky. If the client sets the flag, do not + // override it until the surface is disconnected. This is a temporary workaround for camera + // until they switch to using Buffer State Layers. Currently if client sets the buffer transform + // it may be overriden by the buffer producer when the producer sets the buffer transform. + if (transformToDisplayInverse()) { + transform |= NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY; + } mTransform = transform; return NO_ERROR; } @@ -1568,6 +1659,19 @@ int Surface::setBuffersCta8613Metadata(const android_cta861_3_metadata* metadata return NO_ERROR; } +int Surface::setBuffersHdr10PlusMetadata(const size_t size, const uint8_t* metadata) { + ALOGV("Surface::setBuffersBlobMetadata"); + Mutex::Autolock lock(mMutex); + if (size > 0) { + mHdrMetadata.hdr10plus.assign(metadata, metadata + size); + mHdrMetadata.validTypes |= HdrMetadata::HDR10PLUS; + } else { + mHdrMetadata.validTypes &= ~HdrMetadata::HDR10PLUS; + mHdrMetadata.hdr10plus.clear(); + } + return NO_ERROR; +} + Dataspace Surface::getBuffersDataSpace() { ALOGV("Surface::getBuffersDataSpace"); Mutex::Autolock lock(mMutex); @@ -1576,7 +1680,7 @@ Dataspace Surface::getBuffersDataSpace() { void Surface::freeAllBuffers() { for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { - mSlots[i].buffer = 0; + mSlots[i].buffer = nullptr; } } @@ -1616,12 +1720,12 @@ static status_t copyBlt( // src and dst with, height and format must be identical. no verification // is done here. status_t err; - uint8_t* src_bits = NULL; + uint8_t* src_bits = nullptr; err = src->lock(GRALLOC_USAGE_SW_READ_OFTEN, reg.bounds(), reinterpret_cast<void**>(&src_bits)); ALOGE_IF(err, "error locking src buffer %s", strerror(-err)); - uint8_t* dst_bits = NULL; + uint8_t* dst_bits = nullptr; err = dst->lockAsync(GRALLOC_USAGE_SW_WRITE_OFTEN, reg.bounds(), reinterpret_cast<void**>(&dst_bits), *dstFenceFd); ALOGE_IF(err, "error locking dst buffer %s", strerror(-err)); @@ -1669,7 +1773,7 @@ static status_t copyBlt( status_t Surface::lock( ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds) { - if (mLockedBuffer != 0) { + if (mLockedBuffer != nullptr) { ALOGE("Surface::lock failed, already locked"); return INVALID_OPERATION; } @@ -1701,7 +1805,7 @@ status_t Surface::lock( // figure out if we can copy the frontbuffer back const sp<GraphicBuffer>& frontBuffer(mPostedBuffer); - const bool canCopyBack = (frontBuffer != 0 && + const bool canCopyBack = (frontBuffer != nullptr && backBuffer->width == frontBuffer->width && backBuffer->height == frontBuffer->height && backBuffer->format == frontBuffer->format); @@ -1763,7 +1867,7 @@ status_t Surface::lock( status_t Surface::unlockAndPost() { - if (mLockedBuffer == 0) { + if (mLockedBuffer == nullptr) { ALOGE("Surface::unlockAndPost failed, no locked buffer"); return INVALID_OPERATION; } @@ -1777,7 +1881,7 @@ status_t Surface::unlockAndPost() mLockedBuffer->handle, strerror(-err)); mPostedBuffer = mLockedBuffer; - mLockedBuffer = 0; + mLockedBuffer = nullptr; return err; } |