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