1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 2.0 Module
3 * -------------------------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Read pixels tests
22 *//*--------------------------------------------------------------------*/
23
24 #include "es2fReadPixelsTests.hpp"
25
26 #include "tcuTexture.hpp"
27 #include "tcuTextureUtil.hpp"
28 #include "tcuImageCompare.hpp"
29 #include "tcuTestLog.hpp"
30 #include "tcuRenderTarget.hpp"
31
32 #include "deRandom.hpp"
33 #include "deMath.h"
34 #include "deString.h"
35
36 #include "gluDefs.hpp"
37 #include "gluShaderProgram.hpp"
38 #include "gluStrUtil.hpp"
39 #include "gluTextureUtil.hpp"
40
41 #include "glw.h"
42
43 #include <cstring>
44
45 namespace deqp
46 {
47 namespace gles2
48 {
49 namespace Functional
50 {
51
52 class ReadPixelsTest : public TestCase
53 {
54 public:
55 ReadPixelsTest (Context& context, const char* name, const char* description, bool chooseFormat, int alignment);
56
57 IterateResult iterate (void);
58 void render (tcu::Texture2D& reference);
59
60 private:
61 bool m_chooseFormat;
62 int m_alignment;
63 int m_seed;
64
65 void getFormatInfo (tcu::TextureFormat& format, GLint& glFormat, GLint& glType, int& pixelSize, bool& align);
66 };
67
ReadPixelsTest(Context & context,const char * name,const char * description,bool chooseFormat,int alignment)68 ReadPixelsTest::ReadPixelsTest (Context& context, const char* name, const char* description, bool chooseFormat, int alignment)
69 : TestCase (context, name, description)
70 , m_chooseFormat (chooseFormat)
71 , m_alignment (alignment)
72 , m_seed (deStringHash(name))
73 {
74 }
75
render(tcu::Texture2D & reference)76 void ReadPixelsTest::render (tcu::Texture2D& reference)
77 {
78 // Create program
79 const char* vertexSource =
80 "attribute mediump vec2 a_coord;\n"
81 "void main (void)\n"
82 "{\n"
83 "\tgl_Position = vec4(a_coord, 0.0, 1.0);\n"
84 "}\n";
85
86 const char* fragmentSource =
87 "void main (void)\n"
88 "{\n"
89 "\tgl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);\n"
90 "}\n";
91
92 glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(vertexSource, fragmentSource));
93
94 m_testCtx.getLog() << program;
95 TCU_CHECK(program.isOk());
96 GLU_CHECK_CALL(glUseProgram(program.getProgram()));
97
98 // Render
99 {
100 const float coords[] =
101 {
102 -0.5f, -0.5f,
103 0.5f, -0.5f,
104 0.5f, 0.5f,
105
106 0.5f, 0.5f,
107 -0.5f, 0.5f,
108 -0.5f, -0.5f
109 };
110 GLuint coordLoc;
111
112 coordLoc = glGetAttribLocation(program.getProgram(), "a_coord");
113 GLU_CHECK_MSG("glGetAttribLocation()");
114
115 GLU_CHECK_CALL(glEnableVertexAttribArray(coordLoc));
116
117 GLU_CHECK_CALL(glVertexAttribPointer(coordLoc, 2, GL_FLOAT, GL_FALSE, 0, coords));
118
119 GLU_CHECK_CALL(glDrawArrays(GL_TRIANGLES, 0, 6));
120 GLU_CHECK_CALL(glDisableVertexAttribArray(coordLoc));
121 }
122
123 // Render reference
124
125 const int coordX1 = (int)((-0.5f * reference.getWidth() / 2.0f) + reference.getWidth() / 2.0f);
126 const int coordY1 = (int)((-0.5f * reference.getHeight() / 2.0f) + reference.getHeight() / 2.0f);
127 const int coordX2 = (int)(( 0.5f * reference.getWidth() / 2.0f) + reference.getWidth() / 2.0f);
128 const int coordY2 = (int)(( 0.5f * reference.getHeight() / 2.0f) + reference.getHeight() / 2.0f);
129
130 for (int x = 0; x < reference.getWidth(); x++)
131 {
132 if (x < coordX1 || x > coordX2)
133 continue;
134
135 for (int y = 0; y < reference.getHeight(); y++)
136 {
137 if (y >= coordY1 && y <= coordY2)
138 reference.getLevel(0).setPixel(tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), x, y);
139 }
140 }
141 }
142
getFormatInfo(tcu::TextureFormat & format,GLint & glFormat,GLint & glType,int & pixelSize,bool & align)143 void ReadPixelsTest::getFormatInfo (tcu::TextureFormat& format, GLint& glFormat, GLint& glType, int& pixelSize, bool& align)
144 {
145 if (m_chooseFormat)
146 {
147 GLU_CHECK_CALL(glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &glFormat));
148 GLU_CHECK_CALL(glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &glType));
149
150 format = glu::mapGLTransferFormat(glFormat, glType);
151
152 // Check if aligment is allowed
153 switch (glType)
154 {
155 case GL_BYTE:
156 case GL_UNSIGNED_BYTE:
157 case GL_SHORT:
158 case GL_UNSIGNED_SHORT:
159 case GL_INT:
160 case GL_UNSIGNED_INT:
161 case GL_FLOAT:
162 case GL_HALF_FLOAT:
163 align = true;
164 break;
165
166 case GL_UNSIGNED_SHORT_5_6_5:
167 case GL_UNSIGNED_SHORT_4_4_4_4:
168 case GL_UNSIGNED_SHORT_5_5_5_1:
169 case GL_UNSIGNED_INT_2_10_10_10_REV:
170 case GL_UNSIGNED_INT_10F_11F_11F_REV:
171 case GL_UNSIGNED_INT_24_8:
172 case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
173 case GL_UNSIGNED_INT_5_9_9_9_REV:
174 align = false;
175 break;
176
177 default:
178 throw tcu::InternalError("Unsupported format", "", __FILE__, __LINE__);
179 }
180
181 pixelSize = format.getPixelSize();
182 }
183 else
184 {
185 format = tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
186 pixelSize = 1 * 4;
187 align = true;
188 glFormat = GL_RGBA;
189 glType = GL_UNSIGNED_BYTE;
190 }
191 }
192
iterate(void)193 TestCase::IterateResult ReadPixelsTest::iterate (void)
194 {
195 // Create reference
196 const int width = 13;
197 const int height = 13;
198
199 de::Random rnd(m_seed);
200
201 tcu::TextureFormat format(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
202 int pixelSize;
203 GLint glFormat;
204 GLint glType;
205 bool align;
206
207 getFormatInfo(format, glFormat, glType, pixelSize, align);
208 m_testCtx.getLog() << tcu::TestLog::Message << "Format: " << glu::getPixelFormatStr(glFormat) << ", Type: " << glu::getTypeStr(glType) << tcu::TestLog::EndMessage;
209
210 tcu::Texture2D reference(format, width, height);
211 reference.allocLevel(0);
212
213 GLU_CHECK_CALL(glViewport(0, 0, width, height));
214
215 // Clear color
216 {
217 const float red = rnd.getFloat();
218 const float green = rnd.getFloat();
219 const float blue = rnd.getFloat();
220 const float alpha = 1.0f;
221
222 m_testCtx.getLog() << tcu::TestLog::Message << "Clear color: (" << red << ", " << green << ", " << blue << ", " << alpha << ")" << tcu::TestLog::EndMessage;
223
224 // Clear target
225 GLU_CHECK_CALL(glClearColor(red, green, blue, alpha));
226 GLU_CHECK_CALL(glClear(GL_COLOR_BUFFER_BIT));
227
228 // Clear reference
229 for (int x = 0; x < reference.getWidth(); x++)
230 for (int y = 0; y < reference.getHeight(); y++)
231 reference.getLevel(0).setPixel(tcu::Vec4(red, green, blue, alpha), x, y);
232 }
233
234 render(reference);
235
236 std::vector<deUint8> pixelData;
237 const int rowPitch = (align ? m_alignment * deCeilFloatToInt32(pixelSize * width / (float)m_alignment) : width * pixelSize);
238
239 pixelData.resize(rowPitch * height, 0);
240
241 GLU_CHECK_CALL(glPixelStorei(GL_PACK_ALIGNMENT, m_alignment));
242 GLU_CHECK_CALL(glReadPixels(0, 0, width, height, glFormat, glType, &(pixelData[0])));
243
244 if (m_context.getRenderTarget().getNumSamples() > 1)
245 {
246 const tcu::IVec4 formatBitDepths = tcu::getTextureFormatBitDepth(format);
247 const deUint8 redThreshold = (deUint8)deCeilFloatToInt32(256.0f * (2.0f / (1 << deMin32(m_context.getRenderTarget().getPixelFormat().redBits, formatBitDepths.x()))));
248 const deUint8 greenThreshold = (deUint8)deCeilFloatToInt32(256.0f * (2.0f / (1 << deMin32(m_context.getRenderTarget().getPixelFormat().greenBits, formatBitDepths.y()))));
249 const deUint8 blueThreshold = (deUint8)deCeilFloatToInt32(256.0f * (2.0f / (1 << deMin32(m_context.getRenderTarget().getPixelFormat().blueBits, formatBitDepths.z()))));
250 const deUint8 alphaThreshold = (deUint8)deCeilFloatToInt32(256.0f * (2.0f / (1 << deMin32(m_context.getRenderTarget().getPixelFormat().alphaBits, formatBitDepths.w()))));
251
252 if (tcu::bilinearCompare(m_testCtx.getLog(), "Result", "Result", reference.getLevel(0), tcu::PixelBufferAccess(format, width, height, 1, rowPitch, 0, &(pixelData[0])), tcu::RGBA(redThreshold, greenThreshold, blueThreshold, alphaThreshold), tcu::COMPARE_LOG_RESULT))
253 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
254 else
255 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
256 }
257 else
258 {
259 const tcu::IVec4 formatBitDepths = tcu::getTextureFormatBitDepth(format);
260 const float redThreshold = 2.0f / (1 << deMin32(m_context.getRenderTarget().getPixelFormat().redBits, formatBitDepths.x()));
261 const float greenThreshold = 2.0f / (1 << deMin32(m_context.getRenderTarget().getPixelFormat().greenBits, formatBitDepths.y()));
262 const float blueThreshold = 2.0f / (1 << deMin32(m_context.getRenderTarget().getPixelFormat().blueBits, formatBitDepths.z()));
263 const float alphaThreshold = 2.0f / (1 << deMin32(m_context.getRenderTarget().getPixelFormat().alphaBits, formatBitDepths.w()));
264
265 // Compare
266 if (tcu::floatThresholdCompare(m_testCtx.getLog(), "Result", "Result", reference.getLevel(0), tcu::PixelBufferAccess(format, width, height, 1, rowPitch, 0, &(pixelData[0])), tcu::Vec4(redThreshold, greenThreshold, blueThreshold, alphaThreshold), tcu::COMPARE_LOG_RESULT))
267 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
268 else
269 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
270 }
271
272 return STOP;
273 }
274
ReadPixelsTests(Context & context)275 ReadPixelsTests::ReadPixelsTests (Context& context)
276 : TestCaseGroup(context, "read_pixels", "ReadPixel tests")
277 {
278 }
279
init(void)280 void ReadPixelsTests::init (void)
281 {
282 addChild(new ReadPixelsTest(m_context, "rgba_ubyte_align_1", "", false, 1));
283 addChild(new ReadPixelsTest(m_context, "rgba_ubyte_align_2", "", false, 2));
284 addChild(new ReadPixelsTest(m_context, "rgba_ubyte_align_4", "", false, 4));
285 addChild(new ReadPixelsTest(m_context, "rgba_ubyte_align_8", "", false, 8));
286
287 addChild(new ReadPixelsTest(m_context, "choose_align_1", "", true, 1));
288 addChild(new ReadPixelsTest(m_context, "choose_align_2", "", true, 2));
289 addChild(new ReadPixelsTest(m_context, "choose_align_4", "", true, 4));
290 addChild(new ReadPixelsTest(m_context, "choose_align_8", "", true, 8));
291 }
292
293 } // Functional
294 } // gles2
295 } // deqp
296