Merge vk-gl-cts/vulkan-cts-1.3.4 into vk-gl-cts/vulkan-cts-1.3.5
[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_GLES3,
134                 //API_VG
135                 //API_GLES1
136
137                 API_LAST
138         };
139
140         struct Operation
141         {
142                 Operation (int apiIndex_, const Action& action_) : apiIndex(apiIndex_), action(&action_) {}
143                 int                             apiIndex;
144                 const Action*   action;
145         };
146
147         vector<ApiContext>      contexts;
148         vector<Operation>       operations;
149
150 };
151
152 class ImageApi
153 {
154 public:
155                                         ImageApi                (const Library& egl, int contextId, EGLDisplay display, EGLSurface surface);
156         virtual                 ~ImageApi               (void) {}
157
158 protected:
159         const Library&  m_egl;
160         int                             m_contextId;
161         EGLDisplay              m_display;
162         EGLSurface              m_surface;
163 };
164
165 ImageApi::ImageApi (const Library& egl, int contextId, EGLDisplay display, EGLSurface surface)
166         : m_egl                         (egl)
167         , m_contextId           (contextId)
168         , m_display                     (display)
169         , m_surface                     (surface)
170 {
171 }
172
173 class GLESImageApi : public ImageApi, private glu::CallLogWrapper
174 {
175 public:
176         class GLESAction : public Action
177         {
178         public:
179                 bool                            invoke                                  (ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const;
180                 virtual bool            invokeGLES                              (GLESImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const = 0;
181         };
182
183         class Create : public GLESAction
184         {
185         public:
186                                                                 Create                                  (MovePtr<ImageSource> imgSource, deUint32 numLayers = 1u) : m_imgSource(imgSource), m_numLayers(numLayers) {}
187                 string                                  getRequiredExtension    (void) const { return m_imgSource->getRequiredExtension(); }
188                 bool                                    invokeGLES                              (GLESImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const;
189                 deUint32                                getNumLayers                    (void) const { return m_numLayers; }
190                 glw::GLenum                             getEffectiveFormat              (void) const { return m_imgSource->getEffectiveFormat(); }
191                 bool                                    isYUVFormatImage                (void) const { return m_imgSource->isYUVFormatImage(); }
192         private:
193                 UniquePtr<ImageSource>  m_imgSource;
194                 deUint32                                m_numLayers;
195         };
196
197         class Render : public GLESAction
198         {
199         public:
200                 virtual string                  getRequiredExtension    (void) const { return "GL_OES_EGL_image"; }
201         };
202
203         class RenderTexture2D                           : public Render { public: bool invokeGLES (GLESImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const override; };
204         class RenderTextureCubemap                      : public Render { public: bool invokeGLES (GLESImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const override; };
205         class RenderReadPixelsRenderbuffer      : public Render { public: bool invokeGLES (GLESImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const override; };
206         class RenderDepthbuffer                         : public Render { public: bool invokeGLES (GLESImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const override; };
207         class RenderStencilbuffer                       : public Render { public: bool invokeGLES (GLESImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const override; };
208         class RenderTryAll                                      : public Render { public: bool invokeGLES (GLESImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const override; };
209
210         class RenderTexture2DArray : public Render
211         {
212                 public:
213                         bool    invokeGLES                              (GLESImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const override;
214                         string  getRequiredExtension    (void) const override { return "GL_EXT_EGL_image_array"; }
215         };
216
217         class RenderExternalTexture                     : public Render
218         {
219                 public:
220                         bool    invokeGLES                              (GLESImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const override;
221                         string  getRequiredExtension    (void) const override { return "GL_OES_EGL_image_external"; }
222         };
223
224         class RenderExternalTextureSamplerArray : public Render
225         {
226                 public:
227                         bool    invokeGLES                              (GLESImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const override;
228                         string  getRequiredExtension    (void) const override { return "GL_OES_EGL_image_external"; }
229         };
230         class RenderYUVTexture                  : public Render
231         {
232                 public:
233                         bool    invokeGLES                              (GLESImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const override;
234                         string  getRequiredExtension    (void) const override { return "GL_EXT_YUV_target"; }
235         };
236         class RenderSampleTexture2DArray                                 : public RenderTexture2DArray
237         {
238                 public:
239                         bool    invokeGLES                              (GLESImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const override;
240                         string  getRequiredExtension    (void) const override { return "GL_EXT_EGL_image_array"; }
241         };
242         class Modify : public GLESAction
243         {
244         public:
245                 string                          getRequiredExtension    (void) const { return "GL_OES_EGL_image"; }
246         };
247
248         class ModifyTexSubImage : public Modify
249         {
250         public:
251                                                         ModifyTexSubImage               (GLenum format, GLenum type) : m_format(format), m_type(type) {}
252                 bool                            invokeGLES                              (GLESImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const;
253                 GLenum                          getFormat                               (void) const { return m_format; }
254                 GLenum                          getType                                 (void) const { return m_type; }
255
256         private:
257                 GLenum                          m_format;
258                 GLenum                          m_type;
259         };
260
261         class ModifyRenderbuffer : public Modify
262         {
263         public:
264                 bool                            invokeGLES                              (GLESImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const;
265
266         protected:
267                 virtual void            initializeRbo                   (GLESImageApi& api, GLuint rbo, tcu::Texture2D& ref) const = 0;
268         };
269
270         class ModifyRenderbufferClearColor : public ModifyRenderbuffer
271         {
272         public:
273                                         ModifyRenderbufferClearColor    (tcu::Vec4 color) : m_color(color) {}
274
275         protected:
276                 void            initializeRbo                                   (GLESImageApi& api, GLuint rbo, tcu::Texture2D& ref) const;
277
278                 tcu::Vec4       m_color;
279         };
280
281         class ModifyRenderbufferClearDepth : public ModifyRenderbuffer
282         {
283         public:
284                                         ModifyRenderbufferClearDepth    (GLfloat depth) : m_depth(depth) {}
285
286         protected:
287                 void            initializeRbo                                   (GLESImageApi& api, GLuint rbo, tcu::Texture2D& ref) const;
288
289                 GLfloat         m_depth;
290         };
291
292         class ModifyRenderbufferClearStencil : public ModifyRenderbuffer
293         {
294         public:
295                                         ModifyRenderbufferClearStencil  (GLint stencil) : m_stencil(stencil) {}
296
297         protected:
298                 void            initializeRbo                                   (GLESImageApi& api, GLuint rbo, tcu::Texture2D& ref) const;
299
300                 GLint           m_stencil;
301         };
302
303                                         GLESImageApi                                    (const Library& egl, const glw::Functions& gl, int contextId, tcu::TestLog& log, EGLDisplay display, EGLSurface surface, EGLConfig config, EGLint apiVersion);
304                                         ~GLESImageApi                                   (void);
305
306 private:
307         EGLContext                                      m_context;
308         const glw::Functions&           m_gl;
309
310         MovePtr<UniqueImage>            createImage                     (const ImageSource& source, const ClientBuffer& buffer) const;
311 };
312
313 GLESImageApi::GLESImageApi (const Library& egl, const glw::Functions& gl, int contextId, tcu::TestLog& log, EGLDisplay display, EGLSurface surface, EGLConfig config, EGLint apiVersion)
314         : ImageApi                              (egl, contextId, display, surface)
315         , glu::CallLogWrapper   (gl, log)
316         , m_context                             (DE_NULL)
317         , m_gl                                  (gl)
318 {
319         const EGLint attriblist[] =
320         {
321                 EGL_CONTEXT_CLIENT_VERSION, apiVersion,
322                 EGL_NONE
323         };
324
325         EGLint configId = -1;
326         EGLU_CHECK_CALL(m_egl, getConfigAttrib(m_display, config, EGL_CONFIG_ID, &configId));
327         getLog() << tcu::TestLog::Message << "Creating gles" << apiVersion << " context with config id: " << configId << " context: " << m_contextId << tcu::TestLog::EndMessage;
328         egl.bindAPI(EGL_OPENGL_ES_API);
329         m_context = m_egl.createContext(m_display, config, EGL_NO_CONTEXT, attriblist);
330         EGLU_CHECK_MSG(m_egl, "Failed to create GLES context");
331
332         egl.makeCurrent(display, m_surface, m_surface, m_context);
333         EGLU_CHECK_MSG(m_egl, "Failed to make context current");
334 }
335
336 GLESImageApi::~GLESImageApi (void)
337 {
338         m_egl.makeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
339         m_egl.destroyContext(m_display, m_context);
340 }
341
342 bool GLESImageApi::GLESAction::invoke (ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const
343 {
344         GLESImageApi& glesApi = dynamic_cast<GLESImageApi&>(api);
345
346         glesApi.m_egl.makeCurrent(glesApi.m_display, glesApi.m_surface, glesApi.m_surface, glesApi.m_context);
347         return invokeGLES(glesApi, image, ref);
348 }
349
350 bool GLESImageApi::Create::invokeGLES (GLESImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const
351 {
352         de::UniquePtr<ClientBuffer>     buffer  (m_imgSource->createBuffer(api.m_egl, api.m_gl, &ref));
353
354         GLU_CHECK_GLW_CALL(api.m_gl, finish());
355
356         image = api.createImage(*m_imgSource, *buffer);
357         return true;
358 }
359
360 MovePtr<UniqueImage> GLESImageApi::createImage (const ImageSource& source, const ClientBuffer& buffer) const
361 {
362         const EGLImageKHR image = source.createImage(m_egl, m_display, m_context, buffer.get());
363         return MovePtr<UniqueImage>(new UniqueImage(m_egl, m_display, image));
364 }
365
366 static void imageTargetTexture2D (const Library& egl, const glw::Functions& gl, GLeglImageOES img)
367 {
368         gl.eglImageTargetTexture2DOES(GL_TEXTURE_2D, img);
369         {
370                 const GLenum error = gl.getError();
371
372                 if (error == GL_INVALID_OPERATION)
373                         TCU_THROW(NotSupportedError, "Creating texture2D from EGLImage type not supported");
374
375                 GLU_EXPECT_NO_ERROR(error, "glEGLImageTargetTexture2DOES()");
376                 EGLU_CHECK_MSG(egl, "glEGLImageTargetTexture2DOES()");
377         }
378 }
379
380 static void imageTargetExternalTexture (const Library& egl, const glw::Functions& gl, GLeglImageOES img)
381 {
382         gl.eglImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, img);
383         {
384                 const GLenum error = gl.getError();
385
386                 if (error == GL_INVALID_OPERATION)
387                         TCU_THROW(NotSupportedError, "Creating external texture from EGLImage type not supported");
388
389                 GLU_EXPECT_NO_ERROR(error, "glEGLImageTargetTexture2DOES()");
390                 EGLU_CHECK_MSG(egl, "glEGLImageTargetTexture2DOES()");
391         }
392 }
393
394 static void imageTargetTexture2DArray (const Library& egl, const glw::Functions& gl, GLeglImageOES img)
395 {
396         gl.eglImageTargetTexture2DOES(GL_TEXTURE_2D_ARRAY, img);
397         {
398                 const GLenum error = gl.getError();
399
400                 if (error == GL_INVALID_OPERATION)
401                         TCU_THROW(NotSupportedError, "Creating texture2D array from EGLImage type not supported");
402
403                 GLU_EXPECT_NO_ERROR(error, "glEGLImageTargetTexture2DOES()");
404                 EGLU_CHECK_MSG(egl, "glEGLImageTargetTexture2DOES()");
405         }
406 }
407
408 static void imageTargetRenderbuffer (const Library& egl, const glw::Functions& gl, GLeglImageOES img)
409 {
410         gl.eglImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, img);
411         {
412                 const GLenum error = gl.getError();
413
414                 if (error == GL_INVALID_OPERATION)
415                         TCU_THROW(NotSupportedError, "Creating renderbuffer from EGLImage type not supported");
416
417                 GLU_EXPECT_NO_ERROR(error, "glEGLImageTargetRenderbufferStorageOES()");
418                 EGLU_CHECK_MSG(egl, "glEGLImageTargetRenderbufferStorageOES()");
419         }
420 }
421
422 static void framebufferRenderbuffer (const glw::Functions& gl, GLenum attachment, GLuint rbo)
423 {
424         GLU_CHECK_GLW_CALL(gl, framebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, rbo));
425         TCU_CHECK_AND_THROW(NotSupportedError,
426                                                 gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE,
427                                                 ("EGLImage as " + string(glu::getFramebufferAttachmentName(attachment)) + " not supported").c_str());
428 }
429
430 static set<string> getSupportedExtensions (tcu::TestLog& log, const Library& egl, const EGLDisplay dpy, const glw::Functions gl)
431 {
432         set<string>                             exts;
433         const vector<string>    glExts  = de::splitString((const char*) gl.getString(GL_EXTENSIONS));
434         const vector<string>    eglExts = eglu::getDisplayExtensions(egl, dpy);
435
436         exts.insert(glExts.begin(), glExts.end());
437         exts.insert(eglExts.begin(), eglExts.end());
438
439         if (eglu::getVersion(egl, dpy) >= eglu::Version(1, 5))
440         {
441                 // EGL 1.5 has built-in support for EGLImage and GL sources
442                 exts.insert("EGL_KHR_image_base");
443                 exts.insert("EGL_KHR_gl_texture_2D_image");
444                 exts.insert("EGL_KHR_gl_texture_cubemap_image");
445                 exts.insert("EGL_KHR_gl_renderbuffer_image");
446         }
447
448         if (!de::contains(exts, "EGL_KHR_image_base") && !de::contains(exts, "EGL_KHR_image"))
449         {
450                 log << tcu::TestLog::Message
451                         << "EGL version is under 1.5 and neither EGL_KHR_image nor EGL_KHR_image_base is supported."
452                         << "One should be supported."
453                         << tcu::TestLog::EndMessage;
454                 TCU_THROW(NotSupportedError, "Extension not supported: EGL_KHR_image_base");
455         }
456
457         return exts;
458 }
459
460 static const float squareTriangleCoords[] =
461 {
462         -1.0, -1.0,
463         1.0, -1.0,
464         1.0,  1.0,
465
466         1.0,  1.0,
467         -1.0,  1.0,
468         -1.0, -1.0
469 };
470
471 bool GLESImageApi::RenderTexture2D::invokeGLES (GLESImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
472 {
473         const glw::Functions&   gl              = api.m_gl;
474         tcu::TestLog&                   log             = api.getLog();
475         Texture                                 srcTex  (gl);
476
477         // Branch only taken in TryAll case
478         if (reference.getFormat().order == tcu::TextureFormat::DS || reference.getFormat().order == tcu::TextureFormat::D)
479                 throw IllegalRendererException(); // Skip, GLES does not support sampling depth textures
480         if (reference.getFormat().order == tcu::TextureFormat::S)
481                 throw IllegalRendererException(); // Skip, GLES does not support sampling stencil textures
482
483         gl.clearColor(0.0, 0.0, 0.0, 0.0);
484         gl.viewport(0, 0, reference.getWidth(), reference.getHeight());
485         gl.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
486         gl.disable(GL_DEPTH_TEST);
487
488         log << tcu::TestLog::Message << "Rendering EGLImage as GL_TEXTURE_2D in context: " << api.m_contextId << tcu::TestLog::EndMessage;
489         TCU_CHECK(**img != EGL_NO_IMAGE_KHR);
490
491         GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_2D, *srcTex));
492         imageTargetTexture2D(api.m_egl, gl, **img);
493
494         GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
495         GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
496         GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
497         GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
498
499         const char* const vertexShader =
500                 "attribute highp vec2 a_coord;\n"
501                 "varying mediump vec2 v_texCoord;\n"
502                 "void main(void) {\n"
503                 "\tv_texCoord = vec2((a_coord.x + 1.0) * 0.5, (a_coord.y + 1.0) * 0.5);\n"
504                 "\tgl_Position = vec4(a_coord, -0.1, 1.0);\n"
505                 "}\n";
506
507         const char* const fragmentShader =
508                 "varying mediump vec2 v_texCoord;\n"
509                 "uniform sampler2D u_sampler;\n"
510                 "void main(void) {\n"
511                 "\tmediump vec4 texColor = texture2D(u_sampler, v_texCoord);\n"
512                 "\tgl_FragColor = vec4(texColor);\n"
513                 "}";
514
515         Program program(gl, vertexShader, fragmentShader);
516         TCU_CHECK(program.isOk());
517
518         GLuint glProgram = program.getProgram();
519         GLU_CHECK_GLW_CALL(gl, useProgram(glProgram));
520
521         GLuint coordLoc = gl.getAttribLocation(glProgram, "a_coord");
522         TCU_CHECK_MSG((int)coordLoc != -1, "Couldn't find attribute a_coord");
523
524         GLuint samplerLoc = gl.getUniformLocation(glProgram, "u_sampler");
525         TCU_CHECK_MSG((int)samplerLoc != (int)-1, "Couldn't find uniform u_sampler");
526
527         GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_2D, *srcTex));
528         GLU_CHECK_GLW_CALL(gl, uniform1i(samplerLoc, 0));
529         GLU_CHECK_GLW_CALL(gl, enableVertexAttribArray(coordLoc));
530         GLU_CHECK_GLW_CALL(gl, vertexAttribPointer(coordLoc, 2, GL_FLOAT, GL_FALSE, 0, squareTriangleCoords));
531
532         GLU_CHECK_GLW_CALL(gl, drawArrays(GL_TRIANGLES, 0, 6));
533         GLU_CHECK_GLW_CALL(gl, disableVertexAttribArray(coordLoc));
534         GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_2D, 0));
535
536         tcu::Surface refSurface (reference.getWidth(), reference.getHeight());
537         tcu::Surface screen             (reference.getWidth(), reference.getHeight());
538         GLU_CHECK_GLW_CALL(gl, readPixels(0, 0, screen.getWidth(), screen.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen.getAccess().getDataPtr()));
539
540         tcu::copy(refSurface.getAccess(), reference.getLevel(0));
541
542         float   threshold       = 0.05f;
543         bool    match           = tcu::fuzzyCompare(log, "ComparisonResult", "Image comparison result", refSurface, screen, threshold, tcu::COMPARE_LOG_RESULT);
544
545         return match;
546 }
547
548 // Renders using a single layer from a texture array.
549 bool GLESImageApi::RenderTexture2DArray::invokeGLES (GLESImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
550 {
551         const glw::Functions&   gl              = api.m_gl;
552         tcu::TestLog&                   log             = api.getLog();
553         Texture                                 srcTex  (gl);
554
555         gl.clearColor(0.0, 0.0, 0.0, 0.0);
556         gl.viewport(0, 0, reference.getWidth(), reference.getHeight());
557         gl.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
558         gl.disable(GL_DEPTH_TEST);
559
560         log << tcu::TestLog::Message << "Rendering EGLImage as GL_TEXTURE_2D_ARRAY in context: " << api.m_contextId << tcu::TestLog::EndMessage;
561         TCU_CHECK(**img != EGL_NO_IMAGE_KHR);
562
563         GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_2D_ARRAY, *srcTex));
564         imageTargetTexture2DArray(api.m_egl, gl, **img);
565
566         glu::TransferFormat transferFormat = glu::getTransferFormat(reference.getFormat());
567         // Initializes layer 1.
568         GLU_CHECK_GLW_CALL(gl, texSubImage3D(GL_TEXTURE_2D_ARRAY,
569                         0,                                                                              // Mipmap level
570             0,                                                                          // X offset
571                         0,                                                                              // Y offset
572                         1,                                                                              // Z offset (layer)
573                         reference.getWidth(),                                   // Width
574                         reference.getHeight(),                                  // Height
575                         1u,                                                                             // Depth
576                         transferFormat.format,                                  // Format
577                         transferFormat.dataType,                                // Type
578                         reference.getLevel(0).getDataPtr()));   // Pixel data
579
580
581         GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
582         GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
583         GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
584         GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
585
586         const char* const vertexShader =
587         "#version 320 es\n"
588         "precision highp int;\n"
589         "precision highp float;\n"
590         "layout(location = 0) in vec2 pos_in;\n"
591         "layout(location = 0) out vec2 texcoord_out;\n"
592         "void main()\n"
593         "{\n"
594         "    gl_Position = vec4(pos_in, -0.1, 1.0);\n"
595         "    texcoord_out = vec2((pos_in.x + 1.0) * 0.5, (pos_in.y + 1.0) * 0.5);\n"
596         "}\n";
597
598         const char* const fragmentShader =
599         "#version 320 es\n"
600         "precision highp int;\n"
601         "precision highp float;\n"
602         "layout(location = 0) in vec2 texcoords_in;\n"
603         "layout(location = 0) out vec4 color_out;\n"
604         "uniform layout(binding=0) highp sampler2DArray tex_sampler;\n"
605         "void main()\n"
606         "{\n"
607         // Samples layer 1.
608         "    color_out = texture(tex_sampler, vec3(texcoords_in, 1));\n"
609         "}\n";
610
611         Program program(gl, vertexShader, fragmentShader);
612
613         if (!program.isOk())
614         {
615                 log << tcu::TestLog::Message << "Shader build failed.\n"
616                         << "Vertex: " << program.getShaderInfo(glu::SHADERTYPE_VERTEX).infoLog << "\n"
617                         << vertexShader << "\n"
618                         << "Fragment: " << program.getShaderInfo(glu::SHADERTYPE_FRAGMENT).infoLog << "\n"
619                         << fragmentShader << "\n"
620                         << "Program: " << program.getProgramInfo().infoLog << tcu::TestLog::EndMessage;
621         }
622
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, "pos_in");
629         TCU_CHECK_MSG((int)coordLoc != -1, "Couldn't find attribute pos_in");
630
631         GLuint samplerLoc = gl.getUniformLocation(glProgram, "tex_sampler");
632         TCU_CHECK_MSG((int)samplerLoc != (int)-1, "Couldn't find uniform tex_sampler");
633
634         GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_2D_ARRAY, *srcTex));
635         GLU_CHECK_GLW_CALL(gl, uniform1i(samplerLoc, 0));
636         GLU_CHECK_GLW_CALL(gl, enableVertexAttribArray(coordLoc));
637         GLU_CHECK_GLW_CALL(gl, vertexAttribPointer(coordLoc, 2, GL_FLOAT, GL_FALSE, 0, squareTriangleCoords));
638
639         GLU_CHECK_GLW_CALL(gl, drawArrays(GL_TRIANGLES, 0, 6));
640         GLU_CHECK_GLW_CALL(gl, disableVertexAttribArray(coordLoc));
641
642         tcu::Surface refSurface (reference.getWidth(), reference.getHeight());
643         tcu::Surface screen             (reference.getWidth(), reference.getHeight());
644         GLU_CHECK_GLW_CALL(gl, readPixels(0, 0, screen.getWidth(), screen.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen.getAccess().getDataPtr()));
645
646         tcu::copy(refSurface.getAccess(), reference.getLevel(0));
647
648         float   threshold       = 0.05f;
649         bool    match           = tcu::fuzzyCompare(log, "ComparisonResult", "Image comparison result", refSurface, screen, threshold, tcu::COMPARE_LOG_RESULT);
650
651         return match;
652 }
653
654 //Texture2D array can be both rendered and sampled as a texture.
655 bool GLESImageApi::RenderSampleTexture2DArray::invokeGLES(GLESImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
656 {
657         const glw::Functions&   gl              = api.m_gl;
658         tcu::TestLog&                   log             = api.getLog();
659         Texture                                 srcTex  (gl);
660         Texture                                 srcTexArray     (gl);
661
662         gl.clearColor(0.0, 0.0, 0.0, 0.0);
663         gl.viewport(0, 0, reference.getWidth(), reference.getHeight());
664         gl.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
665         gl.disable(GL_DEPTH_TEST);
666
667         log << tcu::TestLog::Message << "Rendering and sampling EGLImage as GL_TEXTURE_2D_ARRAY in context: " << api.m_contextId << tcu::TestLog::EndMessage;
668         TCU_CHECK(**img != EGL_NO_IMAGE_KHR);
669
670         glu::TransferFormat transferFormat = glu::getTransferFormat(reference.getFormat());
671         deUint32 internalForat = glu::getInternalFormat(reference.getFormat());
672         GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_2D, *srcTex));
673         GLU_CHECK_GLW_CALL(gl, texImage2D(GL_TEXTURE_2D,
674                         0,                                                                              // Level
675                         internalForat,                                                  // Internal format
676                         reference.getWidth(),                                   // Width
677                         reference.getHeight(),                                  // Height
678                         0,                                                                              // Border
679                         transferFormat.format,                                  // Format
680                         transferFormat.dataType,                                // Type
681                         reference.getLevel(0).getDataPtr()));   // Pixel data
682
683         GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
684         GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
685         GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
686         GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
687
688         GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_2D_ARRAY, *srcTexArray));
689         imageTargetTexture2DArray(api.m_egl, gl, **img);
690
691         GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
692         GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
693         GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
694         GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
695
696         /* Create FBO and attach source texture layer 0 */
697         glu::Framebuffer                fbo(gl);
698         GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, *fbo));
699         GLU_CHECK_GLW_CALL(gl, framebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, *srcTexArray, 0, 0));
700
701         const char* const vertexShader0 =
702                 "attribute highp vec2 a_coord;\n"
703                 "varying mediump vec2 v_texCoord;\n"
704                 "void main(void) {\n"
705                 "\tv_texCoord = vec2((a_coord.x + 1.0) * 0.5, (a_coord.y + 1.0) * 0.5);\n"
706                 "\tgl_Position = vec4(a_coord, -0.1, 1.0);\n"
707                 "}\n";
708
709         const char* const fragmentShader0 =
710                 "varying mediump vec2 v_texCoord;\n"
711                 "uniform sampler2D u_sampler;\n"
712                 "void main(void) {\n"
713                 "\tmediump vec4 texColor = texture2D(u_sampler, v_texCoord);\n"
714                 "\tgl_FragColor = vec4(texColor);\n"
715                 "}";
716
717         Program program0(gl, vertexShader0, fragmentShader0);
718         if (!program0.isOk())
719         {
720                 log << tcu::TestLog::Message << "Shader build failed.\n"
721                         << "Vertex: " << program0.getShaderInfo(glu::SHADERTYPE_VERTEX).infoLog << "\n"
722                         << vertexShader0 << "\n"
723                         << "Fragment: " << program0.getShaderInfo(glu::SHADERTYPE_FRAGMENT).infoLog << "\n"
724                         << fragmentShader0 << "\n"
725                         << "Program: " << program0.getProgramInfo().infoLog << tcu::TestLog::EndMessage;
726         }
727
728         TCU_CHECK(program0.isOk());
729
730         GLuint glProgram0 = program0.getProgram();
731         GLU_CHECK_GLW_CALL(gl, useProgram(glProgram0));
732
733         GLuint coordLoc = gl.getAttribLocation(glProgram0, "a_coord");
734         TCU_CHECK_MSG((int)coordLoc != -1, "Couldn't find attribute a_coord");
735         GLuint samplerLoc = gl.getUniformLocation(glProgram0, "u_sampler");
736         TCU_CHECK_MSG((int)samplerLoc != (int)-1, "Couldn't find uniform u_sampler");
737         GLU_CHECK_GLW_CALL(gl, uniform1i(samplerLoc, 0));
738
739         GLU_CHECK_GLW_CALL(gl, enableVertexAttribArray(coordLoc));
740         GLU_CHECK_GLW_CALL(gl, vertexAttribPointer(coordLoc, 2, GL_FLOAT, GL_FALSE, 0, squareTriangleCoords));
741         GLU_CHECK_GLW_CALL(gl, drawArrays(GL_TRIANGLES, 0, 6));
742         GLU_CHECK_GLW_CALL(gl, disableVertexAttribArray(coordLoc));
743
744         tcu::Surface refSurface0        (reference.getWidth(), reference.getHeight());
745         tcu::Surface screen0            (reference.getWidth(), reference.getHeight());
746         GLU_CHECK_GLW_CALL(gl, readPixels(0, 0, screen0.getWidth(), screen0.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen0.getAccess().getDataPtr()));
747
748         tcu::copy(refSurface0.getAccess(), reference.getLevel(0));
749
750         float   threshold       = 0.01f;
751         bool    match           = tcu::fuzzyCompare(log, "ComparisonResult", "Image comparison result", refSurface0, screen0, threshold, tcu::COMPARE_LOG_RESULT);
752
753         if (match == false)
754                 return match;
755
756         /* Bind texture to FBO. */
757         GLU_CHECK_GLW_CALL(gl, framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *srcTex, 0));
758
759         const char* const vertexShader =
760                 "#version 320 es\n"
761                 "precision highp int;\n"
762                 "precision highp float;\n"
763                 "layout(location = 0) in vec2 pos_in;\n"
764                 "layout(location = 0) out vec2 texcoord_out;\n"
765                 "void main()\n"
766                 "{\n"
767                 "    gl_Position = vec4(pos_in, -0.1, 1.0);\n"
768                 "    texcoord_out = vec2((pos_in.x + 1.0) * 0.5, (pos_in.y + 1.0) * 0.5);\n"
769                 "}\n";
770
771         const char* const fragmentShader =
772                 "#version 320 es\n"
773                 "precision highp int;\n"
774                 "precision highp float;\n"
775                 "layout(location = 0) in vec2 texcoords_in;\n"
776                 "layout(location = 0) out vec4 color_out;\n"
777                 "uniform layout(binding=0) highp sampler2DArray tex_sampler;\n"
778                 "void main()\n"
779                 "{\n"
780                 // Samples layer 0.
781                 "    color_out = texture(tex_sampler, vec3(texcoords_in, 0));\n"
782                 "}\n";
783
784         Program program(gl, vertexShader, fragmentShader);
785
786         if (!program.isOk())
787         {
788                 log << tcu::TestLog::Message << "Shader build failed.\n"
789                         << "Vertex: " << program.getShaderInfo(glu::SHADERTYPE_VERTEX).infoLog << "\n"
790                         << vertexShader << "\n"
791                         << "Fragment: " << program.getShaderInfo(glu::SHADERTYPE_FRAGMENT).infoLog << "\n"
792                         << fragmentShader << "\n"
793                         << "Program: " << program.getProgramInfo().infoLog << tcu::TestLog::EndMessage;
794         }
795
796         TCU_CHECK(program.isOk());
797
798         GLuint glProgram = program.getProgram();
799         GLU_CHECK_GLW_CALL(gl, useProgram(glProgram));
800
801         coordLoc = gl.getAttribLocation(glProgram, "pos_in");
802         TCU_CHECK_MSG((int)coordLoc != -1, "Couldn't find attribute pos_in");
803
804         samplerLoc = gl.getUniformLocation(glProgram, "tex_sampler");
805         TCU_CHECK_MSG((int)samplerLoc != (int)-1, "Couldn't find uniform tex_sampler");
806
807         GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_2D_ARRAY, *srcTexArray));
808         GLU_CHECK_GLW_CALL(gl, uniform1i(samplerLoc, 0));
809         GLU_CHECK_GLW_CALL(gl, enableVertexAttribArray(coordLoc));
810         GLU_CHECK_GLW_CALL(gl, vertexAttribPointer(coordLoc, 2, GL_FLOAT, GL_FALSE, 0, squareTriangleCoords));
811
812         GLU_CHECK_GLW_CALL(gl, drawArrays(GL_TRIANGLES, 0, 6));
813         GLU_CHECK_GLW_CALL(gl, disableVertexAttribArray(coordLoc));
814         GLU_CHECK_GLW_CALL(gl, finish());
815
816         tcu::Surface refSurface (reference.getWidth(), reference.getHeight());
817         tcu::Surface screen             (reference.getWidth(), reference.getHeight());
818         GLU_CHECK_GLW_CALL(gl, readPixels(0, 0, screen.getWidth(), screen.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen.getAccess().getDataPtr()));
819
820         tcu::copy(refSurface.getAccess(), reference.getLevel(0));
821
822         GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, 0));
823
824         threshold       = 0.01f;
825         match           = tcu::fuzzyCompare(log, "ComparisonResult", "Image comparison result", refSurface, screen, threshold, tcu::COMPARE_LOG_RESULT);
826         return match;
827 }
828
829 bool GLESImageApi::RenderExternalTexture::invokeGLES (GLESImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
830 {
831         const glw::Functions&   gl              = api.m_gl;
832         tcu::TestLog&                   log             = api.getLog();
833         Texture                                 srcTex  (gl);
834
835         // Branch only taken in TryAll case
836         if (reference.getFormat().order == tcu::TextureFormat::DS || reference.getFormat().order == tcu::TextureFormat::D)
837                 throw IllegalRendererException(); // Skip, GLES2 does not support sampling depth textures
838         if (reference.getFormat().order == tcu::TextureFormat::S)
839                 throw IllegalRendererException(); // Skip, GLES2 does not support sampling stencil textures
840
841         gl.clearColor(0.0, 0.0, 0.0, 0.0);
842         gl.viewport(0, 0, reference.getWidth(), reference.getHeight());
843         gl.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
844         gl.disable(GL_DEPTH_TEST);
845
846         log << tcu::TestLog::Message << "Rendering EGLImage as GL_TEXTURE_EXTERNAL_OES in context: " << api.m_contextId << tcu::TestLog::EndMessage;
847         TCU_CHECK(**img != EGL_NO_IMAGE_KHR);
848
849         GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_EXTERNAL_OES, *srcTex));
850         imageTargetExternalTexture(api.m_egl, gl, **img);
851
852         GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
853         GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
854         GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
855         GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
856
857         const char* const vertexShader =
858                 "attribute highp vec2 a_coord;\n"
859                 "varying mediump vec2 v_texCoord;\n"
860                 "void main(void) {\n"
861                 "\tv_texCoord = vec2((a_coord.x + 1.0) * 0.5, (a_coord.y + 1.0) * 0.5);\n"
862                 "\tgl_Position = vec4(a_coord, -0.1, 1.0);\n"
863                 "}\n";
864
865         const char* const fragmentShader =
866                 "#extension GL_OES_EGL_image_external : require\n"
867                 "varying mediump vec2 v_texCoord;\n"
868                 "uniform samplerExternalOES u_sampler;\n"
869                 "void main(void) {\n"
870                 "\tmediump vec4 texColor = texture2D(u_sampler, v_texCoord);\n"
871                 "\tgl_FragColor = vec4(texColor);\n"
872                 "}";
873
874         Program program(gl, vertexShader, fragmentShader);
875         TCU_CHECK(program.isOk());
876
877         GLuint glProgram = program.getProgram();
878         GLU_CHECK_GLW_CALL(gl, useProgram(glProgram));
879
880         GLuint coordLoc = gl.getAttribLocation(glProgram, "a_coord");
881         TCU_CHECK_MSG((int)coordLoc != -1, "Couldn't find attribute a_coord");
882
883         GLuint samplerLoc = gl.getUniformLocation(glProgram, "u_sampler");
884         TCU_CHECK_MSG((int)samplerLoc != (int)-1, "Couldn't find uniform u_sampler");
885
886         GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_EXTERNAL_OES, *srcTex));
887         GLU_CHECK_GLW_CALL(gl, uniform1i(samplerLoc, 0));
888         GLU_CHECK_GLW_CALL(gl, enableVertexAttribArray(coordLoc));
889         GLU_CHECK_GLW_CALL(gl, vertexAttribPointer(coordLoc, 2, GL_FLOAT, GL_FALSE, 0, squareTriangleCoords));
890
891         GLU_CHECK_GLW_CALL(gl, drawArrays(GL_TRIANGLES, 0, 6));
892         GLU_CHECK_GLW_CALL(gl, disableVertexAttribArray(coordLoc));
893         GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_EXTERNAL_OES, 0));
894
895         tcu::Surface refSurface (reference.getWidth(), reference.getHeight());
896         tcu::Surface screen             (reference.getWidth(), reference.getHeight());
897         GLU_CHECK_GLW_CALL(gl, readPixels(0, 0, screen.getWidth(), screen.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen.getAccess().getDataPtr()));
898
899         tcu::copy(refSurface.getAccess(), reference.getLevel(0));
900
901         float   threshold       = 0.05f;
902         bool    match           = tcu::fuzzyCompare(log, "ComparisonResult", "Image comparison result", refSurface, screen, threshold, tcu::COMPARE_LOG_RESULT);
903
904         return match;
905 }
906
907 bool GLESImageApi::RenderYUVTexture::invokeGLES (GLESImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
908 {
909         const glw::Functions&   gl              = api.m_gl;
910         tcu::TestLog&                   log             = api.getLog();
911         Texture                                 srcTex  (gl);
912
913         DE_ASSERT(reference.isYUVTextureUsed());
914
915         gl.clearColor(0.0, 0.0, 0.0, 0.0);
916         gl.viewport(0, 0, reference.getWidth(), reference.getHeight());
917         gl.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
918         gl.disable(GL_DEPTH_TEST);
919
920         log << tcu::TestLog::Message << "Rendering EGLImage as GL_TEXTURE_EXTERNAL_OES in context: " << api.m_contextId << tcu::TestLog::EndMessage;
921         TCU_CHECK(**img != EGL_NO_IMAGE_KHR);
922         GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_EXTERNAL_OES, *srcTex));
923         imageTargetExternalTexture(api.m_egl, gl, **img);
924         {
925                 /* init YUV texture with glClear, clear color value in YUV color space */
926                 glu::Framebuffer                fbo(gl);
927                 GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, *fbo));
928                 GLU_CHECK_GLW_CALL(gl, framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,  GL_TEXTURE_EXTERNAL_OES,*srcTex, 0));
929                 const tcu::Vec4 colorValues[] =
930                 {
931                         tcu::Vec4(0.9f, 0.5f, 0.65f, 1.0f),
932                         tcu::Vec4(0.5f, 0.7f, 0.65f, 1.0f),
933                         tcu::Vec4(0.2f, 0.5f, 0.65f, 1.0f),
934                         tcu::Vec4(0.3f, 0.1f, 0.5f, 1.0f),
935                         tcu::Vec4(0.8f, 0.2f, 0.3f, 1.0f),
936                         tcu::Vec4(0.9f, 0.4f, 0.8f, 1.0f),
937                 };
938                 tcu::clear(reference.getLevel(0), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
939                 GLU_CHECK_GLW_CALL(gl, enable(GL_SCISSOR_TEST));
940                 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(colorValues); ++ndx)
941                 {
942                         const tcu::IVec2        size    = tcu::IVec2((int)((float)(DE_LENGTH_OF_ARRAY(colorValues) - ndx) * ((float)reference.getWidth() / float(DE_LENGTH_OF_ARRAY(colorValues)))),
943                                                                                                         (int)((float)(DE_LENGTH_OF_ARRAY(colorValues) - ndx) * ((float)reference.getHeight() / float(DE_LENGTH_OF_ARRAY(colorValues)))));
944
945                         if (size.x() == 0 || size.y() == 0)
946                                 break;
947                         GLU_CHECK_GLW_CALL(gl, scissor(0, 0, size.x(), size.y()));
948
949                         GLU_CHECK_GLW_CALL(gl, clearColor(colorValues[ndx].x(), colorValues[ndx].y(), colorValues[ndx].z(), colorValues[ndx].w()));
950                         GLU_CHECK_GLW_CALL(gl, clear(GL_COLOR_BUFFER_BIT));
951                         GLU_CHECK_GLW_CALL(gl, finish());
952                         char tmp[4]={"0"};
953                         GLU_CHECK_GLW_CALL(gl, readPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, (void*)tmp));
954                         tcu::clear(tcu::getSubregion(reference.getLevel(0), 0, 0, size.x(), size.y()), tcu::Vec4(tmp[0]/(255.0f), tmp[1]/(255.0f), tmp[2]/(255.0f), tmp[3]/(255.0f)));
955                 }
956                 GLU_CHECK_GLW_CALL(gl, disable(GL_SCISSOR_TEST));
957                 GLU_CHECK_GLW_CALL(gl, framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_EXTERNAL_OES, 0, 0));
958                 GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, 0));
959                 GLU_CHECK_GLW_CALL(gl, finish());
960         }
961
962         GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
963         GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
964         GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
965         GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
966
967         const char* const vertexShader =
968                 "attribute highp vec2 a_coord;\n"
969                 "varying mediump vec2 v_texCoord;\n"
970                 "void main(void) {\n"
971                 "\tv_texCoord = vec2((a_coord.x + 1.0) * 0.5, (a_coord.y + 1.0) * 0.5);\n"
972                 "\tgl_Position = vec4(a_coord, -0.1, 1.0);\n"
973                 "}\n";
974
975         const char* const fragmentShader =
976                 "#extension GL_OES_EGL_image_external : require\n"
977                 "varying mediump vec2 v_texCoord;\n"
978                 "uniform samplerExternalOES u_sampler;\n"
979                 "void main(void) {\n"
980                 "\tmediump vec4 texColor = texture2D(u_sampler, v_texCoord);\n"
981                 "\tgl_FragColor = vec4(texColor);\n"
982                 "}";
983
984         Program program(gl, vertexShader, fragmentShader);
985         TCU_CHECK(program.isOk());
986
987         GLuint glProgram = program.getProgram();
988         GLU_CHECK_GLW_CALL(gl, useProgram(glProgram));
989
990         GLuint coordLoc = gl.getAttribLocation(glProgram, "a_coord");
991         TCU_CHECK_MSG((int)coordLoc != -1, "Couldn't find attribute a_coord");
992
993         GLuint samplerLoc = gl.getUniformLocation(glProgram, "u_sampler");
994         TCU_CHECK_MSG((int)samplerLoc != (int)-1, "Couldn't find uniform u_sampler");
995
996         GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_EXTERNAL_OES, *srcTex));
997         GLU_CHECK_GLW_CALL(gl, uniform1i(samplerLoc, 0));
998         GLU_CHECK_GLW_CALL(gl, enableVertexAttribArray(coordLoc));
999         GLU_CHECK_GLW_CALL(gl, vertexAttribPointer(coordLoc, 2, GL_FLOAT, GL_FALSE, 0, squareTriangleCoords));
1000
1001         GLU_CHECK_GLW_CALL(gl, drawArrays(GL_TRIANGLES, 0, 6));
1002         GLU_CHECK_GLW_CALL(gl, disableVertexAttribArray(coordLoc));
1003         GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_EXTERNAL_OES, 0));
1004
1005         tcu::Surface refSurface (reference.getWidth(), reference.getHeight());
1006         tcu::Surface screen             (reference.getWidth(), reference.getHeight());
1007         GLU_CHECK_GLW_CALL(gl, readPixels(0, 0, screen.getWidth(), screen.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen.getAccess().getDataPtr()));
1008
1009         tcu::copy(refSurface.getAccess(), reference.getLevel(0));
1010
1011         float   threshold       = 0.05f;
1012         bool    match           = tcu::fuzzyCompare(log, "ComparisonResult", "Image comparison result", refSurface, screen, threshold, tcu::COMPARE_LOG_RESULT);
1013
1014         return match;
1015 }
1016
1017 bool GLESImageApi::RenderExternalTextureSamplerArray::invokeGLES (GLESImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
1018 {
1019         const glw::Functions&   gl              = api.m_gl;
1020         tcu::TestLog&                   log             = api.getLog();
1021         Texture                                 srcTex  (gl);
1022
1023         // Branch only taken in TryAll case
1024         if (reference.getFormat().order == tcu::TextureFormat::DS || reference.getFormat().order == tcu::TextureFormat::D)
1025                 throw IllegalRendererException(); // Skip, GLES2 does not support sampling depth textures
1026         if (reference.getFormat().order == tcu::TextureFormat::S)
1027                 throw IllegalRendererException(); // Skip, GLES2 does not support sampling stencil textures
1028
1029         gl.clearColor(0.0, 0.0, 0.0, 0.0);
1030         gl.viewport(0, 0, reference.getWidth(), reference.getHeight());
1031         gl.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
1032         gl.disable(GL_DEPTH_TEST);
1033
1034         log << tcu::TestLog::Message << "Rendering EGLImage as GL_TEXTURE_EXTERNAL_OES using sampler array in context: " << api.m_contextId << tcu::TestLog::EndMessage;
1035         TCU_CHECK(**img != EGL_NO_IMAGE_KHR);
1036
1037         GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_EXTERNAL_OES, *srcTex));
1038         imageTargetExternalTexture(api.m_egl, gl, **img);
1039
1040         GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
1041         GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
1042         GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
1043         GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
1044
1045         // Texture not associated with an external texture will return (0, 0, 0, 1) when sampled.
1046         GLuint  emptyTex;
1047         gl.genTextures(1, &emptyTex);
1048         gl.activeTexture(GL_TEXTURE1);
1049         GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_EXTERNAL_OES, emptyTex));
1050
1051         const char* const vertexShader =
1052                 "attribute highp vec2 a_coord;\n"
1053                 "varying mediump vec2 v_texCoord;\n"
1054                 "void main(void) {\n"
1055                 "\tv_texCoord = vec2((a_coord.x + 1.0) * 0.5, (a_coord.y + 1.0) * 0.5);\n"
1056                 "\tgl_Position = vec4(a_coord, -0.1, 1.0);\n"
1057                 "}\n";
1058
1059         const char* const fragmentShader =
1060                 "#extension GL_OES_EGL_image_external : require\n"
1061                 "varying mediump vec2 v_texCoord;\n"
1062                 "uniform samplerExternalOES u_sampler[4];\n"
1063                 "void main(void) {\n"
1064                 "\tmediump vec4 texColor = texture2D(u_sampler[2], v_texCoord);\n"
1065                 "\t//These will sample (0, 0, 0, 1) and should not affect the results.\n"
1066                 "\ttexColor += texture2D(u_sampler[0], v_texCoord) - vec4(0, 0, 0, 1);\n"
1067                 "\ttexColor += texture2D(u_sampler[1], v_texCoord) - vec4(0, 0, 0, 1);\n"
1068                 "\ttexColor += texture2D(u_sampler[3], v_texCoord) - vec4(0, 0, 0, 1);\n"
1069                 "\tgl_FragColor = vec4(texColor);\n"
1070                 "}";
1071
1072         Program program(gl, vertexShader, fragmentShader);
1073         TCU_CHECK(program.isOk());
1074
1075         GLuint glProgram = program.getProgram();
1076         GLU_CHECK_GLW_CALL(gl, useProgram(glProgram));
1077
1078         GLuint coordLoc = gl.getAttribLocation(glProgram, "a_coord");
1079         TCU_CHECK_MSG((int)coordLoc != -1, "Couldn't find attribute a_coord");
1080
1081         GLuint samplerLoc0 = gl.getUniformLocation(glProgram, "u_sampler[0]");
1082         TCU_CHECK_MSG((int)samplerLoc0 != (int)-1, "Couldn't find uniform u_sampler[0]");
1083         GLuint samplerLoc1 = gl.getUniformLocation(glProgram, "u_sampler[1]");
1084         TCU_CHECK_MSG((int)samplerLoc1 != (int)-1, "Couldn't find uniform u_sampler[1]");
1085         GLuint samplerLoc2 = gl.getUniformLocation(glProgram, "u_sampler[2]");
1086         TCU_CHECK_MSG((int)samplerLoc2 != (int)-1, "Couldn't find uniform u_sampler[2]");
1087         GLuint samplerLoc3 = gl.getUniformLocation(glProgram, "u_sampler[3]");
1088         TCU_CHECK_MSG((int)samplerLoc3 != (int)-1, "Couldn't find uniform u_sampler[3]");
1089
1090         gl.activeTexture(GL_TEXTURE0);
1091         GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_EXTERNAL_OES, *srcTex));
1092         // One sampler reads a gradient and others opaque black.
1093         GLU_CHECK_GLW_CALL(gl, uniform1i(samplerLoc0, 1));
1094         GLU_CHECK_GLW_CALL(gl, uniform1i(samplerLoc1, 1));
1095         GLU_CHECK_GLW_CALL(gl, uniform1i(samplerLoc2, 0));
1096         GLU_CHECK_GLW_CALL(gl, uniform1i(samplerLoc3, 1));
1097         GLU_CHECK_GLW_CALL(gl, enableVertexAttribArray(coordLoc));
1098         GLU_CHECK_GLW_CALL(gl, vertexAttribPointer(coordLoc, 2, GL_FLOAT, GL_FALSE, 0, squareTriangleCoords));
1099
1100         GLU_CHECK_GLW_CALL(gl, drawArrays(GL_TRIANGLES, 0, 6));
1101         GLU_CHECK_GLW_CALL(gl, disableVertexAttribArray(coordLoc));
1102         GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_EXTERNAL_OES, 0));
1103         gl.activeTexture(GL_TEXTURE1);
1104         GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_EXTERNAL_OES, 0));
1105         gl.deleteTextures(1, &emptyTex);
1106         gl.activeTexture(GL_TEXTURE0);
1107
1108         tcu::Surface refSurface (reference.getWidth(), reference.getHeight());
1109         tcu::Surface screen             (reference.getWidth(), reference.getHeight());
1110         GLU_CHECK_GLW_CALL(gl, readPixels(0, 0, screen.getWidth(), screen.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen.getAccess().getDataPtr()));
1111
1112         tcu::copy(refSurface.getAccess(), reference.getLevel(0));
1113
1114         float   threshold       = 0.05f;
1115         bool    match           = tcu::fuzzyCompare(log, "ComparisonResult", "Image comparison result", refSurface, screen, threshold, tcu::COMPARE_LOG_RESULT);
1116
1117         return match;
1118 }
1119
1120 bool GLESImageApi::RenderDepthbuffer::invokeGLES (GLESImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
1121 {
1122         const glw::Functions&   gl                                      = api.m_gl;
1123         tcu::TestLog&                   log                                     = api.getLog();
1124         Framebuffer                             framebuffer                     (gl);
1125         Renderbuffer                    renderbufferColor       (gl);
1126         Renderbuffer                    renderbufferDepth       (gl);
1127         const tcu::RGBA                 compareThreshold        (32, 32, 32, 32); // layer colors are far apart, large thresholds are ok
1128
1129         // Branch only taken in TryAll case
1130         if (reference.getFormat().order != tcu::TextureFormat::DS && reference.getFormat().order != tcu::TextureFormat::D)
1131                 throw IllegalRendererException(); // Skip, interpreting non-depth data as depth data is not meaningful
1132
1133         log << tcu::TestLog::Message << "Rendering with depth buffer" << tcu::TestLog::EndMessage;
1134
1135         GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, *framebuffer));
1136
1137         GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, *renderbufferColor));
1138         GLU_CHECK_GLW_CALL(gl, renderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, reference.getWidth(), reference.getHeight()));
1139         framebufferRenderbuffer(gl, GL_COLOR_ATTACHMENT0, *renderbufferColor);
1140
1141         GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, *renderbufferDepth));
1142         imageTargetRenderbuffer(api.m_egl, gl, **img);
1143         framebufferRenderbuffer(gl, GL_DEPTH_ATTACHMENT, *renderbufferDepth);
1144         GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, 0));
1145
1146         GLU_CHECK_GLW_CALL(gl, viewport(0, 0, reference.getWidth(), reference.getHeight()));
1147
1148         // Render
1149         const char* vertexShader =
1150                 "attribute highp vec2 a_coord;\n"
1151                 "uniform highp float u_depth;\n"
1152                 "void main(void) {\n"
1153                 "\tgl_Position = vec4(a_coord, u_depth, 1.0);\n"
1154                 "}\n";
1155
1156         const char* fragmentShader =
1157                 "uniform mediump vec4 u_color;\n"
1158                 "void main(void) {\n"
1159                 "\tgl_FragColor = u_color;\n"
1160                 "}";
1161
1162         Program program(gl, vertexShader, fragmentShader);
1163         TCU_CHECK(program.isOk());
1164
1165         GLuint glProgram = program.getProgram();
1166         GLU_CHECK_GLW_CALL(gl, useProgram(glProgram));
1167
1168         GLuint coordLoc = gl.getAttribLocation(glProgram, "a_coord");
1169         TCU_CHECK_MSG((int)coordLoc != -1, "Couldn't find attribute a_coord");
1170
1171         GLuint colorLoc = gl.getUniformLocation(glProgram, "u_color");
1172         TCU_CHECK_MSG((int)colorLoc != (int)-1, "Couldn't find uniform u_color");
1173
1174         GLuint depthLoc = gl.getUniformLocation(glProgram, "u_depth");
1175         TCU_CHECK_MSG((int)depthLoc != (int)-1, "Couldn't find uniform u_depth");
1176
1177         GLU_CHECK_GLW_CALL(gl, clearColor(0.5f, 1.0f, 0.5f, 1.0f));
1178         GLU_CHECK_GLW_CALL(gl, clear(GL_COLOR_BUFFER_BIT));
1179
1180         tcu::Vec4 depthLevelColors[] = {
1181                 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
1182                 tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
1183                 tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f),
1184                 tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
1185                 tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f),
1186
1187                 tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f),
1188                 tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f),
1189                 tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f),
1190                 tcu::Vec4(0.0f, 0.5f, 0.0f, 1.0f),
1191                 tcu::Vec4(0.5f, 0.5f, 0.0f, 1.0f)
1192         };
1193
1194         GLU_CHECK_GLW_CALL(gl, enableVertexAttribArray(coordLoc));
1195         GLU_CHECK_GLW_CALL(gl, vertexAttribPointer(coordLoc, 2, GL_FLOAT, GL_FALSE, 0, squareTriangleCoords));
1196
1197         GLU_CHECK_GLW_CALL(gl, enable(GL_DEPTH_TEST));
1198         GLU_CHECK_GLW_CALL(gl, depthFunc(GL_LESS));
1199         GLU_CHECK_GLW_CALL(gl, depthMask(GL_FALSE));
1200
1201         for (int level = 0; level < DE_LENGTH_OF_ARRAY(depthLevelColors); level++)
1202         {
1203                 const tcu::Vec4 color           = depthLevelColors[level];
1204                 const float             clipDepth       = ((float)(level + 1) * 0.1f) * 2.0f - 1.0f; // depth in clip coords
1205
1206                 GLU_CHECK_GLW_CALL(gl, uniform4f(colorLoc, color.x(), color.y(), color.z(), color.w()));
1207                 GLU_CHECK_GLW_CALL(gl, uniform1f(depthLoc, clipDepth));
1208                 GLU_CHECK_GLW_CALL(gl, drawArrays(GL_TRIANGLES, 0, 6));
1209         }
1210
1211         GLU_CHECK_GLW_CALL(gl, depthMask(GL_TRUE));
1212         GLU_CHECK_GLW_CALL(gl, disable(GL_DEPTH_TEST));
1213         GLU_CHECK_GLW_CALL(gl, disableVertexAttribArray(coordLoc));
1214
1215         const ConstPixelBufferAccess&   refAccess               = reference.getLevel(0);
1216         tcu::Surface                                    screen                  (reference.getWidth(), reference.getHeight());
1217         tcu::Surface                                    referenceScreen (reference.getWidth(), reference.getHeight());
1218
1219         gl.readPixels(0, 0, screen.getWidth(), screen.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen.getAccess().getDataPtr());
1220
1221         for (int y = 0; y < reference.getHeight(); y++)
1222         {
1223                 for (int x = 0; x < reference.getWidth(); x++)
1224                 {
1225                         tcu::Vec4 result = tcu::Vec4(0.5f, 1.0f, 0.5f, 1.0f);
1226
1227                         for (int level = 0; level < DE_LENGTH_OF_ARRAY(depthLevelColors); level++)
1228                         {
1229                                 if ((float)(level + 1) * 0.1f < refAccess.getPixDepth(x, y))
1230                                         result = depthLevelColors[level];
1231                         }
1232
1233                         referenceScreen.getAccess().setPixel(result, x, y);
1234                 }
1235         }
1236
1237         GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, 0));
1238         GLU_CHECK_GLW_CALL(gl, finish());
1239
1240         return tcu::pixelThresholdCompare(log, "Depth buffer rendering result", "Result from rendering with depth buffer", referenceScreen, screen, compareThreshold, tcu::COMPARE_LOG_RESULT);
1241 }
1242
1243 bool GLESImageApi::RenderStencilbuffer::invokeGLES (GLESImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
1244 {
1245         // Branch only taken in TryAll case
1246         if (reference.getFormat().order != tcu::TextureFormat::DS && reference.getFormat().order != tcu::TextureFormat::S)
1247                 throw IllegalRendererException(); // Skip, interpreting non-stencil data as stencil data is not meaningful
1248
1249         const glw::Functions&   gl                                      = api.m_gl;
1250         tcu::TestLog&                   log                                     = api.getLog();
1251         Framebuffer                             framebuffer                     (gl);
1252         Renderbuffer                    renderbufferColor       (gl);
1253         Renderbuffer                    renderbufferStencil (gl);
1254         const tcu::RGBA                 compareThreshold        (32, 32, 32, 32); // layer colors are far apart, large thresholds are ok
1255         const deUint32                  numStencilBits          = tcu::getTextureFormatBitDepth(tcu::getEffectiveDepthStencilTextureFormat(reference.getLevel(0).getFormat(), tcu::Sampler::MODE_STENCIL)).x();
1256         const deUint32                  maxStencil                      = deBitMask32(0, numStencilBits);
1257
1258         log << tcu::TestLog::Message << "Rendering with stencil buffer" << tcu::TestLog::EndMessage;
1259
1260         GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, *framebuffer));
1261
1262         GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, *renderbufferColor));
1263         GLU_CHECK_GLW_CALL(gl, renderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, reference.getWidth(), reference.getHeight()));
1264         framebufferRenderbuffer(gl, GL_COLOR_ATTACHMENT0, *renderbufferColor);
1265
1266         GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, *renderbufferStencil));
1267         imageTargetRenderbuffer(api.m_egl, gl, **img);
1268         framebufferRenderbuffer(gl, GL_STENCIL_ATTACHMENT, *renderbufferStencil);
1269         GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, 0));
1270
1271         GLU_CHECK_GLW_CALL(gl, viewport(0, 0, reference.getWidth(), reference.getHeight()));
1272
1273         // Render
1274         const char* vertexShader =
1275                 "attribute highp vec2 a_coord;\n"
1276                 "void main(void) {\n"
1277                 "\tgl_Position = vec4(a_coord, 0.0, 1.0);\n"
1278                 "}\n";
1279
1280         const char* fragmentShader =
1281                 "uniform mediump vec4 u_color;\n"
1282                 "void main(void) {\n"
1283                 "\tgl_FragColor = u_color;\n"
1284                 "}";
1285
1286         Program program(gl, vertexShader, fragmentShader);
1287         TCU_CHECK(program.isOk());
1288
1289         GLuint glProgram = program.getProgram();
1290         GLU_CHECK_GLW_CALL(gl, useProgram(glProgram));
1291
1292         GLuint coordLoc = gl.getAttribLocation(glProgram, "a_coord");
1293         TCU_CHECK_MSG((int)coordLoc != -1, "Couldn't find attribute a_coord");
1294
1295         GLuint colorLoc = gl.getUniformLocation(glProgram, "u_color");
1296         TCU_CHECK_MSG((int)colorLoc != (int)-1, "Couldn't find uniform u_color");
1297
1298         GLU_CHECK_GLW_CALL(gl, clearColor(0.5f, 1.0f, 0.5f, 1.0f));
1299         GLU_CHECK_GLW_CALL(gl, clear(GL_COLOR_BUFFER_BIT));
1300
1301         tcu::Vec4 stencilLevelColors[] = {
1302                 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
1303                 tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
1304                 tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f),
1305                 tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
1306                 tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f),
1307
1308                 tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f),
1309                 tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f),
1310                 tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f),
1311                 tcu::Vec4(0.0f, 0.5f, 0.0f, 1.0f),
1312                 tcu::Vec4(0.5f, 0.5f, 0.0f, 1.0f)
1313         };
1314
1315         GLU_CHECK_GLW_CALL(gl, enableVertexAttribArray(coordLoc));
1316         GLU_CHECK_GLW_CALL(gl, vertexAttribPointer(coordLoc, 2, GL_FLOAT, GL_FALSE, 0, squareTriangleCoords));
1317
1318         GLU_CHECK_GLW_CALL(gl, enable(GL_STENCIL_TEST));
1319         GLU_CHECK_GLW_CALL(gl, stencilOp(GL_KEEP, GL_KEEP, GL_KEEP));
1320
1321         for (int level = 0; level < DE_LENGTH_OF_ARRAY(stencilLevelColors); level++)
1322         {
1323                 const tcu::Vec4 color   = stencilLevelColors[level];
1324                 const int               stencil = (int)(((float)(level + 1) * 0.1f) * (float)maxStencil);
1325
1326                 GLU_CHECK_GLW_CALL(gl, stencilFunc(GL_LESS, stencil, 0xFFFFFFFFu));
1327                 GLU_CHECK_GLW_CALL(gl, uniform4f(colorLoc, color.x(), color.y(), color.z(), color.w()));
1328                 GLU_CHECK_GLW_CALL(gl, drawArrays(GL_TRIANGLES, 0, 6));
1329         }
1330
1331         GLU_CHECK_GLW_CALL(gl, disable(GL_STENCIL_TEST));
1332         GLU_CHECK_GLW_CALL(gl, disableVertexAttribArray(coordLoc));
1333
1334         const ConstPixelBufferAccess&   refAccess               = reference.getLevel(0);
1335         tcu::Surface                                    screen                  (reference.getWidth(), reference.getHeight());
1336         tcu::Surface                                    referenceScreen (reference.getWidth(), reference.getHeight());
1337
1338         gl.readPixels(0, 0, screen.getWidth(), screen.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen.getAccess().getDataPtr());
1339
1340         for (int y = 0; y < reference.getHeight(); y++)
1341         for (int x = 0; x < reference.getWidth(); x++)
1342         {
1343                 tcu::Vec4 result = tcu::Vec4(0.5f, 1.0f, 0.5f, 1.0f);
1344
1345                 for (int level = 0; level < DE_LENGTH_OF_ARRAY(stencilLevelColors); level++)
1346                 {
1347                         const int levelStencil = (int)(((float)(level + 1) * 0.1f) * (float)maxStencil);
1348                         if (levelStencil < refAccess.getPixStencil(x, y))
1349                                 result = stencilLevelColors[level];
1350                 }
1351
1352                 referenceScreen.getAccess().setPixel(result, x, y);
1353         }
1354
1355         GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, 0));
1356         GLU_CHECK_GLW_CALL(gl, finish());
1357
1358         return tcu::pixelThresholdCompare(log, "StencilResult", "Result from rendering with stencil buffer", referenceScreen, screen, compareThreshold, tcu::COMPARE_LOG_RESULT);
1359 }
1360
1361 bool GLESImageApi::RenderReadPixelsRenderbuffer::invokeGLES (GLESImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
1362 {
1363         switch (glu::getInternalFormat(reference.getFormat()))
1364         {
1365                 case GL_RGBA4:
1366                 case GL_RGB5_A1:
1367                 case GL_RGB565:
1368                         break;
1369                 default:
1370                         // Skip, not in the list of allowed render buffer formats for GLES.
1371                         throw tcu::NotSupportedError("Image format not allowed for glReadPixels.");
1372         }
1373
1374         const glw::Functions&   gl                              = api.m_gl;
1375         const tcu::IVec4                bitDepth                = tcu::getTextureFormatMantissaBitDepth(reference.getFormat());
1376         const tcu::IVec4                threshold               (2 * (tcu::IVec4(1) << (tcu::IVec4(8) - bitDepth)));
1377         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)));
1378         tcu::TestLog&                   log                             = api.getLog();
1379         Framebuffer                             framebuffer             (gl);
1380         Renderbuffer                    renderbuffer    (gl);
1381         tcu::Surface                    screen                  (reference.getWidth(), reference.getHeight());
1382         tcu::Surface                    refSurface              (reference.getWidth(), reference.getHeight());
1383
1384         log << tcu::TestLog::Message << "Reading with ReadPixels from renderbuffer" << tcu::TestLog::EndMessage;
1385
1386         GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, *framebuffer));
1387         GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, *renderbuffer));
1388         imageTargetRenderbuffer(api.m_egl, gl, **img);
1389
1390         GLU_EXPECT_NO_ERROR(gl.getError(), "imageTargetRenderbuffer");
1391         framebufferRenderbuffer(gl, GL_COLOR_ATTACHMENT0, *renderbuffer);
1392         GLU_EXPECT_NO_ERROR(gl.getError(), "framebufferRenderbuffer");
1393
1394         GLU_CHECK_GLW_CALL(gl, viewport(0, 0, reference.getWidth(), reference.getHeight()));
1395
1396         GLU_CHECK_GLW_CALL(gl, readPixels(0, 0, screen.getWidth(), screen.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen.getAccess().getDataPtr()));
1397
1398         GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, 0));
1399         GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, 0));
1400         GLU_CHECK_GLW_CALL(gl, finish());
1401
1402         tcu::copy(refSurface.getAccess(), reference.getLevel(0));
1403
1404         return tcu::pixelThresholdCompare(log, "Renderbuffer read", "Result from reading renderbuffer", refSurface, screen, threshold8, tcu::COMPARE_LOG_RESULT);
1405
1406 }
1407
1408 bool GLESImageApi::RenderTryAll::invokeGLES (GLESImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
1409 {
1410         bool                                                                                    foundSupported                  = false;
1411         tcu::TestLog&                                                                   log                                             = api.getLog();
1412         GLESImageApi::RenderTexture2D                                   renderTex2D;
1413         GLESImageApi::RenderExternalTexture                             renderExternal;
1414         GLESImageApi::RenderExternalTextureSamplerArray renderExternalSamplerArray;
1415         GLESImageApi::RenderReadPixelsRenderbuffer              renderReadPixels;
1416         GLESImageApi::RenderDepthbuffer                                 renderDepth;
1417         GLESImageApi::RenderStencilbuffer                               renderStencil;
1418         Action*                                                                                 actions[]                               = { &renderTex2D, &renderExternal, &renderExternalSamplerArray, &renderReadPixels, &renderDepth, &renderStencil };
1419         set<string>                                                                             exts                                    = getSupportedExtensions(log, api.m_egl, api.m_display, api.m_gl);
1420
1421         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(actions); ++ndx)
1422         {
1423                 try
1424                 {
1425                         const string ext = actions[ndx]->getRequiredExtension();
1426
1427                         if (!de::contains(exts, ext))
1428                                 TCU_THROW_EXPR(NotSupportedError, "Extension not supported", ext.c_str());
1429
1430                         if (!actions[ndx]->invoke(api, img, reference))
1431                                 return false;
1432
1433                         foundSupported = true;
1434                 }
1435                 catch (const tcu::NotSupportedError& error)
1436                 {
1437                         log << tcu::TestLog::Message << error.what() << tcu::TestLog::EndMessage;
1438                 }
1439                 catch (const IllegalRendererException&)
1440                 {
1441                         // not valid renderer
1442                 }
1443         }
1444
1445         if (!foundSupported)
1446                 throw tcu::NotSupportedError("Rendering not supported", "", __FILE__, __LINE__);
1447
1448         return true;
1449 }
1450
1451 bool GLESImageApi::ModifyTexSubImage::invokeGLES (GLESImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
1452 {
1453         const glw::Functions&   gl              = api.m_gl;
1454         tcu::TestLog&                   log             = api.getLog();
1455         glu::Texture                    srcTex  (gl);
1456         const int                               xOffset = 8;
1457         const int                               yOffset = 16;
1458         const int                               xSize   = de::clamp(16, 0, reference.getWidth() - xOffset);
1459         const int                               ySize   = de::clamp(16, 0, reference.getHeight() - yOffset);
1460         tcu::Texture2D                  src             (glu::mapGLTransferFormat(m_format, m_type), xSize, ySize);
1461
1462         log << tcu::TestLog::Message << "Modifying EGLImage with gl.texSubImage2D" << tcu::TestLog::EndMessage;
1463
1464         src.allocLevel(0);
1465         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));
1466
1467         GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_2D, *srcTex));
1468         imageTargetTexture2D(api.m_egl, gl, **img);
1469         GLU_CHECK_GLW_CALL(gl, texSubImage2D(GL_TEXTURE_2D, 0, xOffset, yOffset, src.getWidth(), src.getHeight(), m_format, m_type, src.getLevel(0).getDataPtr()));
1470         GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_2D, 0));
1471         GLU_CHECK_GLW_CALL(gl, finish());
1472
1473         tcu::copy(tcu::getSubregion(reference.getLevel(0), xOffset, yOffset, 0, xSize, ySize, 1), src.getLevel(0));
1474
1475         return true;
1476 }
1477
1478 bool GLESImageApi::ModifyRenderbuffer::invokeGLES (GLESImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
1479 {
1480         const glw::Functions&   gl                              = api.m_gl;
1481         tcu::TestLog&                   log                             = api.getLog();
1482         glu::Framebuffer                framebuffer             (gl);
1483         glu::Renderbuffer               renderbuffer    (gl);
1484
1485         log << tcu::TestLog::Message << "Modifying EGLImage with glClear to renderbuffer" << tcu::TestLog::EndMessage;
1486
1487         GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, *framebuffer));
1488         GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, *renderbuffer));
1489
1490         imageTargetRenderbuffer(api.m_egl, gl, **img);
1491
1492         initializeRbo(api, *renderbuffer, reference);
1493
1494         GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, 0));
1495         GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, 0));
1496
1497         GLU_CHECK_GLW_CALL(gl, finish());
1498
1499         return true;
1500 }
1501
1502 void GLESImageApi::ModifyRenderbufferClearColor::initializeRbo (GLESImageApi& api, GLuint renderbuffer, tcu::Texture2D& reference) const
1503 {
1504         const glw::Functions&   gl              = api.m_gl;
1505
1506         framebufferRenderbuffer(gl, GL_COLOR_ATTACHMENT0, renderbuffer);
1507
1508         GLU_CHECK_GLW_CALL(gl, viewport(0, 0, reference.getWidth(), reference.getHeight()));
1509         GLU_CHECK_GLW_CALL(gl, clearColor(m_color.x(), m_color.y(), m_color.z(), m_color.w()));
1510         GLU_CHECK_GLW_CALL(gl, clear(GL_COLOR_BUFFER_BIT));
1511
1512         tcu::clear(reference.getLevel(0), m_color);
1513 }
1514
1515 void GLESImageApi::ModifyRenderbufferClearDepth::initializeRbo (GLESImageApi& api, GLuint renderbuffer, tcu::Texture2D& reference) const
1516 {
1517         const glw::Functions&   gl              = api.m_gl;
1518
1519         framebufferRenderbuffer(gl, GL_DEPTH_ATTACHMENT, renderbuffer);
1520
1521         GLU_CHECK_GLW_CALL(gl, viewport(0, 0, reference.getWidth(), reference.getHeight()));
1522         GLU_CHECK_GLW_CALL(gl, clearDepthf(m_depth));
1523         GLU_CHECK_GLW_CALL(gl, clear(GL_DEPTH_BUFFER_BIT));
1524
1525         tcu::clearDepth(reference.getLevel(0), m_depth);
1526 }
1527
1528 void GLESImageApi::ModifyRenderbufferClearStencil::initializeRbo (GLESImageApi& api, GLuint renderbuffer, tcu::Texture2D& reference) const
1529 {
1530         const glw::Functions&   gl              = api.m_gl;
1531
1532         framebufferRenderbuffer(gl, GL_STENCIL_ATTACHMENT, renderbuffer);
1533
1534         GLU_CHECK_GLW_CALL(gl, viewport(0, 0, reference.getWidth(), reference.getHeight()));
1535         GLU_CHECK_GLW_CALL(gl, clearStencil(m_stencil));
1536         GLU_CHECK_GLW_CALL(gl, clear(GL_STENCIL_BUFFER_BIT));
1537
1538         tcu::clearStencil(reference.getLevel(0), m_stencil);
1539 }
1540
1541 class ImageFormatCase : public TestCase, private glu::CallLogWrapper
1542 {
1543 public:
1544                                                         ImageFormatCase         (EglTestContext& eglTestCtx, const TestSpec& spec);
1545                                                         ~ImageFormatCase        (void);
1546
1547         void                                    init                            (void);
1548         void                                    deinit                          (void);
1549         IterateResult                   iterate                         (void);
1550         void                                    checkExtensions         (void);
1551
1552 private:
1553         EGLConfig                               getConfig                       (void);
1554
1555         const TestSpec                  m_spec;
1556
1557         vector<ImageApi*>               m_apiContexts;
1558
1559         EGLDisplay                              m_display;
1560         eglu::NativeWindow*             m_window;
1561         EGLSurface                              m_surface;
1562         EGLConfig                               m_config;
1563         int                                             m_curIter;
1564         MovePtr<UniqueImage>    m_img;
1565         tcu::Texture2D                  m_refImg;
1566         glw::Functions                  m_gl;
1567 };
1568
1569 EGLConfig ImageFormatCase::getConfig (void)
1570 {
1571         const GLint             glesApi                 = m_spec.contexts[0] == TestSpec::API_GLES3 ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT;
1572         const EGLint    attribList[]    =
1573         {
1574                 EGL_RENDERABLE_TYPE,    glesApi,
1575                 EGL_SURFACE_TYPE,               EGL_WINDOW_BIT,
1576                 EGL_RED_SIZE,                   8,
1577                 EGL_BLUE_SIZE,                  8,
1578                 EGL_GREEN_SIZE,                 8,
1579                 EGL_ALPHA_SIZE,                 8,
1580                 EGL_DEPTH_SIZE,                 8,
1581                 EGL_NONE
1582         };
1583
1584         return eglu::chooseSingleConfig(m_eglTestCtx.getLibrary(), m_display, attribList);
1585 }
1586
1587 ImageFormatCase::ImageFormatCase (EglTestContext& eglTestCtx, const TestSpec& spec)
1588         : TestCase                              (eglTestCtx, spec.name.c_str(), spec.desc.c_str())
1589         , glu::CallLogWrapper   (m_gl, eglTestCtx.getTestContext().getLog())
1590         , m_spec                                (spec)
1591         , m_display                             (EGL_NO_DISPLAY)
1592         , m_window                              (DE_NULL)
1593         , m_surface                             (EGL_NO_SURFACE)
1594         , m_config                              (0)
1595         , m_curIter                             (0)
1596         , m_refImg                              (tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 1, 1)
1597 {
1598 }
1599
1600 ImageFormatCase::~ImageFormatCase (void)
1601 {
1602         deinit();
1603 }
1604
1605 void ImageFormatCase::checkExtensions (void)
1606 {
1607         set<string> exts = getSupportedExtensions(getLog(), m_eglTestCtx.getLibrary(), m_display, m_gl);
1608
1609         for (int operationNdx = 0; operationNdx < (int)m_spec.operations.size(); operationNdx++)
1610         {
1611                 const TestSpec::Operation&      op      = m_spec.operations[operationNdx];
1612                 const string                            ext     = op.action->getRequiredExtension();
1613
1614                 if (!de::contains(exts, ext))
1615                         TCU_THROW_EXPR(NotSupportedError, "Extension not supported", ext.c_str());
1616         }
1617 }
1618
1619 void ImageFormatCase::init (void)
1620 {
1621         const Library&                                          egl                             = m_eglTestCtx.getLibrary();
1622         const eglu::NativeWindowFactory&        windowFactory   = eglu::selectNativeWindowFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());
1623
1624         try
1625         {
1626                 m_display       = eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay());
1627
1628                 // GLES3 requires either EGL 1.5 or EGL_KHR_create_context extension.
1629                 if (m_spec.contexts[0] == TestSpec::API_GLES3 && eglu::getVersion(egl, m_display) < eglu::Version(1, 5))
1630                 {
1631                         set<string>                             exts;
1632                         const vector<string>    eglExts = eglu::getDisplayExtensions(egl, m_display);
1633                         exts.insert(eglExts.begin(), eglExts.end());
1634
1635                         if (!de::contains(exts, "EGL_KHR_create_context"))
1636                         {
1637                                 getLog() << tcu::TestLog::Message
1638                                                  << "EGL version is under 1.5 and the test is using OpenGL ES 3.2."
1639                                                  << "This requires EGL_KHR_create_context extension."
1640                                                  << tcu::TestLog::EndMessage;
1641                                 TCU_THROW(NotSupportedError, "Extension not supported: EGL_KHR_create_context");
1642                         }
1643                 }
1644
1645                 m_config        = getConfig();
1646                 m_window        = windowFactory.createWindow(&m_eglTestCtx.getNativeDisplay(), m_display, m_config, DE_NULL, eglu::WindowParams(480, 480, eglu::parseWindowVisibility(m_testCtx.getCommandLine())));
1647                 m_surface       = eglu::createWindowSurface(m_eglTestCtx.getNativeDisplay(), *m_window, m_display, m_config, DE_NULL);
1648
1649                 {
1650                         const char*     extensions[]    = { "GL_OES_EGL_image" };
1651                         int                     major                   = 2;
1652                         int                     minor                   = 0;
1653
1654                         if (m_spec.contexts[0] == TestSpec::API_GLES3)
1655                         {
1656                                 major = 3;
1657                                 minor = 2;
1658                         }
1659                         m_eglTestCtx.initGLFunctions(&m_gl, glu::ApiType::es(major, minor), DE_LENGTH_OF_ARRAY(extensions), &extensions[0]);
1660                 }
1661
1662                 for (int contextNdx = 0; contextNdx < (int)m_spec.contexts.size(); contextNdx++)
1663                 {
1664                         ImageApi* api = DE_NULL;
1665                         switch (m_spec.contexts[contextNdx])
1666                         {
1667                                 case TestSpec::API_GLES2:
1668                                 {
1669                                         api = new GLESImageApi(egl, m_gl, contextNdx, getLog(), m_display, m_surface, m_config, 2);
1670                                         break;
1671                                 }
1672
1673                                 case TestSpec::API_GLES3:
1674                                 {
1675                                         api = new GLESImageApi(egl, m_gl, contextNdx, getLog(), m_display, m_surface, m_config, 3);
1676                                         break;
1677                                 }
1678
1679                                 default:
1680                                         DE_ASSERT(false);
1681                                         break;
1682                         }
1683                         m_apiContexts.push_back(api);
1684                 }
1685                 checkExtensions();
1686         }
1687         catch (...)
1688         {
1689                 deinit();
1690                 throw;
1691         }
1692 }
1693
1694 void ImageFormatCase::deinit (void)
1695 {
1696         const Library& egl = m_eglTestCtx.getLibrary();
1697
1698         m_img.clear();
1699
1700         for (int contexNdx = 0 ; contexNdx < (int)m_apiContexts.size(); contexNdx++)
1701                 delete m_apiContexts[contexNdx];
1702
1703         m_apiContexts.clear();
1704
1705         if (m_surface != EGL_NO_SURFACE)
1706         {
1707                 egl.destroySurface(m_display, m_surface);
1708                 m_surface = EGL_NO_SURFACE;
1709         }
1710
1711         delete m_window;
1712         m_window = DE_NULL;
1713
1714         if (m_display != EGL_NO_DISPLAY)
1715         {
1716                 egl.terminate(m_display);
1717                 m_display = EGL_NO_DISPLAY;
1718         }
1719 }
1720
1721 TestCase::IterateResult ImageFormatCase::iterate (void)
1722 {
1723         const TestSpec::Operation&      op              = m_spec.operations[m_curIter++];
1724         ImageApi&                                       api             = *m_apiContexts[op.apiIndex];
1725         const bool                                      isOk    = op.action->invoke(api, m_img, m_refImg);
1726
1727         if (isOk && m_curIter < (int)m_spec.operations.size())
1728                 return CONTINUE;
1729         else if (isOk)
1730                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1731         else
1732                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1733
1734         return STOP;
1735 }
1736
1737 struct LabeledAction
1738 {
1739         string                  label;
1740         MovePtr<Action> action;
1741 };
1742
1743 // A simple vector mockup that we need because MovePtr isn't copy-constructible.
1744 struct LabeledActions
1745 {
1746                                         LabeledActions  (void) : m_numActions(0){}
1747         LabeledAction&  operator[]              (int ndx)                               { DE_ASSERT(0 <= ndx && ndx < m_numActions); return m_actions[ndx]; }
1748         void                    add                             (const string& label, MovePtr<Action> action);
1749         int                             size                    (void) const                    { return m_numActions; }
1750 private:
1751         LabeledAction   m_actions[64];
1752         int                             m_numActions;
1753 };
1754
1755 void LabeledActions::add (const string& label, MovePtr<Action> action)
1756 {
1757         DE_ASSERT(m_numActions < DE_LENGTH_OF_ARRAY(m_actions));
1758         m_actions[m_numActions].label = label;
1759         m_actions[m_numActions].action = action;
1760         ++m_numActions;
1761 }
1762
1763 class ImageTests : public TestCaseGroup
1764 {
1765 protected:
1766                                         ImageTests                                              (EglTestContext& eglTestCtx, const string& name, const string& desc)
1767                                                 : TestCaseGroup(eglTestCtx, name.c_str(), desc.c_str()) {}
1768
1769         void                    addCreateTexture                                (const string& name, EGLenum source, GLenum internalFormat, GLenum format, GLenum type);
1770         void                    addCreateRenderbuffer                   (const string& name, GLenum format);
1771         void                    addCreateAndroidNative                  (const string& name, GLenum format, bool isYUV);
1772         void                    addCreateAndroidNativeArray             (const string& name, GLenum format, deUint32 numLayers);
1773         void                    addCreateTexture2DActions               (const string& prefix);
1774         void                    addCreateTextureCubemapActions  (const string& suffix, GLenum internalFormat, GLenum format, GLenum type);
1775         void                    addCreateRenderbufferActions    (void);
1776         void                    addCreateAndroidNativeActions   (void);
1777
1778         LabeledActions  m_createActions;
1779 };
1780
1781 void ImageTests::addCreateTexture (const string& name, EGLenum source, GLenum internalFormat, GLenum format, GLenum type)
1782 {
1783         m_createActions.add(name, MovePtr<Action>(new GLESImageApi::Create(createTextureImageSource(source, internalFormat, format, type))));
1784 }
1785
1786 void ImageTests::addCreateRenderbuffer (const string& name, GLenum format)
1787 {
1788         m_createActions.add(name, MovePtr<Action>(new GLESImageApi::Create(createRenderbufferImageSource(format))));
1789 }
1790
1791 void ImageTests::addCreateAndroidNative (const string& name, GLenum format, bool isYUV = false)
1792 {
1793         m_createActions.add(name, MovePtr<Action>(new GLESImageApi::Create(createAndroidNativeImageSource(format, 1u, isYUV))));
1794 }
1795
1796 void ImageTests::addCreateAndroidNativeArray (const string& name, GLenum format, deUint32 numLayers)
1797 {
1798         m_createActions.add(name, MovePtr<Action>(new GLESImageApi::Create(createAndroidNativeImageSource(format, numLayers, false), numLayers)));
1799 }
1800
1801 void ImageTests::addCreateTexture2DActions (const string& prefix)
1802 {
1803         addCreateTexture(prefix + "rgb8",               EGL_GL_TEXTURE_2D_KHR,  GL_RGB,         GL_RGB,         GL_UNSIGNED_BYTE);
1804         addCreateTexture(prefix + "rgb565",             EGL_GL_TEXTURE_2D_KHR,  GL_RGB,         GL_RGB,         GL_UNSIGNED_SHORT_5_6_5);
1805         addCreateTexture(prefix + "rgba8",              EGL_GL_TEXTURE_2D_KHR,  GL_RGBA,        GL_RGBA,        GL_UNSIGNED_BYTE);
1806         addCreateTexture(prefix + "rgb5_a1",    EGL_GL_TEXTURE_2D_KHR,  GL_RGBA,        GL_RGBA,        GL_UNSIGNED_SHORT_5_5_5_1);
1807         addCreateTexture(prefix + "rgba4",              EGL_GL_TEXTURE_2D_KHR,  GL_RGBA,        GL_RGBA,        GL_UNSIGNED_SHORT_4_4_4_4);
1808 }
1809
1810 void ImageTests::addCreateTextureCubemapActions (const string& suffix, GLenum internalFormat, GLenum format, GLenum type)
1811 {
1812         addCreateTexture("cubemap_positive_x" + suffix, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR, internalFormat, format, type);
1813         addCreateTexture("cubemap_positive_y" + suffix, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR, internalFormat, format, type);
1814         addCreateTexture("cubemap_positive_z" + suffix, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR, internalFormat, format, type);
1815         addCreateTexture("cubemap_negative_x" + suffix, EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR, internalFormat, format, type);
1816         addCreateTexture("cubemap_negative_y" + suffix, EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR, internalFormat, format, type);
1817         addCreateTexture("cubemap_negative_z" + suffix, EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR, internalFormat, format, type);
1818 }
1819
1820 void ImageTests::addCreateRenderbufferActions (void)
1821 {
1822         addCreateRenderbuffer("renderbuffer_rgba4",             GL_RGBA4);
1823         addCreateRenderbuffer("renderbuffer_rgb5_a1",   GL_RGB5_A1);
1824         addCreateRenderbuffer("renderbuffer_rgb565",    GL_RGB565);
1825         addCreateRenderbuffer("renderbuffer_depth16",   GL_DEPTH_COMPONENT16);
1826         addCreateRenderbuffer("renderbuffer_stencil",   GL_STENCIL_INDEX8);
1827 }
1828
1829 void ImageTests::addCreateAndroidNativeActions (void)
1830 {
1831         addCreateAndroidNative("android_native_rgba4",          GL_RGBA4);
1832         addCreateAndroidNative("android_native_rgb5_a1",        GL_RGB5_A1);
1833         addCreateAndroidNative("android_native_rgb565",         GL_RGB565);
1834         addCreateAndroidNative("android_native_rgb8",           GL_RGB8);
1835         addCreateAndroidNative("android_native_rgba8",          GL_RGBA8);
1836         addCreateAndroidNative("android_native_d16",            GL_DEPTH_COMPONENT16);
1837         addCreateAndroidNative("android_native_d24",            GL_DEPTH_COMPONENT24);
1838         addCreateAndroidNative("android_native_d24s8",          GL_DEPTH24_STENCIL8);
1839         addCreateAndroidNative("android_native_d32f",           GL_DEPTH_COMPONENT32F);
1840         addCreateAndroidNative("android_native_d32fs8",         GL_DEPTH32F_STENCIL8);
1841         addCreateAndroidNative("android_native_rgb10a2",        GL_RGB10_A2);
1842         addCreateAndroidNative("android_native_rgba16f",        GL_RGBA16F);
1843         addCreateAndroidNative("android_native_s8",                     GL_STENCIL_INDEX8);
1844         addCreateAndroidNative("android_native_yuv420",         GL_RGBA8, true);
1845
1846         addCreateAndroidNativeArray("android_native_array_rgba4",       GL_RGBA4,       4u);
1847         addCreateAndroidNativeArray("android_native_array_rgb5_a1",     GL_RGB5_A1,     4u);
1848         addCreateAndroidNativeArray("android_native_array_rgb565",      GL_RGB565,      4u);
1849         addCreateAndroidNativeArray("android_native_array_rgb8",        GL_RGB8,        4u);
1850         addCreateAndroidNativeArray("android_native_array_rgba8",       GL_RGBA8,       4u);
1851 }
1852
1853 class RenderTests : public ImageTests
1854 {
1855 protected:
1856                                                                                         RenderTests                             (EglTestContext& eglTestCtx, const string& name, const string& desc)
1857                                                                                                 : ImageTests                    (eglTestCtx, name, desc) {}
1858
1859         void                                                                    addRenderActions                (void);
1860         LabeledActions                                                  m_renderActions;
1861 };
1862
1863 void RenderTests::addRenderActions (void)
1864 {
1865         m_renderActions.add("texture",                  MovePtr<Action>(new GLESImageApi::RenderTexture2D()));
1866         m_renderActions.add("texture_array",    MovePtr<Action>(new GLESImageApi::RenderTexture2DArray()));
1867         m_renderActions.add("read_pixels",              MovePtr<Action>(new GLESImageApi::RenderReadPixelsRenderbuffer()));
1868         m_renderActions.add("depth_buffer",             MovePtr<Action>(new GLESImageApi::RenderDepthbuffer()));
1869         m_renderActions.add("stencil_buffer",   MovePtr<Action>(new GLESImageApi::RenderStencilbuffer()));
1870         m_renderActions.add("yuv_texture",              MovePtr<Action>(new GLESImageApi::RenderYUVTexture()));
1871         m_renderActions.add("render_sample_texture_array",    MovePtr<Action>(new GLESImageApi::RenderSampleTexture2DArray()));
1872 }
1873
1874 class SimpleCreationTests : public RenderTests
1875 {
1876 public:
1877                         SimpleCreationTests             (EglTestContext& eglTestCtx, const string& name, const string& desc) : RenderTests(eglTestCtx, name, desc) {}
1878         void    init                                    (void);
1879 };
1880
1881 bool isDepthFormat (GLenum format)
1882 {
1883         switch (format)
1884         {
1885                 case GL_RGB:
1886                 case GL_RGB8:
1887                 case GL_RGB565:
1888                 case GL_RGBA:
1889                 case GL_RGBA4:
1890                 case GL_RGBA8:
1891                 case GL_RGB5_A1:
1892                 case GL_RGB10_A2:
1893                 case GL_RGBA16F:
1894                         return false;
1895
1896                 case GL_DEPTH_COMPONENT16:
1897                 case GL_DEPTH_COMPONENT24:
1898                 case GL_DEPTH_COMPONENT32:
1899                 case GL_DEPTH_COMPONENT32F:
1900                 case GL_DEPTH24_STENCIL8:
1901                 case GL_DEPTH32F_STENCIL8:
1902                         return true;
1903
1904                 case GL_STENCIL_INDEX8:
1905                         return false;
1906
1907                 default:
1908                         DE_ASSERT(false);
1909                         return false;
1910         }
1911 }
1912
1913 bool isStencilFormat (GLenum format)
1914 {
1915         switch (format)
1916         {
1917                 case GL_RGB:
1918                 case GL_RGB8:
1919                 case GL_RGB565:
1920                 case GL_RGBA:
1921                 case GL_RGBA4:
1922                 case GL_RGBA8:
1923                 case GL_RGB5_A1:
1924                 case GL_RGB10_A2:
1925                 case GL_RGBA16F:
1926                         return false;
1927
1928                 case GL_DEPTH_COMPONENT16:
1929                 case GL_DEPTH_COMPONENT24:
1930                 case GL_DEPTH_COMPONENT32:
1931                 case GL_DEPTH_COMPONENT32F:
1932                         return false;
1933
1934                 case GL_STENCIL_INDEX8:
1935                 case GL_DEPTH24_STENCIL8:
1936                 case GL_DEPTH32F_STENCIL8:
1937                         return true;
1938
1939                 default:
1940                         DE_ASSERT(false);
1941                         return false;
1942         }
1943 }
1944
1945 bool isCompatibleCreateAndRenderActions (const Action& create, const Action& render)
1946 {
1947         if (const GLESImageApi::Create* glesCreate = dynamic_cast<const GLESImageApi::Create*>(&create))
1948         {
1949                 bool  yuvFormatTest = glesCreate->isYUVFormatImage();
1950                 // this path only for none-yuv format tests
1951                 if(!yuvFormatTest)
1952                 {
1953                     const GLenum createFormat = glesCreate->getEffectiveFormat();
1954
1955                         if (dynamic_cast<const GLESImageApi::RenderTexture2DArray*>(&render))
1956                         {
1957                                 // Makes sense only for texture arrays.
1958                                 if (glesCreate->getNumLayers() <= 1u)
1959                                         return false;
1960                         }
1961                         else if (glesCreate->getNumLayers() != 1u)
1962                         {
1963                                 // Skip other render actions for texture arrays.
1964                                 return false;
1965                         }
1966
1967                         if (dynamic_cast<const GLESImageApi::RenderTexture2D*>(&render))
1968                         {
1969                                 // GLES does not have depth or stencil textures
1970                                 if (isDepthFormat(createFormat) || isStencilFormat(createFormat))
1971                                         return false;
1972                         }
1973
1974                         if (dynamic_cast<const GLESImageApi::RenderReadPixelsRenderbuffer*>(&render))
1975                         {
1976                                 // GLES does not support readPixels for depth or stencil.
1977                                 if (isDepthFormat(createFormat) || isStencilFormat(createFormat))
1978                                         return false;
1979                         }
1980
1981                         if (dynamic_cast<const GLESImageApi::RenderDepthbuffer*>(&render))
1982                         {
1983                                 // Copying non-depth data to depth renderbuffer and expecting meaningful
1984                                 // results just doesn't make any sense.
1985                                 if (!isDepthFormat(createFormat))
1986                                         return false;
1987                         }
1988
1989                         if (dynamic_cast<const GLESImageApi::RenderStencilbuffer*>(&render))
1990                         {
1991                                 // Copying non-stencil data to stencil renderbuffer and expecting meaningful
1992                                 // results just doesn't make any sense.
1993                                 if (!isStencilFormat(createFormat))
1994                                         return false;
1995                         }
1996
1997                         if (dynamic_cast<const GLESImageApi::RenderYUVTexture*>(&render))
1998                         {
1999                                 // In yuv path rendering with non-yuv format native buffer and expecting meaningful
2000                                 // results just doesn't make any sense
2001                                 return false;
2002                         }
2003
2004                         return true;
2005                 }
2006                 else if (dynamic_cast<const GLESImageApi::RenderYUVTexture*>(&render))
2007                 {
2008                         return true;
2009                 }
2010         }
2011         else
2012                 DE_ASSERT(false);
2013
2014         return false;
2015 }
2016
2017 void SimpleCreationTests::init (void)
2018 {
2019         addCreateTexture2DActions("texture_");
2020         addCreateTextureCubemapActions("_rgba", GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
2021         addCreateTextureCubemapActions("_rgb", GL_RGB, GL_RGB, GL_UNSIGNED_BYTE);
2022         addCreateRenderbufferActions();
2023         addCreateAndroidNativeActions();
2024         addRenderActions();
2025
2026         for (int createNdx = 0; createNdx < m_createActions.size(); createNdx++)
2027         {
2028                 const LabeledAction& createAction = m_createActions[createNdx];
2029
2030                 for (int renderNdx = 0; renderNdx < m_renderActions.size(); renderNdx++)
2031                 {
2032                         const LabeledAction&    renderAction    = m_renderActions[renderNdx];
2033                         TestSpec                                spec;
2034
2035                         if (!isCompatibleCreateAndRenderActions(*createAction.action, *renderAction.action))
2036                                 continue;
2037
2038                         if (dynamic_cast<const GLESImageApi::RenderTexture2DArray*>(renderAction.action.get()) ||
2039                                 dynamic_cast<const GLESImageApi::RenderYUVTexture*>(renderAction.action.get()) ||
2040                                 dynamic_cast<const GLESImageApi::RenderSampleTexture2DArray*>(renderAction.action.get()))
2041                         {
2042                                 // Texture array tests require GLES3.
2043                                 spec.name = std::string("gles3_") + createAction.label + "_" + renderAction.label;
2044                                 spec.contexts.push_back(TestSpec::API_GLES3);
2045                         }
2046                         else
2047                         {
2048                                 spec.name = std::string("gles2_") + createAction.label + "_" + renderAction.label;
2049                                 spec.contexts.push_back(TestSpec::API_GLES2);
2050                         }
2051
2052                         spec.desc = spec.name;
2053                         spec.operations.push_back(TestSpec::Operation(0, *createAction.action));
2054                         spec.operations.push_back(TestSpec::Operation(0, *renderAction.action));
2055
2056                         addChild(new ImageFormatCase(m_eglTestCtx, spec));
2057                 }
2058         }
2059 }
2060
2061 TestCaseGroup* createSimpleCreationTests (EglTestContext& eglTestCtx, const string& name, const string& desc)
2062 {
2063         return new SimpleCreationTests(eglTestCtx, name, desc);
2064 }
2065
2066 bool isCompatibleFormats (GLenum createFormat, GLenum modifyFormat, GLenum modifyType)
2067 {
2068         switch (modifyFormat)
2069         {
2070                 case GL_RGB:
2071                         switch (modifyType)
2072                         {
2073                                 case GL_UNSIGNED_BYTE:
2074                                         return createFormat == GL_RGB
2075                                                         || createFormat == GL_RGB8
2076                                                         || createFormat == GL_RGB565
2077                                                         || createFormat == GL_SRGB8;
2078
2079                                 case GL_BYTE:
2080                                         return createFormat == GL_RGB8_SNORM;
2081
2082                                 case GL_UNSIGNED_SHORT_5_6_5:
2083                                         return createFormat == GL_RGB
2084                                                         || createFormat == GL_RGB565;
2085
2086                                 case GL_UNSIGNED_INT_10F_11F_11F_REV:
2087                                         return createFormat == GL_R11F_G11F_B10F;
2088
2089                                 case GL_UNSIGNED_INT_5_9_9_9_REV:
2090                                         return createFormat == GL_RGB9_E5;
2091
2092                                 case GL_HALF_FLOAT:
2093                                         return createFormat == GL_RGB16F
2094                                                         || createFormat == GL_R11F_G11F_B10F
2095                                                         || createFormat == GL_RGB9_E5;
2096
2097                                 case GL_FLOAT:
2098                                         return createFormat == GL_RGB16F
2099                                                         || createFormat == GL_RGB32F
2100                                                         || createFormat == GL_R11F_G11F_B10F
2101                                                         || createFormat == GL_RGB9_E5;
2102
2103                                 default:
2104                                         DE_FATAL("Unknown modify type");
2105                                         return false;
2106                         }
2107
2108                 case GL_RGBA:
2109                         switch (modifyType)
2110                         {
2111                                 case GL_UNSIGNED_BYTE:
2112                                         return createFormat == GL_RGBA8
2113                                                 || createFormat == GL_RGB5_A1
2114                                                 || createFormat == GL_RGBA4
2115                                                 || createFormat == GL_SRGB8_ALPHA8
2116                                                 || createFormat == GL_RGBA;
2117
2118                                 case GL_UNSIGNED_SHORT_4_4_4_4:
2119                                         return createFormat == GL_RGBA4
2120                                                 || createFormat == GL_RGBA;
2121
2122                                 case GL_UNSIGNED_SHORT_5_5_5_1:
2123                                         return createFormat == GL_RGB5_A1
2124                                                 || createFormat == GL_RGBA;
2125
2126                                 case GL_UNSIGNED_INT_2_10_10_10_REV:
2127                                         return createFormat == GL_RGB10_A2
2128                                                 || createFormat == GL_RGB5_A1;
2129
2130                                 case GL_HALF_FLOAT:
2131                                         return createFormat == GL_RGBA16F;
2132
2133                                 case GL_FLOAT:
2134                                         return createFormat == GL_RGBA16F
2135                                                 || createFormat == GL_RGBA32F;
2136
2137                                 default:
2138                                         DE_FATAL("Unknown modify type");
2139                                         return false;
2140                         }
2141
2142                 default:
2143                         DE_FATAL("Unknown modify format");
2144                         return false;
2145         }
2146 }
2147
2148 bool isCompatibleCreateAndModifyActions (const Action& create, const Action& modify)
2149 {
2150         if (const GLESImageApi::Create* glesCreate = dynamic_cast<const GLESImageApi::Create*>(&create))
2151         {
2152                 // No modify tests for texture arrays.
2153                 if (glesCreate->getNumLayers() > 1u)
2154                         return false;
2155                 // No modify tests for yuv format image.
2156                 if (glesCreate->isYUVFormatImage())
2157                         return false;
2158
2159                 const GLenum createFormat = glesCreate->getEffectiveFormat();
2160
2161                 if (const GLESImageApi::ModifyTexSubImage* glesTexSubImageModify = dynamic_cast<const GLESImageApi::ModifyTexSubImage*>(&modify))
2162                 {
2163                         const GLenum modifyFormat       = glesTexSubImageModify->getFormat();
2164                         const GLenum modifyType         = glesTexSubImageModify->getType();
2165
2166                         return isCompatibleFormats(createFormat, modifyFormat, modifyType);
2167                 }
2168
2169                 if (dynamic_cast<const GLESImageApi::ModifyRenderbufferClearColor*>(&modify))
2170                 {
2171                         // reintepreting color as non-color is not meaningful
2172                         if (isDepthFormat(createFormat) || isStencilFormat(createFormat))
2173                                 return false;
2174                 }
2175
2176                 if (dynamic_cast<const GLESImageApi::ModifyRenderbufferClearDepth*>(&modify))
2177                 {
2178                         // reintepreting depth as non-depth is not meaningful
2179                         if (!isDepthFormat(createFormat))
2180                                 return false;
2181                 }
2182
2183                 if (dynamic_cast<const GLESImageApi::ModifyRenderbufferClearStencil*>(&modify))
2184                 {
2185                         // reintepreting stencil as non-stencil is not meaningful
2186                         if (!isStencilFormat(createFormat))
2187                                 return false;
2188                 }
2189
2190                 return true;
2191         }
2192         else
2193                 DE_ASSERT(false);
2194
2195         return false;
2196 }
2197
2198 class MultiContextRenderTests : public RenderTests
2199 {
2200 public:
2201                                         MultiContextRenderTests         (EglTestContext& eglTestCtx, const string& name, const string& desc);
2202         void                    init                                            (void);
2203         void                    addClearActions                         (void);
2204 private:
2205         LabeledActions  m_clearActions;
2206 };
2207
2208 MultiContextRenderTests::MultiContextRenderTests (EglTestContext& eglTestCtx, const string& name, const string& desc)
2209         : RenderTests   (eglTestCtx, name, desc)
2210 {
2211 }
2212
2213 void MultiContextRenderTests::addClearActions (void)
2214 {
2215         m_clearActions.add("clear_color",       MovePtr<Action>(new GLESImageApi::ModifyRenderbufferClearColor(tcu::Vec4(0.8f, 0.2f, 0.9f, 1.0f))));
2216         m_clearActions.add("clear_depth",       MovePtr<Action>(new GLESImageApi::ModifyRenderbufferClearDepth(0.75f)));
2217         m_clearActions.add("clear_stencil",     MovePtr<Action>(new GLESImageApi::ModifyRenderbufferClearStencil(97)));
2218 }
2219
2220 void MultiContextRenderTests::init (void)
2221 {
2222         addCreateTexture2DActions("texture_");
2223         addCreateTextureCubemapActions("_rgba8", GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
2224         addCreateTextureCubemapActions("_rgb8", GL_RGB, GL_RGB, GL_UNSIGNED_BYTE);
2225         addCreateRenderbufferActions();
2226         addCreateAndroidNativeActions();
2227         addRenderActions();
2228         addClearActions();
2229
2230         for (int createNdx = 0; createNdx < m_createActions.size(); createNdx++)
2231         for (int renderNdx = 0; renderNdx < m_renderActions.size(); renderNdx++)
2232         for (int clearNdx = 0; clearNdx < m_clearActions.size(); clearNdx++)
2233         {
2234                 const LabeledAction&    createAction    = m_createActions[createNdx];
2235                 const LabeledAction&    renderAction    = m_renderActions[renderNdx];
2236                 const LabeledAction&    clearAction             = m_clearActions[clearNdx];
2237                 TestSpec                                spec;
2238
2239                 if (!isCompatibleCreateAndRenderActions(*createAction.action, *renderAction.action))
2240                         continue;
2241                 if (!isCompatibleCreateAndModifyActions(*createAction.action, *clearAction.action))
2242                         continue;
2243
2244                 spec.name = std::string("gles2_") + createAction.label + "_" + renderAction.label;
2245
2246                 const GLESImageApi::Create* glesCreate = dynamic_cast<const GLESImageApi::Create*>(createAction.action.get());
2247
2248                 if (!glesCreate)
2249                         DE_FATAL("Dynamic casting to GLESImageApi::Create* failed");
2250
2251                 const GLenum createFormat = glesCreate->getEffectiveFormat();
2252
2253                 if (isDepthFormat(createFormat) && isStencilFormat(createFormat))
2254                 {
2255                         // Combined depth and stencil format. Add the clear action label to avoid test
2256                         // name clashes.
2257                         spec.name += std::string("_") + clearAction.label;
2258                 }
2259
2260                 spec.desc = spec.name;
2261
2262                 spec.contexts.push_back(TestSpec::API_GLES2);
2263                 spec.contexts.push_back(TestSpec::API_GLES2);
2264
2265                 spec.operations.push_back(TestSpec::Operation(0, *createAction.action));
2266                 spec.operations.push_back(TestSpec::Operation(0, *renderAction.action));
2267                 spec.operations.push_back(TestSpec::Operation(0, *clearAction.action));
2268                 spec.operations.push_back(TestSpec::Operation(1, *createAction.action));
2269                 spec.operations.push_back(TestSpec::Operation(0, *renderAction.action));
2270                 spec.operations.push_back(TestSpec::Operation(1, *renderAction.action));
2271
2272                 addChild(new ImageFormatCase(m_eglTestCtx, spec));
2273         }
2274 }
2275
2276 TestCaseGroup* createMultiContextRenderTests (EglTestContext& eglTestCtx, const string& name, const string& desc)
2277 {
2278         return new MultiContextRenderTests(eglTestCtx, name, desc);
2279 }
2280
2281 class ModifyTests : public ImageTests
2282 {
2283 public:
2284                                                                 ModifyTests             (EglTestContext& eglTestCtx, const string& name, const string& desc)
2285                                                                         : ImageTests(eglTestCtx, name, desc) {}
2286
2287         void                                            init                    (void);
2288
2289 protected:
2290         void                                            addModifyActions(void);
2291
2292         LabeledActions                          m_modifyActions;
2293         GLESImageApi::RenderTryAll      m_renderAction;
2294 };
2295
2296 void ModifyTests::addModifyActions (void)
2297 {
2298         m_modifyActions.add("tex_subimage_rgb8",                        MovePtr<Action>(new GLESImageApi::ModifyTexSubImage(GL_RGB,             GL_UNSIGNED_BYTE)));
2299         m_modifyActions.add("tex_subimage_rgb565",                      MovePtr<Action>(new GLESImageApi::ModifyTexSubImage(GL_RGB,             GL_UNSIGNED_SHORT_5_6_5)));
2300         m_modifyActions.add("tex_subimage_rgba8",                       MovePtr<Action>(new GLESImageApi::ModifyTexSubImage(GL_RGBA,    GL_UNSIGNED_BYTE)));
2301         m_modifyActions.add("tex_subimage_rgb5_a1",                     MovePtr<Action>(new GLESImageApi::ModifyTexSubImage(GL_RGBA,    GL_UNSIGNED_SHORT_5_5_5_1)));
2302         m_modifyActions.add("tex_subimage_rgba4",                       MovePtr<Action>(new GLESImageApi::ModifyTexSubImage(GL_RGBA,    GL_UNSIGNED_SHORT_4_4_4_4)));
2303
2304         m_modifyActions.add("renderbuffer_clear_color",         MovePtr<Action>(new GLESImageApi::ModifyRenderbufferClearColor(tcu::Vec4(0.3f, 0.5f, 0.3f, 1.0f))));
2305         m_modifyActions.add("renderbuffer_clear_depth",         MovePtr<Action>(new GLESImageApi::ModifyRenderbufferClearDepth(0.7f)));
2306         m_modifyActions.add("renderbuffer_clear_stencil",       MovePtr<Action>(new GLESImageApi::ModifyRenderbufferClearStencil(78)));
2307 }
2308
2309 void ModifyTests::init (void)
2310 {
2311         addCreateTexture2DActions("tex_");
2312         addCreateRenderbufferActions();
2313         addCreateAndroidNativeActions();
2314         addModifyActions();
2315
2316         for (int createNdx = 0; createNdx < m_createActions.size(); createNdx++)
2317         {
2318                 LabeledAction& createAction = m_createActions[createNdx];
2319
2320                 for (int modifyNdx = 0; modifyNdx < m_modifyActions.size(); modifyNdx++)
2321                 {
2322                         LabeledAction& modifyAction = m_modifyActions[modifyNdx];
2323
2324                         if (!isCompatibleCreateAndModifyActions(*createAction.action, *modifyAction.action))
2325                                 continue;
2326
2327                         TestSpec spec;
2328                         spec.name = createAction.label + "_" + modifyAction.label;
2329                         spec.desc = "gles2_tex_sub_image";
2330
2331                         spec.contexts.push_back(TestSpec::API_GLES2);
2332
2333                         spec.operations.push_back(TestSpec::Operation(0, *createAction.action));
2334                         spec.operations.push_back(TestSpec::Operation(0, m_renderAction));
2335                         spec.operations.push_back(TestSpec::Operation(0, *modifyAction.action));
2336                         spec.operations.push_back(TestSpec::Operation(0, m_renderAction));
2337
2338                         addChild(new ImageFormatCase(m_eglTestCtx, spec));
2339                 }
2340         }
2341 }
2342
2343 TestCaseGroup* createModifyTests (EglTestContext& eglTestCtx, const string& name, const string& desc)
2344 {
2345         return new ModifyTests(eglTestCtx, name, desc);
2346 }
2347
2348 } // Image
2349 } // egl
2350 } // deqp