1 /* 2 * Copyright (C) 2015 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 #include <Rect.h> 19 #include <renderstate/OffscreenBufferPool.h> 20 21 #include <tests/common/TestUtils.h> 22 23 using namespace android::uirenderer; 24 25 TEST(OffscreenBuffer, computeIdealDimension) { 26 EXPECT_EQ(64u, OffscreenBuffer::computeIdealDimension(1)); 27 EXPECT_EQ(64u, OffscreenBuffer::computeIdealDimension(31)); 28 EXPECT_EQ(64u, OffscreenBuffer::computeIdealDimension(33)); 29 EXPECT_EQ(64u, OffscreenBuffer::computeIdealDimension(64)); 30 EXPECT_EQ(1024u, OffscreenBuffer::computeIdealDimension(1000)); 31 } 32 33 RENDERTHREAD_TEST(OffscreenBuffer, construct) { 34 OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 49u, 149u); 35 EXPECT_EQ(49u, layer.viewportWidth); 36 EXPECT_EQ(149u, layer.viewportHeight); 37 38 EXPECT_EQ(64u, layer.texture.width()); 39 EXPECT_EQ(192u, layer.texture.height()); 40 41 EXPECT_EQ(64u * 192u * 4u, layer.getSizeInBytes()); 42 } 43 44 RENDERTHREAD_TEST(OffscreenBuffer, getTextureCoordinates) { 45 OffscreenBuffer layerAligned(renderThread.renderState(), Caches::getInstance(), 256u, 256u); 46 EXPECT_EQ(Rect(0, 1, 1, 0), 47 layerAligned.getTextureCoordinates()); 48 49 OffscreenBuffer layerUnaligned(renderThread.renderState(), Caches::getInstance(), 200u, 225u); 50 EXPECT_EQ(Rect(0, 225.0f / 256.0f, 200.0f / 256.0f, 0), 51 layerUnaligned.getTextureCoordinates()); 52 } 53 54 RENDERTHREAD_TEST(OffscreenBuffer, dirty) { 55 OffscreenBuffer buffer(renderThread.renderState(), Caches::getInstance(), 256u, 256u); 56 buffer.dirty(Rect(-100, -100, 100, 100)); 57 EXPECT_EQ(android::Rect(100, 100), buffer.region.getBounds()); 58 } 59 60 RENDERTHREAD_TEST(OffscreenBufferPool, construct) { 61 OffscreenBufferPool pool; 62 EXPECT_EQ(0u, pool.getCount()) << "pool must be created empty"; 63 EXPECT_EQ(0u, pool.getSize()) << "pool must be created empty"; 64 EXPECT_EQ((uint32_t) Properties::layerPoolSize, pool.getMaxSize()) 65 << "pool must read size from Properties"; 66 } 67 68 RENDERTHREAD_TEST(OffscreenBufferPool, getPutClear) { 69 OffscreenBufferPool pool; 70 71 auto layer = pool.get(renderThread.renderState(), 100u, 200u); 72 EXPECT_EQ(100u, layer->viewportWidth); 73 EXPECT_EQ(200u, layer->viewportHeight); 74 75 ASSERT_LT(layer->getSizeInBytes(), pool.getMaxSize()); 76 77 pool.putOrDelete(layer); 78 ASSERT_EQ(layer->getSizeInBytes(), pool.getSize()); 79 80 auto layer2 = pool.get(renderThread.renderState(), 102u, 202u); 81 EXPECT_EQ(layer, layer2) << "layer should be recycled"; 82 ASSERT_EQ(0u, pool.getSize()) << "pool should have been emptied by removing only layer"; 83 84 pool.putOrDelete(layer); 85 EXPECT_EQ(1u, pool.getCount()); 86 pool.clear(); 87 EXPECT_EQ(0u, pool.getSize()); 88 EXPECT_EQ(0u, pool.getCount()); 89 } 90 91 RENDERTHREAD_TEST(OffscreenBufferPool, resize) { 92 OffscreenBufferPool pool; 93 94 auto layer = pool.get(renderThread.renderState(), 64u, 64u); 95 layer->dirty(Rect(64, 64)); 96 97 // resize in place 98 ASSERT_EQ(layer, pool.resize(layer, 60u, 55u)); 99 EXPECT_TRUE(layer->region.isEmpty()) << "In place resize should clear usage region"; 100 EXPECT_EQ(60u, layer->viewportWidth); 101 EXPECT_EQ(55u, layer->viewportHeight); 102 EXPECT_EQ(64u, layer->texture.width()); 103 EXPECT_EQ(64u, layer->texture.height()); 104 105 // resized to use different object in pool 106 auto layer2 = pool.get(renderThread.renderState(), 128u, 128u); 107 layer2->dirty(Rect(128, 128)); 108 EXPECT_FALSE(layer2->region.isEmpty()); 109 pool.putOrDelete(layer2); 110 ASSERT_EQ(1u, pool.getCount()); 111 112 ASSERT_EQ(layer2, pool.resize(layer, 120u, 125u)); 113 EXPECT_TRUE(layer2->region.isEmpty()) << "Swap resize should clear usage region"; 114 EXPECT_EQ(120u, layer2->viewportWidth); 115 EXPECT_EQ(125u, layer2->viewportHeight); 116 EXPECT_EQ(128u, layer2->texture.width()); 117 EXPECT_EQ(128u, layer2->texture.height()); 118 119 // original allocation now only thing in pool 120 EXPECT_EQ(1u, pool.getCount()); 121 EXPECT_EQ(layer->getSizeInBytes(), pool.getSize()); 122 123 pool.putOrDelete(layer2); 124 } 125 126 RENDERTHREAD_TEST(OffscreenBufferPool, putAndDestroy) { 127 OffscreenBufferPool pool; 128 // layer too big to return to the pool 129 // Note: this relies on the fact that the pool won't reject based on max texture size 130 auto hugeLayer = pool.get(renderThread.renderState(), pool.getMaxSize() / 64, 64); 131 EXPECT_GT(hugeLayer->getSizeInBytes(), pool.getMaxSize()); 132 pool.putOrDelete(hugeLayer); 133 EXPECT_EQ(0u, pool.getCount()); // failed to put (so was destroyed instead) 134 } 135 136 RENDERTHREAD_TEST(OffscreenBufferPool, clear) { 137 EXPECT_EQ(0, GpuMemoryTracker::getInstanceCount(GpuObjectType::OffscreenBuffer)); 138 OffscreenBufferPool pool; 139 140 // Create many buffers, with several at each size 141 std::vector<OffscreenBuffer*> buffers; 142 for (int size = 32; size <= 128; size += 32) { 143 for (int i = 0; i < 10; i++) { 144 buffers.push_back(pool.get(renderThread.renderState(), size, size)); 145 } 146 } 147 EXPECT_EQ(0u, pool.getCount()) << "Expect nothing inside"; 148 for (auto& buffer : buffers) pool.putOrDelete(buffer); 149 EXPECT_EQ(40u, pool.getCount()) << "Expect all items added"; 150 EXPECT_EQ(40, GpuMemoryTracker::getInstanceCount(GpuObjectType::OffscreenBuffer)); 151 pool.clear(); 152 EXPECT_EQ(0u, pool.getCount()) << "Expect all items cleared"; 153 154 EXPECT_EQ(0, GpuMemoryTracker::getInstanceCount(GpuObjectType::OffscreenBuffer)); 155 } 156