xref: /aosp_15_r20/external/deqp/modules/glshared/glsLifetimeTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
2*35238bceSAndroid Build Coastguard Worker  * drawElements Quality Program OpenGL (ES) Module
3*35238bceSAndroid Build Coastguard Worker  * -----------------------------------------------
4*35238bceSAndroid Build Coastguard Worker  *
5*35238bceSAndroid Build Coastguard Worker  * Copyright 2014 The Android Open Source Project
6*35238bceSAndroid Build Coastguard Worker  *
7*35238bceSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
8*35238bceSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
9*35238bceSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
10*35238bceSAndroid Build Coastguard Worker  *
11*35238bceSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
12*35238bceSAndroid Build Coastguard Worker  *
13*35238bceSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
14*35238bceSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
15*35238bceSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16*35238bceSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
17*35238bceSAndroid Build Coastguard Worker  * limitations under the License.
18*35238bceSAndroid Build Coastguard Worker  *
19*35238bceSAndroid Build Coastguard Worker  *//*!
20*35238bceSAndroid Build Coastguard Worker  * \file
21*35238bceSAndroid Build Coastguard Worker  * \brief Common object lifetime tests.
22*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
23*35238bceSAndroid Build Coastguard Worker 
24*35238bceSAndroid Build Coastguard Worker #include "glsLifetimeTests.hpp"
25*35238bceSAndroid Build Coastguard Worker 
26*35238bceSAndroid Build Coastguard Worker #include "deString.h"
27*35238bceSAndroid Build Coastguard Worker #include "deRandom.hpp"
28*35238bceSAndroid Build Coastguard Worker #include "deSTLUtil.hpp"
29*35238bceSAndroid Build Coastguard Worker #include "deStringUtil.hpp"
30*35238bceSAndroid Build Coastguard Worker #include "tcuRGBA.hpp"
31*35238bceSAndroid Build Coastguard Worker #include "tcuImageCompare.hpp"
32*35238bceSAndroid Build Coastguard Worker #include "tcuRenderTarget.hpp"
33*35238bceSAndroid Build Coastguard Worker #include "tcuStringTemplate.hpp"
34*35238bceSAndroid Build Coastguard Worker #include "tcuTestLog.hpp"
35*35238bceSAndroid Build Coastguard Worker #include "gluDrawUtil.hpp"
36*35238bceSAndroid Build Coastguard Worker #include "gluObjectWrapper.hpp"
37*35238bceSAndroid Build Coastguard Worker #include "gluPixelTransfer.hpp"
38*35238bceSAndroid Build Coastguard Worker #include "gluShaderProgram.hpp"
39*35238bceSAndroid Build Coastguard Worker #include "gluDefs.hpp"
40*35238bceSAndroid Build Coastguard Worker #include "gluTextureUtil.hpp"
41*35238bceSAndroid Build Coastguard Worker #include "gluStrUtil.hpp"
42*35238bceSAndroid Build Coastguard Worker #include "glwFunctions.hpp"
43*35238bceSAndroid Build Coastguard Worker 
44*35238bceSAndroid Build Coastguard Worker #include <vector>
45*35238bceSAndroid Build Coastguard Worker #include <map>
46*35238bceSAndroid Build Coastguard Worker #include <algorithm>
47*35238bceSAndroid Build Coastguard Worker #include <sstream>
48*35238bceSAndroid Build Coastguard Worker 
49*35238bceSAndroid Build Coastguard Worker namespace deqp
50*35238bceSAndroid Build Coastguard Worker {
51*35238bceSAndroid Build Coastguard Worker namespace gls
52*35238bceSAndroid Build Coastguard Worker {
53*35238bceSAndroid Build Coastguard Worker namespace LifetimeTests
54*35238bceSAndroid Build Coastguard Worker {
55*35238bceSAndroid Build Coastguard Worker namespace details
56*35238bceSAndroid Build Coastguard Worker {
57*35238bceSAndroid Build Coastguard Worker 
58*35238bceSAndroid Build Coastguard Worker using de::Random;
59*35238bceSAndroid Build Coastguard Worker using std::map;
60*35238bceSAndroid Build Coastguard Worker using std::ostringstream;
61*35238bceSAndroid Build Coastguard Worker using std::string;
62*35238bceSAndroid Build Coastguard Worker using tcu::RenderTarget;
63*35238bceSAndroid Build Coastguard Worker using tcu::RGBA;
64*35238bceSAndroid Build Coastguard Worker using tcu::StringTemplate;
65*35238bceSAndroid Build Coastguard Worker using tcu::TestCase;
66*35238bceSAndroid Build Coastguard Worker typedef TestCase::IterateResult IterateResult;
67*35238bceSAndroid Build Coastguard Worker using glu::Framebuffer;
68*35238bceSAndroid Build Coastguard Worker using glu::Program;
69*35238bceSAndroid Build Coastguard Worker using glu::Shader;
70*35238bceSAndroid Build Coastguard Worker using glu::SHADERTYPE_FRAGMENT;
71*35238bceSAndroid Build Coastguard Worker using glu::SHADERTYPE_VERTEX;
72*35238bceSAndroid Build Coastguard Worker using tcu::ScopedLogSection;
73*35238bceSAndroid Build Coastguard Worker using tcu::TestLog;
74*35238bceSAndroid Build Coastguard Worker using namespace glw;
75*35238bceSAndroid Build Coastguard Worker 
76*35238bceSAndroid Build Coastguard Worker enum
77*35238bceSAndroid Build Coastguard Worker {
78*35238bceSAndroid Build Coastguard Worker     VIEWPORT_SIZE    = 128,
79*35238bceSAndroid Build Coastguard Worker     FRAMEBUFFER_SIZE = 128
80*35238bceSAndroid Build Coastguard Worker };
81*35238bceSAndroid Build Coastguard Worker 
getInteger(ContextWrapper & gl,GLenum queryParam)82*35238bceSAndroid Build Coastguard Worker GLint getInteger(ContextWrapper &gl, GLenum queryParam)
83*35238bceSAndroid Build Coastguard Worker {
84*35238bceSAndroid Build Coastguard Worker     GLint ret = 0;
85*35238bceSAndroid Build Coastguard Worker     GLU_CHECK_CALL_ERROR(gl.glGetIntegerv(queryParam, &ret), gl.glGetError());
86*35238bceSAndroid Build Coastguard Worker     gl.log() << TestLog::Message << "// Single integer output: " << ret << TestLog::EndMessage;
87*35238bceSAndroid Build Coastguard Worker     return ret;
88*35238bceSAndroid Build Coastguard Worker }
89*35238bceSAndroid Build Coastguard Worker 
90*35238bceSAndroid Build Coastguard Worker #define GLSL100_SRC(BODY) ("#version 100\n" #BODY "\n")
91*35238bceSAndroid Build Coastguard Worker 
92*35238bceSAndroid Build Coastguard Worker static const char *const s_vertexShaderSrc =
93*35238bceSAndroid Build Coastguard Worker     GLSL100_SRC(attribute vec2 pos; void main() { gl_Position = vec4(pos.xy, 0.0, 1.0); });
94*35238bceSAndroid Build Coastguard Worker 
95*35238bceSAndroid Build Coastguard Worker static const char *const s_fragmentShaderSrc = GLSL100_SRC(void main() { gl_FragColor = vec4(1.0); });
96*35238bceSAndroid Build Coastguard Worker 
97*35238bceSAndroid Build Coastguard Worker class CheckedShader : public Shader
98*35238bceSAndroid Build Coastguard Worker {
99*35238bceSAndroid Build Coastguard Worker public:
CheckedShader(const RenderContext & renderCtx,glu::ShaderType type,const string & src)100*35238bceSAndroid Build Coastguard Worker     CheckedShader(const RenderContext &renderCtx, glu::ShaderType type, const string &src) : Shader(renderCtx, type)
101*35238bceSAndroid Build Coastguard Worker     {
102*35238bceSAndroid Build Coastguard Worker         const char *const srcStr = src.c_str();
103*35238bceSAndroid Build Coastguard Worker         setSources(1, &srcStr, DE_NULL);
104*35238bceSAndroid Build Coastguard Worker         compile();
105*35238bceSAndroid Build Coastguard Worker         TCU_CHECK(getCompileStatus());
106*35238bceSAndroid Build Coastguard Worker     }
107*35238bceSAndroid Build Coastguard Worker };
108*35238bceSAndroid Build Coastguard Worker 
109*35238bceSAndroid Build Coastguard Worker class CheckedProgram : public Program
110*35238bceSAndroid Build Coastguard Worker {
111*35238bceSAndroid Build Coastguard Worker public:
CheckedProgram(const RenderContext & renderCtx,GLuint vtxShader,GLuint fragShader)112*35238bceSAndroid Build Coastguard Worker     CheckedProgram(const RenderContext &renderCtx, GLuint vtxShader, GLuint fragShader) : Program(renderCtx)
113*35238bceSAndroid Build Coastguard Worker     {
114*35238bceSAndroid Build Coastguard Worker         attachShader(vtxShader);
115*35238bceSAndroid Build Coastguard Worker         attachShader(fragShader);
116*35238bceSAndroid Build Coastguard Worker         link();
117*35238bceSAndroid Build Coastguard Worker         TCU_CHECK(getLinkStatus());
118*35238bceSAndroid Build Coastguard Worker     }
119*35238bceSAndroid Build Coastguard Worker };
120*35238bceSAndroid Build Coastguard Worker 
ContextWrapper(const Context & ctx)121*35238bceSAndroid Build Coastguard Worker ContextWrapper::ContextWrapper(const Context &ctx) : CallLogWrapper(ctx.gl(), ctx.log()), m_ctx(ctx)
122*35238bceSAndroid Build Coastguard Worker {
123*35238bceSAndroid Build Coastguard Worker     enableLogging(true);
124*35238bceSAndroid Build Coastguard Worker }
125*35238bceSAndroid Build Coastguard Worker 
bind(GLuint name)126*35238bceSAndroid Build Coastguard Worker void SimpleBinder::bind(GLuint name)
127*35238bceSAndroid Build Coastguard Worker {
128*35238bceSAndroid Build Coastguard Worker     (this->*m_bindFunc)(m_bindTarget, name);
129*35238bceSAndroid Build Coastguard Worker }
130*35238bceSAndroid Build Coastguard Worker 
getBinding(void)131*35238bceSAndroid Build Coastguard Worker GLuint SimpleBinder::getBinding(void)
132*35238bceSAndroid Build Coastguard Worker {
133*35238bceSAndroid Build Coastguard Worker     return getInteger(*this, m_bindingParam);
134*35238bceSAndroid Build Coastguard Worker }
135*35238bceSAndroid Build Coastguard Worker 
gen(void)136*35238bceSAndroid Build Coastguard Worker GLuint SimpleType::gen(void)
137*35238bceSAndroid Build Coastguard Worker {
138*35238bceSAndroid Build Coastguard Worker     GLuint ret;
139*35238bceSAndroid Build Coastguard Worker     (this->*m_genFunc)(1, &ret);
140*35238bceSAndroid Build Coastguard Worker     return ret;
141*35238bceSAndroid Build Coastguard Worker }
142*35238bceSAndroid Build Coastguard Worker 
143*35238bceSAndroid Build Coastguard Worker class VertexArrayBinder : public SimpleBinder
144*35238bceSAndroid Build Coastguard Worker {
145*35238bceSAndroid Build Coastguard Worker public:
VertexArrayBinder(Context & ctx)146*35238bceSAndroid Build Coastguard Worker     VertexArrayBinder(Context &ctx) : SimpleBinder(ctx, 0, GL_NONE, GL_VERTEX_ARRAY_BINDING, true)
147*35238bceSAndroid Build Coastguard Worker     {
148*35238bceSAndroid Build Coastguard Worker     }
bind(GLuint name)149*35238bceSAndroid Build Coastguard Worker     void bind(GLuint name)
150*35238bceSAndroid Build Coastguard Worker     {
151*35238bceSAndroid Build Coastguard Worker         glBindVertexArray(name);
152*35238bceSAndroid Build Coastguard Worker     }
153*35238bceSAndroid Build Coastguard Worker };
154*35238bceSAndroid Build Coastguard Worker 
155*35238bceSAndroid Build Coastguard Worker class QueryBinder : public Binder
156*35238bceSAndroid Build Coastguard Worker {
157*35238bceSAndroid Build Coastguard Worker public:
QueryBinder(Context & ctx)158*35238bceSAndroid Build Coastguard Worker     QueryBinder(Context &ctx) : Binder(ctx)
159*35238bceSAndroid Build Coastguard Worker     {
160*35238bceSAndroid Build Coastguard Worker     }
bind(GLuint name)161*35238bceSAndroid Build Coastguard Worker     void bind(GLuint name)
162*35238bceSAndroid Build Coastguard Worker     {
163*35238bceSAndroid Build Coastguard Worker         if (name != 0)
164*35238bceSAndroid Build Coastguard Worker             glBeginQuery(GL_ANY_SAMPLES_PASSED, name);
165*35238bceSAndroid Build Coastguard Worker         else
166*35238bceSAndroid Build Coastguard Worker             glEndQuery(GL_ANY_SAMPLES_PASSED);
167*35238bceSAndroid Build Coastguard Worker     }
getBinding(void)168*35238bceSAndroid Build Coastguard Worker     GLuint getBinding(void)
169*35238bceSAndroid Build Coastguard Worker     {
170*35238bceSAndroid Build Coastguard Worker         return 0;
171*35238bceSAndroid Build Coastguard Worker     }
172*35238bceSAndroid Build Coastguard Worker };
173*35238bceSAndroid Build Coastguard Worker 
isDeleteFlagged(GLuint name)174*35238bceSAndroid Build Coastguard Worker bool ProgramType::isDeleteFlagged(GLuint name)
175*35238bceSAndroid Build Coastguard Worker {
176*35238bceSAndroid Build Coastguard Worker     GLint deleteFlagged = 0;
177*35238bceSAndroid Build Coastguard Worker     glGetProgramiv(name, GL_DELETE_STATUS, &deleteFlagged);
178*35238bceSAndroid Build Coastguard Worker     return deleteFlagged != 0;
179*35238bceSAndroid Build Coastguard Worker }
180*35238bceSAndroid Build Coastguard Worker 
isDeleteFlagged(GLuint name)181*35238bceSAndroid Build Coastguard Worker bool ShaderType::isDeleteFlagged(GLuint name)
182*35238bceSAndroid Build Coastguard Worker {
183*35238bceSAndroid Build Coastguard Worker     GLint deleteFlagged = 0;
184*35238bceSAndroid Build Coastguard Worker     glGetShaderiv(name, GL_DELETE_STATUS, &deleteFlagged);
185*35238bceSAndroid Build Coastguard Worker     return deleteFlagged != 0;
186*35238bceSAndroid Build Coastguard Worker }
187*35238bceSAndroid Build Coastguard Worker 
setupFbo(const Context & ctx,GLuint seed,GLuint fbo)188*35238bceSAndroid Build Coastguard Worker void setupFbo(const Context &ctx, GLuint seed, GLuint fbo)
189*35238bceSAndroid Build Coastguard Worker {
190*35238bceSAndroid Build Coastguard Worker     const Functions &gl = ctx.getRenderContext().getFunctions();
191*35238bceSAndroid Build Coastguard Worker 
192*35238bceSAndroid Build Coastguard Worker     GLU_CHECK_CALL_ERROR(gl.bindFramebuffer(GL_FRAMEBUFFER, fbo), gl.getError());
193*35238bceSAndroid Build Coastguard Worker 
194*35238bceSAndroid Build Coastguard Worker     if (seed == 0)
195*35238bceSAndroid Build Coastguard Worker     {
196*35238bceSAndroid Build Coastguard Worker         gl.clearColor(0.0, 0.0, 0.0, 1.0);
197*35238bceSAndroid Build Coastguard Worker         GLU_CHECK_CALL_ERROR(gl.clear(GL_COLOR_BUFFER_BIT), gl.getError());
198*35238bceSAndroid Build Coastguard Worker     }
199*35238bceSAndroid Build Coastguard Worker     else
200*35238bceSAndroid Build Coastguard Worker     {
201*35238bceSAndroid Build Coastguard Worker         Random rnd(seed);
202*35238bceSAndroid Build Coastguard Worker         const GLsizei width  = rnd.getInt(0, FRAMEBUFFER_SIZE);
203*35238bceSAndroid Build Coastguard Worker         const GLsizei height = rnd.getInt(0, FRAMEBUFFER_SIZE);
204*35238bceSAndroid Build Coastguard Worker         const GLint x        = rnd.getInt(0, FRAMEBUFFER_SIZE - width);
205*35238bceSAndroid Build Coastguard Worker         const GLint y        = rnd.getInt(0, FRAMEBUFFER_SIZE - height);
206*35238bceSAndroid Build Coastguard Worker         const GLfloat r1     = rnd.getFloat();
207*35238bceSAndroid Build Coastguard Worker         const GLfloat g1     = rnd.getFloat();
208*35238bceSAndroid Build Coastguard Worker         const GLfloat b1     = rnd.getFloat();
209*35238bceSAndroid Build Coastguard Worker         const GLfloat a1     = rnd.getFloat();
210*35238bceSAndroid Build Coastguard Worker         const GLfloat r2     = rnd.getFloat();
211*35238bceSAndroid Build Coastguard Worker         const GLfloat g2     = rnd.getFloat();
212*35238bceSAndroid Build Coastguard Worker         const GLfloat b2     = rnd.getFloat();
213*35238bceSAndroid Build Coastguard Worker         const GLfloat a2     = rnd.getFloat();
214*35238bceSAndroid Build Coastguard Worker 
215*35238bceSAndroid Build Coastguard Worker         GLU_CHECK_CALL_ERROR(gl.clearColor(r1, g1, b1, a1), gl.getError());
216*35238bceSAndroid Build Coastguard Worker         GLU_CHECK_CALL_ERROR(gl.clear(GL_COLOR_BUFFER_BIT), gl.getError());
217*35238bceSAndroid Build Coastguard Worker         gl.scissor(x, y, width, height);
218*35238bceSAndroid Build Coastguard Worker         gl.enable(GL_SCISSOR_TEST);
219*35238bceSAndroid Build Coastguard Worker         gl.clearColor(r2, g2, b2, a2);
220*35238bceSAndroid Build Coastguard Worker         gl.clear(GL_COLOR_BUFFER_BIT);
221*35238bceSAndroid Build Coastguard Worker         gl.disable(GL_SCISSOR_TEST);
222*35238bceSAndroid Build Coastguard Worker     }
223*35238bceSAndroid Build Coastguard Worker 
224*35238bceSAndroid Build Coastguard Worker     gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
225*35238bceSAndroid Build Coastguard Worker     GLU_CHECK_ERROR(gl.getError());
226*35238bceSAndroid Build Coastguard Worker }
227*35238bceSAndroid Build Coastguard Worker 
drawFbo(const Context & ctx,GLuint fbo,Surface & dst)228*35238bceSAndroid Build Coastguard Worker void drawFbo(const Context &ctx, GLuint fbo, Surface &dst)
229*35238bceSAndroid Build Coastguard Worker {
230*35238bceSAndroid Build Coastguard Worker     const RenderContext &renderCtx = ctx.getRenderContext();
231*35238bceSAndroid Build Coastguard Worker     const Functions &gl            = renderCtx.getFunctions();
232*35238bceSAndroid Build Coastguard Worker 
233*35238bceSAndroid Build Coastguard Worker     GLU_CHECK_CALL_ERROR(gl.bindFramebuffer(GL_FRAMEBUFFER, fbo), gl.getError());
234*35238bceSAndroid Build Coastguard Worker 
235*35238bceSAndroid Build Coastguard Worker     dst.setSize(FRAMEBUFFER_SIZE, FRAMEBUFFER_SIZE);
236*35238bceSAndroid Build Coastguard Worker     glu::readPixels(renderCtx, 0, 0, dst.getAccess());
237*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.getError(), "Read pixels from framebuffer");
238*35238bceSAndroid Build Coastguard Worker 
239*35238bceSAndroid Build Coastguard Worker     GLU_CHECK_CALL_ERROR(gl.bindFramebuffer(GL_FRAMEBUFFER, 0), gl.getError());
240*35238bceSAndroid Build Coastguard Worker }
241*35238bceSAndroid Build Coastguard Worker 
getFboAttachment(const Functions & gl,GLuint fbo,GLenum requiredType)242*35238bceSAndroid Build Coastguard Worker GLuint getFboAttachment(const Functions &gl, GLuint fbo, GLenum requiredType)
243*35238bceSAndroid Build Coastguard Worker {
244*35238bceSAndroid Build Coastguard Worker     GLint type = 0, name = 0;
245*35238bceSAndroid Build Coastguard Worker     gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
246*35238bceSAndroid Build Coastguard Worker     GLU_CHECK_CALL_ERROR(gl.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
247*35238bceSAndroid Build Coastguard Worker                                                                 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &type),
248*35238bceSAndroid Build Coastguard Worker                          gl.getError());
249*35238bceSAndroid Build Coastguard Worker 
250*35238bceSAndroid Build Coastguard Worker     if (GLenum(type) != requiredType || GLenum(type) == GL_NONE)
251*35238bceSAndroid Build Coastguard Worker         return 0;
252*35238bceSAndroid Build Coastguard Worker 
253*35238bceSAndroid Build Coastguard Worker     GLU_CHECK_CALL_ERROR(gl.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
254*35238bceSAndroid Build Coastguard Worker                                                                 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &name),
255*35238bceSAndroid Build Coastguard Worker                          gl.getError());
256*35238bceSAndroid Build Coastguard Worker     gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
257*35238bceSAndroid Build Coastguard Worker     GLU_CHECK_ERROR(gl.getError());
258*35238bceSAndroid Build Coastguard Worker 
259*35238bceSAndroid Build Coastguard Worker     return name;
260*35238bceSAndroid Build Coastguard Worker }
261*35238bceSAndroid Build Coastguard Worker 
initAttachment(GLuint seed,GLuint element)262*35238bceSAndroid Build Coastguard Worker void FboAttacher::initAttachment(GLuint seed, GLuint element)
263*35238bceSAndroid Build Coastguard Worker {
264*35238bceSAndroid Build Coastguard Worker     Binder &binder = *getElementType().binder();
265*35238bceSAndroid Build Coastguard Worker     Framebuffer fbo(getRenderContext());
266*35238bceSAndroid Build Coastguard Worker 
267*35238bceSAndroid Build Coastguard Worker     enableLogging(false);
268*35238bceSAndroid Build Coastguard Worker 
269*35238bceSAndroid Build Coastguard Worker     binder.enableLogging(false);
270*35238bceSAndroid Build Coastguard Worker     binder.bind(element);
271*35238bceSAndroid Build Coastguard Worker     initStorage();
272*35238bceSAndroid Build Coastguard Worker     binder.bind(0);
273*35238bceSAndroid Build Coastguard Worker     binder.enableLogging(true);
274*35238bceSAndroid Build Coastguard Worker 
275*35238bceSAndroid Build Coastguard Worker     attach(element, *fbo);
276*35238bceSAndroid Build Coastguard Worker     setupFbo(getContext(), seed, *fbo);
277*35238bceSAndroid Build Coastguard Worker     detach(element, *fbo);
278*35238bceSAndroid Build Coastguard Worker 
279*35238bceSAndroid Build Coastguard Worker     enableLogging(true);
280*35238bceSAndroid Build Coastguard Worker 
281*35238bceSAndroid Build Coastguard Worker     log() << TestLog::Message << "// Drew to " << getElementType().getName() << " " << element << " with seed " << seed
282*35238bceSAndroid Build Coastguard Worker           << "." << TestLog::EndMessage;
283*35238bceSAndroid Build Coastguard Worker }
284*35238bceSAndroid Build Coastguard Worker 
drawContainer(GLuint fbo,Surface & dst)285*35238bceSAndroid Build Coastguard Worker void FboInputAttacher::drawContainer(GLuint fbo, Surface &dst)
286*35238bceSAndroid Build Coastguard Worker {
287*35238bceSAndroid Build Coastguard Worker     drawFbo(getContext(), fbo, dst);
288*35238bceSAndroid Build Coastguard Worker     log() << TestLog::Message << "// Read pixels from framebuffer " << fbo << " to output image."
289*35238bceSAndroid Build Coastguard Worker           << TestLog::EndMessage;
290*35238bceSAndroid Build Coastguard Worker }
291*35238bceSAndroid Build Coastguard Worker 
setupContainer(GLuint seed,GLuint fbo)292*35238bceSAndroid Build Coastguard Worker void FboOutputAttacher::setupContainer(GLuint seed, GLuint fbo)
293*35238bceSAndroid Build Coastguard Worker {
294*35238bceSAndroid Build Coastguard Worker     setupFbo(getContext(), seed, fbo);
295*35238bceSAndroid Build Coastguard Worker     log() << TestLog::Message << "// Drew to framebuffer " << fbo << " with seed " << seed << "."
296*35238bceSAndroid Build Coastguard Worker           << TestLog::EndMessage;
297*35238bceSAndroid Build Coastguard Worker }
298*35238bceSAndroid Build Coastguard Worker 
drawAttachment(GLuint element,Surface & dst)299*35238bceSAndroid Build Coastguard Worker void FboOutputAttacher::drawAttachment(GLuint element, Surface &dst)
300*35238bceSAndroid Build Coastguard Worker {
301*35238bceSAndroid Build Coastguard Worker     Framebuffer fbo(getRenderContext());
302*35238bceSAndroid Build Coastguard Worker     m_attacher.enableLogging(false);
303*35238bceSAndroid Build Coastguard Worker     m_attacher.attach(element, *fbo);
304*35238bceSAndroid Build Coastguard Worker     drawFbo(getContext(), *fbo, dst);
305*35238bceSAndroid Build Coastguard Worker     m_attacher.detach(element, *fbo);
306*35238bceSAndroid Build Coastguard Worker     m_attacher.enableLogging(true);
307*35238bceSAndroid Build Coastguard Worker     log() << TestLog::Message << "// Read pixels from " << m_attacher.getElementType().getName() << " " << element
308*35238bceSAndroid Build Coastguard Worker           << " to output image." << TestLog::EndMessage;
309*35238bceSAndroid Build Coastguard Worker     GLU_CHECK_ERROR(gl().getError());
310*35238bceSAndroid Build Coastguard Worker }
311*35238bceSAndroid Build Coastguard Worker 
attach(GLuint texture,GLuint fbo)312*35238bceSAndroid Build Coastguard Worker void TextureFboAttacher::attach(GLuint texture, GLuint fbo)
313*35238bceSAndroid Build Coastguard Worker {
314*35238bceSAndroid Build Coastguard Worker     GLU_CHECK_CALL_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, fbo), gl().getError());
315*35238bceSAndroid Build Coastguard Worker     GLU_CHECK_CALL_ERROR(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0),
316*35238bceSAndroid Build Coastguard Worker                          gl().getError());
317*35238bceSAndroid Build Coastguard Worker     GLU_CHECK_CALL_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, 0), gl().getError());
318*35238bceSAndroid Build Coastguard Worker }
319*35238bceSAndroid Build Coastguard Worker 
detach(GLuint texture,GLuint fbo)320*35238bceSAndroid Build Coastguard Worker void TextureFboAttacher::detach(GLuint texture, GLuint fbo)
321*35238bceSAndroid Build Coastguard Worker {
322*35238bceSAndroid Build Coastguard Worker     DE_UNREF(texture);
323*35238bceSAndroid Build Coastguard Worker     GLU_CHECK_CALL_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, fbo), gl().getError());
324*35238bceSAndroid Build Coastguard Worker     GLU_CHECK_CALL_ERROR(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0),
325*35238bceSAndroid Build Coastguard Worker                          gl().getError());
326*35238bceSAndroid Build Coastguard Worker     GLU_CHECK_CALL_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, 0), gl().getError());
327*35238bceSAndroid Build Coastguard Worker }
328*35238bceSAndroid Build Coastguard Worker 
getAttachment(GLuint fbo)329*35238bceSAndroid Build Coastguard Worker GLuint TextureFboAttacher::getAttachment(GLuint fbo)
330*35238bceSAndroid Build Coastguard Worker {
331*35238bceSAndroid Build Coastguard Worker     return getFboAttachment(gl(), fbo, GL_TEXTURE);
332*35238bceSAndroid Build Coastguard Worker }
333*35238bceSAndroid Build Coastguard Worker 
isTextureFormatColorRenderable(const glu::RenderContext & renderCtx,const glu::TransferFormat & format)334*35238bceSAndroid Build Coastguard Worker static bool isTextureFormatColorRenderable(const glu::RenderContext &renderCtx, const glu::TransferFormat &format)
335*35238bceSAndroid Build Coastguard Worker {
336*35238bceSAndroid Build Coastguard Worker     const glw::Functions &gl = renderCtx.getFunctions();
337*35238bceSAndroid Build Coastguard Worker     uint32_t curFbo          = ~0u;
338*35238bceSAndroid Build Coastguard Worker     uint32_t curTex          = ~0u;
339*35238bceSAndroid Build Coastguard Worker     uint32_t testFbo         = 0u;
340*35238bceSAndroid Build Coastguard Worker     uint32_t testTex         = 0u;
341*35238bceSAndroid Build Coastguard Worker     GLenum status            = GL_NONE;
342*35238bceSAndroid Build Coastguard Worker 
343*35238bceSAndroid Build Coastguard Worker     GLU_CHECK_GLW_CALL(gl, getIntegerv(GL_FRAMEBUFFER_BINDING, (int32_t *)&curFbo));
344*35238bceSAndroid Build Coastguard Worker     GLU_CHECK_GLW_CALL(gl, getIntegerv(GL_TEXTURE_BINDING_2D, (int32_t *)&curTex));
345*35238bceSAndroid Build Coastguard Worker 
346*35238bceSAndroid Build Coastguard Worker     try
347*35238bceSAndroid Build Coastguard Worker     {
348*35238bceSAndroid Build Coastguard Worker         GLU_CHECK_GLW_CALL(gl, genTextures(1, &testTex));
349*35238bceSAndroid Build Coastguard Worker         GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_2D, testTex));
350*35238bceSAndroid Build Coastguard Worker         GLU_CHECK_GLW_CALL(gl, texImage2D(GL_TEXTURE_2D, 0, format.format, FRAMEBUFFER_SIZE, FRAMEBUFFER_SIZE, 0,
351*35238bceSAndroid Build Coastguard Worker                                           format.format, format.dataType, DE_NULL));
352*35238bceSAndroid Build Coastguard Worker 
353*35238bceSAndroid Build Coastguard Worker         GLU_CHECK_GLW_CALL(gl, genFramebuffers(1, &testFbo));
354*35238bceSAndroid Build Coastguard Worker         GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, testFbo));
355*35238bceSAndroid Build Coastguard Worker         GLU_CHECK_GLW_CALL(gl, framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, testTex, 0));
356*35238bceSAndroid Build Coastguard Worker 
357*35238bceSAndroid Build Coastguard Worker         status = gl.checkFramebufferStatus(GL_FRAMEBUFFER);
358*35238bceSAndroid Build Coastguard Worker         GLU_CHECK_GLW_MSG(gl, "glCheckFramebufferStatus(GL_FRAMEBUFFER)");
359*35238bceSAndroid Build Coastguard Worker 
360*35238bceSAndroid Build Coastguard Worker         GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_2D, curTex));
361*35238bceSAndroid Build Coastguard Worker         GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, curFbo));
362*35238bceSAndroid Build Coastguard Worker 
363*35238bceSAndroid Build Coastguard Worker         GLU_CHECK_GLW_CALL(gl, deleteTextures(1, &testTex));
364*35238bceSAndroid Build Coastguard Worker         GLU_CHECK_GLW_CALL(gl, deleteFramebuffers(1, &testFbo));
365*35238bceSAndroid Build Coastguard Worker     }
366*35238bceSAndroid Build Coastguard Worker     catch (...)
367*35238bceSAndroid Build Coastguard Worker     {
368*35238bceSAndroid Build Coastguard Worker         if (testTex != 0)
369*35238bceSAndroid Build Coastguard Worker             gl.deleteTextures(1, &testTex);
370*35238bceSAndroid Build Coastguard Worker 
371*35238bceSAndroid Build Coastguard Worker         if (testFbo != 0)
372*35238bceSAndroid Build Coastguard Worker             gl.deleteFramebuffers(1, &testFbo);
373*35238bceSAndroid Build Coastguard Worker 
374*35238bceSAndroid Build Coastguard Worker         throw;
375*35238bceSAndroid Build Coastguard Worker     }
376*35238bceSAndroid Build Coastguard Worker 
377*35238bceSAndroid Build Coastguard Worker     if (status == GL_FRAMEBUFFER_COMPLETE)
378*35238bceSAndroid Build Coastguard Worker         return true;
379*35238bceSAndroid Build Coastguard Worker     else if (status == GL_FRAMEBUFFER_UNSUPPORTED)
380*35238bceSAndroid Build Coastguard Worker         return false;
381*35238bceSAndroid Build Coastguard Worker     else
382*35238bceSAndroid Build Coastguard Worker         TCU_THROW(TestError, (std::string("glCheckFramebufferStatus() returned invalid result code ") +
383*35238bceSAndroid Build Coastguard Worker                               de::toString(glu::getFramebufferStatusStr(status)))
384*35238bceSAndroid Build Coastguard Worker                                  .c_str());
385*35238bceSAndroid Build Coastguard Worker }
386*35238bceSAndroid Build Coastguard Worker 
getRenderableColorTextureFormat(const glu::RenderContext & renderCtx)387*35238bceSAndroid Build Coastguard Worker static glu::TransferFormat getRenderableColorTextureFormat(const glu::RenderContext &renderCtx)
388*35238bceSAndroid Build Coastguard Worker {
389*35238bceSAndroid Build Coastguard Worker     if (glu::contextSupports(renderCtx.getType(), glu::ApiType::es(3, 0)))
390*35238bceSAndroid Build Coastguard Worker         return glu::TransferFormat(GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4);
391*35238bceSAndroid Build Coastguard Worker 
392*35238bceSAndroid Build Coastguard Worker     {
393*35238bceSAndroid Build Coastguard Worker         const glu::TransferFormat candidates[] = {
394*35238bceSAndroid Build Coastguard Worker             glu::TransferFormat(GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4),
395*35238bceSAndroid Build Coastguard Worker             glu::TransferFormat(GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1),
396*35238bceSAndroid Build Coastguard Worker             glu::TransferFormat(GL_RGB, GL_UNSIGNED_SHORT_5_6_5),
397*35238bceSAndroid Build Coastguard Worker             glu::TransferFormat(GL_RGBA, GL_UNSIGNED_BYTE),
398*35238bceSAndroid Build Coastguard Worker         };
399*35238bceSAndroid Build Coastguard Worker 
400*35238bceSAndroid Build Coastguard Worker         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(candidates); ++ndx)
401*35238bceSAndroid Build Coastguard Worker         {
402*35238bceSAndroid Build Coastguard Worker             if (isTextureFormatColorRenderable(renderCtx, candidates[ndx]))
403*35238bceSAndroid Build Coastguard Worker                 return candidates[ndx];
404*35238bceSAndroid Build Coastguard Worker         }
405*35238bceSAndroid Build Coastguard Worker     }
406*35238bceSAndroid Build Coastguard Worker 
407*35238bceSAndroid Build Coastguard Worker     return glu::TransferFormat(GL_NONE, GL_NONE);
408*35238bceSAndroid Build Coastguard Worker }
409*35238bceSAndroid Build Coastguard Worker 
initStorage(void)410*35238bceSAndroid Build Coastguard Worker void TextureFboAttacher::initStorage(void)
411*35238bceSAndroid Build Coastguard Worker {
412*35238bceSAndroid Build Coastguard Worker     const glu::TransferFormat format = getRenderableColorTextureFormat(getRenderContext());
413*35238bceSAndroid Build Coastguard Worker 
414*35238bceSAndroid Build Coastguard Worker     if (format.format == GL_NONE)
415*35238bceSAndroid Build Coastguard Worker         TCU_THROW(NotSupportedError, "No renderable texture format found");
416*35238bceSAndroid Build Coastguard Worker 
417*35238bceSAndroid Build Coastguard Worker     GLU_CHECK_CALL_ERROR(glTexImage2D(GL_TEXTURE_2D, 0, format.format, FRAMEBUFFER_SIZE, FRAMEBUFFER_SIZE, 0,
418*35238bceSAndroid Build Coastguard Worker                                       format.format, format.dataType, DE_NULL),
419*35238bceSAndroid Build Coastguard Worker                          gl().getError());
420*35238bceSAndroid Build Coastguard Worker }
421*35238bceSAndroid Build Coastguard Worker 
isRenderbufferFormatColorRenderable(const glu::RenderContext & renderCtx,const uint32_t format)422*35238bceSAndroid Build Coastguard Worker static bool isRenderbufferFormatColorRenderable(const glu::RenderContext &renderCtx, const uint32_t format)
423*35238bceSAndroid Build Coastguard Worker {
424*35238bceSAndroid Build Coastguard Worker     const glw::Functions &gl = renderCtx.getFunctions();
425*35238bceSAndroid Build Coastguard Worker     uint32_t curFbo          = ~0u;
426*35238bceSAndroid Build Coastguard Worker     uint32_t curRbo          = ~0u;
427*35238bceSAndroid Build Coastguard Worker     uint32_t testFbo         = 0u;
428*35238bceSAndroid Build Coastguard Worker     uint32_t testRbo         = 0u;
429*35238bceSAndroid Build Coastguard Worker     GLenum status            = GL_NONE;
430*35238bceSAndroid Build Coastguard Worker 
431*35238bceSAndroid Build Coastguard Worker     GLU_CHECK_GLW_CALL(gl, getIntegerv(GL_FRAMEBUFFER_BINDING, (int32_t *)&curFbo));
432*35238bceSAndroid Build Coastguard Worker     GLU_CHECK_GLW_CALL(gl, getIntegerv(GL_RENDERBUFFER_BINDING, (int32_t *)&curRbo));
433*35238bceSAndroid Build Coastguard Worker 
434*35238bceSAndroid Build Coastguard Worker     try
435*35238bceSAndroid Build Coastguard Worker     {
436*35238bceSAndroid Build Coastguard Worker         GLU_CHECK_GLW_CALL(gl, genRenderbuffers(1, &testRbo));
437*35238bceSAndroid Build Coastguard Worker         GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, testRbo));
438*35238bceSAndroid Build Coastguard Worker         GLU_CHECK_GLW_CALL(gl, renderbufferStorage(GL_RENDERBUFFER, format, FRAMEBUFFER_SIZE, FRAMEBUFFER_SIZE));
439*35238bceSAndroid Build Coastguard Worker 
440*35238bceSAndroid Build Coastguard Worker         GLU_CHECK_GLW_CALL(gl, genFramebuffers(1, &testFbo));
441*35238bceSAndroid Build Coastguard Worker         GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, testFbo));
442*35238bceSAndroid Build Coastguard Worker         GLU_CHECK_GLW_CALL(gl, framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, testRbo));
443*35238bceSAndroid Build Coastguard Worker 
444*35238bceSAndroid Build Coastguard Worker         status = gl.checkFramebufferStatus(GL_FRAMEBUFFER);
445*35238bceSAndroid Build Coastguard Worker         GLU_CHECK_GLW_MSG(gl, "glCheckFramebufferStatus(GL_FRAMEBUFFER)");
446*35238bceSAndroid Build Coastguard Worker 
447*35238bceSAndroid Build Coastguard Worker         GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, curRbo));
448*35238bceSAndroid Build Coastguard Worker         GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, curFbo));
449*35238bceSAndroid Build Coastguard Worker 
450*35238bceSAndroid Build Coastguard Worker         GLU_CHECK_GLW_CALL(gl, deleteRenderbuffers(1, &testRbo));
451*35238bceSAndroid Build Coastguard Worker         GLU_CHECK_GLW_CALL(gl, deleteFramebuffers(1, &testFbo));
452*35238bceSAndroid Build Coastguard Worker     }
453*35238bceSAndroid Build Coastguard Worker     catch (...)
454*35238bceSAndroid Build Coastguard Worker     {
455*35238bceSAndroid Build Coastguard Worker         if (testRbo != 0)
456*35238bceSAndroid Build Coastguard Worker             gl.deleteRenderbuffers(1, &testRbo);
457*35238bceSAndroid Build Coastguard Worker 
458*35238bceSAndroid Build Coastguard Worker         if (testFbo != 0)
459*35238bceSAndroid Build Coastguard Worker             gl.deleteFramebuffers(1, &testFbo);
460*35238bceSAndroid Build Coastguard Worker 
461*35238bceSAndroid Build Coastguard Worker         throw;
462*35238bceSAndroid Build Coastguard Worker     }
463*35238bceSAndroid Build Coastguard Worker 
464*35238bceSAndroid Build Coastguard Worker     if (status == GL_FRAMEBUFFER_COMPLETE)
465*35238bceSAndroid Build Coastguard Worker         return true;
466*35238bceSAndroid Build Coastguard Worker     else if (status == GL_FRAMEBUFFER_UNSUPPORTED)
467*35238bceSAndroid Build Coastguard Worker         return false;
468*35238bceSAndroid Build Coastguard Worker     else
469*35238bceSAndroid Build Coastguard Worker         TCU_THROW(TestError, (std::string("glCheckFramebufferStatus() returned invalid result code ") +
470*35238bceSAndroid Build Coastguard Worker                               de::toString(glu::getFramebufferStatusStr(status)))
471*35238bceSAndroid Build Coastguard Worker                                  .c_str());
472*35238bceSAndroid Build Coastguard Worker }
473*35238bceSAndroid Build Coastguard Worker 
getRenderableColorRenderbufferFormat(const glu::RenderContext & renderCtx)474*35238bceSAndroid Build Coastguard Worker static uint32_t getRenderableColorRenderbufferFormat(const glu::RenderContext &renderCtx)
475*35238bceSAndroid Build Coastguard Worker {
476*35238bceSAndroid Build Coastguard Worker     if (glu::contextSupports(renderCtx.getType(), glu::ApiType::es(3, 0)))
477*35238bceSAndroid Build Coastguard Worker         return GL_RGBA4;
478*35238bceSAndroid Build Coastguard Worker 
479*35238bceSAndroid Build Coastguard Worker     {
480*35238bceSAndroid Build Coastguard Worker         const uint32_t candidates[] = {
481*35238bceSAndroid Build Coastguard Worker             GL_RGBA4,
482*35238bceSAndroid Build Coastguard Worker             GL_RGB5_A1,
483*35238bceSAndroid Build Coastguard Worker             GL_RGB565,
484*35238bceSAndroid Build Coastguard Worker         };
485*35238bceSAndroid Build Coastguard Worker 
486*35238bceSAndroid Build Coastguard Worker         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(candidates); ++ndx)
487*35238bceSAndroid Build Coastguard Worker         {
488*35238bceSAndroid Build Coastguard Worker             if (isRenderbufferFormatColorRenderable(renderCtx, candidates[ndx]))
489*35238bceSAndroid Build Coastguard Worker                 return candidates[ndx];
490*35238bceSAndroid Build Coastguard Worker         }
491*35238bceSAndroid Build Coastguard Worker     }
492*35238bceSAndroid Build Coastguard Worker 
493*35238bceSAndroid Build Coastguard Worker     return GL_NONE;
494*35238bceSAndroid Build Coastguard Worker }
495*35238bceSAndroid Build Coastguard Worker 
initStorage(void)496*35238bceSAndroid Build Coastguard Worker void RboFboAttacher::initStorage(void)
497*35238bceSAndroid Build Coastguard Worker {
498*35238bceSAndroid Build Coastguard Worker     const uint32_t format = getRenderableColorRenderbufferFormat(getRenderContext());
499*35238bceSAndroid Build Coastguard Worker 
500*35238bceSAndroid Build Coastguard Worker     if (format == GL_NONE)
501*35238bceSAndroid Build Coastguard Worker         TCU_THROW(TestError, "No color-renderable renderbuffer format found");
502*35238bceSAndroid Build Coastguard Worker 
503*35238bceSAndroid Build Coastguard Worker     GLU_CHECK_CALL_ERROR(glRenderbufferStorage(GL_RENDERBUFFER, format, FRAMEBUFFER_SIZE, FRAMEBUFFER_SIZE),
504*35238bceSAndroid Build Coastguard Worker                          gl().getError());
505*35238bceSAndroid Build Coastguard Worker }
506*35238bceSAndroid Build Coastguard Worker 
attach(GLuint rbo,GLuint fbo)507*35238bceSAndroid Build Coastguard Worker void RboFboAttacher::attach(GLuint rbo, GLuint fbo)
508*35238bceSAndroid Build Coastguard Worker {
509*35238bceSAndroid Build Coastguard Worker     GLU_CHECK_CALL_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, fbo), gl().getError());
510*35238bceSAndroid Build Coastguard Worker     GLU_CHECK_CALL_ERROR(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo),
511*35238bceSAndroid Build Coastguard Worker                          gl().getError());
512*35238bceSAndroid Build Coastguard Worker     GLU_CHECK_CALL_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, 0), gl().getError());
513*35238bceSAndroid Build Coastguard Worker }
514*35238bceSAndroid Build Coastguard Worker 
detach(GLuint rbo,GLuint fbo)515*35238bceSAndroid Build Coastguard Worker void RboFboAttacher::detach(GLuint rbo, GLuint fbo)
516*35238bceSAndroid Build Coastguard Worker {
517*35238bceSAndroid Build Coastguard Worker     DE_UNREF(rbo);
518*35238bceSAndroid Build Coastguard Worker     GLU_CHECK_CALL_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, fbo), gl().getError());
519*35238bceSAndroid Build Coastguard Worker     GLU_CHECK_CALL_ERROR(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 0),
520*35238bceSAndroid Build Coastguard Worker                          gl().getError());
521*35238bceSAndroid Build Coastguard Worker     GLU_CHECK_CALL_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, 0), gl().getError());
522*35238bceSAndroid Build Coastguard Worker }
523*35238bceSAndroid Build Coastguard Worker 
getAttachment(GLuint fbo)524*35238bceSAndroid Build Coastguard Worker GLuint RboFboAttacher::getAttachment(GLuint fbo)
525*35238bceSAndroid Build Coastguard Worker {
526*35238bceSAndroid Build Coastguard Worker     return getFboAttachment(gl(), fbo, GL_RENDERBUFFER);
527*35238bceSAndroid Build Coastguard Worker }
528*35238bceSAndroid Build Coastguard Worker 
529*35238bceSAndroid Build Coastguard Worker static const char *const s_fragmentShaderTemplate =
530*35238bceSAndroid Build Coastguard Worker     GLSL100_SRC(void main() { gl_FragColor = vec4(${RED}, ${GREEN}, ${BLUE}, 1.0); });
531*35238bceSAndroid Build Coastguard Worker 
initAttachment(GLuint seed,GLuint shader)532*35238bceSAndroid Build Coastguard Worker void ShaderProgramAttacher::initAttachment(GLuint seed, GLuint shader)
533*35238bceSAndroid Build Coastguard Worker {
534*35238bceSAndroid Build Coastguard Worker     using de::floatToString;
535*35238bceSAndroid Build Coastguard Worker     using de::insert;
536*35238bceSAndroid Build Coastguard Worker 
537*35238bceSAndroid Build Coastguard Worker     Random rnd(seed);
538*35238bceSAndroid Build Coastguard Worker     map<string, string> params;
539*35238bceSAndroid Build Coastguard Worker     const StringTemplate sourceTmpl(s_fragmentShaderTemplate);
540*35238bceSAndroid Build Coastguard Worker 
541*35238bceSAndroid Build Coastguard Worker     insert(params, "RED", floatToString(rnd.getFloat(), 4));
542*35238bceSAndroid Build Coastguard Worker     insert(params, "GREEN", floatToString(rnd.getFloat(), 4));
543*35238bceSAndroid Build Coastguard Worker     insert(params, "BLUE", floatToString(rnd.getFloat(), 4));
544*35238bceSAndroid Build Coastguard Worker 
545*35238bceSAndroid Build Coastguard Worker     {
546*35238bceSAndroid Build Coastguard Worker         const string source         = sourceTmpl.specialize(params);
547*35238bceSAndroid Build Coastguard Worker         const char *const sourceStr = source.c_str();
548*35238bceSAndroid Build Coastguard Worker 
549*35238bceSAndroid Build Coastguard Worker         GLU_CHECK_CALL_ERROR(glShaderSource(shader, 1, &sourceStr, DE_NULL), gl().getError());
550*35238bceSAndroid Build Coastguard Worker         GLU_CHECK_CALL_ERROR(glCompileShader(shader), gl().getError());
551*35238bceSAndroid Build Coastguard Worker 
552*35238bceSAndroid Build Coastguard Worker         {
553*35238bceSAndroid Build Coastguard Worker             GLint compileStatus = 0;
554*35238bceSAndroid Build Coastguard Worker             gl().getShaderiv(shader, GL_COMPILE_STATUS, &compileStatus);
555*35238bceSAndroid Build Coastguard Worker             TCU_CHECK_MSG(compileStatus != 0, sourceStr);
556*35238bceSAndroid Build Coastguard Worker         }
557*35238bceSAndroid Build Coastguard Worker     }
558*35238bceSAndroid Build Coastguard Worker }
559*35238bceSAndroid Build Coastguard Worker 
attach(GLuint shader,GLuint program)560*35238bceSAndroid Build Coastguard Worker void ShaderProgramAttacher::attach(GLuint shader, GLuint program)
561*35238bceSAndroid Build Coastguard Worker {
562*35238bceSAndroid Build Coastguard Worker     GLU_CHECK_CALL_ERROR(glAttachShader(program, shader), gl().getError());
563*35238bceSAndroid Build Coastguard Worker }
564*35238bceSAndroid Build Coastguard Worker 
detach(GLuint shader,GLuint program)565*35238bceSAndroid Build Coastguard Worker void ShaderProgramAttacher::detach(GLuint shader, GLuint program)
566*35238bceSAndroid Build Coastguard Worker {
567*35238bceSAndroid Build Coastguard Worker     GLU_CHECK_CALL_ERROR(glDetachShader(program, shader), gl().getError());
568*35238bceSAndroid Build Coastguard Worker }
569*35238bceSAndroid Build Coastguard Worker 
getAttachment(GLuint program)570*35238bceSAndroid Build Coastguard Worker GLuint ShaderProgramAttacher::getAttachment(GLuint program)
571*35238bceSAndroid Build Coastguard Worker {
572*35238bceSAndroid Build Coastguard Worker     GLuint shaders[2]        = {0, 0};
573*35238bceSAndroid Build Coastguard Worker     const GLsizei shadersLen = DE_LENGTH_OF_ARRAY(shaders);
574*35238bceSAndroid Build Coastguard Worker     GLsizei numShaders       = 0;
575*35238bceSAndroid Build Coastguard Worker     GLuint ret               = 0;
576*35238bceSAndroid Build Coastguard Worker 
577*35238bceSAndroid Build Coastguard Worker     gl().getAttachedShaders(program, shadersLen, &numShaders, shaders);
578*35238bceSAndroid Build Coastguard Worker 
579*35238bceSAndroid Build Coastguard Worker     // There should ever be at most one attached shader in normal use, but if
580*35238bceSAndroid Build Coastguard Worker     // something is wrong, the temporary vertex shader might not have been
581*35238bceSAndroid Build Coastguard Worker     // detached properly, so let's find the fragment shader explicitly.
582*35238bceSAndroid Build Coastguard Worker     for (int ndx = 0; ndx < de::min<GLsizei>(shadersLen, numShaders); ++ndx)
583*35238bceSAndroid Build Coastguard Worker     {
584*35238bceSAndroid Build Coastguard Worker         GLint shaderType = GL_NONE;
585*35238bceSAndroid Build Coastguard Worker         gl().getShaderiv(shaders[ndx], GL_SHADER_TYPE, &shaderType);
586*35238bceSAndroid Build Coastguard Worker 
587*35238bceSAndroid Build Coastguard Worker         if (shaderType == GL_FRAGMENT_SHADER)
588*35238bceSAndroid Build Coastguard Worker         {
589*35238bceSAndroid Build Coastguard Worker             ret = shaders[ndx];
590*35238bceSAndroid Build Coastguard Worker             break;
591*35238bceSAndroid Build Coastguard Worker         }
592*35238bceSAndroid Build Coastguard Worker     }
593*35238bceSAndroid Build Coastguard Worker 
594*35238bceSAndroid Build Coastguard Worker     return ret;
595*35238bceSAndroid Build Coastguard Worker }
596*35238bceSAndroid Build Coastguard Worker 
setViewport(const RenderContext & renderCtx,const Rectangle & rect)597*35238bceSAndroid Build Coastguard Worker void setViewport(const RenderContext &renderCtx, const Rectangle &rect)
598*35238bceSAndroid Build Coastguard Worker {
599*35238bceSAndroid Build Coastguard Worker     renderCtx.getFunctions().viewport(rect.x, rect.y, rect.width, rect.height);
600*35238bceSAndroid Build Coastguard Worker }
601*35238bceSAndroid Build Coastguard Worker 
readRectangle(const RenderContext & renderCtx,const Rectangle & rect,Surface & dst)602*35238bceSAndroid Build Coastguard Worker void readRectangle(const RenderContext &renderCtx, const Rectangle &rect, Surface &dst)
603*35238bceSAndroid Build Coastguard Worker {
604*35238bceSAndroid Build Coastguard Worker     dst.setSize(rect.width, rect.height);
605*35238bceSAndroid Build Coastguard Worker     glu::readPixels(renderCtx, rect.x, rect.y, dst.getAccess());
606*35238bceSAndroid Build Coastguard Worker }
607*35238bceSAndroid Build Coastguard Worker 
randomViewport(const RenderContext & ctx,GLint maxWidth,GLint maxHeight,Random & rnd)608*35238bceSAndroid Build Coastguard Worker Rectangle randomViewport(const RenderContext &ctx, GLint maxWidth, GLint maxHeight, Random &rnd)
609*35238bceSAndroid Build Coastguard Worker {
610*35238bceSAndroid Build Coastguard Worker     const RenderTarget &target = ctx.getRenderTarget();
611*35238bceSAndroid Build Coastguard Worker     const GLint width          = de::min(target.getWidth(), maxWidth);
612*35238bceSAndroid Build Coastguard Worker     const GLint xOff           = rnd.getInt(0, target.getWidth() - width);
613*35238bceSAndroid Build Coastguard Worker     const GLint height         = de::min(target.getHeight(), maxHeight);
614*35238bceSAndroid Build Coastguard Worker     const GLint yOff           = rnd.getInt(0, target.getHeight() - height);
615*35238bceSAndroid Build Coastguard Worker 
616*35238bceSAndroid Build Coastguard Worker     return Rectangle(xOff, yOff, width, height);
617*35238bceSAndroid Build Coastguard Worker }
618*35238bceSAndroid Build Coastguard Worker 
drawContainer(GLuint program,Surface & dst)619*35238bceSAndroid Build Coastguard Worker void ShaderProgramInputAttacher::drawContainer(GLuint program, Surface &dst)
620*35238bceSAndroid Build Coastguard Worker {
621*35238bceSAndroid Build Coastguard Worker     static const float s_vertices[6] = {-1.0, 0.0, 1.0, 1.0, 0.0, -1.0};
622*35238bceSAndroid Build Coastguard Worker     Random rnd(program);
623*35238bceSAndroid Build Coastguard Worker     CheckedShader vtxShader(getRenderContext(), SHADERTYPE_VERTEX, s_vertexShaderSrc);
624*35238bceSAndroid Build Coastguard Worker     const Rectangle viewport = randomViewport(getRenderContext(), VIEWPORT_SIZE, VIEWPORT_SIZE, rnd);
625*35238bceSAndroid Build Coastguard Worker 
626*35238bceSAndroid Build Coastguard Worker     gl().attachShader(program, vtxShader.getShader());
627*35238bceSAndroid Build Coastguard Worker     gl().linkProgram(program);
628*35238bceSAndroid Build Coastguard Worker 
629*35238bceSAndroid Build Coastguard Worker     {
630*35238bceSAndroid Build Coastguard Worker         GLint linkStatus = 0;
631*35238bceSAndroid Build Coastguard Worker         gl().getProgramiv(program, GL_LINK_STATUS, &linkStatus);
632*35238bceSAndroid Build Coastguard Worker         TCU_CHECK(linkStatus != 0);
633*35238bceSAndroid Build Coastguard Worker     }
634*35238bceSAndroid Build Coastguard Worker 
635*35238bceSAndroid Build Coastguard Worker     log() << TestLog::Message << "// Attached a temporary vertex shader and linked program " << program
636*35238bceSAndroid Build Coastguard Worker           << TestLog::EndMessage;
637*35238bceSAndroid Build Coastguard Worker 
638*35238bceSAndroid Build Coastguard Worker     setViewport(getRenderContext(), viewport);
639*35238bceSAndroid Build Coastguard Worker     log() << TestLog::Message << "// Positioned viewport randomly" << TestLog::EndMessage;
640*35238bceSAndroid Build Coastguard Worker 
641*35238bceSAndroid Build Coastguard Worker     glUseProgram(program);
642*35238bceSAndroid Build Coastguard Worker     {
643*35238bceSAndroid Build Coastguard Worker         GLint posLoc = gl().getAttribLocation(program, "pos");
644*35238bceSAndroid Build Coastguard Worker         TCU_CHECK(posLoc >= 0);
645*35238bceSAndroid Build Coastguard Worker 
646*35238bceSAndroid Build Coastguard Worker         gl().enableVertexAttribArray(posLoc);
647*35238bceSAndroid Build Coastguard Worker 
648*35238bceSAndroid Build Coastguard Worker         gl().clearColor(0, 0, 0, 1);
649*35238bceSAndroid Build Coastguard Worker         gl().clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
650*35238bceSAndroid Build Coastguard Worker         gl().vertexAttribPointer(posLoc, 2, GL_FLOAT, GL_FALSE, 0, s_vertices);
651*35238bceSAndroid Build Coastguard Worker         gl().drawArrays(GL_TRIANGLES, 0, 3);
652*35238bceSAndroid Build Coastguard Worker 
653*35238bceSAndroid Build Coastguard Worker         gl().disableVertexAttribArray(posLoc);
654*35238bceSAndroid Build Coastguard Worker         log() << TestLog::Message << "// Drew a fixed triangle" << TestLog::EndMessage;
655*35238bceSAndroid Build Coastguard Worker     }
656*35238bceSAndroid Build Coastguard Worker     glUseProgram(0);
657*35238bceSAndroid Build Coastguard Worker 
658*35238bceSAndroid Build Coastguard Worker     readRectangle(getRenderContext(), viewport, dst);
659*35238bceSAndroid Build Coastguard Worker     log() << TestLog::Message << "// Copied viewport to output image" << TestLog::EndMessage;
660*35238bceSAndroid Build Coastguard Worker 
661*35238bceSAndroid Build Coastguard Worker     gl().detachShader(program, vtxShader.getShader());
662*35238bceSAndroid Build Coastguard Worker     log() << TestLog::Message << "// Removed temporary vertex shader" << TestLog::EndMessage;
663*35238bceSAndroid Build Coastguard Worker }
664*35238bceSAndroid Build Coastguard Worker 
ES2Types(const Context & ctx)665*35238bceSAndroid Build Coastguard Worker ES2Types::ES2Types(const Context &ctx)
666*35238bceSAndroid Build Coastguard Worker     : Types(ctx)
667*35238bceSAndroid Build Coastguard Worker     , m_bufferBind(ctx, &CallLogWrapper::glBindBuffer, GL_ARRAY_BUFFER, GL_ARRAY_BUFFER_BINDING)
668*35238bceSAndroid Build Coastguard Worker     , m_bufferType(ctx, "buffer", &CallLogWrapper::glGenBuffers, &CallLogWrapper::glDeleteBuffers,
669*35238bceSAndroid Build Coastguard Worker                    &CallLogWrapper::glIsBuffer, &m_bufferBind)
670*35238bceSAndroid Build Coastguard Worker     , m_textureBind(ctx, &CallLogWrapper::glBindTexture, GL_TEXTURE_2D, GL_TEXTURE_BINDING_2D)
671*35238bceSAndroid Build Coastguard Worker     , m_textureType(ctx, "texture", &CallLogWrapper::glGenTextures, &CallLogWrapper::glDeleteTextures,
672*35238bceSAndroid Build Coastguard Worker                     &CallLogWrapper::glIsTexture, &m_textureBind)
673*35238bceSAndroid Build Coastguard Worker     , m_rboBind(ctx, &CallLogWrapper::glBindRenderbuffer, GL_RENDERBUFFER, GL_RENDERBUFFER_BINDING)
674*35238bceSAndroid Build Coastguard Worker     , m_rboType(ctx, "renderbuffer", &CallLogWrapper::glGenRenderbuffers, &CallLogWrapper::glDeleteRenderbuffers,
675*35238bceSAndroid Build Coastguard Worker                 &CallLogWrapper::glIsRenderbuffer, &m_rboBind)
676*35238bceSAndroid Build Coastguard Worker     , m_fboBind(ctx, &CallLogWrapper::glBindFramebuffer, GL_FRAMEBUFFER, GL_FRAMEBUFFER_BINDING)
677*35238bceSAndroid Build Coastguard Worker     , m_fboType(ctx, "framebuffer", &CallLogWrapper::glGenFramebuffers, &CallLogWrapper::glDeleteFramebuffers,
678*35238bceSAndroid Build Coastguard Worker                 &CallLogWrapper::glIsFramebuffer, &m_fboBind)
679*35238bceSAndroid Build Coastguard Worker     , m_shaderType(ctx)
680*35238bceSAndroid Build Coastguard Worker     , m_programType(ctx)
681*35238bceSAndroid Build Coastguard Worker     , m_texFboAtt(ctx, m_textureType, m_fboType)
682*35238bceSAndroid Build Coastguard Worker     , m_texFboInAtt(m_texFboAtt)
683*35238bceSAndroid Build Coastguard Worker     , m_texFboOutAtt(m_texFboAtt)
684*35238bceSAndroid Build Coastguard Worker     , m_rboFboAtt(ctx, m_rboType, m_fboType)
685*35238bceSAndroid Build Coastguard Worker     , m_rboFboInAtt(m_rboFboAtt)
686*35238bceSAndroid Build Coastguard Worker     , m_rboFboOutAtt(m_rboFboAtt)
687*35238bceSAndroid Build Coastguard Worker     , m_shaderAtt(ctx, m_shaderType, m_programType)
688*35238bceSAndroid Build Coastguard Worker     , m_shaderInAtt(m_shaderAtt)
689*35238bceSAndroid Build Coastguard Worker {
690*35238bceSAndroid Build Coastguard Worker     Type *const types[] = {&m_bufferType, &m_textureType, &m_rboType, &m_fboType, &m_shaderType, &m_programType};
691*35238bceSAndroid Build Coastguard Worker     m_types.insert(m_types.end(), DE_ARRAY_BEGIN(types), DE_ARRAY_END(types));
692*35238bceSAndroid Build Coastguard Worker 
693*35238bceSAndroid Build Coastguard Worker     m_attachers.push_back(&m_texFboAtt);
694*35238bceSAndroid Build Coastguard Worker     m_attachers.push_back(&m_rboFboAtt);
695*35238bceSAndroid Build Coastguard Worker     m_attachers.push_back(&m_shaderAtt);
696*35238bceSAndroid Build Coastguard Worker 
697*35238bceSAndroid Build Coastguard Worker     m_inAttachers.push_back(&m_texFboInAtt);
698*35238bceSAndroid Build Coastguard Worker     m_inAttachers.push_back(&m_rboFboInAtt);
699*35238bceSAndroid Build Coastguard Worker     m_inAttachers.push_back(&m_shaderInAtt);
700*35238bceSAndroid Build Coastguard Worker 
701*35238bceSAndroid Build Coastguard Worker     m_outAttachers.push_back(&m_texFboOutAtt);
702*35238bceSAndroid Build Coastguard Worker     m_outAttachers.push_back(&m_rboFboOutAtt);
703*35238bceSAndroid Build Coastguard Worker }
704*35238bceSAndroid Build Coastguard Worker 
705*35238bceSAndroid Build Coastguard Worker class Name
706*35238bceSAndroid Build Coastguard Worker {
707*35238bceSAndroid Build Coastguard Worker public:
Name(Type & type)708*35238bceSAndroid Build Coastguard Worker     Name(Type &type) : m_type(type), m_name(type.gen())
709*35238bceSAndroid Build Coastguard Worker     {
710*35238bceSAndroid Build Coastguard Worker     }
Name(Type & type,GLuint name)711*35238bceSAndroid Build Coastguard Worker     Name(Type &type, GLuint name) : m_type(type), m_name(name)
712*35238bceSAndroid Build Coastguard Worker     {
713*35238bceSAndroid Build Coastguard Worker     }
~Name(void)714*35238bceSAndroid Build Coastguard Worker     ~Name(void)
715*35238bceSAndroid Build Coastguard Worker     {
716*35238bceSAndroid Build Coastguard Worker         m_type.release(m_name);
717*35238bceSAndroid Build Coastguard Worker     }
operator *(void) const718*35238bceSAndroid Build Coastguard Worker     GLuint operator*(void) const
719*35238bceSAndroid Build Coastguard Worker     {
720*35238bceSAndroid Build Coastguard Worker         return m_name;
721*35238bceSAndroid Build Coastguard Worker     }
722*35238bceSAndroid Build Coastguard Worker 
723*35238bceSAndroid Build Coastguard Worker private:
724*35238bceSAndroid Build Coastguard Worker     Type &m_type;
725*35238bceSAndroid Build Coastguard Worker     const GLuint m_name;
726*35238bceSAndroid Build Coastguard Worker };
727*35238bceSAndroid Build Coastguard Worker 
728*35238bceSAndroid Build Coastguard Worker class ResultCollector
729*35238bceSAndroid Build Coastguard Worker {
730*35238bceSAndroid Build Coastguard Worker public:
731*35238bceSAndroid Build Coastguard Worker     ResultCollector(TestContext &testCtx);
732*35238bceSAndroid Build Coastguard Worker     bool check(bool cond, const char *msg);
733*35238bceSAndroid Build Coastguard Worker     void fail(const char *msg);
734*35238bceSAndroid Build Coastguard Worker     void warn(const char *msg);
735*35238bceSAndroid Build Coastguard Worker     ~ResultCollector(void);
736*35238bceSAndroid Build Coastguard Worker 
737*35238bceSAndroid Build Coastguard Worker private:
738*35238bceSAndroid Build Coastguard Worker     void addResult(qpTestResult result, const char *msg);
739*35238bceSAndroid Build Coastguard Worker 
740*35238bceSAndroid Build Coastguard Worker     TestContext &m_testCtx;
741*35238bceSAndroid Build Coastguard Worker     TestLog &m_log;
742*35238bceSAndroid Build Coastguard Worker     qpTestResult m_result;
743*35238bceSAndroid Build Coastguard Worker     const char *m_message;
744*35238bceSAndroid Build Coastguard Worker };
745*35238bceSAndroid Build Coastguard Worker 
ResultCollector(TestContext & testCtx)746*35238bceSAndroid Build Coastguard Worker ResultCollector::ResultCollector(TestContext &testCtx)
747*35238bceSAndroid Build Coastguard Worker     : m_testCtx(testCtx)
748*35238bceSAndroid Build Coastguard Worker     , m_log(testCtx.getLog())
749*35238bceSAndroid Build Coastguard Worker     , m_result(QP_TEST_RESULT_PASS)
750*35238bceSAndroid Build Coastguard Worker     , m_message("Pass")
751*35238bceSAndroid Build Coastguard Worker {
752*35238bceSAndroid Build Coastguard Worker }
753*35238bceSAndroid Build Coastguard Worker 
check(bool cond,const char * msg)754*35238bceSAndroid Build Coastguard Worker bool ResultCollector::check(bool cond, const char *msg)
755*35238bceSAndroid Build Coastguard Worker {
756*35238bceSAndroid Build Coastguard Worker     if (!cond)
757*35238bceSAndroid Build Coastguard Worker         fail(msg);
758*35238bceSAndroid Build Coastguard Worker     return cond;
759*35238bceSAndroid Build Coastguard Worker }
760*35238bceSAndroid Build Coastguard Worker 
addResult(qpTestResult result,const char * msg)761*35238bceSAndroid Build Coastguard Worker void ResultCollector::addResult(qpTestResult result, const char *msg)
762*35238bceSAndroid Build Coastguard Worker {
763*35238bceSAndroid Build Coastguard Worker     m_log << TestLog::Message << "// Fail: " << msg << TestLog::EndMessage;
764*35238bceSAndroid Build Coastguard Worker     if (m_result == QP_TEST_RESULT_PASS)
765*35238bceSAndroid Build Coastguard Worker     {
766*35238bceSAndroid Build Coastguard Worker         m_result  = result;
767*35238bceSAndroid Build Coastguard Worker         m_message = msg;
768*35238bceSAndroid Build Coastguard Worker     }
769*35238bceSAndroid Build Coastguard Worker     else
770*35238bceSAndroid Build Coastguard Worker     {
771*35238bceSAndroid Build Coastguard Worker         if (result == QP_TEST_RESULT_FAIL)
772*35238bceSAndroid Build Coastguard Worker             m_result = result;
773*35238bceSAndroid Build Coastguard Worker         m_message = "Multiple problems, see log for details";
774*35238bceSAndroid Build Coastguard Worker     }
775*35238bceSAndroid Build Coastguard Worker }
776*35238bceSAndroid Build Coastguard Worker 
fail(const char * msg)777*35238bceSAndroid Build Coastguard Worker void ResultCollector::fail(const char *msg)
778*35238bceSAndroid Build Coastguard Worker {
779*35238bceSAndroid Build Coastguard Worker     addResult(QP_TEST_RESULT_FAIL, msg);
780*35238bceSAndroid Build Coastguard Worker }
781*35238bceSAndroid Build Coastguard Worker 
warn(const char * msg)782*35238bceSAndroid Build Coastguard Worker void ResultCollector::warn(const char *msg)
783*35238bceSAndroid Build Coastguard Worker {
784*35238bceSAndroid Build Coastguard Worker     addResult(QP_TEST_RESULT_QUALITY_WARNING, msg);
785*35238bceSAndroid Build Coastguard Worker }
786*35238bceSAndroid Build Coastguard Worker 
~ResultCollector(void)787*35238bceSAndroid Build Coastguard Worker ResultCollector::~ResultCollector(void)
788*35238bceSAndroid Build Coastguard Worker {
789*35238bceSAndroid Build Coastguard Worker     m_testCtx.setTestResult(m_result, m_message);
790*35238bceSAndroid Build Coastguard Worker }
791*35238bceSAndroid Build Coastguard Worker 
792*35238bceSAndroid Build Coastguard Worker class TestBase : public TestCase, protected CallLogWrapper
793*35238bceSAndroid Build Coastguard Worker {
794*35238bceSAndroid Build Coastguard Worker protected:
795*35238bceSAndroid Build Coastguard Worker     TestBase(const char *name, const char *description, const Context &ctx);
796*35238bceSAndroid Build Coastguard Worker 
797*35238bceSAndroid Build Coastguard Worker     // Copy ContextWrapper since MI (except for CallLogWrapper) is a no-no.
getContext(void) const798*35238bceSAndroid Build Coastguard Worker     const Context &getContext(void) const
799*35238bceSAndroid Build Coastguard Worker     {
800*35238bceSAndroid Build Coastguard Worker         return m_ctx;
801*35238bceSAndroid Build Coastguard Worker     }
getRenderContext(void) const802*35238bceSAndroid Build Coastguard Worker     const RenderContext &getRenderContext(void) const
803*35238bceSAndroid Build Coastguard Worker     {
804*35238bceSAndroid Build Coastguard Worker         return m_ctx.getRenderContext();
805*35238bceSAndroid Build Coastguard Worker     }
gl(void) const806*35238bceSAndroid Build Coastguard Worker     const Functions &gl(void) const
807*35238bceSAndroid Build Coastguard Worker     {
808*35238bceSAndroid Build Coastguard Worker         return m_ctx.gl();
809*35238bceSAndroid Build Coastguard Worker     }
log(void) const810*35238bceSAndroid Build Coastguard Worker     TestLog &log(void) const
811*35238bceSAndroid Build Coastguard Worker     {
812*35238bceSAndroid Build Coastguard Worker         return m_ctx.log();
813*35238bceSAndroid Build Coastguard Worker     }
814*35238bceSAndroid Build Coastguard Worker     void init(void);
815*35238bceSAndroid Build Coastguard Worker 
816*35238bceSAndroid Build Coastguard Worker     Context m_ctx;
817*35238bceSAndroid Build Coastguard Worker     Random m_rnd;
818*35238bceSAndroid Build Coastguard Worker };
819*35238bceSAndroid Build Coastguard Worker 
TestBase(const char * name,const char * description,const Context & ctx)820*35238bceSAndroid Build Coastguard Worker TestBase::TestBase(const char *name, const char *description, const Context &ctx)
821*35238bceSAndroid Build Coastguard Worker     : TestCase(ctx.getTestContext(), name, description)
822*35238bceSAndroid Build Coastguard Worker     , CallLogWrapper(ctx.gl(), ctx.log())
823*35238bceSAndroid Build Coastguard Worker     , m_ctx(ctx)
824*35238bceSAndroid Build Coastguard Worker     , m_rnd(deStringHash(name))
825*35238bceSAndroid Build Coastguard Worker {
826*35238bceSAndroid Build Coastguard Worker     enableLogging(true);
827*35238bceSAndroid Build Coastguard Worker }
828*35238bceSAndroid Build Coastguard Worker 
init(void)829*35238bceSAndroid Build Coastguard Worker void TestBase::init(void)
830*35238bceSAndroid Build Coastguard Worker {
831*35238bceSAndroid Build Coastguard Worker     m_rnd = Random(deStringHash(getName()));
832*35238bceSAndroid Build Coastguard Worker }
833*35238bceSAndroid Build Coastguard Worker 
834*35238bceSAndroid Build Coastguard Worker class LifeTest : public TestBase
835*35238bceSAndroid Build Coastguard Worker {
836*35238bceSAndroid Build Coastguard Worker public:
837*35238bceSAndroid Build Coastguard Worker     typedef void (LifeTest::*TestFunction)(void);
838*35238bceSAndroid Build Coastguard Worker 
LifeTest(const char * name,const char * description,Type & type,TestFunction test)839*35238bceSAndroid Build Coastguard Worker     LifeTest(const char *name, const char *description, Type &type, TestFunction test)
840*35238bceSAndroid Build Coastguard Worker         : TestBase(name, description, type.getContext())
841*35238bceSAndroid Build Coastguard Worker         , m_type(type)
842*35238bceSAndroid Build Coastguard Worker         , m_test(test)
843*35238bceSAndroid Build Coastguard Worker     {
844*35238bceSAndroid Build Coastguard Worker     }
845*35238bceSAndroid Build Coastguard Worker 
846*35238bceSAndroid Build Coastguard Worker     IterateResult iterate(void);
847*35238bceSAndroid Build Coastguard Worker 
848*35238bceSAndroid Build Coastguard Worker     void testGen(void);
849*35238bceSAndroid Build Coastguard Worker     void testDelete(void);
850*35238bceSAndroid Build Coastguard Worker     void testBind(void);
851*35238bceSAndroid Build Coastguard Worker     void testDeleteBound(void);
852*35238bceSAndroid Build Coastguard Worker     void testBindNoGen(void);
853*35238bceSAndroid Build Coastguard Worker     void testDeleteUsed(void);
854*35238bceSAndroid Build Coastguard Worker 
855*35238bceSAndroid Build Coastguard Worker private:
binder(void)856*35238bceSAndroid Build Coastguard Worker     Binder &binder(void)
857*35238bceSAndroid Build Coastguard Worker     {
858*35238bceSAndroid Build Coastguard Worker         return *m_type.binder();
859*35238bceSAndroid Build Coastguard Worker     }
860*35238bceSAndroid Build Coastguard Worker 
861*35238bceSAndroid Build Coastguard Worker     Type &m_type;
862*35238bceSAndroid Build Coastguard Worker     TestFunction m_test;
863*35238bceSAndroid Build Coastguard Worker };
864*35238bceSAndroid Build Coastguard Worker 
iterate(void)865*35238bceSAndroid Build Coastguard Worker IterateResult LifeTest::iterate(void)
866*35238bceSAndroid Build Coastguard Worker {
867*35238bceSAndroid Build Coastguard Worker     (this->*m_test)();
868*35238bceSAndroid Build Coastguard Worker     return STOP;
869*35238bceSAndroid Build Coastguard Worker }
870*35238bceSAndroid Build Coastguard Worker 
testGen(void)871*35238bceSAndroid Build Coastguard Worker void LifeTest::testGen(void)
872*35238bceSAndroid Build Coastguard Worker {
873*35238bceSAndroid Build Coastguard Worker     ResultCollector errors(getTestContext());
874*35238bceSAndroid Build Coastguard Worker     Name name(m_type);
875*35238bceSAndroid Build Coastguard Worker 
876*35238bceSAndroid Build Coastguard Worker     if (m_type.genCreates())
877*35238bceSAndroid Build Coastguard Worker         errors.check(m_type.exists(*name), "Gen* should have created an object, but didn't");
878*35238bceSAndroid Build Coastguard Worker     else
879*35238bceSAndroid Build Coastguard Worker         errors.check(!m_type.exists(*name), "Gen* should not have created an object, but did");
880*35238bceSAndroid Build Coastguard Worker }
881*35238bceSAndroid Build Coastguard Worker 
testDelete(void)882*35238bceSAndroid Build Coastguard Worker void LifeTest::testDelete(void)
883*35238bceSAndroid Build Coastguard Worker {
884*35238bceSAndroid Build Coastguard Worker     ResultCollector errors(getTestContext());
885*35238bceSAndroid Build Coastguard Worker     GLuint name = m_type.gen();
886*35238bceSAndroid Build Coastguard Worker 
887*35238bceSAndroid Build Coastguard Worker     m_type.release(name);
888*35238bceSAndroid Build Coastguard Worker     errors.check(!m_type.exists(name), "Object still exists after deletion");
889*35238bceSAndroid Build Coastguard Worker }
890*35238bceSAndroid Build Coastguard Worker 
testBind(void)891*35238bceSAndroid Build Coastguard Worker void LifeTest::testBind(void)
892*35238bceSAndroid Build Coastguard Worker {
893*35238bceSAndroid Build Coastguard Worker     ResultCollector errors(getTestContext());
894*35238bceSAndroid Build Coastguard Worker     Name name(m_type);
895*35238bceSAndroid Build Coastguard Worker 
896*35238bceSAndroid Build Coastguard Worker     binder().bind(*name);
897*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl().getError(), "Bind failed");
898*35238bceSAndroid Build Coastguard Worker     errors.check(m_type.exists(*name), "Object does not exist after binding");
899*35238bceSAndroid Build Coastguard Worker     binder().bind(0);
900*35238bceSAndroid Build Coastguard Worker }
901*35238bceSAndroid Build Coastguard Worker 
testDeleteBound(void)902*35238bceSAndroid Build Coastguard Worker void LifeTest::testDeleteBound(void)
903*35238bceSAndroid Build Coastguard Worker {
904*35238bceSAndroid Build Coastguard Worker     const GLuint id = m_type.gen();
905*35238bceSAndroid Build Coastguard Worker     ResultCollector errors(getTestContext());
906*35238bceSAndroid Build Coastguard Worker 
907*35238bceSAndroid Build Coastguard Worker     binder().bind(id);
908*35238bceSAndroid Build Coastguard Worker     m_type.release(id);
909*35238bceSAndroid Build Coastguard Worker 
910*35238bceSAndroid Build Coastguard Worker     if (m_type.nameLingers())
911*35238bceSAndroid Build Coastguard Worker     {
912*35238bceSAndroid Build Coastguard Worker         errors.check(gl().getError() == GL_NO_ERROR, "Deleting bound object failed");
913*35238bceSAndroid Build Coastguard Worker         errors.check(binder().getBinding() == id, "Deleting bound object did not retain binding");
914*35238bceSAndroid Build Coastguard Worker         errors.check(m_type.exists(id), "Deleting bound object made its name invalid");
915*35238bceSAndroid Build Coastguard Worker         errors.check(m_type.isDeleteFlagged(id), "Deleting bound object did not flag the object for deletion");
916*35238bceSAndroid Build Coastguard Worker         binder().bind(0);
917*35238bceSAndroid Build Coastguard Worker     }
918*35238bceSAndroid Build Coastguard Worker     else
919*35238bceSAndroid Build Coastguard Worker     {
920*35238bceSAndroid Build Coastguard Worker         errors.check(gl().getError() == GL_NO_ERROR, "Deleting bound object failed");
921*35238bceSAndroid Build Coastguard Worker         errors.check(binder().getBinding() == 0, "Deleting bound object did not remove binding");
922*35238bceSAndroid Build Coastguard Worker         errors.check(!m_type.exists(id), "Deleting bound object did not make its name invalid");
923*35238bceSAndroid Build Coastguard Worker         binder().bind(0);
924*35238bceSAndroid Build Coastguard Worker     }
925*35238bceSAndroid Build Coastguard Worker 
926*35238bceSAndroid Build Coastguard Worker     errors.check(binder().getBinding() == 0, "Unbinding didn't remove binding");
927*35238bceSAndroid Build Coastguard Worker     errors.check(!m_type.exists(id), "Name is still valid after deleting and unbinding");
928*35238bceSAndroid Build Coastguard Worker }
929*35238bceSAndroid Build Coastguard Worker 
testBindNoGen(void)930*35238bceSAndroid Build Coastguard Worker void LifeTest::testBindNoGen(void)
931*35238bceSAndroid Build Coastguard Worker {
932*35238bceSAndroid Build Coastguard Worker     ResultCollector errors(getTestContext());
933*35238bceSAndroid Build Coastguard Worker     const GLuint id = m_rnd.getUint32();
934*35238bceSAndroid Build Coastguard Worker 
935*35238bceSAndroid Build Coastguard Worker     if (!errors.check(!m_type.exists(id), "Randomly chosen identifier already exists"))
936*35238bceSAndroid Build Coastguard Worker         return;
937*35238bceSAndroid Build Coastguard Worker 
938*35238bceSAndroid Build Coastguard Worker     Name name(m_type, id);
939*35238bceSAndroid Build Coastguard Worker     binder().bind(*name);
940*35238bceSAndroid Build Coastguard Worker 
941*35238bceSAndroid Build Coastguard Worker     if (binder().genRequired())
942*35238bceSAndroid Build Coastguard Worker     {
943*35238bceSAndroid Build Coastguard Worker         errors.check(glGetError() == GL_INVALID_OPERATION,
944*35238bceSAndroid Build Coastguard Worker                      "Did not fail when binding a name not generated by Gen* call");
945*35238bceSAndroid Build Coastguard Worker         errors.check(!m_type.exists(*name), "Bind* created an object for a name not generated by a Gen* call");
946*35238bceSAndroid Build Coastguard Worker     }
947*35238bceSAndroid Build Coastguard Worker     else
948*35238bceSAndroid Build Coastguard Worker     {
949*35238bceSAndroid Build Coastguard Worker         errors.check(glGetError() == GL_NO_ERROR, "Failed when binding a name not generated by Gen* call");
950*35238bceSAndroid Build Coastguard Worker         errors.check(m_type.exists(*name), "Object was not created by the Bind* call");
951*35238bceSAndroid Build Coastguard Worker     }
952*35238bceSAndroid Build Coastguard Worker }
953*35238bceSAndroid Build Coastguard Worker 
testDeleteUsed(void)954*35238bceSAndroid Build Coastguard Worker void LifeTest::testDeleteUsed(void)
955*35238bceSAndroid Build Coastguard Worker {
956*35238bceSAndroid Build Coastguard Worker     ResultCollector errors(getTestContext());
957*35238bceSAndroid Build Coastguard Worker     GLuint programId = 0;
958*35238bceSAndroid Build Coastguard Worker 
959*35238bceSAndroid Build Coastguard Worker     {
960*35238bceSAndroid Build Coastguard Worker         CheckedShader vtxShader(getRenderContext(), SHADERTYPE_VERTEX, s_vertexShaderSrc);
961*35238bceSAndroid Build Coastguard Worker         CheckedShader fragShader(getRenderContext(), SHADERTYPE_FRAGMENT, s_fragmentShaderSrc);
962*35238bceSAndroid Build Coastguard Worker         CheckedProgram program(getRenderContext(), vtxShader.getShader(), fragShader.getShader());
963*35238bceSAndroid Build Coastguard Worker 
964*35238bceSAndroid Build Coastguard Worker         programId = program.getProgram();
965*35238bceSAndroid Build Coastguard Worker 
966*35238bceSAndroid Build Coastguard Worker         log() << TestLog::Message << "// Created and linked program " << programId << TestLog::EndMessage;
967*35238bceSAndroid Build Coastguard Worker         GLU_CHECK_CALL_ERROR(glUseProgram(programId), gl().getError());
968*35238bceSAndroid Build Coastguard Worker 
969*35238bceSAndroid Build Coastguard Worker         log() << TestLog::Message << "// Deleted program " << programId << TestLog::EndMessage;
970*35238bceSAndroid Build Coastguard Worker     }
971*35238bceSAndroid Build Coastguard Worker     TCU_CHECK(glIsProgram(programId));
972*35238bceSAndroid Build Coastguard Worker     {
973*35238bceSAndroid Build Coastguard Worker         GLint deleteFlagged = 0;
974*35238bceSAndroid Build Coastguard Worker         glGetProgramiv(programId, GL_DELETE_STATUS, &deleteFlagged);
975*35238bceSAndroid Build Coastguard Worker         errors.check(deleteFlagged != 0, "Program object was not flagged as deleted");
976*35238bceSAndroid Build Coastguard Worker     }
977*35238bceSAndroid Build Coastguard Worker     GLU_CHECK_CALL_ERROR(glUseProgram(0), gl().getError());
978*35238bceSAndroid Build Coastguard Worker     errors.check(!gl().isProgram(programId), "Deleted program name still valid after being made non-current");
979*35238bceSAndroid Build Coastguard Worker }
980*35238bceSAndroid Build Coastguard Worker 
981*35238bceSAndroid Build Coastguard Worker class AttachmentTest : public TestBase
982*35238bceSAndroid Build Coastguard Worker {
983*35238bceSAndroid Build Coastguard Worker public:
984*35238bceSAndroid Build Coastguard Worker     typedef void (AttachmentTest::*TestFunction)(void);
AttachmentTest(const char * name,const char * description,Attacher & attacher,TestFunction test)985*35238bceSAndroid Build Coastguard Worker     AttachmentTest(const char *name, const char *description, Attacher &attacher, TestFunction test)
986*35238bceSAndroid Build Coastguard Worker         : TestBase(name, description, attacher.getContext())
987*35238bceSAndroid Build Coastguard Worker         , m_attacher(attacher)
988*35238bceSAndroid Build Coastguard Worker         , m_test(test)
989*35238bceSAndroid Build Coastguard Worker     {
990*35238bceSAndroid Build Coastguard Worker     }
991*35238bceSAndroid Build Coastguard Worker     IterateResult iterate(void);
992*35238bceSAndroid Build Coastguard Worker 
993*35238bceSAndroid Build Coastguard Worker     void testDeletedNames(void);
994*35238bceSAndroid Build Coastguard Worker     void testDeletedBinding(void);
995*35238bceSAndroid Build Coastguard Worker     void testDeletedReattach(void);
996*35238bceSAndroid Build Coastguard Worker 
997*35238bceSAndroid Build Coastguard Worker private:
998*35238bceSAndroid Build Coastguard Worker     Attacher &m_attacher;
999*35238bceSAndroid Build Coastguard Worker     const TestFunction m_test;
1000*35238bceSAndroid Build Coastguard Worker };
1001*35238bceSAndroid Build Coastguard Worker 
iterate(void)1002*35238bceSAndroid Build Coastguard Worker IterateResult AttachmentTest::iterate(void)
1003*35238bceSAndroid Build Coastguard Worker {
1004*35238bceSAndroid Build Coastguard Worker     (this->*m_test)();
1005*35238bceSAndroid Build Coastguard Worker     return STOP;
1006*35238bceSAndroid Build Coastguard Worker }
1007*35238bceSAndroid Build Coastguard Worker 
getAttachment(Attacher & attacher,GLuint container)1008*35238bceSAndroid Build Coastguard Worker GLuint getAttachment(Attacher &attacher, GLuint container)
1009*35238bceSAndroid Build Coastguard Worker {
1010*35238bceSAndroid Build Coastguard Worker     const GLuint queriedAttachment = attacher.getAttachment(container);
1011*35238bceSAndroid Build Coastguard Worker     attacher.log() << TestLog::Message << "// Result of query for " << attacher.getElementType().getName()
1012*35238bceSAndroid Build Coastguard Worker                    << " attached to " << attacher.getContainerType().getName() << " " << container << ": "
1013*35238bceSAndroid Build Coastguard Worker                    << queriedAttachment << "." << TestLog::EndMessage;
1014*35238bceSAndroid Build Coastguard Worker     return queriedAttachment;
1015*35238bceSAndroid Build Coastguard Worker }
1016*35238bceSAndroid Build Coastguard Worker 
testDeletedNames(void)1017*35238bceSAndroid Build Coastguard Worker void AttachmentTest::testDeletedNames(void)
1018*35238bceSAndroid Build Coastguard Worker {
1019*35238bceSAndroid Build Coastguard Worker     Type &elemType      = m_attacher.getElementType();
1020*35238bceSAndroid Build Coastguard Worker     Type &containerType = m_attacher.getContainerType();
1021*35238bceSAndroid Build Coastguard Worker     Name container(containerType);
1022*35238bceSAndroid Build Coastguard Worker     ResultCollector errors(getTestContext());
1023*35238bceSAndroid Build Coastguard Worker     GLuint elementId = 0;
1024*35238bceSAndroid Build Coastguard Worker 
1025*35238bceSAndroid Build Coastguard Worker     {
1026*35238bceSAndroid Build Coastguard Worker         Name element(elemType);
1027*35238bceSAndroid Build Coastguard Worker         elementId = *element;
1028*35238bceSAndroid Build Coastguard Worker         m_attacher.initAttachment(0, *element);
1029*35238bceSAndroid Build Coastguard Worker         m_attacher.attach(*element, *container);
1030*35238bceSAndroid Build Coastguard Worker         errors.check(getAttachment(m_attacher, *container) == elementId,
1031*35238bceSAndroid Build Coastguard Worker                      "Attachment name not returned by query even before deletion.");
1032*35238bceSAndroid Build Coastguard Worker     }
1033*35238bceSAndroid Build Coastguard Worker 
1034*35238bceSAndroid Build Coastguard Worker     // "Such a container or other context may continue using the object, and
1035*35238bceSAndroid Build Coastguard Worker     // may still contain state identifying its name as being currently bound"
1036*35238bceSAndroid Build Coastguard Worker     //
1037*35238bceSAndroid Build Coastguard Worker     // We here interpret "may" to mean that whenever the container has a
1038*35238bceSAndroid Build Coastguard Worker     // deleted object attached to it, a query will return that object's former
1039*35238bceSAndroid Build Coastguard Worker     // name.
1040*35238bceSAndroid Build Coastguard Worker     errors.check(getAttachment(m_attacher, *container) == elementId,
1041*35238bceSAndroid Build Coastguard Worker                  "Attachment name not returned by query after attachment was deleted.");
1042*35238bceSAndroid Build Coastguard Worker 
1043*35238bceSAndroid Build Coastguard Worker     if (elemType.nameLingers())
1044*35238bceSAndroid Build Coastguard Worker         errors.check(elemType.exists(elementId), "Attached object name no longer valid after deletion.");
1045*35238bceSAndroid Build Coastguard Worker     else
1046*35238bceSAndroid Build Coastguard Worker         errors.check(!elemType.exists(elementId), "Attached object name still valid after deletion.");
1047*35238bceSAndroid Build Coastguard Worker 
1048*35238bceSAndroid Build Coastguard Worker     m_attacher.detach(elementId, *container);
1049*35238bceSAndroid Build Coastguard Worker     errors.check(getAttachment(m_attacher, *container) == 0,
1050*35238bceSAndroid Build Coastguard Worker                  "Attachment name returned by query even after detachment.");
1051*35238bceSAndroid Build Coastguard Worker     errors.check(!elemType.exists(elementId), "Deleted attached object name still usable after detachment.");
1052*35238bceSAndroid Build Coastguard Worker }
1053*35238bceSAndroid Build Coastguard Worker 
1054*35238bceSAndroid Build Coastguard Worker class InputAttachmentTest : public TestBase
1055*35238bceSAndroid Build Coastguard Worker {
1056*35238bceSAndroid Build Coastguard Worker public:
InputAttachmentTest(const char * name,const char * description,InputAttacher & inputAttacher)1057*35238bceSAndroid Build Coastguard Worker     InputAttachmentTest(const char *name, const char *description, InputAttacher &inputAttacher)
1058*35238bceSAndroid Build Coastguard Worker         : TestBase(name, description, inputAttacher.getContext())
1059*35238bceSAndroid Build Coastguard Worker         , m_inputAttacher(inputAttacher)
1060*35238bceSAndroid Build Coastguard Worker     {
1061*35238bceSAndroid Build Coastguard Worker     }
1062*35238bceSAndroid Build Coastguard Worker 
1063*35238bceSAndroid Build Coastguard Worker     IterateResult iterate(void);
1064*35238bceSAndroid Build Coastguard Worker 
1065*35238bceSAndroid Build Coastguard Worker private:
1066*35238bceSAndroid Build Coastguard Worker     InputAttacher &m_inputAttacher;
1067*35238bceSAndroid Build Coastguard Worker };
1068*35238bceSAndroid Build Coastguard Worker 
replaceName(Type & type,GLuint oldName,TestLog & log)1069*35238bceSAndroid Build Coastguard Worker GLuint replaceName(Type &type, GLuint oldName, TestLog &log)
1070*35238bceSAndroid Build Coastguard Worker {
1071*35238bceSAndroid Build Coastguard Worker     const Binder *const binder = type.binder();
1072*35238bceSAndroid Build Coastguard Worker     const bool genRequired     = binder == DE_NULL || binder->genRequired();
1073*35238bceSAndroid Build Coastguard Worker 
1074*35238bceSAndroid Build Coastguard Worker     if (genRequired)
1075*35238bceSAndroid Build Coastguard Worker         return type.gen();
1076*35238bceSAndroid Build Coastguard Worker 
1077*35238bceSAndroid Build Coastguard Worker     log << TestLog::Message << "// Type does not require Gen* for binding, reusing old id " << oldName << "."
1078*35238bceSAndroid Build Coastguard Worker         << TestLog::EndMessage;
1079*35238bceSAndroid Build Coastguard Worker 
1080*35238bceSAndroid Build Coastguard Worker     return oldName;
1081*35238bceSAndroid Build Coastguard Worker }
1082*35238bceSAndroid Build Coastguard Worker 
iterate(void)1083*35238bceSAndroid Build Coastguard Worker IterateResult InputAttachmentTest::iterate(void)
1084*35238bceSAndroid Build Coastguard Worker {
1085*35238bceSAndroid Build Coastguard Worker     Attacher &attacher  = m_inputAttacher.getAttacher();
1086*35238bceSAndroid Build Coastguard Worker     Type &containerType = attacher.getContainerType();
1087*35238bceSAndroid Build Coastguard Worker     Type &elementType   = attacher.getElementType();
1088*35238bceSAndroid Build Coastguard Worker     Name container(containerType);
1089*35238bceSAndroid Build Coastguard Worker     GLuint elementId     = 0;
1090*35238bceSAndroid Build Coastguard Worker     const GLuint refSeed = m_rnd.getUint32();
1091*35238bceSAndroid Build Coastguard Worker     const GLuint newSeed = m_rnd.getUint32();
1092*35238bceSAndroid Build Coastguard Worker     ResultCollector errors(getTestContext());
1093*35238bceSAndroid Build Coastguard Worker 
1094*35238bceSAndroid Build Coastguard Worker     Surface refSurface; // Surface from drawing with refSeed-seeded attachment
1095*35238bceSAndroid Build Coastguard Worker     Surface delSurface; // Surface from drawing with deleted refSeed attachment
1096*35238bceSAndroid Build Coastguard Worker     Surface newSurface; // Surface from drawing with newSeed-seeded attachment
1097*35238bceSAndroid Build Coastguard Worker 
1098*35238bceSAndroid Build Coastguard Worker     log() << TestLog::Message << "Testing if writing to a newly created object modifies a deleted attachment"
1099*35238bceSAndroid Build Coastguard Worker           << TestLog::EndMessage;
1100*35238bceSAndroid Build Coastguard Worker 
1101*35238bceSAndroid Build Coastguard Worker     {
1102*35238bceSAndroid Build Coastguard Worker         ScopedLogSection section(log(), "Write to original", "Writing to an original attachment");
1103*35238bceSAndroid Build Coastguard Worker         const Name element(elementType);
1104*35238bceSAndroid Build Coastguard Worker 
1105*35238bceSAndroid Build Coastguard Worker         elementId = *element;
1106*35238bceSAndroid Build Coastguard Worker         attacher.initAttachment(refSeed, elementId);
1107*35238bceSAndroid Build Coastguard Worker         attacher.attach(elementId, *container);
1108*35238bceSAndroid Build Coastguard Worker         m_inputAttacher.drawContainer(*container, refSurface);
1109*35238bceSAndroid Build Coastguard Worker         // element gets deleted here
1110*35238bceSAndroid Build Coastguard Worker         log() << TestLog::Message << "// Deleting attachment";
1111*35238bceSAndroid Build Coastguard Worker     }
1112*35238bceSAndroid Build Coastguard Worker     {
1113*35238bceSAndroid Build Coastguard Worker         ScopedLogSection section(log(), "Write to new", "Writing to a new attachment after deleting the original");
1114*35238bceSAndroid Build Coastguard Worker         const GLuint newId = replaceName(elementType, elementId, log());
1115*35238bceSAndroid Build Coastguard Worker         const Name newElement(elementType, newId);
1116*35238bceSAndroid Build Coastguard Worker 
1117*35238bceSAndroid Build Coastguard Worker         attacher.initAttachment(newSeed, newId);
1118*35238bceSAndroid Build Coastguard Worker 
1119*35238bceSAndroid Build Coastguard Worker         m_inputAttacher.drawContainer(*container, delSurface);
1120*35238bceSAndroid Build Coastguard Worker         attacher.detach(elementId, *container);
1121*35238bceSAndroid Build Coastguard Worker 
1122*35238bceSAndroid Build Coastguard Worker         attacher.attach(newId, *container);
1123*35238bceSAndroid Build Coastguard Worker         m_inputAttacher.drawContainer(*container, newSurface);
1124*35238bceSAndroid Build Coastguard Worker         attacher.detach(newId, *container);
1125*35238bceSAndroid Build Coastguard Worker     }
1126*35238bceSAndroid Build Coastguard Worker     {
1127*35238bceSAndroid Build Coastguard Worker         const bool surfacesMatch =
1128*35238bceSAndroid Build Coastguard Worker             tcu::pixelThresholdCompare(log(), "Reading from deleted",
1129*35238bceSAndroid Build Coastguard Worker                                        "Comparison result from reading from a container with a deleted attachment "
1130*35238bceSAndroid Build Coastguard Worker                                        "before and after writing to a fresh object.",
1131*35238bceSAndroid Build Coastguard Worker                                        refSurface, delSurface, RGBA(0, 0, 0, 0), tcu::COMPARE_LOG_RESULT);
1132*35238bceSAndroid Build Coastguard Worker 
1133*35238bceSAndroid Build Coastguard Worker         errors.check(surfacesMatch, "Writing to a fresh object modified the container with a deleted attachment.");
1134*35238bceSAndroid Build Coastguard Worker 
1135*35238bceSAndroid Build Coastguard Worker         if (!surfacesMatch)
1136*35238bceSAndroid Build Coastguard Worker             log() << TestLog::Image("New attachment", "Container state after attached to the fresh object", newSurface);
1137*35238bceSAndroid Build Coastguard Worker     }
1138*35238bceSAndroid Build Coastguard Worker 
1139*35238bceSAndroid Build Coastguard Worker     return STOP;
1140*35238bceSAndroid Build Coastguard Worker }
1141*35238bceSAndroid Build Coastguard Worker 
1142*35238bceSAndroid Build Coastguard Worker class OutputAttachmentTest : public TestBase
1143*35238bceSAndroid Build Coastguard Worker {
1144*35238bceSAndroid Build Coastguard Worker public:
OutputAttachmentTest(const char * name,const char * description,OutputAttacher & outputAttacher)1145*35238bceSAndroid Build Coastguard Worker     OutputAttachmentTest(const char *name, const char *description, OutputAttacher &outputAttacher)
1146*35238bceSAndroid Build Coastguard Worker         : TestBase(name, description, outputAttacher.getContext())
1147*35238bceSAndroid Build Coastguard Worker         , m_outputAttacher(outputAttacher)
1148*35238bceSAndroid Build Coastguard Worker     {
1149*35238bceSAndroid Build Coastguard Worker     }
1150*35238bceSAndroid Build Coastguard Worker     IterateResult iterate(void);
1151*35238bceSAndroid Build Coastguard Worker 
1152*35238bceSAndroid Build Coastguard Worker private:
1153*35238bceSAndroid Build Coastguard Worker     OutputAttacher &m_outputAttacher;
1154*35238bceSAndroid Build Coastguard Worker };
1155*35238bceSAndroid Build Coastguard Worker 
iterate(void)1156*35238bceSAndroid Build Coastguard Worker IterateResult OutputAttachmentTest::iterate(void)
1157*35238bceSAndroid Build Coastguard Worker {
1158*35238bceSAndroid Build Coastguard Worker     Attacher &attacher  = m_outputAttacher.getAttacher();
1159*35238bceSAndroid Build Coastguard Worker     Type &containerType = attacher.getContainerType();
1160*35238bceSAndroid Build Coastguard Worker     Type &elementType   = attacher.getElementType();
1161*35238bceSAndroid Build Coastguard Worker     Name container(containerType);
1162*35238bceSAndroid Build Coastguard Worker     GLuint elementId     = 0;
1163*35238bceSAndroid Build Coastguard Worker     const GLuint refSeed = m_rnd.getUint32();
1164*35238bceSAndroid Build Coastguard Worker     const GLuint newSeed = m_rnd.getUint32();
1165*35238bceSAndroid Build Coastguard Worker     ResultCollector errors(getTestContext());
1166*35238bceSAndroid Build Coastguard Worker     Surface refSurface; // Surface drawn from attachment to refSeed container
1167*35238bceSAndroid Build Coastguard Worker     Surface newSurface; // Surface drawn from attachment to newSeed container
1168*35238bceSAndroid Build Coastguard Worker     Surface delSurface; // Like newSurface, after writing to a deleted attachment
1169*35238bceSAndroid Build Coastguard Worker 
1170*35238bceSAndroid Build Coastguard Worker     log() << TestLog::Message << "Testing if writing to a container with a deleted attachment "
1171*35238bceSAndroid Build Coastguard Worker           << "modifies a newly created object" << TestLog::EndMessage;
1172*35238bceSAndroid Build Coastguard Worker 
1173*35238bceSAndroid Build Coastguard Worker     {
1174*35238bceSAndroid Build Coastguard Worker         ScopedLogSection section(log(), "Write to existing", "Writing to a container with an existing attachment");
1175*35238bceSAndroid Build Coastguard Worker         const Name element(elementType);
1176*35238bceSAndroid Build Coastguard Worker 
1177*35238bceSAndroid Build Coastguard Worker         elementId = *element;
1178*35238bceSAndroid Build Coastguard Worker         attacher.initAttachment(0, elementId);
1179*35238bceSAndroid Build Coastguard Worker         attacher.attach(elementId, *container);
1180*35238bceSAndroid Build Coastguard Worker 
1181*35238bceSAndroid Build Coastguard Worker         // For reference purposes, make note of what refSeed looks like.
1182*35238bceSAndroid Build Coastguard Worker         m_outputAttacher.setupContainer(refSeed, *container);
1183*35238bceSAndroid Build Coastguard Worker         m_outputAttacher.drawAttachment(elementId, refSurface);
1184*35238bceSAndroid Build Coastguard Worker     }
1185*35238bceSAndroid Build Coastguard Worker     {
1186*35238bceSAndroid Build Coastguard Worker         ScopedLogSection section(log(), "Write to deleted", "Writing to a container after deletion of attachment");
1187*35238bceSAndroid Build Coastguard Worker         const GLuint newId = replaceName(elementType, elementId, log());
1188*35238bceSAndroid Build Coastguard Worker         const Name newElement(elementType, newId);
1189*35238bceSAndroid Build Coastguard Worker 
1190*35238bceSAndroid Build Coastguard Worker         log() << TestLog::Message << "Creating a new object " << newId << TestLog::EndMessage;
1191*35238bceSAndroid Build Coastguard Worker 
1192*35238bceSAndroid Build Coastguard Worker         log() << TestLog::Message << "Recording state of new object before writing to container" << TestLog::EndMessage;
1193*35238bceSAndroid Build Coastguard Worker         attacher.initAttachment(newSeed, newId);
1194*35238bceSAndroid Build Coastguard Worker         m_outputAttacher.drawAttachment(newId, newSurface);
1195*35238bceSAndroid Build Coastguard Worker 
1196*35238bceSAndroid Build Coastguard Worker         log() << TestLog::Message << "Writing to container" << TestLog::EndMessage;
1197*35238bceSAndroid Build Coastguard Worker 
1198*35238bceSAndroid Build Coastguard Worker         // Now re-write refSeed to the container.
1199*35238bceSAndroid Build Coastguard Worker         m_outputAttacher.setupContainer(refSeed, *container);
1200*35238bceSAndroid Build Coastguard Worker         // Does it affect the newly created attachment object?
1201*35238bceSAndroid Build Coastguard Worker         m_outputAttacher.drawAttachment(newId, delSurface);
1202*35238bceSAndroid Build Coastguard Worker     }
1203*35238bceSAndroid Build Coastguard Worker     attacher.detach(elementId, *container);
1204*35238bceSAndroid Build Coastguard Worker 
1205*35238bceSAndroid Build Coastguard Worker     const bool surfacesMatch =
1206*35238bceSAndroid Build Coastguard Worker         tcu::pixelThresholdCompare(log(), "Writing to deleted",
1207*35238bceSAndroid Build Coastguard Worker                                    "Comparison result from reading from a fresh object before and after "
1208*35238bceSAndroid Build Coastguard Worker                                    "writing to a container with a deleted attachment",
1209*35238bceSAndroid Build Coastguard Worker                                    newSurface, delSurface, RGBA(0, 0, 0, 0), tcu::COMPARE_LOG_RESULT);
1210*35238bceSAndroid Build Coastguard Worker 
1211*35238bceSAndroid Build Coastguard Worker     errors.check(surfacesMatch, "Writing to container with deleted attachment modified a new object.");
1212*35238bceSAndroid Build Coastguard Worker 
1213*35238bceSAndroid Build Coastguard Worker     if (!surfacesMatch)
1214*35238bceSAndroid Build Coastguard Worker         log() << TestLog::Image("Original attachment",
1215*35238bceSAndroid Build Coastguard Worker                                 "Result of container modification on original attachment before deletion.", refSurface);
1216*35238bceSAndroid Build Coastguard Worker     return STOP;
1217*35238bceSAndroid Build Coastguard Worker }
1218*35238bceSAndroid Build Coastguard Worker 
1219*35238bceSAndroid Build Coastguard Worker struct LifeTestSpec
1220*35238bceSAndroid Build Coastguard Worker {
1221*35238bceSAndroid Build Coastguard Worker     const char *name;
1222*35238bceSAndroid Build Coastguard Worker     LifeTest::TestFunction func;
1223*35238bceSAndroid Build Coastguard Worker     bool needBind;
1224*35238bceSAndroid Build Coastguard Worker };
1225*35238bceSAndroid Build Coastguard Worker 
createLifeTestGroup(TestContext & testCtx,const LifeTestSpec & spec,const vector<Type * > & types)1226*35238bceSAndroid Build Coastguard Worker MovePtr<TestCaseGroup> createLifeTestGroup(TestContext &testCtx, const LifeTestSpec &spec, const vector<Type *> &types)
1227*35238bceSAndroid Build Coastguard Worker {
1228*35238bceSAndroid Build Coastguard Worker     MovePtr<TestCaseGroup> group(new TestCaseGroup(testCtx, spec.name, spec.name));
1229*35238bceSAndroid Build Coastguard Worker 
1230*35238bceSAndroid Build Coastguard Worker     for (vector<Type *>::const_iterator it = types.begin(); it != types.end(); ++it)
1231*35238bceSAndroid Build Coastguard Worker     {
1232*35238bceSAndroid Build Coastguard Worker         Type &type       = **it;
1233*35238bceSAndroid Build Coastguard Worker         const char *name = type.getName();
1234*35238bceSAndroid Build Coastguard Worker         if (!spec.needBind || type.binder() != DE_NULL)
1235*35238bceSAndroid Build Coastguard Worker             group->addChild(new LifeTest(name, name, type, spec.func));
1236*35238bceSAndroid Build Coastguard Worker     }
1237*35238bceSAndroid Build Coastguard Worker 
1238*35238bceSAndroid Build Coastguard Worker     return group;
1239*35238bceSAndroid Build Coastguard Worker }
1240*35238bceSAndroid Build Coastguard Worker 
1241*35238bceSAndroid Build Coastguard Worker static const LifeTestSpec s_lifeTests[] = {
1242*35238bceSAndroid Build Coastguard Worker     {"gen", &LifeTest::testGen, false},
1243*35238bceSAndroid Build Coastguard Worker     {"delete", &LifeTest::testDelete, false},
1244*35238bceSAndroid Build Coastguard Worker     {"bind", &LifeTest::testBind, true},
1245*35238bceSAndroid Build Coastguard Worker     {"delete_bound", &LifeTest::testDeleteBound, true},
1246*35238bceSAndroid Build Coastguard Worker     {"bind_no_gen", &LifeTest::testBindNoGen, true},
1247*35238bceSAndroid Build Coastguard Worker };
1248*35238bceSAndroid Build Coastguard Worker 
attacherName(Attacher & attacher)1249*35238bceSAndroid Build Coastguard Worker string attacherName(Attacher &attacher)
1250*35238bceSAndroid Build Coastguard Worker {
1251*35238bceSAndroid Build Coastguard Worker     ostringstream os;
1252*35238bceSAndroid Build Coastguard Worker     os << attacher.getElementType().getName() << "_" << attacher.getContainerType().getName();
1253*35238bceSAndroid Build Coastguard Worker     return os.str();
1254*35238bceSAndroid Build Coastguard Worker }
1255*35238bceSAndroid Build Coastguard Worker 
addTestCases(TestCaseGroup & group,Types & types)1256*35238bceSAndroid Build Coastguard Worker void addTestCases(TestCaseGroup &group, Types &types)
1257*35238bceSAndroid Build Coastguard Worker {
1258*35238bceSAndroid Build Coastguard Worker     TestContext &testCtx = types.getTestContext();
1259*35238bceSAndroid Build Coastguard Worker 
1260*35238bceSAndroid Build Coastguard Worker     for (const LifeTestSpec *it = DE_ARRAY_BEGIN(s_lifeTests); it != DE_ARRAY_END(s_lifeTests); ++it)
1261*35238bceSAndroid Build Coastguard Worker         group.addChild(createLifeTestGroup(testCtx, *it, types.getTypes()).release());
1262*35238bceSAndroid Build Coastguard Worker 
1263*35238bceSAndroid Build Coastguard Worker     {
1264*35238bceSAndroid Build Coastguard Worker         TestCaseGroup *const delUsedGroup = new TestCaseGroup(testCtx, "delete_used", "Delete current program");
1265*35238bceSAndroid Build Coastguard Worker         group.addChild(delUsedGroup);
1266*35238bceSAndroid Build Coastguard Worker 
1267*35238bceSAndroid Build Coastguard Worker         delUsedGroup->addChild(new LifeTest("program", "program", types.getProgramType(), &LifeTest::testDeleteUsed));
1268*35238bceSAndroid Build Coastguard Worker     }
1269*35238bceSAndroid Build Coastguard Worker 
1270*35238bceSAndroid Build Coastguard Worker     {
1271*35238bceSAndroid Build Coastguard Worker         TestCaseGroup *const attGroup = new TestCaseGroup(testCtx, "attach", "Attachment tests");
1272*35238bceSAndroid Build Coastguard Worker         group.addChild(attGroup);
1273*35238bceSAndroid Build Coastguard Worker 
1274*35238bceSAndroid Build Coastguard Worker         {
1275*35238bceSAndroid Build Coastguard Worker             TestCaseGroup *const nameGroup = new TestCaseGroup(testCtx, "deleted_name", "Name of deleted attachment");
1276*35238bceSAndroid Build Coastguard Worker             attGroup->addChild(nameGroup);
1277*35238bceSAndroid Build Coastguard Worker 
1278*35238bceSAndroid Build Coastguard Worker             const vector<Attacher *> &atts = types.getAttachers();
1279*35238bceSAndroid Build Coastguard Worker             for (vector<Attacher *>::const_iterator it = atts.begin(); it != atts.end(); ++it)
1280*35238bceSAndroid Build Coastguard Worker             {
1281*35238bceSAndroid Build Coastguard Worker                 const string name = attacherName(**it);
1282*35238bceSAndroid Build Coastguard Worker                 nameGroup->addChild(
1283*35238bceSAndroid Build Coastguard Worker                     new AttachmentTest(name.c_str(), name.c_str(), **it, &AttachmentTest::testDeletedNames));
1284*35238bceSAndroid Build Coastguard Worker             }
1285*35238bceSAndroid Build Coastguard Worker         }
1286*35238bceSAndroid Build Coastguard Worker         {
1287*35238bceSAndroid Build Coastguard Worker             TestCaseGroup *inputGroup = new TestCaseGroup(testCtx, "deleted_input", "Input from deleted attachment");
1288*35238bceSAndroid Build Coastguard Worker             attGroup->addChild(inputGroup);
1289*35238bceSAndroid Build Coastguard Worker 
1290*35238bceSAndroid Build Coastguard Worker             const vector<InputAttacher *> &inAtts = types.getInputAttachers();
1291*35238bceSAndroid Build Coastguard Worker             for (vector<InputAttacher *>::const_iterator it = inAtts.begin(); it != inAtts.end(); ++it)
1292*35238bceSAndroid Build Coastguard Worker             {
1293*35238bceSAndroid Build Coastguard Worker                 const string name = attacherName((*it)->getAttacher());
1294*35238bceSAndroid Build Coastguard Worker                 inputGroup->addChild(new InputAttachmentTest(name.c_str(), name.c_str(), **it));
1295*35238bceSAndroid Build Coastguard Worker             }
1296*35238bceSAndroid Build Coastguard Worker         }
1297*35238bceSAndroid Build Coastguard Worker         {
1298*35238bceSAndroid Build Coastguard Worker             TestCaseGroup *outputGroup = new TestCaseGroup(testCtx, "deleted_output", "Output to deleted attachment");
1299*35238bceSAndroid Build Coastguard Worker             attGroup->addChild(outputGroup);
1300*35238bceSAndroid Build Coastguard Worker 
1301*35238bceSAndroid Build Coastguard Worker             const vector<OutputAttacher *> &outAtts = types.getOutputAttachers();
1302*35238bceSAndroid Build Coastguard Worker             for (vector<OutputAttacher *>::const_iterator it = outAtts.begin(); it != outAtts.end(); ++it)
1303*35238bceSAndroid Build Coastguard Worker             {
1304*35238bceSAndroid Build Coastguard Worker                 string name = attacherName((*it)->getAttacher());
1305*35238bceSAndroid Build Coastguard Worker                 outputGroup->addChild(new OutputAttachmentTest(name.c_str(), name.c_str(), **it));
1306*35238bceSAndroid Build Coastguard Worker             }
1307*35238bceSAndroid Build Coastguard Worker         }
1308*35238bceSAndroid Build Coastguard Worker     }
1309*35238bceSAndroid Build Coastguard Worker }
1310*35238bceSAndroid Build Coastguard Worker 
1311*35238bceSAndroid Build Coastguard Worker } // namespace details
1312*35238bceSAndroid Build Coastguard Worker } // namespace LifetimeTests
1313*35238bceSAndroid Build Coastguard Worker } // namespace gls
1314*35238bceSAndroid Build Coastguard Worker } // namespace deqp
1315