xref: /aosp_15_r20/external/deqp/modules/egl/teglNegativePartialUpdateTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program EGL Module
3  * ---------------------------------------
4  *
5  * Copyright 2015 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 Test negative use case of KHR_partial_update
22  *//*--------------------------------------------------------------------*/
23 
24 #include "teglNegativePartialUpdateTests.hpp"
25 
26 #include "tcuTestLog.hpp"
27 #include "tcuSurface.hpp"
28 
29 #include "egluCallLogWrapper.hpp"
30 #include "egluConfigFilter.hpp"
31 #include "egluNativeWindow.hpp"
32 #include "egluStrUtil.hpp"
33 #include "egluUnique.hpp"
34 #include "egluUtil.hpp"
35 
36 #include "eglwLibrary.hpp"
37 #include "eglwEnums.hpp"
38 
39 using namespace eglu;
40 using namespace eglw;
41 using tcu::TestLog;
42 
43 namespace deqp
44 {
45 namespace egl
46 {
47 namespace
48 {
49 
50 class NegativePartialUpdateTest : public TestCase
51 {
52 public:
53     enum SurfaceType // used as a bit field when selecting a suitable EGL config
54     {
55         SURFACETYPE_WINDOW  = 1 << 0,
56         SURFACETYPE_PBUFFER = 1 << 1
57     };
58 
59     NegativePartialUpdateTest(EglTestContext &eglTestCtx, bool preserveBuffer, SurfaceType surfaceType,
60                               const char *name, const char *description);
61     ~NegativePartialUpdateTest(void);
62     void init(void);
63     void deinit(void);
64     virtual IterateResult iterate(void) = 0;
65 
66 protected:
67     void expectError(eglw::EGLenum error);
68     void expectBoolean(EGLBoolean expected, EGLBoolean got);
expectTrue(eglw::EGLBoolean got)69     inline void expectTrue(eglw::EGLBoolean got)
70     {
71         expectBoolean(EGL_TRUE, got);
72     }
expectFalse(eglw::EGLBoolean got)73     inline void expectFalse(eglw::EGLBoolean got)
74     {
75         expectBoolean(EGL_FALSE, got);
76     }
77 
78     const bool m_preserveBuffer;
79     SurfaceType m_surfaceType;
80     EGLDisplay m_eglDisplay;
81     EGLConfig m_eglConfig;
82     NativeWindow *m_window;
83     EGLSurface m_eglSurface;
84     EGLContext m_eglContext;
85 };
86 
isWindow(const CandidateConfig & c)87 bool isWindow(const CandidateConfig &c)
88 {
89     return (c.surfaceType() & EGL_WINDOW_BIT) == EGL_WINDOW_BIT;
90 }
91 
isPbuffer(const CandidateConfig & c)92 bool isPbuffer(const CandidateConfig &c)
93 {
94     return (c.surfaceType() & EGL_PBUFFER_BIT) == EGL_PBUFFER_BIT;
95 }
96 
isES2Renderable(const CandidateConfig & c)97 bool isES2Renderable(const CandidateConfig &c)
98 {
99     return (c.get(EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES2_BIT) == EGL_OPENGL_ES2_BIT;
100 }
101 
hasPreserveSwap(const CandidateConfig & c)102 bool hasPreserveSwap(const CandidateConfig &c)
103 {
104     return (c.surfaceType() & EGL_SWAP_BEHAVIOR_PRESERVED_BIT) == EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
105 }
106 
getEGLConfig(const Library & egl,EGLDisplay eglDisplay,unsigned surfaceTypes,bool preserveBuffer)107 EGLConfig getEGLConfig(const Library &egl, EGLDisplay eglDisplay, unsigned surfaceTypes, bool preserveBuffer)
108 {
109     FilterList filters;
110     if ((surfaceTypes & NegativePartialUpdateTest::SURFACETYPE_WINDOW) != 0)
111         filters << isWindow;
112     if ((surfaceTypes & NegativePartialUpdateTest::SURFACETYPE_PBUFFER) != 0)
113         filters << isPbuffer;
114     if (((surfaceTypes & NegativePartialUpdateTest::SURFACETYPE_WINDOW) == 0) &&
115         ((surfaceTypes & NegativePartialUpdateTest::SURFACETYPE_PBUFFER) == 0))
116         DE_FATAL("Invalid surfaceType");
117 
118     filters << isES2Renderable;
119 
120     if (preserveBuffer)
121         filters << hasPreserveSwap;
122 
123     return chooseSingleConfig(egl, eglDisplay, filters);
124 }
125 
initAndMakeCurrentEGLContext(const Library & egl,EGLDisplay eglDisplay,EGLSurface eglSurface,EGLConfig eglConfig,const EGLint * attribList)126 EGLContext initAndMakeCurrentEGLContext(const Library &egl, EGLDisplay eglDisplay, EGLSurface eglSurface,
127                                         EGLConfig eglConfig, const EGLint *attribList)
128 {
129     EGLContext eglContext = EGL_NO_CONTEXT;
130 
131     egl.bindAPI(EGL_OPENGL_ES_API);
132     eglContext = egl.createContext(eglDisplay, eglConfig, EGL_NO_CONTEXT, attribList);
133     EGLU_CHECK_MSG(egl, "eglCreateContext");
134     TCU_CHECK(eglSurface != EGL_NO_SURFACE);
135     egl.makeCurrent(eglDisplay, eglSurface, eglSurface, eglContext);
136     EGLU_CHECK_MSG(egl, "eglMakeCurrent");
137 
138     return eglContext;
139 }
140 
NegativePartialUpdateTest(EglTestContext & eglTestCtx,bool preserveBuffer,SurfaceType surfaceType,const char * name,const char * description)141 NegativePartialUpdateTest::NegativePartialUpdateTest(EglTestContext &eglTestCtx, bool preserveBuffer,
142                                                      SurfaceType surfaceType, const char *name, const char *description)
143     : TestCase(eglTestCtx, name, description)
144     , m_preserveBuffer(preserveBuffer)
145     , m_surfaceType(surfaceType)
146     , m_eglDisplay(EGL_NO_DISPLAY)
147     , m_window(DE_NULL)
148     , m_eglSurface(EGL_NO_SURFACE)
149     , m_eglContext(EGL_NO_CONTEXT)
150 {
151 }
152 
~NegativePartialUpdateTest(void)153 NegativePartialUpdateTest::~NegativePartialUpdateTest(void)
154 {
155     deinit();
156 }
157 
init(void)158 void NegativePartialUpdateTest::init(void)
159 {
160     const Library &egl                      = m_eglTestCtx.getLibrary();
161     static const EGLint contextAttribList[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
162     const int width                         = 480;
163     const int height                        = 480;
164 
165     m_eglDisplay = getAndInitDisplay(m_eglTestCtx.getNativeDisplay());
166 
167     if (!hasExtension(egl, m_eglDisplay, "EGL_KHR_partial_update"))
168         TCU_THROW(NotSupportedError, "EGL_KHR_partial_update is not supported");
169 
170     if (m_surfaceType == SURFACETYPE_PBUFFER)
171     {
172         m_eglConfig                      = getEGLConfig(egl, m_eglDisplay, SURFACETYPE_PBUFFER, m_preserveBuffer);
173         const EGLint pbufferAttribList[] = {EGL_WIDTH, width, EGL_HEIGHT, height, EGL_NONE};
174         m_eglSurface                     = egl.createPbufferSurface(m_eglDisplay, m_eglConfig, pbufferAttribList);
175     }
176     else
177     {
178         m_eglConfig = getEGLConfig(egl, m_eglDisplay, SURFACETYPE_WINDOW | SURFACETYPE_PBUFFER, m_preserveBuffer);
179         const NativeWindowFactory &factory =
180             selectNativeWindowFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());
181         m_window = factory.createWindow(&m_eglTestCtx.getNativeDisplay(), m_eglDisplay, m_eglConfig, DE_NULL,
182                                         WindowParams(width, height, parseWindowVisibility(m_testCtx.getCommandLine())));
183         m_eglSurface =
184             createWindowSurface(m_eglTestCtx.getNativeDisplay(), *m_window, m_eglDisplay, m_eglConfig, DE_NULL);
185     }
186     m_eglContext = initAndMakeCurrentEGLContext(egl, m_eglDisplay, m_eglSurface, m_eglConfig, contextAttribList);
187 }
188 
deinit(void)189 void NegativePartialUpdateTest::deinit(void)
190 {
191     const Library &egl = m_eglTestCtx.getLibrary();
192 
193     if (m_eglContext != EGL_NO_CONTEXT)
194     {
195         EGLU_CHECK_CALL(egl, makeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
196         EGLU_CHECK_CALL(egl, destroyContext(m_eglDisplay, m_eglContext));
197         m_eglContext = EGL_NO_CONTEXT;
198     }
199 
200     if (m_eglSurface != EGL_NO_SURFACE)
201     {
202         EGLU_CHECK_CALL(egl, destroySurface(m_eglDisplay, m_eglSurface));
203         m_eglSurface = EGL_NO_SURFACE;
204     }
205 
206     if (m_eglDisplay != EGL_NO_DISPLAY)
207     {
208         EGLU_CHECK_CALL(egl, terminate(m_eglDisplay));
209         m_eglDisplay = EGL_NO_DISPLAY;
210     }
211 
212     delete m_window;
213     m_window = DE_NULL;
214 }
215 
expectError(EGLenum expected)216 void NegativePartialUpdateTest::expectError(EGLenum expected)
217 {
218     const EGLenum err = m_eglTestCtx.getLibrary().getError();
219 
220     if (err != expected)
221     {
222         m_testCtx.getLog() << TestLog::Message << "// ERROR expected: " << eglu::getErrorStr(expected)
223                            << ", Got: " << eglu::getErrorStr(err) << TestLog::EndMessage;
224         if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
225             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid error");
226     }
227 }
228 
expectBoolean(EGLBoolean expected,EGLBoolean got)229 void NegativePartialUpdateTest::expectBoolean(EGLBoolean expected, EGLBoolean got)
230 {
231     if (expected != got)
232     {
233         m_testCtx.getLog() << TestLog::Message << "// ERROR expected: " << eglu::getBooleanStr(expected)
234                            << ", Got: " << eglu::getBooleanStr(got) << TestLog::EndMessage;
235         if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
236             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid value");
237     }
238 }
239 
240 class NotPostableTest : public NegativePartialUpdateTest
241 {
242 public:
243     NotPostableTest(EglTestContext &context);
244     TestCase::IterateResult iterate(void);
245 };
246 
NotPostableTest(EglTestContext & context)247 NotPostableTest::NotPostableTest(EglTestContext &context)
248     : NegativePartialUpdateTest(context, false, SURFACETYPE_PBUFFER, "not_postable_surface",
249                                 "Call setDamageRegion() on pbuffer")
250 {
251 }
252 
iterate(void)253 TestCase::IterateResult NotPostableTest::iterate(void)
254 {
255     const Library &egl = m_eglTestCtx.getLibrary();
256     TestLog &log       = m_testCtx.getLog();
257     CallLogWrapper wrapper(egl, log);
258     EGLint damageRegion[] = {10, 10, 10, 10};
259     int bufferAge         = -1;
260 
261     wrapper.enableLogging(true);
262     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
263     {
264         tcu::ScopedLogSection(log, "Test1", "If the surface is pbuffer (not postable) --> EGL_BAD_MATCH");
265         EGLU_CHECK_CALL(egl, surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED));
266         EGLU_CHECK_CALL(egl, querySurface(m_eglDisplay, m_eglSurface, EGL_BUFFER_AGE_KHR, &bufferAge));
267         expectFalse(wrapper.eglSetDamageRegionKHR(m_eglDisplay, m_eglSurface, damageRegion,
268                                                   DE_LENGTH_OF_ARRAY(damageRegion) / 4));
269         expectError(EGL_BAD_MATCH);
270     }
271 
272     return STOP;
273 }
274 
275 class NotCurrentSurfaceTest : public NegativePartialUpdateTest
276 {
277 public:
278     NotCurrentSurfaceTest(EglTestContext &context);
279     TestCase::IterateResult iterate(void);
280 };
281 
NotCurrentSurfaceTest(EglTestContext & context)282 NotCurrentSurfaceTest::NotCurrentSurfaceTest(EglTestContext &context)
283     : NegativePartialUpdateTest(context, false, SURFACETYPE_WINDOW, "not_current_surface",
284                                 "Call setDamageRegion() on pbuffer")
285 {
286 }
287 
iterate(void)288 TestCase::IterateResult NotCurrentSurfaceTest::iterate(void)
289 {
290     const int impossibleBufferAge = -26084;
291     const Library &egl            = m_eglTestCtx.getLibrary();
292     const EGLint attribList[]     = {EGL_WIDTH, 64, EGL_HEIGHT, 64, EGL_NONE};
293     const eglu::UniqueSurface unusedPbuffer(egl, m_eglDisplay,
294                                             egl.createPbufferSurface(m_eglDisplay, m_eglConfig, attribList));
295     TestLog &log = m_testCtx.getLog();
296     CallLogWrapper wrapper(egl, log);
297     EGLint damageRegion[] = {10, 10, 10, 10};
298     int bufferAge         = impossibleBufferAge;
299 
300     wrapper.enableLogging(true);
301     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
302     EGLU_CHECK_CALL(egl, makeCurrent(m_eglDisplay, *unusedPbuffer, *unusedPbuffer, m_eglContext));
303     {
304         tcu::ScopedLogSection(
305             log, "Test2.1",
306             "If query buffer age on a surface that is not the current draw surface --> EGL_BAD_SURFACE");
307         EGLU_CHECK_CALL(egl, surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED));
308         expectFalse(wrapper.eglQuerySurface(m_eglDisplay, m_eglSurface, EGL_BUFFER_AGE_KHR, &bufferAge));
309         expectError(EGL_BAD_SURFACE);
310 
311         if (bufferAge != impossibleBufferAge)
312         {
313             log << tcu::TestLog::Message
314                 << "On failure, eglQuerySurface shouldn't change buffer age but buffer age has been changed to "
315                 << bufferAge << tcu::TestLog::EndMessage;
316             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail, bufferAge shouldn't be changed");
317         }
318     }
319     {
320         tcu::ScopedLogSection(
321             log, "Test2.2",
322             "If call setDamageRegion() on a surface that is not the current draw surface --> EGL_BAD_MATCH");
323         expectFalse(wrapper.eglSetDamageRegionKHR(m_eglDisplay, m_eglSurface, damageRegion, 1));
324         expectError(EGL_BAD_MATCH);
325     }
326 
327     EGLU_CHECK_CALL(egl, makeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
328     {
329         tcu::ScopedLogSection(
330             log, "Test3.1",
331             "If query buffer age on a surface that is not the current draw surface --> EGL_BAD_SURFACE");
332         EGLU_CHECK_CALL(egl, surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED));
333         expectFalse(wrapper.eglQuerySurface(m_eglDisplay, m_eglSurface, EGL_BUFFER_AGE_KHR, &bufferAge));
334         expectError(EGL_BAD_SURFACE);
335 
336         if (bufferAge != impossibleBufferAge)
337         {
338             log << tcu::TestLog::Message
339                 << "On failure, eglQuerySurface shouldn't change buffer age but buffer age has been changed to "
340                 << bufferAge << tcu::TestLog::EndMessage;
341             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail, bufferAge shouldn't be changed");
342         }
343     }
344     {
345         tcu::ScopedLogSection(
346             log, "Test3.2",
347             "If call setDamageRegion() on a surface that is not the current draw surface --> EGL_BAD_MATCH");
348         expectFalse(wrapper.eglSetDamageRegionKHR(m_eglDisplay, m_eglSurface, damageRegion, 1));
349         expectError(EGL_BAD_MATCH);
350     }
351 
352     if (hasExtension(egl, m_eglDisplay, "EGL_KHR_surfaceless_context"))
353     {
354         EGLU_CHECK_CALL(egl, makeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, m_eglContext));
355         {
356             tcu::ScopedLogSection(
357                 log, "Test4.1",
358                 "If query buffer age on a surface that is not the current draw surface --> EGL_BAD_SURFACE");
359             EGLU_CHECK_CALL(egl, surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED));
360             expectFalse(wrapper.eglQuerySurface(m_eglDisplay, m_eglSurface, EGL_BUFFER_AGE_KHR, &bufferAge));
361             expectError(EGL_BAD_SURFACE);
362 
363             if (bufferAge != impossibleBufferAge)
364             {
365                 log << tcu::TestLog::Message
366                     << "On failure, eglQuerySurface shouldn't change buffer age but buffer age has been changed to "
367                     << bufferAge << tcu::TestLog::EndMessage;
368                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail, bufferAge shouldn't be changed");
369             }
370         }
371         {
372             tcu::ScopedLogSection(
373                 log, "Test4.2",
374                 "If call setDamageRegion() on a surface that is not the current draw surface --> EGL_BAD_MATCH");
375             expectFalse(wrapper.eglSetDamageRegionKHR(m_eglDisplay, m_eglSurface, damageRegion, 1));
376             expectError(EGL_BAD_MATCH);
377         }
378     }
379 
380     return STOP;
381 }
382 
383 class BufferPreservedTest : public NegativePartialUpdateTest
384 {
385 public:
386     BufferPreservedTest(EglTestContext &context);
387     TestCase::IterateResult iterate(void);
388 };
389 
BufferPreservedTest(EglTestContext & context)390 BufferPreservedTest::BufferPreservedTest(EglTestContext &context)
391     : NegativePartialUpdateTest(context, true, SURFACETYPE_WINDOW, "buffer_preserved",
392                                 "Call setDamageRegion() on pbuffer")
393 {
394 }
395 
iterate(void)396 TestCase::IterateResult BufferPreservedTest::iterate(void)
397 {
398     const Library &egl = m_eglTestCtx.getLibrary();
399     TestLog &log       = m_testCtx.getLog();
400     CallLogWrapper wrapper(egl, log);
401     EGLint damageRegion[] = {10, 10, 10, 10};
402     int bufferAge         = -1;
403 
404     wrapper.enableLogging(true);
405     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
406     {
407         tcu::ScopedLogSection(log, "Test3", "If buffer_preserved --> EGL_BAD_MATCH");
408         EGLU_CHECK_CALL(egl, surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED));
409         EGLU_CHECK_CALL(egl, querySurface(m_eglDisplay, m_eglSurface, EGL_BUFFER_AGE_KHR, &bufferAge));
410         expectFalse(wrapper.eglSetDamageRegionKHR(m_eglDisplay, m_eglSurface, damageRegion,
411                                                   DE_LENGTH_OF_ARRAY(damageRegion) / 4));
412         expectError(EGL_BAD_MATCH);
413     }
414 
415     return STOP;
416 }
417 
418 class SetTwiceTest : public NegativePartialUpdateTest
419 {
420 public:
421     SetTwiceTest(EglTestContext &context);
422     TestCase::IterateResult iterate(void);
423 };
424 
SetTwiceTest(EglTestContext & context)425 SetTwiceTest::SetTwiceTest(EglTestContext &context)
426     : NegativePartialUpdateTest(context, false, SURFACETYPE_WINDOW, "set_damage_region_twice",
427                                 "Call setDamageRegion() twice")
428 {
429 }
430 
iterate(void)431 TestCase::IterateResult SetTwiceTest::iterate(void)
432 {
433     const Library &egl = m_eglTestCtx.getLibrary();
434     TestLog &log       = m_testCtx.getLog();
435     CallLogWrapper wrapper(egl, log);
436     EGLint damageRegion[] = {10, 10, 10, 10};
437     int bufferAge         = -1;
438 
439     wrapper.enableLogging(true);
440     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
441     {
442         tcu::ScopedLogSection(log, "Test4", "If call setDamageRegion() twice --> EGL_BAD_ACCESS");
443         EGLU_CHECK_CALL(egl, surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED));
444         EGLU_CHECK_CALL(egl, querySurface(m_eglDisplay, m_eglSurface, EGL_BUFFER_AGE_KHR, &bufferAge));
445         expectTrue(wrapper.eglSetDamageRegionKHR(m_eglDisplay, m_eglSurface, damageRegion,
446                                                  DE_LENGTH_OF_ARRAY(damageRegion) / 4));
447         expectFalse(wrapper.eglSetDamageRegionKHR(m_eglDisplay, m_eglSurface, damageRegion,
448                                                   DE_LENGTH_OF_ARRAY(damageRegion) / 4));
449         expectError(EGL_BAD_ACCESS);
450     }
451 
452     return STOP;
453 }
454 
455 class NoAgeTest : public NegativePartialUpdateTest
456 {
457 public:
458     NoAgeTest(EglTestContext &context);
459     TestCase::IterateResult iterate(void);
460 };
461 
NoAgeTest(EglTestContext & context)462 NoAgeTest::NoAgeTest(EglTestContext &context)
463     : NegativePartialUpdateTest(context, false, SURFACETYPE_WINDOW, "set_damage_region_before_query_age",
464                                 "Call setDamageRegion() without querying buffer age")
465 {
466 }
467 
iterate(void)468 TestCase::IterateResult NoAgeTest::iterate(void)
469 {
470     const Library &egl = m_eglTestCtx.getLibrary();
471     TestLog &log       = m_testCtx.getLog();
472     CallLogWrapper wrapper(egl, log);
473     EGLint damageRegion[] = {10, 10, 10, 10};
474 
475     wrapper.enableLogging(true);
476     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
477     {
478         tcu::ScopedLogSection(log, "Test5", "If buffer age is not queried --> EGL_BAD_ACCESS");
479         EGLU_CHECK_CALL(egl, surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED));
480         expectFalse(wrapper.eglSetDamageRegionKHR(m_eglDisplay, m_eglSurface, damageRegion,
481                                                   DE_LENGTH_OF_ARRAY(damageRegion) / 4));
482         expectError(EGL_BAD_ACCESS);
483     }
484 
485     return STOP;
486 }
487 
488 class PassNullTest : public NegativePartialUpdateTest
489 {
490 public:
491     PassNullTest(EglTestContext &context);
492     TestCase::IterateResult iterate(void);
493 };
494 
PassNullTest(EglTestContext & context)495 PassNullTest::PassNullTest(EglTestContext &context)
496     : NegativePartialUpdateTest(context, false, SURFACETYPE_WINDOW, "pass_null_0_as_params",
497                                 "Call setDamageRegion() with (NULL, 0)")
498 {
499 }
500 
iterate(void)501 TestCase::IterateResult PassNullTest::iterate(void)
502 {
503     const Library &egl = m_eglTestCtx.getLibrary();
504     TestLog &log       = m_testCtx.getLog();
505     CallLogWrapper wrapper(egl, log);
506     int bufferAge = -1;
507 
508     wrapper.enableLogging(true);
509     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
510     {
511         tcu::ScopedLogSection(log, "Test6", "If pass (null, 0) to setDamageRegion(), no error");
512         EGLU_CHECK_CALL(egl, surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED));
513         EGLU_CHECK_CALL(egl, querySurface(m_eglDisplay, m_eglSurface, EGL_BUFFER_AGE_KHR, &bufferAge));
514         expectTrue(wrapper.eglSetDamageRegionKHR(m_eglDisplay, m_eglSurface, DE_NULL, 0));
515         expectError(EGL_SUCCESS);
516     }
517 
518     return STOP;
519 }
520 
521 class NotCurrentSurfaceTest2 : public NegativePartialUpdateTest
522 {
523 public:
524     NotCurrentSurfaceTest2(EglTestContext &context);
525     TestCase::IterateResult iterate(void);
526 };
527 
NotCurrentSurfaceTest2(EglTestContext & context)528 NotCurrentSurfaceTest2::NotCurrentSurfaceTest2(EglTestContext &context)
529     : NegativePartialUpdateTest(context, false, SURFACETYPE_WINDOW, "not_current_surface2",
530                                 "Call setDamageRegion() on pbuffer")
531 {
532 }
533 
iterate(void)534 TestCase::IterateResult NotCurrentSurfaceTest2::iterate(void)
535 {
536     const Library &egl        = m_eglTestCtx.getLibrary();
537     const EGLint attribList[] = {EGL_WIDTH, 64, EGL_HEIGHT, 64, EGL_NONE};
538     const eglu::UniqueSurface unusedPbuffer(egl, m_eglDisplay,
539                                             egl.createPbufferSurface(m_eglDisplay, m_eglConfig, attribList));
540     TestLog &log = m_testCtx.getLog();
541     CallLogWrapper wrapper(egl, log);
542     EGLint damageRegion[] = {10, 10, 10, 10};
543     int bufferAge         = -1;
544 
545     wrapper.enableLogging(true);
546     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
547 
548     EGLU_CHECK_CALL(egl, surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED));
549     EGLU_CHECK_CALL(egl, querySurface(m_eglDisplay, m_eglSurface, EGL_BUFFER_AGE_KHR, &bufferAge));
550 
551     {
552         tcu::ScopedLogSection(
553             log, "Test7",
554             "If call setDamageRegion() on a surface that is not the current draw surface --> EGL_BAD_MATCH");
555         EGLU_CHECK_CALL(egl, makeCurrent(m_eglDisplay, *unusedPbuffer, *unusedPbuffer, m_eglContext));
556         expectFalse(wrapper.eglSetDamageRegionKHR(m_eglDisplay, m_eglSurface, damageRegion, 1));
557         expectError(EGL_BAD_MATCH);
558     }
559     {
560         tcu::ScopedLogSection(
561             log, "Test8",
562             "If call setDamageRegion() on a surface that is not the current draw surface --> EGL_BAD_MATCH");
563         EGLU_CHECK_CALL(egl, makeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
564         expectFalse(wrapper.eglSetDamageRegionKHR(m_eglDisplay, m_eglSurface, damageRegion, 1));
565         expectError(EGL_BAD_MATCH);
566     }
567     if (hasExtension(egl, m_eglDisplay, "EGL_KHR_surfaceless_context"))
568     {
569         tcu::ScopedLogSection(
570             log, "Test9",
571             "If call setDamageRegion() on a surface that is not the current draw surface --> EGL_BAD_MATCH");
572         EGLU_CHECK_CALL(egl, makeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, m_eglContext));
573         expectFalse(wrapper.eglSetDamageRegionKHR(m_eglDisplay, m_eglSurface, damageRegion, 1));
574         expectError(EGL_BAD_MATCH);
575     }
576 
577     return STOP;
578 }
579 
580 } // namespace
581 
NegativePartialUpdateTests(EglTestContext & eglTestCtx)582 NegativePartialUpdateTests::NegativePartialUpdateTests(EglTestContext &eglTestCtx)
583     : TestCaseGroup(eglTestCtx, "negative_partial_update", "Negative partial update tests")
584 {
585 }
586 
init(void)587 void NegativePartialUpdateTests::init(void)
588 {
589     addChild(new NotPostableTest(m_eglTestCtx));
590     addChild(new NotCurrentSurfaceTest(m_eglTestCtx));
591     addChild(new BufferPreservedTest(m_eglTestCtx));
592     addChild(new SetTwiceTest(m_eglTestCtx));
593     addChild(new NoAgeTest(m_eglTestCtx));
594     addChild(new PassNullTest(m_eglTestCtx));
595     addChild(new NotCurrentSurfaceTest2(m_eglTestCtx));
596 }
597 
598 } // namespace egl
599 } // namespace deqp
600