summaryrefslogtreecommitdiffstats
path: root/libs
diff options
context:
space:
mode:
authorChris Craik <ccraik@google.com>2015-02-05 00:25:03 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2015-02-05 00:25:04 +0000
commitecad24b49d20f7fb4b75950e9444787967acd347 (patch)
tree74c55efb6736b3b142a299f2c1feae32abf06b7a /libs
parente8d05b5bab49f2becb1762b70275d3914de23be2 (diff)
parent031888744e24b5c7243ac99ec98b78aff5db1c78 (diff)
downloadframeworks_base-ecad24b49d20f7fb4b75950e9444787967acd347.zip
frameworks_base-ecad24b49d20f7fb4b75950e9444787967acd347.tar.gz
frameworks_base-ecad24b49d20f7fb4b75950e9444787967acd347.tar.bz2
Merge "GlopBuilder, and test app refactor"
Diffstat (limited to 'libs')
-rw-r--r--libs/hwui/Android.common.mk7
-rw-r--r--libs/hwui/Glop.h17
-rw-r--r--libs/hwui/GlopBuilder.cpp133
-rw-r--r--libs/hwui/GlopBuilder.h55
-rw-r--r--libs/hwui/OpenGLRenderer.cpp11
-rw-r--r--libs/hwui/RenderNode.cpp5
-rw-r--r--libs/hwui/ResourceCache.h2
-rw-r--r--libs/hwui/Snapshot.cpp4
-rw-r--r--libs/hwui/renderstate/Blend.cpp41
-rw-r--r--libs/hwui/renderstate/Blend.h3
-rw-r--r--libs/hwui/renderstate/MeshState.cpp14
-rw-r--r--libs/hwui/renderstate/MeshState.h8
-rw-r--r--libs/hwui/renderstate/RenderState.cpp11
-rw-r--r--libs/hwui/tests/main.cpp215
-rw-r--r--libs/hwui/utils/PaintUtils.h3
15 files changed, 417 insertions, 112 deletions
diff --git a/libs/hwui/Android.common.mk b/libs/hwui/Android.common.mk
index a05217f..e05dd55 100644
--- a/libs/hwui/Android.common.mk
+++ b/libs/hwui/Android.common.mk
@@ -34,9 +34,9 @@ LOCAL_SRC_FILES := \
CanvasState.cpp \
ClipArea.cpp \
DamageAccumulator.cpp \
- DisplayList.cpp \
DeferredDisplayList.cpp \
DeferredLayerUpdater.cpp \
+ DisplayList.cpp \
DisplayListRenderer.cpp \
Dither.cpp \
DrawProfiler.cpp \
@@ -44,6 +44,7 @@ LOCAL_SRC_FILES := \
FboCache.cpp \
FontRenderer.cpp \
GammaFontRenderer.cpp \
+ GlopBuilder.cpp \
GradientCache.cpp \
Image.cpp \
Interpolator.cpp \
@@ -70,9 +71,9 @@ LOCAL_SRC_FILES := \
Snapshot.cpp \
SpotShadow.cpp \
TessellationCache.cpp \
+ TextDropShadowCache.cpp \
Texture.cpp \
- TextureCache.cpp \
- TextDropShadowCache.cpp
+ TextureCache.cpp
intermediates := $(call intermediates-dir-for,STATIC_LIBRARIES,libRS,TARGET,)
diff --git a/libs/hwui/Glop.h b/libs/hwui/Glop.h
index 730d9df..bbeb19e 100644
--- a/libs/hwui/Glop.h
+++ b/libs/hwui/Glop.h
@@ -23,10 +23,13 @@
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
+#include <SkXfermode.h>
namespace android {
namespace uirenderer {
+class Program;
+
/*
* Enumerates optional vertex attributes
*
@@ -53,18 +56,16 @@ struct Glop {
Rect bounds;
struct Mesh {
- VertexAttribFlags vertexFlags = static_cast<VertexAttribFlags>(0);
+ VertexAttribFlags vertexFlags;
GLuint primitiveMode; // GL_TRIANGLES and GL_TRIANGLE_STRIP supported
- GLuint vertexBufferObject = 0;
- GLuint indexBufferObject = 0;
+ GLuint vertexBufferObject;
+ GLuint indexBufferObject;
int vertexCount;
GLsizei stride;
} mesh;
struct Fill {
Program* program;
- GLuint shaderId;
- GLuint textureId;
struct Color {
float a, r, g, b;
@@ -89,10 +90,8 @@ struct Glop {
} transform;
struct Blend {
- static const SkXfermode::Mode kDisable =
- static_cast<SkXfermode::Mode>(SkXfermode::kLastMode + 1);
- SkXfermode::Mode mode;
- bool swapSrcDst;
+ GLenum src;
+ GLenum dst;
} blend;
/**
diff --git a/libs/hwui/GlopBuilder.cpp b/libs/hwui/GlopBuilder.cpp
new file mode 100644
index 0000000..dafe087
--- /dev/null
+++ b/libs/hwui/GlopBuilder.cpp
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2015 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 "GlopBuilder.h"
+
+#include "Caches.h"
+#include "Glop.h"
+#include "Matrix.h"
+#include "Texture.h"
+#include "renderstate/MeshState.h"
+#include "renderstate/RenderState.h"
+#include "utils/PaintUtils.h"
+
+#include <GLES2/gl2.h>
+#include <SkPaint.h>
+
+namespace android {
+namespace uirenderer {
+
+GlopBuilder::GlopBuilder(RenderState& renderState, Caches& caches, Glop* outGlop)
+ : mRenderState(renderState)
+ , mCaches(caches)
+ , mOutGlop(outGlop){
+}
+
+GlopBuilder& GlopBuilder::setMeshUnitQuad() {
+ mOutGlop->mesh.vertexFlags = static_cast<VertexAttribFlags>(0);
+ mOutGlop->mesh.primitiveMode = GL_TRIANGLE_STRIP;
+ mOutGlop->mesh.vertexBufferObject = mRenderState.meshState().getUnitQuadVBO();
+ mOutGlop->mesh.indexBufferObject = 0;
+ 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);
+ }
+
+ mOutGlop->transform.canvas.load(transform);
+
+ mOutGlop->transform.offset = offset;
+
+ mOutGlop->bounds.set(left, top, right, bottom);
+ mOutGlop->transform.canvas.mapRect(mOutGlop->bounds);
+ return *this;
+}
+
+GlopBuilder& GlopBuilder::setPaint(const SkPaint* paint, float alphaScale) {
+ // TODO: support null paint
+ const SkShader* shader = paint->getShader();
+ const SkColorFilter* colorFilter = paint->getColorFilter();
+
+ SkXfermode::Mode mode = PaintUtils::getXfermode(paint->getXfermode());
+ if (mode != SkXfermode::kClear_Mode) {
+ int color = paint->getColor();
+ float alpha = (SkColorGetA(color) / 255.0f) * alphaScale;
+ if (shader) {
+ // shader discards color channels
+ color |= 0x00FFFFFF;
+ }
+ 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};
+ if (mOutGlop->fill.color.a < 1.0f
+ || (shader && !shader->isOpaque())
+ || PaintUtils::isBlendedColorFilter(colorFilter)
+ || mode != SkXfermode::kSrcOver_Mode) {
+ if (CC_LIKELY(mode <= SkXfermode::kScreen_Mode)) {
+ Blend::getFactors(mode, SWAP_SRC_DST,
+ &mOutGlop->blend.src, &mOutGlop->blend.dst);
+ } else {
+ // These blend modes are not supported by OpenGL directly and have
+ // to be implemented using shaders. Since the shader will perform
+ // 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)) {
+ mDescription.framebufferMode = mode;
+ mDescription.swapSrcDst = SWAP_SRC_DST;
+ // blending in shader, don't enable
+ } else {
+ // unsupported
+ Blend::getFactors(SkXfermode::kSrcOver_Mode, SWAP_SRC_DST,
+ &mOutGlop->blend.src, &mOutGlop->blend.dst);
+ }
+ }
+ }
+
+ return *this;
+}
+
+GlopBuilder& GlopBuilder::setTexture(Texture* texture) {
+ LOG_ALWAYS_FATAL("not yet supported");
+ return *this;
+}
+
+void GlopBuilder::build() {
+ mDescription.modulate = mOutGlop->fill.color.a < 1.0f;
+ mOutGlop->fill.program = mCaches.programCache.get(mDescription);
+}
+
+} /* namespace uirenderer */
+} /* namespace android */
+
diff --git a/libs/hwui/GlopBuilder.h b/libs/hwui/GlopBuilder.h
new file mode 100644
index 0000000..d243d76
--- /dev/null
+++ b/libs/hwui/GlopBuilder.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2015 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 RENDERSTATE_GLOPBUILDER_H
+#define RENDERSTATE_GLOPBUILDER_H
+
+#include "OpenGLRenderer.h"
+#include "Program.h"
+#include "utils/Macros.h"
+
+class SkPaint;
+
+namespace android {
+namespace uirenderer {
+
+class Caches;
+struct Glop;
+class RenderState;
+class Texture;
+class Matrix4;
+
+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& setPaint(const SkPaint* paint, float alphaScale);
+ GlopBuilder& setTexture(Texture* texture);
+ void build();
+private:
+ ProgramDescription mDescription;
+ RenderState& mRenderState;
+ Caches& mCaches;
+ Glop* mOutGlop;
+};
+
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif // RENDERSTATE_GLOPBUILDER_H
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index b56ce4f..f4b12b6 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -19,10 +19,13 @@
#include "DeferredDisplayList.h"
#include "DisplayListRenderer.h"
#include "GammaFontRenderer.h"
+#include "Glop.h"
+#include "GlopBuilder.h"
#include "Patch.h"
#include "PathTessellator.h"
#include "Properties.h"
#include "RenderNode.h"
+#include "renderstate/MeshState.h"
#include "renderstate/RenderState.h"
#include "ShadowTessellator.h"
#include "SkiaShader.h"
@@ -100,7 +103,7 @@ OpenGLRenderer::OpenGLRenderer(RenderState& renderState)
memset(&mDrawModifiers, 0, sizeof(mDrawModifiers));
mDrawModifiers.mOverrideLayerAlpha = 1.0f;
- memcpy(mMeshVertices, kMeshVertices, sizeof(kMeshVertices));
+ memcpy(mMeshVertices, kUnitQuadVertices, sizeof(kUnitQuadVertices));
}
OpenGLRenderer::~OpenGLRenderer() {
@@ -1703,9 +1706,9 @@ void OpenGLRenderer::setupDrawBlending(const SkPaint* paint, bool blend, bool sw
// When the blending mode is kClear_Mode, we need to use a modulate color
// argb=1,0,0,0
accountForClear(mode);
- blend |= (mColorSet && mColorA < 1.0f) ||
- (getShader(paint) && !getShader(paint)->isOpaque()) ||
- PaintUtils::isBlendedColorFilter(getColorFilter(paint));
+ blend |= (mColorSet && mColorA < 1.0f)
+ || (getShader(paint) && !getShader(paint)->isOpaque())
+ || PaintUtils::isBlendedColorFilter(getColorFilter(paint));
chooseBlending(blend, mode, mDescription, swapSrcDst);
}
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index a0a5a1c..659ef6c 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -836,7 +836,6 @@ void RenderNode::issueOperationsOfProjectedChildren(OpenGLRenderer& renderer, T&
*/
template <class T>
void RenderNode::issueOperations(OpenGLRenderer& renderer, T& handler) {
- const int level = handler.level();
if (mDisplayListData->isEmpty()) {
DISPLAY_LIST_LOGD("%*sEmpty display list (%p, %s)", level * 2, "", this, getName());
return;
@@ -860,7 +859,7 @@ void RenderNode::issueOperations(OpenGLRenderer& renderer, T& handler) {
#if DEBUG_DISPLAY_LIST
const Rect& clipRect = renderer.getLocalClipBounds();
DISPLAY_LIST_LOGD("%*sStart display list (%p, %s), localClipBounds: %.0f, %.0f, %.0f, %.0f",
- level * 2, "", this, getName(),
+ handler.level() * 2, "", this, getName(),
clipRect.left, clipRect.top, clipRect.right, clipRect.bottom);
#endif
@@ -900,7 +899,7 @@ void RenderNode::issueOperations(OpenGLRenderer& renderer, T& handler) {
for (size_t opIndex = chunk.beginOpIndex; opIndex < chunk.endOpIndex; opIndex++) {
DisplayListOp *op = mDisplayListData->displayListOps[opIndex];
#if DEBUG_DISPLAY_LIST
- op->output(level + 1);
+ op->output(handler.level() + 1);
#endif
handler(op, saveCountOffset, properties().getClipToBounds());
diff --git a/libs/hwui/ResourceCache.h b/libs/hwui/ResourceCache.h
index c6483ac..4333792 100644
--- a/libs/hwui/ResourceCache.h
+++ b/libs/hwui/ResourceCache.h
@@ -81,7 +81,7 @@ private:
uint32_t mPixelRefStableID;
friend class ResourceCache;
- friend class android::key_value_pair_t<BitmapKey, SkBitmap*>;
+ friend struct android::key_value_pair_t<BitmapKey, SkBitmap*>;
};
class ANDROID_API ResourceCache: public Singleton<ResourceCache> {
diff --git a/libs/hwui/Snapshot.cpp b/libs/hwui/Snapshot.cpp
index 49fb4ba..597d95c 100644
--- a/libs/hwui/Snapshot.cpp
+++ b/libs/hwui/Snapshot.cpp
@@ -203,8 +203,8 @@ void Snapshot::dump() const {
ALOGD("Snapshot %p, flags %x, prev %p, height %d, ignored %d, hasComplexClip %d",
this, flags, previous.get(), getViewportHeight(), isIgnored(), !mClipArea->isSimple());
const Rect& clipRect(mClipArea->getClipRect());
- ALOGD(" ClipRect (at %p) %.1f %.1f %.1f %.1f",
- clipRect, clipRect.left, clipRect.top, clipRect.right, clipRect.bottom);
+ ALOGD(" ClipRect %.1f %.1f %.1f %.1f",
+ clipRect.left, clipRect.top, clipRect.right, clipRect.bottom);
ALOGD(" Transform (at %p):", transform);
transform->dump();
}
diff --git a/libs/hwui/renderstate/Blend.cpp b/libs/hwui/renderstate/Blend.cpp
index 3e7b721..93088e4 100644
--- a/libs/hwui/renderstate/Blend.cpp
+++ b/libs/hwui/renderstate/Blend.cpp
@@ -79,21 +79,10 @@ Blend::Blend()
}
void Blend::enable(SkXfermode::Mode mode, bool swapSrcDst) {
- // enable
- if (!mEnabled) {
- glEnable(GL_BLEND);
- mEnabled = true;
- }
-
- // select blend mode
- GLenum sourceMode = swapSrcDst ? kBlendsSwap[mode].src : kBlends[mode].src;
- GLenum destMode = swapSrcDst ? kBlendsSwap[mode].dst : kBlends[mode].dst;
-
- if (sourceMode != mSrcMode || destMode != mSrcMode) {
- glBlendFunc(sourceMode, destMode);
- mSrcMode = sourceMode;
- mDstMode = destMode;
- }
+ GLenum srcMode;
+ GLenum dstMode;
+ getFactors(mode, swapSrcDst, &srcMode, &dstMode);
+ setFactors(srcMode, dstMode);
}
void Blend::disable() {
@@ -116,6 +105,28 @@ void Blend::syncEnabled() {
}
}
+void Blend::getFactors(SkXfermode::Mode mode, bool swapSrcDst, GLenum* outSrc, GLenum* outDst) {
+ *outSrc = swapSrcDst ? kBlendsSwap[mode].src : kBlends[mode].src;
+ *outDst = swapSrcDst ? kBlendsSwap[mode].dst : kBlends[mode].dst;
+}
+
+void Blend::setFactors(GLenum srcMode, GLenum dstMode) {
+ if (srcMode == GL_ZERO && dstMode == GL_ZERO) {
+ disable();
+ } else {
+ if (!mEnabled) {
+ glEnable(GL_BLEND);
+ mEnabled = true;
+ }
+
+ if (srcMode != mSrcMode || dstMode != mSrcMode) {
+ glBlendFunc(srcMode, dstMode);
+ mSrcMode = srcMode;
+ mDstMode = dstMode;
+ }
+ }
+}
+
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/renderstate/Blend.h b/libs/hwui/renderstate/Blend.h
index b82b477..31d7dde 100644
--- a/libs/hwui/renderstate/Blend.h
+++ b/libs/hwui/renderstate/Blend.h
@@ -32,6 +32,9 @@ public:
void enable(SkXfermode::Mode mode, bool swapSrcDst);
void disable();
void syncEnabled();
+
+ static void getFactors(SkXfermode::Mode mode, bool swapSrcDst, GLenum* outSrc, GLenum* outDst);
+ void setFactors(GLenum src, GLenum dst);
private:
Blend();
void invalidate();
diff --git a/libs/hwui/renderstate/MeshState.cpp b/libs/hwui/renderstate/MeshState.cpp
index 022faf7..50c09c8 100644
--- a/libs/hwui/renderstate/MeshState.cpp
+++ b/libs/hwui/renderstate/MeshState.cpp
@@ -29,11 +29,11 @@ MeshState::MeshState()
, mCurrentTexCoordsStride(0)
, mTexCoordsArrayEnabled(false) {
- glGenBuffers(1, &meshBuffer);
- glBindBuffer(GL_ARRAY_BUFFER, meshBuffer);
- glBufferData(GL_ARRAY_BUFFER, sizeof(kMeshVertices), kMeshVertices, GL_STATIC_DRAW);
+ glGenBuffers(1, &mUnitQuadBuffer);
+ glBindBuffer(GL_ARRAY_BUFFER, mUnitQuadBuffer);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(kUnitQuadVertices), kUnitQuadVertices, GL_STATIC_DRAW);
- mCurrentBuffer = meshBuffer;
+ mCurrentBuffer = mUnitQuadBuffer;
mCurrentIndicesBuffer = 0;
mCurrentPixelBuffer = 0;
@@ -45,7 +45,7 @@ MeshState::MeshState()
}
MeshState::~MeshState() {
- glDeleteBuffers(1, &meshBuffer);
+ glDeleteBuffers(1, &mUnitQuadBuffer);
mCurrentBuffer = 0;
glDeleteBuffers(1, &mQuadListIndices);
@@ -60,11 +60,11 @@ MeshState::~MeshState() {
///////////////////////////////////////////////////////////////////////////////
bool MeshState::bindMeshBuffer() {
- return bindMeshBuffer(meshBuffer);
+ return bindMeshBuffer(mUnitQuadBuffer);
}
bool MeshState::bindMeshBuffer(GLuint buffer) {
- if (!buffer) buffer = meshBuffer;
+ if (!buffer) buffer = mUnitQuadBuffer;
if (mCurrentBuffer != buffer) {
glBindBuffer(GL_ARRAY_BUFFER, buffer);
mCurrentBuffer = buffer;
diff --git a/libs/hwui/renderstate/MeshState.h b/libs/hwui/renderstate/MeshState.h
index 9b1021d..5cb1143 100644
--- a/libs/hwui/renderstate/MeshState.h
+++ b/libs/hwui/renderstate/MeshState.h
@@ -32,7 +32,7 @@ const uint32_t kMaxNumberOfQuads = 2048;
// This array is never used directly but used as a memcpy source in the
// OpenGLRenderer constructor
-const TextureVertex kMeshVertices[] = {
+const TextureVertex kUnitQuadVertices[] = {
{ 0, 0, 0, 0 },
{ 1, 0, 1, 0 },
{ 0, 1, 0, 1 },
@@ -110,12 +110,16 @@ public:
bool bindShadowIndicesBuffer();
bool unbindIndicesBuffer();
+ ///////////////////////////////////////////////////////////////////////////////
+ // Getters - for use in Glop building
+ ///////////////////////////////////////////////////////////////////////////////
+ GLuint getUnitQuadVBO() { return mUnitQuadBuffer; }
private:
MeshState();
bool bindIndicesBufferInternal(const GLuint buffer);
// VBO to draw with
- GLuint meshBuffer;
+ GLuint mUnitQuadBuffer;
GLuint mCurrentBuffer;
GLuint mCurrentIndicesBuffer;
diff --git a/libs/hwui/renderstate/RenderState.cpp b/libs/hwui/renderstate/RenderState.cpp
index 5e02844..0cb3ddb 100644
--- a/libs/hwui/renderstate/RenderState.cpp
+++ b/libs/hwui/renderstate/RenderState.cpp
@@ -219,7 +219,7 @@ void RenderState::render(const Glop& glop) {
mCaches->setProgram(shader.program);
Glop::Fill::Color color = shader.color;
- shader.program->setColor(color.a, color.r, color.g, color.b);
+ shader.program->setColor(color.r, color.g, color.b, color.a);
shader.program->set(glop.transform.ortho,
glop.transform.modelView,
@@ -261,14 +261,13 @@ void RenderState::render(const Glop& glop) {
meshState().bindIndicesBufferInternal(mesh.indexBufferObject);
// ---------- GL state setup ----------
+ blend().setFactors(glop.blend.src, glop.blend.dst);
- if (glop.blend.mode != Glop::Blend::kDisable) {
- blend().enable(glop.blend.mode, glop.blend.swapSrcDst);
+ if (mesh.indexBufferObject) {
+ glDrawElements(glop.mesh.primitiveMode, glop.mesh.vertexCount, GL_UNSIGNED_BYTE, nullptr);
} else {
- blend().disable();
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, glop.mesh.vertexCount);
}
-
- glDrawElements(glop.mesh.primitiveMode, glop.mesh.vertexCount, GL_UNSIGNED_BYTE, nullptr);
}
} /* namespace uirenderer */
diff --git a/libs/hwui/tests/main.cpp b/libs/hwui/tests/main.cpp
index a12dac7..1e7ba23 100644
--- a/libs/hwui/tests/main.cpp
+++ b/libs/hwui/tests/main.cpp
@@ -42,7 +42,8 @@ public:
static DisplayListRenderer* startRecording(RenderNode* node) {
DisplayListRenderer* renderer = new DisplayListRenderer();
- renderer->setViewport(node->getWidth(), node->getHeight());
+ renderer->setViewport(node->stagingProperties().getWidth(),
+ node->stagingProperties().getHeight());
renderer->prepare();
return renderer;
}
@@ -53,80 +54,174 @@ static void endRecording(DisplayListRenderer* renderer, RenderNode* node) {
delete renderer;
}
-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->mutateStagingProperties().setElevation(dp(16));
- node->mutateStagingProperties().mutableOutline().setRoundRect(0, 0, width, height, dp(10), 1);
- node->mutateStagingProperties().mutableOutline().setShouldClip(true);
- node->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y | RenderNode::Z);
-
- DisplayListRenderer* renderer = startRecording(node.get());
- renderer->drawColor(0xFFEEEEEE, SkXfermode::kSrcOver_Mode);
- endRecording(renderer, node.get());
+class TreeContentAnimation {
+public:
+ virtual ~TreeContentAnimation() {}
+ virtual int getFrameCount() { return 150; }
+ virtual void createContent(int width, int height, DisplayListRenderer* renderer) = 0;
+ virtual void doFrame(int frameNr) = 0;
+
+ template <class T>
+ static void run() {
+ T animation;
+
+ TestContext testContext;
+
+ // create the native surface
+ const int width = gDisplay.w;
+ const int height = gDisplay.h;
+ sp<Surface> surface = testContext.surface();
+
+ RenderNode* rootNode = new RenderNode();
+ rootNode->incStrong(nullptr);
+ rootNode->mutateStagingProperties().setLeftTopRightBottom(0, 0, width, height);
+ rootNode->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
+ rootNode->mutateStagingProperties().setClipToBounds(false);
+ rootNode->setPropertyFieldsDirty(RenderNode::GENERIC);
+
+ ContextFactory factory;
+ std::unique_ptr<RenderProxy> proxy(new RenderProxy(false, rootNode, &factory));
+ proxy->loadSystemProperties();
+ proxy->initialize(surface);
+ float lightX = width / 2.0;
+ proxy->setup(width, height, (Vector3){lightX, dp(-200.0f), dp(800.0f)},
+ dp(800.0f), 255 * 0.075, 255 * 0.15);
+
+ android::uirenderer::Rect DUMMY;
+
+ std::vector< sp<RenderNode> > cards;
+
+ DisplayListRenderer* renderer = startRecording(rootNode);
+ animation.createContent(width, height, renderer);
+ endRecording(renderer, rootNode);
+
+ for (int i = 0; i < 150; i++) {
+ testContext.waitForVsync();
+
+ ATRACE_NAME("UI-Draw Frame");
+ animation.doFrame(i);
+ nsecs_t frameTimeNs = systemTime(CLOCK_MONOTONIC);
+ proxy->syncAndDrawFrame(frameTimeNs, 0, gDisplay.density);
+ }
- return node;
-}
+ sleep(5);
-int main(int argc, char* argv[]) {
- TestContext testContext;
-
- // create the native surface
- const int width = gDisplay.w;
- const int height = gDisplay.h;
- sp<Surface> surface = testContext.surface();
-
- RenderNode* rootNode = new RenderNode();
- rootNode->incStrong(nullptr);
- rootNode->mutateStagingProperties().setLeftTopRightBottom(0, 0, width, height);
- rootNode->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
- rootNode->mutateStagingProperties().setClipToBounds(false);
- rootNode->setPropertyFieldsDirty(RenderNode::GENERIC);
-
- ContextFactory factory;
- std::unique_ptr<RenderProxy> proxy(new RenderProxy(false, rootNode, &factory));
- proxy->loadSystemProperties();
- proxy->initialize(surface);
- float lightX = width / 2.0;
- proxy->setup(width, height, (Vector3){lightX, dp(-200.0f), dp(800.0f)},
- dp(800.0f), 255 * 0.075, 255 * 0.15);
-
- android::uirenderer::Rect DUMMY;
+ rootNode->decStrong(nullptr);
+ }
+};
+class ShadowGridAnimation : public TreeContentAnimation {
+public:
std::vector< sp<RenderNode> > cards;
+ void createContent(int width, int height, DisplayListRenderer* renderer) override {
+ android::uirenderer::Rect DUMMY;
+
+ renderer->drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
+ renderer->insertReorderBarrier(true);
+
+ for (int x = dp(16); x < (width - dp(116)); x += dp(116)) {
+ for (int y = dp(16); y < (height - dp(116)); y += dp(116)) {
+ sp<RenderNode> card = createCard(x, y, dp(100), dp(100));
+ renderer->drawRenderNode(card.get(), DUMMY, 0);
+ cards.push_back(card);
+ }
+ }
- DisplayListRenderer* renderer = startRecording(rootNode);
- renderer->drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
- renderer->insertReorderBarrier(true);
-
- for (int x = dp(16); x < (width - dp(116)); x += dp(116)) {
- for (int y = dp(16); y < (height - dp(116)); y += dp(116)) {
- sp<RenderNode> card = createCard(x, y, dp(100), dp(100));
- renderer->drawRenderNode(card.get(), DUMMY, 0);
- cards.push_back(card);
+ renderer->insertReorderBarrier(false);
+ }
+ void doFrame(int frameNr) override {
+ for (size_t ci = 0; ci < cards.size(); ci++) {
+ cards[ci]->mutateStagingProperties().setTranslationX(frameNr);
+ cards[ci]->mutateStagingProperties().setTranslationY(frameNr);
+ cards[ci]->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->mutateStagingProperties().setElevation(dp(16));
+ node->mutateStagingProperties().mutableOutline().setRoundRect(0, 0, width, height, dp(10), 1);
+ node->mutateStagingProperties().mutableOutline().setShouldClip(true);
+ node->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y | RenderNode::Z);
+
+ DisplayListRenderer* renderer = startRecording(node.get());
+ renderer->drawColor(0xFFEEEEEE, SkXfermode::kSrcOver_Mode);
+ endRecording(renderer, node.get());
+ return node;
+ }
+};
- renderer->insertReorderBarrier(false);
- endRecording(renderer, rootNode);
+class RectGridAnimation : public TreeContentAnimation {
+public:
+ sp<RenderNode> card;
+ void createContent(int width, int height, DisplayListRenderer* renderer) override {
+ android::uirenderer::Rect DUMMY;
- for (int i = 0; i < 150; i++) {
- testContext.waitForVsync();
+ renderer->drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
+ renderer->insertReorderBarrier(true);
- ATRACE_NAME("UI-Draw Frame");
- for (size_t ci = 0; ci < cards.size(); ci++) {
- cards[ci]->mutateStagingProperties().setTranslationX(i);
- cards[ci]->mutateStagingProperties().setTranslationY(i);
- cards[ci]->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
+ 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);
+
+ float rects[width * height];
+ int index = 0;
+ for (int xOffset = 0; xOffset < width; xOffset+=2) {
+ for (int yOffset = 0; yOffset < height; yOffset+=2) {
+ rects[index++] = xOffset;
+ rects[index++] = yOffset;
+ rects[index++] = xOffset + 1;
+ rects[index++] = yOffset + 1;
+ }
}
- nsecs_t frameTimeNs = systemTime(CLOCK_MONOTONIC);
- proxy->syncAndDrawFrame(frameTimeNs, 0, gDisplay.density);
+ int count = width * height;
+
+ SkPaint paint;
+ paint.setColor(0xff00ffff);
+ renderer->drawRects(rects, count, &paint);
+
+ endRecording(renderer, node.get());
+ return node;
}
+};
- sleep(5);
+struct cstr_cmp {
+ bool operator()(const char *a, const char *b) const {
+ return std::strcmp(a, b) < 0;
+ }
+};
- rootNode->decStrong(nullptr);
+typedef void (*testProc)();
+std::map<const char*, testProc, cstr_cmp> gTestMap {
+ {"shadowgrid", TreeContentAnimation::run<ShadowGridAnimation>},
+ {"rectgrid", TreeContentAnimation::run<RectGridAnimation> },
+};
+
+int main(int argc, char* argv[]) {
+ const char* testName = argc > 1 ? argv[1] : "shadowgrid";
+ testProc proc = gTestMap[testName];
+ if(!proc) {
+ printf("Error: couldn't find test %s\n", testName);
+ return 1;
+ }
+ proc();
printf("Success!\n");
return 0;
}
diff --git a/libs/hwui/utils/PaintUtils.h b/libs/hwui/utils/PaintUtils.h
index fa0ae03..2091705 100644
--- a/libs/hwui/utils/PaintUtils.h
+++ b/libs/hwui/utils/PaintUtils.h
@@ -16,6 +16,9 @@
#ifndef PAINT_UTILS_H
#define PAINT_UTILS_H
+#include <SkColorFilter.h>
+#include <SkXfermode.h>
+
namespace android {
namespace uirenderer {