You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
316 lines
13 KiB
316 lines
13 KiB
/*
|
|
* Copyright 2013 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.
|
|
*/
|
|
|
|
#ifndef SF_GLESRENDERENGINE_H_
|
|
#define SF_GLESRENDERENGINE_H_
|
|
|
|
#include <condition_variable>
|
|
#include <deque>
|
|
#include <mutex>
|
|
#include <queue>
|
|
#include <thread>
|
|
#include <unordered_map>
|
|
|
|
#include <EGL/egl.h>
|
|
#include <EGL/eglext.h>
|
|
#include <GLES2/gl2.h>
|
|
#include <android-base/thread_annotations.h>
|
|
#include <renderengine/RenderEngine.h>
|
|
#include <renderengine/private/Description.h>
|
|
#include <sys/types.h>
|
|
#include "GLShadowTexture.h"
|
|
#include "ImageManager.h"
|
|
|
|
#define EGL_NO_CONFIG ((EGLConfig)0)
|
|
|
|
namespace android {
|
|
|
|
namespace renderengine {
|
|
|
|
class Mesh;
|
|
class Texture;
|
|
|
|
namespace gl {
|
|
|
|
class GLImage;
|
|
class BlurFilter;
|
|
|
|
class GLESRenderEngine : public RenderEngine {
|
|
public:
|
|
static std::unique_ptr<GLESRenderEngine> create(const RenderEngineCreationArgs& args);
|
|
|
|
GLESRenderEngine(const RenderEngineCreationArgs& args, EGLDisplay display, EGLConfig config,
|
|
EGLContext ctxt, EGLSurface stub, EGLContext protectedContext,
|
|
EGLSurface protectedStub);
|
|
~GLESRenderEngine() override EXCLUDES(mRenderingMutex);
|
|
|
|
std::future<void> primeCache() override;
|
|
void genTextures(size_t count, uint32_t* names) override;
|
|
void deleteTextures(size_t count, uint32_t const* names) override;
|
|
bool isProtected() const override { return mInProtectedContext; }
|
|
bool supportsProtectedContent() const override;
|
|
void useProtectedContext(bool useProtectedContext) override;
|
|
status_t drawLayers(const DisplaySettings& display,
|
|
const std::vector<const LayerSettings*>& layers,
|
|
const std::shared_ptr<ExternalTexture>& buffer,
|
|
const bool useFramebufferCache, base::unique_fd&& bufferFence,
|
|
base::unique_fd* drawFence) override;
|
|
void cleanupPostRender() override;
|
|
int getContextPriority() override;
|
|
bool supportsBackgroundBlur() override { return mBlurFilter != nullptr; }
|
|
void onPrimaryDisplaySizeChanged(ui::Size size) override {}
|
|
|
|
EGLDisplay getEGLDisplay() const { return mEGLDisplay; }
|
|
// Creates an output image for rendering to
|
|
EGLImageKHR createFramebufferImageIfNeeded(ANativeWindowBuffer* nativeBuffer, bool isProtected,
|
|
bool useFramebufferCache)
|
|
EXCLUDES(mFramebufferImageCacheMutex);
|
|
|
|
// Test-only methods
|
|
// Returns true iff mImageCache contains an image keyed by bufferId
|
|
bool isImageCachedForTesting(uint64_t bufferId) EXCLUDES(mRenderingMutex);
|
|
// Returns true iff texName was previously generated by RenderEngine and was
|
|
// not destroyed.
|
|
bool isTextureNameKnownForTesting(uint32_t texName);
|
|
// Returns the buffer ID of the content bound to texName, or nullopt if no
|
|
// such mapping exists.
|
|
std::optional<uint64_t> getBufferIdForTextureNameForTesting(uint32_t texName);
|
|
// Returns true iff mFramebufferImageCache contains an image keyed by bufferId
|
|
bool isFramebufferImageCachedForTesting(uint64_t bufferId)
|
|
EXCLUDES(mFramebufferImageCacheMutex);
|
|
// These are wrappers around public methods above, but exposing Barrier
|
|
// objects so that tests can block.
|
|
std::shared_ptr<ImageManager::Barrier> cacheExternalTextureBufferForTesting(
|
|
const sp<GraphicBuffer>& buffer);
|
|
std::shared_ptr<ImageManager::Barrier> unbindExternalTextureBufferForTesting(uint64_t bufferId);
|
|
|
|
protected:
|
|
Framebuffer* getFramebufferForDrawing();
|
|
void dump(std::string& result) override EXCLUDES(mRenderingMutex)
|
|
EXCLUDES(mFramebufferImageCacheMutex);
|
|
size_t getMaxTextureSize() const override;
|
|
size_t getMaxViewportDims() const override;
|
|
void mapExternalTextureBuffer(const sp<GraphicBuffer>& buffer, bool isRenderable)
|
|
EXCLUDES(mRenderingMutex);
|
|
void unmapExternalTextureBuffer(const sp<GraphicBuffer>& buffer) EXCLUDES(mRenderingMutex);
|
|
bool canSkipPostRenderCleanup() const override;
|
|
|
|
private:
|
|
friend class BindNativeBufferAsFramebuffer;
|
|
|
|
enum GlesVersion {
|
|
GLES_VERSION_1_0 = 0x10000,
|
|
GLES_VERSION_1_1 = 0x10001,
|
|
GLES_VERSION_2_0 = 0x20000,
|
|
GLES_VERSION_3_0 = 0x30000,
|
|
};
|
|
|
|
static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig);
|
|
static GlesVersion parseGlesVersion(const char* str);
|
|
static EGLContext createEglContext(EGLDisplay display, EGLConfig config,
|
|
EGLContext shareContext,
|
|
std::optional<ContextPriority> contextPriority,
|
|
Protection protection);
|
|
static std::optional<RenderEngine::ContextPriority> createContextPriority(
|
|
const RenderEngineCreationArgs& args);
|
|
static EGLSurface createStubEglPbufferSurface(EGLDisplay display, EGLConfig config,
|
|
int hwcFormat, Protection protection);
|
|
std::unique_ptr<Framebuffer> createFramebuffer();
|
|
std::unique_ptr<Image> createImage();
|
|
void checkErrors() const;
|
|
void checkErrors(const char* tag) const;
|
|
void setScissor(const Rect& region);
|
|
void disableScissor();
|
|
bool waitSync(EGLSyncKHR sync, EGLint flags);
|
|
status_t cacheExternalTextureBufferInternal(const sp<GraphicBuffer>& buffer)
|
|
EXCLUDES(mRenderingMutex);
|
|
void unbindExternalTextureBufferInternal(uint64_t bufferId) EXCLUDES(mRenderingMutex);
|
|
status_t bindFrameBuffer(Framebuffer* framebuffer);
|
|
void unbindFrameBuffer(Framebuffer* framebuffer);
|
|
void bindExternalTextureImage(uint32_t texName, const Image& image);
|
|
void bindExternalTextureBuffer(uint32_t texName, const sp<GraphicBuffer>& buffer,
|
|
const sp<Fence>& fence) EXCLUDES(mRenderingMutex);
|
|
void cleanFramebufferCache() EXCLUDES(mFramebufferImageCacheMutex) override;
|
|
|
|
// A data space is considered HDR data space if it has BT2020 color space
|
|
// with PQ or HLG transfer function.
|
|
bool isHdrDataSpace(const ui::Dataspace dataSpace) const;
|
|
bool needsXYZTransformMatrix() const;
|
|
// Defines the viewport, and sets the projection matrix to the projection
|
|
// defined by the clip.
|
|
void setViewportAndProjection(Rect viewport, Rect clip);
|
|
// Evicts stale images from the buffer cache.
|
|
void evictImages(const std::vector<LayerSettings>& layers);
|
|
// Computes the cropping window for the layer and sets up cropping
|
|
// coordinates for the mesh.
|
|
FloatRect setupLayerCropping(const LayerSettings& layer, Mesh& mesh);
|
|
|
|
// We do a special handling for rounded corners when it's possible to turn off blending
|
|
// for the majority of the layer. The rounded corners needs to turn on blending such that
|
|
// we can set the alpha value correctly, however, only the corners need this, and since
|
|
// blending is an expensive operation, we want to turn off blending when it's not necessary.
|
|
void handleRoundedCorners(const DisplaySettings& display, const LayerSettings& layer,
|
|
const Mesh& mesh);
|
|
base::unique_fd flush();
|
|
bool finish();
|
|
bool waitFence(base::unique_fd fenceFd);
|
|
void clearWithColor(float red, float green, float blue, float alpha);
|
|
void fillRegionWithColor(const Region& region, float red, float green, float blue, float alpha);
|
|
void handleShadow(const FloatRect& casterRect, float casterCornerRadius,
|
|
const ShadowSettings& shadowSettings);
|
|
void setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture,
|
|
const half4& color, float cornerRadius);
|
|
void setupLayerTexturing(const Texture& texture);
|
|
void setupFillWithColor(float r, float g, float b, float a);
|
|
void setColorTransform(const mat4& colorTransform);
|
|
void setDisplayColorTransform(const mat4& colorTransform);
|
|
void disableTexturing();
|
|
void disableBlending();
|
|
void setupCornerRadiusCropSize(float width, float height);
|
|
|
|
// HDR and color management related functions and state
|
|
void setSourceY410BT2020(bool enable);
|
|
void setSourceDataSpace(ui::Dataspace source);
|
|
void setOutputDataSpace(ui::Dataspace dataspace);
|
|
void setDisplayMaxLuminance(const float maxLuminance);
|
|
// HUANGLONG begin
|
|
// set Keystone mode to skiaRenderEngine
|
|
void setKeystoneMode(const uint32_t flags, const std::vector<double> matrix) override{};
|
|
// HUANGLONG end
|
|
// drawing
|
|
void drawMesh(const Mesh& mesh);
|
|
|
|
EGLDisplay mEGLDisplay;
|
|
EGLConfig mEGLConfig;
|
|
EGLContext mEGLContext;
|
|
EGLSurface mStubSurface;
|
|
EGLContext mProtectedEGLContext;
|
|
EGLSurface mProtectedStubSurface;
|
|
GLint mMaxViewportDims[2];
|
|
GLint mMaxTextureSize;
|
|
GLuint mVpWidth;
|
|
GLuint mVpHeight;
|
|
Description mState;
|
|
std::unique_ptr<GLShadowTexture> mShadowTexture = nullptr;
|
|
|
|
mat4 mSrgbToXyz;
|
|
mat4 mDisplayP3ToXyz;
|
|
mat4 mBt2020ToXyz;
|
|
mat4 mXyzToSrgb;
|
|
mat4 mXyzToDisplayP3;
|
|
mat4 mXyzToBt2020;
|
|
mat4 mSrgbToDisplayP3;
|
|
mat4 mSrgbToBt2020;
|
|
mat4 mDisplayP3ToSrgb;
|
|
mat4 mDisplayP3ToBt2020;
|
|
mat4 mBt2020ToSrgb;
|
|
mat4 mBt2020ToDisplayP3;
|
|
|
|
bool mInProtectedContext = false;
|
|
// If set to true, then enables tracing flush() and finish() to systrace.
|
|
bool mTraceGpuCompletion = false;
|
|
// Maximum size of mFramebufferImageCache. If more images would be cached, then (approximately)
|
|
// the last recently used buffer should be kicked out.
|
|
uint32_t mFramebufferImageCacheSize = 0;
|
|
|
|
// Cache of output images, keyed by corresponding GraphicBuffer ID.
|
|
std::deque<std::pair<uint64_t, EGLImageKHR>> mFramebufferImageCache
|
|
GUARDED_BY(mFramebufferImageCacheMutex);
|
|
// The only reason why we have this mutex is so that we don't segfault when
|
|
// dumping info.
|
|
std::mutex mFramebufferImageCacheMutex;
|
|
|
|
// Current dataspace of layer being rendered
|
|
ui::Dataspace mDataSpace = ui::Dataspace::UNKNOWN;
|
|
|
|
// Current output dataspace of the render engine
|
|
ui::Dataspace mOutputDataSpace = ui::Dataspace::UNKNOWN;
|
|
|
|
// Whether device supports color management, currently color management
|
|
// supports sRGB, DisplayP3 color spaces.
|
|
const bool mUseColorManagement = false;
|
|
|
|
// Whether only shaders performing tone mapping from HDR to SDR will be generated on
|
|
// primeCache().
|
|
const bool mPrecacheToneMapperShaderOnly = false;
|
|
|
|
// Cache of GL images that we'll store per GraphicBuffer ID
|
|
std::unordered_map<uint64_t, std::unique_ptr<Image>> mImageCache GUARDED_BY(mRenderingMutex);
|
|
std::unordered_map<uint32_t, std::optional<uint64_t>> mTextureView;
|
|
|
|
// Mutex guarding rendering operations, so that:
|
|
// 1. GL operations aren't interleaved, and
|
|
// 2. Internal state related to rendering that is potentially modified by
|
|
// multiple threads is guaranteed thread-safe.
|
|
std::mutex mRenderingMutex;
|
|
|
|
std::unique_ptr<Framebuffer> mDrawingBuffer;
|
|
// this is a 1x1 RGB buffer, but over-allocate in case a driver wants more
|
|
// memory or if it needs to satisfy alignment requirements. In this case:
|
|
// assume that each channel requires 4 bytes, and add 3 additional bytes to
|
|
// ensure that we align on a word. Allocating 16 bytes will provide a
|
|
// guarantee that we don't clobber memory.
|
|
uint32_t mPlaceholderDrawBuffer[4];
|
|
// Placeholder buffer and image, similar to mPlaceholderDrawBuffer, but
|
|
// instead these are intended for cleaning up texture memory with the
|
|
// GL_TEXTURE_EXTERNAL_OES target.
|
|
ANativeWindowBuffer* mPlaceholderBuffer = nullptr;
|
|
EGLImage mPlaceholderImage = EGL_NO_IMAGE_KHR;
|
|
sp<Fence> mLastDrawFence;
|
|
// Store a separate boolean checking if prior resources were cleaned up, as
|
|
// devices that don't support native sync fences can't rely on a last draw
|
|
// fence that doesn't exist.
|
|
bool mPriorResourcesCleaned = true;
|
|
|
|
// Blur effect processor, only instantiated when a layer requests it.
|
|
BlurFilter* mBlurFilter = nullptr;
|
|
|
|
class FlushTracer {
|
|
public:
|
|
FlushTracer(GLESRenderEngine* engine);
|
|
~FlushTracer();
|
|
void queueSync(EGLSyncKHR sync) EXCLUDES(mMutex);
|
|
|
|
struct QueueEntry {
|
|
EGLSyncKHR mSync = nullptr;
|
|
uint64_t mFrameNum = 0;
|
|
};
|
|
|
|
private:
|
|
void loop();
|
|
GLESRenderEngine* const mEngine;
|
|
std::thread mThread;
|
|
std::condition_variable_any mCondition;
|
|
std::mutex mMutex;
|
|
std::queue<QueueEntry> mQueue GUARDED_BY(mMutex);
|
|
uint64_t mFramesQueued GUARDED_BY(mMutex) = 0;
|
|
bool mRunning = true;
|
|
};
|
|
friend class FlushTracer;
|
|
friend class ImageManager;
|
|
friend class GLFramebuffer;
|
|
friend class BlurFilter;
|
|
friend class GenericProgram;
|
|
std::unique_ptr<FlushTracer> mFlushTracer;
|
|
std::unique_ptr<ImageManager> mImageManager;
|
|
};
|
|
|
|
} // namespace gl
|
|
} // namespace renderengine
|
|
} // namespace android
|
|
|
|
#endif /* SF_GLESRENDERENGINE_H_ */
|