Merge vk-gl-cts/vulkan-cts-1.1.2 into vk-gl-cts/vulkan-cts-1.1.3
[platform/upstream/VK-GL-CTS.git] / modules / egl / teglImageFormatTests.cpp
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program EGL 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 EGL image tests.
22  *//*--------------------------------------------------------------------*/
23
24 #include "teglImageFormatTests.hpp"
25
26 #include "deStringUtil.hpp"
27 #include "deSTLUtil.hpp"
28
29 #include "tcuTestLog.hpp"
30 #include "tcuSurface.hpp"
31 #include "tcuTexture.hpp"
32 #include "tcuTextureUtil.hpp"
33 #include "tcuImageCompare.hpp"
34 #include "tcuCommandLine.hpp"
35
36 #include "egluNativeDisplay.hpp"
37 #include "egluNativeWindow.hpp"
38 #include "egluNativePixmap.hpp"
39 #include "egluConfigFilter.hpp"
40 #include "egluUnique.hpp"
41 #include "egluUtil.hpp"
42
43 #include "eglwLibrary.hpp"
44 #include "eglwEnums.hpp"
45
46 #include "gluCallLogWrapper.hpp"
47 #include "gluShaderProgram.hpp"
48 #include "gluStrUtil.hpp"
49 #include "gluTexture.hpp"
50 #include "gluPixelTransfer.hpp"
51 #include "gluObjectWrapper.hpp"
52 #include "gluTextureUtil.hpp"
53
54 #include "glwEnums.hpp"
55 #include "glwFunctions.hpp"
56
57 #include "teglImageUtil.hpp"
58 #include "teglAndroidUtil.hpp"
59
60 #include <vector>
61 #include <string>
62 #include <set>
63
64 using std::vector;
65 using std::set;
66 using std::string;
67
68 using de::MovePtr;
69 using de::UniquePtr;
70
71 using glu::Framebuffer;
72 using glu::Renderbuffer;
73 using glu::Texture;
74
75 using eglu::UniqueImage;
76
77 using tcu::ConstPixelBufferAccess;
78
79 using namespace glw;
80 using namespace eglw;
81
82 namespace deqp
83 {
84 namespace egl
85 {
86
87 namespace
88 {
89
90 glu::ProgramSources programSources (const string& vertexSource, const string& fragmentSource)
91 {
92         glu::ProgramSources sources;
93
94         sources << glu::VertexSource(vertexSource) << glu::FragmentSource(fragmentSource);
95
96         return sources;
97 }
98
99 class Program : public glu::ShaderProgram
100 {
101 public:
102         Program (const glw::Functions& gl, const char* vertexSource, const char* fragmentSource)
103                 : glu::ShaderProgram(gl, programSources(vertexSource, fragmentSource)) {}
104 };
105
106 } // anonymous
107
108 namespace Image
109 {
110
111 class ImageApi;
112
113 class IllegalRendererException : public std::exception
114 {
115 };
116
117 class Action
118 {
119 public:
120         virtual                 ~Action                                 (void) {}
121         virtual bool    invoke                                  (ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& refImg) const = 0;
122         virtual string  getRequiredExtension    (void) const = 0;
123 };
124
125 struct TestSpec
126 {
127         std::string name;
128         std::string desc;
129
130         enum ApiContext
131         {
132                 API_GLES2 = 0,
133                 //API_VG
134                 //API_GLES1
135
136                 API_LAST
137         };
138
139         struct Operation
140         {
141                 Operation (int apiIndex_, const Action& action_) : apiIndex(apiIndex_), action(&action_) {}
142                 int                             apiIndex;
143                 const Action*   action;
144         };
145
146         vector<ApiContext>      contexts;
147         vector<Operation>       operations;
148
149 };
150
151 class ImageApi
152 {
153 public:
154                                         ImageApi                (const Library& egl, int contextId, EGLDisplay display, EGLSurface surface);
155         virtual                 ~ImageApi               (void) {}
156
157 protected:
158         const Library&  m_egl;
159         int                             m_contextId;
160         EGLDisplay              m_display;
161         EGLSurface              m_surface;
162 };
163
164 ImageApi::ImageApi (const Library& egl, int contextId, EGLDisplay display, EGLSurface surface)
165         : m_egl                         (egl)
166         , m_contextId           (contextId)
167         , m_display                     (display)
168         , m_surface                     (surface)
169 {
170 }
171
172 class GLES2ImageApi : public ImageApi, private glu::CallLogWrapper
173 {
174 public:
175         class GLES2Action : public Action
176         {
177         public:
178                 bool                            invoke                                  (ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const;
179                 virtual bool            invokeGLES2                             (GLES2ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const = 0;
180         };
181
182         class Create : public GLES2Action
183         {
184         public:
185                                                                 Create                                  (MovePtr<ImageSource> imgSource) : m_imgSource(imgSource) {}
186                 string                                  getRequiredExtension    (void) const { return m_imgSource->getRequiredExtension(); }
187                 bool                                    invokeGLES2                             (GLES2ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const;
188                 glw::GLenum                             getEffectiveFormat              (void) const { return m_imgSource->getEffectiveFormat(); }
189
190         private:
191                 UniquePtr<ImageSource>  m_imgSource;
192         };
193
194         class Render : public GLES2Action
195         {
196         public:
197                 string                          getRequiredExtension    (void) const { return "GL_OES_EGL_image"; }
198         };
199
200         class RenderTexture2D                           : public Render { public: bool invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const; };
201         class RenderTextureCubemap                      : public Render { public: bool invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const; };
202         class RenderReadPixelsRenderbuffer      : public Render { public: bool invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const; };
203         class RenderDepthbuffer                         : public Render { public: bool invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const; };
204         class RenderStencilbuffer                       : public Render { public: bool invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const; };
205         class RenderTryAll                                      : public Render { public: bool invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const; };
206
207         class Modify : public GLES2Action
208         {
209         public:
210                 string                          getRequiredExtension    (void) const { return "GL_OES_EGL_image"; }
211         };
212
213         class ModifyTexSubImage : public Modify
214         {
215         public:
216                                                         ModifyTexSubImage               (GLenum format, GLenum type) : m_format(format), m_type(type) {}
217                 bool                            invokeGLES2                             (GLES2ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const;
218                 GLenum                          getFormat                               (void) const { return m_format; }
219                 GLenum                          getType                                 (void) const { return m_type; }
220
221         private:
222                 GLenum                          m_format;
223                 GLenum                          m_type;
224         };
225
226         class ModifyRenderbuffer : public Modify
227         {
228         public:
229                 bool                            invokeGLES2                             (GLES2ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const;
230
231         protected:
232                 virtual void            initializeRbo                   (GLES2ImageApi& api, GLuint rbo, tcu::Texture2D& ref) const = 0;
233         };
234
235         class ModifyRenderbufferClearColor : public ModifyRenderbuffer
236         {
237         public:
238                                         ModifyRenderbufferClearColor    (tcu::Vec4 color) : m_color(color) {}
239
240         protected:
241                 void            initializeRbo                                   (GLES2ImageApi& api, GLuint rbo, tcu::Texture2D& ref) const;
242
243                 tcu::Vec4       m_color;
244         };
245
246         class ModifyRenderbufferClearDepth : public ModifyRenderbuffer
247         {
248         public:
249                                         ModifyRenderbufferClearDepth    (GLfloat depth) : m_depth(depth) {}
250
251         protected:
252                 void            initializeRbo                                   (GLES2ImageApi& api, GLuint rbo, tcu::Texture2D& ref) const;
253
254                 GLfloat         m_depth;
255         };
256
257         class ModifyRenderbufferClearStencil : public ModifyRenderbuffer
258         {
259         public:
260                                         ModifyRenderbufferClearStencil  (GLint stencil) : m_stencil(stencil) {}
261
262         protected:
263                 void            initializeRbo                                   (GLES2ImageApi& api, GLuint rbo, tcu::Texture2D& ref) const;
264
265                 GLint           m_stencil;
266         };
267
268                                         GLES2ImageApi                                   (const Library& egl, const glw::Functions& gl, int contextId, tcu::TestLog& log, EGLDisplay display, EGLSurface surface, EGLConfig config);
269                                         ~GLES2ImageApi                                  (void);
270
271 private:
272         EGLContext                                      m_context;
273         const glw::Functions&           m_gl;
274
275         MovePtr<UniqueImage>            createImage                     (const ImageSource& source, const ClientBuffer& buffer) const;
276 };
277
278 GLES2ImageApi::GLES2ImageApi (const Library& egl, const glw::Functions& gl, int contextId, tcu::TestLog& log, EGLDisplay display, EGLSurface surface, EGLConfig config)
279         : ImageApi                              (egl, contextId, display, surface)
280         , glu::CallLogWrapper   (gl, log)
281         , m_context                             (DE_NULL)
282         , m_gl                                  (gl)
283 {
284         const EGLint attriblist[] =
285         {
286                 EGL_CONTEXT_CLIENT_VERSION, 2,
287                 EGL_NONE
288         };
289
290         EGLint configId = -1;
291         EGLU_CHECK_CALL(m_egl, getConfigAttrib(m_display, config, EGL_CONFIG_ID, &configId));
292         getLog() << tcu::TestLog::Message << "Creating gles2 context with config id: " << configId << " context: " << m_contextId << tcu::TestLog::EndMessage;
293         egl.bindAPI(EGL_OPENGL_ES_API);
294         m_context = m_egl.createContext(m_display, config, EGL_NO_CONTEXT, attriblist);
295         EGLU_CHECK_MSG(m_egl, "Failed to create GLES2 context");
296
297         egl.makeCurrent(display, m_surface, m_surface, m_context);
298         EGLU_CHECK_MSG(m_egl, "Failed to make context current");
299 }
300
301 GLES2ImageApi::~GLES2ImageApi (void)
302 {
303         m_egl.makeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
304         m_egl.destroyContext(m_display, m_context);
305 }
306
307 bool GLES2ImageApi::GLES2Action::invoke (ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const
308 {
309         GLES2ImageApi& gles2Api = dynamic_cast<GLES2ImageApi&>(api);
310
311         gles2Api.m_egl.makeCurrent(gles2Api.m_display, gles2Api.m_surface, gles2Api.m_surface, gles2Api.m_context);
312         return invokeGLES2(gles2Api, image, ref);
313 }
314
315
316 bool GLES2ImageApi::Create::invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const
317 {
318         de::UniquePtr<ClientBuffer>     buffer  (m_imgSource->createBuffer(api.m_gl, &ref));
319
320         GLU_CHECK_GLW_CALL(api.m_gl, finish());
321
322         image = api.createImage(*m_imgSource, *buffer);
323         return true;
324 }
325
326 MovePtr<UniqueImage> GLES2ImageApi::createImage (const ImageSource& source, const ClientBuffer& buffer) const
327 {
328         const EGLImageKHR image = source.createImage(m_egl, m_display, m_context, buffer.get());
329         return MovePtr<UniqueImage>(new UniqueImage(m_egl, m_display, image));
330 }
331
332 static void imageTargetTexture2D (const Library& egl, const glw::Functions& gl, GLeglImageOES img)
333 {
334         gl.eglImageTargetTexture2DOES(GL_TEXTURE_2D, img);
335         {
336                 const GLenum error = gl.getError();
337
338                 if (error == GL_INVALID_OPERATION)
339                         TCU_THROW(NotSupportedError, "Creating texture2D from EGLImage type not supported");
340
341                 GLU_EXPECT_NO_ERROR(error, "glEGLImageTargetTexture2DOES()");
342                 EGLU_CHECK_MSG(egl, "glEGLImageTargetTexture2DOES()");
343         }
344 }
345
346 static void imageTargetRenderbuffer (const Library& egl, const glw::Functions& gl, GLeglImageOES img)
347 {
348         gl.eglImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, img);
349         {
350                 const GLenum error = gl.getError();
351
352                 if (error == GL_INVALID_OPERATION)
353                         TCU_THROW(NotSupportedError, "Creating renderbuffer from EGLImage type not supported");
354
355                 GLU_EXPECT_NO_ERROR(error, "glEGLImageTargetRenderbufferStorageOES()");
356                 EGLU_CHECK_MSG(egl, "glEGLImageTargetRenderbufferStorageOES()");
357         }
358 }
359
360 static void framebufferRenderbuffer (const glw::Functions& gl, GLenum attachment, GLuint rbo)
361 {
362         GLU_CHECK_GLW_CALL(gl, framebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, rbo));
363         TCU_CHECK_AND_THROW(NotSupportedError,
364                                                 gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE,
365                                                 ("EGLImage as " + string(glu::getFramebufferAttachmentName(attachment)) + " not supported").c_str());
366 }
367
368 static const float squareTriangleCoords[] =
369 {
370         -1.0, -1.0,
371         1.0, -1.0,
372         1.0,  1.0,
373
374         1.0,  1.0,
375         -1.0,  1.0,
376         -1.0, -1.0
377 };
378
379 bool GLES2ImageApi::RenderTexture2D::invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
380 {
381         const glw::Functions&   gl              = api.m_gl;
382         tcu::TestLog&                   log             = api.getLog();
383         Texture                                 srcTex  (gl);
384
385         // Branch only taken in TryAll case
386         if (reference.getFormat().order == tcu::TextureFormat::DS || reference.getFormat().order == tcu::TextureFormat::D)
387                 throw IllegalRendererException(); // Skip, GLES2 does not support sampling depth textures
388         if (reference.getFormat().order == tcu::TextureFormat::S)
389                 throw IllegalRendererException(); // Skip, GLES2 does not support sampling stencil textures
390
391         gl.clearColor(0.0, 0.0, 0.0, 0.0);
392         gl.viewport(0, 0, reference.getWidth(), reference.getHeight());
393         gl.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
394         gl.disable(GL_DEPTH_TEST);
395
396         log << tcu::TestLog::Message << "Rendering EGLImage as GL_TEXTURE_2D in context: " << api.m_contextId << tcu::TestLog::EndMessage;
397         TCU_CHECK(**img != EGL_NO_IMAGE_KHR);
398
399         GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_2D, *srcTex));
400         imageTargetTexture2D(api.m_egl, gl, **img);
401
402         GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
403         GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
404         GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
405         GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
406
407         const char* const vertexShader =
408                 "attribute highp vec2 a_coord;\n"
409                 "varying mediump vec2 v_texCoord;\n"
410                 "void main(void) {\n"
411                 "\tv_texCoord = vec2((a_coord.x + 1.0) * 0.5, (a_coord.y + 1.0) * 0.5);\n"
412                 "\tgl_Position = vec4(a_coord, -0.1, 1.0);\n"
413                 "}\n";
414
415         const char* const fragmentShader =
416                 "varying mediump vec2 v_texCoord;\n"
417                 "uniform sampler2D u_sampler;\n"
418                 "void main(void) {\n"
419                 "\tmediump vec4 texColor = texture2D(u_sampler, v_texCoord);\n"
420                 "\tgl_FragColor = vec4(texColor);\n"
421                 "}";
422
423         Program program(gl, vertexShader, fragmentShader);
424         TCU_CHECK(program.isOk());
425
426         GLuint glProgram = program.getProgram();
427         GLU_CHECK_GLW_CALL(gl, useProgram(glProgram));
428
429         GLuint coordLoc = gl.getAttribLocation(glProgram, "a_coord");
430         TCU_CHECK_MSG((int)coordLoc != -1, "Couldn't find attribute a_coord");
431
432         GLuint samplerLoc = gl.getUniformLocation(glProgram, "u_sampler");
433         TCU_CHECK_MSG((int)samplerLoc != (int)-1, "Couldn't find uniform u_sampler");
434
435         GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_2D, *srcTex));
436         GLU_CHECK_GLW_CALL(gl, uniform1i(samplerLoc, 0));
437         GLU_CHECK_GLW_CALL(gl, enableVertexAttribArray(coordLoc));
438         GLU_CHECK_GLW_CALL(gl, vertexAttribPointer(coordLoc, 2, GL_FLOAT, GL_FALSE, 0, squareTriangleCoords));
439
440         GLU_CHECK_GLW_CALL(gl, drawArrays(GL_TRIANGLES, 0, 6));
441         GLU_CHECK_GLW_CALL(gl, disableVertexAttribArray(coordLoc));
442         GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_2D, 0));
443
444         tcu::Surface refSurface (reference.getWidth(), reference.getHeight());
445         tcu::Surface screen             (reference.getWidth(), reference.getHeight());
446         GLU_CHECK_GLW_CALL(gl, readPixels(0, 0, screen.getWidth(), screen.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen.getAccess().getDataPtr()));
447
448         tcu::copy(refSurface.getAccess(), reference.getLevel(0));
449
450         float   threshold       = 0.05f;
451         bool    match           = tcu::fuzzyCompare(log, "ComparisonResult", "Image comparison result", refSurface, screen, threshold, tcu::COMPARE_LOG_RESULT);
452
453         return match;
454 }
455
456 bool GLES2ImageApi::RenderDepthbuffer::invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
457 {
458         const glw::Functions&   gl                                      = api.m_gl;
459         tcu::TestLog&                   log                                     = api.getLog();
460         Framebuffer                             framebuffer                     (gl);
461         Renderbuffer                    renderbufferColor       (gl);
462         Renderbuffer                    renderbufferDepth       (gl);
463         const tcu::RGBA                 compareThreshold        (32, 32, 32, 32); // layer colors are far apart, large thresholds are ok
464
465         // Branch only taken in TryAll case
466         if (reference.getFormat().order != tcu::TextureFormat::DS && reference.getFormat().order != tcu::TextureFormat::D)
467                 throw IllegalRendererException(); // Skip, interpreting non-depth data as depth data is not meaningful
468
469         log << tcu::TestLog::Message << "Rendering with depth buffer" << tcu::TestLog::EndMessage;
470
471         GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, *framebuffer));
472
473         GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, *renderbufferColor));
474         GLU_CHECK_GLW_CALL(gl, renderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, reference.getWidth(), reference.getHeight()));
475         framebufferRenderbuffer(gl, GL_COLOR_ATTACHMENT0, *renderbufferColor);
476
477         GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, *renderbufferDepth));
478         imageTargetRenderbuffer(api.m_egl, gl, **img);
479         framebufferRenderbuffer(gl, GL_DEPTH_ATTACHMENT, *renderbufferDepth);
480         GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, 0));
481
482         GLU_CHECK_GLW_CALL(gl, viewport(0, 0, reference.getWidth(), reference.getHeight()));
483
484         // Render
485         const char* vertexShader =
486                 "attribute highp vec2 a_coord;\n"
487                 "uniform highp float u_depth;\n"
488                 "void main(void) {\n"
489                 "\tgl_Position = vec4(a_coord, u_depth, 1.0);\n"
490                 "}\n";
491
492         const char* fragmentShader =
493                 "uniform mediump vec4 u_color;\n"
494                 "void main(void) {\n"
495                 "\tgl_FragColor = u_color;\n"
496                 "}";
497
498         Program program(gl, vertexShader, fragmentShader);
499         TCU_CHECK(program.isOk());
500
501         GLuint glProgram = program.getProgram();
502         GLU_CHECK_GLW_CALL(gl, useProgram(glProgram));
503
504         GLuint coordLoc = gl.getAttribLocation(glProgram, "a_coord");
505         TCU_CHECK_MSG((int)coordLoc != -1, "Couldn't find attribute a_coord");
506
507         GLuint colorLoc = gl.getUniformLocation(glProgram, "u_color");
508         TCU_CHECK_MSG((int)colorLoc != (int)-1, "Couldn't find uniform u_color");
509
510         GLuint depthLoc = gl.getUniformLocation(glProgram, "u_depth");
511         TCU_CHECK_MSG((int)depthLoc != (int)-1, "Couldn't find uniform u_depth");
512
513         GLU_CHECK_GLW_CALL(gl, clearColor(0.5f, 1.0f, 0.5f, 1.0f));
514         GLU_CHECK_GLW_CALL(gl, clear(GL_COLOR_BUFFER_BIT));
515
516         tcu::Vec4 depthLevelColors[] = {
517                 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
518                 tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
519                 tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f),
520                 tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
521                 tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f),
522
523                 tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f),
524                 tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f),
525                 tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f),
526                 tcu::Vec4(0.0f, 0.5f, 0.0f, 1.0f),
527                 tcu::Vec4(0.5f, 0.5f, 0.0f, 1.0f)
528         };
529
530         GLU_CHECK_GLW_CALL(gl, enableVertexAttribArray(coordLoc));
531         GLU_CHECK_GLW_CALL(gl, vertexAttribPointer(coordLoc, 2, GL_FLOAT, GL_FALSE, 0, squareTriangleCoords));
532
533         GLU_CHECK_GLW_CALL(gl, enable(GL_DEPTH_TEST));
534         GLU_CHECK_GLW_CALL(gl, depthFunc(GL_LESS));
535         GLU_CHECK_GLW_CALL(gl, depthMask(GL_FALSE));
536
537         for (int level = 0; level < DE_LENGTH_OF_ARRAY(depthLevelColors); level++)
538         {
539                 const tcu::Vec4 color           = depthLevelColors[level];
540                 const float             clipDepth       = ((float)(level + 1) * 0.1f) * 2.0f - 1.0f; // depth in clip coords
541
542                 GLU_CHECK_GLW_CALL(gl, uniform4f(colorLoc, color.x(), color.y(), color.z(), color.w()));
543                 GLU_CHECK_GLW_CALL(gl, uniform1f(depthLoc, clipDepth));
544                 GLU_CHECK_GLW_CALL(gl, drawArrays(GL_TRIANGLES, 0, 6));
545         }
546
547         GLU_CHECK_GLW_CALL(gl, depthMask(GL_TRUE));
548         GLU_CHECK_GLW_CALL(gl, disable(GL_DEPTH_TEST));
549         GLU_CHECK_GLW_CALL(gl, disableVertexAttribArray(coordLoc));
550
551         const ConstPixelBufferAccess&   refAccess               = reference.getLevel(0);
552         tcu::Surface                                    screen                  (reference.getWidth(), reference.getHeight());
553         tcu::Surface                                    referenceScreen (reference.getWidth(), reference.getHeight());
554
555         gl.readPixels(0, 0, screen.getWidth(), screen.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen.getAccess().getDataPtr());
556
557         for (int y = 0; y < reference.getHeight(); y++)
558         {
559                 for (int x = 0; x < reference.getWidth(); x++)
560                 {
561                         tcu::Vec4 result = tcu::Vec4(0.5f, 1.0f, 0.5f, 1.0f);
562
563                         for (int level = 0; level < DE_LENGTH_OF_ARRAY(depthLevelColors); level++)
564                         {
565                                 if ((float)(level + 1) * 0.1f < refAccess.getPixDepth(x, y))
566                                         result = depthLevelColors[level];
567                         }
568
569                         referenceScreen.getAccess().setPixel(result, x, y);
570                 }
571         }
572
573         GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, 0));
574         GLU_CHECK_GLW_CALL(gl, finish());
575
576         return tcu::pixelThresholdCompare(log, "Depth buffer rendering result", "Result from rendering with depth buffer", referenceScreen, screen, compareThreshold, tcu::COMPARE_LOG_RESULT);
577 }
578
579 bool GLES2ImageApi::RenderStencilbuffer::invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
580 {
581         // Branch only taken in TryAll case
582         if (reference.getFormat().order != tcu::TextureFormat::DS && reference.getFormat().order != tcu::TextureFormat::S)
583                 throw IllegalRendererException(); // Skip, interpreting non-stencil data as stencil data is not meaningful
584
585         const glw::Functions&   gl                                      = api.m_gl;
586         tcu::TestLog&                   log                                     = api.getLog();
587         Framebuffer                             framebuffer                     (gl);
588         Renderbuffer                    renderbufferColor       (gl);
589         Renderbuffer                    renderbufferStencil (gl);
590         const tcu::RGBA                 compareThreshold        (32, 32, 32, 32); // layer colors are far apart, large thresholds are ok
591         const deUint32                  numStencilBits          = tcu::getTextureFormatBitDepth(tcu::getEffectiveDepthStencilTextureFormat(reference.getLevel(0).getFormat(), tcu::Sampler::MODE_STENCIL)).x();
592         const deUint32                  maxStencil                      = deBitMask32(0, numStencilBits);
593
594         log << tcu::TestLog::Message << "Rendering with stencil buffer" << tcu::TestLog::EndMessage;
595
596         GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, *framebuffer));
597
598         GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, *renderbufferColor));
599         GLU_CHECK_GLW_CALL(gl, renderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, reference.getWidth(), reference.getHeight()));
600         framebufferRenderbuffer(gl, GL_COLOR_ATTACHMENT0, *renderbufferColor);
601
602         GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, *renderbufferStencil));
603         imageTargetRenderbuffer(api.m_egl, gl, **img);
604         framebufferRenderbuffer(gl, GL_STENCIL_ATTACHMENT, *renderbufferStencil);
605         GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, 0));
606
607         GLU_CHECK_GLW_CALL(gl, viewport(0, 0, reference.getWidth(), reference.getHeight()));
608
609         // Render
610         const char* vertexShader =
611                 "attribute highp vec2 a_coord;\n"
612                 "void main(void) {\n"
613                 "\tgl_Position = vec4(a_coord, 0.0, 1.0);\n"
614                 "}\n";
615
616         const char* fragmentShader =
617                 "uniform mediump vec4 u_color;\n"
618                 "void main(void) {\n"
619                 "\tgl_FragColor = u_color;\n"
620                 "}";
621
622         Program program(gl, vertexShader, fragmentShader);
623         TCU_CHECK(program.isOk());
624
625         GLuint glProgram = program.getProgram();
626         GLU_CHECK_GLW_CALL(gl, useProgram(glProgram));
627
628         GLuint coordLoc = gl.getAttribLocation(glProgram, "a_coord");
629         TCU_CHECK_MSG((int)coordLoc != -1, "Couldn't find attribute a_coord");
630
631         GLuint colorLoc = gl.getUniformLocation(glProgram, "u_color");
632         TCU_CHECK_MSG((int)colorLoc != (int)-1, "Couldn't find uniform u_color");
633
634         GLU_CHECK_GLW_CALL(gl, clearColor(0.5f, 1.0f, 0.5f, 1.0f));
635         GLU_CHECK_GLW_CALL(gl, clear(GL_COLOR_BUFFER_BIT));
636
637         tcu::Vec4 stencilLevelColors[] = {
638                 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
639                 tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
640                 tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f),
641                 tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
642                 tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f),
643
644                 tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f),
645                 tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f),
646                 tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f),
647                 tcu::Vec4(0.0f, 0.5f, 0.0f, 1.0f),
648                 tcu::Vec4(0.5f, 0.5f, 0.0f, 1.0f)
649         };
650
651         GLU_CHECK_GLW_CALL(gl, enableVertexAttribArray(coordLoc));
652         GLU_CHECK_GLW_CALL(gl, vertexAttribPointer(coordLoc, 2, GL_FLOAT, GL_FALSE, 0, squareTriangleCoords));
653
654         GLU_CHECK_GLW_CALL(gl, enable(GL_STENCIL_TEST));
655         GLU_CHECK_GLW_CALL(gl, stencilOp(GL_KEEP, GL_KEEP, GL_KEEP));
656
657         for (int level = 0; level < DE_LENGTH_OF_ARRAY(stencilLevelColors); level++)
658         {
659                 const tcu::Vec4 color   = stencilLevelColors[level];
660                 const int               stencil = (int)(((float)(level + 1) * 0.1f) * (float)maxStencil);
661
662                 GLU_CHECK_GLW_CALL(gl, stencilFunc(GL_LESS, stencil, 0xFFFFFFFFu));
663                 GLU_CHECK_GLW_CALL(gl, uniform4f(colorLoc, color.x(), color.y(), color.z(), color.w()));
664                 GLU_CHECK_GLW_CALL(gl, drawArrays(GL_TRIANGLES, 0, 6));
665         }
666
667         GLU_CHECK_GLW_CALL(gl, disable(GL_STENCIL_TEST));
668         GLU_CHECK_GLW_CALL(gl, disableVertexAttribArray(coordLoc));
669
670         const ConstPixelBufferAccess&   refAccess               = reference.getLevel(0);
671         tcu::Surface                                    screen                  (reference.getWidth(), reference.getHeight());
672         tcu::Surface                                    referenceScreen (reference.getWidth(), reference.getHeight());
673
674         gl.readPixels(0, 0, screen.getWidth(), screen.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen.getAccess().getDataPtr());
675
676         for (int y = 0; y < reference.getHeight(); y++)
677         for (int x = 0; x < reference.getWidth(); x++)
678         {
679                 tcu::Vec4 result = tcu::Vec4(0.5f, 1.0f, 0.5f, 1.0f);
680
681                 for (int level = 0; level < DE_LENGTH_OF_ARRAY(stencilLevelColors); level++)
682                 {
683                         const int levelStencil = (int)(((float)(level + 1) * 0.1f) * (float)maxStencil);
684                         if (levelStencil < refAccess.getPixStencil(x, y))
685                                 result = stencilLevelColors[level];
686                 }
687
688                 referenceScreen.getAccess().setPixel(result, x, y);
689         }
690
691         GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, 0));
692         GLU_CHECK_GLW_CALL(gl, finish());
693
694         return tcu::pixelThresholdCompare(log, "StencilResult", "Result from rendering with stencil buffer", referenceScreen, screen, compareThreshold, tcu::COMPARE_LOG_RESULT);
695 }
696
697 bool GLES2ImageApi::RenderReadPixelsRenderbuffer::invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
698 {
699         const glw::Functions&   gl                              = api.m_gl;
700         const tcu::IVec4                bitDepth                = tcu::getTextureFormatMantissaBitDepth(reference.getFormat());
701         const tcu::IVec4                threshold               (2 * (tcu::IVec4(1) << (tcu::IVec4(8) - bitDepth)));
702         const tcu::RGBA                 threshold8              ((deUint8)(de::clamp(threshold[0], 0, 255)), (deUint8)(de::clamp(threshold[1], 0, 255)), (deUint8)(de::clamp(threshold[2], 0, 255)), (deUint8)(de::clamp(threshold[3], 0, 255)));
703         tcu::TestLog&                   log                             = api.getLog();
704         Framebuffer                             framebuffer             (gl);
705         Renderbuffer                    renderbuffer    (gl);
706         tcu::Surface                    screen                  (reference.getWidth(), reference.getHeight());
707         tcu::Surface                    refSurface              (reference.getWidth(), reference.getHeight());
708
709         // Branch only taken in TryAll case
710         if (reference.getFormat().order == tcu::TextureFormat::DS || reference.getFormat().order == tcu::TextureFormat::D)
711                 throw IllegalRendererException(); // Skip, GLES2 does not support ReadPixels for depth attachments
712         if (reference.getFormat().order == tcu::TextureFormat::S)
713                 throw IllegalRendererException(); // Skip, GLES2 does not support ReadPixels for stencil attachments
714
715         log << tcu::TestLog::Message << "Reading with ReadPixels from renderbuffer" << tcu::TestLog::EndMessage;
716
717         GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, *framebuffer));
718         GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, *renderbuffer));
719         imageTargetRenderbuffer(api.m_egl, gl, **img);
720         framebufferRenderbuffer(gl, GL_COLOR_ATTACHMENT0, *renderbuffer);
721
722         GLU_CHECK_GLW_CALL(gl, viewport(0, 0, reference.getWidth(), reference.getHeight()));
723
724         gl.readPixels(0, 0, screen.getWidth(), screen.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen.getAccess().getDataPtr());
725
726         GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, 0));
727         GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, 0));
728         GLU_CHECK_GLW_CALL(gl, finish());
729
730         tcu::copy(refSurface.getAccess(), reference.getLevel(0));
731
732         return tcu::pixelThresholdCompare(log, "Renderbuffer read", "Result from reading renderbuffer", refSurface, screen, threshold8, tcu::COMPARE_LOG_RESULT);
733
734 }
735
736 bool GLES2ImageApi::RenderTryAll::invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
737 {
738         bool                                                                            foundSupported                  = false;
739         tcu::TestLog&                                                           log                                             = api.getLog();
740         GLES2ImageApi::RenderTexture2D                          renderTex2D;
741         GLES2ImageApi::RenderReadPixelsRenderbuffer     renderReadPixels;
742         GLES2ImageApi::RenderDepthbuffer                        renderDepth;
743         GLES2ImageApi::RenderStencilbuffer                      renderStencil;
744         Action*                                                                         actions[]                               = { &renderTex2D, &renderReadPixels, &renderDepth, &renderStencil };
745
746         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(actions); ++ndx)
747         {
748                 try
749                 {
750                         if (!actions[ndx]->invoke(api, img, reference))
751                                 return false;
752
753                         foundSupported = true;
754                 }
755                 catch (const tcu::NotSupportedError& error)
756                 {
757                         log << tcu::TestLog::Message << error.what() << tcu::TestLog::EndMessage;
758                 }
759                 catch (const IllegalRendererException&)
760                 {
761                         // not valid renderer
762                 }
763         }
764
765         if (!foundSupported)
766                 throw tcu::NotSupportedError("Rendering not supported", "", __FILE__, __LINE__);
767
768         return true;
769 }
770
771 bool GLES2ImageApi::ModifyTexSubImage::invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
772 {
773         const glw::Functions&   gl              = api.m_gl;
774         tcu::TestLog&                   log             = api.getLog();
775         glu::Texture                    srcTex  (gl);
776         const int                               xOffset = 8;
777         const int                               yOffset = 16;
778         const int                               xSize   = de::clamp(16, 0, reference.getWidth() - xOffset);
779         const int                               ySize   = de::clamp(16, 0, reference.getHeight() - yOffset);
780         tcu::Texture2D                  src             (glu::mapGLTransferFormat(m_format, m_type), xSize, ySize);
781
782         log << tcu::TestLog::Message << "Modifying EGLImage with gl.texSubImage2D" << tcu::TestLog::EndMessage;
783
784         src.allocLevel(0);
785         tcu::fillWithComponentGradients(src.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
786
787         GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_2D, *srcTex));
788         imageTargetTexture2D(api.m_egl, gl, **img);
789         GLU_CHECK_GLW_CALL(gl, texSubImage2D(GL_TEXTURE_2D, 0, xOffset, yOffset, src.getWidth(), src.getHeight(), m_format, m_type, src.getLevel(0).getDataPtr()));
790         GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_2D, 0));
791         GLU_CHECK_GLW_CALL(gl, finish());
792
793         tcu::copy(tcu::getSubregion(reference.getLevel(0), xOffset, yOffset, 0, xSize, ySize, 1), src.getLevel(0));
794
795         return true;
796 }
797
798 bool GLES2ImageApi::ModifyRenderbuffer::invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
799 {
800         const glw::Functions&   gl                              = api.m_gl;
801         tcu::TestLog&                   log                             = api.getLog();
802         glu::Framebuffer                framebuffer             (gl);
803         glu::Renderbuffer               renderbuffer    (gl);
804
805         log << tcu::TestLog::Message << "Modifying EGLImage with glClear to renderbuffer" << tcu::TestLog::EndMessage;
806
807         GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, *framebuffer));
808         GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, *renderbuffer));
809
810         imageTargetRenderbuffer(api.m_egl, gl, **img);
811
812         initializeRbo(api, *renderbuffer, reference);
813
814         GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, 0));
815         GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, 0));
816
817         GLU_CHECK_GLW_CALL(gl, finish());
818
819         return true;
820 }
821
822 void GLES2ImageApi::ModifyRenderbufferClearColor::initializeRbo (GLES2ImageApi& api, GLuint renderbuffer, tcu::Texture2D& reference) const
823 {
824         const glw::Functions&   gl              = api.m_gl;
825
826         framebufferRenderbuffer(gl, GL_COLOR_ATTACHMENT0, renderbuffer);
827
828         GLU_CHECK_GLW_CALL(gl, viewport(0, 0, reference.getWidth(), reference.getHeight()));
829         GLU_CHECK_GLW_CALL(gl, clearColor(m_color.x(), m_color.y(), m_color.z(), m_color.w()));
830         GLU_CHECK_GLW_CALL(gl, clear(GL_COLOR_BUFFER_BIT));
831
832         tcu::clear(reference.getLevel(0), m_color);
833 }
834
835 void GLES2ImageApi::ModifyRenderbufferClearDepth::initializeRbo (GLES2ImageApi& api, GLuint renderbuffer, tcu::Texture2D& reference) const
836 {
837         const glw::Functions&   gl              = api.m_gl;
838
839         framebufferRenderbuffer(gl, GL_DEPTH_ATTACHMENT, renderbuffer);
840
841         GLU_CHECK_GLW_CALL(gl, viewport(0, 0, reference.getWidth(), reference.getHeight()));
842         GLU_CHECK_GLW_CALL(gl, clearDepthf(m_depth));
843         GLU_CHECK_GLW_CALL(gl, clear(GL_DEPTH_BUFFER_BIT));
844
845         tcu::clearDepth(reference.getLevel(0), m_depth);
846 }
847
848 void GLES2ImageApi::ModifyRenderbufferClearStencil::initializeRbo (GLES2ImageApi& api, GLuint renderbuffer, tcu::Texture2D& reference) const
849 {
850         const glw::Functions&   gl              = api.m_gl;
851
852         framebufferRenderbuffer(gl, GL_STENCIL_ATTACHMENT, renderbuffer);
853
854         GLU_CHECK_GLW_CALL(gl, viewport(0, 0, reference.getWidth(), reference.getHeight()));
855         GLU_CHECK_GLW_CALL(gl, clearStencil(m_stencil));
856         GLU_CHECK_GLW_CALL(gl, clear(GL_STENCIL_BUFFER_BIT));
857
858         tcu::clearStencil(reference.getLevel(0), m_stencil);
859 }
860
861 class ImageFormatCase : public TestCase, private glu::CallLogWrapper
862 {
863 public:
864                                                 ImageFormatCase         (EglTestContext& eglTestCtx, const TestSpec& spec);
865                                                 ~ImageFormatCase        (void);
866
867         void                            init                            (void);
868         void                            deinit                          (void);
869         IterateResult           iterate                         (void);
870         void                            checkExtensions         (void);
871
872 private:
873         EGLConfig                       getConfig                       (void);
874
875         const TestSpec          m_spec;
876
877         vector<ImageApi*>       m_apiContexts;
878
879         EGLDisplay                      m_display;
880         eglu::NativeWindow*     m_window;
881         EGLSurface                      m_surface;
882         EGLConfig                       m_config;
883         int                                     m_curIter;
884         MovePtr<UniqueImage>m_img;
885         tcu::Texture2D          m_refImg;
886         glw::Functions          m_gl;
887 };
888
889 EGLConfig ImageFormatCase::getConfig (void)
890 {
891         const EGLint attribList[] =
892         {
893                 EGL_RENDERABLE_TYPE,    EGL_OPENGL_ES2_BIT,
894                 EGL_SURFACE_TYPE,               EGL_WINDOW_BIT,
895                 EGL_RED_SIZE,                   8,
896                 EGL_BLUE_SIZE,                  8,
897                 EGL_GREEN_SIZE,                 8,
898                 EGL_ALPHA_SIZE,                 8,
899                 EGL_DEPTH_SIZE,                 8,
900                 EGL_NONE
901         };
902
903         return eglu::chooseSingleConfig(m_eglTestCtx.getLibrary(), m_display, attribList);
904 }
905
906 ImageFormatCase::ImageFormatCase (EglTestContext& eglTestCtx, const TestSpec& spec)
907         : TestCase                              (eglTestCtx, spec.name.c_str(), spec.desc.c_str())
908         , glu::CallLogWrapper   (m_gl, eglTestCtx.getTestContext().getLog())
909         , m_spec                                (spec)
910         , m_display                             (EGL_NO_DISPLAY)
911         , m_window                              (DE_NULL)
912         , m_surface                             (EGL_NO_SURFACE)
913         , m_config                              (0)
914         , m_curIter                             (0)
915         , m_refImg                              (tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 1, 1)
916 {
917 }
918
919 ImageFormatCase::~ImageFormatCase (void)
920 {
921         deinit();
922 }
923
924 void ImageFormatCase::checkExtensions (void)
925 {
926         const Library&                  egl             = m_eglTestCtx.getLibrary();
927         const EGLDisplay                dpy             = m_display;
928         set<string>                             exts;
929         const vector<string>    glExts  = de::splitString((const char*) m_gl.getString(GL_EXTENSIONS));
930         const vector<string>    eglExts = eglu::getDisplayExtensions(egl, dpy);
931
932         exts.insert(glExts.begin(), glExts.end());
933         exts.insert(eglExts.begin(), eglExts.end());
934
935         if (eglu::getVersion(egl, dpy) >= eglu::Version(1, 5))
936         {
937                 // EGL 1.5 has built-in support for EGLImage and GL sources
938                 exts.insert("EGL_KHR_image_base");
939                 exts.insert("EGL_KHR_gl_texture_2D_image");
940                 exts.insert("EGL_KHR_gl_texture_cubemap_image");
941                 exts.insert("EGL_KHR_gl_renderbuffer_image");
942         }
943
944         if (!de::contains(exts, "EGL_KHR_image_base") && !de::contains(exts, "EGL_KHR_image"))
945         {
946                 getLog() << tcu::TestLog::Message
947                                  << "EGL version is under 1.5 and neither EGL_KHR_image nor EGL_KHR_image_base is supported."
948                                  << "One should be supported."
949                                  << tcu::TestLog::EndMessage;
950                 TCU_THROW(NotSupportedError, "Extension not supported: EGL_KHR_image_base");
951         }
952
953         for (int operationNdx = 0; operationNdx < (int)m_spec.operations.size(); operationNdx++)
954         {
955                 const TestSpec::Operation&      op      = m_spec.operations[operationNdx];
956                 const string                            ext     = op.action->getRequiredExtension();
957
958                 if (!de::contains(exts, ext))
959                         TCU_THROW_EXPR(NotSupportedError, "Extension not supported", ext.c_str());
960         }
961 }
962
963 void ImageFormatCase::init (void)
964 {
965         const Library&                                          egl                             = m_eglTestCtx.getLibrary();
966         const eglu::NativeWindowFactory&        windowFactory   = eglu::selectNativeWindowFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());
967
968         try
969         {
970                 m_display       = eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay());
971                 m_config        = getConfig();
972                 m_window        = windowFactory.createWindow(&m_eglTestCtx.getNativeDisplay(), m_display, m_config, DE_NULL, eglu::WindowParams(480, 480, eglu::parseWindowVisibility(m_testCtx.getCommandLine())));
973                 m_surface       = eglu::createWindowSurface(m_eglTestCtx.getNativeDisplay(), *m_window, m_display, m_config, DE_NULL);
974
975                 {
976                         const char* extensions[] = { "GL_OES_EGL_image" };
977                         m_eglTestCtx.initGLFunctions(&m_gl, glu::ApiType::es(2, 0), DE_LENGTH_OF_ARRAY(extensions), &extensions[0]);
978                 }
979
980                 for (int contextNdx = 0; contextNdx < (int)m_spec.contexts.size(); contextNdx++)
981                 {
982                         ImageApi* api = DE_NULL;
983                         switch (m_spec.contexts[contextNdx])
984                         {
985                                 case TestSpec::API_GLES2:
986                                 {
987                                         api = new GLES2ImageApi(egl, m_gl, contextNdx, getLog(), m_display, m_surface, m_config);
988                                         break;
989                                 }
990
991                                 default:
992                                         DE_ASSERT(false);
993                                         break;
994                         }
995                         m_apiContexts.push_back(api);
996                 }
997                 checkExtensions();
998         }
999         catch (...)
1000         {
1001                 deinit();
1002                 throw;
1003         }
1004 }
1005
1006 void ImageFormatCase::deinit (void)
1007 {
1008         const Library& egl = m_eglTestCtx.getLibrary();
1009
1010         for (int contexNdx = 0 ; contexNdx < (int)m_apiContexts.size(); contexNdx++)
1011                 delete m_apiContexts[contexNdx];
1012
1013         m_apiContexts.clear();
1014
1015         if (m_surface != EGL_NO_SURFACE)
1016         {
1017                 egl.destroySurface(m_display, m_surface);
1018                 m_surface = EGL_NO_SURFACE;
1019         }
1020
1021         delete m_window;
1022         m_window = DE_NULL;
1023
1024         if (m_display != EGL_NO_DISPLAY)
1025         {
1026                 egl.terminate(m_display);
1027                 m_display = EGL_NO_DISPLAY;
1028         }
1029 }
1030
1031 TestCase::IterateResult ImageFormatCase::iterate (void)
1032 {
1033         const TestSpec::Operation&      op              = m_spec.operations[m_curIter++];
1034         ImageApi&                                       api             = *m_apiContexts[op.apiIndex];
1035         const bool                                      isOk    = op.action->invoke(api, m_img, m_refImg);
1036
1037         if (isOk && m_curIter < (int)m_spec.operations.size())
1038                 return CONTINUE;
1039         else if (isOk)
1040                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1041         else
1042                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1043
1044         return STOP;
1045 }
1046
1047 struct LabeledAction
1048 {
1049         string                  label;
1050         MovePtr<Action> action;
1051 };
1052
1053 // A simple vector mockup that we need because MovePtr isn't copy-constructible.
1054 struct LabeledActions
1055 {
1056                                         LabeledActions  (void) : m_numActions(0){}
1057         LabeledAction&  operator[]              (int ndx)                               { DE_ASSERT(0 <= ndx && ndx < m_numActions); return m_actions[ndx]; }
1058         void                    add                             (const string& label, MovePtr<Action> action);
1059         int                             size                    (void) const                    { return m_numActions; }
1060 private:
1061         LabeledAction   m_actions[32];
1062         int                             m_numActions;
1063 };
1064
1065 void LabeledActions::add (const string& label, MovePtr<Action> action)
1066 {
1067         DE_ASSERT(m_numActions < DE_LENGTH_OF_ARRAY(m_actions));
1068         m_actions[m_numActions].label = label;
1069         m_actions[m_numActions].action = action;
1070         ++m_numActions;
1071 }
1072
1073 class ImageTests : public TestCaseGroup
1074 {
1075 protected:
1076                                         ImageTests                                              (EglTestContext& eglTestCtx, const string& name, const string& desc)
1077                                                 : TestCaseGroup(eglTestCtx, name.c_str(), desc.c_str()) {}
1078
1079         void                    addCreateTexture                                (const string& name, EGLenum source, GLenum internalFormat, GLenum format, GLenum type);
1080         void                    addCreateRenderbuffer                   (const string& name, GLenum format);
1081         void                    addCreateAndroidNative                  (const string& name, GLenum format);
1082         void                    addCreateTexture2DActions               (const string& prefix);
1083         void                    addCreateTextureCubemapActions  (const string& suffix, GLenum internalFormat, GLenum format, GLenum type);
1084         void                    addCreateRenderbufferActions    (void);
1085         void                    addCreateAndroidNativeActions   (void);
1086
1087         LabeledActions  m_createActions;
1088 };
1089
1090 void ImageTests::addCreateTexture (const string& name, EGLenum source, GLenum internalFormat, GLenum format, GLenum type)
1091 {
1092         m_createActions.add(name, MovePtr<Action>(new GLES2ImageApi::Create(createTextureImageSource(source, internalFormat, format, type))));
1093 }
1094
1095 void ImageTests::addCreateRenderbuffer (const string& name, GLenum format)
1096 {
1097         m_createActions.add(name, MovePtr<Action>(new GLES2ImageApi::Create(createRenderbufferImageSource(format))));
1098 }
1099
1100 void ImageTests::addCreateAndroidNative (const string& name, GLenum format)
1101 {
1102         m_createActions.add(name, MovePtr<Action>(new GLES2ImageApi::Create(createAndroidNativeImageSource(format))));
1103 }
1104
1105 void ImageTests::addCreateTexture2DActions (const string& prefix)
1106 {
1107         addCreateTexture(prefix + "rgb8",               EGL_GL_TEXTURE_2D_KHR,  GL_RGB,         GL_RGB,         GL_UNSIGNED_BYTE);
1108         addCreateTexture(prefix + "rgb565",             EGL_GL_TEXTURE_2D_KHR,  GL_RGB,         GL_RGB,         GL_UNSIGNED_SHORT_5_6_5);
1109         addCreateTexture(prefix + "rgba8",              EGL_GL_TEXTURE_2D_KHR,  GL_RGBA,        GL_RGBA,        GL_UNSIGNED_BYTE);
1110         addCreateTexture(prefix + "rgb5_a1",    EGL_GL_TEXTURE_2D_KHR,  GL_RGBA,        GL_RGBA,        GL_UNSIGNED_SHORT_5_5_5_1);
1111         addCreateTexture(prefix + "rgba4",              EGL_GL_TEXTURE_2D_KHR,  GL_RGBA,        GL_RGBA,        GL_UNSIGNED_SHORT_4_4_4_4);
1112 }
1113
1114 void ImageTests::addCreateTextureCubemapActions (const string& suffix, GLenum internalFormat, GLenum format, GLenum type)
1115 {
1116         addCreateTexture("cubemap_positive_x" + suffix, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR, internalFormat, format, type);
1117         addCreateTexture("cubemap_positive_y" + suffix, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR, internalFormat, format, type);
1118         addCreateTexture("cubemap_positive_z" + suffix, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR, internalFormat, format, type);
1119         addCreateTexture("cubemap_negative_x" + suffix, EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR, internalFormat, format, type);
1120         addCreateTexture("cubemap_negative_y" + suffix, EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR, internalFormat, format, type);
1121         addCreateTexture("cubemap_negative_z" + suffix, EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR, internalFormat, format, type);
1122 }
1123
1124 void ImageTests::addCreateRenderbufferActions (void)
1125 {
1126         addCreateRenderbuffer("renderbuffer_rgba4",             GL_RGBA4);
1127         addCreateRenderbuffer("renderbuffer_rgb5_a1",   GL_RGB5_A1);
1128         addCreateRenderbuffer("renderbuffer_rgb565",    GL_RGB565);
1129         addCreateRenderbuffer("renderbuffer_depth16",   GL_DEPTH_COMPONENT16);
1130         addCreateRenderbuffer("renderbuffer_stencil",   GL_STENCIL_INDEX8);
1131 }
1132
1133 void ImageTests::addCreateAndroidNativeActions (void)
1134 {
1135         addCreateAndroidNative("android_native_rgb565",         GL_RGB565);
1136         addCreateAndroidNative("android_native_rgb8",           GL_RGB8);
1137         addCreateAndroidNative("android_native_rgba4",          GL_RGBA4);
1138         addCreateAndroidNative("android_native_rgb5_a1",        GL_RGB5_A1);
1139         addCreateAndroidNative("android_native_rgba8",          GL_RGBA8);
1140 }
1141
1142 class RenderTests : public ImageTests
1143 {
1144 protected:
1145                                                                                         RenderTests                             (EglTestContext& eglTestCtx, const string& name, const string& desc)
1146                                                                                                 : ImageTests                    (eglTestCtx, name, desc) {}
1147
1148         void                                                                    addRenderActions                (void);
1149         LabeledActions                                                  m_renderActions;
1150 };
1151
1152 void RenderTests::addRenderActions (void)
1153 {
1154         m_renderActions.add("texture",                  MovePtr<Action>(new GLES2ImageApi::RenderTexture2D()));
1155         m_renderActions.add("read_pixels",              MovePtr<Action>(new GLES2ImageApi::RenderReadPixelsRenderbuffer()));
1156         m_renderActions.add("depth_buffer",             MovePtr<Action>(new GLES2ImageApi::RenderDepthbuffer()));
1157         m_renderActions.add("stencil_buffer",   MovePtr<Action>(new GLES2ImageApi::RenderStencilbuffer()));
1158 }
1159
1160 class SimpleCreationTests : public RenderTests
1161 {
1162 public:
1163                         SimpleCreationTests             (EglTestContext& eglTestCtx, const string& name, const string& desc) : RenderTests(eglTestCtx, name, desc) {}
1164         void    init                                    (void);
1165 };
1166
1167 bool isDepthFormat (GLenum format)
1168 {
1169         switch (format)
1170         {
1171                 case GL_RGB:
1172                 case GL_RGB8:
1173                 case GL_RGB565:
1174                 case GL_RGBA:
1175                 case GL_RGBA4:
1176                 case GL_RGBA8:
1177                 case GL_RGB5_A1:
1178                         return false;
1179
1180                 case GL_DEPTH_COMPONENT16:
1181                         return true;
1182
1183                 case GL_STENCIL_INDEX8:
1184                         return false;
1185
1186                 default:
1187                         DE_ASSERT(false);
1188                         return false;
1189         }
1190 }
1191
1192 bool isStencilFormat (GLenum format)
1193 {
1194         switch (format)
1195         {
1196                 case GL_RGB:
1197                 case GL_RGB8:
1198                 case GL_RGB565:
1199                 case GL_RGBA:
1200                 case GL_RGBA4:
1201                 case GL_RGBA8:
1202                 case GL_RGB5_A1:
1203                         return false;
1204
1205                 case GL_DEPTH_COMPONENT16:
1206                         return false;
1207
1208                 case GL_STENCIL_INDEX8:
1209                         return true;
1210
1211                 default:
1212                         DE_ASSERT(false);
1213                         return false;
1214         }
1215 }
1216
1217 bool isCompatibleCreateAndRenderActions (const Action& create, const Action& render)
1218 {
1219         if (const GLES2ImageApi::Create* gles2Create = dynamic_cast<const GLES2ImageApi::Create*>(&create))
1220         {
1221                 const GLenum createFormat = gles2Create->getEffectiveFormat();
1222
1223                 if (dynamic_cast<const GLES2ImageApi::RenderTexture2D*>(&render))
1224                 {
1225                         // GLES2 does not have depth or stencil textures
1226                         if (isDepthFormat(createFormat) || isStencilFormat(createFormat))
1227                                 return false;
1228                 }
1229
1230                 if (dynamic_cast<const GLES2ImageApi::RenderReadPixelsRenderbuffer*>(&render))
1231                 {
1232                         // GLES2 does not support readPixels for depth or stencil
1233                         if (isDepthFormat(createFormat) || isStencilFormat(createFormat))
1234                                 return false;
1235                 }
1236
1237                 if (dynamic_cast<const GLES2ImageApi::RenderDepthbuffer*>(&render))
1238                 {
1239                         // Copying non-depth data to depth renderbuffer and expecting meaningful
1240                         // results just doesn't make any sense.
1241                         if (!isDepthFormat(createFormat))
1242                                 return false;
1243                 }
1244
1245                 if (dynamic_cast<const GLES2ImageApi::RenderStencilbuffer*>(&render))
1246                 {
1247                         // Copying non-stencil data to stencil renderbuffer and expecting meaningful
1248                         // results just doesn't make any sense.
1249                         if (!isStencilFormat(createFormat))
1250                                 return false;
1251                 }
1252
1253                 return true;
1254         }
1255         else
1256                 DE_ASSERT(false);
1257
1258         return false;
1259 }
1260
1261 void SimpleCreationTests::init (void)
1262 {
1263         addCreateTexture2DActions("texture_");
1264         addCreateTextureCubemapActions("_rgba", GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
1265         addCreateTextureCubemapActions("_rgb", GL_RGB, GL_RGB, GL_UNSIGNED_BYTE);
1266         addCreateRenderbufferActions();
1267         addCreateAndroidNativeActions();
1268         addRenderActions();
1269
1270         for (int createNdx = 0; createNdx < m_createActions.size(); createNdx++)
1271         {
1272                 const LabeledAction& createAction = m_createActions[createNdx];
1273
1274                 for (int renderNdx = 0; renderNdx < m_renderActions.size(); renderNdx++)
1275                 {
1276                         const LabeledAction&    renderAction    = m_renderActions[renderNdx];
1277                         TestSpec                                spec;
1278
1279                         if (!isCompatibleCreateAndRenderActions(*createAction.action, *renderAction.action))
1280                                 continue;
1281
1282                         spec.name = std::string("gles2_") + createAction.label + "_" + renderAction.label;
1283                         spec.desc = spec.name;
1284                         spec.contexts.push_back(TestSpec::API_GLES2);
1285                         spec.operations.push_back(TestSpec::Operation(0, *createAction.action));
1286                         spec.operations.push_back(TestSpec::Operation(0, *renderAction.action));
1287
1288                         addChild(new ImageFormatCase(m_eglTestCtx, spec));
1289                 }
1290         }
1291 }
1292
1293 TestCaseGroup* createSimpleCreationTests (EglTestContext& eglTestCtx, const string& name, const string& desc)
1294 {
1295         return new SimpleCreationTests(eglTestCtx, name, desc);
1296 }
1297
1298 bool isCompatibleFormats (GLenum createFormat, GLenum modifyFormat, GLenum modifyType)
1299 {
1300         switch (modifyFormat)
1301         {
1302                 case GL_RGB:
1303                         switch (modifyType)
1304                         {
1305                                 case GL_UNSIGNED_BYTE:
1306                                         return createFormat == GL_RGB
1307                                                         || createFormat == GL_RGB8
1308                                                         || createFormat == GL_RGB565
1309                                                         || createFormat == GL_SRGB8;
1310
1311                                 case GL_BYTE:
1312                                         return createFormat == GL_RGB8_SNORM;
1313
1314                                 case GL_UNSIGNED_SHORT_5_6_5:
1315                                         return createFormat == GL_RGB
1316                                                         || createFormat == GL_RGB565;
1317
1318                                 case GL_UNSIGNED_INT_10F_11F_11F_REV:
1319                                         return createFormat == GL_R11F_G11F_B10F;
1320
1321                                 case GL_UNSIGNED_INT_5_9_9_9_REV:
1322                                         return createFormat == GL_RGB9_E5;
1323
1324                                 case GL_HALF_FLOAT:
1325                                         return createFormat == GL_RGB16F
1326                                                         || createFormat == GL_R11F_G11F_B10F
1327                                                         || createFormat == GL_RGB9_E5;
1328
1329                                 case GL_FLOAT:
1330                                         return createFormat == GL_RGB16F
1331                                                         || createFormat == GL_RGB32F
1332                                                         || createFormat == GL_R11F_G11F_B10F
1333                                                         || createFormat == GL_RGB9_E5;
1334
1335                                 default:
1336                                         DE_FATAL("Unknown modify type");
1337                                         return false;
1338                         }
1339
1340                 case GL_RGBA:
1341                         switch (modifyType)
1342                         {
1343                                 case GL_UNSIGNED_BYTE:
1344                                         return createFormat == GL_RGBA8
1345                                                 || createFormat == GL_RGB5_A1
1346                                                 || createFormat == GL_RGBA4
1347                                                 || createFormat == GL_SRGB8_ALPHA8
1348                                                 || createFormat == GL_RGBA;
1349
1350                                 case GL_UNSIGNED_SHORT_4_4_4_4:
1351                                         return createFormat == GL_RGBA4
1352                                                 || createFormat == GL_RGBA;
1353
1354                                 case GL_UNSIGNED_SHORT_5_5_5_1:
1355                                         return createFormat == GL_RGB5_A1
1356                                                 || createFormat == GL_RGBA;
1357
1358                                 case GL_UNSIGNED_INT_2_10_10_10_REV:
1359                                         return createFormat == GL_RGB10_A2
1360                                                 || createFormat == GL_RGB5_A1;
1361
1362                                 case GL_HALF_FLOAT:
1363                                         return createFormat == GL_RGBA16F;
1364
1365                                 case GL_FLOAT:
1366                                         return createFormat == GL_RGBA16F
1367                                                 || createFormat == GL_RGBA32F;
1368
1369                                 default:
1370                                         DE_FATAL("Unknown modify type");
1371                                         return false;
1372                         };
1373
1374                 default:
1375                         DE_FATAL("Unknown modify format");
1376                         return false;
1377         }
1378 }
1379
1380 bool isCompatibleCreateAndModifyActions (const Action& create, const Action& modify)
1381 {
1382         if (const GLES2ImageApi::Create* gles2Create = dynamic_cast<const GLES2ImageApi::Create*>(&create))
1383         {
1384                 const GLenum createFormat = gles2Create->getEffectiveFormat();
1385
1386                 if (const GLES2ImageApi::ModifyTexSubImage* gles2TexSubImageModify = dynamic_cast<const GLES2ImageApi::ModifyTexSubImage*>(&modify))
1387                 {
1388                         const GLenum modifyFormat       = gles2TexSubImageModify->getFormat();
1389                         const GLenum modifyType         = gles2TexSubImageModify->getType();
1390
1391                         return isCompatibleFormats(createFormat, modifyFormat, modifyType);
1392                 }
1393
1394                 if (dynamic_cast<const GLES2ImageApi::ModifyRenderbufferClearColor*>(&modify))
1395                 {
1396                         // reintepreting color as non-color is not meaningful
1397                         if (isDepthFormat(createFormat) || isStencilFormat(createFormat))
1398                                 return false;
1399                 }
1400
1401                 if (dynamic_cast<const GLES2ImageApi::ModifyRenderbufferClearDepth*>(&modify))
1402                 {
1403                         // reintepreting depth as non-depth is not meaningful
1404                         if (!isDepthFormat(createFormat))
1405                                 return false;
1406                 }
1407
1408                 if (dynamic_cast<const GLES2ImageApi::ModifyRenderbufferClearStencil*>(&modify))
1409                 {
1410                         // reintepreting stencil as non-stencil is not meaningful
1411                         if (!isStencilFormat(createFormat))
1412                                 return false;
1413                 }
1414
1415                 return true;
1416         }
1417         else
1418                 DE_ASSERT(false);
1419
1420         return false;
1421 }
1422
1423 class MultiContextRenderTests : public RenderTests
1424 {
1425 public:
1426                                         MultiContextRenderTests         (EglTestContext& eglTestCtx, const string& name, const string& desc);
1427         void                    init                                            (void);
1428         void                    addClearActions                         (void);
1429 private:
1430         LabeledActions  m_clearActions;
1431 };
1432
1433 MultiContextRenderTests::MultiContextRenderTests (EglTestContext& eglTestCtx, const string& name, const string& desc)
1434         : RenderTests   (eglTestCtx, name, desc)
1435 {
1436 }
1437
1438 void MultiContextRenderTests::addClearActions (void)
1439 {
1440         m_clearActions.add("renderbuffer_clear_color",          MovePtr<Action>(new GLES2ImageApi::ModifyRenderbufferClearColor(tcu::Vec4(0.8f, 0.2f, 0.9f, 1.0f))));
1441         m_clearActions.add("renderbuffer_clear_depth",          MovePtr<Action>(new GLES2ImageApi::ModifyRenderbufferClearDepth(0.75f)));
1442         m_clearActions.add("renderbuffer_clear_stencil",        MovePtr<Action>(new GLES2ImageApi::ModifyRenderbufferClearStencil(97)));
1443 }
1444
1445 void MultiContextRenderTests::init (void)
1446 {
1447         addCreateTexture2DActions("texture_");
1448         addCreateTextureCubemapActions("_rgba8", GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
1449         addCreateTextureCubemapActions("_rgb8", GL_RGB, GL_RGB, GL_UNSIGNED_BYTE);
1450         addCreateRenderbufferActions();
1451         addCreateAndroidNativeActions();
1452         addRenderActions();
1453         addClearActions();
1454
1455         for (int createNdx = 0; createNdx < m_createActions.size(); createNdx++)
1456         for (int renderNdx = 0; renderNdx < m_renderActions.size(); renderNdx++)
1457         for (int clearNdx = 0; clearNdx < m_clearActions.size(); clearNdx++)
1458         {
1459                 const LabeledAction&    createAction    = m_createActions[createNdx];
1460                 const LabeledAction&    renderAction    = m_renderActions[renderNdx];
1461                 const LabeledAction&    clearAction             = m_clearActions[clearNdx];
1462                 TestSpec                                spec;
1463
1464                 if (!isCompatibleCreateAndRenderActions(*createAction.action, *renderAction.action))
1465                         continue;
1466                 if (!isCompatibleCreateAndModifyActions(*createAction.action, *clearAction.action))
1467                         continue;
1468
1469                 spec.name = std::string("gles2_") + createAction.label + "_" + renderAction.label;
1470                 spec.desc = spec.name;
1471
1472                 spec.contexts.push_back(TestSpec::API_GLES2);
1473                 spec.contexts.push_back(TestSpec::API_GLES2);
1474
1475                 spec.operations.push_back(TestSpec::Operation(0, *createAction.action));
1476                 spec.operations.push_back(TestSpec::Operation(0, *renderAction.action));
1477                 spec.operations.push_back(TestSpec::Operation(0, *clearAction.action));
1478                 spec.operations.push_back(TestSpec::Operation(1, *createAction.action));
1479                 spec.operations.push_back(TestSpec::Operation(0, *renderAction.action));
1480                 spec.operations.push_back(TestSpec::Operation(1, *renderAction.action));
1481
1482                 addChild(new ImageFormatCase(m_eglTestCtx, spec));
1483         }
1484 }
1485
1486 TestCaseGroup* createMultiContextRenderTests (EglTestContext& eglTestCtx, const string& name, const string& desc)
1487 {
1488         return new MultiContextRenderTests(eglTestCtx, name, desc);
1489 }
1490
1491 class ModifyTests : public ImageTests
1492 {
1493 public:
1494                                                                 ModifyTests             (EglTestContext& eglTestCtx, const string& name, const string& desc)
1495                                                                         : ImageTests(eglTestCtx, name, desc) {}
1496
1497         void                                            init                    (void);
1498
1499 protected:
1500         void                                            addModifyActions(void);
1501
1502         LabeledActions                          m_modifyActions;
1503         GLES2ImageApi::RenderTryAll     m_renderAction;
1504 };
1505
1506 void ModifyTests::addModifyActions (void)
1507 {
1508         m_modifyActions.add("tex_subimage_rgb8",                        MovePtr<Action>(new GLES2ImageApi::ModifyTexSubImage(GL_RGB,    GL_UNSIGNED_BYTE)));
1509         m_modifyActions.add("tex_subimage_rgb565",                      MovePtr<Action>(new GLES2ImageApi::ModifyTexSubImage(GL_RGB,    GL_UNSIGNED_SHORT_5_6_5)));
1510         m_modifyActions.add("tex_subimage_rgba8",                       MovePtr<Action>(new GLES2ImageApi::ModifyTexSubImage(GL_RGBA,   GL_UNSIGNED_BYTE)));
1511         m_modifyActions.add("tex_subimage_rgb5_a1",                     MovePtr<Action>(new GLES2ImageApi::ModifyTexSubImage(GL_RGBA,   GL_UNSIGNED_SHORT_5_5_5_1)));
1512         m_modifyActions.add("tex_subimage_rgba4",                       MovePtr<Action>(new GLES2ImageApi::ModifyTexSubImage(GL_RGBA,   GL_UNSIGNED_SHORT_4_4_4_4)));
1513
1514         m_modifyActions.add("renderbuffer_clear_color",         MovePtr<Action>(new GLES2ImageApi::ModifyRenderbufferClearColor(tcu::Vec4(0.3f, 0.5f, 0.3f, 1.0f))));
1515         m_modifyActions.add("renderbuffer_clear_depth",         MovePtr<Action>(new GLES2ImageApi::ModifyRenderbufferClearDepth(0.7f)));
1516         m_modifyActions.add("renderbuffer_clear_stencil",       MovePtr<Action>(new GLES2ImageApi::ModifyRenderbufferClearStencil(78)));
1517 }
1518
1519 void ModifyTests::init (void)
1520 {
1521         addCreateTexture2DActions("tex_");
1522         addCreateRenderbufferActions();
1523         addCreateAndroidNativeActions();
1524         addModifyActions();
1525
1526         for (int createNdx = 0; createNdx < m_createActions.size(); createNdx++)
1527         {
1528                 LabeledAction& createAction = m_createActions[createNdx];
1529
1530                 for (int modifyNdx = 0; modifyNdx < m_modifyActions.size(); modifyNdx++)
1531                 {
1532                         LabeledAction& modifyAction = m_modifyActions[modifyNdx];
1533
1534                         if (!isCompatibleCreateAndModifyActions(*createAction.action, *modifyAction.action))
1535                                 continue;
1536
1537                         TestSpec spec;
1538                         spec.name = createAction.label + "_" + modifyAction.label;
1539                         spec.desc = "gles2_tex_sub_image";
1540
1541                         spec.contexts.push_back(TestSpec::API_GLES2);
1542
1543                         spec.operations.push_back(TestSpec::Operation(0, *createAction.action));
1544                         spec.operations.push_back(TestSpec::Operation(0, m_renderAction));
1545                         spec.operations.push_back(TestSpec::Operation(0, *modifyAction.action));
1546                         spec.operations.push_back(TestSpec::Operation(0, m_renderAction));
1547
1548                         addChild(new ImageFormatCase(m_eglTestCtx, spec));
1549                 }
1550         }
1551 }
1552
1553 TestCaseGroup* createModifyTests (EglTestContext& eglTestCtx, const string& name, const string& desc)
1554 {
1555         return new ModifyTests(eglTestCtx, name, desc);
1556 }
1557
1558 } // Image
1559 } // egl
1560 } // deqp