BakedOpDispatcherTests.cpp revision 92a5d4b99a5554adca0e94627d44d2bd7f4f0bc0
1419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik/* 2419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik * Copyright (C) 2016 The Android Open Source Project 3419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik * 4419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik * Licensed under the Apache License, Version 2.0 (the "License"); 5419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik * you may not use this file except in compliance with the License. 6419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik * You may obtain a copy of the License at 7419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik * 8419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik * http://www.apache.org/licenses/LICENSE-2.0 9419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik * 10419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik * Unless required by applicable law or agreed to in writing, software 11419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik * distributed under the License is distributed on an "AS IS" BASIS, 12419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik * See the License for the specific language governing permissions and 14419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik * limitations under the License. 15419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik */ 16419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik 17419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik#include <gtest/gtest.h> 18419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik 19419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik#include <RecordedOp.h> 20419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik#include <BakedOpDispatcher.h> 21419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik#include <BakedOpRenderer.h> 22419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik#include <tests/common/TestUtils.h> 23419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik 24419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craikusing namespace android::uirenderer; 25419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik 26419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craikstatic BakedOpRenderer::LightInfo sLightInfo; 27419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craikstatic Rect sBaseClip(100, 100); 28419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik 29419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craikclass ValidatingBakedOpRenderer : public BakedOpRenderer { 30419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craikpublic: 31419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik ValidatingBakedOpRenderer(RenderState& renderState, std::function<void(const Glop& glop)> validator) 32419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik : BakedOpRenderer(Caches::getInstance(), renderState, true, sLightInfo) 33419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik , mValidator(validator) { 34419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik mGlopReceiver = ValidatingGlopReceiver; 35419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik } 36419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craikprivate: 37419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik static void ValidatingGlopReceiver(BakedOpRenderer& renderer, const Rect* dirtyBounds, 38419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik const ClipBase* clip, const Glop& glop) { 39419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik 40419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik auto vbor = reinterpret_cast<ValidatingBakedOpRenderer*>(&renderer); 41419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik vbor->mValidator(glop); 42419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik } 43419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik std::function<void(const Glop& glop)> mValidator; 44419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik}; 45419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik 46419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craiktypedef void (*BakedOpReceiver)(BakedOpRenderer&, const BakedOpState&); 47419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik 48419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craikstatic void testUnmergedGlopDispatch(renderthread::RenderThread& renderThread, RecordedOp* op, 49419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik std::function<void(const Glop& glop)> glopVerifier) { 50419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik // Create op, and wrap with basic state. 51419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik LinearAllocator allocator; 52419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik auto snapshot = TestUtils::makeSnapshot(Matrix4::identity(), sBaseClip); 53419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik auto state = BakedOpState::tryConstruct(allocator, *snapshot, *op); 54419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik ASSERT_NE(nullptr, state); 55419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik 56419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik int glopCount = 0; 57419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik auto glopReceiver = [&glopVerifier, &glopCount] (const Glop& glop) { 58419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik ASSERT_EQ(glopCount++, 0) << "Only one Glop expected"; 59419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik glopVerifier(glop); 60419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik }; 61419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik ValidatingBakedOpRenderer renderer(renderThread.renderState(), glopReceiver); 62419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik 63419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik // Dispatch based on op type created, similar to Frame/LayerBuilder dispatch behavior 64419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik#define X(Type) \ 65419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik [](BakedOpRenderer& renderer, const BakedOpState& state) { \ 66419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik BakedOpDispatcher::on##Type(renderer, static_cast<const Type&>(*(state.op)), state); \ 67419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik }, 68419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik static BakedOpReceiver unmergedReceivers[] = BUILD_RENDERABLE_OP_LUT(X); 69419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik#undef X 70419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik unmergedReceivers[op->opId](renderer, *state); 71419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik ASSERT_EQ(1, glopCount) << "Exactly one Glop expected"; 72419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik} 73419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik 74419a1e7ef53468e494d21c66ea7f63c0c522d208Chris CraikRENDERTHREAD_TEST(BakedOpDispatcher, onArc_position) { 75419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik SkPaint strokePaint; 76419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik strokePaint.setStyle(SkPaint::kStroke_Style); 77419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik strokePaint.setStrokeWidth(4); 78419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik ArcOp op(Rect(10, 15, 20, 25), Matrix4::identity(), nullptr, &strokePaint, 0, 270, true); 79419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik testUnmergedGlopDispatch(renderThread, &op, [] (const Glop& glop) { 80419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik // validate glop produced by renderPathTexture (so texture, unit quad) 81419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik auto texture = glop.fill.texture.texture; 82419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik ASSERT_NE(nullptr, texture); 83419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik float expectedOffset = floor(4 * 1.5f + 0.5f); 84419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik EXPECT_EQ(expectedOffset, reinterpret_cast<PathTexture*>(texture)->offset) 85419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik << "Should see conservative offset from PathCache::computeBounds"; 86419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik Rect expectedBounds(10, 15, 20, 25); 87419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik expectedBounds.outset(expectedOffset); 8870969ccde405ea410fc7ccfe869999a03f056686Chris Craik#if !HWUI_NEW_OPS 89419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik EXPECT_EQ(expectedBounds, glop.bounds) << "bounds outset by stroke 'offset'"; 9070969ccde405ea410fc7ccfe869999a03f056686Chris Craik#endif 91419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik Matrix4 expectedModelView; 92419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik expectedModelView.loadTranslate(10 - expectedOffset, 15 - expectedOffset, 0); 93419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik expectedModelView.scale(10 + 2 * expectedOffset, 10 + 2 * expectedOffset, 1); 94419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik EXPECT_EQ(expectedModelView, glop.transform.modelView) 95419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik << "X and Y offsets, and scale both applied to model view"; 96419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik }); 97419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik} 98419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik 99419a1e7ef53468e494d21c66ea7f63c0c522d208Chris CraikRENDERTHREAD_TEST(BakedOpDispatcher, onLayerOp_bufferless) { 100419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik SkPaint layerPaint; 101419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik layerPaint.setAlpha(128); 102419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik OffscreenBuffer* buffer = nullptr; // no providing a buffer, should hit rect fallback case 103419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik LayerOp op(Rect(10, 10), Matrix4::identity(), nullptr, &layerPaint, &buffer); 104419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik testUnmergedGlopDispatch(renderThread, &op, [&renderThread] (const Glop& glop) { 105419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik // rect glop is dispatched with paint props applied 106419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik EXPECT_EQ(renderThread.renderState().meshState().getUnitQuadVBO(), 107419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik glop.mesh.vertices.bufferObject) << "Unit quad should be drawn"; 108419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik EXPECT_EQ(nullptr, glop.fill.texture.texture) << "Should be no texture when layer is null"; 109419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik EXPECT_FLOAT_EQ(128 / 255.0f, glop.fill.color.a) << "Rect quad should use op alpha"; 110419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik }); 111419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik} 11292a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv 11392a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyvstatic int getGlopTransformFlags(renderthread::RenderThread& renderThread, RecordedOp* op) { 11492a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv int result = 0; 11592a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv testUnmergedGlopDispatch(renderThread, op, [&result] (const Glop& glop) { 11692a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv result = glop.transform.transformFlags; 11792a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv }); 11892a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv return result; 11992a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv} 12092a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv 12192a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyvRENDERTHREAD_TEST(BakedOpDispatcher, offsetFlags) { 12292a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv Rect bounds(10, 15, 20, 25); 12392a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv SkPaint paint; 12492a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv SkPaint aaPaint; 12592a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv aaPaint.setAntiAlias(true); 12692a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv 12792a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv RoundRectOp roundRectOp(bounds, Matrix4::identity(), nullptr, &paint, 0, 270); 12892a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv EXPECT_EQ(TransformFlags::None, getGlopTransformFlags(renderThread, &roundRectOp)) 12992a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv << "Expect no offset for round rect op."; 13092a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv 13192a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv const float points[4] = {0.5, 0.5, 1.0, 1.0}; 13292a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv PointsOp antiAliasedPointsOp(bounds, Matrix4::identity(), nullptr, &aaPaint, points, 4); 13392a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv EXPECT_EQ(TransformFlags::None, getGlopTransformFlags(renderThread, &antiAliasedPointsOp)) 13492a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv << "Expect no offset for AA points."; 13592a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv PointsOp pointsOp(bounds, Matrix4::identity(), nullptr, &paint, points, 4); 13692a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv EXPECT_EQ(TransformFlags::OffsetByFudgeFactor, getGlopTransformFlags(renderThread, &pointsOp)) 13792a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv << "Expect an offset for non-AA points."; 13892a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv 13992a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv LinesOp antiAliasedLinesOp(bounds, Matrix4::identity(), nullptr, &aaPaint, points, 4); 14092a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv EXPECT_EQ(TransformFlags::None, getGlopTransformFlags(renderThread, &antiAliasedLinesOp)) 14192a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv << "Expect no offset for AA lines."; 14292a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv LinesOp linesOp(bounds, Matrix4::identity(), nullptr, &paint, points, 4); 14392a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv EXPECT_EQ(TransformFlags::OffsetByFudgeFactor, getGlopTransformFlags(renderThread, &linesOp)) 14492a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv << "Expect an offset for non-AA lines."; 14592a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv}