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 |