switch (format) { case PIXEL_FORMAT_TRANSPARENT: case PIXEL_FORMAT_TRANSLUCENT: format = PIXEL_FORMAT_RGBA_8888; break; case PIXEL_FORMAT_OPAQUE: format = PIXEL_FORMAT_RGBX_8888; break; }
// Creates a custom BufferQueue for SurfaceFlingerConsumer to use sp<IGraphicBufferProducer> producer; sp<IGraphicBufferConsumer> consumer; BufferQueue::createBufferQueue(&producer, &consumer, true); mProducer = new MonitoredProducer(producer, mFlinger, this); { // Grab the SF state lock during this since it's the only safe way to access RenderEngine Mutex::Autolock lock(mFlinger->mStateLock); mConsumer = new BufferLayerConsumer(consumer, mFlinger->getRenderEngine(), mTextureName, this); } mConsumer->setConsumerUsageBits(getEffectiveUsage(0)); mConsumer->setContentsChangedListener(this); mConsumer->setName(mName);
// BufferQueueCore::mMaxDequeuedBufferCount is default to 1 if (!mFlinger->isLayerTripleBufferingDisabled()) { mProducer->setMaxDequeuedBufferCount(2); }
if (constauto display = mFlinger->getDefaultDisplayDevice()) { updateTransformHint(display); } }
// Use rk ashmem ------- if ( NULL == g_gralloc ) { int ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (consthw_module_t **)&g_gralloc); if (ret) { ALOGE("Failed to open gralloc module %d", ret); } } // Use rk ashmem ------- }
// requestBuffer requests a new buffer for the given index. The server (i.e. // the IGraphicBufferProducer implementation) assigns the newly created // buffer to the given slot index, and the client is expected to mirror the // slot->buffer mapping so that it's not necessary to transfer a // GraphicBuffer for every dequeue operation. // // The slot must be in the range of [0, NUM_BUFFER_SLOTS). virtualstatus_trequestBuffer(int slot, sp<GraphicBuffer>* buf)= 0;
// dequeueBuffer requests a new buffer slot for the client to use. Ownership // of the slot is transfered to the client, meaning that the server will not // use the contents of the buffer associated with that slot. // virtualstatus_tdequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w, uint32_t h, PixelFormat format, uint32_t usage)= 0;
// detachBuffer attempts to remove all ownership of the buffer in the given // slot from the buffer queue. If this call succeeds, the slot will be // freed, and there will be no way to obtain the buffer from this interface. // The freed slot will remain unallocated until either it is selected to // hold a freshly allocated buffer in dequeueBuffer or a buffer is attached // to the slot. The buffer must have already been dequeued, and the caller // must already possesses the sp<GraphicBuffer> (i.e., must have called // requestBuffer). // virtualstatus_tdetachBuffer(int slot)= 0;
// attachBuffer attempts to transfer ownership of a buffer to the buffer // queue. If this call succeeds, it will be as if this buffer was dequeued // from the returned slot number. As such, this call will fail if attaching // this buffer would cause too many buffers to be simultaneously dequeued. // virtualstatus_tattachBuffer(int* outSlot, const sp<GraphicBuffer>& buffer)= 0;
// acquireBuffer attempts to acquire ownership of the next pending buffer in // the BufferQueue. If no buffer is pending then it returns // NO_BUFFER_AVAILABLE. If a buffer is successfully acquired, the // information about the buffer is returned in BufferItem. // virtualstatus_tacquireBuffer(BufferItem* buffer, nsecs_t presentWhen, uint64_t maxFrameNumber = 0)= 0;
// releaseBuffer releases a buffer slot from the consumer back to the // BufferQueue. This may be done while the buffer's contents are still // being accessed. The fence will signal when the buffer is no longer // in use. frameNumber is used to indentify the exact buffer returned. // virtualstatus_treleaseBuffer(int buf, uint64_t frameNumber, EGLDisplay display, EGLSyncKHR fence, const sp<Fence>& releaseFence)= 0;
// detachBuffer attempts to remove all ownership of the buffer in the given // slot from the buffer queue. If this call succeeds, the slot will be // freed, and there will be no way to obtain the buffer from this interface. // The freed slot will remain unallocated until either it is selected to // hold a freshly allocated buffer in dequeueBuffer or a buffer is attached // to the slot. The buffer must have already been acquired. // virtualstatus_tdetachBuffer(int slot)= 0;
// attachBuffer attempts to transfer ownership of a buffer to the buffer // queue. If this call succeeds, it will be as if this buffer was acquired // from the returned slot number. As such, this call will fail if attaching // this buffer would cause too many buffers to be simultaneously acquired. // virtualstatus_tattachBuffer(int *outSlot, const sp<GraphicBuffer>& buffer)= 0;
if (!mConnectedToCpu) { int err = Surface::connect(NATIVE_WINDOW_API_CPU); ...... setUsage(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); }
ANativeWindowBuffer* out; int fenceFd = -1; status_t err = dequeueBuffer(&out, &fenceFd); ALOGE_IF(err, "dequeueBuffer failed (%s)", strerror(-err)); if (err == NO_ERROR) { sp<GraphicBuffer> backBuffer(GraphicBuffer::getSelf(out)); const Rect bounds(backBuffer->width, backBuffer->height);
Region newDirtyRegion; if (inOutDirtyBounds) { newDirtyRegion.set(static_cast<Rect const&>(*inOutDirtyBounds)); newDirtyRegion.andSelf(bounds); } else { newDirtyRegion.set(bounds); }
// figure out if we can copy the frontbuffer back const sp<GraphicBuffer>& frontBuffer(mPostedBuffer); constbool canCopyBack = (frontBuffer != nullptr && backBuffer->width == frontBuffer->width && backBuffer->height == frontBuffer->height && backBuffer->format == frontBuffer->format);
if (canCopyBack) { // copy the area that is invalid and not repainted this round const Region copyback(mDirtyRegion.subtract(newDirtyRegion)); if (!copyback.isEmpty()) { copyBlt(backBuffer, frontBuffer, copyback, &fenceFd); } } else { // if we can't copy-back anything, modify the user's dirty // region to make sure they redraw the whole buffer newDirtyRegion.set(bounds); mDirtyRegion.clear(); Mutex::Autolock lock(mMutex); for (size_t i=0 ; i<NUM_BUFFER_SLOTS ; i++) { mSlots[i].dirtyRegion.clear(); } }
{ // scope for the lock Mutex::Autolock lock(mMutex); intbackBufferSlot(getSlotFromBufferLocked(backBuffer.get())); if (backBufferSlot >= 0) { Region& dirtyRegion(mSlots[backBufferSlot].dirtyRegion); mDirtyRegion.subtract(dirtyRegion); dirtyRegion = newDirtyRegion; } }
mDirtyRegion.orSelf(newDirtyRegion); if (inOutDirtyBounds) { *inOutDirtyBounds = newDirtyRegion.getBounds(); }
// If we don't have a free buffer, but we are currently allocating, we wait until allocation // is finished such that we don't allocate in parallel. if (mCore->mFreeBuffers.empty() && mCore->mIsAllocating) { mDequeueWaitingForAllocation = true; mCore->waitWhileAllocatingLocked(lock); mDequeueWaitingForAllocation = false; mDequeueWaitingForAllocationCondition.notify_all(); }
if (format == 0) { format = mCore->mDefaultBufferFormat; }
// Enable the usage bits the consumer requested usage |= mCore->mConsumerUsageBits;
int found = BufferItem::INVALID_BUFFER_SLOT; while (found == BufferItem::INVALID_BUFFER_SLOT) { status_t status = waitForFreeSlotThenRelock(FreeSlotCaller::Dequeue, lock, &found); if (status != NO_ERROR) { return status; }
// This should not happen if (found == BufferQueueCore::INVALID_BUFFER_SLOT) { BQ_LOGE("dequeueBuffer: no available buffer slots"); return -EBUSY; }
// If we are not allowed to allocate new buffers, // waitForFreeSlotThenRelock must have returned a slot containing a // buffer. If this buffer would require reallocation to meet the // requested attributes, we free it and attempt to get another one. if (!mCore->mAllowAllocation) { if (buffer->needsReallocation(width, height, format, BQ_LAYER_COUNT, usage)) { if (mCore->mSharedBufferSlot == found) { BQ_LOGE("dequeueBuffer: cannot re-allocate a sharedbuffer"); return BAD_VALUE; } mCore->mFreeSlots.insert(found); mCore->clearBufferSlotLocked(found); found = BufferItem::INVALID_BUFFER_SLOT; continue; } } }
const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer); if (mCore->mSharedBufferSlot == found && buffer->needsReallocation(width, height, format, BQ_LAYER_COUNT, usage)) { BQ_LOGE("dequeueBuffer: cannot re-allocate a shared" "buffer");
returnFlags |= BUFFER_NEEDS_REALLOCATION; } else { // We add 1 because that will be the frame number when this buffer // is queued mCore->mBufferAge = mCore->mFrameCounter + 1 - mSlots[found].mFrameNumber; }
BQ_LOGV("dequeueBuffer: setting buffer age to %" PRIu64, mCore->mBufferAge);
if (CC_UNLIKELY(mSlots[found].mFence == nullptr)) { BQ_LOGE("dequeueBuffer: about to return a NULL fence - " "slot=%d w=%d h=%d format=%u", found, buffer->width, buffer->height, buffer->format); }
eglDisplay = mSlots[found].mEglDisplay; eglFence = mSlots[found].mEglFence; // Don't return a fence in shared buffer mode, except for the first // frame. *outFence = (mCore->mSharedBufferMode && mCore->mSharedBufferSlot == found) ? Fence::NO_FENCE : mSlots[found].mFence; mSlots[found].mEglFence = EGL_NO_SYNC_KHR; mSlots[found].mFence = Fence::NO_FENCE;
// If shared buffer mode has just been enabled, cache the slot of the // first buffer that is dequeued and mark it as the shared buffer. if (mCore->mSharedBufferMode && mCore->mSharedBufferSlot == BufferQueueCore::INVALID_BUFFER_SLOT) { mCore->mSharedBufferSlot = found; mSlots[found].mBufferState.mShared = true; } } // Autolock scope
if (returnFlags & BUFFER_NEEDS_REALLOCATION) { BQ_LOGV("dequeueBuffer: allocating a new buffer for slot %d", *outSlot); sp<GraphicBuffer> graphicBuffer = new GraphicBuffer( width, height, format, BQ_LAYER_COUNT, usage, {mConsumerName.string(), mConsumerName.size()});
if (mCore->mIsAbandoned) { mCore->mFreeSlots.insert(*outSlot); mCore->clearBufferSlotLocked(*outSlot); BQ_LOGE("dequeueBuffer: BufferQueue has been abandoned"); return NO_INIT; }
VALIDATE_CONSISTENCY(); } // Autolock scope }
if (attachedByConsumer) { returnFlags |= BUFFER_NEEDS_REALLOCATION; }
if (eglFence != EGL_NO_SYNC_KHR) { EGLint result = eglClientWaitSyncKHR(eglDisplay, eglFence, 0, 1000000000); // If something goes wrong, log the error, but return the buffer without // synchronizing access to it. It's too late at this point to abort the // dequeue operation. if (result == EGL_FALSE) { BQ_LOGE("dequeueBuffer: error %#x waiting for fence", eglGetError()); } elseif (result == EGL_TIMEOUT_EXPIRED_KHR) { BQ_LOGE("dequeueBuffer: timeout waiting for fence"); } eglDestroySyncKHR(eglDisplay, eglFence); }
// make sure to not allocate a N x 0 or 0 x N buffer, since this is // allowed from an API stand-point allocate a 1x1 buffer instead. if (!width || !height) width = height = 1;
constuint32_t bpp = bytesPerPixel(format); if (std::numeric_limits<size_t>::max() / width / height < static_cast<size_t>(bpp)) { ALOGE("Failed to allocate (%u x %u) layerCount %u format %d " "usage %" PRIx64 ": Requesting too large a buffer size", width, height, layerCount, format, usage); return BAD_VALUE; }
// Ensure that layerCount is valid. if (layerCount < 1) layerCount = 1;
// TODO(b/72323293, b/72703005): Remove these invalid bits from callers usage &= ~static_cast<uint64_t>((1 << 10) | (1 << 13));
// if stride has no meaning or is too large, // approximate size with the input width instead if ((*stride) != 0 && std::numeric_limits<size_t>::max() / height / (*stride) < static_cast<size_t>(bpp)) { bufSize = static_cast<size_t>(width) * height * bpp; } else { bufSize = static_cast<size_t>((*stride)) * height * bpp; }
{ // scope for the lock Mutex::Autolock lock(mCallbackMutex); while (callbackTicket != mCurrentCallbackTicket) { mCallbackCondition.wait(mCallbackMutex); }
Mutex::Autolock lock(mQueueItemLock); // Reset the frame number tracker when we receive the first buffer after // a frame number reset if (item.mFrameNumber == 1) { mLastFrameNumberReceived = 0; }
// Ensure that callbacks are handled in order while (item.mFrameNumber != mLastFrameNumberReceived + 1) { status_t result = mQueueItemCondition.waitRelative(mQueueItemLock, ms2ns(500)); if (result != NO_ERROR) { ALOGE("[%s] Timed out waiting on callback", mName.string()); } }
mQueueItems.push_back(item); mQueuedFrames++;
// Wake up any pending callbacks mLastFrameNumberReceived = item.mFrameNumber; mQueueItemCondition.broadcast(); }
// If this layer is orphaned, then we run a fake vsync pulse so that // dequeueBuffer doesn't block indefinitely. if (isRemovedFromCurrentState()) { fakeVsync(); } else { mFlinger->signalLayerUpdate(); } mConsumer->onBufferAvailable(item); }
voidSurfaceFlinger::onMessageReceived(int32_t what) NO_THREAD_SAFETY_ANALYSIS { ATRACE_CALL(); switch (what) { case MessageQueue::INVALIDATE: { // calculate the expected present time once and use the cached // value throughout this frame to make sure all layers are // seeing this same value. populateExpectedPresentTime();
// When Backpressure propagation is enabled we want to give a small grace period // for the present fence to fire instead of just giving up on this frame to handle cases // where present fence is just about to get signaled. constint graceTimeForPresentFenceMs = (mPropagateBackpressure && (mPropagateBackpressureClientComposition || !mHadClientComposition)) ? 1 : 0; bool frameMissed = previousFrameMissed(graceTimeForPresentFenceMs); bool hwcFrameMissed = mHadDeviceComposition && frameMissed; bool gpuFrameMissed = mHadClientComposition && frameMissed; ATRACE_INT("FrameMissed", static_cast<int>(frameMissed)); ATRACE_INT("HwcFrameMissed", static_cast<int>(hwcFrameMissed)); ATRACE_INT("GpuFrameMissed", static_cast<int>(gpuFrameMissed)); if (frameMissed) { mFrameMissedCount++; mTimeStats->incrementMissedFrames(); }
if (hwcFrameMissed) { mHwcFrameMissedCount++; }
if (gpuFrameMissed) { mGpuFrameMissedCount++; }
if (mUseSmart90ForVideo) { // This call is made each time SF wakes up and creates a new frame. It is part // of video detection feature. mScheduler->updateFpsBasedOnContent(); }
if (performSetActiveConfig()) { break; }
if (frameMissed && mPropagateBackpressure) { if ((hwcFrameMissed && !gpuFrameMissed) || mPropagateBackpressureClientComposition) { signalLayerUpdate(); break; } }
// Now that we're going to make it to the handleMessageTransaction() // call below it's safe to call updateVrFlinger(), which will // potentially trigger a display handoff. updateVrFlinger();
refreshNeeded |= mRepaintEverything; if (refreshNeeded && CC_LIKELY(mBootStage != BootStage::BOOTLOADER)) { // Signal a refresh if a transaction modified the window state, // a new buffer was latched, or if HWC has requested a full // repaint signalRefresh(); } break; } case MessageQueue::REFRESH: { handleMessageRefresh(); break; } }
// Store the set of layers that need updates. This set must not change as // buffers are being latched, as this could result in a deadlock. // Example: Two producers share the same command stream and: // 1.) Layer 0 is latched // 2.) Layer 0 gets a new frame // 2.) Layer 1 gets a new frame // 3.) Layer 1 is latched. // Display is now waiting on Layer 1's frame, which is behind layer 0's // second frame. But layer 0's second frame could be waiting on display. mDrawingState.traverseInZOrder([&](Layer* layer) { if (layer->hasReadyFrame()) { frameQueued = true; constnsecs_t expectedPresentTime = getExpectedPresentTime(); if (layer->shouldPresentNow(expectedPresentTime)) { mLayersWithQueuedFrames.push_back(layer); } else { ATRACE_NAME("!layer->shouldPresentNow()"); layer->useEmptyDamage(); } } else { layer->useEmptyDamage(); } });
if (!mLayersWithQueuedFrames.empty()) { // mStateLock is needed for latchBuffer as LayerRejecter::reject() // writes to Layer current state. See also b/119481871 Mutex::Autolock lock(mStateLock);
for (auto& layer : mLayersWithQueuedFrames) { if (layer->latchBuffer(visibleRegions, latchTime)) { mLayersPendingRefresh.push_back(layer); } layer->useSurfaceDamage(); if (layer->isBufferLatched()) { newDataLatched = true; } } }
mVisibleRegionsDirty |= visibleRegions;
// If we will need to wake up at some time in the future to deal with a // queued frame that shouldn't be displayed during this vsync period, wake // up during the next vsync period to check again. if (frameQueued && (mLayersWithQueuedFrames.empty() || !newDataLatched)) { signalLayerUpdate(); }
// enter boot animation on first buffer latch if (CC_UNLIKELY(mBootStage == BootStage::BOOTLOADER && newDataLatched)) { ALOGI("Enter boot animation"); mBootStage = BootStage::BOOTANIMATION; }
// Only continue with the refresh if there is actually new work to do return !mLayersWithQueuedFrames.empty() && newDataLatched; }
Mutex::Autolock lock(mQueueItemLock); // Reset the frame number tracker when we receive the first buffer after // a frame number reset if (item.mFrameNumber == 1) { mLastFrameNumberReceived = 0; }
// Ensure that callbacks are handled in order while (item.mFrameNumber != mLastFrameNumberReceived + 1) { status_t result = mQueueItemCondition.waitRelative(mQueueItemLock, ms2ns(500)); if (result != NO_ERROR) { ALOGE("[%s] Timed out waiting on callback", mName.string()); } }
mQueueItems.push_back(item); mQueuedFrames++;
// Wake up any pending callbacks mLastFrameNumberReceived = item.mFrameNumber; mQueueItemCondition.broadcast(); }
// If this layer is orphaned, then we run a fake vsync pulse so that // dequeueBuffer doesn't block indefinitely. if (isRemovedFromCurrentState()) { fakeVsync(); } else { mFlinger->signalLayerUpdate(); } mConsumer->onBufferAvailable(item); }
boolBufferLayer::shouldPresentNow(const DispSync& dispSync)const{ if (mSidebandStreamChanged || mAutoRefresh) { returntrue; }
Mutex::Autolock lock(mQueueItemLock); if (mQueueItems.empty()) { returnfalse; } auto timestamp = mQueueItems[0].mTimestamp; nsecs_t expectedPresent = mConsumer->computeExpectedPresent(dispSync);
// Ignore timestamps more than a second in the future bool isPlausible = timestamp < (expectedPresent + s2ns(1)); ALOGW_IF(!isPlausible, "[%s] Timestamp %" PRId64 " seems implausible " "relative to expectedPresent %" PRId64, mName.string(), timestamp, expectedPresent);
bool refreshRequired = latchSidebandStream(recomputeVisibleRegions); ....... // we'll trigger an update in onPreComposition(). if (mRefreshPending) { returnfalse; } ....... if (!fenceHasSignaled()) { ATRACE_NAME("!fenceHasSignaled()"); mFlinger->signalLayerUpdate(); returnfalse; }
// Capture the old state of the layer for comparisons later const State& s(getDrawingState()); constbool oldOpacity = isOpaque(s); sp<GraphicBuffer> oldBuffer = mActiveBuffer;
if (!allTransactionsSignaled()) { mFlinger->setTransactionFlags(eTraversalNeeded); returnfalse; }
mRefreshPending = true; mFrameLatencyNeeded = true; if (oldBuffer == nullptr) { // the first time we receive a buffer, we need to trigger a // geometry invalidation. recomputeVisibleRegions = true; }
ui::Dataspace dataSpace = getDrawingDataSpace(); // translate legacy dataspaces to modern dataspaces switch (dataSpace) { case ui::Dataspace::SRGB: dataSpace = ui::Dataspace::V0_SRGB; break; case ui::Dataspace::SRGB_LINEAR: dataSpace = ui::Dataspace::V0_SRGB_LINEAR; break; case ui::Dataspace::JFIF: dataSpace = ui::Dataspace::V0_JFIF; break; case ui::Dataspace::BT601_625: dataSpace = ui::Dataspace::V0_BT601_625; break; case ui::Dataspace::BT601_525: dataSpace = ui::Dataspace::V0_BT601_525; break; case ui::Dataspace::BT709: dataSpace = ui::Dataspace::V0_BT709; break; default: break; } mCurrentDataSpace = dataSpace;
if (oldOpacity != isOpaque(s)) { recomputeVisibleRegions = true; }
// Remove any sync points corresponding to the buffer which was just // latched { Mutex::Autolock lock(mLocalSyncPointMutex); auto point = mLocalSyncPoints.begin(); while (point != mLocalSyncPoints.end()) { if (!(*point)->frameIsAvailable() || !(*point)->transactionIsApplied()) { // This sync point must have been added since we started // latching. Don't drop it yet. ++point; continue; }
if ((*point)->getFrameNumber() <= mCurrentFrameNumber) { std::stringstream ss; ss << "Dropping sync point " << (*point)->getFrameNumber(); ATRACE_NAME(ss.str().c_str()); point = mLocalSyncPoints.erase(point); } else { ++point; } } }
returntrue; }
updateActiveBuffer()更新当前激活buffer。 看看Log:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
10-2809:41:00.211179179 I BufferLayer: zjj.rk3399.SF latchBuffer frameworks/native/services/surfaceflinger/BufferLayer.cpp latchBuffer 629 10-2809:41:00.211179179 I BufferLayer: zjj.rk3399.SF hasReadyFrame frameworks/native/services/surfaceflinger/BufferLayer.cpp hasReadyFrame 795 10-2809:41:00.211179179 I BufferQueueLayer: zjj.rk3399.SF updateTexImage frameworks/native/services/surfaceflinger/BufferQueueLayer.cpp updateTexImage 278 10-2809:41:00.211179179 V BufferQueueProducer: [test#0] query: 11? 0 10-2809:41:00.211179179 V BufferLayerConsumer: [test#0] updateTexImage 10-2809:41:00.211179179 I BufferLayerConsumer: zjj.rk3399.SF updateTexImage frameworks/native/services/surfaceflinger/BufferLayerConsumer.cpp updateTexImage 108 10-2809:41:00.211179179 I BufferLayerConsumer: zjj.rk3399.SF acquireBufferLocked frameworks/native/services/surfaceflinger/BufferLayerConsumer.cpp acquireBufferLocked 218 10-2809:41:00.211179179 V ConsumerBase: [test#0] acquireBufferLocked: -> slot=0/1 10-2809:41:00.211179179 I BufferLayerConsumer: zjj.rk3399.SF updateAndReleaseLocked frameworks/native/services/surfaceflinger/BufferLayerConsumer.cpp updateAndReleaseLocked 243 10-2809:41:00.211179179 V BufferLayerConsumer: [test#0] updateAndRelease: (slot=-1 buf=0x0) -> (slot=0 buf=0x70f185f180) 10-2809:41:00.211179179 V BufferLayerConsumer: [test#0] computeCurrentTransformMatrixLocked 10-2809:41:00.211179179 I BufferLayerConsumer: zjj.rk3399.SF computeCurrentTransformMatrixLocked frameworks/native/services/surfaceflinger/BufferLayerConsumer.cpp computeCurrentTransformMatrixLocked 343 10-2809:41:00.211179179 V BufferLayerConsumer: [test#0] getFrameNumber 10-2809:41:00.211179179 I BufferQueueLayer: zjj.rk3399.SF updateActiveBuffer frameworks/native/services/surfaceflinger/BufferQueueLayer.cpp updateActiveBuffer 383 10-2809:41:00.211179179 I BufferLayerConsumer: zjj.rk3399.SF getCurrentBuffer frameworks/native/services/surfaceflinger/BufferLayerConsumer.cpp getCurrentBuffer 402 10-2809:41:00.211179179 I BufferLayer: zjj.rk3399.SF getCompositionLayer frameworks/native/services/surfaceflinger/BufferLayer.cpp getCompositionLayer 939 10-2809:41:00.211179179 I BufferQueueLayer: zjj.rk3399.SF updateFrameNumber frameworks/native/services/surfaceflinger/BufferQueueLayer.cpp updateFrameNumber 398 10-2809:41:00.211179179 V BufferLayerConsumer: [test#0] getFrameNumber 10-2809:41:00.211179179 V BufferLayerConsumer: [test#0] getCurrentDataSpace
X:\frameworks\native\services\surfaceflinger\BufferQueueLayer.cpp status_tBufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime){ // This boolean is used to make sure that SurfaceFlinger's shadow copy // of the buffer queue isn't modified when the buffer queue is returning // BufferItem's that weren't actually queued. This can happen in shared // buffer mode. ALOGI("zjj.rk3399.SF updateTexImage %s %s %d \n",__FILE__,__FUNCTION__,__LINE__);
if (isRemovedFromCurrentState()) { expectedPresentTime = 0; }
// updateTexImage() below might drop the some buffers at the head of the queue if there is a // buffer behind them which is timely to be presented. However this buffer may not be signaled // yet. The code below makes sure that this wouldn't happen by setting maxFrameNumber to the // last buffer that was signaled. uint64_t lastSignaledFrameNumber = mLastFrameNumberReceived; { Mutex::Autolock lock(mQueueItemLock); for (int i = 0; i < mQueueItems.size(); i++) { bool fenceSignaled = mQueueItems[i].mFenceTime->getSignalTime() != Fence::SIGNAL_TIME_PENDING; if (!fenceSignaled) { break; } lastSignaledFrameNumber = mQueueItems[i].mFrameNumber; } } constuint64_t maxFrameNumberToAcquire = std::min(mLastFrameNumberReceived.load(), lastSignaledFrameNumber);
status_t updateResult = mConsumer->updateTexImage(&r, expectedPresentTime, &mAutoRefresh, &queuedBuffer, maxFrameNumberToAcquire); if (updateResult == BufferQueue::PRESENT_LATER) { // Producer doesn't want buffer to be displayed yet. Signal a // layer update so we check again at the next opportunity. mFlinger->signalLayerUpdate(); return BAD_VALUE; } elseif (updateResult == BufferLayerConsumer::BUFFER_REJECTED) { // If the buffer has been rejected, remove it from the shadow queue // and return early if (queuedBuffer) { Mutex::Autolock lock(mQueueItemLock); mConsumer->mergeSurfaceDamage(mQueueItems[0].mSurfaceDamage); mFlinger->mTimeStats->removeTimeRecord(layerID, mQueueItems[0].mFrameNumber); mQueueItems.removeAt(0); mQueuedFrames--; } return BAD_VALUE; } elseif (updateResult != NO_ERROR || mUpdateTexImageFailed) { // This can occur if something goes wrong when trying to create the // EGLImage for this buffer. If this happens, the buffer has already // been released, so we need to clean up the queue and bug out // early. if (queuedBuffer) { Mutex::Autolock lock(mQueueItemLock); mQueueItems.clear(); mQueuedFrames = 0; mFlinger->mTimeStats->onDestroy(layerID); }
// Once we have hit this state, the shadow queue may no longer // correctly reflect the incoming BufferQueue's contents, so even if // updateTexImage starts working, the only safe course of action is // to continue to ignore updates. mUpdateTexImageFailed = true;
return BAD_VALUE; }
if (queuedBuffer) { // Autolock scope auto currentFrameNumber = mConsumer->getFrameNumber();
Mutex::Autolock lock(mQueueItemLock);
// Remove any stale buffers that have been dropped during // updateTexImage while (mQueueItems[0].mFrameNumber != currentFrameNumber) { mConsumer->mergeSurfaceDamage(mQueueItems[0].mSurfaceDamage); mFlinger->mTimeStats->removeTimeRecord(layerID, mQueueItems[0].mFrameNumber); mQueueItems.removeAt(0); mQueuedFrames--; }
// Decrement the queued-frames count. Signal another event if we // have more frames pending. if ((queuedBuffer && mQueuedFrames.fetch_sub(1) > 1) || mAutoRefresh) { mFlinger->signalLayerUpdate(); }
if (mAbandoned) { BLC_LOGE("updateTexImage: BufferLayerConsumer is abandoned!"); return NO_INIT; }
BufferItem item;
// Acquire the next buffer. // In asynchronous mode the list is guaranteed to be one buffer // deep, while in synchronous mode we use the oldest buffer. status_t err = acquireBufferLocked(&item, expectedPresentTime, maxFrameNumber); if (err != NO_ERROR) { if (err == BufferQueue::NO_BUFFER_AVAILABLE) { err = NO_ERROR; } elseif (err == BufferQueue::PRESENT_LATER) { // return the error, without logging } else { BLC_LOGE("updateTexImage: acquire failed: %s (%d)", strerror(-err), err); } return err; }
if (autoRefresh) { *autoRefresh = item.mAutoRefresh; }
if (queuedBuffer) { *queuedBuffer = item.mQueuedBuffer; }
// We call the rejecter here, in case the caller has a reason to // not accept this buffer. This is used by SurfaceFlinger to // reject buffers which have the wrong size int slot = item.mSlot; if (rejecter && rejecter->reject(mSlots[slot].mGraphicBuffer, item)) { releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer); return BUFFER_REJECTED; }
// Release the previous buffer. err = updateAndReleaseLocked(item, &mPendingRelease); if (err != NO_ERROR) { return err; }
if (!mRE.useNativeFenceSync()) { // Bind the new buffer to the GL texture. // // Older devices require the "implicit" synchronization provided // by glEGLImageTargetTexture2DOES, which this method calls. Newer // devices will either call this in Layer::onDraw, or (if it's not // a GL-composited layer) not at all. err = bindTextureImageLocked(); }
// Hang onto the pointer so that it isn't freed in the call to // releaseBufferLocked() if we're in shared buffer mode and both buffers are // the same.
// If item->mGraphicBuffer is not null, this buffer has not been acquired // before, so we need to clean up old references. if (item->mGraphicBuffer != nullptr) { std::lock_guard<std::mutex> lock(mImagesMutex); if (mImages[item->mSlot] == nullptr || mImages[item->mSlot]->graphicBuffer() == nullptr || mImages[item->mSlot]->graphicBuffer()->getId() != item->mGraphicBuffer->getId()) { mImages[item->mSlot] = std::make_shared<Image>(item->mGraphicBuffer, mRE); } }
refreshNeeded |= mRepaintEverything; if (refreshNeeded && CC_LIKELY(mBootStage != BootStage::BOOTLOADER)) { // Signal a refresh if a transaction modified the window state, // a new buffer was latched, or if HWC has requested a full // repaint signalRefresh(); } break;
// rebuild the visible layer list per screen if (CC_UNLIKELY(mVisibleRegionsDirty)) { ATRACE_NAME("rebuildLayerStacks VR Dirty"); mVisibleRegionsDirty = false; invalidateHwcGeometry();
for (constauto& pair : mDisplays) { constauto& displayDevice = pair.second; auto display = displayDevice->getCompositionDisplay(); constauto& displayState = display->getState(); Region opaqueRegion; Region dirtyRegion; compositionengine::Output::OutputLayers layersSortedByZ; Vector<sp<Layer>> deprecated_layersSortedByZ; Vector<sp<Layer>> layersNeedingFences; const ui::Transform& tr = displayState.transform; const Rect bounds = displayState.bounds; if (displayState.isEnabled) { computeVisibleRegions(displayDevice, dirtyRegion, opaqueRegion);
auto display = displayDevice->getCompositionDisplay();
Region aboveOpaqueLayers; Region aboveCoveredLayers; Region dirty;
outDirtyRegion.clear();
mDrawingState.traverseInReverseZOrder([&](Layer* layer) { // 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 (!display->belongsInOutput(layer->getLayerStack(), layer->getPrimaryDisplayOnly())) { return; }
/* * opaqueRegion: area of a surface that is fully opaque. */ Region opaqueRegion;
/* * visibleRegion: area of a surface that is visible on screen * and not fully transparent. This is essentially the layer's * footprint minus the opaque regions above it. * Areas covered by a translucent surface are considered visible. */ Region visibleRegion;
/* * coveredRegion: area of a surface that is covered by all * visible regions above it (which includes the translucent areas). */ Region coveredRegion;
/* * transparentRegion: area of a surface that is hinted to be completely * transparent. This is only used to tell when the layer has no visible * non-transparent regions and can be removed from the layer list. It * does not affect the visibleRegion of this layer or any layers * beneath it. The hint may not be correct if apps don't respect the * SurfaceView restrictions (which, sadly, some don't). */ Region transparentRegion;
// handle hidden surfaces by setting the visible region to empty if (CC_LIKELY(layer->isVisible())) { constbool translucent = !layer->isOpaque(s); Rect bounds(layer->getScreenBounds());
visibleRegion.set(bounds); ui::Transform tr = layer->getTransform(); if (!visibleRegion.isEmpty()) { // Remove the transparent area from the visible region if (translucent) { if (tr.preserveRects()) { // transform the transparent region transparentRegion = tr.transform(layer->getActiveTransparentRegion(s)); } else { // transformation too complex, can't do the // transparent region optimization. transparentRegion.clear(); } }
// compute the opaque region constint32_t layerOrientation = tr.getOrientation(); if (layer->getAlpha() == 1.0f && !translucent && layer->getRoundedCornerState().radius == 0.0f && ((layerOrientation & ui::Transform::ROT_INVALID) == false)) { // the opaque region is the layer's footprint opaqueRegion = visibleRegion; } } }
if (visibleRegion.isEmpty()) { layer->clearVisibilityRegions(); return; }
// Clip the covered region to the visible region coveredRegion = aboveCoveredLayers.intersect(visibleRegion);
// Update aboveCoveredLayers for next (lower) layer aboveCoveredLayers.orSelf(visibleRegion);
// subtract the opaque region covered by the layers above us visibleRegion.subtractSelf(aboveOpaqueLayers);
// compute this layer's dirty region if (layer->contentDirty) { // we need to invalidate the whole region dirty = visibleRegion; // as well, as the old visible region dirty.orSelf(layer->visibleRegion); layer->contentDirty = false; } else { /* compute the exposed region: * the exposed region consists of two components: * 1) what's VISIBLE now and was COVERED before * 2) what's EXPOSED now less what was EXPOSED before * * note that (1) is conservative, we start with the whole * visible region but only keep what used to be covered by * something -- which mean it may have been exposed. * * (2) handles areas that were not covered by anything but got * exposed because of a resize. */ const Region newExposed = visibleRegion - coveredRegion; const Region oldVisibleRegion = layer->visibleRegion; const Region oldCoveredRegion = layer->coveredRegion; const Region oldExposed = oldVisibleRegion - oldCoveredRegion; dirty = (visibleRegion&oldCoveredRegion) | (newExposed-oldExposed); } dirty.subtractSelf(aboveOpaqueLayers);
// accumulate to the screen dirty region outDirtyRegion.orSelf(dirty);
// Update aboveOpaqueLayers for next (lower) layer aboveOpaqueLayers.orSelf(opaqueRegion);
// Store the visible region in screen space layer->setVisibleRegion(visibleRegion); layer->setCoveredRegion(coveredRegion); layer->setVisibleNonTransparentRegion( visibleRegion.subtract(transparentRegion)); });
// rebuild the visible layer list per screen if (CC_UNLIKELY(mVisibleRegionsDirty)) { ATRACE_NAME("rebuildLayerStacks VR Dirty"); mVisibleRegionsDirty = false; invalidateHwcGeometry();
for (constauto& pair : mDisplays) { constauto& displayDevice = pair.second; auto display = displayDevice->getCompositionDisplay(); constauto& displayState = display->getState(); Region opaqueRegion; Region dirtyRegion; compositionengine::Output::OutputLayers layersSortedByZ; Vector<sp<Layer>> deprecated_layersSortedByZ; Vector<sp<Layer>> layersNeedingFences; const ui::Transform& tr = displayState.transform; const Rect bounds = displayState.bounds; if (displayState.isEnabled) { computeVisibleRegions(displayDevice, dirtyRegion, opaqueRegion);
mDrawingState.traverseInZOrder([&](Layer* layer) { auto compositionLayer = layer->getCompositionLayer(); if (compositionLayer == nullptr) { return; }
if (display->belongsInOutput(layer->getLayerStack(), layer->getPrimaryDisplayOnly())) { Region drawRegion(tr.transform( layer->visibleNonTransparentRegion)); drawRegion.andSelf(bounds); if (!drawRegion.isEmpty()) { needsOutputLayer = true; } }
if (needsOutputLayer) { layersSortedByZ.emplace_back( display->getOrCreateOutputLayer(displayId, compositionLayer, layerFE)); deprecated_layersSortedByZ.add(layer);
auto& outputLayerState = layersSortedByZ.back()->editState(); outputLayerState.visibleRegion = tr.transform(layer->visibleRegion.intersect(displayState.viewport)); } elseif (displayId) { // For layers that are being removed from a HWC display, // and that have queued frames, add them to a a list of // released layers so we can properly set a fence. bool hasExistingOutputLayer = display->getOutputLayerForLayer(compositionLayer.get()) != nullptr; bool hasQueuedFrames = std::find(mLayersWithQueuedFrames.cbegin(), mLayersWithQueuedFrames.cend(), layer) != mLayersWithQueuedFrames.cend();
if (hasExistingOutputLayer && hasQueuedFrames) { layersNeedingFences.add(layer); } } }); }
// Apply this display's projection's viewport to the visible region // before giving it to the HWC HAL. Region visible = transform.transform(visibleRegion.intersect(viewport));
// INVALID_BUFFER_SLOT is used to identify BufferStateLayers. Default to 0 // for BufferQueueLayers int slot = (mActiveBufferSlot == BufferQueue::INVALID_BUFFER_SLOT) ? 0 : mActiveBufferSlot; (*outputLayer->editState().hwc) .hwcBufferCache.getHwcBuffer(slot, mActiveBuffer, &hwcSlot, &hwcBuffer);
auto acquireFence = mConsumer->getCurrentFence(); auto error = hwcLayer->setBuffer(hwcSlot, hwcBuffer, acquireFence); if (error != HWC2::Error::None) { ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(), mActiveBuffer->handle, to_string(error).c_str(), static_cast<int32_t>(error)); }
auto& hwc = mCompositionEngine.getHwComposer(); constauto id = mDisplay.getId(); if (id) { status_t error = hwc.prepare(*id, mDisplay); if (error != NO_ERROR) { return error; } }
DisplaySurface::CompositionType compositionType; constbool hasClient = hwc.hasClientComposition(id); constbool hasDevice = hwc.hasDeviceComposition(id); if (hasClient && hasDevice) { compositionType = DisplaySurface::COMPOSITION_MIXED; } elseif (hasClient) { compositionType = DisplaySurface::COMPOSITION_GLES; } elseif (hasDevice) { compositionType = DisplaySurface::COMPOSITION_HWC; } else { // Nothing to do -- when turning the screen off we get a frame like // this. Call it a HWC frame since we won't be doing any GLES work but // will do a prepare/set cycle. compositionType = DisplaySurface::COMPOSITION_HWC; } return mDisplaySurface->prepareFrame(compositionType); }
auto display = displayDevice->getCompositionDisplay(); constauto& displayState = display->getState();
if (displayState.isEnabled) { // transform the dirty region into this screen's coordinate space const Region dirtyRegion = display->getDirtyRegion(repaintEverything);
// repaint the framebuffer (if needed) doDisplayComposition(displayDevice, dirtyRegion);
voidSurfaceFlinger::doDisplayComposition(const sp<DisplayDevice>& displayDevice, const Region& inDirtyRegion){ auto display = displayDevice->getCompositionDisplay(); // We only need to actually compose the display if: // 1) It is being handled by hardware composer, which may need this to // keep its virtual display state machine in sync, or // 2) There is work to be done (the dirty region isn't empty) if (!displayDevice->getId() && inDirtyRegion.isEmpty()) { ALOGV("Skipping display composition"); return; } ALOGI("zjj.rk3399.SF doDisplayComposition %s %s %d \n",__FILE__,__FUNCTION__,__LINE__);
//ALOGV("doDisplayComposition"); base::unique_fd readyFence; if (!doComposeSurfaces(displayDevice, Region::INVALID_REGION, &readyFence)) return;
if (buf == nullptr) { ALOGW("Dequeuing buffer for display [%s] failed, bailing out of " "client composition for this frame", displayDevice->getDisplayName().c_str()); returnfalse; }
// Compute the global color transform matrix. applyColorMatrix = !hasDeviceComposition && !skipClientColorTransform; if (applyColorMatrix) { clientCompositionDisplay.colorTransform = displayState.colorTransformMat; } }
/* * and then, render the layers targeted at the framebuffer */
ALOGV("Rendering client layers"); bool firstLayer = true; Region clearRegion = Region::INVALID_REGION; for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { const Region viewportRegion(displayState.viewport); const Region clip(viewportRegion.intersect(layer->visibleRegion)); ALOGV("Layer: %s", layer->getName().string()); ALOGV(" Composition type: %s", toString(layer->getCompositionType(displayDevice)).c_str()); if (!clip.isEmpty()) { switch (layer->getCompositionType(displayDevice)) { case Hwc2::IComposerClient::Composition::CURSOR: case Hwc2::IComposerClient::Composition::DEVICE: case Hwc2::IComposerClient::Composition::SIDEBAND: case Hwc2::IComposerClient::Composition::SOLID_COLOR: { LOG_ALWAYS_FATAL_IF(!displayId); const Layer::State& state(layer->getDrawingState()); if (layer->getClearClientTarget(displayDevice) && !firstLayer && layer->isOpaque(state) && (layer->getAlpha() == 1.0f) && layer->getRoundedCornerState().radius == 0.0f && hasClientComposition) { // never clear the very first layer since we're // guaranteed the FB is already cleared renderengine::LayerSettings layerSettings; Region dummyRegion; bool prepared = layer->prepareClientLayer(renderArea, clip, dummyRegion, supportProtectedContent, layerSettings);
// Perform some cleanup steps if we used client composition. if (hasClientComposition) { clientCompositionDisplay.clearRegion = clearRegion;
// We boost GPU frequency here because there will be color spaces conversion // and it's expensive. We boost the GPU frequency so that GPU composition can // finish in time. We must reset GPU frequency afterwards, because high frequency // consumes extra battery. constbool expensiveRenderingExpected = clientCompositionDisplay.outputDataspace == Dataspace::DISPLAY_P3; if (expensiveRenderingExpected && displayId) { mPowerAdvisor.setExpensiveRenderingExpected(*displayId, true); } if (!debugRegion.isEmpty()) { Region::const_iterator it = debugRegion.begin(); Region::const_iterator end = debugRegion.end(); while (it != end) { const Rect& rect = *it++; renderengine::LayerSettings layerSettings; layerSettings.source.buffer.buffer = nullptr; layerSettings.source.solidColor = half3(1.0, 0.0, 1.0); layerSettings.geometry.boundaries = rect.toFloatRect(); layerSettings.alpha = half(1.0); clientCompositionLayers.push_back(layerSettings); } } ALOGD_CALLSTACK("drawLayers");
10-2809:40:54.275179179 V SurfaceFlinger: hasClientComposition 10-2809:40:54.275179179 I CompositionEngine: zjj.rk3399.SF dequeueBuffer frameworks/native/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp dequeueBuffer 166 10-2809:40:54.275179179 D CompositionEngine: queueBuffer 10-2809:40:54.297179179 D CompositionEngine: #00 pc 000000000011ed98 /system/lib64/libsurfaceflinger.so (android::compositionengine::impl::RenderSurface::dequeueBuffer(android::base::unique_fd_impl<android::base::DefaultCloser>*)+184) 10-2809:40:54.297179179 D CompositionEngine: #01 pc 00000000000e3998 /system/lib64/libsurfaceflinger.so (android::SurfaceFlinger::doComposeSurfaces(android::sp<android::DisplayDevice> const&, android::Region const&, android::base::unique_fd_impl<android::base::DefaultCloser>*)+1024) 10-2809:40:54.297179179 D CompositionEngine: #02 pc 00000000000e0868 /system/lib64/libsurfaceflinger.so (android::SurfaceFlinger::handleMessageRefresh()+3528) 10-2809:40:54.297179179 D CompositionEngine: #03 pc 00000000000df6bc /system/lib64/libsurfaceflinger.so (android::SurfaceFlinger::onMessageReceived(int)+9484) 10-2809:40:54.297179179 D CompositionEngine: #04 pc 0000000000017dfc /system/lib64/libutils.so (android::Looper::pollInner(int)+332) 10-2809:40:54.297179179 D CompositionEngine: #05 pc 0000000000017c10 /system/lib64/libutils.so (android::Looper::pollOnce(int, int*, int*, void**)+56) 10-2809:40:54.297179179 D CompositionEngine: #06 pc 00000000000ced04 /system/lib64/libsurfaceflinger.so (android::impl::MessageQueue::waitMessage()+92) 10-2809:40:54.297179179 D CompositionEngine: #07 pc 00000000000dc69c /system/lib64/libsurfaceflinger.so (android::SurfaceFlinger::run()+20) 10-2809:40:54.297179179 D CompositionEngine: #08 pc 0000000000003370 /system/bin/surfaceflinger (main+800) 10-2809:40:54.297179179 D CompositionEngine: #09 pc 000000000007d844 /apex/com.android.runtime/lib64/bionic/libc.so (__libc_init+108) 10-2809:40:54.297179179 V Surface : Surface::dequeueBuffer 10-2809:40:54.297179179 V BufferQueueProducer: [FramebufferSurface] dequeueBuffer: w=0 h=0 format=0x1, usage=0x200 10-2809:40:54.297179179 V BufferQueueProducer: [FramebufferSurface] dequeueBuffer: setting buffer age to 1 10-2809:40:54.297179179 V BufferQueueProducer: [FramebufferSurface] dequeueBuffer: returning slot=2/0 buf=0x70de65bb40 flags=0x1 10-2809:40:54.297179179 V BufferQueueProducer: [FramebufferSurface] requestBuffer: slot 2 10-2809:40:54.297179179 V SurfaceFlinger: Rendering client layers
status_t result = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buffer, &fd);
if (result != NO_ERROR) { ALOGE("ANativeWindow::dequeueBuffer failed for display [%s] with error: %d", mDisplay.getName().c_str(), result); // Return fast here as we can't do much more - any rendering we do // now will just be wrong. return mGraphicBuffer; }
ALOGW_IF(mGraphicBuffer != nullptr, "Clobbering a non-null pointer to a buffer [%p].", mGraphicBuffer->getNativeBuffer()->handle); mGraphicBuffer = GraphicBuffer::from(buffer);
Layer::prepareClientLayer(renderArea, clip, useIdentityTransform, clearRegion, supportProtectedContent, layer); if (CC_UNLIKELY(mActiveBuffer == 0)) { // the texture has not been created yet, this Layer has // in fact never been drawn into. This happens frequently with // SurfaceView because the WindowManager can't know when the client // has drawn the first time.
// If there is nothing under us, we paint the screen in black, otherwise // we just skip this update.
// figure out if there is something below us Region under; bool finished = false; mFlinger->mDrawingState.traverseInZOrder([&](Layer* layer) { if (finished || layer == static_cast<BufferLayer const*>(this)) { finished = true; return; } under.orSelf(layer->visibleRegion); }); // if not everything below us is covered, we plug the holes! Region holes(clip.subtract(under)); if (!holes.isEmpty()) { clearRegion.orSelf(holes); } returnfalse; }
//rk_ext: Deliver to GLESRenderEngine for 10bit to 8bit layer.source.buffer.currentcrop = mCurrentCrop;
bool blackOutLayer = (isProtected() && !supportProtectedContent) || (isSecure() && !renderArea.isSecure()); const State& s(getDrawingState()); if (!blackOutLayer) { layer.source.buffer.buffer = mActiveBuffer; layer.source.buffer.isOpaque = isOpaque(s); layer.source.buffer.fence = mActiveBufferFence; layer.source.buffer.textureName = mTextureName; layer.source.buffer.usePremultipliedAlpha = getPremultipledAlpha(); layer.source.buffer.isY410BT2020 = isHdrY410(); // TODO: we could be more subtle with isFixedSize() constbool useFiltering = needsFiltering(renderArea.getDisplayDevice()) || renderArea.needsFiltering() || isFixedSize();
// Query the texture matrix given our current filtering mode. float textureMatrix[16]; setFilteringEnabled(useFiltering); getDrawingTransformMatrix(textureMatrix);
if (getTransformToDisplayInverse()) { /* * the code below applies the primary display's inverse transform to * the texture transform */ uint32_t transform = DisplayDevice::getPrimaryDisplayOrientationTransform(); mat4 tr = inverseOrientation(transform);
/** * TODO(b/36727915): This is basically a hack. * * Ensure that regardless of the parent transformation, * this buffer is always transformed from native display * orientation to display orientation. For example, in the case * of a camera where the buffer remains in native orientation, * we want the pixels to always be upright. */ sp<Layer> p = mDrawingParent.promote(); if (p != nullptr) { constauto parentTransform = p->getTransform(); tr = tr * inverseOrientation(parentTransform.getOrientation()); }
// and finally apply it to the original texture matrix const mat4 texTransform(mat4(static_cast<constfloat*>(textureMatrix)) * tr); memcpy(textureMatrix, texTransform.asArray(), sizeof(textureMatrix)); }
// BufferStateLayers can have a "buffer size" of [0, 0, -1, -1] when no display frame has // been set and there is no parent layer bounds. In that case, the scale is meaningless so // ignore them. if (!getBufferSize(s).isValid()) { bufferWidth = float(win.right) - float(win.left); bufferHeight = float(win.bottom) - float(win.top); }
layer.source.buffer.useTextureFiltering = useFiltering; layer.source.buffer.textureTransform = mat4(static_cast<constfloat*>(textureMatrix)) * tr; } else { // If layer is blacked out, force alpha to 1 so that we draw a black color // layer. layer.source.buffer.buffer = nullptr; layer.alpha = 1.0; }
if (fbo.getStatus() != NO_ERROR) { ALOGE("Failed to bind framebuffer! Aborting GPU composition for buffer (%p).", buffer->handle); checkErrors(); return fbo.getStatus(); }
// clear the entire buffer, sometimes when we reuse buffers we'd persist // ghost images otherwise. // we also require a full transparent framebuffer for overlays. This is // probably not quite efficient on all GPUs, since we could filter out // opaque layers. clearWithColor(0.0, 0.0, 0.0, 0.0);
const half3 solidColor = layer.source.solidColor; const half4 color = half4(solidColor.r, solidColor.g, solidColor.b, layer.alpha); // Buffer sources will have a black solid color ignored in the shader, // so in that scenario the solid color passed here is arbitrary. setupLayerBlending(usePremultipliedAlpha, isOpaque, disableTexture, color, layer.geometry.roundedCornersRadius); if (layer.disableBlending) { glDisable(GL_BLEND); } setSourceDataSpace(layer.sourceDataspace);
// We only want to do a special handling for rounded corners when having rounded corners // is the only reason it needs to turn on blending, otherwise, we handle it like the // usual way since it needs to turn on blending anyway. if (layer.geometry.roundedCornersRadius > 0.0 && color.a >= 1.0f && isOpaque) { handleRoundedCorners(display, layer, mesh); } else { drawMesh(mesh); }
// Cleanup if there's a buffer source if (layer.source.buffer.buffer != nullptr) { disableBlending(); setSourceY410BT2020(false); disableTexturing(); } }
*drawFence = flush(); } // If flush failed or we don't support native fences, we need to force the // gl command stream to be executed. if (drawFence == nullptr || drawFence->get() < 0) { ALOGI("zjj.rk3399.SF drawFence %s %s %d \n",__FILE__,__FUNCTION__,__LINE__);
bool success = finish(); if (!success) { ALOGE("Failed to flush RenderEngine commands"); checkErrors(); // Chances are, something illegal happened (either the caller passed // us bad parameters, or we messed up our shader generation). return INVALID_OPERATION; } }
checkErrors(); return NO_ERROR; }
看看Log:
1 2 3 4 5 6 7 8
10-2809:40:54.319179179 I RenderEngine: zjj.rk3399.SF drawLayers frameworks/native/libs/renderengine/gl/GLESRenderEngine.cpp drawLayers 1089 10-2809:40:54.319179179 I RenderEngine: zjj.rk3399.SF getFramebufferForDrawing frameworks/native/libs/renderengine/gl/GLESRenderEngine.cpp getFramebufferForDrawing 484 10-2809:40:54.319179179 I RenderEngine: zjj.rk3399.SF setNativeWindowBuffer frameworks/native/libs/renderengine/gl/GLFramebuffer.cpp setNativeWindowBuffer 48 10-2809:40:54.319179179 I RenderEngine: zjj.rk3399.SF createFramebufferImageIfNeeded frameworks/native/libs/renderengine/gl/GLESRenderEngine.cpp createFramebufferImageIfNeeded 944 10-2809:40:54.320179179 I RenderEngine: zjj.rk3399.SF bindFrameBuffer frameworks/native/libs/renderengine/gl/GLESRenderEngine.cpp bindFrameBuffer 883 10-2809:40:54.320179179 I RenderEngine: zjj.rk3399.SF bindExternalTextureBuffer frameworks/native/libs/renderengine/gl/GLESRenderEngine.cpp bindExternalTextureBuffer 667 10-2809:40:54.320179179 I RenderEngine: zjj.rk3399.SF bindExternalTextureImage frameworks/native/libs/renderengine/gl/GLESRenderEngine.cpp bindExternalTextureImage 648 10-2809:40:54.321179179 I RenderEngine: zjj.rk3399.SF flush frameworks/native/libs/renderengine/gl/GLESRenderEngine.cpp flush 503
if (hwc.hasClientComposition(id) || hwc.hasFlipClientTargetRequest(id)) { // hasFlipClientTargetRequest could return true even if we haven't // dequeued a buffer before. Try dequeueing one if we don't have a // buffer ready. if (mGraphicBuffer == nullptr) { ALOGI("Attempting to queue a client composited buffer without one " "previously dequeued for display [%s]. Attempting to dequeue " "a scratch buffer now", mDisplay.getName().c_str()); // We shouldn't deadlock here, since mGraphicBuffer == nullptr only // after a successful call to queueBuffer, or if dequeueBuffer has // never been called. base::unique_fd unused; dequeueBuffer(&unused); }
if (mGraphicBuffer == nullptr) { ALOGE("No buffer is ready for display [%s]", mDisplay.getName().c_str()); } else { status_t result = mNativeWindow->queueBuffer(mNativeWindow.get(), mGraphicBuffer->getNativeBuffer(), dup(readyFence)); if (result != NO_ERROR) { ALOGE("Error when queueing buffer for display [%s]: %d", mDisplay.getName().c_str(), result); // We risk blocking on dequeueBuffer if the primary display failed // to queue up its buffer, so crash here. if (!mDisplay.isVirtual()) { LOG_ALWAYS_FATAL("ANativeWindow::queueBuffer failed with error: %d", result); } else { mNativeWindow->cancelBuffer(mNativeWindow.get(), mGraphicBuffer->getNativeBuffer(), dup(readyFence)); } }
mGraphicBuffer = nullptr; } }
status_t result = mDisplaySurface->advanceFrame(); if (result != NO_ERROR) { ALOGE("[%s] failed pushing new frame to HWC: %d", mDisplay.getName().c_str(), result); } }
// If the BufferQueue has freed and reallocated a buffer in mCurrentSlot // then we may have acquired the slot we already own. If we had released // our current buffer before we call acquireBuffer then that release call // would have returned STALE_BUFFER_SLOT, and we would have called // freeBufferLocked on that slot. Because the buffer slot has already // been overwritten with the new buffer all we have to do is skip the // releaseBuffer call and we should be in the same state we'd be in if we // had released the old buffer first. if (mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT && item.mSlot != mCurrentBufferSlot) { mHasPendingRelease = true; mPreviousBufferSlot = mCurrentBufferSlot; mPreviousBuffer = mCurrentBuffer; } mCurrentBufferSlot = item.mSlot; mCurrentBuffer = mSlots[mCurrentBufferSlot].mGraphicBuffer; mCurrentFence = item.mFence;
if (displayState.isEnabled) { if (displayId) { getHwComposer().presentAndGetReleaseFences(*displayId); } display->getRenderSurface()->onPresentDisplayCompleted(); for (auto& layer : display->getOutputLayersOrderedByZ()) { sp<Fence> releaseFence = Fence::NO_FENCE; bool usedClientComposition = true;
// The layer buffer from the previous frame (if any) is released // by HWC only when the release fence from this frame (if any) is // signaled. Always get the release fence from HWC first. if (layer->getState().hwc) { constauto& hwcState = *layer->getState().hwc; releaseFence = getHwComposer().getLayerReleaseFence(*displayId, hwcState.hwcLayer.get()); usedClientComposition = hwcState.hwcCompositionType == Hwc2::IComposerClient::Composition::CLIENT; }
// If the layer was client composited in the previous frame, we // need to merge with the previous client target acquire fence. // Since we do not track that, always merge with the current // client target acquire fence when it is available, even though // this is suboptimal. if (usedClientComposition) { releaseFence = Fence::merge("LayerRelease", releaseFence, display->getRenderSurface()->getClientTargetAcquireFence()); }
// We've got a list of layers needing fences, that are disjoint with // display->getVisibleLayersSortedByZ. The best we can do is to // supply them with the present fence. if (!displayDevice->getLayersNeedingFences().isEmpty()) { sp<Fence> presentFence = displayId ? getHwComposer().getPresentFence(*displayId) : Fence::NO_FENCE; for (auto& layer : displayDevice->getLayersNeedingFences()) { layer->getCompositionLayer()->getLayerFE()->onLayerDisplayed(presentFence); } }
if (displayId) { getHwComposer().clearReleaseFences(*displayId); } } }
X:\frameworks\native\libs\gui\ConsumerBase.cpp status_tConsumerBase::releaseBufferLocked( int slot, const sp<GraphicBuffer> graphicBuffer, EGLDisplay display, EGLSyncKHR eglFence){ if (mAbandoned) { CB_LOGE("releaseBufferLocked: ConsumerBase is abandoned!"); return NO_INIT; } // If consumer no longer tracks this graphicBuffer (we received a new // buffer on the same slot), the buffer producer is definitely no longer // tracking it. if (!stillTracking(slot, graphicBuffer)) { return OK; }
voidSurfaceFlinger::postFrame() { // |mStateLock| not needed as we are on the main thread ALOGI("zjj.rk3399.SF postFrame %s %s %d \n",__FILE__,__FUNCTION__,__LINE__);
// Release any buffers which were replaced this frame nsecs_t dequeueReadyTime = systemTime(); for (auto& layer : mLayersWithQueuedFrames) { layer->releasePendingBuffer(dequeueReadyTime); }
// |mStateLock| not needed as we are on the main thread constauto displayDevice = getDefaultDisplayDeviceLocked();
// We use the mRefreshStartTime which might be sampled a little later than // when we started doing work for this frame, but that should be okay // since updateCompositorTiming has snapping logic. updateCompositorTiming(stats, mRefreshStartTime, presentFenceTime); CompositorTiming compositorTiming; { std::lock_guard<std::mutex> lock(getBE().mCompositorTimingLock); compositorTiming = getBE().mCompositorTiming; }
// Lock the mStateLock in case SurfaceFlinger is in the middle of applying a transaction. // If we do not lock here, a callback could be sent without all of its SurfaceControls and // metrics. { Mutex::Autolock _l(mStateLock); mTransactionCompletedThread.sendCallbacks(); }
if (mLumaSampling && mRegionSamplingThread) { mRegionSamplingThread->notifyNewContent(); }
// Even though ATRACE_INT64 already checks if tracing is enabled, it doesn't prevent the // side-effect of getTotalSize(), so we check that again here if (ATRACE_ENABLED()) { ATRACE_INT64("Total Buffer Size", GraphicBufferAllocator::get().getTotalSize()); } }