Break Layer class into Gl and Vulkan subclasses
Test: manual testing Change-Id: Ibd2beed39de3ac6da7448e96496253cfe427dfbb
This commit is contained in:
@@ -75,6 +75,7 @@ hwui_src_files := \
|
||||
FrameInfo.cpp \
|
||||
FrameInfoVisualizer.cpp \
|
||||
GammaFontRenderer.cpp \
|
||||
GlLayer.cpp \
|
||||
GlopBuilder.cpp \
|
||||
GpuMemoryTracker.cpp \
|
||||
GradientCache.cpp \
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#include "Caches.h"
|
||||
|
||||
#include "GammaFontRenderer.h"
|
||||
#include "Layer.h"
|
||||
#include "GlLayer.h"
|
||||
#include "Properties.h"
|
||||
#include "renderstate/RenderState.h"
|
||||
#include "ShadowTessellator.h"
|
||||
@@ -170,9 +170,11 @@ void Caches::dumpMemoryUsage(String8 &log) {
|
||||
for (std::set<Layer*>::iterator it = mRenderState->mActiveLayers.begin();
|
||||
it != mRenderState->mActiveLayers.end(); it++) {
|
||||
const Layer* layer = *it;
|
||||
log.appendFormat(" Layer size %dx%d; texid=%u refs=%d\n",
|
||||
LOG_ALWAYS_FATAL_IF(layer->getApi() != Layer::Api::OpenGL);
|
||||
const GlLayer* glLayer = static_cast<const GlLayer*>(layer);
|
||||
log.appendFormat(" GlLayer size %dx%d; texid=%u refs=%d\n",
|
||||
layer->getWidth(), layer->getHeight(),
|
||||
layer->getTextureId(),
|
||||
glLayer->getTextureId(),
|
||||
layer->getStrongCount());
|
||||
memused += layer->getWidth() * layer->getHeight() * 4;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
#include "DeferredLayerUpdater.h"
|
||||
|
||||
#include "GlLayer.h"
|
||||
#include "renderthread/EglManager.h"
|
||||
#include "renderthread/RenderTask.h"
|
||||
#include "utils/PaintUtils.h"
|
||||
@@ -55,9 +56,12 @@ void DeferredLayerUpdater::apply() {
|
||||
mLayer->setAlpha(mAlpha, mMode);
|
||||
|
||||
if (mSurfaceTexture.get()) {
|
||||
LOG_ALWAYS_FATAL_IF(mLayer->getApi() != Layer::Api::OpenGL,
|
||||
"apply surfaceTexture with non GL backend %x, GL %x, VK %x",
|
||||
mLayer->getApi(), Layer::Api::OpenGL, Layer::Api::Vulkan);
|
||||
if (mNeedsGLContextAttach) {
|
||||
mNeedsGLContextAttach = false;
|
||||
mSurfaceTexture->attachToContext(mLayer->getTextureId());
|
||||
mSurfaceTexture->attachToContext(static_cast<GlLayer*>(mLayer)->getTextureId());
|
||||
}
|
||||
if (mUpdateTexImage) {
|
||||
mUpdateTexImage = false;
|
||||
@@ -71,6 +75,9 @@ void DeferredLayerUpdater::apply() {
|
||||
}
|
||||
|
||||
void DeferredLayerUpdater::doUpdateTexImage() {
|
||||
LOG_ALWAYS_FATAL_IF(mLayer->getApi() != Layer::Api::OpenGL,
|
||||
"doUpdateTexImage non GL backend %x, GL %x, VK %x",
|
||||
mLayer->getApi(), Layer::Api::OpenGL, Layer::Api::Vulkan);
|
||||
if (mSurfaceTexture->updateTexImage() == NO_ERROR) {
|
||||
float transform[16];
|
||||
|
||||
@@ -112,28 +119,36 @@ void DeferredLayerUpdater::doUpdateTexImage() {
|
||||
|
||||
void DeferredLayerUpdater::updateLayer(bool forceFilter, GLenum renderTarget,
|
||||
const float* textureTransform) {
|
||||
LOG_ALWAYS_FATAL_IF(mLayer->getApi() != Layer::Api::OpenGL,
|
||||
"updateLayer non GL backend %x, GL %x, VK %x",
|
||||
mLayer->getApi(), Layer::Api::OpenGL, Layer::Api::Vulkan);
|
||||
|
||||
mLayer->setBlend(mBlend);
|
||||
mLayer->setForceFilter(forceFilter);
|
||||
mLayer->setSize(mWidth, mHeight);
|
||||
mLayer->getTexTransform().load(textureTransform);
|
||||
|
||||
if (renderTarget != mLayer->getRenderTarget()) {
|
||||
mLayer->setRenderTarget(renderTarget);
|
||||
mLayer->bindTexture();
|
||||
mLayer->setFilter(GL_NEAREST, false, true);
|
||||
mLayer->setWrap(GL_CLAMP_TO_EDGE, false, true);
|
||||
GlLayer* glLayer = static_cast<GlLayer*>(mLayer);
|
||||
if (renderTarget != glLayer->getRenderTarget()) {
|
||||
glLayer->setRenderTarget(renderTarget);
|
||||
glLayer->bindTexture();
|
||||
glLayer->setFilter(GL_NEAREST, false, true);
|
||||
glLayer->setWrap(GL_CLAMP_TO_EDGE, false, true);
|
||||
}
|
||||
}
|
||||
|
||||
void DeferredLayerUpdater::detachSurfaceTexture() {
|
||||
if (mSurfaceTexture.get()) {
|
||||
LOG_ALWAYS_FATAL_IF(mLayer->getApi() != Layer::Api::OpenGL,
|
||||
"detachSurfaceTexture with non GL backend %x, GL %x, VK %x",
|
||||
mLayer->getApi(), Layer::Api::OpenGL, Layer::Api::Vulkan);
|
||||
status_t err = mSurfaceTexture->detachFromContext();
|
||||
if (err != 0) {
|
||||
// TODO: Elevate to fatal exception
|
||||
ALOGE("Failed to detach SurfaceTexture from context %d", err);
|
||||
}
|
||||
mSurfaceTexture = nullptr;
|
||||
mLayer->clearTexture();
|
||||
static_cast<GlLayer*>(mLayer)->clearTexture();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,9 @@
|
||||
#include <SkMatrix.h>
|
||||
#include <utils/StrongPointer.h>
|
||||
|
||||
#include <GLES2/gl2.h>
|
||||
#include <GLES2/gl2ext.h>
|
||||
|
||||
#include "Layer.h"
|
||||
#include "Rect.h"
|
||||
#include "renderthread/RenderThread.h"
|
||||
@@ -60,8 +63,8 @@ public:
|
||||
|
||||
ANDROID_API void setSurfaceTexture(const sp<GLConsumer>& texture, bool needsAttach) {
|
||||
if (texture.get() != mSurfaceTexture.get()) {
|
||||
mNeedsGLContextAttach = needsAttach;
|
||||
mSurfaceTexture = texture;
|
||||
mNeedsGLContextAttach = needsAttach;
|
||||
|
||||
GLenum target = texture->getCurrentTextureTarget();
|
||||
LOG_ALWAYS_FATAL_IF(target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES,
|
||||
|
||||
76
libs/hwui/GlLayer.cpp
Normal file
76
libs/hwui/GlLayer.cpp
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "GlLayer.h"
|
||||
|
||||
#include "Caches.h"
|
||||
#include "RenderNode.h"
|
||||
#include "renderstate/RenderState.h"
|
||||
#include "utils/TraceUtils.h"
|
||||
|
||||
#include <utils/Log.h>
|
||||
|
||||
#define ATRACE_LAYER_WORK(label) \
|
||||
ATRACE_FORMAT("%s HW Layer DisplayList %s %ux%u", \
|
||||
label, \
|
||||
(renderNode.get() != NULL) ? renderNode->getName() : "", \
|
||||
getWidth(), getHeight())
|
||||
|
||||
namespace android {
|
||||
namespace uirenderer {
|
||||
|
||||
GlLayer::GlLayer(RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight)
|
||||
: Layer(renderState, Api::OpenGL)
|
||||
, caches(Caches::getInstance())
|
||||
, texture(caches) {
|
||||
texture.mWidth = layerWidth;
|
||||
texture.mHeight = layerHeight;
|
||||
}
|
||||
|
||||
GlLayer::~GlLayer() {
|
||||
if (texture.mId) {
|
||||
texture.deleteTexture();
|
||||
}
|
||||
}
|
||||
|
||||
void GlLayer::onGlContextLost() {
|
||||
texture.deleteTexture();
|
||||
}
|
||||
|
||||
void GlLayer::bindTexture() const {
|
||||
if (texture.mId) {
|
||||
caches.textureState().bindTexture(texture.target(), texture.mId);
|
||||
}
|
||||
}
|
||||
|
||||
void GlLayer::generateTexture() {
|
||||
if (!texture.mId) {
|
||||
glGenTextures(1, &texture.mId);
|
||||
}
|
||||
}
|
||||
|
||||
void GlLayer::clearTexture() {
|
||||
// There's a rare possibility that Caches could have been destroyed already
|
||||
// since this method is queued up as a task.
|
||||
// Since this is a reset method, treat this as non-fatal.
|
||||
if (caches.isInitialized()) {
|
||||
caches.textureState().unbindTexture(texture.mId);
|
||||
}
|
||||
texture.mId = 0;
|
||||
}
|
||||
|
||||
}; // namespace uirenderer
|
||||
}; // namespace android
|
||||
112
libs/hwui/GlLayer.h
Normal file
112
libs/hwui/GlLayer.h
Normal file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Layer.h"
|
||||
|
||||
#include "Texture.h"
|
||||
|
||||
namespace android {
|
||||
namespace uirenderer {
|
||||
|
||||
// Forward declarations
|
||||
class Caches;
|
||||
|
||||
/**
|
||||
* A layer has dimensions and is backed by an OpenGL texture or FBO.
|
||||
*/
|
||||
class GlLayer : public Layer {
|
||||
public:
|
||||
GlLayer(RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight);
|
||||
virtual ~GlLayer();
|
||||
|
||||
uint32_t getWidth() const override {
|
||||
return texture.mWidth;
|
||||
}
|
||||
|
||||
uint32_t getHeight() const override {
|
||||
return texture.mHeight;
|
||||
}
|
||||
|
||||
void setSize(uint32_t width, uint32_t height) override {
|
||||
texture.updateSize(width, height, texture.internalFormat(), texture.format(),
|
||||
texture.target());
|
||||
}
|
||||
|
||||
void setBlend(bool blend) override {
|
||||
texture.blend = blend;
|
||||
}
|
||||
|
||||
bool isBlend() const override {
|
||||
return texture.blend;
|
||||
}
|
||||
|
||||
inline GLuint getTextureId() const {
|
||||
return texture.id();
|
||||
}
|
||||
|
||||
inline Texture& getTexture() {
|
||||
return texture;
|
||||
}
|
||||
|
||||
inline GLenum getRenderTarget() const {
|
||||
return texture.target();
|
||||
}
|
||||
|
||||
inline void setRenderTarget(GLenum renderTarget) {
|
||||
texture.mTarget = renderTarget;
|
||||
}
|
||||
|
||||
inline bool isRenderable() const {
|
||||
return texture.target() != GL_NONE;
|
||||
}
|
||||
|
||||
void setWrap(GLenum wrap, bool bindTexture = false, bool force = false) {
|
||||
texture.setWrap(wrap, bindTexture, force);
|
||||
}
|
||||
|
||||
void setFilter(GLenum filter, bool bindTexture = false, bool force = false) {
|
||||
texture.setFilter(filter, bindTexture, force);
|
||||
}
|
||||
|
||||
void bindTexture() const;
|
||||
void generateTexture();
|
||||
|
||||
/**
|
||||
* When the caller frees the texture itself, the caller
|
||||
* must call this method to tell this layer that it lost
|
||||
* the texture.
|
||||
*/
|
||||
void clearTexture();
|
||||
|
||||
/**
|
||||
* Lost the GL context but the layer is still around, mark it invalid internally
|
||||
* so the dtor knows not to do any GL work
|
||||
*/
|
||||
void onGlContextLost();
|
||||
|
||||
private:
|
||||
Caches& caches;
|
||||
|
||||
/**
|
||||
* The texture backing this layer.
|
||||
*/
|
||||
Texture texture;
|
||||
}; // struct GlLayer
|
||||
|
||||
}; // namespace uirenderer
|
||||
}; // namespace android
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "GlopBuilder.h"
|
||||
|
||||
#include "Caches.h"
|
||||
#include "GlLayer.h"
|
||||
#include "Glop.h"
|
||||
#include "Layer.h"
|
||||
#include "Matrix.h"
|
||||
@@ -440,7 +441,7 @@ GlopBuilder& GlopBuilder::setFillLayer(Texture& texture, const SkColorFilter* co
|
||||
return *this;
|
||||
}
|
||||
|
||||
GlopBuilder& GlopBuilder::setFillTextureLayer(Layer& layer, float alpha) {
|
||||
GlopBuilder& GlopBuilder::setFillTextureLayer(GlLayer& layer, float alpha) {
|
||||
TRIGGER_STAGE(kFillStage);
|
||||
REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ namespace android {
|
||||
namespace uirenderer {
|
||||
|
||||
class Caches;
|
||||
class GlLayer;
|
||||
class Matrix4;
|
||||
class Patch;
|
||||
class RenderState;
|
||||
@@ -71,7 +72,7 @@ public:
|
||||
GlopBuilder& setFillClear();
|
||||
GlopBuilder& setFillLayer(Texture& texture, const SkColorFilter* colorFilter,
|
||||
float alpha, SkBlendMode mode, Blend::ModeOrderSwap modeUsage);
|
||||
GlopBuilder& setFillTextureLayer(Layer& layer, float alpha);
|
||||
GlopBuilder& setFillTextureLayer(GlLayer& layer, float alpha);
|
||||
// TODO: setFillLayer normally forces its own wrap & filter mode,
|
||||
// which isn't always correct.
|
||||
GlopBuilder& setFillExternalTexture(Texture& texture, Matrix4& textureTransform);
|
||||
|
||||
@@ -16,77 +16,36 @@
|
||||
|
||||
#include "Layer.h"
|
||||
|
||||
#include "Caches.h"
|
||||
#include "RenderNode.h"
|
||||
#include "renderstate/RenderState.h"
|
||||
#include "utils/TraceUtils.h"
|
||||
|
||||
#include <utils/Log.h>
|
||||
|
||||
#define ATRACE_LAYER_WORK(label) \
|
||||
ATRACE_FORMAT("%s HW Layer DisplayList %s %ux%u", \
|
||||
label, \
|
||||
(renderNode.get() != NULL) ? renderNode->getName() : "", \
|
||||
getWidth(), getHeight())
|
||||
#include <SkColorFilter.h>
|
||||
|
||||
namespace android {
|
||||
namespace uirenderer {
|
||||
|
||||
Layer::Layer(RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight)
|
||||
Layer::Layer(RenderState& renderState, Api api)
|
||||
: GpuMemoryTracker(GpuObjectType::Layer)
|
||||
, state(State::Uncached)
|
||||
, caches(Caches::getInstance())
|
||||
, renderState(renderState)
|
||||
, texture(caches) {
|
||||
, mRenderState(renderState)
|
||||
, mApi(api) {
|
||||
// TODO: This is a violation of Android's typical ref counting, but it
|
||||
// preserves the old inc/dec ref locations. This should be changed...
|
||||
incStrong(nullptr);
|
||||
texture.mWidth = layerWidth;
|
||||
texture.mHeight = layerHeight;
|
||||
|
||||
renderState.registerLayer(this);
|
||||
}
|
||||
|
||||
Layer::~Layer() {
|
||||
renderState.unregisterLayer(this);
|
||||
SkSafeUnref(colorFilter);
|
||||
|
||||
if (texture.mId) {
|
||||
texture.deleteTexture();
|
||||
}
|
||||
}
|
||||
|
||||
void Layer::onGlContextLost() {
|
||||
texture.deleteTexture();
|
||||
mRenderState.unregisterLayer(this);
|
||||
}
|
||||
|
||||
void Layer::setColorFilter(SkColorFilter* filter) {
|
||||
SkRefCnt_SafeAssign(colorFilter, filter);
|
||||
}
|
||||
|
||||
void Layer::bindTexture() const {
|
||||
if (texture.mId) {
|
||||
caches.textureState().bindTexture(texture.target(), texture.mId);
|
||||
}
|
||||
}
|
||||
|
||||
void Layer::generateTexture() {
|
||||
if (!texture.mId) {
|
||||
glGenTextures(1, &texture.mId);
|
||||
}
|
||||
}
|
||||
|
||||
void Layer::clearTexture() {
|
||||
// There's a rare possibility that Caches could have been destroyed already
|
||||
// since this method is queued up as a task.
|
||||
// Since this is a reset method, treat this as non-fatal.
|
||||
if (caches.isInitialized()) {
|
||||
caches.textureState().unbindTexture(texture.mId);
|
||||
}
|
||||
texture.mId = 0;
|
||||
}
|
||||
|
||||
void Layer::postDecStrong() {
|
||||
renderState.postDecStrong(this);
|
||||
mRenderState.postDecStrong(this);
|
||||
}
|
||||
|
||||
}; // namespace uirenderer
|
||||
|
||||
@@ -16,25 +16,13 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cutils/compiler.h>
|
||||
#include <sys/types.h>
|
||||
#include <utils/StrongPointer.h>
|
||||
#include <utils/RefBase.h>
|
||||
#include <memory>
|
||||
|
||||
#include <GLES2/gl2.h>
|
||||
#include <GpuMemoryTracker.h>
|
||||
|
||||
#include <ui/Region.h>
|
||||
|
||||
#include <SkPaint.h>
|
||||
#include <SkBlendMode.h>
|
||||
|
||||
#include "Matrix.h"
|
||||
#include "Rect.h"
|
||||
#include "RenderBuffer.h"
|
||||
#include "Texture.h"
|
||||
#include "Vertex.h"
|
||||
|
||||
namespace android {
|
||||
namespace uirenderer {
|
||||
@@ -43,49 +31,33 @@ namespace uirenderer {
|
||||
// Layers
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Forward declarations
|
||||
class Caches;
|
||||
class RenderState;
|
||||
|
||||
/**
|
||||
* A layer has dimensions and is backed by an OpenGL texture or FBO.
|
||||
* A layer has dimensions and is backed by a backend specific texture or framebuffer.
|
||||
*/
|
||||
class Layer : public VirtualLightRefBase, GpuMemoryTracker {
|
||||
public:
|
||||
// layer lifecycle, controlled from outside
|
||||
enum class State {
|
||||
Uncached = 0,
|
||||
InCache = 1,
|
||||
FailedToCache = 2,
|
||||
RemovedFromCache = 3,
|
||||
DeletedFromCache = 4,
|
||||
InGarbageList = 5,
|
||||
enum class Api {
|
||||
OpenGL = 0,
|
||||
Vulkan = 1,
|
||||
};
|
||||
State state; // public for logging/debugging purposes
|
||||
|
||||
Layer(RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight);
|
||||
Api getApi() const {
|
||||
return mApi;
|
||||
}
|
||||
|
||||
~Layer();
|
||||
|
||||
inline uint32_t getWidth() const {
|
||||
return texture.mWidth;
|
||||
}
|
||||
virtual uint32_t getWidth() const = 0;
|
||||
|
||||
inline uint32_t getHeight() const {
|
||||
return texture.mHeight;
|
||||
}
|
||||
virtual uint32_t getHeight() const = 0;
|
||||
|
||||
void setSize(uint32_t width, uint32_t height) {
|
||||
texture.updateSize(width, height, texture.internalFormat(), texture.format(),
|
||||
texture.target());
|
||||
}
|
||||
virtual void setSize(uint32_t width, uint32_t height) = 0;
|
||||
|
||||
inline void setBlend(bool blend) {
|
||||
texture.blend = blend;
|
||||
}
|
||||
virtual void setBlend(bool blend) = 0;
|
||||
|
||||
inline bool isBlend() const {
|
||||
return texture.blend;
|
||||
}
|
||||
virtual bool isBlend() const = 0;
|
||||
|
||||
inline void setForceFilter(bool forceFilter) {
|
||||
this->forceFilter = forceFilter;
|
||||
@@ -112,50 +84,12 @@ public:
|
||||
return mode;
|
||||
}
|
||||
|
||||
inline GLuint getTextureId() const {
|
||||
return texture.id();
|
||||
}
|
||||
|
||||
inline Texture& getTexture() {
|
||||
return texture;
|
||||
}
|
||||
|
||||
inline GLenum getRenderTarget() const {
|
||||
return texture.target();
|
||||
}
|
||||
|
||||
inline void setRenderTarget(GLenum renderTarget) {
|
||||
texture.mTarget = renderTarget;
|
||||
}
|
||||
|
||||
inline bool isRenderable() const {
|
||||
return texture.target() != GL_NONE;
|
||||
}
|
||||
|
||||
void setWrap(GLenum wrap, bool bindTexture = false, bool force = false) {
|
||||
texture.setWrap(wrap, bindTexture, force);
|
||||
}
|
||||
|
||||
void setFilter(GLenum filter, bool bindTexture = false, bool force = false) {
|
||||
texture.setFilter(filter, bindTexture, force);
|
||||
}
|
||||
|
||||
inline SkColorFilter* getColorFilter() const {
|
||||
return colorFilter;
|
||||
}
|
||||
|
||||
void setColorFilter(SkColorFilter* filter);
|
||||
|
||||
void bindTexture() const;
|
||||
void generateTexture();
|
||||
|
||||
/**
|
||||
* When the caller frees the texture itself, the caller
|
||||
* must call this method to tell this layer that it lost
|
||||
* the texture.
|
||||
*/
|
||||
void clearTexture();
|
||||
|
||||
inline mat4& getTexTransform() {
|
||||
return texTransform;
|
||||
}
|
||||
@@ -170,21 +104,13 @@ public:
|
||||
*/
|
||||
void postDecStrong();
|
||||
|
||||
/**
|
||||
* Lost the GL context but the layer is still around, mark it invalid internally
|
||||
* so the dtor knows not to do any GL work
|
||||
*/
|
||||
void onGlContextLost();
|
||||
protected:
|
||||
Layer(RenderState& renderState, Api api);
|
||||
|
||||
RenderState& mRenderState;
|
||||
|
||||
private:
|
||||
Caches& caches;
|
||||
|
||||
RenderState& renderState;
|
||||
|
||||
/**
|
||||
* The texture backing this layer.
|
||||
*/
|
||||
Texture texture;
|
||||
Api mApi;
|
||||
|
||||
/**
|
||||
* Color filter used to draw this layer. Optional.
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#include "Caches.h"
|
||||
#include "Image.h"
|
||||
#include "GlopBuilder.h"
|
||||
#include "Layer.h"
|
||||
#include "GlLayer.h"
|
||||
#include "renderstate/RenderState.h"
|
||||
#include "renderthread/EglManager.h"
|
||||
#include "utils/GLUtils.h"
|
||||
@@ -262,7 +262,7 @@ CopyResult OpenGLReadbackImpl::copyImageInto(EGLImageKHR eglImage,
|
||||
}
|
||||
|
||||
bool OpenGLReadbackImpl::copyLayerInto(renderthread::RenderThread& renderThread,
|
||||
Layer& layer, SkBitmap* bitmap) {
|
||||
GlLayer& layer, SkBitmap* bitmap) {
|
||||
return CopyResult::Success == copyTextureInto(Caches::getInstance(),
|
||||
renderThread.renderState(), layer.getTexture(), layer.getTexTransform(),
|
||||
Rect(), bitmap);
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace android {
|
||||
namespace uirenderer {
|
||||
|
||||
class Matrix4;
|
||||
class Layer;
|
||||
class GlLayer;
|
||||
|
||||
class OpenGLReadback : public Readback {
|
||||
public:
|
||||
@@ -49,7 +49,7 @@ public:
|
||||
/**
|
||||
* Copies the layer's contents into the provided bitmap.
|
||||
*/
|
||||
static bool copyLayerInto(renderthread::RenderThread& renderThread, Layer& layer,
|
||||
static bool copyLayerInto(renderthread::RenderThread& renderThread, GlLayer& layer,
|
||||
SkBitmap* bitmap);
|
||||
|
||||
protected:
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "font/FontUtil.h"
|
||||
#include "GlLayer.h"
|
||||
#include "Matrix.h"
|
||||
#include "Rect.h"
|
||||
#include "RenderNode.h"
|
||||
@@ -413,7 +414,7 @@ struct TextOnPathOp : RecordedOp {
|
||||
};
|
||||
|
||||
struct TextureLayerOp : RecordedOp {
|
||||
TextureLayerOp(BASE_PARAMS_PAINTLESS, Layer* layer)
|
||||
TextureLayerOp(BASE_PARAMS_PAINTLESS, GlLayer* layer)
|
||||
: SUPER_PAINTLESS(TextureLayerOp)
|
||||
, layer(layer) {}
|
||||
|
||||
@@ -424,7 +425,7 @@ struct TextureLayerOp : RecordedOp {
|
||||
, layer(op.layer) {
|
||||
|
||||
}
|
||||
Layer* layer;
|
||||
GlLayer* layer;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -606,13 +606,14 @@ void RecordingCanvas::drawLayer(DeferredLayerUpdater* layerHandle) {
|
||||
// We ref the DeferredLayerUpdater due to its thread-safe ref-counting semantics.
|
||||
mDisplayList->ref(layerHandle);
|
||||
|
||||
LOG_ALWAYS_FATAL_IF(layerHandle->backingLayer()->getApi() != Layer::Api::OpenGL);
|
||||
// Note that the backing layer has *not* yet been updated, so don't trust
|
||||
// its width, height, transform, etc...!
|
||||
addOp(alloc().create_trivial<TextureLayerOp>(
|
||||
Rect(layerHandle->getWidth(), layerHandle->getHeight()),
|
||||
*(mState.currentSnapshot()->transform),
|
||||
getRecordedClip(),
|
||||
layerHandle->backingLayer()));
|
||||
static_cast<GlLayer*>(layerHandle->backingLayer())));
|
||||
}
|
||||
|
||||
void RecordingCanvas::callDrawGLFunction(Functor* functor,
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
#include "Caches.h"
|
||||
#include "Extensions.h"
|
||||
#include "Layer.h"
|
||||
#include "Matrix.h"
|
||||
#include "Texture.h"
|
||||
#include "hwui/Bitmap.h"
|
||||
@@ -317,42 +316,6 @@ bool tryStoreCompose(Caches& caches, const SkShader& shader, const Matrix4& mode
|
||||
return true;
|
||||
}
|
||||
|
||||
bool tryStoreLayer(Caches& caches, const SkShader& shader, const Matrix4& modelViewMatrix,
|
||||
GLuint* textureUnit, ProgramDescription* description,
|
||||
SkiaShaderData::LayerShaderData* outData) {
|
||||
Layer* layer;
|
||||
if (!shader.asACustomShader(reinterpret_cast<void**>(&layer))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
description->hasBitmap = true;
|
||||
outData->layer = layer;
|
||||
outData->bitmapSampler = (*textureUnit)++;
|
||||
|
||||
const float width = layer->getWidth();
|
||||
const float height = layer->getHeight();
|
||||
|
||||
computeScreenSpaceMatrix(outData->textureTransform, SkMatrix::I(), shader.getLocalMatrix(),
|
||||
modelViewMatrix);
|
||||
|
||||
outData->textureDimension[0] = 1.0f / width;
|
||||
outData->textureDimension[1] = 1.0f / height;
|
||||
return true;
|
||||
}
|
||||
|
||||
void applyLayer(Caches& caches, const SkiaShaderData::LayerShaderData& data) {
|
||||
caches.textureState().activateTexture(data.bitmapSampler);
|
||||
|
||||
data.layer->bindTexture();
|
||||
data.layer->setWrap(GL_CLAMP_TO_EDGE);
|
||||
data.layer->setFilter(GL_LINEAR);
|
||||
|
||||
glUniform1i(caches.program().getUniform("bitmapSampler"), data.bitmapSampler);
|
||||
glUniformMatrix4fv(caches.program().getUniform("textureTransform"), 1,
|
||||
GL_FALSE, &data.textureTransform.data[0]);
|
||||
glUniform2fv(caches.program().getUniform("textureDimension"), 1, &data.textureDimension[0]);
|
||||
}
|
||||
|
||||
void SkiaShader::store(Caches& caches, const SkShader& shader, const Matrix4& modelViewMatrix,
|
||||
GLuint* textureUnit, ProgramDescription* description,
|
||||
SkiaShaderData* outData) {
|
||||
@@ -374,12 +337,6 @@ void SkiaShader::store(Caches& caches, const SkShader& shader, const Matrix4& mo
|
||||
return;
|
||||
}
|
||||
|
||||
if (tryStoreLayer(caches, shader, modelViewMatrix,
|
||||
textureUnit, description, &outData->layerData)) {
|
||||
outData->skiaShaderType = kLayer_SkiaShaderType;
|
||||
return;
|
||||
}
|
||||
|
||||
// Unknown/unsupported type, so explicitly ignore shader
|
||||
outData->skiaShaderType = kNone_SkiaShaderType;
|
||||
}
|
||||
@@ -394,10 +351,6 @@ void SkiaShader::apply(Caches& caches, const SkiaShaderData& data,
|
||||
if (data.skiaShaderType & kBitmap_SkiaShaderType) {
|
||||
applyBitmap(caches, data.bitmapData);
|
||||
}
|
||||
|
||||
if (data.skiaShaderType == kLayer_SkiaShaderType) {
|
||||
applyLayer(caches, data.layerData);
|
||||
}
|
||||
}
|
||||
|
||||
}; // namespace uirenderer
|
||||
|
||||
@@ -29,7 +29,6 @@ namespace uirenderer {
|
||||
|
||||
class Caches;
|
||||
class Extensions;
|
||||
class Layer;
|
||||
class Texture;
|
||||
struct ProgramDescription;
|
||||
|
||||
@@ -45,7 +44,6 @@ enum SkiaShaderType {
|
||||
kBitmap_SkiaShaderType = 1,
|
||||
kGradient_SkiaShaderType = 2,
|
||||
kCompose_SkiaShaderType = kBitmap_SkiaShaderType | kGradient_SkiaShaderType,
|
||||
kLayer_SkiaShaderType = 4,
|
||||
};
|
||||
|
||||
struct SkiaShaderData {
|
||||
@@ -71,15 +69,6 @@ struct SkiaShaderData {
|
||||
GLuint gradientSampler;
|
||||
GLenum wrapST;
|
||||
} gradientData;
|
||||
struct LayerShaderData {
|
||||
Layer* layer;
|
||||
GLuint bitmapSampler;
|
||||
GLenum wrapS;
|
||||
GLenum wrapT;
|
||||
|
||||
Matrix4 textureTransform;
|
||||
float textureDimension[2];
|
||||
} layerData;
|
||||
};
|
||||
|
||||
class SkiaShader {
|
||||
|
||||
@@ -159,10 +159,10 @@ public:
|
||||
*/
|
||||
void* isInUse = nullptr;
|
||||
private:
|
||||
// TODO: Temporarily grant private access to Layer, remove once
|
||||
// Layer can be de-tangled from being a dual-purpose render target
|
||||
// TODO: Temporarily grant private access to GlLayer, remove once
|
||||
// GlLayer can be de-tangled from being a dual-purpose render target
|
||||
// and external texture wrapper
|
||||
friend class Layer;
|
||||
friend class GlLayer;
|
||||
|
||||
// Returns true if the size changed, false if it was the same
|
||||
bool updateSize(uint32_t width, uint32_t height, GLint internalFormat,
|
||||
|
||||
70
libs/hwui/VkLayer.h
Normal file
70
libs/hwui/VkLayer.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Layer.h"
|
||||
|
||||
#include <SkSurface.h>
|
||||
|
||||
namespace android {
|
||||
namespace uirenderer {
|
||||
/**
|
||||
* A layer has dimensions and is backed by a VkImage.
|
||||
*/
|
||||
class VkLayer : public Layer {
|
||||
public:
|
||||
VkLayer(RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight)
|
||||
: Layer(renderState, Api::Vulkan) {}
|
||||
|
||||
virtual ~VkLayer() {}
|
||||
|
||||
uint32_t getWidth() const override {
|
||||
return mWidth;
|
||||
}
|
||||
|
||||
uint32_t getHeight() const override {
|
||||
return mHeight;
|
||||
}
|
||||
|
||||
void setSize(uint32_t width, uint32_t height) override {
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
}
|
||||
|
||||
void setBlend(bool blend) override {
|
||||
mBlend = blend;
|
||||
}
|
||||
|
||||
bool isBlend() const override {
|
||||
return mBlend;
|
||||
}
|
||||
|
||||
sk_sp<SkSurface> getSurface() {
|
||||
return mSurface;
|
||||
}
|
||||
|
||||
private:
|
||||
int mWidth;
|
||||
int mHeight;
|
||||
bool mBlend;
|
||||
|
||||
sk_sp<SkSurface> mSurface;
|
||||
|
||||
}; // struct VkLayer
|
||||
|
||||
}; // namespace uirenderer
|
||||
}; // namespace android
|
||||
@@ -14,6 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "GlLayer.h"
|
||||
#include "LayerDrawable.h"
|
||||
#include "SkColorFilter.h"
|
||||
#include "gl/GrGLTypes.h"
|
||||
@@ -35,12 +36,14 @@ bool LayerDrawable::DrawLayer(GrContext* context, SkCanvas* canvas, Layer* layer
|
||||
layer->getTransform().copyTo(transform);
|
||||
canvas->concat(transform);
|
||||
}
|
||||
|
||||
GlLayer* glLayer = static_cast<GlLayer*>(layer);
|
||||
GrGLTextureInfo externalTexture;
|
||||
externalTexture.fTarget = layer->getRenderTarget();
|
||||
externalTexture.fID = layer->getTextureId();
|
||||
externalTexture.fTarget = glLayer->getRenderTarget();
|
||||
externalTexture.fID = glLayer->getTextureId();
|
||||
GrBackendTextureDesc textureDescription;
|
||||
textureDescription.fWidth = layer->getWidth();
|
||||
textureDescription.fHeight = layer->getHeight();
|
||||
textureDescription.fWidth = glLayer->getWidth();
|
||||
textureDescription.fHeight = glLayer->getHeight();
|
||||
textureDescription.fConfig = kRGBA_8888_GrPixelConfig;
|
||||
textureDescription.fOrigin = kTopLeft_GrSurfaceOrigin;
|
||||
textureDescription.fTextureHandle = reinterpret_cast<GrBackendObject>(&externalTexture);
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "SkiaOpenGLPipeline.h"
|
||||
|
||||
#include "DeferredLayerUpdater.h"
|
||||
#include "GlLayer.h"
|
||||
#include "LayerDrawable.h"
|
||||
#include "renderthread/EglManager.h"
|
||||
#include "renderthread/Frame.h"
|
||||
@@ -136,7 +137,7 @@ bool SkiaOpenGLPipeline::copyLayerInto(DeferredLayerUpdater* deferredLayer, SkBi
|
||||
|
||||
DeferredLayerUpdater* SkiaOpenGLPipeline::createTextureLayer() {
|
||||
mEglManager.initialize();
|
||||
Layer* layer = new Layer(mRenderThread.renderState(), 0, 0);
|
||||
GlLayer* layer = new GlLayer(mRenderThread.renderState(), 0, 0);
|
||||
layer->generateTexture();
|
||||
return new DeferredLayerUpdater(layer);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "renderstate/RenderState.h"
|
||||
#include "SkiaPipeline.h"
|
||||
#include "SkiaProfileRenderer.h"
|
||||
#include "VkLayer.h"
|
||||
|
||||
#include <SkSurface.h>
|
||||
#include <SkTypes.h>
|
||||
@@ -119,7 +120,8 @@ bool SkiaVulkanPipeline::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bi
|
||||
|
||||
DeferredLayerUpdater* SkiaVulkanPipeline::createTextureLayer() {
|
||||
mVkManager.initialize();
|
||||
Layer* layer = new Layer(mRenderThread.renderState(), 0, 0);
|
||||
|
||||
VkLayer* layer = new VkLayer(mRenderThread.renderState(), 0, 0);
|
||||
return new DeferredLayerUpdater(layer);
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "GlLayer.h"
|
||||
#include <GpuMemoryTracker.h>
|
||||
#include "renderstate/RenderState.h"
|
||||
|
||||
@@ -55,7 +56,9 @@ void RenderState::onGLContextCreated() {
|
||||
}
|
||||
|
||||
static void layerLostGlContext(Layer* layer) {
|
||||
layer->onGlContextLost();
|
||||
LOG_ALWAYS_FATAL_IF(layer->getApi() != Layer::Api::OpenGL,
|
||||
"layerLostGlContext on non GL layer");
|
||||
static_cast<GlLayer*>(layer)->onGlContextLost();
|
||||
}
|
||||
|
||||
void RenderState::onGLContextDestroyed() {
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "DeferredLayerUpdater.h"
|
||||
#include "EglManager.h"
|
||||
#include "Frame.h"
|
||||
#include "GlLayer.h"
|
||||
#include "ProfileRenderer.h"
|
||||
#include "renderstate/RenderState.h"
|
||||
#include "OpenGLReadback.h"
|
||||
@@ -120,12 +121,13 @@ bool OpenGLPipeline::swapBuffers(const Frame& frame, bool drew, const SkRect& sc
|
||||
bool OpenGLPipeline::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) {
|
||||
ATRACE_CALL();
|
||||
layer->apply();
|
||||
return OpenGLReadbackImpl::copyLayerInto(mRenderThread, *(layer->backingLayer()), bitmap);
|
||||
return OpenGLReadbackImpl::copyLayerInto(mRenderThread,
|
||||
static_cast<GlLayer&>(*layer->backingLayer()), bitmap);
|
||||
}
|
||||
|
||||
DeferredLayerUpdater* OpenGLPipeline::createTextureLayer() {
|
||||
mEglManager.initialize();
|
||||
Layer* layer = new Layer(mRenderThread.renderState(), 0, 0);
|
||||
GlLayer* layer = new GlLayer(mRenderThread.renderState(), 0, 0);
|
||||
Caches::getInstance().textureState().activateTexture(0);
|
||||
layer->generateTexture();
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
#include "DeferredLayerUpdater.h"
|
||||
#include "GlLayer.h"
|
||||
|
||||
#include "renderthread/OpenGLPipeline.h"
|
||||
#include "tests/common/TestUtils.h"
|
||||
@@ -32,7 +33,10 @@ RENDERTHREAD_TEST(DeferredLayerUpdater, updateLayer) {
|
||||
|
||||
|
||||
// updates are deferred so the backing layer should still be in its default state
|
||||
EXPECT_EQ((uint32_t)GL_NONE, layerUpdater->backingLayer()->getRenderTarget());
|
||||
if (layerUpdater->backingLayer()->getApi() == Layer::Api::OpenGL) {
|
||||
GlLayer* glLayer = static_cast<GlLayer*>(layerUpdater->backingLayer());
|
||||
EXPECT_EQ((uint32_t)GL_NONE, glLayer->getRenderTarget());
|
||||
}
|
||||
EXPECT_EQ(0u, layerUpdater->backingLayer()->getWidth());
|
||||
EXPECT_EQ(0u, layerUpdater->backingLayer()->getHeight());
|
||||
EXPECT_FALSE(layerUpdater->backingLayer()->getForceFilter());
|
||||
@@ -45,7 +49,10 @@ RENDERTHREAD_TEST(DeferredLayerUpdater, updateLayer) {
|
||||
layerUpdater->updateLayer(true, GL_TEXTURE_EXTERNAL_OES, scaledMatrix.data);
|
||||
|
||||
// the backing layer should now have all the properties applied.
|
||||
EXPECT_EQ((uint32_t)GL_TEXTURE_EXTERNAL_OES, layerUpdater->backingLayer()->getRenderTarget());
|
||||
if (layerUpdater->backingLayer()->getApi() == Layer::Api::OpenGL) {
|
||||
GlLayer* glLayer = static_cast<GlLayer*>(layerUpdater->backingLayer());
|
||||
EXPECT_EQ((uint32_t)GL_TEXTURE_EXTERNAL_OES, glLayer->getRenderTarget());
|
||||
}
|
||||
EXPECT_EQ(100u, layerUpdater->backingLayer()->getWidth());
|
||||
EXPECT_EQ(100u, layerUpdater->backingLayer()->getHeight());
|
||||
EXPECT_TRUE(layerUpdater->backingLayer()->getForceFilter());
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <BakedOpState.h>
|
||||
#include <DeferredLayerUpdater.h>
|
||||
#include <FrameBuilder.h>
|
||||
#include <GlLayer.h>
|
||||
#include <LayerUpdateQueue.h>
|
||||
#include <RecordedOp.h>
|
||||
#include <RecordingCanvas.h>
|
||||
@@ -698,7 +699,10 @@ RENDERTHREAD_TEST(FrameBuilder, textureLayer_combineMatrices) {
|
||||
RENDERTHREAD_TEST(FrameBuilder, textureLayer_reject) {
|
||||
auto layerUpdater = TestUtils::createTextureLayerUpdater(renderThread, 100, 100,
|
||||
SkMatrix::MakeTrans(5, 5));
|
||||
layerUpdater->backingLayer()->setRenderTarget(GL_NONE); // Should be rejected
|
||||
if (layerUpdater->backingLayer()->getApi() != Layer::Api::OpenGL) return;
|
||||
|
||||
GlLayer* glLayer = static_cast<GlLayer*>(layerUpdater->backingLayer());
|
||||
glLayer->setRenderTarget(GL_NONE); // Should be rejected
|
||||
|
||||
auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
|
||||
[&layerUpdater](RenderProperties& props, RecordingCanvas& canvas) {
|
||||
|
||||
Reference in New Issue
Block a user