Allow glFramebufferTexture2D with level!=0 in ES2 tests with ES3
[platform/upstream/VK-GL-CTS.git] / modules / gles2 / functional / es2fFboApiTest.cpp
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 2.0 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 Framebuffer Object API Tests.
22  *
23  * Notes:
24  *   All gl calls are passed thru sgl2::Context class. Reasons:
25  *    + Name, object allocation is tracked and live resources are freed
26  *      when Context is destroyed.
27  *    + Makes it possible to easily log all relevant calls into test log.
28  *      \todo [pyry] This is not implemented yet
29  *//*--------------------------------------------------------------------*/
30
31 #include "es2fFboApiTest.hpp"
32 #include "sglrGLContext.hpp"
33 #include "gluDefs.hpp"
34 #include "gluContextInfo.hpp"
35 #include "gluStrUtil.hpp"
36 #include "tcuRenderTarget.hpp"
37 #include "deString.h"
38 #include "glwFunctions.hpp"
39 #include "glsFboUtil.hpp"
40 #include "glwEnums.hpp"
41
42 #include <iterator>
43 #include <algorithm>
44
45 namespace deqp
46 {
47 namespace gles2
48 {
49 namespace Functional
50 {
51
52 using std::string;
53 using std::vector;
54 using tcu::TestLog;
55
56 using glw::GLenum;
57 using glw::GLint;
58
59 static void logComment (tcu::TestContext& testCtx, const char* comment)
60 {
61         testCtx.getLog() << TestLog::Message << "// " << comment << TestLog::EndMessage;
62 }
63
64 static void checkError (tcu::TestContext& testCtx, sglr::Context& ctx, GLenum expect)
65 {
66         GLenum result = ctx.getError();
67         testCtx.getLog() << TestLog::Message << "// " << (result == expect ? "Pass" : "Fail") << ", expected " << glu::getErrorStr(expect) << TestLog::EndMessage;
68
69         if (result != expect)
70                 testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Error code mismatch");
71 }
72
73 static void checkEitherError (tcu::TestContext& testCtx, sglr::Context& ctx, GLenum expectA, GLenum expectB)
74 {
75         GLenum  result  = ctx.getError();
76         bool    isOk    = (result == expectA || result == expectB);
77
78         testCtx.getLog() << TestLog::Message << "// " << (isOk ? "Pass" : "Fail") << ", expected " << glu::getErrorStr(expectA) << " or " << glu::getErrorStr(expectB) << TestLog::EndMessage;
79
80         if (!isOk)
81                 testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Error code mismatch");
82 }
83
84 static const char* getAttachmentName (GLenum attachment)
85 {
86         switch (attachment)
87         {
88                 case GL_COLOR_ATTACHMENT0:      return "GL_COLOR_ATTACHMENT0";
89                 case GL_DEPTH_ATTACHMENT:       return "GL_DEPTH_ATTACHMENT";
90                 case GL_STENCIL_ATTACHMENT:     return "GL_STENCIL_ATTACHMENT";
91                 default: throw tcu::InternalError("Unknown attachment", "", __FILE__, __LINE__);
92         }
93 }
94
95 static const char* getAttachmentParameterName (GLenum pname)
96 {
97         switch (pname)
98         {
99                 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:                             return "GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE";
100                 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:                             return "GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME";
101                 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:                   return "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL";
102                 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:   return "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE";
103                 default: throw tcu::InternalError("Unknown parameter", "", __FILE__, __LINE__);
104         }
105 }
106
107 static string getAttachmentParameterValueName (GLint value)
108 {
109         switch (value)
110         {
111                 case 0:                                                                 return "GL_NONE(0)";
112                 case GL_TEXTURE:                                                return "GL_TEXTURE";
113                 case GL_RENDERBUFFER:                                   return "GL_RENDERBUFFER";
114                 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:    return "GL_TEXTURE_CUBE_MAP_POSITIVE_X";
115                 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:    return "GL_TEXTURE_CUBE_MAP_NEGATIVE_X";
116                 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:    return "GL_TEXTURE_CUBE_MAP_POSITIVE_Y";
117                 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:    return "GL_TEXTURE_CUBE_MAP_NEGATIVE_Y";
118                 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:    return "GL_TEXTURE_CUBE_MAP_POSITIVE_Z";
119                 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:    return "GL_TEXTURE_CUBE_MAP_NEGATIVE_Z";
120                 default:
121                 {
122                         char tmp[64];
123                         deSprintf(tmp, sizeof(tmp), "0x%x", value);
124                         return string(tmp);
125                 }
126         }
127 }
128
129 static void checkFboAttachmentParam (tcu::TestContext& testCtx, sglr::Context& ctx, GLenum attachment, GLenum pname, GLint expectedValue)
130 {
131         TestLog& log = testCtx.getLog();
132         log << TestLog::Message << "// Querying " << getAttachmentName(attachment) << " " << getAttachmentParameterName(pname) << TestLog::EndMessage;
133
134         GLint value = 0xcdcdcdcd;
135         ctx.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, attachment, pname, &value);
136
137         GLenum err = ctx.getError();
138
139         if (value == expectedValue && err == GL_NO_ERROR)
140                 log << TestLog::Message << "// Pass" << TestLog::EndMessage;
141         else
142         {
143                 log << TestLog::Message << "// Fail, expected " << getAttachmentParameterValueName(expectedValue) << " without error" << TestLog::EndMessage;
144                 testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid result for attachment param query");
145         }
146 }
147
148 static void notSupportedTest (tcu::TestContext& testCtx, sglr::Context& context)
149 {
150         DE_UNREF(testCtx);
151         DE_UNREF(context);
152         throw tcu::NotSupportedError("Not supported", "", __FILE__, __LINE__);
153 }
154
155 static void textureLevelsTest (tcu::TestContext& testCtx, sglr::Context& context)
156 {
157         deUint32        tex             = 1;
158         deUint32        fbo             = 1;
159
160         context.bindTexture(GL_TEXTURE_2D, tex);
161         context.texImage2D(GL_TEXTURE_2D, 0, GL_RGB, 256, 256);
162         context.texImage2D(GL_TEXTURE_2D, 1, GL_RGB, 128, 128);
163
164         context.bindFramebuffer(GL_FRAMEBUFFER, fbo);
165
166         static int levels[] = { 2, 1, 0, -1, 0x7fffffff, 0, 1 };
167
168         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(levels); ndx++)
169         {
170                 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, levels[ndx]);
171                 checkError(testCtx, context, levels[ndx] == 0 ? GL_NO_ERROR : GL_INVALID_VALUE);
172         }
173 }
174
175 static void textureLevelsWithRenderToMipmapTest (tcu::TestContext& testCtx, sglr::Context& context)
176 {
177         deUint32        tex             = 1;
178         deUint32        fbo             = 1;
179
180         context.bindTexture(GL_TEXTURE_2D, tex);
181         context.texImage2D(GL_TEXTURE_2D, 0, GL_RGB, 256, 256);
182         context.texImage2D(GL_TEXTURE_2D, 1, GL_RGB, 128, 128);
183
184         context.bindFramebuffer(GL_FRAMEBUFFER, fbo);
185
186         static int levels[] = { 2, 1, 0, -1, 0x7fffffff, 0, 1 };
187
188         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(levels); ndx++)
189         {
190                 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, levels[ndx]);
191                 checkError(testCtx, context, de::inBounds(levels[ndx], 0, 16) ? GL_NO_ERROR : GL_INVALID_VALUE);
192         }
193 }
194
195 static void validTex2DAttachmentsTest (tcu::TestContext& testCtx, sglr::Context& context)
196 {
197         context.bindFramebuffer(GL_FRAMEBUFFER, 1);
198         static const GLenum attachmentPoints[] =
199         {
200                 GL_COLOR_ATTACHMENT0,
201                 GL_DEPTH_ATTACHMENT,
202                 GL_STENCIL_ATTACHMENT
203         };
204
205         // Texture2D
206         deUint32 tex2D = 1;
207         context.bindTexture(GL_TEXTURE_2D, tex2D);
208         for (int pointNdx = 0; pointNdx < DE_LENGTH_OF_ARRAY(attachmentPoints); pointNdx++)
209         {
210                 context.framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoints[pointNdx], GL_TEXTURE_2D, tex2D, 0);
211                 checkError(testCtx, context, GL_NO_ERROR);
212         }
213 }
214
215 static void validTexCubeAttachmentsTest (tcu::TestContext& testCtx, sglr::Context& context)
216 {
217         static const GLenum attachmentPoints[] =
218         {
219                 GL_COLOR_ATTACHMENT0,
220                 GL_DEPTH_ATTACHMENT,
221                 GL_STENCIL_ATTACHMENT
222         };
223         static const GLenum cubeTargets[] =
224         {
225                 GL_TEXTURE_CUBE_MAP_POSITIVE_X,
226                 GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
227                 GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
228                 GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
229                 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
230                 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
231         };
232
233         context.bindFramebuffer(GL_FRAMEBUFFER, 1);
234
235         // TextureCube
236         deUint32 texCube = 2;
237         context.bindTexture(GL_TEXTURE_CUBE_MAP, texCube);
238         for (int pointNdx = 0; pointNdx < DE_LENGTH_OF_ARRAY(attachmentPoints); pointNdx++)
239         {
240                 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(cubeTargets); targetNdx++)
241                 {
242                         context.framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoints[pointNdx], cubeTargets[targetNdx], texCube, 0);
243                         checkError(testCtx, context, GL_NO_ERROR);
244                 }
245         }
246 }
247
248 static void validRboAttachmentsTest (tcu::TestContext& testCtx, sglr::Context& context)
249 {
250         static const GLenum attachmentPoints[] =
251         {
252                 GL_COLOR_ATTACHMENT0,
253                 GL_DEPTH_ATTACHMENT,
254                 GL_STENCIL_ATTACHMENT
255         };
256
257         context.bindFramebuffer(GL_FRAMEBUFFER, 1);
258
259         // Renderbuffer
260         deUint32 rbo = 3;
261         context.bindRenderbuffer(GL_RENDERBUFFER, rbo);
262         for (int pointNdx = 0; pointNdx < DE_LENGTH_OF_ARRAY(attachmentPoints); pointNdx++)
263         {
264                 context.framebufferRenderbuffer(GL_FRAMEBUFFER, attachmentPoints[pointNdx], GL_RENDERBUFFER, rbo);
265                 checkError(testCtx, context, GL_NO_ERROR);
266         }
267 }
268
269 static void attachToDefaultFramebufferTest (tcu::TestContext& testCtx, sglr::Context& context)
270 {
271         logComment(testCtx, "Attaching 2D texture to default framebuffer");
272
273         deUint32 tex2D = 1;
274         context.bindTexture(GL_TEXTURE_2D, tex2D);
275         context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex2D, 0);
276         checkError(testCtx, context, GL_INVALID_OPERATION);
277
278         logComment(testCtx, "Attaching renderbuffer to default framebuffer");
279
280         deUint32 rbo = 1;
281         context.bindRenderbuffer(GL_RENDERBUFFER, rbo);
282         context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo);
283         checkError(testCtx, context, GL_INVALID_OPERATION);
284 }
285
286 static void invalidTex2DAttachmentTest (tcu::TestContext& testCtx, sglr::Context& context)
287 {
288         context.bindFramebuffer(GL_FRAMEBUFFER, 1);
289
290         logComment(testCtx, "Attaching 2D texture using GL_TEXTURE_CUBE_MAP_NEGATIVE_X texture target");
291
292         deUint32 tex2D = 1;
293         context.bindTexture(GL_TEXTURE_2D, tex2D);
294         context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, tex2D, 0);
295         checkError(testCtx, context, GL_INVALID_OPERATION);
296
297         logComment(testCtx, "Attaching deleted 2D texture object");
298         context.deleteTextures(1, &tex2D);
299         context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex2D, 0);
300         checkError(testCtx, context, GL_INVALID_OPERATION);
301 }
302
303 static void invalidTexCubeAttachmentTest (tcu::TestContext& testCtx, sglr::Context& context)
304 {
305         context.bindFramebuffer(GL_FRAMEBUFFER, 1);
306
307         logComment(testCtx, "Attaching cube texture using GL_TEXTURE_2D texture target");
308         deUint32 texCube = 2;
309         context.bindTexture(GL_TEXTURE_CUBE_MAP, texCube);
310         context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texCube, 0);
311         checkError(testCtx, context, GL_INVALID_OPERATION);
312
313         logComment(testCtx, "Attaching deleted cube texture object");
314         context.deleteTextures(1, &texCube);
315         context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X, texCube, 0);
316         checkError(testCtx, context, GL_INVALID_OPERATION);
317 }
318
319 static void invalidRboAttachmentTest (tcu::TestContext& testCtx, sglr::Context& context)
320 {
321         context.bindFramebuffer(GL_FRAMEBUFFER, 1);
322
323         logComment(testCtx, "Attaching renderbuffer using GL_FRAMEBUFFER renderbuffer target");
324         deUint32 rbo = 3;
325         context.bindRenderbuffer(GL_RENDERBUFFER, rbo);
326         context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER, rbo);
327         checkError(testCtx, context, GL_INVALID_ENUM);
328
329         logComment(testCtx, "Attaching deleted renderbuffer object");
330         context.deleteRenderbuffers(1, &rbo);
331         context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);
332         checkError(testCtx, context, GL_INVALID_OPERATION);
333 }
334
335 static void attachNamesTest (tcu::TestContext& testCtx, sglr::Context& context)
336 {
337         context.bindFramebuffer(GL_FRAMEBUFFER, 1);
338
339         // Just allocate some names, don't bind for storage
340         deUint32 reservedTexName;
341         context.genTextures(1, &reservedTexName);
342
343         logComment(testCtx, "Attaching allocated texture name to 2D target");
344         context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, reservedTexName, 0);
345         checkError(testCtx, context, GL_INVALID_OPERATION);
346
347         logComment(testCtx, "Attaching allocated texture name to cube target");
348         context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, reservedTexName, 0);
349         checkError(testCtx, context, GL_INVALID_OPERATION);
350
351         deUint32 reservedRboName;
352         context.genRenderbuffers(1, &reservedRboName);
353
354         logComment(testCtx, "Attaching allocated renderbuffer name");
355         context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, reservedRboName);
356         checkError(testCtx, context, GL_INVALID_OPERATION);
357 }
358
359 static void attachmentQueryDefaultFboTest (tcu::TestContext& testCtx, sglr::Context& ctx)
360 {
361         // Check that proper error codes are returned
362         GLint unused = 1;
363         ctx.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &unused);
364         checkEitherError(testCtx, ctx, GL_INVALID_ENUM, GL_INVALID_OPERATION);
365         ctx.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &unused);
366         checkEitherError(testCtx, ctx, GL_INVALID_ENUM, GL_INVALID_OPERATION);
367         ctx.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, &unused);
368         checkEitherError(testCtx, ctx, GL_INVALID_ENUM, GL_INVALID_OPERATION);
369         ctx.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, &unused);
370         checkEitherError(testCtx, ctx, GL_INVALID_ENUM, GL_INVALID_OPERATION);
371 }
372
373 static void attachmentQueryEmptyFboTest (tcu::TestContext& testCtx, sglr::Context& ctx)
374 {
375         static const GLenum attachmentPoints[] =
376         {
377                 GL_COLOR_ATTACHMENT0,
378                 GL_DEPTH_ATTACHMENT,
379                 GL_STENCIL_ATTACHMENT
380         };
381
382         ctx.bindFramebuffer(GL_FRAMEBUFFER, 1);
383
384         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(attachmentPoints); ndx++)
385                 checkFboAttachmentParam(testCtx, ctx, attachmentPoints[ndx], GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_NONE);
386
387         // Check that proper error codes are returned
388         GLint unused = -1;
389         ctx.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &unused);
390         checkError(testCtx, ctx, GL_INVALID_ENUM);
391         ctx.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, &unused);
392         checkError(testCtx, ctx, GL_INVALID_ENUM);
393         ctx.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, &unused);
394         checkError(testCtx, ctx, GL_INVALID_ENUM);
395 }
396
397 static void es3AttachmentQueryEmptyFboTest (tcu::TestContext& testCtx, sglr::Context& ctx)
398 {
399         // Error codes changed for ES3 so this version of test should be
400         // used when ES2 context is created on ES3 capable hardwere
401
402         static const GLenum attachmentPoints[] =
403         {
404                 GL_COLOR_ATTACHMENT0,
405                 GL_DEPTH_ATTACHMENT,
406                 GL_STENCIL_ATTACHMENT
407         };
408
409         ctx.bindFramebuffer(GL_FRAMEBUFFER, 1);
410
411         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(attachmentPoints); ndx++)
412                 checkFboAttachmentParam(testCtx, ctx, attachmentPoints[ndx], GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_NONE);
413
414         checkFboAttachmentParam(testCtx, ctx, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, 0);
415
416         // Check that proper error codes are returned
417         GLint unused = -1;
418         ctx.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, &unused);
419         checkError(testCtx, ctx, GL_INVALID_OPERATION);
420         ctx.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, &unused);
421         checkError(testCtx, ctx, GL_INVALID_OPERATION);
422 }
423
424 static void attachmentQueryTex2DTest (tcu::TestContext& testCtx, sglr::Context& ctx)
425 {
426         ctx.bindFramebuffer(GL_FRAMEBUFFER, 1);
427
428         ctx.bindTexture(GL_TEXTURE_2D, 1);
429         ctx.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 1, 0);
430
431         checkFboAttachmentParam(testCtx, ctx, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_TEXTURE);
432         checkFboAttachmentParam(testCtx, ctx, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, 1);
433         checkFboAttachmentParam(testCtx, ctx, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, 0);
434         checkFboAttachmentParam(testCtx, ctx, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, 0);
435 }
436
437 static void attachmentQueryTexCubeTest (tcu::TestContext& testCtx, sglr::Context& ctx)
438 {
439         ctx.bindFramebuffer(GL_FRAMEBUFFER, 1);
440
441         ctx.bindTexture(GL_TEXTURE_CUBE_MAP, 2);
442         ctx.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 2, 0);
443
444         checkFboAttachmentParam(testCtx, ctx, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_TEXTURE);
445         checkFboAttachmentParam(testCtx, ctx, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, 2);
446         checkFboAttachmentParam(testCtx, ctx, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, 0);
447         checkFboAttachmentParam(testCtx, ctx, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y);
448 }
449
450 static void attachmentQueryRboTest (tcu::TestContext& testCtx, sglr::Context& ctx)
451 {
452         ctx.bindFramebuffer(GL_FRAMEBUFFER, 1);
453
454         ctx.bindRenderbuffer(GL_RENDERBUFFER, 3);
455         ctx.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 3);
456
457         checkFboAttachmentParam(testCtx, ctx, GL_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_RENDERBUFFER);
458         checkFboAttachmentParam(testCtx, ctx, GL_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, 3);
459
460         GLint unused = 0;
461         ctx.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, &unused);
462         checkError(testCtx, ctx, GL_INVALID_ENUM);
463         ctx.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, &unused);
464         checkError(testCtx, ctx, GL_INVALID_ENUM);
465 }
466
467 static void deleteTex2DAttachedToBoundFboTest (tcu::TestContext& testCtx, sglr::Context& ctx)
468 {
469         ctx.bindFramebuffer(GL_FRAMEBUFFER, 1);
470
471         deUint32 tex2D = 1;
472         ctx.bindTexture(GL_TEXTURE_2D, tex2D);
473         ctx.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex2D, 0);
474
475         checkFboAttachmentParam(testCtx, ctx, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_TEXTURE);
476         checkFboAttachmentParam(testCtx, ctx, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, tex2D);
477
478         ctx.deleteTextures(1, &tex2D);
479
480         checkFboAttachmentParam(testCtx, ctx, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_NONE);
481 }
482
483 static void deleteTexCubeAttachedToBoundFboTest (tcu::TestContext& testCtx, sglr::Context& ctx)
484 {
485         ctx.bindFramebuffer(GL_FRAMEBUFFER, 1);
486
487         deUint32 texCube = 1;
488         ctx.bindTexture(GL_TEXTURE_CUBE_MAP, texCube);
489         ctx.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_CUBE_MAP_POSITIVE_X, texCube, 0);
490
491         checkFboAttachmentParam(testCtx, ctx, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_TEXTURE);
492         checkFboAttachmentParam(testCtx, ctx, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, texCube);
493
494         ctx.deleteTextures(1, &texCube);
495
496         checkFboAttachmentParam(testCtx, ctx, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_NONE);
497 }
498
499 static void deleteRboAttachedToBoundFboTest (tcu::TestContext& testCtx, sglr::Context& ctx)
500 {
501         ctx.bindFramebuffer(GL_FRAMEBUFFER, 1);
502
503         deUint32 rbo = 1;
504         ctx.bindRenderbuffer(GL_RENDERBUFFER, rbo);
505         ctx.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);
506
507         checkFboAttachmentParam(testCtx, ctx, GL_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_RENDERBUFFER);
508         checkFboAttachmentParam(testCtx, ctx, GL_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, rbo);
509
510         ctx.deleteRenderbuffers(1, &rbo);
511
512         checkFboAttachmentParam(testCtx, ctx, GL_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_NONE);
513 }
514
515 static void deleteTex2DAttachedToNotBoundFboTest (tcu::TestContext& testCtx, sglr::Context& ctx)
516 {
517         ctx.bindFramebuffer(GL_FRAMEBUFFER, 1);
518
519         deUint32 tex2D = 1;
520         ctx.bindTexture(GL_TEXTURE_2D, tex2D);
521         ctx.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex2D, 0);
522
523         checkFboAttachmentParam(testCtx, ctx, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_TEXTURE);
524         checkFboAttachmentParam(testCtx, ctx, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, tex2D);
525
526         ctx.bindFramebuffer(GL_FRAMEBUFFER, 0);
527
528         ctx.deleteTextures(1, &tex2D);
529
530         ctx.bindFramebuffer(GL_FRAMEBUFFER, 1);
531
532         checkFboAttachmentParam(testCtx, ctx, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_TEXTURE);
533         checkFboAttachmentParam(testCtx, ctx, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, tex2D);
534 }
535
536 static void deleteTexCubeAttachedToNotBoundFboTest (tcu::TestContext& testCtx, sglr::Context& ctx)
537 {
538         ctx.bindFramebuffer(GL_FRAMEBUFFER, 1);
539
540         deUint32 texCube = 1;
541         ctx.bindTexture(GL_TEXTURE_CUBE_MAP, texCube);
542         ctx.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_CUBE_MAP_POSITIVE_X, texCube, 0);
543
544         checkFboAttachmentParam(testCtx, ctx, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_TEXTURE);
545         checkFboAttachmentParam(testCtx, ctx, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, texCube);
546
547         ctx.bindFramebuffer(GL_FRAMEBUFFER, 0);
548
549         ctx.deleteTextures(1, &texCube);
550
551         ctx.bindFramebuffer(GL_FRAMEBUFFER, 1);
552
553         checkFboAttachmentParam(testCtx, ctx, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_TEXTURE);
554         checkFboAttachmentParam(testCtx, ctx, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, texCube);
555 }
556
557 static void deleteRboAttachedToNotBoundFboTest (tcu::TestContext& testCtx, sglr::Context& ctx)
558 {
559         ctx.bindFramebuffer(GL_FRAMEBUFFER, 1);
560
561         deUint32 rbo = 1;
562         ctx.bindRenderbuffer(GL_RENDERBUFFER, rbo);
563         ctx.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);
564
565         checkFboAttachmentParam(testCtx, ctx, GL_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_RENDERBUFFER);
566         checkFboAttachmentParam(testCtx, ctx, GL_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, rbo);
567
568         ctx.bindFramebuffer(GL_FRAMEBUFFER, 0);
569
570         ctx.deleteRenderbuffers(1, &rbo);
571
572         ctx.bindFramebuffer(GL_FRAMEBUFFER, 1);
573
574         checkFboAttachmentParam(testCtx, ctx, GL_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_RENDERBUFFER);
575         checkFboAttachmentParam(testCtx, ctx, GL_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, rbo);
576 }
577
578 class FboApiCase : public TestCase
579 {
580 public:
581         typedef void (*TestFunc) (tcu::TestContext& testCtx, sglr::Context& context);
582
583                                                                 FboApiCase                              (Context& context, const char* name, const char* description, TestFunc test);
584         virtual                                         ~FboApiCase                             (void);
585
586         virtual IterateResult           iterate                                 (void);
587
588 private:
589                                                                 FboApiCase                              (const FboApiCase& other);
590         FboApiCase&                                     operator=                               (const FboApiCase& other);
591
592         TestFunc                                        m_testFunc;
593 };
594
595 FboApiCase::FboApiCase (Context& context, const char* name, const char* description, TestFunc test)
596         : TestCase              (context, name, description)
597         , m_testFunc    (test)
598 {
599 }
600
601 FboApiCase::~FboApiCase (void)
602 {
603 }
604
605 TestCase::IterateResult FboApiCase::iterate (void)
606 {
607         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
608
609         GLU_EXPECT_NO_ERROR(gl.getError(), "Before test case");
610
611         // Initialize result to PASS
612         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
613
614         // Execute test case
615         {
616                 sglr::GLContext context(m_context.getRenderContext(), m_testCtx.getLog(), sglr::GLCONTEXT_LOG_CALLS, tcu::IVec4(0, 0, m_context.getRenderTarget().getWidth(), m_context.getRenderTarget().getHeight()));
617                 m_testFunc(m_testCtx, context);
618         }
619
620         GLU_EXPECT_NO_ERROR(gl.getError(), "After test case");
621
622         return STOP;
623 }
624
625 FboApiTestGroup::FboApiTestGroup (Context& context)
626         : TestCaseGroup(context, "api", "API Tests")
627 {
628 }
629
630 FboApiTestGroup::~FboApiTestGroup (void)
631 {
632 }
633
634 void FboApiTestGroup::init (void)
635 {
636         std::set<std::string> extensions;
637         std::copy(m_context.getContextInfo().getExtensions().begin(), m_context.getContextInfo().getExtensions().end(), std::inserter(extensions, extensions.begin()));
638
639         const glu::RenderContext& renderContext = m_context.getRenderContext();
640         bool  defaultFboIsZero  = renderContext.getDefaultFramebuffer() == 0;
641         bool  isES3Compatible   = gls::FboUtil::checkExtensionSupport(renderContext, "DEQP_gles3_core_compatible");
642         bool  hasRenderToMipmap = isES3Compatible || extensions.find("GL_OES_fbo_render_mipmap") != extensions.end();
643
644         // Valid attachments
645         addChild(new FboApiCase(m_context, "valid_tex2d_attachments",                                   "Valid 2D texture attachments",                                                 validTex2DAttachmentsTest));
646         addChild(new FboApiCase(m_context, "valid_texcube_attachments",                                 "Valid cubemap attachments",                                                    validTexCubeAttachmentsTest));
647         addChild(new FboApiCase(m_context, "valid_rbo_attachments",                                             "Valid renderbuffer attachments",                                               validRboAttachmentsTest));
648
649         // Invalid attachments
650         addChild(new FboApiCase(m_context, "attach_to_default_fbo",                                             "Invalid usage: attaching to default FBO",                              defaultFboIsZero ? attachToDefaultFramebufferTest : notSupportedTest));
651         addChild(new FboApiCase(m_context, "invalid_tex2d_attachments",                                 "Invalid 2D texture attachments",                                               invalidTex2DAttachmentTest));
652         addChild(new FboApiCase(m_context, "invalid_texcube_attachments",                               "Invalid cubemap attachments",                                                  invalidTexCubeAttachmentTest));
653         addChild(new FboApiCase(m_context, "invalid_rbo_attachments",                                   "Invalid renderbuffer attachments",                                             invalidRboAttachmentTest));
654         addChild(new FboApiCase(m_context, "attach_names",                                                              "Attach allocated names without objects",                               attachNamesTest));
655
656         addChild(new FboApiCase(m_context, "texture_levels",                                                    "Valid and invalid texturel levels",                                    hasRenderToMipmap ? textureLevelsWithRenderToMipmapTest : textureLevelsTest));
657
658         // Attachment queries
659         addChild(new FboApiCase(m_context, "attachment_query_default_fbo",                              "Query attachments from default FBO",                                   defaultFboIsZero ? attachmentQueryDefaultFboTest : notSupportedTest));
660         addChild(new FboApiCase(m_context, "attachment_query_empty_fbo",                                "Query attachments from empty FBO",                                             isES3Compatible ? es3AttachmentQueryEmptyFboTest : attachmentQueryEmptyFboTest));
661         addChild(new FboApiCase(m_context, "attachment_query_tex2d",                                    "Query 2d texture attachment properties",                               attachmentQueryTex2DTest));
662         addChild(new FboApiCase(m_context, "attachment_query_texcube",                                  "Query cubemap attachment properties",                                  attachmentQueryTexCubeTest));
663         addChild(new FboApiCase(m_context, "attachment_query_rbo",                                              "Query renderbuffer attachment properties",                             attachmentQueryRboTest));
664
665         // Delete attachments
666         addChild(new FboApiCase(m_context, "delete_tex_2d_attached_to_bound_fbo",               "Delete 2d texture attached to currently bound FBO",    deleteTex2DAttachedToBoundFboTest));
667         addChild(new FboApiCase(m_context, "delete_tex_cube_attached_to_bound_fbo",             "Delete cubemap attached to currently bound FBO",               deleteTexCubeAttachedToBoundFboTest));
668         addChild(new FboApiCase(m_context, "delete_rbo_attached_to_bound_fbo",                  "Delete renderbuffer attached to currently bound FBO",  deleteRboAttachedToBoundFboTest));
669
670         addChild(new FboApiCase(m_context, "delete_tex_2d_attached_to_not_bound_fbo",   "Delete 2d texture attached to FBO",                                    deleteTex2DAttachedToNotBoundFboTest));
671         addChild(new FboApiCase(m_context, "delete_tex_cube_attached_to_not_bound_fbo", "Delete cubemap attached to FBO",                                               deleteTexCubeAttachedToNotBoundFboTest));
672         addChild(new FboApiCase(m_context, "delete_rbo_attached_to_not_bound_fbo",              "Delete renderbuffer attached to FBO",                                  deleteRboAttachedToNotBoundFboTest));
673 }
674
675 } // Functional
676 } // gles2
677 } // deqp