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