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.server.wallpaper; 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_HEIGHT; 27 import static android.opengl.EGL14.EGL_NONE; 28 import static android.opengl.EGL14.EGL_NO_CONTEXT; 29 import static android.opengl.EGL14.EGL_NO_DISPLAY; 30 import static android.opengl.EGL14.EGL_NO_SURFACE; 31 import static android.opengl.EGL14.EGL_OPENGL_ES2_BIT; 32 import static android.opengl.EGL14.EGL_RED_SIZE; 33 import static android.opengl.EGL14.EGL_RENDERABLE_TYPE; 34 import static android.opengl.EGL14.EGL_STENCIL_SIZE; 35 import static android.opengl.EGL14.EGL_WIDTH; 36 import static android.opengl.EGL14.eglChooseConfig; 37 import static android.opengl.EGL14.eglCreateContext; 38 import static android.opengl.EGL14.eglCreatePbufferSurface; 39 import static android.opengl.EGL14.eglDestroyContext; 40 import static android.opengl.EGL14.eglDestroySurface; 41 import static android.opengl.EGL14.eglGetDisplay; 42 import static android.opengl.EGL14.eglGetError; 43 import static android.opengl.EGL14.eglInitialize; 44 import static android.opengl.EGL14.eglMakeCurrent; 45 import static android.opengl.EGL14.eglTerminate; 46 import static android.opengl.GLES20.GL_MAX_TEXTURE_SIZE; 47 import static android.opengl.GLES20.glGetIntegerv; 48 49 import android.opengl.EGLConfig; 50 import android.opengl.EGLContext; 51 import android.opengl.EGLDisplay; 52 import android.opengl.EGLSurface; 53 import android.opengl.GLUtils; 54 import android.os.SystemProperties; 55 import android.util.Log; 56 57 class GLHelper { 58 private static final String TAG = GLHelper.class.getSimpleName(); 59 private static final int sMaxTextureSize; 60 61 static { 62 int maxTextureSize = SystemProperties.getInt("sys.max_texture_size", 0); 63 sMaxTextureSize = maxTextureSize > 0 ? maxTextureSize : retrieveTextureSizeFromGL(); 64 } 65 retrieveTextureSizeFromGL()66 private static int retrieveTextureSizeFromGL() { 67 try { 68 String err; 69 70 // Before we can retrieve info from GL, 71 // we have to create EGLContext, EGLConfig and EGLDisplay first. 72 // We will fail at querying info from GL once one of above failed. 73 // When this happens, we will use defValue instead. 74 EGLDisplay eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); 75 if (eglDisplay == null || eglDisplay == EGL_NO_DISPLAY) { 76 err = "eglGetDisplay failed: " + GLUtils.getEGLErrorString(eglGetError()); 77 throw new RuntimeException(err); 78 } 79 80 if (!eglInitialize(eglDisplay, null, 0 /* majorOffset */, null, 1 /* minorOffset */)) { 81 err = "eglInitialize failed: " + GLUtils.getEGLErrorString(eglGetError()); 82 throw new RuntimeException(err); 83 } 84 85 EGLConfig eglConfig = null; 86 int[] configsCount = new int[1]; 87 EGLConfig[] configs = new EGLConfig[1]; 88 int[] configSpec = new int[] { 89 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 90 EGL_RED_SIZE, 8, 91 EGL_GREEN_SIZE, 8, 92 EGL_BLUE_SIZE, 8, 93 EGL_ALPHA_SIZE, 0, 94 EGL_DEPTH_SIZE, 0, 95 EGL_STENCIL_SIZE, 0, 96 EGL_CONFIG_CAVEAT, EGL_NONE, 97 EGL_NONE 98 }; 99 100 if (!eglChooseConfig(eglDisplay, configSpec, 0 /* attrib_listOffset */, 101 configs, 0 /* configOffset */, 1 /* config_size */, 102 configsCount, 0 /* num_configOffset */)) { 103 err = "eglChooseConfig failed: " + GLUtils.getEGLErrorString(eglGetError()); 104 throw new RuntimeException(err); 105 } else if (configsCount[0] > 0) { 106 eglConfig = configs[0]; 107 } 108 109 if (eglConfig == null) { 110 throw new RuntimeException("eglConfig not initialized!"); 111 } 112 113 int[] attr_list = new int[] {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE}; 114 EGLContext eglContext = eglCreateContext( 115 eglDisplay, eglConfig, EGL_NO_CONTEXT, attr_list, 0 /* offset */); 116 117 if (eglContext == null || eglContext == EGL_NO_CONTEXT) { 118 err = "eglCreateContext failed: " + GLUtils.getEGLErrorString(eglGetError()); 119 throw new RuntimeException(err); 120 } 121 122 // We create a push buffer temporarily for querying info from GL. 123 int[] attrs = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE}; 124 EGLSurface eglSurface = 125 eglCreatePbufferSurface(eglDisplay, eglConfig, attrs, 0 /* offset */); 126 eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext); 127 128 // Now, we are ready to query the info from GL. 129 int[] maxSize = new int[1]; 130 glGetIntegerv(GL_MAX_TEXTURE_SIZE, maxSize, 0 /* offset */); 131 132 // We have got the info we want, release all egl resources. 133 eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 134 eglDestroySurface(eglDisplay, eglSurface); 135 eglDestroyContext(eglDisplay, eglContext); 136 eglTerminate(eglDisplay); 137 return maxSize[0]; 138 } catch (RuntimeException e) { 139 Log.w(TAG, "Retrieve from GL failed", e); 140 return Integer.MAX_VALUE; 141 } 142 } 143 getMaxTextureSize()144 static int getMaxTextureSize() { 145 return sMaxTextureSize; 146 } 147 } 148 149