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 "Standalone.h"
17 #include "GLTestUtils.h"
18
19 #include <memory>
20
21 namespace emugl {
22
23 struct ClearColorParam {
24 const GLESApi glVersion;
25 const bool fastBlit;
26
ClearColorParamemugl::ClearColorParam27 ClearColorParam(GLESApi glVersion, bool fastBlit)
28 : glVersion(glVersion), fastBlit(fastBlit) {}
29 };
30
PrintTo(const ClearColorParam & param,std::ostream * os)31 static void PrintTo(const ClearColorParam& param, std::ostream* os) {
32 *os << "ClearColorParam(";
33
34 switch (param.glVersion) {
35 case GLESApi_CM: *os << "GLESApi_CM"; break;
36 case GLESApi_2: *os << "GLESApi_2"; break;
37 case GLESApi_3_0: *os << "GLESApi_3_0"; break;
38 case GLESApi_3_1: *os << "GLESApi_3_1"; break;
39 case GLESApi_3_2: *os << "GLESApi_3_2"; break;
40 default: *os << "GLESApi(" << int(param.glVersion) << ")"; break;
41 }
42
43 *os << ", " << (param.fastBlit ? "fast blit" : "slow blit") << ")";
44 }
45
46 class ClearColor final : public SampleApplication {
47 public:
ClearColor(ClearColorParam param)48 ClearColor(ClearColorParam param) : SampleApplication(256, 256, 60, param.glVersion) {
49 if (!param.fastBlit) {
50 // Disable fast blit and then recreate the color buffer to apply the
51 // change.
52 mFb->disableFastBlit();
53
54 mFb->closeColorBuffer(mColorBuffer);
55 mColorBuffer = mFb->createColorBuffer(
56 mWidth, mHeight, GL_RGBA, FRAMEWORK_FORMAT_GL_COMPATIBLE);
57 mFb->setWindowSurfaceColorBuffer(mSurface, mColorBuffer);
58 }
59 }
60
~ClearColor()61 ~ClearColor() {
62 auto gl = LazyLoadedGLESv2Dispatch::get();
63 if (mFbo) {
64 gl->glDeleteFramebuffers(1, &mFbo);
65 gl->glDeleteTextures(1, &mTexture);
66 }
67 }
68
setClearColor(float r,float g,float b,float a)69 void setClearColor(float r, float g, float b, float a) {
70 mRed = r;
71 mGreen = g;
72 mBlue = b;
73 mAlpha = a;
74 }
75
setUseFboCombined(bool useFbo)76 void setUseFboCombined(bool useFbo) {
77 mUseFboCombined = useFbo;
78 }
79
setUseFbo(bool useFboDraw,bool useFboRead)80 void setUseFbo(bool useFboDraw, bool useFboRead) {
81 mUseFboDraw = useFboDraw;
82 mUseFboRead = useFboRead;
83 }
84
initialize()85 void initialize() override {
86 auto gl = LazyLoadedGLESv2Dispatch::get();
87 gl->glActiveTexture(GL_TEXTURE0);
88
89 if (!mFbo) {
90 gl->glGenFramebuffers(1, &mFbo);
91 gl->glGenTextures(1, &mTexture);
92
93 gl->glBindTexture(GL_TEXTURE_2D, mTexture);
94 gl->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
95 mWidth, mHeight, 0,
96 GL_RGBA, GL_UNSIGNED_BYTE, 0);
97 gl->glBindTexture(GL_TEXTURE_2D, 0);
98
99 gl->glBindFramebuffer(GL_FRAMEBUFFER, mFbo);
100 gl->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
101 GL_TEXTURE_2D, mTexture, 0);
102 gl->glBindFramebuffer(GL_FRAMEBUFFER, 0);
103 }
104 }
105
draw()106 void draw() override {
107 auto gl = LazyLoadedGLESv2Dispatch::get();
108
109 gl->glBindFramebuffer(GL_FRAMEBUFFER, mUseFboCombined ? mFbo : 0);
110
111 if (mUseFboDraw) {
112 gl->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFbo);
113 }
114 if (mUseFboRead) {
115 gl->glBindFramebuffer(GL_READ_FRAMEBUFFER, mFbo);
116 }
117
118 gl->glClearColor(mRed, mGreen, mBlue, mAlpha);
119 gl->glClear(GL_COLOR_BUFFER_BIT);
120 }
121
setNonDefaultCombinedFbo()122 void setNonDefaultCombinedFbo() {
123 setUseFboCombined(true);
124 }
125
setNonDefaultDrawFbo()126 void setNonDefaultDrawFbo() {
127 setUseFbo(true, mUseFboRead);
128 }
129
setNonDefaultReadFbo()130 void setNonDefaultReadFbo() {
131 setUseFbo(mUseFboDraw, true);
132 }
133
drawWithColor(const float drawColor[4])134 void drawWithColor(const float drawColor[4]) {
135 setClearColor(drawColor[0], drawColor[1], drawColor[2], drawColor[3]);
136 drawOnce();
137 }
138
verifySwappedColor(const float wantedColor[4])139 void verifySwappedColor(const float wantedColor[4]) {
140 TestTexture targetBuffer =
141 createTestTextureRGBA8888SingleColor(
142 mWidth, mHeight, wantedColor[0], wantedColor[1], wantedColor[2], wantedColor[3]);
143
144 TestTexture forRead =
145 createTestTextureRGBA8888SingleColor(
146 mWidth, mHeight, 0.0f, 0.0f, 0.0f, 0.0f);
147
148 mFb->readColorBuffer(
149 mColorBuffer, 0, 0, mWidth, mHeight,
150 GL_RGBA, GL_UNSIGNED_BYTE, forRead.data());
151
152 EXPECT_TRUE(
153 ImageMatches(mWidth, mHeight, 4, mWidth, targetBuffer.data(), forRead.data()));
154 }
155
156 private:
157 bool mUseFboCombined = false;
158 bool mUseFboDraw = false;
159 bool mUseFboRead = false;
160
161 GLuint mFbo = 0;
162 GLuint mTexture = 0;
163
164 float mRed = 1.0f;
165 float mGreen = 1.0f;
166 float mBlue = 1.0f;
167 float mAlpha = 1.0f;
168 };
169
170 static constexpr float kDrawColorRed[4] = { 1.0f, 0.0f, 0.0f, 1.0f };
171 static constexpr float kDrawColorGreen[4] = { 0.0f, 1.0f, 0.0f, 1.0f };
172
173 class CombinedFramebufferBlit : public ::testing::Test, public ::testing::WithParamInterface<ClearColorParam> {
174 protected:
SetUp()175 virtual void SetUp() override {
176 mApp.reset(new ClearColor(GetParam()));
177 }
178
TearDown()179 virtual void TearDown() override {
180 mApp.reset();
181 EXPECT_EQ(EGL_SUCCESS, LazyLoadedEGLDispatch::get()->eglGetError())
182 << "DefaultFramebufferBlitTest TearDown found an EGL error";
183 }
184
185 std::unique_ptr<ClearColor> mApp;
186 };
187
TEST_P(CombinedFramebufferBlit,DefaultDrawDefaultRead)188 TEST_P(CombinedFramebufferBlit, DefaultDrawDefaultRead) {
189 // Draw to default framebuffer; color should show up
190 mApp->drawWithColor(kDrawColorRed);
191 mApp->verifySwappedColor(kDrawColorRed);
192 }
193
TEST_P(CombinedFramebufferBlit,NonDefault)194 TEST_P(CombinedFramebufferBlit, NonDefault) {
195 mApp->drawWithColor(kDrawColorRed);
196 mApp->verifySwappedColor(kDrawColorRed);
197
198 // Color should not be affected by the draw to a non-default framebuffer.
199 mApp->setNonDefaultCombinedFbo();
200
201 mApp->drawWithColor(kDrawColorGreen);
202 mApp->verifySwappedColor(kDrawColorRed);
203 }
204
205 // Test blitting both with only the fast blit path.
206 INSTANTIATE_TEST_SUITE_P(CombinedFramebufferBlitTest,
207 CombinedFramebufferBlit,
208 testing::Values(
209 ClearColorParam(GLESApi_CM, true),
210 ClearColorParam(GLESApi_2, true),
211 ClearColorParam(GLESApi_3_0, true)));
212
213 class NonDefaultFramebufferBlit : public CombinedFramebufferBlit { };
214
TEST_P(NonDefaultFramebufferBlit,NonDefaultDrawNonDefaultRead)215 TEST_P(NonDefaultFramebufferBlit, NonDefaultDrawNonDefaultRead) {
216 mApp->drawWithColor(kDrawColorRed);
217 mApp->verifySwappedColor(kDrawColorRed);
218
219 // Color should not be affected by the draw to non-default
220 // draw/read framebuffers.
221 // (we preserve the previous contents of the surface in
222 // SampleApplication::drawOnce)
223 mApp->setNonDefaultDrawFbo();
224 mApp->setNonDefaultReadFbo();
225
226 mApp->drawWithColor(kDrawColorGreen);
227 mApp->verifySwappedColor(kDrawColorRed);
228 }
229
TEST_P(NonDefaultFramebufferBlit,DefaultDrawNonDefaultRead)230 TEST_P(NonDefaultFramebufferBlit, DefaultDrawNonDefaultRead) {
231 mApp->drawWithColor(kDrawColorRed);
232 mApp->verifySwappedColor(kDrawColorRed);
233
234 // Bug: 110996998
235 // Draw to default framebuffer, and have a non-default
236 // read framebuffer bound. Color should show up
237 mApp->setNonDefaultReadFbo();
238
239 mApp->drawWithColor(kDrawColorGreen);
240 mApp->verifySwappedColor(kDrawColorGreen);
241 }
242
TEST_P(NonDefaultFramebufferBlit,NonDefaultDrawDefaultRead)243 TEST_P(NonDefaultFramebufferBlit, NonDefaultDrawDefaultRead) {
244 mApp->drawWithColor(kDrawColorRed);
245 mApp->verifySwappedColor(kDrawColorRed);
246
247 // Draw to non-default framebuffer, and have the default
248 // read framebuffer bound. Color should not show up.
249 // (we preserve the previous contents of the surface in
250 // SampleApplication::drawOnce)
251 mApp->setNonDefaultDrawFbo();
252
253 mApp->drawWithColor(kDrawColorGreen);
254 mApp->verifySwappedColor(kDrawColorRed);
255 }
256
257 // Test blitting both with and without the fast blit path.
258 INSTANTIATE_TEST_SUITE_P(DefaultFramebufferBlitTest,
259 NonDefaultFramebufferBlit,
260 testing::Values(
261 ClearColorParam(GLESApi_3_0, true)));
262
263
264 } // namespace emugl
265