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