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 
15 #include "GLSnapshotTesting.h"
16 
17 #include <gtest/gtest.h>
18 
19 namespace gfxstream {
20 namespace gl {
21 namespace {
22 
23 struct GlRenderbufferFormat {
24     GLenum name;
25     GLsizei red;
26     GLsizei green;
27     GLsizei blue;
28     GLsizei alpha;
29     GLsizei depth;
30     GLsizei stencil;
31 };
32 
33 struct GlRenderbufferState {
34     GLuint width;
35     GLuint height;
36     GlRenderbufferFormat format;
37 };
38 
39 static const GlRenderbufferState kGLES2DefaultRenderbufferState = {
40         0,
41         0,
42         {.name = GL_RGBA4}};
43 
44 static const GlRenderbufferFormat kGLES2RenderbufferFormatFieldSizes[] = {
45         {GL_DEPTH_COMPONENT16, 0, 0, 0, 0, 16, 0},
46         {GL_RGBA4, 4, 4, 4, 4, 0, 0},
47         {GL_RGB5_A1, 5, 5, 5, 1, 0, 0},
48         {GL_RGB565, 5, 6, 5, 0, 0, 0},
49         {GL_STENCIL_INDEX8, 0, 0, 0, 0, 0, 8},
50 };
51 
52 static const GlRenderbufferState kGLES2TestRenderbufferStates[] = {
53         {1, 1, kGLES2RenderbufferFormatFieldSizes[0]},
54         {0, 3, kGLES2RenderbufferFormatFieldSizes[1]},
55         {2, 2, kGLES2RenderbufferFormatFieldSizes[1]},
56         {4, 4, kGLES2RenderbufferFormatFieldSizes[2]},
57         {8, 8, kGLES2RenderbufferFormatFieldSizes[3]},
58         {16, 16, kGLES2RenderbufferFormatFieldSizes[4]},
59 };
60 
61 class SnapshotGlRenderbufferTest : public SnapshotPreserveTest {
62 public:
defaultStateCheck()63     void defaultStateCheck() override {
64         EXPECT_EQ(GL_FALSE, gl->glIsRenderbuffer(m_renderbuffer_name));
65         EXPECT_TRUE(compareGlobalGlInt(gl, GL_RENDERBUFFER_BINDING, 0));
66     }
67 
changedStateCheck()68     void changedStateCheck() override {
69         EXPECT_EQ(GL_TRUE, gl->glIsRenderbuffer(m_renderbuffer_name));
70         EXPECT_TRUE(compareGlobalGlInt(gl, GL_RENDERBUFFER_BINDING,
71                                        m_renderbuffer_name));
72 
73         EXPECT_TRUE(compareParameter(GL_RENDERBUFFER_WIDTH, m_state.width));
74         EXPECT_TRUE(compareParameter(GL_RENDERBUFFER_HEIGHT, m_state.height));
75         EXPECT_TRUE(compareParameter(GL_RENDERBUFFER_INTERNAL_FORMAT,
76                                      m_state.format.name));
77         EXPECT_TRUE(
78                 compareParameter(GL_RENDERBUFFER_RED_SIZE, m_state.format.red));
79         EXPECT_TRUE(compareParameter(GL_RENDERBUFFER_GREEN_SIZE,
80                                      m_state.format.green));
81         EXPECT_TRUE(compareParameter(GL_RENDERBUFFER_BLUE_SIZE,
82                                      m_state.format.blue));
83         EXPECT_TRUE(compareParameter(GL_RENDERBUFFER_ALPHA_SIZE,
84                                      m_state.format.alpha));
85         EXPECT_TRUE(compareParameter(GL_RENDERBUFFER_DEPTH_SIZE,
86                                      m_state.format.depth));
87         EXPECT_TRUE(compareParameter(GL_RENDERBUFFER_STENCIL_SIZE,
88                                      m_state.format.stencil));
89     }
90 
stateChange()91     void stateChange() override {
92         gl->glGenRenderbuffers(1, &m_renderbuffer_name);
93         gl->glBindRenderbuffer(GL_RENDERBUFFER, m_renderbuffer_name);
94 
95         m_state_changer();
96     }
97 
setStateChanger(std::function<void ()> changer)98     void setStateChanger(std::function<void()> changer) {
99         m_state_changer = changer;
100     }
101 
102 protected:
compareParameter(GLenum name,GLint expected)103     testing::AssertionResult compareParameter(GLenum name, GLint expected) {
104         GLint actual;
105         gl->glGetRenderbufferParameteriv(GL_RENDERBUFFER, name, &actual);
106         return compareValue<GLint>(
107                 expected, actual,
108                 "GL Renderbuffer object mismatch for param " +
109                         describeGlEnum(name) + ":");
110     }
111 
112     GLuint m_renderbuffer_name = 0;
113     GlRenderbufferState m_state = kGLES2DefaultRenderbufferState;
__anondb282f770202null114     std::function<void()> m_state_changer = [] {};
115 };
116 
TEST_F(SnapshotGlRenderbufferTest,CreateAndBind)117 TEST_F(SnapshotGlRenderbufferTest, CreateAndBind) {
118     const char* kAngleName = "ANGLE";
119     const char* kSwiftshaderName = "SwiftShader";
120     const char* kRendererString
121             = reinterpret_cast<const char*>(gl->glGetString(GL_RENDERER));
122     if (strncmp(kRendererString, kAngleName, strlen(kAngleName))
123             && strncmp(kRendererString, kSwiftshaderName,
124                     strlen(kSwiftshaderName))) {
125         GTEST_SKIP() << "b/247873185 SwANGLE has wrong default format.";
126     }
127     doCheckedSnapshot();
128 }
129 
130 class SnapshotGlRenderbufferFormatTest
131     : public SnapshotGlRenderbufferTest,
132       public ::testing::WithParamInterface<GlRenderbufferState> {};
133 
TEST_P(SnapshotGlRenderbufferFormatTest,SetFormat)134 TEST_P(SnapshotGlRenderbufferFormatTest, SetFormat) {
135     setStateChanger([this] {
136         GLint maxSize;
137         gl->glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &maxSize);
138         m_state = GetParam();
139         if (maxSize < m_state.width || maxSize < m_state.height) {
140             fprintf(stderr,
141                     "test dimensions exceed max renderbuffer size %d; "
142                     "using max size instead\n",
143                     maxSize);
144             m_state.width = maxSize;
145             m_state.height = maxSize;
146         }
147         gl->glRenderbufferStorage(GL_RENDERBUFFER, m_state.format.name,
148                                   m_state.width, m_state.height);
149 
150         // The actual number of bits used for each format doesn't necessarily
151         // match how they are defined.
152         GLint fieldSize;
153         gl->glGetRenderbufferParameteriv(GL_RENDERBUFFER,
154                                          GL_RENDERBUFFER_RED_SIZE, &fieldSize);
155         if (fieldSize != m_state.format.red) {
156             fprintf(stderr,
157                     "format 0x%x internal RED uses %d bits instead of %d\n",
158                     m_state.format.name, fieldSize, m_state.format.red);
159             m_state.format.red = fieldSize;
160         }
161         gl->glGetRenderbufferParameteriv(
162                 GL_RENDERBUFFER, GL_RENDERBUFFER_GREEN_SIZE, &fieldSize);
163         if (fieldSize != m_state.format.green) {
164             fprintf(stderr,
165                     "format 0x%x internal GREEN uses %d bits instead of %d\n",
166                     m_state.format.name, fieldSize, m_state.format.green);
167             m_state.format.green = fieldSize;
168         }
169         gl->glGetRenderbufferParameteriv(GL_RENDERBUFFER,
170                                          GL_RENDERBUFFER_BLUE_SIZE, &fieldSize);
171         if (fieldSize != m_state.format.blue) {
172             fprintf(stderr,
173                     "format 0x%x internal BLUE uses %d bits instead of %d\n",
174                     m_state.format.name, fieldSize, m_state.format.blue);
175             m_state.format.blue = fieldSize;
176         }
177         gl->glGetRenderbufferParameteriv(
178                 GL_RENDERBUFFER, GL_RENDERBUFFER_ALPHA_SIZE, &fieldSize);
179         if (fieldSize != m_state.format.alpha) {
180             fprintf(stderr,
181                     "format 0x%x internal ALPHA uses %d bits instead of %d\n",
182                     m_state.format.name, fieldSize, m_state.format.alpha);
183             m_state.format.alpha = fieldSize;
184         }
185         gl->glGetRenderbufferParameteriv(
186                 GL_RENDERBUFFER, GL_RENDERBUFFER_DEPTH_SIZE, &fieldSize);
187         if (fieldSize != m_state.format.depth) {
188             fprintf(stderr,
189                     "format 0x%x internal DEPTH uses %d bits instead of %d\n",
190                     m_state.format.name, fieldSize, m_state.format.depth);
191             m_state.format.depth = fieldSize;
192         }
193         gl->glGetRenderbufferParameteriv(
194                 GL_RENDERBUFFER, GL_RENDERBUFFER_STENCIL_SIZE, &fieldSize);
195         if (fieldSize != m_state.format.stencil) {
196             fprintf(stderr,
197                     "format 0x%x internal STENCIL uses %d bits instead of %d\n",
198                     m_state.format.name, fieldSize, m_state.format.stencil);
199             m_state.format.stencil = fieldSize;
200         }
201         EXPECT_EQ(GL_NO_ERROR, gl->glGetError());
202     });
203     doCheckedSnapshot();
204 }
205 
206 INSTANTIATE_TEST_SUITE_P(GLES2SnapshotRenderbuffers,
207                          SnapshotGlRenderbufferFormatTest,
208                          ::testing::ValuesIn(kGLES2TestRenderbufferStates));
209 
210 }  // namespace
211 }  // namespace gl
212 }  // namespace gfxstream
213