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