Merge "Merge "Fix NPE finding target activity after recents animation controller crash" into pi-dev am: ebcfc4bb79 am: 4790ae379d"
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index 90cc7bb..0933e98 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -15,9 +15,6 @@
#include <cutils/ashmem.h>
#include <hwui/Canvas.h>
-#include <Caches.h>
-#include <TextureCache.h>
-
using namespace android;
void doThrowNPE(JNIEnv* env) {
diff --git a/core/jni/android/graphics/Path.cpp b/core/jni/android/graphics/Path.cpp
index 97abd82..aedb6ac 100644
--- a/core/jni/android/graphics/Path.cpp
+++ b/core/jni/android/graphics/Path.cpp
@@ -28,7 +28,6 @@
#include "SkPathOps.h"
#include "SkGeometry.h" // WARNING: Internal Skia Header
-#include <Caches.h>
#include <vector>
#include <map>
@@ -38,10 +37,6 @@
public:
static void finalizer(SkPath* obj) {
- // Purge entries from the HWUI path cache if this path's data is unique
- if (obj->unique() && android::uirenderer::Caches::hasInstance()) {
- android::uirenderer::Caches::getInstance().pathCache.removeDeferred(obj);
- }
delete obj;
}
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 3495c4f..d716844 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -211,14 +211,12 @@
"DeferredLayerUpdater.cpp",
"DeviceInfo.cpp",
"DisplayList.cpp",
- "FboCache.cpp",
"FrameBuilder.cpp",
"FrameInfo.cpp",
"FrameInfoVisualizer.cpp",
"GlLayer.cpp",
"GlopBuilder.cpp",
"GpuMemoryTracker.cpp",
- "GradientCache.cpp",
"Image.cpp",
"Interpolator.cpp",
"JankTracker.cpp",
@@ -229,8 +227,6 @@
"OpDumper.cpp",
"EglReadback.cpp",
"Patch.cpp",
- "PatchCache.cpp",
- "PathCache.cpp",
"PathParser.cpp",
"PathTessellator.cpp",
"PixelBuffer.cpp",
@@ -238,12 +234,10 @@
"ProfileDataContainer.cpp",
"ProfileRenderer.cpp",
"Program.cpp",
- "ProgramCache.cpp",
"Properties.cpp",
"PropertyValuesAnimatorSet.cpp",
"PropertyValuesHolder.cpp",
"RecordingCanvas.cpp",
- "RenderBufferCache.cpp",
"RenderNode.cpp",
"RenderProperties.cpp",
"ResourceCache.cpp",
@@ -253,9 +247,7 @@
"SkiaShader.cpp",
"Snapshot.cpp",
"SpotShadow.cpp",
- "TessellationCache.cpp",
"Texture.cpp",
- "TextureCache.cpp",
"VectorDrawable.cpp",
"VkLayer.cpp",
"protos/graphicsstats.proto",
@@ -411,7 +403,6 @@
"tests/microbench/LinearAllocatorBench.cpp",
"tests/microbench/PathParserBench.cpp",
"tests/microbench/RenderNodeBench.cpp",
- "tests/microbench/ShadowBench.cpp",
"tests/microbench/TaskManagerBench.cpp",
],
}
diff --git a/libs/hwui/BakedOpDispatcher.cpp b/libs/hwui/BakedOpDispatcher.cpp
index 2c7aab8..1f931ed 100644
--- a/libs/hwui/BakedOpDispatcher.cpp
+++ b/libs/hwui/BakedOpDispatcher.cpp
@@ -36,153 +36,14 @@
namespace android {
namespace uirenderer {
-static void storeTexturedRect(TextureVertex* vertices, const Rect& bounds) {
- vertices[0] = {bounds.left, bounds.top, 0, 0};
- vertices[1] = {bounds.right, bounds.top, 1, 0};
- vertices[2] = {bounds.left, bounds.bottom, 0, 1};
- vertices[3] = {bounds.right, bounds.bottom, 1, 1};
-}
-
void BakedOpDispatcher::onMergedBitmapOps(BakedOpRenderer& renderer,
const MergedBakedOpList& opList) {
- const BakedOpState& firstState = *(opList.states[0]);
- Bitmap* bitmap = (static_cast<const BitmapOp*>(opList.states[0]->op))->bitmap;
-
- Texture* texture = renderer.caches().textureCache.get(bitmap);
- if (!texture) return;
- const AutoTexture autoCleanup(texture);
-
- TextureVertex vertices[opList.count * 4];
- for (size_t i = 0; i < opList.count; i++) {
- const BakedOpState& state = *(opList.states[i]);
- TextureVertex* rectVerts = &vertices[i * 4];
-
- // calculate unclipped bounds, since they'll determine texture coordinates
- Rect opBounds = state.op->unmappedBounds;
- state.computedState.transform.mapRect(opBounds);
- if (CC_LIKELY(state.computedState.transform.isPureTranslate())) {
- // pure translate, so snap (same behavior as onBitmapOp)
- opBounds.snapToPixelBoundaries();
- }
- storeTexturedRect(rectVerts, opBounds);
- renderer.dirtyRenderTarget(opBounds);
- }
-
- const int textureFillFlags = (bitmap->colorType() == kAlpha_8_SkColorType)
- ? TextureFillFlags::IsAlphaMaskTexture
- : TextureFillFlags::None;
- Glop glop;
- GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
- .setRoundRectClipState(firstState.roundRectClipState)
- .setMeshTexturedIndexedQuads(vertices, opList.count * 6)
- .setFillTexturePaint(*texture, textureFillFlags, firstState.op->paint, firstState.alpha)
- .setTransform(Matrix4::identity(), TransformFlags::None)
- .setModelViewIdentityEmptyBounds()
- .build();
- ClipRect renderTargetClip(opList.clip);
- const ClipBase* clip = opList.clipSideFlags ? &renderTargetClip : nullptr;
- renderer.renderGlop(nullptr, clip, glop);
+ // DEAD CODE
}
void BakedOpDispatcher::onMergedPatchOps(BakedOpRenderer& renderer,
const MergedBakedOpList& opList) {
- const PatchOp& firstOp = *(static_cast<const PatchOp*>(opList.states[0]->op));
- const BakedOpState& firstState = *(opList.states[0]);
-
- // Batches will usually contain a small number of items so it's
- // worth performing a first iteration to count the exact number
- // of vertices we need in the new mesh
- uint32_t totalVertices = 0;
-
- for (size_t i = 0; i < opList.count; i++) {
- const PatchOp& op = *(static_cast<const PatchOp*>(opList.states[i]->op));
-
- // TODO: cache mesh lookups
- const Patch* opMesh = renderer.caches().patchCache.get(
- op.bitmap->width(), op.bitmap->height(), op.unmappedBounds.getWidth(),
- op.unmappedBounds.getHeight(), op.patch);
- totalVertices += opMesh->verticesCount;
- }
-
- const bool dirtyRenderTarget = renderer.offscreenRenderTarget();
-
- uint32_t indexCount = 0;
-
- TextureVertex vertices[totalVertices];
- TextureVertex* vertex = &vertices[0];
- // Create a mesh that contains the transformed vertices for all the
- // 9-patch objects that are part of the batch. Note that onDefer()
- // enforces ops drawn by this function to have a pure translate or
- // identity matrix
- for (size_t i = 0; i < opList.count; i++) {
- const PatchOp& op = *(static_cast<const PatchOp*>(opList.states[i]->op));
- const BakedOpState& state = *opList.states[i];
-
- // TODO: cache mesh lookups
- const Patch* opMesh = renderer.caches().patchCache.get(
- op.bitmap->width(), op.bitmap->height(), op.unmappedBounds.getWidth(),
- op.unmappedBounds.getHeight(), op.patch);
-
- uint32_t vertexCount = opMesh->verticesCount;
- if (vertexCount == 0) continue;
-
- // We use the bounds to know where to translate our vertices
- // Using patchOp->state.mBounds wouldn't work because these
- // bounds are clipped
- const float tx = floorf(state.computedState.transform.getTranslateX() +
- op.unmappedBounds.left + 0.5f);
- const float ty = floorf(state.computedState.transform.getTranslateY() +
- op.unmappedBounds.top + 0.5f);
-
- // Copy & transform all the vertices for the current operation
- TextureVertex* opVertices = opMesh->vertices.get();
- for (uint32_t j = 0; j < vertexCount; j++, opVertices++) {
- TextureVertex::set(vertex++, opVertices->x + tx, opVertices->y + ty, opVertices->u,
- opVertices->v);
- }
-
- // Dirty the current layer if possible. When the 9-patch does not
- // contain empty quads we can take a shortcut and simply set the
- // dirty rect to the object's bounds.
- if (dirtyRenderTarget) {
- if (!opMesh->hasEmptyQuads) {
- renderer.dirtyRenderTarget(Rect(tx, ty, tx + op.unmappedBounds.getWidth(),
- ty + op.unmappedBounds.getHeight()));
- } else {
- const size_t count = opMesh->quads.size();
- for (size_t i = 0; i < count; i++) {
- const Rect& quadBounds = opMesh->quads[i];
- const float x = tx + quadBounds.left;
- const float y = ty + quadBounds.top;
- renderer.dirtyRenderTarget(
- Rect(x, y, x + quadBounds.getWidth(), y + quadBounds.getHeight()));
- }
- }
- }
-
- indexCount += opMesh->indexCount;
- }
-
- Texture* texture = renderer.caches().textureCache.get(firstOp.bitmap);
- if (!texture) return;
- const AutoTexture autoCleanup(texture);
-
- // 9 patches are built for stretching - always filter
- int textureFillFlags = TextureFillFlags::ForceFilter;
- if (firstOp.bitmap->colorType() == kAlpha_8_SkColorType) {
- textureFillFlags |= TextureFillFlags::IsAlphaMaskTexture;
- }
- Glop glop;
- GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
- .setRoundRectClipState(firstState.roundRectClipState)
- .setMeshTexturedIndexedQuads(vertices, indexCount)
- .setFillTexturePaint(*texture, textureFillFlags, firstOp.paint, firstState.alpha)
- .setTransform(Matrix4::identity(), TransformFlags::None)
- .setModelViewIdentityEmptyBounds()
- .build();
- ClipRect renderTargetClip(opList.clip);
- const ClipBase* clip = opList.clipSideFlags ? &renderTargetClip : nullptr;
- renderer.renderGlop(nullptr, clip, glop);
+ // DEAD CODE
}
static void renderTextShadow(BakedOpRenderer& renderer, const TextOp& op,
@@ -244,29 +105,6 @@
}
}
-static void renderConvexPath(BakedOpRenderer& renderer, const BakedOpState& state,
- const SkPath& path, const SkPaint& paint) {
- VertexBuffer vertexBuffer;
- // TODO: try clipping large paths to viewport
- PathTessellator::tessellatePath(path, &paint, state.computedState.transform, vertexBuffer);
- renderVertexBuffer(renderer, state, vertexBuffer, 0.0f, 0.0f, paint, 0);
-}
-
-static void renderPathTexture(BakedOpRenderer& renderer, const BakedOpState& state, float xOffset,
- float yOffset, PathTexture& texture, const SkPaint& paint) {
- Rect dest(texture.width(), texture.height());
- dest.translate(xOffset + texture.left - texture.offset, yOffset + texture.top - texture.offset);
- Glop glop;
- GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
- .setRoundRectClipState(state.roundRectClipState)
- .setMeshTexturedUnitQuad(nullptr)
- .setFillPathTexturePaint(texture, paint, state.alpha)
- .setTransform(state.computedState.transform, TransformFlags::None)
- .setModelViewMapUnitToRect(dest)
- .build();
- renderer.renderGlop(state, glop);
-}
-
SkRect getBoundsOfFill(const RecordedOp& op) {
SkRect bounds = op.unmappedBounds.toSkRect();
if (op.paint->getStyle() == SkPaint::kStrokeAndFill_Style) {
@@ -278,29 +116,7 @@
void BakedOpDispatcher::onArcOp(BakedOpRenderer& renderer, const ArcOp& op,
const BakedOpState& state) {
- // TODO: support fills (accounting for concavity if useCenter && sweepAngle > 180)
- if (op.paint->getStyle() != SkPaint::kStroke_Style || op.paint->getPathEffect() != nullptr ||
- op.useCenter) {
- PathTexture* texture = renderer.caches().pathCache.getArc(
- op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight(), op.startAngle,
- op.sweepAngle, op.useCenter, op.paint);
- const AutoTexture holder(texture);
- if (CC_LIKELY(holder.texture)) {
- renderPathTexture(renderer, state, op.unmappedBounds.left, op.unmappedBounds.top,
- *texture, *(op.paint));
- }
- } else {
- SkRect rect = getBoundsOfFill(op);
- SkPath path;
- if (op.useCenter) {
- path.moveTo(rect.centerX(), rect.centerY());
- }
- path.arcTo(rect, op.startAngle, op.sweepAngle, !op.useCenter);
- if (op.useCenter) {
- path.close();
- }
- renderConvexPath(renderer, state, path, *(op.paint));
- }
+ // DEAD CODE
}
void BakedOpDispatcher::onBitmapOp(BakedOpRenderer& renderer, const BitmapOp& op,
@@ -325,69 +141,7 @@
void BakedOpDispatcher::onBitmapMeshOp(BakedOpRenderer& renderer, const BitmapMeshOp& op,
const BakedOpState& state) {
- Texture* texture = renderer.caches().textureCache.get(op.bitmap);
- if (!texture) {
- return;
- }
- const AutoTexture autoCleanup(texture);
-
- const uint32_t elementCount = op.meshWidth * op.meshHeight * 6;
-
- std::unique_ptr<ColorTextureVertex[]> mesh(new ColorTextureVertex[elementCount]);
- ColorTextureVertex* vertex = &mesh[0];
-
- const int* colors = op.colors;
- std::unique_ptr<int[]> tempColors;
- if (!colors) {
- uint32_t colorsCount = (op.meshWidth + 1) * (op.meshHeight + 1);
- tempColors.reset(new int[colorsCount]);
- memset(tempColors.get(), 0xff, colorsCount * sizeof(int));
- colors = tempColors.get();
- }
-
- for (int32_t y = 0; y < op.meshHeight; y++) {
- for (int32_t x = 0; x < op.meshWidth; x++) {
- uint32_t i = (y * (op.meshWidth + 1) + x) * 2;
-
- float u1 = float(x) / op.meshWidth;
- float u2 = float(x + 1) / op.meshWidth;
- float v1 = float(y) / op.meshHeight;
- float v2 = float(y + 1) / op.meshHeight;
-
- int ax = i + (op.meshWidth + 1) * 2;
- int ay = ax + 1;
- int bx = i;
- int by = bx + 1;
- int cx = i + 2;
- int cy = cx + 1;
- int dx = i + (op.meshWidth + 1) * 2 + 2;
- int dy = dx + 1;
-
- const float* vertices = op.vertices;
- ColorTextureVertex::set(vertex++, vertices[dx], vertices[dy], u2, v2, colors[dx / 2]);
- ColorTextureVertex::set(vertex++, vertices[ax], vertices[ay], u1, v2, colors[ax / 2]);
- ColorTextureVertex::set(vertex++, vertices[bx], vertices[by], u1, v1, colors[bx / 2]);
-
- ColorTextureVertex::set(vertex++, vertices[dx], vertices[dy], u2, v2, colors[dx / 2]);
- ColorTextureVertex::set(vertex++, vertices[bx], vertices[by], u1, v1, colors[bx / 2]);
- ColorTextureVertex::set(vertex++, vertices[cx], vertices[cy], u2, v1, colors[cx / 2]);
- }
- }
-
- /*
- * 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(renderer.renderState(), renderer.caches(), &glop)
- .setRoundRectClipState(state.roundRectClipState)
- .setMeshColoredTexturedMesh(mesh.get(), elementCount)
- .setFillTexturePaint(*texture, textureFillFlags, op.paint, state.alpha)
- .setTransform(state.computedState.transform, TransformFlags::None)
- .setModelViewOffsetRect(0, 0, op.unmappedBounds)
- .build();
- renderer.renderGlop(state, glop);
+ // DEAD CODE
}
void BakedOpDispatcher::onBitmapRectOp(BakedOpRenderer& renderer, const BitmapRectOp& op,
@@ -450,67 +204,17 @@
void BakedOpDispatcher::onOvalOp(BakedOpRenderer& renderer, const OvalOp& op,
const BakedOpState& state) {
- if (op.paint->getPathEffect() != nullptr) {
- PathTexture* texture = renderer.caches().pathCache.getOval(
- op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight(), op.paint);
- const AutoTexture holder(texture);
- if (CC_LIKELY(holder.texture)) {
- renderPathTexture(renderer, state, op.unmappedBounds.left, op.unmappedBounds.top,
- *texture, *(op.paint));
- }
- } else {
- SkPath path;
- SkRect rect = getBoundsOfFill(op);
- path.addOval(rect);
-
- if (state.computedState.localProjectionPathMask != nullptr) {
- // Mask the ripple path by the local space projection mask in local space.
- // Note that this can create CCW paths.
- Op(path, *state.computedState.localProjectionPathMask, kIntersect_SkPathOp, &path);
- }
- renderConvexPath(renderer, state, path, *(op.paint));
- }
+ // DEAD CODE
}
void BakedOpDispatcher::onPatchOp(BakedOpRenderer& renderer, const PatchOp& op,
const BakedOpState& state) {
- // 9 patches are built for stretching - always filter
- int textureFillFlags = TextureFillFlags::ForceFilter;
- if (op.bitmap->colorType() == kAlpha_8_SkColorType) {
- textureFillFlags |= TextureFillFlags::IsAlphaMaskTexture;
- }
-
- // TODO: avoid redoing the below work each frame:
- const Patch* mesh = renderer.caches().patchCache.get(op.bitmap->width(), op.bitmap->height(),
- op.unmappedBounds.getWidth(),
- op.unmappedBounds.getHeight(), op.patch);
-
- Texture* texture = renderer.caches().textureCache.get(op.bitmap);
- if (CC_LIKELY(texture)) {
- const AutoTexture autoCleanup(texture);
- Glop glop;
- GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
- .setRoundRectClipState(state.roundRectClipState)
- .setMeshPatchQuads(*mesh)
- .setFillTexturePaint(*texture, textureFillFlags, op.paint, state.alpha)
- .setTransform(state.computedState.transform, TransformFlags::None)
- .setModelViewOffsetRectSnap(
- op.unmappedBounds.left, op.unmappedBounds.top,
- Rect(op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight()))
- .build();
- renderer.renderGlop(state, glop);
- }
+ // DEAD CODE
}
void BakedOpDispatcher::onPathOp(BakedOpRenderer& renderer, const PathOp& op,
const BakedOpState& state) {
- PathTexture* texture = renderer.caches().pathCache.get(op.path, op.paint);
- const AutoTexture holder(texture);
- if (CC_LIKELY(holder.texture)) {
- // Unlike other callers to renderPathTexture, no offsets are used because PathOp doesn't
- // have any translate built in, other than what's in the SkPath itself
- renderPathTexture(renderer, state, 0, 0, *texture, *(op.paint));
- }
+ // DEAD CODE
}
void BakedOpDispatcher::onPointsOp(BakedOpRenderer& renderer, const PointsOp& op,
@@ -527,96 +231,12 @@
void BakedOpDispatcher::onRectOp(BakedOpRenderer& renderer, const RectOp& op,
const BakedOpState& state) {
- if (op.paint->getStyle() != SkPaint::kFill_Style) {
- // only fill + default miter is supported by drawConvexPath, since others must handle joins
- static_assert(SkPaintDefaults_MiterLimit == 4.0f, "Miter limit has changed");
- if (CC_UNLIKELY(op.paint->getPathEffect() != nullptr ||
- op.paint->getStrokeJoin() != SkPaint::kMiter_Join ||
- op.paint->getStrokeMiter() != SkPaintDefaults_MiterLimit)) {
- PathTexture* texture = renderer.caches().pathCache.getRect(
- op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight(), op.paint);
- const AutoTexture holder(texture);
- if (CC_LIKELY(holder.texture)) {
- renderPathTexture(renderer, state, op.unmappedBounds.left, op.unmappedBounds.top,
- *texture, *(op.paint));
- }
- } else {
- SkPath path;
- path.addRect(getBoundsOfFill(op));
- renderConvexPath(renderer, state, path, *(op.paint));
- }
- } else {
- if (op.paint->isAntiAlias() && !state.computedState.transform.isSimple()) {
- SkPath path;
- path.addRect(op.unmappedBounds.toSkRect());
- renderConvexPath(renderer, state, path, *(op.paint));
- } else {
- // render simple unit quad, no tessellation required
- Glop glop;
- GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
- .setRoundRectClipState(state.roundRectClipState)
- .setMeshUnitQuad()
- .setFillPaint(*op.paint, state.alpha)
- .setTransform(state.computedState.transform, TransformFlags::None)
- .setModelViewMapUnitToRect(op.unmappedBounds)
- .build();
- renderer.renderGlop(state, glop);
- }
- }
+ // DEAD CODE
}
void BakedOpDispatcher::onRoundRectOp(BakedOpRenderer& renderer, const RoundRectOp& op,
const BakedOpState& state) {
- if (op.paint->getPathEffect() != nullptr) {
- PathTexture* texture = renderer.caches().pathCache.getRoundRect(
- op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight(), op.rx, op.ry,
- op.paint);
- const AutoTexture holder(texture);
- if (CC_LIKELY(holder.texture)) {
- renderPathTexture(renderer, state, op.unmappedBounds.left, op.unmappedBounds.top,
- *texture, *(op.paint));
- }
- } else {
- const VertexBuffer* buffer = renderer.caches().tessellationCache.getRoundRect(
- state.computedState.transform, *(op.paint), op.unmappedBounds.getWidth(),
- op.unmappedBounds.getHeight(), op.rx, op.ry);
- renderVertexBuffer(renderer, state, *buffer, op.unmappedBounds.left, op.unmappedBounds.top,
- *(op.paint), 0);
- }
-}
-
-static void renderShadow(BakedOpRenderer& renderer, const BakedOpState& state, float casterAlpha,
- const VertexBuffer* ambientShadowVertexBuffer,
- const VertexBuffer* spotShadowVertexBuffer) {
- SkPaint paint;
- paint.setAntiAlias(true); // want to use AlphaVertex
-
- // The caller has made sure casterAlpha > 0.
- uint8_t ambientShadowAlpha = renderer.getLightInfo().ambientShadowAlpha;
- if (CC_UNLIKELY(Properties::overrideAmbientShadowStrength >= 0)) {
- ambientShadowAlpha = Properties::overrideAmbientShadowStrength;
- }
- if (ambientShadowVertexBuffer && ambientShadowAlpha > 0) {
- paint.setAlpha((uint8_t)(casterAlpha * ambientShadowAlpha));
- renderVertexBuffer(renderer, state, *ambientShadowVertexBuffer, 0, 0, paint,
- VertexBufferRenderFlags::ShadowInterp);
- }
-
- uint8_t spotShadowAlpha = renderer.getLightInfo().spotShadowAlpha;
- if (CC_UNLIKELY(Properties::overrideSpotShadowStrength >= 0)) {
- spotShadowAlpha = Properties::overrideSpotShadowStrength;
- }
- if (spotShadowVertexBuffer && spotShadowAlpha > 0) {
- paint.setAlpha((uint8_t)(casterAlpha * spotShadowAlpha));
- renderVertexBuffer(renderer, state, *spotShadowVertexBuffer, 0, 0, paint,
- VertexBufferRenderFlags::ShadowInterp);
- }
-}
-
-void BakedOpDispatcher::onShadowOp(BakedOpRenderer& renderer, const ShadowOp& op,
- const BakedOpState& state) {
- TessellationCache::vertexBuffer_pair_t buffers = op.shadowTask->getResult();
- renderShadow(renderer, state, op.casterAlpha, buffers.first, buffers.second);
+ // DEAD CODE
}
void BakedOpDispatcher::onSimpleRectsOp(BakedOpRenderer& renderer, const SimpleRectsOp& op,
diff --git a/libs/hwui/BakedOpRenderer.cpp b/libs/hwui/BakedOpRenderer.cpp
index 6b64b94..0a3e3e4 100644
--- a/libs/hwui/BakedOpRenderer.cpp
+++ b/libs/hwui/BakedOpRenderer.cpp
@@ -84,7 +84,6 @@
// if stencil was used for clipping, detach it and return it to pool
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0);
GL_CHECKPOINT(MODERATE);
- mCaches.renderBufferCache.put(mRenderTarget.stencil);
mRenderTarget.stencil = nullptr;
}
mRenderTarget.lastStencilClip = nullptr;
@@ -182,7 +181,7 @@
}
Texture* BakedOpRenderer::getTexture(Bitmap* bitmap) {
- return mCaches.textureCache.get(bitmap);
+ return nullptr;
}
void BakedOpRenderer::drawRects(const float* rects, int count, const SkPaint* paint) {
@@ -304,15 +303,7 @@
// Stencil needed, but current stencil isn't up to date
mRenderTarget.lastStencilClip = clip;
- if (mRenderTarget.frameBufferId != 0 && !mRenderTarget.stencil) {
- OffscreenBuffer* layer = mRenderTarget.offscreenBuffer;
- mRenderTarget.stencil = mCaches.renderBufferCache.get(
- Stencil::getLayerStencilFormat(), layer->texture.width(),
- layer->texture.height());
- // stencil is bound + allocated - associate it with current FBO
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
- GL_RENDERBUFFER, mRenderTarget.stencil->getName());
- }
+ // DEAD CODE
if (clip->mode == ClipMode::RectangleList) {
setupStencilRectList(clip);
diff --git a/libs/hwui/BakedOpRenderer.h b/libs/hwui/BakedOpRenderer.h
index 7c0590d..ae8928e 100644
--- a/libs/hwui/BakedOpRenderer.h
+++ b/libs/hwui/BakedOpRenderer.h
@@ -26,6 +26,7 @@
class Caches;
struct Glop;
class Layer;
+struct RenderBuffer;
class RenderState;
struct ClipBase;
diff --git a/libs/hwui/BakedOpState.cpp b/libs/hwui/BakedOpState.cpp
index 63edf77..0c673f3 100644
--- a/libs/hwui/BakedOpState.cpp
+++ b/libs/hwui/BakedOpState.cpp
@@ -149,14 +149,6 @@
return bakedState;
}
-BakedOpState* BakedOpState::tryShadowOpConstruct(LinearAllocator& allocator, Snapshot& snapshot,
- const ShadowOp* shadowOpPtr) {
- if (CC_UNLIKELY(snapshot.getRenderTargetClip().isEmpty())) return nullptr;
-
- // clip isn't empty, so construct the op
- return allocator.create_trivial<BakedOpState>(allocator, snapshot, shadowOpPtr);
-}
-
BakedOpState* BakedOpState::directConstruct(LinearAllocator& allocator, const ClipRect* clip,
const Rect& dstRect, const RecordedOp& recordedOp) {
return allocator.create_trivial<BakedOpState>(clip, dstRect, recordedOp);
diff --git a/libs/hwui/BakedOpState.h b/libs/hwui/BakedOpState.h
index e12dfbb..a50feff 100644
--- a/libs/hwui/BakedOpState.h
+++ b/libs/hwui/BakedOpState.h
@@ -120,9 +120,6 @@
StrokeBehavior strokeBehavior,
bool expandForPathTexture);
- static BakedOpState* tryShadowOpConstruct(LinearAllocator& allocator, Snapshot& snapshot,
- const ShadowOp* shadowOpPtr);
-
static BakedOpState* directConstruct(LinearAllocator& allocator, const ClipRect* clip,
const Rect& dstRect, const RecordedOp& recordedOp);
@@ -154,12 +151,6 @@
, roundRectClipState(snapshot.roundRectClipState)
, op(&recordedOp) {}
- BakedOpState(LinearAllocator& allocator, Snapshot& snapshot, const ShadowOp* shadowOpPtr)
- : computedState(allocator, snapshot)
- , alpha(snapshot.alpha)
- , roundRectClipState(snapshot.roundRectClipState)
- , op(shadowOpPtr) {}
-
BakedOpState(const ClipRect* clipRect, const Rect& dstRect, const RecordedOp& recordedOp)
: computedState(clipRect, dstRect)
, alpha(1.0f)
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 6aefb35..9c2ab5c 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -46,10 +46,7 @@
///////////////////////////////////////////////////////////////////////////////
Caches::Caches(RenderState& renderState)
- : gradientCache(extensions())
- , patchCache(renderState)
- , programCache(extensions())
- , mRenderState(&renderState)
+ : mRenderState(&renderState)
, mInitialized(false) {
INIT_LOGD("Creating OpenGL renderer caches");
init();
@@ -102,13 +99,8 @@
if (!mInitialized) return;
mRegionMesh.reset(nullptr);
- fboCache.clear();
-
- programCache.clear();
mProgram = nullptr;
- patchCache.clear();
-
clearGarbage();
delete mPixelBufferState;
@@ -119,7 +111,7 @@
}
void Caches::setProgram(const ProgramDescription& description) {
- setProgram(programCache.get(description));
+ // DEAD CODE
}
void Caches::setProgram(Program* program) {
@@ -157,8 +149,6 @@
void Caches::dumpMemoryUsage(String8& log) {
uint32_t total = 0;
log.appendFormat("Current memory usage / total memory usage (bytes):\n");
- log.appendFormat(" TextureCache %8d / %8d\n", textureCache.getSize(),
- textureCache.getMaxSize());
if (mRenderState) {
int memused = 0;
for (std::set<Layer*>::iterator it = mRenderState->mActiveLayers.begin();
@@ -174,27 +164,6 @@
mRenderState->mActiveLayers.size());
total += memused;
}
- log.appendFormat(" RenderBufferCache %8d / %8d\n", renderBufferCache.getSize(),
- renderBufferCache.getMaxSize());
- log.appendFormat(" GradientCache %8d / %8d\n", gradientCache.getSize(),
- gradientCache.getMaxSize());
- log.appendFormat(" PathCache %8d / %8d\n", pathCache.getSize(),
- pathCache.getMaxSize());
- log.appendFormat(" TessellationCache %8d / %8d\n", tessellationCache.getSize(),
- tessellationCache.getMaxSize());
- log.appendFormat(" PatchCache %8d / %8d\n", patchCache.getSize(),
- patchCache.getMaxSize());
-
- log.appendFormat("Other:\n");
- log.appendFormat(" FboCache %8d / %8d\n", fboCache.getSize(),
- fboCache.getMaxSize());
-
- total += textureCache.getSize();
- total += renderBufferCache.getSize();
- total += gradientCache.getSize();
- total += pathCache.getSize();
- total += tessellationCache.getSize();
- total += patchCache.getSize();
log.appendFormat("Total memory usage:\n");
log.appendFormat(" %d bytes, %.2f MB\n", total, total / 1024.0f / 1024.0f);
@@ -205,30 +174,9 @@
///////////////////////////////////////////////////////////////////////////////
void Caches::clearGarbage() {
- pathCache.clearGarbage();
- patchCache.clearGarbage();
}
void Caches::flush(FlushMode mode) {
- FLUSH_LOGD("Flushing caches (mode %d)", mode);
-
- switch (mode) {
- case FlushMode::Full:
- textureCache.clear();
- patchCache.clear();
- gradientCache.clear();
- fboCache.clear();
- // fall through
- case FlushMode::Moderate:
- textureCache.flush();
- pathCache.clear();
- tessellationCache.clear();
- // fall through
- case FlushMode::Layers:
- renderBufferCache.clear();
- break;
- }
-
clearGarbage();
glFinish();
// Errors during cleanup should be considered non-fatal, dump them and
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index ed2d0b3..4cb6aff 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -18,15 +18,8 @@
#include "DeviceInfo.h"
#include "Extensions.h"
-#include "FboCache.h"
-#include "GradientCache.h"
-#include "PatchCache.h"
-#include "PathCache.h"
-#include "ProgramCache.h"
-#include "RenderBufferCache.h"
+#include "Program.h"
#include "ResourceCache.h"
-#include "TessellationCache.h"
-#include "TextureCache.h"
#include "renderstate/PixelBufferState.h"
#include "renderstate/TextureState.h"
#include "thread/TaskManager.h"
@@ -140,15 +133,6 @@
GLint maxTextureSize;
public:
- TextureCache textureCache;
- RenderBufferCache renderBufferCache;
- GradientCache gradientCache;
- PatchCache patchCache;
- PathCache pathCache;
- ProgramCache programCache;
- TessellationCache tessellationCache;
- FboCache fboCache;
-
TaskManager tasks;
bool gpuPixelBuffersEnabled;
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index aa87aea..f1f0d2d 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -64,9 +64,6 @@
for (size_t i = 0; i < pathResources.size(); i++) {
const SkPath* path = pathResources[i];
- if (path->unique() && Caches::hasInstance()) {
- Caches::getInstance().pathCache.removeDeferred(path);
- }
delete path;
}
diff --git a/libs/hwui/FboCache.cpp b/libs/hwui/FboCache.cpp
deleted file mode 100644
index 88302cc..0000000
--- a/libs/hwui/FboCache.cpp
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdlib.h>
-
-#include "Debug.h"
-#include "FboCache.h"
-#include "Properties.h"
-
-namespace android {
-namespace uirenderer {
-
-///////////////////////////////////////////////////////////////////////////////
-// Constructors/destructor
-///////////////////////////////////////////////////////////////////////////////
-
-FboCache::FboCache() : mMaxSize(0) {}
-
-FboCache::~FboCache() {
- clear();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Size management
-///////////////////////////////////////////////////////////////////////////////
-
-uint32_t FboCache::getSize() {
- return mCache.size();
-}
-
-uint32_t FboCache::getMaxSize() {
- return mMaxSize;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Caching
-///////////////////////////////////////////////////////////////////////////////
-
-void FboCache::clear() {
- for (size_t i = 0; i < mCache.size(); i++) {
- const GLuint fbo = mCache.itemAt(i);
- glDeleteFramebuffers(1, &fbo);
- }
- mCache.clear();
-}
-
-GLuint FboCache::get() {
- GLuint fbo;
- if (mCache.size() > 0) {
- fbo = mCache.itemAt(mCache.size() - 1);
- mCache.removeAt(mCache.size() - 1);
- } else {
- glGenFramebuffers(1, &fbo);
- }
- return fbo;
-}
-
-bool FboCache::put(GLuint fbo) {
- if (mCache.size() < mMaxSize) {
- mCache.add(fbo);
- return true;
- }
-
- glDeleteFramebuffers(1, &fbo);
- return false;
-}
-
-}; // namespace uirenderer
-}; // namespace android
diff --git a/libs/hwui/FboCache.h b/libs/hwui/FboCache.h
deleted file mode 100644
index 5e8bb0c..0000000
--- a/libs/hwui/FboCache.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HWUI_FBO_CACHE_H
-#define ANDROID_HWUI_FBO_CACHE_H
-
-#include <GLES2/gl2.h>
-
-#include <utils/SortedVector.h>
-
-namespace android {
-namespace uirenderer {
-
-///////////////////////////////////////////////////////////////////////////////
-// Cache
-///////////////////////////////////////////////////////////////////////////////
-
-class FboCache {
-public:
- FboCache();
- ~FboCache();
-
- /**
- * Returns an FBO from the cache. If no FBO is available, a new one
- * is created. If creating a new FBO fails, 0 is returned.
- *
- * When an FBO is obtained from the cache, it is removed and the
- * total number of FBOs available in the cache decreases.
- *
- * @return The name of the FBO, or 0 if no FBO can be obtained.
- */
- GLuint get();
-
- /**
- * Adds the specified FBO to the cache.
- *
- * @param fbo The FBO to add to the cache.
- *
- * @return True if the FBO was added, false otherwise.
- */
- bool put(GLuint fbo);
-
- /**
- * Clears the cache. This causes all FBOs to be deleted.
- */
- void clear();
-
- /**
- * Returns the current size of the cache.
- */
- uint32_t getSize();
-
- /**
- * Returns the maximum number of FBOs that the cache can hold.
- */
- uint32_t getMaxSize();
-
-private:
- SortedVector<GLuint> mCache;
- uint32_t mMaxSize;
-}; // class FboCache
-
-}; // namespace uirenderer
-}; // namespace android
-
-#endif // ANDROID_HWUI_FBO_CACHE_H
diff --git a/libs/hwui/FrameBuilder.cpp b/libs/hwui/FrameBuilder.cpp
index 049cd45..575aea5 100644
--- a/libs/hwui/FrameBuilder.cpp
+++ b/libs/hwui/FrameBuilder.cpp
@@ -386,71 +386,7 @@
}
void FrameBuilder::deferShadow(const ClipBase* reorderClip, const RenderNodeOp& casterNodeOp) {
- auto& node = *casterNodeOp.renderNode;
- auto& properties = node.properties();
-
- if (properties.getAlpha() <= 0.0f || properties.getOutline().getAlpha() <= 0.0f ||
- !properties.getOutline().getPath() || properties.getScaleX() == 0 ||
- properties.getScaleY() == 0) {
- // no shadow to draw
- return;
- }
-
- const SkPath* casterOutlinePath = properties.getOutline().getPath();
- const SkPath* revealClipPath = properties.getRevealClip().getPath();
- if (revealClipPath && revealClipPath->isEmpty()) return;
-
- float casterAlpha = properties.getAlpha() * properties.getOutline().getAlpha();
-
- // holds temporary SkPath to store the result of intersections
- SkPath* frameAllocatedPath = nullptr;
- const SkPath* casterPath = casterOutlinePath;
-
- // intersect the shadow-casting path with the reveal, if present
- if (revealClipPath) {
- frameAllocatedPath = createFrameAllocatedPath();
-
- Op(*casterPath, *revealClipPath, kIntersect_SkPathOp, frameAllocatedPath);
- casterPath = frameAllocatedPath;
- }
-
- // intersect the shadow-casting path with the clipBounds, if present
- if (properties.getClippingFlags() & CLIP_TO_CLIP_BOUNDS) {
- if (!frameAllocatedPath) {
- frameAllocatedPath = createFrameAllocatedPath();
- }
- Rect clipBounds;
- properties.getClippingRectForFlags(CLIP_TO_CLIP_BOUNDS, &clipBounds);
- SkPath clipBoundsPath;
- clipBoundsPath.addRect(clipBounds.left, clipBounds.top, clipBounds.right,
- clipBounds.bottom);
-
- Op(*casterPath, clipBoundsPath, kIntersect_SkPathOp, frameAllocatedPath);
- casterPath = frameAllocatedPath;
- }
-
- // apply reorder clip to shadow, so it respects clip at beginning of reorderable chunk
- int restoreTo = mCanvasState.save(SaveFlags::MatrixClip);
- mCanvasState.writableSnapshot()->applyClip(reorderClip,
- *mCanvasState.currentSnapshot()->transform);
- if (CC_LIKELY(!mCanvasState.getRenderTargetClipBounds().isEmpty())) {
- Matrix4 shadowMatrixXY(casterNodeOp.localMatrix);
- Matrix4 shadowMatrixZ(casterNodeOp.localMatrix);
- node.applyViewPropertyTransforms(shadowMatrixXY, false);
- node.applyViewPropertyTransforms(shadowMatrixZ, true);
-
- sp<TessellationCache::ShadowTask> task = mCaches.tessellationCache.getShadowTask(
- mCanvasState.currentTransform(), mCanvasState.getLocalClipBounds(),
- casterAlpha >= 1.0f, casterPath, &shadowMatrixXY, &shadowMatrixZ,
- mCanvasState.currentSnapshot()->getRelativeLightCenter(), mLightRadius);
- ShadowOp* shadowOp = mAllocator.create<ShadowOp>(task, casterAlpha);
- BakedOpState* bakedOpState = BakedOpState::tryShadowOpConstruct(
- mAllocator, *mCanvasState.writableSnapshot(), shadowOp);
- if (CC_LIKELY(bakedOpState)) {
- currentLayer().deferUnmergeableOp(mAllocator, bakedOpState, OpBatchType::Shadow);
- }
- }
- mCanvasState.restoreToCount(restoreTo);
+ // DEAD CODE
}
void FrameBuilder::deferProjectedChildren(const RenderNode& renderNode) {
@@ -682,10 +618,7 @@
}
void FrameBuilder::deferPathOp(const PathOp& op) {
- auto state = deferStrokeableOp(op, OpBatchType::AlphaMaskTexture);
- if (CC_LIKELY(state)) {
- mCaches.pathCache.precache(op.path, op.paint);
- }
+ /*auto state = */deferStrokeableOp(op, OpBatchType::AlphaMaskTexture);
}
void FrameBuilder::deferPointsOp(const PointsOp& op) {
@@ -698,13 +631,7 @@
}
void FrameBuilder::deferRoundRectOp(const RoundRectOp& op) {
- auto state = deferStrokeableOp(op, tessBatchId(op));
- if (CC_LIKELY(state && !op.paint->getPathEffect())) {
- // TODO: consider storing tessellation task in BakedOpState
- mCaches.tessellationCache.precacheRoundRect(state->computedState.transform, *(op.paint),
- op.unmappedBounds.getWidth(),
- op.unmappedBounds.getHeight(), op.rx, op.ry);
- }
+ // DEAD CODE
}
void FrameBuilder::deferRoundRectPropsOp(const RoundRectPropsOp& op) {
diff --git a/libs/hwui/GlopBuilder.cpp b/libs/hwui/GlopBuilder.cpp
index 941373d..13a4112 100644
--- a/libs/hwui/GlopBuilder.cpp
+++ b/libs/hwui/GlopBuilder.cpp
@@ -21,7 +21,6 @@
#include "Layer.h"
#include "Matrix.h"
#include "Patch.h"
-#include "PathCache.h"
#include "SkiaShader.h"
#include "Texture.h"
#include "VertexBuffer.h"
@@ -203,17 +202,7 @@
}
GlopBuilder& GlopBuilder::setMeshPatchQuads(const Patch& patch) {
- TRIGGER_STAGE(kMeshStage);
-
- mOutGlop->mesh.primitiveMode = GL_TRIANGLES;
- mOutGlop->mesh.indices = {mRenderState.meshState().getQuadListIBO(), nullptr};
- mOutGlop->mesh.vertices = {mCaches.patchCache.getMeshBuffer(),
- VertexAttribFlags::TextureCoord,
- (void*)patch.positionOffset,
- (void*)patch.textureOffset,
- nullptr,
- kTextureVertexStride};
- mOutGlop->mesh.elementCount = patch.indexCount;
+ // DEAD CODE
return *this;
}
@@ -365,17 +354,7 @@
GlopBuilder& GlopBuilder::setFillPathTexturePaint(PathTexture& texture, const SkPaint& paint,
float alphaScale) {
- TRIGGER_STAGE(kFillStage);
- REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);
-
- // specify invalid filter/clamp, since these are always static for PathTextures
- mOutGlop->fill.texture = {&texture, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr};
-
- setFill(paint.getColor(), alphaScale, paint.getBlendMode(), Blend::ModeOrderSwap::NoSwap,
- paint.getShader(), paint.getColorFilter());
-
- mDescription.hasAlpha8Texture = true;
- mDescription.modulate = mOutGlop->fill.color.isNotBlack();
+ // DEAD CODE
return *this;
}
@@ -625,9 +604,6 @@
mOutGlop->fill.colorEnabled = mDescription.modulate || singleColor;
verify(mDescription, *mOutGlop);
-
- // Final step: populate program and map bounds into render target space
- mOutGlop->fill.program = mCaches.programCache.get(mDescription);
}
void GlopBuilder::dump(const Glop& glop) {
diff --git a/libs/hwui/GradientCache.cpp b/libs/hwui/GradientCache.cpp
deleted file mode 100644
index 21e3c73..0000000
--- a/libs/hwui/GradientCache.cpp
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <utils/JenkinsHash.h>
-
-#include "Caches.h"
-#include "Debug.h"
-#include "DeviceInfo.h"
-#include "GradientCache.h"
-#include "Properties.h"
-
-#include <cutils/properties.h>
-
-namespace android {
-namespace uirenderer {
-
-///////////////////////////////////////////////////////////////////////////////
-// Functions
-///////////////////////////////////////////////////////////////////////////////
-
-template <typename T>
-static inline T min(T a, T b) {
- return a < b ? a : b;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Cache entry
-///////////////////////////////////////////////////////////////////////////////
-
-hash_t GradientCacheEntry::hash() const {
- uint32_t hash = JenkinsHashMix(0, count);
- for (uint32_t i = 0; i < count; i++) {
- hash = JenkinsHashMix(hash, android::hash_type(colors[i]));
- hash = JenkinsHashMix(hash, android::hash_type(positions[i]));
- }
- return JenkinsHashWhiten(hash);
-}
-
-int GradientCacheEntry::compare(const GradientCacheEntry& lhs, const GradientCacheEntry& rhs) {
- int deltaInt = int(lhs.count) - int(rhs.count);
- if (deltaInt != 0) return deltaInt;
-
- deltaInt = memcmp(lhs.colors.get(), rhs.colors.get(), lhs.count * sizeof(uint32_t));
- if (deltaInt != 0) return deltaInt;
-
- return memcmp(lhs.positions.get(), rhs.positions.get(), lhs.count * sizeof(float));
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Constructors/destructor
-///////////////////////////////////////////////////////////////////////////////
-
-GradientCache::GradientCache(const Extensions& extensions)
- : mCache(LruCache<GradientCacheEntry, Texture*>::kUnlimitedCapacity)
- , mSize(0)
- , mMaxSize(MB(1))
- , mUseFloatTexture(extensions.hasFloatTextures())
- , mHasNpot(extensions.hasNPot())
- , mHasLinearBlending(extensions.hasLinearBlending()) {
- mMaxTextureSize = DeviceInfo::get()->maxTextureSize();
-
- mCache.setOnEntryRemovedListener(this);
-}
-
-GradientCache::~GradientCache() {
- mCache.clear();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Size management
-///////////////////////////////////////////////////////////////////////////////
-
-uint32_t GradientCache::getSize() {
- return mSize;
-}
-
-uint32_t GradientCache::getMaxSize() {
- return mMaxSize;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Callbacks
-///////////////////////////////////////////////////////////////////////////////
-
-void GradientCache::operator()(GradientCacheEntry&, Texture*& texture) {
- if (texture) {
- mSize -= texture->objectSize();
- texture->deleteTexture();
- delete texture;
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Caching
-///////////////////////////////////////////////////////////////////////////////
-
-Texture* GradientCache::get(uint32_t* colors, float* positions, int count) {
- GradientCacheEntry gradient(colors, positions, count);
- Texture* texture = mCache.get(gradient);
-
- if (!texture) {
- texture = addLinearGradient(gradient, colors, positions, count);
- }
-
- return texture;
-}
-
-void GradientCache::clear() {
- mCache.clear();
-}
-
-void GradientCache::getGradientInfo(const uint32_t* colors, const int count, GradientInfo& info) {
- uint32_t width = 256 * (count - 1);
-
- // If the npot extension is not supported we cannot use non-clamp
- // wrap modes. We therefore find the nearest largest power of 2
- // unless width is already a power of 2
- if (!mHasNpot && (width & (width - 1)) != 0) {
- width = 1 << (32 - __builtin_clz(width));
- }
-
- bool hasAlpha = false;
- for (int i = 0; i < count; i++) {
- if (((colors[i] >> 24) & 0xff) < 255) {
- hasAlpha = true;
- break;
- }
- }
-
- info.width = min(width, uint32_t(mMaxTextureSize));
- info.hasAlpha = hasAlpha;
-}
-
-Texture* GradientCache::addLinearGradient(GradientCacheEntry& gradient, uint32_t* colors,
- float* positions, int count) {
- GradientInfo info;
- getGradientInfo(colors, count, info);
-
- Texture* texture = new Texture(Caches::getInstance());
- texture->blend = info.hasAlpha;
- texture->generation = 1;
-
- // Assume the cache is always big enough
- const uint32_t size = info.width * 2 * bytesPerPixel();
- while (getSize() + size > mMaxSize) {
- LOG_ALWAYS_FATAL_IF(!mCache.removeOldest(),
- "Ran out of things to remove from the cache? getSize() = %" PRIu32
- ", size = %" PRIu32 ", mMaxSize = %" PRIu32 ", width = %" PRIu32,
- getSize(), size, mMaxSize, info.width);
- }
-
- generateTexture(colors, positions, info.width, 2, texture);
-
- mSize += size;
- LOG_ALWAYS_FATAL_IF((int)size != texture->objectSize(),
- "size != texture->objectSize(), size %" PRIu32
- ", objectSize %d"
- " width = %" PRIu32 " bytesPerPixel() = %zu",
- size, texture->objectSize(), info.width, bytesPerPixel());
- mCache.put(gradient, texture);
-
- return texture;
-}
-
-size_t GradientCache::bytesPerPixel() const {
- // We use 4 channels (RGBA)
- return 4 * (mUseFloatTexture ? /* fp16 */ 2 : sizeof(uint8_t));
-}
-
-size_t GradientCache::sourceBytesPerPixel() const {
- // We use 4 channels (RGBA) and upload from floats (not half floats)
- return 4 * (mUseFloatTexture ? sizeof(float) : sizeof(uint8_t));
-}
-
-void GradientCache::mixBytes(const FloatColor& start, const FloatColor& end, float amount,
- uint8_t*& dst) const {
- float oppAmount = 1.0f - amount;
- float a = start.a * oppAmount + end.a * amount;
- *dst++ = uint8_t(OECF(start.r * oppAmount + end.r * amount) * 255.0f);
- *dst++ = uint8_t(OECF(start.g * oppAmount + end.g * amount) * 255.0f);
- *dst++ = uint8_t(OECF(start.b * oppAmount + end.b * amount) * 255.0f);
- *dst++ = uint8_t(a * 255.0f);
-}
-
-void GradientCache::mixFloats(const FloatColor& start, const FloatColor& end, float amount,
- uint8_t*& dst) const {
- float oppAmount = 1.0f - amount;
- float a = start.a * oppAmount + end.a * amount;
- float* d = (float*)dst;
-#ifdef ANDROID_ENABLE_LINEAR_BLENDING
- // We want to stay linear
- *d++ = (start.r * oppAmount + end.r * amount);
- *d++ = (start.g * oppAmount + end.g * amount);
- *d++ = (start.b * oppAmount + end.b * amount);
-#else
- *d++ = OECF(start.r * oppAmount + end.r * amount);
- *d++ = OECF(start.g * oppAmount + end.g * amount);
- *d++ = OECF(start.b * oppAmount + end.b * amount);
-#endif
- *d++ = a;
- dst += 4 * sizeof(float);
-}
-
-void GradientCache::generateTexture(uint32_t* colors, float* positions, const uint32_t width,
- const uint32_t height, Texture* texture) {
- const GLsizei rowBytes = width * sourceBytesPerPixel();
- uint8_t pixels[rowBytes * height];
-
- static ChannelMixer gMixers[] = {
- // colors are stored gamma-encoded
- &android::uirenderer::GradientCache::mixBytes,
- // colors are stored in linear (linear blending on)
- // or gamma-encoded (linear blending off)
- &android::uirenderer::GradientCache::mixFloats,
- };
- ChannelMixer mix = gMixers[mUseFloatTexture];
-
- FloatColor start;
- start.set(colors[0]);
-
- FloatColor end;
- end.set(colors[1]);
-
- int currentPos = 1;
- float startPos = positions[0];
- float distance = positions[1] - startPos;
-
- uint8_t* dst = pixels;
- for (uint32_t x = 0; x < width; x++) {
- float pos = x / float(width - 1);
- if (pos > positions[currentPos]) {
- start = end;
- startPos = positions[currentPos];
-
- currentPos++;
-
- end.set(colors[currentPos]);
- distance = positions[currentPos] - startPos;
- }
-
- float amount = (pos - startPos) / distance;
- (this->*mix)(start, end, amount, dst);
- }
-
- memcpy(pixels + rowBytes, pixels, rowBytes);
-
- if (mUseFloatTexture) {
- texture->upload(GL_RGBA16F, width, height, GL_RGBA, GL_FLOAT, pixels);
- } else {
- GLint internalFormat = mHasLinearBlending ? GL_SRGB8_ALPHA8 : GL_RGBA;
- texture->upload(internalFormat, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
- }
-
- texture->setFilter(GL_LINEAR);
- texture->setWrap(GL_CLAMP_TO_EDGE);
-}
-
-}; // namespace uirenderer
-}; // namespace android
diff --git a/libs/hwui/GradientCache.h b/libs/hwui/GradientCache.h
deleted file mode 100644
index ff426cd..0000000
--- a/libs/hwui/GradientCache.h
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HWUI_GRADIENT_CACHE_H
-#define ANDROID_HWUI_GRADIENT_CACHE_H
-
-#include <memory>
-
-#include <GLES3/gl3.h>
-
-#include <SkShader.h>
-
-#include <utils/LruCache.h>
-#include <utils/Mutex.h>
-
-#include "FloatColor.h"
-
-namespace android {
-namespace uirenderer {
-
-class Texture;
-
-struct GradientCacheEntry {
- GradientCacheEntry() {
- count = 0;
- colors = nullptr;
- positions = nullptr;
- }
-
- GradientCacheEntry(uint32_t* colors, float* positions, uint32_t count) {
- copy(colors, positions, count);
- }
-
- GradientCacheEntry(const GradientCacheEntry& entry) {
- copy(entry.colors.get(), entry.positions.get(), entry.count);
- }
-
- GradientCacheEntry& operator=(const GradientCacheEntry& entry) {
- if (this != &entry) {
- copy(entry.colors.get(), entry.positions.get(), entry.count);
- }
-
- return *this;
- }
-
- hash_t hash() const;
-
- static int compare(const GradientCacheEntry& lhs, const GradientCacheEntry& rhs);
-
- bool operator==(const GradientCacheEntry& other) const { return compare(*this, other) == 0; }
-
- bool operator!=(const GradientCacheEntry& other) const { return compare(*this, other) != 0; }
-
- std::unique_ptr<uint32_t[]> colors;
- std::unique_ptr<float[]> positions;
- uint32_t count;
-
-private:
- void copy(uint32_t* colors, float* positions, uint32_t count) {
- this->count = count;
- this->colors.reset(new uint32_t[count]);
- this->positions.reset(new float[count]);
-
- memcpy(this->colors.get(), colors, count * sizeof(uint32_t));
- memcpy(this->positions.get(), positions, count * sizeof(float));
- }
-
-}; // GradientCacheEntry
-
-// Caching support
-
-inline int strictly_order_type(const GradientCacheEntry& lhs, const GradientCacheEntry& rhs) {
- return GradientCacheEntry::compare(lhs, rhs) < 0;
-}
-
-inline int compare_type(const GradientCacheEntry& lhs, const GradientCacheEntry& rhs) {
- return GradientCacheEntry::compare(lhs, rhs);
-}
-
-inline hash_t hash_type(const GradientCacheEntry& entry) {
- return entry.hash();
-}
-
-/**
- * A simple LRU gradient cache. The cache has a maximum size expressed in bytes.
- * Any texture added to the cache causing the cache to grow beyond the maximum
- * allowed size will also cause the oldest texture to be kicked out.
- */
-class GradientCache : public OnEntryRemoved<GradientCacheEntry, Texture*> {
-public:
- explicit GradientCache(const Extensions& extensions);
- ~GradientCache();
-
- /**
- * Used as a callback when an entry is removed from the cache.
- * Do not invoke directly.
- */
- void operator()(GradientCacheEntry& shader, Texture*& texture) override;
-
- /**
- * Returns the texture associated with the specified shader.
- */
- Texture* get(uint32_t* colors, float* positions, int count);
-
- /**
- * Clears the cache. This causes all textures to be deleted.
- */
- void clear();
-
- /**
- * Returns the maximum size of the cache in bytes.
- */
- uint32_t getMaxSize();
- /**
- * Returns the current size of the cache in bytes.
- */
- uint32_t getSize();
-
-private:
- /**
- * Adds a new linear gradient to the cache. The generated texture is
- * returned.
- */
- Texture* addLinearGradient(GradientCacheEntry& gradient, uint32_t* colors, float* positions,
- int count);
-
- void generateTexture(uint32_t* colors, float* positions, const uint32_t width,
- const uint32_t height, Texture* texture);
-
- struct GradientInfo {
- uint32_t width;
- bool hasAlpha;
- };
-
- void getGradientInfo(const uint32_t* colors, const int count, GradientInfo& info);
-
- size_t bytesPerPixel() const;
- size_t sourceBytesPerPixel() const;
-
- typedef void (GradientCache::*ChannelMixer)(const FloatColor& start, const FloatColor& end,
- float amount, uint8_t*& dst) const;
-
- void mixBytes(const FloatColor& start, const FloatColor& end, float amount,
- uint8_t*& dst) const;
- void mixFloats(const FloatColor& start, const FloatColor& end, float amount,
- uint8_t*& dst) const;
-
- LruCache<GradientCacheEntry, Texture*> mCache;
-
- uint32_t mSize;
- const uint32_t mMaxSize;
-
- GLint mMaxTextureSize;
- bool mUseFloatTexture;
- bool mHasNpot;
- bool mHasLinearBlending;
-
- mutable Mutex mLock;
-}; // class GradientCache
-
-}; // namespace uirenderer
-}; // namespace android
-
-#endif // ANDROID_HWUI_GRADIENT_CACHE_H
diff --git a/libs/hwui/PatchCache.cpp b/libs/hwui/PatchCache.cpp
deleted file mode 100644
index 673d73c..0000000
--- a/libs/hwui/PatchCache.cpp
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <utils/JenkinsHash.h>
-#include <utils/Log.h>
-
-#include "Caches.h"
-#include "Patch.h"
-#include "PatchCache.h"
-#include "Properties.h"
-#include "renderstate/RenderState.h"
-
-namespace android {
-namespace uirenderer {
-
-///////////////////////////////////////////////////////////////////////////////
-// Constructors/destructor
-///////////////////////////////////////////////////////////////////////////////
-
-PatchCache::PatchCache(RenderState& renderState)
- : mRenderState(renderState)
- , mMaxSize(KB(128))
- , mSize(0)
- , mCache(LruCache<PatchDescription, Patch*>::kUnlimitedCapacity)
- , mMeshBuffer(0)
- , mFreeBlocks(nullptr) {}
-
-PatchCache::~PatchCache() {
- clear();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Caching
-///////////////////////////////////////////////////////////////////////////////
-
-hash_t PatchCache::PatchDescription::hash() const {
- uint32_t hash = JenkinsHashMix(0, android::hash_type(mPatch));
- hash = JenkinsHashMix(hash, mBitmapWidth);
- hash = JenkinsHashMix(hash, mBitmapHeight);
- hash = JenkinsHashMix(hash, mPixelWidth);
- hash = JenkinsHashMix(hash, mPixelHeight);
- return JenkinsHashWhiten(hash);
-}
-
-int PatchCache::PatchDescription::compare(const PatchCache::PatchDescription& lhs,
- const PatchCache::PatchDescription& rhs) {
- return memcmp(&lhs, &rhs, sizeof(PatchDescription));
-}
-
-void PatchCache::clear() {
- clearCache();
-
- if (mMeshBuffer) {
- mRenderState.meshState().deleteMeshBuffer(mMeshBuffer);
- mMeshBuffer = 0;
- mSize = 0;
- }
-}
-
-void PatchCache::clearCache() {
- LruCache<PatchDescription, Patch*>::Iterator i(mCache);
- while (i.next()) {
- delete i.value();
- }
- mCache.clear();
-
- BufferBlock* block = mFreeBlocks;
- while (block) {
- BufferBlock* next = block->next;
- delete block;
- block = next;
- }
- mFreeBlocks = nullptr;
-}
-
-void PatchCache::remove(Vector<patch_pair_t>& patchesToRemove, Res_png_9patch* patch) {
- LruCache<PatchDescription, Patch*>::Iterator i(mCache);
- while (i.next()) {
- const PatchDescription& key = i.key();
- if (key.getPatch() == patch) {
- patchesToRemove.push(patch_pair_t(&key, i.value()));
- }
- }
-}
-
-void PatchCache::removeDeferred(Res_png_9patch* patch) {
- Mutex::Autolock _l(mLock);
-
- // Assert that patch is not already garbage
- size_t count = mGarbage.size();
- for (size_t i = 0; i < count; i++) {
- if (patch == mGarbage[i]) {
- patch = nullptr;
- break;
- }
- }
- LOG_ALWAYS_FATAL_IF(patch == nullptr);
-
- mGarbage.push(patch);
-}
-
-void PatchCache::clearGarbage() {
- Vector<patch_pair_t> patchesToRemove;
-
- { // scope for the mutex
- Mutex::Autolock _l(mLock);
- size_t count = mGarbage.size();
- for (size_t i = 0; i < count; i++) {
- Res_png_9patch* patch = mGarbage[i];
- remove(patchesToRemove, patch);
- // A Res_png_9patch is actually an array of byte that's larger
- // than sizeof(Res_png_9patch). It must be freed as an array.
- delete[](int8_t*) patch;
- }
- mGarbage.clear();
- }
-
- // TODO: We could sort patchesToRemove by offset to merge
- // adjacent free blocks
- for (size_t i = 0; i < patchesToRemove.size(); i++) {
- const patch_pair_t& pair = patchesToRemove[i];
-
- // Release the patch and mark the space in the free list
- Patch* patch = pair.getSecond();
- BufferBlock* block = new BufferBlock(patch->positionOffset, patch->getSize());
- block->next = mFreeBlocks;
- mFreeBlocks = block;
-
- mSize -= patch->getSize();
-
- mCache.remove(*pair.getFirst());
- delete patch;
- }
-
-#if DEBUG_PATCHES
- if (patchesToRemove.size() > 0) {
- dumpFreeBlocks("Removed garbage");
- }
-#endif
-}
-
-void PatchCache::createVertexBuffer() {
- mRenderState.meshState().genOrUpdateMeshBuffer(&mMeshBuffer, mMaxSize, nullptr,
- GL_DYNAMIC_DRAW);
- mSize = 0;
- mFreeBlocks = new BufferBlock(0, mMaxSize);
-}
-
-/**
- * Sets the mesh's offsets and copies its associated vertices into
- * the mesh buffer (VBO).
- */
-void PatchCache::setupMesh(Patch* newMesh) {
- // This call ensures the VBO exists and that it is bound
- if (!mMeshBuffer) {
- createVertexBuffer();
- }
-
- // If we're running out of space, let's clear the entire cache
- uint32_t size = newMesh->getSize();
- if (mSize + size > mMaxSize) {
- clearCache();
- createVertexBuffer();
- }
-
- // Find a block where we can fit the mesh
- BufferBlock* previous = nullptr;
- BufferBlock* block = mFreeBlocks;
- while (block) {
- // The mesh fits
- if (block->size >= size) {
- break;
- }
- previous = block;
- block = block->next;
- }
-
- // We have enough space left in the buffer, but it's
- // too fragmented, let's clear the cache
- if (!block) {
- clearCache();
- createVertexBuffer();
- previous = nullptr;
- block = mFreeBlocks;
- }
-
- // Copy the 9patch mesh in the VBO
- newMesh->positionOffset = (GLintptr)(block->offset);
- newMesh->textureOffset = newMesh->positionOffset + kMeshTextureOffset;
-
- mRenderState.meshState().updateMeshBufferSubData(mMeshBuffer, newMesh->positionOffset, size,
- newMesh->vertices.get());
-
- // Remove the block since we've used it entirely
- if (block->size == size) {
- if (previous) {
- previous->next = block->next;
- } else {
- mFreeBlocks = block->next;
- }
- delete block;
- } else {
- // Resize the block now that it's occupied
- block->offset += size;
- block->size -= size;
- }
-
- mSize += size;
-}
-
-static const UvMapper sIdentity;
-
-const Patch* PatchCache::get(const uint32_t bitmapWidth, const uint32_t bitmapHeight,
- const float pixelWidth, const float pixelHeight,
- const Res_png_9patch* patch) {
- const PatchDescription description(bitmapWidth, bitmapHeight, pixelWidth, pixelHeight, patch);
- const Patch* mesh = mCache.get(description);
-
- if (!mesh) {
- Patch* newMesh =
- new Patch(bitmapWidth, bitmapHeight, pixelWidth, pixelHeight, sIdentity, patch);
-
- if (newMesh->vertices) {
- setupMesh(newMesh);
- }
-
-#if DEBUG_PATCHES
- dumpFreeBlocks("Adding patch");
-#endif
-
- mCache.put(description, newMesh);
- return newMesh;
- }
-
- return mesh;
-}
-
-#if DEBUG_PATCHES
-void PatchCache::dumpFreeBlocks(const char* prefix) {
- String8 dump;
- BufferBlock* block = mFreeBlocks;
- while (block) {
- dump.appendFormat("->(%d, %d)", block->positionOffset, block->size);
- block = block->next;
- }
- ALOGD("%s: Free blocks%s", prefix, dump.string());
-}
-#endif
-
-}; // namespace uirenderer
-}; // namespace android
diff --git a/libs/hwui/PatchCache.h b/libs/hwui/PatchCache.h
deleted file mode 100644
index 273c3f5..0000000
--- a/libs/hwui/PatchCache.h
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <GLES2/gl2.h>
-
-#include <utils/LruCache.h>
-
-#include <androidfw/ResourceTypes.h>
-
-#include "Debug.h"
-#include "utils/Pair.h"
-
-namespace android {
-namespace uirenderer {
-
-class Patch;
-
-///////////////////////////////////////////////////////////////////////////////
-// Defines
-///////////////////////////////////////////////////////////////////////////////
-
-// Debug
-#if DEBUG_PATCHES
-#define PATCH_LOGD(...) ALOGD(__VA_ARGS__)
-#else
-#define PATCH_LOGD(...)
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-// Cache
-///////////////////////////////////////////////////////////////////////////////
-
-class Caches;
-class RenderState;
-
-class PatchCache {
-public:
- explicit PatchCache(RenderState& renderState);
- ~PatchCache();
-
- const Patch* get(const uint32_t bitmapWidth, const uint32_t bitmapHeight,
- const float pixelWidth, const float pixelHeight, const Res_png_9patch* patch);
- void clear();
-
- uint32_t getSize() const { return mSize; }
-
- uint32_t getMaxSize() const { return mMaxSize; }
-
- GLuint getMeshBuffer() const { return mMeshBuffer; }
-
- /**
- * Removes the entries associated with the specified 9-patch. This is meant
- * to be called from threads that are not the EGL context thread (GC thread
- * on the VM side for instance.)
- */
- void removeDeferred(Res_png_9patch* patch);
-
- /**
- * Process deferred removals.
- */
- void clearGarbage();
-
-private:
- struct PatchDescription {
- PatchDescription()
- : mPatch(nullptr)
- , mBitmapWidth(0)
- , mBitmapHeight(0)
- , mPixelWidth(0)
- , mPixelHeight(0) {}
-
- PatchDescription(const uint32_t bitmapWidth, const uint32_t bitmapHeight,
- const float pixelWidth, const float pixelHeight,
- const Res_png_9patch* patch)
- : mPatch(patch)
- , mBitmapWidth(bitmapWidth)
- , mBitmapHeight(bitmapHeight)
- , mPixelWidth(pixelWidth)
- , mPixelHeight(pixelHeight) {}
-
- hash_t hash() const;
-
- const Res_png_9patch* getPatch() const { return mPatch; }
-
- static int compare(const PatchDescription& lhs, const PatchDescription& rhs);
-
- bool operator==(const PatchDescription& other) const { return compare(*this, other) == 0; }
-
- bool operator!=(const PatchDescription& other) const { return compare(*this, other) != 0; }
-
- friend inline int strictly_order_type(const PatchDescription& lhs,
- const PatchDescription& rhs) {
- return PatchDescription::compare(lhs, rhs) < 0;
- }
-
- friend inline int compare_type(const PatchDescription& lhs, const PatchDescription& rhs) {
- return PatchDescription::compare(lhs, rhs);
- }
-
- friend inline hash_t hash_type(const PatchDescription& entry) { return entry.hash(); }
-
- private:
- const Res_png_9patch* mPatch;
- uint32_t mBitmapWidth;
- uint32_t mBitmapHeight;
- float mPixelWidth;
- float mPixelHeight;
-
- }; // struct PatchDescription
-
- /**
- * A buffer block represents an empty range in the mesh buffer
- * that can be used to store vertices.
- *
- * The patch cache maintains a linked-list of buffer blocks
- * to track available regions of memory in the VBO.
- */
- struct BufferBlock {
- BufferBlock(uint32_t offset, uint32_t size) : offset(offset), size(size), next(nullptr) {}
-
- uint32_t offset;
- uint32_t size;
-
- BufferBlock* next;
- }; // struct BufferBlock
-
- typedef Pair<const PatchDescription*, Patch*> patch_pair_t;
-
- void clearCache();
- void createVertexBuffer();
-
- void setupMesh(Patch* newMesh);
-
- void remove(Vector<patch_pair_t>& patchesToRemove, Res_png_9patch* patch);
-
-#if DEBUG_PATCHES
- void dumpFreeBlocks(const char* prefix);
-#endif
-
- RenderState& mRenderState;
- const uint32_t mMaxSize;
- uint32_t mSize;
-
- LruCache<PatchDescription, Patch*> mCache;
-
- GLuint mMeshBuffer;
- // First available free block inside the mesh buffer
- BufferBlock* mFreeBlocks;
-
- // Garbage tracking, required to handle GC events on the VM side
- Vector<Res_png_9patch*> mGarbage;
- mutable Mutex mLock;
-}; // class PatchCache
-
-}; // namespace uirenderer
-}; // namespace android
diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp
deleted file mode 100644
index e67c5bd..0000000
--- a/libs/hwui/PathCache.cpp
+++ /dev/null
@@ -1,559 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <SkBitmap.h>
-#include <SkCanvas.h>
-#include <SkColor.h>
-#include <SkColorFilter.h>
-#include <SkMaskFilter.h>
-#include <SkPaint.h>
-#include <SkPath.h>
-#include <SkPathEffect.h>
-#include <SkRect.h>
-
-#include <utils/JenkinsHash.h>
-#include <utils/Trace.h>
-
-#include "Caches.h"
-#include "PathCache.h"
-
-#include "thread/Signal.h"
-#include "thread/TaskProcessor.h"
-
-#include <cutils/properties.h>
-
-namespace android {
-namespace uirenderer {
-
-static constexpr size_t PATH_CACHE_COUNT_LIMIT = 256;
-
-template <class T>
-static bool compareWidthHeight(const T& lhs, const T& rhs) {
- return (lhs.mWidth == rhs.mWidth) && (lhs.mHeight == rhs.mHeight);
-}
-
-static bool compareRoundRects(const PathDescription::Shape::RoundRect& lhs,
- const PathDescription::Shape::RoundRect& rhs) {
- return compareWidthHeight(lhs, rhs) && lhs.mRx == rhs.mRx && lhs.mRy == rhs.mRy;
-}
-
-static bool compareArcs(const PathDescription::Shape::Arc& lhs,
- const PathDescription::Shape::Arc& rhs) {
- return compareWidthHeight(lhs, rhs) && lhs.mStartAngle == rhs.mStartAngle &&
- lhs.mSweepAngle == rhs.mSweepAngle && lhs.mUseCenter == rhs.mUseCenter;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Cache entries
-///////////////////////////////////////////////////////////////////////////////
-
-PathDescription::PathDescription()
- : type(ShapeType::None)
- , join(SkPaint::kDefault_Join)
- , cap(SkPaint::kDefault_Cap)
- , style(SkPaint::kFill_Style)
- , miter(4.0f)
- , strokeWidth(1.0f)
- , pathEffect(nullptr) {
- // Shape bits should be set to zeroes, because they are used for hash calculation.
- memset(&shape, 0, sizeof(Shape));
-}
-
-PathDescription::PathDescription(ShapeType type, const SkPaint* paint)
- : type(type)
- , join(paint->getStrokeJoin())
- , cap(paint->getStrokeCap())
- , style(paint->getStyle())
- , miter(paint->getStrokeMiter())
- , strokeWidth(paint->getStrokeWidth())
- , pathEffect(paint->getPathEffect()) {
- // Shape bits should be set to zeroes, because they are used for hash calculation.
- memset(&shape, 0, sizeof(Shape));
-}
-
-hash_t PathDescription::hash() const {
- uint32_t hash = JenkinsHashMix(0, static_cast<int>(type));
- hash = JenkinsHashMix(hash, join);
- hash = JenkinsHashMix(hash, cap);
- hash = JenkinsHashMix(hash, style);
- hash = JenkinsHashMix(hash, android::hash_type(miter));
- hash = JenkinsHashMix(hash, android::hash_type(strokeWidth));
- hash = JenkinsHashMix(hash, android::hash_type(pathEffect));
- hash = JenkinsHashMixBytes(hash, (uint8_t*)&shape, sizeof(Shape));
- return JenkinsHashWhiten(hash);
-}
-
-bool PathDescription::operator==(const PathDescription& rhs) const {
- if (type != rhs.type) return false;
- if (join != rhs.join) return false;
- if (cap != rhs.cap) return false;
- if (style != rhs.style) return false;
- if (miter != rhs.miter) return false;
- if (strokeWidth != rhs.strokeWidth) return false;
- if (pathEffect != rhs.pathEffect) return false;
- switch (type) {
- case ShapeType::None:
- return 0;
- case ShapeType::Rect:
- return compareWidthHeight(shape.rect, rhs.shape.rect);
- case ShapeType::RoundRect:
- return compareRoundRects(shape.roundRect, rhs.shape.roundRect);
- case ShapeType::Circle:
- return shape.circle.mRadius == rhs.shape.circle.mRadius;
- case ShapeType::Oval:
- return compareWidthHeight(shape.oval, rhs.shape.oval);
- case ShapeType::Arc:
- return compareArcs(shape.arc, rhs.shape.arc);
- case ShapeType::Path:
- return shape.path.mGenerationID == rhs.shape.path.mGenerationID;
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Utilities
-///////////////////////////////////////////////////////////////////////////////
-
-static void computePathBounds(const SkPath* path, const SkPaint* paint, PathTexture* texture,
- uint32_t& width, uint32_t& height) {
- const SkRect& bounds = path->getBounds();
- const float pathWidth = std::max(bounds.width(), 1.0f);
- const float pathHeight = std::max(bounds.height(), 1.0f);
-
- texture->left = floorf(bounds.fLeft);
- texture->top = floorf(bounds.fTop);
-
- texture->offset = (int)floorf(std::max(paint->getStrokeWidth(), 1.0f) * 1.5f + 0.5f);
-
- width = uint32_t(pathWidth + texture->offset * 2.0 + 0.5);
- height = uint32_t(pathHeight + texture->offset * 2.0 + 0.5);
-}
-
-static void initPaint(SkPaint& paint) {
- // Make sure the paint is opaque, color, alpha, filter, etc.
- // will be applied later when compositing the alpha8 texture
- paint.setColor(SK_ColorBLACK);
- paint.setAlpha(255);
- paint.setColorFilter(nullptr);
- paint.setMaskFilter(nullptr);
- paint.setShader(nullptr);
- paint.setBlendMode(SkBlendMode::kSrc);
-}
-
-static sk_sp<Bitmap> drawPath(const SkPath* path, const SkPaint* paint, PathTexture* texture,
- uint32_t maxTextureSize) {
- uint32_t width, height;
- computePathBounds(path, paint, texture, width, height);
- if (width > maxTextureSize || height > maxTextureSize) {
- ALOGW("Shape too large to be rendered into a texture (%dx%d, max=%dx%d)", width, height,
- maxTextureSize, maxTextureSize);
- return nullptr;
- }
-
- sk_sp<Bitmap> bitmap = Bitmap::allocateHeapBitmap(SkImageInfo::MakeA8(width, height));
- SkPaint pathPaint(*paint);
- initPaint(pathPaint);
-
- SkBitmap skBitmap;
- bitmap->getSkBitmap(&skBitmap);
- skBitmap.eraseColor(0);
- SkCanvas canvas(skBitmap);
- canvas.translate(-texture->left + texture->offset, -texture->top + texture->offset);
- canvas.drawPath(*path, pathPaint);
- return bitmap;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Cache constructor/destructor
-///////////////////////////////////////////////////////////////////////////////
-
-PathCache::PathCache()
- : mCache(LruCache<PathDescription, PathTexture*>::kUnlimitedCapacity)
- , mSize(0)
- , mMaxSize(DeviceInfo::multiplyByResolution(4)) {
- mCache.setOnEntryRemovedListener(this);
- mMaxTextureSize = DeviceInfo::get()->maxTextureSize();
- mDebugEnabled = Properties::debugLevel & kDebugCaches;
-}
-
-PathCache::~PathCache() {
- mCache.clear();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Size management
-///////////////////////////////////////////////////////////////////////////////
-
-uint32_t PathCache::getSize() {
- return mSize;
-}
-
-uint32_t PathCache::getMaxSize() {
- return mMaxSize;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Callbacks
-///////////////////////////////////////////////////////////////////////////////
-
-void PathCache::operator()(PathDescription& entry, PathTexture*& texture) {
- removeTexture(texture);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Caching
-///////////////////////////////////////////////////////////////////////////////
-
-void PathCache::removeTexture(PathTexture* texture) {
- if (texture) {
- const uint32_t size = texture->width() * texture->height();
-
- // If there is a pending task we must wait for it to return
- // before attempting our cleanup
- const sp<PathTask>& task = texture->task();
- if (task != nullptr) {
- task->getResult();
- texture->clearTask();
- } else {
- // If there is a pending task, the path was not added
- // to the cache and the size wasn't increased
- if (size > mSize) {
- ALOGE("Removing path texture of size %d will leave "
- "the cache in an inconsistent state",
- size);
- }
- mSize -= size;
- }
-
- PATH_LOGD("PathCache::delete name, size, mSize = %d, %d, %d", texture->id, size, mSize);
- if (mDebugEnabled) {
- ALOGD("Shape deleted, size = %d", size);
- }
-
- texture->deleteTexture();
- delete texture;
- }
-}
-
-void PathCache::purgeCache(uint32_t width, uint32_t height) {
- const uint32_t size = width * height;
- // Don't even try to cache a bitmap that's bigger than the cache
- if (size < mMaxSize) {
- while (mSize + size > mMaxSize) {
- mCache.removeOldest();
- }
- }
-}
-
-void PathCache::trim() {
- while (mSize > mMaxSize || mCache.size() > PATH_CACHE_COUNT_LIMIT) {
- LOG_ALWAYS_FATAL_IF(!mCache.size(),
- "Inconsistent mSize! Ran out of items to remove!"
- " mSize = %u, mMaxSize = %u",
- mSize, mMaxSize);
- mCache.removeOldest();
- }
-}
-
-PathTexture* PathCache::addTexture(const PathDescription& entry, const SkPath* path,
- const SkPaint* paint) {
- ATRACE_NAME("Generate Path Texture");
-
- PathTexture* texture = new PathTexture(Caches::getInstance(), path->getGenerationID());
- sk_sp<Bitmap> bitmap(drawPath(path, paint, texture, mMaxTextureSize));
- if (!bitmap) {
- delete texture;
- return nullptr;
- }
-
- purgeCache(bitmap->width(), bitmap->height());
- generateTexture(entry, *bitmap, texture);
- return texture;
-}
-
-void PathCache::generateTexture(const PathDescription& entry, Bitmap& bitmap, PathTexture* texture,
- bool addToCache) {
- generateTexture(bitmap, texture);
-
- // Note here that we upload to a texture even if it's bigger than mMaxSize.
- // Such an entry in mCache will only be temporary, since it will be evicted
- // immediately on trim, or on any other Path entering the cache.
- uint32_t size = texture->width() * texture->height();
- mSize += size;
- PATH_LOGD("PathCache::get/create: name, size, mSize = %d, %d, %d", texture->id, size, mSize);
- if (mDebugEnabled) {
- ALOGD("Shape created, size = %d", size);
- }
- if (addToCache) {
- mCache.put(entry, texture);
- }
-}
-
-void PathCache::clear() {
- mCache.clear();
-}
-
-void PathCache::generateTexture(Bitmap& bitmap, Texture* texture) {
- ATRACE_NAME("Upload Path Texture");
- texture->upload(bitmap);
- texture->setFilter(GL_LINEAR);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Path precaching
-///////////////////////////////////////////////////////////////////////////////
-
-PathCache::PathProcessor::PathProcessor(Caches& caches)
- : TaskProcessor<sk_sp<Bitmap> >(&caches.tasks), mMaxTextureSize(caches.maxTextureSize) {}
-
-void PathCache::PathProcessor::onProcess(const sp<Task<sk_sp<Bitmap> > >& task) {
- PathTask* t = static_cast<PathTask*>(task.get());
- ATRACE_NAME("pathPrecache");
-
- t->setResult(drawPath(&t->path, &t->paint, t->texture, mMaxTextureSize));
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Paths
-///////////////////////////////////////////////////////////////////////////////
-
-void PathCache::removeDeferred(const SkPath* path) {
- Mutex::Autolock l(mLock);
- mGarbage.push_back(path->getGenerationID());
-}
-
-void PathCache::clearGarbage() {
- Vector<PathDescription> pathsToRemove;
-
- { // scope for the mutex
- Mutex::Autolock l(mLock);
- for (const uint32_t generationID : mGarbage) {
- LruCache<PathDescription, PathTexture*>::Iterator iter(mCache);
- while (iter.next()) {
- const PathDescription& key = iter.key();
- if (key.type == ShapeType::Path && key.shape.path.mGenerationID == generationID) {
- pathsToRemove.push(key);
- }
- }
- }
- mGarbage.clear();
- }
-
- for (size_t i = 0; i < pathsToRemove.size(); i++) {
- mCache.remove(pathsToRemove.itemAt(i));
- }
-}
-
-PathTexture* PathCache::get(const SkPath* path, const SkPaint* paint) {
- PathDescription entry(ShapeType::Path, paint);
- entry.shape.path.mGenerationID = path->getGenerationID();
-
- PathTexture* texture = mCache.get(entry);
-
- if (!texture) {
- texture = addTexture(entry, path, paint);
- } else {
- // A bitmap is attached to the texture, this means we need to
- // upload it as a GL texture
- const sp<PathTask>& task = texture->task();
- if (task != nullptr) {
- // But we must first wait for the worker thread to be done
- // producing the bitmap, so let's wait
- sk_sp<Bitmap> bitmap = task->getResult();
- if (bitmap) {
- generateTexture(entry, *bitmap, texture, false);
- texture->clearTask();
- } else {
- texture->clearTask();
- texture = nullptr;
- mCache.remove(entry);
- }
- }
- }
-
- return texture;
-}
-
-void PathCache::remove(const SkPath* path, const SkPaint* paint) {
- PathDescription entry(ShapeType::Path, paint);
- entry.shape.path.mGenerationID = path->getGenerationID();
- mCache.remove(entry);
-}
-
-void PathCache::precache(const SkPath* path, const SkPaint* paint) {
- if (!Caches::getInstance().tasks.canRunTasks()) {
- return;
- }
-
- PathDescription entry(ShapeType::Path, paint);
- entry.shape.path.mGenerationID = path->getGenerationID();
-
- PathTexture* texture = mCache.get(entry);
-
- bool generate = false;
- if (!texture) {
- generate = true;
- }
-
- if (generate) {
- // It is important to specify the generation ID so we do not
- // attempt to precache the same path several times
- texture = new PathTexture(Caches::getInstance(), path->getGenerationID());
- sp<PathTask> task = new PathTask(path, paint, texture);
- texture->setTask(task);
-
- // During the precaching phase we insert path texture objects into
- // the cache that do not point to any GL texture. They are instead
- // treated as a task for the precaching worker thread. This is why
- // we do not check the cache limit when inserting these objects.
- // The conversion into GL texture will happen in get(), when a client
- // asks for a path texture. This is also when the cache limit will
- // be enforced.
- mCache.put(entry, texture);
-
- if (mProcessor == nullptr) {
- mProcessor = new PathProcessor(Caches::getInstance());
- }
- mProcessor->add(task);
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Rounded rects
-///////////////////////////////////////////////////////////////////////////////
-
-PathTexture* PathCache::getRoundRect(float width, float height, float rx, float ry,
- const SkPaint* paint) {
- PathDescription entry(ShapeType::RoundRect, paint);
- entry.shape.roundRect.mWidth = width;
- entry.shape.roundRect.mHeight = height;
- entry.shape.roundRect.mRx = rx;
- entry.shape.roundRect.mRy = ry;
-
- PathTexture* texture = get(entry);
-
- if (!texture) {
- SkPath path;
- SkRect r;
- r.set(0.0f, 0.0f, width, height);
- path.addRoundRect(r, rx, ry, SkPath::kCW_Direction);
-
- texture = addTexture(entry, &path, paint);
- }
-
- return texture;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Circles
-///////////////////////////////////////////////////////////////////////////////
-
-PathTexture* PathCache::getCircle(float radius, const SkPaint* paint) {
- PathDescription entry(ShapeType::Circle, paint);
- entry.shape.circle.mRadius = radius;
-
- PathTexture* texture = get(entry);
-
- if (!texture) {
- SkPath path;
- path.addCircle(radius, radius, radius, SkPath::kCW_Direction);
-
- texture = addTexture(entry, &path, paint);
- }
-
- return texture;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Ovals
-///////////////////////////////////////////////////////////////////////////////
-
-PathTexture* PathCache::getOval(float width, float height, const SkPaint* paint) {
- PathDescription entry(ShapeType::Oval, paint);
- entry.shape.oval.mWidth = width;
- entry.shape.oval.mHeight = height;
-
- PathTexture* texture = get(entry);
-
- if (!texture) {
- SkPath path;
- SkRect r;
- r.set(0.0f, 0.0f, width, height);
- path.addOval(r, SkPath::kCW_Direction);
-
- texture = addTexture(entry, &path, paint);
- }
-
- return texture;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Rects
-///////////////////////////////////////////////////////////////////////////////
-
-PathTexture* PathCache::getRect(float width, float height, const SkPaint* paint) {
- PathDescription entry(ShapeType::Rect, paint);
- entry.shape.rect.mWidth = width;
- entry.shape.rect.mHeight = height;
-
- PathTexture* texture = get(entry);
-
- if (!texture) {
- SkPath path;
- SkRect r;
- r.set(0.0f, 0.0f, width, height);
- path.addRect(r, SkPath::kCW_Direction);
-
- texture = addTexture(entry, &path, paint);
- }
-
- return texture;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Arcs
-///////////////////////////////////////////////////////////////////////////////
-
-PathTexture* PathCache::getArc(float width, float height, float startAngle, float sweepAngle,
- bool useCenter, const SkPaint* paint) {
- PathDescription entry(ShapeType::Arc, paint);
- entry.shape.arc.mWidth = width;
- entry.shape.arc.mHeight = height;
- entry.shape.arc.mStartAngle = startAngle;
- entry.shape.arc.mSweepAngle = sweepAngle;
- entry.shape.arc.mUseCenter = useCenter;
-
- PathTexture* texture = get(entry);
-
- if (!texture) {
- SkPath path;
- SkRect r;
- r.set(0.0f, 0.0f, width, height);
- if (useCenter) {
- path.moveTo(r.centerX(), r.centerY());
- }
- path.arcTo(r, startAngle, sweepAngle, !useCenter);
- if (useCenter) {
- path.close();
- }
-
- texture = addTexture(entry, &path, paint);
- }
-
- return texture;
-}
-
-}; // namespace uirenderer
-}; // namespace android
diff --git a/libs/hwui/PathCache.h b/libs/hwui/PathCache.h
deleted file mode 100644
index 28c8bbb..0000000
--- a/libs/hwui/PathCache.h
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HWUI_PATH_CACHE_H
-#define ANDROID_HWUI_PATH_CACHE_H
-
-#include "Debug.h"
-#include "Texture.h"
-#include "hwui/Bitmap.h"
-#include "thread/Task.h"
-#include "thread/TaskProcessor.h"
-#include "utils/Macros.h"
-#include "utils/Pair.h"
-
-#include <GLES2/gl2.h>
-#include <SkPaint.h>
-#include <SkPath.h>
-#include <utils/LruCache.h>
-#include <utils/Mutex.h>
-
-#include <vector>
-
-class SkCanvas;
-class SkPaint;
-struct SkRect;
-
-namespace android {
-namespace uirenderer {
-
-class Caches;
-///////////////////////////////////////////////////////////////////////////////
-// Defines
-///////////////////////////////////////////////////////////////////////////////
-
-// Debug
-#if DEBUG_PATHS
-#define PATH_LOGD(...) ALOGD(__VA_ARGS__)
-#else
-#define PATH_LOGD(...)
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-// Classes
-///////////////////////////////////////////////////////////////////////////////
-
-struct PathTexture;
-class PathTask : public Task<sk_sp<Bitmap>> {
-public:
- PathTask(const SkPath* path, const SkPaint* paint, PathTexture* texture)
- : path(*path), paint(*paint), texture(texture) {}
-
- // copied, since input path not guaranteed to survive for duration of task
- const SkPath path;
-
- // copied, since input paint may not be immutable
- const SkPaint paint;
- PathTexture* texture;
-};
-
-/**
- * Alpha texture used to represent a path.
- */
-struct PathTexture : public Texture {
- PathTexture(Caches& caches, int generation) : Texture(caches) { this->generation = generation; }
-
- ~PathTexture() { clearTask(); }
-
- /**
- * Left coordinate of the path bounds.
- */
- float left = 0;
- /**
- * Top coordinate of the path bounds.
- */
- float top = 0;
- /**
- * Offset to draw the path at the correct origin.
- */
- float offset = 0;
-
- sp<PathTask> task() const { return mTask; }
-
- void setTask(const sp<PathTask>& task) { mTask = task; }
-
- void clearTask() {
- if (mTask != nullptr) {
- mTask.clear();
- }
- }
-
-private:
- sp<PathTask> mTask;
-}; // struct PathTexture
-
-enum class ShapeType { None, Rect, RoundRect, Circle, Oval, Arc, Path };
-
-struct PathDescription {
- HASHABLE_TYPE(PathDescription);
- ShapeType type;
- SkPaint::Join join;
- SkPaint::Cap cap;
- SkPaint::Style style;
- float miter;
- float strokeWidth;
- SkPathEffect* pathEffect;
- union Shape {
- struct Path {
- uint32_t mGenerationID;
- } path;
- struct RoundRect {
- float mWidth;
- float mHeight;
- float mRx;
- float mRy;
- } roundRect;
- struct Circle {
- float mRadius;
- } circle;
- struct Oval {
- float mWidth;
- float mHeight;
- } oval;
- struct Rect {
- float mWidth;
- float mHeight;
- } rect;
- struct Arc {
- float mWidth;
- float mHeight;
- float mStartAngle;
- float mSweepAngle;
- bool mUseCenter;
- } arc;
- } shape;
-
- PathDescription();
- PathDescription(ShapeType shapeType, const SkPaint* paint);
-};
-
-/**
- * A simple LRU shape cache. The cache has a maximum size expressed in bytes.
- * Any texture added to the cache causing the cache to grow beyond the maximum
- * allowed size will also cause the oldest texture to be kicked out.
- */
-class PathCache : public OnEntryRemoved<PathDescription, PathTexture*> {
-public:
- PathCache();
- ~PathCache();
-
- /**
- * Used as a callback when an entry is removed from the cache.
- * Do not invoke directly.
- */
- void operator()(PathDescription& path, PathTexture*& texture) override;
-
- /**
- * Clears the cache. This causes all textures to be deleted.
- */
- void clear();
-
- /**
- * Returns the maximum size of the cache in bytes.
- */
- uint32_t getMaxSize();
- /**
- * Returns the current size of the cache in bytes.
- */
- uint32_t getSize();
-
- PathTexture* getRoundRect(float width, float height, float rx, float ry, const SkPaint* paint);
- PathTexture* getCircle(float radius, const SkPaint* paint);
- PathTexture* getOval(float width, float height, const SkPaint* paint);
- PathTexture* getRect(float width, float height, const SkPaint* paint);
- PathTexture* getArc(float width, float height, float startAngle, float sweepAngle,
- bool useCenter, const SkPaint* paint);
- PathTexture* get(const SkPath* path, const SkPaint* paint);
- void remove(const SkPath* path, const SkPaint* paint);
-
- /**
- * Removes the specified path. This is meant to be called from threads
- * that are not the EGL context thread.
- */
- ANDROID_API void removeDeferred(const SkPath* path);
- /**
- * Process deferred removals.
- */
- void clearGarbage();
- /**
- * Trims the contents of the cache, removing items until it's under its
- * specified limit.
- *
- * Trimming is used for caches that support pre-caching from a worker
- * thread. During pre-caching the maximum limit of the cache can be
- * exceeded for the duration of the frame. It is therefore required to
- * trim the cache at the end of the frame to keep the total amount of
- * memory used under control.
- */
- void trim();
-
- /**
- * Precaches the specified path using background threads.
- */
- void precache(const SkPath* path, const SkPaint* paint);
-
-private:
- PathTexture* addTexture(const PathDescription& entry, const SkPath* path, const SkPaint* paint);
-
- /**
- * Generates the texture from a bitmap into the specified texture structure.
- */
- void generateTexture(Bitmap& bitmap, Texture* texture);
- void generateTexture(const PathDescription& entry, Bitmap& bitmap, PathTexture* texture,
- bool addToCache = true);
-
- PathTexture* get(const PathDescription& entry) { return mCache.get(entry); }
-
- /**
- * Ensures there is enough space in the cache for a texture of the specified
- * dimensions.
- */
- void purgeCache(uint32_t width, uint32_t height);
-
- void removeTexture(PathTexture* texture);
-
- void init();
-
- class PathProcessor : public TaskProcessor<sk_sp<Bitmap>> {
- public:
- explicit PathProcessor(Caches& caches);
- ~PathProcessor() {}
-
- virtual void onProcess(const sp<Task<sk_sp<Bitmap>>>& task) override;
-
- private:
- uint32_t mMaxTextureSize;
- };
-
- LruCache<PathDescription, PathTexture*> mCache;
- uint32_t mSize;
- const uint32_t mMaxSize;
- GLuint mMaxTextureSize;
-
- bool mDebugEnabled;
-
- sp<PathProcessor> mProcessor;
-
- std::vector<uint32_t> mGarbage;
- mutable Mutex mLock;
-}; // class PathCache
-
-}; // namespace uirenderer
-}; // namespace android
-
-#endif // ANDROID_HWUI_PATH_CACHE_H
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
deleted file mode 100644
index 2839ed7..0000000
--- a/libs/hwui/ProgramCache.cpp
+++ /dev/null
@@ -1,865 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <utils/String8.h>
-
-#include "Caches.h"
-#include "ProgramCache.h"
-#include "Properties.h"
-
-namespace android {
-namespace uirenderer {
-
-///////////////////////////////////////////////////////////////////////////////
-// Defines
-///////////////////////////////////////////////////////////////////////////////
-
-#define MODULATE_OP_NO_MODULATE 0
-#define MODULATE_OP_MODULATE 1
-#define MODULATE_OP_MODULATE_A8 2
-
-#define STR(x) STR1(x)
-#define STR1(x) #x
-
-///////////////////////////////////////////////////////////////////////////////
-// Vertex shaders snippets
-///////////////////////////////////////////////////////////////////////////////
-
-const char* gVS_Header_Start =
- "#version 100\n"
- "attribute vec4 position;\n";
-const char* gVS_Header_Attributes_TexCoords = "attribute vec2 texCoords;\n";
-const char* gVS_Header_Attributes_Colors = "attribute vec4 colors;\n";
-const char* gVS_Header_Attributes_VertexAlphaParameters = "attribute float vtxAlpha;\n";
-const char* gVS_Header_Uniforms_TextureTransform = "uniform mat4 mainTextureTransform;\n";
-const char* gVS_Header_Uniforms =
- "uniform mat4 projection;\n"
- "uniform mat4 transform;\n";
-const char* gVS_Header_Uniforms_HasGradient = "uniform mat4 screenSpace;\n";
-const char* gVS_Header_Uniforms_HasBitmap =
- "uniform mat4 textureTransform;\n"
- "uniform mediump vec2 textureDimension;\n";
-const char* gVS_Header_Uniforms_HasRoundRectClip =
- "uniform mat4 roundRectInvTransform;\n"
- "uniform mediump vec4 roundRectInnerRectLTWH;\n"
- "uniform mediump float roundRectRadius;\n";
-const char* gVS_Header_Varyings_HasTexture = "varying highp vec2 outTexCoords;\n";
-const char* gVS_Header_Varyings_HasColors = "varying vec4 outColors;\n";
-const char* gVS_Header_Varyings_HasVertexAlpha = "varying float alpha;\n";
-const char* gVS_Header_Varyings_HasBitmap = "varying highp vec2 outBitmapTexCoords;\n";
-const char* gVS_Header_Varyings_HasGradient[6] = {
- // Linear
- "varying highp vec2 linear;\n", "varying float linear;\n",
-
- // Circular
- "varying highp vec2 circular;\n", "varying highp vec2 circular;\n",
-
- // Sweep
- "varying highp vec2 sweep;\n", "varying highp vec2 sweep;\n",
-};
-const char* gVS_Header_Varyings_HasRoundRectClip = "varying mediump vec2 roundRectPos;\n";
-const char* gVS_Main = "\nvoid main(void) {\n";
-const char* gVS_Main_OutTexCoords = " outTexCoords = texCoords;\n";
-const char* gVS_Main_OutColors = " outColors = colors;\n";
-const char* gVS_Main_OutTransformedTexCoords =
- " outTexCoords = (mainTextureTransform * vec4(texCoords, 0.0, 1.0)).xy;\n";
-const char* gVS_Main_OutGradient[6] = {
- // Linear
- " linear = vec2((screenSpace * position).x, 0.5);\n",
- " linear = (screenSpace * position).x;\n",
-
- // Circular
- " circular = (screenSpace * position).xy;\n",
- " circular = (screenSpace * position).xy;\n",
-
- // Sweep
- " sweep = (screenSpace * position).xy;\n", " sweep = (screenSpace * position).xy;\n"};
-const char* gVS_Main_OutBitmapTexCoords =
- " outBitmapTexCoords = (textureTransform * position).xy * textureDimension;\n";
-const char* gVS_Main_Position =
- " vec4 transformedPosition = projection * transform * position;\n"
- " gl_Position = transformedPosition;\n";
-
-const char* gVS_Main_VertexAlpha = " alpha = vtxAlpha;\n";
-
-const char* gVS_Main_HasRoundRectClip =
- " roundRectPos = ((roundRectInvTransform * transformedPosition).xy / roundRectRadius) - "
- "roundRectInnerRectLTWH.xy;\n";
-const char* gVS_Footer = "}\n\n";
-
-///////////////////////////////////////////////////////////////////////////////
-// Fragment shaders snippets
-///////////////////////////////////////////////////////////////////////////////
-
-const char* gFS_Header_Start = "#version 100\n";
-const char* gFS_Header_Extension_FramebufferFetch =
- "#extension GL_NV_shader_framebuffer_fetch : enable\n\n";
-const char* gFS_Header_Extension_ExternalTexture =
- "#extension GL_OES_EGL_image_external : require\n\n";
-const char* gFS_Header = "precision mediump float;\n\n";
-const char* gFS_Uniforms_Color = "uniform vec4 color;\n";
-const char* gFS_Uniforms_TextureSampler = "uniform sampler2D baseSampler;\n";
-const char* gFS_Uniforms_ExternalTextureSampler = "uniform samplerExternalOES baseSampler;\n";
-const char* gFS_Uniforms_GradientSampler[2] = {
- "uniform vec2 screenSize;\n"
- "uniform sampler2D gradientSampler;\n",
-
- "uniform vec2 screenSize;\n"
- "uniform vec4 startColor;\n"
- "uniform vec4 endColor;\n"};
-const char* gFS_Uniforms_BitmapSampler = "uniform sampler2D bitmapSampler;\n";
-const char* gFS_Uniforms_BitmapExternalSampler = "uniform samplerExternalOES bitmapSampler;\n";
-const char* gFS_Uniforms_ColorOp[3] = {
- // None
- "",
- // Matrix
- "uniform mat4 colorMatrix;\n"
- "uniform vec4 colorMatrixVector;\n",
- // PorterDuff
- "uniform vec4 colorBlend;\n"};
-
-const char* gFS_Uniforms_HasRoundRectClip =
- "uniform mediump vec4 roundRectInnerRectLTWH;\n"
- "uniform mediump float roundRectRadius;\n";
-
-const char* gFS_Uniforms_ColorSpaceConversion =
- // TODO: Should we use a 3D LUT to combine the matrix and transfer functions?
- // 32x32x32 fp16 LUTs (for scRGB output) are large and heavy to generate...
- "uniform mat3 colorSpaceMatrix;\n";
-
-const char* gFS_Uniforms_TransferFunction[4] = {
- // In this order: g, a, b, c, d, e, f
- // See ColorSpace::TransferParameters
- // We'll use hardware sRGB conversion as much as possible
- "", "uniform float transferFunction[7];\n", "uniform float transferFunction[5];\n",
- "uniform float transferFunctionGamma;\n"};
-
-const char* gFS_OETF[2] = {
- R"__SHADER__(
- vec4 OETF(const vec4 linear) {
- return linear;
- }
- )__SHADER__",
- // We expect linear data to be scRGB so we mirror the gamma function
- R"__SHADER__(
- vec4 OETF(const vec4 linear) {
- return vec4(sign(linear.rgb) * OETF_sRGB(abs(linear.rgb)), linear.a);
- }
- )__SHADER__"};
-
-const char* gFS_ColorConvert[3] = {
- // Just OETF
- R"__SHADER__(
- vec4 colorConvert(const vec4 color) {
- return OETF(color);
- }
- )__SHADER__",
- // Full color conversion for opaque bitmaps
- R"__SHADER__(
- vec4 colorConvert(const vec4 color) {
- return OETF(vec4(colorSpaceMatrix * EOTF_Parametric(color.rgb), color.a));
- }
- )__SHADER__",
- // Full color conversion for translucent bitmaps
- // Note: 0.5/256=0.0019
- R"__SHADER__(
- vec4 colorConvert(in vec4 color) {
- color.rgb /= color.a + 0.0019;
- color = OETF(vec4(colorSpaceMatrix * EOTF_Parametric(color.rgb), color.a));
- color.rgb *= color.a + 0.0019;
- return color;
- }
- )__SHADER__",
-};
-
-const char* gFS_sRGB_TransferFunctions = R"__SHADER__(
- float OETF_sRGB(const float linear) {
- // IEC 61966-2-1:1999
- return linear <= 0.0031308 ? linear * 12.92 : (pow(linear, 1.0 / 2.4) * 1.055) - 0.055;
- }
-
- vec3 OETF_sRGB(const vec3 linear) {
- return vec3(OETF_sRGB(linear.r), OETF_sRGB(linear.g), OETF_sRGB(linear.b));
- }
-
- float EOTF_sRGB(float srgb) {
- // IEC 61966-2-1:1999
- return srgb <= 0.04045 ? srgb / 12.92 : pow((srgb + 0.055) / 1.055, 2.4);
- }
-)__SHADER__";
-
-const char* gFS_TransferFunction[4] = {
- // Conversion done by the texture unit (sRGB)
- R"__SHADER__(
- vec3 EOTF_Parametric(const vec3 x) {
- return x;
- }
- )__SHADER__",
- // Full transfer function
- // TODO: We should probably use a 1D LUT (256x1 with texelFetch() since input is 8 bit)
- // TODO: That would cause 3 dependent texture fetches. Is it worth it?
- R"__SHADER__(
- float EOTF_Parametric(float x) {
- return x <= transferFunction[4]
- ? transferFunction[3] * x + transferFunction[6]
- : pow(transferFunction[1] * x + transferFunction[2], transferFunction[0])
- + transferFunction[5];
- }
-
- vec3 EOTF_Parametric(const vec3 x) {
- return vec3(EOTF_Parametric(x.r), EOTF_Parametric(x.g), EOTF_Parametric(x.b));
- }
- )__SHADER__",
- // Limited transfer function, e = f = 0.0
- R"__SHADER__(
- float EOTF_Parametric(float x) {
- return x <= transferFunction[4]
- ? transferFunction[3] * x
- : pow(transferFunction[1] * x + transferFunction[2], transferFunction[0]);
- }
-
- vec3 EOTF_Parametric(const vec3 x) {
- return vec3(EOTF_Parametric(x.r), EOTF_Parametric(x.g), EOTF_Parametric(x.b));
- }
- )__SHADER__",
- // Gamma transfer function, e = f = 0.0
- R"__SHADER__(
- vec3 EOTF_Parametric(const vec3 x) {
- return vec3(pow(x.r, transferFunctionGamma),
- pow(x.g, transferFunctionGamma),
- pow(x.b, transferFunctionGamma));
- }
- )__SHADER__"};
-
-// Dithering must be done in the quantization space
-// When we are writing to an sRGB framebuffer, we must do the following:
-// EOTF(OETF(color) + dither)
-// The dithering pattern is generated with a triangle noise generator in the range [-1.0,1.0]
-// TODO: Handle linear fp16 render targets
-const char* gFS_GradientFunctions = R"__SHADER__(
- float triangleNoise(const highp vec2 n) {
- highp vec2 p = fract(n * vec2(5.3987, 5.4421));
- p += dot(p.yx, p.xy + vec2(21.5351, 14.3137));
- highp float xy = p.x * p.y;
- return fract(xy * 95.4307) + fract(xy * 75.04961) - 1.0;
- }
-)__SHADER__";
-
-const char* gFS_GradientPreamble[2] = {
- // Linear framebuffer
- R"__SHADER__(
- vec4 dither(const vec4 color) {
- return color + (triangleNoise(gl_FragCoord.xy * screenSize.xy) / 255.0);
- }
- )__SHADER__",
- // sRGB framebuffer
- R"__SHADER__(
- vec4 dither(const vec4 color) {
- vec3 dithered = sqrt(color.rgb) + (triangleNoise(gl_FragCoord.xy * screenSize.xy) / 255.0);
- return vec4(dithered * dithered, color.a);
- }
- )__SHADER__",
-};
-
-// Uses luminance coefficients from Rec.709 to choose the appropriate gamma
-// The gamma() function assumes that bright text will be displayed on a dark
-// background and that dark text will be displayed on bright background
-// The gamma coefficient is chosen to thicken or thin the text accordingly
-// The dot product used to compute the luminance could be approximated with
-// a simple max(color.r, color.g, color.b)
-const char* gFS_Gamma_Preamble = R"__SHADER__(
- #define GAMMA (%.2f)
- #define GAMMA_INV (%.2f)
-
- float gamma(float a, const vec3 color) {
- float luminance = dot(color, vec3(0.2126, 0.7152, 0.0722));
- return pow(a, luminance < 0.5 ? GAMMA_INV : GAMMA);
- }
-)__SHADER__";
-
-const char* gFS_Main =
- "\nvoid main(void) {\n"
- " vec4 fragColor;\n";
-
-const char* gFS_Main_AddDither = " fragColor = dither(fragColor);\n";
-
-// General case
-const char* gFS_Main_FetchColor = " fragColor = color;\n";
-const char* gFS_Main_ModulateColor = " fragColor *= color.a;\n";
-const char* gFS_Main_ApplyVertexAlphaLinearInterp = " fragColor *= alpha;\n";
-const char* gFS_Main_ApplyVertexAlphaShadowInterp =
- // map alpha through shadow alpha sampler
- " fragColor *= texture2D(baseSampler, vec2(alpha, 0.5)).a;\n";
-const char* gFS_Main_FetchTexture[2] = {
- // Don't modulate
- " fragColor = colorConvert(texture2D(baseSampler, outTexCoords));\n",
- // Modulate
- " fragColor = color * colorConvert(texture2D(baseSampler, outTexCoords));\n"};
-const char* gFS_Main_FetchA8Texture[4] = {
- // Don't modulate
- " fragColor = texture2D(baseSampler, outTexCoords);\n",
- " fragColor = texture2D(baseSampler, outTexCoords);\n",
- // Modulate
- " fragColor = color * texture2D(baseSampler, outTexCoords).a;\n",
- " fragColor = color * gamma(texture2D(baseSampler, outTexCoords).a, color.rgb);\n",
-};
-const char* gFS_Main_FetchGradient[6] = {
- // Linear
- " vec4 gradientColor = texture2D(gradientSampler, linear);\n",
-
- " vec4 gradientColor = mix(startColor, endColor, clamp(linear, 0.0, 1.0));\n",
-
- // Circular
- " vec4 gradientColor = texture2D(gradientSampler, vec2(length(circular), 0.5));\n",
-
- " vec4 gradientColor = mix(startColor, endColor, clamp(length(circular), 0.0, 1.0));\n",
-
- // Sweep
- " highp float index = atan(sweep.y, sweep.x) * 0.15915494309; // inv(2 * PI)\n"
- " vec4 gradientColor = texture2D(gradientSampler, vec2(index - floor(index), 0.5));\n",
-
- " highp float index = atan(sweep.y, sweep.x) * 0.15915494309; // inv(2 * PI)\n"
- " vec4 gradientColor = mix(startColor, endColor, clamp(index - floor(index), 0.0, "
- "1.0));\n"};
-const char* gFS_Main_FetchBitmap =
- " vec4 bitmapColor = colorConvert(texture2D(bitmapSampler, outBitmapTexCoords));\n";
-const char* gFS_Main_FetchBitmapNpot =
- " vec4 bitmapColor = colorConvert(texture2D(bitmapSampler, "
- "wrap(outBitmapTexCoords)));\n";
-const char* gFS_Main_BlendShadersBG = " fragColor = blendShaders(gradientColor, bitmapColor)";
-const char* gFS_Main_BlendShadersGB = " fragColor = blendShaders(bitmapColor, gradientColor)";
-const char* gFS_Main_BlendShaders_Modulate[6] = {
- // Don't modulate
- ";\n", ";\n",
- // Modulate
- " * color.a;\n", " * color.a;\n",
- // Modulate with alpha 8 texture
- " * texture2D(baseSampler, outTexCoords).a;\n",
- " * gamma(texture2D(baseSampler, outTexCoords).a, color.rgb);\n",
-};
-const char* gFS_Main_GradientShader_Modulate[6] = {
- // Don't modulate
- " fragColor = gradientColor;\n", " fragColor = gradientColor;\n",
- // Modulate
- " fragColor = gradientColor * color.a;\n", " fragColor = gradientColor * color.a;\n",
- // Modulate with alpha 8 texture
- " fragColor = gradientColor * texture2D(baseSampler, outTexCoords).a;\n",
- " fragColor = gradientColor * gamma(texture2D(baseSampler, outTexCoords).a, "
- "gradientColor.rgb);\n",
-};
-const char* gFS_Main_BitmapShader_Modulate[6] = {
- // Don't modulate
- " fragColor = bitmapColor;\n", " fragColor = bitmapColor;\n",
- // Modulate
- " fragColor = bitmapColor * color.a;\n", " fragColor = bitmapColor * color.a;\n",
- // Modulate with alpha 8 texture
- " fragColor = bitmapColor * texture2D(baseSampler, outTexCoords).a;\n",
- " fragColor = bitmapColor * gamma(texture2D(baseSampler, outTexCoords).a, "
- "bitmapColor.rgb);\n",
-};
-const char* gFS_Main_FragColor = " gl_FragColor = fragColor;\n";
-const char* gFS_Main_FragColor_HasColors = " gl_FragColor *= outColors;\n";
-const char* gFS_Main_FragColor_Blend =
- " gl_FragColor = blendFramebuffer(fragColor, gl_LastFragColor);\n";
-const char* gFS_Main_FragColor_Blend_Swap =
- " gl_FragColor = blendFramebuffer(gl_LastFragColor, fragColor);\n";
-const char* gFS_Main_ApplyColorOp[3] = {
- // None
- "",
- // Matrix
- " fragColor.rgb /= (fragColor.a + 0.0019);\n" // un-premultiply
- " fragColor *= colorMatrix;\n"
- " fragColor += colorMatrixVector;\n"
- " fragColor.rgb *= (fragColor.a + 0.0019);\n", // re-premultiply
- // PorterDuff
- " fragColor = blendColors(colorBlend, fragColor);\n"};
-
-// Note: LTWH (left top width height) -> xyzw
-// roundRectPos is now divided by roundRectRadius in vertex shader
-// after we also subtract roundRectInnerRectLTWH.xy from roundRectPos
-const char* gFS_Main_FragColor_HasRoundRectClip =
- " mediump vec2 fragToLT = -roundRectPos;\n"
- " mediump vec2 fragFromRB = roundRectPos - roundRectInnerRectLTWH.zw;\n"
-
- // since distance is divided by radius, it's in [0;1] so precision is not an issue
- // this also lets us clamp(0.0, 1.0) instead of max() which is cheaper on GPUs
- " mediump vec2 dist = clamp(max(fragToLT, fragFromRB), 0.0, 1.0);\n"
- " mediump float linearDist = clamp(roundRectRadius - (length(dist) * roundRectRadius), "
- "0.0, 1.0);\n"
- " gl_FragColor *= linearDist;\n";
-
-const char* gFS_Main_DebugHighlight = " gl_FragColor.rgb = vec3(0.0, gl_FragColor.a, 0.0);\n";
-const char* gFS_Footer = "}\n\n";
-
-///////////////////////////////////////////////////////////////////////////////
-// PorterDuff snippets
-///////////////////////////////////////////////////////////////////////////////
-
-const char* gBlendOps[18] = {
- // Clear
- "return vec4(0.0, 0.0, 0.0, 0.0);\n",
- // Src
- "return src;\n",
- // Dst
- "return dst;\n",
- // SrcOver
- "return src + dst * (1.0 - src.a);\n",
- // DstOver
- "return dst + src * (1.0 - dst.a);\n",
- // SrcIn
- "return src * dst.a;\n",
- // DstIn
- "return dst * src.a;\n",
- // SrcOut
- "return src * (1.0 - dst.a);\n",
- // DstOut
- "return dst * (1.0 - src.a);\n",
- // SrcAtop
- "return vec4(src.rgb * dst.a + (1.0 - src.a) * dst.rgb, dst.a);\n",
- // DstAtop
- "return vec4(dst.rgb * src.a + (1.0 - dst.a) * src.rgb, src.a);\n",
- // Xor
- "return vec4(src.rgb * (1.0 - dst.a) + (1.0 - src.a) * dst.rgb, "
- "src.a + dst.a - 2.0 * src.a * dst.a);\n",
- // Plus
- "return min(src + dst, 1.0);\n",
- // Modulate
- "return src * dst;\n",
- // Screen
- "return src + dst - src * dst;\n",
- // Overlay
- "return clamp(vec4(mix("
- "2.0 * src.rgb * dst.rgb + src.rgb * (1.0 - dst.a) + dst.rgb * (1.0 - src.a), "
- "src.a * dst.a - 2.0 * (dst.a - dst.rgb) * (src.a - src.rgb) + src.rgb * (1.0 - dst.a) + "
- "dst.rgb * (1.0 - src.a), "
- "step(dst.a, 2.0 * dst.rgb)), "
- "src.a + dst.a - src.a * dst.a), 0.0, 1.0);\n",
- // Darken
- "return vec4(src.rgb * (1.0 - dst.a) + (1.0 - src.a) * dst.rgb + "
- "min(src.rgb * dst.a, dst.rgb * src.a), src.a + dst.a - src.a * dst.a);\n",
- // Lighten
- "return vec4(src.rgb * (1.0 - dst.a) + (1.0 - src.a) * dst.rgb + "
- "max(src.rgb * dst.a, dst.rgb * src.a), src.a + dst.a - src.a * dst.a);\n",
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// Constructors/destructors
-///////////////////////////////////////////////////////////////////////////////
-
-ProgramCache::ProgramCache(const Extensions& extensions)
- : mHasES3(extensions.getMajorGlVersion() >= 3)
- , mHasLinearBlending(extensions.hasLinearBlending()) {}
-
-ProgramCache::~ProgramCache() {
- clear();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Cache management
-///////////////////////////////////////////////////////////////////////////////
-
-void ProgramCache::clear() {
- PROGRAM_LOGD("Clearing program cache");
- mCache.clear();
-}
-
-Program* ProgramCache::get(const ProgramDescription& description) {
- programid key = description.key();
- if (key == (PROGRAM_KEY_TEXTURE | PROGRAM_KEY_A8_TEXTURE)) {
- // program for A8, unmodulated, texture w/o shader (black text/path textures) is equivalent
- // to standard texture program (bitmaps, patches). Consider them equivalent.
- key = PROGRAM_KEY_TEXTURE;
- }
-
- auto iter = mCache.find(key);
- Program* program = nullptr;
- if (iter == mCache.end()) {
- description.log("Could not find program");
- program = generateProgram(description, key);
- mCache[key] = std::unique_ptr<Program>(program);
- } else {
- program = iter->second.get();
- }
- return program;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Program generation
-///////////////////////////////////////////////////////////////////////////////
-
-Program* ProgramCache::generateProgram(const ProgramDescription& description, programid key) {
- String8 vertexShader = generateVertexShader(description);
- String8 fragmentShader = generateFragmentShader(description);
-
- return new Program(description, vertexShader.string(), fragmentShader.string());
-}
-
-static inline size_t gradientIndex(const ProgramDescription& description) {
- return description.gradientType * 2 + description.isSimpleGradient;
-}
-
-String8 ProgramCache::generateVertexShader(const ProgramDescription& description) {
- // Add attributes
- String8 shader(gVS_Header_Start);
- if (description.hasTexture || description.hasExternalTexture) {
- shader.append(gVS_Header_Attributes_TexCoords);
- }
- if (description.hasVertexAlpha) {
- shader.append(gVS_Header_Attributes_VertexAlphaParameters);
- }
- if (description.hasColors) {
- shader.append(gVS_Header_Attributes_Colors);
- }
- // Uniforms
- shader.append(gVS_Header_Uniforms);
- if (description.hasTextureTransform) {
- shader.append(gVS_Header_Uniforms_TextureTransform);
- }
- if (description.hasGradient) {
- shader.append(gVS_Header_Uniforms_HasGradient);
- }
- if (description.hasBitmap) {
- shader.append(gVS_Header_Uniforms_HasBitmap);
- }
- if (description.hasRoundRectClip) {
- shader.append(gVS_Header_Uniforms_HasRoundRectClip);
- }
- // Varyings
- if (description.hasTexture || description.hasExternalTexture) {
- shader.append(gVS_Header_Varyings_HasTexture);
- }
- if (description.hasVertexAlpha) {
- shader.append(gVS_Header_Varyings_HasVertexAlpha);
- }
- if (description.hasColors) {
- shader.append(gVS_Header_Varyings_HasColors);
- }
- if (description.hasGradient) {
- shader.append(gVS_Header_Varyings_HasGradient[gradientIndex(description)]);
- }
- if (description.hasBitmap) {
- shader.append(gVS_Header_Varyings_HasBitmap);
- }
- if (description.hasRoundRectClip) {
- shader.append(gVS_Header_Varyings_HasRoundRectClip);
- }
-
- // Begin the shader
- shader.append(gVS_Main);
- {
- if (description.hasTextureTransform) {
- shader.append(gVS_Main_OutTransformedTexCoords);
- } else if (description.hasTexture || description.hasExternalTexture) {
- shader.append(gVS_Main_OutTexCoords);
- }
- if (description.hasVertexAlpha) {
- shader.append(gVS_Main_VertexAlpha);
- }
- if (description.hasColors) {
- shader.append(gVS_Main_OutColors);
- }
- if (description.hasBitmap) {
- shader.append(gVS_Main_OutBitmapTexCoords);
- }
- // Output transformed position
- shader.append(gVS_Main_Position);
- if (description.hasGradient) {
- shader.append(gVS_Main_OutGradient[gradientIndex(description)]);
- }
- if (description.hasRoundRectClip) {
- shader.append(gVS_Main_HasRoundRectClip);
- }
- }
- // End the shader
- shader.append(gVS_Footer);
-
- PROGRAM_LOGD("*** Generated vertex shader:\n\n%s", shader.string());
-
- return shader;
-}
-
-static bool shaderOp(const ProgramDescription& description, String8& shader, const int modulateOp,
- const char** snippets) {
- int op = description.hasAlpha8Texture ? MODULATE_OP_MODULATE_A8 : modulateOp;
- op = op * 2 + description.hasGammaCorrection;
- shader.append(snippets[op]);
- return description.hasAlpha8Texture;
-}
-
-String8 ProgramCache::generateFragmentShader(const ProgramDescription& description) {
- String8 shader(gFS_Header_Start);
-
- const bool blendFramebuffer = description.framebufferMode >= SkBlendMode::kPlus;
- if (blendFramebuffer) {
- shader.append(gFS_Header_Extension_FramebufferFetch);
- }
- if (description.hasExternalTexture ||
- (description.hasBitmap && description.isShaderBitmapExternal)) {
- shader.append(gFS_Header_Extension_ExternalTexture);
- }
-
- shader.append(gFS_Header);
-
- // Varyings
- if (description.hasTexture || description.hasExternalTexture) {
- shader.append(gVS_Header_Varyings_HasTexture);
- }
- if (description.hasVertexAlpha) {
- shader.append(gVS_Header_Varyings_HasVertexAlpha);
- }
- if (description.hasColors) {
- shader.append(gVS_Header_Varyings_HasColors);
- }
- if (description.hasGradient) {
- shader.append(gVS_Header_Varyings_HasGradient[gradientIndex(description)]);
- }
- if (description.hasBitmap) {
- shader.append(gVS_Header_Varyings_HasBitmap);
- }
- if (description.hasRoundRectClip) {
- shader.append(gVS_Header_Varyings_HasRoundRectClip);
- }
-
- // Uniforms
- int modulateOp = MODULATE_OP_NO_MODULATE;
- const bool singleColor = !description.hasTexture && !description.hasExternalTexture &&
- !description.hasGradient && !description.hasBitmap;
-
- if (description.modulate || singleColor) {
- shader.append(gFS_Uniforms_Color);
- if (!singleColor) modulateOp = MODULATE_OP_MODULATE;
- }
- if (description.hasTexture || description.useShadowAlphaInterp) {
- shader.append(gFS_Uniforms_TextureSampler);
- } else if (description.hasExternalTexture) {
- shader.append(gFS_Uniforms_ExternalTextureSampler);
- }
- if (description.hasGradient) {
- shader.append(gFS_Uniforms_GradientSampler[description.isSimpleGradient]);
- }
- if (description.hasRoundRectClip) {
- shader.append(gFS_Uniforms_HasRoundRectClip);
- }
-
- if (description.hasGammaCorrection) {
- shader.appendFormat(gFS_Gamma_Preamble, Properties::textGamma,
- 1.0f / Properties::textGamma);
- }
-
- if (description.hasBitmap) {
- if (description.isShaderBitmapExternal) {
- shader.append(gFS_Uniforms_BitmapExternalSampler);
- } else {
- shader.append(gFS_Uniforms_BitmapSampler);
- }
- }
- shader.append(gFS_Uniforms_ColorOp[static_cast<int>(description.colorOp)]);
-
- if (description.hasColorSpaceConversion) {
- shader.append(gFS_Uniforms_ColorSpaceConversion);
- }
- shader.append(gFS_Uniforms_TransferFunction[static_cast<int>(description.transferFunction)]);
-
- // Generate required functions
- if (description.hasGradient && description.hasBitmap) {
- generateBlend(shader, "blendShaders", description.shadersMode);
- }
- if (description.colorOp == ProgramDescription::ColorFilterMode::Blend) {
- generateBlend(shader, "blendColors", description.colorMode);
- }
- if (blendFramebuffer) {
- generateBlend(shader, "blendFramebuffer", description.framebufferMode);
- }
- if (description.useShaderBasedWrap) {
- generateTextureWrap(shader, description.bitmapWrapS, description.bitmapWrapT);
- }
- if (description.hasGradient || description.hasLinearTexture ||
- description.hasColorSpaceConversion) {
- shader.append(gFS_sRGB_TransferFunctions);
- }
- if (description.hasBitmap || ((description.hasTexture || description.hasExternalTexture) &&
- !description.hasAlpha8Texture)) {
- shader.append(gFS_TransferFunction[static_cast<int>(description.transferFunction)]);
- shader.append(
- gFS_OETF[(description.hasLinearTexture || description.hasColorSpaceConversion) &&
- !mHasLinearBlending]);
- shader.append(gFS_ColorConvert[description.hasColorSpaceConversion
- ? 1 + description.hasTranslucentConversion
- : 0]);
- }
- if (description.hasGradient) {
- shader.append(gFS_GradientFunctions);
- shader.append(gFS_GradientPreamble[mHasLinearBlending]);
- }
-
- // Begin the shader
- shader.append(gFS_Main);
- {
- // Stores the result in fragColor directly
- if (description.hasTexture || description.hasExternalTexture) {
- if (description.hasAlpha8Texture) {
- if (!description.hasGradient && !description.hasBitmap) {
- shader.append(gFS_Main_FetchA8Texture[modulateOp * 2 +
- description.hasGammaCorrection]);
- }
- } else {
- shader.append(gFS_Main_FetchTexture[modulateOp]);
- }
- } else {
- if (!description.hasGradient && !description.hasBitmap) {
- shader.append(gFS_Main_FetchColor);
- }
- }
- if (description.hasGradient) {
- shader.append(gFS_Main_FetchGradient[gradientIndex(description)]);
- }
- if (description.hasBitmap) {
- if (!description.useShaderBasedWrap) {
- shader.append(gFS_Main_FetchBitmap);
- } else {
- shader.append(gFS_Main_FetchBitmapNpot);
- }
- }
- bool applyModulate = false;
- // Case when we have two shaders set
- if (description.hasGradient && description.hasBitmap) {
- if (description.isBitmapFirst) {
- shader.append(gFS_Main_BlendShadersBG);
- } else {
- shader.append(gFS_Main_BlendShadersGB);
- }
- applyModulate =
- shaderOp(description, shader, modulateOp, gFS_Main_BlendShaders_Modulate);
- } else {
- if (description.hasGradient) {
- applyModulate =
- shaderOp(description, shader, modulateOp, gFS_Main_GradientShader_Modulate);
- } else if (description.hasBitmap) {
- applyModulate =
- shaderOp(description, shader, modulateOp, gFS_Main_BitmapShader_Modulate);
- }
- }
-
- if (description.modulate && applyModulate) {
- shader.append(gFS_Main_ModulateColor);
- }
-
- // Apply the color op if needed
- shader.append(gFS_Main_ApplyColorOp[static_cast<int>(description.colorOp)]);
-
- if (description.hasVertexAlpha) {
- if (description.useShadowAlphaInterp) {
- shader.append(gFS_Main_ApplyVertexAlphaShadowInterp);
- } else {
- shader.append(gFS_Main_ApplyVertexAlphaLinearInterp);
- }
- }
-
- if (description.hasGradient) {
- shader.append(gFS_Main_AddDither);
- }
-
- // Output the fragment
- if (!blendFramebuffer) {
- shader.append(gFS_Main_FragColor);
- } else {
- shader.append(!description.swapSrcDst ? gFS_Main_FragColor_Blend
- : gFS_Main_FragColor_Blend_Swap);
- }
- if (description.hasColors) {
- shader.append(gFS_Main_FragColor_HasColors);
- }
- if (description.hasRoundRectClip) {
- shader.append(gFS_Main_FragColor_HasRoundRectClip);
- }
- if (description.hasDebugHighlight) {
- shader.append(gFS_Main_DebugHighlight);
- }
- }
- // End the shader
- shader.append(gFS_Footer);
-
-#if DEBUG_PROGRAMS
- PROGRAM_LOGD("*** Generated fragment shader:\n\n");
- printLongString(shader);
-#endif
-
- return shader;
-}
-
-void ProgramCache::generateBlend(String8& shader, const char* name, SkBlendMode mode) {
- shader.append("\nvec4 ");
- shader.append(name);
- shader.append("(vec4 src, vec4 dst) {\n");
- shader.append(" ");
- shader.append(gBlendOps[(int)mode]);
- shader.append("}\n");
-}
-
-void ProgramCache::generateTextureWrap(String8& shader, GLenum wrapS, GLenum wrapT) {
- shader.append("\nhighp vec2 wrap(highp vec2 texCoords) {\n");
- if (wrapS == GL_MIRRORED_REPEAT) {
- shader.append(" highp float xMod2 = mod(texCoords.x, 2.0);\n");
- shader.append(" if (xMod2 > 1.0) xMod2 = 2.0 - xMod2;\n");
- }
- if (wrapT == GL_MIRRORED_REPEAT) {
- shader.append(" highp float yMod2 = mod(texCoords.y, 2.0);\n");
- shader.append(" if (yMod2 > 1.0) yMod2 = 2.0 - yMod2;\n");
- }
- shader.append(" return vec2(");
- switch (wrapS) {
- case GL_CLAMP_TO_EDGE:
- shader.append("texCoords.x");
- break;
- case GL_REPEAT:
- shader.append("mod(texCoords.x, 1.0)");
- break;
- case GL_MIRRORED_REPEAT:
- shader.append("xMod2");
- break;
- }
- shader.append(", ");
- switch (wrapT) {
- case GL_CLAMP_TO_EDGE:
- shader.append("texCoords.y");
- break;
- case GL_REPEAT:
- shader.append("mod(texCoords.y, 1.0)");
- break;
- case GL_MIRRORED_REPEAT:
- shader.append("yMod2");
- break;
- }
- shader.append(");\n");
- shader.append("}\n");
-}
-
-void ProgramCache::printLongString(const String8& shader) const {
- ssize_t index = 0;
- ssize_t lastIndex = 0;
- const char* str = shader.string();
- while ((index = shader.find("\n", index)) > -1) {
- String8 line(str, index - lastIndex);
- if (line.length() == 0) line.append("\n");
- ALOGD("%s", line.string());
- index++;
- str += (index - lastIndex);
- lastIndex = index;
- }
-}
-
-}; // namespace uirenderer
-}; // namespace android
diff --git a/libs/hwui/ProgramCache.h b/libs/hwui/ProgramCache.h
deleted file mode 100644
index 488a499..0000000
--- a/libs/hwui/ProgramCache.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HWUI_PROGRAM_CACHE_H
-#define ANDROID_HWUI_PROGRAM_CACHE_H
-
-#include <utils/KeyedVector.h>
-#include <utils/Log.h>
-#include <utils/String8.h>
-#include <map>
-
-#include <GLES2/gl2.h>
-
-#include "Debug.h"
-#include "Program.h"
-
-namespace android {
-namespace uirenderer {
-
-///////////////////////////////////////////////////////////////////////////////
-// Cache
-///////////////////////////////////////////////////////////////////////////////
-
-/**
- * Generates and caches program. Programs are generated based on
- * ProgramDescriptions.
- */
-class ProgramCache {
-public:
- explicit ProgramCache(const Extensions& extensions);
- ~ProgramCache();
-
- Program* get(const ProgramDescription& description);
-
- void clear();
-
-private:
- Program* generateProgram(const ProgramDescription& description, programid key);
- String8 generateVertexShader(const ProgramDescription& description);
- String8 generateFragmentShader(const ProgramDescription& description);
- void generateBlend(String8& shader, const char* name, SkBlendMode mode);
- void generateTextureWrap(String8& shader, GLenum wrapS, GLenum wrapT);
-
- void printLongString(const String8& shader) const;
-
- std::map<programid, std::unique_ptr<Program>> mCache;
-
- const bool mHasES3;
- const bool mHasLinearBlending;
-}; // class ProgramCache
-
-}; // namespace uirenderer
-}; // namespace android
-
-#endif // ANDROID_HWUI_PROGRAM_CACHE_H
diff --git a/libs/hwui/RecordedOp.h b/libs/hwui/RecordedOp.h
index f514691..a8f105d 100644
--- a/libs/hwui/RecordedOp.h
+++ b/libs/hwui/RecordedOp.h
@@ -20,7 +20,6 @@
#include "Matrix.h"
#include "Rect.h"
#include "RenderNode.h"
-#include "TessellationCache.h"
#include "Vector.h"
#include "utils/LinearAllocator.h"
#include "utils/PaintUtils.h"
@@ -84,7 +83,6 @@
PRE_RENDER_OP_FN(EndUnclippedLayerOp) \
PRE_RENDER_OP_FN(VectorDrawableOp) \
\
- RENDER_ONLY_OP_FN(ShadowOp) \
RENDER_ONLY_OP_FN(LayerOp) \
RENDER_ONLY_OP_FN(CopyToLayerOp) \
RENDER_ONLY_OP_FN(CopyFromLayerOp) \
@@ -333,23 +331,6 @@
VectorDrawable::Tree* vectorDrawable;
};
-/**
- * Real-time, dynamic-lit shadow.
- *
- * Uses invalid/empty bounds and matrix since ShadowOp bounds aren't known at defer time,
- * and are resolved dynamically, and transform isn't needed.
- *
- * State construction handles these properties specially, ignoring matrix/bounds.
- */
-struct ShadowOp : RecordedOp {
- ShadowOp(sp<TessellationCache::ShadowTask>& shadowTask, float casterAlpha)
- : RecordedOp(RecordedOpId::ShadowOp, Rect(), Matrix4::identity(), nullptr, nullptr)
- , shadowTask(shadowTask)
- , casterAlpha(casterAlpha){};
- sp<TessellationCache::ShadowTask> shadowTask;
- const float casterAlpha;
-};
-
struct SimpleRectsOp : RecordedOp { // Filled, no AA (TODO: better name?)
SimpleRectsOp(BASE_PARAMS, Vertex* vertices, size_t vertexCount)
: SUPER(SimpleRectsOp), vertices(vertices), vertexCount(vertexCount) {}
diff --git a/libs/hwui/RenderBufferCache.cpp b/libs/hwui/RenderBufferCache.cpp
deleted file mode 100644
index 98010d8..0000000
--- a/libs/hwui/RenderBufferCache.cpp
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "RenderBufferCache.h"
-#include "Debug.h"
-#include "DeviceInfo.h"
-#include "Properties.h"
-
-#include <utils/Log.h>
-
-#include <cstdlib>
-
-namespace android {
-namespace uirenderer {
-
-///////////////////////////////////////////////////////////////////////////////
-// Defines
-///////////////////////////////////////////////////////////////////////////////
-
-// Debug
-#if DEBUG_RENDER_BUFFERS
-#define RENDER_BUFFER_LOGD(...) ALOGD(__VA_ARGS__)
-#else
-#define RENDER_BUFFER_LOGD(...)
-#endif
-
-static uint32_t calculateRboCacheSize() {
- // TODO: Do we need to use extensions().has4BitStencil() here?
- // The tuning guide recommends it, but all real devices are configured
- // with a larger cache than necessary by 4x, so keep the 2x for now regardless
- return DeviceInfo::multiplyByResolution(2);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Constructors/destructor
-///////////////////////////////////////////////////////////////////////////////
-
-RenderBufferCache::RenderBufferCache() : mSize(0), mMaxSize(calculateRboCacheSize()) {}
-
-RenderBufferCache::~RenderBufferCache() {
- clear();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Size management
-///////////////////////////////////////////////////////////////////////////////
-
-uint32_t RenderBufferCache::getSize() {
- return mSize;
-}
-
-uint32_t RenderBufferCache::getMaxSize() {
- return mMaxSize;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Caching
-///////////////////////////////////////////////////////////////////////////////
-
-int RenderBufferCache::RenderBufferEntry::compare(const RenderBufferCache::RenderBufferEntry& lhs,
- const RenderBufferCache::RenderBufferEntry& rhs) {
- int deltaInt = int(lhs.mWidth) - int(rhs.mWidth);
- if (deltaInt != 0) return deltaInt;
-
- deltaInt = int(lhs.mHeight) - int(rhs.mHeight);
- if (deltaInt != 0) return deltaInt;
-
- return int(lhs.mFormat) - int(rhs.mFormat);
-}
-
-void RenderBufferCache::deleteBuffer(RenderBuffer* buffer) {
- if (buffer) {
- RENDER_BUFFER_LOGD("Deleted %s render buffer (%dx%d)",
- RenderBuffer::formatName(buffer->getFormat()), buffer->getWidth(),
- buffer->getHeight());
-
- mSize -= buffer->getSize();
- delete buffer;
- }
-}
-
-void RenderBufferCache::clear() {
- for (auto entry : mCache) {
- deleteBuffer(entry.mBuffer);
- }
- mCache.clear();
-}
-
-RenderBuffer* RenderBufferCache::get(GLenum format, const uint32_t width, const uint32_t height) {
- RenderBuffer* buffer = nullptr;
-
- RenderBufferEntry entry(format, width, height);
- auto iter = mCache.find(entry);
-
- if (iter != mCache.end()) {
- entry = *iter;
- mCache.erase(iter);
-
- buffer = entry.mBuffer;
- mSize -= buffer->getSize();
-
- RENDER_BUFFER_LOGD("Found %s render buffer (%dx%d)", RenderBuffer::formatName(format),
- width, height);
- } else {
- buffer = new RenderBuffer(format, width, height);
-
- RENDER_BUFFER_LOGD("Created new %s render buffer (%dx%d)", RenderBuffer::formatName(format),
- width, height);
- }
-
- buffer->bind();
- buffer->allocate();
-
- return buffer;
-}
-
-bool RenderBufferCache::put(RenderBuffer* buffer) {
- if (!buffer) return false;
-
- const uint32_t size = buffer->getSize();
- if (size < mMaxSize) {
- while (mSize + size > mMaxSize) {
- RenderBuffer* victim = mCache.begin()->mBuffer;
- deleteBuffer(victim);
- mCache.erase(mCache.begin());
- }
-
- RenderBufferEntry entry(buffer);
-
- mCache.insert(entry);
- mSize += size;
-
- RENDER_BUFFER_LOGD("Added %s render buffer (%dx%d)",
- RenderBuffer::formatName(buffer->getFormat()), buffer->getWidth(),
- buffer->getHeight());
-
- return true;
- } else {
- RENDER_BUFFER_LOGD("Deleted %s render buffer (%dx%d) Size=%d, MaxSize=%d",
- RenderBuffer::formatName(buffer->getFormat()), buffer->getWidth(),
- buffer->getHeight(), size, mMaxSize);
- delete buffer;
- }
- return false;
-}
-
-}; // namespace uirenderer
-}; // namespace android
diff --git a/libs/hwui/RenderBufferCache.h b/libs/hwui/RenderBufferCache.h
deleted file mode 100644
index c936a52..0000000
--- a/libs/hwui/RenderBufferCache.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HWUI_RENDER_BUFFER_CACHE_H
-#define ANDROID_HWUI_RENDER_BUFFER_CACHE_H
-
-#include <GLES2/gl2.h>
-
-#include "RenderBuffer.h"
-
-#include <set>
-
-namespace android {
-namespace uirenderer {
-
-class RenderBufferCache {
-public:
- RenderBufferCache();
- ~RenderBufferCache();
-
- /**
- * Returns a buffer with the exact specified dimensions. If no suitable
- * buffer can be found, a new one is created and returned. If creating a
- * new buffer fails, NULL is returned.
- *
- * When a buffer is obtained from the cache, it is removed and the total
- * size of the cache goes down.
- *
- * The returned buffer is always allocated and bound
- * (see RenderBuffer::isAllocated()).
- *
- * @param format The desired render buffer format
- * @param width The desired width of the buffer
- * @param height The desired height of the buffer
- */
- RenderBuffer* get(GLenum format, const uint32_t width, const uint32_t height);
-
- /**
- * Adds the buffer to the cache. The buffer will not be added if there is
- * not enough space available. Adding a buffer can cause other buffer to
- * be removed from the cache.
- *
- * @param buffer The render buffer to add to the cache
- *
- * @return True if the buffer was added, false otherwise.
- */
- bool put(RenderBuffer* buffer);
- /**
- * Clears the cache. This causes all layers to be deleted.
- */
- void clear();
-
- /**
- * Returns the maximum size of the cache in bytes.
- */
- uint32_t getMaxSize();
- /**
- * Returns the current size of the cache in bytes.
- */
- uint32_t getSize();
-
-private:
- struct RenderBufferEntry {
- RenderBufferEntry() : mBuffer(nullptr), mWidth(0), mHeight(0) {}
-
- RenderBufferEntry(GLenum format, const uint32_t width, const uint32_t height)
- : mBuffer(nullptr), mFormat(format), mWidth(width), mHeight(height) {}
-
- explicit RenderBufferEntry(RenderBuffer* buffer)
- : mBuffer(buffer)
- , mFormat(buffer->getFormat())
- , mWidth(buffer->getWidth())
- , mHeight(buffer->getHeight()) {}
-
- static int compare(const RenderBufferEntry& lhs, const RenderBufferEntry& rhs);
-
- bool operator==(const RenderBufferEntry& other) const { return compare(*this, other) == 0; }
-
- bool operator!=(const RenderBufferEntry& other) const { return compare(*this, other) != 0; }
-
- bool operator<(const RenderBufferEntry& other) const {
- return RenderBufferEntry::compare(*this, other) < 0;
- }
-
- RenderBuffer* mBuffer;
- GLenum mFormat;
- uint32_t mWidth;
- uint32_t mHeight;
- }; // struct RenderBufferEntry
-
- void deleteBuffer(RenderBuffer* buffer);
-
- std::multiset<RenderBufferEntry> mCache;
-
- uint32_t mSize;
- uint32_t mMaxSize;
-}; // class RenderBufferCache
-
-}; // namespace uirenderer
-}; // namespace android
-
-#endif // ANDROID_HWUI_RENDER_BUFFER_CACHE_H
diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp
index d60b994..464a58d 100644
--- a/libs/hwui/ResourceCache.cpp
+++ b/libs/hwui/ResourceCache.cpp
@@ -113,7 +113,7 @@
if (ref == nullptr) {
// If we're not tracking this resource, just delete it
if (Caches::hasInstance()) {
- Caches::getInstance().patchCache.removeDeferred(resource);
+ // DEAD CODE
} else {
// A Res_png_9patch is actually an array of byte that's larger
// than sizeof(Res_png_9patch). It must be freed as an array.
@@ -136,7 +136,7 @@
switch (ref->resourceType) {
case kNinePatch: {
if (Caches::hasInstance()) {
- Caches::getInstance().patchCache.removeDeferred((Res_png_9patch*)resource);
+ // DEAD CODE
} else {
// A Res_png_9patch is actually an array of byte that's larger
// than sizeof(Res_png_9patch). It must be freed as an array.
diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp
index df74655..6f7bb9b 100644
--- a/libs/hwui/SkiaShader.cpp
+++ b/libs/hwui/SkiaShader.cpp
@@ -45,13 +45,6 @@
static_assert(gTileModes[SkShader::kMirror_TileMode] == GL_MIRRORED_REPEAT,
"SkShader TileModes have changed");
-/**
- * This function does not work for n == 0.
- */
-static inline bool isPowerOfTwo(unsigned int n) {
- return !(n & (n - 1));
-}
-
static inline void bindUniformColor(int slot, FloatColor color) {
glUniform4fv(slot, 1, reinterpret_cast<const float*>(&color));
}
@@ -80,106 +73,9 @@
}
///////////////////////////////////////////////////////////////////////////////
-// Gradient shader matrix helpers
-///////////////////////////////////////////////////////////////////////////////
-
-static void toLinearUnitMatrix(const SkPoint pts[2], SkMatrix* matrix) {
- SkVector vec = pts[1] - pts[0];
- const float mag = vec.length();
- const float inv = mag ? 1.0f / mag : 0;
-
- vec.scale(inv);
- matrix->setSinCos(-vec.fY, vec.fX, pts[0].fX, pts[0].fY);
- matrix->postTranslate(-pts[0].fX, -pts[0].fY);
- matrix->postScale(inv, inv);
-}
-
-static void toCircularUnitMatrix(const float x, const float y, const float radius,
- SkMatrix* matrix) {
- const float inv = 1.0f / radius;
- matrix->setTranslate(-x, -y);
- matrix->postScale(inv, inv);
-}
-
-static void toSweepUnitMatrix(const float x, const float y, SkMatrix* matrix) {
- matrix->setTranslate(-x, -y);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Common gradient code
-///////////////////////////////////////////////////////////////////////////////
-
-static bool isSimpleGradient(const SkShader::GradientInfo& gradInfo) {
- return gradInfo.fColorCount == 2 && gradInfo.fTileMode == SkShader::kClamp_TileMode;
-}
-
-///////////////////////////////////////////////////////////////////////////////
// Store / apply
///////////////////////////////////////////////////////////////////////////////
-bool tryStoreGradient(Caches& caches, const SkShader& shader, const Matrix4 modelViewMatrix,
- GLuint* textureUnit, ProgramDescription* description,
- SkiaShaderData::GradientShaderData* outData) {
- SkShader::GradientInfo gradInfo;
- gradInfo.fColorCount = 0;
- gradInfo.fColors = nullptr;
- gradInfo.fColorOffsets = nullptr;
-
- SkMatrix unitMatrix;
- switch (shader.asAGradient(&gradInfo)) {
- case SkShader::kLinear_GradientType:
- description->gradientType = ProgramDescription::kGradientLinear;
-
- toLinearUnitMatrix(gradInfo.fPoint, &unitMatrix);
- break;
- case SkShader::kRadial_GradientType:
- description->gradientType = ProgramDescription::kGradientCircular;
-
- toCircularUnitMatrix(gradInfo.fPoint[0].fX, gradInfo.fPoint[0].fY, gradInfo.fRadius[0],
- &unitMatrix);
- break;
- case SkShader::kSweep_GradientType:
- description->gradientType = ProgramDescription::kGradientSweep;
-
- toSweepUnitMatrix(gradInfo.fPoint[0].fX, gradInfo.fPoint[0].fY, &unitMatrix);
- break;
- default:
- // Do nothing. This shader is unsupported.
- return false;
- }
- description->hasGradient = true;
- description->isSimpleGradient = isSimpleGradient(gradInfo);
-
- computeScreenSpaceMatrix(outData->screenSpace, unitMatrix, shader.getLocalMatrix(),
- modelViewMatrix);
-
- // re-query shader to get full color / offset data
- std::unique_ptr<SkColor[]> colorStorage(new SkColor[gradInfo.fColorCount]);
- std::unique_ptr<SkScalar[]> colorOffsets(new SkScalar[gradInfo.fColorCount]);
- gradInfo.fColors = &colorStorage[0];
- gradInfo.fColorOffsets = &colorOffsets[0];
- shader.asAGradient(&gradInfo);
-
- if (CC_UNLIKELY(!description->isSimpleGradient)) {
- outData->gradientSampler = (*textureUnit)++;
-
-#ifndef SK_SCALAR_IS_FLOAT
-#error Need to convert gradInfo.fColorOffsets to float!
-#endif
- outData->gradientTexture = caches.gradientCache.get(
- gradInfo.fColors, gradInfo.fColorOffsets, gradInfo.fColorCount);
- outData->wrapST = gTileModes[gradInfo.fTileMode];
- } else {
- outData->gradientSampler = 0;
- outData->gradientTexture = nullptr;
-
- outData->startColor.set(gradInfo.fColors[0]);
- outData->endColor.set(gradInfo.fColors[1]);
- }
-
- return true;
-}
-
void applyGradient(Caches& caches, const SkiaShaderData::GradientShaderData& data,
const GLsizei width, const GLsizei height) {
if (CC_UNLIKELY(data.gradientTexture)) {
@@ -199,52 +95,7 @@
bool tryStoreBitmap(Caches& caches, const SkShader& shader, const Matrix4& modelViewMatrix,
GLuint* textureUnit, ProgramDescription* description,
SkiaShaderData::BitmapShaderData* outData) {
- SkBitmap bitmap;
- SkShader::TileMode xy[2];
- if (!shader.isABitmap(&bitmap, nullptr, xy)) {
- return false;
- }
-
- // TODO: create hwui-owned BitmapShader.
- Bitmap* hwuiBitmap = static_cast<Bitmap*>(bitmap.pixelRef());
- outData->bitmapTexture = caches.textureCache.get(hwuiBitmap);
- if (!outData->bitmapTexture) return false;
-
- outData->bitmapSampler = (*textureUnit)++;
-
- const float width = outData->bitmapTexture->width();
- const float height = outData->bitmapTexture->height();
-
- Texture* texture = outData->bitmapTexture;
-
- description->hasBitmap = true;
- description->hasLinearTexture = texture->isLinear();
- description->hasColorSpaceConversion = texture->hasColorSpaceConversion();
- description->transferFunction = texture->getTransferFunctionType();
- description->hasTranslucentConversion = texture->blend;
- description->isShaderBitmapExternal = hwuiBitmap->isHardware();
- // gralloc doesn't support non-clamp modes
- if (hwuiBitmap->isHardware() ||
- (!caches.extensions().hasNPot() && (!isPowerOfTwo(width) || !isPowerOfTwo(height)) &&
- (xy[0] != SkShader::kClamp_TileMode || xy[1] != SkShader::kClamp_TileMode))) {
- // need non-clamp mode, but it's not supported for this draw,
- // so enable custom shader logic to mimic
- description->useShaderBasedWrap = true;
- description->bitmapWrapS = gTileModes[xy[0]];
- description->bitmapWrapT = gTileModes[xy[1]];
-
- outData->wrapS = GL_CLAMP_TO_EDGE;
- outData->wrapT = GL_CLAMP_TO_EDGE;
- } else {
- outData->wrapS = gTileModes[xy[0]];
- outData->wrapT = gTileModes[xy[1]];
- }
-
- computeScreenSpaceMatrix(outData->textureTransform, SkMatrix::I(), shader.getLocalMatrix(),
- modelViewMatrix);
- outData->textureDimension[0] = 1.0f / width;
- outData->textureDimension[1] = 1.0f / height;
-
+ // DEAD CODE
return true;
}
@@ -287,9 +138,6 @@
LOG_ALWAYS_FATAL_IF(!tryStoreBitmap(caches, bitmapShader, modelViewMatrix, textureUnit,
description, &outData->bitmapData),
"failed storing bitmap shader data");
- LOG_ALWAYS_FATAL_IF(!tryStoreGradient(caches, gradientShader, modelViewMatrix, textureUnit,
- description, &outData->gradientData),
- "failing storing gradient shader data");
}
bool tryStoreCompose(Caches& caches, const SkShader& shader, const Matrix4& modelViewMatrix,
@@ -323,12 +171,7 @@
void SkiaShader::store(Caches& caches, const SkShader& shader, const Matrix4& modelViewMatrix,
GLuint* textureUnit, ProgramDescription* description,
SkiaShaderData* outData) {
- if (tryStoreGradient(caches, shader, modelViewMatrix, textureUnit, description,
- &outData->gradientData)) {
- outData->skiaShaderType = kGradient_SkiaShaderType;
- return;
- }
-
+ // DEAD CODE
if (tryStoreBitmap(caches, shader, modelViewMatrix, textureUnit, description,
&outData->bitmapData)) {
outData->skiaShaderType = kBitmap_SkiaShaderType;
diff --git a/libs/hwui/TessellationCache.cpp b/libs/hwui/TessellationCache.cpp
deleted file mode 100644
index c7d93da..0000000
--- a/libs/hwui/TessellationCache.cpp
+++ /dev/null
@@ -1,444 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <utils/JenkinsHash.h>
-#include <utils/Trace.h>
-
-#include "Caches.h"
-#include "PathTessellator.h"
-#include "ShadowTessellator.h"
-#include "TessellationCache.h"
-
-#include "thread/Signal.h"
-#include "thread/Task.h"
-#include "thread/TaskProcessor.h"
-
-namespace android {
-namespace uirenderer {
-
-///////////////////////////////////////////////////////////////////////////////
-// Cache entries
-///////////////////////////////////////////////////////////////////////////////
-
-TessellationCache::Description::Description()
- : type(Type::None)
- , scaleX(1.0f)
- , scaleY(1.0f)
- , aa(false)
- , cap(SkPaint::kDefault_Cap)
- , style(SkPaint::kFill_Style)
- , strokeWidth(1.0f) {
- // Shape bits should be set to zeroes, because they are used for hash calculation.
- memset(&shape, 0, sizeof(Shape));
-}
-
-TessellationCache::Description::Description(Type type, const Matrix4& transform,
- const SkPaint& paint)
- : type(type)
- , aa(paint.isAntiAlias())
- , cap(paint.getStrokeCap())
- , style(paint.getStyle())
- , strokeWidth(paint.getStrokeWidth()) {
- PathTessellator::extractTessellationScales(transform, &scaleX, &scaleY);
- // Shape bits should be set to zeroes, because they are used for hash calculation.
- memset(&shape, 0, sizeof(Shape));
-}
-
-bool TessellationCache::Description::operator==(const TessellationCache::Description& rhs) const {
- if (type != rhs.type) return false;
- if (scaleX != rhs.scaleX) return false;
- if (scaleY != rhs.scaleY) return false;
- if (aa != rhs.aa) return false;
- if (cap != rhs.cap) return false;
- if (style != rhs.style) return false;
- if (strokeWidth != rhs.strokeWidth) return false;
- if (type == Type::None) return true;
- const Shape::RoundRect& lRect = shape.roundRect;
- const Shape::RoundRect& rRect = rhs.shape.roundRect;
-
- if (lRect.width != rRect.width) return false;
- if (lRect.height != rRect.height) return false;
- if (lRect.rx != rRect.rx) return false;
- return lRect.ry == rRect.ry;
-}
-
-hash_t TessellationCache::Description::hash() const {
- uint32_t hash = JenkinsHashMix(0, static_cast<int>(type));
- hash = JenkinsHashMix(hash, aa);
- hash = JenkinsHashMix(hash, cap);
- hash = JenkinsHashMix(hash, style);
- hash = JenkinsHashMix(hash, android::hash_type(strokeWidth));
- hash = JenkinsHashMix(hash, android::hash_type(scaleX));
- hash = JenkinsHashMix(hash, android::hash_type(scaleY));
- hash = JenkinsHashMixBytes(hash, (uint8_t*)&shape, sizeof(Shape));
- return JenkinsHashWhiten(hash);
-}
-
-void TessellationCache::Description::setupMatrixAndPaint(Matrix4* matrix, SkPaint* paint) const {
- matrix->loadScale(scaleX, scaleY, 1.0f);
- paint->setAntiAlias(aa);
- paint->setStrokeCap(cap);
- paint->setStyle(style);
- paint->setStrokeWidth(strokeWidth);
-}
-
-TessellationCache::ShadowDescription::ShadowDescription() : nodeKey(nullptr) {
- memset(&matrixData, 0, sizeof(matrixData));
-}
-
-TessellationCache::ShadowDescription::ShadowDescription(const SkPath* nodeKey,
- const Matrix4* drawTransform)
- : nodeKey(nodeKey) {
- memcpy(&matrixData, drawTransform->data, sizeof(matrixData));
-}
-
-bool TessellationCache::ShadowDescription::operator==(
- const TessellationCache::ShadowDescription& rhs) const {
- return nodeKey == rhs.nodeKey && memcmp(&matrixData, &rhs.matrixData, sizeof(matrixData)) == 0;
-}
-
-hash_t TessellationCache::ShadowDescription::hash() const {
- uint32_t hash = JenkinsHashMixBytes(0, (uint8_t*)&nodeKey, sizeof(const void*));
- hash = JenkinsHashMixBytes(hash, (uint8_t*)&matrixData, sizeof(matrixData));
- return JenkinsHashWhiten(hash);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// General purpose tessellation task processing
-///////////////////////////////////////////////////////////////////////////////
-
-class TessellationCache::TessellationTask : public Task<VertexBuffer*> {
-public:
- TessellationTask(Tessellator tessellator, const Description& description)
- : tessellator(tessellator), description(description) {}
-
- ~TessellationTask() {}
-
- Tessellator tessellator;
- Description description;
-};
-
-class TessellationCache::TessellationProcessor : public TaskProcessor<VertexBuffer*> {
-public:
- explicit TessellationProcessor(Caches& caches) : TaskProcessor<VertexBuffer*>(&caches.tasks) {}
- ~TessellationProcessor() {}
-
- virtual void onProcess(const sp<Task<VertexBuffer*> >& task) override {
- TessellationTask* t = static_cast<TessellationTask*>(task.get());
- ATRACE_NAME("shape tessellation");
- VertexBuffer* buffer = t->tessellator(t->description);
- t->setResult(buffer);
- }
-};
-
-class TessellationCache::Buffer {
-public:
- explicit Buffer(const sp<Task<VertexBuffer*> >& task) : mTask(task), mBuffer(nullptr) {}
-
- ~Buffer() {
- mTask.clear();
- delete mBuffer;
- }
-
- unsigned int getSize() {
- blockOnPrecache();
- return mBuffer->getSize();
- }
-
- const VertexBuffer* getVertexBuffer() {
- blockOnPrecache();
- return mBuffer;
- }
-
-private:
- void blockOnPrecache() {
- if (mTask != nullptr) {
- mBuffer = mTask->getResult();
- LOG_ALWAYS_FATAL_IF(mBuffer == nullptr, "Failed to precache");
- mTask.clear();
- }
- }
- sp<Task<VertexBuffer*> > mTask;
- VertexBuffer* mBuffer;
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// Shadow tessellation task processing
-///////////////////////////////////////////////////////////////////////////////
-
-static void mapPointFakeZ(Vector3& point, const mat4* transformXY, const mat4* transformZ) {
- // map z coordinate with true 3d matrix
- point.z = transformZ->mapZ(point);
-
- // map x,y coordinates with draw/Skia matrix
- transformXY->mapPoint(point.x, point.y);
-}
-
-static void reverseVertexArray(Vertex* polygon, int len) {
- int n = len / 2;
- for (int i = 0; i < n; i++) {
- Vertex tmp = polygon[i];
- int k = len - 1 - i;
- polygon[i] = polygon[k];
- polygon[k] = tmp;
- }
-}
-
-void tessellateShadows(const Matrix4* drawTransform, const Rect* localClip, bool isCasterOpaque,
- const SkPath* casterPerimeter, const Matrix4* casterTransformXY,
- const Matrix4* casterTransformZ, const Vector3& lightCenter,
- float lightRadius, VertexBuffer& ambientBuffer, VertexBuffer& spotBuffer) {
- // tessellate caster outline into a 2d polygon
- std::vector<Vertex> casterVertices2d;
- const float casterRefinementThreshold = 2.0f;
- PathTessellator::approximatePathOutlineVertices(*casterPerimeter, casterRefinementThreshold,
- casterVertices2d);
-
- // Shadow requires CCW for now. TODO: remove potential double-reverse
- reverseVertexArray(&casterVertices2d.front(), casterVertices2d.size());
-
- if (casterVertices2d.size() == 0) return;
-
- // map 2d caster poly into 3d
- const int casterVertexCount = casterVertices2d.size();
- Vector3 casterPolygon[casterVertexCount];
- float minZ = FLT_MAX;
- float maxZ = -FLT_MAX;
- for (int i = 0; i < casterVertexCount; i++) {
- const Vertex& point2d = casterVertices2d[i];
- casterPolygon[i] = (Vector3){point2d.x, point2d.y, 0};
- mapPointFakeZ(casterPolygon[i], casterTransformXY, casterTransformZ);
- minZ = std::min(minZ, casterPolygon[i].z);
- maxZ = std::max(maxZ, casterPolygon[i].z);
- }
-
- // map the centroid of the caster into 3d
- Vector2 centroid = ShadowTessellator::centroid2d(
- reinterpret_cast<const Vector2*>(&casterVertices2d.front()), casterVertexCount);
- Vector3 centroid3d = {centroid.x, centroid.y, 0};
- mapPointFakeZ(centroid3d, casterTransformXY, casterTransformZ);
-
- // if the caster intersects the z=0 plane, lift it in Z so it doesn't
- if (minZ < SHADOW_MIN_CASTER_Z) {
- float casterLift = SHADOW_MIN_CASTER_Z - minZ;
- for (int i = 0; i < casterVertexCount; i++) {
- casterPolygon[i].z += casterLift;
- }
- centroid3d.z += casterLift;
- }
-
- // Check whether we want to draw the shadow at all by checking the caster's bounds against clip.
- // We only have ortho projection, so we can just ignore the Z in caster for
- // simple rejection calculation.
- Rect casterBounds(casterPerimeter->getBounds());
- casterTransformXY->mapRect(casterBounds);
-
- // actual tessellation of both shadows
- ShadowTessellator::tessellateAmbientShadow(isCasterOpaque, casterPolygon, casterVertexCount,
- centroid3d, casterBounds, *localClip, maxZ,
- ambientBuffer);
-
- ShadowTessellator::tessellateSpotShadow(isCasterOpaque, casterPolygon, casterVertexCount,
- centroid3d, *drawTransform, lightCenter, lightRadius,
- casterBounds, *localClip, spotBuffer);
-}
-
-class ShadowProcessor : public TaskProcessor<TessellationCache::vertexBuffer_pair_t> {
-public:
- explicit ShadowProcessor(Caches& caches)
- : TaskProcessor<TessellationCache::vertexBuffer_pair_t>(&caches.tasks) {}
- ~ShadowProcessor() {}
-
- virtual void onProcess(const sp<Task<TessellationCache::vertexBuffer_pair_t> >& task) override {
- TessellationCache::ShadowTask* t = static_cast<TessellationCache::ShadowTask*>(task.get());
- ATRACE_NAME("shadow tessellation");
-
- tessellateShadows(&t->drawTransform, &t->localClip, t->opaque, &t->casterPerimeter,
- &t->transformXY, &t->transformZ, t->lightCenter, t->lightRadius,
- t->ambientBuffer, t->spotBuffer);
-
- t->setResult(TessellationCache::vertexBuffer_pair_t(&t->ambientBuffer, &t->spotBuffer));
- }
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// Cache constructor/destructor
-///////////////////////////////////////////////////////////////////////////////
-
-TessellationCache::TessellationCache()
- : mMaxSize(MB(1))
- , mCache(LruCache<Description, Buffer*>::kUnlimitedCapacity)
- , mShadowCache(
- LruCache<ShadowDescription, Task<vertexBuffer_pair_t*>*>::kUnlimitedCapacity) {
- mCache.setOnEntryRemovedListener(&mBufferRemovedListener);
- mShadowCache.setOnEntryRemovedListener(&mBufferPairRemovedListener);
- mDebugEnabled = Properties::debugLevel & kDebugCaches;
-}
-
-TessellationCache::~TessellationCache() {
- mCache.clear();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Size management
-///////////////////////////////////////////////////////////////////////////////
-
-uint32_t TessellationCache::getSize() {
- LruCache<Description, Buffer*>::Iterator iter(mCache);
- uint32_t size = 0;
- while (iter.next()) {
- size += iter.value()->getSize();
- }
- return size;
-}
-
-uint32_t TessellationCache::getMaxSize() {
- return mMaxSize;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Caching
-///////////////////////////////////////////////////////////////////////////////
-
-void TessellationCache::trim() {
- uint32_t size = getSize();
- while (size > mMaxSize) {
- size -= mCache.peekOldestValue()->getSize();
- mCache.removeOldest();
- }
- mShadowCache.clear();
-}
-
-void TessellationCache::clear() {
- mCache.clear();
- mShadowCache.clear();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Callbacks
-///////////////////////////////////////////////////////////////////////////////
-
-void TessellationCache::BufferRemovedListener::operator()(Description& description,
- Buffer*& buffer) {
- delete buffer;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Shadows
-///////////////////////////////////////////////////////////////////////////////
-
-void TessellationCache::precacheShadows(const Matrix4* drawTransform, const Rect& localClip,
- bool opaque, const SkPath* casterPerimeter,
- const Matrix4* transformXY, const Matrix4* transformZ,
- const Vector3& lightCenter, float lightRadius) {
- ShadowDescription key(casterPerimeter, drawTransform);
-
- if (mShadowCache.get(key)) return;
- sp<ShadowTask> task = new ShadowTask(drawTransform, localClip, opaque, casterPerimeter,
- transformXY, transformZ, lightCenter, lightRadius);
- if (mShadowProcessor == nullptr) {
- mShadowProcessor = new ShadowProcessor(Caches::getInstance());
- }
- mShadowProcessor->add(task);
- task->incStrong(nullptr); // not using sp<>s, so manually ref while in the cache
- mShadowCache.put(key, task.get());
-}
-
-sp<TessellationCache::ShadowTask> TessellationCache::getShadowTask(
- const Matrix4* drawTransform, const Rect& localClip, bool opaque,
- const SkPath* casterPerimeter, const Matrix4* transformXY, const Matrix4* transformZ,
- const Vector3& lightCenter, float lightRadius) {
- ShadowDescription key(casterPerimeter, drawTransform);
- ShadowTask* task = static_cast<ShadowTask*>(mShadowCache.get(key));
- if (!task) {
- precacheShadows(drawTransform, localClip, opaque, casterPerimeter, transformXY, transformZ,
- lightCenter, lightRadius);
- task = static_cast<ShadowTask*>(mShadowCache.get(key));
- }
- LOG_ALWAYS_FATAL_IF(task == nullptr, "shadow not precached");
- return task;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Tessellation precaching
-///////////////////////////////////////////////////////////////////////////////
-
-TessellationCache::Buffer* TessellationCache::getOrCreateBuffer(const Description& entry,
- Tessellator tessellator) {
- Buffer* buffer = mCache.get(entry);
- if (!buffer) {
- // not cached, enqueue a task to fill the buffer
- sp<TessellationTask> task = new TessellationTask(tessellator, entry);
- buffer = new Buffer(task);
-
- if (mProcessor == nullptr) {
- mProcessor = new TessellationProcessor(Caches::getInstance());
- }
- mProcessor->add(task);
- bool inserted = mCache.put(entry, buffer);
- // Note to the static analyzer that this insert should always succeed.
- LOG_ALWAYS_FATAL_IF(!inserted, "buffers shouldn't spontaneously appear in the cache");
- }
- return buffer;
-}
-
-static VertexBuffer* tessellatePath(const TessellationCache::Description& description,
- const SkPath& path) {
- Matrix4 matrix;
- SkPaint paint;
- description.setupMatrixAndPaint(&matrix, &paint);
- VertexBuffer* buffer = new VertexBuffer();
- PathTessellator::tessellatePath(path, &paint, matrix, *buffer);
- return buffer;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// RoundRect
-///////////////////////////////////////////////////////////////////////////////
-
-static VertexBuffer* tessellateRoundRect(const TessellationCache::Description& description) {
- SkRect rect =
- SkRect::MakeWH(description.shape.roundRect.width, description.shape.roundRect.height);
- float rx = description.shape.roundRect.rx;
- float ry = description.shape.roundRect.ry;
- if (description.style == SkPaint::kStrokeAndFill_Style) {
- float outset = description.strokeWidth / 2;
- rect.outset(outset, outset);
- rx += outset;
- ry += outset;
- }
- SkPath path;
- path.addRoundRect(rect, rx, ry);
- return tessellatePath(description, path);
-}
-
-TessellationCache::Buffer* TessellationCache::getRoundRectBuffer(const Matrix4& transform,
- const SkPaint& paint, float width,
- float height, float rx, float ry) {
- Description entry(Description::Type::RoundRect, transform, paint);
- entry.shape.roundRect.width = width;
- entry.shape.roundRect.height = height;
- entry.shape.roundRect.rx = rx;
- entry.shape.roundRect.ry = ry;
- return getOrCreateBuffer(entry, &tessellateRoundRect);
-}
-const VertexBuffer* TessellationCache::getRoundRect(const Matrix4& transform, const SkPaint& paint,
- float width, float height, float rx, float ry) {
- return getRoundRectBuffer(transform, paint, width, height, rx, ry)->getVertexBuffer();
-}
-
-}; // namespace uirenderer
-}; // namespace android
diff --git a/libs/hwui/TessellationCache.h b/libs/hwui/TessellationCache.h
deleted file mode 100644
index a0f0ed4..0000000
--- a/libs/hwui/TessellationCache.h
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include "Debug.h"
-#include "Matrix.h"
-#include "Rect.h"
-#include "Vector.h"
-#include "VertexBuffer.h"
-#include "thread/TaskProcessor.h"
-#include "utils/Macros.h"
-#include "utils/Pair.h"
-
-#include <SkPaint.h>
-#include <SkPath.h>
-
-#include <utils/LruCache.h>
-#include <utils/Mutex.h>
-#include <utils/StrongPointer.h>
-
-class SkBitmap;
-class SkCanvas;
-struct SkRect;
-
-namespace android {
-namespace uirenderer {
-
-class Caches;
-class VertexBuffer;
-
-///////////////////////////////////////////////////////////////////////////////
-// Classes
-///////////////////////////////////////////////////////////////////////////////
-
-class TessellationCache {
-public:
- typedef Pair<VertexBuffer*, VertexBuffer*> vertexBuffer_pair_t;
-
- struct Description {
- HASHABLE_TYPE(Description);
- enum class Type {
- None,
- RoundRect,
- };
-
- Type type;
- float scaleX;
- float scaleY;
- bool aa;
- SkPaint::Cap cap;
- SkPaint::Style style;
- float strokeWidth;
- union Shape {
- struct RoundRect {
- float width;
- float height;
- float rx;
- float ry;
- } roundRect;
- } shape;
-
- Description();
- Description(Type type, const Matrix4& transform, const SkPaint& paint);
- void setupMatrixAndPaint(Matrix4* matrix, SkPaint* paint) const;
- };
-
- struct ShadowDescription {
- HASHABLE_TYPE(ShadowDescription);
- const SkPath* nodeKey;
- float matrixData[16];
-
- ShadowDescription();
- ShadowDescription(const SkPath* nodeKey, const Matrix4* drawTransform);
- };
-
- class ShadowTask : public Task<vertexBuffer_pair_t> {
- public:
- ShadowTask(const Matrix4* drawTransform, const Rect& localClip, bool opaque,
- const SkPath* casterPerimeter, const Matrix4* transformXY,
- const Matrix4* transformZ, const Vector3& lightCenter, float lightRadius)
- : drawTransform(*drawTransform)
- , localClip(localClip)
- , opaque(opaque)
- , casterPerimeter(*casterPerimeter)
- , transformXY(*transformXY)
- , transformZ(*transformZ)
- , lightCenter(lightCenter)
- , lightRadius(lightRadius) {}
-
- /* Note - we deep copy all task parameters, because *even though* pointers into Allocator
- * controlled objects (like the SkPath and Matrix4s) should be safe for the entire frame,
- * certain Allocators are destroyed before trim() is called to flush incomplete tasks.
- *
- * These deep copies could be avoided, long term, by canceling or flushing outstanding
- * tasks before tearing down single-frame LinearAllocators.
- */
- const Matrix4 drawTransform;
- const Rect localClip;
- bool opaque;
- const SkPath casterPerimeter;
- const Matrix4 transformXY;
- const Matrix4 transformZ;
- const Vector3 lightCenter;
- const float lightRadius;
- VertexBuffer ambientBuffer;
- VertexBuffer spotBuffer;
- };
-
- TessellationCache();
- ~TessellationCache();
-
- /**
- * Clears the cache. This causes all TessellationBuffers to be deleted.
- */
- void clear();
- /**
- * Returns the maximum size of the cache in bytes.
- */
- uint32_t getMaxSize();
- /**
- * Returns the current size of the cache in bytes.
- */
- uint32_t getSize();
-
- /**
- * Trims the contents of the cache, removing items until it's under its
- * specified limit.
- *
- * Trimming is used for caches that support pre-caching from a worker
- * thread. During pre-caching the maximum limit of the cache can be
- * exceeded for the duration of the frame. It is therefore required to
- * trim the cache at the end of the frame to keep the total amount of
- * memory used under control.
- *
- * Also removes transient Shadow VertexBuffers, which aren't cached between frames.
- */
- void trim();
-
- // TODO: precache/get for Oval, Lines, Points, etc.
-
- void precacheRoundRect(const Matrix4& transform, const SkPaint& paint, float width,
- float height, float rx, float ry) {
- getRoundRectBuffer(transform, paint, width, height, rx, ry);
- }
- const VertexBuffer* getRoundRect(const Matrix4& transform, const SkPaint& paint, float width,
- float height, float rx, float ry);
-
- sp<ShadowTask> getShadowTask(const Matrix4* drawTransform, const Rect& localClip, bool opaque,
- const SkPath* casterPerimeter, const Matrix4* transformXY,
- const Matrix4* transformZ, const Vector3& lightCenter,
- float lightRadius);
-
-private:
- class Buffer;
- class TessellationTask;
- class TessellationProcessor;
-
- typedef VertexBuffer* (*Tessellator)(const Description&);
-
- void precacheShadows(const Matrix4* drawTransform, const Rect& localClip, bool opaque,
- const SkPath* casterPerimeter, const Matrix4* transformXY,
- const Matrix4* transformZ, const Vector3& lightCenter, float lightRadius);
-
- Buffer* getRectBuffer(const Matrix4& transform, const SkPaint& paint, float width,
- float height);
- Buffer* getRoundRectBuffer(const Matrix4& transform, const SkPaint& paint, float width,
- float height, float rx, float ry);
-
- Buffer* getOrCreateBuffer(const Description& entry, Tessellator tessellator);
-
- const uint32_t mMaxSize;
-
- bool mDebugEnabled;
-
- mutable Mutex mLock;
-
- ///////////////////////////////////////////////////////////////////////////////
- // General tessellation caching
- ///////////////////////////////////////////////////////////////////////////////
- sp<TaskProcessor<VertexBuffer*> > mProcessor;
- LruCache<Description, Buffer*> mCache;
- class BufferRemovedListener : public OnEntryRemoved<Description, Buffer*> {
- void operator()(Description& description, Buffer*& buffer) override;
- };
- BufferRemovedListener mBufferRemovedListener;
-
- ///////////////////////////////////////////////////////////////////////////////
- // Shadow tessellation caching
- ///////////////////////////////////////////////////////////////////////////////
- sp<TaskProcessor<vertexBuffer_pair_t> > mShadowProcessor;
-
- // holds a pointer, and implicit strong ref to each shadow task of the frame
- LruCache<ShadowDescription, Task<vertexBuffer_pair_t>*> mShadowCache;
- class BufferPairRemovedListener
- : public OnEntryRemoved<ShadowDescription, Task<vertexBuffer_pair_t>*> {
- void operator()(ShadowDescription& description,
- Task<vertexBuffer_pair_t>*& bufferPairTask) override {
- bufferPairTask->decStrong(nullptr);
- }
- };
- BufferPairRemovedListener mBufferPairRemovedListener;
-
-}; // class TessellationCache
-
-void tessellateShadows(const Matrix4* drawTransform, const Rect* localClip, bool isCasterOpaque,
- const SkPath* casterPerimeter, const Matrix4* casterTransformXY,
- const Matrix4* casterTransformZ, const Vector3& lightCenter,
- float lightRadius, VertexBuffer& ambientBuffer, VertexBuffer& spotBuffer);
-
-}; // namespace uirenderer
-}; // namespace android
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
deleted file mode 100644
index 9d365fb..0000000
--- a/libs/hwui/TextureCache.cpp
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <GLES2/gl2.h>
-
-#include <utils/Mutex.h>
-
-#include "Caches.h"
-#include "DeviceInfo.h"
-#include "Properties.h"
-#include "Texture.h"
-#include "TextureCache.h"
-#include "hwui/Bitmap.h"
-#include "utils/TraceUtils.h"
-
-namespace android {
-namespace uirenderer {
-
-///////////////////////////////////////////////////////////////////////////////
-// Constructors/destructor
-///////////////////////////////////////////////////////////////////////////////
-
-TextureCache::TextureCache()
- : mCache(LruCache<uint32_t, Texture*>::kUnlimitedCapacity)
- , mSize(0)
- , mMaxSize(DeviceInfo::multiplyByResolution(4 * 6)) // 6 screen-sized RGBA_8888 bitmaps
- , mFlushRate(.4f) {
- mCache.setOnEntryRemovedListener(this);
- mMaxTextureSize = DeviceInfo::get()->maxTextureSize();
- mDebugEnabled = Properties::debugLevel & kDebugCaches;
-}
-
-TextureCache::~TextureCache() {
- this->clear();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Size management
-///////////////////////////////////////////////////////////////////////////////
-
-uint32_t TextureCache::getSize() {
- return mSize;
-}
-
-uint32_t TextureCache::getMaxSize() {
- return mMaxSize;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Callbacks
-///////////////////////////////////////////////////////////////////////////////
-
-void TextureCache::operator()(uint32_t&, Texture*& texture) {
- // This will be called already locked
- if (texture) {
- mSize -= texture->bitmapSize;
- TEXTURE_LOGD("TextureCache::callback: name, removed size, mSize = %d, %d, %d", texture->id,
- texture->bitmapSize, mSize);
- if (mDebugEnabled) {
- ALOGD("Texture deleted, size = %d", texture->bitmapSize);
- }
- texture->deleteTexture();
- delete texture;
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Caching
-///////////////////////////////////////////////////////////////////////////////
-
-void TextureCache::resetMarkInUse(void* ownerToken) {
- LruCache<uint32_t, Texture*>::Iterator iter(mCache);
- while (iter.next()) {
- if (iter.value()->isInUse == ownerToken) {
- iter.value()->isInUse = nullptr;
- }
- }
-}
-
-bool TextureCache::canMakeTextureFromBitmap(Bitmap* bitmap) {
- if (bitmap->width() > mMaxTextureSize || bitmap->height() > mMaxTextureSize) {
- ALOGW("Bitmap too large to be uploaded into a texture (%dx%d, max=%dx%d)", bitmap->width(),
- bitmap->height(), mMaxTextureSize, mMaxTextureSize);
- return false;
- }
- return true;
-}
-
-Texture* TextureCache::createTexture(Bitmap* bitmap) {
- Texture* texture = new Texture(Caches::getInstance());
- texture->bitmapSize = bitmap->rowBytes() * bitmap->height();
- texture->generation = bitmap->getGenerationID();
- texture->upload(*bitmap);
- return texture;
-}
-
-// Returns a prepared Texture* that either is already in the cache or can fit
-// in the cache (and is thus added to the cache)
-Texture* TextureCache::getCachedTexture(Bitmap* bitmap) {
- if (bitmap->isHardware()) {
- auto textureIterator = mHardwareTextures.find(bitmap->getStableID());
- if (textureIterator == mHardwareTextures.end()) {
- Texture* texture = createTexture(bitmap);
- mHardwareTextures.insert(
- std::make_pair(bitmap->getStableID(), std::unique_ptr<Texture>(texture)));
- if (mDebugEnabled) {
- ALOGD("Texture created for hw bitmap size = %d", texture->bitmapSize);
- }
- return texture;
- }
- return textureIterator->second.get();
- }
-
- Texture* texture = mCache.get(bitmap->getStableID());
-
- if (!texture) {
- if (!canMakeTextureFromBitmap(bitmap)) {
- return nullptr;
- }
-
- const uint32_t size = bitmap->rowBytes() * bitmap->height();
- bool canCache = size < mMaxSize;
- // Don't even try to cache a bitmap that's bigger than the cache
- while (canCache && mSize + size > mMaxSize) {
- Texture* oldest = mCache.peekOldestValue();
- if (oldest && !oldest->isInUse) {
- mCache.removeOldest();
- } else {
- canCache = false;
- }
- }
-
- if (canCache) {
- texture = createTexture(bitmap);
- mSize += size;
- TEXTURE_LOGD("TextureCache::get: create texture(%p): name, size, mSize = %d, %d, %d",
- bitmap, texture->id, size, mSize);
- if (mDebugEnabled) {
- ALOGD("Texture created, size = %d", size);
- }
- mCache.put(bitmap->getStableID(), texture);
- }
- } else if (!texture->isInUse && bitmap->getGenerationID() != texture->generation) {
- // Texture was in the cache but is dirty, re-upload
- // TODO: Re-adjust the cache size if the bitmap's dimensions have changed
- texture->upload(*bitmap);
- texture->generation = bitmap->getGenerationID();
- }
-
- return texture;
-}
-
-bool TextureCache::prefetchAndMarkInUse(void* ownerToken, Bitmap* bitmap) {
- Texture* texture = getCachedTexture(bitmap);
- if (texture) {
- texture->isInUse = ownerToken;
- }
- return texture;
-}
-
-bool TextureCache::prefetch(Bitmap* bitmap) {
- return getCachedTexture(bitmap);
-}
-
-Texture* TextureCache::get(Bitmap* bitmap) {
- Texture* texture = getCachedTexture(bitmap);
-
- if (!texture) {
- if (!canMakeTextureFromBitmap(bitmap)) {
- return nullptr;
- }
- texture = createTexture(bitmap);
- texture->cleanup = true;
- }
-
- return texture;
-}
-
-bool TextureCache::destroyTexture(uint32_t pixelRefStableID) {
- auto hardwareIter = mHardwareTextures.find(pixelRefStableID);
- if (hardwareIter != mHardwareTextures.end()) {
- hardwareIter->second->deleteTexture();
- mHardwareTextures.erase(hardwareIter);
- return true;
- }
- return mCache.remove(pixelRefStableID);
-}
-
-void TextureCache::clear() {
- mCache.clear();
- for (auto& iter : mHardwareTextures) {
- iter.second->deleteTexture();
- }
- mHardwareTextures.clear();
- TEXTURE_LOGD("TextureCache:clear(), mSize = %d", mSize);
-}
-
-void TextureCache::flush() {
- if (mFlushRate >= 1.0f || mCache.size() == 0) return;
- if (mFlushRate <= 0.0f) {
- clear();
- return;
- }
-
- uint32_t targetSize = uint32_t(mSize * mFlushRate);
- TEXTURE_LOGD("TextureCache::flush: target size: %d", targetSize);
-
- while (mSize > targetSize) {
- mCache.removeOldest();
- }
-}
-
-}; // namespace uirenderer
-}; // namespace android
diff --git a/libs/hwui/TextureCache.h b/libs/hwui/TextureCache.h
deleted file mode 100644
index 19e7bea..0000000
--- a/libs/hwui/TextureCache.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HWUI_TEXTURE_CACHE_H
-#define ANDROID_HWUI_TEXTURE_CACHE_H
-
-#include <SkBitmap.h>
-
-#include <cutils/compiler.h>
-
-#include <utils/LruCache.h>
-#include <utils/Mutex.h>
-
-#include "Debug.h"
-
-#include <unordered_map>
-#include <vector>
-
-namespace android {
-
-class Bitmap;
-
-namespace uirenderer {
-
-class Texture;
-
-///////////////////////////////////////////////////////////////////////////////
-// Defines
-///////////////////////////////////////////////////////////////////////////////
-
-// Debug
-#if DEBUG_TEXTURES
-#define TEXTURE_LOGD(...) ALOGD(__VA_ARGS__)
-#else
-#define TEXTURE_LOGD(...)
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-// Classes
-///////////////////////////////////////////////////////////////////////////////
-
-/**
- * A simple LRU texture cache. The cache has a maximum size expressed in bytes.
- * Any texture added to the cache causing the cache to grow beyond the maximum
- * allowed size will also cause the oldest texture to be kicked out.
- */
-class TextureCache : public OnEntryRemoved<uint32_t, Texture*> {
-public:
- TextureCache();
- ~TextureCache();
-
- /**
- * Used as a callback when an entry is removed from the cache.
- * Do not invoke directly.
- */
- void operator()(uint32_t&, Texture*& texture) override;
-
- /**
- * Resets all Textures to not be marked as in use
- */
- void resetMarkInUse(void* ownerToken);
-
- /**
- * Attempts to precache the SkBitmap. Returns true if a Texture was successfully
- * acquired for the bitmap, false otherwise. If a Texture was acquired it is
- * marked as in use.
- */
- bool prefetchAndMarkInUse(void* ownerToken, Bitmap* bitmap);
-
- /**
- * Attempts to precache the SkBitmap. Returns true if a Texture was successfully
- * acquired for the bitmap, false otherwise. Does not mark the Texture
- * as in use and won't update currently in-use Textures.
- */
- bool prefetch(Bitmap* bitmap);
-
- /**
- * Returns the texture associated with the specified bitmap from within the cache.
- * If the texture cannot be found in the cache, a new texture is generated.
- */
- Texture* get(Bitmap* bitmap);
-
- /**
- * Removes the texture associated with the specified pixelRef. Must be called from RenderThread
- * Returns true if a texture was destroyed, false if no texture with that id was found
- */
- bool destroyTexture(uint32_t pixelRefStableID);
-
- /**
- * Clears the cache. This causes all textures to be deleted.
- */
- void clear();
-
- /**
- * Returns the maximum size of the cache in bytes.
- */
- uint32_t getMaxSize();
- /**
- * Returns the current size of the cache in bytes.
- */
- uint32_t getSize();
-
- /**
- * Partially flushes the cache. The amount of memory freed by a flush
- * is defined by the flush rate.
- */
- void flush();
-
-private:
- bool canMakeTextureFromBitmap(Bitmap* bitmap);
-
- Texture* getCachedTexture(Bitmap* bitmap);
- Texture* createTexture(Bitmap* bitmap);
-
- LruCache<uint32_t, Texture*> mCache;
-
- uint32_t mSize;
- const uint32_t mMaxSize;
- GLint mMaxTextureSize;
-
- const float mFlushRate;
-
- bool mDebugEnabled;
-
- std::unordered_map<uint32_t, std::unique_ptr<Texture>> mHardwareTextures;
-}; // class TextureCache
-
-}; // namespace uirenderer
-}; // namespace android
-
-#endif // ANDROID_HWUI_TEXTURE_CACHE_H
diff --git a/libs/hwui/font/CachedGlyphInfo.h b/libs/hwui/font/CachedGlyphInfo.h
deleted file mode 100644
index 93bb823..0000000
--- a/libs/hwui/font/CachedGlyphInfo.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HWUI_CACHED_GLYPH_INFO_H
-#define ANDROID_HWUI_CACHED_GLYPH_INFO_H
-
-namespace android {
-namespace uirenderer {
-
-class CacheTexture;
-
-struct CachedGlyphInfo {
- // Has the cache been invalidated?
- bool mIsValid;
- // Location of the cached glyph in the bitmap
- // in case we need to resize the texture or
- // render to bitmap
- uint32_t mStartX;
- uint32_t mStartY;
- uint32_t mBitmapWidth;
- uint32_t mBitmapHeight;
- // Also cache texture coords for the quad
- float mBitmapMinU;
- float mBitmapMinV;
- float mBitmapMaxU;
- float mBitmapMaxV;
- // Minimize how much we call freetype
- uint32_t mGlyphIndex;
- float mAdvanceX;
- float mAdvanceY;
- // Values below contain a glyph's origin in the bitmap
- int32_t mBitmapLeft;
- int32_t mBitmapTop;
- // Auto-kerning; represents a 2.6 fixed-point value with range [-1, 1].
- int8_t mLsbDelta;
- int8_t mRsbDelta;
- CacheTexture* mCacheTexture;
-};
-
-}; // namespace uirenderer
-}; // namespace android
-
-#endif // ANDROID_HWUI_CACHED_GLYPH_INFO_H
diff --git a/libs/hwui/renderstate/RenderState.cpp b/libs/hwui/renderstate/RenderState.cpp
index 5e33353..f173136 100644
--- a/libs/hwui/renderstate/RenderState.cpp
+++ b/libs/hwui/renderstate/RenderState.cpp
@@ -125,10 +125,7 @@
}
void RenderState::onBitmapDestroyed(uint32_t pixelRefId) {
- if (mCaches && mCaches->textureCache.destroyTexture(pixelRefId)) {
- glFlush();
- GL_CHECKPOINT(MODERATE);
- }
+ // DEAD CODE
}
void RenderState::setViewport(GLsizei width, GLsizei height) {
diff --git a/libs/hwui/tests/microbench/ShadowBench.cpp b/libs/hwui/tests/microbench/ShadowBench.cpp
deleted file mode 100644
index 12da783..0000000
--- a/libs/hwui/tests/microbench/ShadowBench.cpp
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <benchmark/benchmark.h>
-
-#include "Matrix.h"
-#include "Rect.h"
-#include "TessellationCache.h"
-#include "Vector.h"
-#include "VertexBuffer.h"
-
-#include <SkPath.h>
-
-#include <memory>
-
-using namespace android;
-using namespace android::uirenderer;
-
-struct ShadowTestData {
- Matrix4 drawTransform;
- Rect localClip;
- Matrix4 casterTransformXY;
- Matrix4 casterTransformZ;
- Vector3 lightCenter;
- float lightRadius;
-};
-
-void createShadowTestData(ShadowTestData* out) {
- static float SAMPLE_DRAW_TRANSFORM[] = {
- 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1,
- };
- static float SAMPLE_CASTERXY[] = {
- 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 32, 32, 0, 1,
- };
- static float SAMPLE_CASTERZ[] = {
- 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 32, 32, 32, 1,
- };
- static Rect SAMPLE_CLIP(0, 0, 1536, 2048);
- static Vector3 SAMPLE_LIGHT_CENTER{768, -400, 1600};
- static float SAMPLE_LIGHT_RADIUS = 1600;
-
- out->drawTransform.load(SAMPLE_DRAW_TRANSFORM);
- out->localClip = SAMPLE_CLIP;
- out->casterTransformXY.load(SAMPLE_CASTERXY);
- out->casterTransformZ.load(SAMPLE_CASTERZ);
- out->lightCenter = SAMPLE_LIGHT_CENTER;
- out->lightRadius = SAMPLE_LIGHT_RADIUS;
-}
-
-static inline void tessellateShadows(ShadowTestData& testData, bool opaque, const SkPath& shape,
- VertexBuffer* ambient, VertexBuffer* spot) {
- tessellateShadows(&testData.drawTransform, &testData.localClip, opaque, &shape,
- &testData.casterTransformXY, &testData.casterTransformZ, testData.lightCenter,
- testData.lightRadius, *ambient, *spot);
-}
-
-void BM_TessellateShadows_roundrect_opaque(benchmark::State& state) {
- ShadowTestData shadowData;
- createShadowTestData(&shadowData);
- SkPath path;
- path.addRoundRect(SkRect::MakeWH(100, 100), 5, 5);
-
- while (state.KeepRunning()) {
- VertexBuffer ambient;
- VertexBuffer spot;
- tessellateShadows(shadowData, true, path, &ambient, &spot);
- benchmark::DoNotOptimize(&ambient);
- benchmark::DoNotOptimize(&spot);
- }
-}
-BENCHMARK(BM_TessellateShadows_roundrect_opaque);
-
-void BM_TessellateShadows_roundrect_translucent(benchmark::State& state) {
- ShadowTestData shadowData;
- createShadowTestData(&shadowData);
- SkPath path;
- path.reset();
- path.addRoundRect(SkRect::MakeLTRB(0, 0, 100, 100), 5, 5);
-
- while (state.KeepRunning()) {
- std::unique_ptr<VertexBuffer> ambient(new VertexBuffer);
- std::unique_ptr<VertexBuffer> spot(new VertexBuffer);
- tessellateShadows(shadowData, false, path, ambient.get(), spot.get());
- benchmark::DoNotOptimize(ambient.get());
- benchmark::DoNotOptimize(spot.get());
- }
-}
-BENCHMARK(BM_TessellateShadows_roundrect_translucent);
diff --git a/libs/hwui/utils/PaintUtils.h b/libs/hwui/utils/PaintUtils.h
index 233adae..f8e8a0a 100644
--- a/libs/hwui/utils/PaintUtils.h
+++ b/libs/hwui/utils/PaintUtils.h
@@ -20,6 +20,7 @@
#include <SkColorFilter.h>
#include <SkDrawLooper.h>
+#include <SkPaint.h>
#include <SkShader.h>
namespace android {