summaryrefslogtreecommitdiff
path: root/libs/hwui/renderthread
diff options
context:
space:
mode:
Diffstat (limited to 'libs/hwui/renderthread')
-rw-r--r--libs/hwui/renderthread/CacheManager.cpp77
-rw-r--r--libs/hwui/renderthread/CacheManager.h18
-rw-r--r--libs/hwui/renderthread/CanvasContext.cpp143
-rw-r--r--libs/hwui/renderthread/CanvasContext.h47
-rw-r--r--libs/hwui/renderthread/DrawFrameTask.cpp13
-rw-r--r--libs/hwui/renderthread/DrawFrameTask.h8
-rw-r--r--libs/hwui/renderthread/EglManager.cpp206
-rw-r--r--libs/hwui/renderthread/EglManager.h2
-rw-r--r--libs/hwui/renderthread/Frame.h7
-rw-r--r--libs/hwui/renderthread/IRenderPipeline.h34
-rw-r--r--libs/hwui/renderthread/OpenGLPipeline.cpp136
-rw-r--r--libs/hwui/renderthread/OpenGLPipeline.h27
-rw-r--r--libs/hwui/renderthread/RenderProxy.cpp616
-rw-r--r--libs/hwui/renderthread/RenderProxy.h45
-rw-r--r--libs/hwui/renderthread/RenderTask.h6
-rw-r--r--libs/hwui/renderthread/RenderThread.cpp292
-rw-r--r--libs/hwui/renderthread/RenderThread.h57
-rw-r--r--libs/hwui/renderthread/TimeLord.cpp5
-rw-r--r--libs/hwui/renderthread/VulkanManager.cpp229
-rw-r--r--libs/hwui/renderthread/VulkanManager.h25
20 files changed, 711 insertions, 1282 deletions
diff --git a/libs/hwui/renderthread/CacheManager.cpp b/libs/hwui/renderthread/CacheManager.cpp
index 55694d046c2f..907f2d2d398f 100644
--- a/libs/hwui/renderthread/CacheManager.cpp
+++ b/libs/hwui/renderthread/CacheManager.cpp
@@ -17,11 +17,14 @@
#include "CacheManager.h"
#include "Layer.h"
+#include "Properties.h"
#include "RenderThread.h"
+#include "pipeline/skia/ShaderCache.h"
#include "renderstate/RenderState.h"
-#include <gui/Surface.h>
#include <GrContextOptions.h>
+#include <SkExecutor.h>
+#include <gui/Surface.h>
#include <math.h>
#include <set>
@@ -41,19 +44,22 @@ namespace renderthread {
#define FONT_CACHE_MIN_MB (0.5f)
#define FONT_CACHE_MAX_MB (4.0f)
-CacheManager::CacheManager(const DisplayInfo& display)
- : mMaxSurfaceArea(display.w * display.h) {
- mVectorDrawableAtlas = new skiapipeline::VectorDrawableAtlas(mMaxSurfaceArea/2,
- skiapipeline::VectorDrawableAtlas::StorageMode::allowSharedSurface);
+CacheManager::CacheManager(const DisplayInfo& display) : mMaxSurfaceArea(display.w * display.h) {
+ mVectorDrawableAtlas = new skiapipeline::VectorDrawableAtlas(
+ mMaxSurfaceArea / 2,
+ skiapipeline::VectorDrawableAtlas::StorageMode::disallowSharedSurface);
+ if (Properties::isSkiaEnabled()) {
+ skiapipeline::ShaderCache::get().initShaderDiskCache();
+ }
}
-void CacheManager::reset(GrContext* context) {
- if (context != mGrContext.get()) {
+void CacheManager::reset(sk_sp<GrContext> context) {
+ if (context != mGrContext) {
destroy();
}
if (context) {
- mGrContext = sk_ref_sp(context);
+ mGrContext = std::move(context);
mGrContext->getResourceCacheLimits(&mMaxResources, nullptr);
updateContextCacheSizes();
}
@@ -62,7 +68,9 @@ void CacheManager::reset(GrContext* context) {
void CacheManager::destroy() {
// cleanup any caches here as the GrContext is about to go away...
mGrContext.reset(nullptr);
- mVectorDrawableAtlas = new skiapipeline::VectorDrawableAtlas(mMaxSurfaceArea/2);
+ mVectorDrawableAtlas = new skiapipeline::VectorDrawableAtlas(
+ mMaxSurfaceArea / 2,
+ skiapipeline::VectorDrawableAtlas::StorageMode::disallowSharedSurface);
}
void CacheManager::updateContextCacheSizes() {
@@ -72,6 +80,29 @@ void CacheManager::updateContextCacheSizes() {
mGrContext->setResourceCacheLimits(mMaxResources, mMaxResourceBytes);
}
+class CacheManager::SkiaTaskProcessor : public TaskProcessor<bool>, public SkExecutor {
+public:
+ explicit SkiaTaskProcessor(TaskManager* taskManager) : TaskProcessor<bool>(taskManager) {}
+
+ // This is really a Task<void> but that doesn't really work when Future<>
+ // expects to be able to get/set a value
+ struct SkiaTask : public Task<bool> {
+ std::function<void()> func;
+ };
+
+ virtual void add(std::function<void(void)> func) override {
+ sp<SkiaTask> task(new SkiaTask());
+ task->func = func;
+ TaskProcessor<bool>::add(task);
+ }
+
+ virtual void onProcess(const sp<Task<bool> >& task) override {
+ SkiaTask* t = static_cast<SkiaTask*>(task.get());
+ t->func();
+ task->setResult(true);
+ }
+};
+
void CacheManager::configureContext(GrContextOptions* contextOptions) {
contextOptions->fAllowPathMaskCaching = true;
@@ -94,6 +125,15 @@ void CacheManager::configureContext(GrContextOptions* contextOptions) {
// Skia's implementation doesn't provide a mechanism to resize the font cache due to
// the potential cost of recreating the glyphs.
contextOptions->fGlyphCacheTextureMaximumBytes = fontCacheMB * 1024 * 1024;
+
+ if (mTaskManager.canRunTasks()) {
+ if (!mTaskProcessor.get()) {
+ mTaskProcessor = new SkiaTaskProcessor(&mTaskManager);
+ }
+ contextOptions->fExecutor = mTaskProcessor.get();
+ }
+
+ contextOptions->fPersistentCache = &skiapipeline::ShaderCache::get();
}
void CacheManager::trimMemory(TrimMemoryMode mode) {
@@ -105,7 +145,7 @@ void CacheManager::trimMemory(TrimMemoryMode mode) {
switch (mode) {
case TrimMemoryMode::Complete:
- mVectorDrawableAtlas = new skiapipeline::VectorDrawableAtlas(mMaxSurfaceArea/2);
+ mVectorDrawableAtlas = new skiapipeline::VectorDrawableAtlas(mMaxSurfaceArea / 2);
mGrContext->freeGpuResources();
break;
case TrimMemoryMode::UiHidden:
@@ -143,8 +183,8 @@ void CacheManager::dumpMemoryUsage(String8& log, const RenderState* renderState)
log.appendFormat("Caches:\n");
log.appendFormat(" Current / Maximum\n");
- log.appendFormat(" VectorDrawableAtlas %6.2f kB / %6.2f kB (entries = %zu)\n",
- 0.0f, 0.0f, (size_t)0);
+ log.appendFormat(" VectorDrawableAtlas %6.2f kB / %6.2f kB (entries = %zu)\n", 0.0f, 0.0f,
+ (size_t)0);
if (renderState) {
if (renderState->mActiveLayers.size() > 0) {
@@ -153,24 +193,21 @@ void CacheManager::dumpMemoryUsage(String8& log, const RenderState* renderState)
size_t layerMemoryTotal = 0;
for (std::set<Layer*>::iterator it = renderState->mActiveLayers.begin();
- it != renderState->mActiveLayers.end(); it++) {
+ it != renderState->mActiveLayers.end(); it++) {
const Layer* layer = *it;
const char* layerType = layer->getApi() == Layer::Api::OpenGL ? "GlLayer" : "VkLayer";
- log.appendFormat(" %s size %dx%d\n", layerType,
- layer->getWidth(), layer->getHeight());
+ log.appendFormat(" %s size %dx%d\n", layerType, layer->getWidth(),
+ layer->getHeight());
layerMemoryTotal += layer->getWidth() * layer->getHeight() * 4;
}
log.appendFormat(" Layers Total %6.2f kB (numLayers = %zu)\n",
layerMemoryTotal / 1024.0f, renderState->mActiveLayers.size());
}
-
log.appendFormat("Total memory usage:\n");
- log.appendFormat(" %zu bytes, %.2f MB (%.2f MB is purgeable)\n",
- bytesCached, bytesCached / 1024.0f / 1024.0f,
+ log.appendFormat(" %zu bytes, %.2f MB (%.2f MB is purgeable)\n", bytesCached,
+ bytesCached / 1024.0f / 1024.0f,
mGrContext->getResourceCachePurgeableBytes() / 1024.0f / 1024.0f);
-
-
}
} /* namespace renderthread */
diff --git a/libs/hwui/renderthread/CacheManager.h b/libs/hwui/renderthread/CacheManager.h
index 90362f33358d..7d733525194f 100644
--- a/libs/hwui/renderthread/CacheManager.h
+++ b/libs/hwui/renderthread/CacheManager.h
@@ -22,7 +22,10 @@
#include <ui/DisplayInfo.h>
#include <utils/String8.h>
#include <vector>
+
#include "pipeline/skia/VectorDrawableAtlas.h"
+#include "thread/TaskManager.h"
+#include "thread/TaskProcessor.h"
namespace android {
@@ -39,10 +42,7 @@ class RenderThread;
class CacheManager {
public:
- enum class TrimMemoryMode {
- Complete,
- UiHidden
- };
+ enum class TrimMemoryMode { Complete, UiHidden };
void configureContext(GrContextOptions* context);
void trimMemory(TrimMemoryMode mode);
@@ -54,13 +54,14 @@ public:
size_t getCacheSize() const { return mMaxResourceBytes; }
size_t getBackgroundCacheSize() const { return mBackgroundResourceBytes; }
+ TaskManager* getTaskManager() { return &mTaskManager; }
+
private:
friend class RenderThread;
CacheManager(const DisplayInfo& display);
-
- void reset(GrContext* grContext);
+ void reset(sk_sp<GrContext> grContext);
void destroy();
void updateContextCacheSizes();
@@ -77,6 +78,10 @@ private:
};
sp<skiapipeline::VectorDrawableAtlas> mVectorDrawableAtlas;
+
+ class SkiaTaskProcessor;
+ sp<SkiaTaskProcessor> mTaskProcessor;
+ TaskManager mTaskManager;
};
} /* namespace renderthread */
@@ -84,4 +89,3 @@ private:
} /* namespace android */
#endif /* CACHEMANAGER_H */
-
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 5d7f5948b0ec..820789dd055d 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -14,35 +14,36 @@
* limitations under the License.
*/
-#include <GpuMemoryTracker.h>
#include "CanvasContext.h"
+#include <GpuMemoryTracker.h>
#include "AnimationContext.h"
#include "Caches.h"
#include "EglManager.h"
#include "Frame.h"
#include "LayerUpdateQueue.h"
+#include "OpenGLPipeline.h"
#include "Properties.h"
#include "RenderThread.h"
#include "hwui/Canvas.h"
-#include "renderstate/RenderState.h"
-#include "renderstate/Stencil.h"
-#include "protos/hwui.pb.h"
-#include "OpenGLPipeline.h"
#include "pipeline/skia/SkiaOpenGLPipeline.h"
#include "pipeline/skia/SkiaPipeline.h"
#include "pipeline/skia/SkiaVulkanPipeline.h"
+#include "protos/hwui.pb.h"
+#include "renderstate/RenderState.h"
+#include "renderstate/Stencil.h"
#include "utils/GLUtils.h"
#include "utils/TimeUtils.h"
+#include "../Properties.h"
#include <cutils/properties.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <private/hwui/DrawGlInfo.h>
#include <strings.h>
-#include <algorithm>
#include <fcntl.h>
#include <sys/stat.h>
+#include <algorithm>
#include <cstdlib>
@@ -63,23 +64,22 @@ namespace android {
namespace uirenderer {
namespace renderthread {
-CanvasContext* CanvasContext::create(RenderThread& thread,
- bool translucent, RenderNode* rootRenderNode, IContextFactory* contextFactory) {
-
+CanvasContext* CanvasContext::create(RenderThread& thread, bool translucent,
+ RenderNode* rootRenderNode, IContextFactory* contextFactory) {
auto renderType = Properties::getRenderPipelineType();
switch (renderType) {
case RenderPipelineType::OpenGL:
return new CanvasContext(thread, translucent, rootRenderNode, contextFactory,
- std::make_unique<OpenGLPipeline>(thread));
+ std::make_unique<OpenGLPipeline>(thread));
case RenderPipelineType::SkiaGL:
return new CanvasContext(thread, translucent, rootRenderNode, contextFactory,
- std::make_unique<skiapipeline::SkiaOpenGLPipeline>(thread));
+ std::make_unique<skiapipeline::SkiaOpenGLPipeline>(thread));
case RenderPipelineType::SkiaVulkan:
return new CanvasContext(thread, translucent, rootRenderNode, contextFactory,
- std::make_unique<skiapipeline::SkiaVulkanPipeline>(thread));
+ std::make_unique<skiapipeline::SkiaVulkanPipeline>(thread));
default:
- LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t) renderType);
+ LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t)renderType);
break;
}
return nullptr;
@@ -96,7 +96,7 @@ void CanvasContext::destroyLayer(RenderNode* node) {
skiapipeline::SkiaPipeline::destroyLayer(node);
break;
default:
- LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t) renderType);
+ LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t)renderType);
break;
}
}
@@ -115,7 +115,7 @@ void CanvasContext::invokeFunctor(const RenderThread& thread, Functor* functor)
skiapipeline::SkiaVulkanPipeline::invokeFunctor(thread, functor);
break;
default:
- LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t) renderType);
+ LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t)renderType);
break;
}
}
@@ -131,14 +131,14 @@ void CanvasContext::prepareToDraw(const RenderThread& thread, Bitmap* bitmap) {
skiapipeline::SkiaPipeline::prepareToDraw(thread, bitmap);
break;
default:
- LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t) renderType);
+ LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t)renderType);
break;
}
}
-CanvasContext::CanvasContext(RenderThread& thread, bool translucent,
- RenderNode* rootRenderNode, IContextFactory* contextFactory,
- std::unique_ptr<IRenderPipeline> renderPipeline)
+CanvasContext::CanvasContext(RenderThread& thread, bool translucent, RenderNode* rootRenderNode,
+ IContextFactory* contextFactory,
+ std::unique_ptr<IRenderPipeline> renderPipeline)
: mRenderThread(thread)
, mOpaque(!translucent)
, mAnimationContext(contextFactory->createAnimationContext(mRenderThread.timeLord()))
@@ -170,7 +170,7 @@ void CanvasContext::addRenderNode(RenderNode* node, bool placeFront) {
void CanvasContext::removeRenderNode(RenderNode* node) {
node->clearRoot();
mRenderNodes.erase(std::remove(mRenderNodes.begin(), mRenderNodes.end(), node),
- mRenderNodes.end());
+ mRenderNodes.end());
}
void CanvasContext::destroy() {
@@ -181,21 +181,21 @@ void CanvasContext::destroy() {
mAnimationContext->destroy();
}
-void CanvasContext::setSurface(Surface* surface) {
+void CanvasContext::setSurface(sp<Surface>&& surface) {
ATRACE_CALL();
- mNativeSurface = surface;
+ mNativeSurface = std::move(surface);
ColorMode colorMode = mWideColorGamut ? ColorMode::WideColorGamut : ColorMode::Srgb;
- bool hasSurface = mRenderPipeline->setSurface(surface, mSwapBehavior, colorMode);
+ bool hasSurface = mRenderPipeline->setSurface(mNativeSurface.get(), mSwapBehavior, colorMode);
mFrameNumber = -1;
if (hasSurface) {
- mHaveNewSurface = true;
- mSwapHistory.clear();
+ mHaveNewSurface = true;
+ mSwapHistory.clear();
} else {
- mRenderThread.removeFrameCallback(this);
+ mRenderThread.removeFrameCallback(this);
}
}
@@ -203,15 +203,7 @@ void CanvasContext::setSwapBehavior(SwapBehavior swapBehavior) {
mSwapBehavior = swapBehavior;
}
-void CanvasContext::initialize(Surface* surface) {
- setSurface(surface);
-}
-
-void CanvasContext::updateSurface(Surface* surface) {
- setSurface(surface);
-}
-
-bool CanvasContext::pauseSurface(Surface* surface) {
+bool CanvasContext::pauseSurface() {
return mRenderThread.removeFrameCallback(this);
}
@@ -227,8 +219,7 @@ void CanvasContext::setStopped(bool stopped) {
}
}
-void CanvasContext::setup(float lightRadius,
- uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
+void CanvasContext::setup(float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
mLightGeometry.radius = lightRadius;
mLightInfo.ambientShadowAlpha = ambientShadowAlpha;
mLightInfo.spotShadowAlpha = spotShadowAlpha;
@@ -262,7 +253,7 @@ bool CanvasContext::makeCurrent() {
return true;
default:
LOG_ALWAYS_FATAL("unexpected result %d from IRenderPipeline::makeCurrent",
- (int32_t) result);
+ (int32_t)result);
}
return true;
@@ -285,8 +276,7 @@ bool CanvasContext::isSwapChainStuffed() {
// Was there a happy queue & dequeue time? If so, don't
// consider it stuffed
- if (swapA.dequeueDuration < SLOW_THRESHOLD
- && swapA.queueDuration < SLOW_THRESHOLD) {
+ if (swapA.dequeueDuration < SLOW_THRESHOLD && swapA.queueDuration < SLOW_THRESHOLD) {
return false;
}
@@ -301,8 +291,7 @@ bool CanvasContext::isSwapChainStuffed() {
// Was there a happy queue & dequeue time? If so, don't
// consider it stuffed
- if (swapB.dequeueDuration < SLOW_THRESHOLD
- && swapB.queueDuration < SLOW_THRESHOLD) {
+ if (swapB.dequeueDuration < SLOW_THRESHOLD && swapB.queueDuration < SLOW_THRESHOLD) {
return false;
}
@@ -314,8 +303,8 @@ bool CanvasContext::isSwapChainStuffed() {
return true;
}
-void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo,
- int64_t syncQueued, RenderNode* target) {
+void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo, int64_t syncQueued,
+ RenderNode* target) {
mRenderThread.removeFrameCallback(this);
// If the previous frame was dropped we don't need to hold onto it, so
@@ -331,6 +320,7 @@ void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo,
info.layerUpdateQueue = &mLayerUpdateQueue;
mAnimationContext->startFrame(info.mode);
+ mRenderPipeline->onPrepareTree();
for (const sp<RenderNode>& node : mRenderNodes) {
// Only the primary target node will be drawn full - all other nodes would get drawn in
// real time mode. In case of a window, the primary node is the window content and the other
@@ -365,8 +355,8 @@ void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo,
// Already drew for this vsync pulse, UI draw request missed
// the deadline for RT animations
info.out.canDrawThisFrame = false;
- } else if (vsyncDelta >= mRenderThread.timeLord().frameIntervalNanos() * 3
- || (latestVsync - mLastDropVsync) < 500_ms) {
+ } else if (vsyncDelta >= mRenderThread.timeLord().frameIntervalNanos() * 3 ||
+ (latestVsync - mLastDropVsync) < 500_ms) {
// It's been several frame intervals, assume the buffer queue is fine
// or the last drop was too recent
info.out.canDrawThisFrame = true;
@@ -386,6 +376,9 @@ void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo,
}
if (info.out.hasAnimations || !info.out.canDrawThisFrame) {
+ if (CC_UNLIKELY(!Properties::enableRTAnimations)) {
+ info.out.requiresUiRedraw = true;
+ }
if (!info.out.requiresUiRedraw) {
// If animationsNeedsRedraw is set don't bother posting for an RT anim
// as we will just end up fighting the UI thread.
@@ -409,10 +402,10 @@ void CanvasContext::draw() {
mDamageAccumulator.finish(&dirty);
// TODO: Re-enable after figuring out cause of b/22592975
-// if (dirty.isEmpty() && Properties::skipEmptyFrames) {
-// mCurrentFrameInfo->addFlag(FrameInfoFlags::SkippedFrame);
-// return;
-// }
+ // if (dirty.isEmpty() && Properties::skipEmptyFrames) {
+ // mCurrentFrameInfo->addFlag(FrameInfoFlags::SkippedFrame);
+ // return;
+ // }
mCurrentFrameInfo->markIssueDrawCommandsStart();
@@ -421,18 +414,19 @@ void CanvasContext::draw() {
SkRect windowDirty = computeDirtyRect(frame, &dirty);
bool drew = mRenderPipeline->draw(frame, windowDirty, dirty, mLightGeometry, &mLayerUpdateQueue,
- mContentDrawBounds, mOpaque, mWideColorGamut, mLightInfo, mRenderNodes, &(profiler()));
+ mContentDrawBounds, mOpaque, mWideColorGamut, mLightInfo,
+ mRenderNodes, &(profiler()));
waitOnFences();
bool requireSwap = false;
- bool didSwap = mRenderPipeline->swapBuffers(frame, drew, windowDirty, mCurrentFrameInfo,
- &requireSwap);
+ bool didSwap =
+ mRenderPipeline->swapBuffers(frame, drew, windowDirty, mCurrentFrameInfo, &requireSwap);
mIsDirty = false;
if (requireSwap) {
- if (!didSwap) { //some error happened
+ if (!didSwap) { // some error happened
setSurface(nullptr);
}
SwapHistory& swap = mSwapHistory.next();
@@ -456,10 +450,8 @@ void CanvasContext::draw() {
swap.dequeueDuration = 0;
swap.queueDuration = 0;
}
- mCurrentFrameInfo->set(FrameInfoIndex::DequeueBufferDuration)
- = swap.dequeueDuration;
- mCurrentFrameInfo->set(FrameInfoIndex::QueueBufferDuration)
- = swap.queueDuration;
+ mCurrentFrameInfo->set(FrameInfoIndex::DequeueBufferDuration) = swap.dequeueDuration;
+ mCurrentFrameInfo->set(FrameInfoIndex::QueueBufferDuration) = swap.queueDuration;
mHaveNewSurface = false;
mFrameNumber = -1;
} else {
@@ -471,9 +463,9 @@ void CanvasContext::draw() {
mCurrentFrameInfo->markFrameCompleted();
#if LOG_FRAMETIME_MMA
- float thisFrame = mCurrentFrameInfo->duration(
- FrameInfoIndex::IssueDrawCommandsStart,
- FrameInfoIndex::FrameCompleted) / NANOS_PER_MILLIS_F;
+ float thisFrame = mCurrentFrameInfo->duration(FrameInfoIndex::IssueDrawCommandsStart,
+ FrameInfoIndex::FrameCompleted) /
+ NANOS_PER_MILLIS_F;
if (sFrameCount) {
sBenchMma = ((9 * sBenchMma) + thisFrame) / 10;
} else {
@@ -498,7 +490,6 @@ void CanvasContext::draw() {
caches.fontRenderer.getFontRenderer().historyTracker().frameCompleted();
}
#endif
-
}
// Called by choreographer to do an RT-driven animation
@@ -512,9 +503,7 @@ void CanvasContext::prepareAndDraw(RenderNode* node) {
nsecs_t vsync = mRenderThread.timeLord().computeFrameTimeNanos();
int64_t frameInfo[UI_THREAD_FRAME_INFO_SIZE];
- UiFrameInfoBuilder(frameInfo)
- .addFlag(FrameInfoFlags::RTAnimation)
- .setVsync(vsync, vsync);
+ UiFrameInfoBuilder(frameInfo).addFlag(FrameInfoFlags::RTAnimation).setVsync(vsync, vsync);
TreeInfo info(TreeInfo::MODE_RT_ONLY, *this);
prepareTree(info, frameInfo, systemTime(CLOCK_MONOTONIC), node);
@@ -536,7 +525,7 @@ void CanvasContext::freePrefetchedLayers() {
if (mPrefetchedLayers.size()) {
for (auto& node : mPrefetchedLayers) {
ALOGW("Incorrectly called buildLayer on View: %s, destroying layer...",
- node->getName());
+ node->getName());
node->destroyLayers();
node->decStrong(nullptr);
}
@@ -562,8 +551,8 @@ void CanvasContext::buildLayer(RenderNode* node) {
// purposes when the frame is actually drawn
node->setPropertyFieldsDirty(RenderNode::GENERIC);
- mRenderPipeline->renderLayers(mLightGeometry, &mLayerUpdateQueue,
- mOpaque, mWideColorGamut, mLightInfo);
+ mRenderPipeline->renderLayers(mLightGeometry, &mLayerUpdateQueue, mOpaque, mWideColorGamut,
+ mLightInfo);
node->incStrong(nullptr);
mPrefetchedLayers.insert(node);
@@ -614,7 +603,7 @@ void CanvasContext::trimMemory(RenderThread& thread, int level) {
break;
}
default:
- LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t) renderType);
+ LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t)renderType);
break;
}
}
@@ -641,7 +630,7 @@ void CanvasContext::serializeDisplayListTree() {
using namespace google::protobuf::io;
char package[128];
// Check whether tracing is enabled for this process.
- FILE * file = fopen("/proc/self/cmdline", "r");
+ FILE* file = fopen("/proc/self/cmdline", "r");
if (file) {
if (!fgets(package, 128, file)) {
ALOGE("Error reading cmdline: %s (%d)", strerror(errno), errno);
@@ -650,8 +639,7 @@ void CanvasContext::serializeDisplayListTree() {
}
fclose(file);
} else {
- ALOGE("Error opening /proc/self/cmdline: %s (%d)", strerror(errno),
- errno);
+ ALOGE("Error opening /proc/self/cmdline: %s (%d)", strerror(errno), errno);
return;
}
char path[1024];
@@ -682,8 +670,7 @@ void CanvasContext::waitOnFences() {
class CanvasContext::FuncTaskProcessor : public TaskProcessor<bool> {
public:
- explicit FuncTaskProcessor(TaskManager* taskManager)
- : TaskProcessor<bool>(taskManager) {}
+ explicit FuncTaskProcessor(TaskManager* taskManager) : TaskProcessor<bool>(taskManager) {}
virtual void onProcess(const sp<Task<bool> >& task) override {
FuncTask* t = static_cast<FuncTask*>(task.get());
@@ -721,8 +708,8 @@ SkRect CanvasContext::computeDirtyRect(const Frame& frame, SkRect* dirty) {
dirty->setEmpty();
} else {
if (!dirty->isEmpty() && !dirty->intersect(0, 0, frame.width(), frame.height())) {
- ALOGW("Dirty " RECT_STRING " doesn't intersect with 0 0 %d %d ?",
- SK_RECT_ARGS(*dirty), frame.width(), frame.height());
+ ALOGW("Dirty " RECT_STRING " doesn't intersect with 0 0 %d %d ?", SK_RECT_ARGS(*dirty),
+ frame.width(), frame.height());
dirty->setEmpty();
}
profiler().unionDirty(dirty);
@@ -742,7 +729,7 @@ SkRect CanvasContext::computeDirtyRect(const Frame& frame, SkRect* dirty) {
// last frame so there's nothing to union() against
// Therefore we only care about the > 1 case.
if (frame.bufferAge() > 1) {
- if (frame.bufferAge() > (int) mSwapHistory.size()) {
+ if (frame.bufferAge() > (int)mSwapHistory.size()) {
// We don't have enough history to handle this old of a buffer
// Just do a full-draw
dirty->set(0, 0, frame.width(), frame.height());
@@ -751,7 +738,7 @@ SkRect CanvasContext::computeDirtyRect(const Frame& frame, SkRect* dirty) {
// to the damage history (happens below)
// So we need to damage
for (int i = mSwapHistory.size() - 1;
- i > ((int) mSwapHistory.size()) - frame.bufferAge(); i--) {
+ i > ((int)mSwapHistory.size()) - frame.bufferAge(); i--) {
dirty->join(mSwapHistory[i].damage);
}
}
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 4a5b2c72b02a..d80a24737a7a 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -27,17 +27,17 @@
#include "IRenderPipeline.h"
#include "LayerUpdateQueue.h"
#include "RenderNode.h"
-#include "thread/Task.h"
-#include "thread/TaskProcessor.h"
#include "renderthread/RenderTask.h"
#include "renderthread/RenderThread.h"
+#include "thread/Task.h"
+#include "thread/TaskProcessor.h"
-#include <cutils/compiler.h>
#include <EGL/egl.h>
#include <SkBitmap.h>
#include <SkRect.h>
-#include <utils/Functor.h>
+#include <cutils/compiler.h>
#include <gui/Surface.h>
+#include <utils/Functor.h>
#include <functional>
#include <set>
@@ -63,8 +63,8 @@ class Frame;
// TODO: Rename to Renderer or some other per-window, top-level manager
class CanvasContext : public IFrameCallback {
public:
- static CanvasContext* create(RenderThread& thread, bool translucent,
- RenderNode* rootRenderNode, IContextFactory* contextFactory);
+ static CanvasContext* create(RenderThread& thread, bool translucent, RenderNode* rootRenderNode,
+ IContextFactory* contextFactory);
virtual ~CanvasContext();
/**
@@ -89,9 +89,7 @@ public:
bool pinImages(std::vector<SkImage*>& mutableImages) {
return mRenderPipeline->pinImages(mutableImages);
}
- bool pinImages(LsaVector<sk_sp<Bitmap>>& images) {
- return mRenderPipeline->pinImages(images);
- }
+ bool pinImages(LsaVector<sk_sp<Bitmap>>& images) { return mRenderPipeline->pinImages(images); }
/**
* Unpin any image that had be previously pinned to the GPU cache
@@ -117,20 +115,17 @@ public:
// Won't take effect until next EGLSurface creation
void setSwapBehavior(SwapBehavior swapBehavior);
- void initialize(Surface* surface);
- void updateSurface(Surface* surface);
- bool pauseSurface(Surface* surface);
+ void setSurface(sp<Surface>&& surface);
+ bool pauseSurface();
void setStopped(bool stopped);
bool hasSurface() { return mNativeSurface.get(); }
- void setup(float lightRadius,
- uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
+ void setup(float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
void setLightCenter(const Vector3& lightCenter);
void setOpaque(bool opaque);
void setWideGamut(bool wideGamut);
bool makeCurrent();
- void prepareTree(TreeInfo& info, int64_t* uiFrameInfo,
- int64_t syncQueued, RenderNode* target);
+ void prepareTree(TreeInfo& info, int64_t* uiFrameInfo, int64_t syncQueued, RenderNode* target);
void draw();
void destroy();
@@ -162,13 +157,9 @@ public:
void addRenderNode(RenderNode* node, bool placeFront);
void removeRenderNode(RenderNode* node);
- void setContentDrawBounds(const Rect& bounds) {
- mContentDrawBounds = bounds;
- }
+ void setContentDrawBounds(const Rect& bounds) { mContentDrawBounds = bounds; }
- RenderState& getRenderState() {
- return mRenderThread.renderState();
- }
+ RenderState& getRenderState() { return mRenderThread.renderState(); }
void addFrameMetricsObserver(FrameMetricsObserver* observer) {
if (mFrameMetricsReporter.get() == nullptr) {
@@ -198,15 +189,13 @@ public:
private:
CanvasContext(RenderThread& thread, bool translucent, RenderNode* rootRenderNode,
- IContextFactory* contextFactory, std::unique_ptr<IRenderPipeline> renderPipeline);
+ IContextFactory* contextFactory, std::unique_ptr<IRenderPipeline> renderPipeline);
friend class RegisterFrameCallbackTask;
// TODO: Replace with something better for layer & other GL object
// lifecycle tracking
friend class android::uirenderer::RenderState;
- void setSurface(Surface* window);
-
void freePrefetchedLayers();
bool isSwapChainStuffed();
@@ -242,14 +231,14 @@ private:
bool mOpaque;
bool mWideColorGamut = false;
BakedOpRenderer::LightInfo mLightInfo;
- FrameBuilder::LightGeometry mLightGeometry = { {0, 0, 0}, 0 };
+ FrameBuilder::LightGeometry mLightGeometry = {{0, 0, 0}, 0};
bool mHaveNewSurface = false;
DamageAccumulator mDamageAccumulator;
LayerUpdateQueue mLayerUpdateQueue;
std::unique_ptr<AnimationContext> mAnimationContext;
- std::vector< sp<RenderNode> > mRenderNodes;
+ std::vector<sp<RenderNode>> mRenderNodes;
FrameInfo* mCurrentFrameInfo = nullptr;
std::string mName;
@@ -269,8 +258,8 @@ private:
};
class FuncTaskProcessor;
- std::vector< sp<FuncTask> > mFrameFences;
- sp<TaskProcessor<bool> > mFrameWorkProcessor;
+ std::vector<sp<FuncTask>> mFrameFences;
+ sp<TaskProcessor<bool>> mFrameWorkProcessor;
std::unique_ptr<IRenderPipeline> mRenderPipeline;
};
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index a097272df359..8372331c0352 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -33,21 +33,20 @@ DrawFrameTask::DrawFrameTask()
: mRenderThread(nullptr)
, mContext(nullptr)
, mContentDrawBounds(0, 0, 0, 0)
- , mSyncResult(SyncResult::OK) {
-}
+ , mSyncResult(SyncResult::OK) {}
-DrawFrameTask::~DrawFrameTask() {
-}
+DrawFrameTask::~DrawFrameTask() {}
void DrawFrameTask::setContext(RenderThread* thread, CanvasContext* context,
- RenderNode* targetNode) {
+ RenderNode* targetNode) {
mRenderThread = thread;
mContext = context;
mTargetNode = targetNode;
}
void DrawFrameTask::pushLayerUpdate(DeferredLayerUpdater* layer) {
- LOG_ALWAYS_FATAL_IF(!mContext, "Lifecycle violation, there's no context to pushLayerUpdate with!");
+ LOG_ALWAYS_FATAL_IF(!mContext,
+ "Lifecycle violation, there's no context to pushLayerUpdate with!");
for (size_t i = 0; i < mLayers.size(); i++) {
if (mLayers[i].get() == layer) {
@@ -78,7 +77,7 @@ int DrawFrameTask::drawFrame() {
void DrawFrameTask::postAndWait() {
AutoMutex _lock(mLock);
- mRenderThread->queue(this);
+ mRenderThread->queue().post([this]() { run(); });
mSignal.wait(mLock);
}
diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h
index 83ecb98f548f..ea51ae4a42b7 100644
--- a/libs/hwui/renderthread/DrawFrameTask.h
+++ b/libs/hwui/renderthread/DrawFrameTask.h
@@ -24,8 +24,8 @@
#include "RenderTask.h"
-#include "../Rect.h"
#include "../FrameInfo.h"
+#include "../Rect.h"
#include "../TreeInfo.h"
namespace android {
@@ -55,7 +55,7 @@ enum {
* tracked across many frames not just a single frame.
* It is the sync-state task, and will kick off the post-sync draw
*/
-class DrawFrameTask : public RenderTask {
+class DrawFrameTask {
public:
DrawFrameTask();
virtual ~DrawFrameTask();
@@ -72,7 +72,7 @@ public:
int64_t* frameInfo() { return mFrameInfo; }
- virtual void run() override;
+ void run();
private:
void postAndWait();
@@ -90,7 +90,7 @@ private:
/*********************************************
* Single frame data
*********************************************/
- std::vector< sp<DeferredLayerUpdater> > mLayers;
+ std::vector<sp<DeferredLayerUpdater> > mLayers;
int mSyncResult;
int64_t mSyncQueued;
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index bd4708da562a..5b87e1013baf 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -18,17 +18,17 @@
#include <string>
-#include "utils/StringUtils.h"
#include <cutils/properties.h>
#include <log/log.h>
+#include "utils/StringUtils.h"
#include "Caches.h"
#include "DeviceInfo.h"
#include "Frame.h"
#include "Properties.h"
#include "RenderThread.h"
-#include "renderstate/RenderState.h"
#include "Texture.h"
+#include "renderstate/RenderState.h"
#include <EGL/eglext.h>
#include <GrContextOptions.h>
@@ -47,7 +47,9 @@ namespace android {
namespace uirenderer {
namespace renderthread {
-#define ERROR_CASE(x) case x: return #x;
+#define ERROR_CASE(x) \
+ case x: \
+ return #x;
static const char* egl_error_str(EGLint error) {
switch (error) {
ERROR_CASE(EGL_SUCCESS)
@@ -65,8 +67,8 @@ static const char* egl_error_str(EGLint error) {
ERROR_CASE(EGL_BAD_PARAMETER)
ERROR_CASE(EGL_BAD_SURFACE)
ERROR_CASE(EGL_CONTEXT_LOST)
- default:
- return "Unknown error";
+ default:
+ return "Unknown error";
}
}
const char* EglManager::eglErrorString() {
@@ -89,8 +91,7 @@ EglManager::EglManager(RenderThread& thread)
, mEglConfigWideGamut(nullptr)
, mEglContext(EGL_NO_CONTEXT)
, mPBufferSurface(EGL_NO_SURFACE)
- , mCurrentSurface(EGL_NO_SURFACE) {
-}
+ , mCurrentSurface(EGL_NO_SURFACE) {}
void EglManager::initialize() {
if (hasEglContext()) return;
@@ -98,12 +99,12 @@ void EglManager::initialize() {
ATRACE_NAME("Creating EGLContext");
mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- LOG_ALWAYS_FATAL_IF(mEglDisplay == EGL_NO_DISPLAY,
- "Failed to get EGL_DEFAULT_DISPLAY! err=%s", eglErrorString());
+ LOG_ALWAYS_FATAL_IF(mEglDisplay == EGL_NO_DISPLAY, "Failed to get EGL_DEFAULT_DISPLAY! err=%s",
+ eglErrorString());
EGLint major, minor;
LOG_ALWAYS_FATAL_IF(eglInitialize(mEglDisplay, &major, &minor) == EGL_FALSE,
- "Failed to initialize display %p! err=%s", mEglDisplay, eglErrorString());
+ "Failed to initialize display %p! err=%s", mEglDisplay, eglErrorString());
ALOGI("Initialized EGL, version %d.%d", (int)major, (int)minor);
@@ -138,26 +139,26 @@ void EglManager::initialize() {
LOG_ALWAYS_FATAL_IF(!glInterface.get());
GrContextOptions options;
- options.fGpuPathRenderers &= ~GrContextOptions::GpuPathRenderers::kDistanceField;
+ options.fDisableDistanceFieldPaths = true;
mRenderThread.cacheManager().configureContext(&options);
- mRenderThread.setGrContext(GrContext::Create(GrBackend::kOpenGL_GrBackend,
- (GrBackendContext)glInterface.get(), options));
+ sk_sp<GrContext> grContext(GrContext::MakeGL(std::move(glInterface), options));
+ LOG_ALWAYS_FATAL_IF(!grContext.get());
+ mRenderThread.setGrContext(grContext);
}
}
void EglManager::initExtensions() {
- auto extensions = StringUtils::split(
- eglQueryString(mEglDisplay, EGL_EXTENSIONS));
+ auto extensions = StringUtils::split(eglQueryString(mEglDisplay, EGL_EXTENSIONS));
// For our purposes we don't care if EGL_BUFFER_AGE is a result of
// EGL_EXT_buffer_age or EGL_KHR_partial_update as our usage is covered
// under EGL_KHR_partial_update and we don't need the expanded scope
// that EGL_EXT_buffer_age provides.
- EglExtensions.bufferAge = extensions.has("EGL_EXT_buffer_age")
- || extensions.has("EGL_KHR_partial_update");
+ EglExtensions.bufferAge =
+ extensions.has("EGL_EXT_buffer_age") || extensions.has("EGL_KHR_partial_update");
EglExtensions.setDamage = extensions.has("EGL_KHR_partial_update");
LOG_ALWAYS_FATAL_IF(!extensions.has("EGL_KHR_swap_buffers_with_damage"),
- "Missing required extension EGL_KHR_swap_buffers_with_damage");
+ "Missing required extension EGL_KHR_swap_buffers_with_damage");
EglExtensions.glColorSpace = extensions.has("EGL_KHR_gl_colorspace");
EglExtensions.noConfigContext = extensions.has("EGL_KHR_no_config_context");
@@ -175,30 +176,37 @@ bool EglManager::hasEglContext() {
void EglManager::loadConfigs() {
ALOGD("Swap behavior %d", static_cast<int>(mSwapBehavior));
- EGLint swapBehavior = (mSwapBehavior == SwapBehavior::Preserved)
- ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0;
- EGLint attribs[] = {
- EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
- EGL_RED_SIZE, 8,
- EGL_GREEN_SIZE, 8,
- EGL_BLUE_SIZE, 8,
- EGL_ALPHA_SIZE, 8,
- EGL_DEPTH_SIZE, 0,
- EGL_CONFIG_CAVEAT, EGL_NONE,
- EGL_STENCIL_SIZE, Stencil::getStencilSize(),
- EGL_SURFACE_TYPE, EGL_WINDOW_BIT | swapBehavior,
- EGL_NONE
- };
+ EGLint swapBehavior =
+ (mSwapBehavior == SwapBehavior::Preserved) ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0;
+ EGLint attribs[] = {EGL_RENDERABLE_TYPE,
+ EGL_OPENGL_ES2_BIT,
+ EGL_RED_SIZE,
+ 8,
+ EGL_GREEN_SIZE,
+ 8,
+ EGL_BLUE_SIZE,
+ 8,
+ EGL_ALPHA_SIZE,
+ 8,
+ EGL_DEPTH_SIZE,
+ 0,
+ EGL_CONFIG_CAVEAT,
+ EGL_NONE,
+ EGL_STENCIL_SIZE,
+ Stencil::getStencilSize(),
+ EGL_SURFACE_TYPE,
+ EGL_WINDOW_BIT | swapBehavior,
+ EGL_NONE};
EGLint numConfigs = 1;
- if (!eglChooseConfig(mEglDisplay, attribs, &mEglConfig, numConfigs, &numConfigs)
- || numConfigs != 1) {
+ if (!eglChooseConfig(mEglDisplay, attribs, &mEglConfig, numConfigs, &numConfigs) ||
+ numConfigs != 1) {
if (mSwapBehavior == SwapBehavior::Preserved) {
// Try again without dirty regions enabled
ALOGW("Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...");
mSwapBehavior = SwapBehavior::Discard;
loadConfigs();
- return; // the call to loadConfigs() we just made picks the wide gamut config
+ return; // the call to loadConfigs() we just made picks the wide gamut config
} else {
// Failed to get a valid config
LOG_ALWAYS_FATAL("Failed to choose config, error = %s", eglErrorString());
@@ -207,22 +215,30 @@ void EglManager::loadConfigs() {
if (EglExtensions.pixelFormatFloat) {
// If we reached this point, we have a valid swap behavior
- EGLint attribs16F[] = {
- EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
- EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT,
- EGL_RED_SIZE, 16,
- EGL_GREEN_SIZE, 16,
- EGL_BLUE_SIZE, 16,
- EGL_ALPHA_SIZE, 16,
- EGL_DEPTH_SIZE, 0,
- EGL_STENCIL_SIZE, Stencil::getStencilSize(),
- EGL_SURFACE_TYPE, EGL_WINDOW_BIT | swapBehavior,
- EGL_NONE
- };
+ EGLint attribs16F[] = {EGL_RENDERABLE_TYPE,
+ EGL_OPENGL_ES2_BIT,
+ EGL_COLOR_COMPONENT_TYPE_EXT,
+ EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT,
+ EGL_RED_SIZE,
+ 16,
+ EGL_GREEN_SIZE,
+ 16,
+ EGL_BLUE_SIZE,
+ 16,
+ EGL_ALPHA_SIZE,
+ 16,
+ EGL_DEPTH_SIZE,
+ 0,
+ EGL_STENCIL_SIZE,
+ Stencil::getStencilSize(),
+ EGL_SURFACE_TYPE,
+ EGL_WINDOW_BIT | swapBehavior,
+ EGL_NONE};
numConfigs = 1;
- if (!eglChooseConfig(mEglDisplay, attribs16F, &mEglConfigWideGamut, numConfigs, &numConfigs)
- || numConfigs != 1) {
+ if (!eglChooseConfig(mEglDisplay, attribs16F, &mEglConfigWideGamut, numConfigs,
+ &numConfigs) ||
+ numConfigs != 1) {
ALOGE("Device claims wide gamut support, cannot find matching config, error = %s",
eglErrorString());
EglExtensions.pixelFormatFloat = false;
@@ -231,23 +247,20 @@ void EglManager::loadConfigs() {
}
void EglManager::createContext() {
- EGLint attribs[] = {
- EGL_CONTEXT_CLIENT_VERSION, GLES_VERSION,
- EGL_NONE
- };
- mEglContext = eglCreateContext(mEglDisplay,
- EglExtensions.noConfigContext ? ((EGLConfig) nullptr) : mEglConfig,
+ EGLint attribs[] = {EGL_CONTEXT_CLIENT_VERSION, GLES_VERSION, EGL_NONE};
+ mEglContext = eglCreateContext(
+ mEglDisplay, EglExtensions.noConfigContext ? ((EGLConfig) nullptr) : mEglConfig,
EGL_NO_CONTEXT, attribs);
- LOG_ALWAYS_FATAL_IF(mEglContext == EGL_NO_CONTEXT,
- "Failed to create context, error = %s", eglErrorString());
+ LOG_ALWAYS_FATAL_IF(mEglContext == EGL_NO_CONTEXT, "Failed to create context, error = %s",
+ eglErrorString());
}
void EglManager::createPBufferSurface() {
LOG_ALWAYS_FATAL_IF(mEglDisplay == EGL_NO_DISPLAY,
- "usePBufferSurface() called on uninitialized GlobalContext!");
+ "usePBufferSurface() called on uninitialized GlobalContext!");
if (mPBufferSurface == EGL_NO_SURFACE) {
- EGLint attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE };
+ EGLint attribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE};
mPBufferSurface = eglCreatePbufferSurface(mEglDisplay, mEglConfig, attribs);
}
}
@@ -255,8 +268,8 @@ void EglManager::createPBufferSurface() {
EGLSurface EglManager::createSurface(EGLNativeWindowType window, bool wideColorGamut) {
initialize();
- wideColorGamut = wideColorGamut && EglExtensions.glColorSpace && EglExtensions.scRGB
- && EglExtensions.pixelFormatFloat && EglExtensions.noConfigContext;
+ wideColorGamut = wideColorGamut && EglExtensions.glColorSpace && EglExtensions.scRGB &&
+ EglExtensions.pixelFormatFloat && EglExtensions.noConfigContext;
// The color space we want to use depends on whether linear blending is turned
// on and whether the app has requested wide color gamut rendering. When wide
@@ -280,10 +293,7 @@ EGLSurface EglManager::createSurface(EGLNativeWindowType window, bool wideColorG
// We insert to placeholders to set EGL_GL_COLORSPACE_KHR and its value.
// According to section 3.4.1 of the EGL specification, the attributes
// list is considered empty if the first entry is EGL_NONE
- EGLint attribs[] = {
- EGL_NONE, EGL_NONE,
- EGL_NONE
- };
+ EGLint attribs[] = {EGL_NONE, EGL_NONE, EGL_NONE};
if (EglExtensions.glColorSpace) {
attribs[0] = EGL_GL_COLORSPACE_KHR;
@@ -302,16 +312,17 @@ EGLSurface EglManager::createSurface(EGLNativeWindowType window, bool wideColorG
#endif
}
- EGLSurface surface = eglCreateWindowSurface(mEglDisplay,
- wideColorGamut ? mEglConfigWideGamut : mEglConfig, window, attribs);
+ EGLSurface surface = eglCreateWindowSurface(
+ mEglDisplay, wideColorGamut ? mEglConfigWideGamut : mEglConfig, window, attribs);
LOG_ALWAYS_FATAL_IF(surface == EGL_NO_SURFACE,
- "Failed to create EGLSurface for window %p, eglErr = %s",
- (void*) window, eglErrorString());
+ "Failed to create EGLSurface for window %p, eglErr = %s", (void*)window,
+ eglErrorString());
if (mSwapBehavior != SwapBehavior::Preserved) {
- LOG_ALWAYS_FATAL_IF(eglSurfaceAttrib(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED) == EGL_FALSE,
+ LOG_ALWAYS_FATAL_IF(eglSurfaceAttrib(mEglDisplay, surface, EGL_SWAP_BEHAVIOR,
+ EGL_BUFFER_DESTROYED) == EGL_FALSE,
"Failed to set swap behavior to destroyed for window %p, eglErr = %s",
- (void*) window, eglErrorString());
+ (void*)window, eglErrorString());
}
return surface;
@@ -353,11 +364,11 @@ bool EglManager::makeCurrent(EGLSurface surface, EGLint* errOut) {
if (!eglMakeCurrent(mEglDisplay, surface, surface, mEglContext)) {
if (errOut) {
*errOut = eglGetError();
- ALOGW("Failed to make current on surface %p, error=%s",
- (void*)surface, egl_error_str(*errOut));
+ ALOGW("Failed to make current on surface %p, error=%s", (void*)surface,
+ egl_error_str(*errOut));
} else {
- LOG_ALWAYS_FATAL("Failed to make current on surface %p, error=%s",
- (void*)surface, eglErrorString());
+ LOG_ALWAYS_FATAL("Failed to make current on surface %p, error=%s", (void*)surface,
+ eglErrorString());
}
}
mCurrentSurface = surface;
@@ -369,21 +380,20 @@ bool EglManager::makeCurrent(EGLSurface surface, EGLint* errOut) {
EGLint EglManager::queryBufferAge(EGLSurface surface) {
switch (mSwapBehavior) {
- case SwapBehavior::Discard:
- return 0;
- case SwapBehavior::Preserved:
- return 1;
- case SwapBehavior::BufferAge:
- EGLint bufferAge;
- eglQuerySurface(mEglDisplay, surface, EGL_BUFFER_AGE_EXT, &bufferAge);
- return bufferAge;
+ case SwapBehavior::Discard:
+ return 0;
+ case SwapBehavior::Preserved:
+ return 1;
+ case SwapBehavior::BufferAge:
+ EGLint bufferAge;
+ eglQuerySurface(mEglDisplay, surface, EGL_BUFFER_AGE_EXT, &bufferAge);
+ return bufferAge;
}
return 0;
}
Frame EglManager::beginFrame(EGLSurface surface) {
- LOG_ALWAYS_FATAL_IF(surface == EGL_NO_SURFACE,
- "Tried to beginFrame on EGL_NO_SURFACE!");
+ LOG_ALWAYS_FATAL_IF(surface == EGL_NO_SURFACE, "Tried to beginFrame on EGL_NO_SURFACE!");
makeCurrent(surface);
Frame frame;
frame.mSurface = surface;
@@ -401,7 +411,7 @@ void EglManager::damageFrame(const Frame& frame, const SkRect& dirty) {
frame.map(dirty, rects);
if (!eglSetDamageRegionKHR(mEglDisplay, frame.mSurface, rects, 1)) {
LOG_ALWAYS_FATAL("Failed to set damage region on surface %p, error=%s",
- (void*)frame.mSurface, eglErrorString());
+ (void*)frame.mSurface, eglErrorString());
}
}
#endif
@@ -412,7 +422,6 @@ bool EglManager::damageRequiresSwap() {
}
bool EglManager::swapBuffers(const Frame& frame, const SkRect& screenDirty) {
-
if (CC_UNLIKELY(Properties::waitForGpuCompletion)) {
ATRACE_NAME("Finishing GPU work");
fence();
@@ -420,8 +429,7 @@ bool EglManager::swapBuffers(const Frame& frame, const SkRect& screenDirty) {
EGLint rects[4];
frame.map(screenDirty, rects);
- eglSwapBuffersWithDamageKHR(mEglDisplay, frame.mSurface, rects,
- screenDirty.isEmpty() ? 0 : 1);
+ eglSwapBuffersWithDamageKHR(mEglDisplay, frame.mSurface, rects, screenDirty.isEmpty() ? 0 : 1);
EGLint err = eglGetError();
if (CC_LIKELY(err == EGL_SUCCESS)) {
@@ -431,20 +439,18 @@ bool EglManager::swapBuffers(const Frame& frame, const SkRect& screenDirty) {
// For some reason our surface was destroyed out from under us
// This really shouldn't happen, but if it does we can recover easily
// by just not trying to use the surface anymore
- ALOGW("swapBuffers encountered EGL error %d on %p, halting rendering...",
- err, frame.mSurface);
+ ALOGW("swapBuffers encountered EGL error %d on %p, halting rendering...", err,
+ frame.mSurface);
return false;
}
- LOG_ALWAYS_FATAL("Encountered EGL error %d %s during rendering",
- err, egl_error_str(err));
+ LOG_ALWAYS_FATAL("Encountered EGL error %d %s during rendering", err, egl_error_str(err));
// Impossible to hit this, but the compiler doesn't know that
return false;
}
void EglManager::fence() {
EGLSyncKHR fence = eglCreateSyncKHR(mEglDisplay, EGL_SYNC_FENCE_KHR, NULL);
- eglClientWaitSyncKHR(mEglDisplay, fence,
- EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, EGL_FOREVER_KHR);
+ eglClientWaitSyncKHR(mEglDisplay, fence, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, EGL_FOREVER_KHR);
eglDestroySyncKHR(mEglDisplay, fence);
}
@@ -452,17 +458,17 @@ bool EglManager::setPreserveBuffer(EGLSurface surface, bool preserve) {
if (mSwapBehavior != SwapBehavior::Preserved) return false;
bool preserved = eglSurfaceAttrib(mEglDisplay, surface, EGL_SWAP_BEHAVIOR,
- preserve ? EGL_BUFFER_PRESERVED : EGL_BUFFER_DESTROYED);
+ preserve ? EGL_BUFFER_PRESERVED : EGL_BUFFER_DESTROYED);
if (!preserved) {
- ALOGW("Failed to set EGL_SWAP_BEHAVIOR on surface %p, error=%s",
- (void*) surface, eglErrorString());
+ ALOGW("Failed to set EGL_SWAP_BEHAVIOR on surface %p, error=%s", (void*)surface,
+ eglErrorString());
// Maybe it's already set?
EGLint swapBehavior;
if (eglQuerySurface(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, &swapBehavior)) {
preserved = (swapBehavior == EGL_BUFFER_PRESERVED);
} else {
- ALOGW("Failed to query EGL_SWAP_BEHAVIOR on surface %p, error=%p",
- (void*) surface, eglErrorString());
+ ALOGW("Failed to query EGL_SWAP_BEHAVIOR on surface %p, error=%p", (void*)surface,
+ eglErrorString());
}
}
diff --git a/libs/hwui/renderthread/EglManager.h b/libs/hwui/renderthread/EglManager.h
index 2982c23552c9..ef9effbf9953 100644
--- a/libs/hwui/renderthread/EglManager.h
+++ b/libs/hwui/renderthread/EglManager.h
@@ -16,9 +16,9 @@
#ifndef EGLMANAGER_H
#define EGLMANAGER_H
-#include <cutils/compiler.h>
#include <EGL/egl.h>
#include <SkRect.h>
+#include <cutils/compiler.h>
#include <ui/GraphicBuffer.h>
#include <utils/StrongPointer.h>
diff --git a/libs/hwui/renderthread/Frame.h b/libs/hwui/renderthread/Frame.h
index 99996fe40626..d266faa4f7c9 100644
--- a/libs/hwui/renderthread/Frame.h
+++ b/libs/hwui/renderthread/Frame.h
@@ -19,7 +19,7 @@
#include <stdint.h>
struct SkRect;
-typedef void *EGLSurface;
+typedef void* EGLSurface;
namespace android {
namespace uirenderer {
@@ -28,9 +28,7 @@ namespace renderthread {
class Frame {
public:
Frame(int32_t width, int32_t height, int32_t bufferAge)
- : mWidth(width)
- , mHeight(height)
- , mBufferAge(bufferAge) { }
+ : mWidth(width), mHeight(height), mBufferAge(bufferAge) {}
int32_t width() const { return mWidth; }
int32_t height() const { return mHeight; }
@@ -57,4 +55,3 @@ private:
} /* namespace renderthread */
} /* namespace uirenderer */
} /* namespace android */
-
diff --git a/libs/hwui/renderthread/IRenderPipeline.h b/libs/hwui/renderthread/IRenderPipeline.h
index f9b6e384d211..246ab269b838 100644
--- a/libs/hwui/renderthread/IRenderPipeline.h
+++ b/libs/hwui/renderthread/IRenderPipeline.h
@@ -17,6 +17,7 @@
#pragma once
#include "FrameInfoVisualizer.h"
+#include "SwapBehavior.h"
#include <SkRect.h>
#include <utils/RefBase.h>
@@ -33,16 +34,7 @@ class DeferredLayerUpdater;
namespace renderthread {
-enum class SwapBehavior {
- kSwap_default,
- kSwap_discardBuffer,
-};
-
-enum class MakeCurrentResult {
- AlreadyCurrent,
- Failed,
- Succeeded
-};
+enum class MakeCurrentResult { AlreadyCurrent, Failed, Succeeded };
enum class ColorMode {
Srgb,
@@ -57,14 +49,13 @@ public:
virtual MakeCurrentResult makeCurrent() = 0;
virtual Frame getFrame() = 0;
virtual bool draw(const Frame& frame, const SkRect& screenDirty, const SkRect& dirty,
- const FrameBuilder::LightGeometry& lightGeometry,
- LayerUpdateQueue* layerUpdateQueue,
- const Rect& contentDrawBounds, bool opaque, bool wideColorGamut,
- const BakedOpRenderer::LightInfo& lightInfo,
- const std::vector< sp<RenderNode> >& renderNodes,
- FrameInfoVisualizer* profiler) = 0;
+ const FrameBuilder::LightGeometry& lightGeometry,
+ LayerUpdateQueue* layerUpdateQueue, const Rect& contentDrawBounds,
+ bool opaque, bool wideColorGamut, const BakedOpRenderer::LightInfo& lightInfo,
+ const std::vector<sp<RenderNode>>& renderNodes,
+ FrameInfoVisualizer* profiler) = 0;
virtual bool swapBuffers(const Frame& frame, bool drew, const SkRect& screenDirty,
- FrameInfo* currentFrameInfo, bool* requireSwap) = 0;
+ FrameInfo* currentFrameInfo, bool* requireSwap) = 0;
virtual bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) = 0;
virtual DeferredLayerUpdater* createTextureLayer() = 0;
virtual bool setSurface(Surface* window, SwapBehavior swapBehavior, ColorMode colorMode) = 0;
@@ -73,14 +64,15 @@ public:
virtual bool isContextReady() = 0;
virtual void onDestroyHardwareResources() = 0;
virtual void renderLayers(const FrameBuilder::LightGeometry& lightGeometry,
- LayerUpdateQueue* layerUpdateQueue, bool opaque, bool wideColorGamut,
- const BakedOpRenderer::LightInfo& lightInfo) = 0;
+ LayerUpdateQueue* layerUpdateQueue, bool opaque, bool wideColorGamut,
+ const BakedOpRenderer::LightInfo& lightInfo) = 0;
virtual TaskManager* getTaskManager() = 0;
- virtual bool createOrUpdateLayer(RenderNode* node,
- const DamageAccumulator& damageAccumulator, bool wideColorGamut) = 0;
+ virtual bool createOrUpdateLayer(RenderNode* node, const DamageAccumulator& damageAccumulator,
+ bool wideColorGamut) = 0;
virtual bool pinImages(std::vector<SkImage*>& mutableImages) = 0;
virtual bool pinImages(LsaVector<sk_sp<Bitmap>>& images) = 0;
virtual void unpinImages() = 0;
+ virtual void onPrepareTree() = 0;
virtual ~IRenderPipeline() {}
};
diff --git a/libs/hwui/renderthread/OpenGLPipeline.cpp b/libs/hwui/renderthread/OpenGLPipeline.cpp
index 7283eb123d6a..f3103fd0cbb4 100644
--- a/libs/hwui/renderthread/OpenGLPipeline.cpp
+++ b/libs/hwui/renderthread/OpenGLPipeline.cpp
@@ -20,9 +20,9 @@
#include "EglManager.h"
#include "Frame.h"
#include "GlLayer.h"
+#include "OpenGLReadback.h"
#include "ProfileRenderer.h"
#include "renderstate/RenderState.h"
-#include "OpenGLReadback.h"
#include <cutils/properties.h>
#include <strings.h>
@@ -32,9 +32,7 @@ namespace uirenderer {
namespace renderthread {
OpenGLPipeline::OpenGLPipeline(RenderThread& thread)
- : mEglManager(thread.eglManager())
- , mRenderThread(thread) {
-}
+ : mEglManager(thread.eglManager()), mRenderThread(thread) {}
MakeCurrentResult OpenGLPipeline::makeCurrent() {
// TODO: Figure out why this workaround is needed, see b/13913604
@@ -51,23 +49,21 @@ MakeCurrentResult OpenGLPipeline::makeCurrent() {
Frame OpenGLPipeline::getFrame() {
LOG_ALWAYS_FATAL_IF(mEglSurface == EGL_NO_SURFACE,
- "drawRenderNode called on a context with no surface!");
+ "drawRenderNode called on a context with no surface!");
return mEglManager.beginFrame(mEglSurface);
}
bool OpenGLPipeline::draw(const Frame& frame, const SkRect& screenDirty, const SkRect& dirty,
- const FrameBuilder::LightGeometry& lightGeometry,
- LayerUpdateQueue* layerUpdateQueue,
- const Rect& contentDrawBounds, bool opaque, bool wideColorGamut,
- const BakedOpRenderer::LightInfo& lightInfo,
- const std::vector< sp<RenderNode> >& renderNodes,
- FrameInfoVisualizer* profiler) {
-
+ const FrameBuilder::LightGeometry& lightGeometry,
+ LayerUpdateQueue* layerUpdateQueue, const Rect& contentDrawBounds,
+ bool opaque, bool wideColorGamut,
+ const BakedOpRenderer::LightInfo& lightInfo,
+ const std::vector<sp<RenderNode>>& renderNodes,
+ FrameInfoVisualizer* profiler) {
mEglManager.damageFrame(frame, dirty);
bool drew = false;
-
auto& caches = Caches::getInstance();
FrameBuilder frameBuilder(dirty, frame.width(), frame.height(), lightGeometry, caches);
@@ -76,8 +72,8 @@ bool OpenGLPipeline::draw(const Frame& frame, const SkRect& screenDirty, const S
frameBuilder.deferRenderNodeScene(renderNodes, contentDrawBounds);
- BakedOpRenderer renderer(caches, mRenderThread.renderState(),
- opaque, wideColorGamut, lightInfo);
+ BakedOpRenderer renderer(caches, mRenderThread.renderState(), opaque, wideColorGamut,
+ lightInfo);
frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer);
ProfileRenderer profileRenderer(renderer);
profiler->draw(profileRenderer);
@@ -100,8 +96,7 @@ bool OpenGLPipeline::draw(const Frame& frame, const SkRect& screenDirty, const S
}
bool OpenGLPipeline::swapBuffers(const Frame& frame, bool drew, const SkRect& screenDirty,
- FrameInfo* currentFrameInfo, bool* requireSwap) {
-
+ FrameInfo* currentFrameInfo, bool* requireSwap) {
GL_CHECKPOINT(LOW);
// Even if we decided to cancel the frame, from the perspective of jank
@@ -123,13 +118,13 @@ bool OpenGLPipeline::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap
layer->updateTexImage();
layer->apply();
return OpenGLReadbackImpl::copyLayerInto(mRenderThread,
- static_cast<GlLayer&>(*layer->backingLayer()), bitmap);
+ static_cast<GlLayer&>(*layer->backingLayer()), bitmap);
}
static Layer* createLayer(RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight,
- SkColorFilter* colorFilter, int alpha, SkBlendMode mode, bool blend) {
- GlLayer* layer = new GlLayer(renderState, layerWidth, layerHeight, colorFilter, alpha,
- mode, blend);
+ SkColorFilter* colorFilter, int alpha, SkBlendMode mode, bool blend) {
+ GlLayer* layer =
+ new GlLayer(renderState, layerWidth, layerHeight, colorFilter, alpha, mode, blend);
Caches::getInstance().textureState().activateTexture(0);
layer->generateTexture();
return layer;
@@ -147,7 +142,6 @@ void OpenGLPipeline::onStop() {
}
bool OpenGLPipeline::setSurface(Surface* surface, SwapBehavior swapBehavior, ColorMode colorMode) {
-
if (mEglSurface != EGL_NO_SURFACE) {
mEglManager.destroySurface(mEglSurface);
mEglSurface = EGL_NO_SURFACE;
@@ -184,14 +178,16 @@ void OpenGLPipeline::onDestroyHardwareResources() {
}
void OpenGLPipeline::renderLayers(const FrameBuilder::LightGeometry& lightGeometry,
- LayerUpdateQueue* layerUpdateQueue, bool opaque, bool wideColorGamut,
- const BakedOpRenderer::LightInfo& lightInfo) {
- static const std::vector< sp<RenderNode> > emptyNodeList;
+ LayerUpdateQueue* layerUpdateQueue, bool opaque,
+ bool wideColorGamut,
+ const BakedOpRenderer::LightInfo& lightInfo) {
+ static const std::vector<sp<RenderNode>> emptyNodeList;
auto& caches = Caches::getInstance();
FrameBuilder frameBuilder(*layerUpdateQueue, lightGeometry, caches);
layerUpdateQueue->clear();
// TODO: Handle wide color gamut contexts
- BakedOpRenderer renderer(caches, mRenderThread.renderState(), opaque, wideColorGamut, lightInfo);
+ BakedOpRenderer renderer(caches, mRenderThread.renderState(), opaque, wideColorGamut,
+ lightInfo);
LOG_ALWAYS_FATAL_IF(renderer.didDraw(), "shouldn't draw in buildlayer case");
frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer);
}
@@ -205,13 +201,14 @@ static bool layerMatchesWH(OffscreenBuffer* layer, int width, int height) {
}
bool OpenGLPipeline::createOrUpdateLayer(RenderNode* node,
- const DamageAccumulator& damageAccumulator, bool wideColorGamut) {
+ const DamageAccumulator& damageAccumulator,
+ bool wideColorGamut) {
RenderState& renderState = mRenderThread.renderState();
OffscreenBufferPool& layerPool = renderState.layerPool();
bool transformUpdateNeeded = false;
if (node->getLayer() == nullptr) {
- node->setLayer(layerPool.get(renderState,
- node->getWidth(), node->getHeight(), wideColorGamut));
+ node->setLayer(
+ layerPool.get(renderState, node->getWidth(), node->getHeight(), wideColorGamut));
transformUpdateNeeded = true;
} else if (!layerMatchesWH(node->getLayer(), node->getWidth(), node->getHeight())) {
// TODO: remove now irrelevant, currently enqueued damage (respecting damage ordering)
@@ -273,8 +270,7 @@ void OpenGLPipeline::invokeFunctor(const RenderThread& thread, Functor* functor)
class AutoEglFence {
public:
- AutoEglFence(EGLDisplay display)
- : mDisplay(display) {
+ AutoEglFence(EGLDisplay display) : mDisplay(display) {
fence = eglCreateSyncKHR(mDisplay, EGL_SYNC_FENCE_KHR, NULL);
}
@@ -285,17 +281,17 @@ public:
}
EGLSyncKHR fence = EGL_NO_SYNC_KHR;
+
private:
EGLDisplay mDisplay = EGL_NO_DISPLAY;
};
class AutoEglImage {
public:
- AutoEglImage(EGLDisplay display, EGLClientBuffer clientBuffer)
- : mDisplay(display) {
- EGLint imageAttrs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE };
- image = eglCreateImageKHR(display, EGL_NO_CONTEXT,
- EGL_NATIVE_BUFFER_ANDROID, clientBuffer, imageAttrs);
+ AutoEglImage(EGLDisplay display, EGLClientBuffer clientBuffer) : mDisplay(display) {
+ EGLint imageAttrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE};
+ image = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, clientBuffer,
+ imageAttrs);
}
~AutoEglImage() {
@@ -305,21 +301,19 @@ public:
}
EGLImageKHR image = EGL_NO_IMAGE_KHR;
+
private:
EGLDisplay mDisplay = EGL_NO_DISPLAY;
};
class AutoGlTexture {
public:
- AutoGlTexture(uirenderer::Caches& caches)
- : mCaches(caches) {
+ AutoGlTexture(uirenderer::Caches& caches) : mCaches(caches) {
glGenTextures(1, &mTexture);
caches.textureState().bindTexture(mTexture);
}
- ~AutoGlTexture() {
- mCaches.textureState().deleteTexture(mTexture);
- }
+ ~AutoGlTexture() { mCaches.textureState().deleteTexture(mTexture); }
private:
uirenderer::Caches& mCaches;
@@ -327,18 +321,17 @@ private:
};
static bool uploadBitmapToGraphicBuffer(uirenderer::Caches& caches, SkBitmap& bitmap,
- GraphicBuffer& buffer, GLint format, GLint type) {
+ GraphicBuffer& buffer, GLint format, GLint type) {
EGLDisplay display = eglGetCurrentDisplay();
- LOG_ALWAYS_FATAL_IF(display == EGL_NO_DISPLAY,
- "Failed to get EGL_DEFAULT_DISPLAY! err=%s",
- uirenderer::renderthread::EglManager::eglErrorString());
+ LOG_ALWAYS_FATAL_IF(display == EGL_NO_DISPLAY, "Failed to get EGL_DEFAULT_DISPLAY! err=%s",
+ uirenderer::renderthread::EglManager::eglErrorString());
// We use an EGLImage to access the content of the GraphicBuffer
// The EGL image is later bound to a 2D texture
- EGLClientBuffer clientBuffer = (EGLClientBuffer) buffer.getNativeBuffer();
+ EGLClientBuffer clientBuffer = (EGLClientBuffer)buffer.getNativeBuffer();
AutoEglImage autoImage(display, clientBuffer);
if (autoImage.image == EGL_NO_IMAGE_KHR) {
ALOGW("Could not create EGL image, err =%s",
- uirenderer::renderthread::EglManager::eglErrorString());
+ uirenderer::renderthread::EglManager::eglErrorString());
return false;
}
AutoGlTexture glTexture(caches);
@@ -346,8 +339,8 @@ static bool uploadBitmapToGraphicBuffer(uirenderer::Caches& caches, SkBitmap& bi
GL_CHECKPOINT(MODERATE);
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bitmap.width(), bitmap.height(),
- format, type, bitmap.getPixels());
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bitmap.width(), bitmap.height(), format, type,
+ bitmap.getPixels());
GL_CHECKPOINT(MODERATE);
@@ -362,7 +355,7 @@ static bool uploadBitmapToGraphicBuffer(uirenderer::Caches& caches, SkBitmap& bi
// The flag EGL_SYNC_FLUSH_COMMANDS_BIT_KHR will trigger a
// pipeline flush (similar to what a glFlush() would do.)
EGLint waitStatus = eglClientWaitSyncKHR(display, autoFence.fence,
- EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, FENCE_TIMEOUT);
+ EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, FENCE_TIMEOUT);
if (waitStatus != EGL_CONDITION_SATISFIED_KHR) {
LOG_ALWAYS_FATAL("Failed to wait for the fence %#x", eglGetError());
return false;
@@ -373,24 +366,24 @@ static bool uploadBitmapToGraphicBuffer(uirenderer::Caches& caches, SkBitmap& bi
// TODO: handle SRGB sanely
static PixelFormat internalFormatToPixelFormat(GLint internalFormat) {
switch (internalFormat) {
- case GL_LUMINANCE:
- return PIXEL_FORMAT_RGBA_8888;
- case GL_SRGB8_ALPHA8:
- return PIXEL_FORMAT_RGBA_8888;
- case GL_RGBA:
- return PIXEL_FORMAT_RGBA_8888;
- case GL_RGB:
- return PIXEL_FORMAT_RGB_565;
- case GL_RGBA16F:
- return PIXEL_FORMAT_RGBA_FP16;
- default:
- LOG_ALWAYS_FATAL("Unsupported bitmap colorType: %d", internalFormat);
- return PIXEL_FORMAT_UNKNOWN;
+ case GL_LUMINANCE:
+ return PIXEL_FORMAT_RGBA_8888;
+ case GL_SRGB8_ALPHA8:
+ return PIXEL_FORMAT_RGBA_8888;
+ case GL_RGBA:
+ return PIXEL_FORMAT_RGBA_8888;
+ case GL_RGB:
+ return PIXEL_FORMAT_RGB_565;
+ case GL_RGBA16F:
+ return PIXEL_FORMAT_RGBA_FP16;
+ default:
+ LOG_ALWAYS_FATAL("Unsupported bitmap colorType: %d", internalFormat);
+ return PIXEL_FORMAT_UNKNOWN;
}
}
sk_sp<Bitmap> OpenGLPipeline::allocateHardwareBitmap(RenderThread& renderThread,
- SkBitmap& skBitmap) {
+ SkBitmap& skBitmap) {
renderThread.eglManager().initialize();
uirenderer::Caches& caches = uirenderer::Caches::getInstance();
@@ -404,13 +397,14 @@ sk_sp<Bitmap> OpenGLPipeline::allocateHardwareBitmap(RenderThread& renderThread,
bool hasLinearBlending = caches.extensions().hasLinearBlending();
GLint format, type, internalFormat;
uirenderer::Texture::colorTypeToGlFormatAndType(caches, skBitmap.colorType(),
- needSRGB && hasLinearBlending, &internalFormat, &format, &type);
+ needSRGB && hasLinearBlending, &internalFormat,
+ &format, &type);
PixelFormat pixelFormat = internalFormatToPixelFormat(internalFormat);
- sp<GraphicBuffer> buffer = new GraphicBuffer(info.width(), info.height(), pixelFormat,
- GraphicBuffer::USAGE_HW_TEXTURE |
- GraphicBuffer::USAGE_SW_WRITE_NEVER |
- GraphicBuffer::USAGE_SW_READ_NEVER,
+ sp<GraphicBuffer> buffer = new GraphicBuffer(
+ info.width(), info.height(), pixelFormat,
+ GraphicBuffer::USAGE_HW_TEXTURE | GraphicBuffer::USAGE_SW_WRITE_NEVER |
+ GraphicBuffer::USAGE_SW_READ_NEVER,
std::string("Bitmap::allocateHardwareBitmap pid [") + std::to_string(getpid()) + "]");
status_t error = buffer->initCheck();
@@ -420,8 +414,8 @@ sk_sp<Bitmap> OpenGLPipeline::allocateHardwareBitmap(RenderThread& renderThread,
}
SkBitmap bitmap;
- if (CC_UNLIKELY(uirenderer::Texture::hasUnsupportedColorType(skBitmap.info(),
- hasLinearBlending))) {
+ if (CC_UNLIKELY(
+ uirenderer::Texture::hasUnsupportedColorType(skBitmap.info(), hasLinearBlending))) {
sk_sp<SkColorSpace> sRGB = SkColorSpace::MakeSRGB();
bitmap = uirenderer::Texture::uploadToN32(skBitmap, hasLinearBlending, std::move(sRGB));
} else {
diff --git a/libs/hwui/renderthread/OpenGLPipeline.h b/libs/hwui/renderthread/OpenGLPipeline.h
index 4ca19fb6245c..118007c6a46c 100644
--- a/libs/hwui/renderthread/OpenGLPipeline.h
+++ b/libs/hwui/renderthread/OpenGLPipeline.h
@@ -16,9 +16,9 @@
#pragma once
-#include "CanvasContext.h"
#include "BakedOpDispatcher.h"
#include "BakedOpRenderer.h"
+#include "CanvasContext.h"
#include "FrameBuilder.h"
#include "IRenderPipeline.h"
@@ -34,14 +34,13 @@ public:
MakeCurrentResult makeCurrent() override;
Frame getFrame() override;
bool draw(const Frame& frame, const SkRect& screenDirty, const SkRect& dirty,
- const FrameBuilder::LightGeometry& lightGeometry,
- LayerUpdateQueue* layerUpdateQueue,
- const Rect& contentDrawBounds, bool opaque, bool wideColorGamut,
- const BakedOpRenderer::LightInfo& lightInfo,
- const std::vector< sp<RenderNode> >& renderNodes,
- FrameInfoVisualizer* profiler) override;
+ const FrameBuilder::LightGeometry& lightGeometry, LayerUpdateQueue* layerUpdateQueue,
+ const Rect& contentDrawBounds, bool opaque, bool wideColorGamut,
+ const BakedOpRenderer::LightInfo& lightInfo,
+ const std::vector<sp<RenderNode>>& renderNodes,
+ FrameInfoVisualizer* profiler) override;
bool swapBuffers(const Frame& frame, bool drew, const SkRect& screenDirty,
- FrameInfo* currentFrameInfo, bool* requireSwap) override;
+ FrameInfo* currentFrameInfo, bool* requireSwap) override;
bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) override;
DeferredLayerUpdater* createTextureLayer() override;
bool setSurface(Surface* window, SwapBehavior swapBehavior, ColorMode colorMode) override;
@@ -50,19 +49,19 @@ public:
bool isContextReady() override;
void onDestroyHardwareResources() override;
void renderLayers(const FrameBuilder::LightGeometry& lightGeometry,
- LayerUpdateQueue* layerUpdateQueue, bool opaque, bool wideColorGamut,
- const BakedOpRenderer::LightInfo& lightInfo) override;
+ LayerUpdateQueue* layerUpdateQueue, bool opaque, bool wideColorGamut,
+ const BakedOpRenderer::LightInfo& lightInfo) override;
TaskManager* getTaskManager() override;
- bool createOrUpdateLayer(RenderNode* node,
- const DamageAccumulator& damageAccumulator, bool wideColorGamut) override;
+ bool createOrUpdateLayer(RenderNode* node, const DamageAccumulator& damageAccumulator,
+ bool wideColorGamut) override;
bool pinImages(std::vector<SkImage*>& mutableImages) override { return false; }
bool pinImages(LsaVector<sk_sp<Bitmap>>& images) override;
void unpinImages() override;
+ void onPrepareTree() override {}
static void destroyLayer(RenderNode* node);
static void prepareToDraw(const RenderThread& thread, Bitmap* bitmap);
static void invokeFunctor(const RenderThread& thread, Functor* functor);
- static sk_sp<Bitmap> allocateHardwareBitmap(RenderThread& thread,
- SkBitmap& skBitmap);
+ static sk_sp<Bitmap> allocateHardwareBitmap(RenderThread& thread, SkBitmap& skBitmap);
private:
EglManager& mEglManager;
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 9048bd14b35c..79e46ed9e65f 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -22,11 +22,11 @@
#include "Readback.h"
#include "Rect.h"
#include "pipeline/skia/VectorDrawableAtlas.h"
+#include "renderstate/RenderState.h"
#include "renderthread/CanvasContext.h"
#include "renderthread/EglManager.h"
#include "renderthread/RenderTask.h"
#include "renderthread/RenderThread.h"
-#include "renderstate/RenderState.h"
#include "utils/Macros.h"
#include "utils/TimeUtils.h"
@@ -36,46 +36,12 @@ namespace android {
namespace uirenderer {
namespace renderthread {
-#define ARGS(method) method ## Args
-
-#define CREATE_BRIDGE0(name) CREATE_BRIDGE(name,,,,,,,,)
-#define CREATE_BRIDGE1(name, a1) CREATE_BRIDGE(name, a1,,,,,,,)
-#define CREATE_BRIDGE2(name, a1, a2) CREATE_BRIDGE(name, a1,a2,,,,,,)
-#define CREATE_BRIDGE3(name, a1, a2, a3) CREATE_BRIDGE(name, a1,a2,a3,,,,,)
-#define CREATE_BRIDGE4(name, a1, a2, a3, a4) CREATE_BRIDGE(name, a1,a2,a3,a4,,,,)
-#define CREATE_BRIDGE5(name, a1, a2, a3, a4, a5) CREATE_BRIDGE(name, a1,a2,a3,a4,a5,,,)
-#define CREATE_BRIDGE6(name, a1, a2, a3, a4, a5, a6) CREATE_BRIDGE(name, a1,a2,a3,a4,a5,a6,,)
-#define CREATE_BRIDGE7(name, a1, a2, a3, a4, a5, a6, a7) CREATE_BRIDGE(name, a1,a2,a3,a4,a5,a6,a7,)
-#define CREATE_BRIDGE(name, a1, a2, a3, a4, a5, a6, a7, a8) \
- typedef struct { \
- a1; a2; a3; a4; a5; a6; a7; a8; \
- } ARGS(name); \
- static_assert(std::is_trivially_destructible<ARGS(name)>::value, \
- "Error, ARGS must be trivially destructible!"); \
- static void* Bridge_ ## name(ARGS(name)* args)
-
-#define SETUP_TASK(method) \
- LOG_ALWAYS_FATAL_IF( METHOD_INVOKE_PAYLOAD_SIZE < sizeof(ARGS(method)), \
- "METHOD_INVOKE_PAYLOAD_SIZE %zu is smaller than sizeof(" #method "Args) %zu", \
- METHOD_INVOKE_PAYLOAD_SIZE, sizeof(ARGS(method))); \
- MethodInvokeRenderTask* task = new MethodInvokeRenderTask((RunnableMethod) Bridge_ ## method); \
- ARGS(method) *args = (ARGS(method) *) task->payload()
-
-CREATE_BRIDGE4(createContext, RenderThread* thread, bool translucent,
- RenderNode* rootRenderNode, IContextFactory* contextFactory) {
- return CanvasContext::create(*args->thread, args->translucent,
- args->rootRenderNode, args->contextFactory);
-}
-
-RenderProxy::RenderProxy(bool translucent, RenderNode* rootRenderNode, IContextFactory* contextFactory)
- : mRenderThread(RenderThread::getInstance())
- , mContext(nullptr) {
- SETUP_TASK(createContext);
- args->translucent = translucent;
- args->rootRenderNode = rootRenderNode;
- args->thread = &mRenderThread;
- args->contextFactory = contextFactory;
- mContext = (CanvasContext*) postAndWait(task);
+RenderProxy::RenderProxy(bool translucent, RenderNode* rootRenderNode,
+ IContextFactory* contextFactory)
+ : mRenderThread(RenderThread::getInstance()), mContext(nullptr) {
+ mContext = mRenderThread.queue().runSync([&]() -> CanvasContext* {
+ return CanvasContext::create(mRenderThread, translucent, rootRenderNode, contextFactory);
+ });
mDrawFrameTask.setContext(&mRenderThread, mContext, rootRenderNode);
}
@@ -83,162 +49,72 @@ RenderProxy::~RenderProxy() {
destroyContext();
}
-CREATE_BRIDGE1(destroyContext, CanvasContext* context) {
- delete args->context;
- return nullptr;
-}
-
void RenderProxy::destroyContext() {
if (mContext) {
- SETUP_TASK(destroyContext);
- args->context = mContext;
- mContext = nullptr;
mDrawFrameTask.setContext(nullptr, nullptr, nullptr);
// This is also a fence as we need to be certain that there are no
// outstanding mDrawFrame tasks posted before it is destroyed
- postAndWait(task);
+ mRenderThread.queue().runSync([this]() { delete mContext; });
+ mContext = nullptr;
}
}
-CREATE_BRIDGE2(setSwapBehavior, CanvasContext* context, SwapBehavior swapBehavior) {
- args->context->setSwapBehavior(args->swapBehavior);
- return nullptr;
-}
-
void RenderProxy::setSwapBehavior(SwapBehavior swapBehavior) {
- SETUP_TASK(setSwapBehavior);
- args->context = mContext;
- args->swapBehavior = swapBehavior;
- post(task);
-}
-
-CREATE_BRIDGE1(loadSystemProperties, CanvasContext* context) {
- bool needsRedraw = false;
- if (Caches::hasInstance()) {
- needsRedraw = Properties::load();
- }
- if (args->context->profiler().consumeProperties()) {
- needsRedraw = true;
- }
- return (void*) needsRedraw;
+ mRenderThread.queue().post([this, swapBehavior]() { mContext->setSwapBehavior(swapBehavior); });
}
bool RenderProxy::loadSystemProperties() {
- SETUP_TASK(loadSystemProperties);
- args->context = mContext;
- return (bool) postAndWait(task);
-}
-
-CREATE_BRIDGE2(setName, CanvasContext* context, const char* name) {
- args->context->setName(std::string(args->name));
- return nullptr;
+ return mRenderThread.queue().runSync([this]() -> bool {
+ bool needsRedraw = false;
+ if (Caches::hasInstance()) {
+ needsRedraw = Properties::load();
+ }
+ if (mContext->profiler().consumeProperties()) {
+ needsRedraw = true;
+ }
+ return needsRedraw;
+ });
}
void RenderProxy::setName(const char* name) {
- SETUP_TASK(setName);
- args->context = mContext;
- args->name = name;
- postAndWait(task); // block since name/value pointers owned by caller
-}
-
-CREATE_BRIDGE2(initialize, CanvasContext* context, Surface* surface) {
- args->context->initialize(args->surface);
- return nullptr;
+ // block since name/value pointers owned by caller
+ // TODO: Support move arguments
+ mRenderThread.queue().runSync([this, name]() { mContext->setName(std::string(name)); });
}
void RenderProxy::initialize(const sp<Surface>& surface) {
- SETUP_TASK(initialize);
- args->context = mContext;
- args->surface = surface.get();
- post(task);
-}
-
-CREATE_BRIDGE2(updateSurface, CanvasContext* context, Surface* surface) {
- args->context->updateSurface(args->surface);
- return nullptr;
+ mRenderThread.queue().post(
+ [ this, surf = surface ]() mutable { mContext->setSurface(std::move(surf)); });
}
void RenderProxy::updateSurface(const sp<Surface>& surface) {
- SETUP_TASK(updateSurface);
- args->context = mContext;
- args->surface = surface.get();
- post(task);
-}
-
-CREATE_BRIDGE2(pauseSurface, CanvasContext* context, Surface* surface) {
- return (void*) args->context->pauseSurface(args->surface);
+ mRenderThread.queue().post(
+ [ this, surf = surface ]() mutable { mContext->setSurface(std::move(surf)); });
}
bool RenderProxy::pauseSurface(const sp<Surface>& surface) {
- SETUP_TASK(pauseSurface);
- args->context = mContext;
- args->surface = surface.get();
- return (bool) postAndWait(task);
-}
-
-CREATE_BRIDGE2(setStopped, CanvasContext* context, bool stopped) {
- args->context->setStopped(args->stopped);
- return nullptr;
+ return mRenderThread.queue().runSync([this]() -> bool { return mContext->pauseSurface(); });
}
void RenderProxy::setStopped(bool stopped) {
- SETUP_TASK(setStopped);
- args->context = mContext;
- args->stopped = stopped;
- postAndWait(task);
-}
-
-CREATE_BRIDGE4(setup, CanvasContext* context,
- float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
- args->context->setup(args->lightRadius,
- args->ambientShadowAlpha, args->spotShadowAlpha);
- return nullptr;
+ mRenderThread.queue().runSync([this, stopped]() { mContext->setStopped(stopped); });
}
-void RenderProxy::setup(float lightRadius,
- uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
- SETUP_TASK(setup);
- args->context = mContext;
- args->lightRadius = lightRadius;
- args->ambientShadowAlpha = ambientShadowAlpha;
- args->spotShadowAlpha = spotShadowAlpha;
- post(task);
-}
-
-CREATE_BRIDGE2(setLightCenter, CanvasContext* context, Vector3 lightCenter) {
- args->context->setLightCenter(args->lightCenter);
- return nullptr;
+void RenderProxy::setup(float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
+ mRenderThread.queue().post(
+ [=]() { mContext->setup(lightRadius, ambientShadowAlpha, spotShadowAlpha); });
}
void RenderProxy::setLightCenter(const Vector3& lightCenter) {
- SETUP_TASK(setLightCenter);
- args->context = mContext;
- args->lightCenter = lightCenter;
- post(task);
-}
-
-CREATE_BRIDGE2(setOpaque, CanvasContext* context, bool opaque) {
- args->context->setOpaque(args->opaque);
- return nullptr;
+ mRenderThread.queue().post([=]() { mContext->setLightCenter(lightCenter); });
}
void RenderProxy::setOpaque(bool opaque) {
- SETUP_TASK(setOpaque);
- args->context = mContext;
- args->opaque = opaque;
- post(task);
-}
-
-CREATE_BRIDGE2(setWideGamut, CanvasContext* context, bool wideGamut) {
- args->context->setWideGamut(args->wideGamut);
- return nullptr;
+ mRenderThread.queue().post([=]() { mContext->setOpaque(opaque); });
}
void RenderProxy::setWideGamut(bool wideGamut) {
- SETUP_TASK(setWideGamut);
- args->context = mContext;
- args->wideGamut = wideGamut;
- post(task);
+ mRenderThread.queue().post([=]() { mContext->setWideGamut(wideGamut); });
}
int64_t* RenderProxy::frameInfo() {
@@ -249,77 +125,40 @@ int RenderProxy::syncAndDrawFrame() {
return mDrawFrameTask.drawFrame();
}
-CREATE_BRIDGE1(destroy, CanvasContext* context) {
- args->context->destroy();
- return nullptr;
-}
-
void RenderProxy::destroy() {
- SETUP_TASK(destroy);
- args->context = mContext;
// destroyCanvasAndSurface() needs a fence as when it returns the
// underlying BufferQueue is going to be released from under
// the render thread.
- postAndWait(task);
-}
-
-CREATE_BRIDGE2(invokeFunctor, RenderThread* thread, Functor* functor) {
- CanvasContext::invokeFunctor(*args->thread, args->functor);
- return nullptr;
+ mRenderThread.queue().runSync([=]() { mContext->destroy(); });
}
void RenderProxy::invokeFunctor(Functor* functor, bool waitForCompletion) {
ATRACE_CALL();
RenderThread& thread = RenderThread::getInstance();
- SETUP_TASK(invokeFunctor);
- args->thread = &thread;
- args->functor = functor;
+ auto invoke = [&thread, functor]() { CanvasContext::invokeFunctor(thread, functor); };
if (waitForCompletion) {
// waitForCompletion = true is expected to be fairly rare and only
// happen in destruction. Thus it should be fine to temporarily
// create a Mutex
- staticPostAndWait(task);
+ thread.queue().runSync(std::move(invoke));
} else {
- thread.queue(task);
+ thread.queue().post(std::move(invoke));
}
}
-CREATE_BRIDGE1(createTextureLayer, CanvasContext* context) {
- return args->context->createTextureLayer();
-}
-
DeferredLayerUpdater* RenderProxy::createTextureLayer() {
- SETUP_TASK(createTextureLayer);
- args->context = mContext;
- void* retval = postAndWait(task);
- DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(retval);
- return layer;
-}
-
-CREATE_BRIDGE2(buildLayer, CanvasContext* context, RenderNode* node) {
- args->context->buildLayer(args->node);
- return nullptr;
+ return mRenderThread.queue().runSync([this]() -> auto {
+ return mContext->createTextureLayer();
+ });
}
void RenderProxy::buildLayer(RenderNode* node) {
- SETUP_TASK(buildLayer);
- args->context = mContext;
- args->node = node;
- postAndWait(task);
-}
-
-CREATE_BRIDGE3(copyLayerInto, CanvasContext* context, DeferredLayerUpdater* layer,
- SkBitmap* bitmap) {
- bool success = args->context->copyLayerInto(args->layer, args->bitmap);
- return (void*) success;
+ mRenderThread.queue().runSync([&]() { mContext->buildLayer(node); });
}
bool RenderProxy::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap& bitmap) {
- SETUP_TASK(copyLayerInto);
- args->context = mContext;
- args->layer = layer;
- args->bitmap = &bitmap;
- return (bool) postAndWait(task);
+ return mRenderThread.queue().runSync(
+ [&]() -> bool { return mContext->copyLayerInto(layer, &bitmap); });
}
void RenderProxy::pushLayerUpdate(DeferredLayerUpdater* layer) {
@@ -330,302 +169,129 @@ void RenderProxy::cancelLayerUpdate(DeferredLayerUpdater* layer) {
mDrawFrameTask.removeLayerUpdate(layer);
}
-CREATE_BRIDGE1(detachSurfaceTexture, DeferredLayerUpdater* layer) {
- args->layer->detachSurfaceTexture();
- return nullptr;
-}
-
void RenderProxy::detachSurfaceTexture(DeferredLayerUpdater* layer) {
- SETUP_TASK(detachSurfaceTexture);
- args->layer = layer;
- postAndWait(task);
-}
-
-CREATE_BRIDGE1(destroyHardwareResources, CanvasContext* context) {
- args->context->destroyHardwareResources();
- return nullptr;
+ return mRenderThread.queue().runSync([&]() { layer->detachSurfaceTexture(); });
}
void RenderProxy::destroyHardwareResources() {
- SETUP_TASK(destroyHardwareResources);
- args->context = mContext;
- postAndWait(task);
-}
-
-CREATE_BRIDGE2(trimMemory, RenderThread* thread, int level) {
- CanvasContext::trimMemory(*args->thread, args->level);
- return nullptr;
+ return mRenderThread.queue().runSync([&]() { mContext->destroyHardwareResources(); });
}
void RenderProxy::trimMemory(int level) {
// Avoid creating a RenderThread to do a trimMemory.
if (RenderThread::hasInstance()) {
RenderThread& thread = RenderThread::getInstance();
- SETUP_TASK(trimMemory);
- args->thread = &thread;
- args->level = level;
- thread.queue(task);
+ thread.queue().post([&thread, level]() { CanvasContext::trimMemory(thread, level); });
}
}
-CREATE_BRIDGE2(overrideProperty, const char* name, const char* value) {
- Properties::overrideProperty(args->name, args->value);
- return nullptr;
-}
-
void RenderProxy::overrideProperty(const char* name, const char* value) {
- SETUP_TASK(overrideProperty);
- args->name = name;
- args->value = value;
- staticPostAndWait(task); // expensive, but block here since name/value pointers owned by caller
+ // expensive, but block here since name/value pointers owned by caller
+ RenderThread::getInstance().queue().runSync(
+ [&]() { Properties::overrideProperty(name, value); });
}
-CREATE_BRIDGE0(fence) {
- // Intentionally empty
- return nullptr;
-}
-
-template <typename T>
-void UNUSED(T t) {}
-
void RenderProxy::fence() {
- SETUP_TASK(fence);
- UNUSED(args);
- postAndWait(task);
+ mRenderThread.queue().runSync([]() {});
}
void RenderProxy::staticFence() {
- SETUP_TASK(fence);
- UNUSED(args);
- staticPostAndWait(task);
-}
-
-CREATE_BRIDGE1(stopDrawing, CanvasContext* context) {
- args->context->stopDrawing();
- return nullptr;
+ RenderThread::getInstance().queue().runSync([]() {});
}
void RenderProxy::stopDrawing() {
- SETUP_TASK(stopDrawing);
- args->context = mContext;
- postAndWait(task);
-}
-
-CREATE_BRIDGE1(notifyFramePending, CanvasContext* context) {
- args->context->notifyFramePending();
- return nullptr;
+ mRenderThread.queue().runSync([this]() { mContext->stopDrawing(); });
}
void RenderProxy::notifyFramePending() {
- SETUP_TASK(notifyFramePending);
- args->context = mContext;
- mRenderThread.queueAtFront(task);
-}
-
-CREATE_BRIDGE4(dumpProfileInfo, CanvasContext* context, RenderThread* thread,
- int fd, int dumpFlags) {
- args->context->profiler().dumpData(args->fd);
- if (args->dumpFlags & DumpFlags::FrameStats) {
- args->context->dumpFrames(args->fd);
- }
- if (args->dumpFlags & DumpFlags::JankStats) {
- args->thread->globalProfileData()->dump(args->fd);
- }
- if (args->dumpFlags & DumpFlags::Reset) {
- args->context->resetFrameStats();
- }
- return nullptr;
+ mRenderThread.queue().post([this]() { mContext->notifyFramePending(); });
}
void RenderProxy::dumpProfileInfo(int fd, int dumpFlags) {
- SETUP_TASK(dumpProfileInfo);
- args->context = mContext;
- args->thread = &mRenderThread;
- args->fd = fd;
- args->dumpFlags = dumpFlags;
- postAndWait(task);
-}
-
-CREATE_BRIDGE1(resetProfileInfo, CanvasContext* context) {
- args->context->resetFrameStats();
- return nullptr;
+ mRenderThread.queue().runSync([&]() {
+ mContext->profiler().dumpData(fd);
+ if (dumpFlags & DumpFlags::FrameStats) {
+ mContext->dumpFrames(fd);
+ }
+ if (dumpFlags & DumpFlags::JankStats) {
+ mRenderThread.globalProfileData()->dump(fd);
+ }
+ if (dumpFlags & DumpFlags::Reset) {
+ mContext->resetFrameStats();
+ }
+ });
}
void RenderProxy::resetProfileInfo() {
- SETUP_TASK(resetProfileInfo);
- args->context = mContext;
- postAndWait(task);
-}
-
-CREATE_BRIDGE2(frameTimePercentile, RenderThread* thread, int percentile) {
- return reinterpret_cast<void*>(static_cast<uintptr_t>(
- args->thread->globalProfileData()->findPercentile(args->percentile)));
-}
-
-uint32_t RenderProxy::frameTimePercentile(int p) {
- SETUP_TASK(frameTimePercentile);
- args->thread = &mRenderThread;
- args->percentile = p;
- return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(
- postAndWait(task)));
+ mRenderThread.queue().runSync([=]() { mContext->resetFrameStats(); });
}
-CREATE_BRIDGE2(dumpGraphicsMemory, int fd, RenderThread* thread) {
- args->thread->dumpGraphicsMemory(args->fd);
- return nullptr;
+uint32_t RenderProxy::frameTimePercentile(int percentile) {
+ return mRenderThread.queue().runSync([&]() -> auto {
+ return mRenderThread.globalProfileData()->findPercentile(percentile);
+ });
}
void RenderProxy::dumpGraphicsMemory(int fd) {
- if (!RenderThread::hasInstance()) return;
- SETUP_TASK(dumpGraphicsMemory);
- args->fd = fd;
- args->thread = &RenderThread::getInstance();
- staticPostAndWait(task);
-}
-
-CREATE_BRIDGE2(setProcessStatsBuffer, RenderThread* thread, int fd) {
- args->thread->globalProfileData().switchStorageToAshmem(args->fd);
- close(args->fd);
- return nullptr;
+ auto& thread = RenderThread::getInstance();
+ thread.queue().runSync([&]() { thread.dumpGraphicsMemory(fd); });
}
void RenderProxy::setProcessStatsBuffer(int fd) {
- SETUP_TASK(setProcessStatsBuffer);
auto& rt = RenderThread::getInstance();
- args->thread = &rt;
- args->fd = dup(fd);
- rt.queue(task);
-}
-
-CREATE_BRIDGE1(rotateProcessStatsBuffer, RenderThread* thread) {
- args->thread->globalProfileData().rotateStorage();
- return nullptr;
+ rt.queue().post([&rt, fd = dup(fd) ]() {
+ rt.globalProfileData().switchStorageToAshmem(fd);
+ close(fd);
+ });
}
void RenderProxy::rotateProcessStatsBuffer() {
- SETUP_TASK(rotateProcessStatsBuffer);
auto& rt = RenderThread::getInstance();
- args->thread = &rt;
- rt.queue(task);
+ rt.queue().post([&rt]() { rt.globalProfileData().rotateStorage(); });
}
int RenderProxy::getRenderThreadTid() {
return mRenderThread.getTid();
}
-CREATE_BRIDGE3(addRenderNode, CanvasContext* context, RenderNode* node, bool placeFront) {
- args->context->addRenderNode(args->node, args->placeFront);
- return nullptr;
-}
-
void RenderProxy::addRenderNode(RenderNode* node, bool placeFront) {
- SETUP_TASK(addRenderNode);
- args->context = mContext;
- args->node = node;
- args->placeFront = placeFront;
- post(task);
-}
-
-CREATE_BRIDGE2(removeRenderNode, CanvasContext* context, RenderNode* node) {
- args->context->removeRenderNode(args->node);
- return nullptr;
+ mRenderThread.queue().post([=]() { mContext->addRenderNode(node, placeFront); });
}
void RenderProxy::removeRenderNode(RenderNode* node) {
- SETUP_TASK(removeRenderNode);
- args->context = mContext;
- args->node = node;
- post(task);
-}
-
-CREATE_BRIDGE2(drawRenderNode, CanvasContext* context, RenderNode* node) {
- args->context->prepareAndDraw(args->node);
- return nullptr;
+ mRenderThread.queue().post([=]() { mContext->removeRenderNode(node); });
}
void RenderProxy::drawRenderNode(RenderNode* node) {
- SETUP_TASK(drawRenderNode);
- args->context = mContext;
- args->node = node;
- // Be pseudo-thread-safe and don't use any member variables
- staticPostAndWait(task);
+ mRenderThread.queue().runSync([=]() { mContext->prepareAndDraw(node); });
}
void RenderProxy::setContentDrawBounds(int left, int top, int right, int bottom) {
mDrawFrameTask.setContentDrawBounds(left, top, right, bottom);
}
-CREATE_BRIDGE1(serializeDisplayListTree, CanvasContext* context) {
- args->context->serializeDisplayListTree();
- return nullptr;
-}
-
void RenderProxy::serializeDisplayListTree() {
- SETUP_TASK(serializeDisplayListTree);
- args->context = mContext;
- post(task);
-}
-
-CREATE_BRIDGE2(addFrameMetricsObserver, CanvasContext* context,
- FrameMetricsObserver* frameStatsObserver) {
- args->context->addFrameMetricsObserver(args->frameStatsObserver);
- if (args->frameStatsObserver != nullptr) {
- args->frameStatsObserver->decStrong(args->context);
- }
- return nullptr;
-}
-
-void RenderProxy::addFrameMetricsObserver(FrameMetricsObserver* observer) {
- SETUP_TASK(addFrameMetricsObserver);
- args->context = mContext;
- args->frameStatsObserver = observer;
- if (observer != nullptr) {
- observer->incStrong(mContext);
- }
- post(task);
-}
-
-CREATE_BRIDGE2(removeFrameMetricsObserver, CanvasContext* context,
- FrameMetricsObserver* frameStatsObserver) {
- args->context->removeFrameMetricsObserver(args->frameStatsObserver);
- if (args->frameStatsObserver != nullptr) {
- args->frameStatsObserver->decStrong(args->context);
- }
- return nullptr;
-}
-
-void RenderProxy::removeFrameMetricsObserver(FrameMetricsObserver* observer) {
- SETUP_TASK(removeFrameMetricsObserver);
- args->context = mContext;
- args->frameStatsObserver = observer;
- if (observer != nullptr) {
- observer->incStrong(mContext);
- }
- post(task);
+ mRenderThread.queue().post([=]() { mContext->serializeDisplayListTree(); });
}
-CREATE_BRIDGE4(copySurfaceInto, RenderThread* thread,
- Surface* surface, Rect srcRect, SkBitmap* bitmap) {
- return (void*)args->thread->readback().copySurfaceInto(*args->surface,
- args->srcRect, args->bitmap);
+void RenderProxy::addFrameMetricsObserver(FrameMetricsObserver* observerPtr) {
+ mRenderThread.queue().post([ this, observer = sp{observerPtr} ]() {
+ mContext->addFrameMetricsObserver(observer.get());
+ });
}
-int RenderProxy::copySurfaceInto(sp<Surface>& surface, int left, int top,
- int right, int bottom, SkBitmap* bitmap) {
- SETUP_TASK(copySurfaceInto);
- args->bitmap = bitmap;
- args->surface = surface.get();
- args->thread = &RenderThread::getInstance();
- args->srcRect.set(left, top, right, bottom);
- return static_cast<int>(
- reinterpret_cast<intptr_t>( staticPostAndWait(task) ));
+void RenderProxy::removeFrameMetricsObserver(FrameMetricsObserver* observerPtr) {
+ mRenderThread.queue().post([ this, observer = sp{observerPtr} ]() {
+ mContext->removeFrameMetricsObserver(observer.get());
+ });
}
-CREATE_BRIDGE2(prepareToDraw, RenderThread* thread, Bitmap* bitmap) {
- CanvasContext::prepareToDraw(*args->thread, args->bitmap);
- args->bitmap->unref();
- args->bitmap = nullptr;
- return nullptr;
+int RenderProxy::copySurfaceInto(sp<Surface>& surface, int left, int top, int right, int bottom,
+ SkBitmap* bitmap) {
+ auto& thread = RenderThread::getInstance();
+ return static_cast<int>(thread.queue().runSync([&]() -> auto {
+ return thread.readback().copySurfaceInto(*surface, Rect(left, top, right, bottom), bitmap);
+ }));
}
void RenderProxy::prepareToDraw(Bitmap& bitmap) {
@@ -635,10 +301,11 @@ void RenderProxy::prepareToDraw(Bitmap& bitmap) {
// window or not.
if (!RenderThread::hasInstance()) return;
RenderThread* renderThread = &RenderThread::getInstance();
- SETUP_TASK(prepareToDraw);
- args->thread = renderThread;
bitmap.ref();
- args->bitmap = &bitmap;
+ auto task = [renderThread, &bitmap]() {
+ CanvasContext::prepareToDraw(*renderThread, &bitmap);
+ bitmap.unref();
+ };
nsecs_t lastVsync = renderThread->timeLord().latestVsync();
nsecs_t estimatedNextVsync = lastVsync + renderThread->timeLord().frameIntervalNanos();
nsecs_t timeToNextVsync = estimatedNextVsync - systemTime(CLOCK_MONOTONIC);
@@ -648,97 +315,52 @@ void RenderProxy::prepareToDraw(Bitmap& bitmap) {
// TODO: Make this concept a first-class supported thing? RT could use
// knowledge of pending draws to better schedule this task
if (timeToNextVsync > -6_ms && timeToNextVsync < 1_ms) {
- renderThread->queueAt(task, estimatedNextVsync + 8_ms);
+ renderThread->queue().postAt(estimatedNextVsync + 8_ms, task);
} else {
- renderThread->queue(task);
+ renderThread->queue().post(task);
}
}
-CREATE_BRIDGE2(allocateHardwareBitmap, RenderThread* thread, SkBitmap* bitmap) {
- sk_sp<Bitmap> hardwareBitmap = args->thread->allocateHardwareBitmap(*args->bitmap);
- return hardwareBitmap.release();
-}
-
sk_sp<Bitmap> RenderProxy::allocateHardwareBitmap(SkBitmap& bitmap) {
- SETUP_TASK(allocateHardwareBitmap);
- args->bitmap = &bitmap;
- args->thread = &RenderThread::getInstance();
- sk_sp<Bitmap> hardwareBitmap(reinterpret_cast<Bitmap*>(staticPostAndWait(task)));
- return hardwareBitmap;
-}
-
-CREATE_BRIDGE3(copyGraphicBufferInto, RenderThread* thread, GraphicBuffer* buffer, SkBitmap* bitmap) {
- return (void*) args->thread->readback().copyGraphicBufferInto(args->buffer, args->bitmap);
+ auto& thread = RenderThread::getInstance();
+ return thread.queue().runSync([&]() -> auto { return thread.allocateHardwareBitmap(bitmap); });
}
int RenderProxy::copyGraphicBufferInto(GraphicBuffer* buffer, SkBitmap* bitmap) {
RenderThread& thread = RenderThread::getInstance();
if (Properties::isSkiaEnabled() && gettid() == thread.getTid()) {
- //TODO: fix everything that hits this. We should never be triggering a readback ourselves.
- return (int) thread.readback().copyGraphicBufferInto(buffer, bitmap);
+ // TODO: fix everything that hits this. We should never be triggering a readback ourselves.
+ return (int)thread.readback().copyGraphicBufferInto(buffer, bitmap);
} else {
- SETUP_TASK(copyGraphicBufferInto);
- args->thread = &thread;
- args->bitmap = bitmap;
- args->buffer = buffer;
- return static_cast<int>(reinterpret_cast<intptr_t>(staticPostAndWait(task)));
+ return thread.queue().runSync([&]() -> int {
+ return (int)thread.readback().copyGraphicBufferInto(buffer, bitmap);
+ });
}
}
-CREATE_BRIDGE2(onBitmapDestroyed, RenderThread* thread, uint32_t pixelRefId) {
- args->thread->renderState().onBitmapDestroyed(args->pixelRefId);
- return nullptr;
-}
-
void RenderProxy::onBitmapDestroyed(uint32_t pixelRefId) {
if (!RenderThread::hasInstance()) return;
- SETUP_TASK(onBitmapDestroyed);
RenderThread& thread = RenderThread::getInstance();
- args->thread = &thread;
- args->pixelRefId = pixelRefId;
- thread.queue(task);
+ thread.queue().post(
+ [&thread, pixelRefId]() { thread.renderState().onBitmapDestroyed(pixelRefId); });
}
void RenderProxy::disableVsync() {
Properties::disableVsync = true;
}
-void RenderProxy::post(RenderTask* task) {
- mRenderThread.queue(task);
-}
-
-CREATE_BRIDGE1(repackVectorDrawableAtlas, RenderThread* thread) {
- args->thread->cacheManager().acquireVectorDrawableAtlas()->repackIfNeeded(
- args->thread->getGrContext());
- return nullptr;
-}
-
void RenderProxy::repackVectorDrawableAtlas() {
RenderThread& thread = RenderThread::getInstance();
- SETUP_TASK(repackVectorDrawableAtlas);
- args->thread = &thread;
- thread.queue(task);
-}
-
-void* RenderProxy::postAndWait(MethodInvokeRenderTask* task) {
- void* retval;
- task->setReturnPtr(&retval);
- SignalingRenderTask syncTask(task, &mSyncMutex, &mSyncCondition);
- AutoMutex _lock(mSyncMutex);
- mRenderThread.queue(&syncTask);
- while (!syncTask.hasRun()) {
- mSyncCondition.wait(mSyncMutex);
- }
- return retval;
+ thread.queue().post([&thread]() {
+ thread.cacheManager().acquireVectorDrawableAtlas()->repackIfNeeded(thread.getGrContext());
+ });
}
-void* RenderProxy::staticPostAndWait(MethodInvokeRenderTask* task) {
+void RenderProxy::releaseVDAtlasEntries() {
RenderThread& thread = RenderThread::getInstance();
- LOG_ALWAYS_FATAL_IF(gettid() == thread.getTid());
- void* retval;
- task->setReturnPtr(&retval);
- thread.queueAndWait(task);
- return retval;
+ thread.queue().post([&thread]() {
+ thread.cacheManager().acquireVectorDrawableAtlas()->delayedReleaseEntries();
+ });
}
} /* namespace renderthread */
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 06eaebd066ee..bc57d9255ad5 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -17,22 +17,16 @@
#ifndef RENDERPROXY_H_
#define RENDERPROXY_H_
-#include "RenderTask.h"
-
-#include <cutils/compiler.h>
-#include <EGL/egl.h>
#include <SkBitmap.h>
-#include <utils/Condition.h>
+#include <cutils/compiler.h>
+#include <gui/Surface.h>
#include <utils/Functor.h>
-#include <utils/Mutex.h>
-#include <utils/Timers.h>
-#include <utils/StrongPointer.h>
-#include "../Caches.h"
#include "../FrameMetricsObserver.h"
#include "../IContextFactory.h"
-#include "CanvasContext.h"
#include "DrawFrameTask.h"
+#include "SwapBehavior.h"
+#include "hwui/Bitmap.h"
namespace android {
class GraphicBuffer;
@@ -41,22 +35,20 @@ namespace uirenderer {
class DeferredLayerUpdater;
class RenderNode;
-class DisplayList;
-class Layer;
class Rect;
namespace renderthread {
-class ErrorChannel;
+class CanvasContext;
class RenderThread;
class RenderProxyBridge;
namespace DumpFlags {
- enum {
- FrameStats = 1 << 0,
- Reset = 1 << 1,
- JankStats = 1 << 2,
- };
+enum {
+ FrameStats = 1 << 0,
+ Reset = 1 << 1,
+ JankStats = 1 << 2,
+};
};
/*
@@ -81,8 +73,7 @@ public:
ANDROID_API void updateSurface(const sp<Surface>& surface);
ANDROID_API bool pauseSurface(const sp<Surface>& surface);
ANDROID_API void setStopped(bool stopped);
- ANDROID_API void setup(float lightRadius,
- uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
+ ANDROID_API void setup(float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
ANDROID_API void setLightCenter(const Vector3& lightCenter);
ANDROID_API void setOpaque(bool opaque);
ANDROID_API void setWideGamut(bool wideGamut);
@@ -129,8 +120,8 @@ public:
ANDROID_API void removeFrameMetricsObserver(FrameMetricsObserver* observer);
ANDROID_API long getDroppedFrameReportCount();
- ANDROID_API static int copySurfaceInto(sp<Surface>& surface,
- int left, int top, int right, int bottom, SkBitmap* bitmap);
+ ANDROID_API static int copySurfaceInto(sp<Surface>& surface, int left, int top, int right,
+ int bottom, SkBitmap* bitmap);
ANDROID_API static void prepareToDraw(Bitmap& bitmap);
static sk_sp<Bitmap> allocateHardwareBitmap(SkBitmap& bitmap);
@@ -143,22 +134,16 @@ public:
static void repackVectorDrawableAtlas();
+ static void releaseVDAtlasEntries();
+
private:
RenderThread& mRenderThread;
CanvasContext* mContext;
DrawFrameTask mDrawFrameTask;
- Mutex mSyncMutex;
- Condition mSyncCondition;
-
void destroyContext();
- void post(RenderTask* task);
- void* postAndWait(MethodInvokeRenderTask* task);
-
- static void* staticPostAndWait(MethodInvokeRenderTask* task);
-
// Friend class to help with bridging
friend class RenderProxyBridge;
};
diff --git a/libs/hwui/renderthread/RenderTask.h b/libs/hwui/renderthread/RenderTask.h
index a7acf91cbdb1..c56a3578ad58 100644
--- a/libs/hwui/renderthread/RenderTask.h
+++ b/libs/hwui/renderthread/RenderTask.h
@@ -53,7 +53,7 @@ public:
ANDROID_API virtual void run() = 0;
RenderTask* mNext;
- nsecs_t mRunAt; // nano-seconds on the SYSTEM_TIME_MONOTONIC clock
+ nsecs_t mRunAt; // nano-seconds on the SYSTEM_TIME_MONOTONIC clock
};
class SignalingRenderTask : public RenderTask {
@@ -75,8 +75,7 @@ typedef void* (*RunnableMethod)(void* data);
class MethodInvokeRenderTask : public RenderTask {
public:
- explicit MethodInvokeRenderTask(RunnableMethod method)
- : mMethod(method), mReturnPtr(nullptr) {}
+ explicit MethodInvokeRenderTask(RunnableMethod method) : mMethod(method), mReturnPtr(nullptr) {}
void* payload() { return mData; }
void setReturnPtr(void** retptr) { mReturnPtr = retptr; }
@@ -89,6 +88,7 @@ public:
// Commit suicide
delete this;
}
+
private:
RunnableMethod mMethod;
char mData[METHOD_INVOKE_PAYLOAD_SIZE];
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index 72a428f1c70c..8e0546b529af 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -16,17 +16,18 @@
#include "RenderThread.h"
-#include "hwui/Bitmap.h"
-#include "renderstate/RenderState.h"
-#include "renderthread/OpenGLPipeline.h"
-#include "pipeline/skia/SkiaOpenGLReadback.h"
-#include "pipeline/skia/SkiaOpenGLPipeline.h"
-#include "pipeline/skia/SkiaVulkanPipeline.h"
#include "CanvasContext.h"
#include "EglManager.h"
#include "OpenGLReadback.h"
#include "RenderProxy.h"
#include "VulkanManager.h"
+#include "hwui/Bitmap.h"
+#include "pipeline/skia/SkiaOpenGLPipeline.h"
+#include "pipeline/skia/SkiaOpenGLReadback.h"
+#include "pipeline/skia/SkiaVulkanReadback.h"
+#include "pipeline/skia/SkiaVulkanPipeline.h"
+#include "renderstate/RenderState.h"
+#include "renderthread/OpenGLPipeline.h"
#include "utils/FatVector.h"
#include <gui/DisplayEventReceiver.h>
@@ -49,107 +50,19 @@ static const size_t EVENT_BUFFER_SIZE = 100;
// Slight delay to give the UI time to push us a new frame before we replay
static const nsecs_t DISPATCH_FRAME_CALLBACKS_DELAY = milliseconds_to_nanoseconds(4);
-TaskQueue::TaskQueue() : mHead(nullptr), mTail(nullptr) {}
-
-RenderTask* TaskQueue::next() {
- RenderTask* ret = mHead;
- if (ret) {
- mHead = ret->mNext;
- if (!mHead) {
- mTail = nullptr;
- }
- ret->mNext = nullptr;
- }
- return ret;
-}
-
-RenderTask* TaskQueue::peek() {
- return mHead;
-}
-
-void TaskQueue::queue(RenderTask* task) {
- // Since the RenderTask itself forms the linked list it is not allowed
- // to have the same task queued twice
- LOG_ALWAYS_FATAL_IF(task->mNext || mTail == task, "Task is already in the queue!");
- if (mTail) {
- // Fast path if we can just append
- if (mTail->mRunAt <= task->mRunAt) {
- mTail->mNext = task;
- mTail = task;
- } else {
- // Need to find the proper insertion point
- RenderTask* previous = nullptr;
- RenderTask* next = mHead;
- while (next && next->mRunAt <= task->mRunAt) {
- previous = next;
- next = next->mNext;
- }
- if (!previous) {
- task->mNext = mHead;
- mHead = task;
- } else {
- previous->mNext = task;
- if (next) {
- task->mNext = next;
- } else {
- mTail = task;
- }
- }
- }
- } else {
- mTail = mHead = task;
- }
-}
-
-void TaskQueue::queueAtFront(RenderTask* task) {
- LOG_ALWAYS_FATAL_IF(task->mNext || mHead == task, "Task is already in the queue!");
- if (mTail) {
- task->mNext = mHead;
- mHead = task;
- } else {
- mTail = mHead = task;
- }
-}
-
-void TaskQueue::remove(RenderTask* task) {
- // TaskQueue is strict here to enforce that users are keeping track of
- // their RenderTasks due to how their memory is managed
- LOG_ALWAYS_FATAL_IF(!task->mNext && mTail != task,
- "Cannot remove a task that isn't in the queue!");
-
- // If task is the head we can just call next() to pop it off
- // Otherwise we need to scan through to find the task before it
- if (peek() == task) {
- next();
- } else {
- RenderTask* previous = mHead;
- while (previous->mNext != task) {
- previous = previous->mNext;
- }
- previous->mNext = task->mNext;
- if (mTail == task) {
- mTail = previous;
- }
- }
-}
-
-class DispatchFrameCallbacks : public RenderTask {
-private:
- RenderThread* mRenderThread;
-public:
- explicit DispatchFrameCallbacks(RenderThread* rt) : mRenderThread(rt) {}
-
- virtual void run() override {
- mRenderThread->dispatchFrameCallbacks();
- }
-};
-
static bool gHasRenderThreadInstance = false;
+static void (*gOnStartHook)() = nullptr;
+
bool RenderThread::hasInstance() {
return gHasRenderThreadInstance;
}
+void RenderThread::setOnStartHook(void (*onStartHook)()) {
+ LOG_ALWAYS_FATAL_IF(hasInstance(), "can't set an onStartHook after we've started...");
+ gOnStartHook = onStartHook;
+}
+
RenderThread& RenderThread::getInstance() {
// This is a pointer because otherwise __cxa_finalize
// will try to delete it like a Good Citizen but that causes us to crash
@@ -159,19 +72,16 @@ RenderThread& RenderThread::getInstance() {
return *sInstance;
}
-RenderThread::RenderThread() : Thread(true)
- , mNextWakeup(LLONG_MAX)
+RenderThread::RenderThread()
+ : ThreadBase()
, mDisplayEventReceiver(nullptr)
, mVsyncRequested(false)
, mFrameCallbackTaskPending(false)
- , mFrameCallbackTask(nullptr)
, mRenderState(nullptr)
, mEglManager(nullptr)
, mVkManager(nullptr) {
Properties::load();
- mFrameCallbackTask = new DispatchFrameCallbacks(this);
- mLooper = new Looper(false);
- run("RenderThread");
+ start("RenderThread");
}
RenderThread::~RenderThread() {
@@ -182,17 +92,18 @@ void RenderThread::initializeDisplayEventReceiver() {
LOG_ALWAYS_FATAL_IF(mDisplayEventReceiver, "Initializing a second DisplayEventReceiver?");
mDisplayEventReceiver = new DisplayEventReceiver();
status_t status = mDisplayEventReceiver->initCheck();
- LOG_ALWAYS_FATAL_IF(status != NO_ERROR, "Initialization of DisplayEventReceiver "
- "failed with status: %d", status);
+ LOG_ALWAYS_FATAL_IF(status != NO_ERROR,
+ "Initialization of DisplayEventReceiver "
+ "failed with status: %d",
+ status);
// Register the FD
- mLooper->addFd(mDisplayEventReceiver->getFd(), 0,
- Looper::EVENT_INPUT, RenderThread::displayEventReceiverCallback, this);
+ mLooper->addFd(mDisplayEventReceiver->getFd(), 0, Looper::EVENT_INPUT,
+ RenderThread::displayEventReceiverCallback, this);
}
void RenderThread::initThreadLocals() {
- sp<IBinder> dtoken(SurfaceComposerClient::getBuiltInDisplay(
- ISurfaceComposer::eDisplayIdMain));
+ sp<IBinder> dtoken(SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
status_t status = SurfaceComposerClient::getDisplayInfo(dtoken, &mDisplayInfo);
LOG_ALWAYS_FATAL_IF(status, "Failed to get display info\n");
nsecs_t frameIntervalNanos = static_cast<nsecs_t>(1000000000 / mDisplayInfo.fps);
@@ -232,18 +143,15 @@ void RenderThread::dumpGraphicsMemory(int fd) {
break;
}
default:
- LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t) renderType);
+ LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t)renderType);
break;
}
- FILE *file = fdopen(fd, "a");
- fprintf(file, "\n%s\n", cachesOutput.string());
- fprintf(file, "\nPipeline=%s\n", pipeline.string());
- fflush(file);
+ dprintf(fd, "\n%s\n", cachesOutput.string());
+ dprintf(fd, "\nPipeline=%s\n", pipeline.string());
}
Readback& RenderThread::readback() {
-
if (!mReadback) {
auto renderType = Properties::getRenderPipelineType();
switch (renderType) {
@@ -251,14 +159,13 @@ Readback& RenderThread::readback() {
mReadback = new OpenGLReadbackImpl(*this);
break;
case RenderPipelineType::SkiaGL:
- case RenderPipelineType::SkiaVulkan:
- // It works to use the OpenGL pipeline for Vulkan but this is not
- // ideal as it causes us to create an OpenGL context in addition
- // to the Vulkan one.
mReadback = new skiapipeline::SkiaOpenGLReadback(*this);
break;
+ case RenderPipelineType::SkiaVulkan:
+ mReadback = new skiapipeline::SkiaVulkanReadback(*this);
+ break;
default:
- LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t) renderType);
+ LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t)renderType);
break;
}
}
@@ -266,30 +173,32 @@ Readback& RenderThread::readback() {
return *mReadback;
}
-void RenderThread::setGrContext(GrContext* context) {
+void RenderThread::setGrContext(sk_sp<GrContext> context) {
mCacheManager->reset(context);
- if (mGrContext.get()) {
+ if (mGrContext) {
mGrContext->releaseResourcesAndAbandonContext();
}
- mGrContext.reset(context);
+ mGrContext = std::move(context);
}
int RenderThread::displayEventReceiverCallback(int fd, int events, void* data) {
if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) {
ALOGE("Display event receiver pipe was closed or an error occurred. "
- "events=0x%x", events);
- return 0; // remove the callback
+ "events=0x%x",
+ events);
+ return 0; // remove the callback
}
if (!(events & Looper::EVENT_INPUT)) {
ALOGW("Received spurious callback for unhandled poll event. "
- "events=0x%x", events);
- return 1; // keep the callback
+ "events=0x%x",
+ events);
+ return 1; // keep the callback
}
reinterpret_cast<RenderThread*>(data)->drainDisplayEventQueue();
- return 1; // keep the callback
+ return 1; // keep the callback
}
static nsecs_t latestVsyncEvent(DisplayEventReceiver* receiver) {
@@ -300,9 +209,9 @@ static nsecs_t latestVsyncEvent(DisplayEventReceiver* receiver) {
for (ssize_t i = 0; i < n; i++) {
const DisplayEventReceiver::Event& ev = buf[i];
switch (ev.header.type) {
- case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
- latest = ev.header.timestamp;
- break;
+ case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
+ latest = ev.header.timestamp;
+ break;
}
}
}
@@ -321,7 +230,7 @@ void RenderThread::drainDisplayEventQueue() {
ATRACE_NAME("queue mFrameCallbackTask");
mFrameCallbackTaskPending = true;
nsecs_t runAt = (vsyncEvent + DISPATCH_FRAME_CALLBACKS_DELAY);
- queueAt(mFrameCallbackTask, runAt);
+ queue().postAt(runAt, [this]() { dispatchFrameCallbacks(); });
}
}
}
@@ -337,7 +246,8 @@ void RenderThread::dispatchFrameCallbacks() {
// Assume one of them will probably animate again so preemptively
// request the next vsync in case it occurs mid-frame
requestVsync();
- for (std::set<IFrameCallback*>::iterator it = callbacks.begin(); it != callbacks.end(); it++) {
+ for (std::set<IFrameCallback*>::iterator it = callbacks.begin(); it != callbacks.end();
+ it++) {
(*it)->doFrame();
}
}
@@ -347,49 +257,25 @@ void RenderThread::requestVsync() {
if (!mVsyncRequested) {
mVsyncRequested = true;
status_t status = mDisplayEventReceiver->requestNextVsync();
- LOG_ALWAYS_FATAL_IF(status != NO_ERROR,
- "requestNextVsync failed with status: %d", status);
+ LOG_ALWAYS_FATAL_IF(status != NO_ERROR, "requestNextVsync failed with status: %d", status);
}
}
bool RenderThread::threadLoop() {
setpriority(PRIO_PROCESS, 0, PRIORITY_DISPLAY);
+ if (gOnStartHook) {
+ gOnStartHook();
+ }
initThreadLocals();
- int timeoutMillis = -1;
- for (;;) {
- int result = mLooper->pollOnce(timeoutMillis);
- LOG_ALWAYS_FATAL_IF(result == Looper::POLL_ERROR,
- "RenderThread Looper POLL_ERROR!");
-
- nsecs_t nextWakeup;
- {
- FatVector<RenderTask*, 10> workQueue;
- // Process our queue, if we have anything. By first acquiring
- // all the pending events then processing them we avoid vsync
- // starvation if more tasks are queued while we are processing tasks.
- while (RenderTask* task = nextTask(&nextWakeup)) {
- workQueue.push_back(task);
- }
- for (auto task : workQueue) {
- task->run();
- // task may have deleted itself, do not reference it again
- }
- }
- if (nextWakeup == LLONG_MAX) {
- timeoutMillis = -1;
- } else {
- nsecs_t timeoutNanos = nextWakeup - systemTime(SYSTEM_TIME_MONOTONIC);
- timeoutMillis = nanoseconds_to_milliseconds(timeoutNanos);
- if (timeoutMillis < 0) {
- timeoutMillis = 0;
- }
- }
+ while (true) {
+ waitForWork();
+ processQueue();
if (mPendingRegistrationFrameCallbacks.size() && !mFrameCallbackTaskPending) {
drainDisplayEventQueue();
- mFrameCallbacks.insert(
- mPendingRegistrationFrameCallbacks.begin(), mPendingRegistrationFrameCallbacks.end());
+ mFrameCallbacks.insert(mPendingRegistrationFrameCallbacks.begin(),
+ mPendingRegistrationFrameCallbacks.end());
mPendingRegistrationFrameCallbacks.clear();
requestVsync();
}
@@ -406,46 +292,6 @@ bool RenderThread::threadLoop() {
return false;
}
-void RenderThread::queue(RenderTask* task) {
- AutoMutex _lock(mLock);
- mQueue.queue(task);
- if (mNextWakeup && task->mRunAt < mNextWakeup) {
- mNextWakeup = 0;
- mLooper->wake();
- }
-}
-
-void RenderThread::queueAndWait(RenderTask* task) {
- // These need to be local to the thread to avoid the Condition
- // signaling the wrong thread. The easiest way to achieve that is to just
- // make this on the stack, although that has a slight cost to it
- Mutex mutex;
- Condition condition;
- SignalingRenderTask syncTask(task, &mutex, &condition);
-
- AutoMutex _lock(mutex);
- queue(&syncTask);
- while (!syncTask.hasRun()) {
- condition.wait(mutex);
- }
-}
-
-void RenderThread::queueAtFront(RenderTask* task) {
- AutoMutex _lock(mLock);
- mQueue.queueAtFront(task);
- mLooper->wake();
-}
-
-void RenderThread::queueAt(RenderTask* task, nsecs_t runAtNs) {
- task->mRunAt = runAtNs;
- queue(task);
-}
-
-void RenderThread::remove(RenderTask* task) {
- AutoMutex _lock(mLock);
- mQueue.remove(task);
-}
-
void RenderThread::postFrameCallback(IFrameCallback* callback) {
mPendingRegistrationFrameCallbacks.insert(callback);
}
@@ -463,26 +309,6 @@ void RenderThread::pushBackFrameCallback(IFrameCallback* callback) {
}
}
-RenderTask* RenderThread::nextTask(nsecs_t* nextWakeup) {
- AutoMutex _lock(mLock);
- RenderTask* next = mQueue.peek();
- if (!next) {
- mNextWakeup = LLONG_MAX;
- } else {
- mNextWakeup = next->mRunAt;
- // Most tasks won't be delayed, so avoid unnecessary systemTime() calls
- if (next->mRunAt <= 0 || next->mRunAt <= systemTime(SYSTEM_TIME_MONOTONIC)) {
- next = mQueue.next();
- } else {
- next = nullptr;
- }
- }
- if (nextWakeup) {
- *nextWakeup = mNextWakeup;
- }
- return next;
-}
-
sk_sp<Bitmap> RenderThread::allocateHardwareBitmap(SkBitmap& skBitmap) {
auto renderType = Properties::getRenderPipelineType();
switch (renderType) {
@@ -493,12 +319,16 @@ sk_sp<Bitmap> RenderThread::allocateHardwareBitmap(SkBitmap& skBitmap) {
case RenderPipelineType::SkiaVulkan:
return skiapipeline::SkiaVulkanPipeline::allocateHardwareBitmap(*this, skBitmap);
default:
- LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t) renderType);
+ LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t)renderType);
break;
}
return nullptr;
}
+bool RenderThread::isCurrent() {
+ return gettid() == getInstance().getTid();
+}
+
} /* namespace renderthread */
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index bef47b3e27c5..3aa548773b3b 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -22,15 +22,18 @@
#include "../JankTracker.h"
#include "CacheManager.h"
#include "TimeLord.h"
+#include "thread/ThreadBase.h"
#include <GrContext.h>
-#include <cutils/compiler.h>
#include <SkBitmap.h>
+#include <cutils/compiler.h>
#include <ui/DisplayInfo.h>
#include <utils/Looper.h>
#include <utils/Thread.h>
+#include <thread/ThreadBase.h>
#include <memory>
+#include <mutex>
#include <set>
namespace android {
@@ -47,26 +50,10 @@ class TestUtils;
namespace renderthread {
class CanvasContext;
-class DispatchFrameCallbacks;
class EglManager;
class RenderProxy;
class VulkanManager;
-class TaskQueue {
-public:
- TaskQueue();
-
- RenderTask* next();
- void queue(RenderTask* task);
- void queueAtFront(RenderTask* task);
- RenderTask* peek();
- void remove(RenderTask* task);
-
-private:
- RenderTask* mHead;
- RenderTask* mTail;
-};
-
// Mimics android.view.Choreographer.FrameCallback
class IFrameCallback {
public:
@@ -76,16 +63,14 @@ protected:
~IFrameCallback() {}
};
-class ANDROID_API RenderThread : public Thread {
+class RenderThread : private ThreadBase {
PREVENT_COPY_AND_ASSIGN(RenderThread);
+
public:
- // RenderThread takes complete ownership of tasks that are queued
- // and will delete them after they are run
- ANDROID_API void queue(RenderTask* task);
- ANDROID_API void queueAndWait(RenderTask* task);
- ANDROID_API void queueAtFront(RenderTask* task);
- void queueAt(RenderTask* task, nsecs_t runAtNs);
- void remove(RenderTask* task);
+ // Sets a callback that fires before any RenderThread setup has occured.
+ ANDROID_API static void setOnStartHook(void (*onStartHook)());
+
+ WorkQueue& queue() { return ThreadBase::queue(); }
// Mimics android.view.Choreographer
void postFrameCallback(IFrameCallback* callback);
@@ -103,7 +88,7 @@ public:
const DisplayInfo& mainDisplayInfo() { return mDisplayInfo; }
GrContext* getGrContext() const { return mGrContext.get(); }
- void setGrContext(GrContext* cxt);
+ void setGrContext(sk_sp<GrContext> cxt);
CacheManager& cacheManager() { return *mCacheManager; }
VulkanManager& vulkanManager() { return *mVkManager; }
@@ -111,6 +96,14 @@ public:
sk_sp<Bitmap> allocateHardwareBitmap(SkBitmap& skBitmap);
void dumpGraphicsMemory(int fd);
+ /**
+ * isCurrent provides a way to query, if the caller is running on
+ * the render thread.
+ *
+ * @return true only if isCurrent is invoked from the render thread.
+ */
+ static bool isCurrent();
+
protected:
virtual bool threadLoop() override;
@@ -132,17 +125,6 @@ private:
void dispatchFrameCallbacks();
void requestVsync();
- // Returns the next task to be run. If this returns NULL nextWakeup is set
- // to the time to requery for the nextTask to run. mNextWakeup is also
- // set to this time
- RenderTask* nextTask(nsecs_t* nextWakeup);
-
- sp<Looper> mLooper;
- Mutex mLock;
-
- nsecs_t mNextWakeup;
- TaskQueue mQueue;
-
DisplayInfo mDisplayInfo;
DisplayEventReceiver* mDisplayEventReceiver;
@@ -154,7 +136,6 @@ private:
// the previous one
std::set<IFrameCallback*> mPendingRegistrationFrameCallbacks;
bool mFrameCallbackTaskPending;
- DispatchFrameCallbacks* mFrameCallbackTask;
TimeLord mTimeLord;
RenderState* mRenderState;
diff --git a/libs/hwui/renderthread/TimeLord.cpp b/libs/hwui/renderthread/TimeLord.cpp
index 6c2575f699bb..b82c5d159756 100644
--- a/libs/hwui/renderthread/TimeLord.cpp
+++ b/libs/hwui/renderthread/TimeLord.cpp
@@ -19,10 +19,7 @@ namespace android {
namespace uirenderer {
namespace renderthread {
-TimeLord::TimeLord()
- : mFrameIntervalNanos(milliseconds_to_nanoseconds(16))
- , mFrameTimeNanos(0) {
-}
+TimeLord::TimeLord() : mFrameIntervalNanos(milliseconds_to_nanoseconds(16)), mFrameTimeNanos(0) {}
bool TimeLord::vsyncReceived(nsecs_t vsync) {
if (vsync > mFrameTimeNanos) {
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index 2195143658d2..9d246ffc9a4a 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -31,11 +31,10 @@ namespace android {
namespace uirenderer {
namespace renderthread {
-#define GET_PROC(F) m ## F = (PFN_vk ## F) vkGetInstanceProcAddr(instance, "vk" #F)
-#define GET_DEV_PROC(F) m ## F = (PFN_vk ## F) vkGetDeviceProcAddr(device, "vk" #F)
+#define GET_PROC(F) m##F = (PFN_vk##F)vkGetInstanceProcAddr(instance, "vk" #F)
+#define GET_DEV_PROC(F) m##F = (PFN_vk##F)vkGetDeviceProcAddr(device, "vk" #F)
-VulkanManager::VulkanManager(RenderThread& thread) : mRenderThread(thread) {
-}
+VulkanManager::VulkanManager(RenderThread& thread) : mRenderThread(thread) {}
void VulkanManager::destroy() {
if (!hasVkContext()) return;
@@ -51,12 +50,15 @@ void VulkanManager::destroy() {
}
void VulkanManager::initialize() {
- if (hasVkContext()) { return; }
+ if (hasVkContext()) {
+ return;
+ }
auto canPresent = [](VkInstance, VkPhysicalDevice, uint32_t) { return true; };
mBackendContext.reset(GrVkBackendContext::Create(vkGetInstanceProcAddr, vkGetDeviceProcAddr,
- &mPresentQueueIndex, canPresent));
+ &mPresentQueueIndex, canPresent));
+ LOG_ALWAYS_FATAL_IF(!mBackendContext.get());
// Get all the addresses of needed vulkan functions
VkInstance instance = mBackendContext->fInstance;
@@ -99,15 +101,19 @@ void VulkanManager::initialize() {
// this needs to be on the render queue
commandPoolInfo.queueFamilyIndex = mBackendContext->fGraphicsQueueIndex;
commandPoolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
- SkDEBUGCODE(VkResult res =) mCreateCommandPool(mBackendContext->fDevice,
- &commandPoolInfo, nullptr, &mCommandPool);
+ SkDEBUGCODE(VkResult res =) mCreateCommandPool(mBackendContext->fDevice, &commandPoolInfo,
+ nullptr, &mCommandPool);
SkASSERT(VK_SUCCESS == res);
}
mGetDeviceQueue(mBackendContext->fDevice, mPresentQueueIndex, 0, &mPresentQueue);
- mRenderThread.setGrContext(GrContext::Create(kVulkan_GrBackend,
- (GrBackendContext) mBackendContext.get()));
+ GrContextOptions options;
+ options.fDisableDistanceFieldPaths = true;
+ mRenderThread.cacheManager().configureContext(&options);
+ sk_sp<GrContext> grContext(GrContext::MakeVulkan(mBackendContext, options));
+ LOG_ALWAYS_FATAL_IF(!grContext.get());
+ mRenderThread.setGrContext(grContext);
DeviceInfo::initialize(mRenderThread.getGrContext()->caps()->maxRenderTargetSize());
if (Properties::enablePartialUpdates && Properties::useBufferAge) {
@@ -127,13 +133,13 @@ VulkanSurface::BackbufferInfo* VulkanManager::getAvailableBackbuffer(VulkanSurfa
surface->mCurrentBackbufferIndex = 0;
}
- VulkanSurface::BackbufferInfo* backbuffer = surface->mBackbuffers +
- surface->mCurrentBackbufferIndex;
+ VulkanSurface::BackbufferInfo* backbuffer =
+ surface->mBackbuffers + surface->mCurrentBackbufferIndex;
// Before we reuse a backbuffer, make sure its fences have all signaled so that we can safely
// reuse its commands buffers.
- VkResult res = mWaitForFences(mBackendContext->fDevice, 2, backbuffer->mUsageFences,
- true, UINT64_MAX);
+ VkResult res =
+ mWaitForFences(mBackendContext->fDevice, 2, backbuffer->mUsageFences, true, UINT64_MAX);
if (res != VK_SUCCESS) {
return nullptr;
}
@@ -141,7 +147,6 @@ VulkanSurface::BackbufferInfo* VulkanManager::getAvailableBackbuffer(VulkanSurfa
return backbuffer;
}
-
SkSurface* VulkanManager::getBackbufferSurface(VulkanSurface* surface) {
VulkanSurface::BackbufferInfo* backbuffer = getAvailableBackbuffer(surface);
SkASSERT(backbuffer);
@@ -154,7 +159,8 @@ SkSurface* VulkanManager::getBackbufferSurface(VulkanSurface* surface) {
// The acquire will signal the attached mAcquireSemaphore. We use this to know the image has
// finished presenting and that it is safe to begin sending new commands to the returned image.
res = mAcquireNextImageKHR(mBackendContext->fDevice, surface->mSwapchain, UINT64_MAX,
- backbuffer->mAcquireSemaphore, VK_NULL_HANDLE, &backbuffer->mImageIndex);
+ backbuffer->mAcquireSemaphore, VK_NULL_HANDLE,
+ &backbuffer->mImageIndex);
if (VK_ERROR_SURFACE_LOST_KHR == res) {
// need to figure out how to create a new vkSurface without the platformData*
@@ -172,7 +178,8 @@ SkSurface* VulkanManager::getBackbufferSurface(VulkanSurface* surface) {
// acquire the image
res = mAcquireNextImageKHR(mBackendContext->fDevice, surface->mSwapchain, UINT64_MAX,
- backbuffer->mAcquireSemaphore, VK_NULL_HANDLE, &backbuffer->mImageIndex);
+ backbuffer->mAcquireSemaphore, VK_NULL_HANDLE,
+ &backbuffer->mImageIndex);
if (VK_SUCCESS != res) {
return nullptr;
@@ -182,25 +189,25 @@ SkSurface* VulkanManager::getBackbufferSurface(VulkanSurface* surface) {
// set up layout transfer from initial to color attachment
VkImageLayout layout = surface->mImageInfos[backbuffer->mImageIndex].mImageLayout;
SkASSERT(VK_IMAGE_LAYOUT_UNDEFINED == layout || VK_IMAGE_LAYOUT_PRESENT_SRC_KHR == layout);
- VkPipelineStageFlags srcStageMask = (VK_IMAGE_LAYOUT_UNDEFINED == layout) ?
- VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT :
- VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ VkPipelineStageFlags srcStageMask = (VK_IMAGE_LAYOUT_UNDEFINED == layout)
+ ? VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT
+ : VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
- VkAccessFlags srcAccessMask = (VK_IMAGE_LAYOUT_UNDEFINED == layout) ?
- 0 : VK_ACCESS_MEMORY_READ_BIT;
+ VkAccessFlags srcAccessMask =
+ (VK_IMAGE_LAYOUT_UNDEFINED == layout) ? 0 : VK_ACCESS_MEMORY_READ_BIT;
VkAccessFlags dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
VkImageMemoryBarrier imageMemoryBarrier = {
- VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
- NULL, // pNext
- srcAccessMask, // outputMask
- dstAccessMask, // inputMask
- layout, // oldLayout
- VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // newLayout
- mPresentQueueIndex, // srcQueueFamilyIndex
- mBackendContext->fGraphicsQueueIndex, // dstQueueFamilyIndex
- surface->mImages[backbuffer->mImageIndex], // image
- { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } // subresourceRange
+ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
+ NULL, // pNext
+ srcAccessMask, // outputMask
+ dstAccessMask, // inputMask
+ layout, // oldLayout
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // newLayout
+ mPresentQueueIndex, // srcQueueFamilyIndex
+ mBackendContext->fGraphicsQueueIndex, // dstQueueFamilyIndex
+ surface->mImages[backbuffer->mImageIndex], // image
+ {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1} // subresourceRange
};
mResetCommandBuffer(backbuffer->mTransitionCmdBuffers[0], 0);
@@ -210,8 +217,8 @@ SkSurface* VulkanManager::getBackbufferSurface(VulkanSurface* surface) {
info.flags = 0;
mBeginCommandBuffer(backbuffer->mTransitionCmdBuffers[0], &info);
- mCmdPipelineBarrier(backbuffer->mTransitionCmdBuffers[0], srcStageMask, dstStageMask, 0,
- 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier);
+ mCmdPipelineBarrier(backbuffer->mTransitionCmdBuffers[0], srcStageMask, dstStageMask, 0, 0,
+ nullptr, 0, nullptr, 1, &imageMemoryBarrier);
mEndCommandBuffer(backbuffer->mTransitionCmdBuffers[0]);
@@ -235,7 +242,7 @@ SkSurface* VulkanManager::getBackbufferSurface(VulkanSurface* surface) {
GrVkImageInfo* imageInfo;
sk_sp<SkSurface> skSurface = surface->mImageInfos[backbuffer->mImageIndex].mSurface;
skSurface->getRenderTargetHandle((GrBackendObject*)&imageInfo,
- SkSurface::kFlushRead_BackendHandleAccess);
+ SkSurface::kFlushRead_BackendHandleAccess);
imageInfo->updateImageLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
surface->mBackbuffer = std::move(skSurface);
@@ -246,14 +253,14 @@ void VulkanManager::destroyBuffers(VulkanSurface* surface) {
if (surface->mBackbuffers) {
for (uint32_t i = 0; i < surface->mImageCount + 1; ++i) {
mWaitForFences(mBackendContext->fDevice, 2, surface->mBackbuffers[i].mUsageFences, true,
- UINT64_MAX);
+ UINT64_MAX);
surface->mBackbuffers[i].mImageIndex = -1;
mDestroySemaphore(mBackendContext->fDevice, surface->mBackbuffers[i].mAcquireSemaphore,
- nullptr);
+ nullptr);
mDestroySemaphore(mBackendContext->fDevice, surface->mBackbuffers[i].mRenderSemaphore,
- nullptr);
+ nullptr);
mFreeCommandBuffers(mBackendContext->fDevice, mCommandPool, 2,
- surface->mBackbuffers[i].mTransitionCmdBuffers);
+ surface->mBackbuffers[i].mTransitionCmdBuffers);
mDestroyFence(mBackendContext->fDevice, surface->mBackbuffers[i].mUsageFences[0], 0);
mDestroyFence(mBackendContext->fDevice, surface->mBackbuffers[i].mUsageFences[1], 0);
}
@@ -290,11 +297,11 @@ void VulkanManager::destroySurface(VulkanSurface* surface) {
void VulkanManager::createBuffers(VulkanSurface* surface, VkFormat format, VkExtent2D extent) {
mGetSwapchainImagesKHR(mBackendContext->fDevice, surface->mSwapchain, &surface->mImageCount,
- nullptr);
+ nullptr);
SkASSERT(surface->mImageCount);
surface->mImages = new VkImage[surface->mImageCount];
- mGetSwapchainImagesKHR(mBackendContext->fDevice, surface->mSwapchain,
- &surface->mImageCount, surface->mImages);
+ mGetSwapchainImagesKHR(mBackendContext->fDevice, surface->mSwapchain, &surface->mImageCount,
+ surface->mImages);
SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
@@ -303,7 +310,7 @@ void VulkanManager::createBuffers(VulkanSurface* surface, VkFormat format, VkExt
for (uint32_t i = 0; i < surface->mImageCount; ++i) {
GrVkImageInfo info;
info.fImage = surface->mImages[i];
- info.fAlloc = { VK_NULL_HANDLE, 0, 0, 0 };
+ info.fAlloc = {VK_NULL_HANDLE, 0, 0, 0};
info.fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
info.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
info.fFormat = format;
@@ -312,8 +319,8 @@ void VulkanManager::createBuffers(VulkanSurface* surface, VkFormat format, VkExt
GrBackendRenderTarget backendRT(extent.width, extent.height, 0, 0, info);
VulkanSurface::ImageInfo& imageInfo = surface->mImageInfos[i];
- imageInfo.mSurface = SkSurface::MakeFromBackendRenderTarget(mRenderThread.getGrContext(),
- backendRT, kTopLeft_GrSurfaceOrigin, nullptr, &props);
+ imageInfo.mSurface = SkSurface::MakeFromBackendRenderTarget(
+ mRenderThread.getGrContext(), backendRT, kTopLeft_GrSurfaceOrigin, nullptr, &props);
}
SkASSERT(mCommandPool != VK_NULL_HANDLE);
@@ -343,16 +350,16 @@ void VulkanManager::createBuffers(VulkanSurface* surface, VkFormat format, VkExt
for (uint32_t i = 0; i < surface->mImageCount + 1; ++i) {
SkDEBUGCODE(VkResult res);
surface->mBackbuffers[i].mImageIndex = -1;
- SkDEBUGCODE(res = ) mCreateSemaphore(mBackendContext->fDevice, &semaphoreInfo, nullptr,
- &surface->mBackbuffers[i].mAcquireSemaphore);
- SkDEBUGCODE(res = ) mCreateSemaphore(mBackendContext->fDevice, &semaphoreInfo, nullptr,
- &surface->mBackbuffers[i].mRenderSemaphore);
- SkDEBUGCODE(res = ) mAllocateCommandBuffers(mBackendContext->fDevice, &commandBuffersInfo,
- surface->mBackbuffers[i].mTransitionCmdBuffers);
- SkDEBUGCODE(res = ) mCreateFence(mBackendContext->fDevice, &fenceInfo, nullptr,
- &surface->mBackbuffers[i].mUsageFences[0]);
- SkDEBUGCODE(res = ) mCreateFence(mBackendContext->fDevice, &fenceInfo, nullptr,
- &surface->mBackbuffers[i].mUsageFences[1]);
+ SkDEBUGCODE(res =) mCreateSemaphore(mBackendContext->fDevice, &semaphoreInfo, nullptr,
+ &surface->mBackbuffers[i].mAcquireSemaphore);
+ SkDEBUGCODE(res =) mCreateSemaphore(mBackendContext->fDevice, &semaphoreInfo, nullptr,
+ &surface->mBackbuffers[i].mRenderSemaphore);
+ SkDEBUGCODE(res =) mAllocateCommandBuffers(mBackendContext->fDevice, &commandBuffersInfo,
+ surface->mBackbuffers[i].mTransitionCmdBuffers);
+ SkDEBUGCODE(res =) mCreateFence(mBackendContext->fDevice, &fenceInfo, nullptr,
+ &surface->mBackbuffers[i].mUsageFences[0]);
+ SkDEBUGCODE(res =) mCreateFence(mBackendContext->fDevice, &fenceInfo, nullptr,
+ &surface->mBackbuffers[i].mUsageFences[1]);
SkASSERT(VK_SUCCESS == res);
}
surface->mCurrentBackbufferIndex = surface->mImageCount;
@@ -362,35 +369,36 @@ bool VulkanManager::createSwapchain(VulkanSurface* surface) {
// check for capabilities
VkSurfaceCapabilitiesKHR caps;
VkResult res = mGetPhysicalDeviceSurfaceCapabilitiesKHR(mBackendContext->fPhysicalDevice,
- surface->mVkSurface, &caps);
+ surface->mVkSurface, &caps);
if (VK_SUCCESS != res) {
return false;
}
uint32_t surfaceFormatCount;
res = mGetPhysicalDeviceSurfaceFormatsKHR(mBackendContext->fPhysicalDevice, surface->mVkSurface,
- &surfaceFormatCount, nullptr);
+ &surfaceFormatCount, nullptr);
if (VK_SUCCESS != res) {
return false;
}
FatVector<VkSurfaceFormatKHR, 4> surfaceFormats(surfaceFormatCount);
res = mGetPhysicalDeviceSurfaceFormatsKHR(mBackendContext->fPhysicalDevice, surface->mVkSurface,
- &surfaceFormatCount, surfaceFormats.data());
+ &surfaceFormatCount, surfaceFormats.data());
if (VK_SUCCESS != res) {
return false;
}
uint32_t presentModeCount;
res = mGetPhysicalDeviceSurfacePresentModesKHR(mBackendContext->fPhysicalDevice,
- surface->mVkSurface, &presentModeCount, nullptr);
+ surface->mVkSurface, &presentModeCount, nullptr);
if (VK_SUCCESS != res) {
return false;
}
FatVector<VkPresentModeKHR, VK_PRESENT_MODE_RANGE_SIZE_KHR> presentModes(presentModeCount);
res = mGetPhysicalDeviceSurfacePresentModesKHR(mBackendContext->fPhysicalDevice,
- surface->mVkSurface, &presentModeCount, presentModes.data());
+ surface->mVkSurface, &presentModeCount,
+ presentModes.data());
if (VK_SUCCESS != res) {
return false;
}
@@ -420,12 +428,12 @@ bool VulkanManager::createSwapchain(VulkanSurface* surface) {
VK_IMAGE_USAGE_TRANSFER_DST_BIT;
SkASSERT((caps.supportedUsageFlags & usageFlags) == usageFlags);
SkASSERT(caps.supportedTransforms & caps.currentTransform);
- SkASSERT(caps.supportedCompositeAlpha & (VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR |
- VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR));
+ SkASSERT(caps.supportedCompositeAlpha &
+ (VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR | VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR));
VkCompositeAlphaFlagBitsKHR composite_alpha =
- (caps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR) ?
- VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR :
- VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
+ (caps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR)
+ ? VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR
+ : VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
// Pick our surface format. For now, just make sure it matches our sRGB request:
VkFormat surfaceFormat = VK_FORMAT_UNDEFINED;
@@ -470,7 +478,7 @@ bool VulkanManager::createSwapchain(VulkanSurface* surface) {
swapchainCreateInfo.imageArrayLayers = 1;
swapchainCreateInfo.imageUsage = usageFlags;
- uint32_t queueFamilies[] = { mBackendContext->fGraphicsQueueIndex, mPresentQueueIndex };
+ uint32_t queueFamilies[] = {mBackendContext->fGraphicsQueueIndex, mPresentQueueIndex};
if (mBackendContext->fGraphicsQueueIndex != mPresentQueueIndex) {
swapchainCreateInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
swapchainCreateInfo.queueFamilyIndexCount = 2;
@@ -488,7 +496,7 @@ bool VulkanManager::createSwapchain(VulkanSurface* surface) {
swapchainCreateInfo.oldSwapchain = surface->mSwapchain;
res = mCreateSwapchainKHR(mBackendContext->fDevice, &swapchainCreateInfo, nullptr,
- &surface->mSwapchain);
+ &surface->mSwapchain);
if (VK_SUCCESS != res) {
return false;
}
@@ -507,7 +515,6 @@ bool VulkanManager::createSwapchain(VulkanSurface* surface) {
return true;
}
-
VulkanSurface* VulkanManager::createSurface(ANativeWindow* window) {
initialize();
@@ -524,21 +531,20 @@ VulkanSurface* VulkanManager::createSurface(ANativeWindow* window) {
surfaceCreateInfo.flags = 0;
surfaceCreateInfo.window = window;
- VkResult res = mCreateAndroidSurfaceKHR(mBackendContext->fInstance, &surfaceCreateInfo,
- nullptr, &surface->mVkSurface);
+ VkResult res = mCreateAndroidSurfaceKHR(mBackendContext->fInstance, &surfaceCreateInfo, nullptr,
+ &surface->mVkSurface);
if (VK_SUCCESS != res) {
delete surface;
return nullptr;
}
-SkDEBUGCODE(
- VkBool32 supported;
- res = mGetPhysicalDeviceSurfaceSupportKHR(mBackendContext->fPhysicalDevice,
- mPresentQueueIndex, surface->mVkSurface, &supported);
- // All physical devices and queue families on Android must be capable of presentation with any
- // native window.
- SkASSERT(VK_SUCCESS == res && supported);
-);
+ SkDEBUGCODE(VkBool32 supported; res = mGetPhysicalDeviceSurfaceSupportKHR(
+ mBackendContext->fPhysicalDevice, mPresentQueueIndex,
+ surface->mVkSurface, &supported);
+ // All physical devices and queue families on Android must be capable of
+ // presentation with any
+ // native window.
+ SkASSERT(VK_SUCCESS == res && supported););
if (!createSwapchain(surface)) {
destroySurface(surface);
@@ -573,11 +579,9 @@ static VkAccessFlags layoutToSrcAccessMask(const VkImageLayout layout) {
VkAccessFlags flags = 0;
if (VK_IMAGE_LAYOUT_GENERAL == layout) {
flags = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
- VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
- VK_ACCESS_TRANSFER_WRITE_BIT |
- VK_ACCESS_TRANSFER_READ_BIT |
- VK_ACCESS_SHADER_READ_BIT |
- VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_HOST_READ_BIT;
+ VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT |
+ VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_HOST_WRITE_BIT |
+ VK_ACCESS_HOST_READ_BIT;
} else if (VK_IMAGE_LAYOUT_PREINITIALIZED == layout) {
flags = VK_ACCESS_HOST_WRITE_BIT;
} else if (VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL == layout) {
@@ -600,12 +604,13 @@ void VulkanManager::swapBuffers(VulkanSurface* surface) {
mDeviceWaitIdle(mBackendContext->fDevice);
}
- VulkanSurface::BackbufferInfo* backbuffer = surface->mBackbuffers +
- surface->mCurrentBackbufferIndex;
+ SkASSERT(surface->mBackbuffers);
+ VulkanSurface::BackbufferInfo* backbuffer =
+ surface->mBackbuffers + surface->mCurrentBackbufferIndex;
GrVkImageInfo* imageInfo;
SkSurface* skSurface = surface->mImageInfos[backbuffer->mImageIndex].mSurface.get();
skSurface->getRenderTargetHandle((GrBackendObject*)&imageInfo,
- SkSurface::kFlushRead_BackendHandleAccess);
+ SkSurface::kFlushRead_BackendHandleAccess);
// Check to make sure we never change the actually wrapped image
SkASSERT(imageInfo->fImage == surface->mImages[backbuffer->mImageIndex]);
@@ -618,16 +623,16 @@ void VulkanManager::swapBuffers(VulkanSurface* surface) {
VkAccessFlags dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
VkImageMemoryBarrier imageMemoryBarrier = {
- VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
- NULL, // pNext
- srcAccessMask, // outputMask
- dstAccessMask, // inputMask
- layout, // oldLayout
- VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, // newLayout
- mBackendContext->fGraphicsQueueIndex, // srcQueueFamilyIndex
- mPresentQueueIndex, // dstQueueFamilyIndex
- surface->mImages[backbuffer->mImageIndex], // image
- { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } // subresourceRange
+ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
+ NULL, // pNext
+ srcAccessMask, // outputMask
+ dstAccessMask, // inputMask
+ layout, // oldLayout
+ VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, // newLayout
+ mBackendContext->fGraphicsQueueIndex, // srcQueueFamilyIndex
+ mPresentQueueIndex, // dstQueueFamilyIndex
+ surface->mImages[backbuffer->mImageIndex], // image
+ {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1} // subresourceRange
};
mResetCommandBuffer(backbuffer->mTransitionCmdBuffers[1], 0);
@@ -636,8 +641,8 @@ void VulkanManager::swapBuffers(VulkanSurface* surface) {
info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
info.flags = 0;
mBeginCommandBuffer(backbuffer->mTransitionCmdBuffers[1], &info);
- mCmdPipelineBarrier(backbuffer->mTransitionCmdBuffers[1], srcStageMask, dstStageMask, 0,
- 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier);
+ mCmdPipelineBarrier(backbuffer->mTransitionCmdBuffers[1], srcStageMask, dstStageMask, 0, 0,
+ nullptr, 0, nullptr, 1, &imageMemoryBarrier);
mEndCommandBuffer(backbuffer->mTransitionCmdBuffers[1]);
surface->mImageInfos[backbuffer->mImageIndex].mImageLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
@@ -661,16 +666,15 @@ void VulkanManager::swapBuffers(VulkanSurface* surface) {
// Submit present operation to present queue. We use a semaphore here to make sure all rendering
// to the image is complete and that the layout has been change to present on the graphics
// queue.
- const VkPresentInfoKHR presentInfo =
- {
- VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, // sType
- NULL, // pNext
- 1, // waitSemaphoreCount
- &backbuffer->mRenderSemaphore, // pWaitSemaphores
- 1, // swapchainCount
- &surface->mSwapchain, // pSwapchains
- &backbuffer->mImageIndex, // pImageIndices
- NULL // pResults
+ const VkPresentInfoKHR presentInfo = {
+ VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, // sType
+ NULL, // pNext
+ 1, // waitSemaphoreCount
+ &backbuffer->mRenderSemaphore, // pWaitSemaphores
+ 1, // swapchainCount
+ &surface->mSwapchain, // pSwapchains
+ &backbuffer->mImageIndex, // pImageIndices
+ NULL // pResults
};
mQueuePresentKHR(mPresentQueue, &presentInfo);
@@ -682,10 +686,11 @@ void VulkanManager::swapBuffers(VulkanSurface* surface) {
}
int VulkanManager::getAge(VulkanSurface* surface) {
- VulkanSurface::BackbufferInfo* backbuffer = surface->mBackbuffers +
- surface->mCurrentBackbufferIndex;
- if (mSwapBehavior == SwapBehavior::Discard
- || surface->mImageInfos[backbuffer->mImageIndex].mInvalid) {
+ SkASSERT(surface->mBackbuffers);
+ VulkanSurface::BackbufferInfo* backbuffer =
+ surface->mBackbuffers + surface->mCurrentBackbufferIndex;
+ if (mSwapBehavior == SwapBehavior::Discard ||
+ surface->mImageInfos[backbuffer->mImageIndex].mInvalid) {
return 0;
}
uint16_t lastUsed = surface->mImageInfos[backbuffer->mImageIndex].mLastUsed;
diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h
index d225b3fc4ec0..c319c9ec209f 100644
--- a/libs/hwui/renderthread/VulkanManager.h
+++ b/libs/hwui/renderthread/VulkanManager.h
@@ -37,13 +37,14 @@ public:
private:
friend class VulkanManager;
struct BackbufferInfo {
- uint32_t mImageIndex; // image this is associated with
- VkSemaphore mAcquireSemaphore; // we signal on this for acquisition of image
- VkSemaphore mRenderSemaphore; // we wait on this for rendering to be done
- VkCommandBuffer mTransitionCmdBuffers[2]; // to transition layout between present and render
+ uint32_t mImageIndex; // image this is associated with
+ VkSemaphore mAcquireSemaphore; // we signal on this for acquisition of image
+ VkSemaphore mRenderSemaphore; // we wait on this for rendering to be done
+ VkCommandBuffer
+ mTransitionCmdBuffers[2]; // to transition layout between present and render
// We use these fences to make sure the above Command buffers have finished their work
// before attempting to reuse them or destroy them.
- VkFence mUsageFences[2];
+ VkFence mUsageFences[2];
};
struct ImageInfo {
@@ -58,11 +59,11 @@ private:
VkSurfaceKHR mVkSurface = VK_NULL_HANDLE;
VkSwapchainKHR mSwapchain = VK_NULL_HANDLE;
- BackbufferInfo* mBackbuffers;
+ BackbufferInfo* mBackbuffers = nullptr;
uint32_t mCurrentBackbufferIndex;
uint32_t mImageCount;
- VkImage* mImages;
+ VkImage* mImages = nullptr;
ImageInfo* mImageInfos;
uint16_t mCurrentTime = 0;
};
@@ -118,11 +119,16 @@ private:
VulkanSurface::BackbufferInfo* getAvailableBackbuffer(VulkanSurface* surface);
// simple wrapper class that exists only to initialize a pointer to NULL
- template <typename FNPTR_TYPE> class VkPtr {
+ template <typename FNPTR_TYPE>
+ class VkPtr {
public:
VkPtr() : fPtr(NULL) {}
- VkPtr operator=(FNPTR_TYPE ptr) { fPtr = ptr; return *this; }
+ VkPtr operator=(FNPTR_TYPE ptr) {
+ fPtr = ptr;
+ return *this;
+ }
operator FNPTR_TYPE() const { return fPtr; }
+
private:
FNPTR_TYPE fPtr;
};
@@ -183,4 +189,3 @@ private:
} /* namespace android */
#endif /* VULKANMANAGER_H */
-