xref: /aosp_15_r20/external/deqp/modules/egl/teglImageUtil.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 Common utilities for EGL images.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "teglImageUtil.hpp"
25 
26 #include "tcuTexture.hpp"
27 #include "tcuTextureUtil.hpp"
28 
29 #include "egluGLUtil.hpp"
30 #include "egluNativeWindow.hpp"
31 #include "egluNativePixmap.hpp"
32 
33 #include "eglwLibrary.hpp"
34 #include "eglwEnums.hpp"
35 
36 #include "glwEnums.hpp"
37 
38 #include "gluObjectWrapper.hpp"
39 #include "gluTextureUtil.hpp"
40 
41 namespace deqp
42 {
43 namespace egl
44 {
45 namespace Image
46 {
47 
48 using std::string;
49 using std::vector;
50 
51 using de::MovePtr;
52 using de::UniquePtr;
53 
54 using tcu::Texture2D;
55 using tcu::TextureFormat;
56 using tcu::Vec4;
57 
58 using glu::Framebuffer;
59 using glu::Texture;
60 
61 using eglu::AttribMap;
62 using eglu::NativeDisplay;
63 using eglu::NativeDisplayFactory;
64 using eglu::NativePixmap;
65 using eglu::NativePixmapFactory;
66 using eglu::NativeWindow;
67 using eglu::NativeWindowFactory;
68 using eglu::UniqueSurface;
69 using eglu::WindowParams;
70 
71 using namespace glw;
72 using namespace eglw;
73 
74 enum
75 {
76     IMAGE_WIDTH  = 64,
77     IMAGE_HEIGHT = 64,
78 };
79 
80 template <typename T>
81 struct NativeSurface : public ManagedSurface
82 {
83 public:
NativeSurfacedeqp::egl::Image::NativeSurface84     explicit NativeSurface(MovePtr<UniqueSurface> surface, MovePtr<T> native)
85         : ManagedSurface(surface)
86         , m_native(native)
87     {
88     }
89 
90 private:
91     UniquePtr<T> m_native;
92 };
93 
94 typedef NativeSurface<NativeWindow> NativeWindowSurface;
95 typedef NativeSurface<NativePixmap> NativePixmapSurface;
96 
createSurface(EglTestContext & eglTestCtx,EGLDisplay dpy,EGLConfig config,int width,int height)97 MovePtr<ManagedSurface> createSurface(EglTestContext &eglTestCtx, EGLDisplay dpy, EGLConfig config, int width,
98                                       int height)
99 {
100     const Library &egl                         = eglTestCtx.getLibrary();
101     EGLint surfaceTypeBits                     = eglu::getConfigAttribInt(egl, dpy, config, EGL_SURFACE_TYPE);
102     const NativeDisplayFactory &displayFactory = eglTestCtx.getNativeDisplayFactory();
103     NativeDisplay &nativeDisplay               = eglTestCtx.getNativeDisplay();
104 
105     if (surfaceTypeBits & EGL_PBUFFER_BIT)
106     {
107         static const EGLint attribs[] = {EGL_WIDTH, width, EGL_HEIGHT, height, EGL_NONE};
108         const EGLSurface surface      = egl.createPbufferSurface(dpy, config, attribs);
109 
110         EGLU_CHECK_MSG(egl, "eglCreatePbufferSurface()");
111 
112         return de::newMovePtr<ManagedSurface>(MovePtr<UniqueSurface>(new UniqueSurface(egl, dpy, surface)));
113     }
114     else if (surfaceTypeBits & EGL_WINDOW_BIT)
115     {
116         const NativeWindowFactory &windowFactory =
117             selectNativeWindowFactory(displayFactory, eglTestCtx.getTestContext().getCommandLine());
118 
119         MovePtr<NativeWindow> window(windowFactory.createWindow(
120             &nativeDisplay, dpy, config, DE_NULL, WindowParams(width, height, WindowParams::VISIBILITY_DONT_CARE)));
121         const EGLSurface surface = eglu::createWindowSurface(nativeDisplay, *window, dpy, config, DE_NULL);
122 
123         return MovePtr<ManagedSurface>(
124             new NativeWindowSurface(MovePtr<UniqueSurface>(new UniqueSurface(egl, dpy, surface)), window));
125     }
126     else if (surfaceTypeBits & EGL_PIXMAP_BIT)
127     {
128         const NativePixmapFactory &pixmapFactory =
129             selectNativePixmapFactory(displayFactory, eglTestCtx.getTestContext().getCommandLine());
130 
131         MovePtr<NativePixmap> pixmap(pixmapFactory.createPixmap(&nativeDisplay, dpy, config, DE_NULL, width, height));
132         const EGLSurface surface =
133             eglu::createPixmapSurface(eglTestCtx.getNativeDisplay(), *pixmap, dpy, config, DE_NULL);
134 
135         return MovePtr<ManagedSurface>(
136             new NativePixmapSurface(MovePtr<UniqueSurface>(new UniqueSurface(egl, dpy, surface)), pixmap));
137     }
138     else
139         TCU_FAIL("No valid surface types supported in config");
140 }
141 
142 class GLClientBuffer : public ClientBuffer
143 {
get(void) const144     EGLClientBuffer get(void) const
145     {
146         return reinterpret_cast<EGLClientBuffer>(static_cast<uintptr_t>(getName()));
147     }
148 
149 protected:
150     virtual GLuint getName(void) const = 0;
151 };
152 
153 class TextureClientBuffer : public GLClientBuffer
154 {
155 public:
TextureClientBuffer(const glw::Functions & gl)156     TextureClientBuffer(const glw::Functions &gl) : m_texture(gl)
157     {
158     }
getName(void) const159     GLuint getName(void) const
160     {
161         return *m_texture;
162     }
163 
164 private:
165     glu::Texture m_texture;
166 };
167 
168 class GLImageSource : public ImageSource
169 {
170 public:
171     EGLImageKHR createImage(const Library &egl, EGLDisplay dpy, EGLContext ctx, EGLClientBuffer clientBuffer) const;
172 
173 protected:
174     virtual AttribMap getCreateAttribs(void) const = 0;
175     virtual EGLenum getSource(void) const          = 0;
176 };
177 
createImage(const Library & egl,EGLDisplay dpy,EGLContext ctx,EGLClientBuffer clientBuffer) const178 EGLImageKHR GLImageSource::createImage(const Library &egl, EGLDisplay dpy, EGLContext ctx,
179                                        EGLClientBuffer clientBuffer) const
180 {
181     AttribMap attribMap = getCreateAttribs();
182 
183     attribMap[EGL_IMAGE_PRESERVED_KHR] = EGL_TRUE;
184 
185     {
186         const vector<EGLint> attribs = eglu::attribMapToList(attribMap);
187         const EGLImageKHR image      = egl.createImageKHR(dpy, ctx, getSource(), clientBuffer, &attribs.front());
188         EGLU_CHECK_MSG(egl, "eglCreateImageKHR()");
189         return image;
190     }
191 }
192 
193 class TextureImageSource : public GLImageSource
194 {
195 public:
TextureImageSource(GLenum internalFormat,GLenum format,GLenum type,bool useTexLevel0)196     TextureImageSource(GLenum internalFormat, GLenum format, GLenum type, bool useTexLevel0)
197         : m_internalFormat(internalFormat)
198         , m_format(format)
199         , m_type(type)
200         , m_useTexLevel0(useTexLevel0)
201     {
202     }
203     MovePtr<ClientBuffer> createBuffer(const eglw::Library &egl, const glw::Functions &gl, Texture2D *reference) const;
204     GLenum getEffectiveFormat(void) const;
getInternalFormat(void) const205     GLenum getInternalFormat(void) const
206     {
207         return m_internalFormat;
208     }
209 
210 protected:
211     AttribMap getCreateAttribs(void) const;
212     virtual void initTexture(const glw::Functions &gl) const = 0;
213     virtual GLenum getGLTarget(void) const                   = 0;
214 
215     const GLenum m_internalFormat;
216     const GLenum m_format;
217     const GLenum m_type;
218     const bool m_useTexLevel0;
219 };
220 
isSizedFormat(GLenum format)221 bool isSizedFormat(GLenum format)
222 {
223     try
224     {
225         glu::mapGLInternalFormat(format);
226         return true;
227     }
228     catch (const tcu::InternalError &)
229     {
230         return false;
231     }
232 }
233 
getEffectiveFormat(GLenum format,GLenum type)234 GLenum getEffectiveFormat(GLenum format, GLenum type)
235 {
236     return glu::getInternalFormat(glu::mapGLTransferFormat(format, type));
237 }
238 
getEffectiveFormat(void) const239 GLenum TextureImageSource::getEffectiveFormat(void) const
240 {
241     if (isSizedFormat(m_internalFormat))
242         return m_internalFormat;
243     else
244         return deqp::egl::Image::getEffectiveFormat(m_format, m_type);
245 }
246 
getCreateAttribs(void) const247 AttribMap TextureImageSource::getCreateAttribs(void) const
248 {
249     AttribMap ret;
250 
251     ret[EGL_GL_TEXTURE_LEVEL_KHR] = 0;
252 
253     return ret;
254 }
255 
createBuffer(const eglw::Library & egl,const glw::Functions & gl,Texture2D * ref) const256 MovePtr<ClientBuffer> TextureImageSource::createBuffer(const eglw::Library &egl, const glw::Functions &gl,
257                                                        Texture2D *ref) const
258 {
259     DE_UNREF(egl);
260 
261     MovePtr<TextureClientBuffer> clientBuffer(new TextureClientBuffer(gl));
262     const GLuint texture = clientBuffer->getName();
263     const GLenum target  = getGLTarget();
264 
265     GLU_CHECK_GLW_CALL(gl, bindTexture(target, texture));
266     initTexture(gl);
267 
268     if (!m_useTexLevel0)
269     {
270         // Set minification filter to linear. This makes the texture complete.
271         GLU_CHECK_GLW_CALL(gl, texParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
272     }
273 
274     if (ref != DE_NULL)
275     {
276         GLenum imgTarget = eglu::getImageGLTarget(getSource());
277 
278         *ref = Texture2D(glu::mapGLTransferFormat(m_format, m_type), IMAGE_WIDTH, IMAGE_HEIGHT);
279         ref->allocLevel(0);
280         tcu::fillWithComponentGradients(ref->getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f),
281                                         tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
282 
283         GLU_CHECK_GLW_CALL(gl, texParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
284         GLU_CHECK_GLW_CALL(gl, texParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
285         GLU_CHECK_GLW_CALL(gl, texParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
286         GLU_CHECK_GLW_CALL(gl, texParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
287 
288         GLU_CHECK_GLW_CALL(gl, texImage2D(imgTarget, 0, m_internalFormat, IMAGE_WIDTH, IMAGE_HEIGHT, 0, m_format,
289                                           m_type, ref->getLevel(0).getDataPtr()));
290     }
291     GLU_CHECK_GLW_CALL(gl, bindTexture(target, 0));
292     return MovePtr<ClientBuffer>(clientBuffer);
293 }
294 
295 class Texture2DImageSource : public TextureImageSource
296 {
297 public:
Texture2DImageSource(GLenum internalFormat,GLenum format,GLenum type,bool useTexLevel0)298     Texture2DImageSource(GLenum internalFormat, GLenum format, GLenum type, bool useTexLevel0)
299         : TextureImageSource(internalFormat, format, type, useTexLevel0)
300     {
301     }
getSource(void) const302     EGLenum getSource(void) const
303     {
304         return EGL_GL_TEXTURE_2D_KHR;
305     }
getRequiredExtension(void) const306     string getRequiredExtension(void) const
307     {
308         return "EGL_KHR_gl_texture_2D_image";
309     }
getGLTarget(void) const310     GLenum getGLTarget(void) const
311     {
312         return GL_TEXTURE_2D;
313     }
314 
315 protected:
316     void initTexture(const glw::Functions &gl) const;
317 };
318 
initTexture(const glw::Functions & gl) const319 void Texture2DImageSource::initTexture(const glw::Functions &gl) const
320 {
321     // Specify mipmap level 0
322     GLU_CHECK_CALL_ERROR(
323         gl.texImage2D(GL_TEXTURE_2D, 0, m_internalFormat, IMAGE_WIDTH, IMAGE_HEIGHT, 0, m_format, m_type, DE_NULL),
324         gl.getError());
325 }
326 
327 class TextureCubeMapImageSource : public TextureImageSource
328 {
329 public:
TextureCubeMapImageSource(EGLenum source,GLenum internalFormat,GLenum format,GLenum type,bool useTexLevel0)330     TextureCubeMapImageSource(EGLenum source, GLenum internalFormat, GLenum format, GLenum type, bool useTexLevel0)
331         : TextureImageSource(internalFormat, format, type, useTexLevel0)
332         , m_source(source)
333     {
334     }
getSource(void) const335     EGLenum getSource(void) const
336     {
337         return m_source;
338     }
getRequiredExtension(void) const339     string getRequiredExtension(void) const
340     {
341         return "EGL_KHR_gl_texture_cubemap_image";
342     }
getGLTarget(void) const343     GLenum getGLTarget(void) const
344     {
345         return GL_TEXTURE_CUBE_MAP;
346     }
347 
348 protected:
349     void initTexture(const glw::Functions &gl) const;
350 
351     EGLenum m_source;
352 };
353 
initTexture(const glw::Functions & gl) const354 void TextureCubeMapImageSource::initTexture(const glw::Functions &gl) const
355 {
356     // Specify mipmap level 0 for all faces
357     static const GLenum faces[] = {GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
358                                    GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
359                                    GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z};
360 
361     for (int faceNdx = 0; faceNdx < DE_LENGTH_OF_ARRAY(faces); faceNdx++)
362         GLU_CHECK_GLW_CALL(gl, texImage2D(faces[faceNdx], 0, m_internalFormat, IMAGE_WIDTH, IMAGE_HEIGHT, 0, m_format,
363                                           m_type, DE_NULL));
364 }
365 
366 class RenderbufferClientBuffer : public GLClientBuffer
367 {
368 public:
RenderbufferClientBuffer(const glw::Functions & gl)369     RenderbufferClientBuffer(const glw::Functions &gl) : m_rbo(gl)
370     {
371     }
getName(void) const372     GLuint getName(void) const
373     {
374         return *m_rbo;
375     }
376 
377 private:
378     glu::Renderbuffer m_rbo;
379 };
380 
381 class RenderbufferImageSource : public GLImageSource
382 {
383 public:
RenderbufferImageSource(GLenum format)384     RenderbufferImageSource(GLenum format) : m_format(format)
385     {
386     }
387 
getRequiredExtension(void) const388     string getRequiredExtension(void) const
389     {
390         return "EGL_KHR_gl_renderbuffer_image";
391     }
392     MovePtr<ClientBuffer> createBuffer(const eglw::Library &egl, const glw::Functions &gl, Texture2D *reference) const;
getEffectiveFormat(void) const393     GLenum getEffectiveFormat(void) const
394     {
395         return m_format;
396     }
397 
398 protected:
getSource(void) const399     EGLenum getSource(void) const
400     {
401         return EGL_GL_RENDERBUFFER_KHR;
402     }
getCreateAttribs(void) const403     AttribMap getCreateAttribs(void) const
404     {
405         return AttribMap();
406     }
407 
408     GLenum m_format;
409 };
410 
initializeStencilRbo(const glw::Functions & gl,GLuint rbo,Texture2D & ref)411 void initializeStencilRbo(const glw::Functions &gl, GLuint rbo, Texture2D &ref)
412 {
413     static const uint32_t stencilValues[] = {
414         0xBF688C11u, 0xB43D2922u, 0x055D5FFBu, 0x9300655Eu, 0x63BE0DF2u,
415         0x0345C13Bu, 0x1C184832u, 0xD107040Fu, 0x9B91569Fu, 0x0F0CFDC7u,
416     };
417 
418     const uint32_t numStencilBits =
419         tcu::getTextureFormatBitDepth(
420             tcu::getEffectiveDepthStencilTextureFormat(ref.getLevel(0).getFormat(), tcu::Sampler::MODE_STENCIL))
421             .x();
422     const uint32_t stencilMask = deBitMask32(0, numStencilBits);
423 
424     GLU_CHECK_GLW_CALL(gl, framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo));
425     GLU_CHECK_GLW_CALL(gl, clearStencil(0));
426     GLU_CHECK_GLW_CALL(gl, clear(GL_STENCIL_BUFFER_BIT));
427     tcu::clearStencil(ref.getLevel(0), 0);
428 
429     // create a pattern
430     GLU_CHECK_GLW_CALL(gl, enable(GL_SCISSOR_TEST));
431     for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(stencilValues); ++ndx)
432     {
433         const uint32_t stencil = stencilValues[ndx] & stencilMask;
434         const tcu::IVec2 size =
435             tcu::IVec2((int)((float)(DE_LENGTH_OF_ARRAY(stencilValues) - ndx) *
436                              ((float)ref.getWidth() / float(DE_LENGTH_OF_ARRAY(stencilValues)))),
437                        (int)((float)(DE_LENGTH_OF_ARRAY(stencilValues) - ndx) *
438                              ((float)ref.getHeight() / float(DE_LENGTH_OF_ARRAY(stencilValues) + 4)))); // not symmetric
439 
440         if (size.x() == 0 || size.y() == 0)
441             break;
442 
443         GLU_CHECK_GLW_CALL(gl, scissor(0, 0, size.x(), size.y()));
444         GLU_CHECK_GLW_CALL(gl, clearStencil(stencil));
445         GLU_CHECK_GLW_CALL(gl, clear(GL_STENCIL_BUFFER_BIT));
446 
447         tcu::clearStencil(tcu::getSubregion(ref.getLevel(0), 0, 0, size.x(), size.y()), stencil);
448     }
449 
450     GLU_CHECK_GLW_CALL(gl, disable(GL_SCISSOR_TEST));
451     GLU_CHECK_GLW_CALL(gl, framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0));
452 }
453 
initializeDepthRbo(const glw::Functions & gl,GLuint rbo,Texture2D & ref)454 void initializeDepthRbo(const glw::Functions &gl, GLuint rbo, Texture2D &ref)
455 {
456     const int NUM_STEPS = 13;
457 
458     GLU_CHECK_GLW_CALL(gl, framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo));
459 
460     GLU_CHECK_GLW_CALL(gl, clearDepthf(0.0f));
461     GLU_CHECK_GLW_CALL(gl, clear(GL_DEPTH_BUFFER_BIT));
462     tcu::clearDepth(ref.getLevel(0), 0.0f);
463 
464     // create a pattern
465     GLU_CHECK_GLW_CALL(gl, enable(GL_SCISSOR_TEST));
466     for (int ndx = 0; ndx < NUM_STEPS; ++ndx)
467     {
468         const float depth     = (float)ndx / float(NUM_STEPS);
469         const tcu::IVec2 size = tcu::IVec2(
470             (int)((float)(NUM_STEPS - ndx) * ((float)ref.getWidth() / float(NUM_STEPS))),
471             (int)((float)(NUM_STEPS - ndx) * ((float)ref.getHeight() / float(NUM_STEPS + 4)))); // not symmetric
472 
473         if (size.x() == 0 || size.y() == 0)
474             break;
475 
476         GLU_CHECK_GLW_CALL(gl, scissor(0, 0, size.x(), size.y()));
477         GLU_CHECK_GLW_CALL(gl, clearDepthf(depth));
478         GLU_CHECK_GLW_CALL(gl, clear(GL_DEPTH_BUFFER_BIT));
479 
480         tcu::clearDepth(tcu::getSubregion(ref.getLevel(0), 0, 0, size.x(), size.y()), depth);
481     }
482 
483     GLU_CHECK_GLW_CALL(gl, disable(GL_SCISSOR_TEST));
484     GLU_CHECK_GLW_CALL(gl, framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0));
485 }
486 
initializeColorRbo(const glw::Functions & gl,GLuint rbo,Texture2D & ref)487 void initializeColorRbo(const glw::Functions &gl, GLuint rbo, Texture2D &ref)
488 {
489     static const tcu::Vec4 colorValues[] = {
490         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),
491         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),
492     };
493 
494     GLU_CHECK_GLW_CALL(gl, framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo));
495     GLU_CHECK_GLW_CALL(gl, clearColor(1.0f, 1.0f, 0.0f, 1.0f));
496     GLU_CHECK_GLW_CALL(gl, clear(GL_COLOR_BUFFER_BIT));
497     tcu::clear(ref.getLevel(0), Vec4(1.0f, 1.0f, 0.0f, 1.0f));
498 
499     // create a pattern
500     GLU_CHECK_GLW_CALL(gl, enable(GL_SCISSOR_TEST));
501     for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(colorValues); ++ndx)
502     {
503         const tcu::IVec2 size =
504             tcu::IVec2((int)((float)(DE_LENGTH_OF_ARRAY(colorValues) - ndx) *
505                              ((float)ref.getWidth() / float(DE_LENGTH_OF_ARRAY(colorValues)))),
506                        (int)((float)(DE_LENGTH_OF_ARRAY(colorValues) - ndx) *
507                              ((float)ref.getHeight() / float(DE_LENGTH_OF_ARRAY(colorValues) + 4)))); // not symmetric
508 
509         if (size.x() == 0 || size.y() == 0)
510             break;
511 
512         GLU_CHECK_GLW_CALL(gl, scissor(0, 0, size.x(), size.y()));
513         GLU_CHECK_GLW_CALL(
514             gl, clearColor(colorValues[ndx].x(), colorValues[ndx].y(), colorValues[ndx].z(), colorValues[ndx].w()));
515         GLU_CHECK_GLW_CALL(gl, clear(GL_COLOR_BUFFER_BIT));
516 
517         tcu::clear(tcu::getSubregion(ref.getLevel(0), 0, 0, size.x(), size.y()), colorValues[ndx]);
518     }
519 
520     GLU_CHECK_GLW_CALL(gl, disable(GL_SCISSOR_TEST));
521     GLU_CHECK_GLW_CALL(gl, framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 0));
522 }
523 
createBuffer(const eglw::Library & egl,const glw::Functions & gl,Texture2D * ref) const524 MovePtr<ClientBuffer> RenderbufferImageSource::createBuffer(const eglw::Library &egl, const glw::Functions &gl,
525                                                             Texture2D *ref) const
526 {
527     DE_UNREF(egl);
528 
529     MovePtr<RenderbufferClientBuffer> buffer(new RenderbufferClientBuffer(gl));
530     const GLuint rbo = buffer->getName();
531 
532     GLU_CHECK_CALL_ERROR(gl.bindRenderbuffer(GL_RENDERBUFFER, rbo), gl.getError());
533 
534     // Specify storage.
535     GLU_CHECK_CALL_ERROR(gl.renderbufferStorage(GL_RENDERBUFFER, m_format, 64, 64), gl.getError());
536 
537     if (ref != DE_NULL)
538     {
539         Framebuffer fbo(gl);
540         const TextureFormat texFormat = glu::mapGLInternalFormat(m_format);
541 
542         *ref = tcu::Texture2D(texFormat, 64, 64);
543         ref->allocLevel(0);
544 
545         gl.bindFramebuffer(GL_FRAMEBUFFER, *fbo);
546         switch (m_format)
547         {
548         case GL_STENCIL_INDEX8:
549             initializeStencilRbo(gl, rbo, *ref);
550             break;
551         case GL_DEPTH_COMPONENT16:
552             initializeDepthRbo(gl, rbo, *ref);
553             break;
554         case GL_RGBA4:
555             initializeColorRbo(gl, rbo, *ref);
556             break;
557         case GL_RGB5_A1:
558             initializeColorRbo(gl, rbo, *ref);
559             break;
560         case GL_RGB565:
561             initializeColorRbo(gl, rbo, *ref);
562             break;
563         default:
564             DE_FATAL("Impossible");
565         }
566 
567         gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
568     }
569 
570     return MovePtr<ClientBuffer>(buffer);
571 }
572 
573 class UnsupportedImageSource : public ImageSource
574 {
575 public:
UnsupportedImageSource(const string & message,GLenum format,bool isYUV)576     UnsupportedImageSource(const string &message, GLenum format, bool isYUV)
577         : m_message(message)
578         , m_format(format)
579         , m_isY8Cb8Cr8_420(isYUV)
580     {
581     }
getRequiredExtension(void) const582     string getRequiredExtension(void) const
583     {
584         fail();
585         return "";
586     }
createBuffer(const eglw::Library & egl,const glw::Functions &,tcu::Texture2D *) const587     MovePtr<ClientBuffer> createBuffer(const eglw::Library &egl, const glw::Functions &, tcu::Texture2D *) const
588     {
589         DE_UNREF(egl);
590         fail();
591         return de::MovePtr<ClientBuffer>();
592     }
593     EGLImageKHR createImage(const Library &egl, EGLDisplay dpy, EGLContext ctx, EGLClientBuffer clientBuffer) const;
getEffectiveFormat(void) const594     GLenum getEffectiveFormat(void) const
595     {
596         return m_format;
597     }
isYUVFormatImage(void) const598     bool isYUVFormatImage(void) const
599     {
600         return m_isY8Cb8Cr8_420;
601     };
602 
603 private:
604     const string m_message;
605     GLenum m_format;
606     bool m_isY8Cb8Cr8_420;
fail(void) const607     void fail(void) const
608     {
609         TCU_THROW(NotSupportedError, m_message.c_str());
610     }
611 };
612 
createImage(const Library &,EGLDisplay,EGLContext,EGLClientBuffer) const613 EGLImageKHR UnsupportedImageSource::createImage(const Library &, EGLDisplay, EGLContext, EGLClientBuffer) const
614 {
615     fail();
616     return EGL_NO_IMAGE_KHR;
617 }
618 
createTextureImageSource(EGLenum source,GLenum internalFormat,GLenum format,GLenum type,bool useTexLevel0)619 MovePtr<ImageSource> createTextureImageSource(EGLenum source, GLenum internalFormat, GLenum format, GLenum type,
620                                               bool useTexLevel0)
621 {
622     if (source == EGL_GL_TEXTURE_2D_KHR)
623         return MovePtr<ImageSource>(new Texture2DImageSource(internalFormat, format, type, useTexLevel0));
624     else
625         return MovePtr<ImageSource>(new TextureCubeMapImageSource(source, internalFormat, format, type, useTexLevel0));
626 }
627 
createRenderbufferImageSource(GLenum format)628 MovePtr<ImageSource> createRenderbufferImageSource(GLenum format)
629 {
630     return MovePtr<ImageSource>(new RenderbufferImageSource(format));
631 }
632 
createUnsupportedImageSource(const string & message,GLenum format,bool isYUV)633 MovePtr<ImageSource> createUnsupportedImageSource(const string &message, GLenum format, bool isYUV)
634 {
635     return MovePtr<ImageSource>(new UnsupportedImageSource(message, format, isYUV));
636 }
637 
638 } // namespace Image
639 } // namespace egl
640 } // namespace deqp
641