390 lines
13 KiB
C++
390 lines
13 KiB
C++
|
/*
|
||
|
* Copyright 2013 The Android Open Source Project
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
|
||
|
#define LOG_TAG "SurfaceTextureMultiContextGL_test"
|
||
|
//#define LOG_NDEBUG 0
|
||
|
|
||
|
#include "SurfaceTextureMultiContextGL.h"
|
||
|
|
||
|
#include "FillBuffer.h"
|
||
|
|
||
|
#include <GLES/glext.h>
|
||
|
|
||
|
namespace android {
|
||
|
|
||
|
TEST_F(SurfaceTextureMultiContextGLTest, UpdateFromMultipleContextsFails) {
|
||
|
ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
|
||
|
|
||
|
// Latch the texture contents on the primary context.
|
||
|
mFW->waitForFrame();
|
||
|
ASSERT_EQ(OK, mST->updateTexImage());
|
||
|
|
||
|
// Attempt to latch the texture on the secondary context.
|
||
|
ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
|
||
|
mSecondEglContext));
|
||
|
ASSERT_EQ(EGL_SUCCESS, eglGetError());
|
||
|
ASSERT_EQ(INVALID_OPERATION, mST->updateTexImage());
|
||
|
}
|
||
|
|
||
|
TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextSucceeds) {
|
||
|
ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
|
||
|
|
||
|
// Latch the texture contents on the primary context.
|
||
|
mFW->waitForFrame();
|
||
|
ASSERT_EQ(OK, mST->updateTexImage());
|
||
|
|
||
|
// Detach from the primary context.
|
||
|
ASSERT_EQ(OK, mST->detachFromContext());
|
||
|
|
||
|
// Check that the GL texture was deleted.
|
||
|
EXPECT_EQ(GL_FALSE, glIsTexture(TEX_ID));
|
||
|
}
|
||
|
|
||
|
TEST_F(SurfaceTextureMultiContextGLTest,
|
||
|
DetachFromContextSucceedsAfterProducerDisconnect) {
|
||
|
ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
|
||
|
|
||
|
// Latch the texture contents on the primary context.
|
||
|
mFW->waitForFrame();
|
||
|
ASSERT_EQ(OK, mST->updateTexImage());
|
||
|
|
||
|
// Detach from the primary context.
|
||
|
native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_CPU);
|
||
|
ASSERT_EQ(OK, mST->detachFromContext());
|
||
|
|
||
|
// Check that the GL texture was deleted.
|
||
|
EXPECT_EQ(GL_FALSE, glIsTexture(TEX_ID));
|
||
|
}
|
||
|
|
||
|
TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextFailsWhenAbandoned) {
|
||
|
ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
|
||
|
|
||
|
// Latch the texture contents on the primary context.
|
||
|
mFW->waitForFrame();
|
||
|
ASSERT_EQ(OK, mST->updateTexImage());
|
||
|
|
||
|
// Attempt to detach from the primary context.
|
||
|
mST->abandon();
|
||
|
ASSERT_EQ(NO_INIT, mST->detachFromContext());
|
||
|
}
|
||
|
|
||
|
TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextFailsWhenDetached) {
|
||
|
ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
|
||
|
|
||
|
// Latch the texture contents on the primary context.
|
||
|
mFW->waitForFrame();
|
||
|
ASSERT_EQ(OK, mST->updateTexImage());
|
||
|
|
||
|
// Detach from the primary context.
|
||
|
ASSERT_EQ(OK, mST->detachFromContext());
|
||
|
|
||
|
// Attempt to detach from the primary context again.
|
||
|
ASSERT_EQ(INVALID_OPERATION, mST->detachFromContext());
|
||
|
}
|
||
|
|
||
|
TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextFailsWithNoDisplay) {
|
||
|
ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
|
||
|
|
||
|
// Latch the texture contents on the primary context.
|
||
|
mFW->waitForFrame();
|
||
|
ASSERT_EQ(OK, mST->updateTexImage());
|
||
|
|
||
|
// Make there be no current display.
|
||
|
ASSERT_TRUE(eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
|
||
|
EGL_NO_CONTEXT));
|
||
|
ASSERT_EQ(EGL_SUCCESS, eglGetError());
|
||
|
|
||
|
// Attempt to detach from the primary context.
|
||
|
ASSERT_EQ(INVALID_OPERATION, mST->detachFromContext());
|
||
|
}
|
||
|
|
||
|
TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextFailsWithNoContext) {
|
||
|
ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
|
||
|
|
||
|
// Latch the texture contents on the primary context.
|
||
|
mFW->waitForFrame();
|
||
|
ASSERT_EQ(OK, mST->updateTexImage());
|
||
|
|
||
|
// Make current context be incorrect.
|
||
|
ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
|
||
|
mSecondEglContext));
|
||
|
ASSERT_EQ(EGL_SUCCESS, eglGetError());
|
||
|
|
||
|
// Attempt to detach from the primary context.
|
||
|
ASSERT_EQ(INVALID_OPERATION, mST->detachFromContext());
|
||
|
}
|
||
|
|
||
|
TEST_F(SurfaceTextureMultiContextGLTest, UpdateTexImageFailsWhenDetached) {
|
||
|
ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
|
||
|
|
||
|
// Detach from the primary context.
|
||
|
ASSERT_EQ(OK, mST->detachFromContext());
|
||
|
|
||
|
// Attempt to latch the texture contents on the primary context.
|
||
|
mFW->waitForFrame();
|
||
|
ASSERT_EQ(INVALID_OPERATION, mST->updateTexImage());
|
||
|
}
|
||
|
|
||
|
TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextSucceeds) {
|
||
|
ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
|
||
|
|
||
|
// Latch the texture contents on the primary context.
|
||
|
mFW->waitForFrame();
|
||
|
ASSERT_EQ(OK, mST->updateTexImage());
|
||
|
|
||
|
// Detach from the primary context.
|
||
|
ASSERT_EQ(OK, mST->detachFromContext());
|
||
|
|
||
|
// Attach to the secondary context.
|
||
|
ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
|
||
|
mSecondEglContext));
|
||
|
ASSERT_EQ(OK, mST->attachToContext(SECOND_TEX_ID));
|
||
|
|
||
|
// Verify that the texture object was created and bound.
|
||
|
GLint texBinding = -1;
|
||
|
glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &texBinding);
|
||
|
EXPECT_EQ(SECOND_TEX_ID, texBinding);
|
||
|
|
||
|
// Try to use the texture from the secondary context.
|
||
|
glClearColor(0.2, 0.2, 0.2, 0.2);
|
||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||
|
glViewport(0, 0, 1, 1);
|
||
|
mSecondTextureRenderer->drawTexture();
|
||
|
ASSERT_TRUE(checkPixel( 0, 0, 35, 35, 35, 35));
|
||
|
ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
|
||
|
}
|
||
|
|
||
|
TEST_F(SurfaceTextureMultiContextGLTest,
|
||
|
AttachToContextSucceedsAfterProducerDisconnect) {
|
||
|
ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
|
||
|
|
||
|
// Latch the texture contents on the primary context.
|
||
|
mFW->waitForFrame();
|
||
|
ASSERT_EQ(OK, mST->updateTexImage());
|
||
|
|
||
|
// Detach from the primary context.
|
||
|
native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_CPU);
|
||
|
ASSERT_EQ(OK, mST->detachFromContext());
|
||
|
|
||
|
// Attach to the secondary context.
|
||
|
ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
|
||
|
mSecondEglContext));
|
||
|
ASSERT_EQ(OK, mST->attachToContext(SECOND_TEX_ID));
|
||
|
|
||
|
// Verify that the texture object was created and bound.
|
||
|
GLint texBinding = -1;
|
||
|
glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &texBinding);
|
||
|
EXPECT_EQ(SECOND_TEX_ID, texBinding);
|
||
|
|
||
|
// Try to use the texture from the secondary context.
|
||
|
glClearColor(0.2, 0.2, 0.2, 0.2);
|
||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||
|
glViewport(0, 0, 1, 1);
|
||
|
mSecondTextureRenderer->drawTexture();
|
||
|
ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
|
||
|
ASSERT_TRUE(checkPixel( 0, 0, 35, 35, 35, 35));
|
||
|
}
|
||
|
|
||
|
TEST_F(SurfaceTextureMultiContextGLTest,
|
||
|
AttachToContextSucceedsBeforeUpdateTexImage) {
|
||
|
ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
|
||
|
|
||
|
// Detach from the primary context.
|
||
|
native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_CPU);
|
||
|
ASSERT_EQ(OK, mST->detachFromContext());
|
||
|
|
||
|
// Attach to the secondary context.
|
||
|
ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
|
||
|
mSecondEglContext));
|
||
|
ASSERT_EQ(OK, mST->attachToContext(SECOND_TEX_ID));
|
||
|
|
||
|
// Verify that the texture object was created and bound.
|
||
|
GLint texBinding = -1;
|
||
|
glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &texBinding);
|
||
|
EXPECT_EQ(SECOND_TEX_ID, texBinding);
|
||
|
|
||
|
// Latch the texture contents on the primary context.
|
||
|
mFW->waitForFrame();
|
||
|
ASSERT_EQ(OK, mST->updateTexImage());
|
||
|
|
||
|
// Try to use the texture from the secondary context.
|
||
|
glClearColor(0.2, 0.2, 0.2, 0.2);
|
||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||
|
glViewport(0, 0, 1, 1);
|
||
|
mSecondTextureRenderer->drawTexture();
|
||
|
ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
|
||
|
ASSERT_TRUE(checkPixel( 0, 0, 35, 35, 35, 35));
|
||
|
}
|
||
|
|
||
|
TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextFailsWhenAbandoned) {
|
||
|
ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
|
||
|
|
||
|
// Latch the texture contents on the primary context.
|
||
|
mFW->waitForFrame();
|
||
|
ASSERT_EQ(OK, mST->updateTexImage());
|
||
|
|
||
|
// Detach from the primary context.
|
||
|
ASSERT_EQ(OK, mST->detachFromContext());
|
||
|
|
||
|
// Attempt to attach to the secondary context.
|
||
|
mST->abandon();
|
||
|
|
||
|
// Attempt to attach to the primary context.
|
||
|
ASSERT_EQ(NO_INIT, mST->attachToContext(SECOND_TEX_ID));
|
||
|
}
|
||
|
|
||
|
TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextFailsWhenAttached) {
|
||
|
ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
|
||
|
|
||
|
// Latch the texture contents on the primary context.
|
||
|
mFW->waitForFrame();
|
||
|
ASSERT_EQ(OK, mST->updateTexImage());
|
||
|
|
||
|
// Attempt to attach to the primary context.
|
||
|
ASSERT_EQ(INVALID_OPERATION, mST->attachToContext(SECOND_TEX_ID));
|
||
|
}
|
||
|
|
||
|
TEST_F(SurfaceTextureMultiContextGLTest,
|
||
|
AttachToContextFailsWhenAttachedBeforeUpdateTexImage) {
|
||
|
ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
|
||
|
|
||
|
// Attempt to attach to the primary context.
|
||
|
ASSERT_EQ(INVALID_OPERATION, mST->attachToContext(SECOND_TEX_ID));
|
||
|
}
|
||
|
|
||
|
TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextFailsWithNoDisplay) {
|
||
|
ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
|
||
|
|
||
|
// Latch the texture contents on the primary context.
|
||
|
mFW->waitForFrame();
|
||
|
ASSERT_EQ(OK, mST->updateTexImage());
|
||
|
|
||
|
// Detach from the primary context.
|
||
|
ASSERT_EQ(OK, mST->detachFromContext());
|
||
|
|
||
|
// Make there be no current display.
|
||
|
ASSERT_TRUE(eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
|
||
|
EGL_NO_CONTEXT));
|
||
|
ASSERT_EQ(EGL_SUCCESS, eglGetError());
|
||
|
|
||
|
// Attempt to attach with no context current.
|
||
|
ASSERT_EQ(INVALID_OPERATION, mST->attachToContext(SECOND_TEX_ID));
|
||
|
}
|
||
|
|
||
|
TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextSucceedsTwice) {
|
||
|
ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
|
||
|
|
||
|
// Latch the texture contents on the primary context.
|
||
|
mFW->waitForFrame();
|
||
|
ASSERT_EQ(OK, mST->updateTexImage());
|
||
|
|
||
|
// Detach from the primary context.
|
||
|
ASSERT_EQ(OK, mST->detachFromContext());
|
||
|
|
||
|
// Attach to the secondary context.
|
||
|
ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
|
||
|
mSecondEglContext));
|
||
|
ASSERT_EQ(OK, mST->attachToContext(SECOND_TEX_ID));
|
||
|
|
||
|
// Detach from the secondary context.
|
||
|
ASSERT_EQ(OK, mST->detachFromContext());
|
||
|
|
||
|
// Attach to the tertiary context.
|
||
|
ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
|
||
|
mThirdEglContext));
|
||
|
ASSERT_EQ(OK, mST->attachToContext(THIRD_TEX_ID));
|
||
|
|
||
|
// Verify that the texture object was created and bound.
|
||
|
GLint texBinding = -1;
|
||
|
glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &texBinding);
|
||
|
EXPECT_EQ(THIRD_TEX_ID, texBinding);
|
||
|
|
||
|
// Try to use the texture from the tertiary context.
|
||
|
glClearColor(0.2, 0.2, 0.2, 0.2);
|
||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||
|
glViewport(0, 0, 1, 1);
|
||
|
mThirdTextureRenderer->drawTexture();
|
||
|
ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
|
||
|
ASSERT_TRUE(checkPixel( 0, 0, 35, 35, 35, 35));
|
||
|
}
|
||
|
|
||
|
TEST_F(SurfaceTextureMultiContextGLTest,
|
||
|
AttachToContextSucceedsTwiceBeforeUpdateTexImage) {
|
||
|
ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
|
||
|
|
||
|
// Detach from the primary context.
|
||
|
ASSERT_EQ(OK, mST->detachFromContext());
|
||
|
|
||
|
// Attach to the secondary context.
|
||
|
ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
|
||
|
mSecondEglContext));
|
||
|
ASSERT_EQ(OK, mST->attachToContext(SECOND_TEX_ID));
|
||
|
|
||
|
// Detach from the secondary context.
|
||
|
ASSERT_EQ(OK, mST->detachFromContext());
|
||
|
|
||
|
// Attach to the tertiary context.
|
||
|
ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
|
||
|
mThirdEglContext));
|
||
|
ASSERT_EQ(OK, mST->attachToContext(THIRD_TEX_ID));
|
||
|
|
||
|
// Verify that the texture object was created and bound.
|
||
|
GLint texBinding = -1;
|
||
|
glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &texBinding);
|
||
|
EXPECT_EQ(THIRD_TEX_ID, texBinding);
|
||
|
|
||
|
// Latch the texture contents on the tertiary context.
|
||
|
mFW->waitForFrame();
|
||
|
ASSERT_EQ(OK, mST->updateTexImage());
|
||
|
|
||
|
// Try to use the texture from the tertiary context.
|
||
|
glClearColor(0.2, 0.2, 0.2, 0.2);
|
||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||
|
glViewport(0, 0, 1, 1);
|
||
|
mThirdTextureRenderer->drawTexture();
|
||
|
ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
|
||
|
ASSERT_TRUE(checkPixel( 0, 0, 35, 35, 35, 35));
|
||
|
}
|
||
|
|
||
|
TEST_F(SurfaceTextureMultiContextGLTest,
|
||
|
UpdateTexImageSucceedsForBufferConsumedBeforeDetach) {
|
||
|
ASSERT_EQ(NO_ERROR, mST->setDefaultMaxBufferCount(2));
|
||
|
|
||
|
// produce two frames and consume them both on the primary context
|
||
|
ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
|
||
|
mFW->waitForFrame();
|
||
|
ASSERT_EQ(OK, mST->updateTexImage());
|
||
|
|
||
|
ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
|
||
|
mFW->waitForFrame();
|
||
|
ASSERT_EQ(OK, mST->updateTexImage());
|
||
|
|
||
|
// produce one more frame
|
||
|
ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
|
||
|
|
||
|
// Detach from the primary context and attach to the secondary context
|
||
|
ASSERT_EQ(OK, mST->detachFromContext());
|
||
|
ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
|
||
|
mSecondEglContext));
|
||
|
ASSERT_EQ(OK, mST->attachToContext(SECOND_TEX_ID));
|
||
|
|
||
|
// Consume final frame on secondary context
|
||
|
mFW->waitForFrame();
|
||
|
ASSERT_EQ(OK, mST->updateTexImage());
|
||
|
}
|
||
|
|
||
|
} // namespace android
|