1/*
2 * Copyright 2014 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#ifndef ANDROID_GUI_BUFFERSLOT_H
18#define ANDROID_GUI_BUFFERSLOT_H
19
20#include <ui/Fence.h>
21#include <ui/GraphicBuffer.h>
22
23#include <EGL/egl.h>
24#include <EGL/eglext.h>
25
26#include <utils/StrongPointer.h>
27
28namespace android {
29
30class Fence;
31
32// BufferState tracks the states in which a buffer slot can be.
33struct BufferState {
34
35    // All slots are initially FREE (not dequeued, queued, acquired, or shared).
36    BufferState()
37    : mDequeueCount(0),
38      mQueueCount(0),
39      mAcquireCount(0),
40      mShared(false) {
41    }
42
43    uint32_t mDequeueCount;
44    uint32_t mQueueCount;
45    uint32_t mAcquireCount;
46    bool mShared;
47
48    // A buffer can be in one of five states, represented as below:
49    //
50    //         | mShared | mDequeueCount | mQueueCount | mAcquireCount |
51    // --------|---------|---------------|-------------|---------------|
52    // FREE    |  false  |       0       |      0      |       0       |
53    // DEQUEUED|  false  |       1       |      0      |       0       |
54    // QUEUED  |  false  |       0       |      1      |       0       |
55    // ACQUIRED|  false  |       0       |      0      |       1       |
56    // SHARED  |  true   |      any      |     any     |      any      |
57    //
58    // FREE indicates that the buffer is available to be dequeued by the
59    // producer. The slot is "owned" by BufferQueue. It transitions to DEQUEUED
60    // when dequeueBuffer is called.
61    //
62    // DEQUEUED indicates that the buffer has been dequeued by the producer, but
63    // has not yet been queued or canceled. The producer may modify the
64    // buffer's contents as soon as the associated release fence is signaled.
65    // The slot is "owned" by the producer. It can transition to QUEUED (via
66    // queueBuffer or attachBuffer) or back to FREE (via cancelBuffer or
67    // detachBuffer).
68    //
69    // QUEUED indicates that the buffer has been filled by the producer and
70    // queued for use by the consumer. The buffer contents may continue to be
71    // modified for a finite time, so the contents must not be accessed until
72    // the associated fence is signaled. The slot is "owned" by BufferQueue. It
73    // can transition to ACQUIRED (via acquireBuffer) or to FREE (if another
74    // buffer is queued in asynchronous mode).
75    //
76    // ACQUIRED indicates that the buffer has been acquired by the consumer. As
77    // with QUEUED, the contents must not be accessed by the consumer until the
78    // acquire fence is signaled. The slot is "owned" by the consumer. It
79    // transitions to FREE when releaseBuffer (or detachBuffer) is called. A
80    // detached buffer can also enter the ACQUIRED state via attachBuffer.
81    //
82    // SHARED indicates that this buffer is being used in shared buffer
83    // mode. It can be in any combination of the other states at the same time,
84    // except for FREE (since that excludes being in any other state). It can
85    // also be dequeued, queued, or acquired multiple times.
86
87    inline bool isFree() const {
88        return !isAcquired() && !isDequeued() && !isQueued();
89    }
90
91    inline bool isDequeued() const {
92        return mDequeueCount > 0;
93    }
94
95    inline bool isQueued() const {
96        return mQueueCount > 0;
97    }
98
99    inline bool isAcquired() const {
100        return mAcquireCount > 0;
101    }
102
103    inline bool isShared() const {
104        return mShared;
105    }
106
107    inline void reset() {
108        *this = BufferState();
109    }
110
111    const char* string() const;
112
113    inline void dequeue() {
114        mDequeueCount++;
115    }
116
117    inline void detachProducer() {
118        if (mDequeueCount > 0) {
119            mDequeueCount--;
120        }
121    }
122
123    inline void attachProducer() {
124        mDequeueCount++;
125    }
126
127    inline void queue() {
128        if (mDequeueCount > 0) {
129            mDequeueCount--;
130        }
131        mQueueCount++;
132    }
133
134    inline void cancel() {
135        if (mDequeueCount > 0) {
136            mDequeueCount--;
137        }
138    }
139
140    inline void freeQueued() {
141        if (mQueueCount > 0) {
142            mQueueCount--;
143        }
144    }
145
146    inline void acquire() {
147        if (mQueueCount > 0) {
148            mQueueCount--;
149        }
150        mAcquireCount++;
151    }
152
153    inline void acquireNotInQueue() {
154        mAcquireCount++;
155    }
156
157    inline void release() {
158        if (mAcquireCount > 0) {
159            mAcquireCount--;
160        }
161    }
162
163    inline void detachConsumer() {
164        if (mAcquireCount > 0) {
165            mAcquireCount--;
166        }
167    }
168
169    inline void attachConsumer() {
170        mAcquireCount++;
171    }
172};
173
174struct BufferSlot {
175
176    BufferSlot()
177    : mGraphicBuffer(nullptr),
178      mEglDisplay(EGL_NO_DISPLAY),
179      mBufferState(),
180      mRequestBufferCalled(false),
181      mFrameNumber(0),
182      mEglFence(EGL_NO_SYNC_KHR),
183      mFence(Fence::NO_FENCE),
184      mAcquireCalled(false),
185      mNeedsReallocation(false) {
186    }
187
188    // mGraphicBuffer points to the buffer allocated for this slot or is NULL
189    // if no buffer has been allocated.
190    sp<GraphicBuffer> mGraphicBuffer;
191
192    // mEglDisplay is the EGLDisplay used to create EGLSyncKHR objects.
193    EGLDisplay mEglDisplay;
194
195    // mBufferState is the current state of this buffer slot.
196    BufferState mBufferState;
197
198    // mRequestBufferCalled is used for validating that the producer did
199    // call requestBuffer() when told to do so. Technically this is not
200    // needed but useful for debugging and catching producer bugs.
201    bool mRequestBufferCalled;
202
203    // mFrameNumber is the number of the queued frame for this slot.  This
204    // is used to dequeue buffers in LRU order (useful because buffers
205    // may be released before their release fence is signaled).
206    uint64_t mFrameNumber;
207
208    // mEglFence is the EGL sync object that must signal before the buffer
209    // associated with this buffer slot may be dequeued. It is initialized
210    // to EGL_NO_SYNC_KHR when the buffer is created and may be set to a
211    // new sync object in releaseBuffer.  (This is deprecated in favor of
212    // mFence, below.)
213    EGLSyncKHR mEglFence;
214
215    // mFence is a fence which will signal when work initiated by the
216    // previous owner of the buffer is finished. When the buffer is FREE,
217    // the fence indicates when the consumer has finished reading
218    // from the buffer, or when the producer has finished writing if it
219    // called cancelBuffer after queueing some writes. When the buffer is
220    // QUEUED, it indicates when the producer has finished filling the
221    // buffer. When the buffer is DEQUEUED or ACQUIRED, the fence has been
222    // passed to the consumer or producer along with ownership of the
223    // buffer, and mFence is set to NO_FENCE.
224    sp<Fence> mFence;
225
226    // Indicates whether this buffer has been seen by a consumer yet
227    bool mAcquireCalled;
228
229    // Indicates whether the buffer was re-allocated without notifying the
230    // producer. If so, it needs to set the BUFFER_NEEDS_REALLOCATION flag when
231    // dequeued to prevent the producer from using a stale cached buffer.
232    bool mNeedsReallocation;
233};
234
235} // namespace android
236
237#endif
238