blob: 7dac3ef0f44a80fe312c7d966c122aa70b96d7f6 [file] [log] [blame]
Stan Iliev564ca3e2018-09-04 22:00:00 +00001/*
2 * Copyright (C) 2018 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#pragma once
18
19#include <EGL/egl.h>
20#include <EGL/eglext.h>
21
22#include <gui/BufferQueueDefs.h>
23
24#include <ui/FenceTime.h>
25#include <ui/GraphicBuffer.h>
26#include <utils/Mutex.h>
27
28namespace android {
29
30class SurfaceTexture;
31
32/*
33 * EGLConsumer implements the parts of SurfaceTexture that deal with
34 * textures attached to an GL context.
35 */
36class EGLConsumer {
37public:
38 EGLConsumer();
39
40 /**
41 * updateTexImage acquires the most recently queued buffer, and sets the
42 * image contents of the target texture to it.
43 *
44 * This call may only be made while the OpenGL ES context to which the
45 * target texture belongs is bound to the calling thread.
46 *
47 * This calls doGLFenceWait to ensure proper synchronization.
48 */
49 status_t updateTexImage(SurfaceTexture& st);
50
51 /*
52 * releaseTexImage releases the texture acquired in updateTexImage().
53 * This is intended to be used in single buffer mode.
54 *
55 * This call may only be made while the OpenGL ES context to which the
56 * target texture belongs is bound to the calling thread.
57 */
58 status_t releaseTexImage(SurfaceTexture& st);
59
60 /**
61 * detachFromContext detaches the EGLConsumer from the calling thread's
62 * current OpenGL ES context. This context must be the same as the context
63 * that was current for previous calls to updateTexImage.
64 *
65 * Detaching a EGLConsumer from an OpenGL ES context will result in the
66 * deletion of the OpenGL ES texture object into which the images were being
67 * streamed. After a EGLConsumer has been detached from the OpenGL ES
68 * context calls to updateTexImage will fail returning INVALID_OPERATION
69 * until the EGLConsumer is attached to a new OpenGL ES context using the
70 * attachToContext method.
71 */
72 status_t detachFromContext(SurfaceTexture& st);
73
74 /**
75 * attachToContext attaches a EGLConsumer that is currently in the
76 * 'detached' state to the current OpenGL ES context. A EGLConsumer is
77 * in the 'detached' state iff detachFromContext has successfully been
78 * called and no calls to attachToContext have succeeded since the last
79 * detachFromContext call. Calls to attachToContext made on a
80 * EGLConsumer that is not in the 'detached' state will result in an
81 * INVALID_OPERATION error.
82 *
83 * The tex argument specifies the OpenGL ES texture object name in the
84 * new context into which the image contents will be streamed. A successful
85 * call to attachToContext will result in this texture object being bound to
86 * the texture target and populated with the image contents that were
87 * current at the time of the last call to detachFromContext.
88 */
89 status_t attachToContext(uint32_t tex, SurfaceTexture& st);
90
91 /**
92 * onAcquireBufferLocked amends the ConsumerBase method to update the
93 * mEglSlots array in addition to the ConsumerBase behavior.
94 */
95 void onAcquireBufferLocked(BufferItem* item, SurfaceTexture& st);
96
97 /**
98 * onReleaseBufferLocked amends the ConsumerBase method to update the
99 * mEglSlots array in addition to the ConsumerBase.
100 */
101 void onReleaseBufferLocked(int slot);
102
103 /**
104 * onFreeBufferLocked frees up the given buffer slot. If the slot has been
105 * initialized this will release the reference to the GraphicBuffer in that
106 * slot and destroy the EGLImage in that slot. Otherwise it has no effect.
107 */
108 void onFreeBufferLocked(int slotIndex);
109
110 /**
111 * onAbandonLocked amends the ConsumerBase method to clear
112 * mCurrentTextureImage in addition to the ConsumerBase behavior.
113 */
114 void onAbandonLocked();
115
116protected:
117 struct PendingRelease {
118 PendingRelease()
119 : isPending(false)
120 , currentTexture(-1)
121 , graphicBuffer()
122 , display(nullptr)
123 , fence(nullptr) {}
124
125 bool isPending;
126 int currentTexture;
127 sp<GraphicBuffer> graphicBuffer;
128 EGLDisplay display;
129 EGLSyncKHR fence;
130 };
131
132 /**
133 * This releases the buffer in the slot referenced by mCurrentTexture,
134 * then updates state to refer to the BufferItem, which must be a
135 * newly-acquired buffer. If pendingRelease is not null, the parameters
136 * which would have been passed to releaseBufferLocked upon the successful
137 * completion of the method will instead be returned to the caller, so that
138 * it may call releaseBufferLocked itself later.
139 */
140 status_t updateAndReleaseLocked(const BufferItem& item, PendingRelease* pendingRelease,
141 SurfaceTexture& st);
142
143 /**
144 * Binds mTexName and the current buffer to mTexTarget. Uses
145 * mCurrentTexture if it's set, mCurrentTextureImage if not. If the
146 * bind succeeds, this calls doGLFenceWait.
147 */
148 status_t bindTextureImageLocked(SurfaceTexture& st);
149
150 /**
151 * Gets the current EGLDisplay and EGLContext values, and compares them
152 * to mEglDisplay and mEglContext. If the fields have been previously
153 * set, the values must match; if not, the fields are set to the current
154 * values.
155 * The contextCheck argument is used to ensure that a GL context is
156 * properly set; when set to false, the check is not performed.
157 */
158 status_t checkAndUpdateEglStateLocked(SurfaceTexture& st, bool contextCheck = false);
159
160 /**
161 * EglImage is a utility class for tracking and creating EGLImageKHRs. There
162 * is primarily just one image per slot, but there is also special cases:
163 * - For releaseTexImage, we use a debug image (mReleasedTexImage)
164 * - After freeBuffer, we must still keep the current image/buffer
165 * Reference counting EGLImages lets us handle all these cases easily while
166 * also only creating new EGLImages from buffers when required.
167 */
168 class EglImage : public LightRefBase<EglImage> {
169 public:
170 EglImage(sp<GraphicBuffer> graphicBuffer);
171
172 /**
173 * createIfNeeded creates an EGLImage if required (we haven't created
174 * one yet, or the EGLDisplay or crop-rect has changed).
175 */
176 status_t createIfNeeded(EGLDisplay display, bool forceCreate = false);
177
178 /**
179 * This calls glEGLImageTargetTexture2DOES to bind the image to the
180 * texture in the specified texture target.
181 */
182 void bindToTextureTarget(uint32_t texTarget);
183
184 const sp<GraphicBuffer>& graphicBuffer() { return mGraphicBuffer; }
185 const native_handle* graphicBufferHandle() {
186 return mGraphicBuffer == nullptr ? nullptr : mGraphicBuffer->handle;
187 }
188
189 private:
190 // Only allow instantiation using ref counting.
191 friend class LightRefBase<EglImage>;
192 virtual ~EglImage();
193
194 // createImage creates a new EGLImage from a GraphicBuffer.
195 EGLImageKHR createImage(EGLDisplay dpy, const sp<GraphicBuffer>& graphicBuffer);
196
197 // Disallow copying
198 EglImage(const EglImage& rhs);
199 void operator=(const EglImage& rhs);
200
201 // mGraphicBuffer is the buffer that was used to create this image.
202 sp<GraphicBuffer> mGraphicBuffer;
203
204 // mEglImage is the EGLImage created from mGraphicBuffer.
205 EGLImageKHR mEglImage;
206
207 // mEGLDisplay is the EGLDisplay that was used to create mEglImage.
208 EGLDisplay mEglDisplay;
209
210 // mCropRect is the crop rectangle passed to EGL when mEglImage
211 // was created.
212 Rect mCropRect;
213 };
214
215 /**
216 * doGLFenceWaitLocked inserts a wait command into the OpenGL ES command
217 * stream to ensure that it is safe for future OpenGL ES commands to
218 * access the current texture buffer.
219 */
220 status_t doGLFenceWaitLocked(SurfaceTexture& st) const;
221
222 /**
223 * syncForReleaseLocked performs the synchronization needed to release the
224 * current slot from an OpenGL ES context. If needed it will set the
225 * current slot's fence to guard against a producer accessing the buffer
226 * before the outstanding accesses have completed.
227 */
228 status_t syncForReleaseLocked(EGLDisplay dpy, SurfaceTexture& st);
229
230 /**
231 * returns a graphic buffer used when the texture image has been released
232 */
233 static sp<GraphicBuffer> getDebugTexImageBuffer();
234
235 /**
236 * The default consumer usage flags that EGLConsumer always sets on its
237 * BufferQueue instance; these will be OR:d with any additional flags passed
238 * from the EGLConsumer user. In particular, EGLConsumer will always
239 * consume buffers as hardware textures.
240 */
241 static const uint64_t DEFAULT_USAGE_FLAGS = GraphicBuffer::USAGE_HW_TEXTURE;
242
243 /**
244 * mCurrentTextureImage is the EglImage/buffer of the current texture. It's
245 * possible that this buffer is not associated with any buffer slot, so we
246 * must track it separately in order to support the getCurrentBuffer method.
247 */
248 sp<EglImage> mCurrentTextureImage;
249
250 /**
251 * EGLSlot contains the information and object references that
252 * EGLConsumer maintains about a BufferQueue buffer slot.
253 */
254 struct EglSlot {
255 EglSlot() : mEglFence(EGL_NO_SYNC_KHR) {}
256
257 /**
258 * mEglImage is the EGLImage created from mGraphicBuffer.
259 */
260 sp<EglImage> mEglImage;
261
262 /**
263 * mFence is the EGL sync object that must signal before the buffer
264 * associated with this buffer slot may be dequeued. It is initialized
265 * to EGL_NO_SYNC_KHR when the buffer is created and (optionally, based
266 * on a compile-time option) set to a new sync object in updateTexImage.
267 */
268 EGLSyncKHR mEglFence;
269 };
270
271 /**
272 * mEglDisplay is the EGLDisplay with which this EGLConsumer is currently
273 * associated. It is intialized to EGL_NO_DISPLAY and gets set to the
274 * current display when updateTexImage is called for the first time and when
275 * attachToContext is called.
276 */
277 EGLDisplay mEglDisplay;
278
279 /**
280 * mEglContext is the OpenGL ES context with which this EGLConsumer is
281 * currently associated. It is initialized to EGL_NO_CONTEXT and gets set
282 * to the current GL context when updateTexImage is called for the first
283 * time and when attachToContext is called.
284 */
285 EGLContext mEglContext;
286
287 /**
288 * mEGLSlots stores the buffers that have been allocated by the BufferQueue
289 * for each buffer slot. It is initialized to null pointers, and gets
290 * filled in with the result of BufferQueue::acquire when the
291 * client dequeues a buffer from a
292 * slot that has not yet been used. The buffer allocated to a slot will also
293 * be replaced if the requested buffer usage or geometry differs from that
294 * of the buffer allocated to a slot.
295 */
296 EglSlot mEglSlots[BufferQueueDefs::NUM_BUFFER_SLOTS];
297
298 /**
299 * protects static initialization
300 */
301 static Mutex sStaticInitLock;
302
303 /**
304 * mReleasedTexImageBuffer is a dummy buffer used when in single buffer
305 * mode and releaseTexImage() has been called
306 */
307 static sp<GraphicBuffer> sReleasedTexImageBuffer;
308 sp<EglImage> mReleasedTexImage;
309};
310
Chris Blume7b8a8082018-11-30 15:51:58 -0800311} // namespace android