1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 //#define LOG_NDEBUG 0
18 #undef LOG_TAG
19 #define LOG_TAG "BufferStateLayer"
20 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
21
22 #include <limits>
23
24 #include <compositionengine/Display.h>
25 #include <compositionengine/Layer.h>
26 #include <compositionengine/OutputLayer.h>
27 #include <compositionengine/impl/LayerCompositionState.h>
28 #include <compositionengine/impl/OutputLayerCompositionState.h>
29 #include <gui/BufferQueue.h>
30 #include <private/gui/SyncFeatures.h>
31 #include <renderengine/Image.h>
32
33 #include "BufferStateLayer.h"
34 #include "ColorLayer.h"
35 #include "TimeStats/TimeStats.h"
36
37 namespace android {
38
39 // clang-format off
40 const std::array<float, 16> BufferStateLayer::IDENTITY_MATRIX{
41 1, 0, 0, 0,
42 0, 1, 0, 0,
43 0, 0, 1, 0,
44 0, 0, 0, 1
45 };
46 // clang-format on
47
BufferStateLayer(const LayerCreationArgs & args)48 BufferStateLayer::BufferStateLayer(const LayerCreationArgs& args)
49 : BufferLayer(args), mHwcSlotGenerator(new HwcSlotGenerator()) {
50 mOverrideScalingMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW;
51 mCurrentState.dataspace = ui::Dataspace::V0_SRGB;
52 }
~BufferStateLayer()53 BufferStateLayer::~BufferStateLayer() {
54 if (mActiveBuffer != nullptr) {
55 auto& engine(mFlinger->getRenderEngine());
56 engine.unbindExternalTextureBuffer(mActiveBuffer->getId());
57 }
58 }
59
60 // -----------------------------------------------------------------------
61 // Interface implementation for Layer
62 // -----------------------------------------------------------------------
onLayerDisplayed(const sp<Fence> & releaseFence)63 void BufferStateLayer::onLayerDisplayed(const sp<Fence>& releaseFence) {
64 // The previous release fence notifies the client that SurfaceFlinger is done with the previous
65 // buffer that was presented on this layer. The first transaction that came in this frame that
66 // replaced the previous buffer on this layer needs this release fence, because the fence will
67 // let the client know when that previous buffer is removed from the screen.
68 //
69 // Every other transaction on this layer does not need a release fence because no other
70 // Transactions that were set on this layer this frame are going to have their preceeding buffer
71 // removed from the display this frame.
72 //
73 // For example, if we have 3 transactions this frame. The first transaction doesn't contain a
74 // buffer so it doesn't need a previous release fence because the layer still needs the previous
75 // buffer. The second transaction contains a buffer so it needs a previous release fence because
76 // the previous buffer will be released this frame. The third transaction also contains a
77 // buffer. It replaces the buffer in the second transaction. The buffer in the second
78 // transaction will now no longer be presented so it is released immediately and the third
79 // transaction doesn't need a previous release fence.
80 for (auto& handle : mDrawingState.callbackHandles) {
81 if (handle->releasePreviousBuffer) {
82 handle->previousReleaseFence = releaseFence;
83 break;
84 }
85 }
86 }
87
setTransformHint(uint32_t) const88 void BufferStateLayer::setTransformHint(uint32_t /*orientation*/) const {
89 // TODO(marissaw): send the transform hint to buffer owner
90 return;
91 }
92
releasePendingBuffer(nsecs_t)93 void BufferStateLayer::releasePendingBuffer(nsecs_t /*dequeueReadyTime*/) {
94 mFlinger->getTransactionCompletedThread().addPresentedCallbackHandles(
95 mDrawingState.callbackHandles);
96
97 mDrawingState.callbackHandles = {};
98 }
99
shouldPresentNow(nsecs_t) const100 bool BufferStateLayer::shouldPresentNow(nsecs_t /*expectedPresentTime*/) const {
101 if (getSidebandStreamChanged() || getAutoRefresh()) {
102 return true;
103 }
104
105 return hasFrameUpdate();
106 }
107
willPresentCurrentTransaction() const108 bool BufferStateLayer::willPresentCurrentTransaction() const {
109 // Returns true if the most recent Transaction applied to CurrentState will be presented.
110 return getSidebandStreamChanged() || getAutoRefresh() ||
111 (mCurrentState.modified &&
112 (mCurrentState.buffer != nullptr || mCurrentState.bgColorLayer != nullptr));
113 }
114
getTransformToDisplayInverse() const115 bool BufferStateLayer::getTransformToDisplayInverse() const {
116 return mCurrentState.transformToDisplayInverse;
117 }
118
pushPendingState()119 void BufferStateLayer::pushPendingState() {
120 if (!mCurrentState.modified) {
121 return;
122 }
123 mPendingStates.push_back(mCurrentState);
124 ATRACE_INT(mTransactionName.string(), mPendingStates.size());
125 }
126
applyPendingStates(Layer::State * stateToCommit)127 bool BufferStateLayer::applyPendingStates(Layer::State* stateToCommit) {
128 const bool stateUpdateAvailable = !mPendingStates.empty();
129 while (!mPendingStates.empty()) {
130 popPendingState(stateToCommit);
131 }
132 mCurrentStateModified = stateUpdateAvailable && mCurrentState.modified;
133 mCurrentState.modified = false;
134 return stateUpdateAvailable;
135 }
136
137 // Crop that applies to the window
getCrop(const Layer::State &) const138 Rect BufferStateLayer::getCrop(const Layer::State& /*s*/) const {
139 return Rect::INVALID_RECT;
140 }
141
setTransform(uint32_t transform)142 bool BufferStateLayer::setTransform(uint32_t transform) {
143 if (mCurrentState.transform == transform) return false;
144 mCurrentState.transform = transform;
145 mCurrentState.modified = true;
146 setTransactionFlags(eTransactionNeeded);
147 return true;
148 }
149
setTransformToDisplayInverse(bool transformToDisplayInverse)150 bool BufferStateLayer::setTransformToDisplayInverse(bool transformToDisplayInverse) {
151 if (mCurrentState.transformToDisplayInverse == transformToDisplayInverse) return false;
152 mCurrentState.sequence++;
153 mCurrentState.transformToDisplayInverse = transformToDisplayInverse;
154 mCurrentState.modified = true;
155 setTransactionFlags(eTransactionNeeded);
156 return true;
157 }
158
setCrop(const Rect & crop)159 bool BufferStateLayer::setCrop(const Rect& crop) {
160 Rect c = crop;
161 if (c.left < 0) {
162 c.left = 0;
163 }
164 if (c.top < 0) {
165 c.top = 0;
166 }
167 // If the width and/or height are < 0, make it [0, 0, -1, -1] so the equality comparision below
168 // treats all invalid rectangles the same.
169 if (!c.isValid()) {
170 c.makeInvalid();
171 }
172
173 if (mCurrentState.crop == c) return false;
174 mCurrentState.crop = c;
175 mCurrentState.modified = true;
176 setTransactionFlags(eTransactionNeeded);
177 return true;
178 }
179
setFrame(const Rect & frame)180 bool BufferStateLayer::setFrame(const Rect& frame) {
181 int x = frame.left;
182 int y = frame.top;
183 int w = frame.getWidth();
184 int h = frame.getHeight();
185
186 if (x < 0) {
187 x = 0;
188 w = frame.right;
189 }
190
191 if (y < 0) {
192 y = 0;
193 h = frame.bottom;
194 }
195
196 if (mCurrentState.active.transform.tx() == x && mCurrentState.active.transform.ty() == y &&
197 mCurrentState.active.w == w && mCurrentState.active.h == h) {
198 return false;
199 }
200
201 if (!frame.isValid()) {
202 x = y = w = h = 0;
203 }
204 mCurrentState.active.transform.set(x, y);
205 mCurrentState.active.w = w;
206 mCurrentState.active.h = h;
207
208 mCurrentState.sequence++;
209 mCurrentState.modified = true;
210 setTransactionFlags(eTransactionNeeded);
211 return true;
212 }
213
setBuffer(const sp<GraphicBuffer> & buffer,nsecs_t postTime,nsecs_t desiredPresentTime,const client_cache_t & clientCacheId)214 bool BufferStateLayer::setBuffer(const sp<GraphicBuffer>& buffer, nsecs_t postTime,
215 nsecs_t desiredPresentTime, const client_cache_t& clientCacheId) {
216 if (mCurrentState.buffer) {
217 mReleasePreviousBuffer = true;
218 }
219
220 mCurrentState.buffer = buffer;
221 mCurrentState.clientCacheId = clientCacheId;
222 mCurrentState.modified = true;
223 setTransactionFlags(eTransactionNeeded);
224
225 mFlinger->mTimeStats->setPostTime(getSequence(), getFrameNumber(), getName().c_str(), postTime);
226 mDesiredPresentTime = desiredPresentTime;
227
228 if (mFlinger->mUseSmart90ForVideo) {
229 const nsecs_t presentTime = (mDesiredPresentTime == -1) ? 0 : mDesiredPresentTime;
230 mFlinger->mScheduler->addLayerPresentTimeAndHDR(mSchedulerLayerHandle, presentTime,
231 mCurrentState.hdrMetadata.validTypes != 0);
232 }
233
234 return true;
235 }
236
setAcquireFence(const sp<Fence> & fence)237 bool BufferStateLayer::setAcquireFence(const sp<Fence>& fence) {
238 // The acquire fences of BufferStateLayers have already signaled before they are set
239 mCallbackHandleAcquireTime = fence->getSignalTime();
240
241 mCurrentState.acquireFence = fence;
242 mCurrentState.modified = true;
243 setTransactionFlags(eTransactionNeeded);
244 return true;
245 }
246
setDataspace(ui::Dataspace dataspace)247 bool BufferStateLayer::setDataspace(ui::Dataspace dataspace) {
248 if (mCurrentState.dataspace == dataspace) return false;
249 mCurrentState.dataspace = dataspace;
250 mCurrentState.modified = true;
251 setTransactionFlags(eTransactionNeeded);
252 return true;
253 }
254
setHdrMetadata(const HdrMetadata & hdrMetadata)255 bool BufferStateLayer::setHdrMetadata(const HdrMetadata& hdrMetadata) {
256 if (mCurrentState.hdrMetadata == hdrMetadata) return false;
257 mCurrentState.hdrMetadata = hdrMetadata;
258 mCurrentState.modified = true;
259 setTransactionFlags(eTransactionNeeded);
260 return true;
261 }
262
setSurfaceDamageRegion(const Region & surfaceDamage)263 bool BufferStateLayer::setSurfaceDamageRegion(const Region& surfaceDamage) {
264 mCurrentState.surfaceDamageRegion = surfaceDamage;
265 mCurrentState.modified = true;
266 setTransactionFlags(eTransactionNeeded);
267 return true;
268 }
269
setApi(int32_t api)270 bool BufferStateLayer::setApi(int32_t api) {
271 if (mCurrentState.api == api) return false;
272 mCurrentState.api = api;
273 mCurrentState.modified = true;
274 setTransactionFlags(eTransactionNeeded);
275 return true;
276 }
277
setSidebandStream(const sp<NativeHandle> & sidebandStream)278 bool BufferStateLayer::setSidebandStream(const sp<NativeHandle>& sidebandStream) {
279 if (mCurrentState.sidebandStream == sidebandStream) return false;
280 mCurrentState.sidebandStream = sidebandStream;
281 mCurrentState.modified = true;
282 setTransactionFlags(eTransactionNeeded);
283
284 if (!mSidebandStreamChanged.exchange(true)) {
285 // mSidebandStreamChanged was false
286 mFlinger->signalLayerUpdate();
287 }
288 return true;
289 }
290
setTransactionCompletedListeners(const std::vector<sp<CallbackHandle>> & handles)291 bool BufferStateLayer::setTransactionCompletedListeners(
292 const std::vector<sp<CallbackHandle>>& handles) {
293 // If there is no handle, we will not send a callback so reset mReleasePreviousBuffer and return
294 if (handles.empty()) {
295 mReleasePreviousBuffer = false;
296 return false;
297 }
298
299 const bool willPresent = willPresentCurrentTransaction();
300
301 for (const auto& handle : handles) {
302 // If this transaction set a buffer on this layer, release its previous buffer
303 handle->releasePreviousBuffer = mReleasePreviousBuffer;
304
305 // If this layer will be presented in this frame
306 if (willPresent) {
307 // If this transaction set an acquire fence on this layer, set its acquire time
308 handle->acquireTime = mCallbackHandleAcquireTime;
309
310 // Notify the transaction completed thread that there is a pending latched callback
311 // handle
312 mFlinger->getTransactionCompletedThread().registerPendingCallbackHandle(handle);
313
314 // Store so latched time and release fence can be set
315 mCurrentState.callbackHandles.push_back(handle);
316
317 } else { // If this layer will NOT need to be relatched and presented this frame
318 // Notify the transaction completed thread this handle is done
319 mFlinger->getTransactionCompletedThread().addUnpresentedCallbackHandle(handle);
320 }
321 }
322
323 mReleasePreviousBuffer = false;
324 mCallbackHandleAcquireTime = -1;
325
326 return willPresent;
327 }
328
setTransparentRegionHint(const Region & transparent)329 bool BufferStateLayer::setTransparentRegionHint(const Region& transparent) {
330 mCurrentState.transparentRegionHint = transparent;
331 mCurrentState.modified = true;
332 setTransactionFlags(eTransactionNeeded);
333 return true;
334 }
335
getBufferSize(const State & s) const336 Rect BufferStateLayer::getBufferSize(const State& s) const {
337 // for buffer state layers we use the display frame size as the buffer size.
338 if (getActiveWidth(s) < UINT32_MAX && getActiveHeight(s) < UINT32_MAX) {
339 return Rect(getActiveWidth(s), getActiveHeight(s));
340 }
341
342 // if the display frame is not defined, use the parent bounds as the buffer size.
343 const auto& p = mDrawingParent.promote();
344 if (p != nullptr) {
345 Rect parentBounds = Rect(p->getBounds(Region()));
346 if (!parentBounds.isEmpty()) {
347 return parentBounds;
348 }
349 }
350
351 return Rect::INVALID_RECT;
352 }
353
computeSourceBounds(const FloatRect & parentBounds) const354 FloatRect BufferStateLayer::computeSourceBounds(const FloatRect& parentBounds) const {
355 const State& s(getDrawingState());
356 // for buffer state layers we use the display frame size as the buffer size.
357 if (getActiveWidth(s) < UINT32_MAX && getActiveHeight(s) < UINT32_MAX) {
358 return FloatRect(0, 0, getActiveWidth(s), getActiveHeight(s));
359 }
360
361 // if the display frame is not defined, use the parent bounds as the buffer size.
362 return parentBounds;
363 }
364
365 // -----------------------------------------------------------------------
366
367 // -----------------------------------------------------------------------
368 // Interface implementation for BufferLayer
369 // -----------------------------------------------------------------------
fenceHasSignaled() const370 bool BufferStateLayer::fenceHasSignaled() const {
371 if (latchUnsignaledBuffers()) {
372 return true;
373 }
374
375 return getDrawingState().acquireFence->getStatus() == Fence::Status::Signaled;
376 }
377
framePresentTimeIsCurrent() const378 bool BufferStateLayer::framePresentTimeIsCurrent() const {
379 if (!hasFrameUpdate() || isRemovedFromCurrentState()) {
380 return true;
381 }
382
383 return mDesiredPresentTime <= mFlinger->mScheduler->expectedPresentTime();
384 }
385
getDesiredPresentTime()386 nsecs_t BufferStateLayer::getDesiredPresentTime() {
387 return mDesiredPresentTime;
388 }
389
getCurrentFenceTime() const390 std::shared_ptr<FenceTime> BufferStateLayer::getCurrentFenceTime() const {
391 return std::make_shared<FenceTime>(getDrawingState().acquireFence);
392 }
393
getDrawingTransformMatrix(float * matrix)394 void BufferStateLayer::getDrawingTransformMatrix(float *matrix) {
395 std::copy(std::begin(mTransformMatrix), std::end(mTransformMatrix), matrix);
396 }
397
getDrawingTransform() const398 uint32_t BufferStateLayer::getDrawingTransform() const {
399 return getDrawingState().transform;
400 }
401
getDrawingDataSpace() const402 ui::Dataspace BufferStateLayer::getDrawingDataSpace() const {
403 return getDrawingState().dataspace;
404 }
405
406 // Crop that applies to the buffer
getDrawingCrop() const407 Rect BufferStateLayer::getDrawingCrop() const {
408 const State& s(getDrawingState());
409
410 if (s.crop.isEmpty() && s.buffer) {
411 return s.buffer->getBounds();
412 } else if (s.buffer) {
413 Rect crop = s.crop;
414 crop.left = std::max(crop.left, 0);
415 crop.top = std::max(crop.top, 0);
416 uint32_t bufferWidth = s.buffer->getWidth();
417 uint32_t bufferHeight = s.buffer->getHeight();
418 if (bufferHeight <= std::numeric_limits<int32_t>::max() &&
419 bufferWidth <= std::numeric_limits<int32_t>::max()) {
420 crop.right = std::min(crop.right, static_cast<int32_t>(bufferWidth));
421 crop.bottom = std::min(crop.bottom, static_cast<int32_t>(bufferHeight));
422 }
423 if (!crop.isValid()) {
424 // Crop rect is out of bounds, return whole buffer
425 return s.buffer->getBounds();
426 }
427 return crop;
428 }
429 return s.crop;
430 }
431
getDrawingScalingMode() const432 uint32_t BufferStateLayer::getDrawingScalingMode() const {
433 return NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW;
434 }
435
getDrawingSurfaceDamage() const436 Region BufferStateLayer::getDrawingSurfaceDamage() const {
437 return getDrawingState().surfaceDamageRegion;
438 }
439
getDrawingHdrMetadata() const440 const HdrMetadata& BufferStateLayer::getDrawingHdrMetadata() const {
441 return getDrawingState().hdrMetadata;
442 }
443
getDrawingApi() const444 int BufferStateLayer::getDrawingApi() const {
445 return getDrawingState().api;
446 }
447
getPixelFormat() const448 PixelFormat BufferStateLayer::getPixelFormat() const {
449 if (!mActiveBuffer) {
450 return PIXEL_FORMAT_NONE;
451 }
452 return mActiveBuffer->format;
453 }
454
getFrameNumber() const455 uint64_t BufferStateLayer::getFrameNumber() const {
456 return mFrameNumber;
457 }
458
getAutoRefresh() const459 bool BufferStateLayer::getAutoRefresh() const {
460 // TODO(marissaw): support shared buffer mode
461 return false;
462 }
463
getSidebandStreamChanged() const464 bool BufferStateLayer::getSidebandStreamChanged() const {
465 return mSidebandStreamChanged.load();
466 }
467
latchSidebandStream(bool & recomputeVisibleRegions)468 bool BufferStateLayer::latchSidebandStream(bool& recomputeVisibleRegions) {
469 if (mSidebandStreamChanged.exchange(false)) {
470 const State& s(getDrawingState());
471 // mSidebandStreamChanged was true
472 LOG_ALWAYS_FATAL_IF(!getCompositionLayer());
473 mSidebandStream = s.sidebandStream;
474 getCompositionLayer()->editState().frontEnd.sidebandStream = mSidebandStream;
475 if (mSidebandStream != nullptr) {
476 setTransactionFlags(eTransactionNeeded);
477 mFlinger->setTransactionFlags(eTraversalNeeded);
478 }
479 recomputeVisibleRegions = true;
480
481 return true;
482 }
483 return false;
484 }
485
hasFrameUpdate() const486 bool BufferStateLayer::hasFrameUpdate() const {
487 const State& c(getCurrentState());
488 return mCurrentStateModified && (c.buffer != nullptr || c.bgColorLayer != nullptr);
489 }
490
setFilteringEnabled(bool enabled)491 void BufferStateLayer::setFilteringEnabled(bool enabled) {
492 GLConsumer::computeTransformMatrix(mTransformMatrix.data(), mActiveBuffer, mCurrentCrop,
493 mCurrentTransform, enabled);
494 }
495
bindTextureImage()496 status_t BufferStateLayer::bindTextureImage() {
497 const State& s(getDrawingState());
498 auto& engine(mFlinger->getRenderEngine());
499
500 return engine.bindExternalTextureBuffer(mTextureName, s.buffer, s.acquireFence);
501 }
502
updateTexImage(bool &,nsecs_t latchTime)503 status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nsecs_t latchTime) {
504 const State& s(getDrawingState());
505
506 if (!s.buffer) {
507 if (s.bgColorLayer) {
508 for (auto& handle : mDrawingState.callbackHandles) {
509 handle->latchTime = latchTime;
510 }
511 }
512 return NO_ERROR;
513 }
514
515 const int32_t layerID = getSequence();
516
517 // Reject if the layer is invalid
518 uint32_t bufferWidth = s.buffer->width;
519 uint32_t bufferHeight = s.buffer->height;
520
521 if (s.transform & ui::Transform::ROT_90) {
522 std::swap(bufferWidth, bufferHeight);
523 }
524
525 if (s.transformToDisplayInverse) {
526 uint32_t invTransform = DisplayDevice::getPrimaryDisplayOrientationTransform();
527 if (invTransform & ui::Transform::ROT_90) {
528 std::swap(bufferWidth, bufferHeight);
529 }
530 }
531
532 if (getEffectiveScalingMode() == NATIVE_WINDOW_SCALING_MODE_FREEZE &&
533 (s.active.w != bufferWidth || s.active.h != bufferHeight)) {
534 ALOGE("[%s] rejecting buffer: "
535 "bufferWidth=%d, bufferHeight=%d, front.active.{w=%d, h=%d}",
536 mName.string(), bufferWidth, bufferHeight, s.active.w, s.active.h);
537 mFlinger->mTimeStats->removeTimeRecord(layerID, getFrameNumber());
538 return BAD_VALUE;
539 }
540
541 for (auto& handle : mDrawingState.callbackHandles) {
542 handle->latchTime = latchTime;
543 }
544
545 if (!SyncFeatures::getInstance().useNativeFenceSync()) {
546 // Bind the new buffer to the GL texture.
547 //
548 // Older devices require the "implicit" synchronization provided
549 // by glEGLImageTargetTexture2DOES, which this method calls. Newer
550 // devices will either call this in Layer::onDraw, or (if it's not
551 // a GL-composited layer) not at all.
552 status_t err = bindTextureImage();
553 if (err != NO_ERROR) {
554 mFlinger->mTimeStats->onDestroy(layerID);
555 return BAD_VALUE;
556 }
557 }
558
559 mFlinger->mTimeStats->setAcquireFence(layerID, getFrameNumber(), getCurrentFenceTime());
560 mFlinger->mTimeStats->setLatchTime(layerID, getFrameNumber(), latchTime);
561
562 mCurrentStateModified = false;
563
564 return NO_ERROR;
565 }
566
updateActiveBuffer()567 status_t BufferStateLayer::updateActiveBuffer() {
568 const State& s(getDrawingState());
569
570 if (s.buffer == nullptr) {
571 return BAD_VALUE;
572 }
573
574 if (mActiveBuffer != nullptr) {
575 // todo: get this to work with BufferStateLayerCache
576 auto& engine(mFlinger->getRenderEngine());
577 engine.unbindExternalTextureBuffer(mActiveBuffer->getId());
578 }
579 mActiveBuffer = s.buffer;
580 mActiveBufferFence = s.acquireFence;
581 auto& layerCompositionState = getCompositionLayer()->editState().frontEnd;
582 layerCompositionState.buffer = mActiveBuffer;
583 layerCompositionState.bufferSlot = 0;
584
585 return NO_ERROR;
586 }
587
updateFrameNumber(nsecs_t)588 status_t BufferStateLayer::updateFrameNumber(nsecs_t /*latchTime*/) {
589 // TODO(marissaw): support frame history events
590 mCurrentFrameNumber = mFrameNumber;
591 return NO_ERROR;
592 }
593
setHwcLayerBuffer(const sp<const DisplayDevice> & display)594 void BufferStateLayer::setHwcLayerBuffer(const sp<const DisplayDevice>& display) {
595 const auto outputLayer = findOutputLayerForDisplay(display);
596 LOG_FATAL_IF(!outputLayer || !outputLayer->getState().hwc);
597 auto& hwcInfo = *outputLayer->editState().hwc;
598 auto& hwcLayer = hwcInfo.hwcLayer;
599
600 const State& s(getDrawingState());
601
602 uint32_t hwcSlot;
603 sp<GraphicBuffer> buffer;
604 hwcInfo.hwcBufferCache.getHwcBuffer(mHwcSlotGenerator->getHwcCacheSlot(s.clientCacheId),
605 s.buffer, &hwcSlot, &buffer);
606
607 auto error = hwcLayer->setBuffer(hwcSlot, buffer, s.acquireFence);
608 if (error != HWC2::Error::None) {
609 ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(),
610 s.buffer->handle, to_string(error).c_str(), static_cast<int32_t>(error));
611 }
612
613 mFrameNumber++;
614 }
615
onFirstRef()616 void BufferStateLayer::onFirstRef() {
617 BufferLayer::onFirstRef();
618
619 if (const auto display = mFlinger->getDefaultDisplayDevice()) {
620 updateTransformHint(display);
621 }
622 }
623
bufferErased(const client_cache_t & clientCacheId)624 void BufferStateLayer::HwcSlotGenerator::bufferErased(const client_cache_t& clientCacheId) {
625 std::lock_guard lock(mMutex);
626 if (!clientCacheId.isValid()) {
627 ALOGE("invalid process, failed to erase buffer");
628 return;
629 }
630 eraseBufferLocked(clientCacheId);
631 }
632
getHwcCacheSlot(const client_cache_t & clientCacheId)633 uint32_t BufferStateLayer::HwcSlotGenerator::getHwcCacheSlot(const client_cache_t& clientCacheId) {
634 std::lock_guard<std::mutex> lock(mMutex);
635 auto itr = mCachedBuffers.find(clientCacheId);
636 if (itr == mCachedBuffers.end()) {
637 return addCachedBuffer(clientCacheId);
638 }
639 auto& [hwcCacheSlot, counter] = itr->second;
640 counter = mCounter++;
641 return hwcCacheSlot;
642 }
643
addCachedBuffer(const client_cache_t & clientCacheId)644 uint32_t BufferStateLayer::HwcSlotGenerator::addCachedBuffer(const client_cache_t& clientCacheId)
645 REQUIRES(mMutex) {
646 if (!clientCacheId.isValid()) {
647 ALOGE("invalid process, returning invalid slot");
648 return BufferQueue::INVALID_BUFFER_SLOT;
649 }
650
651 ClientCache::getInstance().registerErasedRecipient(clientCacheId, wp<ErasedRecipient>(this));
652
653 uint32_t hwcCacheSlot = getFreeHwcCacheSlot();
654 mCachedBuffers[clientCacheId] = {hwcCacheSlot, mCounter++};
655 return hwcCacheSlot;
656 }
657
getFreeHwcCacheSlot()658 uint32_t BufferStateLayer::HwcSlotGenerator::getFreeHwcCacheSlot() REQUIRES(mMutex) {
659 if (mFreeHwcCacheSlots.empty()) {
660 evictLeastRecentlyUsed();
661 }
662
663 uint32_t hwcCacheSlot = mFreeHwcCacheSlots.top();
664 mFreeHwcCacheSlots.pop();
665 return hwcCacheSlot;
666 }
667
evictLeastRecentlyUsed()668 void BufferStateLayer::HwcSlotGenerator::evictLeastRecentlyUsed() REQUIRES(mMutex) {
669 uint64_t minCounter = UINT_MAX;
670 client_cache_t minClientCacheId = {};
671 for (const auto& [clientCacheId, slotCounter] : mCachedBuffers) {
672 const auto& [hwcCacheSlot, counter] = slotCounter;
673 if (counter < minCounter) {
674 minCounter = counter;
675 minClientCacheId = clientCacheId;
676 }
677 }
678 eraseBufferLocked(minClientCacheId);
679
680 ClientCache::getInstance().unregisterErasedRecipient(minClientCacheId, this);
681 }
682
eraseBufferLocked(const client_cache_t & clientCacheId)683 void BufferStateLayer::HwcSlotGenerator::eraseBufferLocked(const client_cache_t& clientCacheId)
684 REQUIRES(mMutex) {
685 auto itr = mCachedBuffers.find(clientCacheId);
686 if (itr == mCachedBuffers.end()) {
687 return;
688 }
689 auto& [hwcCacheSlot, counter] = itr->second;
690
691 // TODO send to hwc cache and resources
692
693 mFreeHwcCacheSlots.push(hwcCacheSlot);
694 mCachedBuffers.erase(clientCacheId);
695 }
696 } // namespace android
697