1 // Copyright (C) 2018 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 #include <gtest/gtest.h>
15
16 #include "host-common/testing/MockGraphicsAgentFactory.h"
17 #include "Standalone.h"
18 #include "GLTestUtils.h"
19
20 #include <memory>
21
22 namespace gfxstream {
23 namespace {
24
25 using gl::GLESApi;
26 using gl::GLESApi_2;
27 using gl::GLESApi_3_0;
28 using gl::GLESApi_3_1;
29 using gl::GLESApi_3_2;
30 using gl::GLESApi_CM;
31 using gl::LazyLoadedEGLDispatch;
32 using gl::LazyLoadedGLESv2Dispatch;
33
34 struct ClearColorParam {
35 const GLESApi glVersion;
36 const bool fastBlit;
37
ClearColorParamgfxstream::__anon25739e500111::ClearColorParam38 ClearColorParam(GLESApi glVersion, bool fastBlit)
39 : glVersion(glVersion), fastBlit(fastBlit) {}
40 };
41
PrintTo(const ClearColorParam & param,std::ostream * os)42 static void PrintTo(const ClearColorParam& param, std::ostream* os) {
43 *os << "ClearColorParam(";
44
45 switch (param.glVersion) {
46 case GLESApi_CM: *os << "GLESApi_CM"; break;
47 case GLESApi_2: *os << "GLESApi_2"; break;
48 case GLESApi_3_0: *os << "GLESApi_3_0"; break;
49 case GLESApi_3_1: *os << "GLESApi_3_1"; break;
50 case GLESApi_3_2: *os << "GLESApi_3_2"; break;
51 default: *os << "GLESApi(" << int(param.glVersion) << ")"; break;
52 }
53
54 *os << ", " << (param.fastBlit ? "fast blit" : "slow blit") << ")";
55 }
56
57 class ClearColor final : public SampleApplication {
58 public:
ClearColor(ClearColorParam param)59 ClearColor(ClearColorParam param) : SampleApplication(256, 256, 60, param.glVersion) {
60 if (!param.fastBlit) {
61 // Disable fast blit and then recreate the color buffer to apply the
62 // change.
63 mFb->disableFastBlitForTesting();
64
65 mFb->closeColorBuffer(mColorBuffer);
66 mColorBuffer = mFb->createColorBuffer(
67 mWidth, mHeight, GL_RGBA, FRAMEWORK_FORMAT_GL_COMPATIBLE);
68 mFb->setEmulatedEglWindowSurfaceColorBuffer(mSurface, mColorBuffer);
69 }
70 }
71
~ClearColor()72 ~ClearColor() {
73 auto gl = LazyLoadedGLESv2Dispatch::get();
74 if (mFbo) {
75 gl->glDeleteFramebuffers(1, &mFbo);
76 gl->glDeleteTextures(1, &mTexture);
77 }
78 }
79
setClearColor(float r,float g,float b,float a)80 void setClearColor(float r, float g, float b, float a) {
81 mRed = r;
82 mGreen = g;
83 mBlue = b;
84 mAlpha = a;
85 }
86
setUseFboCombined(bool useFbo)87 void setUseFboCombined(bool useFbo) {
88 mUseFboCombined = useFbo;
89 }
90
setUseFbo(bool useFboDraw,bool useFboRead)91 void setUseFbo(bool useFboDraw, bool useFboRead) {
92 mUseFboDraw = useFboDraw;
93 mUseFboRead = useFboRead;
94 }
95
initialize()96 void initialize() override {
97 auto gl = LazyLoadedGLESv2Dispatch::get();
98 gl->glActiveTexture(GL_TEXTURE0);
99
100 if (!mFbo) {
101 gl->glGenFramebuffers(1, &mFbo);
102 gl->glGenTextures(1, &mTexture);
103
104 gl->glBindTexture(GL_TEXTURE_2D, mTexture);
105 gl->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
106 mWidth, mHeight, 0,
107 GL_RGBA, GL_UNSIGNED_BYTE, 0);
108 gl->glBindTexture(GL_TEXTURE_2D, 0);
109
110 gl->glBindFramebuffer(GL_FRAMEBUFFER, mFbo);
111 gl->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
112 GL_TEXTURE_2D, mTexture, 0);
113 gl->glBindFramebuffer(GL_FRAMEBUFFER, 0);
114 }
115 }
116
draw()117 void draw() override {
118 auto gl = LazyLoadedGLESv2Dispatch::get();
119
120 gl->glBindFramebuffer(GL_FRAMEBUFFER, mUseFboCombined ? mFbo : 0);
121
122 if (mUseFboDraw) {
123 gl->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFbo);
124 }
125 if (mUseFboRead) {
126 gl->glBindFramebuffer(GL_READ_FRAMEBUFFER, mFbo);
127 }
128
129 gl->glClearColor(mRed, mGreen, mBlue, mAlpha);
130 gl->glClear(GL_COLOR_BUFFER_BIT);
131 }
132
setNonDefaultCombinedFbo()133 void setNonDefaultCombinedFbo() {
134 setUseFboCombined(true);
135 }
136
setNonDefaultDrawFbo()137 void setNonDefaultDrawFbo() {
138 setUseFbo(true, mUseFboRead);
139 }
140
setNonDefaultReadFbo()141 void setNonDefaultReadFbo() {
142 setUseFbo(mUseFboDraw, true);
143 }
144
drawWithColor(const float drawColor[4])145 void drawWithColor(const float drawColor[4]) {
146 setClearColor(drawColor[0], drawColor[1], drawColor[2], drawColor[3]);
147 drawOnce();
148 }
149
verifySwappedColor(const float wantedColor[4])150 void verifySwappedColor(const float wantedColor[4]) {
151 TestTexture targetBuffer =
152 createTestTextureRGBA8888SingleColor(
153 mWidth, mHeight, wantedColor[0], wantedColor[1], wantedColor[2], wantedColor[3]);
154
155 TestTexture forRead =
156 createTestTextureRGBA8888SingleColor(
157 mWidth, mHeight, 0.0f, 0.0f, 0.0f, 0.0f);
158
159 mFb->readColorBuffer(
160 mColorBuffer, 0, 0, mWidth, mHeight,
161 GL_RGBA, GL_UNSIGNED_BYTE, forRead.data());
162
163 EXPECT_TRUE(
164 ImageMatches(mWidth, mHeight, 4, mWidth, targetBuffer.data(), forRead.data()));
165 }
166
167 private:
168 bool mUseFboCombined = false;
169 bool mUseFboDraw = false;
170 bool mUseFboRead = false;
171
172 GLuint mFbo = 0;
173 GLuint mTexture = 0;
174
175 float mRed = 1.0f;
176 float mGreen = 1.0f;
177 float mBlue = 1.0f;
178 float mAlpha = 1.0f;
179 };
180
181 static constexpr float kDrawColorRed[4] = { 1.0f, 0.0f, 0.0f, 1.0f };
182 static constexpr float kDrawColorGreen[4] = { 0.0f, 1.0f, 0.0f, 1.0f };
183
184 class CombinedFramebufferBlit : public ::testing::Test, public ::testing::WithParamInterface<ClearColorParam> {
185 protected:
SetUpTestSuite()186 static void SetUpTestSuite() {
187 android::emulation::injectGraphicsAgents(
188 android::emulation::MockGraphicsAgentFactory());
189 }
190
TearDownTestSuite()191 static void TearDownTestSuite() { }
192
SetUp()193 virtual void SetUp() override {
194 mApp.reset(new ClearColor(GetParam()));
195 }
196
TearDown()197 virtual void TearDown() override {
198 mApp.reset();
199 EXPECT_EQ(EGL_SUCCESS, LazyLoadedEGLDispatch::get()->eglGetError())
200 << "DefaultFramebufferBlitTest TearDown found an EGL error";
201 }
202
203 std::unique_ptr<ClearColor> mApp;
204 };
205
TEST_P(CombinedFramebufferBlit,DefaultDrawDefaultRead)206 TEST_P(CombinedFramebufferBlit, DefaultDrawDefaultRead) {
207 // Draw to default framebuffer; color should show up
208 mApp->drawWithColor(kDrawColorRed);
209 mApp->verifySwappedColor(kDrawColorRed);
210 }
211
TEST_P(CombinedFramebufferBlit,NonDefault)212 TEST_P(CombinedFramebufferBlit, NonDefault) {
213 mApp->drawWithColor(kDrawColorRed);
214 mApp->verifySwappedColor(kDrawColorRed);
215
216 // Color should not be affected by the draw to a non-default framebuffer.
217 mApp->setNonDefaultCombinedFbo();
218
219 mApp->drawWithColor(kDrawColorGreen);
220 mApp->verifySwappedColor(kDrawColorRed);
221 }
222
223 // Test blitting both with only the fast blit path.
224 INSTANTIATE_TEST_SUITE_P(CombinedFramebufferBlitTest,
225 CombinedFramebufferBlit,
226 testing::Values(
227 ClearColorParam(GLESApi_CM, true),
228 ClearColorParam(GLESApi_2, true),
229 ClearColorParam(GLESApi_3_0, true)));
230
231 class NonDefaultFramebufferBlit : public CombinedFramebufferBlit { };
232
TEST_P(NonDefaultFramebufferBlit,NonDefaultDrawNonDefaultRead)233 TEST_P(NonDefaultFramebufferBlit, NonDefaultDrawNonDefaultRead) {
234 mApp->drawWithColor(kDrawColorRed);
235 mApp->verifySwappedColor(kDrawColorRed);
236
237 // Color should not be affected by the draw to non-default
238 // draw/read framebuffers.
239 // (we preserve the previous contents of the surface in
240 // SampleApplication::drawOnce)
241 mApp->setNonDefaultDrawFbo();
242 mApp->setNonDefaultReadFbo();
243
244 mApp->drawWithColor(kDrawColorGreen);
245 mApp->verifySwappedColor(kDrawColorRed);
246 }
247
TEST_P(NonDefaultFramebufferBlit,DefaultDrawNonDefaultRead)248 TEST_P(NonDefaultFramebufferBlit, DefaultDrawNonDefaultRead) {
249 mApp->drawWithColor(kDrawColorRed);
250 mApp->verifySwappedColor(kDrawColorRed);
251
252 // Bug: 110996998
253 // Draw to default framebuffer, and have a non-default
254 // read framebuffer bound. Color should show up
255 mApp->setNonDefaultReadFbo();
256
257 mApp->drawWithColor(kDrawColorGreen);
258 mApp->verifySwappedColor(kDrawColorGreen);
259 }
260
TEST_P(NonDefaultFramebufferBlit,NonDefaultDrawDefaultRead)261 TEST_P(NonDefaultFramebufferBlit, NonDefaultDrawDefaultRead) {
262 mApp->drawWithColor(kDrawColorRed);
263 mApp->verifySwappedColor(kDrawColorRed);
264
265 // Draw to non-default framebuffer, and have the default
266 // read framebuffer bound. Color should not show up.
267 // (we preserve the previous contents of the surface in
268 // SampleApplication::drawOnce)
269 mApp->setNonDefaultDrawFbo();
270
271 mApp->drawWithColor(kDrawColorGreen);
272 mApp->verifySwappedColor(kDrawColorRed);
273 }
274
275 // Test blitting both with and without the fast blit path.
276 INSTANTIATE_TEST_SUITE_P(DefaultFramebufferBlitTest,
277 NonDefaultFramebufferBlit,
278 testing::Values(
279 ClearColorParam(GLESApi_3_0, true)));
280
281 } // namespace
282 } // namespace gfxstream
283