| Dan Stoza | 289ade1 | 2014-02-28 11:17:17 -0800 | [diff] [blame] | 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 |  | 
|  | 28 | namespace android { | 
|  | 29 |  | 
|  | 30 | class Fence; | 
|  | 31 |  | 
| Pablo Ceballos | ccdfd60 | 2015-10-07 15:05:45 -0700 | [diff] [blame] | 32 | // BufferState tracks the states in which a buffer slot can be. | 
|  | 33 | struct 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 | // | 
| Pablo Ceballos | 2dcb363 | 2016-03-17 15:50:23 -0700 | [diff] [blame] | 82 | // SHARED indicates that this buffer is being used in shared buffer | 
| Pablo Ceballos | ccdfd60 | 2015-10-07 15:05:45 -0700 | [diff] [blame] | 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 |  | 
| Dan Stoza | 289ade1 | 2014-02-28 11:17:17 -0800 | [diff] [blame] | 174 | struct BufferSlot { | 
|  | 175 |  | 
|  | 176 | BufferSlot() | 
| Pablo Ceballos | 23b4abe | 2016-01-08 12:15:22 -0800 | [diff] [blame] | 177 | : mGraphicBuffer(nullptr), | 
|  | 178 | mEglDisplay(EGL_NO_DISPLAY), | 
| Pablo Ceballos | ccdfd60 | 2015-10-07 15:05:45 -0700 | [diff] [blame] | 179 | mBufferState(), | 
| Dan Stoza | 289ade1 | 2014-02-28 11:17:17 -0800 | [diff] [blame] | 180 | mRequestBufferCalled(false), | 
|  | 181 | mFrameNumber(0), | 
|  | 182 | mEglFence(EGL_NO_SYNC_KHR), | 
| Pablo Ceballos | 23b4abe | 2016-01-08 12:15:22 -0800 | [diff] [blame] | 183 | mFence(Fence::NO_FENCE), | 
| Dan Stoza | 289ade1 | 2014-02-28 11:17:17 -0800 | [diff] [blame] | 184 | mAcquireCalled(false), | 
| Pablo Ceballos | 23b4abe | 2016-01-08 12:15:22 -0800 | [diff] [blame] | 185 | mNeedsReallocation(false) { | 
| Dan Stoza | 289ade1 | 2014-02-28 11:17:17 -0800 | [diff] [blame] | 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 |  | 
| Dan Stoza | 289ade1 | 2014-02-28 11:17:17 -0800 | [diff] [blame] | 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 |  | 
| Pablo Ceballos | 23b4abe | 2016-01-08 12:15:22 -0800 | [diff] [blame] | 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; | 
| Dan Stoza | 289ade1 | 2014-02-28 11:17:17 -0800 | [diff] [blame] | 233 | }; | 
|  | 234 |  | 
|  | 235 | } // namespace android | 
|  | 236 |  | 
|  | 237 | #endif |