OutputTest.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. /*
  2. * Copyright 2019 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. #include <cmath>
  17. #include <compositionengine/impl/Output.h>
  18. #include <compositionengine/mock/CompositionEngine.h>
  19. #include <compositionengine/mock/DisplayColorProfile.h>
  20. #include <compositionengine/mock/Layer.h>
  21. #include <compositionengine/mock/LayerFE.h>
  22. #include <compositionengine/mock/OutputLayer.h>
  23. #include <compositionengine/mock/RenderSurface.h>
  24. #include <gtest/gtest.h>
  25. #include <ui/Rect.h>
  26. #include <ui/Region.h>
  27. #include "RegionMatcher.h"
  28. #include "TransformMatcher.h"
  29. namespace android::compositionengine {
  30. namespace {
  31. using testing::Return;
  32. using testing::ReturnRef;
  33. using testing::StrictMock;
  34. class OutputTest : public testing::Test {
  35. public:
  36. OutputTest() {
  37. mOutput.setDisplayColorProfileForTest(
  38. std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
  39. mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
  40. mOutput.editState().bounds = kDefaultDisplaySize;
  41. }
  42. ~OutputTest() override = default;
  43. static const Rect kDefaultDisplaySize;
  44. StrictMock<mock::CompositionEngine> mCompositionEngine;
  45. mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
  46. mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
  47. impl::Output mOutput{mCompositionEngine};
  48. };
  49. const Rect OutputTest::kDefaultDisplaySize{100, 200};
  50. /* ------------------------------------------------------------------------
  51. * Basic construction
  52. */
  53. TEST_F(OutputTest, canInstantiateOutput) {
  54. // The validation check checks each required component.
  55. EXPECT_CALL(*mDisplayColorProfile, isValid()).WillOnce(Return(true));
  56. EXPECT_CALL(*mRenderSurface, isValid()).WillOnce(Return(true));
  57. EXPECT_TRUE(mOutput.isValid());
  58. // If we take away the required components, it is no longer valid.
  59. mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>());
  60. EXPECT_CALL(*mDisplayColorProfile, isValid()).WillOnce(Return(true));
  61. EXPECT_FALSE(mOutput.isValid());
  62. }
  63. /* ------------------------------------------------------------------------
  64. * Output::setCompositionEnabled()
  65. */
  66. TEST_F(OutputTest, setCompositionEnabledDoesNothingIfAlreadyEnabled) {
  67. mOutput.editState().isEnabled = true;
  68. mOutput.setCompositionEnabled(true);
  69. EXPECT_TRUE(mOutput.getState().isEnabled);
  70. EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region()));
  71. }
  72. TEST_F(OutputTest, setCompositionEnabledSetsEnabledAndDirtiesEntireOutput) {
  73. mOutput.editState().isEnabled = false;
  74. mOutput.setCompositionEnabled(true);
  75. EXPECT_TRUE(mOutput.getState().isEnabled);
  76. EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
  77. }
  78. TEST_F(OutputTest, setCompositionEnabledSetsDisabledAndDirtiesEntireOutput) {
  79. mOutput.editState().isEnabled = true;
  80. mOutput.setCompositionEnabled(false);
  81. EXPECT_FALSE(mOutput.getState().isEnabled);
  82. EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
  83. }
  84. /* ------------------------------------------------------------------------
  85. * Output::setProjection()
  86. */
  87. TEST_F(OutputTest, setProjectionTriviallyWorks) {
  88. const ui::Transform transform{ui::Transform::ROT_180};
  89. const int32_t orientation = 123;
  90. const Rect frame{1, 2, 3, 4};
  91. const Rect viewport{5, 6, 7, 8};
  92. const Rect scissor{9, 10, 11, 12};
  93. const bool needsFiltering = true;
  94. mOutput.setProjection(transform, orientation, frame, viewport, scissor, needsFiltering);
  95. EXPECT_THAT(mOutput.getState().transform, TransformEq(transform));
  96. EXPECT_EQ(orientation, mOutput.getState().orientation);
  97. EXPECT_EQ(frame, mOutput.getState().frame);
  98. EXPECT_EQ(viewport, mOutput.getState().viewport);
  99. EXPECT_EQ(scissor, mOutput.getState().scissor);
  100. EXPECT_EQ(needsFiltering, mOutput.getState().needsFiltering);
  101. }
  102. /* ------------------------------------------------------------------------
  103. * Output::setBounds()
  104. */
  105. TEST_F(OutputTest, setBoundsSetsSizeAndDirtiesEntireOutput) {
  106. const ui::Size displaySize{200, 400};
  107. EXPECT_CALL(*mRenderSurface, setDisplaySize(displaySize)).Times(1);
  108. EXPECT_CALL(*mRenderSurface, getSize()).WillOnce(ReturnRef(displaySize));
  109. mOutput.setBounds(displaySize);
  110. EXPECT_EQ(Rect(displaySize), mOutput.getState().bounds);
  111. EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region(Rect(displaySize))));
  112. }
  113. /* ------------------------------------------------------------------------
  114. * Output::setLayerStackFilter()
  115. */
  116. TEST_F(OutputTest, setLayerStackFilterSetsFilterAndDirtiesEntireOutput) {
  117. const uint32_t layerStack = 123u;
  118. mOutput.setLayerStackFilter(layerStack, true);
  119. EXPECT_TRUE(mOutput.getState().layerStackInternal);
  120. EXPECT_EQ(layerStack, mOutput.getState().layerStackId);
  121. EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
  122. }
  123. /* ------------------------------------------------------------------------
  124. * Output::setColorTransform
  125. */
  126. TEST_F(OutputTest, setColorTransformSetsTransform) {
  127. // Identity matrix sets an identity state value
  128. const mat4 identity;
  129. mOutput.setColorTransform(identity);
  130. EXPECT_EQ(HAL_COLOR_TRANSFORM_IDENTITY, mOutput.getState().colorTransform);
  131. EXPECT_EQ(identity, mOutput.getState().colorTransformMat);
  132. // Since identity is the default, the dirty region should be unchanged (empty)
  133. EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region()));
  134. // Non-identity matrix sets a non-identity state value
  135. const mat4 nonIdentityHalf = mat4() * 0.5;
  136. mOutput.setColorTransform(nonIdentityHalf);
  137. EXPECT_EQ(HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX, mOutput.getState().colorTransform);
  138. EXPECT_EQ(nonIdentityHalf, mOutput.getState().colorTransformMat);
  139. // Since this is a state change, the entire output should now be dirty.
  140. EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
  141. // Non-identity matrix sets a non-identity state value
  142. const mat4 nonIdentityQuarter = mat4() * 0.25;
  143. mOutput.setColorTransform(nonIdentityQuarter);
  144. EXPECT_EQ(HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX, mOutput.getState().colorTransform);
  145. EXPECT_EQ(nonIdentityQuarter, mOutput.getState().colorTransformMat);
  146. // Since this is a state change, the entire output should now be dirty.
  147. EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
  148. }
  149. /* ------------------------------------------------------------------------
  150. * Output::setColorMode
  151. */
  152. TEST_F(OutputTest, setColorModeSetsStateAndDirtiesOutputIfChanged) {
  153. EXPECT_CALL(*mRenderSurface, setBufferDataspace(ui::Dataspace::DISPLAY_P3)).Times(1);
  154. mOutput.setColorMode(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
  155. ui::RenderIntent::TONE_MAP_COLORIMETRIC);
  156. EXPECT_EQ(ui::ColorMode::DISPLAY_P3, mOutput.getState().colorMode);
  157. EXPECT_EQ(ui::Dataspace::DISPLAY_P3, mOutput.getState().dataspace);
  158. EXPECT_EQ(ui::RenderIntent::TONE_MAP_COLORIMETRIC, mOutput.getState().renderIntent);
  159. EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
  160. }
  161. TEST_F(OutputTest, setColorModeDoesNothingIfNoChange) {
  162. mOutput.editState().colorMode = ui::ColorMode::DISPLAY_P3;
  163. mOutput.editState().dataspace = ui::Dataspace::DISPLAY_P3;
  164. mOutput.editState().renderIntent = ui::RenderIntent::TONE_MAP_COLORIMETRIC;
  165. mOutput.setColorMode(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
  166. ui::RenderIntent::TONE_MAP_COLORIMETRIC);
  167. EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region()));
  168. }
  169. /* ------------------------------------------------------------------------
  170. * Output::setRenderSurface()
  171. */
  172. TEST_F(OutputTest, setRenderSurfaceResetsBounds) {
  173. const ui::Size newDisplaySize{640, 480};
  174. mock::RenderSurface* renderSurface = new StrictMock<mock::RenderSurface>();
  175. EXPECT_CALL(*renderSurface, getSize()).WillOnce(ReturnRef(newDisplaySize));
  176. mOutput.setRenderSurface(std::unique_ptr<RenderSurface>(renderSurface));
  177. EXPECT_EQ(Rect(newDisplaySize), mOutput.getState().bounds);
  178. }
  179. /* ------------------------------------------------------------------------
  180. * Output::getDirtyRegion()
  181. */
  182. TEST_F(OutputTest, getDirtyRegionWithRepaintEverythingTrue) {
  183. const Rect viewport{100, 200};
  184. mOutput.editState().viewport = viewport;
  185. mOutput.editState().dirtyRegion.set(50, 300);
  186. {
  187. Region result = mOutput.getDirtyRegion(true);
  188. EXPECT_THAT(result, RegionEq(Region(viewport)));
  189. }
  190. }
  191. TEST_F(OutputTest, getDirtyRegionWithRepaintEverythingFalse) {
  192. const Rect viewport{100, 200};
  193. mOutput.editState().viewport = viewport;
  194. mOutput.editState().dirtyRegion.set(50, 300);
  195. {
  196. Region result = mOutput.getDirtyRegion(false);
  197. // The dirtyRegion should be clipped to the display bounds.
  198. EXPECT_THAT(result, RegionEq(Region(Rect(50, 200))));
  199. }
  200. }
  201. /* ------------------------------------------------------------------------
  202. * Output::belongsInOutput()
  203. */
  204. TEST_F(OutputTest, belongsInOutputFiltersAsExpected) {
  205. const uint32_t layerStack1 = 123u;
  206. const uint32_t layerStack2 = 456u;
  207. const String8 activesystemname = String8("");
  208. const String8 systemname = String8("");
  209. // If the output accepts layerStack1 and internal-only layers....
  210. mOutput.setLayerStackFilter(layerStack1, true);
  211. // Any layer with layerStack1 belongs to it, internal-only or not.
  212. EXPECT_TRUE(mOutput.belongsInOutput(layerStack1, activesystemname, systemname, false));
  213. EXPECT_TRUE(mOutput.belongsInOutput(layerStack1, activesystemname, systemname, true));
  214. EXPECT_FALSE(mOutput.belongsInOutput(layerStack2, activesystemname, systemname, true));
  215. EXPECT_FALSE(mOutput.belongsInOutput(layerStack2, activesystemname, systemname, false));
  216. // If the output accepts layerStack21 but not internal-only layers...
  217. mOutput.setLayerStackFilter(layerStack1, false);
  218. // Only non-internal layers with layerStack1 belong to it.
  219. EXPECT_TRUE(mOutput.belongsInOutput(layerStack1, activesystemname, systemname, false));
  220. EXPECT_FALSE(mOutput.belongsInOutput(layerStack1, activesystemname, systemname, true));
  221. EXPECT_FALSE(mOutput.belongsInOutput(layerStack2, activesystemname, systemname, true));
  222. EXPECT_FALSE(mOutput.belongsInOutput(layerStack2, activesystemname, systemname, false));
  223. }
  224. /* ------------------------------------------------------------------------
  225. * Output::getOutputLayerForLayer()
  226. */
  227. TEST_F(OutputTest, getOutputLayerForLayerWorks) {
  228. mock::OutputLayer* outputLayer1 = new StrictMock<mock::OutputLayer>();
  229. mock::OutputLayer* outputLayer2 = new StrictMock<mock::OutputLayer>();
  230. Output::OutputLayers outputLayers;
  231. outputLayers.emplace_back(std::unique_ptr<OutputLayer>(outputLayer1));
  232. outputLayers.emplace_back(nullptr);
  233. outputLayers.emplace_back(std::unique_ptr<OutputLayer>(outputLayer2));
  234. mOutput.setOutputLayersOrderedByZ(std::move(outputLayers));
  235. StrictMock<mock::Layer> layer;
  236. StrictMock<mock::Layer> otherLayer;
  237. // If the input layer matches the first OutputLayer, it will be returned.
  238. EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(layer));
  239. EXPECT_EQ(outputLayer1, mOutput.getOutputLayerForLayer(&layer));
  240. // If the input layer matches the second OutputLayer, it will be returned.
  241. EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(otherLayer));
  242. EXPECT_CALL(*outputLayer2, getLayer()).WillOnce(ReturnRef(layer));
  243. EXPECT_EQ(outputLayer2, mOutput.getOutputLayerForLayer(&layer));
  244. // If the input layer does not match an output layer, null will be returned.
  245. EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(otherLayer));
  246. EXPECT_CALL(*outputLayer2, getLayer()).WillOnce(ReturnRef(otherLayer));
  247. EXPECT_EQ(nullptr, mOutput.getOutputLayerForLayer(&layer));
  248. }
  249. /* ------------------------------------------------------------------------
  250. * Output::getOrCreateOutputLayer()
  251. */
  252. TEST_F(OutputTest, getOrCreateOutputLayerWorks) {
  253. mock::OutputLayer* existingOutputLayer = new StrictMock<mock::OutputLayer>();
  254. Output::OutputLayers outputLayers;
  255. outputLayers.emplace_back(nullptr);
  256. outputLayers.emplace_back(std::unique_ptr<OutputLayer>(existingOutputLayer));
  257. mOutput.setOutputLayersOrderedByZ(std::move(outputLayers));
  258. std::shared_ptr<mock::Layer> layer{new StrictMock<mock::Layer>()};
  259. sp<LayerFE> layerFE{new StrictMock<mock::LayerFE>()};
  260. StrictMock<mock::Layer> otherLayer;
  261. {
  262. // If there is no OutputLayer corresponding to the input layer, a
  263. // new OutputLayer is constructed and returned.
  264. EXPECT_CALL(*existingOutputLayer, getLayer()).WillOnce(ReturnRef(otherLayer));
  265. auto result = mOutput.getOrCreateOutputLayer(std::nullopt, layer, layerFE);
  266. EXPECT_NE(existingOutputLayer, result.get());
  267. EXPECT_TRUE(result.get() != nullptr);
  268. EXPECT_EQ(layer.get(), &result->getLayer());
  269. EXPECT_EQ(layerFE.get(), &result->getLayerFE());
  270. // The entries in the ordered array should be unchanged.
  271. auto& outputLayers = mOutput.getOutputLayersOrderedByZ();
  272. EXPECT_EQ(nullptr, outputLayers[0].get());
  273. EXPECT_EQ(existingOutputLayer, outputLayers[1].get());
  274. }
  275. {
  276. // If there is an existing OutputLayer for the requested layer, an owned
  277. // pointer is returned
  278. EXPECT_CALL(*existingOutputLayer, getLayer()).WillOnce(ReturnRef(*layer));
  279. auto result = mOutput.getOrCreateOutputLayer(std::nullopt, layer, layerFE);
  280. EXPECT_EQ(existingOutputLayer, result.get());
  281. // The corresponding entry in the ordered array should be cleared.
  282. auto& outputLayers = mOutput.getOutputLayersOrderedByZ();
  283. EXPECT_EQ(nullptr, outputLayers[0].get());
  284. EXPECT_EQ(nullptr, outputLayers[1].get());
  285. }
  286. }
  287. } // namespace
  288. } // namespace android::compositionengine