summaryrefslogtreecommitdiff
path: root/libs/renderengine/gl/GLESRenderEngine.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/renderengine/gl/GLESRenderEngine.cpp')
-rw-r--r--libs/renderengine/gl/GLESRenderEngine.cpp348
1 files changed, 247 insertions, 101 deletions
diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp
index 92e7e715ea..467f848237 100644
--- a/libs/renderengine/gl/GLESRenderEngine.cpp
+++ b/libs/renderengine/gl/GLESRenderEngine.cpp
@@ -15,6 +15,7 @@
*/
//#define LOG_NDEBUG 0
+#include "EGL/egl.h"
#undef LOG_TAG
#define LOG_TAG "RenderEngine"
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
@@ -51,8 +52,6 @@
#include "ProgramCache.h"
#include "filters/BlurFilter.h"
-extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
-
bool checkGlError(const char* op, int lineNumber) {
bool errorFound = false;
GLint error = glGetError();
@@ -116,6 +115,28 @@ namespace android {
namespace renderengine {
namespace gl {
+class BindNativeBufferAsFramebuffer {
+public:
+ BindNativeBufferAsFramebuffer(GLESRenderEngine& engine, ANativeWindowBuffer* buffer,
+ const bool useFramebufferCache)
+ : mEngine(engine), mFramebuffer(mEngine.getFramebufferForDrawing()), mStatus(NO_ERROR) {
+ mStatus = mFramebuffer->setNativeWindowBuffer(buffer, mEngine.isProtected(),
+ useFramebufferCache)
+ ? mEngine.bindFrameBuffer(mFramebuffer)
+ : NO_MEMORY;
+ }
+ ~BindNativeBufferAsFramebuffer() {
+ mFramebuffer->setNativeWindowBuffer(nullptr, false, /*arbitrary*/ true);
+ mEngine.unbindFrameBuffer(mFramebuffer);
+ }
+ status_t getStatus() const { return mStatus; }
+
+private:
+ GLESRenderEngine& mEngine;
+ Framebuffer* mFramebuffer;
+ status_t mStatus;
+};
+
using base::StringAppendF;
using ui::Dataspace;
@@ -201,23 +222,47 @@ static status_t selectEGLConfig(EGLDisplay display, EGLint format, EGLint render
return err;
}
+std::optional<RenderEngine::ContextPriority> GLESRenderEngine::createContextPriority(
+ const RenderEngineCreationArgs& args) {
+ if (!GLExtensions::getInstance().hasContextPriority()) {
+ return std::nullopt;
+ }
+
+ switch (args.contextPriority) {
+ case RenderEngine::ContextPriority::REALTIME:
+ if (gl::GLExtensions::getInstance().hasRealtimePriority()) {
+ return RenderEngine::ContextPriority::REALTIME;
+ } else {
+ ALOGI("Realtime priority unsupported, degrading gracefully to high priority");
+ return RenderEngine::ContextPriority::HIGH;
+ }
+ case RenderEngine::ContextPriority::HIGH:
+ case RenderEngine::ContextPriority::MEDIUM:
+ case RenderEngine::ContextPriority::LOW:
+ return args.contextPriority;
+ default:
+ return std::nullopt;
+ }
+}
+
std::unique_ptr<GLESRenderEngine> GLESRenderEngine::create(const RenderEngineCreationArgs& args) {
// initialize EGL for the default display
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (!eglInitialize(display, nullptr, nullptr)) {
- LOG_ALWAYS_FATAL("failed to initialize EGL");
+ LOG_ALWAYS_FATAL("failed to initialize EGL. EGL error=0x%x", eglGetError());
}
- const auto eglVersion = eglQueryStringImplementationANDROID(display, EGL_VERSION);
+ const auto eglVersion = eglQueryString(display, EGL_VERSION);
if (!eglVersion) {
checkGlError(__FUNCTION__, __LINE__);
- LOG_ALWAYS_FATAL("eglQueryStringImplementationANDROID(EGL_VERSION) failed");
+ LOG_ALWAYS_FATAL("eglQueryString(EGL_VERSION) failed");
}
- const auto eglExtensions = eglQueryStringImplementationANDROID(display, EGL_EXTENSIONS);
+ // Use the Android impl to grab EGL_NV_context_priority_realtime
+ const auto eglExtensions = eglQueryString(display, EGL_EXTENSIONS);
if (!eglExtensions) {
checkGlError(__FUNCTION__, __LINE__);
- LOG_ALWAYS_FATAL("eglQueryStringImplementationANDROID(EGL_EXTENSIONS) failed");
+ LOG_ALWAYS_FATAL("eglQueryString(EGL_EXTENSIONS) failed");
}
GLExtensions& extensions = GLExtensions::getInstance();
@@ -230,37 +275,36 @@ std::unique_ptr<GLESRenderEngine> GLESRenderEngine::create(const RenderEngineCre
config = chooseEglConfig(display, args.pixelFormat, /*logConfig*/ true);
}
- bool useContextPriority =
- extensions.hasContextPriority() && args.contextPriority == ContextPriority::HIGH;
+ const std::optional<RenderEngine::ContextPriority> priority = createContextPriority(args);
EGLContext protectedContext = EGL_NO_CONTEXT;
if (args.enableProtectedContext && extensions.hasProtectedContent()) {
- protectedContext = createEglContext(display, config, nullptr, useContextPriority,
- Protection::PROTECTED);
+ protectedContext =
+ createEglContext(display, config, nullptr, priority, Protection::PROTECTED);
ALOGE_IF(protectedContext == EGL_NO_CONTEXT, "Can't create protected context");
}
- EGLContext ctxt = createEglContext(display, config, protectedContext, useContextPriority,
- Protection::UNPROTECTED);
+ EGLContext ctxt =
+ createEglContext(display, config, protectedContext, priority, Protection::UNPROTECTED);
// if can't create a GL context, we can only abort.
LOG_ALWAYS_FATAL_IF(ctxt == EGL_NO_CONTEXT, "EGLContext creation failed");
- EGLSurface dummy = EGL_NO_SURFACE;
+ EGLSurface stub = EGL_NO_SURFACE;
if (!extensions.hasSurfacelessContext()) {
- dummy = createDummyEglPbufferSurface(display, config, args.pixelFormat,
- Protection::UNPROTECTED);
- LOG_ALWAYS_FATAL_IF(dummy == EGL_NO_SURFACE, "can't create dummy pbuffer");
+ stub = createStubEglPbufferSurface(display, config, args.pixelFormat,
+ Protection::UNPROTECTED);
+ LOG_ALWAYS_FATAL_IF(stub == EGL_NO_SURFACE, "can't create stub pbuffer");
}
- EGLBoolean success = eglMakeCurrent(display, dummy, dummy, ctxt);
- LOG_ALWAYS_FATAL_IF(!success, "can't make dummy pbuffer current");
+ EGLBoolean success = eglMakeCurrent(display, stub, stub, ctxt);
+ LOG_ALWAYS_FATAL_IF(!success, "can't make stub pbuffer current");
extensions.initWithGLStrings(glGetString(GL_VENDOR), glGetString(GL_RENDERER),
glGetString(GL_VERSION), glGetString(GL_EXTENSIONS));
- EGLSurface protectedDummy = EGL_NO_SURFACE;
+ EGLSurface protectedStub = EGL_NO_SURFACE;
if (protectedContext != EGL_NO_CONTEXT && !extensions.hasSurfacelessContext()) {
- protectedDummy = createDummyEglPbufferSurface(display, config, args.pixelFormat,
- Protection::PROTECTED);
- ALOGE_IF(protectedDummy == EGL_NO_SURFACE, "can't create protected dummy pbuffer");
+ protectedStub = createStubEglPbufferSurface(display, config, args.pixelFormat,
+ Protection::PROTECTED);
+ ALOGE_IF(protectedStub == EGL_NO_SURFACE, "can't create protected stub pbuffer");
}
// now figure out what version of GL did we actually get
@@ -278,8 +322,8 @@ std::unique_ptr<GLESRenderEngine> GLESRenderEngine::create(const RenderEngineCre
break;
case GLES_VERSION_2_0:
case GLES_VERSION_3_0:
- engine = std::make_unique<GLESRenderEngine>(args, display, config, ctxt, dummy,
- protectedContext, protectedDummy);
+ engine = std::make_unique<GLESRenderEngine>(args, display, config, ctxt, stub,
+ protectedContext, protectedStub);
break;
}
@@ -290,7 +334,6 @@ std::unique_ptr<GLESRenderEngine> GLESRenderEngine::create(const RenderEngineCre
ALOGI("extensions: %s", extensions.getExtensions());
ALOGI("GL_MAX_TEXTURE_SIZE = %zu", engine->getMaxTextureSize());
ALOGI("GL_MAX_VIEWPORT_DIMS = %zu", engine->getMaxViewportDims());
-
return engine;
}
@@ -334,19 +377,20 @@ EGLConfig GLESRenderEngine::chooseEglConfig(EGLDisplay display, int format, bool
}
GLESRenderEngine::GLESRenderEngine(const RenderEngineCreationArgs& args, EGLDisplay display,
- EGLConfig config, EGLContext ctxt, EGLSurface dummy,
- EGLContext protectedContext, EGLSurface protectedDummy)
- : renderengine::impl::RenderEngine(args),
+ EGLConfig config, EGLContext ctxt, EGLSurface stub,
+ EGLContext protectedContext, EGLSurface protectedStub)
+ : RenderEngine(args.renderEngineType),
mEGLDisplay(display),
mEGLConfig(config),
mEGLContext(ctxt),
- mDummySurface(dummy),
+ mStubSurface(stub),
mProtectedEGLContext(protectedContext),
- mProtectedDummySurface(protectedDummy),
+ mProtectedStubSurface(protectedStub),
mVpWidth(0),
mVpHeight(0),
mFramebufferImageCacheSize(args.imageCacheSize),
- mUseColorManagement(args.useColorManagement) {
+ mUseColorManagement(args.useColorManagement),
+ mPrecacheToneMapperShaderOnly(args.precacheToneMapperShaderOnly) {
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
glGetIntegerv(GL_MAX_VIEWPORT_DIMS, mMaxViewportDims);
@@ -355,12 +399,12 @@ GLESRenderEngine::GLESRenderEngine(const RenderEngineCreationArgs& args, EGLDisp
// Initialize protected EGL Context.
if (mProtectedEGLContext != EGL_NO_CONTEXT) {
- EGLBoolean success = eglMakeCurrent(display, mProtectedDummySurface, mProtectedDummySurface,
+ EGLBoolean success = eglMakeCurrent(display, mProtectedStubSurface, mProtectedStubSurface,
mProtectedEGLContext);
ALOGE_IF(!success, "can't make protected context current");
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glPixelStorei(GL_PACK_ALIGNMENT, 4);
- success = eglMakeCurrent(display, mDummySurface, mDummySurface, mEGLContext);
+ success = eglMakeCurrent(display, mStubSurface, mStubSurface, mEGLContext);
LOG_ALWAYS_FATAL_IF(!success, "can't make default context current");
}
@@ -409,23 +453,54 @@ GLESRenderEngine::GLESRenderEngine(const RenderEngineCreationArgs& args, EGLDisp
mImageManager = std::make_unique<ImageManager>(this);
mImageManager->initThread();
mDrawingBuffer = createFramebuffer();
+ sp<GraphicBuffer> buf =
+ new GraphicBuffer(1, 1, PIXEL_FORMAT_RGBA_8888, 1,
+ GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE, "placeholder");
+
+ const status_t err = buf->initCheck();
+ if (err != OK) {
+ ALOGE("Error allocating placeholder buffer: %d", err);
+ return;
+ }
+ mPlaceholderBuffer = buf.get();
+ EGLint attributes[] = {
+ EGL_NONE,
+ };
+ mPlaceholderImage = eglCreateImageKHR(mEGLDisplay, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
+ mPlaceholderBuffer, attributes);
+ ALOGE_IF(mPlaceholderImage == EGL_NO_IMAGE_KHR, "Failed to create placeholder image: %#x",
+ eglGetError());
+
+ mShadowTexture = std::make_unique<GLShadowTexture>();
}
GLESRenderEngine::~GLESRenderEngine() {
// Destroy the image manager first.
mImageManager = nullptr;
+ mShadowTexture = nullptr;
+ cleanFramebufferCache();
+ ProgramCache::getInstance().purgeCaches();
std::lock_guard<std::mutex> lock(mRenderingMutex);
+ glDisableVertexAttribArray(Program::position);
unbindFrameBuffer(mDrawingBuffer.get());
mDrawingBuffer = nullptr;
- while (!mFramebufferImageCache.empty()) {
- EGLImageKHR expired = mFramebufferImageCache.front().second;
- mFramebufferImageCache.pop_front();
- eglDestroyImageKHR(mEGLDisplay, expired);
- DEBUG_EGL_IMAGE_TRACKER_DESTROY();
- }
+ eglDestroyImageKHR(mEGLDisplay, mPlaceholderImage);
mImageCache.clear();
+ if (mStubSurface != EGL_NO_SURFACE) {
+ eglDestroySurface(mEGLDisplay, mStubSurface);
+ }
+ if (mProtectedStubSurface != EGL_NO_SURFACE) {
+ eglDestroySurface(mEGLDisplay, mProtectedStubSurface);
+ }
+ if (mEGLContext != EGL_NO_CONTEXT) {
+ eglDestroyContext(mEGLDisplay, mEGLContext);
+ }
+ if (mProtectedEGLContext != EGL_NO_CONTEXT) {
+ eglDestroyContext(mEGLDisplay, mProtectedEGLContext);
+ }
eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
eglTerminate(mEGLDisplay);
+ eglReleaseThread();
}
std::unique_ptr<Framebuffer> GLESRenderEngine::createFramebuffer() {
@@ -440,10 +515,10 @@ Framebuffer* GLESRenderEngine::getFramebufferForDrawing() {
return mDrawingBuffer.get();
}
-void GLESRenderEngine::primeCache() const {
+std::future<void> GLESRenderEngine::primeCache() {
ProgramCache::getInstance().primeCache(mInProtectedContext ? mProtectedEGLContext : mEGLContext,
- mArgs.useColorManagement,
- mArgs.precacheToneMapperShaderOnly);
+ mUseColorManagement, mPrecacheToneMapperShaderOnly);
+ return {};
}
base::unique_fd GLESRenderEngine::flush() {
@@ -589,6 +664,9 @@ void GLESRenderEngine::genTextures(size_t count, uint32_t* names) {
}
void GLESRenderEngine::deleteTextures(size_t count, uint32_t const* names) {
+ for (int i = 0; i < count; ++i) {
+ mTextureView.erase(names[i]);
+ }
glDeleteTextures(count, names);
}
@@ -603,13 +681,8 @@ void GLESRenderEngine::bindExternalTextureImage(uint32_t texName, const Image& i
}
}
-status_t GLESRenderEngine::bindExternalTextureBuffer(uint32_t texName,
- const sp<GraphicBuffer>& buffer,
- const sp<Fence>& bufferFence) {
- if (buffer == nullptr) {
- return BAD_VALUE;
- }
-
+void GLESRenderEngine::bindExternalTextureBuffer(uint32_t texName, const sp<GraphicBuffer>& buffer,
+ const sp<Fence>& bufferFence) {
ATRACE_CALL();
bool found = false;
@@ -625,7 +698,8 @@ status_t GLESRenderEngine::bindExternalTextureBuffer(uint32_t texName,
if (!found) {
status_t cacheResult = mImageManager->cache(buffer);
if (cacheResult != NO_ERROR) {
- return cacheResult;
+ ALOGE("Error with caching buffer: %d", cacheResult);
+ return;
}
}
@@ -642,10 +716,11 @@ status_t GLESRenderEngine::bindExternalTextureBuffer(uint32_t texName,
// We failed creating the image if we got here, so bail out.
ALOGE("Failed to create an EGLImage when rendering");
bindExternalTextureImage(texName, *createImage());
- return NO_INIT;
+ return;
}
bindExternalTextureImage(texName, *cachedImage->second);
+ mTextureView.insert_or_assign(texName, buffer->getId());
}
// Wait for the new buffer to be ready.
@@ -654,25 +729,27 @@ status_t GLESRenderEngine::bindExternalTextureBuffer(uint32_t texName,
base::unique_fd fenceFd(bufferFence->dup());
if (fenceFd == -1) {
ALOGE("error dup'ing fence fd: %d", errno);
- return -errno;
+ return;
}
if (!waitFence(std::move(fenceFd))) {
ALOGE("failed to wait on fence fd");
- return UNKNOWN_ERROR;
+ return;
}
} else {
status_t err = bufferFence->waitForever("RenderEngine::bindExternalTextureBuffer");
if (err != NO_ERROR) {
ALOGE("error waiting for fence: %d", err);
- return err;
+ return;
}
}
}
- return NO_ERROR;
+ return;
}
-void GLESRenderEngine::cacheExternalTextureBuffer(const sp<GraphicBuffer>& buffer) {
+void GLESRenderEngine::mapExternalTextureBuffer(const sp<GraphicBuffer>& buffer,
+ bool /*isRenderable*/) {
+ ATRACE_CALL();
mImageManager->cacheAsync(buffer, nullptr);
}
@@ -703,9 +780,9 @@ status_t GLESRenderEngine::cacheExternalTextureBufferInternal(const sp<GraphicBu
bool created = newImage->setNativeWindowBuffer(buffer->getNativeBuffer(),
buffer->getUsage() & GRALLOC_USAGE_PROTECTED);
if (!created) {
- ALOGE("Failed to create image. size=%ux%u st=%u usage=%#" PRIx64 " fmt=%d",
- buffer->getWidth(), buffer->getHeight(), buffer->getStride(), buffer->getUsage(),
- buffer->getPixelFormat());
+ ALOGE("Failed to create image. id=%" PRIx64 " size=%ux%u st=%u usage=%#" PRIx64 " fmt=%d",
+ buffer->getId(), buffer->getWidth(), buffer->getHeight(), buffer->getStride(),
+ buffer->getUsage(), buffer->getPixelFormat());
return NO_INIT;
}
@@ -722,8 +799,8 @@ status_t GLESRenderEngine::cacheExternalTextureBufferInternal(const sp<GraphicBu
return NO_ERROR;
}
-void GLESRenderEngine::unbindExternalTextureBuffer(uint64_t bufferId) {
- mImageManager->releaseAsync(bufferId, nullptr);
+void GLESRenderEngine::unmapExternalTextureBuffer(const sp<GraphicBuffer>& buffer) {
+ mImageManager->releaseAsync(buffer->getId(), nullptr);
}
std::shared_ptr<ImageManager::Barrier> GLESRenderEngine::unbindExternalTextureBufferForTesting(
@@ -751,6 +828,12 @@ void GLESRenderEngine::unbindExternalTextureBufferInternal(uint64_t bufferId) {
ALOGV("Failed to find image for buffer: %" PRIu64, bufferId);
}
+int GLESRenderEngine::getContextPriority() {
+ int value;
+ eglQueryContext(mEGLDisplay, mEGLContext, EGL_CONTEXT_PRIORITY_LEVEL_IMG, &value);
+ return value;
+}
+
FloatRect GLESRenderEngine::setupLayerCropping(const LayerSettings& layer, Mesh& mesh) {
// Translate win by the rounded corners rect coordinates, to have all values in
// layer coordinate space.
@@ -887,23 +970,41 @@ void GLESRenderEngine::unbindFrameBuffer(Framebuffer* /*framebuffer*/) {
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
-bool GLESRenderEngine::cleanupPostRender() {
+bool GLESRenderEngine::canSkipPostRenderCleanup() const {
+ return mPriorResourcesCleaned ||
+ (mLastDrawFence != nullptr && mLastDrawFence->getStatus() != Fence::Status::Signaled);
+}
+
+void GLESRenderEngine::cleanupPostRender() {
ATRACE_CALL();
- if (mPriorResourcesCleaned ||
- (mLastDrawFence != nullptr && mLastDrawFence->getStatus() != Fence::Status::Signaled)) {
+ if (canSkipPostRenderCleanup()) {
// If we don't have a prior frame needing cleanup, then don't do anything.
- return false;
+ return;
}
- // Bind the texture to dummy data so that backing image data can be freed.
+ // Bind the texture to placeholder so that backing image data can be freed.
GLFramebuffer* glFramebuffer = static_cast<GLFramebuffer*>(getFramebufferForDrawing());
glFramebuffer->allocateBuffers(1, 1, mPlaceholderDrawBuffer);
+
// Release the cached fence here, so that we don't churn reallocations when
// we could no-op repeated calls of this method instead.
mLastDrawFence = nullptr;
mPriorResourcesCleaned = true;
- return true;
+}
+
+void GLESRenderEngine::cleanFramebufferCache() {
+ std::lock_guard<std::mutex> lock(mFramebufferImageCacheMutex);
+ // Bind the texture to placeholder so that backing image data can be freed.
+ GLFramebuffer* glFramebuffer = static_cast<GLFramebuffer*>(getFramebufferForDrawing());
+ glFramebuffer->allocateBuffers(1, 1, mPlaceholderDrawBuffer);
+
+ while (!mFramebufferImageCache.empty()) {
+ EGLImageKHR expired = mFramebufferImageCache.front().second;
+ mFramebufferImageCache.pop_front();
+ eglDestroyImageKHR(mEGLDisplay, expired);
+ DEBUG_EGL_IMAGE_TRACKER_DESTROY();
+ }
}
void GLESRenderEngine::checkErrors() const {
@@ -927,20 +1028,17 @@ bool GLESRenderEngine::supportsProtectedContent() const {
return mProtectedEGLContext != EGL_NO_CONTEXT;
}
-bool GLESRenderEngine::useProtectedContext(bool useProtectedContext) {
- if (useProtectedContext == mInProtectedContext) {
- return true;
- }
- if (useProtectedContext && mProtectedEGLContext == EGL_NO_CONTEXT) {
- return false;
+void GLESRenderEngine::useProtectedContext(bool useProtectedContext) {
+ if (useProtectedContext == mInProtectedContext ||
+ (useProtectedContext && !supportsProtectedContent())) {
+ return;
}
- const EGLSurface surface = useProtectedContext ? mProtectedDummySurface : mDummySurface;
+
+ const EGLSurface surface = useProtectedContext ? mProtectedStubSurface : mStubSurface;
const EGLContext context = useProtectedContext ? mProtectedEGLContext : mEGLContext;
- const bool success = eglMakeCurrent(mEGLDisplay, surface, surface, context) == EGL_TRUE;
- if (success) {
+ if (eglMakeCurrent(mEGLDisplay, surface, surface, context) == EGL_TRUE) {
mInProtectedContext = useProtectedContext;
}
- return success;
}
EGLImageKHR GLESRenderEngine::createFramebufferImageIfNeeded(ANativeWindowBuffer* nativeBuffer,
bool isProtected,
@@ -982,7 +1080,7 @@ EGLImageKHR GLESRenderEngine::createFramebufferImageIfNeeded(ANativeWindowBuffer
status_t GLESRenderEngine::drawLayers(const DisplaySettings& display,
const std::vector<const LayerSettings*>& layers,
- ANativeWindowBuffer* const buffer,
+ const std::shared_ptr<ExternalTexture>& buffer,
const bool useFramebufferCache, base::unique_fd&& bufferFence,
base::unique_fd* drawFence) {
ATRACE_CALL();
@@ -1005,6 +1103,8 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display,
return BAD_VALUE;
}
+ validateOutputBufferUsage(buffer->getBuffer());
+
std::unique_ptr<BindNativeBufferAsFramebuffer> fbo;
// Gathering layers that requested blur, we'll need them to decide when to render to an
// offscreen buffer, and when to render to the native buffer.
@@ -1019,10 +1119,14 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display,
const auto blurLayersSize = blurLayers.size();
if (blurLayersSize == 0) {
- fbo = std::make_unique<BindNativeBufferAsFramebuffer>(*this, buffer, useFramebufferCache);
+ fbo = std::make_unique<BindNativeBufferAsFramebuffer>(*this,
+ buffer->getBuffer()
+ .get()
+ ->getNativeBuffer(),
+ useFramebufferCache);
if (fbo->getStatus() != NO_ERROR) {
ALOGE("Failed to bind framebuffer! Aborting GPU composition for buffer (%p).",
- buffer->handle);
+ buffer->getBuffer()->handle);
checkErrors();
return fbo->getStatus();
}
@@ -1033,7 +1137,7 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display,
mBlurFilter->setAsDrawTarget(display, blurLayers.front()->backgroundBlurRadius);
if (status != NO_ERROR) {
ALOGE("Failed to prepare blur filter! Aborting GPU composition for buffer (%p).",
- buffer->handle);
+ buffer->getBuffer()->handle);
checkErrors();
return status;
}
@@ -1048,6 +1152,7 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display,
setOutputDataSpace(display.outputDataspace);
setDisplayMaxLuminance(display.maxLuminance);
+ setDisplayColorTransform(display.colorTransform);
const mat4 projectionMatrix =
ui::Transform(display.orientation).asMatrix4() * mState.projectionMatrix;
@@ -1069,14 +1174,17 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display,
auto status = mBlurFilter->prepare();
if (status != NO_ERROR) {
ALOGE("Failed to render blur effect! Aborting GPU composition for buffer (%p).",
- buffer->handle);
+ buffer->getBuffer()->handle);
checkErrors("Can't render first blur pass");
return status;
}
if (blurLayers.size() == 0) {
// Done blurring, time to bind the native FBO and render our blur onto it.
- fbo = std::make_unique<BindNativeBufferAsFramebuffer>(*this, buffer,
+ fbo = std::make_unique<BindNativeBufferAsFramebuffer>(*this,
+ buffer.get()
+ ->getBuffer()
+ ->getNativeBuffer(),
useFramebufferCache);
status = fbo->getStatus();
setViewportAndProjection(display.physicalDisplay, display.clip);
@@ -1088,7 +1196,7 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display,
}
if (status != NO_ERROR) {
ALOGE("Failed to bind framebuffer! Aborting GPU composition for buffer (%p).",
- buffer->handle);
+ buffer->getBuffer()->handle);
checkErrors("Can't bind native framebuffer");
return status;
}
@@ -1096,14 +1204,16 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display,
status = mBlurFilter->render(blurLayersSize > 1);
if (status != NO_ERROR) {
ALOGE("Failed to render blur effect! Aborting GPU composition for buffer (%p).",
- buffer->handle);
+ buffer->getBuffer()->handle);
checkErrors("Can't render blur filter");
return status;
}
}
- mState.maxMasteringLuminance = layer->source.buffer.maxMasteringLuminance;
- mState.maxContentLuminance = layer->source.buffer.maxContentLuminance;
+ // Ensure luminance is at least 100 nits to avoid div-by-zero
+ const float maxLuminance = std::max(100.f, layer->source.buffer.maxLuminanceNits);
+ mState.maxMasteringLuminance = maxLuminance;
+ mState.maxContentLuminance = maxLuminance;
mState.projectionMatrix = projectionMatrix * layer->geometry.positionTransform;
const FloatRect bounds = layer->geometry.boundaries;
@@ -1114,7 +1224,7 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display,
position[3] = vec2(bounds.right, bounds.top);
setupLayerCropping(*layer, mesh);
- setColorTransform(display.colorTransform * layer->colorTransform);
+ setColorTransform(layer->colorTransform);
bool usePremultipliedAlpha = true;
bool disableTexture = true;
@@ -1123,7 +1233,8 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display,
disableTexture = false;
isOpaque = layer->source.buffer.isOpaque;
- sp<GraphicBuffer> gBuf = layer->source.buffer.buffer;
+ sp<GraphicBuffer> gBuf = layer->source.buffer.buffer->getBuffer();
+ validateInputBufferUsage(gBuf);
bindExternalTextureBuffer(layer->source.buffer.textureName, gBuf,
layer->source.buffer.fence);
@@ -1143,6 +1254,11 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display,
texCoords[2] = vec2(1.0, 1.0);
texCoords[3] = vec2(1.0, 0.0);
setupLayerTexturing(texture);
+
+ // Do not cache protected EGLImage, protected memory is limited.
+ if (gBuf->getUsage() & GRALLOC_USAGE_PROTECTED) {
+ unmapExternalTextureBuffer(gBuf);
+ }
}
const half3 solidColor = layer->source.solidColor;
@@ -1228,7 +1344,8 @@ void GLESRenderEngine::setupLayerBlending(bool premultipliedAlpha, bool opaque,
if (color.a < 1.0f || !opaque || cornerRadius > 0.0f) {
glEnable(GL_BLEND);
- glBlendFunc(premultipliedAlpha ? GL_ONE : GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(premultipliedAlpha ? GL_ONE : GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
+ GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
} else {
glDisable(GL_BLEND);
}
@@ -1270,6 +1387,10 @@ void GLESRenderEngine::setColorTransform(const mat4& colorTransform) {
mState.colorMatrix = colorTransform;
}
+void GLESRenderEngine::setDisplayColorTransform(const mat4& colorTransform) {
+ mState.displayColorMatrix = colorTransform;
+}
+
void GLESRenderEngine::disableTexturing() {
mState.textureEnabled = false;
}
@@ -1512,7 +1633,8 @@ GLESRenderEngine::GlesVersion GLESRenderEngine::parseGlesVersion(const char* str
}
EGLContext GLESRenderEngine::createEglContext(EGLDisplay display, EGLConfig config,
- EGLContext shareContext, bool useContextPriority,
+ EGLContext shareContext,
+ std::optional<ContextPriority> contextPriority,
Protection protection) {
EGLint renderableType = 0;
if (config == EGL_NO_CONFIG) {
@@ -1535,9 +1657,23 @@ EGLContext GLESRenderEngine::createEglContext(EGLDisplay display, EGLConfig conf
contextAttributes.reserve(7);
contextAttributes.push_back(EGL_CONTEXT_CLIENT_VERSION);
contextAttributes.push_back(contextClientVersion);
- if (useContextPriority) {
+ if (contextPriority) {
contextAttributes.push_back(EGL_CONTEXT_PRIORITY_LEVEL_IMG);
- contextAttributes.push_back(EGL_CONTEXT_PRIORITY_HIGH_IMG);
+ switch (*contextPriority) {
+ case ContextPriority::REALTIME:
+ contextAttributes.push_back(EGL_CONTEXT_PRIORITY_REALTIME_NV);
+ break;
+ case ContextPriority::MEDIUM:
+ contextAttributes.push_back(EGL_CONTEXT_PRIORITY_MEDIUM_IMG);
+ break;
+ case ContextPriority::LOW:
+ contextAttributes.push_back(EGL_CONTEXT_PRIORITY_LOW_IMG);
+ break;
+ case ContextPriority::HIGH:
+ default:
+ contextAttributes.push_back(EGL_CONTEXT_PRIORITY_HIGH_IMG);
+ break;
+ }
}
if (protection == Protection::PROTECTED) {
contextAttributes.push_back(EGL_PROTECTED_CONTENT_EXT);
@@ -1562,11 +1698,11 @@ EGLContext GLESRenderEngine::createEglContext(EGLDisplay display, EGLConfig conf
return context;
}
-EGLSurface GLESRenderEngine::createDummyEglPbufferSurface(EGLDisplay display, EGLConfig config,
- int hwcFormat, Protection protection) {
- EGLConfig dummyConfig = config;
- if (dummyConfig == EGL_NO_CONFIG) {
- dummyConfig = chooseEglConfig(display, hwcFormat, /*logConfig*/ true);
+EGLSurface GLESRenderEngine::createStubEglPbufferSurface(EGLDisplay display, EGLConfig config,
+ int hwcFormat, Protection protection) {
+ EGLConfig stubConfig = config;
+ if (stubConfig == EGL_NO_CONFIG) {
+ stubConfig = chooseEglConfig(display, hwcFormat, /*logConfig*/ true);
}
std::vector<EGLint> attributes;
attributes.reserve(7);
@@ -1580,7 +1716,7 @@ EGLSurface GLESRenderEngine::createDummyEglPbufferSurface(EGLDisplay display, EG
}
attributes.push_back(EGL_NONE);
- return eglCreatePbufferSurface(display, dummyConfig, attributes.data());
+ return eglCreatePbufferSurface(display, stubConfig, attributes.data());
}
bool GLESRenderEngine::isHdrDataSpace(const Dataspace dataSpace) const {
@@ -1616,6 +1752,16 @@ bool GLESRenderEngine::isImageCachedForTesting(uint64_t bufferId) {
return cachedImage != mImageCache.end();
}
+bool GLESRenderEngine::isTextureNameKnownForTesting(uint32_t texName) {
+ const auto& entry = mTextureView.find(texName);
+ return entry != mTextureView.end();
+}
+
+std::optional<uint64_t> GLESRenderEngine::getBufferIdForTextureNameForTesting(uint32_t texName) {
+ const auto& entry = mTextureView.find(texName);
+ return entry != mTextureView.end() ? entry->second : std::nullopt;
+}
+
bool GLESRenderEngine::isFramebufferImageCachedForTesting(uint64_t bufferId) {
std::lock_guard<std::mutex> lock(mFramebufferImageCacheMutex);
return std::any_of(mFramebufferImageCache.cbegin(), mFramebufferImageCache.cend(),
@@ -1704,7 +1850,7 @@ void GLESRenderEngine::handleShadow(const FloatRect& casterRect, float casterCor
mState.cornerRadius = 0.0f;
mState.drawShadows = true;
- setupLayerTexturing(mShadowTexture.getTexture());
+ setupLayerTexturing(mShadowTexture->getTexture());
drawMesh(mesh);
mState.drawShadows = false;
}