You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
240 lines
8.2 KiB
240 lines
8.2 KiB
/*
|
|
* Copyright (C) 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.
|
|
*/
|
|
|
|
#include <android/native_window.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <EGL/egl.h>
|
|
#include <EGL/eglext.h>
|
|
#include <GLES2/gl2.h>
|
|
#include <GLES2/gl2ext.h>
|
|
|
|
#include "ContextSwitchRenderer.h"
|
|
#include <graphics/GLUtils.h>
|
|
|
|
#define LOG_TAG "CTS_OPENGL"
|
|
#define LOG_NDEBUG 0
|
|
#include <android/log.h>
|
|
#include <Trace.h>
|
|
|
|
static const EGLint contextAttribs[] = {
|
|
EGL_CONTEXT_CLIENT_VERSION, 2,
|
|
EGL_NONE };
|
|
|
|
static const int NUM_WORKER_CONTEXTS = 7;
|
|
|
|
static const int CS_TEXTURE_SIZE = 64;
|
|
|
|
static const int CS_NUM_VERTICES = 6;
|
|
|
|
static const float CS_VERTICES[CS_NUM_VERTICES * 3] = {
|
|
0.1f, 0.1f, -0.1f,
|
|
-0.1f, 0.1f, -0.1f,
|
|
-0.1f, -0.1f, -0.1f,
|
|
-0.1f, -0.1f, -0.1f,
|
|
0.1f, -0.1f, -0.1f,
|
|
0.1f, 0.1f, -0.1f };
|
|
|
|
static const float CS_TEX_COORDS[CS_NUM_VERTICES * 2] = {
|
|
1.0f, 1.0f,
|
|
0.0f, 1.0f,
|
|
0.0f, 0.0f,
|
|
0.0f, 0.0f,
|
|
1.0f, 0.0f,
|
|
1.0f, 1.0f };
|
|
|
|
static const char* CS_VERTEX =
|
|
"attribute vec4 a_Position;"
|
|
"attribute vec2 a_TexCoord;"
|
|
"uniform float u_Translate;"
|
|
"varying vec2 v_TexCoord;"
|
|
"void main() {"
|
|
" v_TexCoord = a_TexCoord;"
|
|
" gl_Position.x = a_Position.x + u_Translate;"
|
|
" gl_Position.yzw = a_Position.yzw;"
|
|
"}";
|
|
|
|
static const char* CS_FRAGMENT =
|
|
"precision mediump float;"
|
|
"uniform sampler2D u_Texture;"
|
|
"varying vec2 v_TexCoord;"
|
|
"void main() {"
|
|
" gl_FragColor = texture2D(u_Texture, v_TexCoord);"
|
|
"}";
|
|
|
|
ContextSwitchRenderer::ContextSwitchRenderer(ANativeWindow* window, bool offscreen) :
|
|
Renderer(window, offscreen), mContexts(NULL), mWorkload(0) {
|
|
}
|
|
|
|
bool ContextSwitchRenderer::setUp(int workload) {
|
|
SCOPED_TRACE();
|
|
mWorkload = workload;
|
|
if (!Renderer::setUp(workload)) {
|
|
return false;
|
|
}
|
|
|
|
// Setup texture.
|
|
mTextureId = GLUtils::genTexture(CS_TEXTURE_SIZE, CS_TEXTURE_SIZE, GLUtils::RANDOM_FILL);
|
|
if (mTextureId == 0) {
|
|
return false;
|
|
}
|
|
|
|
// Create program.
|
|
mProgramId = GLUtils::createProgram(&CS_VERTEX, &CS_FRAGMENT);
|
|
if (mProgramId == 0) {
|
|
return false;
|
|
}
|
|
// Bind attributes.
|
|
mTextureUniformHandle = glGetUniformLocation(mProgramId, "u_Texture");
|
|
mTranslateUniformHandle = glGetUniformLocation(mProgramId, "u_Translate");
|
|
mPositionHandle = glGetAttribLocation(mProgramId, "a_Position");
|
|
mTexCoordHandle = glGetAttribLocation(mProgramId, "a_TexCoord");
|
|
|
|
mContexts = new EGLContext[NUM_WORKER_CONTEXTS];
|
|
mFboIds = new GLuint[NUM_WORKER_CONTEXTS];
|
|
for (int i = 0; i < NUM_WORKER_CONTEXTS; i++) {
|
|
// Create the contexts, they share data with the main one.
|
|
mContexts[i] = eglCreateContext(mEglDisplay, mGlConfig, mEglContext, contextAttribs);
|
|
if (EGL_NO_CONTEXT == mContexts[i] || EGL_SUCCESS != eglGetError()) {
|
|
return false;
|
|
}
|
|
|
|
if (!eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mContexts[i])
|
|
|| EGL_SUCCESS != eglGetError()) {
|
|
return false;
|
|
}
|
|
if (mOffscreen) {
|
|
// FBOs are not shared across contexts, textures and renderbuffers are though.
|
|
glGenFramebuffers(1, &mFboIds[i]);
|
|
glBindFramebuffer(GL_FRAMEBUFFER, mFboIds[i]);
|
|
|
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
|
|
GL_RENDERBUFFER, mFboDepthId);
|
|
|
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
|
GL_TEXTURE_2D, mFboTexId, 0);
|
|
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
|
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
|
__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "Framebuffer not complete: %d", status);
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool ContextSwitchRenderer::tearDown() {
|
|
SCOPED_TRACE();
|
|
if (mContexts) {
|
|
// Destroy the contexts, the main one will be handled by Renderer::eglTearDown().
|
|
for (int i = 0; i < NUM_WORKER_CONTEXTS; i++) {
|
|
if (mOffscreen) {
|
|
if (mFboIds[i] != 0) {
|
|
eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mContexts[i]);
|
|
glDeleteFramebuffers(1, &mFboIds[i]);
|
|
mFboIds[i] = 0;
|
|
}
|
|
}
|
|
eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
|
eglDestroyContext(mEglDisplay, mContexts[i]);
|
|
}
|
|
delete[] mContexts;
|
|
}
|
|
eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext);
|
|
if (mTextureId != 0) {
|
|
glDeleteTextures(1, &mTextureId);
|
|
mTextureId = 0;
|
|
}
|
|
if (!Renderer::tearDown()) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void ContextSwitchRenderer::drawWorkload() {
|
|
SCOPED_TRACE();
|
|
|
|
if (mWorkload > 8) {
|
|
return; // This test does not support higher workloads.
|
|
}
|
|
|
|
// Set the background clear color to black.
|
|
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
|
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
|
|
// No culling of back faces
|
|
glDisable(GL_CULL_FACE);
|
|
// No depth testing
|
|
glDisable(GL_DEPTH_TEST);
|
|
|
|
EGLSyncKHR fence = eglCreateSyncKHR(mEglDisplay, EGL_SYNC_FENCE_KHR, NULL);
|
|
|
|
const int TOTAL_NUM_CONTEXTS = NUM_WORKER_CONTEXTS + 1;
|
|
const float TRANSLATION = 0.9f - (TOTAL_NUM_CONTEXTS * 0.2f);
|
|
for (int i = 0; i < TOTAL_NUM_CONTEXTS; i++) {
|
|
eglWaitSyncKHR(mEglDisplay, fence, 0);
|
|
eglDestroySyncKHR(mEglDisplay, fence);
|
|
glUseProgram(mProgramId);
|
|
|
|
// Set the texture.
|
|
glActiveTexture (GL_TEXTURE0);
|
|
glBindTexture(GL_TEXTURE_2D, mTextureId);
|
|
glUniform1i(mTextureUniformHandle, 0);
|
|
|
|
// Set the x translate.
|
|
glUniform1f(mTranslateUniformHandle, (i * 0.2f) + TRANSLATION);
|
|
|
|
glEnableVertexAttribArray(mPositionHandle);
|
|
glEnableVertexAttribArray(mTexCoordHandle);
|
|
glVertexAttribPointer(mPositionHandle, 3, GL_FLOAT, false, 0, CS_VERTICES);
|
|
glVertexAttribPointer(mTexCoordHandle, 2, GL_FLOAT, false, 0, CS_TEX_COORDS);
|
|
|
|
glDrawArrays(GL_TRIANGLES, 0, CS_NUM_VERTICES);
|
|
fence = eglCreateSyncKHR(mEglDisplay, EGL_SYNC_FENCE_KHR, NULL);
|
|
|
|
// Switch to next context.
|
|
if (i < (mWorkload - 1)) {
|
|
eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mContexts[i]);
|
|
// Switch to FBO and re-attach.
|
|
if (mOffscreen) {
|
|
glBindFramebuffer(GL_FRAMEBUFFER, mFboIds[i]);
|
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
|
|
GL_RENDERBUFFER, mFboDepthId);
|
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
|
GL_TEXTURE_2D, mFboTexId, 0);
|
|
glViewport(0, 0, mFboWidth, mFboHeight);
|
|
}
|
|
}
|
|
GLuint err = glGetError();
|
|
if (err != GL_NO_ERROR) {
|
|
__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "GLError %d in drawWorkload", err);
|
|
break;
|
|
}
|
|
}
|
|
|
|
eglWaitSyncKHR(mEglDisplay, fence, 0);
|
|
eglDestroySyncKHR(mEglDisplay, fence);
|
|
|
|
// Switch back to the main context.
|
|
eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext);
|
|
if (mOffscreen) {
|
|
glBindFramebuffer(GL_FRAMEBUFFER, mFboId);
|
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
|
|
GL_RENDERBUFFER, mFboDepthId);
|
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
|
GL_TEXTURE_2D, mFboTexId, 0);
|
|
glViewport(0, 0, mFboWidth, mFboHeight);
|
|
}
|
|
}
|