remove unneeded RecordedOps

Test: make

Change-Id: Ifcb0df64ad649623ae875462f55d9009a4e1ac03
This commit is contained in:
Mike Reed
2018-05-09 09:16:40 -04:00
parent 293cd1027b
commit faaf6872b1
12 changed files with 1 additions and 1083 deletions

View File

@@ -206,15 +206,12 @@ cc_defaults {
"FrameInfoVisualizer.cpp",
"GlLayer.cpp",
"GpuMemoryTracker.cpp",
"Image.cpp",
"Interpolator.cpp",
"JankTracker.cpp",
"Layer.cpp",
"LayerUpdateQueue.cpp",
"Matrix.cpp",
"OpDumper.cpp",
"EglReadback.cpp",
"Patch.cpp",
"PathParser.cpp",
"PixelBuffer.cpp",
"ProfileData.cpp",
@@ -318,7 +315,6 @@ cc_test {
"tests/unit/LayerUpdateQueueTests.cpp",
"tests/unit/LinearAllocatorTests.cpp",
"tests/unit/MatrixTests.cpp",
"tests/unit/OpDumperTests.cpp",
"tests/unit/PathInterpolatorTests.cpp",
"tests/unit/RenderNodeDrawableTests.cpp",
"tests/unit/RenderNodeTests.cpp",

View File

@@ -1,61 +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 <utils/Log.h>
#include "Caches.h"
#include "Image.h"
namespace android {
namespace uirenderer {
Image::Image(sp<GraphicBuffer> buffer) {
// Create the EGLImage object that maps the GraphicBuffer
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
EGLClientBuffer clientBuffer = (EGLClientBuffer)buffer->getNativeBuffer();
EGLint attrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE};
mImage = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, clientBuffer,
attrs);
if (mImage == EGL_NO_IMAGE_KHR) {
ALOGW("Error creating image (%#x)", eglGetError());
mTexture = 0;
} else {
// Create a 2D texture to sample from the EGLImage
glGenTextures(1, &mTexture);
Caches::getInstance().textureState().bindTexture(mTexture);
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, mImage);
GLenum status = GL_NO_ERROR;
while ((status = glGetError()) != GL_NO_ERROR) {
ALOGW("Error creating image (%#x)", status);
}
}
}
Image::~Image() {
if (mImage != EGL_NO_IMAGE_KHR) {
eglDestroyImageKHR(eglGetDisplay(EGL_DEFAULT_DISPLAY), mImage);
mImage = EGL_NO_IMAGE_KHR;
Caches::getInstance().textureState().deleteTexture(mTexture);
mTexture = 0;
}
}
}; // namespace uirenderer
}; // namespace android

View File

@@ -1,63 +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_IMAGE_H
#define ANDROID_HWUI_IMAGE_H
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <ui/GraphicBuffer.h>
namespace android {
namespace uirenderer {
/**
* A simple wrapper that creates an EGLImage and a texture for a GraphicBuffer.
*/
class Image {
public:
/**
* Creates a new image from the specified graphic buffer. If the image
* cannot be created, getTexture() will return 0 and getImage() will
* return EGL_NO_IMAGE_KHR.
*/
explicit Image(sp<GraphicBuffer> buffer);
~Image();
/**
* Returns the name of the GL texture that can be used to sample
* from this image.
*/
GLuint getTexture() const { return mTexture; }
/**
* Returns the name of the EGL image represented by this object.
*/
EGLImageKHR getImage() const { return mImage; }
private:
GLuint mTexture;
EGLImageKHR mImage;
}; // class Image
}; // namespace uirenderer
}; // namespace android
#endif // ANDROID_HWUI_IMAGE_H

View File

@@ -1,53 +0,0 @@
/*
* Copyright (C) 2016 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 "OpDumper.h"
#include "ClipArea.h"
#include "RecordedOp.h"
namespace android {
namespace uirenderer {
#define STRINGIFY(n) #n,
static const char* sOpNameLut[] = BUILD_FULL_OP_LUT(STRINGIFY);
void OpDumper::dump(const RecordedOp& op, std::ostream& output, int level) {
for (int i = 0; i < level; i++) {
output << " ";
}
Rect localBounds(op.unmappedBounds);
op.localMatrix.mapRect(localBounds);
output << sOpNameLut[op.opId] << " " << localBounds;
if (op.localClip &&
(!op.localClip->rect.contains(localBounds) || op.localClip->intersectWithRoot)) {
output << std::fixed << std::setprecision(0) << " clip=" << op.localClip->rect
<< " mode=" << (int)op.localClip->mode;
if (op.localClip->intersectWithRoot) {
output << " iwr";
}
}
}
const char* OpDumper::opName(const RecordedOp& op) {
return sOpNameLut[op.opId];
}
} // namespace uirenderer
} // namespace android

View File

@@ -1,33 +0,0 @@
/*
* Copyright (C) 2016 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 <ostream>
namespace android {
namespace uirenderer {
struct RecordedOp;
class OpDumper {
public:
static void dump(const RecordedOp& op, std::ostream& output, int level = 0);
static const char* opName(const RecordedOp& op);
};
}; // namespace uirenderer
}; // namespace android

View File

@@ -1,229 +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 "Patch.h"
#include "Caches.h"
#include "Properties.h"
#include "UvMapper.h"
#include "utils/MathUtils.h"
#include <utils/Log.h>
#include <algorithm>
namespace android {
namespace uirenderer {
///////////////////////////////////////////////////////////////////////////////
// Vertices management
///////////////////////////////////////////////////////////////////////////////
uint32_t Patch::getSize() const {
return verticesCount * sizeof(TextureVertex);
}
Patch::Patch(const float bitmapWidth, const float bitmapHeight, float width, float height,
const UvMapper& mapper, const Res_png_9patch* patch)
: mColors(patch->getColors()) {
int8_t emptyQuads = 0;
const int8_t numColors = patch->numColors;
if (uint8_t(numColors) < sizeof(uint32_t) * 4) {
for (int8_t i = 0; i < numColors; i++) {
if (mColors[i] == 0x0) {
emptyQuads++;
}
}
}
hasEmptyQuads = emptyQuads > 0;
uint32_t xCount = patch->numXDivs;
uint32_t yCount = patch->numYDivs;
uint32_t maxVertices = ((xCount + 1) * (yCount + 1) - emptyQuads) * 4;
if (maxVertices == 0) return;
vertices.reset(new TextureVertex[maxVertices]);
TextureVertex* vertex = vertices.get();
const int32_t* xDivs = patch->getXDivs();
const int32_t* yDivs = patch->getYDivs();
const uint32_t xStretchCount = (xCount + 1) >> 1;
const uint32_t yStretchCount = (yCount + 1) >> 1;
float stretchX = 0.0f;
float stretchY = 0.0f;
float rescaleX = 1.0f;
float rescaleY = 1.0f;
if (xStretchCount > 0) {
uint32_t stretchSize = 0;
for (uint32_t i = 1; i < xCount; i += 2) {
stretchSize += xDivs[i] - xDivs[i - 1];
}
const float xStretchTex = stretchSize;
const float fixed = bitmapWidth - stretchSize;
const float xStretch = std::max(width - fixed, 0.0f);
stretchX = xStretch / xStretchTex;
rescaleX = fixed == 0.0f ? 0.0f : std::min(std::max(width, 0.0f) / fixed, 1.0f);
}
if (yStretchCount > 0) {
uint32_t stretchSize = 0;
for (uint32_t i = 1; i < yCount; i += 2) {
stretchSize += yDivs[i] - yDivs[i - 1];
}
const float yStretchTex = stretchSize;
const float fixed = bitmapHeight - stretchSize;
const float yStretch = std::max(height - fixed, 0.0f);
stretchY = yStretch / yStretchTex;
rescaleY = fixed == 0.0f ? 0.0f : std::min(std::max(height, 0.0f) / fixed, 1.0f);
}
uint32_t quadCount = 0;
float previousStepY = 0.0f;
float y1 = 0.0f;
float y2 = 0.0f;
float v1 = 0.0f;
mUvMapper = mapper;
for (uint32_t i = 0; i < yCount; i++) {
float stepY = yDivs[i];
const float segment = stepY - previousStepY;
if (i & 1) {
y2 = y1 + floorf(segment * stretchY + 0.5f);
} else {
y2 = y1 + segment * rescaleY;
}
float vOffset = y1 == y2 ? 0.0f : 0.5 - (0.5 * segment / (y2 - y1));
float v2 = std::max(0.0f, stepY - vOffset) / bitmapHeight;
v1 += vOffset / bitmapHeight;
if (stepY > 0.0f) {
generateRow(xDivs, xCount, vertex, y1, y2, v1, v2, stretchX, rescaleX, width,
bitmapWidth, quadCount);
}
y1 = y2;
v1 = stepY / bitmapHeight;
previousStepY = stepY;
}
if (previousStepY != bitmapHeight) {
y2 = height;
generateRow(xDivs, xCount, vertex, y1, y2, v1, 1.0f, stretchX, rescaleX, width, bitmapWidth,
quadCount);
}
if (verticesCount != maxVertices) {
std::unique_ptr<TextureVertex[]> reducedVertices(new TextureVertex[verticesCount]);
memcpy(reducedVertices.get(), vertices.get(), verticesCount * sizeof(TextureVertex));
vertices = std::move(reducedVertices);
}
}
void Patch::generateRow(const int32_t* xDivs, uint32_t xCount, TextureVertex*& vertex, float y1,
float y2, float v1, float v2, float stretchX, float rescaleX, float width,
float bitmapWidth, uint32_t& quadCount) {
float previousStepX = 0.0f;
float x1 = 0.0f;
float x2 = 0.0f;
float u1 = 0.0f;
// Generate the row quad by quad
for (uint32_t i = 0; i < xCount; i++) {
float stepX = xDivs[i];
const float segment = stepX - previousStepX;
if (i & 1) {
x2 = x1 + floorf(segment * stretchX + 0.5f);
} else {
x2 = x1 + segment * rescaleX;
}
float uOffset = x1 == x2 ? 0.0f : 0.5 - (0.5 * segment / (x2 - x1));
float u2 = std::max(0.0f, stepX - uOffset) / bitmapWidth;
u1 += uOffset / bitmapWidth;
if (stepX > 0.0f) {
generateQuad(vertex, x1, y1, x2, y2, u1, v1, u2, v2, quadCount);
}
x1 = x2;
u1 = stepX / bitmapWidth;
previousStepX = stepX;
}
if (previousStepX != bitmapWidth) {
x2 = width;
generateQuad(vertex, x1, y1, x2, y2, u1, v1, 1.0f, v2, quadCount);
}
}
void Patch::generateQuad(TextureVertex*& vertex, float x1, float y1, float x2, float y2, float u1,
float v1, float u2, float v2, uint32_t& quadCount) {
const uint32_t oldQuadCount = quadCount;
quadCount++;
x1 = std::max(x1, 0.0f);
x2 = std::max(x2, 0.0f);
y1 = std::max(y1, 0.0f);
y2 = std::max(y2, 0.0f);
// Skip degenerate and transparent (empty) quads
if ((mColors[oldQuadCount] == 0) || x1 >= x2 || y1 >= y2) {
#if DEBUG_PATCHES_EMPTY_VERTICES
PATCH_LOGD(" quad %d (empty)", oldQuadCount);
PATCH_LOGD(" left, top = %.2f, %.2f\t\tu1, v1 = %.8f, %.8f", x1, y1, u1, v1);
PATCH_LOGD(" right, bottom = %.2f, %.2f\t\tu2, v2 = %.8f, %.8f", x2, y2, u2, v2);
#endif
return;
}
// Record all non empty quads
if (hasEmptyQuads) {
quads.emplace_back(x1, y1, x2, y2);
}
mUvMapper.map(u1, v1, u2, v2);
TextureVertex::set(vertex++, x1, y1, u1, v1);
TextureVertex::set(vertex++, x2, y1, u2, v1);
TextureVertex::set(vertex++, x1, y2, u1, v2);
TextureVertex::set(vertex++, x2, y2, u2, v2);
verticesCount += 4;
indexCount += 6;
#if DEBUG_PATCHES_VERTICES
PATCH_LOGD(" quad %d", oldQuadCount);
PATCH_LOGD(" left, top = %.2f, %.2f\t\tu1, v1 = %.8f, %.8f", x1, y1, u1, v1);
PATCH_LOGD(" right, bottom = %.2f, %.2f\t\tu2, v2 = %.8f, %.8f", x2, y2, u2, v2);
#endif
}
}; // namespace uirenderer
}; // namespace android

View File

@@ -1,73 +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_PATCH_H
#define ANDROID_HWUI_PATCH_H
#include <sys/types.h>
#include <GLES2/gl2.h>
#include <androidfw/ResourceTypes.h>
#include "Rect.h"
#include "UvMapper.h"
#include <vector>
namespace android {
namespace uirenderer {
struct TextureVertex;
///////////////////////////////////////////////////////////////////////////////
// 9-patch structures
///////////////////////////////////////////////////////////////////////////////
class Patch {
public:
Patch(const float bitmapWidth, const float bitmapHeight, float width, float height,
const UvMapper& mapper, const Res_png_9patch* patch);
/**
* Returns the size of this patch's mesh in bytes.
*/
uint32_t getSize() const;
std::unique_ptr<TextureVertex[]> vertices;
uint32_t verticesCount = 0;
uint32_t indexCount = 0;
bool hasEmptyQuads = false;
std::vector<Rect> quads;
GLintptr positionOffset = 0;
GLintptr textureOffset = 0;
private:
void generateRow(const int32_t* xDivs, uint32_t xCount, TextureVertex*& vertex, float y1,
float y2, float v1, float v2, float stretchX, float rescaleX, float width,
float bitmapWidth, uint32_t& quadCount);
void generateQuad(TextureVertex*& vertex, float x1, float y1, float x2, float y2, float u1,
float v1, float u2, float v2, uint32_t& quadCount);
const uint32_t* mColors;
UvMapper mUvMapper;
}; // struct Patch
}; // namespace uirenderer
}; // namespace android
#endif // ANDROID_HWUI_PATCH_H

View File

@@ -1,481 +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.
*/
#pragma once
#include "GlLayer.h"
#include "Matrix.h"
#include "Rect.h"
#include "RenderNode.h"
#include "Vector.h"
#include "utils/LinearAllocator.h"
#include "utils/PaintUtils.h"
#include <androidfw/ResourceTypes.h>
class SkBitmap;
class SkPaint;
namespace android {
namespace uirenderer {
struct ClipBase;
class OffscreenBuffer;
class RenderNode;
class DeferredLayerUpdater;
typedef uint16_t glyph_t;
struct Vertex;
namespace VectorDrawable {
class Tree;
}
/**
* Authoritative op list, used for generating the op ID enum, ID based LUTS, and
* the functions to which they dispatch. Parameter macros are executed for each op,
* in order, based on the op's type.
*
* There are 4 types of op, which defines dispatch/LUT capability:
*
* | DisplayList | Render | Merge |
* -------------|-------------|-------------|-------------|
* PRE RENDER | Yes | | |
* RENDER ONLY | | Yes | |
* UNMERGEABLE | Yes | Yes | |
* MERGEABLE | Yes | Yes | Yes |
*
* PRE RENDER - These ops are recorded into DisplayLists, but can't be directly rendered. This
* may be because they need to be transformed into other op types (e.g. CirclePropsOp),
* be traversed to access multiple renderable ops within (e.g. RenderNodeOp), or because they
* modify renderbuffer lifecycle, instead of directly rendering content (the various LayerOps).
*
* RENDER ONLY - These ops cannot be recorded into DisplayLists, and are instead implicitly
* constructed from other commands/RenderNode properties. They cannot be merged.
*
* UNMERGEABLE - These ops can be recorded into DisplayLists and rendered directly, but do not
* support merged rendering.
*
* MERGEABLE - These ops can be recorded into DisplayLists and rendered individually, or merged
* under certain circumstances.
*/
#define MAP_OPS_BASED_ON_TYPE(PRE_RENDER_OP_FN, RENDER_ONLY_OP_FN, UNMERGEABLE_OP_FN, \
MERGEABLE_OP_FN) \
PRE_RENDER_OP_FN(RenderNodeOp) \
PRE_RENDER_OP_FN(CirclePropsOp) \
PRE_RENDER_OP_FN(RoundRectPropsOp) \
PRE_RENDER_OP_FN(BeginLayerOp) \
PRE_RENDER_OP_FN(EndLayerOp) \
PRE_RENDER_OP_FN(BeginUnclippedLayerOp) \
PRE_RENDER_OP_FN(EndUnclippedLayerOp) \
PRE_RENDER_OP_FN(VectorDrawableOp) \
\
RENDER_ONLY_OP_FN(LayerOp) \
RENDER_ONLY_OP_FN(CopyToLayerOp) \
RENDER_ONLY_OP_FN(CopyFromLayerOp) \
\
UNMERGEABLE_OP_FN(ArcOp) \
UNMERGEABLE_OP_FN(BitmapMeshOp) \
UNMERGEABLE_OP_FN(BitmapRectOp) \
UNMERGEABLE_OP_FN(ColorOp) \
UNMERGEABLE_OP_FN(FunctorOp) \
UNMERGEABLE_OP_FN(LinesOp) \
UNMERGEABLE_OP_FN(OvalOp) \
UNMERGEABLE_OP_FN(PathOp) \
UNMERGEABLE_OP_FN(PointsOp) \
UNMERGEABLE_OP_FN(RectOp) \
UNMERGEABLE_OP_FN(RoundRectOp) \
UNMERGEABLE_OP_FN(SimpleRectsOp) \
UNMERGEABLE_OP_FN(TextOnPathOp) \
UNMERGEABLE_OP_FN(TextureLayerOp) \
\
MERGEABLE_OP_FN(BitmapOp) \
MERGEABLE_OP_FN(PatchOp) \
MERGEABLE_OP_FN(TextOp)
/**
* LUT generators, which will insert nullptr for unsupported ops
*/
#define NULLPTR_OP_FN(Type) nullptr,
#define BUILD_DEFERRABLE_OP_LUT(OP_FN) \
{ MAP_OPS_BASED_ON_TYPE(OP_FN, NULLPTR_OP_FN, OP_FN, OP_FN) }
#define BUILD_MERGEABLE_OP_LUT(OP_FN) \
{ MAP_OPS_BASED_ON_TYPE(NULLPTR_OP_FN, NULLPTR_OP_FN, NULLPTR_OP_FN, OP_FN) }
#define BUILD_RENDERABLE_OP_LUT(OP_FN) \
{ MAP_OPS_BASED_ON_TYPE(NULLPTR_OP_FN, OP_FN, OP_FN, OP_FN) }
#define BUILD_FULL_OP_LUT(OP_FN) \
{ MAP_OPS_BASED_ON_TYPE(OP_FN, OP_FN, OP_FN, OP_FN) }
/**
* Op mapping functions, which skip unsupported ops.
*
* Note: Do not use for LUTS, since these do not preserve ID order.
*/
#define NULL_OP_FN(Type)
#define MAP_DEFERRABLE_OPS(OP_FN) MAP_OPS_BASED_ON_TYPE(OP_FN, NULL_OP_FN, OP_FN, OP_FN)
#define MAP_MERGEABLE_OPS(OP_FN) MAP_OPS_BASED_ON_TYPE(NULL_OP_FN, NULL_OP_FN, NULL_OP_FN, OP_FN)
#define MAP_RENDERABLE_OPS(OP_FN) MAP_OPS_BASED_ON_TYPE(NULL_OP_FN, OP_FN, OP_FN, OP_FN)
// Generate OpId enum
#define IDENTITY_FN(Type) Type,
namespace RecordedOpId {
enum {
MAP_OPS_BASED_ON_TYPE(IDENTITY_FN, IDENTITY_FN, IDENTITY_FN, IDENTITY_FN) Count,
};
}
static_assert(RecordedOpId::RenderNodeOp == 0, "First index must be zero for LUTs to work");
#define BASE_PARAMS \
const Rect &unmappedBounds, const Matrix4 &localMatrix, const ClipBase *localClip, \
const SkPaint *paint
#define BASE_PARAMS_PAINTLESS \
const Rect &unmappedBounds, const Matrix4 &localMatrix, const ClipBase *localClip
#define SUPER(Type) RecordedOp(RecordedOpId::Type, unmappedBounds, localMatrix, localClip, paint)
#define SUPER_PAINTLESS(Type) \
RecordedOp(RecordedOpId::Type, unmappedBounds, localMatrix, localClip, nullptr)
struct RecordedOp {
/* ID from RecordedOpId - generally used for jumping into function tables */
const int opId;
/* bounds in *local* space, without accounting for DisplayList transformation, or stroke */
const Rect unmappedBounds;
/* transform in recording space (vs DisplayList origin) */
const Matrix4 localMatrix;
/* clip in recording space - nullptr if not clipped */
const ClipBase* localClip;
/* optional paint, stored in base object to simplify merging logic */
const SkPaint* paint;
protected:
RecordedOp(unsigned int opId, BASE_PARAMS)
: opId(opId)
, unmappedBounds(unmappedBounds)
, localMatrix(localMatrix)
, localClip(localClip)
, paint(paint) {}
};
struct RenderNodeOp : RecordedOp {
RenderNodeOp(BASE_PARAMS_PAINTLESS, RenderNode* renderNode)
: SUPER_PAINTLESS(RenderNodeOp), renderNode(renderNode) {}
RenderNode* renderNode; // not const, since drawing modifies it
/**
* Holds the transformation between the projection surface ViewGroup and this RenderNode
* drawing instance. Represents any translations / transformations done within the drawing of
* the compositing ancestor ViewGroup's draw, before the draw of the View represented by this
* DisplayList draw instance.
*
* Note: doesn't include transformation within the RenderNode, or its properties.
*/
Matrix4 transformFromCompositingAncestor;
bool skipInOrderDraw = false;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
// Standard Ops
////////////////////////////////////////////////////////////////////////////////////////////////////
struct ArcOp : RecordedOp {
ArcOp(BASE_PARAMS, float startAngle, float sweepAngle, bool useCenter)
: SUPER(ArcOp), startAngle(startAngle), sweepAngle(sweepAngle), useCenter(useCenter) {}
const float startAngle;
const float sweepAngle;
const bool useCenter;
};
struct BitmapOp : RecordedOp {
BitmapOp(BASE_PARAMS, Bitmap* bitmap) : SUPER(BitmapOp), bitmap(bitmap) {}
Bitmap* bitmap;
};
struct BitmapMeshOp : RecordedOp {
BitmapMeshOp(BASE_PARAMS, Bitmap* bitmap, int meshWidth, int meshHeight, const float* vertices,
const int* colors)
: SUPER(BitmapMeshOp)
, bitmap(bitmap)
, meshWidth(meshWidth)
, meshHeight(meshHeight)
, vertices(vertices)
, colors(colors) {}
Bitmap* bitmap;
const int meshWidth;
const int meshHeight;
const float* vertices;
const int* colors;
};
struct BitmapRectOp : RecordedOp {
BitmapRectOp(BASE_PARAMS, Bitmap* bitmap, const Rect& src)
: SUPER(BitmapRectOp), bitmap(bitmap), src(src) {}
Bitmap* bitmap;
const Rect src;
};
struct CirclePropsOp : RecordedOp {
CirclePropsOp(const Matrix4& localMatrix, const ClipBase* localClip, const SkPaint* paint,
float* x, float* y, float* radius)
: RecordedOp(RecordedOpId::CirclePropsOp, Rect(), localMatrix, localClip, paint)
, x(x)
, y(y)
, radius(radius) {}
const float* x;
const float* y;
const float* radius;
};
struct ColorOp : RecordedOp {
// Note: unbounded op that will fillclip, so no bounds/matrix needed
ColorOp(const ClipBase* localClip, int color, SkBlendMode mode)
: RecordedOp(RecordedOpId::ColorOp, Rect(), Matrix4::identity(), localClip, nullptr)
, color(color)
, mode(mode) {}
const int color;
const SkBlendMode mode;
};
struct FunctorOp : RecordedOp {
// Note: undefined record-time bounds, since this op fills the clip
// TODO: explicitly define bounds
FunctorOp(const Matrix4& localMatrix, const ClipBase* localClip, Functor* functor)
: RecordedOp(RecordedOpId::FunctorOp, Rect(), localMatrix, localClip, nullptr)
, functor(functor) {}
Functor* functor;
};
struct LinesOp : RecordedOp {
LinesOp(BASE_PARAMS, const float* points, const int floatCount)
: SUPER(LinesOp), points(points), floatCount(floatCount) {}
const float* points;
const int floatCount;
};
struct OvalOp : RecordedOp {
OvalOp(BASE_PARAMS) : SUPER(OvalOp) {}
};
struct PatchOp : RecordedOp {
PatchOp(BASE_PARAMS, Bitmap* bitmap, const Res_png_9patch* patch)
: SUPER(PatchOp), bitmap(bitmap), patch(patch) {}
Bitmap* bitmap;
const Res_png_9patch* patch;
};
struct PathOp : RecordedOp {
PathOp(BASE_PARAMS, const SkPath* path) : SUPER(PathOp), path(path) {}
const SkPath* path;
};
struct PointsOp : RecordedOp {
PointsOp(BASE_PARAMS, const float* points, const int floatCount)
: SUPER(PointsOp), points(points), floatCount(floatCount) {}
const float* points;
const int floatCount;
};
struct RectOp : RecordedOp {
RectOp(BASE_PARAMS) : SUPER(RectOp) {}
};
struct RoundRectOp : RecordedOp {
RoundRectOp(BASE_PARAMS, float rx, float ry) : SUPER(RoundRectOp), rx(rx), ry(ry) {}
const float rx;
const float ry;
};
struct RoundRectPropsOp : RecordedOp {
RoundRectPropsOp(const Matrix4& localMatrix, const ClipBase* localClip, const SkPaint* paint,
float* left, float* top, float* right, float* bottom, float* rx, float* ry)
: RecordedOp(RecordedOpId::RoundRectPropsOp, Rect(), localMatrix, localClip, paint)
, left(left)
, top(top)
, right(right)
, bottom(bottom)
, rx(rx)
, ry(ry) {}
const float* left;
const float* top;
const float* right;
const float* bottom;
const float* rx;
const float* ry;
};
struct VectorDrawableOp : RecordedOp {
VectorDrawableOp(VectorDrawable::Tree* tree, BASE_PARAMS_PAINTLESS)
: SUPER_PAINTLESS(VectorDrawableOp), vectorDrawable(tree) {}
VectorDrawable::Tree* vectorDrawable;
};
struct SimpleRectsOp : RecordedOp { // Filled, no AA (TODO: better name?)
SimpleRectsOp(BASE_PARAMS, Vertex* vertices, size_t vertexCount)
: SUPER(SimpleRectsOp), vertices(vertices), vertexCount(vertexCount) {}
Vertex* vertices;
const size_t vertexCount;
};
struct TextOp : RecordedOp {
TextOp(BASE_PARAMS, const glyph_t* glyphs, const float* positions, int glyphCount, float x,
float y)
: SUPER(TextOp)
, glyphs(glyphs)
, positions(positions)
, glyphCount(glyphCount)
, x(x)
, y(y) {}
const glyph_t* glyphs;
const float* positions;
const int glyphCount;
const float x;
const float y;
};
struct TextOnPathOp : RecordedOp {
// TODO: explicitly define bounds
TextOnPathOp(const Matrix4& localMatrix, const ClipBase* localClip, const SkPaint* paint,
const glyph_t* glyphs, int glyphCount, const SkPath* path, float hOffset,
float vOffset)
: RecordedOp(RecordedOpId::TextOnPathOp, Rect(), localMatrix, localClip, paint)
, glyphs(glyphs)
, glyphCount(glyphCount)
, path(path)
, hOffset(hOffset)
, vOffset(vOffset) {}
const glyph_t* glyphs;
const int glyphCount;
const SkPath* path;
const float hOffset;
const float vOffset;
};
struct TextureLayerOp : RecordedOp {
TextureLayerOp(BASE_PARAMS_PAINTLESS, DeferredLayerUpdater* layer)
: SUPER_PAINTLESS(TextureLayerOp), layerHandle(layer) {}
// Copy an existing TextureLayerOp, replacing the underlying matrix
TextureLayerOp(const TextureLayerOp& op, const Matrix4& replacementMatrix)
: RecordedOp(RecordedOpId::TextureLayerOp, op.unmappedBounds, replacementMatrix,
op.localClip, op.paint)
, layerHandle(op.layerHandle) {}
DeferredLayerUpdater* layerHandle;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
// Layers
////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Stateful operation! denotes the creation of an off-screen layer,
* and that commands following will render into it.
*/
struct BeginLayerOp : RecordedOp {
BeginLayerOp(BASE_PARAMS) : SUPER(BeginLayerOp) {}
};
/**
* Stateful operation! Denotes end of off-screen layer, and that
* commands since last BeginLayerOp should be drawn into parent FBO.
*
* State in this op is empty, it just serves to signal that a layer has been finished.
*/
struct EndLayerOp : RecordedOp {
EndLayerOp()
: RecordedOp(RecordedOpId::EndLayerOp, Rect(), Matrix4::identity(), nullptr, nullptr) {}
};
struct BeginUnclippedLayerOp : RecordedOp {
BeginUnclippedLayerOp(BASE_PARAMS) : SUPER(BeginUnclippedLayerOp) {}
};
struct EndUnclippedLayerOp : RecordedOp {
EndUnclippedLayerOp()
: RecordedOp(RecordedOpId::EndUnclippedLayerOp, Rect(), Matrix4::identity(), nullptr,
nullptr) {}
};
struct CopyToLayerOp : RecordedOp {
CopyToLayerOp(const RecordedOp& op, OffscreenBuffer** layerHandle)
: RecordedOp(RecordedOpId::CopyToLayerOp, op.unmappedBounds, op.localMatrix,
nullptr, // clip intentionally ignored
op.paint)
, layerHandle(layerHandle) {}
// Records a handle to the Layer object, since the Layer itself won't be
// constructed until after this operation is constructed.
OffscreenBuffer** layerHandle;
};
// draw the parameter layer underneath
struct CopyFromLayerOp : RecordedOp {
CopyFromLayerOp(const RecordedOp& op, OffscreenBuffer** layerHandle)
: RecordedOp(RecordedOpId::CopyFromLayerOp, op.unmappedBounds, op.localMatrix,
nullptr, // clip intentionally ignored
op.paint)
, layerHandle(layerHandle) {}
// Records a handle to the Layer object, since the Layer itself won't be
// constructed until after this operation is constructed.
OffscreenBuffer** layerHandle;
};
/**
* Draws an OffscreenBuffer.
*
* Alpha, mode, and colorfilter are embedded, since LayerOps are always dynamically generated,
* when creating/tracking a SkPaint* during defer isn't worth the bother.
*/
struct LayerOp : RecordedOp {
// Records a one-use (saveLayer) layer for drawing.
LayerOp(BASE_PARAMS, OffscreenBuffer** layerHandle)
: SUPER_PAINTLESS(LayerOp)
, layerHandle(layerHandle)
, alpha(paint ? paint->getAlpha() / 255.0f : 1.0f)
, mode(PaintUtils::getBlendModeDirect(paint))
, colorFilter(paint ? paint->getColorFilter() : nullptr) {}
explicit LayerOp(RenderNode& node)
: RecordedOp(RecordedOpId::LayerOp, Rect(node.getWidth(), node.getHeight()),
Matrix4::identity(), nullptr, nullptr)
, layerHandle(node.getLayerHandle())
, alpha(node.properties().layerProperties().alpha() / 255.0f)
, mode(node.properties().layerProperties().xferMode())
, colorFilter(node.properties().layerProperties().colorFilter()) {}
// Records a handle to the Layer object, since the Layer itself won't be
// constructed until after this operation is constructed.
OffscreenBuffer** layerHandle;
const float alpha;
const SkBlendMode mode;
// pointer to object owned by either LayerProperties, or a recorded Paint object in a
// BeginLayerOp. Lives longer than LayerOp in either case, so no skia ref counting is used.
SkColorFilter* colorFilter;
};
}; // namespace uirenderer
}; // namespace android

View File

@@ -18,7 +18,6 @@
#include "DamageAccumulator.h"
#include "Debug.h"
#include "RecordedOp.h"
#include "TreeInfo.h"
#include "VectorDrawable.h"
#include "renderstate/RenderState.h"

View File

@@ -74,46 +74,6 @@ struct TextureVertex {
REQUIRE_COMPATIBLE_LAYOUT(TextureVertex);
/**
* Simple structure to describe a vertex with a position, texture UV and an
* sRGB color with alpha. The color is stored pre-multiplied in linear space.
*/
struct ColorTextureVertex {
float x, y;
float u, v;
float r, g, b, a; // pre-multiplied linear
static inline void set(ColorTextureVertex* vertex, float x, float y, float u, float v,
uint32_t color) {
FloatColor c;
c.set(color);
*vertex = {x, y, u, v, c.r, c.g, c.b, c.a};
}
}; // struct ColorTextureVertex
REQUIRE_COMPATIBLE_LAYOUT(ColorTextureVertex);
/**
* Simple structure to describe a vertex with a position and an alpha value.
*/
struct AlphaVertex {
float x, y;
float alpha;
static inline void set(AlphaVertex* vertex, float x, float y, float alpha) {
*vertex = {x, y, alpha};
}
static inline void copyWithOffset(AlphaVertex* vertex, const AlphaVertex& src, float x,
float y) {
AlphaVertex::set(vertex, src.x + x, src.y + y, src.alpha);
}
static inline void setColor(AlphaVertex* vertex, float alpha) { vertex[0].alpha = alpha; }
}; // struct AlphaVertex
REQUIRE_COMPATIBLE_LAYOUT(AlphaVertex);
}; // namespace uirenderer
}; // namespace android

View File

@@ -18,6 +18,7 @@
#include <DeviceInfo.h>
#include <DisplayList.h>
#include <GlLayer.h>
#include <Matrix.h>
#include <Properties.h>
#include <Rect.h>
@@ -28,8 +29,6 @@
#include <renderstate/RenderState.h>
#include <renderthread/RenderThread.h>
#include <RecordedOp.h>
#include <memory>
namespace android {

View File

@@ -1,43 +0,0 @@
/*
* Copyright (C) 2016 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 <gtest/gtest.h>
#include "OpDumper.h"
#include "tests/common/TestUtils.h"
using namespace android;
using namespace android::uirenderer;
TEST(OpDumper, dump) {
SkPaint paint;
RectOp op(uirenderer::Rect(100, 100), Matrix4::identity(), nullptr, &paint);
std::stringstream stream;
OpDumper::dump(op, stream);
EXPECT_STREQ("RectOp [100 x 100]", stream.str().c_str());
stream.str("");
OpDumper::dump(op, stream, 2);
EXPECT_STREQ(" RectOp [100 x 100]", stream.str().c_str());
ClipRect clipRect(uirenderer::Rect(50, 50));
op.localClip = &clipRect;
stream.str("");
OpDumper::dump(op, stream, 2);
EXPECT_STREQ(" RectOp [100 x 100] clip=[50 x 50] mode=0", stream.str().c_str());
}