Home | History | Annotate | Download | only in unit
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <gtest/gtest.h>
     18 
     19 #include <GrRectanizer.h>
     20 #include "pipeline/skia/VectorDrawableAtlas.h"
     21 #include "tests/common/TestUtils.h"
     22 
     23 using namespace android;
     24 using namespace android::uirenderer;
     25 using namespace android::uirenderer::renderthread;
     26 using namespace android::uirenderer::skiapipeline;
     27 
     28 RENDERTHREAD_SKIA_PIPELINE_TEST(VectorDrawableAtlas, addGetRemove) {
     29     VectorDrawableAtlas atlas(100 * 100);
     30     atlas.prepareForDraw(renderThread.getGrContext());
     31     // create 150 rects 10x10, which won't fit in the atlas (atlas can fit no more than 100 rects)
     32     const int MAX_RECTS = 150;
     33     AtlasEntry VDRects[MAX_RECTS];
     34 
     35     sk_sp<SkSurface> atlasSurface;
     36 
     37     // check we are able to allocate new rects
     38     // check that rects in the atlas do not intersect
     39     for (uint32_t i = 0; i < MAX_RECTS; i++) {
     40         VDRects[i] = atlas.requestNewEntry(10, 10, renderThread.getGrContext());
     41         if (0 == i) {
     42             atlasSurface = VDRects[0].surface;
     43         }
     44         ASSERT_TRUE(VDRects[i].key != INVALID_ATLAS_KEY);
     45         ASSERT_TRUE(VDRects[i].surface.get() != nullptr);
     46         ASSERT_TRUE(VDRects[i].rect.width() == 10 && VDRects[i].rect.height() == 10);
     47 
     48         // nothing in the atlas should intersect
     49         if (atlasSurface.get() == VDRects[i].surface.get()) {
     50             for (uint32_t j = 0; j < i; j++) {
     51                 if (atlasSurface.get() == VDRects[j].surface.get()) {
     52                     ASSERT_FALSE(VDRects[i].rect.intersect(VDRects[j].rect));
     53                 }
     54             }
     55         }
     56     }
     57 
     58     // first 1/3 rects should all be in the same surface
     59     for (uint32_t i = 1; i < MAX_RECTS / 3; i++) {
     60         ASSERT_NE(VDRects[i].key, VDRects[0].key);
     61         ASSERT_EQ(VDRects[i].surface.get(), atlasSurface.get());
     62     }
     63 
     64     // first rect is using atlas and last is a standalone surface
     65     ASSERT_NE(VDRects[0].surface.get(), VDRects[MAX_RECTS - 1].surface.get());
     66 
     67     // check getEntry returns the same surfaces that we had created
     68     for (uint32_t i = 0; i < MAX_RECTS; i++) {
     69         auto VDRect = atlas.getEntry(VDRects[i].key);
     70         ASSERT_TRUE(VDRect.key != INVALID_ATLAS_KEY);
     71         ASSERT_EQ(VDRects[i].key, VDRect.key);
     72         ASSERT_EQ(VDRects[i].surface.get(), VDRect.surface.get());
     73         ASSERT_EQ(VDRects[i].rect, VDRect.rect);
     74         atlas.releaseEntry(VDRect.key);
     75     }
     76 
     77     // check that any new rects will be allocated in the atlas, even that rectanizer is full.
     78     // rects in the atlas should not intersect.
     79     for (uint32_t i = 0; i < MAX_RECTS / 3; i++) {
     80         VDRects[i] = atlas.requestNewEntry(10, 10, renderThread.getGrContext());
     81         ASSERT_TRUE(VDRects[i].key != INVALID_ATLAS_KEY);
     82         ASSERT_EQ(VDRects[i].surface.get(), atlasSurface.get());
     83         ASSERT_TRUE(VDRects[i].rect.width() == 10 && VDRects[i].rect.height() == 10);
     84         for (uint32_t j = 0; j < i; j++) {
     85             ASSERT_FALSE(VDRects[i].rect.intersect(VDRects[j].rect));
     86         }
     87     }
     88 }
     89 
     90 RENDERTHREAD_SKIA_PIPELINE_TEST(VectorDrawableAtlas, disallowSharedSurface) {
     91     VectorDrawableAtlas atlas(100 * 100);
     92     // don't allow to use a shared surface
     93     atlas.setStorageMode(VectorDrawableAtlas::StorageMode::disallowSharedSurface);
     94     atlas.prepareForDraw(renderThread.getGrContext());
     95     // create 150 rects 10x10, which won't fit in the atlas (atlas can fit no more than 100 rects)
     96     const int MAX_RECTS = 150;
     97     AtlasEntry VDRects[MAX_RECTS];
     98 
     99     // check we are able to allocate new rects
    100     // check that rects in the atlas use unique surfaces
    101     for (uint32_t i = 0; i < MAX_RECTS; i++) {
    102         VDRects[i] = atlas.requestNewEntry(10, 10, renderThread.getGrContext());
    103         ASSERT_TRUE(VDRects[i].key != INVALID_ATLAS_KEY);
    104         ASSERT_TRUE(VDRects[i].surface.get() != nullptr);
    105         ASSERT_TRUE(VDRects[i].rect.width() == 10 && VDRects[i].rect.height() == 10);
    106 
    107         // nothing in the atlas should use the same surface
    108         for (uint32_t j = 0; j < i; j++) {
    109             ASSERT_NE(VDRects[i].surface.get(), VDRects[j].surface.get());
    110         }
    111     }
    112 }
    113 
    114 RENDERTHREAD_SKIA_PIPELINE_TEST(VectorDrawableAtlas, repack) {
    115     VectorDrawableAtlas atlas(100 * 100);
    116     ASSERT_FALSE(atlas.isFragmented());
    117     atlas.prepareForDraw(renderThread.getGrContext());
    118     ASSERT_FALSE(atlas.isFragmented());
    119     // create 150 rects 10x10, which won't fit in the atlas (atlas can fit no more than 100 rects)
    120     const int MAX_RECTS = 150;
    121     AtlasEntry VDRects[MAX_RECTS];
    122 
    123     sk_sp<SkSurface> atlasSurface;
    124 
    125     // fill the atlas with check we are able to allocate new rects
    126     for (uint32_t i = 0; i < MAX_RECTS; i++) {
    127         VDRects[i] = atlas.requestNewEntry(10, 10, renderThread.getGrContext());
    128         if (0 == i) {
    129             atlasSurface = VDRects[0].surface;
    130         }
    131         ASSERT_TRUE(VDRects[i].key != INVALID_ATLAS_KEY);
    132     }
    133 
    134     ASSERT_FALSE(atlas.isFragmented());
    135 
    136     // first 1/3 rects should all be in the same surface
    137     for (uint32_t i = 1; i < MAX_RECTS / 3; i++) {
    138         ASSERT_NE(VDRects[i].key, VDRects[0].key);
    139         ASSERT_EQ(VDRects[i].surface.get(), atlasSurface.get());
    140     }
    141 
    142     // release all entries
    143     for (uint32_t i = 0; i < MAX_RECTS; i++) {
    144         auto VDRect = atlas.getEntry(VDRects[i].key);
    145         ASSERT_TRUE(VDRect.key != INVALID_ATLAS_KEY);
    146         atlas.releaseEntry(VDRect.key);
    147     }
    148 
    149     ASSERT_FALSE(atlas.isFragmented());
    150 
    151     // allocate 4x4 rects, which will fragment the atlas badly, because each entry occupies a 10x10
    152     // area
    153     for (uint32_t i = 0; i < 4 * MAX_RECTS; i++) {
    154         AtlasEntry entry = atlas.requestNewEntry(4, 4, renderThread.getGrContext());
    155         ASSERT_TRUE(entry.key != INVALID_ATLAS_KEY);
    156     }
    157 
    158     ASSERT_TRUE(atlas.isFragmented());
    159 
    160     atlas.repackIfNeeded(renderThread.getGrContext());
    161 
    162     ASSERT_FALSE(atlas.isFragmented());
    163 }