summaryrefslogtreecommitdiff
path: root/libs/hwui/renderthread
diff options
context:
space:
mode:
Diffstat (limited to 'libs/hwui/renderthread')
-rw-r--r--libs/hwui/renderthread/CanvasContext.cpp12
-rw-r--r--libs/hwui/renderthread/CanvasContext.h6
-rw-r--r--libs/hwui/renderthread/DrawFrameTask.cpp18
-rw-r--r--libs/hwui/renderthread/DrawFrameTask.h9
-rw-r--r--libs/hwui/renderthread/EglManager.cpp7
-rw-r--r--libs/hwui/renderthread/RenderEffectCapabilityQuery.cpp39
-rw-r--r--libs/hwui/renderthread/RenderEffectCapabilityQuery.h35
-rw-r--r--libs/hwui/renderthread/RenderProxy.cpp6
-rw-r--r--libs/hwui/renderthread/RenderProxy.h3
9 files changed, 115 insertions, 20 deletions
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 2f3a509831d1..a066e6f7c693 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -491,10 +491,10 @@ nsecs_t CanvasContext::draw() {
// Notify the callbacks, even if there's nothing to draw so they aren't waiting
// indefinitely
waitOnFences();
- for (auto& func : mFrameCompleteCallbacks) {
- std::invoke(func, mFrameNumber);
+ for (auto& func : mFrameCommitCallbacks) {
+ std::invoke(func, false /* didProduceBuffer */);
}
- mFrameCompleteCallbacks.clear();
+ mFrameCommitCallbacks.clear();
return 0;
}
@@ -603,10 +603,10 @@ nsecs_t CanvasContext::draw() {
#endif
if (didSwap) {
- for (auto& func : mFrameCompleteCallbacks) {
- std::invoke(func, frameCompleteNr);
+ for (auto& func : mFrameCommitCallbacks) {
+ std::invoke(func, true /* didProduceBuffer */);
}
- mFrameCompleteCallbacks.clear();
+ mFrameCommitCallbacks.clear();
}
if (requireSwap) {
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 6dbfcc349d50..9df429badd5e 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -187,8 +187,8 @@ public:
IRenderPipeline* getRenderPipeline() { return mRenderPipeline.get(); }
- void addFrameCompleteListener(std::function<void(int64_t)>&& func) {
- mFrameCompleteCallbacks.push_back(std::move(func));
+ void addFrameCommitListener(std::function<void(bool)>&& func) {
+ mFrameCommitCallbacks.push_back(std::move(func));
}
void setPictureCapturedCallback(const std::function<void(sk_sp<SkPicture>&&)>& callback) {
@@ -320,7 +320,7 @@ private:
std::vector<std::future<void>> mFrameFences;
std::unique_ptr<IRenderPipeline> mRenderPipeline;
- std::vector<std::function<void(int64_t)>> mFrameCompleteCallbacks;
+ std::vector<std::function<void(bool)>> mFrameCommitCallbacks;
// If set to true, we expect that callbacks into onSurfaceStatsAvailable
bool mExpectSurfaceStats = false;
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index e7081df2b558..94aedd0f43be 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -150,16 +150,18 @@ void DrawFrameTask::run() {
canUnblockUiThread = syncFrameState(info);
canDrawThisFrame = info.out.canDrawThisFrame;
- if (mFrameCompleteCallback) {
- mContext->addFrameCompleteListener(std::move(mFrameCompleteCallback));
- mFrameCompleteCallback = nullptr;
+ if (mFrameCommitCallback) {
+ mContext->addFrameCommitListener(std::move(mFrameCommitCallback));
+ mFrameCommitCallback = nullptr;
}
}
// Grab a copy of everything we need
CanvasContext* context = mContext;
- std::function<void(int64_t)> callback = std::move(mFrameCallback);
+ std::function<void(int64_t)> frameCallback = std::move(mFrameCallback);
+ std::function<void()> frameCompleteCallback = std::move(mFrameCompleteCallback);
mFrameCallback = nullptr;
+ mFrameCompleteCallback = nullptr;
int64_t intendedVsync = mFrameInfo[static_cast<int>(FrameInfoIndex::IntendedVsync)];
int64_t frameDeadline = mFrameInfo[static_cast<int>(FrameInfoIndex::FrameDeadline)];
int64_t frameStartTime = mFrameInfo[static_cast<int>(FrameInfoIndex::FrameStartTime)];
@@ -170,9 +172,9 @@ void DrawFrameTask::run() {
}
// Even if we aren't drawing this vsync pulse the next frame number will still be accurate
- if (CC_UNLIKELY(callback)) {
+ if (CC_UNLIKELY(frameCallback)) {
context->enqueueFrameWork(
- [callback, frameNr = context->getFrameNumber()]() { callback(frameNr); });
+ [frameCallback, frameNr = context->getFrameNumber()]() { frameCallback(frameNr); });
}
nsecs_t dequeueBufferDuration = 0;
@@ -189,6 +191,10 @@ void DrawFrameTask::run() {
context->waitOnFences();
}
+ if (CC_UNLIKELY(frameCompleteCallback)) {
+ std::invoke(frameCompleteCallback);
+ }
+
if (!canUnblockUiThread) {
unblockUiThread();
}
diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h
index 6a61a2bb645f..e3ea802b07b9 100644
--- a/libs/hwui/renderthread/DrawFrameTask.h
+++ b/libs/hwui/renderthread/DrawFrameTask.h
@@ -81,7 +81,11 @@ public:
mFrameCallback = std::move(callback);
}
- void setFrameCompleteCallback(std::function<void(int64_t)>&& callback) {
+ void setFrameCommitCallback(std::function<void(bool)>&& callback) {
+ mFrameCommitCallback = std::move(callback);
+ }
+
+ void setFrameCompleteCallback(std::function<void()>&& callback) {
mFrameCompleteCallback = std::move(callback);
}
@@ -123,7 +127,8 @@ private:
int64_t mFrameInfo[UI_THREAD_FRAME_INFO_SIZE];
std::function<void(int64_t)> mFrameCallback;
- std::function<void(int64_t)> mFrameCompleteCallback;
+ std::function<void(bool)> mFrameCommitCallback;
+ std::function<void()> mFrameCompleteCallback;
nsecs_t mLastDequeueBufferDuration = 0;
nsecs_t mLastTargetWorkDuration = 0;
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index 383c79b27918..c7d7a17a23eb 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -28,6 +28,7 @@
#include "Frame.h"
#include "Properties.h"
+#include "RenderEffectCapabilityQuery.h"
#include "utils/Color.h"
#include "utils/StringUtils.h"
@@ -148,7 +149,11 @@ void EglManager::initialize() {
mHasWideColorGamutSupport = EglExtensions.glColorSpace && hasWideColorSpaceExtension;
auto* vendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR));
- Properties::enableRenderEffectCache = (strcmp(vendor, "Qualcomm") != 0);
+ auto* version = reinterpret_cast<const char*>(glGetString(GL_VERSION));
+ Properties::enableRenderEffectCache = supportsRenderEffectCache(
+ vendor, version);
+ ALOGV("RenderEffectCache supported %d on driver version %s",
+ Properties::enableRenderEffectCache, version);
}
EGLConfig EglManager::load8BitsConfig(EGLDisplay display, EglManager::SwapBehavior swapBehavior) {
diff --git a/libs/hwui/renderthread/RenderEffectCapabilityQuery.cpp b/libs/hwui/renderthread/RenderEffectCapabilityQuery.cpp
new file mode 100644
index 000000000000..a003988575c8
--- /dev/null
+++ b/libs/hwui/renderthread/RenderEffectCapabilityQuery.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+#include <stdio.h>
+#include <string.h>
+#include <utils/Log.h>
+
+bool supportsRenderEffectCache(const char* vendor, const char* version) {
+ if (strcmp(vendor, "Qualcomm") != 0) {
+ return true;
+ }
+
+ int major;
+ int minor;
+ int driverMajor;
+ int driverMinor;
+ int n = sscanf(version,"OpenGL ES %d.%d V@%d.%d",
+ &major,
+ &minor,
+ &driverMajor,
+ &driverMinor);
+ // Ensure we have parsed the vendor string properly and we have either
+ // a newer major driver version, or the minor version is rev'ed
+ // Based on b/198227600#comment5 it appears that the corresponding fix
+ // is in driver version 571.0
+ return n == 4 && driverMajor >= 571;
+} \ No newline at end of file
diff --git a/libs/hwui/renderthread/RenderEffectCapabilityQuery.h b/libs/hwui/renderthread/RenderEffectCapabilityQuery.h
new file mode 100644
index 000000000000..ea673dd0386d
--- /dev/null
+++ b/libs/hwui/renderthread/RenderEffectCapabilityQuery.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 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
+
+/**
+ * Verify if the provided vendor and version supports RenderEffect caching
+ * behavior.
+ *
+ * Certain Open GL Driver implementations run into blocking scenarios
+ * with Fence::waitForever without a corresponding signal to unblock
+ * This happens during attempts to cache SkImage instances across frames
+ * especially in circumstances using RenderEffect/SkImageFilter internally.
+ * So detect the corresponding GL Vendor and driver version to determine if
+ * caching SkImage instances across frames is supported.
+ * See b/197263715 & b/193145089
+ * @param vendor Vendor of the GL driver
+ * @param version Version of the GL driver from the given vendor
+ * @return True if a RenderEffect result can be cached across frames,
+ * false otherwise
+ */
+bool supportsRenderEffectCache(const char* vendor, const char* version);
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index c485ce2781e5..72d4ac5081e6 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -326,7 +326,11 @@ void RenderProxy::setFrameCallback(std::function<void(int64_t)>&& callback) {
mDrawFrameTask.setFrameCallback(std::move(callback));
}
-void RenderProxy::setFrameCompleteCallback(std::function<void(int64_t)>&& callback) {
+void RenderProxy::setFrameCommitCallback(std::function<void(bool)>&& callback) {
+ mDrawFrameTask.setFrameCommitCallback(std::move(callback));
+}
+
+void RenderProxy::setFrameCompleteCallback(std::function<void()>&& callback) {
mDrawFrameTask.setFrameCompleteCallback(std::move(callback));
}
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 2b5405c82563..6417b38df064 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -124,7 +124,8 @@ public:
const std::function<bool(int64_t, int64_t, int64_t)>& callback);
void setPrepareSurfaceControlForWebviewCallback(const std::function<void()>& callback);
void setFrameCallback(std::function<void(int64_t)>&& callback);
- void setFrameCompleteCallback(std::function<void(int64_t)>&& callback);
+ void setFrameCommitCallback(std::function<void(bool)>&& callback);
+ void setFrameCompleteCallback(std::function<void()>&& callback);
void addFrameMetricsObserver(FrameMetricsObserver* observer);
void removeFrameMetricsObserver(FrameMetricsObserver* observer);