xref: /aosp_15_r20/external/deqp/modules/gles3/functional/es3fLifetimeTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 3.0 Module
3  * -------------------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Object lifetime tests.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "es3fLifetimeTests.hpp"
25 
26 #include "deRandom.hpp"
27 #include "deUniquePtr.hpp"
28 #include "tcuRenderTarget.hpp"
29 #include "tcuSurface.hpp"
30 #include "gluDrawUtil.hpp"
31 #include "gluObjectWrapper.hpp"
32 #include "gluPixelTransfer.hpp"
33 #include "gluShaderProgram.hpp"
34 #include "glsLifetimeTests.hpp"
35 #include "glwEnums.hpp"
36 #include "glwFunctions.hpp"
37 
38 #include <vector>
39 
40 namespace deqp
41 {
42 namespace gles3
43 {
44 namespace Functional
45 {
46 namespace
47 {
48 
49 using de::MovePtr;
50 using de::Random;
51 using glu::Buffer;
52 using glu::CallLogWrapper;
53 using glu::ProgramSources;
54 using glu::RenderContext;
55 using glu::VertexArray;
56 using std::vector;
57 using tcu::RenderTarget;
58 using tcu::Surface;
59 using tcu::TestContext;
60 using tcu::TestLog;
61 namespace lt = gls::LifetimeTests;
62 using namespace lt;
63 using namespace glw;
64 typedef TestCase::IterateResult IterateResult;
65 
66 enum
67 {
68     VIEWPORT_SIZE = 128
69 };
70 
71 class ScaleProgram : public glu::ShaderProgram
72 {
73 public:
74     ScaleProgram(lt::Context &ctx);
75     void draw(GLuint vao, GLfloat scale, bool tf, Surface *dst);
76     void setPos(GLuint buffer, GLuint vao);
77 
78 private:
79     ProgramSources getSources(void);
80 
81     const RenderContext &m_renderCtx;
82     GLint m_scaleLoc;
83     GLint m_posLoc;
84 };
85 
86 enum
87 {
88     NUM_COMPONENTS = 4,
89     NUM_VERTICES   = 3
90 };
91 
ScaleProgram(lt::Context & ctx)92 ScaleProgram::ScaleProgram(lt::Context &ctx)
93     : glu::ShaderProgram(ctx.getRenderContext(), getSources())
94     , m_renderCtx(ctx.getRenderContext())
95 {
96     const Functions &gl = m_renderCtx.getFunctions();
97     TCU_CHECK(isOk());
98     m_scaleLoc = gl.getUniformLocation(getProgram(), "scale");
99     m_posLoc   = gl.getAttribLocation(getProgram(), "pos");
100 }
101 
102 #define GLSL(VERSION, BODY) ("#version " #VERSION "\n" #BODY "\n")
103 
104 static const char *const s_vertexShaderSrc = GLSL(
105     100, attribute vec4 pos; uniform float scale; void main() { gl_Position = vec4(scale * pos.xy, pos.zw); });
106 
107 static const char *const s_fragmentShaderSrc = GLSL(
108     100, void main() { gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0); });
109 
getSources(void)110 ProgramSources ScaleProgram::getSources(void)
111 {
112     using namespace glu;
113     ProgramSources sources;
114     sources << VertexSource(s_vertexShaderSrc) << FragmentSource(s_fragmentShaderSrc)
115             << TransformFeedbackMode(GL_INTERLEAVED_ATTRIBS) << TransformFeedbackVarying("gl_Position");
116     return sources;
117 }
118 
draw(GLuint vao,GLfloat scale,bool tf,Surface * dst)119 void ScaleProgram::draw(GLuint vao, GLfloat scale, bool tf, Surface *dst)
120 {
121     const Functions &gl = m_renderCtx.getFunctions();
122     de::Random rnd(vao);
123     Rectangle viewport = randomViewport(m_renderCtx, VIEWPORT_SIZE, VIEWPORT_SIZE, rnd);
124     setViewport(m_renderCtx, viewport);
125     gl.clearColor(0, 0, 0, 1);
126     gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
127 
128     gl.bindVertexArray(vao);
129     gl.enableVertexAttribArray(m_posLoc);
130     GLU_CHECK_CALL_ERROR(gl.useProgram(getProgram()), gl.getError());
131 
132     gl.uniform1f(m_scaleLoc, scale);
133 
134     if (tf)
135     {
136         gl.beginTransformFeedback(GL_TRIANGLES);
137         if (gl.getError() == GL_INVALID_OPERATION)
138             return;
139     }
140     GLU_CHECK_CALL_ERROR(gl.drawArrays(GL_TRIANGLES, 0, 3), gl.getError());
141     if (tf)
142         gl.endTransformFeedback();
143 
144     if (dst != DE_NULL)
145         readRectangle(m_renderCtx, viewport, *dst);
146 
147     gl.bindVertexArray(0);
148 }
149 
setPos(GLuint buffer,GLuint vao)150 void ScaleProgram::setPos(GLuint buffer, GLuint vao)
151 {
152     const Functions &gl = m_renderCtx.getFunctions();
153 
154     gl.bindBuffer(GL_ARRAY_BUFFER, buffer);
155     gl.bindVertexArray(vao);
156     GLU_CHECK_CALL_ERROR(gl.vertexAttribPointer(m_posLoc, NUM_COMPONENTS, GL_FLOAT, false, 0, DE_NULL), gl.getError());
157     gl.bindVertexArray(0);
158     gl.bindBuffer(GL_ARRAY_BUFFER, 0);
159     GLU_CHECK_ERROR(gl.getError());
160 }
161 
162 class VertexArrayBinder : public SimpleBinder
163 {
164 public:
VertexArrayBinder(lt::Context & ctx)165     VertexArrayBinder(lt::Context &ctx) : SimpleBinder(ctx, 0, GL_NONE, GL_VERTEX_ARRAY_BINDING, true)
166     {
167     }
bind(GLuint name)168     void bind(GLuint name)
169     {
170         glBindVertexArray(name);
171     }
172 };
173 
174 class SamplerBinder : public Binder
175 {
176 public:
SamplerBinder(lt::Context & ctx)177     SamplerBinder(lt::Context &ctx) : Binder(ctx)
178     {
179     }
bind(GLuint name)180     void bind(GLuint name)
181     {
182         glBindSampler(0, name);
183     }
getBinding(void)184     GLuint getBinding(void)
185     {
186         GLint arr[32] = {};
187         glGetIntegerv(GL_SAMPLER_BINDING, arr);
188         log() << TestLog::Message << "// First output integer: " << arr[0] << TestLog::EndMessage;
189         return arr[0];
190     }
genRequired(void) const191     bool genRequired(void) const
192     {
193         return true;
194     }
195 };
196 
197 class QueryBinder : public Binder
198 {
199 public:
QueryBinder(lt::Context & ctx)200     QueryBinder(lt::Context &ctx) : Binder(ctx)
201     {
202     }
bind(GLuint name)203     void bind(GLuint name)
204     {
205         if (name != 0)
206             glBeginQuery(GL_ANY_SAMPLES_PASSED, name);
207         else
208             glEndQuery(GL_ANY_SAMPLES_PASSED);
209     }
getBinding(void)210     GLuint getBinding(void)
211     {
212         return 0;
213     }
214 };
215 
216 class BufferVAOAttacher : public Attacher
217 {
218 public:
BufferVAOAttacher(lt::Context & ctx,Type & elementType,Type & varrType,ScaleProgram & program)219     BufferVAOAttacher(lt::Context &ctx, Type &elementType, Type &varrType, ScaleProgram &program)
220         : Attacher(ctx, elementType, varrType)
221         , m_program(program)
222     {
223     }
224     void initAttachment(GLuint seed, GLuint element);
225     void attach(GLuint element, GLuint container);
226     void detach(GLuint element, GLuint container);
canAttachDeleted(void) const227     bool canAttachDeleted(void) const
228     {
229         return false;
230     }
getProgram(void)231     ScaleProgram &getProgram(void)
232     {
233         return m_program;
234     }
235     GLuint getAttachment(GLuint container);
236 
237 private:
238     ScaleProgram &m_program;
239 };
240 
241 static const GLfloat s_varrData[NUM_VERTICES * NUM_COMPONENTS] = {-1.0, 0.0, 0.0, 1.0,  1.0, 1.0,
242                                                                   0.0,  1.0, 0.0, -1.0, 0.0, 1.0};
243 
initBuffer(const Functions & gl,GLuint seed,GLenum usage,GLuint buffer)244 void initBuffer(const Functions &gl, GLuint seed, GLenum usage, GLuint buffer)
245 {
246     gl.bindBuffer(GL_ARRAY_BUFFER, buffer);
247     if (seed == 0)
248         gl.bufferData(GL_ARRAY_BUFFER, sizeof(s_varrData), s_varrData, usage);
249     else
250     {
251         Random rnd(seed);
252         GLfloat data[DE_LENGTH_OF_ARRAY(s_varrData)];
253 
254         for (int ndx = 0; ndx < NUM_VERTICES; ndx++)
255         {
256             GLfloat *vertex = &data[ndx * NUM_COMPONENTS];
257             vertex[0]       = 2.0f * (rnd.getFloat() - 0.5f);
258             vertex[1]       = 2.0f * (rnd.getFloat() - 0.5f);
259             DE_STATIC_ASSERT(NUM_COMPONENTS == 4);
260             vertex[2] = 0.0f;
261             vertex[3] = 1.0f;
262         }
263         gl.bufferData(GL_ARRAY_BUFFER, sizeof(data), data, usage);
264     }
265     gl.bindBuffer(GL_ARRAY_BUFFER, 0);
266     GLU_CHECK_ERROR(gl.getError());
267 }
268 
initAttachment(GLuint seed,GLuint buffer)269 void BufferVAOAttacher::initAttachment(GLuint seed, GLuint buffer)
270 {
271     initBuffer(gl(), seed, GL_STATIC_DRAW, buffer);
272     log() << TestLog::Message << "// Initialized buffer " << buffer << " from seed " << seed << TestLog::EndMessage;
273 }
274 
attach(GLuint buffer,GLuint vao)275 void BufferVAOAttacher::attach(GLuint buffer, GLuint vao)
276 {
277     m_program.setPos(buffer, vao);
278     log() << TestLog::Message << "// Set the `pos` attribute in VAO " << vao << " to buffer " << buffer
279           << TestLog::EndMessage;
280 }
281 
detach(GLuint buffer,GLuint varr)282 void BufferVAOAttacher::detach(GLuint buffer, GLuint varr)
283 {
284     DE_UNREF(buffer);
285     attach(0, varr);
286 }
287 
getAttachment(GLuint varr)288 GLuint BufferVAOAttacher::getAttachment(GLuint varr)
289 {
290     GLint name = 0;
291     gl().bindVertexArray(varr);
292     gl().getVertexAttribiv(0, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &name);
293     gl().bindVertexArray(0);
294     GLU_CHECK_ERROR(gl().getError());
295     return GLuint(name);
296 }
297 
298 class BufferVAOInputAttacher : public InputAttacher
299 {
300 public:
BufferVAOInputAttacher(BufferVAOAttacher & attacher)301     BufferVAOInputAttacher(BufferVAOAttacher &attacher) : InputAttacher(attacher), m_program(attacher.getProgram())
302     {
303     }
304     void drawContainer(GLuint container, Surface &dst);
305 
306 private:
307     ScaleProgram &m_program;
308 };
309 
drawContainer(GLuint vao,Surface & dst)310 void BufferVAOInputAttacher::drawContainer(GLuint vao, Surface &dst)
311 {
312     m_program.draw(vao, 1.0, false, &dst);
313     log() << TestLog::Message << "// Drew an output image with VAO " << vao << TestLog::EndMessage;
314 }
315 
316 class BufferTfAttacher : public Attacher
317 {
318 public:
BufferTfAttacher(lt::Context & ctx,Type & bufferType,Type & tfType)319     BufferTfAttacher(lt::Context &ctx, Type &bufferType, Type &tfType) : Attacher(ctx, bufferType, tfType)
320     {
321     }
322     void initAttachment(GLuint seed, GLuint element);
323     void attach(GLuint buffer, GLuint tf);
324     void detach(GLuint buffer, GLuint tf);
canAttachDeleted(void) const325     bool canAttachDeleted(void) const
326     {
327         return false;
328     }
329     GLuint getAttachment(GLuint tf);
330 };
331 
initAttachment(GLuint seed,GLuint buffer)332 void BufferTfAttacher::initAttachment(GLuint seed, GLuint buffer)
333 {
334     initBuffer(gl(), seed, GL_DYNAMIC_READ, buffer);
335     log() << TestLog::Message << "// Initialized buffer " << buffer << " from seed " << seed << TestLog::EndMessage;
336 }
337 
attach(GLuint buffer,GLuint tf)338 void BufferTfAttacher::attach(GLuint buffer, GLuint tf)
339 {
340     glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, tf);
341     glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, buffer);
342     glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
343     GLU_CHECK_ERROR(gl().getError());
344 }
345 
detach(GLuint buffer,GLuint tf)346 void BufferTfAttacher::detach(GLuint buffer, GLuint tf)
347 {
348     DE_UNREF(buffer);
349     glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, tf);
350     glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0);
351     glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
352     GLU_CHECK_ERROR(gl().getError());
353 }
354 
getAttachment(GLuint tf)355 GLuint BufferTfAttacher::getAttachment(GLuint tf)
356 {
357     GLint ret = 0;
358     gl().bindTransformFeedback(GL_TRANSFORM_FEEDBACK, tf);
359     gl().getIntegeri_v(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, 0, &ret);
360     gl().bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
361     GLU_CHECK_ERROR(gl().getError());
362     return GLuint(ret);
363 }
364 
365 class BufferTfOutputAttacher : public OutputAttacher
366 {
367 public:
BufferTfOutputAttacher(BufferTfAttacher & attacher,ScaleProgram & program)368     BufferTfOutputAttacher(BufferTfAttacher &attacher, ScaleProgram &program)
369         : OutputAttacher(attacher)
370         , m_program(program)
371     {
372     }
373     void setupContainer(GLuint seed, GLuint container);
374     void drawAttachment(GLuint attachment, Surface &dst);
375 
376 private:
377     ScaleProgram &m_program;
378 };
379 
drawAttachment(GLuint buffer,Surface & dst)380 void BufferTfOutputAttacher::drawAttachment(GLuint buffer, Surface &dst)
381 {
382     VertexArray vao(getRenderContext());
383 
384     m_program.setPos(buffer, *vao);
385     m_program.draw(*vao, 1.0, false, &dst);
386     log() << TestLog::Message << "// Drew output image with vertices from buffer " << buffer << TestLog::EndMessage;
387     GLU_CHECK_ERROR(gl().getError());
388 }
389 
setupContainer(GLuint seed,GLuint tf)390 void BufferTfOutputAttacher::setupContainer(GLuint seed, GLuint tf)
391 {
392     Buffer posBuf(getRenderContext());
393     VertexArray vao(getRenderContext());
394 
395     initBuffer(gl(), seed, GL_STATIC_DRAW, *posBuf);
396     m_program.setPos(*posBuf, *vao);
397 
398     glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, tf);
399     m_program.draw(*vao, -1.0, true, DE_NULL);
400     log() << TestLog::Message << "// Drew an image with seed " << seed << " with transform feedback to " << tf
401           << TestLog::EndMessage;
402     glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
403     GLU_CHECK_ERROR(gl().getError());
404 }
405 
406 class ES3Types : public ES2Types
407 {
408 public:
409     ES3Types(lt::Context &ctx);
410 
411 private:
412     ScaleProgram m_program;
413     QueryBinder m_queryBind;
414     SimpleType m_queryType;
415     SimpleBinder m_tfBind;
416     SimpleType m_tfType;
417     VertexArrayBinder m_varrBind;
418     SimpleType m_varrType;
419     SamplerBinder m_samplerBind;
420     SimpleType m_samplerType;
421     BufferVAOAttacher m_bufVarrAtt;
422     BufferVAOInputAttacher m_bufVarrInAtt;
423     BufferTfAttacher m_bufTfAtt;
424     BufferTfOutputAttacher m_bufTfOutAtt;
425 };
426 
ES3Types(lt::Context & ctx)427 ES3Types::ES3Types(lt::Context &ctx)
428     : ES2Types(ctx)
429     , m_program(ctx)
430     , m_queryBind(ctx)
431     , m_queryType(ctx, "query", &CallLogWrapper::glGenQueries, &CallLogWrapper::glDeleteQueries,
432                   &CallLogWrapper::glIsQuery, &m_queryBind)
433     , m_tfBind(ctx, &CallLogWrapper::glBindTransformFeedback, GL_TRANSFORM_FEEDBACK, GL_TRANSFORM_FEEDBACK_BINDING,
434                true)
435     , m_tfType(ctx, "transform_feedback", &CallLogWrapper::glGenTransformFeedbacks,
436                &CallLogWrapper::glDeleteTransformFeedbacks, &CallLogWrapper::glIsTransformFeedback, &m_tfBind)
437     , m_varrBind(ctx)
438     , m_varrType(ctx, "vertex_array", &CallLogWrapper::glGenVertexArrays, &CallLogWrapper::glDeleteVertexArrays,
439                  &CallLogWrapper::glIsVertexArray, &m_varrBind)
440     , m_samplerBind(ctx)
441     , m_samplerType(ctx, "sampler", &CallLogWrapper::glGenSamplers, &CallLogWrapper::glDeleteSamplers,
442                     &CallLogWrapper::glIsSampler, &m_samplerBind, true)
443     , m_bufVarrAtt(ctx, m_bufferType, m_varrType, m_program)
444     , m_bufVarrInAtt(m_bufVarrAtt)
445     , m_bufTfAtt(ctx, m_bufferType, m_tfType)
446     , m_bufTfOutAtt(m_bufTfAtt, m_program)
447 {
448     Type *types[] = {&m_queryType, &m_tfType, &m_varrType, &m_samplerType};
449     m_types.insert(m_types.end(), DE_ARRAY_BEGIN(types), DE_ARRAY_END(types));
450 
451     m_attachers.push_back(&m_bufVarrAtt);
452     m_attachers.push_back(&m_bufTfAtt);
453 
454     m_inAttachers.push_back(&m_bufVarrInAtt);
455     m_outAttachers.push_back(&m_bufTfOutAtt);
456 }
457 
458 class TfDeleteActiveTest : public TestCase, private CallLogWrapper
459 {
460 public:
461     TfDeleteActiveTest(gles3::Context &context, const char *name, const char *description);
462     IterateResult iterate(void);
463 };
464 
TfDeleteActiveTest(gles3::Context & context,const char * name,const char * description)465 TfDeleteActiveTest::TfDeleteActiveTest(gles3::Context &context, const char *name, const char *description)
466     : TestCase(context, name, description)
467     , CallLogWrapper(context.getRenderContext().getFunctions(), context.getTestContext().getLog())
468 {
469     enableLogging(true);
470 }
471 
472 class ScopedTransformFeedbackFeedback
473 {
474 public:
475     ScopedTransformFeedbackFeedback(glu::CallLogWrapper &gl, GLenum type);
476     ~ScopedTransformFeedbackFeedback(void);
477 
478 private:
479     glu::CallLogWrapper &m_gl;
480 };
481 
ScopedTransformFeedbackFeedback(glu::CallLogWrapper & gl,GLenum type)482 ScopedTransformFeedbackFeedback::ScopedTransformFeedbackFeedback(glu::CallLogWrapper &gl, GLenum type) : m_gl(gl)
483 {
484     m_gl.glBeginTransformFeedback(type);
485     GLU_EXPECT_NO_ERROR(m_gl.glGetError(), "glBeginTransformFeedback");
486 }
487 
~ScopedTransformFeedbackFeedback(void)488 ScopedTransformFeedbackFeedback::~ScopedTransformFeedbackFeedback(void)
489 {
490     m_gl.glEndTransformFeedback();
491 }
492 
iterate(void)493 IterateResult TfDeleteActiveTest::iterate(void)
494 {
495     static const char *const s_xfbVertexSource =
496         "#version 300 es\n"
497         "void main ()\n"
498         "{\n"
499         "    gl_Position = vec4(float(gl_VertexID) / 2.0, float(gl_VertexID % 2) / 2.0, 0.0, 1.0);\n"
500         "}\n";
501     static const char *const s_xfbFragmentSource = "#version 300 es\n"
502                                                    "layout(location=0) out mediump vec4 dEQP_FragColor;\n"
503                                                    "void main ()\n"
504                                                    "{\n"
505                                                    "    dEQP_FragColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
506                                                    "}\n";
507 
508     glu::Buffer buf(m_context.getRenderContext());
509     GLuint tf = 0;
510     glu::ShaderProgram program(m_context.getRenderContext(), glu::ProgramSources()
511                                                                  << glu::VertexSource(s_xfbVertexSource)
512                                                                  << glu::FragmentSource(s_xfbFragmentSource)
513                                                                  << glu::TransformFeedbackMode(GL_INTERLEAVED_ATTRIBS)
514                                                                  << glu::TransformFeedbackVarying("gl_Position"));
515 
516     if (!program.isOk())
517     {
518         m_testCtx.getLog() << program;
519         throw tcu::TestError("failed to build program");
520     }
521 
522     try
523     {
524         GLU_CHECK_CALL(glUseProgram(program.getProgram()));
525         GLU_CHECK_CALL(glGenTransformFeedbacks(1, &tf));
526         GLU_CHECK_CALL(glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, tf));
527         GLU_CHECK_CALL(glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, *buf));
528         GLU_CHECK_CALL(
529             glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 3 * sizeof(glw::GLfloat[4]), DE_NULL, GL_DYNAMIC_COPY));
530 
531         {
532             ScopedTransformFeedbackFeedback xfb(static_cast<glu::CallLogWrapper &>(*this), GL_TRIANGLES);
533 
534             glDeleteTransformFeedbacks(1, &tf);
535             {
536                 GLenum err = glGetError();
537                 if (err != GL_INVALID_OPERATION)
538                     getTestContext().setTestResult(
539                         QP_TEST_RESULT_FAIL, "Deleting active transform feedback did not produce GL_INVALID_OPERATION");
540                 else
541                     getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
542             }
543         }
544         GLU_CHECK(); // ScopedTransformFeedbackFeedback::dtor might modify error state
545 
546         GLU_CHECK_CALL(glDeleteTransformFeedbacks(1, &tf));
547     }
548     catch (const glu::Error &)
549     {
550         glDeleteTransformFeedbacks(1, &tf);
551         throw;
552     }
553 
554     return STOP;
555 }
556 
557 class TestGroup : public TestCaseGroup
558 {
559 public:
TestGroup(gles3::Context & context)560     TestGroup(gles3::Context &context) : TestCaseGroup(context, "lifetime", "Object lifetime tests")
561     {
562     }
563     void init(void);
564 
565 private:
566     MovePtr<Types> m_types;
567 };
568 
init(void)569 void TestGroup::init(void)
570 {
571     gles3::Context &ctx = getContext();
572     lt::Context ltCtx(ctx.getRenderContext(), ctx.getTestContext());
573 
574     m_types = MovePtr<Types>(new ES3Types(ltCtx));
575 
576     addTestCases(*this, *m_types);
577 
578     TestCaseGroup *deleteActiveGroup = new TestCaseGroup(ctx, "delete_active", "Delete active object");
579     addChild(deleteActiveGroup);
580     deleteActiveGroup->addChild(new TfDeleteActiveTest(ctx, "transform_feedback", "Transform Feedback"));
581 }
582 
583 } // namespace
584 
createLifetimeTests(Context & context)585 TestCaseGroup *createLifetimeTests(Context &context)
586 {
587     return new TestGroup(context);
588 }
589 
590 } // namespace Functional
591 } // namespace gles3
592 } // namespace deqp
593