• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.systemui.glwallpaper;
18 
19 import static android.opengl.EGL14.EGL_ALPHA_SIZE;
20 import static android.opengl.EGL14.EGL_BLUE_SIZE;
21 import static android.opengl.EGL14.EGL_CONFIG_CAVEAT;
22 import static android.opengl.EGL14.EGL_CONTEXT_CLIENT_VERSION;
23 import static android.opengl.EGL14.EGL_DEFAULT_DISPLAY;
24 import static android.opengl.EGL14.EGL_DEPTH_SIZE;
25 import static android.opengl.EGL14.EGL_GREEN_SIZE;
26 import static android.opengl.EGL14.EGL_NONE;
27 import static android.opengl.EGL14.EGL_NO_CONTEXT;
28 import static android.opengl.EGL14.EGL_NO_DISPLAY;
29 import static android.opengl.EGL14.EGL_NO_SURFACE;
30 import static android.opengl.EGL14.EGL_OPENGL_ES2_BIT;
31 import static android.opengl.EGL14.EGL_RED_SIZE;
32 import static android.opengl.EGL14.EGL_RENDERABLE_TYPE;
33 import static android.opengl.EGL14.EGL_STENCIL_SIZE;
34 import static android.opengl.EGL14.EGL_SUCCESS;
35 import static android.opengl.EGL14.eglChooseConfig;
36 import static android.opengl.EGL14.eglCreateContext;
37 import static android.opengl.EGL14.eglCreateWindowSurface;
38 import static android.opengl.EGL14.eglDestroyContext;
39 import static android.opengl.EGL14.eglDestroySurface;
40 import static android.opengl.EGL14.eglGetDisplay;
41 import static android.opengl.EGL14.eglGetError;
42 import static android.opengl.EGL14.eglInitialize;
43 import static android.opengl.EGL14.eglMakeCurrent;
44 import static android.opengl.EGL14.eglSwapBuffers;
45 import static android.opengl.EGL14.eglTerminate;
46 
47 import android.opengl.EGLConfig;
48 import android.opengl.EGLContext;
49 import android.opengl.EGLDisplay;
50 import android.opengl.EGLSurface;
51 import android.opengl.GLUtils;
52 import android.util.Log;
53 import android.view.SurfaceHolder;
54 
55 import java.io.FileDescriptor;
56 import java.io.PrintWriter;
57 
58 /**
59  * A helper class to handle EGL management.
60  */
61 public class EglHelper {
62     private static final String TAG = EglHelper.class.getSimpleName();
63     // Below two constants make drawing at low priority, so other things can preempt our drawing.
64     private static final int EGL_CONTEXT_PRIORITY_LEVEL_IMG = 0x3100;
65     private static final int EGL_CONTEXT_PRIORITY_LOW_IMG = 0x3103;
66 
67     private EGLDisplay mEglDisplay;
68     private EGLConfig mEglConfig;
69     private EGLContext mEglContext;
70     private EGLSurface mEglSurface;
71     private final int[] mEglVersion = new int[2];
72     private boolean mEglReady;
73 
74     /**
75      * Initialize EGL and prepare EglSurface.
76      * @param surfaceHolder surface holder.
77      * @return true if EglSurface is ready.
78      */
init(SurfaceHolder surfaceHolder)79     public boolean init(SurfaceHolder surfaceHolder) {
80         mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
81         if (mEglDisplay == EGL_NO_DISPLAY) {
82             Log.w(TAG, "eglGetDisplay failed: " + GLUtils.getEGLErrorString(eglGetError()));
83             return false;
84         }
85 
86         if (!eglInitialize(mEglDisplay, mEglVersion, 0 /* majorOffset */,
87                     mEglVersion, 1 /* minorOffset */)) {
88             Log.w(TAG, "eglInitialize failed: " + GLUtils.getEGLErrorString(eglGetError()));
89             return false;
90         }
91 
92         mEglConfig = chooseEglConfig();
93         if (mEglConfig == null) {
94             Log.w(TAG, "eglConfig not initialized!");
95             return false;
96         }
97 
98         if (!createEglContext()) {
99             Log.w(TAG, "Can't create EGLContext!");
100             return false;
101         }
102 
103         if (!createEglSurface(surfaceHolder)) {
104             Log.w(TAG, "Can't create EGLSurface!");
105             return false;
106         }
107 
108         mEglReady = true;
109         return true;
110     }
111 
chooseEglConfig()112     private EGLConfig chooseEglConfig() {
113         int[] configsCount = new int[1];
114         EGLConfig[] configs = new EGLConfig[1];
115         int[] configSpec = getConfig();
116         if (!eglChooseConfig(mEglDisplay, configSpec, 0, configs, 0, 1, configsCount, 0)) {
117             Log.w(TAG, "eglChooseConfig failed: " + GLUtils.getEGLErrorString(eglGetError()));
118             return null;
119         } else {
120             if (configsCount[0] <= 0) {
121                 Log.w(TAG, "eglChooseConfig failed, invalid configs count: " + configsCount[0]);
122                 return null;
123             } else {
124                 return configs[0];
125             }
126         }
127     }
128 
getConfig()129     private int[] getConfig() {
130         return new int[] {
131             EGL_RED_SIZE, 8,
132             EGL_GREEN_SIZE, 8,
133             EGL_BLUE_SIZE, 8,
134             EGL_ALPHA_SIZE, 8,
135             EGL_DEPTH_SIZE, 0,
136             EGL_STENCIL_SIZE, 0,
137             EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
138             EGL_CONFIG_CAVEAT, EGL_NONE,
139             EGL_NONE
140         };
141     }
142 
143     /**
144      * Prepare an EglSurface.
145      * @param surfaceHolder surface holder.
146      * @return true if EglSurface is ready.
147      */
createEglSurface(SurfaceHolder surfaceHolder)148     public boolean createEglSurface(SurfaceHolder surfaceHolder) {
149         mEglSurface = eglCreateWindowSurface(mEglDisplay, mEglConfig, surfaceHolder, null, 0);
150         if (mEglSurface == null || mEglSurface == EGL_NO_SURFACE) {
151             Log.w(TAG, "createWindowSurface failed: " + GLUtils.getEGLErrorString(eglGetError()));
152             return false;
153         }
154 
155         if (!eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
156             Log.w(TAG, "eglMakeCurrent failed: " + GLUtils.getEGLErrorString(eglGetError()));
157             return false;
158         }
159 
160         return true;
161     }
162 
163     /**
164      * Destroy EglSurface.
165      */
destroyEglSurface()166     public void destroyEglSurface() {
167         if (hasEglSurface()) {
168             eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
169             eglDestroySurface(mEglDisplay, mEglSurface);
170             mEglSurface = null;
171         }
172     }
173 
174     /**
175      * Check if we have a valid EglSurface.
176      * @return true if EglSurface is ready.
177      */
hasEglSurface()178     public boolean hasEglSurface() {
179         return mEglSurface != null && mEglSurface != EGL_NO_SURFACE;
180     }
181 
182     /**
183      * Prepare EglContext.
184      * @return true if EglContext is ready.
185      */
createEglContext()186     public boolean createEglContext() {
187         int[] attrib_list = new int[] {EGL_CONTEXT_CLIENT_VERSION, 2,
188                 EGL_CONTEXT_PRIORITY_LEVEL_IMG, EGL_CONTEXT_PRIORITY_LOW_IMG, EGL_NONE};
189         mEglContext = eglCreateContext(mEglDisplay, mEglConfig, EGL_NO_CONTEXT, attrib_list, 0);
190         if (mEglContext == EGL_NO_CONTEXT) {
191             Log.w(TAG, "eglCreateContext failed: " + GLUtils.getEGLErrorString(eglGetError()));
192             return false;
193         }
194         return true;
195     }
196 
197     /**
198      * Destroy EglContext.
199      */
destroyEglContext()200     public void destroyEglContext() {
201         if (hasEglContext()) {
202             eglDestroyContext(mEglDisplay, mEglContext);
203             mEglContext = null;
204         }
205     }
206 
207     /**
208      * Check if we have EglContext.
209      * @return true if EglContext is ready.
210      */
hasEglContext()211     public boolean hasEglContext() {
212         return mEglContext != null;
213     }
214 
215     /**
216      * Swap buffer to display.
217      * @return true if swap successfully.
218      */
swapBuffer()219     public boolean swapBuffer() {
220         boolean status = eglSwapBuffers(mEglDisplay, mEglSurface);
221         int error = eglGetError();
222         if (error != EGL_SUCCESS) {
223             Log.w(TAG, "eglSwapBuffers failed: " + GLUtils.getEGLErrorString(error));
224         }
225         return status;
226     }
227 
228     /**
229      * Destroy EglSurface and EglContext, then terminate EGL.
230      */
finish()231     public void finish() {
232         if (hasEglSurface()) {
233             destroyEglSurface();
234         }
235         if (hasEglContext()) {
236             destroyEglContext();
237         }
238         eglTerminate(mEglDisplay);
239         mEglReady = false;
240     }
241 
242     /**
243      * Called to dump current state.
244      * @param prefix prefix.
245      * @param fd fd.
246      * @param out out.
247      * @param args args.
248      */
dump(String prefix, FileDescriptor fd, PrintWriter out, String[] args)249     public void dump(String prefix, FileDescriptor fd, PrintWriter out, String[] args) {
250         String eglVersion = mEglVersion[0] + "." + mEglVersion[1];
251         out.print(prefix); out.print("EGL version="); out.print(eglVersion);
252         out.print(", "); out.print("EGL ready="); out.print(mEglReady);
253         out.print(", "); out.print("has EglContext="); out.print(hasEglContext());
254         out.print(", "); out.print("has EglSurface="); out.println(hasEglSurface());
255 
256         int[] configs = getConfig();
257         StringBuilder sb = new StringBuilder();
258         sb.append('{');
259         for (int egl : configs) {
260             sb.append("0x").append(Integer.toHexString(egl)).append(",");
261         }
262         sb.setCharAt(sb.length() - 1, '}');
263         out.print(prefix); out.print("EglConfig="); out.println(sb.toString());
264     }
265 }
266