summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Craik <ccraik@google.com>2015-02-06 23:06:43 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2015-02-06 23:06:44 +0000
commitf7ccbfbd9811e3b1c3accd9e3e92688d31a8a2bd (patch)
treeb08c13be9ce7e46c971db5437bcb94de5a5bb5ac
parent12271e22014c2e2cd0ecdb9938ff8b618c68bc56 (diff)
parent117bdbcfa3e8306dad21e7e01fa71b00cdfa7265 (diff)
downloadframeworks_base-f7ccbfbd9811e3b1c3accd9e3e92688d31a8a2bd.zip
frameworks_base-f7ccbfbd9811e3b1c3accd9e3e92688d31a8a2bd.tar.gz
frameworks_base-f7ccbfbd9811e3b1c3accd9e3e92688d31a8a2bd.tar.bz2
Merge "Glop ColorFilter & VertexBuffer support, initial enable"
-rw-r--r--libs/hwui/AmbientShadow.cpp2
-rw-r--r--libs/hwui/Caches.cpp11
-rw-r--r--libs/hwui/Caches.h12
-rw-r--r--libs/hwui/Dither.cpp4
-rw-r--r--libs/hwui/Dither.h1
-rw-r--r--libs/hwui/Extensions.cpp17
-rw-r--r--libs/hwui/Extensions.h11
-rw-r--r--libs/hwui/Glop.h33
-rw-r--r--libs/hwui/GlopBuilder.cpp145
-rw-r--r--libs/hwui/GlopBuilder.h23
-rw-r--r--libs/hwui/GradientCache.cpp19
-rw-r--r--libs/hwui/GradientCache.h3
-rw-r--r--libs/hwui/LayerRenderer.cpp2
-rw-r--r--libs/hwui/OpenGLRenderer.cpp106
-rwxr-xr-xlibs/hwui/OpenGLRenderer.h4
-rw-r--r--libs/hwui/PathTessellator.cpp3
-rw-r--r--libs/hwui/Program.h4
-rw-r--r--libs/hwui/ProgramCache.cpp3
-rw-r--r--libs/hwui/ProgramCache.h2
-rw-r--r--libs/hwui/Query.h152
-rw-r--r--libs/hwui/ShadowTessellator.cpp27
-rw-r--r--libs/hwui/ShadowTessellator.h2
-rw-r--r--libs/hwui/SpotShadow.cpp2
-rw-r--r--libs/hwui/TextureCache.cpp33
-rw-r--r--libs/hwui/TextureCache.h5
-rw-r--r--libs/hwui/VertexBuffer.h19
-rw-r--r--libs/hwui/font/CacheTexture.cpp2
-rw-r--r--libs/hwui/renderstate/Blend.cpp4
-rw-r--r--libs/hwui/renderstate/Blend.h2
-rw-r--r--libs/hwui/renderstate/MeshState.cpp48
-rw-r--r--libs/hwui/renderstate/MeshState.h7
-rw-r--r--libs/hwui/renderstate/RenderState.cpp78
-rw-r--r--libs/hwui/renderstate/RenderState.h5
-rw-r--r--libs/hwui/renderstate/Scissor.cpp7
-rw-r--r--libs/hwui/renderstate/Scissor.h1
-rw-r--r--libs/hwui/renderstate/Stencil.cpp10
-rw-r--r--libs/hwui/renderstate/Stencil.h2
-rw-r--r--libs/hwui/tests/main.cpp40
-rw-r--r--libs/hwui/utils/PaintUtils.h7
39 files changed, 443 insertions, 415 deletions
diff --git a/libs/hwui/AmbientShadow.cpp b/libs/hwui/AmbientShadow.cpp
index 6ec42c2..0a210d6 100644
--- a/libs/hwui/AmbientShadow.cpp
+++ b/libs/hwui/AmbientShadow.cpp
@@ -179,7 +179,7 @@ inline bool needsExtraForEdge(float firstAlpha, float secondAlpha) {
void AmbientShadow::createAmbientShadow(bool isCasterOpaque,
const Vector3* casterVertices, int casterVertexCount, const Vector3& centroid3d,
float heightFactor, float geomFactor, VertexBuffer& shadowVertexBuffer) {
- shadowVertexBuffer.setMode(VertexBuffer::kIndices);
+ shadowVertexBuffer.setMeshFeatureFlags(VertexBuffer::kAlpha | VertexBuffer::kIndices);
// In order to computer the outer vertices in one loop, we need pre-compute
// the normal by the vertex (n - 1) to vertex 0, and the spike and alpha value
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index af1b1cd..f4fc068 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -48,10 +48,11 @@ Caches* Caches::sInstance = nullptr;
///////////////////////////////////////////////////////////////////////////////
Caches::Caches(RenderState& renderState)
- : patchCache(renderState)
+ : gradientCache(mExtensions)
+ , patchCache(renderState)
+ , programCache(mExtensions)
, dither(*this)
, mRenderState(&renderState)
- , mExtensions(Extensions::getInstance())
, mInitialized(false) {
INIT_LOGD("Creating OpenGL renderer caches");
init();
@@ -187,9 +188,9 @@ bool Caches::initProperties() {
INIT_LOGD(" Draw reorder enabled");
}
- return (prevDebugLayersUpdates != debugLayersUpdates) ||
- (prevDebugOverdraw != debugOverdraw) ||
- (prevDebugStencilClip != debugStencilClip);
+ return (prevDebugLayersUpdates != debugLayersUpdates)
+ || (prevDebugOverdraw != debugOverdraw)
+ || (prevDebugStencilClip != debugStencilClip);
}
void Caches::terminate() {
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 16e2058..18bb5e6 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -178,14 +178,18 @@ public:
kStencilShowRegion
};
StencilClipDebug debugStencilClip;
-
+private:
+ // Declared before gradientCache and programCache which need this to initialize.
+ // TODO: cleanup / move elsewhere
+ Extensions mExtensions;
+public:
TextureCache textureCache;
LayerCache layerCache;
RenderBufferCache renderBufferCache;
GradientCache gradientCache;
- ProgramCache programCache;
- PathCache pathCache;
PatchCache patchCache;
+ PathCache pathCache;
+ ProgramCache programCache;
TessellationCache tessellationCache;
TextDropShadowCache dropShadowCache;
FboCache fboCache;
@@ -220,6 +224,7 @@ public:
void setProgram(const ProgramDescription& description);
void setProgram(Program* program);
+ Extensions& extensions() { return mExtensions; }
Program& program() { return *mProgram; }
PixelBufferState& pixelBufferState() { return *mPixelBufferState; }
TextureState& textureState() { return *mTextureState; }
@@ -248,7 +253,6 @@ private:
}
RenderState* mRenderState;
- Extensions& mExtensions;
// Used to render layers
std::unique_ptr<TextureVertex[]> mRegionMesh;
diff --git a/libs/hwui/Dither.cpp b/libs/hwui/Dither.cpp
index 359c193..1ba6511 100644
--- a/libs/hwui/Dither.cpp
+++ b/libs/hwui/Dither.cpp
@@ -32,8 +32,6 @@ Dither::Dither(Caches& caches)
void Dither::bindDitherTexture() {
if (!mInitialized) {
- bool useFloatTexture = Extensions::getInstance().hasFloatTextures();
-
glGenTextures(1, &mDitherTexture);
mCaches.textureState().bindTexture(mDitherTexture);
@@ -43,7 +41,7 @@ void Dither::bindDitherTexture() {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
- if (useFloatTexture) {
+ if (mCaches.extensions().hasFloatTextures()) {
// We use a R16F texture, let's remap the alpha channel to the
// red channel to avoid changing the shader sampling code on GL ES 3.0+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_RED);
diff --git a/libs/hwui/Dither.h b/libs/hwui/Dither.h
index facd1ea..b589b80 100644
--- a/libs/hwui/Dither.h
+++ b/libs/hwui/Dither.h
@@ -23,6 +23,7 @@ namespace android {
namespace uirenderer {
class Caches;
+class Extensions;
class Program;
// Must be a power of two
diff --git a/libs/hwui/Extensions.cpp b/libs/hwui/Extensions.cpp
index 8352c3f..c68822b 100644
--- a/libs/hwui/Extensions.cpp
+++ b/libs/hwui/Extensions.cpp
@@ -16,18 +16,16 @@
#define LOG_TAG "OpenGLRenderer"
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
+#include "Extensions.h"
+
+#include "Debug.h"
+#include "Properties.h"
#include <EGL/egl.h>
#include <EGL/eglext.h>
-
+#include <GLES2/gl2ext.h>
#include <utils/Log.h>
-#include "Debug.h"
-#include "Extensions.h"
-#include "Properties.h"
-
namespace android {
using namespace uirenderer;
@@ -50,7 +48,7 @@ namespace uirenderer {
// Constructors
///////////////////////////////////////////////////////////////////////////////
-Extensions::Extensions(): Singleton<Extensions>() {
+Extensions::Extensions() {
// Query GL extensions
findExtensions((const char*) glGetString(GL_EXTENSIONS), mGlExtensionList);
mHasNPot = hasGlExtension("GL_OES_texture_npot");
@@ -93,9 +91,6 @@ Extensions::Extensions(): Singleton<Extensions>() {
}
}
-Extensions::~Extensions() {
-}
-
///////////////////////////////////////////////////////////////////////////////
// Methods
///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/Extensions.h b/libs/hwui/Extensions.h
index 25d4c5e..731001a 100644
--- a/libs/hwui/Extensions.h
+++ b/libs/hwui/Extensions.h
@@ -23,6 +23,8 @@
#include <utils/SortedVector.h>
#include <utils/String8.h>
+#include <GLES2/gl2.h>
+
namespace android {
namespace uirenderer {
@@ -30,8 +32,10 @@ namespace uirenderer {
// Classes
///////////////////////////////////////////////////////////////////////////////
-class ANDROID_API Extensions: public Singleton<Extensions> {
+class ANDROID_API Extensions {
public:
+ Extensions();
+
inline bool hasNPot() const { return mHasNPot; }
inline bool hasFramebufferFetch() const { return mHasFramebufferFetch; }
inline bool hasDiscardFramebuffer() const { return mHasDiscardFramebuffer; }
@@ -55,13 +59,8 @@ public:
void dump() const;
private:
- Extensions();
- ~Extensions();
-
void findExtensions(const char* extensions, SortedVector<String8>& list) const;
- friend class Singleton<Extensions>;
-
SortedVector<String8> mGlExtensionList;
SortedVector<String8> mEglExtensionList;
diff --git a/libs/hwui/Glop.h b/libs/hwui/Glop.h
index bbeb19e..9150869 100644
--- a/libs/hwui/Glop.h
+++ b/libs/hwui/Glop.h
@@ -38,11 +38,13 @@ class Program;
*/
enum VertexAttribFlags {
// NOTE: position attribute always enabled
+ kNone_Attrib = 0,
kTextureCoord_Attrib = 1 << 0,
kColor_Attrib = 1 << 1,
kAlpha_Attrib = 1 << 2,
};
+
/**
* Structure containing all data required to issue a single OpenGL draw
*
@@ -53,40 +55,53 @@ enum VertexAttribFlags {
*/
// TODO: PREVENT_COPY_AND_ASSIGN(...) or similar
struct Glop {
+ struct FloatColor {
+ float a, r, g, b;
+ };
+
Rect bounds;
+ /*
+ * Stores mesh - vertex and index data.
+ *
+ * buffer objects and void*s are mutually exclusive
+ * indices are optional
+ */
struct Mesh {
VertexAttribFlags vertexFlags;
GLuint primitiveMode; // GL_TRIANGLES and GL_TRIANGLE_STRIP supported
GLuint vertexBufferObject;
GLuint indexBufferObject;
+ const void* vertices;
+ const void* indices;
int vertexCount;
GLsizei stride;
} mesh;
struct Fill {
Program* program;
-
- struct Color {
- float a, r, g, b;
- } color;
+ FloatColor color;
/* TODO
union shader {
//...
}; TODO
- union filter {
- //color
- //matrix + vector
- };
*/
+ ProgramDescription::ColorFilterMode filterMode;
+ union Filter {
+ struct Matrix {
+ float matrix[16];
+ float vector[4];
+ } matrix;
+ FloatColor color;
+ } filter;
} fill;
struct Transform {
Matrix4 ortho; // TODO: out of op, since this is static per FBO
Matrix4 modelView;
Matrix4 canvas;
- bool offset;
+ bool fudgingOffset;
} transform;
struct Blend {
diff --git a/libs/hwui/GlopBuilder.cpp b/libs/hwui/GlopBuilder.cpp
index dafe087..e22af40 100644
--- a/libs/hwui/GlopBuilder.cpp
+++ b/libs/hwui/GlopBuilder.cpp
@@ -18,10 +18,12 @@
#include "Caches.h"
#include "Glop.h"
#include "Matrix.h"
-#include "Texture.h"
#include "renderstate/MeshState.h"
#include "renderstate/RenderState.h"
+#include "SkiaShader.h"
+#include "Texture.h"
#include "utils/PaintUtils.h"
+#include "VertexBuffer.h"
#include <GLES2/gl2.h>
#include <SkPaint.h>
@@ -29,42 +31,82 @@
namespace android {
namespace uirenderer {
+#define TRIGGER_STAGE(stageFlag) \
+ LOG_ALWAYS_FATAL_IF(stageFlag & mStageFlags, "Stage %d cannot be run twice"); \
+ mStageFlags = static_cast<StageFlags>(mStageFlags | stageFlag)
+
GlopBuilder::GlopBuilder(RenderState& renderState, Caches& caches, Glop* outGlop)
: mRenderState(renderState)
, mCaches(caches)
, mOutGlop(outGlop){
+ mStageFlags = kInitialStage;
+}
+
+GlopBuilder& GlopBuilder::setMeshVertexBuffer(const VertexBuffer& vertexBuffer, bool shadowInterp) {
+ TRIGGER_STAGE(kMeshStage);
+
+ const VertexBuffer::MeshFeatureFlags flags = vertexBuffer.getMeshFeatureFlags();
+
+ bool alphaVertex = flags & VertexBuffer::kAlpha;
+ bool indices = flags & VertexBuffer::kIndices;
+ mOutGlop->mesh.vertexFlags = alphaVertex ? kAlpha_Attrib : kNone_Attrib;
+ mOutGlop->mesh.primitiveMode = GL_TRIANGLE_STRIP;
+ mOutGlop->mesh.vertexBufferObject = 0;
+ mOutGlop->mesh.vertices = vertexBuffer.getBuffer();
+ mOutGlop->mesh.indexBufferObject = 0;
+ mOutGlop->mesh.indices = vertexBuffer.getIndices();
+ mOutGlop->mesh.vertexCount = indices
+ ? vertexBuffer.getIndexCount() : vertexBuffer.getVertexCount();
+ mOutGlop->mesh.stride = alphaVertex ? kAlphaVertexStride : kVertexStride;
+
+ mDescription.hasVertexAlpha = alphaVertex;
+ mDescription.useShadowAlphaInterp = shadowInterp;
+ return *this;
}
GlopBuilder& GlopBuilder::setMeshUnitQuad() {
- mOutGlop->mesh.vertexFlags = static_cast<VertexAttribFlags>(0);
+ TRIGGER_STAGE(kMeshStage);
+
+ mOutGlop->mesh.vertexFlags = kNone_Attrib;
mOutGlop->mesh.primitiveMode = GL_TRIANGLE_STRIP;
mOutGlop->mesh.vertexBufferObject = mRenderState.meshState().getUnitQuadVBO();
+ mOutGlop->mesh.vertices = nullptr;
mOutGlop->mesh.indexBufferObject = 0;
+ mOutGlop->mesh.indices = nullptr;
mOutGlop->mesh.vertexCount = 4;
mOutGlop->mesh.stride = kTextureVertexStride;
return *this;
}
-GlopBuilder& GlopBuilder::setTransformAndRect(ModelViewMode mode,
- const Matrix4& ortho, const Matrix4& transform,
- float left, float top, float right, float bottom, bool offset) {
- mOutGlop->transform.ortho.load(ortho);
-
- mOutGlop->transform.modelView.loadTranslate(left, top, 0.0f);
- if (mode == kModelViewMode_TranslateAndScale) {
- mOutGlop->transform.modelView.scale(right - left, bottom - top, 1.0f);
- }
+GlopBuilder& GlopBuilder::setTransform(const Matrix4& ortho,
+ const Matrix4& transform, bool fudgingOffset) {
+ TRIGGER_STAGE(kTransformStage);
+ mOutGlop->transform.ortho.load(ortho);
mOutGlop->transform.canvas.load(transform);
+ mOutGlop->transform.fudgingOffset = fudgingOffset;
+ return *this;
+}
- mOutGlop->transform.offset = offset;
+GlopBuilder& GlopBuilder::setModelViewMapUnitToRect(const Rect destination) {
+ TRIGGER_STAGE(kModelViewStage);
+ mOutGlop->transform.modelView.loadTranslate(destination.left, destination.top, 0.0f);
+ mOutGlop->transform.modelView.scale(destination.getWidth(), destination.getHeight(), 1.0f);
+ mOutGlop->bounds = destination;
+ return *this;
+}
- mOutGlop->bounds.set(left, top, right, bottom);
- mOutGlop->transform.canvas.mapRect(mOutGlop->bounds);
+GlopBuilder& GlopBuilder::setModelViewOffsetRect(float offsetX, float offsetY, const Rect source) {
+ TRIGGER_STAGE(kModelViewStage);
+ mOutGlop->transform.modelView.loadTranslate(offsetX, offsetY, 0.0f);
+ mOutGlop->bounds = source;
+ mOutGlop->bounds.translate(offsetX, offsetY);
return *this;
}
GlopBuilder& GlopBuilder::setPaint(const SkPaint* paint, float alphaScale) {
+ TRIGGER_STAGE(kFillStage);
+
// TODO: support null paint
const SkShader* shader = paint->getShader();
const SkColorFilter* colorFilter = paint->getColorFilter();
@@ -73,25 +115,25 @@ GlopBuilder& GlopBuilder::setPaint(const SkPaint* paint, float alphaScale) {
if (mode != SkXfermode::kClear_Mode) {
int color = paint->getColor();
float alpha = (SkColorGetA(color) / 255.0f) * alphaScale;
- if (shader) {
- // shader discards color channels
- color |= 0x00FFFFFF;
+ if (!shader) {
+ float colorScale = alpha / 255.0f;
+ mOutGlop->fill.color = {
+ alpha,
+ colorScale * SkColorGetR(color),
+ colorScale * SkColorGetG(color),
+ colorScale * SkColorGetB(color)
+ };
+ } else {
+ mOutGlop->fill.color = { alpha, 1, 1, 1 };
}
- mOutGlop->fill.color = {
- alpha,
- alpha * SkColorGetR(color),
- alpha * SkColorGetG(color),
- alpha * SkColorGetB(color)
- };
} else {
mOutGlop->fill.color = { 1, 0, 0, 0 };
}
const bool SWAP_SRC_DST = false;
- const bool HAS_FRAMEBUFFER_FETCH = false; //mExtensions.hasFramebufferFetch();
- mOutGlop->blend = {GL_ZERO, GL_ZERO};
+ mOutGlop->blend = { GL_ZERO, GL_ZERO };
if (mOutGlop->fill.color.a < 1.0f
- || (shader && !shader->isOpaque())
+ || PaintUtils::isBlendedShader(shader)
|| PaintUtils::isBlendedColorFilter(colorFilter)
|| mode != SkXfermode::kSrcOver_Mode) {
if (CC_LIKELY(mode <= SkXfermode::kScreen_Mode)) {
@@ -103,7 +145,7 @@ GlopBuilder& GlopBuilder::setPaint(const SkPaint* paint, float alphaScale) {
// the blending, don't enable GL blending off here
// If the blend mode cannot be implemented using shaders, fall
// back to the default SrcOver blend mode instead
- if (CC_UNLIKELY(HAS_FRAMEBUFFER_FETCH)) {
+ if (CC_UNLIKELY(mCaches.extensions().hasFramebufferFetch())) {
mDescription.framebufferMode = mode;
mDescription.swapSrcDst = SWAP_SRC_DST;
// blending in shader, don't enable
@@ -115,17 +157,58 @@ GlopBuilder& GlopBuilder::setPaint(const SkPaint* paint, float alphaScale) {
}
}
- return *this;
-}
+ if (shader) {
+ SkiaShader::describe(&mCaches, mDescription, mCaches.extensions(), *shader);
+ // TODO: store shader data
+ LOG_ALWAYS_FATAL("shaders not yet supported");
+ }
+
+ if (colorFilter) {
+ SkColor color;
+ SkXfermode::Mode mode;
+ SkScalar srcColorMatrix[20];
+ if (colorFilter->asColorMode(&color, &mode)) {
+ mOutGlop->fill.filterMode = mDescription.colorOp = ProgramDescription::kColorBlend;
+ mDescription.colorMode = mode;
+
+ const float alpha = SkColorGetA(color) / 255.0f;
+ float colorScale = alpha / 255.0f;
+ mOutGlop->fill.filter.color = {
+ alpha,
+ colorScale * SkColorGetR(color),
+ colorScale * SkColorGetG(color),
+ colorScale * SkColorGetB(color),
+ };
+ } else if (colorFilter->asColorMatrix(srcColorMatrix)) {
+ mOutGlop->fill.filterMode = mDescription.colorOp = ProgramDescription::kColorMatrix;
+
+ float* colorMatrix = mOutGlop->fill.filter.matrix.matrix;
+ memcpy(colorMatrix, srcColorMatrix, 4 * sizeof(float));
+ memcpy(&colorMatrix[4], &srcColorMatrix[5], 4 * sizeof(float));
+ memcpy(&colorMatrix[8], &srcColorMatrix[10], 4 * sizeof(float));
+ memcpy(&colorMatrix[12], &srcColorMatrix[15], 4 * sizeof(float));
+
+ // Skia uses the range [0..255] for the addition vector, but we need
+ // the [0..1] range to apply the vector in GLSL
+ float* colorVector = mOutGlop->fill.filter.matrix.vector;
+ colorVector[0] = srcColorMatrix[4] / 255.0f;
+ colorVector[1] = srcColorMatrix[9] / 255.0f;
+ colorVector[2] = srcColorMatrix[14] / 255.0f;
+ colorVector[3] = srcColorMatrix[19] / 255.0f;
+ }
+ } else {
+ mOutGlop->fill.filterMode = ProgramDescription::kColorNone;
+ }
-GlopBuilder& GlopBuilder::setTexture(Texture* texture) {
- LOG_ALWAYS_FATAL("not yet supported");
return *this;
}
void GlopBuilder::build() {
+ LOG_ALWAYS_FATAL_IF(mStageFlags != kAllStages, "glop not fully prepared!");
+
mDescription.modulate = mOutGlop->fill.color.a < 1.0f;
mOutGlop->fill.program = mCaches.programCache.get(mDescription);
+ mOutGlop->transform.canvas.mapRect(mOutGlop->bounds);
}
} /* namespace uirenderer */
diff --git a/libs/hwui/GlopBuilder.h b/libs/hwui/GlopBuilder.h
index d243d76..c7464cd 100644
--- a/libs/hwui/GlopBuilder.h
+++ b/libs/hwui/GlopBuilder.h
@@ -27,22 +27,35 @@ namespace uirenderer {
class Caches;
struct Glop;
+class Matrix4;
class RenderState;
class Texture;
-class Matrix4;
+class VertexBuffer;
class GlopBuilder {
PREVENT_COPY_AND_ASSIGN(GlopBuilder);
public:
GlopBuilder(RenderState& renderState, Caches& caches, Glop* outGlop);
GlopBuilder& setMeshUnitQuad();
- GlopBuilder& setTransformAndRect(ModelViewMode mode,
- const Matrix4& ortho, const Matrix4& transform,
- float left, float top, float right, float bottom, bool offset);
+ GlopBuilder& setMeshVertexBuffer(const VertexBuffer& vertexBuffer, bool shadowInterp);
+
+ GlopBuilder& setTransform(const Matrix4& ortho, const Matrix4& transform, bool fudgingOffset);
+
+ GlopBuilder& setModelViewMapUnitToRect(const Rect destination);
+ GlopBuilder& setModelViewOffsetRect(float offsetX, float offsetY, const Rect source);
+
GlopBuilder& setPaint(const SkPaint* paint, float alphaScale);
- GlopBuilder& setTexture(Texture* texture);
void build();
private:
+ enum StageFlags {
+ kInitialStage = 0,
+ kMeshStage = 1 << 0,
+ kTransformStage = 1 << 1,
+ kModelViewStage = 1 << 2,
+ kFillStage = 1 << 3,
+ kAllStages = kMeshStage | kTransformStage | kModelViewStage | kFillStage,
+ } mStageFlags;
+
ProgramDescription mDescription;
RenderState& mRenderState;
Caches& mCaches;
diff --git a/libs/hwui/GradientCache.cpp b/libs/hwui/GradientCache.cpp
index 416b0b3..fb4c785 100644
--- a/libs/hwui/GradientCache.cpp
+++ b/libs/hwui/GradientCache.cpp
@@ -62,9 +62,12 @@ int GradientCacheEntry::compare(const GradientCacheEntry& lhs, const GradientCac
// Constructors/destructor
///////////////////////////////////////////////////////////////////////////////
-GradientCache::GradientCache():
- mCache(LruCache<GradientCacheEntry, Texture*>::kUnlimitedCapacity),
- mSize(0), mMaxSize(MB(DEFAULT_GRADIENT_CACHE_SIZE)) {
+GradientCache::GradientCache(Extensions& extensions)
+ : mCache(LruCache<GradientCacheEntry, Texture*>::kUnlimitedCapacity)
+ , mSize(0)
+ , mMaxSize(MB(DEFAULT_GRADIENT_CACHE_SIZE))
+ , mUseFloatTexture(extensions.hasFloatTextures())
+ , mHasNpot(extensions.hasNPot()){
char property[PROPERTY_VALUE_MAX];
if (property_get(PROPERTY_GRADIENT_CACHE_SIZE, property, nullptr) > 0) {
INIT_LOGD(" Setting gradient cache size to %sMB", property);
@@ -76,16 +79,6 @@ GradientCache::GradientCache():
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
mCache.setOnEntryRemovedListener(this);
-
- const Extensions& extensions = Extensions::getInstance();
- mUseFloatTexture = extensions.hasFloatTextures();
- mHasNpot = extensions.hasNPot();
-}
-
-GradientCache::GradientCache(uint32_t maxByteSize):
- mCache(LruCache<GradientCacheEntry, Texture*>::kUnlimitedCapacity),
- mSize(0), mMaxSize(maxByteSize) {
- mCache.setOnEntryRemovedListener(this);
}
GradientCache::~GradientCache() {
diff --git a/libs/hwui/GradientCache.h b/libs/hwui/GradientCache.h
index 1714e6d..08319ea 100644
--- a/libs/hwui/GradientCache.h
+++ b/libs/hwui/GradientCache.h
@@ -104,8 +104,7 @@ inline hash_t hash_type(const GradientCacheEntry& entry) {
*/
class GradientCache: public OnEntryRemoved<GradientCacheEntry, Texture*> {
public:
- GradientCache();
- GradientCache(uint32_t maxByteSize);
+ GradientCache(Extensions& extensions);
~GradientCache();
/**
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index d2f9a94..b4b14e8 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -337,7 +337,7 @@ void LayerRenderer::flushLayer(RenderState& renderState, Layer* layer) {
if (fbo) {
// If possible, discard any enqueud operations on deferred
// rendering architectures
- if (Extensions::getInstance().hasDiscardFramebuffer()) {
+ if (Caches::getInstance().extensions().hasDiscardFramebuffer()) {
GLuint previousFbo = renderState.getFramebuffer();
if (fbo != previousFbo) {
renderState.bindFramebuffer(fbo);
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index f4b12b6..5a0cc1e 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -88,7 +88,6 @@ static inline T min(T a, T b) {
OpenGLRenderer::OpenGLRenderer(RenderState& renderState)
: mState(*this)
, mCaches(Caches::getInstance())
- , mExtensions(Extensions::getInstance())
, mRenderState(renderState)
, mFrameStarted(false)
, mScissorOptimizationDisabled(false)
@@ -194,7 +193,7 @@ void OpenGLRenderer::discardFramebuffer(float left, float top, float right, floa
// If we know that we are going to redraw the entire framebuffer,
// perform a discard to let the driver know we don't need to preserve
// the back buffer for this frame.
- if (mExtensions.hasDiscardFramebuffer() &&
+ if (mCaches.extensions().hasDiscardFramebuffer() &&
left <= 0.0f && top <= 0.0f && right >= mState.getWidth() && bottom >= mState.getHeight()) {
const bool isFbo = onGetTargetFbo() == 0;
const GLenum attachments[] = {
@@ -904,7 +903,7 @@ void OpenGLRenderer::drawTextureLayer(Layer* layer, const Rect& rect) {
setupDrawTextureTransformUniforms(layer->getTexTransform());
setupDrawMesh(&mMeshVertices[0].x, &mMeshVertices[0].u);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, kMeshCount);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, kUnitQuadCount);
}
void OpenGLRenderer::composeLayerRect(Layer* layer, const Rect& rect, bool swap) {
@@ -946,7 +945,7 @@ void OpenGLRenderer::composeLayerRect(Layer* layer, const Rect& rect, bool swap)
drawTextureMesh(x, y, x + rect.getWidth(), y + rect.getHeight(),
layer->getTexture(), &layerPaint, blend,
&mMeshVertices[0].x, &mMeshVertices[0].u,
- GL_TRIANGLE_STRIP, kMeshCount, swap, swap || simpleTransform);
+ GL_TRIANGLE_STRIP, kUnitQuadCount, swap, swap || simpleTransform);
resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
}
@@ -1386,7 +1385,8 @@ void OpenGLRenderer::attachStencilBufferToLayer(Layer* layer) {
endTiling();
RenderBuffer* buffer = mCaches.renderBufferCache.get(
- Stencil::getSmallestStencilFormat(), layer->getWidth(), layer->getHeight());
+ Stencil::getSmallestStencilFormat(),
+ layer->getWidth(), layer->getHeight());
layer->setStencilRenderBuffer(buffer);
startTiling(layer->clipRect, layer->layer.getHeight());
@@ -1572,6 +1572,18 @@ void OpenGLRenderer::debugClip() {
#endif
}
+void OpenGLRenderer::renderGlop(const Glop& glop) {
+ if (mState.getDirtyClip()) {
+ if (mRenderState.scissor().isEnabled()) {
+ setScissorFromClip();
+ }
+
+ setStencilFromClip();
+ }
+ mRenderState.render(glop);
+ dirtyLayer(glop.bounds.left, glop.bounds.top, glop.bounds.right, glop.bounds.bottom);
+}
+
///////////////////////////////////////////////////////////////////////////////
// Drawing commands
///////////////////////////////////////////////////////////////////////////////
@@ -1600,9 +1612,9 @@ void OpenGLRenderer::setupDraw(bool clearLayer) {
// Enable debug highlight when what we're about to draw is tested against
// the stencil buffer and if stencil highlight debugging is on
- mDescription.hasDebugHighlight = !mCaches.debugOverdraw &&
- mCaches.debugStencilClip == Caches::kStencilShowHighlight &&
- mRenderState.stencil().isTestEnabled();
+ mDescription.hasDebugHighlight = !mCaches.debugOverdraw
+ && mCaches.debugStencilClip == Caches::kStencilShowHighlight
+ && mRenderState.stencil().isTestEnabled();
}
void OpenGLRenderer::setupDrawWithTexture(bool isAlpha8) {
@@ -1662,7 +1674,7 @@ void OpenGLRenderer::setupDrawColor(float r, float g, float b, float a) {
void OpenGLRenderer::setupDrawShader(const SkShader* shader) {
if (shader != nullptr) {
- SkiaShader::describe(&mCaches, mDescription, mExtensions, *shader);
+ SkiaShader::describe(&mCaches, mDescription, mCaches.extensions(), *shader);
}
}
@@ -1783,7 +1795,8 @@ void OpenGLRenderer::setupDrawShaderUniforms(const SkShader* shader, bool ignore
mModelViewMatrix.load(modelViewWithoutTransform);
}
- SkiaShader::setupProgram(&mCaches, mModelViewMatrix, &mTextureUnit, mExtensions, *shader);
+ SkiaShader::setupProgram(&mCaches, mModelViewMatrix, &mTextureUnit,
+ mCaches.extensions(), *shader);
}
void OpenGLRenderer::setupDrawColorFilterUniforms(const SkColorFilter* filter) {
@@ -1977,7 +1990,7 @@ void OpenGLRenderer::drawAlphaBitmap(Texture* texture, float left, float top,
// bitmaps get packed in the atlas
drawAlpha8TextureMesh(x, y, x + texture->width, y + texture->height, texture->id,
paint, (GLvoid*) nullptr, (GLvoid*) kMeshTextureOffset,
- GL_TRIANGLE_STRIP, kMeshCount, ignoreTransform);
+ GL_TRIANGLE_STRIP, kUnitQuadCount, ignoreTransform);
}
/**
@@ -2131,7 +2144,7 @@ void OpenGLRenderer::drawBitmapMesh(const SkBitmap* bitmap, int meshWidth, int m
setupDrawBlending(paint, true);
setupDrawProgram();
setupDrawDirtyRegionsDisabled();
- setupDrawModelView(kModelViewMode_TranslateAndScale, false, 0.0f, 0.0f, 1.0f, 1.0f);
+ setupDrawModelView(kModelViewMode_Translate, false, 0, 0, 0, 0);
setupDrawTexture(texture->id);
setupDrawPureColorUniforms();
setupDrawColorFilterUniforms(getColorFilter(paint));
@@ -2217,12 +2230,12 @@ void OpenGLRenderer::drawBitmap(const SkBitmap* bitmap,
drawAlpha8TextureMesh(dstLeft, dstTop, dstRight, dstBottom,
texture->id, paint,
&mMeshVertices[0].x, &mMeshVertices[0].u,
- GL_TRIANGLE_STRIP, kMeshCount, ignoreTransform);
+ GL_TRIANGLE_STRIP, kUnitQuadCount, ignoreTransform);
} else {
drawTextureMesh(dstLeft, dstTop, dstRight, dstBottom,
texture->id, paint, texture->blend,
&mMeshVertices[0].x, &mMeshVertices[0].u,
- GL_TRIANGLE_STRIP, kMeshCount, false, ignoreTransform);
+ GL_TRIANGLE_STRIP, kUnitQuadCount, false, ignoreTransform);
}
if (CC_UNLIKELY(useScaleTransform)) {
@@ -2332,17 +2345,33 @@ void OpenGLRenderer::drawVertexBuffer(float translateX, float translateY,
return;
}
+ if (!paint->getShader() && !currentSnapshot()->roundRectClipState) {
+ Glop glop;
+ GlopBuilder aBuilder(mRenderState, mCaches, &glop);
+ bool fudgeOffset = displayFlags & kVertexBuffer_Offset;
+ bool shadowInterp = displayFlags & kVertexBuffer_ShadowInterp;
+ aBuilder.setMeshVertexBuffer(vertexBuffer, shadowInterp)
+ .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), fudgeOffset)
+ .setModelViewOffsetRect(translateX, translateY, vertexBuffer.getBounds())
+ .setPaint(paint, currentSnapshot()->alpha)
+ .build();
+ renderGlop(glop);
+ return;
+ }
+
+
+ const VertexBuffer::MeshFeatureFlags meshFeatureFlags = vertexBuffer.getMeshFeatureFlags();
Rect bounds(vertexBuffer.getBounds());
bounds.translate(translateX, translateY);
dirtyLayer(bounds.left, bounds.top, bounds.right, bounds.bottom, *currentTransform());
int color = paint->getColor();
- bool isAA = paint->isAntiAlias();
+ bool isAA = meshFeatureFlags & VertexBuffer::kAlpha;
setupDraw();
setupDrawNoTexture();
if (isAA) setupDrawVertexAlpha((displayFlags & kVertexBuffer_ShadowInterp));
- setupDrawColor(color, ((color >> 24) & 0xFF) * writableSnapshot()->alpha);
+ setupDrawColor(color, ((color >> 24) & 0xFF) * currentSnapshot()->alpha);
setupDrawColorFilter(getColorFilter(paint));
setupDrawShader(getShader(paint));
setupDrawBlending(paint, isAA);
@@ -2368,22 +2397,13 @@ void OpenGLRenderer::drawVertexBuffer(float translateX, float translateY,
glVertexAttribPointer(alphaSlot, 1, GL_FLOAT, GL_FALSE, kAlphaVertexStride, alphaCoords);
}
- const VertexBuffer::Mode mode = vertexBuffer.getMode();
- if (mode == VertexBuffer::kStandard) {
- mRenderState.meshState().unbindIndicesBuffer();
- glDrawArrays(GL_TRIANGLE_STRIP, 0, vertexBuffer.getVertexCount());
- } else if (mode == VertexBuffer::kOnePolyRingShadow) {
- mRenderState.meshState().bindShadowIndicesBuffer();
- glDrawElements(GL_TRIANGLE_STRIP, ONE_POLY_RING_SHADOW_INDEX_COUNT,
- GL_UNSIGNED_SHORT, nullptr);
- } else if (mode == VertexBuffer::kTwoPolyRingShadow) {
- mRenderState.meshState().bindShadowIndicesBuffer();
- glDrawElements(GL_TRIANGLE_STRIP, TWO_POLY_RING_SHADOW_INDEX_COUNT,
- GL_UNSIGNED_SHORT, nullptr);
- } else if (mode == VertexBuffer::kIndices) {
+ if (meshFeatureFlags & VertexBuffer::kIndices) {
mRenderState.meshState().unbindIndicesBuffer();
glDrawElements(GL_TRIANGLE_STRIP, vertexBuffer.getIndexCount(),
GL_UNSIGNED_SHORT, vertexBuffer.getIndices());
+ } else {
+ mRenderState.meshState().unbindIndicesBuffer();
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, vertexBuffer.getVertexCount());
}
if (isAA) {
@@ -2665,7 +2685,7 @@ void OpenGLRenderer::drawTextShadow(const SkPaint* paint, const char* text,
setupDrawShaderUniforms(getShader(paint));
setupDrawMesh(nullptr, (GLvoid*) kMeshTextureOffset);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, kMeshCount);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, kUnitQuadCount);
}
bool OpenGLRenderer::canSkipText(const SkPaint* paint) const {
@@ -3099,7 +3119,7 @@ void OpenGLRenderer::drawPathTexture(const PathTexture* texture,
setupDrawShaderUniforms(getShader(paint));
setupDrawMesh(nullptr, (GLvoid*) kMeshTextureOffset);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, kMeshCount);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, kUnitQuadCount);
}
// Same values used by Skia
@@ -3258,6 +3278,20 @@ void OpenGLRenderer::drawColorRects(const float* rects, int count, const SkPaint
void OpenGLRenderer::drawColorRect(float left, float top, float right, float bottom,
const SkPaint* paint, bool ignoreTransform) {
+
+ if (!paint->getShader() && !currentSnapshot()->roundRectClipState) {
+ const Matrix4& transform = ignoreTransform ? Matrix4::identity() : *currentTransform();
+ Glop glop;
+ GlopBuilder aBuilder(mRenderState, mCaches, &glop);
+ aBuilder.setMeshUnitQuad()
+ .setTransform(currentSnapshot()->getOrthoMatrix(), transform, false)
+ .setModelViewMapUnitToRect(Rect(left, top, right, bottom))
+ .setPaint(paint, currentSnapshot()->alpha)
+ .build();
+ renderGlop(glop);
+ return;
+ }
+
int color = paint->getColor();
// If a shader is set, preserve only the alpha
if (getShader(paint)) {
@@ -3278,7 +3312,7 @@ void OpenGLRenderer::drawColorRect(float left, float top, float right, float bot
setupDrawColorFilterUniforms(getColorFilter(paint));
setupDrawSimpleMesh();
- glDrawArrays(GL_TRIANGLE_STRIP, 0, kMeshCount);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, kUnitQuadCount);
}
void OpenGLRenderer::drawTextureRect(float left, float top, float right, float bottom,
@@ -3305,11 +3339,11 @@ void OpenGLRenderer::drawTextureRect(float left, float top, float right, float b
texture->setFilter(GL_NEAREST, true);
drawTextureMesh(x, y, x + texture->width, y + texture->height, texture->id,
paint, texture->blend, vertices, texCoords,
- GL_TRIANGLE_STRIP, kMeshCount, false, true);
+ GL_TRIANGLE_STRIP, kUnitQuadCount, false, true);
} else {
texture->setFilter(getFilter(paint), true);
drawTextureMesh(left, top, right, bottom, texture->id, paint,
- texture->blend, vertices, texCoords, GL_TRIANGLE_STRIP, kMeshCount);
+ texture->blend, vertices, texCoords, GL_TRIANGLE_STRIP, kUnitQuadCount);
}
if (texture->uvMapper) {
@@ -3404,7 +3438,7 @@ void OpenGLRenderer::drawAlpha8TextureMesh(float left, float top, float right, f
void OpenGLRenderer::chooseBlending(bool blend, SkXfermode::Mode mode,
ProgramDescription& description, bool swapSrcDst) {
- if (writableSnapshot()->roundRectClipState != nullptr /*&& !mSkipOutlineClip*/) {
+ if (currentSnapshot()->roundRectClipState != nullptr /*&& !mSkipOutlineClip*/) {
blend = true;
mDescription.hasRoundRectClip = true;
}
@@ -3419,7 +3453,7 @@ void OpenGLRenderer::chooseBlending(bool blend, SkXfermode::Mode mode,
// If the blend mode cannot be implemented using shaders, fall
// back to the default SrcOver blend mode instead
if (CC_UNLIKELY(mode > SkXfermode::kScreen_Mode)) {
- if (CC_UNLIKELY(mExtensions.hasFramebufferFetch())) {
+ if (CC_UNLIKELY(mCaches.extensions().hasFramebufferFetch())) {
description.framebufferMode = mode;
description.swapSrcDst = swapSrcDst;
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index f0de089..f097041 100755
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -57,6 +57,7 @@ namespace android {
namespace uirenderer {
class DeferredDisplayState;
+struct Glop;
class RenderState;
class RenderNode;
class TextSetupFunctor;
@@ -529,10 +530,11 @@ protected:
CanvasState mState;
Caches& mCaches;
- Extensions& mExtensions; // TODO: move to RenderState
RenderState& mRenderState;
private:
+ void renderGlop(const Glop& glop);
+
/**
* Discards the content of the framebuffer if supported by the driver.
* This method should be called at the beginning of a frame to optimize
diff --git a/libs/hwui/PathTessellator.cpp b/libs/hwui/PathTessellator.cpp
index ceec4fc..3d8a749 100644
--- a/libs/hwui/PathTessellator.cpp
+++ b/libs/hwui/PathTessellator.cpp
@@ -783,6 +783,7 @@ void PathTessellator::tessellatePath(const SkPath &path, const SkPaint* paint,
Rect bounds(path.getBounds());
paintInfo.expandBoundsForStroke(&bounds);
vertexBuffer.setBounds(bounds);
+ vertexBuffer.setMeshFeatureFlags(paintInfo.isAA ? VertexBuffer::kAlpha : VertexBuffer::kNone);
}
template <class TYPE>
@@ -840,6 +841,7 @@ void PathTessellator::tessellatePoints(const float* points, int count, const SkP
// expand bounds from vertex coords to pixel data
paintInfo.expandBoundsForStroke(&bounds);
vertexBuffer.setBounds(bounds);
+ vertexBuffer.setMeshFeatureFlags(paintInfo.isAA ? VertexBuffer::kAlpha : VertexBuffer::kNone);
}
void PathTessellator::tessellateLines(const float* points, int count, const SkPaint* paint,
@@ -890,6 +892,7 @@ void PathTessellator::tessellateLines(const float* points, int count, const SkPa
// expand bounds from vertex coords to pixel data
paintInfo.expandBoundsForStroke(&bounds);
vertexBuffer.setBounds(bounds);
+ vertexBuffer.setMeshFeatureFlags(paintInfo.isAA ? VertexBuffer::kAlpha : VertexBuffer::kNone);
}
///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/Program.h b/libs/hwui/Program.h
index b637450..01231b5 100644
--- a/libs/hwui/Program.h
+++ b/libs/hwui/Program.h
@@ -102,7 +102,7 @@ typedef uint64_t programid;
* A ProgramDescription must be used in conjunction with a ProgramCache.
*/
struct ProgramDescription {
- enum ColorModifier {
+ enum ColorFilterMode {
kColorNone = 0,
kColorMatrix,
kColorBlend
@@ -148,7 +148,7 @@ struct ProgramDescription {
GLenum bitmapWrapT;
// Color operations
- ColorModifier colorOp;
+ ColorFilterMode colorOp;
SkXfermode::Mode colorMode;
// Framebuffer blending (requires Extensions.hasFramebufferFetch())
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index 3bbd520..8c6a91cc 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -404,7 +404,8 @@ const char* gBlendOps[18] = {
// Constructors/destructors
///////////////////////////////////////////////////////////////////////////////
-ProgramCache::ProgramCache(): mHasES3(Extensions::getInstance().getMajorGlVersion() >= 3) {
+ProgramCache::ProgramCache(Extensions& extensions)
+ : mHasES3(extensions.getMajorGlVersion() >= 3) {
}
ProgramCache::~ProgramCache() {
diff --git a/libs/hwui/ProgramCache.h b/libs/hwui/ProgramCache.h
index 30fa0df..1dadda1 100644
--- a/libs/hwui/ProgramCache.h
+++ b/libs/hwui/ProgramCache.h
@@ -40,7 +40,7 @@ namespace uirenderer {
*/
class ProgramCache {
public:
- ProgramCache();
+ ProgramCache(Extensions& extensions);
~ProgramCache();
Program* get(const ProgramDescription& description);
diff --git a/libs/hwui/Query.h b/libs/hwui/Query.h
deleted file mode 100644
index e25b16b..0000000
--- a/libs/hwui/Query.h
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#ifndef ANDROID_HWUI_QUERY_H
-#define ANDROID_HWUI_QUERY_H
-
-#include <GLES3/gl3.h>
-
-#include "Extensions.h"
-
-namespace android {
-namespace uirenderer {
-
-/**
- * A Query instance can be used to perform occlusion queries. If the device
- * does not support occlusion queries, the result of a query will always be
- * 0 and the result will always be marked available.
- *
- * To run an occlusion query successfully, you must start end end the query:
- *
- * Query query;
- * query.begin();
- * // execute OpenGL calls
- * query.end();
- * GLuint result = query.getResult();
- */
-class Query {
-public:
- /**
- * Possible query targets.
- */
- enum Target {
- /**
- * Indicates if any sample passed the depth & stencil tests.
- */
- kTargetSamples = GL_ANY_SAMPLES_PASSED,
- /**
- * Indicates if any sample passed the depth & stencil tests.
- * The implementation may choose to use a less precise version
- * of the test, potentially resulting in false positives.
- */
- kTargetConservativeSamples = GL_ANY_SAMPLES_PASSED_CONSERVATIVE,
- };
-
- /**
- * Creates a new query with the specified target. The default
- * target is kTargetSamples (of GL_ANY_SAMPLES_PASSED in OpenGL.)
- */
- Query(Target target = kTargetSamples): mActive(false), mTarget(target),
- mCanQuery(Extensions::getInstance().hasOcclusionQueries()),
- mQuery(0) {
- }
-
- ~Query() {
- if (mQuery) {
- glDeleteQueries(1, &mQuery);
- }
- }
-
- /**
- * Begins the query. If the query has already begun or if the device
- * does not support occlusion queries, calling this method as no effect.
- * After calling this method successfully, the query is marked active.
- */
- void begin() {
- if (!mActive && mCanQuery) {
- if (!mQuery) {
- glGenQueries(1, &mQuery);
- }
-
- glBeginQuery(mTarget, mQuery);
- mActive = true;
- }
- }
-
- /**
- * Ends the query. If the query has already begun or if the device
- * does not support occlusion queries, calling this method as no effect.
- * After calling this method successfully, the query is marked inactive.
- */
- void end() {
- if (mQuery && mActive) {
- glEndQuery(mTarget);
- mActive = false;
- }
- }
-
- /**
- * Returns true if the query is active, false otherwise.
- */
- bool isActive() {
- return mActive;
- }
-
- /**
- * Returns true if the result of the query is available,
- * false otherwise. Calling getResult() before the result
- * is available may result in the calling thread being blocked.
- * If the device does not support queries, this method always
- * returns true.
- */
- bool isResultAvailable() {
- if (!mQuery) return true;
-
- GLuint result;
- glGetQueryObjectuiv(mQuery, GL_QUERY_RESULT_AVAILABLE, &result);
- return result == GL_TRUE;
- }
-
- /**
- * Returns the result of the query. If the device does not
- * support queries this method will return 0.
- *
- * Calling this method implicitely calls end() if the query
- * is currently active.
- */
- GLuint getResult() {
- if (!mQuery) return 0;
-
- end();
-
- GLuint result;
- glGetQueryObjectuiv(mQuery, GL_QUERY_RESULT, &result);
- return result;
- }
-
-
-private:
- bool mActive;
- GLenum mTarget;
- bool mCanQuery;
- GLuint mQuery;
-
-}; // class Query
-
-}; // namespace uirenderer
-}; // namespace android
-
-#endif // ANDROID_HWUI_QUERY_H
diff --git a/libs/hwui/ShadowTessellator.cpp b/libs/hwui/ShadowTessellator.cpp
index f8917e3..ca7f48d 100644
--- a/libs/hwui/ShadowTessellator.cpp
+++ b/libs/hwui/ShadowTessellator.cpp
@@ -113,33 +113,6 @@ void ShadowTessellator::tessellateSpotShadow(bool isCasterOpaque,
#endif
}
-void ShadowTessellator::generateShadowIndices(uint16_t* shadowIndices) {
- int currentIndex = 0;
- const int rays = SHADOW_RAY_COUNT;
- // For the penumbra area.
- for (int layer = 0; layer < 2; layer ++) {
- int baseIndex = layer * rays;
- for (int i = 0; i < rays; i++) {
- shadowIndices[currentIndex++] = i + baseIndex;
- shadowIndices[currentIndex++] = rays + i + baseIndex;
- }
- // To close the loop, back to the ray 0.
- shadowIndices[currentIndex++] = 0 + baseIndex;
- // Note this is the same as the first index of next layer loop.
- shadowIndices[currentIndex++] = rays + baseIndex;
- }
-
-#if DEBUG_SHADOW
- if (currentIndex != MAX_SHADOW_INDEX_COUNT) {
- ALOGW("vertex index count is wrong. current %d, expected %d",
- currentIndex, MAX_SHADOW_INDEX_COUNT);
- }
- for (int i = 0; i < MAX_SHADOW_INDEX_COUNT; i++) {
- ALOGD("vertex index is (%d, %d)", i, shadowIndices[i]);
- }
-#endif
-}
-
/**
* Calculate the centroid of a 2d polygon.
*
diff --git a/libs/hwui/ShadowTessellator.h b/libs/hwui/ShadowTessellator.h
index 16ad91d..c04d8ef 100644
--- a/libs/hwui/ShadowTessellator.h
+++ b/libs/hwui/ShadowTessellator.h
@@ -78,8 +78,6 @@ public:
const mat4& receiverTransform, const Vector3& lightCenter, int lightRadius,
const Rect& casterBounds, const Rect& localClip, VertexBuffer& shadowVertexBuffer);
- static void generateShadowIndices(uint16_t* shadowIndices);
-
static Vector2 centroid2d(const Vector2* poly, int polyLength);
static bool isClockwise(const Vector2* polygon, int len);
diff --git a/libs/hwui/SpotShadow.cpp b/libs/hwui/SpotShadow.cpp
index a03192a..b3b06d6 100644
--- a/libs/hwui/SpotShadow.cpp
+++ b/libs/hwui/SpotShadow.cpp
@@ -1031,7 +1031,7 @@ void SpotShadow::generateTriangleStrip(bool isCasterOpaque, float shadowStrength
ShadowTessellator::checkOverflow(vertexBufferIndex, totalVertexCount, "Spot Vertex Buffer");
ShadowTessellator::checkOverflow(indexBufferIndex, totalIndexCount, "Spot Index Buffer");
- shadowTriangleStrip.setMode(VertexBuffer::kIndices);
+ shadowTriangleStrip.setMeshFeatureFlags(VertexBuffer::kAlpha | VertexBuffer::kIndices);
shadowTriangleStrip.computeBounds<AlphaVertex>();
}
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
index fe8fb5b..f4f8e44 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -38,10 +38,12 @@ namespace uirenderer {
// Constructors/destructor
///////////////////////////////////////////////////////////////////////////////
-TextureCache::TextureCache():
- mCache(LruCache<uint32_t, Texture*>::kUnlimitedCapacity),
- mSize(0), mMaxSize(MB(DEFAULT_TEXTURE_CACHE_SIZE)),
- mFlushRate(DEFAULT_TEXTURE_CACHE_FLUSH_RATE), mAssetAtlas(nullptr) {
+TextureCache::TextureCache()
+ : mCache(LruCache<uint32_t, Texture*>::kUnlimitedCapacity)
+ , mSize(0)
+ , mMaxSize(MB(DEFAULT_TEXTURE_CACHE_SIZE))
+ , mFlushRate(DEFAULT_TEXTURE_CACHE_FLUSH_RATE)
+ , mAssetAtlas(nullptr) {
char property[PROPERTY_VALUE_MAX];
if (property_get(PROPERTY_TEXTURE_CACHE_SIZE, property, nullptr) > 0) {
INIT_LOGD(" Setting texture cache size to %sMB", property);
@@ -59,20 +61,6 @@ TextureCache::TextureCache():
DEFAULT_TEXTURE_CACHE_FLUSH_RATE * 100.0f);
}
- init();
-}
-
-TextureCache::TextureCache(uint32_t maxByteSize):
- mCache(LruCache<uint32_t, Texture*>::kUnlimitedCapacity),
- mSize(0), mMaxSize(maxByteSize), mAssetAtlas(nullptr) {
- init();
-}
-
-TextureCache::~TextureCache() {
- mCache.clear();
-}
-
-void TextureCache::init() {
mCache.setOnEntryRemovedListener(this);
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
@@ -81,6 +69,10 @@ void TextureCache::init() {
mDebugEnabled = readDebugLevel() & kDebugCaches;
}
+TextureCache::~TextureCache() {
+ mCache.clear();
+}
+
///////////////////////////////////////////////////////////////////////////////
// Size management
///////////////////////////////////////////////////////////////////////////////
@@ -280,7 +272,7 @@ void TextureCache::generateTexture(const SkBitmap* bitmap, Texture* texture, boo
// We could also enable mipmapping if both bitmap dimensions are powers
// of 2 but we'd have to deal with size changes. Let's keep this simple
- const bool canMipMap = Extensions::getInstance().hasNPot();
+ const bool canMipMap = Caches::getInstance().extensions().hasNPot();
// If the texture had mipmap enabled but not anymore,
// force a glTexImage2D to discard the mipmap levels
@@ -355,7 +347,8 @@ void TextureCache::uploadLoFiTexture(bool resize, const SkBitmap* bitmap,
void TextureCache::uploadToTexture(bool resize, GLenum format, GLsizei stride, GLsizei bpp,
GLsizei width, GLsizei height, GLenum type, const GLvoid * data) {
glPixelStorei(GL_UNPACK_ALIGNMENT, bpp);
- const bool useStride = stride != width && Extensions::getInstance().hasUnpackRowLength();
+ const bool useStride = stride != width
+ && Caches::getInstance().extensions().hasUnpackRowLength();
if ((stride == width) || useStride) {
if (useStride) {
glPixelStorei(GL_UNPACK_ROW_LENGTH, stride);
diff --git a/libs/hwui/TextureCache.h b/libs/hwui/TextureCache.h
index b97d92d..a2c6380 100644
--- a/libs/hwui/TextureCache.h
+++ b/libs/hwui/TextureCache.h
@@ -52,10 +52,9 @@ class AssetAtlas;
* Any texture added to the cache causing the cache to grow beyond the maximum
* allowed size will also cause the oldest texture to be kicked out.
*/
-class TextureCache: public OnEntryRemoved<uint32_t, Texture*> {
+class TextureCache : public OnEntryRemoved<uint32_t, Texture*> {
public:
TextureCache();
- TextureCache(uint32_t maxByteSize);
~TextureCache();
/**
@@ -146,8 +145,6 @@ private:
void uploadToTexture(bool resize, GLenum format, GLsizei stride, GLsizei bpp,
GLsizei width, GLsizei height, GLenum type, const GLvoid * data);
- void init();
-
LruCache<uint32_t, Texture*> mCache;
uint32_t mSize;
diff --git a/libs/hwui/VertexBuffer.h b/libs/hwui/VertexBuffer.h
index d81dd42..9be4d84 100644
--- a/libs/hwui/VertexBuffer.h
+++ b/libs/hwui/VertexBuffer.h
@@ -24,11 +24,10 @@ namespace uirenderer {
class VertexBuffer {
public:
- enum Mode {
- kStandard = 0,
- kOnePolyRingShadow = 1,
- kTwoPolyRingShadow = 2,
- kIndices = 3
+ enum MeshFeatureFlags {
+ kNone = 0,
+ kAlpha = 1 << 0,
+ kIndices = 1 << 1,
};
VertexBuffer()
@@ -39,7 +38,7 @@ public:
, mAllocatedVertexCount(0)
, mAllocatedIndexCount(0)
, mByteCount(0)
- , mMode(kStandard)
+ , mMeshFeatureFlags(kNone)
, mReallocBuffer(nullptr)
, mCleanupMethod(nullptr)
, mCleanupIndexMethod(nullptr)
@@ -135,10 +134,12 @@ public:
void updateVertexCount(unsigned int newCount) {
mVertexCount = MathUtils::min(newCount, mAllocatedVertexCount);
}
- Mode getMode() const { return mMode; }
+ MeshFeatureFlags getMeshFeatureFlags() const { return mMeshFeatureFlags; }
+ void setMeshFeatureFlags(int flags) {
+ mMeshFeatureFlags = static_cast<MeshFeatureFlags>(flags);
+ }
void setBounds(Rect bounds) { mBounds = bounds; }
- void setMode(Mode mode) { mMode = mode; }
template <class TYPE>
void createDegenerateSeparators(int allocSize) {
@@ -166,7 +167,7 @@ private:
unsigned int mAllocatedIndexCount;
unsigned int mByteCount;
- Mode mMode;
+ MeshFeatureFlags mMeshFeatureFlags;
void* mReallocBuffer; // used for multi-allocation
diff --git a/libs/hwui/font/CacheTexture.cpp b/libs/hwui/font/CacheTexture.cpp
index 53fa0dc..9314126 100644
--- a/libs/hwui/font/CacheTexture.cpp
+++ b/libs/hwui/font/CacheTexture.cpp
@@ -120,7 +120,7 @@ CacheTexture::CacheTexture(uint16_t width, uint16_t height, GLenum format, uint3
// OpenGL ES 3.0+ lets us specify the row length for unpack operations such
// as glTexSubImage2D(). This allows us to upload a sub-rectangle of a texture.
// With OpenGL ES 2.0 we have to upload entire stripes instead.
- mHasUnpackRowLength = Extensions::getInstance().hasUnpackRowLength();
+ mHasUnpackRowLength = mCaches.extensions().hasUnpackRowLength();
}
CacheTexture::~CacheTexture() {
diff --git a/libs/hwui/renderstate/Blend.cpp b/libs/hwui/renderstate/Blend.cpp
index 93088e4..c751dba 100644
--- a/libs/hwui/renderstate/Blend.cpp
+++ b/libs/hwui/renderstate/Blend.cpp
@@ -127,6 +127,10 @@ void Blend::setFactors(GLenum srcMode, GLenum dstMode) {
}
}
+void Blend::dump() {
+ ALOGD("Blend: enabled %d, func src %d, dst %d", mEnabled, mSrcMode, mDstMode);
+}
+
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/renderstate/Blend.h b/libs/hwui/renderstate/Blend.h
index 31d7dde..6d0c115 100644
--- a/libs/hwui/renderstate/Blend.h
+++ b/libs/hwui/renderstate/Blend.h
@@ -35,6 +35,8 @@ public:
static void getFactors(SkXfermode::Mode mode, bool swapSrcDst, GLenum* outSrc, GLenum* outDst);
void setFactors(GLenum src, GLenum dst);
+
+ void dump();
private:
Blend();
void invalidate();
diff --git a/libs/hwui/renderstate/MeshState.cpp b/libs/hwui/renderstate/MeshState.cpp
index 50c09c8..ce6030d 100644
--- a/libs/hwui/renderstate/MeshState.cpp
+++ b/libs/hwui/renderstate/MeshState.cpp
@@ -23,22 +23,20 @@ namespace android {
namespace uirenderer {
MeshState::MeshState()
- : mCurrentPositionPointer(this)
+ : mCurrentIndicesBuffer(0)
+ , mCurrentPixelBuffer(0)
+ , mCurrentPositionPointer(this)
, mCurrentPositionStride(0)
, mCurrentTexCoordsPointer(this)
, mCurrentTexCoordsStride(0)
- , mTexCoordsArrayEnabled(false) {
+ , mTexCoordsArrayEnabled(false)
+ , mQuadListIndices(0) {
glGenBuffers(1, &mUnitQuadBuffer);
glBindBuffer(GL_ARRAY_BUFFER, mUnitQuadBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(kUnitQuadVertices), kUnitQuadVertices, GL_STATIC_DRAW);
mCurrentBuffer = mUnitQuadBuffer;
- mCurrentIndicesBuffer = 0;
- mCurrentPixelBuffer = 0;
-
- mQuadListIndices = 0;
- mShadowStripsIndices = 0;
// position attribute always enabled
glEnableVertexAttribArray(Program::kBindingPosition);
@@ -50,9 +48,10 @@ MeshState::~MeshState() {
glDeleteBuffers(1, &mQuadListIndices);
mQuadListIndices = 0;
+}
- glDeleteBuffers(1, &mShadowStripsIndices);
- mShadowStripsIndices = 0;
+void MeshState::dump() {
+ ALOGD("MeshState vertices: unitQuad %d, current %d", mUnitQuadBuffer, mCurrentBuffer);
}
///////////////////////////////////////////////////////////////////////////////
@@ -65,18 +64,17 @@ bool MeshState::bindMeshBuffer() {
bool MeshState::bindMeshBuffer(GLuint buffer) {
if (!buffer) buffer = mUnitQuadBuffer;
- if (mCurrentBuffer != buffer) {
- glBindBuffer(GL_ARRAY_BUFFER, buffer);
- mCurrentBuffer = buffer;
- return true;
- }
- return false;
+ return bindMeshBufferInternal(buffer);
}
bool MeshState::unbindMeshBuffer() {
- if (mCurrentBuffer) {
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- mCurrentBuffer = 0;
+ return bindMeshBufferInternal(0);
+}
+
+bool MeshState::bindMeshBufferInternal(GLuint buffer) {
+ if (mCurrentBuffer != buffer) {
+ glBindBuffer(GL_ARRAY_BUFFER, buffer);
+ mCurrentBuffer = buffer;
return true;
}
return false;
@@ -163,20 +161,6 @@ bool MeshState::bindQuadIndicesBuffer() {
return bindIndicesBufferInternal(mQuadListIndices);
}
-bool MeshState::bindShadowIndicesBuffer() {
- if (!mShadowStripsIndices) {
- std::unique_ptr<uint16_t[]> shadowIndices(new uint16_t[MAX_SHADOW_INDEX_COUNT]);
- ShadowTessellator::generateShadowIndices(shadowIndices.get());
- glGenBuffers(1, &mShadowStripsIndices);
- bool force = bindIndicesBufferInternal(mShadowStripsIndices);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, MAX_SHADOW_INDEX_COUNT * sizeof(uint16_t),
- shadowIndices.get(), GL_STATIC_DRAW);
- return force;
- }
-
- return bindIndicesBufferInternal(mShadowStripsIndices);
-}
-
bool MeshState::unbindIndicesBuffer() {
if (mCurrentIndicesBuffer) {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
diff --git a/libs/hwui/renderstate/MeshState.h b/libs/hwui/renderstate/MeshState.h
index 5cb1143..afc6267 100644
--- a/libs/hwui/renderstate/MeshState.h
+++ b/libs/hwui/renderstate/MeshState.h
@@ -47,7 +47,7 @@ const GLsizei kMeshTextureOffset = 2 * sizeof(float);
const GLsizei kVertexAlphaOffset = 2 * sizeof(float);
const GLsizei kVertexAAWidthOffset = 2 * sizeof(float);
const GLsizei kVertexAALengthOffset = 3 * sizeof(float);
-const GLsizei kMeshCount = 4;
+const GLsizei kUnitQuadCount = 4;
class MeshState {
private:
@@ -55,6 +55,7 @@ private:
public:
~MeshState();
+ void dump();
///////////////////////////////////////////////////////////////////////////////
// Buffer objects
///////////////////////////////////////////////////////////////////////////////
@@ -107,7 +108,6 @@ public:
* gMaxNumberOfQuads quads.
*/
bool bindQuadIndicesBuffer();
- bool bindShadowIndicesBuffer();
bool unbindIndicesBuffer();
///////////////////////////////////////////////////////////////////////////////
@@ -116,9 +116,9 @@ public:
GLuint getUnitQuadVBO() { return mUnitQuadBuffer; }
private:
MeshState();
+ bool bindMeshBufferInternal(const GLuint buffer);
bool bindIndicesBufferInternal(const GLuint buffer);
- // VBO to draw with
GLuint mUnitQuadBuffer;
GLuint mCurrentBuffer;
@@ -134,7 +134,6 @@ private:
// Global index buffer
GLuint mQuadListIndices;
- GLuint mShadowStripsIndices;
};
} /* namespace uirenderer */
diff --git a/libs/hwui/renderstate/RenderState.cpp b/libs/hwui/renderstate/RenderState.cpp
index 0cb3ddb..ba49833 100644
--- a/libs/hwui/renderstate/RenderState.cpp
+++ b/libs/hwui/renderstate/RenderState.cpp
@@ -17,6 +17,7 @@
#include "renderthread/CanvasContext.h"
#include "renderthread/EglManager.h"
+#include "utils/GLUtils.h"
namespace android {
namespace uirenderer {
@@ -215,18 +216,41 @@ void RenderState::render(const Glop& glop) {
const Glop::Mesh& mesh = glop.mesh;
const Glop::Fill& shader = glop.fill;
+ // --------------------------------------------
// ---------- Shader + uniform setup ----------
+ // --------------------------------------------
mCaches->setProgram(shader.program);
- Glop::Fill::Color color = shader.color;
+ Glop::FloatColor color = shader.color;
shader.program->setColor(color.r, color.g, color.b, color.a);
shader.program->set(glop.transform.ortho,
glop.transform.modelView,
glop.transform.canvas,
- glop.transform.offset);
+ glop.transform.fudgingOffset);
+
+ if (glop.fill.filterMode == ProgramDescription::kColorBlend) {
+ const Glop::FloatColor& color = glop.fill.filter.color;
+ glUniform4f(mCaches->program().getUniform("colorBlend"),
+ color.r, color.g, color.b, color.a);
+ } else if (glop.fill.filterMode == ProgramDescription::kColorMatrix) {
+ glUniformMatrix4fv(mCaches->program().getUniform("colorMatrix"), 1, GL_FALSE,
+ glop.fill.filter.matrix.matrix);
+ glUniform4fv(mCaches->program().getUniform("colorMatrixVector"), 1,
+ glop.fill.filter.matrix.vector);
+ }
+ // --------------------------------
// ---------- Mesh setup ----------
+ // --------------------------------
+ // vertices
+ bool force = meshState().bindMeshBufferInternal(mesh.vertexBufferObject)
+ || (mesh.vertices != nullptr);
+ meshState().bindPositionVertexPointer(force, mesh.vertices, mesh.stride);
+
+ // indices
+ meshState().bindIndicesBufferInternal(mesh.indexBufferObject);
+
if (glop.mesh.vertexFlags & kTextureCoord_Attrib) {
// TODO: support textures
LOG_ALWAYS_FATAL("textures not yet supported");
@@ -234,41 +258,43 @@ void RenderState::render(const Glop& glop) {
meshState().disableTexCoordsVertexArray();
}
if (glop.mesh.vertexFlags & kColor_Attrib) {
- LOG_ALWAYS_FATAL("color attribute not yet supported");
+ LOG_ALWAYS_FATAL("color vertex attribute not yet supported");
// TODO: enable color, disable when done
}
+ int alphaSlot = -1;
if (glop.mesh.vertexFlags & kAlpha_Attrib) {
- LOG_ALWAYS_FATAL("alpha attribute not yet supported");
- // TODO: enable alpha attribute, disable when done
+ const void* alphaCoords = ((const GLbyte*) glop.mesh.vertices) + kVertexAlphaOffset;
+ alphaSlot = shader.program->getAttrib("vtxAlpha");
+ glEnableVertexAttribArray(alphaSlot);
+ glVertexAttribPointer(alphaSlot, 1, GL_FLOAT, GL_FALSE, kAlphaVertexStride, alphaCoords);
}
- /**
- * Hard-coded vertex assumptions:
- * - required
- * - xy floats
- * - 0 offset
- * - in VBO
- */
- bool force = meshState().bindMeshBuffer(mesh.vertexBufferObject);
- meshState().bindPositionVertexPointer(force, nullptr, mesh.stride);
-
- /**
- * Hard-coded index assumptions:
- * - optional
- * - 0 offset
- * - in IBO
- */
- meshState().bindIndicesBufferInternal(mesh.indexBufferObject);
-
+ // ------------------------------------
// ---------- GL state setup ----------
+ // ------------------------------------
blend().setFactors(glop.blend.src, glop.blend.dst);
- if (mesh.indexBufferObject) {
- glDrawElements(glop.mesh.primitiveMode, glop.mesh.vertexCount, GL_UNSIGNED_BYTE, nullptr);
+ // ------------------------------------
+ // ---------- GL state setup ----------
+ // ------------------------------------
+ if (mesh.indexBufferObject || mesh.indices) {
+ glDrawElements(glop.mesh.primitiveMode, glop.mesh.vertexCount,
+ GL_UNSIGNED_SHORT, mesh.indices);
} else {
- glDrawArrays(GL_TRIANGLE_STRIP, 0, glop.mesh.vertexCount);
+ glDrawArrays(glop.mesh.primitiveMode, 0, glop.mesh.vertexCount);
+ }
+
+ if (glop.mesh.vertexFlags & kAlpha_Attrib) {
+ glDisableVertexAttribArray(alphaSlot);
}
}
+void RenderState::dump() {
+ blend().dump();
+ meshState().dump();
+ scissor().dump();
+ stencil().dump();
+}
+
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/renderstate/RenderState.h b/libs/hwui/renderstate/RenderState.h
index 2e28ff6..4fd792c 100644
--- a/libs/hwui/renderstate/RenderState.h
+++ b/libs/hwui/renderstate/RenderState.h
@@ -91,6 +91,8 @@ public:
MeshState& meshState() { return *mMeshState; }
Scissor& scissor() { return *mScissor; }
Stencil& stencil() { return *mStencil; }
+
+ void dump();
private:
friend class renderthread::RenderThread;
friend class Caches;
@@ -99,9 +101,6 @@ private:
void resumeFromFunctorInvoke();
void assertOnGLThread();
- void setupVertexAttributes(const Glop& glop);
- void tearDownVertexAttributes(const Glop& glop);
-
RenderState(renderthread::RenderThread& thread);
~RenderState();
diff --git a/libs/hwui/renderstate/Scissor.cpp b/libs/hwui/renderstate/Scissor.cpp
index 66c31a2..95dcd18 100644
--- a/libs/hwui/renderstate/Scissor.cpp
+++ b/libs/hwui/renderstate/Scissor.cpp
@@ -15,6 +15,8 @@
*/
#include "renderstate/Scissor.h"
+#include <utils/Log.h>
+
namespace android {
namespace uirenderer {
@@ -79,6 +81,11 @@ void Scissor::invalidate() {
reset();
}
+void Scissor::dump() {
+ ALOGD("Scissor: enabled %d, %d %d %d %d",
+ mEnabled, mScissorX, mScissorY, mScissorWidth, mScissorHeight);
+}
+
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/renderstate/Scissor.h b/libs/hwui/renderstate/Scissor.h
index cc8b3dd..b37ec58 100644
--- a/libs/hwui/renderstate/Scissor.h
+++ b/libs/hwui/renderstate/Scissor.h
@@ -29,6 +29,7 @@ public:
bool set(GLint x, GLint y, GLint width, GLint height);
void reset();
bool isEnabled() { return mEnabled; }
+ void dump();
private:
Scissor();
void invalidate();
diff --git a/libs/hwui/renderstate/Stencil.cpp b/libs/hwui/renderstate/Stencil.cpp
index acbed14..cedb233 100644
--- a/libs/hwui/renderstate/Stencil.cpp
+++ b/libs/hwui/renderstate/Stencil.cpp
@@ -14,10 +14,12 @@
* limitations under the License.
*/
+#include "renderstate/Stencil.h"
+
+#include "Caches.h"
#include "Debug.h"
#include "Extensions.h"
#include "Properties.h"
-#include "renderstate/Stencil.h"
#include <GLES2/gl2ext.h>
@@ -42,7 +44,7 @@ uint8_t Stencil::getStencilSize() {
GLenum Stencil::getSmallestStencilFormat() {
#if !DEBUG_STENCIL
- const Extensions& extensions = Extensions::getInstance();
+ const Extensions& extensions = Caches::getInstance().extensions();
if (extensions.has1BitStencil()) {
return GL_STENCIL_INDEX1_OES;
} else if (extensions.has4BitStencil()) {
@@ -123,5 +125,9 @@ void Stencil::disable() {
}
}
+void Stencil::dump() {
+ ALOGD("Stencil: state %d", mState);
+}
+
}; // namespace uirenderer
}; // namespace android
diff --git a/libs/hwui/renderstate/Stencil.h b/libs/hwui/renderstate/Stencil.h
index 20bb955..a88beae 100644
--- a/libs/hwui/renderstate/Stencil.h
+++ b/libs/hwui/renderstate/Stencil.h
@@ -98,6 +98,8 @@ public:
return mState == kTest;
}
+ void dump();
+
private:
void enable();
diff --git a/libs/hwui/tests/main.cpp b/libs/hwui/tests/main.cpp
index 1e7ba23..5f445f4 100644
--- a/libs/hwui/tests/main.cpp
+++ b/libs/hwui/tests/main.cpp
@@ -201,6 +201,45 @@ private:
}
};
+class OvalAnimation : public TreeContentAnimation {
+public:
+ sp<RenderNode> card;
+ void createContent(int width, int height, DisplayListRenderer* renderer) override {
+ android::uirenderer::Rect DUMMY;
+
+ renderer->drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
+ renderer->insertReorderBarrier(true);
+
+ card = createCard(40, 40, 200, 200);
+ renderer->drawRenderNode(card.get(), DUMMY, 0);
+
+ renderer->insertReorderBarrier(false);
+ }
+
+ void doFrame(int frameNr) override {
+ card->mutateStagingProperties().setTranslationX(frameNr);
+ card->mutateStagingProperties().setTranslationY(frameNr);
+ card->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
+ }
+private:
+ sp<RenderNode> createCard(int x, int y, int width, int height) {
+ sp<RenderNode> node = new RenderNode();
+ node->mutateStagingProperties().setLeftTopRightBottom(x, y, x + width, y + height);
+ node->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
+
+ DisplayListRenderer* renderer = startRecording(node.get());
+ renderer->drawColor(0xFFFF00FF, SkXfermode::kSrcOver_Mode);
+
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setColor(0xFF00FFFF);
+ renderer->drawOval(0, 0, width, height, paint);
+
+ endRecording(renderer, node.get());
+ return node;
+ }
+};
+
struct cstr_cmp {
bool operator()(const char *a, const char *b) const {
return std::strcmp(a, b) < 0;
@@ -212,6 +251,7 @@ typedef void (*testProc)();
std::map<const char*, testProc, cstr_cmp> gTestMap {
{"shadowgrid", TreeContentAnimation::run<ShadowGridAnimation>},
{"rectgrid", TreeContentAnimation::run<RectGridAnimation> },
+ {"oval", TreeContentAnimation::run<OvalAnimation> },
};
int main(int argc, char* argv[]) {
diff --git a/libs/hwui/utils/PaintUtils.h b/libs/hwui/utils/PaintUtils.h
index 2091705..679e2bf 100644
--- a/libs/hwui/utils/PaintUtils.h
+++ b/libs/hwui/utils/PaintUtils.h
@@ -52,6 +52,13 @@ public:
&& getXfermode(paint.getXfermode()) == SkXfermode::kSrcOver_Mode;
}
+ static bool isBlendedShader(const SkShader* shader) {
+ if (shader == nullptr) {
+ return false;
+ }
+ return !shader->isOpaque();
+ }
+
static bool isBlendedColorFilter(const SkColorFilter* filter) {
if (filter == nullptr) {
return false;