summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
Diffstat (limited to 'libs')
-rw-r--r--libs/hwui/FontRenderer.cpp13
-rw-r--r--libs/hwui/FrameInfo.cpp16
-rw-r--r--libs/hwui/FrameInfo.h9
-rw-r--r--libs/hwui/FrameInfoVisualizer.cpp104
-rw-r--r--libs/hwui/FrameInfoVisualizer.h40
-rw-r--r--libs/hwui/Glop.h47
-rw-r--r--libs/hwui/GlopBuilder.cpp91
-rw-r--r--libs/hwui/GlopBuilder.h24
-rw-r--r--libs/hwui/OpenGLRenderer.cpp97
-rwxr-xr-xlibs/hwui/OpenGLRenderer.h17
-rw-r--r--libs/hwui/SkiaShader.cpp15
-rw-r--r--libs/hwui/SkiaShader.h2
-rw-r--r--libs/hwui/renderstate/RenderState.cpp16
-rw-r--r--libs/hwui/renderthread/CanvasContext.cpp16
-rw-r--r--libs/hwui/renderthread/RenderProxy.cpp13
15 files changed, 312 insertions, 208 deletions
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index c79ae777d051..9664f58b1752 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -51,17 +51,20 @@ namespace uirenderer {
///////////////////////////////////////////////////////////////////////////////
void TextDrawFunctor::draw(CacheTexture& texture, bool linearFiltering) {
- int textureFillFlags = static_cast<int>(texture.getFormat() == GL_ALPHA
- ? TextureFillFlags::kIsAlphaMaskTexture : TextureFillFlags::kNone);
+ int textureFillFlags = TextureFillFlags::None;
+ if (texture.getFormat() == GL_ALPHA) {
+ textureFillFlags |= TextureFillFlags::IsAlphaMaskTexture;
+ }
if (linearFiltering) {
- textureFillFlags |= TextureFillFlags::kForceFilter;
+ textureFillFlags |= TextureFillFlags::ForceFilter;
}
- const Matrix4& transform = pureTranslate ? Matrix4::identity() : *(renderer->currentTransform());
+ int transformFlags = pureTranslate
+ ? TransformFlags::MeshIgnoresCanvasTransform : TransformFlags::None;
Glop glop;
GlopBuilder(renderer->mRenderState, renderer->mCaches, &glop)
.setMeshTexturedIndexedQuads(texture.mesh(), texture.meshElementCount())
.setFillTexturePaint(texture.getTexture(), textureFillFlags, paint, renderer->currentSnapshot()->alpha)
- .setTransform(renderer->currentSnapshot()->getOrthoMatrix(), transform, false)
+ .setTransform(*(renderer->currentSnapshot()), transformFlags)
.setModelViewOffsetRect(0, 0, Rect(0, 0, 0, 0))
.setRoundRectClipState(renderer->currentSnapshot()->roundRectClipState)
.build();
diff --git a/libs/hwui/FrameInfo.cpp b/libs/hwui/FrameInfo.cpp
index 6da1fa808d0a..c24833bf3509 100644
--- a/libs/hwui/FrameInfo.cpp
+++ b/libs/hwui/FrameInfo.cpp
@@ -20,6 +20,22 @@
namespace android {
namespace uirenderer {
+std::string FrameInfoNames[] = {
+ "Flags",
+ "IntendedVsync",
+ "Vsync",
+ "OldestInputEvent",
+ "NewestInputEvent",
+ "HandleInputStart",
+ "AnimationStart",
+ "PerformTraversalsStart",
+ "DrawStart",
+ "SyncStart",
+ "IssueDrawCommandsStart",
+ "SwapBuffers",
+ "FrameCompleted",
+};
+
void FrameInfo::importUiThreadInfo(int64_t* info) {
memcpy(mFrameInfo, info, UI_THREAD_FRAME_INFO_SIZE * sizeof(int64_t));
}
diff --git a/libs/hwui/FrameInfo.h b/libs/hwui/FrameInfo.h
index c8189b8df955..bcfae1b9e901 100644
--- a/libs/hwui/FrameInfo.h
+++ b/libs/hwui/FrameInfo.h
@@ -22,6 +22,7 @@
#include <utils/Timers.h>
#include <memory.h>
+#include <string>
namespace android {
namespace uirenderer {
@@ -49,6 +50,8 @@ enum class FrameInfoIndex {
kNumIndexes
};
+extern std::string FrameInfoNames[];
+
enum class FrameInfoFlags {
kWindowLayoutChanged = 1 << 0,
kRTAnimation = 1 << 1,
@@ -66,6 +69,12 @@ public:
UiFrameInfoBuilder& setVsync(nsecs_t vsyncTime, nsecs_t intendedVsync) {
set(FrameInfoIndex::kVsync) = vsyncTime;
set(FrameInfoIndex::kIntendedVsync) = intendedVsync;
+ // Pretend the other fields are all at vsync, too, so that naive
+ // duration calculations end up being 0 instead of very large
+ set(FrameInfoIndex::kHandleInputStart) = vsyncTime;
+ set(FrameInfoIndex::kAnimationStart) = vsyncTime;
+ set(FrameInfoIndex::kPerformTraversalsStart) = vsyncTime;
+ set(FrameInfoIndex::kDrawStart) = vsyncTime;
return *this;
}
diff --git a/libs/hwui/FrameInfoVisualizer.cpp b/libs/hwui/FrameInfoVisualizer.cpp
index 041174265348..95b099542f44 100644
--- a/libs/hwui/FrameInfoVisualizer.cpp
+++ b/libs/hwui/FrameInfoVisualizer.cpp
@@ -18,6 +18,7 @@
#include "OpenGLRenderer.h"
#include <cutils/compiler.h>
+#include <array>
#define RETURN_IF_PROFILING_DISABLED() if (CC_LIKELY(mType == ProfileType::None)) return
#define RETURN_IF_DISABLED() if (CC_LIKELY(mType == ProfileType::None && !mShowDirtyRegions)) return
@@ -26,19 +27,10 @@
#define PROFILE_DRAW_THRESHOLD_STROKE_WIDTH 2
#define PROFILE_DRAW_DP_PER_MS 7
-// Number of floats we want to display from FrameTimingData
-// If this is changed make sure to update the indexes below
-#define NUM_ELEMENTS 4
-
-#define RECORD_INDEX 0
-#define PREPARE_INDEX 1
-#define PLAYBACK_INDEX 2
-#define SWAPBUFFERS_INDEX 3
-
// Must be NUM_ELEMENTS in size
-static const SkColor ELEMENT_COLORS[] = { 0xcf3e66cc, 0xcf8f00ff, 0xcfdc3912, 0xcfe69800 };
static const SkColor CURRENT_FRAME_COLOR = 0xcf5faa4d;
static const SkColor THRESHOLD_COLOR = 0xff5faa4d;
+static const SkColor BAR_ALPHA = 0xCF000000;
// We could get this from TimeLord and use the actual frame interval, but
// this is good enough
@@ -47,6 +39,24 @@ static const SkColor THRESHOLD_COLOR = 0xff5faa4d;
namespace android {
namespace uirenderer {
+struct BarSegment {
+ FrameInfoIndex start;
+ FrameInfoIndex end;
+ SkColor color;
+};
+
+static const std::array<BarSegment,9> Bar {{
+ { FrameInfoIndex::kIntendedVsync, FrameInfoIndex::kVsync, 0x00695C },
+ { FrameInfoIndex::kVsync, FrameInfoIndex::kHandleInputStart, 0x00796B },
+ { FrameInfoIndex::kHandleInputStart, FrameInfoIndex::kAnimationStart, 0x00897B },
+ { FrameInfoIndex::kAnimationStart, FrameInfoIndex::kPerformTraversalsStart, 0x009688 },
+ { FrameInfoIndex::kPerformTraversalsStart, FrameInfoIndex::kDrawStart, 0x26A69A},
+ { FrameInfoIndex::kDrawStart, FrameInfoIndex::kSyncStart, 0x2196F3},
+ { FrameInfoIndex::kSyncStart, FrameInfoIndex::kIssueDrawCommandsStart, 0x4FC3F7},
+ { FrameInfoIndex::kIssueDrawCommandsStart, FrameInfoIndex::kSwapBuffers, 0xF44336},
+ { FrameInfoIndex::kSwapBuffers, FrameInfoIndex::kFrameCompleted, 0xFF9800},
+}};
+
static int dpToPx(int dp, float density) {
return (int) (dp * density + 0.5f);
}
@@ -93,9 +103,9 @@ void FrameInfoVisualizer::draw(OpenGLRenderer* canvas) {
}
if (mType == ProfileType::Bars) {
- prepareShapes(canvas->getViewportHeight());
+ initializeRects(canvas->getViewportHeight());
drawGraph(canvas);
- drawCurrentFrame(canvas);
+ drawCurrentFrame(canvas->getViewportHeight(), canvas);
drawThreshold(canvas);
}
}
@@ -103,57 +113,61 @@ void FrameInfoVisualizer::draw(OpenGLRenderer* canvas) {
void FrameInfoVisualizer::createData() {
if (mRects.get()) return;
- mRects.reset(new float*[mFrameSource.capacity()]);
- for (int i = 0; i < NUM_ELEMENTS; i++) {
- // 4 floats per rect
- mRects.get()[i] = (float*) calloc(mFrameSource.capacity(), 4 * sizeof(float));
- }
+ mRects.reset(new float[mFrameSource.capacity() * 4]);
}
void FrameInfoVisualizer::destroyData() {
mRects.reset(nullptr);
}
-void FrameInfoVisualizer::addRect(Rect& r, float data, float* shapeOutput) {
- r.top = r.bottom - (data * mVerticalUnit);
- shapeOutput[0] = r.left;
- shapeOutput[1] = r.top;
- shapeOutput[2] = r.right;
- shapeOutput[3] = r.bottom;
- r.bottom = r.top;
+void FrameInfoVisualizer::initializeRects(const int baseline) {
+ float left = 0;
+ // Set the bottom of all the shapes to the baseline
+ for (size_t i = 0; i < (mFrameSource.capacity() * 4); i += 4) {
+ // Rects are LTRB
+ mRects[i + 0] = left;
+ mRects[i + 1] = baseline;
+ left += mHorizontalUnit;
+ mRects[i + 2] = left;
+ mRects[i + 3] = baseline;
+ }
}
-void FrameInfoVisualizer::prepareShapes(const int baseline) {
- Rect r;
- r.right = mHorizontalUnit;
- for (size_t i = 0; i < mFrameSource.size(); i++) {
- const int shapeIndex = i * 4;
- r.bottom = baseline;
- addRect(r, recordDuration(i), mRects.get()[RECORD_INDEX] + shapeIndex);
- addRect(r, prepareDuration(i), mRects.get()[PREPARE_INDEX] + shapeIndex);
- addRect(r, issueDrawDuration(i), mRects.get()[PLAYBACK_INDEX] + shapeIndex);
- addRect(r, swapBuffersDuration(i), mRects.get()[SWAPBUFFERS_INDEX] + shapeIndex);
- r.translate(mHorizontalUnit, 0);
+void FrameInfoVisualizer::nextBarSegment(FrameInfoIndex start, FrameInfoIndex end) {
+ for (size_t fi = 0, ri = 0; fi < mFrameSource.size(); fi++, ri += 4) {
+ // TODO: Skipped frames will leave little holes in the graph, but this
+ // is better than bogus and freaky lines, so...
+ if (mFrameSource[fi][FrameInfoIndex::kFlags] & FrameInfoFlags::kSkippedFrame) {
+ continue;
+ }
+
+ // Set the bottom to the old top (build upwards)
+ mRects[ri + 3] = mRects[ri + 1];
+ // Move the top up by the duration
+ mRects[ri + 1] -= mVerticalUnit * duration(fi, start, end);
}
}
void FrameInfoVisualizer::drawGraph(OpenGLRenderer* canvas) {
SkPaint paint;
- for (int i = 0; i < NUM_ELEMENTS; i++) {
- paint.setColor(ELEMENT_COLORS[i]);
- canvas->drawRects(mRects.get()[i], mFrameSource.capacity() * 4, &paint);
+ for (size_t i = 0; i < Bar.size(); i++) {
+ paint.setColor(Bar[i].color | BAR_ALPHA);
+ nextBarSegment(Bar[i].start, Bar[i].end);
+ canvas->drawRects(mRects.get(), (mFrameSource.size() - 1) * 4, &paint);
}
}
-void FrameInfoVisualizer::drawCurrentFrame(OpenGLRenderer* canvas) {
+void FrameInfoVisualizer::drawCurrentFrame(const int baseline, OpenGLRenderer* canvas) {
// This draws a solid rect over the entirety of the current frame's shape
// To do so we use the bottom of mRects[0] and the top of mRects[NUM_ELEMENTS-1]
// which will therefore fully overlap the previously drawn rects
SkPaint paint;
paint.setColor(CURRENT_FRAME_COLOR);
- const int i = (mFrameSource.size() - 1) * 4;
- canvas->drawRect(mRects.get()[0][i], mRects.get()[NUM_ELEMENTS-1][i+1],
- mRects.get()[0][i+2], mRects.get()[0][i+3], &paint);
+ size_t fi = mFrameSource.size() - 1;
+ size_t ri = fi * 4;
+ float top = baseline - (mVerticalUnit * duration(fi,
+ FrameInfoIndex::kIntendedVsync, FrameInfoIndex::kIssueDrawCommandsStart));
+ canvas->drawRect(mRects[ri], top, mRects[ri + 2], baseline, &paint);
}
void FrameInfoVisualizer::drawThreshold(OpenGLRenderer* canvas) {
@@ -205,8 +219,10 @@ void FrameInfoVisualizer::dumpData(int fd) {
}
mLastFrameLogged = mFrameSource[i][FrameInfoIndex::kIntendedVsync];
fprintf(file, "\t%3.2f\t%3.2f\t%3.2f\t%3.2f\n",
- recordDuration(i), prepareDuration(i),
- issueDrawDuration(i), swapBuffersDuration(i));
+ duration(i, FrameInfoIndex::kIntendedVsync, FrameInfoIndex::kSyncStart),
+ duration(i, FrameInfoIndex::kSyncStart, FrameInfoIndex::kIssueDrawCommandsStart),
+ duration(i, FrameInfoIndex::kIssueDrawCommandsStart, FrameInfoIndex::kSwapBuffers),
+ duration(i, FrameInfoIndex::kSwapBuffers, FrameInfoIndex::kFrameCompleted));
}
fflush(file);
diff --git a/libs/hwui/FrameInfoVisualizer.h b/libs/hwui/FrameInfoVisualizer.h
index f62e34dacbf4..3fa458659124 100644
--- a/libs/hwui/FrameInfoVisualizer.h
+++ b/libs/hwui/FrameInfoVisualizer.h
@@ -54,41 +54,21 @@ private:
void createData();
void destroyData();
- void addRect(Rect& r, float data, float* shapeOutput);
- void prepareShapes(const int baseline);
+ void initializeRects(const int baseline);
+ void nextBarSegment(FrameInfoIndex start, FrameInfoIndex end);
void drawGraph(OpenGLRenderer* canvas);
- void drawCurrentFrame(OpenGLRenderer* canvas);
+ void drawCurrentFrame(const int baseline, OpenGLRenderer* canvas);
void drawThreshold(OpenGLRenderer* canvas);
- static inline float duration(nsecs_t start, nsecs_t end) {
- float duration = ((end - start) * 0.000001f);
+ inline float duration(size_t index, FrameInfoIndex start, FrameInfoIndex end) {
+ nsecs_t ns_start = mFrameSource[index][start];
+ nsecs_t ns_end = mFrameSource[index][end];
+ float duration = ((ns_end - ns_start) * 0.000001f);
+ // Clamp to large to avoid spiking off the top of the screen
+ duration = duration > 50.0f ? 50.0f : duration;
return duration > 0.0f ? duration : 0.0f;
}
- inline float recordDuration(size_t index) {
- return duration(
- mFrameSource[index][FrameInfoIndex::kIntendedVsync],
- mFrameSource[index][FrameInfoIndex::kSyncStart]);
- }
-
- inline float prepareDuration(size_t index) {
- return duration(
- mFrameSource[index][FrameInfoIndex::kSyncStart],
- mFrameSource[index][FrameInfoIndex::kIssueDrawCommandsStart]);
- }
-
- inline float issueDrawDuration(size_t index) {
- return duration(
- mFrameSource[index][FrameInfoIndex::kIssueDrawCommandsStart],
- mFrameSource[index][FrameInfoIndex::kSwapBuffers]);
- }
-
- inline float swapBuffersDuration(size_t index) {
- return duration(
- mFrameSource[index][FrameInfoIndex::kSwapBuffers],
- mFrameSource[index][FrameInfoIndex::kFrameCompleted]);
- }
-
ProfileType mType = ProfileType::None;
float mDensity = 0;
@@ -105,7 +85,7 @@ private:
* OpenGLRenderer:drawRects() that makes up all the FrameTimingData:record
* information.
*/
- std::unique_ptr<float*> mRects;
+ std::unique_ptr<float[]> mRects;
bool mShowDirtyRegions = false;
SkRect mDirtyRegion;
diff --git a/libs/hwui/Glop.h b/libs/hwui/Glop.h
index 2c6f6c120d16..fa20b0807a88 100644
--- a/libs/hwui/Glop.h
+++ b/libs/hwui/Glop.h
@@ -41,13 +41,32 @@ class Texture;
* Position is always enabled by MeshState, these other attributes
* are enabled/disabled dynamically based on mesh content.
*/
-enum class VertexAttribFlags {
- kNone = 0,
- kTextureCoord = 1 << 0,
- kColor = 1 << 1,
- kAlpha = 1 << 2,
+
+namespace VertexAttribFlags {
+ enum {
+ None = 0,
+ TextureCoord = 1 << 0,
+ Color = 1 << 1,
+ Alpha = 1 << 2,
+ };
+};
+
+/*
+ * Enumerates transform features
+ */
+namespace TransformFlags {
+ enum {
+ None = 0,
+
+ // offset the eventual drawing matrix by a tiny amount to
+ // disambiguate sampling patterns with non-AA rendering
+ OffsetByFudgeFactor = 1 << 0,
+
+ // Canvas transform isn't applied to the mesh at draw time,
+ //since it's already built in.
+ MeshIgnoresCanvasTransform = 1 << 1,
+ };
};
-MAKE_FLAGS_ENUM(VertexAttribFlags)
/**
* Structure containing all data required to issue an OpenGL draw
@@ -116,10 +135,22 @@ struct Glop {
} fill;
struct Transform {
- Matrix4 ortho; // TODO: out of op, since this is static per FBO
+ // Orthographic projection matrix for current FBO
+ // TODO: move out of Glop, since this is static per FBO
+ Matrix4 ortho;
+
+ // modelView transform, accounting for delta between mesh transform and content of the mesh
+ // often represents x/y offsets within command, or scaling for mesh unit size
Matrix4 modelView;
+
+ // Canvas transform of Glop - not necessarily applied to geometry (see flags)
Matrix4 canvas;
- bool fudgingOffset;
+ int transformFlags;
+
+ const Matrix4& meshTransform() const {
+ return (transformFlags & TransformFlags::MeshIgnoresCanvasTransform)
+ ? Matrix4::identity() : canvas;
+ }
} transform;
const RoundRectClipState* roundRectClipState;
diff --git a/libs/hwui/GlopBuilder.cpp b/libs/hwui/GlopBuilder.cpp
index e25f81eaa8af..b7cdaa2abc81 100644
--- a/libs/hwui/GlopBuilder.cpp
+++ b/libs/hwui/GlopBuilder.cpp
@@ -66,7 +66,7 @@ GlopBuilder& GlopBuilder::setMeshUnitQuad() {
mOutGlop->mesh.indices = { 0, nullptr };
mOutGlop->mesh.vertices = {
mRenderState.meshState().getUnitQuadVBO(),
- static_cast<int>(VertexAttribFlags::kNone),
+ VertexAttribFlags::None,
nullptr, nullptr, nullptr,
kTextureVertexStride };
mOutGlop->mesh.elementCount = 4;
@@ -85,7 +85,7 @@ GlopBuilder& GlopBuilder::setMeshTexturedUnitQuad(const UvMapper* uvMapper) {
mOutGlop->mesh.indices = { 0, nullptr };
mOutGlop->mesh.vertices = {
mRenderState.meshState().getUnitQuadVBO(),
- static_cast<int>(VertexAttribFlags::kTextureCoord),
+ VertexAttribFlags::TextureCoord,
nullptr, (const void*) kMeshTextureOffset, nullptr,
kTextureVertexStride };
mOutGlop->mesh.elementCount = 4;
@@ -105,7 +105,7 @@ GlopBuilder& GlopBuilder::setMeshTexturedUvQuad(const UvMapper* uvMapper, Rect u
mOutGlop->mesh.indices = { 0, nullptr };
mOutGlop->mesh.vertices = {
0,
- static_cast<int>(VertexAttribFlags::kTextureCoord),
+ VertexAttribFlags::TextureCoord,
&textureVertex[0].x, &textureVertex[0].u, nullptr,
kTextureVertexStride };
mOutGlop->mesh.elementCount = 4;
@@ -119,7 +119,7 @@ GlopBuilder& GlopBuilder::setMeshIndexedQuads(Vertex* vertexData, int quadCount)
mOutGlop->mesh.indices = { mRenderState.meshState().getQuadListIBO(), nullptr };
mOutGlop->mesh.vertices = {
0,
- static_cast<int>(VertexAttribFlags::kNone),
+ VertexAttribFlags::None,
vertexData, nullptr, nullptr,
kVertexStride };
mOutGlop->mesh.elementCount = 6 * quadCount;
@@ -133,7 +133,7 @@ GlopBuilder& GlopBuilder::setMeshTexturedIndexedQuads(TextureVertex* vertexData,
mOutGlop->mesh.indices = { mRenderState.meshState().getQuadListIBO(), nullptr };
mOutGlop->mesh.vertices = {
0,
- static_cast<int>(VertexAttribFlags::kTextureCoord),
+ VertexAttribFlags::TextureCoord,
&vertexData[0].x, &vertexData[0].u, nullptr,
kTextureVertexStride };
mOutGlop->mesh.elementCount = elementCount;
@@ -147,7 +147,7 @@ GlopBuilder& GlopBuilder::setMeshTexturedMesh(TextureVertex* vertexData, int ele
mOutGlop->mesh.indices = { 0, nullptr };
mOutGlop->mesh.vertices = {
0,
- static_cast<int>(VertexAttribFlags::kTextureCoord),
+ VertexAttribFlags::TextureCoord,
&vertexData[0].x, &vertexData[0].u, nullptr,
kTextureVertexStride };
mOutGlop->mesh.elementCount = elementCount;
@@ -161,7 +161,7 @@ GlopBuilder& GlopBuilder::setMeshColoredTexturedMesh(ColorTextureVertex* vertexD
mOutGlop->mesh.indices = { 0, nullptr };
mOutGlop->mesh.vertices = {
0,
- VertexAttribFlags::kTextureCoord | VertexAttribFlags::kColor,
+ VertexAttribFlags::TextureCoord | VertexAttribFlags::Color,
&vertexData[0].x, &vertexData[0].u, &vertexData[0].r,
kColorTextureVertexStride };
mOutGlop->mesh.elementCount = elementCount;
@@ -180,7 +180,7 @@ GlopBuilder& GlopBuilder::setMeshVertexBuffer(const VertexBuffer& vertexBuffer,
mOutGlop->mesh.indices = { 0, vertexBuffer.getIndices() };
mOutGlop->mesh.vertices = {
0,
- static_cast<int>(alphaVertex ? VertexAttribFlags::kAlpha : VertexAttribFlags::kNone),
+ alphaVertex ? VertexAttribFlags::Alpha : VertexAttribFlags::None,
vertexBuffer.getBuffer(), nullptr, nullptr,
alphaVertex ? kAlphaVertexStride : kVertexStride };
mOutGlop->mesh.elementCount = indices
@@ -197,7 +197,7 @@ GlopBuilder& GlopBuilder::setMeshPatchQuads(const Patch& patch) {
mOutGlop->mesh.indices = { mRenderState.meshState().getQuadListIBO(), nullptr };
mOutGlop->mesh.vertices = {
mCaches.patchCache.getMeshBuffer(),
- static_cast<int>(VertexAttribFlags::kTextureCoord),
+ VertexAttribFlags::TextureCoord,
(void*)patch.positionOffset, (void*)patch.textureOffset, nullptr,
kTextureVertexStride };
mOutGlop->mesh.elementCount = patch.indexCount;
@@ -230,7 +230,7 @@ void GlopBuilder::setFill(int color, float alphaScale,
mOutGlop->blend = { GL_ZERO, GL_ZERO };
if (mOutGlop->fill.color.a < 1.0f
- || (mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::kAlpha)
+ || (mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::Alpha)
|| (mOutGlop->fill.texture.texture && mOutGlop->fill.texture.texture->blend)
|| mOutGlop->roundRectClipState
|| PaintUtils::isBlendedShader(shader)
@@ -298,12 +298,12 @@ void GlopBuilder::setFill(int color, float alphaScale,
}
}
-GlopBuilder& GlopBuilder::setFillTexturePaint(Texture& texture, int textureFillFlags,
- const SkPaint* paint, float alphaScale) {
+GlopBuilder& GlopBuilder::setFillTexturePaint(Texture& texture,
+ const int textureFillFlags, const SkPaint* paint, float alphaScale) {
TRIGGER_STAGE(kFillStage);
REQUIRE_STAGES(kMeshStage);
- GLenum filter = (textureFillFlags & TextureFillFlags::kForceFilter)
+ GLenum filter = (textureFillFlags & TextureFillFlags::ForceFilter)
? GL_LINEAR : PaintUtils::getFilter(paint);
mOutGlop->fill.texture = { &texture,
GL_TEXTURE_2D, filter, GL_CLAMP_TO_EDGE, nullptr };
@@ -312,7 +312,7 @@ GlopBuilder& GlopBuilder::setFillTexturePaint(Texture& texture, int textureFillF
int color = paint->getColor();
SkShader* shader = paint->getShader();
- if (!(textureFillFlags & TextureFillFlags::kIsAlphaMaskTexture)) {
+ if (!(textureFillFlags & TextureFillFlags::IsAlphaMaskTexture)) {
// Texture defines color, so disable shaders, and reset all non-alpha color channels
color |= 0x00FFFFFF;
shader = nullptr;
@@ -324,7 +324,7 @@ GlopBuilder& GlopBuilder::setFillTexturePaint(Texture& texture, int textureFillF
mOutGlop->fill.color = { alphaScale, alphaScale, alphaScale, alphaScale };
if (alphaScale < 1.0f
- || (mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::kAlpha)
+ || (mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::Alpha)
|| texture.blend
|| mOutGlop->roundRectClipState) {
Blend::getFactors(SkXfermode::kSrcOver_Mode, Blend::ModeOrderSwap::NoSwap,
@@ -334,7 +334,7 @@ GlopBuilder& GlopBuilder::setFillTexturePaint(Texture& texture, int textureFillF
}
}
- if (textureFillFlags & TextureFillFlags::kIsAlphaMaskTexture) {
+ if (textureFillFlags & TextureFillFlags::IsAlphaMaskTexture) {
mDescription.modulate = mOutGlop->fill.color.isNotBlack();
mDescription.hasAlpha8Texture = true;
} else {
@@ -452,14 +452,13 @@ GlopBuilder& GlopBuilder::setFillTextureLayer(Layer& layer, float alpha) {
// Transform
////////////////////////////////////////////////////////////////////////////////
-GlopBuilder& GlopBuilder::setTransform(const Matrix4& ortho,
- const Matrix4& transform, bool fudgingOffset) {
+void GlopBuilder::setTransform(const Matrix4& ortho, const Matrix4& canvas,
+ const int transformFlags) {
TRIGGER_STAGE(kTransformStage);
mOutGlop->transform.ortho.load(ortho);
- mOutGlop->transform.canvas.load(transform);
- mOutGlop->transform.fudgingOffset = fudgingOffset;
- return *this;
+ mOutGlop->transform.canvas.load(canvas);
+ mOutGlop->transform.transformFlags = transformFlags;
}
////////////////////////////////////////////////////////////////////////////////
@@ -482,11 +481,11 @@ GlopBuilder& GlopBuilder::setModelViewMapUnitToRectSnap(const Rect destination)
float left = destination.left;
float top = destination.top;
- const Matrix4& canvasTransform = mOutGlop->transform.canvas;
- if (CC_LIKELY(canvasTransform.isPureTranslate())) {
+ const Matrix4& meshTransform = mOutGlop->transform.meshTransform();
+ if (CC_LIKELY(meshTransform.isPureTranslate())) {
// snap by adjusting the model view matrix
- const float translateX = canvasTransform.getTranslateX();
- const float translateY = canvasTransform.getTranslateY();
+ const float translateX = meshTransform.getTranslateX();
+ const float translateY = meshTransform.getTranslateY();
left = (int) floorf(left + translateX + 0.5f) - translateX;
top = (int) floorf(top + translateY + 0.5f) - translateY;
@@ -512,11 +511,11 @@ GlopBuilder& GlopBuilder::setModelViewOffsetRectSnap(float offsetX, float offset
TRIGGER_STAGE(kModelViewStage);
REQUIRE_STAGES(kTransformStage | kFillStage);
- const Matrix4& canvasTransform = mOutGlop->transform.canvas;
- if (CC_LIKELY(canvasTransform.isPureTranslate())) {
+ const Matrix4& meshTransform = mOutGlop->transform.meshTransform();
+ if (CC_LIKELY(meshTransform.isPureTranslate())) {
// snap by adjusting the model view matrix
- const float translateX = canvasTransform.getTranslateX();
- const float translateY = canvasTransform.getTranslateY();
+ const float translateX = meshTransform.getTranslateX();
+ const float translateY = meshTransform.getTranslateY();
offsetX = (int) floorf(offsetX + translateX + source.left + 0.5f) - translateX - source.left;
offsetY = (int) floorf(offsetY + translateY + source.top + 0.5f) - translateY - source.top;
@@ -549,7 +548,7 @@ void verify(const ProgramDescription& description, const Glop& glop) {
if (glop.fill.texture.texture != nullptr) {
LOG_ALWAYS_FATAL_IF(((description.hasTexture && description.hasExternalTexture)
|| (!description.hasTexture && !description.hasExternalTexture)
- || ((glop.mesh.vertices.attribFlags & VertexAttribFlags::kTextureCoord) == 0)),
+ || ((glop.mesh.vertices.attribFlags & VertexAttribFlags::TextureCoord) == 0)),
"Texture %p, hT%d, hET %d, attribFlags %x",
glop.fill.texture.texture,
description.hasTexture, description.hasExternalTexture,
@@ -557,13 +556,13 @@ void verify(const ProgramDescription& description, const Glop& glop) {
} else {
LOG_ALWAYS_FATAL_IF((description.hasTexture
|| description.hasExternalTexture
- || ((glop.mesh.vertices.attribFlags & VertexAttribFlags::kTextureCoord) != 0)),
+ || ((glop.mesh.vertices.attribFlags & VertexAttribFlags::TextureCoord) != 0)),
"No texture, hT%d, hET %d, attribFlags %x",
description.hasTexture, description.hasExternalTexture,
glop.mesh.vertices.attribFlags);
}
- if ((glop.mesh.vertices.attribFlags & VertexAttribFlags::kAlpha)
+ if ((glop.mesh.vertices.attribFlags & VertexAttribFlags::Alpha)
&& glop.mesh.vertices.bufferObject) {
LOG_ALWAYS_FATAL("VBO and alpha attributes are not currently compatible");
}
@@ -575,16 +574,16 @@ void verify(const ProgramDescription& description, const Glop& glop) {
void GlopBuilder::build() {
REQUIRE_STAGES(kAllStages);
- if (mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::kTextureCoord) {
+ if (mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::TextureCoord) {
if (mOutGlop->fill.texture.target == GL_TEXTURE_2D) {
mDescription.hasTexture = true;
} else {
mDescription.hasExternalTexture = true;
}
-
}
- mDescription.hasColors = mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::kColor;
- mDescription.hasVertexAlpha = mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::kAlpha;
+
+ mDescription.hasColors = mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::Color;
+ mDescription.hasVertexAlpha = mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::Alpha;
// Enable debug highlight when what we're about to draw is tested against
// the stencil buffer and if stencil highlight debugging is on
@@ -594,8 +593,22 @@ void GlopBuilder::build() {
// serialize shader info into ShaderData
GLuint textureUnit = mOutGlop->fill.texture.texture ? 1 : 0;
- SkiaShader::store(mCaches, mShader, mOutGlop->transform.modelView,
- &textureUnit, &mDescription, &(mOutGlop->fill.skiaShaderData));
+
+ if (CC_LIKELY(!mShader)) {
+ mOutGlop->fill.skiaShaderData.skiaShaderType = kNone_SkiaShaderType;
+ } else {
+ Matrix4 shaderMatrix;
+ if (mOutGlop->transform.transformFlags & TransformFlags::MeshIgnoresCanvasTransform) {
+ // canvas level transform was built into the modelView and geometry,
+ // so the shader matrix must reverse this
+ shaderMatrix.loadInverse(mOutGlop->transform.canvas);
+ shaderMatrix.multiply(mOutGlop->transform.modelView);
+ } else {
+ shaderMatrix.load(mOutGlop->transform.modelView);
+ }
+ SkiaShader::store(mCaches, *mShader, shaderMatrix,
+ &textureUnit, &mDescription, &(mOutGlop->fill.skiaShaderData));
+ }
// duplicates ProgramCache's definition of color uniform presence
const bool singleColor = !mDescription.hasTexture
@@ -608,7 +621,7 @@ void GlopBuilder::build() {
// Final step: populate program and map bounds into render target space
mOutGlop->fill.program = mCaches.programCache.get(mDescription);
- mOutGlop->transform.canvas.mapRect(mOutGlop->bounds);
+ mOutGlop->transform.meshTransform().mapRect(mOutGlop->bounds);
}
} /* namespace uirenderer */
diff --git a/libs/hwui/GlopBuilder.h b/libs/hwui/GlopBuilder.h
index b335a2c5a25e..549bb21e5f8d 100644
--- a/libs/hwui/GlopBuilder.h
+++ b/libs/hwui/GlopBuilder.h
@@ -16,6 +16,7 @@
#ifndef RENDERSTATE_GLOPBUILDER_H
#define RENDERSTATE_GLOPBUILDER_H
+#include "Glop.h"
#include "OpenGLRenderer.h"
#include "Program.h"
#include "renderstate/Blend.h"
@@ -32,14 +33,14 @@ class Matrix4;
class RenderState;
class Texture;
class VertexBuffer;
-struct Glop;
-enum class TextureFillFlags {
- kNone = 0,
- kIsAlphaMaskTexture = 1 << 0,
- kForceFilter = 1 << 1,
-};
-MAKE_FLAGS_ENUM(TextureFillFlags);
+namespace TextureFillFlags {
+ enum {
+ None = 0,
+ IsAlphaMaskTexture = 1 << 0,
+ ForceFilter = 1 << 1,
+ };
+}
class GlopBuilder {
PREVENT_COPY_AND_ASSIGN(GlopBuilder);
@@ -57,7 +58,7 @@ public:
GlopBuilder& setMeshPatchQuads(const Patch& patch);
GlopBuilder& setFillPaint(const SkPaint& paint, float alphaScale);
- GlopBuilder& setFillTexturePaint(Texture& texture, int textureFillFlags,
+ GlopBuilder& setFillTexturePaint(Texture& texture, const int textureFillFlags,
const SkPaint* paint, float alphaScale);
GlopBuilder& setFillPathTexturePaint(PathTexture& texture,
const SkPaint& paint, float alphaScale);
@@ -69,7 +70,10 @@ public:
float alpha, SkXfermode::Mode mode, Blend::ModeOrderSwap modeUsage);
GlopBuilder& setFillTextureLayer(Layer& layer, float alpha);
- GlopBuilder& setTransform(const Matrix4& ortho, const Matrix4& transform, bool fudgingOffset);
+ GlopBuilder& setTransform(const Snapshot& snapshot, const int transformFlags) {
+ setTransform(snapshot.getOrthoMatrix(), *snapshot.transform, transformFlags);
+ return *this;
+ }
GlopBuilder& setModelViewMapUnitToRect(const Rect destination);
GlopBuilder& setModelViewMapUnitToRectSnap(const Rect destination);
@@ -98,6 +102,8 @@ private:
void setFill(int color, float alphaScale,
SkXfermode::Mode mode, Blend::ModeOrderSwap modeUsage,
const SkShader* shader, const SkColorFilter* colorFilter);
+ void setTransform(const Matrix4& ortho, const Matrix4& canvas,
+ const int transformFlags);
enum StageFlags {
kInitialStage = 0,
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 8f916202e9e6..576937655f7a 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -827,7 +827,7 @@ void OpenGLRenderer::composeLayer(const Snapshot& removed, const Snapshot& resto
// the layer contains screen buffer content that shouldn't be alpha modulated
// (and any necessary alpha modulation was handled drawing into the layer)
writableSnapshot()->alpha = 1.0f;
- composeLayerRect(layer, rect, true);
+ composeLayerRectSwapped(layer, rect);
restore();
}
@@ -849,31 +849,40 @@ void OpenGLRenderer::drawTextureLayer(Layer* layer, const Rect& rect) {
GlopBuilder(mRenderState, mCaches, &glop)
.setMeshTexturedUvQuad(nullptr, Rect(0, 1, 1, 0)) // TODO: simplify with VBO
.setFillTextureLayer(*layer, getLayerAlpha(layer))
- .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
+ .setTransform(*currentSnapshot(), TransformFlags::None)
.setModelViewMapUnitToRectOptionalSnap(tryToSnap, rect)
.setRoundRectClipState(currentSnapshot()->roundRectClipState)
.build();
renderGlop(glop);
}
-void OpenGLRenderer::composeLayerRect(Layer* layer, const Rect& rect, bool swap) {
+void OpenGLRenderer::composeLayerRectSwapped(Layer* layer, const Rect& rect) {
+ Glop glop;
+ GlopBuilder(mRenderState, mCaches, &glop)
+ .setMeshTexturedUvQuad(nullptr, layer->texCoords)
+ .setFillLayer(layer->getTexture(), layer->getColorFilter(),
+ getLayerAlpha(layer), layer->getMode(), Blend::ModeOrderSwap::Swap)
+ .setTransform(*currentSnapshot(), TransformFlags::MeshIgnoresCanvasTransform)
+ .setModelViewMapUnitToRect(rect)
+ .setRoundRectClipState(currentSnapshot()->roundRectClipState)
+ .build();
+ renderGlop(glop);
+}
+
+void OpenGLRenderer::composeLayerRect(Layer* layer, const Rect& rect) {
if (layer->isTextureLayer()) {
EVENT_LOGD("composeTextureLayerRect");
drawTextureLayer(layer, rect);
} else {
EVENT_LOGD("composeHardwareLayerRect");
- Blend::ModeOrderSwap modeUsage = swap ?
- Blend::ModeOrderSwap::Swap : Blend::ModeOrderSwap::NoSwap;
- const Matrix4& transform = swap ? Matrix4::identity() : *currentTransform();
- const bool tryToSnap = !swap
- && layer->getWidth() == static_cast<uint32_t>(rect.getWidth())
+ const bool tryToSnap = layer->getWidth() == static_cast<uint32_t>(rect.getWidth())
&& layer->getHeight() == static_cast<uint32_t>(rect.getHeight());
Glop glop;
GlopBuilder(mRenderState, mCaches, &glop)
.setMeshTexturedUvQuad(nullptr, layer->texCoords)
- .setFillLayer(layer->getTexture(), layer->getColorFilter(), getLayerAlpha(layer), layer->getMode(), modeUsage)
- .setTransform(currentSnapshot()->getOrthoMatrix(), transform, false)
+ .setFillLayer(layer->getTexture(), layer->getColorFilter(), getLayerAlpha(layer), layer->getMode(), Blend::ModeOrderSwap::NoSwap)
+ .setTransform(*currentSnapshot(), TransformFlags::None)
.setModelViewMapUnitToRectOptionalSnap(tryToSnap, rect)
.setRoundRectClipState(currentSnapshot()->roundRectClipState)
.build();
@@ -1014,7 +1023,7 @@ void OpenGLRenderer::composeLayerRegion(Layer* layer, const Rect& rect) {
GlopBuilder(mRenderState, mCaches, &glop)
.setMeshTexturedIndexedQuads(&quadVertices[0], count * 6)
.setFillLayer(layer->getTexture(), layer->getColorFilter(), getLayerAlpha(layer), layer->getMode(), Blend::ModeOrderSwap::NoSwap)
- .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
+ .setTransform(*currentSnapshot(), TransformFlags::None)
.setModelViewOffsetRectSnap(rect.left, rect.top, modelRect)
.setRoundRectClipState(currentSnapshot()->roundRectClipState)
.build();
@@ -1128,11 +1137,12 @@ void OpenGLRenderer::clearLayerRegions() {
// stencil setup from doing the same thing again
mLayers.clear();
+ const int transformFlags = TransformFlags::MeshIgnoresCanvasTransform;
Glop glop;
GlopBuilder(mRenderState, mCaches, &glop)
.setMeshIndexedQuads(&mesh[0], quadCount)
.setFillClear()
- .setTransform(currentSnapshot()->getOrthoMatrix(), Matrix4::identity(), false)
+ .setTransform(*currentSnapshot(), transformFlags)
.setModelViewOffsetRect(0, 0, Rect(currentSnapshot()->getClipRect()))
.setRoundRectClipState(currentSnapshot()->roundRectClipState)
.build();
@@ -1316,13 +1326,13 @@ void OpenGLRenderer::drawRectangleList(const RectangleList& rectangleList) {
mRenderState.scissor().set(scissorBox.left, getViewportHeight() - scissorBox.bottom,
scissorBox.getWidth(), scissorBox.getHeight());
-
+ const int transformFlags = TransformFlags::MeshIgnoresCanvasTransform;
Glop glop;
Vertex* vertices = &rectangleVertices[0];
GlopBuilder(mRenderState, mCaches, &glop)
.setMeshIndexedQuads(vertices, rectangleVertices.size() / 4)
.setFillBlack()
- .setTransform(currentSnapshot()->getOrthoMatrix(), Matrix4::identity(), false)
+ .setTransform(*currentSnapshot(), transformFlags)
.setModelViewOffsetRect(0, 0, scissorBox)
.setRoundRectClipState(currentSnapshot()->roundRectClipState)
.build();
@@ -1518,13 +1528,15 @@ void OpenGLRenderer::drawBitmaps(const SkBitmap* bitmap, AssetAtlas::Entry* entr
bool snap = pureTranslate;
const float x = floorf(bounds.left + 0.5f);
const float y = floorf(bounds.top + 0.5f);
- int textureFillFlags = static_cast<int>((bitmap->colorType() == kAlpha_8_SkColorType)
- ? TextureFillFlags::kIsAlphaMaskTexture : TextureFillFlags::kNone);
+
+ const int textureFillFlags = (bitmap->colorType() == kAlpha_8_SkColorType)
+ ? TextureFillFlags::IsAlphaMaskTexture : TextureFillFlags::None;
+ const int transformFlags = TransformFlags::MeshIgnoresCanvasTransform;
Glop glop;
GlopBuilder(mRenderState, mCaches, &glop)
.setMeshTexturedMesh(vertices, bitmapCount * 6)
.setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha)
- .setTransform(currentSnapshot()->getOrthoMatrix(), Matrix4::identity(), false)
+ .setTransform(*currentSnapshot(), transformFlags)
.setModelViewOffsetRectOptionalSnap(snap, x, y, Rect(0, 0, bounds.getWidth(), bounds.getHeight()))
.setRoundRectClipState(currentSnapshot()->roundRectClipState)
.build();
@@ -1541,13 +1553,13 @@ void OpenGLRenderer::drawBitmap(const SkBitmap* bitmap, const SkPaint* paint) {
if (!texture) return;
const AutoTexture autoCleanup(texture);
- int textureFillFlags = static_cast<int>((bitmap->colorType() == kAlpha_8_SkColorType)
- ? TextureFillFlags::kIsAlphaMaskTexture : TextureFillFlags::kNone);
+ const int textureFillFlags = (bitmap->colorType() == kAlpha_8_SkColorType)
+ ? TextureFillFlags::IsAlphaMaskTexture : TextureFillFlags::None;
Glop glop;
GlopBuilder(mRenderState, mCaches, &glop)
.setMeshTexturedUnitQuad(texture->uvMapper)
.setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha)
- .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
+ .setTransform(*currentSnapshot(), TransformFlags::None)
.setModelViewMapUnitToRectSnap(Rect(0, 0, texture->width, texture->height))
.setRoundRectClipState(currentSnapshot()->roundRectClipState)
.build();
@@ -1632,11 +1644,12 @@ void OpenGLRenderer::drawBitmapMesh(const SkBitmap* bitmap, int meshWidth, int m
* TODO: handle alpha_8 textures correctly by applying paint color, but *not*
* shader in that case to mimic the behavior in SkiaCanvas::drawBitmapMesh.
*/
+ const int textureFillFlags = TextureFillFlags::None;
Glop glop;
GlopBuilder(mRenderState, mCaches, &glop)
.setMeshColoredTexturedMesh(mesh.get(), elementCount)
- .setFillTexturePaint(*texture, static_cast<int>(TextureFillFlags::kNone), paint, currentSnapshot()->alpha)
- .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
+ .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha)
+ .setTransform(*currentSnapshot(), TransformFlags::None)
.setModelViewOffsetRect(0, 0, Rect(left, top, right, bottom))
.setRoundRectClipState(currentSnapshot()->roundRectClipState)
.build();
@@ -1657,16 +1670,15 @@ void OpenGLRenderer::drawBitmap(const SkBitmap* bitmap, Rect src, Rect dst, cons
fmin(1.0f, src.right / texture->width),
fmin(1.0f, src.bottom / texture->height));
- const int textureFillFlags = static_cast<int>((bitmap->colorType() == kAlpha_8_SkColorType)
- ? TextureFillFlags::kIsAlphaMaskTexture : TextureFillFlags::kNone);
+ const int textureFillFlags = (bitmap->colorType() == kAlpha_8_SkColorType)
+ ? TextureFillFlags::IsAlphaMaskTexture : TextureFillFlags::None;
const bool tryToSnap = MathUtils::areEqual(src.getWidth(), dst.getWidth())
&& MathUtils::areEqual(src.getHeight(), dst.getHeight());
-
Glop glop;
GlopBuilder(mRenderState, mCaches, &glop)
.setMeshTexturedUvQuad(texture->uvMapper, uv)
.setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha)
- .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
+ .setTransform(*currentSnapshot(), TransformFlags::None)
.setModelViewMapUnitToRectOptionalSnap(tryToSnap, dst)
.setRoundRectClipState(currentSnapshot()->roundRectClipState)
.build();
@@ -1684,15 +1696,15 @@ void OpenGLRenderer::drawPatch(const SkBitmap* bitmap, const Patch* mesh,
if (!texture) return;
// 9 patches are built for stretching - always filter
- int textureFillFlags = static_cast<int>(TextureFillFlags::kForceFilter);
+ int textureFillFlags = TextureFillFlags::ForceFilter;
if (bitmap->colorType() == kAlpha_8_SkColorType) {
- textureFillFlags |= TextureFillFlags::kIsAlphaMaskTexture;
+ textureFillFlags |= TextureFillFlags::IsAlphaMaskTexture;
}
Glop glop;
GlopBuilder(mRenderState, mCaches, &glop)
.setMeshPatchQuads(*mesh)
.setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha)
- .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
+ .setTransform(*currentSnapshot(), TransformFlags::None)
.setModelViewOffsetRectSnap(left, top, Rect(0, 0, right - left, bottom - top)) // TODO: get minimal bounds from patch
.setRoundRectClipState(currentSnapshot()->roundRectClipState)
.build();
@@ -1712,16 +1724,17 @@ void OpenGLRenderer::drawPatches(const SkBitmap* bitmap, AssetAtlas::Entry* entr
const AutoTexture autoCleanup(texture);
// TODO: get correct bounds from caller
+ const int transformFlags = TransformFlags::MeshIgnoresCanvasTransform;
// 9 patches are built for stretching - always filter
- int textureFillFlags = static_cast<int>(TextureFillFlags::kForceFilter);
+ int textureFillFlags = TextureFillFlags::ForceFilter;
if (bitmap->colorType() == kAlpha_8_SkColorType) {
- textureFillFlags |= TextureFillFlags::kIsAlphaMaskTexture;
+ textureFillFlags |= TextureFillFlags::IsAlphaMaskTexture;
}
Glop glop;
GlopBuilder(mRenderState, mCaches, &glop)
.setMeshTexturedIndexedQuads(vertices, elementCount)
.setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha)
- .setTransform(currentSnapshot()->getOrthoMatrix(), Matrix4::identity(), false)
+ .setTransform(*currentSnapshot(), transformFlags)
.setModelViewOffsetRect(0, 0, Rect(0, 0, 0, 0))
.setRoundRectClipState(currentSnapshot()->roundRectClipState)
.build();
@@ -1736,13 +1749,13 @@ void OpenGLRenderer::drawVertexBuffer(float translateX, float translateY,
return;
}
- bool fudgeOffset = displayFlags & kVertexBuffer_Offset;
bool shadowInterp = displayFlags & kVertexBuffer_ShadowInterp;
+ const int transformFlags = TransformFlags::OffsetByFudgeFactor;
Glop glop;
GlopBuilder(mRenderState, mCaches, &glop)
.setMeshVertexBuffer(vertexBuffer, shadowInterp)
.setFillPaint(*paint, currentSnapshot()->alpha)
- .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), fudgeOffset)
+ .setTransform(*currentSnapshot(), transformFlags)
.setModelViewOffsetRect(translateX, translateY, vertexBuffer.getBounds())
.setRoundRectClipState(currentSnapshot()->roundRectClipState)
.build();
@@ -2028,7 +2041,7 @@ void OpenGLRenderer::drawTextShadow(const SkPaint* paint, const char* text,
GlopBuilder(mRenderState, mCaches, &glop)
.setMeshTexturedUnitQuad(nullptr)
.setFillShadowTexturePaint(*texture, textShadow.color, *paint, currentSnapshot()->alpha)
- .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
+ .setTransform(*currentSnapshot(), TransformFlags::None)
.setModelViewMapUnitToRect(Rect(sx, sy, sx + texture->width, sy + texture->height))
.setRoundRectClipState(currentSnapshot()->roundRectClipState)
.build();
@@ -2353,7 +2366,7 @@ void OpenGLRenderer::drawLayer(Layer* layer, float x, float y) {
GlopBuilder(mRenderState, mCaches, &glop)
.setMeshTexturedIndexedQuads(layer->mesh, layer->meshElementCount)
.setFillLayer(layer->getTexture(), layer->getColorFilter(), getLayerAlpha(layer), layer->getMode(), Blend::ModeOrderSwap::NoSwap)
- .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
+ .setTransform(*currentSnapshot(), TransformFlags::None)
.setModelViewOffsetRectSnap(x, y, Rect(0, 0, layer->layer.getWidth(), layer->layer.getHeight()))
.setRoundRectClipState(currentSnapshot()->roundRectClipState)
.build();
@@ -2411,7 +2424,7 @@ void OpenGLRenderer::drawPathTexture(PathTexture* texture, float x, float y,
GlopBuilder(mRenderState, mCaches, &glop)
.setMeshTexturedUnitQuad(nullptr)
.setFillPathTexturePaint(*texture, *paint, currentSnapshot()->alpha)
- .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
+ .setTransform(*currentSnapshot(), TransformFlags::None)
.setModelViewMapUnitToRect(Rect(x, y, x + texture->width, y + texture->height))
.setRoundRectClipState(currentSnapshot()->roundRectClipState)
.build();
@@ -2543,12 +2556,13 @@ void OpenGLRenderer::drawColorRects(const float* rects, int count, const SkPaint
return;
}
- const Matrix4& transform = ignoreTransform ? Matrix4::identity() : *currentTransform();
+ const int transformFlags = ignoreTransform
+ ? TransformFlags::MeshIgnoresCanvasTransform : TransformFlags::None;
Glop glop;
GlopBuilder(mRenderState, mCaches, &glop)
.setMeshIndexedQuads(&mesh[0], count / 4)
.setFillPaint(*paint, currentSnapshot()->alpha)
- .setTransform(currentSnapshot()->getOrthoMatrix(), transform, false)
+ .setTransform(*currentSnapshot(), transformFlags)
.setModelViewOffsetRect(0, 0, Rect(left, top, right, bottom))
.setRoundRectClipState(currentSnapshot()->roundRectClipState)
.build();
@@ -2557,12 +2571,13 @@ 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) {
- const Matrix4& transform = ignoreTransform ? Matrix4::identity() : *currentTransform();
+ const int transformFlags = ignoreTransform
+ ? TransformFlags::MeshIgnoresCanvasTransform : TransformFlags::None;
Glop glop;
GlopBuilder(mRenderState, mCaches, &glop)
.setMeshUnitQuad()
.setFillPaint(*paint, currentSnapshot()->alpha)
- .setTransform(currentSnapshot()->getOrthoMatrix(), transform, false)
+ .setTransform(*currentSnapshot(), transformFlags)
.setModelViewMapUnitToRect(Rect(left, top, right, bottom))
.setRoundRectClipState(currentSnapshot()->roundRectClipState)
.build();
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 8dae82c5b114..29fbf0c985d7 100755
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -640,13 +640,20 @@ private:
void composeLayerRegion(Layer* layer, const Rect& rect);
/**
- * Compose the specified layer as a simple rectangle.
+ * Restores the content in layer to the screen, swapping the blend mode,
+ * specifically used in the restore() of a saveLayerAlpha().
*
- * @param layer The layer to compose
- * @param rect The layer's bounds
- * @param swap If true, the source and destination are swapped
+ * This allows e.g. a layer that would have been drawn on top of existing content (with SrcOver)
+ * to be drawn underneath.
+ *
+ * This will always ignore the canvas transform.
+ */
+ void composeLayerRectSwapped(Layer* layer, const Rect& rect);
+
+ /**
+ * Draws the content in layer to the screen.
*/
- void composeLayerRect(Layer* layer, const Rect& rect, bool swap = false);
+ void composeLayerRect(Layer* layer, const Rect& rect);
/**
* Clears all the regions corresponding to the current list of layers.
diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp
index ecf8b6ba8219..2cfb9e1dc8c1 100644
--- a/libs/hwui/SkiaShader.cpp
+++ b/libs/hwui/SkiaShader.cpp
@@ -346,33 +346,28 @@ void applyLayer(Caches& caches, const SkiaShaderData::LayerShaderData& data) {
glUniform2fv(caches.program().getUniform("textureDimension"), 1, &data.textureDimension[0]);
}
-void SkiaShader::store(Caches& caches, const SkShader* shader, const Matrix4& modelViewMatrix,
+void SkiaShader::store(Caches& caches, const SkShader& shader, const Matrix4& modelViewMatrix,
GLuint* textureUnit, ProgramDescription* description,
SkiaShaderData* outData) {
- if (!shader) {
- outData->skiaShaderType = kNone_SkiaShaderType;
- return;
- }
-
- if (tryStoreGradient(caches, *shader, modelViewMatrix,
+ if (tryStoreGradient(caches, shader, modelViewMatrix,
textureUnit, description, &outData->gradientData)) {
outData->skiaShaderType = kGradient_SkiaShaderType;
return;
}
- if (tryStoreBitmap(caches, *shader, modelViewMatrix,
+ if (tryStoreBitmap(caches, shader, modelViewMatrix,
textureUnit, description, &outData->bitmapData)) {
outData->skiaShaderType = kBitmap_SkiaShaderType;
return;
}
- if (tryStoreCompose(caches, *shader, modelViewMatrix,
+ if (tryStoreCompose(caches, shader, modelViewMatrix,
textureUnit, description, outData)) {
outData->skiaShaderType = kCompose_SkiaShaderType;
return;
}
- if (tryStoreLayer(caches, *shader, modelViewMatrix,
+ if (tryStoreLayer(caches, shader, modelViewMatrix,
textureUnit, description, &outData->layerData)) {
outData->skiaShaderType = kLayer_SkiaShaderType;
}
diff --git a/libs/hwui/SkiaShader.h b/libs/hwui/SkiaShader.h
index 5b8aa86aaf5f..884196d9fc62 100644
--- a/libs/hwui/SkiaShader.h
+++ b/libs/hwui/SkiaShader.h
@@ -87,7 +87,7 @@ struct SkiaShaderData {
class SkiaShader {
public:
- static void store(Caches& caches, const SkShader* shader, const Matrix4& modelViewMatrix,
+ static void store(Caches& caches, const SkShader& shader, const Matrix4& modelViewMatrix,
GLuint* textureUnit, ProgramDescription* description,
SkiaShaderData* outData);
static void apply(Caches& caches, const SkiaShaderData& data);
diff --git a/libs/hwui/renderstate/RenderState.cpp b/libs/hwui/renderstate/RenderState.cpp
index df12e63017f4..3ebd57b33c81 100644
--- a/libs/hwui/renderstate/RenderState.cpp
+++ b/libs/hwui/renderstate/RenderState.cpp
@@ -217,8 +217,8 @@ void RenderState::render(const Glop& glop) {
fill.program->set(glop.transform.ortho,
glop.transform.modelView,
- glop.transform.canvas,
- glop.transform.fudgingOffset);
+ glop.transform.meshTransform(),
+ glop.transform.transformFlags & TransformFlags::OffsetByFudgeFactor);
// Color filter uniforms
if (fill.filterMode == ProgramDescription::kColorBlend) {
@@ -260,7 +260,7 @@ void RenderState::render(const Glop& glop) {
// indices
meshState().bindIndicesBufferInternal(indices.bufferObject);
- if (vertices.attribFlags & VertexAttribFlags::kTextureCoord) {
+ if (vertices.attribFlags & VertexAttribFlags::TextureCoord) {
const Glop::Fill::TextureData& texture = fill.texture;
// texture always takes slot 0, shader samplers increment from there
mCaches->textureState().activateTexture(0);
@@ -284,13 +284,13 @@ void RenderState::render(const Glop& glop) {
meshState().disableTexCoordsVertexArray();
}
int colorLocation = -1;
- if (vertices.attribFlags & VertexAttribFlags::kColor) {
+ if (vertices.attribFlags & VertexAttribFlags::Color) {
colorLocation = fill.program->getAttrib("colors");
glEnableVertexAttribArray(colorLocation);
glVertexAttribPointer(colorLocation, 4, GL_FLOAT, GL_FALSE, vertices.stride, vertices.color);
}
int alphaLocation = -1;
- if (vertices.attribFlags & VertexAttribFlags::kAlpha) {
+ if (vertices.attribFlags & VertexAttribFlags::Alpha) {
// NOTE: alpha vertex position is computed assuming no VBO
const void* alphaCoords = ((const GLbyte*) vertices.position) + kVertexAlphaOffset;
alphaLocation = fill.program->getAttrib("vtxAlpha");
@@ -318,7 +318,7 @@ void RenderState::render(const Glop& glop) {
// rebind pointers without forcing, since initial bind handled above
meshState().bindPositionVertexPointer(false, vertexData, vertices.stride);
- if (vertices.attribFlags & VertexAttribFlags::kTextureCoord) {
+ if (vertices.attribFlags & VertexAttribFlags::TextureCoord) {
meshState().bindTexCoordsVertexPointer(false,
vertexData + kMeshTextureOffset, vertices.stride);
}
@@ -336,10 +336,10 @@ void RenderState::render(const Glop& glop) {
// -----------------------------------
// ---------- Mesh teardown ----------
// -----------------------------------
- if (vertices.attribFlags & VertexAttribFlags::kAlpha) {
+ if (vertices.attribFlags & VertexAttribFlags::Alpha) {
glDisableVertexAttribArray(alphaLocation);
}
- if (vertices.attribFlags & VertexAttribFlags::kColor) {
+ if (vertices.attribFlags & VertexAttribFlags::Color) {
glDisableVertexAttribArray(colorLocation);
}
}
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 706e14ed7316..f8490b6c9aba 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -156,10 +156,18 @@ void CanvasContext::processLayerUpdate(DeferredLayerUpdater* layerUpdater) {
}
}
+static bool wasSkipped(FrameInfo* info) {
+ return info && ((*info)[FrameInfoIndex::kFlags] & FrameInfoFlags::kSkippedFrame);
+}
+
void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo) {
mRenderThread.removeFrameCallback(this);
- mCurrentFrameInfo = &mFrames.next();
+ // If the previous frame was dropped we don't need to hold onto it, so
+ // just keep using the previous frame's structure instead
+ if (!wasSkipped(mCurrentFrameInfo)) {
+ mCurrentFrameInfo = &mFrames.next();
+ }
mCurrentFrameInfo->importUiThreadInfo(uiFrameInfo);
mCurrentFrameInfo->markSyncStart();
@@ -391,7 +399,11 @@ void CanvasContext::setTextureAtlas(RenderThread& thread,
void CanvasContext::dumpFrames(int fd) {
FILE* file = fdopen(fd, "a");
- fprintf(file, "\n\n---PROFILEDATA---");
+ fprintf(file, "\n\n---PROFILEDATA---\n");
+ for (size_t i = 0; i < static_cast<size_t>(FrameInfoIndex::kNumIndexes); i++) {
+ fprintf(file, FrameInfoNames[i].c_str());
+ fprintf(file, ",");
+ }
for (size_t i = 0; i < mFrames.size(); i++) {
FrameInfo& frame = mFrames[i];
if (frame[FrameInfoIndex::kSyncStart] == 0) {
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index d8a9921c0854..6d9acd429279 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -52,11 +52,12 @@ namespace renderthread {
MethodInvokeRenderTask* task = new MethodInvokeRenderTask((RunnableMethod) Bridge_ ## method); \
ARGS(method) *args = (ARGS(method) *) task->payload()
-enum class DumpFlags {
- kFrameStats = 1 << 0,
- kReset = 1 << 1,
+namespace DumpFlags {
+ enum {
+ FrameStats = 1 << 0,
+ Reset = 1 << 1,
+ };
};
-MAKE_FLAGS_ENUM(DumpFlags)
CREATE_BRIDGE4(createContext, RenderThread* thread, bool translucent,
RenderNode* rootRenderNode, IContextFactory* contextFactory) {
@@ -409,10 +410,10 @@ CREATE_BRIDGE4(dumpProfileInfo, CanvasContext* context, RenderThread* thread,
int fd, int dumpFlags) {
args->context->profiler().dumpData(args->fd);
args->thread->jankTracker().dump(args->fd);
- if (args->dumpFlags & DumpFlags::kFrameStats) {
+ if (args->dumpFlags & DumpFlags::FrameStats) {
args->context->dumpFrames(args->fd);
}
- if (args->dumpFlags & DumpFlags::kReset) {
+ if (args->dumpFlags & DumpFlags::Reset) {
args->context->resetFrameStats();
}
return nullptr;