summaryrefslogtreecommitdiff
path: root/services/surfaceflinger/BufferStateLayer.h
blob: e5674785afb45de6372270ab3245fde57f6bf2c4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include "BufferLayer.h"
#include "Layer.h"

#include <renderengine/Image.h>
#include <renderengine/RenderEngine.h>
#include <system/window.h>
#include <utils/String8.h>

#include <stack>

namespace android {

class SlotGenerationTest;

class BufferStateLayer : public BufferLayer {
public:
    explicit BufferStateLayer(const LayerCreationArgs&);

    ~BufferStateLayer() override;

    // Implements Layer.
    const char* getType() const override { return "BufferStateLayer"; }

    void onLayerDisplayed(const sp<Fence>& releaseFence) override;
    void releasePendingBuffer(nsecs_t dequeueReadyTime) override;

    void finalizeFrameEventHistory(const std::shared_ptr<FenceTime>& glDoneFence,
                                   const CompositorTiming& compositorTiming) override;

    bool isBufferDue(nsecs_t /*expectedPresentTime*/) const override { return true; }

    Region getActiveTransparentRegion(const Layer::State& s) const override {
        return s.transparentRegionHint;
    }
    Rect getCrop(const Layer::State& s) const;

    bool setTransform(uint32_t transform) override;
    bool setTransformToDisplayInverse(bool transformToDisplayInverse) override;
    bool setCrop(const Rect& crop) override;
    bool setBuffer(const std::shared_ptr<renderengine::ExternalTexture>& buffer,
                   const sp<Fence>& acquireFence, nsecs_t postTime, nsecs_t desiredPresentTime,
                   bool isAutoTimestamp, const client_cache_t& clientCacheId, uint64_t frameNumber,
                   std::optional<nsecs_t> dequeueTime, const FrameTimelineInfo& info,
                   const sp<ITransactionCompletedListener>& transactionListener) override;
    bool setAcquireFence(const sp<Fence>& fence) override;
    bool setDataspace(ui::Dataspace dataspace) override;
    bool setHdrMetadata(const HdrMetadata& hdrMetadata) override;
    bool setSurfaceDamageRegion(const Region& surfaceDamage) override;
    bool setApi(int32_t api) override;
    bool setSidebandStream(const sp<NativeHandle>& sidebandStream) override;
    bool setTransactionCompletedListeners(const std::vector<sp<CallbackHandle>>& handles) override;
    bool addFrameEvent(const sp<Fence>& acquireFence, nsecs_t postedTime,
                       nsecs_t requestedPresentTime) override;
    bool setPosition(float /*x*/, float /*y*/) override;
    bool setMatrix(const layer_state_t::matrix22_t& /*matrix*/,
                   bool /*allowNonRectPreservingTransforms*/);

    // Override to ignore legacy layer state properties that are not used by BufferStateLayer
    bool setSize(uint32_t /*w*/, uint32_t /*h*/) override { return false; }
    bool setTransparentRegionHint(const Region& transparent) override;

    Rect getBufferSize(const State& s) const override;
    FloatRect computeSourceBounds(const FloatRect& parentBounds) const override;
    void setAutoRefresh(bool autoRefresh) override;

    bool setBufferCrop(const Rect& bufferCrop) override;
    bool setDestinationFrame(const Rect& destinationFrame) override;
    bool updateGeometry() override;

    // -----------------------------------------------------------------------

    // -----------------------------------------------------------------------
    // Interface implementation for BufferLayer
    // -----------------------------------------------------------------------
    bool fenceHasSignaled() const override;
    bool framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const override;
    bool onPreComposition(nsecs_t refreshStartTime) override;
    uint32_t getEffectiveScalingMode() const override;

    // See mPendingBufferTransactions
    void decrementPendingBufferCount();
    void bufferMayChange(const sp<GraphicBuffer>& newBuffer) override;
    std::atomic<int32_t>* getPendingBufferCounter() override { return &mPendingBufferTransactions; }
    std::string getPendingBufferCounterName() override { return mBlastTransactionName; }

    bool shouldPresentNow(nsecs_t /*expectedPresentTime*/) const override { return true; }

protected:
    void gatherBufferInfo() override;
    uint64_t getHeadFrameNumber(nsecs_t expectedPresentTime) const;
    void onSurfaceFrameCreated(const std::shared_ptr<frametimeline::SurfaceFrame>& surfaceFrame);
    ui::Transform getInputTransform() const override;
    Rect getInputBounds() const override;

private:
    friend class SlotGenerationTest;
    friend class TransactionFrameTracerTest;
    friend class TransactionSurfaceFrameTest;

    inline void tracePendingBufferCount(int32_t pendingBuffers);

    bool updateFrameEventHistory(const sp<Fence>& acquireFence, nsecs_t postedTime,
                                 nsecs_t requestedPresentTime);

    status_t addReleaseFence(const sp<CallbackHandle>& ch, const sp<Fence>& releaseFence);

    uint64_t getFrameNumber(nsecs_t expectedPresentTime) const override;

    bool latchSidebandStream(bool& recomputeVisibleRegions) override;

    bool hasFrameUpdate() const override;

    status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime,
                            nsecs_t expectedPresentTime) override;

    status_t updateActiveBuffer() override;
    status_t updateFrameNumber(nsecs_t latchTime) override;

    sp<Layer> createClone() override;

    // Crop that applies to the buffer
    Rect computeBufferCrop(const State& s);

    bool willPresentCurrentTransaction() const;

    bool bufferNeedsFiltering() const override;

    sp<Fence> mPreviousReleaseFence;
    ReleaseCallbackId mPreviousReleaseCallbackId = ReleaseCallbackId::INVALID_ID;
    uint64_t mPreviousReleasedFrameNumber = 0;

    bool mReleasePreviousBuffer = false;

    // Stores the last set acquire fence signal time used to populate the callback handle's acquire
    // time.
    nsecs_t mCallbackHandleAcquireTime = -1;

    std::deque<std::shared_ptr<android::frametimeline::SurfaceFrame>> mPendingJankClassifications;
    // An upper bound on the number of SurfaceFrames in the pending classifications deque.
    static constexpr int kPendingClassificationMaxSurfaceFrames = 25;

    const std::string mBlastTransactionName{"BufferTX - " + mName};
    // This integer is incremented everytime a buffer arrives at the server for this layer,
    // and decremented when a buffer is dropped or latched. When changed the integer is exported
    // to systrace with ATRACE_INT and mBlastTransactionName. This way when debugging perf it is
    // possible to see when a buffer arrived at the server, and in which frame it latched.
    //
    // You can understand the trace this way:
    //     - If the integer increases, a buffer arrived at the server.
    //     - If the integer decreases in latchBuffer, that buffer was latched
    //     - If the integer decreases in setBuffer or doTransaction, a buffer was dropped
    std::atomic<int32_t> mPendingBufferTransactions{0};

    // Contains requested position and matrix updates. This will be applied if the client does
    // not specify a destination frame.
    ui::Transform mRequestedTransform;

    // TODO(marissaw): support sticky transform for LEGACY camera mode

    class HwcSlotGenerator : public ClientCache::ErasedRecipient {
    public:
        HwcSlotGenerator() {
            for (uint32_t i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
                mFreeHwcCacheSlots.push(i);
            }
        }

        void bufferErased(const client_cache_t& clientCacheId);

        uint32_t getHwcCacheSlot(const client_cache_t& clientCacheId);

    private:
        friend class SlotGenerationTest;
        uint32_t addCachedBuffer(const client_cache_t& clientCacheId) REQUIRES(mMutex);
        uint32_t getFreeHwcCacheSlot() REQUIRES(mMutex);
        void evictLeastRecentlyUsed() REQUIRES(mMutex);
        void eraseBufferLocked(const client_cache_t& clientCacheId) REQUIRES(mMutex);

        struct CachedBufferHash {
            std::size_t operator()(const client_cache_t& clientCacheId) const {
                return std::hash<uint64_t>{}(clientCacheId.id);
            }
        };

        std::mutex mMutex;

        std::unordered_map<client_cache_t,
                           std::pair<uint32_t /*HwcCacheSlot*/, uint32_t /*counter*/>,
                           CachedBufferHash>
                mCachedBuffers GUARDED_BY(mMutex);
        std::stack<uint32_t /*HwcCacheSlot*/> mFreeHwcCacheSlots GUARDED_BY(mMutex);

        // The cache increments this counter value when a slot is updated or used.
        // Used to track the least recently-used buffer
        uint64_t mCounter = 0;
    };

    sp<HwcSlotGenerator> mHwcSlotGenerator;
};

} // namespace android