xref: /aosp_15_r20/frameworks/native/cmds/flatland/GLHelper.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1*38e8c45fSAndroid Build Coastguard Worker /*
2*38e8c45fSAndroid Build Coastguard Worker  * Copyright (C) 2012 The Android Open Source Project
3*38e8c45fSAndroid Build Coastguard Worker  *
4*38e8c45fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*38e8c45fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*38e8c45fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*38e8c45fSAndroid Build Coastguard Worker  *
8*38e8c45fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*38e8c45fSAndroid Build Coastguard Worker  *
10*38e8c45fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*38e8c45fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*38e8c45fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*38e8c45fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*38e8c45fSAndroid Build Coastguard Worker  * limitations under the License.
15*38e8c45fSAndroid Build Coastguard Worker  */
16*38e8c45fSAndroid Build Coastguard Worker 
17*38e8c45fSAndroid Build Coastguard Worker #include "GLHelper.h"
18*38e8c45fSAndroid Build Coastguard Worker 
19*38e8c45fSAndroid Build Coastguard Worker #include <GLES2/gl2.h>
20*38e8c45fSAndroid Build Coastguard Worker #include <GLES2/gl2ext.h>
21*38e8c45fSAndroid Build Coastguard Worker #include <com_android_graphics_libgui_flags.h>
22*38e8c45fSAndroid Build Coastguard Worker #include <gui/SurfaceComposerClient.h>
23*38e8c45fSAndroid Build Coastguard Worker #include <ui/DisplayMode.h>
24*38e8c45fSAndroid Build Coastguard Worker 
25*38e8c45fSAndroid Build Coastguard Worker namespace android {
26*38e8c45fSAndroid Build Coastguard Worker 
GLHelper()27*38e8c45fSAndroid Build Coastguard Worker GLHelper::GLHelper() :
28*38e8c45fSAndroid Build Coastguard Worker     mDisplay(EGL_NO_DISPLAY),
29*38e8c45fSAndroid Build Coastguard Worker     mContext(EGL_NO_CONTEXT),
30*38e8c45fSAndroid Build Coastguard Worker     mDummySurface(EGL_NO_SURFACE),
31*38e8c45fSAndroid Build Coastguard Worker     mConfig(0),
32*38e8c45fSAndroid Build Coastguard Worker     mShaderPrograms(nullptr),
33*38e8c45fSAndroid Build Coastguard Worker     mDitherTexture(0) {
34*38e8c45fSAndroid Build Coastguard Worker }
35*38e8c45fSAndroid Build Coastguard Worker 
~GLHelper()36*38e8c45fSAndroid Build Coastguard Worker GLHelper::~GLHelper() {
37*38e8c45fSAndroid Build Coastguard Worker }
38*38e8c45fSAndroid Build Coastguard Worker 
setUp(const sp<IBinder> & displayToken,const ShaderDesc * shaderDescs,size_t numShaders)39*38e8c45fSAndroid Build Coastguard Worker bool GLHelper::setUp(const sp<IBinder>& displayToken, const ShaderDesc* shaderDescs,
40*38e8c45fSAndroid Build Coastguard Worker                      size_t numShaders) {
41*38e8c45fSAndroid Build Coastguard Worker     bool result;
42*38e8c45fSAndroid Build Coastguard Worker 
43*38e8c45fSAndroid Build Coastguard Worker     mDisplayToken = displayToken;
44*38e8c45fSAndroid Build Coastguard Worker 
45*38e8c45fSAndroid Build Coastguard Worker     mDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
46*38e8c45fSAndroid Build Coastguard Worker     if (mDisplay == EGL_NO_DISPLAY) {
47*38e8c45fSAndroid Build Coastguard Worker         fprintf(stderr, "eglGetDisplay error: %#x\n", eglGetError());
48*38e8c45fSAndroid Build Coastguard Worker         return false;
49*38e8c45fSAndroid Build Coastguard Worker     }
50*38e8c45fSAndroid Build Coastguard Worker 
51*38e8c45fSAndroid Build Coastguard Worker     EGLint majorVersion;
52*38e8c45fSAndroid Build Coastguard Worker     EGLint minorVersion;
53*38e8c45fSAndroid Build Coastguard Worker     result = eglInitialize(mDisplay, &majorVersion, &minorVersion);
54*38e8c45fSAndroid Build Coastguard Worker     if (result != EGL_TRUE) {
55*38e8c45fSAndroid Build Coastguard Worker         fprintf(stderr, "eglInitialize error: %#x\n", eglGetError());
56*38e8c45fSAndroid Build Coastguard Worker         return false;
57*38e8c45fSAndroid Build Coastguard Worker     }
58*38e8c45fSAndroid Build Coastguard Worker 
59*38e8c45fSAndroid Build Coastguard Worker     EGLint numConfigs = 0;
60*38e8c45fSAndroid Build Coastguard Worker     EGLint configAttribs[] = {
61*38e8c45fSAndroid Build Coastguard Worker         EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
62*38e8c45fSAndroid Build Coastguard Worker         EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
63*38e8c45fSAndroid Build Coastguard Worker         EGL_RED_SIZE, 8,
64*38e8c45fSAndroid Build Coastguard Worker         EGL_GREEN_SIZE, 8,
65*38e8c45fSAndroid Build Coastguard Worker         EGL_BLUE_SIZE, 8,
66*38e8c45fSAndroid Build Coastguard Worker         EGL_ALPHA_SIZE, 8,
67*38e8c45fSAndroid Build Coastguard Worker         EGL_NONE
68*38e8c45fSAndroid Build Coastguard Worker     };
69*38e8c45fSAndroid Build Coastguard Worker     result = eglChooseConfig(mDisplay, configAttribs, &mConfig, 1,
70*38e8c45fSAndroid Build Coastguard Worker             &numConfigs);
71*38e8c45fSAndroid Build Coastguard Worker     if (result != EGL_TRUE) {
72*38e8c45fSAndroid Build Coastguard Worker         fprintf(stderr, "eglChooseConfig error: %#x\n", eglGetError());
73*38e8c45fSAndroid Build Coastguard Worker         return false;
74*38e8c45fSAndroid Build Coastguard Worker     }
75*38e8c45fSAndroid Build Coastguard Worker 
76*38e8c45fSAndroid Build Coastguard Worker     EGLint contextAttribs[] = {
77*38e8c45fSAndroid Build Coastguard Worker         EGL_CONTEXT_CLIENT_VERSION, 2,
78*38e8c45fSAndroid Build Coastguard Worker         EGL_NONE
79*38e8c45fSAndroid Build Coastguard Worker     };
80*38e8c45fSAndroid Build Coastguard Worker     mContext = eglCreateContext(mDisplay, mConfig, EGL_NO_CONTEXT,
81*38e8c45fSAndroid Build Coastguard Worker             contextAttribs);
82*38e8c45fSAndroid Build Coastguard Worker     if (mContext == EGL_NO_CONTEXT) {
83*38e8c45fSAndroid Build Coastguard Worker         fprintf(stderr, "eglCreateContext error: %#x\n", eglGetError());
84*38e8c45fSAndroid Build Coastguard Worker         return false;
85*38e8c45fSAndroid Build Coastguard Worker     }
86*38e8c45fSAndroid Build Coastguard Worker 
87*38e8c45fSAndroid Build Coastguard Worker     bool resultb = createNamedSurfaceTexture(0, 1, 1, &mDummyGLConsumer,
88*38e8c45fSAndroid Build Coastguard Worker             &mDummySurface);
89*38e8c45fSAndroid Build Coastguard Worker     if (!resultb) {
90*38e8c45fSAndroid Build Coastguard Worker         return false;
91*38e8c45fSAndroid Build Coastguard Worker     }
92*38e8c45fSAndroid Build Coastguard Worker 
93*38e8c45fSAndroid Build Coastguard Worker     resultb = makeCurrent(mDummySurface);
94*38e8c45fSAndroid Build Coastguard Worker     if (!resultb) {
95*38e8c45fSAndroid Build Coastguard Worker         return false;
96*38e8c45fSAndroid Build Coastguard Worker     }
97*38e8c45fSAndroid Build Coastguard Worker 
98*38e8c45fSAndroid Build Coastguard Worker     resultb = setUpShaders(shaderDescs, numShaders);
99*38e8c45fSAndroid Build Coastguard Worker     if (!resultb) {
100*38e8c45fSAndroid Build Coastguard Worker         return false;
101*38e8c45fSAndroid Build Coastguard Worker     }
102*38e8c45fSAndroid Build Coastguard Worker 
103*38e8c45fSAndroid Build Coastguard Worker     return true;
104*38e8c45fSAndroid Build Coastguard Worker }
105*38e8c45fSAndroid Build Coastguard Worker 
tearDown()106*38e8c45fSAndroid Build Coastguard Worker void GLHelper::tearDown() {
107*38e8c45fSAndroid Build Coastguard Worker     if (mShaderPrograms != nullptr) {
108*38e8c45fSAndroid Build Coastguard Worker         delete[] mShaderPrograms;
109*38e8c45fSAndroid Build Coastguard Worker         mShaderPrograms = nullptr;
110*38e8c45fSAndroid Build Coastguard Worker     }
111*38e8c45fSAndroid Build Coastguard Worker 
112*38e8c45fSAndroid Build Coastguard Worker     if (mSurfaceComposerClient != nullptr) {
113*38e8c45fSAndroid Build Coastguard Worker         mSurfaceComposerClient->dispose();
114*38e8c45fSAndroid Build Coastguard Worker         mSurfaceComposerClient.clear();
115*38e8c45fSAndroid Build Coastguard Worker     }
116*38e8c45fSAndroid Build Coastguard Worker 
117*38e8c45fSAndroid Build Coastguard Worker     if (mDisplay != EGL_NO_DISPLAY) {
118*38e8c45fSAndroid Build Coastguard Worker         eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
119*38e8c45fSAndroid Build Coastguard Worker                 EGL_NO_CONTEXT);
120*38e8c45fSAndroid Build Coastguard Worker     }
121*38e8c45fSAndroid Build Coastguard Worker 
122*38e8c45fSAndroid Build Coastguard Worker     if (mContext != EGL_NO_CONTEXT) {
123*38e8c45fSAndroid Build Coastguard Worker         eglDestroyContext(mDisplay, mContext);
124*38e8c45fSAndroid Build Coastguard Worker     }
125*38e8c45fSAndroid Build Coastguard Worker 
126*38e8c45fSAndroid Build Coastguard Worker     if (mDummySurface != EGL_NO_SURFACE) {
127*38e8c45fSAndroid Build Coastguard Worker         eglDestroySurface(mDisplay, mDummySurface);
128*38e8c45fSAndroid Build Coastguard Worker     }
129*38e8c45fSAndroid Build Coastguard Worker 
130*38e8c45fSAndroid Build Coastguard Worker     mDisplay = EGL_NO_DISPLAY;
131*38e8c45fSAndroid Build Coastguard Worker     mContext = EGL_NO_CONTEXT;
132*38e8c45fSAndroid Build Coastguard Worker     mDummySurface = EGL_NO_SURFACE;
133*38e8c45fSAndroid Build Coastguard Worker     mDummyGLConsumer.clear();
134*38e8c45fSAndroid Build Coastguard Worker     mConfig = 0;
135*38e8c45fSAndroid Build Coastguard Worker }
136*38e8c45fSAndroid Build Coastguard Worker 
makeCurrent(EGLSurface surface)137*38e8c45fSAndroid Build Coastguard Worker bool GLHelper::makeCurrent(EGLSurface surface) {
138*38e8c45fSAndroid Build Coastguard Worker     EGLint result;
139*38e8c45fSAndroid Build Coastguard Worker 
140*38e8c45fSAndroid Build Coastguard Worker     result = eglMakeCurrent(mDisplay, surface, surface, mContext);
141*38e8c45fSAndroid Build Coastguard Worker     if (result != EGL_TRUE) {
142*38e8c45fSAndroid Build Coastguard Worker         fprintf(stderr, "eglMakeCurrent error: %#x\n", eglGetError());
143*38e8c45fSAndroid Build Coastguard Worker         return false;
144*38e8c45fSAndroid Build Coastguard Worker     }
145*38e8c45fSAndroid Build Coastguard Worker 
146*38e8c45fSAndroid Build Coastguard Worker     EGLint w, h;
147*38e8c45fSAndroid Build Coastguard Worker     eglQuerySurface(mDisplay, surface, EGL_WIDTH, &w);
148*38e8c45fSAndroid Build Coastguard Worker     eglQuerySurface(mDisplay, surface, EGL_HEIGHT, &h);
149*38e8c45fSAndroid Build Coastguard Worker     glViewport(0, 0, w, h);
150*38e8c45fSAndroid Build Coastguard Worker 
151*38e8c45fSAndroid Build Coastguard Worker     return true;
152*38e8c45fSAndroid Build Coastguard Worker }
153*38e8c45fSAndroid Build Coastguard Worker 
createSurfaceTexture(uint32_t w,uint32_t h,sp<GLConsumer> * glConsumer,EGLSurface * surface,GLuint * name)154*38e8c45fSAndroid Build Coastguard Worker bool GLHelper::createSurfaceTexture(uint32_t w, uint32_t h,
155*38e8c45fSAndroid Build Coastguard Worker         sp<GLConsumer>* glConsumer, EGLSurface* surface,
156*38e8c45fSAndroid Build Coastguard Worker         GLuint* name) {
157*38e8c45fSAndroid Build Coastguard Worker     if (!makeCurrent(mDummySurface)) {
158*38e8c45fSAndroid Build Coastguard Worker         return false;
159*38e8c45fSAndroid Build Coastguard Worker     }
160*38e8c45fSAndroid Build Coastguard Worker 
161*38e8c45fSAndroid Build Coastguard Worker     *name = 0;
162*38e8c45fSAndroid Build Coastguard Worker     glGenTextures(1, name);
163*38e8c45fSAndroid Build Coastguard Worker     if (*name == 0) {
164*38e8c45fSAndroid Build Coastguard Worker         fprintf(stderr, "glGenTextures error: %#x\n", glGetError());
165*38e8c45fSAndroid Build Coastguard Worker         return false;
166*38e8c45fSAndroid Build Coastguard Worker     }
167*38e8c45fSAndroid Build Coastguard Worker 
168*38e8c45fSAndroid Build Coastguard Worker     return createNamedSurfaceTexture(*name, w, h, glConsumer, surface);
169*38e8c45fSAndroid Build Coastguard Worker }
170*38e8c45fSAndroid Build Coastguard Worker 
destroySurface(EGLSurface * surface)171*38e8c45fSAndroid Build Coastguard Worker void GLHelper::destroySurface(EGLSurface* surface) {
172*38e8c45fSAndroid Build Coastguard Worker     if (eglGetCurrentSurface(EGL_READ) == *surface ||
173*38e8c45fSAndroid Build Coastguard Worker             eglGetCurrentSurface(EGL_DRAW) == *surface) {
174*38e8c45fSAndroid Build Coastguard Worker         eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
175*38e8c45fSAndroid Build Coastguard Worker                 EGL_NO_CONTEXT);
176*38e8c45fSAndroid Build Coastguard Worker     }
177*38e8c45fSAndroid Build Coastguard Worker     eglDestroySurface(mDisplay, *surface);
178*38e8c45fSAndroid Build Coastguard Worker     *surface = EGL_NO_SURFACE;
179*38e8c45fSAndroid Build Coastguard Worker }
180*38e8c45fSAndroid Build Coastguard Worker 
swapBuffers(EGLSurface surface)181*38e8c45fSAndroid Build Coastguard Worker bool GLHelper::swapBuffers(EGLSurface surface) {
182*38e8c45fSAndroid Build Coastguard Worker     EGLint result;
183*38e8c45fSAndroid Build Coastguard Worker     result = eglSwapBuffers(mDisplay, surface);
184*38e8c45fSAndroid Build Coastguard Worker     if (result != EGL_TRUE) {
185*38e8c45fSAndroid Build Coastguard Worker         fprintf(stderr, "eglSwapBuffers error: %#x\n", eglGetError());
186*38e8c45fSAndroid Build Coastguard Worker         return false;
187*38e8c45fSAndroid Build Coastguard Worker     }
188*38e8c45fSAndroid Build Coastguard Worker     return true;
189*38e8c45fSAndroid Build Coastguard Worker }
190*38e8c45fSAndroid Build Coastguard Worker 
getShaderProgram(const char * name,GLuint * outPgm)191*38e8c45fSAndroid Build Coastguard Worker bool GLHelper::getShaderProgram(const char* name, GLuint* outPgm) {
192*38e8c45fSAndroid Build Coastguard Worker     for (size_t i = 0; i < mNumShaders; i++) {
193*38e8c45fSAndroid Build Coastguard Worker         if (strcmp(mShaderDescs[i].name, name) == 0) {
194*38e8c45fSAndroid Build Coastguard Worker             *outPgm = mShaderPrograms[i];
195*38e8c45fSAndroid Build Coastguard Worker             return true;
196*38e8c45fSAndroid Build Coastguard Worker         }
197*38e8c45fSAndroid Build Coastguard Worker     }
198*38e8c45fSAndroid Build Coastguard Worker 
199*38e8c45fSAndroid Build Coastguard Worker     fprintf(stderr, "unknown shader name: \"%s\"\n", name);
200*38e8c45fSAndroid Build Coastguard Worker 
201*38e8c45fSAndroid Build Coastguard Worker     return false;
202*38e8c45fSAndroid Build Coastguard Worker }
203*38e8c45fSAndroid Build Coastguard Worker 
createNamedSurfaceTexture(GLuint name,uint32_t w,uint32_t h,sp<GLConsumer> * glConsumer,EGLSurface * surface)204*38e8c45fSAndroid Build Coastguard Worker bool GLHelper::createNamedSurfaceTexture(GLuint name, uint32_t w, uint32_t h,
205*38e8c45fSAndroid Build Coastguard Worker         sp<GLConsumer>* glConsumer, EGLSurface* surface) {
206*38e8c45fSAndroid Build Coastguard Worker #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
207*38e8c45fSAndroid Build Coastguard Worker     sp<GLConsumer> glc = new GLConsumer(name, GL_TEXTURE_EXTERNAL_OES, false, true);
208*38e8c45fSAndroid Build Coastguard Worker     glc->setDefaultBufferSize(w, h);
209*38e8c45fSAndroid Build Coastguard Worker     glc->getSurface()->setMaxDequeuedBufferCount(2);
210*38e8c45fSAndroid Build Coastguard Worker     glc->setConsumerUsageBits(GRALLOC_USAGE_HW_COMPOSER);
211*38e8c45fSAndroid Build Coastguard Worker 
212*38e8c45fSAndroid Build Coastguard Worker     sp<ANativeWindow> anw = glc->getSurface();
213*38e8c45fSAndroid Build Coastguard Worker #else
214*38e8c45fSAndroid Build Coastguard Worker     sp<IGraphicBufferProducer> producer;
215*38e8c45fSAndroid Build Coastguard Worker     sp<IGraphicBufferConsumer> consumer;
216*38e8c45fSAndroid Build Coastguard Worker     BufferQueue::createBufferQueue(&producer, &consumer);
217*38e8c45fSAndroid Build Coastguard Worker     sp<GLConsumer> glc = new GLConsumer(consumer, name,
218*38e8c45fSAndroid Build Coastguard Worker             GL_TEXTURE_EXTERNAL_OES, false, true);
219*38e8c45fSAndroid Build Coastguard Worker     glc->setDefaultBufferSize(w, h);
220*38e8c45fSAndroid Build Coastguard Worker     producer->setMaxDequeuedBufferCount(2);
221*38e8c45fSAndroid Build Coastguard Worker     glc->setConsumerUsageBits(GRALLOC_USAGE_HW_COMPOSER);
222*38e8c45fSAndroid Build Coastguard Worker 
223*38e8c45fSAndroid Build Coastguard Worker     sp<ANativeWindow> anw = new Surface(producer);
224*38e8c45fSAndroid Build Coastguard Worker #endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
225*38e8c45fSAndroid Build Coastguard Worker     EGLSurface s = eglCreateWindowSurface(mDisplay, mConfig, anw.get(), nullptr);
226*38e8c45fSAndroid Build Coastguard Worker     if (s == EGL_NO_SURFACE) {
227*38e8c45fSAndroid Build Coastguard Worker         fprintf(stderr, "eglCreateWindowSurface error: %#x\n", eglGetError());
228*38e8c45fSAndroid Build Coastguard Worker         return false;
229*38e8c45fSAndroid Build Coastguard Worker     }
230*38e8c45fSAndroid Build Coastguard Worker 
231*38e8c45fSAndroid Build Coastguard Worker     *glConsumer = glc;
232*38e8c45fSAndroid Build Coastguard Worker     *surface = s;
233*38e8c45fSAndroid Build Coastguard Worker     return true;
234*38e8c45fSAndroid Build Coastguard Worker }
235*38e8c45fSAndroid Build Coastguard Worker 
computeWindowScale(uint32_t w,uint32_t h,float * scale)236*38e8c45fSAndroid Build Coastguard Worker bool GLHelper::computeWindowScale(uint32_t w, uint32_t h, float* scale) {
237*38e8c45fSAndroid Build Coastguard Worker     ui::DisplayMode mode;
238*38e8c45fSAndroid Build Coastguard Worker     status_t err = mSurfaceComposerClient->getActiveDisplayMode(mDisplayToken, &mode);
239*38e8c45fSAndroid Build Coastguard Worker     if (err != NO_ERROR) {
240*38e8c45fSAndroid Build Coastguard Worker         fprintf(stderr, "SurfaceComposer::getActiveDisplayMode failed: %#x\n", err);
241*38e8c45fSAndroid Build Coastguard Worker         return false;
242*38e8c45fSAndroid Build Coastguard Worker     }
243*38e8c45fSAndroid Build Coastguard Worker 
244*38e8c45fSAndroid Build Coastguard Worker     float scaleX = static_cast<float>(mode.resolution.getWidth()) / w;
245*38e8c45fSAndroid Build Coastguard Worker     float scaleY = static_cast<float>(mode.resolution.getHeight()) / h;
246*38e8c45fSAndroid Build Coastguard Worker     *scale = scaleX < scaleY ? scaleX : scaleY;
247*38e8c45fSAndroid Build Coastguard Worker 
248*38e8c45fSAndroid Build Coastguard Worker     return true;
249*38e8c45fSAndroid Build Coastguard Worker }
250*38e8c45fSAndroid Build Coastguard Worker 
createWindowSurface(uint32_t w,uint32_t h,sp<SurfaceControl> * surfaceControl,EGLSurface * surface)251*38e8c45fSAndroid Build Coastguard Worker bool GLHelper::createWindowSurface(uint32_t w, uint32_t h,
252*38e8c45fSAndroid Build Coastguard Worker         sp<SurfaceControl>* surfaceControl, EGLSurface* surface) {
253*38e8c45fSAndroid Build Coastguard Worker     bool result;
254*38e8c45fSAndroid Build Coastguard Worker     status_t err;
255*38e8c45fSAndroid Build Coastguard Worker 
256*38e8c45fSAndroid Build Coastguard Worker     if (mSurfaceComposerClient == nullptr) {
257*38e8c45fSAndroid Build Coastguard Worker         mSurfaceComposerClient = new SurfaceComposerClient;
258*38e8c45fSAndroid Build Coastguard Worker     }
259*38e8c45fSAndroid Build Coastguard Worker     err = mSurfaceComposerClient->initCheck();
260*38e8c45fSAndroid Build Coastguard Worker     if (err != NO_ERROR) {
261*38e8c45fSAndroid Build Coastguard Worker         fprintf(stderr, "SurfaceComposerClient::initCheck error: %#x\n", err);
262*38e8c45fSAndroid Build Coastguard Worker         return false;
263*38e8c45fSAndroid Build Coastguard Worker     }
264*38e8c45fSAndroid Build Coastguard Worker 
265*38e8c45fSAndroid Build Coastguard Worker     sp<SurfaceControl> sc = mSurfaceComposerClient->createSurface(
266*38e8c45fSAndroid Build Coastguard Worker             String8("Benchmark"), w, h, PIXEL_FORMAT_RGBA_8888, 0);
267*38e8c45fSAndroid Build Coastguard Worker     if (sc == nullptr || !sc->isValid()) {
268*38e8c45fSAndroid Build Coastguard Worker         fprintf(stderr, "Failed to create SurfaceControl.\n");
269*38e8c45fSAndroid Build Coastguard Worker         return false;
270*38e8c45fSAndroid Build Coastguard Worker     }
271*38e8c45fSAndroid Build Coastguard Worker 
272*38e8c45fSAndroid Build Coastguard Worker     float scale;
273*38e8c45fSAndroid Build Coastguard Worker     result = computeWindowScale(w, h, &scale);
274*38e8c45fSAndroid Build Coastguard Worker     if (!result) {
275*38e8c45fSAndroid Build Coastguard Worker         return false;
276*38e8c45fSAndroid Build Coastguard Worker     }
277*38e8c45fSAndroid Build Coastguard Worker 
278*38e8c45fSAndroid Build Coastguard Worker     SurfaceComposerClient::Transaction{}.setLayer(sc, 0x7FFFFFFF)
279*38e8c45fSAndroid Build Coastguard Worker             .setMatrix(sc, scale, 0.0f, 0.0f, scale)
280*38e8c45fSAndroid Build Coastguard Worker             .show(sc)
281*38e8c45fSAndroid Build Coastguard Worker             .apply();
282*38e8c45fSAndroid Build Coastguard Worker 
283*38e8c45fSAndroid Build Coastguard Worker     sp<ANativeWindow> anw = sc->getSurface();
284*38e8c45fSAndroid Build Coastguard Worker     EGLSurface s = eglCreateWindowSurface(mDisplay, mConfig, anw.get(), nullptr);
285*38e8c45fSAndroid Build Coastguard Worker     if (s == EGL_NO_SURFACE) {
286*38e8c45fSAndroid Build Coastguard Worker         fprintf(stderr, "eglCreateWindowSurface error: %#x\n", eglGetError());
287*38e8c45fSAndroid Build Coastguard Worker         return false;
288*38e8c45fSAndroid Build Coastguard Worker     }
289*38e8c45fSAndroid Build Coastguard Worker 
290*38e8c45fSAndroid Build Coastguard Worker     *surfaceControl = sc;
291*38e8c45fSAndroid Build Coastguard Worker     *surface = s;
292*38e8c45fSAndroid Build Coastguard Worker     return true;
293*38e8c45fSAndroid Build Coastguard Worker }
294*38e8c45fSAndroid Build Coastguard Worker 
compileShader(GLenum shaderType,const char * src,GLuint * outShader)295*38e8c45fSAndroid Build Coastguard Worker static bool compileShader(GLenum shaderType, const char* src,
296*38e8c45fSAndroid Build Coastguard Worker         GLuint* outShader) {
297*38e8c45fSAndroid Build Coastguard Worker     GLuint shader = glCreateShader(shaderType);
298*38e8c45fSAndroid Build Coastguard Worker     if (shader == 0) {
299*38e8c45fSAndroid Build Coastguard Worker         fprintf(stderr, "glCreateShader error: %#x\n", glGetError());
300*38e8c45fSAndroid Build Coastguard Worker         return false;
301*38e8c45fSAndroid Build Coastguard Worker     }
302*38e8c45fSAndroid Build Coastguard Worker 
303*38e8c45fSAndroid Build Coastguard Worker     glShaderSource(shader, 1, &src, nullptr);
304*38e8c45fSAndroid Build Coastguard Worker     glCompileShader(shader);
305*38e8c45fSAndroid Build Coastguard Worker 
306*38e8c45fSAndroid Build Coastguard Worker     GLint compiled = 0;
307*38e8c45fSAndroid Build Coastguard Worker     glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
308*38e8c45fSAndroid Build Coastguard Worker     if (!compiled) {
309*38e8c45fSAndroid Build Coastguard Worker         GLint infoLen = 0;
310*38e8c45fSAndroid Build Coastguard Worker         glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
311*38e8c45fSAndroid Build Coastguard Worker         if (infoLen) {
312*38e8c45fSAndroid Build Coastguard Worker             char* buf = new char[infoLen];
313*38e8c45fSAndroid Build Coastguard Worker             if (buf) {
314*38e8c45fSAndroid Build Coastguard Worker                 glGetShaderInfoLog(shader, infoLen, nullptr, buf);
315*38e8c45fSAndroid Build Coastguard Worker                 fprintf(stderr, "Shader compile log:\n%s\n", buf);
316*38e8c45fSAndroid Build Coastguard Worker                 delete[] buf;
317*38e8c45fSAndroid Build Coastguard Worker             }
318*38e8c45fSAndroid Build Coastguard Worker         }
319*38e8c45fSAndroid Build Coastguard Worker         glDeleteShader(shader);
320*38e8c45fSAndroid Build Coastguard Worker         return false;
321*38e8c45fSAndroid Build Coastguard Worker     }
322*38e8c45fSAndroid Build Coastguard Worker     *outShader = shader;
323*38e8c45fSAndroid Build Coastguard Worker     return true;
324*38e8c45fSAndroid Build Coastguard Worker }
325*38e8c45fSAndroid Build Coastguard Worker 
printShaderSource(const char * const * src)326*38e8c45fSAndroid Build Coastguard Worker static void printShaderSource(const char* const* src) {
327*38e8c45fSAndroid Build Coastguard Worker     for (size_t i = 0; i < MAX_SHADER_LINES && src[i] != nullptr; i++) {
328*38e8c45fSAndroid Build Coastguard Worker         fprintf(stderr, "%3zu: %s\n", i+1, src[i]);
329*38e8c45fSAndroid Build Coastguard Worker     }
330*38e8c45fSAndroid Build Coastguard Worker }
331*38e8c45fSAndroid Build Coastguard Worker 
makeShaderString(const char * const * src)332*38e8c45fSAndroid Build Coastguard Worker static const char* makeShaderString(const char* const* src) {
333*38e8c45fSAndroid Build Coastguard Worker     size_t len = 0;
334*38e8c45fSAndroid Build Coastguard Worker     for (size_t i = 0; i < MAX_SHADER_LINES && src[i] != nullptr; i++) {
335*38e8c45fSAndroid Build Coastguard Worker         // The +1 is for the '\n' that will be added.
336*38e8c45fSAndroid Build Coastguard Worker         len += strlen(src[i]) + 1;
337*38e8c45fSAndroid Build Coastguard Worker     }
338*38e8c45fSAndroid Build Coastguard Worker 
339*38e8c45fSAndroid Build Coastguard Worker     char* result = new char[len+1];
340*38e8c45fSAndroid Build Coastguard Worker     char* end = result;
341*38e8c45fSAndroid Build Coastguard Worker     for (size_t i = 0; i < MAX_SHADER_LINES && src[i] != nullptr; i++) {
342*38e8c45fSAndroid Build Coastguard Worker         strcpy(end, src[i]);
343*38e8c45fSAndroid Build Coastguard Worker         end += strlen(src[i]);
344*38e8c45fSAndroid Build Coastguard Worker         *end = '\n';
345*38e8c45fSAndroid Build Coastguard Worker         end++;
346*38e8c45fSAndroid Build Coastguard Worker     }
347*38e8c45fSAndroid Build Coastguard Worker     *end = '\0';
348*38e8c45fSAndroid Build Coastguard Worker 
349*38e8c45fSAndroid Build Coastguard Worker     return result;
350*38e8c45fSAndroid Build Coastguard Worker }
351*38e8c45fSAndroid Build Coastguard Worker 
compileShaderLines(GLenum shaderType,const char * const * lines,GLuint * outShader)352*38e8c45fSAndroid Build Coastguard Worker static bool compileShaderLines(GLenum shaderType, const char* const* lines,
353*38e8c45fSAndroid Build Coastguard Worker         GLuint* outShader) {
354*38e8c45fSAndroid Build Coastguard Worker     const char* src = makeShaderString(lines);
355*38e8c45fSAndroid Build Coastguard Worker     bool result = compileShader(shaderType, src, outShader);
356*38e8c45fSAndroid Build Coastguard Worker     if (!result) {
357*38e8c45fSAndroid Build Coastguard Worker         fprintf(stderr, "Shader source:\n");
358*38e8c45fSAndroid Build Coastguard Worker         printShaderSource(lines);
359*38e8c45fSAndroid Build Coastguard Worker         delete[] src;
360*38e8c45fSAndroid Build Coastguard Worker         return false;
361*38e8c45fSAndroid Build Coastguard Worker     }
362*38e8c45fSAndroid Build Coastguard Worker     delete[] src;
363*38e8c45fSAndroid Build Coastguard Worker 
364*38e8c45fSAndroid Build Coastguard Worker     return true;
365*38e8c45fSAndroid Build Coastguard Worker }
366*38e8c45fSAndroid Build Coastguard Worker 
linkShaderProgram(GLuint vs,GLuint fs,GLuint * outPgm)367*38e8c45fSAndroid Build Coastguard Worker static bool linkShaderProgram(GLuint vs, GLuint fs, GLuint* outPgm) {
368*38e8c45fSAndroid Build Coastguard Worker     GLuint program = glCreateProgram();
369*38e8c45fSAndroid Build Coastguard Worker     if (program == 0) {
370*38e8c45fSAndroid Build Coastguard Worker         fprintf(stderr, "glCreateProgram error: %#x\n", glGetError());
371*38e8c45fSAndroid Build Coastguard Worker         return false;
372*38e8c45fSAndroid Build Coastguard Worker     }
373*38e8c45fSAndroid Build Coastguard Worker 
374*38e8c45fSAndroid Build Coastguard Worker     glAttachShader(program, vs);
375*38e8c45fSAndroid Build Coastguard Worker     glAttachShader(program, fs);
376*38e8c45fSAndroid Build Coastguard Worker     glLinkProgram(program);
377*38e8c45fSAndroid Build Coastguard Worker     GLint linkStatus = GL_FALSE;
378*38e8c45fSAndroid Build Coastguard Worker     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
379*38e8c45fSAndroid Build Coastguard Worker     if (linkStatus != GL_TRUE) {
380*38e8c45fSAndroid Build Coastguard Worker         GLint bufLength = 0;
381*38e8c45fSAndroid Build Coastguard Worker         glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
382*38e8c45fSAndroid Build Coastguard Worker         if (bufLength) {
383*38e8c45fSAndroid Build Coastguard Worker             char* buf = new char[bufLength];
384*38e8c45fSAndroid Build Coastguard Worker             if (buf) {
385*38e8c45fSAndroid Build Coastguard Worker                 glGetProgramInfoLog(program, bufLength, nullptr, buf);
386*38e8c45fSAndroid Build Coastguard Worker                 fprintf(stderr, "Program link log:\n%s\n", buf);
387*38e8c45fSAndroid Build Coastguard Worker                 delete[] buf;
388*38e8c45fSAndroid Build Coastguard Worker             }
389*38e8c45fSAndroid Build Coastguard Worker         }
390*38e8c45fSAndroid Build Coastguard Worker         glDeleteProgram(program);
391*38e8c45fSAndroid Build Coastguard Worker         program = 0;
392*38e8c45fSAndroid Build Coastguard Worker     }
393*38e8c45fSAndroid Build Coastguard Worker 
394*38e8c45fSAndroid Build Coastguard Worker     *outPgm = program;
395*38e8c45fSAndroid Build Coastguard Worker     return program != 0;
396*38e8c45fSAndroid Build Coastguard Worker }
397*38e8c45fSAndroid Build Coastguard Worker 
setUpShaders(const ShaderDesc * shaderDescs,size_t numShaders)398*38e8c45fSAndroid Build Coastguard Worker bool GLHelper::setUpShaders(const ShaderDesc* shaderDescs, size_t numShaders) {
399*38e8c45fSAndroid Build Coastguard Worker     mShaderPrograms = new GLuint[numShaders];
400*38e8c45fSAndroid Build Coastguard Worker     bool result = true;
401*38e8c45fSAndroid Build Coastguard Worker 
402*38e8c45fSAndroid Build Coastguard Worker     for (size_t i = 0; i < numShaders && result; i++) {
403*38e8c45fSAndroid Build Coastguard Worker         GLuint vs, fs;
404*38e8c45fSAndroid Build Coastguard Worker 
405*38e8c45fSAndroid Build Coastguard Worker         result = compileShaderLines(GL_VERTEX_SHADER,
406*38e8c45fSAndroid Build Coastguard Worker                 shaderDescs[i].vertexShader, &vs);
407*38e8c45fSAndroid Build Coastguard Worker         if (!result) {
408*38e8c45fSAndroid Build Coastguard Worker             return false;
409*38e8c45fSAndroid Build Coastguard Worker         }
410*38e8c45fSAndroid Build Coastguard Worker 
411*38e8c45fSAndroid Build Coastguard Worker         result = compileShaderLines(GL_FRAGMENT_SHADER,
412*38e8c45fSAndroid Build Coastguard Worker                 shaderDescs[i].fragmentShader, &fs);
413*38e8c45fSAndroid Build Coastguard Worker         if (!result) {
414*38e8c45fSAndroid Build Coastguard Worker             glDeleteShader(vs);
415*38e8c45fSAndroid Build Coastguard Worker             return false;
416*38e8c45fSAndroid Build Coastguard Worker         }
417*38e8c45fSAndroid Build Coastguard Worker 
418*38e8c45fSAndroid Build Coastguard Worker         result = linkShaderProgram(vs, fs, &mShaderPrograms[i]);
419*38e8c45fSAndroid Build Coastguard Worker         glDeleteShader(vs);
420*38e8c45fSAndroid Build Coastguard Worker         glDeleteShader(fs);
421*38e8c45fSAndroid Build Coastguard Worker     }
422*38e8c45fSAndroid Build Coastguard Worker 
423*38e8c45fSAndroid Build Coastguard Worker     mNumShaders = numShaders;
424*38e8c45fSAndroid Build Coastguard Worker     mShaderDescs = shaderDescs;
425*38e8c45fSAndroid Build Coastguard Worker 
426*38e8c45fSAndroid Build Coastguard Worker     return result;
427*38e8c45fSAndroid Build Coastguard Worker }
428*38e8c45fSAndroid Build Coastguard Worker 
getDitherTexture(GLuint * outTexName)429*38e8c45fSAndroid Build Coastguard Worker bool GLHelper::getDitherTexture(GLuint* outTexName) {
430*38e8c45fSAndroid Build Coastguard Worker     if (mDitherTexture == 0) {
431*38e8c45fSAndroid Build Coastguard Worker         const uint8_t pattern[] = {
432*38e8c45fSAndroid Build Coastguard Worker              0,  8,  2, 10,
433*38e8c45fSAndroid Build Coastguard Worker             12,  4, 14,  6,
434*38e8c45fSAndroid Build Coastguard Worker              3, 11,  1,  9,
435*38e8c45fSAndroid Build Coastguard Worker             15,  7, 13,  5
436*38e8c45fSAndroid Build Coastguard Worker         };
437*38e8c45fSAndroid Build Coastguard Worker 
438*38e8c45fSAndroid Build Coastguard Worker         glGenTextures(1, &mDitherTexture);
439*38e8c45fSAndroid Build Coastguard Worker         glBindTexture(GL_TEXTURE_2D, mDitherTexture);
440*38e8c45fSAndroid Build Coastguard Worker 
441*38e8c45fSAndroid Build Coastguard Worker         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
442*38e8c45fSAndroid Build Coastguard Worker         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
443*38e8c45fSAndroid Build Coastguard Worker 
444*38e8c45fSAndroid Build Coastguard Worker         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
445*38e8c45fSAndroid Build Coastguard Worker         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
446*38e8c45fSAndroid Build Coastguard Worker 
447*38e8c45fSAndroid Build Coastguard Worker         glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, DITHER_KERNEL_SIZE,
448*38e8c45fSAndroid Build Coastguard Worker                 DITHER_KERNEL_SIZE, 0, GL_ALPHA, GL_UNSIGNED_BYTE, &pattern);
449*38e8c45fSAndroid Build Coastguard Worker     }
450*38e8c45fSAndroid Build Coastguard Worker 
451*38e8c45fSAndroid Build Coastguard Worker     *outTexName = mDitherTexture;
452*38e8c45fSAndroid Build Coastguard Worker 
453*38e8c45fSAndroid Build Coastguard Worker     return true;
454*38e8c45fSAndroid Build Coastguard Worker }
455*38e8c45fSAndroid Build Coastguard Worker 
456*38e8c45fSAndroid Build Coastguard Worker }
457