diff options
-rw-r--r-- | libs/hwui/DisplayListOp.h | 3 | ||||
-rw-r--r-- | libs/hwui/FloatColor.h | 36 | ||||
-rw-r--r-- | libs/hwui/Glop.h | 25 | ||||
-rw-r--r-- | libs/hwui/GlopBuilder.cpp | 291 | ||||
-rw-r--r-- | libs/hwui/GlopBuilder.h | 18 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 135 | ||||
-rwxr-xr-x | libs/hwui/OpenGLRenderer.h | 16 | ||||
-rw-r--r-- | libs/hwui/Program.cpp | 4 | ||||
-rw-r--r-- | libs/hwui/Program.h | 3 | ||||
-rw-r--r-- | libs/hwui/Vertex.h | 6 | ||||
-rw-r--r-- | libs/hwui/renderstate/Blend.cpp | 2 | ||||
-rw-r--r-- | libs/hwui/renderstate/RenderState.cpp | 60 | ||||
-rw-r--r-- | libs/hwui/utils/Macros.h | 4 | ||||
-rw-r--r-- | libs/hwui/utils/PaintUtils.h | 7 |
14 files changed, 421 insertions, 189 deletions
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h index d128ffe..cca8a06 100644 --- a/libs/hwui/DisplayListOp.h +++ b/libs/hwui/DisplayListOp.h @@ -668,7 +668,8 @@ public: } virtual void output(int level, uint32_t logFlags) const override { - OP_LOG("Draw bitmap %p at %f %f%s", mBitmap, mLocalBounds.left, mLocalBounds.top, + OP_LOG("Draw bitmap %p of size %dx%d%s", + mBitmap, mBitmap->width(), mBitmap->height(), mEntry ? " using AssetAtlas" : ""); } diff --git a/libs/hwui/FloatColor.h b/libs/hwui/FloatColor.h new file mode 100644 index 0000000..803b9d4 --- /dev/null +++ b/libs/hwui/FloatColor.h @@ -0,0 +1,36 @@ +/* + * 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 FLOATCOLOR_H +#define FLOATCOLOR_H + +#include "utils/Macros.h" + +namespace android { +namespace uirenderer { + +struct FloatColor { + float r; + float g; + float b; + float a; +}; + +REQUIRE_COMPATIBLE_LAYOUT(FloatColor); + +} /* namespace uirenderer */ +} /* namespace android */ + +#endif /* FLOATCOLOR_H */ diff --git a/libs/hwui/Glop.h b/libs/hwui/Glop.h index e2adff8..12c6e45 100644 --- a/libs/hwui/Glop.h +++ b/libs/hwui/Glop.h @@ -17,6 +17,7 @@ #ifndef ANDROID_HWUI_GLOP_H #define ANDROID_HWUI_GLOP_H +#include "FloatColor.h" #include "Matrix.h" #include "Rect.h" #include "utils/Macros.h" @@ -29,6 +30,7 @@ namespace android { namespace uirenderer { class Program; +class RoundRectClipState; /* * Enumerates optional vertex attributes @@ -44,22 +46,23 @@ enum VertexAttribFlags { kAlpha_Attrib = 1 << 2, }; - /** - * Structure containing all data required to issue a single OpenGL draw + * Structure containing all data required to issue an OpenGL draw * * Includes all of the mesh, fill, and GL state required to perform * the operation. Pieces of data are either directly copied into the * structure, or stored as a pointer or GL object reference to data - * managed + * managed. + * + * Eventually, a Glop should be able to be drawn multiple times from + * a single construction, up until GL context destruction. Currently, + * vertex/index/Texture/RoundRectClipState pointers prevent this from + * being safe. */ // TODO: PREVENT_COPY_AND_ASSIGN(...) or similar struct Glop { - struct FloatColor { - float a, r, g, b; - }; - Rect bounds; + const RoundRectClipState* roundRectClipState; /* * Stores mesh - vertex and index data. @@ -74,12 +77,18 @@ struct Glop { GLuint indexBufferObject; const void* vertices; const void* indices; - int vertexCount; + int elementCount; GLsizei stride; + GLvoid* texCoordOffset; + TextureVertex mappedVertices[4]; } mesh; struct Fill { Program* program; + Texture* texture; + GLenum textureFilter; + + bool colorEnabled; FloatColor color; /* TODO diff --git a/libs/hwui/GlopBuilder.cpp b/libs/hwui/GlopBuilder.cpp index 5373275..e56988c 100644 --- a/libs/hwui/GlopBuilder.cpp +++ b/libs/hwui/GlopBuilder.cpp @@ -33,52 +33,72 @@ namespace uirenderer { #define TRIGGER_STAGE(stageFlag) \ LOG_ALWAYS_FATAL_IF(stageFlag & mStageFlags, "Stage %d cannot be run twice"); \ - mStageFlags = static_cast<StageFlags>(mStageFlags | stageFlag) + mStageFlags = static_cast<StageFlags>(mStageFlags | (stageFlag)) #define REQUIRE_STAGES(requiredFlags) \ - LOG_ALWAYS_FATAL_IF((mStageFlags & requiredFlags) != requiredFlags, \ + LOG_ALWAYS_FATAL_IF((mStageFlags & (requiredFlags)) != (requiredFlags), \ "not prepared for current stage") +static void setUnitQuadTextureCoords(Rect uvs, TextureVertex* quadVertex) {; + TextureVertex::setUV(quadVertex++, uvs.left, uvs.top); + TextureVertex::setUV(quadVertex++, uvs.right, uvs.top); + TextureVertex::setUV(quadVertex++, uvs.left, uvs.bottom); + TextureVertex::setUV(quadVertex++, uvs.right, uvs.bottom); +} + GlopBuilder::GlopBuilder(RenderState& renderState, Caches& caches, Glop* outGlop) : mRenderState(renderState) , mCaches(caches) - , mOutGlop(outGlop){ + , mOutGlop(outGlop) { mStageFlags = kInitialStage; } -GlopBuilder& GlopBuilder::setMeshVertexBuffer(const VertexBuffer& vertexBuffer, bool shadowInterp) { - TRIGGER_STAGE(kMeshStage); +//////////////////////////////////////////////////////////////////////////////// +// Mesh +//////////////////////////////////////////////////////////////////////////////// - const VertexBuffer::MeshFeatureFlags flags = vertexBuffer.getMeshFeatureFlags(); +GlopBuilder& GlopBuilder::setMeshUnitQuad() { + TRIGGER_STAGE(kMeshStage); - bool alphaVertex = flags & VertexBuffer::kAlpha; - bool indices = flags & VertexBuffer::kIndices; - mOutGlop->mesh.vertexFlags = alphaVertex ? kAlpha_Attrib : kNone_Attrib; + mOutGlop->mesh.vertexFlags = kNone_Attrib; mOutGlop->mesh.primitiveMode = GL_TRIANGLE_STRIP; - mOutGlop->mesh.vertexBufferObject = 0; - mOutGlop->mesh.vertices = vertexBuffer.getBuffer(); + mOutGlop->mesh.vertexBufferObject = mRenderState.meshState().getUnitQuadVBO(); + mOutGlop->mesh.vertices = nullptr; 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; + mOutGlop->mesh.indices = nullptr; + mOutGlop->mesh.elementCount = 4; + mOutGlop->mesh.stride = kTextureVertexStride; + mOutGlop->mesh.texCoordOffset = nullptr; return *this; } -GlopBuilder& GlopBuilder::setMeshUnitQuad() { +GlopBuilder& GlopBuilder::setMeshTexturedUnitQuad(const UvMapper* uvMapper, + bool isAlphaMaskTexture) { TRIGGER_STAGE(kMeshStage); - mOutGlop->mesh.vertexFlags = kNone_Attrib; + mOutGlop->mesh.vertexFlags = kTextureCoord_Attrib; mOutGlop->mesh.primitiveMode = GL_TRIANGLE_STRIP; - mOutGlop->mesh.vertexBufferObject = mRenderState.meshState().getUnitQuadVBO(); - mOutGlop->mesh.vertices = nullptr; + + if (CC_UNLIKELY(uvMapper)) { + Rect uvs(0, 0, 1, 1); + uvMapper->map(uvs); + setUnitQuadTextureCoords(uvs, &mOutGlop->mesh.mappedVertices[0]); + + mOutGlop->mesh.vertexBufferObject = 0; + mOutGlop->mesh.vertices = &mOutGlop->mesh.mappedVertices[0]; + } else { + // standard UV coordinates, use regular unit quad VBO + mOutGlop->mesh.vertexBufferObject = mRenderState.meshState().getUnitQuadVBO(); + mOutGlop->mesh.vertices = nullptr; + } mOutGlop->mesh.indexBufferObject = 0; mOutGlop->mesh.indices = nullptr; - mOutGlop->mesh.vertexCount = 4; + mOutGlop->mesh.elementCount = 4; mOutGlop->mesh.stride = kTextureVertexStride; + mOutGlop->mesh.texCoordOffset = (GLvoid*) kMeshTextureOffset; + + mDescription.hasTexture = true; + mDescription.hasAlpha8Texture = isAlphaMaskTexture; return *this; } @@ -91,92 +111,64 @@ GlopBuilder& GlopBuilder::setMeshIndexedQuads(void* vertexData, int quadCount) { mOutGlop->mesh.vertices = vertexData; mOutGlop->mesh.indexBufferObject = mRenderState.meshState().getQuadListIBO(); mOutGlop->mesh.indices = nullptr; - mOutGlop->mesh.vertexCount = 6 * quadCount; + mOutGlop->mesh.elementCount = 6 * quadCount; mOutGlop->mesh.stride = kVertexStride; + mOutGlop->mesh.texCoordOffset = nullptr; return *this; } -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; -} - -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; -} - -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::setOptionalPaint(const SkPaint* paint, float alphaScale) { - if (paint) { - return setPaint(*paint, alphaScale); - } - - TRIGGER_STAGE(kFillStage); - REQUIRE_STAGES(kMeshStage); +GlopBuilder& GlopBuilder::setMeshVertexBuffer(const VertexBuffer& vertexBuffer, bool shadowInterp) { + TRIGGER_STAGE(kMeshStage); - mOutGlop->fill.color = { alphaScale, alphaScale, alphaScale, alphaScale }; + const VertexBuffer::MeshFeatureFlags flags = vertexBuffer.getMeshFeatureFlags(); - const bool SWAP_SRC_DST = false; - // TODO: account for texture blend - if (alphaScale < 1.0f - || (mOutGlop->mesh.vertexFlags & kAlpha_Attrib)) { - Blend::getFactors(SkXfermode::kSrcOver_Mode, SWAP_SRC_DST, - &mOutGlop->blend.src, &mOutGlop->blend.dst); - } else { - mOutGlop->blend = { GL_ZERO, GL_ZERO }; - } + 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.elementCount = indices + ? vertexBuffer.getIndexCount() : vertexBuffer.getVertexCount(); + mOutGlop->mesh.stride = alphaVertex ? kAlphaVertexStride : kVertexStride; + mDescription.hasVertexAlpha = alphaVertex; + mDescription.useShadowAlphaInterp = shadowInterp; return *this; } -GlopBuilder& GlopBuilder::setPaint(const SkPaint& paint, float alphaScale) { - TRIGGER_STAGE(kFillStage); - REQUIRE_STAGES(kMeshStage); - const SkShader* shader = paint.getShader(); - const SkColorFilter* colorFilter = paint.getColorFilter(); +//////////////////////////////////////////////////////////////////////////////// +// Fill +//////////////////////////////////////////////////////////////////////////////// - SkXfermode::Mode mode = PaintUtils::getXfermode(paint.getXfermode()); +void GlopBuilder::setFill(int color, float alphaScale, SkXfermode::Mode mode, + const SkShader* shader, const SkColorFilter* colorFilter) { if (mode != SkXfermode::kClear_Mode) { - int color = paint.getColor(); float alpha = (SkColorGetA(color) / 255.0f) * alphaScale; if (!shader) { float colorScale = alpha / 255.0f; mOutGlop->fill.color = { - alpha, colorScale * SkColorGetR(color), colorScale * SkColorGetG(color), - colorScale * SkColorGetB(color) + colorScale * SkColorGetB(color), + alpha }; } else { - mOutGlop->fill.color = { alpha, 1, 1, 1 }; + mOutGlop->fill.color = { 1, 1, 1, alpha }; } } else { - mOutGlop->fill.color = { 1, 0, 0, 0 }; + mOutGlop->fill.color = { 0, 0, 0, 1 }; } const bool SWAP_SRC_DST = false; mOutGlop->blend = { GL_ZERO, GL_ZERO }; if (mOutGlop->fill.color.a < 1.0f || (mOutGlop->mesh.vertexFlags & kAlpha_Attrib) + || (mOutGlop->fill.texture && mOutGlop->fill.texture->blend) + || mOutGlop->roundRectClipState || PaintUtils::isBlendedShader(shader) || PaintUtils::isBlendedColorFilter(colorFilter) || mode != SkXfermode::kSrcOver_Mode) { @@ -218,10 +210,10 @@ GlopBuilder& GlopBuilder::setPaint(const SkPaint& paint, float alphaScale) { 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), + alpha, }; } else if (colorFilter->asColorMatrix(srcColorMatrix)) { mOutGlop->fill.filterMode = mDescription.colorOp = ProgramDescription::kColorMatrix; @@ -245,18 +237,151 @@ GlopBuilder& GlopBuilder::setPaint(const SkPaint& paint, float alphaScale) { } else { mOutGlop->fill.filterMode = ProgramDescription::kColorNone; } +} + +GlopBuilder& GlopBuilder::setFillTexturePaint(Texture& texture, bool isAlphaMaskTexture, + const SkPaint* paint, float alphaScale) { + TRIGGER_STAGE(kFillStage); + REQUIRE_STAGES(kMeshStage); + + mOutGlop->fill.texture = &texture; + mOutGlop->fill.textureFilter = PaintUtils::getFilter(paint); + + if (paint) { + int color = paint->getColor(); + SkShader* shader = paint->getShader(); + + if (!isAlphaMaskTexture) { + // Texture defines color, so disable shaders, and reset all non-alpha color channels + color |= 0x00FFFFFF; + shader = nullptr; + } + setFill(color, alphaScale, PaintUtils::getXfermode(paint->getXfermode()), + shader, paint->getColorFilter()); + } else { + mOutGlop->fill.color = { alphaScale, alphaScale, alphaScale, alphaScale }; + + const bool SWAP_SRC_DST = false; + if (alphaScale < 1.0f + || (mOutGlop->mesh.vertexFlags & kAlpha_Attrib) + || texture.blend + || mOutGlop->roundRectClipState) { + Blend::getFactors(SkXfermode::kSrcOver_Mode, SWAP_SRC_DST, + &mOutGlop->blend.src, &mOutGlop->blend.dst); + } else { + mOutGlop->blend = { GL_ZERO, GL_ZERO }; + } + } + + if (isAlphaMaskTexture) { + mDescription.modulate = mOutGlop->fill.color.a < 1.0f + || mOutGlop->fill.color.r > 0.0f + || mOutGlop->fill.color.g > 0.0f + || mOutGlop->fill.color.b > 0.0f; + } else { + mDescription.modulate = mOutGlop->fill.color.a < 1.0f; + } + return *this; +} + +GlopBuilder& GlopBuilder::setFillPaint(const SkPaint& paint, float alphaScale) { + TRIGGER_STAGE(kFillStage); + REQUIRE_STAGES(kMeshStage); + + mOutGlop->fill.texture = nullptr; + mOutGlop->fill.textureFilter = GL_NEAREST; + + setFill(paint.getColor(), alphaScale, PaintUtils::getXfermode(paint.getXfermode()), + paint.getShader(), paint.getColorFilter()); + mDescription.modulate = mOutGlop->fill.color.a < 1.0f; + return *this; +} + +//////////////////////////////////////////////////////////////////////////////// +// Transform +//////////////////////////////////////////////////////////////////////////////// + +GlopBuilder& GlopBuilder::setTransformClip(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; +} + + +//////////////////////////////////////////////////////////////////////////////// +// ModelView +//////////////////////////////////////////////////////////////////////////////// + +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; +} + +GlopBuilder& GlopBuilder::setModelViewMapUnitToRectSnap(const Rect destination) { + TRIGGER_STAGE(kModelViewStage); + REQUIRE_STAGES(kTransformStage | kFillStage); + + float left = destination.left; + float top = destination.top; + + const Matrix4& canvasTransform = mOutGlop->transform.canvas; + if (CC_LIKELY(canvasTransform.isPureTranslate())) { + const float translateX = canvasTransform.getTranslateX(); + const float translateY = canvasTransform.getTranslateY(); + + left = (int) floorf(left + translateX + 0.5f) - translateX; + top = (int) floorf(top + translateY + 0.5f) - translateY; + mOutGlop->fill.textureFilter = GL_NEAREST; + } + + mOutGlop->transform.modelView.loadTranslate(left, top, 0.0f); + mOutGlop->transform.modelView.scale(destination.getWidth(), destination.getHeight(), 1.0f); + mOutGlop->bounds = destination; + return *this; +} + +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::setRoundRectClipState(const RoundRectClipState* roundRectClipState) { + TRIGGER_STAGE(kRoundRectClipStage); + + mOutGlop->roundRectClipState = roundRectClipState; + mDescription.hasRoundRectClip = roundRectClipState != nullptr; return *this; } +//////////////////////////////////////////////////////////////////////////////// +// Build +//////////////////////////////////////////////////////////////////////////////// + void GlopBuilder::build() { REQUIRE_STAGES(kAllStages); - mDescription.modulate = mOutGlop->fill.color.a < 1.0f; mOutGlop->fill.program = mCaches.programCache.get(mDescription); mOutGlop->transform.canvas.mapRect(mOutGlop->bounds); + + // duplicates ProgramCache's definition of color uniform presence + const bool singleColor = !mDescription.hasTexture + && !mDescription.hasExternalTexture + && !mDescription.hasGradient + && !mDescription.hasBitmap; + mOutGlop->fill.colorEnabled = mDescription.modulate || singleColor; } } /* namespace uirenderer */ } /* namespace android */ - diff --git a/libs/hwui/GlopBuilder.h b/libs/hwui/GlopBuilder.h index 48ce81a..04d421c 100644 --- a/libs/hwui/GlopBuilder.h +++ b/libs/hwui/GlopBuilder.h @@ -38,25 +38,35 @@ public: GlopBuilder(RenderState& renderState, Caches& caches, Glop* outGlop); GlopBuilder& setMeshUnitQuad(); + GlopBuilder& setMeshTexturedUnitQuad(const UvMapper* uvMapper, bool isAlphaMaskTexture); GlopBuilder& setMeshVertexBuffer(const VertexBuffer& vertexBuffer, bool shadowInterp); GlopBuilder& setMeshIndexedQuads(void* vertexData, int quadCount); - GlopBuilder& setTransform(const Matrix4& ortho, const Matrix4& transform, bool fudgingOffset); + GlopBuilder& setFillPaint(const SkPaint& paint, float alphaScale); + GlopBuilder& setFillTexturePaint(Texture& texture, bool isAlphaMaskTexture, + const SkPaint* paint, float alphaScale); + + GlopBuilder& setTransformClip(const Matrix4& ortho, const Matrix4& transform, bool fudgingOffset); GlopBuilder& setModelViewMapUnitToRect(const Rect destination); + GlopBuilder& setModelViewMapUnitToRectSnap(const Rect destination); GlopBuilder& setModelViewOffsetRect(float offsetX, float offsetY, const Rect source); - GlopBuilder& setOptionalPaint(const SkPaint* paint, float alphaScale); - GlopBuilder& setPaint(const SkPaint& paint, float alphaScale); + GlopBuilder& setRoundRectClipState(const RoundRectClipState* roundRectClipState); + void build(); private: + void setFill(int color, float alphaScale, SkXfermode::Mode mode, + const SkShader* shader, const SkColorFilter* colorFilter); + enum StageFlags { kInitialStage = 0, kMeshStage = 1 << 0, kTransformStage = 1 << 1, kModelViewStage = 1 << 2, kFillStage = 1 << 3, - kAllStages = kMeshStage | kTransformStage | kModelViewStage | kFillStage, + kRoundRectClipStage = 1 << 4, + kAllStages = kMeshStage | kFillStage | kTransformStage | kModelViewStage | kRoundRectClipStage, } mStageFlags; ProgramDescription mDescription; diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 61cd16f..0841124 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -57,16 +57,11 @@ #define EVENT_LOGD(...) #endif +#define USE_GLOPS true + namespace android { namespace uirenderer { -static GLenum getFilter(const SkPaint* paint) { - if (!paint || paint->getFilterLevel() != SkPaint::kNone_FilterLevel) { - return GL_LINEAR; - } - return GL_NEAREST; -} - /////////////////////////////////////////////////////////////////////////////// // Globals /////////////////////////////////////////////////////////////////////////////// @@ -1586,6 +1581,7 @@ void OpenGLRenderer::renderGlop(const Glop& glop) { // TODO: specify more clearly when a draw should dirty the layer. // is writing to the stencil the only time we should ignore this? dirtyLayer(glop.bounds.left, glop.bounds.top, glop.bounds.right, glop.bounds.bottom); + mDirty = true; } } @@ -1611,7 +1607,7 @@ void OpenGLRenderer::setupDraw(bool clearLayer) { mSetShaderColor = false; mColorSet = false; - mColorA = mColorR = mColorG = mColorB = 0.0f; + mColor.a = mColor.r = mColor.g = mColor.b = 0.0f; mTextureUnit = 0; mTrackDirtyRegions = true; @@ -1647,21 +1643,21 @@ void OpenGLRenderer::setupDrawVertexAlpha(bool useShadowAlphaInterp) { } void OpenGLRenderer::setupDrawColor(int color, int alpha) { - mColorA = alpha / 255.0f; - mColorR = mColorA * ((color >> 16) & 0xFF) / 255.0f; - mColorG = mColorA * ((color >> 8) & 0xFF) / 255.0f; - mColorB = mColorA * ((color ) & 0xFF) / 255.0f; + mColor.a = alpha / 255.0f; + mColor.r = mColor.a * ((color >> 16) & 0xFF) / 255.0f; + mColor.g = mColor.a * ((color >> 8) & 0xFF) / 255.0f; + mColor.b = mColor.a * ((color ) & 0xFF) / 255.0f; mColorSet = true; - mSetShaderColor = mDescription.setColorModulate(mColorA); + mSetShaderColor = mDescription.setColorModulate(mColor.a); } void OpenGLRenderer::setupDrawAlpha8Color(int color, int alpha) { - mColorA = alpha / 255.0f; - mColorR = mColorA * ((color >> 16) & 0xFF) / 255.0f; - mColorG = mColorA * ((color >> 8) & 0xFF) / 255.0f; - mColorB = mColorA * ((color ) & 0xFF) / 255.0f; + mColor.a = alpha / 255.0f; + mColor.r = mColor.a * ((color >> 16) & 0xFF) / 255.0f; + mColor.g = mColor.a * ((color >> 8) & 0xFF) / 255.0f; + mColor.b = mColor.a * ((color ) & 0xFF) / 255.0f; mColorSet = true; - mSetShaderColor = mDescription.setAlpha8ColorModulate(mColorR, mColorG, mColorB, mColorA); + mSetShaderColor = mDescription.setAlpha8ColorModulate(mColor.r, mColor.g, mColor.b, mColor.a); } void OpenGLRenderer::setupDrawTextGamma(const SkPaint* paint) { @@ -1669,10 +1665,10 @@ void OpenGLRenderer::setupDrawTextGamma(const SkPaint* paint) { } void OpenGLRenderer::setupDrawColor(float r, float g, float b, float a) { - mColorA = a; - mColorR = r; - mColorG = g; - mColorB = b; + mColor.a = a; + mColor.r = r; + mColor.g = g; + mColor.b = b; mColorSet = true; mSetShaderColor = mDescription.setColorModulate(a); } @@ -1699,8 +1695,8 @@ void OpenGLRenderer::setupDrawColorFilter(const SkColorFilter* filter) { void OpenGLRenderer::accountForClear(SkXfermode::Mode mode) { if (mColorSet && mode == SkXfermode::kClear_Mode) { - mColorA = 1.0f; - mColorR = mColorG = mColorB = 0.0f; + mColor.a = 1.0f; + mColor.r = mColor.g = mColor.b = 0.0f; mSetShaderColor = mDescription.modulate = true; } } @@ -1713,7 +1709,7 @@ void OpenGLRenderer::setupDrawBlending(const Layer* layer, bool swapSrcDst) { // TODO: check shader blending, once we have shader drawing support for layers. bool blend = layer->isBlend() || getLayerAlpha(layer) < 1.0f - || (mColorSet && mColorA < 1.0f) + || (mColorSet && mColor.a < 1.0f) || PaintUtils::isBlendedColorFilter(layer->getColorFilter()); chooseBlending(blend, mode, mDescription, swapSrcDst); } @@ -1723,7 +1719,7 @@ 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) + blend |= (mColorSet && mColor.a < 1.0f) || (getShader(paint) && !getShader(paint)->isOpaque()) || PaintUtils::isBlendedColorFilter(getColorFilter(paint)); chooseBlending(blend, mode, mDescription, swapSrcDst); @@ -1775,13 +1771,13 @@ void OpenGLRenderer::setupDrawModelView(ModelViewMode mode, bool offset, void OpenGLRenderer::setupDrawColorUniforms(bool hasShader) { if ((mColorSet && !hasShader) || (hasShader && mSetShaderColor)) { - mCaches.program().setColor(mColorR, mColorG, mColorB, mColorA); + mCaches.program().setColor(mColor); } } void OpenGLRenderer::setupDrawPureColorUniforms() { if (mSetShaderColor) { - mCaches.program().setColor(mColorR, mColorG, mColorB, mColorA); + mCaches.program().setColor(mColor); } } @@ -1973,22 +1969,34 @@ void OpenGLRenderer::drawRenderNode(RenderNode* renderNode, Rect& dirty, int32_t } } -void OpenGLRenderer::drawAlphaBitmap(Texture* texture, float left, float top, - const SkPaint* paint) { - float x = left; - float y = top; +void OpenGLRenderer::drawAlphaBitmap(Texture* texture, const SkPaint* paint) { + if (USE_GLOPS && (!paint || !paint->getShader())) { + Glop glop; + GlopBuilder aBuilder(mRenderState, mCaches, &glop); + aBuilder.setMeshTexturedUnitQuad(texture->uvMapper, true) + .setFillTexturePaint(*texture, true, paint, currentSnapshot()->alpha) + .setTransformClip(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false) + .setModelViewMapUnitToRectSnap(Rect(0, 0, texture->width, texture->height)) + .setRoundRectClipState(currentSnapshot()->roundRectClipState) + .build(); + renderGlop(glop); + return; + } + + float x = 0; + float y = 0; texture->setWrap(GL_CLAMP_TO_EDGE, true); bool ignoreTransform = false; if (currentTransform()->isPureTranslate()) { - x = (int) floorf(left + currentTransform()->getTranslateX() + 0.5f); - y = (int) floorf(top + currentTransform()->getTranslateY() + 0.5f); + x = (int) floorf(currentTransform()->getTranslateX() + 0.5f); + y = (int) floorf(currentTransform()->getTranslateY() + 0.5f); ignoreTransform = true; texture->setFilter(GL_NEAREST, true); } else { - texture->setFilter(getFilter(paint), true); + texture->setFilter(PaintUtils::getFilter(paint), true); } // No need to check for a UV mapper on the texture object, only ARGB_8888 @@ -2013,7 +2021,7 @@ void OpenGLRenderer::drawBitmaps(const SkBitmap* bitmap, AssetAtlas::Entry* entr const AutoTexture autoCleanup(texture); texture->setWrap(GL_CLAMP_TO_EDGE, true); - texture->setFilter(pureTranslate ? GL_NEAREST : getFilter(paint), true); + texture->setFilter(pureTranslate ? GL_NEAREST : PaintUtils::getFilter(paint), true); const float x = (int) floorf(bounds.left + 0.5f); const float y = (int) floorf(bounds.top + 0.5f); @@ -2043,9 +2051,9 @@ void OpenGLRenderer::drawBitmap(const SkBitmap* bitmap, const SkPaint* paint) { const AutoTexture autoCleanup(texture); if (CC_UNLIKELY(bitmap->colorType() == kAlpha_8_SkColorType)) { - drawAlphaBitmap(texture, 0, 0, paint); + drawAlphaBitmap(texture, paint); } else { - drawTextureRect(0, 0, bitmap->width(), bitmap->height(), texture, paint); + drawTextureRect(texture, paint); } mDirty = true; @@ -2130,7 +2138,7 @@ void OpenGLRenderer::drawBitmapMesh(const SkBitmap* bitmap, int meshWidth, int m const AutoTexture autoCleanup(texture); texture->setWrap(GL_CLAMP_TO_EDGE, true); - texture->setFilter(getFilter(paint), true); + texture->setFilter(PaintUtils::getFilter(paint), true); int alpha; SkXfermode::Mode mode; @@ -2213,10 +2221,10 @@ void OpenGLRenderer::drawBitmap(const SkBitmap* bitmap, dstLeft = x; dstTop = y; - texture->setFilter(scaled ? getFilter(paint) : GL_NEAREST, true); + texture->setFilter(scaled ? PaintUtils::getFilter(paint) : GL_NEAREST, true); ignoreTransform = true; } else { - texture->setFilter(getFilter(paint), true); + texture->setFilter(PaintUtils::getFilter(paint), true); } if (CC_UNLIKELY(useScaleTransform)) { @@ -2350,15 +2358,16 @@ void OpenGLRenderer::drawVertexBuffer(float translateX, float translateY, return; } - if (!paint->getShader() && !currentSnapshot()->roundRectClipState) { + if (USE_GLOPS && !paint->getShader()) { 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) + .setFillPaint(*paint, currentSnapshot()->alpha) + .setTransformClip(currentSnapshot()->getOrthoMatrix(), *currentTransform(), fudgeOffset) .setModelViewOffsetRect(translateX, translateY, vertexBuffer.getBounds()) - .setPaint(*paint, currentSnapshot()->alpha) + .setRoundRectClipState(currentSnapshot()->roundRectClipState) .build(); renderGlop(glop); return; @@ -3251,14 +3260,15 @@ void OpenGLRenderer::drawColorRects(const float* rects, int count, const SkPaint return; } - if (!paint->getShader() && !currentSnapshot()->roundRectClipState) { + if (USE_GLOPS && !paint->getShader()) { const Matrix4& transform = ignoreTransform ? Matrix4::identity() : *currentTransform(); Glop glop; GlopBuilder aBuilder(mRenderState, mCaches, &glop); aBuilder.setMeshIndexedQuads(&mesh[0], count / 4) - .setTransform(currentSnapshot()->getOrthoMatrix(), transform, false) + .setFillPaint(*paint, currentSnapshot()->alpha) + .setTransformClip(currentSnapshot()->getOrthoMatrix(), transform, false) .setModelViewOffsetRect(0, 0, Rect(left, top, right, bottom)) - .setPaint(*paint, currentSnapshot()->alpha) + .setRoundRectClipState(currentSnapshot()->roundRectClipState) .build(); renderGlop(glop); return; @@ -3296,14 +3306,15 @@ 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) { + if (USE_GLOPS && !paint->getShader()) { const Matrix4& transform = ignoreTransform ? Matrix4::identity() : *currentTransform(); Glop glop; GlopBuilder aBuilder(mRenderState, mCaches, &glop); aBuilder.setMeshUnitQuad() - .setTransform(currentSnapshot()->getOrthoMatrix(), transform, false) + .setFillPaint(*paint, currentSnapshot()->alpha) + .setTransformClip(currentSnapshot()->getOrthoMatrix(), transform, false) .setModelViewMapUnitToRect(Rect(left, top, right, bottom)) - .setPaint(*paint, currentSnapshot()->alpha) + .setRoundRectClipState(currentSnapshot()->roundRectClipState) .build(); renderGlop(glop); return; @@ -3332,8 +3343,20 @@ void OpenGLRenderer::drawColorRect(float left, float top, float right, float bot glDrawArrays(GL_TRIANGLE_STRIP, 0, kUnitQuadCount); } -void OpenGLRenderer::drawTextureRect(float left, float top, float right, float bottom, - Texture* texture, const SkPaint* paint) { +void OpenGLRenderer::drawTextureRect(Texture* texture, const SkPaint* paint) { + if (USE_GLOPS) { + Glop glop; + GlopBuilder aBuilder(mRenderState, mCaches, &glop); + aBuilder.setMeshTexturedUnitQuad(texture->uvMapper, false) + .setFillTexturePaint(*texture, false, paint, currentSnapshot()->alpha) + .setTransformClip(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false) + .setModelViewMapUnitToRectSnap(Rect(0, 0, texture->width, texture->height)) + .setRoundRectClipState(currentSnapshot()->roundRectClipState) + .build(); + renderGlop(glop); + return; + } + texture->setWrap(GL_CLAMP_TO_EDGE, true); GLvoid* vertices = (GLvoid*) nullptr; @@ -3350,16 +3373,16 @@ void OpenGLRenderer::drawTextureRect(float left, float top, float right, float b } if (CC_LIKELY(currentTransform()->isPureTranslate())) { - const float x = (int) floorf(left + currentTransform()->getTranslateX() + 0.5f); - const float y = (int) floorf(top + currentTransform()->getTranslateY() + 0.5f); + const float x = (int) floorf(currentTransform()->getTranslateX() + 0.5f); + const float y = (int) floorf(currentTransform()->getTranslateY() + 0.5f); texture->setFilter(GL_NEAREST, true); drawTextureMesh(x, y, x + texture->width, y + texture->height, texture->id, paint, texture->blend, vertices, texCoords, GL_TRIANGLE_STRIP, kUnitQuadCount, false, true); } else { - texture->setFilter(getFilter(paint), true); - drawTextureMesh(left, top, right, bottom, texture->id, paint, + texture->setFilter(PaintUtils::getFilter(paint), true); + drawTextureMesh(0, 0, texture->width, texture->height, texture->id, paint, texture->blend, vertices, texCoords, GL_TRIANGLE_STRIP, kUnitQuadCount); } diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index f097041..4f8a2ea 100755 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -697,11 +697,9 @@ private: * different compositing rules. * * @param texture The texture to draw with - * @param left The x coordinate of the bitmap - * @param top The y coordinate of the bitmap * @param paint The paint to render with */ - void drawAlphaBitmap(Texture* texture, float left, float top, const SkPaint* paint); + void drawAlphaBitmap(Texture* texture, const SkPaint* paint); /** * Renders a strip of polygons with the specified paint, used for tessellated geometry. @@ -730,18 +728,12 @@ private: void drawConvexPath(const SkPath& path, const SkPaint* paint); /** - * Draws a textured rectangle with the specified texture. The specified coordinates - * are transformed by the current snapshot's transform matrix. + * Draws a textured rectangle with the specified texture. * - * @param left The left coordinate of the rectangle - * @param top The top coordinate of the rectangle - * @param right The right coordinate of the rectangle - * @param bottom The bottom coordinate of the rectangle * @param texture The texture to use * @param paint The paint containing the alpha, blending mode, etc. */ - void drawTextureRect(float left, float top, float right, float bottom, - Texture* texture, const SkPaint* paint); + void drawTextureRect(Texture* texture, const SkPaint* paint); /** * Draws a textured mesh with the specified texture. If the indices are omitted, @@ -1010,7 +1002,7 @@ private: ProgramDescription mDescription; // Color description bool mColorSet; - float mColorA, mColorR, mColorG, mColorB; + FloatColor mColor; // Indicates that the shader should get a color bool mSetShaderColor; // Current texture unit diff --git a/libs/hwui/Program.cpp b/libs/hwui/Program.cpp index 5f34b34..32713e9 100644 --- a/libs/hwui/Program.cpp +++ b/libs/hwui/Program.cpp @@ -177,12 +177,12 @@ void Program::set(const mat4& projectionMatrix, const mat4& modelViewMatrix, glUniformMatrix4fv(transform, 1, GL_FALSE, &t.data[0]); } -void Program::setColor(const float r, const float g, const float b, const float a) { +void Program::setColor(FloatColor color) { if (!mHasColorUniform) { mColorUniform = getUniform("color"); mHasColorUniform = true; } - glUniform4f(mColorUniform, r, g, b, a); + glUniform4f(mColorUniform, color.r, color.g, color.b, color.a); } void Program::use() { diff --git a/libs/hwui/Program.h b/libs/hwui/Program.h index 01231b5..af1e4a7 100644 --- a/libs/hwui/Program.h +++ b/libs/hwui/Program.h @@ -25,6 +25,7 @@ #include <SkXfermode.h> #include "Debug.h" +#include "FloatColor.h" #include "Matrix.h" #include "Properties.h" @@ -363,7 +364,7 @@ public: /** * Sets the color associated with this shader. */ - void setColor(const float r, const float g, const float b, const float a); + void setColor(FloatColor color); /** * Name of the texCoords attribute if it exists (kBindingTexCoords), -1 otherwise. diff --git a/libs/hwui/Vertex.h b/libs/hwui/Vertex.h index 5b80bbd..fd3845d 100644 --- a/libs/hwui/Vertex.h +++ b/libs/hwui/Vertex.h @@ -19,11 +19,9 @@ #include "Vector.h" -#include <type_traits> +#include "utils/Macros.h" -#define REQUIRE_COMPATIBLE_LAYOUT(TARGET_TYPE) \ - static_assert(std::is_standard_layout<TARGET_TYPE>::value, \ - #TARGET_TYPE " must have standard layout") +#include <type_traits> namespace android { namespace uirenderer { diff --git a/libs/hwui/renderstate/Blend.cpp b/libs/hwui/renderstate/Blend.cpp index c751dba..789f6cc 100644 --- a/libs/hwui/renderstate/Blend.cpp +++ b/libs/hwui/renderstate/Blend.cpp @@ -119,7 +119,7 @@ void Blend::setFactors(GLenum srcMode, GLenum dstMode) { mEnabled = true; } - if (srcMode != mSrcMode || dstMode != mSrcMode) { + if (srcMode != mSrcMode || dstMode != mDstMode) { glBlendFunc(srcMode, dstMode); mSrcMode = srcMode; mDstMode = dstMode; diff --git a/libs/hwui/renderstate/RenderState.cpp b/libs/hwui/renderstate/RenderState.cpp index 6394dc1..3953ecd 100644 --- a/libs/hwui/renderstate/RenderState.cpp +++ b/libs/hwui/renderstate/RenderState.cpp @@ -209,23 +209,25 @@ void RenderState::postDecStrong(VirtualLightRefBase* object) { void RenderState::render(const Glop& glop) { const Glop::Mesh& mesh = glop.mesh; - const Glop::Fill& shader = glop.fill; + const Glop::Fill& fill = glop.fill; - // -------------------------------------------- - // ---------- Shader + uniform setup ---------- - // -------------------------------------------- - mCaches->setProgram(shader.program); + // --------------------------------------------- + // ---------- Program + uniform setup ---------- + // --------------------------------------------- + mCaches->setProgram(fill.program); - Glop::FloatColor color = shader.color; - shader.program->setColor(color.r, color.g, color.b, color.a); + if (fill.colorEnabled) { + fill.program->setColor(fill.color); + } - shader.program->set(glop.transform.ortho, + fill.program->set(glop.transform.ortho, glop.transform.modelView, glop.transform.canvas, glop.transform.fudgingOffset); + // Color filter uniforms if (glop.fill.filterMode == ProgramDescription::kColorBlend) { - const Glop::FloatColor& color = glop.fill.filter.color; + const 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) { @@ -235,11 +237,28 @@ void RenderState::render(const Glop& glop) { glop.fill.filter.matrix.vector); } + // Round rect clipping uniforms + if (glop.roundRectClipState) { + // TODO: avoid query, and cache values (or RRCS ptr) in program + const RoundRectClipState* state = glop.roundRectClipState; + const Rect& innerRect = state->innerRect; + glUniform4f(fill.program->getUniform("roundRectInnerRectLTRB"), + innerRect.left, innerRect.top, + innerRect.right, innerRect.bottom); + glUniformMatrix4fv(fill.program->getUniform("roundRectInvTransform"), + 1, GL_FALSE, &state->matrix.data[0]); + + // add half pixel to round out integer rect space to cover pixel centers + float roundedOutRadius = state->radius + 0.5f; + glUniform1f(fill.program->getUniform("roundRectRadius"), + roundedOutRadius); + } + // -------------------------------- // ---------- Mesh setup ---------- // -------------------------------- // vertices - bool force = meshState().bindMeshBufferInternal(mesh.vertexBufferObject) + const bool force = meshState().bindMeshBufferInternal(mesh.vertexBufferObject) || (mesh.vertices != nullptr); meshState().bindPositionVertexPointer(force, mesh.vertices, mesh.stride); @@ -247,19 +266,26 @@ void RenderState::render(const Glop& glop) { meshState().bindIndicesBufferInternal(mesh.indexBufferObject); if (mesh.vertexFlags & kTextureCoord_Attrib) { - // TODO: support textures - LOG_ALWAYS_FATAL("textures not yet supported"); + // TODO: to support shaders, increment texture unit + mCaches->textureState().activateTexture(0); + + glop.fill.texture->setWrap(GL_CLAMP_TO_EDGE, true); + glop.fill.texture->setFilter(glop.fill.textureFilter, true); + + mCaches->textureState().bindTexture(fill.texture->id); + meshState().enableTexCoordsVertexArray(); + meshState().bindTexCoordsVertexPointer(force, mesh.texCoordOffset); } else { meshState().disableTexCoordsVertexArray(); } if (mesh.vertexFlags & kColor_Attrib) { LOG_ALWAYS_FATAL("color vertex attribute not yet supported"); - // TODO: enable color, disable when done + // TODO: enable color attribute, disable when done } int alphaSlot = -1; if (mesh.vertexFlags & kAlpha_Attrib) { const void* alphaCoords = ((const GLbyte*) glop.mesh.vertices) + kVertexAlphaOffset; - alphaSlot = shader.program->getAttrib("vtxAlpha"); + alphaSlot = fill.program->getAttrib("vtxAlpha"); glEnableVertexAttribArray(alphaSlot); glVertexAttribPointer(alphaSlot, 1, GL_FLOAT, GL_FALSE, kAlphaVertexStride, alphaCoords); } @@ -275,7 +301,7 @@ void RenderState::render(const Glop& glop) { if (mesh.indexBufferObject == meshState().getQuadListIBO()) { // Since the indexed quad list is of limited length, we loop over // the glDrawXXX method while updating the vertex pointer - GLsizei elementsCount = mesh.vertexCount; + GLsizei elementsCount = mesh.elementCount; const GLbyte* vertices = static_cast<const GLbyte*>(mesh.vertices); while (elementsCount > 0) { GLsizei drawCount = MathUtils::min(elementsCount, (GLsizei) kMaxNumberOfQuads * 6); @@ -287,9 +313,9 @@ void RenderState::render(const Glop& glop) { vertices += (drawCount / 6) * 4 * mesh.stride; } } else if (mesh.indexBufferObject || mesh.indices) { - glDrawElements(mesh.primitiveMode, mesh.vertexCount, GL_UNSIGNED_SHORT, mesh.indices); + glDrawElements(mesh.primitiveMode, mesh.elementCount, GL_UNSIGNED_SHORT, mesh.indices); } else { - glDrawArrays(mesh.primitiveMode, 0, mesh.vertexCount); + glDrawArrays(mesh.primitiveMode, 0, mesh.elementCount); } // ----------------------------------- diff --git a/libs/hwui/utils/Macros.h b/libs/hwui/utils/Macros.h index fe43fdb..eae73a9 100644 --- a/libs/hwui/utils/Macros.h +++ b/libs/hwui/utils/Macros.h @@ -29,4 +29,8 @@ friend inline int compare_type(const Type& lhs, const Type& rhs) { return lhs.compare(rhs); } \ friend inline hash_t hash_type(const Type& entry) { return entry.hash(); } +#define REQUIRE_COMPATIBLE_LAYOUT(Type) \ + static_assert(std::is_standard_layout<Type>::value, \ + #Type " must have standard layout") + #endif /* MACROS_H */ diff --git a/libs/hwui/utils/PaintUtils.h b/libs/hwui/utils/PaintUtils.h index 679e2bf..1a5cbf8 100644 --- a/libs/hwui/utils/PaintUtils.h +++ b/libs/hwui/utils/PaintUtils.h @@ -37,6 +37,13 @@ public: return resultMode; } + static inline GLenum getFilter(const SkPaint* paint) { + if (!paint || paint->getFilterLevel() != SkPaint::kNone_FilterLevel) { + return GL_LINEAR; + } + return GL_NEAREST; + } + // TODO: move to a method on android:Paint? replace with SkPaint::nothingToDraw()? static inline bool paintWillNotDraw(const SkPaint& paint) { return paint.getAlpha() == 0 |