7b8a808b7d
When closing a namespace a } is sufficient. It doesn't need to be }; like closing a class or enum. Within frameworks/base/libs/hwui there is a mix between } and }; when closing a namespace. There are even mixes between a .h and the corresponding .cpp files. In a separate CL I was asked to not close with };. That was a good comment. I adopted the style from nearby code. This CL cleans up the nearby code. Test: I made sure the code still built as expected. Change-Id: Ieb314a4f48d6e33752463f3be4361fdc9be97482
312 lines
12 KiB
C++
312 lines
12 KiB
C++
/*
|
|
* 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 <EGL/egl.h>
|
|
#include <EGL/eglext.h>
|
|
|
|
#include <gui/BufferQueueDefs.h>
|
|
|
|
#include <ui/FenceTime.h>
|
|
#include <ui/GraphicBuffer.h>
|
|
#include <utils/Mutex.h>
|
|
|
|
namespace android {
|
|
|
|
class SurfaceTexture;
|
|
|
|
/*
|
|
* EGLConsumer implements the parts of SurfaceTexture that deal with
|
|
* textures attached to an GL context.
|
|
*/
|
|
class EGLConsumer {
|
|
public:
|
|
EGLConsumer();
|
|
|
|
/**
|
|
* updateTexImage acquires the most recently queued buffer, and sets the
|
|
* image contents of the target texture to it.
|
|
*
|
|
* This call may only be made while the OpenGL ES context to which the
|
|
* target texture belongs is bound to the calling thread.
|
|
*
|
|
* This calls doGLFenceWait to ensure proper synchronization.
|
|
*/
|
|
status_t updateTexImage(SurfaceTexture& st);
|
|
|
|
/*
|
|
* releaseTexImage releases the texture acquired in updateTexImage().
|
|
* This is intended to be used in single buffer mode.
|
|
*
|
|
* This call may only be made while the OpenGL ES context to which the
|
|
* target texture belongs is bound to the calling thread.
|
|
*/
|
|
status_t releaseTexImage(SurfaceTexture& st);
|
|
|
|
/**
|
|
* detachFromContext detaches the EGLConsumer from the calling thread's
|
|
* current OpenGL ES context. This context must be the same as the context
|
|
* that was current for previous calls to updateTexImage.
|
|
*
|
|
* Detaching a EGLConsumer from an OpenGL ES context will result in the
|
|
* deletion of the OpenGL ES texture object into which the images were being
|
|
* streamed. After a EGLConsumer has been detached from the OpenGL ES
|
|
* context calls to updateTexImage will fail returning INVALID_OPERATION
|
|
* until the EGLConsumer is attached to a new OpenGL ES context using the
|
|
* attachToContext method.
|
|
*/
|
|
status_t detachFromContext(SurfaceTexture& st);
|
|
|
|
/**
|
|
* attachToContext attaches a EGLConsumer that is currently in the
|
|
* 'detached' state to the current OpenGL ES context. A EGLConsumer is
|
|
* in the 'detached' state iff detachFromContext has successfully been
|
|
* called and no calls to attachToContext have succeeded since the last
|
|
* detachFromContext call. Calls to attachToContext made on a
|
|
* EGLConsumer that is not in the 'detached' state will result in an
|
|
* INVALID_OPERATION error.
|
|
*
|
|
* The tex argument specifies the OpenGL ES texture object name in the
|
|
* new context into which the image contents will be streamed. A successful
|
|
* call to attachToContext will result in this texture object being bound to
|
|
* the texture target and populated with the image contents that were
|
|
* current at the time of the last call to detachFromContext.
|
|
*/
|
|
status_t attachToContext(uint32_t tex, SurfaceTexture& st);
|
|
|
|
/**
|
|
* onAcquireBufferLocked amends the ConsumerBase method to update the
|
|
* mEglSlots array in addition to the ConsumerBase behavior.
|
|
*/
|
|
void onAcquireBufferLocked(BufferItem* item, SurfaceTexture& st);
|
|
|
|
/**
|
|
* onReleaseBufferLocked amends the ConsumerBase method to update the
|
|
* mEglSlots array in addition to the ConsumerBase.
|
|
*/
|
|
void onReleaseBufferLocked(int slot);
|
|
|
|
/**
|
|
* onFreeBufferLocked frees up the given buffer slot. If the slot has been
|
|
* initialized this will release the reference to the GraphicBuffer in that
|
|
* slot and destroy the EGLImage in that slot. Otherwise it has no effect.
|
|
*/
|
|
void onFreeBufferLocked(int slotIndex);
|
|
|
|
/**
|
|
* onAbandonLocked amends the ConsumerBase method to clear
|
|
* mCurrentTextureImage in addition to the ConsumerBase behavior.
|
|
*/
|
|
void onAbandonLocked();
|
|
|
|
protected:
|
|
struct PendingRelease {
|
|
PendingRelease()
|
|
: isPending(false)
|
|
, currentTexture(-1)
|
|
, graphicBuffer()
|
|
, display(nullptr)
|
|
, fence(nullptr) {}
|
|
|
|
bool isPending;
|
|
int currentTexture;
|
|
sp<GraphicBuffer> graphicBuffer;
|
|
EGLDisplay display;
|
|
EGLSyncKHR fence;
|
|
};
|
|
|
|
/**
|
|
* This releases the buffer in the slot referenced by mCurrentTexture,
|
|
* then updates state to refer to the BufferItem, which must be a
|
|
* newly-acquired buffer. If pendingRelease is not null, the parameters
|
|
* which would have been passed to releaseBufferLocked upon the successful
|
|
* completion of the method will instead be returned to the caller, so that
|
|
* it may call releaseBufferLocked itself later.
|
|
*/
|
|
status_t updateAndReleaseLocked(const BufferItem& item, PendingRelease* pendingRelease,
|
|
SurfaceTexture& st);
|
|
|
|
/**
|
|
* Binds mTexName and the current buffer to mTexTarget. Uses
|
|
* mCurrentTexture if it's set, mCurrentTextureImage if not. If the
|
|
* bind succeeds, this calls doGLFenceWait.
|
|
*/
|
|
status_t bindTextureImageLocked(SurfaceTexture& st);
|
|
|
|
/**
|
|
* Gets the current EGLDisplay and EGLContext values, and compares them
|
|
* to mEglDisplay and mEglContext. If the fields have been previously
|
|
* set, the values must match; if not, the fields are set to the current
|
|
* values.
|
|
* The contextCheck argument is used to ensure that a GL context is
|
|
* properly set; when set to false, the check is not performed.
|
|
*/
|
|
status_t checkAndUpdateEglStateLocked(SurfaceTexture& st, bool contextCheck = false);
|
|
|
|
/**
|
|
* EglImage is a utility class for tracking and creating EGLImageKHRs. There
|
|
* is primarily just one image per slot, but there is also special cases:
|
|
* - For releaseTexImage, we use a debug image (mReleasedTexImage)
|
|
* - After freeBuffer, we must still keep the current image/buffer
|
|
* Reference counting EGLImages lets us handle all these cases easily while
|
|
* also only creating new EGLImages from buffers when required.
|
|
*/
|
|
class EglImage : public LightRefBase<EglImage> {
|
|
public:
|
|
EglImage(sp<GraphicBuffer> graphicBuffer);
|
|
|
|
/**
|
|
* createIfNeeded creates an EGLImage if required (we haven't created
|
|
* one yet, or the EGLDisplay or crop-rect has changed).
|
|
*/
|
|
status_t createIfNeeded(EGLDisplay display, bool forceCreate = false);
|
|
|
|
/**
|
|
* This calls glEGLImageTargetTexture2DOES to bind the image to the
|
|
* texture in the specified texture target.
|
|
*/
|
|
void bindToTextureTarget(uint32_t texTarget);
|
|
|
|
const sp<GraphicBuffer>& graphicBuffer() { return mGraphicBuffer; }
|
|
const native_handle* graphicBufferHandle() {
|
|
return mGraphicBuffer == nullptr ? nullptr : mGraphicBuffer->handle;
|
|
}
|
|
|
|
private:
|
|
// Only allow instantiation using ref counting.
|
|
friend class LightRefBase<EglImage>;
|
|
virtual ~EglImage();
|
|
|
|
// createImage creates a new EGLImage from a GraphicBuffer.
|
|
EGLImageKHR createImage(EGLDisplay dpy, const sp<GraphicBuffer>& graphicBuffer);
|
|
|
|
// Disallow copying
|
|
EglImage(const EglImage& rhs);
|
|
void operator=(const EglImage& rhs);
|
|
|
|
// mGraphicBuffer is the buffer that was used to create this image.
|
|
sp<GraphicBuffer> mGraphicBuffer;
|
|
|
|
// mEglImage is the EGLImage created from mGraphicBuffer.
|
|
EGLImageKHR mEglImage;
|
|
|
|
// mEGLDisplay is the EGLDisplay that was used to create mEglImage.
|
|
EGLDisplay mEglDisplay;
|
|
|
|
// mCropRect is the crop rectangle passed to EGL when mEglImage
|
|
// was created.
|
|
Rect mCropRect;
|
|
};
|
|
|
|
/**
|
|
* doGLFenceWaitLocked inserts a wait command into the OpenGL ES command
|
|
* stream to ensure that it is safe for future OpenGL ES commands to
|
|
* access the current texture buffer.
|
|
*/
|
|
status_t doGLFenceWaitLocked(SurfaceTexture& st) const;
|
|
|
|
/**
|
|
* syncForReleaseLocked performs the synchronization needed to release the
|
|
* current slot from an OpenGL ES context. If needed it will set the
|
|
* current slot's fence to guard against a producer accessing the buffer
|
|
* before the outstanding accesses have completed.
|
|
*/
|
|
status_t syncForReleaseLocked(EGLDisplay dpy, SurfaceTexture& st);
|
|
|
|
/**
|
|
* returns a graphic buffer used when the texture image has been released
|
|
*/
|
|
static sp<GraphicBuffer> getDebugTexImageBuffer();
|
|
|
|
/**
|
|
* The default consumer usage flags that EGLConsumer always sets on its
|
|
* BufferQueue instance; these will be OR:d with any additional flags passed
|
|
* from the EGLConsumer user. In particular, EGLConsumer will always
|
|
* consume buffers as hardware textures.
|
|
*/
|
|
static const uint64_t DEFAULT_USAGE_FLAGS = GraphicBuffer::USAGE_HW_TEXTURE;
|
|
|
|
/**
|
|
* mCurrentTextureImage is the EglImage/buffer of the current texture. It's
|
|
* possible that this buffer is not associated with any buffer slot, so we
|
|
* must track it separately in order to support the getCurrentBuffer method.
|
|
*/
|
|
sp<EglImage> mCurrentTextureImage;
|
|
|
|
/**
|
|
* EGLSlot contains the information and object references that
|
|
* EGLConsumer maintains about a BufferQueue buffer slot.
|
|
*/
|
|
struct EglSlot {
|
|
EglSlot() : mEglFence(EGL_NO_SYNC_KHR) {}
|
|
|
|
/**
|
|
* mEglImage is the EGLImage created from mGraphicBuffer.
|
|
*/
|
|
sp<EglImage> mEglImage;
|
|
|
|
/**
|
|
* mFence is the EGL sync object that must signal before the buffer
|
|
* associated with this buffer slot may be dequeued. It is initialized
|
|
* to EGL_NO_SYNC_KHR when the buffer is created and (optionally, based
|
|
* on a compile-time option) set to a new sync object in updateTexImage.
|
|
*/
|
|
EGLSyncKHR mEglFence;
|
|
};
|
|
|
|
/**
|
|
* mEglDisplay is the EGLDisplay with which this EGLConsumer is currently
|
|
* associated. It is intialized to EGL_NO_DISPLAY and gets set to the
|
|
* current display when updateTexImage is called for the first time and when
|
|
* attachToContext is called.
|
|
*/
|
|
EGLDisplay mEglDisplay;
|
|
|
|
/**
|
|
* mEglContext is the OpenGL ES context with which this EGLConsumer is
|
|
* currently associated. It is initialized to EGL_NO_CONTEXT and gets set
|
|
* to the current GL context when updateTexImage is called for the first
|
|
* time and when attachToContext is called.
|
|
*/
|
|
EGLContext mEglContext;
|
|
|
|
/**
|
|
* mEGLSlots stores the buffers that have been allocated by the BufferQueue
|
|
* for each buffer slot. It is initialized to null pointers, and gets
|
|
* filled in with the result of BufferQueue::acquire when the
|
|
* client dequeues a buffer from a
|
|
* slot that has not yet been used. The buffer allocated to a slot will also
|
|
* be replaced if the requested buffer usage or geometry differs from that
|
|
* of the buffer allocated to a slot.
|
|
*/
|
|
EglSlot mEglSlots[BufferQueueDefs::NUM_BUFFER_SLOTS];
|
|
|
|
/**
|
|
* protects static initialization
|
|
*/
|
|
static Mutex sStaticInitLock;
|
|
|
|
/**
|
|
* mReleasedTexImageBuffer is a dummy buffer used when in single buffer
|
|
* mode and releaseTexImage() has been called
|
|
*/
|
|
static sp<GraphicBuffer> sReleasedTexImageBuffer;
|
|
sp<EglImage> mReleasedTexImage;
|
|
};
|
|
|
|
} // namespace android
|