1 /*
2  * Copyright 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "SurfaceTextureMultiContextGL_test"
18 //#define LOG_NDEBUG 0
19 
20 #include "SurfaceTextureMultiContextGL.h"
21 
22 #include "FillBuffer.h"
23 
24 #include <GLES/glext.h>
25 
26 namespace android {
27 
TEST_F(SurfaceTextureMultiContextGLTest,UpdateFromMultipleContextsFails)28 TEST_F(SurfaceTextureMultiContextGLTest, UpdateFromMultipleContextsFails) {
29     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
30 
31     // Latch the texture contents on the primary context.
32     mFW->waitForFrame();
33     ASSERT_EQ(OK, mST->updateTexImage());
34 
35     // Attempt to latch the texture on the secondary context.
36     ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
37             mSecondEglContext));
38     ASSERT_EQ(EGL_SUCCESS, eglGetError());
39     ASSERT_EQ(INVALID_OPERATION, mST->updateTexImage());
40 }
41 
TEST_F(SurfaceTextureMultiContextGLTest,DetachFromContextSucceeds)42 TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextSucceeds) {
43     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
44 
45     // Latch the texture contents on the primary context.
46     mFW->waitForFrame();
47     ASSERT_EQ(OK, mST->updateTexImage());
48 
49     // Detach from the primary context.
50     ASSERT_EQ(OK, mST->detachFromContext());
51 
52     // Check that the GL texture was deleted.
53     EXPECT_EQ(GL_FALSE, glIsTexture(TEX_ID));
54 }
55 
TEST_F(SurfaceTextureMultiContextGLTest,DetachFromContextSucceedsAfterProducerDisconnect)56 TEST_F(SurfaceTextureMultiContextGLTest,
57         DetachFromContextSucceedsAfterProducerDisconnect) {
58     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
59 
60     // Latch the texture contents on the primary context.
61     mFW->waitForFrame();
62     ASSERT_EQ(OK, mST->updateTexImage());
63 
64     // Detach from the primary context.
65     native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_CPU);
66     ASSERT_EQ(OK, mST->detachFromContext());
67 
68     // Check that the GL texture was deleted.
69     EXPECT_EQ(GL_FALSE, glIsTexture(TEX_ID));
70 }
71 
TEST_F(SurfaceTextureMultiContextGLTest,DetachFromContextFailsWhenAbandoned)72 TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextFailsWhenAbandoned) {
73     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
74 
75     // Latch the texture contents on the primary context.
76     mFW->waitForFrame();
77     ASSERT_EQ(OK, mST->updateTexImage());
78 
79     // Attempt to detach from the primary context.
80     mST->abandon();
81     ASSERT_EQ(NO_INIT, mST->detachFromContext());
82 }
83 
TEST_F(SurfaceTextureMultiContextGLTest,DetachFromContextFailsWhenDetached)84 TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextFailsWhenDetached) {
85     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
86 
87     // Latch the texture contents on the primary context.
88     mFW->waitForFrame();
89     ASSERT_EQ(OK, mST->updateTexImage());
90 
91     // Detach from the primary context.
92     ASSERT_EQ(OK, mST->detachFromContext());
93 
94     // Attempt to detach from the primary context again.
95     ASSERT_EQ(INVALID_OPERATION, mST->detachFromContext());
96 }
97 
TEST_F(SurfaceTextureMultiContextGLTest,DetachFromContextFailsWithNoDisplay)98 TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextFailsWithNoDisplay) {
99     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
100 
101     // Latch the texture contents on the primary context.
102     mFW->waitForFrame();
103     ASSERT_EQ(OK, mST->updateTexImage());
104 
105     // Make there be no current display.
106     ASSERT_TRUE(eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
107             EGL_NO_CONTEXT));
108     ASSERT_EQ(EGL_SUCCESS, eglGetError());
109 
110     // Attempt to detach from the primary context.
111     ASSERT_EQ(INVALID_OPERATION, mST->detachFromContext());
112 }
113 
TEST_F(SurfaceTextureMultiContextGLTest,DetachFromContextFailsWithNoContext)114 TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextFailsWithNoContext) {
115     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
116 
117     // Latch the texture contents on the primary context.
118     mFW->waitForFrame();
119     ASSERT_EQ(OK, mST->updateTexImage());
120 
121     // Make current context be incorrect.
122     ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
123             mSecondEglContext));
124     ASSERT_EQ(EGL_SUCCESS, eglGetError());
125 
126     // Attempt to detach from the primary context.
127     ASSERT_EQ(INVALID_OPERATION, mST->detachFromContext());
128 }
129 
TEST_F(SurfaceTextureMultiContextGLTest,UpdateTexImageFailsWhenDetached)130 TEST_F(SurfaceTextureMultiContextGLTest, UpdateTexImageFailsWhenDetached) {
131     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
132 
133     // Detach from the primary context.
134     ASSERT_EQ(OK, mST->detachFromContext());
135 
136     // Attempt to latch the texture contents on the primary context.
137     mFW->waitForFrame();
138     ASSERT_EQ(INVALID_OPERATION, mST->updateTexImage());
139 }
140 
TEST_F(SurfaceTextureMultiContextGLTest,AttachToContextSucceeds)141 TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextSucceeds) {
142     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
143 
144     // Latch the texture contents on the primary context.
145     mFW->waitForFrame();
146     ASSERT_EQ(OK, mST->updateTexImage());
147 
148     // Detach from the primary context.
149     ASSERT_EQ(OK, mST->detachFromContext());
150 
151     // Attach to the secondary context.
152     ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
153             mSecondEglContext));
154     ASSERT_EQ(OK, mST->attachToContext(SECOND_TEX_ID));
155 
156     // Verify that the texture object was created and bound.
157     GLint texBinding = -1;
158     glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &texBinding);
159     EXPECT_EQ(SECOND_TEX_ID, texBinding);
160 
161     // Try to use the texture from the secondary context.
162     glClearColor(0.2, 0.2, 0.2, 0.2);
163     glClear(GL_COLOR_BUFFER_BIT);
164     glViewport(0, 0, 1, 1);
165     mSecondTextureRenderer->drawTexture();
166     ASSERT_TRUE(checkPixel( 0,  0,  35,  35,  35,  35));
167     ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
168 }
169 
TEST_F(SurfaceTextureMultiContextGLTest,AttachToContextSucceedsAfterProducerDisconnect)170 TEST_F(SurfaceTextureMultiContextGLTest,
171         AttachToContextSucceedsAfterProducerDisconnect) {
172     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
173 
174     // Latch the texture contents on the primary context.
175     mFW->waitForFrame();
176     ASSERT_EQ(OK, mST->updateTexImage());
177 
178     // Detach from the primary context.
179     native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_CPU);
180     ASSERT_EQ(OK, mST->detachFromContext());
181 
182     // Attach to the secondary context.
183     ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
184             mSecondEglContext));
185     ASSERT_EQ(OK, mST->attachToContext(SECOND_TEX_ID));
186 
187     // Verify that the texture object was created and bound.
188     GLint texBinding = -1;
189     glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &texBinding);
190     EXPECT_EQ(SECOND_TEX_ID, texBinding);
191 
192     // Try to use the texture from the secondary context.
193     glClearColor(0.2, 0.2, 0.2, 0.2);
194     glClear(GL_COLOR_BUFFER_BIT);
195     glViewport(0, 0, 1, 1);
196     mSecondTextureRenderer->drawTexture();
197     ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
198     ASSERT_TRUE(checkPixel( 0,  0,  35,  35,  35,  35));
199 }
200 
TEST_F(SurfaceTextureMultiContextGLTest,AttachToContextSucceedsBeforeUpdateTexImage)201 TEST_F(SurfaceTextureMultiContextGLTest,
202         AttachToContextSucceedsBeforeUpdateTexImage) {
203     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
204 
205     // Detach from the primary context.
206     native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_CPU);
207     ASSERT_EQ(OK, mST->detachFromContext());
208 
209     // Attach to the secondary context.
210     ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
211             mSecondEglContext));
212     ASSERT_EQ(OK, mST->attachToContext(SECOND_TEX_ID));
213 
214     // Verify that the texture object was created and bound.
215     GLint texBinding = -1;
216     glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &texBinding);
217     EXPECT_EQ(SECOND_TEX_ID, texBinding);
218 
219     // Latch the texture contents on the primary context.
220     mFW->waitForFrame();
221     ASSERT_EQ(OK, mST->updateTexImage());
222 
223     // Try to use the texture from the secondary context.
224     glClearColor(0.2, 0.2, 0.2, 0.2);
225     glClear(GL_COLOR_BUFFER_BIT);
226     glViewport(0, 0, 1, 1);
227     mSecondTextureRenderer->drawTexture();
228     ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
229     ASSERT_TRUE(checkPixel( 0,  0,  35,  35,  35,  35));
230 }
231 
TEST_F(SurfaceTextureMultiContextGLTest,AttachToContextFailsWhenAbandoned)232 TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextFailsWhenAbandoned) {
233     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
234 
235     // Latch the texture contents on the primary context.
236     mFW->waitForFrame();
237     ASSERT_EQ(OK, mST->updateTexImage());
238 
239     // Detach from the primary context.
240     ASSERT_EQ(OK, mST->detachFromContext());
241 
242     // Attempt to attach to the secondary context.
243     mST->abandon();
244 
245     // Attempt to attach to the primary context.
246     ASSERT_EQ(NO_INIT, mST->attachToContext(SECOND_TEX_ID));
247 }
248 
TEST_F(SurfaceTextureMultiContextGLTest,AttachToContextFailsWhenAttached)249 TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextFailsWhenAttached) {
250     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
251 
252     // Latch the texture contents on the primary context.
253     mFW->waitForFrame();
254     ASSERT_EQ(OK, mST->updateTexImage());
255 
256     // Attempt to attach to the primary context.
257     ASSERT_EQ(INVALID_OPERATION, mST->attachToContext(SECOND_TEX_ID));
258 }
259 
TEST_F(SurfaceTextureMultiContextGLTest,AttachToContextFailsWhenAttachedBeforeUpdateTexImage)260 TEST_F(SurfaceTextureMultiContextGLTest,
261         AttachToContextFailsWhenAttachedBeforeUpdateTexImage) {
262     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
263 
264     // Attempt to attach to the primary context.
265     ASSERT_EQ(INVALID_OPERATION, mST->attachToContext(SECOND_TEX_ID));
266 }
267 
TEST_F(SurfaceTextureMultiContextGLTest,AttachToContextFailsWithNoDisplay)268 TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextFailsWithNoDisplay) {
269     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
270 
271     // Latch the texture contents on the primary context.
272     mFW->waitForFrame();
273     ASSERT_EQ(OK, mST->updateTexImage());
274 
275     // Detach from the primary context.
276     ASSERT_EQ(OK, mST->detachFromContext());
277 
278     // Make there be no current display.
279     ASSERT_TRUE(eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
280             EGL_NO_CONTEXT));
281     ASSERT_EQ(EGL_SUCCESS, eglGetError());
282 
283     // Attempt to attach with no context current.
284     ASSERT_EQ(INVALID_OPERATION, mST->attachToContext(SECOND_TEX_ID));
285 }
286 
TEST_F(SurfaceTextureMultiContextGLTest,AttachToContextSucceedsTwice)287 TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextSucceedsTwice) {
288     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
289 
290     // Latch the texture contents on the primary context.
291     mFW->waitForFrame();
292     ASSERT_EQ(OK, mST->updateTexImage());
293 
294     // Detach from the primary context.
295     ASSERT_EQ(OK, mST->detachFromContext());
296 
297     // Attach to the secondary context.
298     ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
299             mSecondEglContext));
300     ASSERT_EQ(OK, mST->attachToContext(SECOND_TEX_ID));
301 
302     // Detach from the secondary context.
303     ASSERT_EQ(OK, mST->detachFromContext());
304 
305     // Attach to the tertiary context.
306     ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
307             mThirdEglContext));
308     ASSERT_EQ(OK, mST->attachToContext(THIRD_TEX_ID));
309 
310     // Verify that the texture object was created and bound.
311     GLint texBinding = -1;
312     glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &texBinding);
313     EXPECT_EQ(THIRD_TEX_ID, texBinding);
314 
315     // Try to use the texture from the tertiary context.
316     glClearColor(0.2, 0.2, 0.2, 0.2);
317     glClear(GL_COLOR_BUFFER_BIT);
318     glViewport(0, 0, 1, 1);
319     mThirdTextureRenderer->drawTexture();
320     ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
321     ASSERT_TRUE(checkPixel( 0,  0,  35,  35,  35,  35));
322 }
323 
TEST_F(SurfaceTextureMultiContextGLTest,AttachToContextSucceedsTwiceBeforeUpdateTexImage)324 TEST_F(SurfaceTextureMultiContextGLTest,
325         AttachToContextSucceedsTwiceBeforeUpdateTexImage) {
326     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
327 
328     // Detach from the primary context.
329     ASSERT_EQ(OK, mST->detachFromContext());
330 
331     // Attach to the secondary context.
332     ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
333             mSecondEglContext));
334     ASSERT_EQ(OK, mST->attachToContext(SECOND_TEX_ID));
335 
336     // Detach from the secondary context.
337     ASSERT_EQ(OK, mST->detachFromContext());
338 
339     // Attach to the tertiary context.
340     ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
341             mThirdEglContext));
342     ASSERT_EQ(OK, mST->attachToContext(THIRD_TEX_ID));
343 
344     // Verify that the texture object was created and bound.
345     GLint texBinding = -1;
346     glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &texBinding);
347     EXPECT_EQ(THIRD_TEX_ID, texBinding);
348 
349     // Latch the texture contents on the tertiary context.
350     mFW->waitForFrame();
351     ASSERT_EQ(OK, mST->updateTexImage());
352 
353     // Try to use the texture from the tertiary context.
354     glClearColor(0.2, 0.2, 0.2, 0.2);
355     glClear(GL_COLOR_BUFFER_BIT);
356     glViewport(0, 0, 1, 1);
357     mThirdTextureRenderer->drawTexture();
358     ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
359     ASSERT_TRUE(checkPixel( 0,  0,  35,  35,  35,  35));
360 }
361 
TEST_F(SurfaceTextureMultiContextGLTest,UpdateTexImageSucceedsForBufferConsumedBeforeDetach)362 TEST_F(SurfaceTextureMultiContextGLTest,
363         UpdateTexImageSucceedsForBufferConsumedBeforeDetach) {
364     ASSERT_EQ(NO_ERROR, mST->setDefaultMaxBufferCount(2));
365 
366     // produce two frames and consume them both on the primary context
367     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
368     mFW->waitForFrame();
369     ASSERT_EQ(OK, mST->updateTexImage());
370 
371     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
372     mFW->waitForFrame();
373     ASSERT_EQ(OK, mST->updateTexImage());
374 
375     // produce one more frame
376     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
377 
378     // Detach from the primary context and attach to the secondary context
379     ASSERT_EQ(OK, mST->detachFromContext());
380     ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
381             mSecondEglContext));
382     ASSERT_EQ(OK, mST->attachToContext(SECOND_TEX_ID));
383 
384     // Consume final frame on secondary context
385     mFW->waitForFrame();
386     ASSERT_EQ(OK, mST->updateTexImage());
387 }
388 
TEST_F(SurfaceTextureMultiContextGLTest,AttachAfterDisplayTerminatedSucceeds)389 TEST_F(SurfaceTextureMultiContextGLTest,
390        AttachAfterDisplayTerminatedSucceeds) {
391     ASSERT_EQ(NO_ERROR, mST->setDefaultMaxBufferCount(2));
392 
393     // produce two frames and consume them both on the primary context
394     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
395     mFW->waitForFrame();
396     ASSERT_EQ(OK, mST->updateTexImage());
397 
398     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
399     mFW->waitForFrame();
400     ASSERT_EQ(OK, mST->updateTexImage());
401 
402     // produce one more frame
403     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
404 
405     // Detach from the primary context.
406     ASSERT_EQ(OK, mST->releaseTexImage());
407     ASSERT_EQ(OK, mST->detachFromContext());
408 
409     // Terminate and then initialize the display. All contexts, surfaces
410     // and images are invalid at this point.
411     EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
412     ASSERT_NE(EGL_NO_DISPLAY, mEglDisplay);
413     EGLint majorVersion = 0;
414     EGLint minorVersion = 0;
415     EXPECT_TRUE(eglTerminate(display));
416     EXPECT_TRUE(eglInitialize(mEglDisplay, &majorVersion, &minorVersion));
417     ASSERT_EQ(EGL_SUCCESS, eglGetError());
418 
419     // The surface is invalid so create it again.
420     EGLint pbufferAttribs[] = {
421         EGL_WIDTH, 64,
422         EGL_HEIGHT, 64,
423         EGL_NONE };
424     mEglSurface = eglCreatePbufferSurface(mEglDisplay, mGlConfig,
425             pbufferAttribs);
426 
427     // The second context is invalid so create it again.
428     mSecondEglContext = eglCreateContext(mEglDisplay, mGlConfig,
429             EGL_NO_CONTEXT, getContextAttribs());
430     ASSERT_EQ(EGL_SUCCESS, eglGetError());
431     ASSERT_NE(EGL_NO_CONTEXT, mSecondEglContext);
432 
433     ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
434             mSecondEglContext));
435     ASSERT_EQ(EGL_SUCCESS, eglGetError());
436 
437     // Now attach to and consume final frame on secondary context.
438     ASSERT_EQ(OK, mST->attachToContext(SECOND_TEX_ID));
439     mFW->waitForFrame();
440     ASSERT_EQ(OK, mST->updateTexImage());
441 }
442 
443 
444 } // namespace android
445