1*b7c941bbSAndroid Build Coastguard Worker /*
2*b7c941bbSAndroid Build Coastguard Worker * Copyright (C) 2013 The Android Open Source Project
3*b7c941bbSAndroid Build Coastguard Worker *
4*b7c941bbSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5*b7c941bbSAndroid Build Coastguard Worker * in compliance with the License. You may obtain a copy of the License at
6*b7c941bbSAndroid Build Coastguard Worker *
7*b7c941bbSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
8*b7c941bbSAndroid Build Coastguard Worker *
9*b7c941bbSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software distributed under the License
10*b7c941bbSAndroid Build Coastguard Worker * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11*b7c941bbSAndroid Build Coastguard Worker * or implied. See the License for the specific language governing permissions and limitations under
12*b7c941bbSAndroid Build Coastguard Worker * the License.
13*b7c941bbSAndroid Build Coastguard Worker */
14*b7c941bbSAndroid Build Coastguard Worker
15*b7c941bbSAndroid Build Coastguard Worker #include <android/native_window.h>
16*b7c941bbSAndroid Build Coastguard Worker
17*b7c941bbSAndroid Build Coastguard Worker #include <stdlib.h>
18*b7c941bbSAndroid Build Coastguard Worker
19*b7c941bbSAndroid Build Coastguard Worker #include <EGL/egl.h>
20*b7c941bbSAndroid Build Coastguard Worker #include <EGL/eglext.h>
21*b7c941bbSAndroid Build Coastguard Worker #include <GLES2/gl2.h>
22*b7c941bbSAndroid Build Coastguard Worker #include <GLES2/gl2ext.h>
23*b7c941bbSAndroid Build Coastguard Worker
24*b7c941bbSAndroid Build Coastguard Worker #include "ContextSwitchRenderer.h"
25*b7c941bbSAndroid Build Coastguard Worker #include <graphics/GLUtils.h>
26*b7c941bbSAndroid Build Coastguard Worker
27*b7c941bbSAndroid Build Coastguard Worker #define LOG_TAG "CTS_OPENGL"
28*b7c941bbSAndroid Build Coastguard Worker #define LOG_NDEBUG 0
29*b7c941bbSAndroid Build Coastguard Worker #include <android/log.h>
30*b7c941bbSAndroid Build Coastguard Worker #include <Trace.h>
31*b7c941bbSAndroid Build Coastguard Worker
32*b7c941bbSAndroid Build Coastguard Worker static const EGLint contextAttribs[] = {
33*b7c941bbSAndroid Build Coastguard Worker EGL_CONTEXT_CLIENT_VERSION, 2,
34*b7c941bbSAndroid Build Coastguard Worker EGL_NONE };
35*b7c941bbSAndroid Build Coastguard Worker
36*b7c941bbSAndroid Build Coastguard Worker static const int NUM_WORKER_CONTEXTS = 7;
37*b7c941bbSAndroid Build Coastguard Worker
38*b7c941bbSAndroid Build Coastguard Worker static const int CS_TEXTURE_SIZE = 64;
39*b7c941bbSAndroid Build Coastguard Worker
40*b7c941bbSAndroid Build Coastguard Worker static const int CS_NUM_VERTICES = 6;
41*b7c941bbSAndroid Build Coastguard Worker
42*b7c941bbSAndroid Build Coastguard Worker static const float CS_VERTICES[CS_NUM_VERTICES * 3] = {
43*b7c941bbSAndroid Build Coastguard Worker 0.1f, 0.1f, -0.1f,
44*b7c941bbSAndroid Build Coastguard Worker -0.1f, 0.1f, -0.1f,
45*b7c941bbSAndroid Build Coastguard Worker -0.1f, -0.1f, -0.1f,
46*b7c941bbSAndroid Build Coastguard Worker -0.1f, -0.1f, -0.1f,
47*b7c941bbSAndroid Build Coastguard Worker 0.1f, -0.1f, -0.1f,
48*b7c941bbSAndroid Build Coastguard Worker 0.1f, 0.1f, -0.1f };
49*b7c941bbSAndroid Build Coastguard Worker
50*b7c941bbSAndroid Build Coastguard Worker static const float CS_TEX_COORDS[CS_NUM_VERTICES * 2] = {
51*b7c941bbSAndroid Build Coastguard Worker 1.0f, 1.0f,
52*b7c941bbSAndroid Build Coastguard Worker 0.0f, 1.0f,
53*b7c941bbSAndroid Build Coastguard Worker 0.0f, 0.0f,
54*b7c941bbSAndroid Build Coastguard Worker 0.0f, 0.0f,
55*b7c941bbSAndroid Build Coastguard Worker 1.0f, 0.0f,
56*b7c941bbSAndroid Build Coastguard Worker 1.0f, 1.0f };
57*b7c941bbSAndroid Build Coastguard Worker
58*b7c941bbSAndroid Build Coastguard Worker static const char* CS_VERTEX =
59*b7c941bbSAndroid Build Coastguard Worker "attribute vec4 a_Position;"
60*b7c941bbSAndroid Build Coastguard Worker "attribute vec2 a_TexCoord;"
61*b7c941bbSAndroid Build Coastguard Worker "uniform float u_Translate;"
62*b7c941bbSAndroid Build Coastguard Worker "varying vec2 v_TexCoord;"
63*b7c941bbSAndroid Build Coastguard Worker "void main() {"
64*b7c941bbSAndroid Build Coastguard Worker " v_TexCoord = a_TexCoord;"
65*b7c941bbSAndroid Build Coastguard Worker " gl_Position.x = a_Position.x + u_Translate;"
66*b7c941bbSAndroid Build Coastguard Worker " gl_Position.yzw = a_Position.yzw;"
67*b7c941bbSAndroid Build Coastguard Worker "}";
68*b7c941bbSAndroid Build Coastguard Worker
69*b7c941bbSAndroid Build Coastguard Worker static const char* CS_FRAGMENT =
70*b7c941bbSAndroid Build Coastguard Worker "precision mediump float;"
71*b7c941bbSAndroid Build Coastguard Worker "uniform sampler2D u_Texture;"
72*b7c941bbSAndroid Build Coastguard Worker "varying vec2 v_TexCoord;"
73*b7c941bbSAndroid Build Coastguard Worker "void main() {"
74*b7c941bbSAndroid Build Coastguard Worker " gl_FragColor = texture2D(u_Texture, v_TexCoord);"
75*b7c941bbSAndroid Build Coastguard Worker "}";
76*b7c941bbSAndroid Build Coastguard Worker
ContextSwitchRenderer(ANativeWindow * window,bool offscreen)77*b7c941bbSAndroid Build Coastguard Worker ContextSwitchRenderer::ContextSwitchRenderer(ANativeWindow* window, bool offscreen) :
78*b7c941bbSAndroid Build Coastguard Worker Renderer(window, offscreen), mContexts(NULL), mWorkload(0) {
79*b7c941bbSAndroid Build Coastguard Worker }
80*b7c941bbSAndroid Build Coastguard Worker
setUp(int workload)81*b7c941bbSAndroid Build Coastguard Worker bool ContextSwitchRenderer::setUp(int workload) {
82*b7c941bbSAndroid Build Coastguard Worker SCOPED_TRACE();
83*b7c941bbSAndroid Build Coastguard Worker mWorkload = workload;
84*b7c941bbSAndroid Build Coastguard Worker if (!Renderer::setUp(workload)) {
85*b7c941bbSAndroid Build Coastguard Worker return false;
86*b7c941bbSAndroid Build Coastguard Worker }
87*b7c941bbSAndroid Build Coastguard Worker
88*b7c941bbSAndroid Build Coastguard Worker // Setup texture.
89*b7c941bbSAndroid Build Coastguard Worker mTextureId = GLUtils::genTexture(CS_TEXTURE_SIZE, CS_TEXTURE_SIZE, GLUtils::RANDOM_FILL);
90*b7c941bbSAndroid Build Coastguard Worker if (mTextureId == 0) {
91*b7c941bbSAndroid Build Coastguard Worker return false;
92*b7c941bbSAndroid Build Coastguard Worker }
93*b7c941bbSAndroid Build Coastguard Worker
94*b7c941bbSAndroid Build Coastguard Worker // Create program.
95*b7c941bbSAndroid Build Coastguard Worker mProgramId = GLUtils::createProgram(&CS_VERTEX, &CS_FRAGMENT);
96*b7c941bbSAndroid Build Coastguard Worker if (mProgramId == 0) {
97*b7c941bbSAndroid Build Coastguard Worker return false;
98*b7c941bbSAndroid Build Coastguard Worker }
99*b7c941bbSAndroid Build Coastguard Worker // Bind attributes.
100*b7c941bbSAndroid Build Coastguard Worker mTextureUniformHandle = glGetUniformLocation(mProgramId, "u_Texture");
101*b7c941bbSAndroid Build Coastguard Worker mTranslateUniformHandle = glGetUniformLocation(mProgramId, "u_Translate");
102*b7c941bbSAndroid Build Coastguard Worker mPositionHandle = glGetAttribLocation(mProgramId, "a_Position");
103*b7c941bbSAndroid Build Coastguard Worker mTexCoordHandle = glGetAttribLocation(mProgramId, "a_TexCoord");
104*b7c941bbSAndroid Build Coastguard Worker
105*b7c941bbSAndroid Build Coastguard Worker mContexts = new EGLContext[NUM_WORKER_CONTEXTS];
106*b7c941bbSAndroid Build Coastguard Worker mFboIds = new GLuint[NUM_WORKER_CONTEXTS];
107*b7c941bbSAndroid Build Coastguard Worker for (int i = 0; i < NUM_WORKER_CONTEXTS; i++) {
108*b7c941bbSAndroid Build Coastguard Worker // Create the contexts, they share data with the main one.
109*b7c941bbSAndroid Build Coastguard Worker mContexts[i] = eglCreateContext(mEglDisplay, mGlConfig, mEglContext, contextAttribs);
110*b7c941bbSAndroid Build Coastguard Worker if (EGL_NO_CONTEXT == mContexts[i] || EGL_SUCCESS != eglGetError()) {
111*b7c941bbSAndroid Build Coastguard Worker return false;
112*b7c941bbSAndroid Build Coastguard Worker }
113*b7c941bbSAndroid Build Coastguard Worker
114*b7c941bbSAndroid Build Coastguard Worker if (!eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mContexts[i])
115*b7c941bbSAndroid Build Coastguard Worker || EGL_SUCCESS != eglGetError()) {
116*b7c941bbSAndroid Build Coastguard Worker return false;
117*b7c941bbSAndroid Build Coastguard Worker }
118*b7c941bbSAndroid Build Coastguard Worker if (mOffscreen) {
119*b7c941bbSAndroid Build Coastguard Worker // FBOs are not shared across contexts, textures and renderbuffers are though.
120*b7c941bbSAndroid Build Coastguard Worker glGenFramebuffers(1, &mFboIds[i]);
121*b7c941bbSAndroid Build Coastguard Worker glBindFramebuffer(GL_FRAMEBUFFER, mFboIds[i]);
122*b7c941bbSAndroid Build Coastguard Worker
123*b7c941bbSAndroid Build Coastguard Worker glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
124*b7c941bbSAndroid Build Coastguard Worker GL_RENDERBUFFER, mFboDepthId);
125*b7c941bbSAndroid Build Coastguard Worker
126*b7c941bbSAndroid Build Coastguard Worker glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
127*b7c941bbSAndroid Build Coastguard Worker GL_TEXTURE_2D, mFboTexId, 0);
128*b7c941bbSAndroid Build Coastguard Worker GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
129*b7c941bbSAndroid Build Coastguard Worker if (status != GL_FRAMEBUFFER_COMPLETE) {
130*b7c941bbSAndroid Build Coastguard Worker __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "Framebuffer not complete: %d", status);
131*b7c941bbSAndroid Build Coastguard Worker return false;
132*b7c941bbSAndroid Build Coastguard Worker }
133*b7c941bbSAndroid Build Coastguard Worker }
134*b7c941bbSAndroid Build Coastguard Worker }
135*b7c941bbSAndroid Build Coastguard Worker return true;
136*b7c941bbSAndroid Build Coastguard Worker }
137*b7c941bbSAndroid Build Coastguard Worker
tearDown()138*b7c941bbSAndroid Build Coastguard Worker bool ContextSwitchRenderer::tearDown() {
139*b7c941bbSAndroid Build Coastguard Worker SCOPED_TRACE();
140*b7c941bbSAndroid Build Coastguard Worker if (mContexts) {
141*b7c941bbSAndroid Build Coastguard Worker // Destroy the contexts, the main one will be handled by Renderer::eglTearDown().
142*b7c941bbSAndroid Build Coastguard Worker for (int i = 0; i < NUM_WORKER_CONTEXTS; i++) {
143*b7c941bbSAndroid Build Coastguard Worker if (mOffscreen) {
144*b7c941bbSAndroid Build Coastguard Worker if (mFboIds[i] != 0) {
145*b7c941bbSAndroid Build Coastguard Worker eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mContexts[i]);
146*b7c941bbSAndroid Build Coastguard Worker glDeleteFramebuffers(1, &mFboIds[i]);
147*b7c941bbSAndroid Build Coastguard Worker mFboIds[i] = 0;
148*b7c941bbSAndroid Build Coastguard Worker }
149*b7c941bbSAndroid Build Coastguard Worker }
150*b7c941bbSAndroid Build Coastguard Worker eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
151*b7c941bbSAndroid Build Coastguard Worker eglDestroyContext(mEglDisplay, mContexts[i]);
152*b7c941bbSAndroid Build Coastguard Worker }
153*b7c941bbSAndroid Build Coastguard Worker delete[] mContexts;
154*b7c941bbSAndroid Build Coastguard Worker }
155*b7c941bbSAndroid Build Coastguard Worker eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext);
156*b7c941bbSAndroid Build Coastguard Worker if (mTextureId != 0) {
157*b7c941bbSAndroid Build Coastguard Worker glDeleteTextures(1, &mTextureId);
158*b7c941bbSAndroid Build Coastguard Worker mTextureId = 0;
159*b7c941bbSAndroid Build Coastguard Worker }
160*b7c941bbSAndroid Build Coastguard Worker if (!Renderer::tearDown()) {
161*b7c941bbSAndroid Build Coastguard Worker return false;
162*b7c941bbSAndroid Build Coastguard Worker }
163*b7c941bbSAndroid Build Coastguard Worker return true;
164*b7c941bbSAndroid Build Coastguard Worker }
165*b7c941bbSAndroid Build Coastguard Worker
drawWorkload()166*b7c941bbSAndroid Build Coastguard Worker void ContextSwitchRenderer::drawWorkload() {
167*b7c941bbSAndroid Build Coastguard Worker SCOPED_TRACE();
168*b7c941bbSAndroid Build Coastguard Worker
169*b7c941bbSAndroid Build Coastguard Worker if (mWorkload > 8) {
170*b7c941bbSAndroid Build Coastguard Worker return; // This test does not support higher workloads.
171*b7c941bbSAndroid Build Coastguard Worker }
172*b7c941bbSAndroid Build Coastguard Worker
173*b7c941bbSAndroid Build Coastguard Worker // Set the background clear color to black.
174*b7c941bbSAndroid Build Coastguard Worker glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
175*b7c941bbSAndroid Build Coastguard Worker glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
176*b7c941bbSAndroid Build Coastguard Worker // No culling of back faces
177*b7c941bbSAndroid Build Coastguard Worker glDisable(GL_CULL_FACE);
178*b7c941bbSAndroid Build Coastguard Worker // No depth testing
179*b7c941bbSAndroid Build Coastguard Worker glDisable(GL_DEPTH_TEST);
180*b7c941bbSAndroid Build Coastguard Worker
181*b7c941bbSAndroid Build Coastguard Worker EGLSyncKHR fence = eglCreateSyncKHR(mEglDisplay, EGL_SYNC_FENCE_KHR, NULL);
182*b7c941bbSAndroid Build Coastguard Worker
183*b7c941bbSAndroid Build Coastguard Worker const int TOTAL_NUM_CONTEXTS = NUM_WORKER_CONTEXTS + 1;
184*b7c941bbSAndroid Build Coastguard Worker const float TRANSLATION = 0.9f - (TOTAL_NUM_CONTEXTS * 0.2f);
185*b7c941bbSAndroid Build Coastguard Worker for (int i = 0; i < TOTAL_NUM_CONTEXTS; i++) {
186*b7c941bbSAndroid Build Coastguard Worker eglWaitSyncKHR(mEglDisplay, fence, 0);
187*b7c941bbSAndroid Build Coastguard Worker eglDestroySyncKHR(mEglDisplay, fence);
188*b7c941bbSAndroid Build Coastguard Worker glUseProgram(mProgramId);
189*b7c941bbSAndroid Build Coastguard Worker
190*b7c941bbSAndroid Build Coastguard Worker // Set the texture.
191*b7c941bbSAndroid Build Coastguard Worker glActiveTexture (GL_TEXTURE0);
192*b7c941bbSAndroid Build Coastguard Worker glBindTexture(GL_TEXTURE_2D, mTextureId);
193*b7c941bbSAndroid Build Coastguard Worker glUniform1i(mTextureUniformHandle, 0);
194*b7c941bbSAndroid Build Coastguard Worker
195*b7c941bbSAndroid Build Coastguard Worker // Set the x translate.
196*b7c941bbSAndroid Build Coastguard Worker glUniform1f(mTranslateUniformHandle, (i * 0.2f) + TRANSLATION);
197*b7c941bbSAndroid Build Coastguard Worker
198*b7c941bbSAndroid Build Coastguard Worker glEnableVertexAttribArray(mPositionHandle);
199*b7c941bbSAndroid Build Coastguard Worker glEnableVertexAttribArray(mTexCoordHandle);
200*b7c941bbSAndroid Build Coastguard Worker glVertexAttribPointer(mPositionHandle, 3, GL_FLOAT, false, 0, CS_VERTICES);
201*b7c941bbSAndroid Build Coastguard Worker glVertexAttribPointer(mTexCoordHandle, 2, GL_FLOAT, false, 0, CS_TEX_COORDS);
202*b7c941bbSAndroid Build Coastguard Worker
203*b7c941bbSAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, CS_NUM_VERTICES);
204*b7c941bbSAndroid Build Coastguard Worker fence = eglCreateSyncKHR(mEglDisplay, EGL_SYNC_FENCE_KHR, NULL);
205*b7c941bbSAndroid Build Coastguard Worker
206*b7c941bbSAndroid Build Coastguard Worker // Switch to next context.
207*b7c941bbSAndroid Build Coastguard Worker if (i < (mWorkload - 1)) {
208*b7c941bbSAndroid Build Coastguard Worker eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mContexts[i]);
209*b7c941bbSAndroid Build Coastguard Worker // Switch to FBO and re-attach.
210*b7c941bbSAndroid Build Coastguard Worker if (mOffscreen) {
211*b7c941bbSAndroid Build Coastguard Worker glBindFramebuffer(GL_FRAMEBUFFER, mFboIds[i]);
212*b7c941bbSAndroid Build Coastguard Worker glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
213*b7c941bbSAndroid Build Coastguard Worker GL_RENDERBUFFER, mFboDepthId);
214*b7c941bbSAndroid Build Coastguard Worker glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
215*b7c941bbSAndroid Build Coastguard Worker GL_TEXTURE_2D, mFboTexId, 0);
216*b7c941bbSAndroid Build Coastguard Worker glViewport(0, 0, mFboWidth, mFboHeight);
217*b7c941bbSAndroid Build Coastguard Worker }
218*b7c941bbSAndroid Build Coastguard Worker }
219*b7c941bbSAndroid Build Coastguard Worker GLuint err = glGetError();
220*b7c941bbSAndroid Build Coastguard Worker if (err != GL_NO_ERROR) {
221*b7c941bbSAndroid Build Coastguard Worker __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "GLError %d in drawWorkload", err);
222*b7c941bbSAndroid Build Coastguard Worker break;
223*b7c941bbSAndroid Build Coastguard Worker }
224*b7c941bbSAndroid Build Coastguard Worker }
225*b7c941bbSAndroid Build Coastguard Worker
226*b7c941bbSAndroid Build Coastguard Worker eglWaitSyncKHR(mEglDisplay, fence, 0);
227*b7c941bbSAndroid Build Coastguard Worker eglDestroySyncKHR(mEglDisplay, fence);
228*b7c941bbSAndroid Build Coastguard Worker
229*b7c941bbSAndroid Build Coastguard Worker // Switch back to the main context.
230*b7c941bbSAndroid Build Coastguard Worker eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext);
231*b7c941bbSAndroid Build Coastguard Worker if (mOffscreen) {
232*b7c941bbSAndroid Build Coastguard Worker glBindFramebuffer(GL_FRAMEBUFFER, mFboId);
233*b7c941bbSAndroid Build Coastguard Worker glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
234*b7c941bbSAndroid Build Coastguard Worker GL_RENDERBUFFER, mFboDepthId);
235*b7c941bbSAndroid Build Coastguard Worker glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
236*b7c941bbSAndroid Build Coastguard Worker GL_TEXTURE_2D, mFboTexId, 0);
237*b7c941bbSAndroid Build Coastguard Worker glViewport(0, 0, mFboWidth, mFboHeight);
238*b7c941bbSAndroid Build Coastguard Worker }
239*b7c941bbSAndroid Build Coastguard Worker }
240