xref: /aosp_15_r20/cts/tests/openglperf2/jni/primitive/contextswitch/ContextSwitchRenderer.cpp (revision b7c941bb3fa97aba169d73cee0bed2de8ac964bf)
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