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