Merge "Support render-ahead in vulkan" into qt-dev
This commit is contained in:
@@ -17,8 +17,8 @@
|
||||
#include "Properties.h"
|
||||
#include "Debug.h"
|
||||
#include "DeviceInfo.h"
|
||||
#include "SkTraceEventCommon.h"
|
||||
#include "HWUIProperties.sysprop.h"
|
||||
#include "SkTraceEventCommon.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
@@ -67,7 +67,7 @@ bool Properties::debuggingEnabled = false;
|
||||
bool Properties::isolatedProcess = false;
|
||||
|
||||
int Properties::contextPriority = 0;
|
||||
int Properties::defaultRenderAhead = 0;
|
||||
uint32_t Properties::defaultRenderAhead = 0;
|
||||
|
||||
static int property_get_int(const char* key, int defaultValue) {
|
||||
char buf[PROPERTY_VALUE_MAX] = {
|
||||
@@ -130,12 +130,9 @@ bool Properties::load() {
|
||||
|
||||
enableForceDarkSupport = property_get_bool(PROPERTY_ENABLE_FORCE_DARK, true);
|
||||
|
||||
defaultRenderAhead = std::max(0, std::min(2, property_get_int(PROPERTY_RENDERAHEAD,
|
||||
render_ahead().value_or(0))));
|
||||
|
||||
if (defaultRenderAhead && sRenderPipelineType == RenderPipelineType::SkiaVulkan) {
|
||||
ALOGW("hwui.render_ahead of %d ignored because pipeline is skiavk", defaultRenderAhead);
|
||||
}
|
||||
defaultRenderAhead =
|
||||
std::max(0u, std::min(2u, static_cast<uint32_t>(property_get_int(
|
||||
PROPERTY_RENDERAHEAD, render_ahead().value_or(0)))));
|
||||
|
||||
return (prevDebugLayersUpdates != debugLayersUpdates) || (prevDebugOverdraw != debugOverdraw);
|
||||
}
|
||||
|
||||
@@ -253,7 +253,7 @@ public:
|
||||
|
||||
ANDROID_API static int contextPriority;
|
||||
|
||||
static int defaultRenderAhead;
|
||||
static uint32_t defaultRenderAhead;
|
||||
|
||||
private:
|
||||
static ProfileType sProfileType;
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
#include "ShaderCache.h"
|
||||
#include <GrContext.h>
|
||||
#include <log/log.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <algorithm>
|
||||
@@ -23,7 +24,6 @@
|
||||
#include "FileBlobCache.h"
|
||||
#include "Properties.h"
|
||||
#include "utils/TraceUtils.h"
|
||||
#include <GrContext.h>
|
||||
|
||||
namespace android {
|
||||
namespace uirenderer {
|
||||
|
||||
@@ -101,7 +101,7 @@ bool SkiaOpenGLPipeline::draw(const Frame& frame, const SkRect& screenDirty, con
|
||||
|
||||
SkiaPipeline::updateLighting(lightGeometry, lightInfo);
|
||||
renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface,
|
||||
SkMatrix::I());
|
||||
SkMatrix::I());
|
||||
layerUpdateQueue->clear();
|
||||
|
||||
// Draw visual debugging features
|
||||
@@ -156,8 +156,23 @@ void SkiaOpenGLPipeline::onStop() {
|
||||
}
|
||||
}
|
||||
|
||||
static void setBufferCount(ANativeWindow* window, uint32_t extraBuffers) {
|
||||
int query_value;
|
||||
int err = window->query(window, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &query_value);
|
||||
if (err != 0 || query_value < 0) {
|
||||
ALOGE("window->query failed: %s (%d) value=%d", strerror(-err), err, query_value);
|
||||
return;
|
||||
}
|
||||
auto min_undequeued_buffers = static_cast<uint32_t>(query_value);
|
||||
|
||||
int bufferCount = min_undequeued_buffers + 2 + extraBuffers;
|
||||
ALOGD("Setting buffer count to %d, min_undequeued %u, extraBuffers %u",
|
||||
bufferCount, min_undequeued_buffers, extraBuffers);
|
||||
native_window_set_buffer_count(window, bufferCount);
|
||||
}
|
||||
|
||||
bool SkiaOpenGLPipeline::setSurface(ANativeWindow* surface, SwapBehavior swapBehavior,
|
||||
ColorMode colorMode) {
|
||||
ColorMode colorMode, uint32_t extraBuffers) {
|
||||
if (mEglSurface != EGL_NO_SURFACE) {
|
||||
mEglManager.destroySurface(mEglSurface);
|
||||
mEglSurface = EGL_NO_SURFACE;
|
||||
@@ -177,6 +192,7 @@ bool SkiaOpenGLPipeline::setSurface(ANativeWindow* surface, SwapBehavior swapBeh
|
||||
if (mEglSurface != EGL_NO_SURFACE) {
|
||||
const bool preserveBuffer = (swapBehavior != SwapBehavior::kSwap_discardBuffer);
|
||||
mBufferPreserved = mEglManager.setPreserveBuffer(mEglSurface, preserveBuffer);
|
||||
setBufferCount(surface, extraBuffers);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
FrameInfo* currentFrameInfo, bool* requireSwap) override;
|
||||
DeferredLayerUpdater* createTextureLayer() override;
|
||||
bool setSurface(ANativeWindow* surface, renderthread::SwapBehavior swapBehavior,
|
||||
renderthread::ColorMode colorMode) override;
|
||||
renderthread::ColorMode colorMode, uint32_t extraBuffers) override;
|
||||
void onStop() override;
|
||||
bool isSurfaceReady() override;
|
||||
bool isContextReady() override;
|
||||
|
||||
@@ -250,8 +250,9 @@ SkCanvas* SkiaPipeline::tryCapture(SkSurface* surface) {
|
||||
}
|
||||
if (mCaptureSequence > 0 || mPictureCapturedCallback) {
|
||||
mRecorder.reset(new SkPictureRecorder());
|
||||
SkCanvas* pictureCanvas = mRecorder->beginRecording(surface->width(), surface->height(), nullptr,
|
||||
SkPictureRecorder::kPlaybackDrawPicture_RecordFlag);
|
||||
SkCanvas* pictureCanvas =
|
||||
mRecorder->beginRecording(surface->width(), surface->height(), nullptr,
|
||||
SkPictureRecorder::kPlaybackDrawPicture_RecordFlag);
|
||||
mNwayCanvas = std::make_unique<SkNWayCanvas>(surface->width(), surface->height());
|
||||
mNwayCanvas->addCanvas(surface->getCanvas());
|
||||
mNwayCanvas->addCanvas(pictureCanvas);
|
||||
@@ -276,8 +277,7 @@ void SkiaPipeline::endCapture(SkSurface* surface) {
|
||||
if (1 == mCaptureSequence) {
|
||||
savePictureAsync(data, mCapturedFile);
|
||||
} else {
|
||||
savePictureAsync(data,
|
||||
mCapturedFile + "_" + std::to_string(mCaptureSequence));
|
||||
savePictureAsync(data, mCapturedFile + "_" + std::to_string(mCaptureSequence));
|
||||
}
|
||||
mCaptureSequence--;
|
||||
}
|
||||
@@ -327,7 +327,7 @@ static Rect nodeBounds(RenderNode& node) {
|
||||
auto& props = node.properties();
|
||||
return Rect(props.getLeft(), props.getTop(), props.getRight(), props.getBottom());
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void SkiaPipeline::renderFrameImpl(const LayerUpdateQueue& layers, const SkRect& clip,
|
||||
const std::vector<sp<RenderNode>>& nodes, bool opaque,
|
||||
@@ -464,10 +464,20 @@ void SkiaPipeline::setSurfaceColorProperties(ColorMode colorMode) {
|
||||
// (3) Requires RGBA colors (instead of BGRA).
|
||||
static const uint32_t kOverdrawColors[2][6] = {
|
||||
{
|
||||
0x00000000, 0x00000000, 0x2f2f0000, 0x2f002f00, 0x3f00003f, 0x7f00007f,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x2f2f0000,
|
||||
0x2f002f00,
|
||||
0x3f00003f,
|
||||
0x7f00007f,
|
||||
},
|
||||
{
|
||||
0x00000000, 0x00000000, 0x2f2f0000, 0x4f004f4f, 0x5f50335f, 0x7f00007f,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x2f2f0000,
|
||||
0x4f004f4f,
|
||||
0x5f50335f,
|
||||
0x7f00007f,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -142,8 +142,7 @@ void SkiaRecordingCanvas::callDrawGLFunction(Functor* functor,
|
||||
void SkiaRecordingCanvas::drawWebViewFunctor(int functor) {
|
||||
FunctorDrawable* functorDrawable;
|
||||
if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) {
|
||||
functorDrawable =
|
||||
mDisplayList->allocateDrawable<VkFunctorDrawable>(functor, asSkCanvas());
|
||||
functorDrawable = mDisplayList->allocateDrawable<VkFunctorDrawable>(functor, asSkCanvas());
|
||||
} else {
|
||||
functorDrawable = mDisplayList->allocateDrawable<GLFunctorDrawable>(functor, asSkCanvas());
|
||||
}
|
||||
|
||||
@@ -18,12 +18,12 @@
|
||||
|
||||
#include "DeferredLayerUpdater.h"
|
||||
#include "Readback.h"
|
||||
#include "ShaderCache.h"
|
||||
#include "SkiaPipeline.h"
|
||||
#include "SkiaProfileRenderer.h"
|
||||
#include "VkInteropFunctorDrawable.h"
|
||||
#include "renderstate/RenderState.h"
|
||||
#include "renderthread/Frame.h"
|
||||
#include "ShaderCache.h"
|
||||
|
||||
#include <SkSurface.h>
|
||||
#include <SkTypes.h>
|
||||
@@ -70,8 +70,8 @@ bool SkiaVulkanPipeline::draw(const Frame& frame, const SkRect& screenDirty, con
|
||||
return false;
|
||||
}
|
||||
SkiaPipeline::updateLighting(lightGeometry, lightInfo);
|
||||
renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds,
|
||||
backBuffer, mVkSurface->getCurrentPreTransform());
|
||||
renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, backBuffer,
|
||||
mVkSurface->getCurrentPreTransform());
|
||||
ShaderCache::get().onVkFrameFlushed(mRenderThread.getGrContext());
|
||||
layerUpdateQueue->clear();
|
||||
|
||||
@@ -116,7 +116,7 @@ DeferredLayerUpdater* SkiaVulkanPipeline::createTextureLayer() {
|
||||
void SkiaVulkanPipeline::onStop() {}
|
||||
|
||||
bool SkiaVulkanPipeline::setSurface(ANativeWindow* surface, SwapBehavior swapBehavior,
|
||||
ColorMode colorMode) {
|
||||
ColorMode colorMode, uint32_t extraBuffers) {
|
||||
if (mVkSurface) {
|
||||
mVkManager.destroySurface(mVkSurface);
|
||||
mVkSurface = nullptr;
|
||||
@@ -125,8 +125,9 @@ bool SkiaVulkanPipeline::setSurface(ANativeWindow* surface, SwapBehavior swapBeh
|
||||
setSurfaceColorProperties(colorMode);
|
||||
if (surface) {
|
||||
mRenderThread.requireVkContext();
|
||||
mVkSurface = mVkManager.createSurface(surface, colorMode, mSurfaceColorSpace,
|
||||
mSurfaceColorType, mRenderThread.getGrContext());
|
||||
mVkSurface =
|
||||
mVkManager.createSurface(surface, colorMode, mSurfaceColorSpace, mSurfaceColorType,
|
||||
mRenderThread.getGrContext(), extraBuffers);
|
||||
}
|
||||
|
||||
return mVkSurface != nullptr;
|
||||
|
||||
@@ -43,7 +43,7 @@ public:
|
||||
FrameInfo* currentFrameInfo, bool* requireSwap) override;
|
||||
DeferredLayerUpdater* createTextureLayer() override;
|
||||
bool setSurface(ANativeWindow* surface, renderthread::SwapBehavior swapBehavior,
|
||||
renderthread::ColorMode colorMode) override;
|
||||
renderthread::ColorMode colorMode, uint32_t extraBuffers) override;
|
||||
void onStop() override;
|
||||
bool isSurfaceReady() override;
|
||||
bool isContextReady() override;
|
||||
|
||||
@@ -17,16 +17,16 @@
|
||||
#include "VkFunctorDrawable.h"
|
||||
#include <private/hwui/DrawVkInfo.h>
|
||||
|
||||
#include "renderthread/VulkanManager.h"
|
||||
#include "renderthread/RenderThread.h"
|
||||
#include <SkAndroidFrameworkUtils.h>
|
||||
#include <GrBackendDrawableInfo.h>
|
||||
#include <SkAndroidFrameworkUtils.h>
|
||||
#include <SkImage.h>
|
||||
#include <utils/Color.h>
|
||||
#include <utils/Trace.h>
|
||||
#include <utils/TraceUtils.h>
|
||||
#include <vk/GrVkTypes.h>
|
||||
#include <thread>
|
||||
#include "renderthread/RenderThread.h"
|
||||
#include "renderthread/VulkanManager.h"
|
||||
#include "thread/ThreadBase.h"
|
||||
#include "utils/TimeUtils.h"
|
||||
|
||||
@@ -64,13 +64,13 @@ void VkFunctorDrawHandler::draw(const GrBackendDrawableInfo& info) {
|
||||
|
||||
SkMatrix44 mat4(mMatrix);
|
||||
VkFunctorDrawParams params{
|
||||
.width = mImageInfo.width(),
|
||||
.height = mImageInfo.height(),
|
||||
.color_space_ptr = mImageInfo.colorSpace(),
|
||||
.clip_left = mClip.fLeft,
|
||||
.clip_top = mClip.fTop,
|
||||
.clip_right = mClip.fRight,
|
||||
.clip_bottom = mClip.fBottom,
|
||||
.width = mImageInfo.width(),
|
||||
.height = mImageInfo.height(),
|
||||
.color_space_ptr = mImageInfo.colorSpace(),
|
||||
.clip_left = mClip.fLeft,
|
||||
.clip_top = mClip.fTop,
|
||||
.clip_right = mClip.fRight,
|
||||
.clip_bottom = mClip.fBottom,
|
||||
};
|
||||
mat4.asColMajorf(¶ms.transform[0]);
|
||||
params.secondary_command_buffer = vulkan_info.fSecondaryCommandBuffer;
|
||||
@@ -87,8 +87,7 @@ void VkFunctorDrawHandler::draw(const GrBackendDrawableInfo& info) {
|
||||
vulkan_info.fDrawBounds->extent.height = mClip.fBottom - mClip.fTop;
|
||||
}
|
||||
|
||||
VkFunctorDrawable::~VkFunctorDrawable() {
|
||||
}
|
||||
VkFunctorDrawable::~VkFunctorDrawable() {}
|
||||
|
||||
void VkFunctorDrawable::onDraw(SkCanvas* canvas) {
|
||||
// "canvas" is either SkNWayCanvas created by SkiaPipeline::tryCapture (SKP capture use case) or
|
||||
@@ -106,9 +105,8 @@ void VkFunctorDrawable::onDraw(SkCanvas* canvas) {
|
||||
SkCanvas* gpuCanvas = SkAndroidFrameworkUtils::getBaseWrappedCanvas(canvas);
|
||||
// Enforce "canvas" must be an AlphaFilterCanvas. For GPU canvas, the call should come from
|
||||
// onSnapGpuDrawHandler.
|
||||
LOG_ALWAYS_FATAL_IF(
|
||||
gpuCanvas == canvas,
|
||||
"VkFunctorDrawable::onDraw() should not be called with a GPU canvas!");
|
||||
LOG_ALWAYS_FATAL_IF(gpuCanvas == canvas,
|
||||
"VkFunctorDrawable::onDraw() should not be called with a GPU canvas!");
|
||||
|
||||
// This will invoke onSnapGpuDrawHandler and regular draw flow.
|
||||
gpuCanvas->drawDrawable(this);
|
||||
|
||||
@@ -21,17 +21,16 @@
|
||||
#include "RenderThread.h"
|
||||
#include "pipeline/skia/ShaderCache.h"
|
||||
#include "pipeline/skia/SkiaMemoryTracer.h"
|
||||
#include "Properties.h"
|
||||
#include "renderstate/RenderState.h"
|
||||
#include "thread/CommonPool.h"
|
||||
|
||||
#include <GrContextOptions.h>
|
||||
#include <SkExecutor.h>
|
||||
#include <SkGraphics.h>
|
||||
#include <SkMathPriv.h>
|
||||
#include <gui/Surface.h>
|
||||
#include <math.h>
|
||||
#include <set>
|
||||
#include <SkMathPriv.h>
|
||||
|
||||
namespace android {
|
||||
namespace uirenderer {
|
||||
@@ -79,14 +78,13 @@ void CacheManager::updateContextCacheSizes() {
|
||||
|
||||
class CommonPoolExecutor : public SkExecutor {
|
||||
public:
|
||||
virtual void add(std::function<void(void)> func) override {
|
||||
CommonPool::post(std::move(func));
|
||||
}
|
||||
virtual void add(std::function<void(void)> func) override { CommonPool::post(std::move(func)); }
|
||||
};
|
||||
|
||||
static CommonPoolExecutor sDefaultExecutor;
|
||||
|
||||
void CacheManager::configureContext(GrContextOptions* contextOptions, const void* identity, ssize_t size) {
|
||||
void CacheManager::configureContext(GrContextOptions* contextOptions, const void* identity,
|
||||
ssize_t size) {
|
||||
contextOptions->fAllowPathMaskCaching = true;
|
||||
|
||||
// This sets the maximum size for a single texture atlas in the GPU font cache. If necessary,
|
||||
@@ -180,7 +178,8 @@ void CacheManager::dumpMemoryUsage(String8& log, const RenderState* renderState)
|
||||
}
|
||||
|
||||
const char* layerType = Properties::getRenderPipelineType() == RenderPipelineType::SkiaGL
|
||||
? "GlLayer" : "VkLayer";
|
||||
? "GlLayer"
|
||||
: "VkLayer";
|
||||
size_t layerMemoryTotal = 0;
|
||||
for (std::set<Layer*>::iterator it = renderState->mActiveLayers.begin();
|
||||
it != renderState->mActiveLayers.end(); it++) {
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "CanvasContext.h"
|
||||
#include <GpuMemoryTracker.h>
|
||||
|
||||
#include "../Properties.h"
|
||||
#include "AnimationContext.h"
|
||||
#include "EglManager.h"
|
||||
#include "Frame.h"
|
||||
@@ -31,7 +32,6 @@
|
||||
#include "utils/GLUtils.h"
|
||||
#include "utils/TimeUtils.h"
|
||||
#include "utils/TraceUtils.h"
|
||||
#include "../Properties.h"
|
||||
|
||||
#include <cutils/properties.h>
|
||||
#include <private/hwui/DrawGlInfo.h>
|
||||
@@ -153,7 +153,8 @@ void CanvasContext::setSurface(sp<Surface>&& surface) {
|
||||
}
|
||||
|
||||
ColorMode colorMode = mWideColorGamut ? ColorMode::WideColorGamut : ColorMode::SRGB;
|
||||
bool hasSurface = mRenderPipeline->setSurface(mNativeSurface.get(), mSwapBehavior, colorMode);
|
||||
bool hasSurface = mRenderPipeline->setSurface(mNativeSurface.get(), mSwapBehavior, colorMode,
|
||||
mRenderAheadDepth);
|
||||
|
||||
mFrameNumber = -1;
|
||||
|
||||
@@ -298,7 +299,7 @@ void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo, int64_t sy
|
||||
|
||||
mAnimationContext->startFrame(info.mode);
|
||||
mRenderPipeline->onPrepareTree();
|
||||
for (const sp<RenderNode> &node : mRenderNodes) {
|
||||
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
|
||||
// node(s) are non client / filler nodes.
|
||||
@@ -322,7 +323,7 @@ void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo, int64_t sy
|
||||
|
||||
if (CC_LIKELY(mSwapHistory.size() && !Properties::forceDrawFrame)) {
|
||||
nsecs_t latestVsync = mRenderThread.timeLord().latestVsync();
|
||||
SwapHistory &lastSwap = mSwapHistory.back();
|
||||
SwapHistory& lastSwap = mSwapHistory.back();
|
||||
nsecs_t vsyncDelta = std::abs(lastSwap.vsyncTime - latestVsync);
|
||||
// The slight fudge-factor is to deal with cases where
|
||||
// the vsync was estimated due to being slow handling the signal.
|
||||
@@ -405,8 +406,7 @@ void CanvasContext::draw() {
|
||||
SkRect dirty;
|
||||
mDamageAccumulator.finish(&dirty);
|
||||
|
||||
if (dirty.isEmpty() && Properties::skipEmptyFrames
|
||||
&& !surfaceRequiresRedraw()) {
|
||||
if (dirty.isEmpty() && Properties::skipEmptyFrames && !surfaceRequiresRedraw()) {
|
||||
mCurrentFrameInfo->addFlag(FrameInfoFlags::SkippedFrame);
|
||||
return;
|
||||
}
|
||||
@@ -416,21 +416,21 @@ void CanvasContext::draw() {
|
||||
Frame frame = mRenderPipeline->getFrame();
|
||||
|
||||
SkRect windowDirty = computeDirtyRect(frame, &dirty);
|
||||
if (mRenderAheadDepth) {
|
||||
auto presentTime =
|
||||
mCurrentFrameInfo->get(FrameInfoIndex::Vsync) +
|
||||
(mRenderThread.timeLord().frameIntervalNanos() * (mRenderAheadDepth + 1));
|
||||
native_window_set_buffers_timestamp(mNativeSurface.get(), presentTime);
|
||||
}
|
||||
|
||||
bool drew = mRenderPipeline->draw(frame, windowDirty, dirty, mLightGeometry, &mLayerUpdateQueue,
|
||||
mContentDrawBounds, mOpaque, mLightInfo,
|
||||
mRenderNodes, &(profiler()));
|
||||
mContentDrawBounds, mOpaque, mLightInfo, mRenderNodes,
|
||||
&(profiler()));
|
||||
|
||||
int64_t frameCompleteNr = mFrameCompleteCallbacks.size() ? getFrameNumber() : -1;
|
||||
|
||||
waitOnFences();
|
||||
|
||||
if (mRenderAheadDepth) {
|
||||
auto presentTime = mCurrentFrameInfo->get(FrameInfoIndex::Vsync) +
|
||||
(mRenderThread.timeLord().frameIntervalNanos() * (mRenderAheadDepth + 1));
|
||||
native_window_set_buffers_timestamp(mNativeSurface.get(), presentTime);
|
||||
}
|
||||
|
||||
bool requireSwap = false;
|
||||
bool didSwap =
|
||||
mRenderPipeline->swapBuffers(frame, drew, windowDirty, mCurrentFrameInfo, &requireSwap);
|
||||
@@ -645,21 +645,13 @@ bool CanvasContext::surfaceRequiresRedraw() {
|
||||
}
|
||||
|
||||
void CanvasContext::applyRenderAheadSettings() {
|
||||
if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) {
|
||||
// TODO: Fix SkiaVulkan's assumptions on buffer counts. And SIGBUS crashes.
|
||||
mRenderAheadDepth = 0;
|
||||
return;
|
||||
}
|
||||
if (mNativeSurface) {
|
||||
native_window_set_buffer_count(mNativeSurface.get(), 3 + mRenderAheadDepth);
|
||||
if (!mRenderAheadDepth) {
|
||||
native_window_set_buffers_timestamp(mNativeSurface.get(), NATIVE_WINDOW_TIMESTAMP_AUTO);
|
||||
}
|
||||
if (mNativeSurface && !mRenderAheadDepth) {
|
||||
native_window_set_buffers_timestamp(mNativeSurface.get(), NATIVE_WINDOW_TIMESTAMP_AUTO);
|
||||
}
|
||||
}
|
||||
|
||||
void CanvasContext::setRenderAheadDepth(int renderAhead) {
|
||||
if (renderAhead < 0 || renderAhead > 2 || renderAhead == mRenderAheadDepth) {
|
||||
void CanvasContext::setRenderAheadDepth(uint32_t renderAhead) {
|
||||
if (renderAhead > 2 || renderAhead == mRenderAheadDepth || mNativeSurface) {
|
||||
return;
|
||||
}
|
||||
mRenderAheadDepth = renderAhead;
|
||||
|
||||
@@ -17,15 +17,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "DamageAccumulator.h"
|
||||
#include "Lighting.h"
|
||||
#include "FrameInfo.h"
|
||||
#include "FrameInfoVisualizer.h"
|
||||
#include "FrameMetricsReporter.h"
|
||||
#include "IContextFactory.h"
|
||||
#include "IRenderPipeline.h"
|
||||
#include "LayerUpdateQueue.h"
|
||||
#include "RenderNode.h"
|
||||
#include "Lighting.h"
|
||||
#include "ReliableSurface.h"
|
||||
#include "RenderNode.h"
|
||||
#include "renderthread/RenderTask.h"
|
||||
#include "renderthread/RenderThread.h"
|
||||
|
||||
@@ -37,10 +37,10 @@
|
||||
#include <utils/Functor.h>
|
||||
|
||||
#include <functional>
|
||||
#include <future>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <future>
|
||||
|
||||
namespace android {
|
||||
namespace uirenderer {
|
||||
@@ -187,9 +187,7 @@ public:
|
||||
mRenderPipeline->setPictureCapturedCallback(callback);
|
||||
}
|
||||
|
||||
void setForceDark(bool enable) {
|
||||
mUseForceDark = enable;
|
||||
}
|
||||
void setForceDark(bool enable) { mUseForceDark = enable; }
|
||||
|
||||
bool useForceDark() {
|
||||
// The force-dark override has the highest priority, followed by the disable setting
|
||||
@@ -204,7 +202,8 @@ public:
|
||||
return mUseForceDark;
|
||||
}
|
||||
|
||||
void setRenderAheadDepth(int renderAhead);
|
||||
// Must be called before setSurface
|
||||
void setRenderAheadDepth(uint32_t renderAhead);
|
||||
|
||||
private:
|
||||
CanvasContext(RenderThread& thread, bool translucent, RenderNode* rootRenderNode,
|
||||
@@ -238,7 +237,7 @@ private:
|
||||
// painted onto its surface.
|
||||
bool mIsDirty = false;
|
||||
SwapBehavior mSwapBehavior = SwapBehavior::kSwap_default;
|
||||
int mRenderAheadDepth = 0;
|
||||
uint32_t mRenderAheadDepth = 0;
|
||||
struct SwapHistory {
|
||||
SkRect damage;
|
||||
nsecs_t vsyncTime;
|
||||
|
||||
@@ -109,9 +109,8 @@ void DrawFrameTask::run() {
|
||||
|
||||
// Even if we aren't drawing this vsync pulse the next frame number will still be accurate
|
||||
if (CC_UNLIKELY(callback)) {
|
||||
context->enqueueFrameWork([callback, frameNr = context->getFrameNumber()]() {
|
||||
callback(frameNr);
|
||||
});
|
||||
context->enqueueFrameWork(
|
||||
[callback, frameNr = context->getFrameNumber()]() { callback(frameNr); });
|
||||
}
|
||||
|
||||
if (CC_LIKELY(canDrawThisFrame)) {
|
||||
|
||||
@@ -29,10 +29,10 @@
|
||||
#include <EGL/eglext.h>
|
||||
#include <GLES/gl.h>
|
||||
|
||||
#include <gui/Surface.h>
|
||||
#include <system/window.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <system/window.h>
|
||||
#include <gui/Surface.h>
|
||||
|
||||
#define GLES_VERSION 2
|
||||
|
||||
@@ -171,8 +171,7 @@ EGLConfig EglManager::load8BitsConfig(EGLDisplay display, EglManager::SwapBehavi
|
||||
EGL_NONE};
|
||||
EGLConfig config = EGL_NO_CONFIG_KHR;
|
||||
EGLint numConfigs = 1;
|
||||
if (!eglChooseConfig(display, attribs, &config, numConfigs, &numConfigs) ||
|
||||
numConfigs != 1) {
|
||||
if (!eglChooseConfig(display, attribs, &config, numConfigs, &numConfigs) || numConfigs != 1) {
|
||||
return EGL_NO_CONFIG_KHR;
|
||||
}
|
||||
return config;
|
||||
@@ -203,8 +202,7 @@ EGLConfig EglManager::loadFP16Config(EGLDisplay display, SwapBehavior swapBehavi
|
||||
EGL_NONE};
|
||||
EGLConfig config = EGL_NO_CONFIG_KHR;
|
||||
EGLint numConfigs = 1;
|
||||
if (!eglChooseConfig(display, attribs, &config, numConfigs, &numConfigs) ||
|
||||
numConfigs != 1) {
|
||||
if (!eglChooseConfig(display, attribs, &config, numConfigs, &numConfigs) || numConfigs != 1) {
|
||||
return EGL_NO_CONFIG_KHR;
|
||||
}
|
||||
return config;
|
||||
@@ -262,7 +260,7 @@ void EglManager::loadConfigs() {
|
||||
mEglConfigWideGamut = loadFP16Config(mEglDisplay, mSwapBehavior);
|
||||
if (mEglConfigWideGamut == EGL_NO_CONFIG_KHR) {
|
||||
ALOGE("Device claims wide gamut support, cannot find matching config, error = %s",
|
||||
eglErrorString());
|
||||
eglErrorString());
|
||||
EglExtensions.pixelFormatFloat = false;
|
||||
}
|
||||
} else if (wideColorType == SkColorType::kN32_SkColorType) {
|
||||
@@ -350,7 +348,7 @@ Result<EGLSurface, EGLint> EglManager::createSurface(EGLNativeWindowType window,
|
||||
EGLSurface surface = eglCreateWindowSurface(
|
||||
mEglDisplay, wideColorGamut ? mEglConfigWideGamut : mEglConfig, window, attribs);
|
||||
if (surface == EGL_NO_SURFACE) {
|
||||
return Error<EGLint> { eglGetError() };
|
||||
return Error<EGLint>{eglGetError()};
|
||||
}
|
||||
|
||||
if (mSwapBehavior != SwapBehavior::Preserved) {
|
||||
@@ -525,12 +523,8 @@ status_t EglManager::fenceWait(sp<Fence>& fence) {
|
||||
ALOGE("EglManager::fenceWait: error dup'ing fence fd: %d", errno);
|
||||
return -errno;
|
||||
}
|
||||
EGLint attribs[] = {
|
||||
EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd,
|
||||
EGL_NONE
|
||||
};
|
||||
EGLSyncKHR sync = eglCreateSyncKHR(mEglDisplay,
|
||||
EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
|
||||
EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd, EGL_NONE};
|
||||
EGLSyncKHR sync = eglCreateSyncKHR(mEglDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
|
||||
if (sync == EGL_NO_SYNC_KHR) {
|
||||
close(fenceFd);
|
||||
ALOGE("EglManager::fenceWait: error creating EGL fence: %#x", eglGetError());
|
||||
@@ -559,18 +553,16 @@ status_t EglManager::fenceWait(sp<Fence>& fence) {
|
||||
}
|
||||
|
||||
status_t EglManager::createReleaseFence(bool useFenceSync, EGLSyncKHR* eglFence,
|
||||
sp<Fence>& nativeFence) {
|
||||
sp<Fence>& nativeFence) {
|
||||
if (!hasEglContext()) {
|
||||
ALOGE("EglManager::createReleaseFence: EGLDisplay not initialized");
|
||||
return INVALID_OPERATION;
|
||||
}
|
||||
|
||||
if (SyncFeatures::getInstance().useNativeFenceSync()) {
|
||||
EGLSyncKHR sync = eglCreateSyncKHR(mEglDisplay,
|
||||
EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
|
||||
EGLSyncKHR sync = eglCreateSyncKHR(mEglDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
|
||||
if (sync == EGL_NO_SYNC_KHR) {
|
||||
ALOGE("EglManager::createReleaseFence: error creating EGL fence: %#x",
|
||||
eglGetError());
|
||||
ALOGE("EglManager::createReleaseFence: error creating EGL fence: %#x", eglGetError());
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
glFlush();
|
||||
@@ -578,7 +570,8 @@ status_t EglManager::createReleaseFence(bool useFenceSync, EGLSyncKHR* eglFence,
|
||||
eglDestroySyncKHR(mEglDisplay, sync);
|
||||
if (fenceFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
|
||||
ALOGE("EglManager::createReleaseFence: error dup'ing native fence "
|
||||
"fd: %#x", eglGetError());
|
||||
"fd: %#x",
|
||||
eglGetError());
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
nativeFence = new Fence(fenceFd);
|
||||
@@ -592,7 +585,7 @@ status_t EglManager::createReleaseFence(bool useFenceSync, EGLSyncKHR* eglFence,
|
||||
EGLint result = eglClientWaitSyncKHR(mEglDisplay, *eglFence, 0, 1000000000);
|
||||
if (result == EGL_FALSE) {
|
||||
ALOGE("EglManager::createReleaseFence: error waiting for previous fence: %#x",
|
||||
eglGetError());
|
||||
eglGetError());
|
||||
return UNKNOWN_ERROR;
|
||||
} else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
|
||||
ALOGE("EglManager::createReleaseFence: timeout waiting for previous fence");
|
||||
|
||||
@@ -66,8 +66,8 @@ public:
|
||||
virtual bool swapBuffers(const Frame& frame, bool drew, const SkRect& screenDirty,
|
||||
FrameInfo* currentFrameInfo, bool* requireSwap) = 0;
|
||||
virtual DeferredLayerUpdater* createTextureLayer() = 0;
|
||||
virtual bool setSurface(ANativeWindow* window, SwapBehavior swapBehavior,
|
||||
ColorMode colorMode) = 0;
|
||||
virtual bool setSurface(ANativeWindow* window, SwapBehavior swapBehavior, ColorMode colorMode,
|
||||
uint32_t extraBuffers) = 0;
|
||||
virtual void onStop() = 0;
|
||||
virtual bool isSurfaceReady() = 0;
|
||||
virtual bool isContextReady() = 0;
|
||||
|
||||
@@ -34,13 +34,13 @@ struct SurfaceExposer : Surface {
|
||||
// Make warnings happy
|
||||
SurfaceExposer() = delete;
|
||||
|
||||
using Surface::setBufferCount;
|
||||
using Surface::setSwapInterval;
|
||||
using Surface::dequeueBuffer;
|
||||
using Surface::queueBuffer;
|
||||
using Surface::cancelBuffer;
|
||||
using Surface::dequeueBuffer;
|
||||
using Surface::lockBuffer_DEPRECATED;
|
||||
using Surface::perform;
|
||||
using Surface::queueBuffer;
|
||||
using Surface::setBufferCount;
|
||||
using Surface::setSwapInterval;
|
||||
};
|
||||
|
||||
#define callProtected(surface, func, ...) ((*surface).*&SurfaceExposer::func)(__VA_ARGS__)
|
||||
|
||||
@@ -84,7 +84,7 @@ void RenderProxy::setName(const char* name) {
|
||||
|
||||
void RenderProxy::setSurface(const sp<Surface>& surface) {
|
||||
mRenderThread.queue().post(
|
||||
[ this, surf = surface ]() mutable { mContext->setSurface(std::move(surf)); });
|
||||
[this, surf = surface]() mutable { mContext->setSurface(std::move(surf)); });
|
||||
}
|
||||
|
||||
void RenderProxy::allocateBuffers() {
|
||||
@@ -251,7 +251,7 @@ void RenderProxy::dumpGraphicsMemory(int fd) {
|
||||
|
||||
void RenderProxy::setProcessStatsBuffer(int fd) {
|
||||
auto& rt = RenderThread::getInstance();
|
||||
rt.queue().post([&rt, fd = dup(fd) ]() {
|
||||
rt.queue().post([&rt, fd = dup(fd)]() {
|
||||
rt.globalProfileData().switchStorageToAshmem(fd);
|
||||
close(fd);
|
||||
});
|
||||
@@ -285,7 +285,7 @@ void RenderProxy::setContentDrawBounds(int left, int top, int right, int bottom)
|
||||
void RenderProxy::setPictureCapturedCallback(
|
||||
const std::function<void(sk_sp<SkPicture>&&)>& callback) {
|
||||
mRenderThread.queue().post(
|
||||
[ this, cb = callback ]() { mContext->setPictureCapturedCallback(cb); });
|
||||
[this, cb = callback]() { mContext->setPictureCapturedCallback(cb); });
|
||||
}
|
||||
|
||||
void RenderProxy::setFrameCallback(std::function<void(int64_t)>&& callback) {
|
||||
@@ -297,13 +297,13 @@ void RenderProxy::setFrameCompleteCallback(std::function<void(int64_t)>&& callba
|
||||
}
|
||||
|
||||
void RenderProxy::addFrameMetricsObserver(FrameMetricsObserver* observerPtr) {
|
||||
mRenderThread.queue().post([ this, observer = sp{observerPtr} ]() {
|
||||
mRenderThread.queue().post([this, observer = sp{observerPtr}]() {
|
||||
mContext->addFrameMetricsObserver(observer.get());
|
||||
});
|
||||
}
|
||||
|
||||
void RenderProxy::removeFrameMetricsObserver(FrameMetricsObserver* observerPtr) {
|
||||
mRenderThread.queue().post([ this, observer = sp{observerPtr} ]() {
|
||||
mRenderThread.queue().post([this, observer = sp{observerPtr}]() {
|
||||
mContext->removeFrameMetricsObserver(observer.get());
|
||||
});
|
||||
}
|
||||
@@ -313,9 +313,8 @@ void RenderProxy::setForceDark(bool enable) {
|
||||
}
|
||||
|
||||
void RenderProxy::setRenderAheadDepth(int renderAhead) {
|
||||
mRenderThread.queue().post([ context = mContext, renderAhead ] {
|
||||
context->setRenderAheadDepth(renderAhead);
|
||||
});
|
||||
mRenderThread.queue().post(
|
||||
[context = mContext, renderAhead] { context->setRenderAheadDepth(renderAhead); });
|
||||
}
|
||||
|
||||
int RenderProxy::copySurfaceInto(sp<Surface>& surface, int left, int top, int right, int bottom,
|
||||
@@ -393,9 +392,7 @@ void RenderProxy::releaseVDAtlasEntries() {
|
||||
void RenderProxy::preload() {
|
||||
// Create RenderThread object and start the thread. Then preload Vulkan/EGL driver.
|
||||
auto& thread = RenderThread::getInstance();
|
||||
thread.queue().post([&thread]() {
|
||||
thread.preload();
|
||||
});
|
||||
thread.queue().post([&thread]() { thread.preload(); });
|
||||
}
|
||||
|
||||
} /* namespace renderthread */
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#include "RenderThread.h"
|
||||
|
||||
#include "../HardwareBitmapUploader.h"
|
||||
#include "CanvasContext.h"
|
||||
#include "DeviceInfo.h"
|
||||
#include "EglManager.h"
|
||||
@@ -29,7 +30,6 @@
|
||||
#include "utils/FatVector.h"
|
||||
#include "utils/TimeUtils.h"
|
||||
#include "utils/TraceUtils.h"
|
||||
#include "../HardwareBitmapUploader.h"
|
||||
|
||||
#ifdef HWUI_GLES_WRAP_ENABLED
|
||||
#include "debug/GlesDriver.h"
|
||||
@@ -410,9 +410,7 @@ bool RenderThread::isCurrent() {
|
||||
void RenderThread::preload() {
|
||||
// EGL driver is always preloaded only if HWUI renders with GL.
|
||||
if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaGL) {
|
||||
std::thread eglInitThread([]() {
|
||||
eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
});
|
||||
std::thread eglInitThread([]() { eglGetDisplay(EGL_DEFAULT_DISPLAY); });
|
||||
eglInitThread.detach();
|
||||
} else {
|
||||
requireVkContext();
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
#include "../JankTracker.h"
|
||||
#include "CacheManager.h"
|
||||
#include "TimeLord.h"
|
||||
#include "thread/ThreadBase.h"
|
||||
#include "WebViewFunctorManager.h"
|
||||
#include "thread/ThreadBase.h"
|
||||
#include "utils/TimeUtils.h"
|
||||
|
||||
#include <GrContext.h>
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
#include <GrBackendSurface.h>
|
||||
#include <GrContext.h>
|
||||
#include <GrTypes.h>
|
||||
#include <GrTypes.h>
|
||||
#include <vk/GrVkExtensions.h>
|
||||
#include <vk/GrVkTypes.h>
|
||||
|
||||
@@ -43,7 +42,7 @@ static void free_features_extensions_structs(const VkPhysicalDeviceFeatures2& fe
|
||||
// so we can get access to the pNext for the next struct.
|
||||
struct CommonVulkanHeader {
|
||||
VkStructureType sType;
|
||||
void* pNext;
|
||||
void* pNext;
|
||||
};
|
||||
|
||||
void* pNext = features.pNext;
|
||||
@@ -94,13 +93,13 @@ void VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFe
|
||||
VkResult err;
|
||||
|
||||
constexpr VkApplicationInfo app_info = {
|
||||
VK_STRUCTURE_TYPE_APPLICATION_INFO, // sType
|
||||
nullptr, // pNext
|
||||
"android framework", // pApplicationName
|
||||
0, // applicationVersion
|
||||
"android framework", // pEngineName
|
||||
0, // engineVerison
|
||||
mAPIVersion, // apiVersion
|
||||
VK_STRUCTURE_TYPE_APPLICATION_INFO, // sType
|
||||
nullptr, // pNext
|
||||
"android framework", // pApplicationName
|
||||
0, // applicationVersion
|
||||
"android framework", // pEngineName
|
||||
0, // engineVerison
|
||||
mAPIVersion, // apiVersion
|
||||
};
|
||||
|
||||
{
|
||||
@@ -128,14 +127,14 @@ void VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFe
|
||||
}
|
||||
|
||||
const VkInstanceCreateInfo instance_create = {
|
||||
VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // sType
|
||||
nullptr, // pNext
|
||||
0, // flags
|
||||
&app_info, // pApplicationInfo
|
||||
0, // enabledLayerNameCount
|
||||
nullptr, // ppEnabledLayerNames
|
||||
(uint32_t) mInstanceExtensions.size(), // enabledExtensionNameCount
|
||||
mInstanceExtensions.data(), // ppEnabledExtensionNames
|
||||
VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // sType
|
||||
nullptr, // pNext
|
||||
0, // flags
|
||||
&app_info, // pApplicationInfo
|
||||
0, // enabledLayerNameCount
|
||||
nullptr, // ppEnabledLayerNames
|
||||
(uint32_t)mInstanceExtensions.size(), // enabledExtensionNameCount
|
||||
mInstanceExtensions.data(), // ppEnabledExtensionNames
|
||||
};
|
||||
|
||||
GET_PROC(CreateInstance);
|
||||
@@ -200,11 +199,11 @@ void VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFe
|
||||
{
|
||||
uint32_t extensionCount = 0;
|
||||
err = mEnumerateDeviceExtensionProperties(mPhysicalDevice, nullptr, &extensionCount,
|
||||
nullptr);
|
||||
nullptr);
|
||||
LOG_ALWAYS_FATAL_IF(VK_SUCCESS != err);
|
||||
mDeviceExtensionsOwner.resize(extensionCount);
|
||||
err = mEnumerateDeviceExtensionProperties(mPhysicalDevice, nullptr, &extensionCount,
|
||||
mDeviceExtensionsOwner.data());
|
||||
mDeviceExtensionsOwner.data());
|
||||
LOG_ALWAYS_FATAL_IF(VK_SUCCESS != err);
|
||||
bool hasKHRSwapchainExtension = false;
|
||||
for (const VkExtensionProperties& extension : mDeviceExtensionsOwner) {
|
||||
@@ -216,7 +215,7 @@ void VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFe
|
||||
LOG_ALWAYS_FATAL_IF(!hasKHRSwapchainExtension);
|
||||
}
|
||||
|
||||
auto getProc = [] (const char* proc_name, VkInstance instance, VkDevice device) {
|
||||
auto getProc = [](const char* proc_name, VkInstance instance, VkDevice device) {
|
||||
if (device != VK_NULL_HANDLE) {
|
||||
return vkGetDeviceProcAddr(device, proc_name);
|
||||
}
|
||||
@@ -224,7 +223,8 @@ void VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFe
|
||||
};
|
||||
|
||||
grExtensions.init(getProc, mInstance, mPhysicalDevice, mInstanceExtensions.size(),
|
||||
mInstanceExtensions.data(), mDeviceExtensions.size(), mDeviceExtensions.data());
|
||||
mInstanceExtensions.data(), mDeviceExtensions.size(),
|
||||
mDeviceExtensions.data());
|
||||
|
||||
LOG_ALWAYS_FATAL_IF(!grExtensions.hasExtension(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, 1));
|
||||
|
||||
@@ -237,7 +237,7 @@ void VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFe
|
||||
|
||||
if (grExtensions.hasExtension(VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME, 2)) {
|
||||
VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT* blend;
|
||||
blend = (VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT*) malloc(
|
||||
blend = (VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT*)malloc(
|
||||
sizeof(VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT));
|
||||
LOG_ALWAYS_FATAL_IF(!blend);
|
||||
blend->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT;
|
||||
@@ -247,7 +247,7 @@ void VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFe
|
||||
}
|
||||
|
||||
VkPhysicalDeviceSamplerYcbcrConversionFeatures* ycbcrFeature;
|
||||
ycbcrFeature = (VkPhysicalDeviceSamplerYcbcrConversionFeatures*) malloc(
|
||||
ycbcrFeature = (VkPhysicalDeviceSamplerYcbcrConversionFeatures*)malloc(
|
||||
sizeof(VkPhysicalDeviceSamplerYcbcrConversionFeatures));
|
||||
LOG_ALWAYS_FATAL_IF(!ycbcrFeature);
|
||||
ycbcrFeature->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES;
|
||||
@@ -261,17 +261,17 @@ void VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFe
|
||||
// and we can't depend on it on all platforms
|
||||
features.features.robustBufferAccess = VK_FALSE;
|
||||
|
||||
float queuePriorities[1] = { 0.0 };
|
||||
float queuePriorities[1] = {0.0};
|
||||
|
||||
void* queueNextPtr = nullptr;
|
||||
|
||||
VkDeviceQueueGlobalPriorityCreateInfoEXT queuePriorityCreateInfo;
|
||||
|
||||
if (Properties::contextPriority != 0
|
||||
&& grExtensions.hasExtension(VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME, 2)) {
|
||||
if (Properties::contextPriority != 0 &&
|
||||
grExtensions.hasExtension(VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME, 2)) {
|
||||
memset(&queuePriorityCreateInfo, 0, sizeof(VkDeviceQueueGlobalPriorityCreateInfoEXT));
|
||||
queuePriorityCreateInfo.sType =
|
||||
VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT;
|
||||
VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT;
|
||||
queuePriorityCreateInfo.pNext = nullptr;
|
||||
switch (Properties::contextPriority) {
|
||||
case EGL_CONTEXT_PRIORITY_LOW_IMG:
|
||||
@@ -285,41 +285,40 @@ void VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFe
|
||||
break;
|
||||
default:
|
||||
LOG_ALWAYS_FATAL("Unsupported context priority");
|
||||
}
|
||||
queueNextPtr = &queuePriorityCreateInfo;
|
||||
}
|
||||
queueNextPtr = &queuePriorityCreateInfo;
|
||||
}
|
||||
|
||||
const VkDeviceQueueCreateInfo queueInfo[2] = {
|
||||
{
|
||||
VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
|
||||
queueNextPtr, // pNext
|
||||
0, // VkDeviceQueueCreateFlags
|
||||
mGraphicsQueueIndex, // queueFamilyIndex
|
||||
1, // queueCount
|
||||
queuePriorities, // pQueuePriorities
|
||||
},
|
||||
{
|
||||
VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
|
||||
queueNextPtr, // pNext
|
||||
0, // VkDeviceQueueCreateFlags
|
||||
mPresentQueueIndex, // queueFamilyIndex
|
||||
1, // queueCount
|
||||
queuePriorities, // pQueuePriorities
|
||||
}
|
||||
};
|
||||
{
|
||||
VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
|
||||
queueNextPtr, // pNext
|
||||
0, // VkDeviceQueueCreateFlags
|
||||
mGraphicsQueueIndex, // queueFamilyIndex
|
||||
1, // queueCount
|
||||
queuePriorities, // pQueuePriorities
|
||||
},
|
||||
{
|
||||
VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
|
||||
queueNextPtr, // pNext
|
||||
0, // VkDeviceQueueCreateFlags
|
||||
mPresentQueueIndex, // queueFamilyIndex
|
||||
1, // queueCount
|
||||
queuePriorities, // pQueuePriorities
|
||||
}};
|
||||
uint32_t queueInfoCount = (mPresentQueueIndex != mGraphicsQueueIndex) ? 2 : 1;
|
||||
|
||||
const VkDeviceCreateInfo deviceInfo = {
|
||||
VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // sType
|
||||
&features, // pNext
|
||||
0, // VkDeviceCreateFlags
|
||||
queueInfoCount, // queueCreateInfoCount
|
||||
queueInfo, // pQueueCreateInfos
|
||||
0, // layerCount
|
||||
nullptr, // ppEnabledLayerNames
|
||||
(uint32_t) mDeviceExtensions.size(), // extensionCount
|
||||
mDeviceExtensions.data(), // ppEnabledExtensionNames
|
||||
nullptr, // ppEnabledFeatures
|
||||
VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // sType
|
||||
&features, // pNext
|
||||
0, // VkDeviceCreateFlags
|
||||
queueInfoCount, // queueCreateInfoCount
|
||||
queueInfo, // pQueueCreateInfos
|
||||
0, // layerCount
|
||||
nullptr, // ppEnabledLayerNames
|
||||
(uint32_t)mDeviceExtensions.size(), // extensionCount
|
||||
mDeviceExtensions.data(), // ppEnabledExtensionNames
|
||||
nullptr, // ppEnabledFeatures
|
||||
};
|
||||
|
||||
LOG_ALWAYS_FATAL_IF(mCreateDevice(mPhysicalDevice, &deviceInfo, nullptr, &mDevice));
|
||||
@@ -371,8 +370,8 @@ void VulkanManager::initialize() {
|
||||
// this needs to be on the render queue
|
||||
commandPoolInfo.queueFamilyIndex = mGraphicsQueueIndex;
|
||||
commandPoolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
|
||||
SkDEBUGCODE(VkResult res =) mCreateCommandPool(mDevice, &commandPoolInfo, nullptr,
|
||||
&mCommandPool);
|
||||
SkDEBUGCODE(VkResult res =)
|
||||
mCreateCommandPool(mDevice, &commandPoolInfo, nullptr, &mCommandPool);
|
||||
SkASSERT(VK_SUCCESS == res);
|
||||
}
|
||||
LOG_ALWAYS_FATAL_IF(mCommandPool == VK_NULL_HANDLE);
|
||||
@@ -391,7 +390,7 @@ void VulkanManager::initialize() {
|
||||
}
|
||||
|
||||
sk_sp<GrContext> VulkanManager::createContext(const GrContextOptions& options) {
|
||||
auto getProc = [] (const char* proc_name, VkInstance instance, VkDevice device) {
|
||||
auto getProc = [](const char* proc_name, VkInstance instance, VkDevice device) {
|
||||
if (device != VK_NULL_HANDLE) {
|
||||
return vkGetDeviceProcAddr(device, proc_name);
|
||||
}
|
||||
@@ -431,7 +430,6 @@ VkFunctorInitParams VulkanManager::getVkFunctorInitParams() const {
|
||||
}
|
||||
|
||||
Frame VulkanManager::dequeueNextBuffer(VulkanSurface* surface) {
|
||||
|
||||
VulkanSurface::NativeBufferInfo* bufferInfo = surface->dequeueNativeBuffer();
|
||||
|
||||
if (bufferInfo == nullptr) {
|
||||
@@ -480,7 +478,7 @@ Frame VulkanManager::dequeueNextBuffer(VulkanSurface* surface) {
|
||||
bufferInfo->skSurface->wait(1, &backendSemaphore);
|
||||
// The following flush blocks the GPU immediately instead of waiting for other
|
||||
// drawing ops. It seems dequeue_fence is not respected otherwise.
|
||||
//TODO: remove the flush after finding why backendSemaphore is not working.
|
||||
// TODO: remove the flush after finding why backendSemaphore is not working.
|
||||
bufferInfo->skSurface->flush();
|
||||
}
|
||||
}
|
||||
@@ -557,15 +555,15 @@ void VulkanManager::destroySurface(VulkanSurface* surface) {
|
||||
|
||||
VulkanSurface* VulkanManager::createSurface(ANativeWindow* window, ColorMode colorMode,
|
||||
sk_sp<SkColorSpace> surfaceColorSpace,
|
||||
SkColorType surfaceColorType,
|
||||
GrContext* grContext) {
|
||||
SkColorType surfaceColorType, GrContext* grContext,
|
||||
uint32_t extraBuffers) {
|
||||
LOG_ALWAYS_FATAL_IF(!hasVkContext(), "Not initialized");
|
||||
if (!window) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return VulkanSurface::Create(window, colorMode, surfaceColorType, surfaceColorSpace, grContext,
|
||||
*this);
|
||||
*this, extraBuffers);
|
||||
}
|
||||
|
||||
bool VulkanManager::setupDummyCommandBuffer() {
|
||||
|
||||
@@ -18,16 +18,16 @@
|
||||
#define VULKANMANAGER_H
|
||||
|
||||
#if !defined(VK_USE_PLATFORM_ANDROID_KHR)
|
||||
# define VK_USE_PLATFORM_ANDROID_KHR
|
||||
#define VK_USE_PLATFORM_ANDROID_KHR
|
||||
#endif
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
#include <GrContextOptions.h>
|
||||
#include <vk/GrVkExtensions.h>
|
||||
#include <SkSurface.h>
|
||||
#include <ui/Fence.h>
|
||||
#include <utils/StrongPointer.h>
|
||||
#include <vk/GrVkBackendContext.h>
|
||||
#include <vk/GrVkExtensions.h>
|
||||
#include "Frame.h"
|
||||
#include "IRenderPipeline.h"
|
||||
#include "VulkanSurface.h"
|
||||
@@ -59,8 +59,8 @@ public:
|
||||
// Create and destroy functions for wrapping an ANativeWindow in a VulkanSurface
|
||||
VulkanSurface* createSurface(ANativeWindow* window, ColorMode colorMode,
|
||||
sk_sp<SkColorSpace> surfaceColorSpace,
|
||||
SkColorType surfaceColorType,
|
||||
GrContext* grContext);
|
||||
SkColorType surfaceColorType, GrContext* grContext,
|
||||
uint32_t extraBuffers);
|
||||
void destroySurface(VulkanSurface* surface);
|
||||
|
||||
Frame dequeueNextBuffer(VulkanSurface* surface);
|
||||
|
||||
@@ -16,12 +16,12 @@
|
||||
|
||||
#include "VulkanSurface.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <SkSurface.h>
|
||||
#include <algorithm>
|
||||
|
||||
#include "VulkanManager.h"
|
||||
#include "utils/TraceUtils.h"
|
||||
#include "utils/Color.h"
|
||||
#include "utils/TraceUtils.h"
|
||||
|
||||
namespace android {
|
||||
namespace uirenderer {
|
||||
@@ -31,10 +31,9 @@ static bool IsTransformSupported(int transform) {
|
||||
// For now, only support pure rotations, not flip or flip-and-rotate, until we have
|
||||
// more time to test them and build sample code. As far as I know we never actually
|
||||
// use anything besides pure rotations anyway.
|
||||
return transform == 0
|
||||
|| transform == NATIVE_WINDOW_TRANSFORM_ROT_90
|
||||
|| transform == NATIVE_WINDOW_TRANSFORM_ROT_180
|
||||
|| transform == NATIVE_WINDOW_TRANSFORM_ROT_270;
|
||||
return transform == 0 || transform == NATIVE_WINDOW_TRANSFORM_ROT_90 ||
|
||||
transform == NATIVE_WINDOW_TRANSFORM_ROT_180 ||
|
||||
transform == NATIVE_WINDOW_TRANSFORM_ROT_270;
|
||||
}
|
||||
|
||||
static int InvertTransform(int transform) {
|
||||
@@ -85,16 +84,16 @@ static SkMatrix GetPreTransformMatrix(SkISize windowSize, int transform) {
|
||||
}
|
||||
|
||||
void VulkanSurface::ComputeWindowSizeAndTransform(WindowInfo* windowInfo, const SkISize& minSize,
|
||||
const SkISize& maxSize) {
|
||||
const SkISize& maxSize) {
|
||||
SkISize& windowSize = windowInfo->size;
|
||||
|
||||
// clamp width & height to handle currentExtent of -1 and protect us from broken hints
|
||||
if (windowSize.width() < minSize.width() || windowSize.width() > maxSize.width()
|
||||
|| windowSize.height() < minSize.height() || windowSize.height() > maxSize.height()) {
|
||||
if (windowSize.width() < minSize.width() || windowSize.width() > maxSize.width() ||
|
||||
windowSize.height() < minSize.height() || windowSize.height() > maxSize.height()) {
|
||||
int width = std::min(maxSize.width(), std::max(minSize.width(), windowSize.width()));
|
||||
int height = std::min(maxSize.height(), std::max(minSize.height(), windowSize.height()));
|
||||
ALOGE("Invalid Window Dimensions [%d, %d]; clamping to [%d, %d]",
|
||||
windowSize.width(), windowSize.height(), width, height);
|
||||
ALOGE("Invalid Window Dimensions [%d, %d]; clamping to [%d, %d]", windowSize.width(),
|
||||
windowSize.height(), width, height);
|
||||
windowSize.set(width, height);
|
||||
}
|
||||
|
||||
@@ -145,12 +144,8 @@ class VkSurfaceAutoDeleter {
|
||||
public:
|
||||
VkSurfaceAutoDeleter(VkInstance instance, VkSurfaceKHR surface,
|
||||
PFN_vkDestroySurfaceKHR destroySurfaceKHR)
|
||||
: mInstance(instance)
|
||||
, mSurface(surface)
|
||||
, mDestroySurfaceKHR(destroySurfaceKHR) {}
|
||||
~VkSurfaceAutoDeleter() {
|
||||
destroy();
|
||||
}
|
||||
: mInstance(instance), mSurface(surface), mDestroySurfaceKHR(destroySurfaceKHR) {}
|
||||
~VkSurfaceAutoDeleter() { destroy(); }
|
||||
|
||||
void destroy() {
|
||||
if (mSurface != VK_NULL_HANDLE) {
|
||||
@@ -166,9 +161,9 @@ private:
|
||||
};
|
||||
|
||||
VulkanSurface* VulkanSurface::Create(ANativeWindow* window, ColorMode colorMode,
|
||||
SkColorType colorType, sk_sp<SkColorSpace> colorSpace,
|
||||
GrContext* grContext, const VulkanManager& vkManager) {
|
||||
|
||||
SkColorType colorType, sk_sp<SkColorSpace> colorSpace,
|
||||
GrContext* grContext, const VulkanManager& vkManager,
|
||||
uint32_t extraBuffers) {
|
||||
VkAndroidSurfaceCreateInfoKHR surfaceCreateInfo;
|
||||
memset(&surfaceCreateInfo, 0, sizeof(VkAndroidSurfaceCreateInfoKHR));
|
||||
surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
|
||||
@@ -188,10 +183,11 @@ VulkanSurface* VulkanSurface::Create(ANativeWindow* window, ColorMode colorMode,
|
||||
vkManager.mDestroySurfaceKHR);
|
||||
|
||||
SkDEBUGCODE(VkBool32 supported; res = vkManager.mGetPhysicalDeviceSurfaceSupportKHR(
|
||||
vkManager.mPhysicalDevice, vkManager.mPresentQueueIndex, vkSurface, &supported);
|
||||
// All physical devices and queue families on Android must be capable of
|
||||
// presentation with any native window.
|
||||
SkASSERT(VK_SUCCESS == res && supported););
|
||||
vkManager.mPhysicalDevice, vkManager.mPresentQueueIndex,
|
||||
vkSurface, &supported);
|
||||
// All physical devices and queue families on Android must be capable of
|
||||
// presentation with any native window.
|
||||
SkASSERT(VK_SUCCESS == res && supported););
|
||||
|
||||
// check for capabilities
|
||||
VkSurfaceCapabilitiesKHR caps;
|
||||
@@ -225,14 +221,13 @@ VulkanSurface* VulkanSurface::Create(ANativeWindow* window, ColorMode colorMode,
|
||||
int query_value;
|
||||
int err = window->query(window, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &query_value);
|
||||
if (err != 0 || query_value < 0) {
|
||||
ALOGE("window->query failed: %s (%d) value=%d", strerror(-err), err,
|
||||
query_value);
|
||||
ALOGE("window->query failed: %s (%d) value=%d", strerror(-err), err, query_value);
|
||||
return nullptr;
|
||||
}
|
||||
auto min_undequeued_buffers = static_cast<uint32_t>(query_value);
|
||||
|
||||
windowInfo.bufferCount = min_undequeued_buffers
|
||||
+ std::max(VulkanSurface::sTargetBufferCount, caps.minImageCount);
|
||||
windowInfo.bufferCount = min_undequeued_buffers +
|
||||
std::max(sTargetBufferCount + extraBuffers, caps.minImageCount);
|
||||
if (caps.maxImageCount > 0 && windowInfo.bufferCount > caps.maxImageCount) {
|
||||
// Application must settle for fewer images than desired:
|
||||
windowInfo.bufferCount = caps.maxImageCount;
|
||||
@@ -241,8 +236,7 @@ VulkanSurface* VulkanSurface::Create(ANativeWindow* window, ColorMode colorMode,
|
||||
// Currently Skia requires the images to be color attachments and support all transfer
|
||||
// operations.
|
||||
VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
|
||||
VK_IMAGE_USAGE_SAMPLED_BIT |
|
||||
VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
|
||||
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
|
||||
VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||
LOG_ALWAYS_FATAL_IF((caps.supportedUsageFlags & usageFlags) != usageFlags);
|
||||
|
||||
@@ -336,7 +330,8 @@ bool VulkanSurface::UpdateWindow(ANativeWindow* window, const WindowInfo& window
|
||||
err = native_window_set_buffers_data_space(window, windowInfo.dataspace);
|
||||
if (err != 0) {
|
||||
ALOGE("VulkanSurface::UpdateWindow() native_window_set_buffers_data_space(%d) "
|
||||
"failed: %s (%d)", windowInfo.dataspace, strerror(-err), err);
|
||||
"failed: %s (%d)",
|
||||
windowInfo.dataspace, strerror(-err), err);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -344,7 +339,8 @@ bool VulkanSurface::UpdateWindow(ANativeWindow* window, const WindowInfo& window
|
||||
err = native_window_set_buffers_dimensions(window, size.width(), size.height());
|
||||
if (err != 0) {
|
||||
ALOGE("VulkanSurface::UpdateWindow() native_window_set_buffers_dimensions(%d,%d) "
|
||||
"failed: %s (%d)", size.width(), size.height(), strerror(-err), err);
|
||||
"failed: %s (%d)",
|
||||
size.width(), size.height(), strerror(-err), err);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -357,7 +353,8 @@ bool VulkanSurface::UpdateWindow(ANativeWindow* window, const WindowInfo& window
|
||||
err = native_window_set_buffers_transform(window, InvertTransform(windowInfo.transform));
|
||||
if (err != 0) {
|
||||
ALOGE("VulkanSurface::UpdateWindow() native_window_set_buffers_transform(%d) "
|
||||
"failed: %s (%d)", windowInfo.transform, strerror(-err), err);
|
||||
"failed: %s (%d)",
|
||||
windowInfo.transform, strerror(-err), err);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -366,7 +363,8 @@ bool VulkanSurface::UpdateWindow(ANativeWindow* window, const WindowInfo& window
|
||||
err = native_window_set_scaling_mode(window, NATIVE_WINDOW_SCALING_MODE_FREEZE);
|
||||
if (err != 0) {
|
||||
ALOGE("VulkanSurface::UpdateWindow() native_window_set_scaling_mode(SCALE_TO_WINDOW) "
|
||||
"failed: %s (%d)", strerror(-err), err);
|
||||
"failed: %s (%d)",
|
||||
strerror(-err), err);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -388,12 +386,12 @@ bool VulkanSurface::UpdateWindow(ANativeWindow* window, const WindowInfo& window
|
||||
}
|
||||
|
||||
VulkanSurface::VulkanSurface(ANativeWindow* window, const WindowInfo& windowInfo,
|
||||
SkISize minWindowSize, SkISize maxWindowSize, GrContext* grContext)
|
||||
SkISize minWindowSize, SkISize maxWindowSize, GrContext* grContext)
|
||||
: mNativeWindow(window)
|
||||
, mWindowInfo(windowInfo)
|
||||
, mGrContext(grContext)
|
||||
, mMinWindowSize(minWindowSize)
|
||||
, mMaxWindowSize(maxWindowSize) { }
|
||||
, mMaxWindowSize(maxWindowSize) {}
|
||||
|
||||
VulkanSurface::~VulkanSurface() {
|
||||
releaseBuffers();
|
||||
@@ -436,8 +434,7 @@ VulkanSurface::NativeBufferInfo* VulkanSurface::dequeueNativeBuffer() {
|
||||
// value at the end of the function if everything dequeued correctly.
|
||||
mCurrentBufferInfo = nullptr;
|
||||
|
||||
|
||||
//check if the native window has been resized or rotated and update accordingly
|
||||
// check if the native window has been resized or rotated and update accordingly
|
||||
SkISize newSize = SkISize::MakeEmpty();
|
||||
int transformHint = 0;
|
||||
mNativeWindow->query(mNativeWindow.get(), NATIVE_WINDOW_WIDTH, &newSize.fWidth);
|
||||
@@ -457,8 +454,8 @@ VulkanSurface::NativeBufferInfo* VulkanSurface::dequeueNativeBuffer() {
|
||||
newWindowInfo.actualSize.height());
|
||||
if (err != 0) {
|
||||
ALOGE("native_window_set_buffers_dimensions(%d,%d) failed: %s (%d)",
|
||||
newWindowInfo.actualSize.width(),
|
||||
newWindowInfo.actualSize.height(), strerror(-err), err);
|
||||
newWindowInfo.actualSize.width(), newWindowInfo.actualSize.height(),
|
||||
strerror(-err), err);
|
||||
return nullptr;
|
||||
}
|
||||
// reset the NativeBufferInfo (including SkSurface) associated with the old buffers. The
|
||||
@@ -469,7 +466,7 @@ VulkanSurface::NativeBufferInfo* VulkanSurface::dequeueNativeBuffer() {
|
||||
|
||||
if (newWindowInfo.transform != mWindowInfo.transform) {
|
||||
err = native_window_set_buffers_transform(mNativeWindow.get(),
|
||||
InvertTransform(newWindowInfo.transform));
|
||||
InvertTransform(newWindowInfo.transform));
|
||||
if (err != 0) {
|
||||
ALOGE("native_window_set_buffers_transform(%d) failed: %s (%d)",
|
||||
newWindowInfo.transform, strerror(-err), err);
|
||||
@@ -512,11 +509,9 @@ VulkanSurface::NativeBufferInfo* VulkanSurface::dequeueNativeBuffer() {
|
||||
VulkanSurface::NativeBufferInfo* bufferInfo = &mNativeBuffers[idx];
|
||||
|
||||
if (bufferInfo->skSurface.get() == nullptr) {
|
||||
bufferInfo->skSurface =
|
||||
SkSurface::MakeFromAHardwareBuffer(mGrContext,
|
||||
ANativeWindowBuffer_getHardwareBuffer(bufferInfo->buffer.get()),
|
||||
kTopLeft_GrSurfaceOrigin, DataSpaceToColorSpace(mWindowInfo.dataspace),
|
||||
nullptr);
|
||||
bufferInfo->skSurface = SkSurface::MakeFromAHardwareBuffer(
|
||||
mGrContext, ANativeWindowBuffer_getHardwareBuffer(bufferInfo->buffer.get()),
|
||||
kTopLeft_GrSurfaceOrigin, DataSpaceToColorSpace(mWindowInfo.dataspace), nullptr);
|
||||
if (bufferInfo->skSurface.get() == nullptr) {
|
||||
ALOGE("SkSurface::MakeFromAHardwareBuffer failed");
|
||||
mNativeWindow->cancelBuffer(mNativeWindow.get(), buffer, fence_fd);
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
#include <system/window.h>
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
#include <SkSize.h>
|
||||
#include <SkRefCnt.h>
|
||||
#include <SkSize.h>
|
||||
|
||||
#include "IRenderPipeline.h"
|
||||
|
||||
@@ -34,12 +34,9 @@ class VulkanManager;
|
||||
|
||||
class VulkanSurface {
|
||||
public:
|
||||
static VulkanSurface* Create(ANativeWindow* window,
|
||||
ColorMode colorMode,
|
||||
SkColorType colorType,
|
||||
sk_sp<SkColorSpace> colorSpace,
|
||||
GrContext* grContext,
|
||||
const VulkanManager& vkManager);
|
||||
static VulkanSurface* Create(ANativeWindow* window, ColorMode colorMode, SkColorType colorType,
|
||||
sk_sp<SkColorSpace> colorSpace, GrContext* grContext,
|
||||
const VulkanManager& vkManager, uint32_t extraBuffers);
|
||||
~VulkanSurface();
|
||||
|
||||
sk_sp<SkSurface> getCurrentSkSurface() {
|
||||
@@ -104,15 +101,10 @@ private:
|
||||
SkMatrix preTransform;
|
||||
};
|
||||
|
||||
VulkanSurface(ANativeWindow* window,
|
||||
const WindowInfo& windowInfo,
|
||||
SkISize minWindowSize,
|
||||
SkISize maxWindowSize,
|
||||
GrContext* grContext);
|
||||
static bool UpdateWindow(ANativeWindow* window,
|
||||
const WindowInfo& windowInfo);
|
||||
static void ComputeWindowSizeAndTransform(WindowInfo* windowInfo,
|
||||
const SkISize& minSize,
|
||||
VulkanSurface(ANativeWindow* window, const WindowInfo& windowInfo, SkISize minWindowSize,
|
||||
SkISize maxWindowSize, GrContext* grContext);
|
||||
static bool UpdateWindow(ANativeWindow* window, const WindowInfo& windowInfo);
|
||||
static void ComputeWindowSizeAndTransform(WindowInfo* windowInfo, const SkISize& minSize,
|
||||
const SkISize& maxSize);
|
||||
void releaseBuffers();
|
||||
|
||||
|
||||
@@ -31,6 +31,9 @@
|
||||
#include "renderthread/CanvasContext.h"
|
||||
#include "tests/common/TestUtils.h"
|
||||
|
||||
#include <gui/BufferItemConsumer.h>
|
||||
#include <gui/Surface.h>
|
||||
|
||||
using namespace android;
|
||||
using namespace android::uirenderer;
|
||||
using namespace android::uirenderer::renderthread;
|
||||
@@ -421,10 +424,20 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, clip_replace) {
|
||||
EXPECT_EQ(1, surface->canvas()->mDrawCounter);
|
||||
}
|
||||
|
||||
static sp<Surface> createDummySurface() {
|
||||
sp<IGraphicBufferProducer> producer;
|
||||
sp<IGraphicBufferConsumer> consumer;
|
||||
BufferQueue::createBufferQueue(&producer, &consumer);
|
||||
producer->setMaxDequeuedBufferCount(1);
|
||||
producer->setAsyncMode(true);
|
||||
return new Surface(producer);
|
||||
}
|
||||
|
||||
RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, context_lost) {
|
||||
auto surface = createDummySurface();
|
||||
auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
|
||||
EXPECT_FALSE(pipeline->isSurfaceReady());
|
||||
EXPECT_TRUE(pipeline->setSurface((Surface*)0x01, SwapBehavior::kSwap_default, ColorMode::SRGB));
|
||||
EXPECT_TRUE(pipeline->setSurface(surface.get(), SwapBehavior::kSwap_default, ColorMode::SRGB, 0));
|
||||
EXPECT_TRUE(pipeline->isSurfaceReady());
|
||||
renderThread.destroyRenderingContext();
|
||||
EXPECT_FALSE(pipeline->isSurfaceReady());
|
||||
|
||||
Reference in New Issue
Block a user