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