From d711ac4858337539c2188f47ef015e5b88080830 Mon Sep 17 00:00:00 2001 From: Shan Huang Date: Tue, 13 Jul 2021 18:36:57 +0800 Subject: Migrate boot animation from GLES 1.0 to GLES2.0. Main changes in how rendering is done: - Texts and images are drawing using a textured quad instead of glDrawTexiOES. - Shaders are introduced to draw with textures. - Frame fading is also done with shaders now, instead of drawing background colored transparent rectangles. Test: Verified the main animation, clock text, progress text and stock android animation all render correctly. Bug: 190093578 Change-Id: Ie3f336d22bcc9e24f06a2bd62683d7a8c87a85f6 --- cmds/bootanimation/BootAnimation.cpp | 268 +++++++++++++++++++++++------------ 1 file changed, 181 insertions(+), 87 deletions(-) (limited to 'cmds/bootanimation/BootAnimation.cpp') diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index 3109c5c1e075..25b7f249fc49 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -52,9 +52,8 @@ #include #include #include - -#include -#include +#include +#include #include #include "BootAnimation.h" @@ -108,6 +107,53 @@ static const char PROGRESS_PROP_NAME[] = "service.bootanim.progress"; static const char DISPLAYS_PROP_NAME[] = "persist.service.bootanim.displays"; static const int ANIM_ENTRY_NAME_MAX = ANIM_PATH_MAX + 1; static constexpr size_t TEXT_POS_LEN_MAX = 16; +static const char U_TEXTURE[] = "uTexture"; +static const char U_FADE[] = "uFade"; +static const char U_CROP_AREA[] = "uCropArea"; +static const char A_UV[] = "aUv"; +static const char A_POSITION[] = "aPosition"; +static const char VERTEX_SHADER_SOURCE[] = R"( + attribute vec4 aPosition; + attribute vec2 aUv; + varying vec2 vUv; + void main() { + gl_Position = aPosition; + vUv = aUv; + })"; +static const char IMAGE_FRAG_SHADER_SOURCE[] = R"( + uniform sampler2D uTexture; + uniform float uFade; + varying vec2 vUv; + void main() { + vec4 color = texture2D(uTexture, vUv); + gl_FragColor = vec4(color.x, color.y, color.z, 1.0 - uFade); + })"; +static const char TEXT_FRAG_SHADER_SOURCE[] = R"( + uniform sampler2D uTexture; + uniform vec4 uCropArea; + varying vec2 vUv; + void main() { + vec2 uv = vec2(mix(uCropArea.x, uCropArea.z, vUv.x), + mix(uCropArea.y, uCropArea.w, vUv.y)); + gl_FragColor = texture2D(uTexture, uv); + })"; + +static GLfloat quadPositions[] = { + -0.5f, -0.5f, + +0.5f, -0.5f, + +0.5f, +0.5f, + +0.5f, +0.5f, + -0.5f, +0.5f, + -0.5f, -0.5f +}; +static GLfloat quadUVs[] = { + 0.0f, 1.0f, + 1.0f, 1.0f, + 1.0f, 0.0f, + 1.0f, 0.0f, + 0.0f, 0.0f, + 0.0f, 1.0f +}; // --------------------------------------------------------------------------- @@ -209,7 +255,6 @@ status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets, const int w = bitmapInfo.width; const int h = bitmapInfo.height; - GLint crop[4] = { 0, h, w, -h }; texture->w = w; texture->h = h; @@ -237,11 +282,10 @@ status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets, break; } - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); return NO_ERROR; } @@ -263,7 +307,6 @@ status_t BootAnimation::initTexture(FileMap* map, int* width, int* height) { const int w = bitmapInfo.width; const int h = bitmapInfo.height; - GLint crop[4] = { 0, h, w, -h }; int tw = 1 << (31 - __builtin_clz(w)); int th = 1 << (31 - __builtin_clz(h)); if (tw < w) tw <<= 1; @@ -297,7 +340,10 @@ status_t BootAnimation::initTexture(FileMap* map, int* width, int* height) { break; } - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); *width = w; *height = h; @@ -470,7 +516,9 @@ status_t BootAnimation::readyToRun() { eglInitialize(display, nullptr, nullptr); EGLConfig config = getEglConfig(display); EGLSurface surface = eglCreateWindowSurface(display, config, s.get(), nullptr); - EGLContext context = eglCreateContext(display, config, nullptr, nullptr); + // Initialize egl context with client version number 2.0. + EGLint contextAttributes[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE}; + EGLContext context = eglCreateContext(display, config, nullptr, contextAttributes); EGLint w, h; eglQuerySurface(display, surface, EGL_WIDTH, &w); eglQuerySurface(display, surface, EGL_HEIGHT, &h); @@ -503,11 +551,6 @@ status_t BootAnimation::readyToRun() { void BootAnimation::projectSceneToWindow() { glViewport(0, 0, mWidth, mHeight); glScissor(0, 0, mWidth, mHeight); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrthof(0, static_cast(mWidth), 0, static_cast(mHeight), -1, 1); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); } void BootAnimation::resizeSurface(int newWidth, int newHeight) { @@ -600,8 +643,68 @@ void BootAnimation::findBootAnimationFile() { } } +GLuint compileShader(GLenum shaderType, const GLchar *source) { + GLuint shader = glCreateShader(shaderType); + glShaderSource(shader, 1, &source, 0); + glCompileShader(shader); + GLint isCompiled = 0; + glGetShaderiv(shader, GL_COMPILE_STATUS, &isCompiled); + if (isCompiled == GL_FALSE) { + SLOGE("Compile shader failed. Shader type: %d", shaderType); + return 0; + } + return shader; +} + +GLuint linkShader(GLuint vertexShader, GLuint fragmentShader) { + GLuint program = glCreateProgram(); + glAttachShader(program, vertexShader); + glAttachShader(program, fragmentShader); + glLinkProgram(program); + GLint isLinked = 0; + glGetProgramiv(program, GL_LINK_STATUS, (int *)&isLinked); + if (isLinked == GL_FALSE) { + SLOGE("Linking shader failed. Shader handles: vert %d, frag %d", + vertexShader, fragmentShader); + return 0; + } + return program; +} + +void BootAnimation::initShaders() { + GLuint vertexShader = compileShader(GL_VERTEX_SHADER, (const GLchar *)VERTEX_SHADER_SOURCE); + GLuint imageFragmentShader = + compileShader(GL_FRAGMENT_SHADER, (const GLchar *)IMAGE_FRAG_SHADER_SOURCE); + GLuint textFragmentShader = + compileShader(GL_FRAGMENT_SHADER, (const GLchar *)TEXT_FRAG_SHADER_SOURCE); + + // Initialize image shader. + mImageShader = linkShader(vertexShader, imageFragmentShader); + GLint positionLocation = glGetAttribLocation(mImageShader, A_POSITION); + GLint uvLocation = glGetAttribLocation(mImageShader, A_UV); + mImageTextureLocation = glGetUniformLocation(mImageShader, U_TEXTURE); + mImageFadeLocation = glGetUniformLocation(mImageShader, U_FADE); + glEnableVertexAttribArray(positionLocation); + glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, quadPositions); + glVertexAttribPointer(uvLocation, 2, GL_FLOAT, GL_FALSE, 0, quadUVs); + glEnableVertexAttribArray(uvLocation); + + // Initialize text shader. + mTextShader = linkShader(vertexShader, textFragmentShader); + positionLocation = glGetAttribLocation(mTextShader, A_POSITION); + uvLocation = glGetAttribLocation(mTextShader, A_UV); + mTextTextureLocation = glGetUniformLocation(mTextShader, U_TEXTURE); + mTextCropAreaLocation = glGetUniformLocation(mTextShader, U_CROP_AREA); + glEnableVertexAttribArray(positionLocation); + glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, quadPositions); + glVertexAttribPointer(uvLocation, 2, GL_FLOAT, GL_FALSE, 0, quadUVs); + glEnableVertexAttribArray(uvLocation); +} + bool BootAnimation::threadLoop() { bool result; + initShaders(); + // We have no bootanimation file, so we use the stock android logo // animation. if (mZipFileName.isEmpty()) { @@ -623,6 +726,8 @@ bool BootAnimation::threadLoop() { } bool BootAnimation::android() { + glActiveTexture(GL_TEXTURE0); + SLOGD("%sAnimationShownTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot", elapsedRealtime()); initTexture(&mAndroid[0], mAssets, "images/android-logo-mask.png"); @@ -631,19 +736,14 @@ bool BootAnimation::android() { mCallbacks->init({}); // clear screen - glShadeModel(GL_FLAT); glDisable(GL_DITHER); glDisable(GL_SCISSOR_TEST); glClearColor(0,0,0,1); glClear(GL_COLOR_BUFFER_BIT); eglSwapBuffers(mDisplay, mSurface); - glEnable(GL_TEXTURE_2D); - glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - // Blend state glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); const nsecs_t startTime = systemTime(); do { @@ -666,12 +766,12 @@ bool BootAnimation::android() { glEnable(GL_SCISSOR_TEST); glDisable(GL_BLEND); glBindTexture(GL_TEXTURE_2D, mAndroid[1].name); - glDrawTexiOES(x, yc, 0, mAndroid[1].w, mAndroid[1].h); - glDrawTexiOES(x + mAndroid[1].w, yc, 0, mAndroid[1].w, mAndroid[1].h); + drawTexturedQuad(x, yc, mAndroid[1].w, mAndroid[1].h); + drawTexturedQuad(x + mAndroid[1].w, yc, mAndroid[1].w, mAndroid[1].h); glEnable(GL_BLEND); glBindTexture(GL_TEXTURE_2D, mAndroid[0].name); - glDrawTexiOES(xc, yc, 0, mAndroid[0].w, mAndroid[0].h); + drawTexturedQuad(xc, yc, mAndroid[0].w, mAndroid[0].h); EGLBoolean res = eglSwapBuffers(mDisplay, mSurface); if (res == EGL_FALSE) @@ -798,10 +898,10 @@ status_t BootAnimation::initFont(Font* font, const char* fallback) { status = initTexture(font->map, &font->texture.w, &font->texture.h); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } else if (fallback != nullptr) { status = initTexture(&font->texture, mAssets, fallback); } else { @@ -816,40 +916,11 @@ status_t BootAnimation::initFont(Font* font, const char* fallback) { return status; } -void BootAnimation::fadeFrame(const int frameLeft, const int frameBottom, const int frameWidth, - const int frameHeight, const Animation::Part& part, - const int fadedFramesCount) { - glEnable(GL_BLEND); - glEnableClientState(GL_VERTEX_ARRAY); - glDisable(GL_TEXTURE_2D); - // avoid creating a hole due to mixing result alpha with GL_REPLACE texture - glBlendFuncSeparateOES(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE); - - const float alpha = static_cast(fadedFramesCount) / part.framesToFadeCount; - glColor4f(part.backgroundColor[0], part.backgroundColor[1], part.backgroundColor[2], alpha); - - const float frameStartX = static_cast(frameLeft); - const float frameStartY = static_cast(frameBottom); - const float frameEndX = frameStartX + frameWidth; - const float frameEndY = frameStartY + frameHeight; - const GLfloat frameRect[] = { - frameStartX, frameStartY, - frameEndX, frameStartY, - frameEndX, frameEndY, - frameStartX, frameEndY - }; - glVertexPointer(2, GL_FLOAT, 0, frameRect); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_TEXTURE_2D); - glDisableClientState(GL_VERTEX_ARRAY); - glDisable(GL_BLEND); -} - void BootAnimation::drawText(const char* str, const Font& font, bool bold, int* x, int* y) { glEnable(GL_BLEND); // Allow us to draw on top of the animation glBindTexture(GL_TEXTURE_2D, font.texture.name); + glUseProgram(mTextShader); + glUniform1i(mTextTextureLocation, 0); const int len = strlen(str); const int strWidth = font.char_width * len; @@ -865,8 +936,6 @@ void BootAnimation::drawText(const char* str, const Font& font, bool bold, int* *y = mHeight + *y - font.char_height; } - int cropRect[4] = { 0, 0, font.char_width, -font.char_height }; - for (int i = 0; i < len; i++) { char c = str[i]; @@ -878,13 +947,13 @@ void BootAnimation::drawText(const char* str, const Font& font, bool bold, int* const int charPos = (c - FONT_BEGIN_CHAR); // Position in the list of valid characters const int row = charPos / FONT_NUM_COLS; const int col = charPos % FONT_NUM_COLS; - cropRect[0] = col * font.char_width; // Left of column - cropRect[1] = row * font.char_height * 2; // Top of row - // Move down to bottom of regular (one char_heigh) or bold (two char_heigh) line - cropRect[1] += bold ? 2 * font.char_height : font.char_height; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, cropRect); - - glDrawTexiOES(*x, *y, 0, font.char_width, font.char_height); + // Bold fonts are expected in the second half of each row. + float v0 = (row + (bold ? 0.5f : 0.0f)) / FONT_NUM_ROWS; + float u0 = ((float)col) / FONT_NUM_COLS; + float v1 = v0 + 1.0f / FONT_NUM_ROWS / 2; + float u1 = u0 + 1.0f / FONT_NUM_COLS; + glUniform4f(mTextCropAreaLocation, u0, v0, u1, v1); + drawTexturedQuad(*x, *y, font.char_width, font.char_height); *x += font.char_width; } @@ -1166,19 +1235,16 @@ bool BootAnimation::movie() { // Blend required to draw time on top of animation frames. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glShadeModel(GL_FLAT); glDisable(GL_DITHER); glDisable(GL_SCISSOR_TEST); glDisable(GL_BLEND); - glBindTexture(GL_TEXTURE_2D, 0); glEnable(GL_TEXTURE_2D); - glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - + glBindTexture(GL_TEXTURE_2D, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); bool clockFontInitialized = false; if (mClockEnabled) { clockFontInitialized = @@ -1218,6 +1284,34 @@ bool BootAnimation::shouldStopPlayingPart(const Animation::Part& part, (lastDisplayedProgress == 0 || lastDisplayedProgress == 100); } +// Linear mapping from range to range +float mapLinear(float x, float a1, float a2, float b1, float b2) { + return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 ); +} + +void BootAnimation::drawTexturedQuad(float xStart, float yStart, float width, float height) { + // Map coordinates from screen space to world space. + float x0 = mapLinear(xStart, 0, mWidth, -1, 1); + float y0 = mapLinear(yStart, 0, mHeight, -1, 1); + float x1 = mapLinear(xStart + width, 0, mWidth, -1, 1); + float y1 = mapLinear(yStart + height, 0, mHeight, -1, 1); + // Update quad vertex positions. + quadPositions[0] = x0; + quadPositions[1] = y0; + quadPositions[2] = x1; + quadPositions[3] = y0; + quadPositions[4] = x1; + quadPositions[5] = y1; + quadPositions[6] = x1; + quadPositions[7] = y1; + quadPositions[8] = x0; + quadPositions[9] = y1; + quadPositions[10] = x0; + quadPositions[11] = y0; + glDrawArrays(GL_TRIANGLES, 0, + sizeof(quadPositions) / sizeof(quadPositions[0]) / 2); +} + bool BootAnimation::playAnimation(const Animation& animation) { const size_t pcount = animation.parts.size(); nsecs_t frameDuration = s2ns(1) / animation.fps; @@ -1230,7 +1324,6 @@ bool BootAnimation::playAnimation(const Animation& animation) { for (size_t i=0 ; i 0) { glBindTexture(GL_TEXTURE_2D, frame.tid); } else { - if (part.count != 1) { - glGenTextures(1, &frame.tid); - glBindTexture(GL_TEXTURE_2D, frame.tid); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } + glGenTextures(1, &frame.tid); + glBindTexture(GL_TEXTURE_2D, frame.tid); int w, h; initTexture(frame.map, &w, &h); } @@ -1300,16 +1389,21 @@ bool BootAnimation::playAnimation(const Animation& animation) { // specify the y center as ceiling((mHeight - frame.trimHeight) / 2) // which is equivalent to mHeight - (yc + frame.trimHeight) const int frameDrawY = mHeight - (yc + frame.trimHeight); - glDrawTexiOES(xc, frameDrawY, 0, frame.trimWidth, frame.trimHeight); + float fade = 0; // if the part hasn't been stopped yet then continue fading if necessary if (exitPending() && part.hasFadingPhase()) { - fadeFrame(xc, frameDrawY, frame.trimWidth, frame.trimHeight, part, - ++fadedFramesCount); + fade = static_cast(++fadedFramesCount) / part.framesToFadeCount; if (fadedFramesCount >= part.framesToFadeCount) { fadedFramesCount = MAX_FADED_FRAMES_COUNT; // no more fading } } + glUseProgram(mImageShader); + glUniform1i(mImageTextureLocation, 0); + glUniform1f(mImageFadeLocation, fade); + glEnable(GL_BLEND); + drawTexturedQuad(xc, frameDrawY, frame.trimWidth, frame.trimHeight); + glDisable(GL_BLEND); if (mClockEnabled && mTimeIsAccurate && validClock(part)) { drawClock(animation.clockFont, part.clockPosX, part.clockPosY); -- cgit v1.2.3-59-g8ed1b From 2ded80094ee534cfbf360e89562f9d6f1cee33e0 Mon Sep 17 00:00:00 2001 From: Greg Kaiser Date: Mon, 19 Jul 2021 17:03:27 +0000 Subject: Revert "Migrate boot animation from GLES 1.0 to GLES2.0." This reverts commit d711ac4858337539c2188f47ef015e5b88080830. Reason for revert: Breaks boot animation on wembley device Bug: 194074093 Change-Id: Id6143bfd1e35089a7df88470978cd064de2d839c Test: wembley has boot animation again with this reverted --- cmds/bootanimation/Android.bp | 2 +- cmds/bootanimation/BootAnimation.cpp | 268 ++++++++++++----------------------- cmds/bootanimation/BootAnimation.h | 10 +- 3 files changed, 89 insertions(+), 191 deletions(-) (limited to 'cmds/bootanimation/BootAnimation.cpp') diff --git a/cmds/bootanimation/Android.bp b/cmds/bootanimation/Android.bp index 3534624a58a2..b2b66c27f795 100644 --- a/cmds/bootanimation/Android.bp +++ b/cmds/bootanimation/Android.bp @@ -71,7 +71,7 @@ cc_library_shared { "libui", "libjnigraphics", "libEGL", - "libGLESv2", + "libGLESv1_CM", "libgui", ], } diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index 25b7f249fc49..3109c5c1e075 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -52,8 +52,9 @@ #include #include #include -#include -#include + +#include +#include #include #include "BootAnimation.h" @@ -107,53 +108,6 @@ static const char PROGRESS_PROP_NAME[] = "service.bootanim.progress"; static const char DISPLAYS_PROP_NAME[] = "persist.service.bootanim.displays"; static const int ANIM_ENTRY_NAME_MAX = ANIM_PATH_MAX + 1; static constexpr size_t TEXT_POS_LEN_MAX = 16; -static const char U_TEXTURE[] = "uTexture"; -static const char U_FADE[] = "uFade"; -static const char U_CROP_AREA[] = "uCropArea"; -static const char A_UV[] = "aUv"; -static const char A_POSITION[] = "aPosition"; -static const char VERTEX_SHADER_SOURCE[] = R"( - attribute vec4 aPosition; - attribute vec2 aUv; - varying vec2 vUv; - void main() { - gl_Position = aPosition; - vUv = aUv; - })"; -static const char IMAGE_FRAG_SHADER_SOURCE[] = R"( - uniform sampler2D uTexture; - uniform float uFade; - varying vec2 vUv; - void main() { - vec4 color = texture2D(uTexture, vUv); - gl_FragColor = vec4(color.x, color.y, color.z, 1.0 - uFade); - })"; -static const char TEXT_FRAG_SHADER_SOURCE[] = R"( - uniform sampler2D uTexture; - uniform vec4 uCropArea; - varying vec2 vUv; - void main() { - vec2 uv = vec2(mix(uCropArea.x, uCropArea.z, vUv.x), - mix(uCropArea.y, uCropArea.w, vUv.y)); - gl_FragColor = texture2D(uTexture, uv); - })"; - -static GLfloat quadPositions[] = { - -0.5f, -0.5f, - +0.5f, -0.5f, - +0.5f, +0.5f, - +0.5f, +0.5f, - -0.5f, +0.5f, - -0.5f, -0.5f -}; -static GLfloat quadUVs[] = { - 0.0f, 1.0f, - 1.0f, 1.0f, - 1.0f, 0.0f, - 1.0f, 0.0f, - 0.0f, 0.0f, - 0.0f, 1.0f -}; // --------------------------------------------------------------------------- @@ -255,6 +209,7 @@ status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets, const int w = bitmapInfo.width; const int h = bitmapInfo.height; + GLint crop[4] = { 0, h, w, -h }; texture->w = w; texture->h = h; @@ -282,10 +237,11 @@ status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets, break; } - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop); + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); return NO_ERROR; } @@ -307,6 +263,7 @@ status_t BootAnimation::initTexture(FileMap* map, int* width, int* height) { const int w = bitmapInfo.width; const int h = bitmapInfo.height; + GLint crop[4] = { 0, h, w, -h }; int tw = 1 << (31 - __builtin_clz(w)); int th = 1 << (31 - __builtin_clz(h)); if (tw < w) tw <<= 1; @@ -340,10 +297,7 @@ status_t BootAnimation::initTexture(FileMap* map, int* width, int* height) { break; } - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop); *width = w; *height = h; @@ -516,9 +470,7 @@ status_t BootAnimation::readyToRun() { eglInitialize(display, nullptr, nullptr); EGLConfig config = getEglConfig(display); EGLSurface surface = eglCreateWindowSurface(display, config, s.get(), nullptr); - // Initialize egl context with client version number 2.0. - EGLint contextAttributes[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE}; - EGLContext context = eglCreateContext(display, config, nullptr, contextAttributes); + EGLContext context = eglCreateContext(display, config, nullptr, nullptr); EGLint w, h; eglQuerySurface(display, surface, EGL_WIDTH, &w); eglQuerySurface(display, surface, EGL_HEIGHT, &h); @@ -551,6 +503,11 @@ status_t BootAnimation::readyToRun() { void BootAnimation::projectSceneToWindow() { glViewport(0, 0, mWidth, mHeight); glScissor(0, 0, mWidth, mHeight); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrthof(0, static_cast(mWidth), 0, static_cast(mHeight), -1, 1); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); } void BootAnimation::resizeSurface(int newWidth, int newHeight) { @@ -643,68 +600,8 @@ void BootAnimation::findBootAnimationFile() { } } -GLuint compileShader(GLenum shaderType, const GLchar *source) { - GLuint shader = glCreateShader(shaderType); - glShaderSource(shader, 1, &source, 0); - glCompileShader(shader); - GLint isCompiled = 0; - glGetShaderiv(shader, GL_COMPILE_STATUS, &isCompiled); - if (isCompiled == GL_FALSE) { - SLOGE("Compile shader failed. Shader type: %d", shaderType); - return 0; - } - return shader; -} - -GLuint linkShader(GLuint vertexShader, GLuint fragmentShader) { - GLuint program = glCreateProgram(); - glAttachShader(program, vertexShader); - glAttachShader(program, fragmentShader); - glLinkProgram(program); - GLint isLinked = 0; - glGetProgramiv(program, GL_LINK_STATUS, (int *)&isLinked); - if (isLinked == GL_FALSE) { - SLOGE("Linking shader failed. Shader handles: vert %d, frag %d", - vertexShader, fragmentShader); - return 0; - } - return program; -} - -void BootAnimation::initShaders() { - GLuint vertexShader = compileShader(GL_VERTEX_SHADER, (const GLchar *)VERTEX_SHADER_SOURCE); - GLuint imageFragmentShader = - compileShader(GL_FRAGMENT_SHADER, (const GLchar *)IMAGE_FRAG_SHADER_SOURCE); - GLuint textFragmentShader = - compileShader(GL_FRAGMENT_SHADER, (const GLchar *)TEXT_FRAG_SHADER_SOURCE); - - // Initialize image shader. - mImageShader = linkShader(vertexShader, imageFragmentShader); - GLint positionLocation = glGetAttribLocation(mImageShader, A_POSITION); - GLint uvLocation = glGetAttribLocation(mImageShader, A_UV); - mImageTextureLocation = glGetUniformLocation(mImageShader, U_TEXTURE); - mImageFadeLocation = glGetUniformLocation(mImageShader, U_FADE); - glEnableVertexAttribArray(positionLocation); - glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, quadPositions); - glVertexAttribPointer(uvLocation, 2, GL_FLOAT, GL_FALSE, 0, quadUVs); - glEnableVertexAttribArray(uvLocation); - - // Initialize text shader. - mTextShader = linkShader(vertexShader, textFragmentShader); - positionLocation = glGetAttribLocation(mTextShader, A_POSITION); - uvLocation = glGetAttribLocation(mTextShader, A_UV); - mTextTextureLocation = glGetUniformLocation(mTextShader, U_TEXTURE); - mTextCropAreaLocation = glGetUniformLocation(mTextShader, U_CROP_AREA); - glEnableVertexAttribArray(positionLocation); - glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, quadPositions); - glVertexAttribPointer(uvLocation, 2, GL_FLOAT, GL_FALSE, 0, quadUVs); - glEnableVertexAttribArray(uvLocation); -} - bool BootAnimation::threadLoop() { bool result; - initShaders(); - // We have no bootanimation file, so we use the stock android logo // animation. if (mZipFileName.isEmpty()) { @@ -726,8 +623,6 @@ bool BootAnimation::threadLoop() { } bool BootAnimation::android() { - glActiveTexture(GL_TEXTURE0); - SLOGD("%sAnimationShownTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot", elapsedRealtime()); initTexture(&mAndroid[0], mAssets, "images/android-logo-mask.png"); @@ -736,14 +631,19 @@ bool BootAnimation::android() { mCallbacks->init({}); // clear screen + glShadeModel(GL_FLAT); glDisable(GL_DITHER); glDisable(GL_SCISSOR_TEST); glClearColor(0,0,0,1); glClear(GL_COLOR_BUFFER_BIT); eglSwapBuffers(mDisplay, mSurface); + glEnable(GL_TEXTURE_2D); + glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + // Blend state glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); const nsecs_t startTime = systemTime(); do { @@ -766,12 +666,12 @@ bool BootAnimation::android() { glEnable(GL_SCISSOR_TEST); glDisable(GL_BLEND); glBindTexture(GL_TEXTURE_2D, mAndroid[1].name); - drawTexturedQuad(x, yc, mAndroid[1].w, mAndroid[1].h); - drawTexturedQuad(x + mAndroid[1].w, yc, mAndroid[1].w, mAndroid[1].h); + glDrawTexiOES(x, yc, 0, mAndroid[1].w, mAndroid[1].h); + glDrawTexiOES(x + mAndroid[1].w, yc, 0, mAndroid[1].w, mAndroid[1].h); glEnable(GL_BLEND); glBindTexture(GL_TEXTURE_2D, mAndroid[0].name); - drawTexturedQuad(xc, yc, mAndroid[0].w, mAndroid[0].h); + glDrawTexiOES(xc, yc, 0, mAndroid[0].w, mAndroid[0].h); EGLBoolean res = eglSwapBuffers(mDisplay, mSurface); if (res == EGL_FALSE) @@ -898,10 +798,10 @@ status_t BootAnimation::initFont(Font* font, const char* fallback) { status = initTexture(font->map, &font->texture.w, &font->texture.h); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); } else if (fallback != nullptr) { status = initTexture(&font->texture, mAssets, fallback); } else { @@ -916,11 +816,40 @@ status_t BootAnimation::initFont(Font* font, const char* fallback) { return status; } +void BootAnimation::fadeFrame(const int frameLeft, const int frameBottom, const int frameWidth, + const int frameHeight, const Animation::Part& part, + const int fadedFramesCount) { + glEnable(GL_BLEND); + glEnableClientState(GL_VERTEX_ARRAY); + glDisable(GL_TEXTURE_2D); + // avoid creating a hole due to mixing result alpha with GL_REPLACE texture + glBlendFuncSeparateOES(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE); + + const float alpha = static_cast(fadedFramesCount) / part.framesToFadeCount; + glColor4f(part.backgroundColor[0], part.backgroundColor[1], part.backgroundColor[2], alpha); + + const float frameStartX = static_cast(frameLeft); + const float frameStartY = static_cast(frameBottom); + const float frameEndX = frameStartX + frameWidth; + const float frameEndY = frameStartY + frameHeight; + const GLfloat frameRect[] = { + frameStartX, frameStartY, + frameEndX, frameStartY, + frameEndX, frameEndY, + frameStartX, frameEndY + }; + glVertexPointer(2, GL_FLOAT, 0, frameRect); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_TEXTURE_2D); + glDisableClientState(GL_VERTEX_ARRAY); + glDisable(GL_BLEND); +} + void BootAnimation::drawText(const char* str, const Font& font, bool bold, int* x, int* y) { glEnable(GL_BLEND); // Allow us to draw on top of the animation glBindTexture(GL_TEXTURE_2D, font.texture.name); - glUseProgram(mTextShader); - glUniform1i(mTextTextureLocation, 0); const int len = strlen(str); const int strWidth = font.char_width * len; @@ -936,6 +865,8 @@ void BootAnimation::drawText(const char* str, const Font& font, bool bold, int* *y = mHeight + *y - font.char_height; } + int cropRect[4] = { 0, 0, font.char_width, -font.char_height }; + for (int i = 0; i < len; i++) { char c = str[i]; @@ -947,13 +878,13 @@ void BootAnimation::drawText(const char* str, const Font& font, bool bold, int* const int charPos = (c - FONT_BEGIN_CHAR); // Position in the list of valid characters const int row = charPos / FONT_NUM_COLS; const int col = charPos % FONT_NUM_COLS; - // Bold fonts are expected in the second half of each row. - float v0 = (row + (bold ? 0.5f : 0.0f)) / FONT_NUM_ROWS; - float u0 = ((float)col) / FONT_NUM_COLS; - float v1 = v0 + 1.0f / FONT_NUM_ROWS / 2; - float u1 = u0 + 1.0f / FONT_NUM_COLS; - glUniform4f(mTextCropAreaLocation, u0, v0, u1, v1); - drawTexturedQuad(*x, *y, font.char_width, font.char_height); + cropRect[0] = col * font.char_width; // Left of column + cropRect[1] = row * font.char_height * 2; // Top of row + // Move down to bottom of regular (one char_heigh) or bold (two char_heigh) line + cropRect[1] += bold ? 2 * font.char_height : font.char_height; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, cropRect); + + glDrawTexiOES(*x, *y, 0, font.char_width, font.char_height); *x += font.char_width; } @@ -1235,16 +1166,19 @@ bool BootAnimation::movie() { // Blend required to draw time on top of animation frames. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glShadeModel(GL_FLAT); glDisable(GL_DITHER); glDisable(GL_SCISSOR_TEST); glDisable(GL_BLEND); - glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glEnable(GL_TEXTURE_2D); + glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + bool clockFontInitialized = false; if (mClockEnabled) { clockFontInitialized = @@ -1284,34 +1218,6 @@ bool BootAnimation::shouldStopPlayingPart(const Animation::Part& part, (lastDisplayedProgress == 0 || lastDisplayedProgress == 100); } -// Linear mapping from range to range -float mapLinear(float x, float a1, float a2, float b1, float b2) { - return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 ); -} - -void BootAnimation::drawTexturedQuad(float xStart, float yStart, float width, float height) { - // Map coordinates from screen space to world space. - float x0 = mapLinear(xStart, 0, mWidth, -1, 1); - float y0 = mapLinear(yStart, 0, mHeight, -1, 1); - float x1 = mapLinear(xStart + width, 0, mWidth, -1, 1); - float y1 = mapLinear(yStart + height, 0, mHeight, -1, 1); - // Update quad vertex positions. - quadPositions[0] = x0; - quadPositions[1] = y0; - quadPositions[2] = x1; - quadPositions[3] = y0; - quadPositions[4] = x1; - quadPositions[5] = y1; - quadPositions[6] = x1; - quadPositions[7] = y1; - quadPositions[8] = x0; - quadPositions[9] = y1; - quadPositions[10] = x0; - quadPositions[11] = y0; - glDrawArrays(GL_TRIANGLES, 0, - sizeof(quadPositions) / sizeof(quadPositions[0]) / 2); -} - bool BootAnimation::playAnimation(const Animation& animation) { const size_t pcount = animation.parts.size(); nsecs_t frameDuration = s2ns(1) / animation.fps; @@ -1324,6 +1230,7 @@ bool BootAnimation::playAnimation(const Animation& animation) { for (size_t i=0 ; i 0) { glBindTexture(GL_TEXTURE_2D, frame.tid); } else { - glGenTextures(1, &frame.tid); - glBindTexture(GL_TEXTURE_2D, frame.tid); + if (part.count != 1) { + glGenTextures(1, &frame.tid); + glBindTexture(GL_TEXTURE_2D, frame.tid); + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } int w, h; initTexture(frame.map, &w, &h); } @@ -1389,21 +1300,16 @@ bool BootAnimation::playAnimation(const Animation& animation) { // specify the y center as ceiling((mHeight - frame.trimHeight) / 2) // which is equivalent to mHeight - (yc + frame.trimHeight) const int frameDrawY = mHeight - (yc + frame.trimHeight); + glDrawTexiOES(xc, frameDrawY, 0, frame.trimWidth, frame.trimHeight); - float fade = 0; // if the part hasn't been stopped yet then continue fading if necessary if (exitPending() && part.hasFadingPhase()) { - fade = static_cast(++fadedFramesCount) / part.framesToFadeCount; + fadeFrame(xc, frameDrawY, frame.trimWidth, frame.trimHeight, part, + ++fadedFramesCount); if (fadedFramesCount >= part.framesToFadeCount) { fadedFramesCount = MAX_FADED_FRAMES_COUNT; // no more fading } } - glUseProgram(mImageShader); - glUniform1i(mImageTextureLocation, 0); - glUniform1f(mImageFadeLocation, fade); - glEnable(GL_BLEND); - drawTexturedQuad(xc, frameDrawY, frame.trimWidth, frame.trimHeight); - glDisable(GL_BLEND); if (mClockEnabled && mTimeIsAccurate && validClock(part)) { drawClock(animation.clockFont, part.clockPosX, part.clockPosY); diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h index 7b616d91c58b..f8a31c6d8790 100644 --- a/cmds/bootanimation/BootAnimation.h +++ b/cmds/bootanimation/BootAnimation.h @@ -31,7 +31,7 @@ #include #include -#include +#include namespace android { @@ -166,7 +166,6 @@ private: status_t initTexture(Texture* texture, AssetManager& asset, const char* name); status_t initTexture(FileMap* map, int* width, int* height); status_t initFont(Font* font, const char* fallback); - void initShaders(); bool android(); bool movie(); void drawText(const char* str, const Font& font, bool bold, int* x, int* y); @@ -174,7 +173,6 @@ private: void drawProgress(int percent, const Font& font, const int xPos, const int yPos); void fadeFrame(int frameLeft, int frameBottom, int frameWidth, int frameHeight, const Animation::Part& part, int fadedFramesCount); - void drawTexturedQuad(float xStart, float yStart, float width, float height); bool validClock(const Animation::Part& part); Animation* loadAnimation(const String8&); bool playAnimation(const Animation&); @@ -220,12 +218,6 @@ private: sp mTimeCheckThread = nullptr; sp mCallbacks; Animation* mAnimation = nullptr; - GLuint mImageShader; - GLuint mTextShader; - GLuint mImageFadeLocation; - GLuint mImageTextureLocation; - GLuint mTextCropAreaLocation; - GLuint mTextTextureLocation; }; // --------------------------------------------------------------------------- -- cgit v1.2.3-59-g8ed1b From 989de3d470dca6df8319be87c8f60c0fdc092b25 Mon Sep 17 00:00:00 2001 From: Dominik Laskowski Date: Tue, 27 Jul 2021 21:09:34 -0700 Subject: Use ui::LayerStack Bug: 182939859 Test: Build Change-Id: I4658471996939713a6330a9c4a7d05cf4c91833a --- cmds/bootanimation/BootAnimation.cpp | 13 ++++++------- core/jni/android_view_SurfaceControl.cpp | 4 ++-- libs/input/SpriteController.cpp | 3 ++- 3 files changed, 10 insertions(+), 10 deletions(-) (limited to 'cmds/bootanimation/BootAnimation.cpp') diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index 3109c5c1e075..5c75d14dc920 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -448,16 +448,15 @@ status_t BootAnimation::readyToRun() { // In the case of multi-display, boot animation shows on the specified displays // in addition to the primary display - auto ids = SurfaceComposerClient::getPhysicalDisplayIds(); - constexpr uint32_t LAYER_STACK = 0; - for (auto id : physicalDisplayIds) { + const auto ids = SurfaceComposerClient::getPhysicalDisplayIds(); + for (const auto id : physicalDisplayIds) { if (std::find(ids.begin(), ids.end(), id) != ids.end()) { - sp token = SurfaceComposerClient::getPhysicalDisplayToken(id); - if (token != nullptr) - t.setDisplayLayerStack(token, LAYER_STACK); + if (const auto token = SurfaceComposerClient::getPhysicalDisplayToken(id)) { + t.setDisplayLayerStack(token, ui::DEFAULT_LAYER_STACK); + } } } - t.setLayerStack(control, LAYER_STACK); + t.setLayerStack(control, ui::DEFAULT_LAYER_STACK); } t.setLayer(control, 0x40000000) diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index f63c0e5a4b04..b9233a087c33 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -814,7 +814,7 @@ static void nativeSetLayerStack(JNIEnv* env, jclass clazz, jlong transactionObj, auto transaction = reinterpret_cast(transactionObj); SurfaceControl* const ctrl = reinterpret_cast(nativeObject); - transaction->setLayerStack(ctrl, layerStack); + transaction->setLayerStack(ctrl, ui::LayerStack::fromValue(layerStack)); } static void nativeSetShadowRadius(JNIEnv* env, jclass clazz, jlong transactionObj, @@ -1013,7 +1013,7 @@ static void nativeSetDisplayLayerStack(JNIEnv* env, jclass clazz, { auto transaction = reinterpret_cast(transactionObj); - transaction->setDisplayLayerStack(token, layerStack); + transaction->setDisplayLayerStack(token, ui::LayerStack::fromValue(layerStack)); } } diff --git a/libs/input/SpriteController.cpp b/libs/input/SpriteController.cpp index acd8bced0612..12c6a32bd0ad 100644 --- a/libs/input/SpriteController.cpp +++ b/libs/input/SpriteController.cpp @@ -169,7 +169,8 @@ void SpriteController::doUpdateSprites() { // If surface is a new one, we have to set right layer stack. if (update.surfaceChanged || update.state.dirty & DIRTY_DISPLAY_ID) { - t.setLayerStack(update.state.surfaceControl, update.state.displayId); + t.setLayerStack(update.state.surfaceControl, + ui::LayerStack::fromValue(update.state.displayId)); needApplyTransaction = true; } } -- cgit v1.2.3-59-g8ed1b From 8eedc0293d53d31f96c2f9cd2f773149aaf5d63f Mon Sep 17 00:00:00 2001 From: Lucas Dupin Date: Thu, 29 Jul 2021 21:49:07 +0000 Subject: Revert "Revert "Migrate boot animation from GLES 1.0 to GLES2.0."" This reverts commit 2ded80094ee534cfbf360e89562f9d6f1cee33e0. Reason for revert: Working on fixing the regression that happened on Wembly, so we can resume feature work. Change-Id: I9a624beffdaf97f131046fd4441a251ed3a448ad Test: adb shell /system/bin/bootanimation Bug: 190093578 --- cmds/bootanimation/Android.bp | 2 +- cmds/bootanimation/BootAnimation.cpp | 271 ++++++++++++++++++++++++----------- cmds/bootanimation/BootAnimation.h | 10 +- 3 files changed, 194 insertions(+), 89 deletions(-) (limited to 'cmds/bootanimation/BootAnimation.cpp') diff --git a/cmds/bootanimation/Android.bp b/cmds/bootanimation/Android.bp index b2b66c27f795..3534624a58a2 100644 --- a/cmds/bootanimation/Android.bp +++ b/cmds/bootanimation/Android.bp @@ -71,7 +71,7 @@ cc_library_shared { "libui", "libjnigraphics", "libEGL", - "libGLESv1_CM", + "libGLESv2", "libgui", ], } diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index 3109c5c1e075..6e27aff5ae7b 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -52,9 +52,8 @@ #include #include #include - -#include -#include +#include +#include #include #include "BootAnimation.h" @@ -108,6 +107,56 @@ static const char PROGRESS_PROP_NAME[] = "service.bootanim.progress"; static const char DISPLAYS_PROP_NAME[] = "persist.service.bootanim.displays"; static const int ANIM_ENTRY_NAME_MAX = ANIM_PATH_MAX + 1; static constexpr size_t TEXT_POS_LEN_MAX = 16; +static const char U_TEXTURE[] = "uTexture"; +static const char U_FADE[] = "uFade"; +static const char U_CROP_AREA[] = "uCropArea"; +static const char A_UV[] = "aUv"; +static const char A_POSITION[] = "aPosition"; +static const char VERTEX_SHADER_SOURCE[] = R"( + precision mediump float; + attribute vec4 aPosition; + attribute highp vec2 aUv; + varying highp vec2 vUv; + void main() { + gl_Position = aPosition; + vUv = aUv; + })"; +static const char IMAGE_FRAG_SHADER_SOURCE[] = R"( + precision mediump float; + uniform sampler2D uTexture; + uniform float uFade; + varying highp vec2 vUv; + void main() { + vec4 color = texture2D(uTexture, vUv); + gl_FragColor = vec4(color.x, color.y, color.z, 1.0 - uFade); + })"; +static const char TEXT_FRAG_SHADER_SOURCE[] = R"( + precision mediump float; + uniform sampler2D uTexture; + uniform vec4 uCropArea; + varying highp vec2 vUv; + void main() { + vec2 uv = vec2(mix(uCropArea.x, uCropArea.z, vUv.x), + mix(uCropArea.y, uCropArea.w, vUv.y)); + gl_FragColor = texture2D(uTexture, uv); + })"; + +static GLfloat quadPositions[] = { + -0.5f, -0.5f, + +0.5f, -0.5f, + +0.5f, +0.5f, + +0.5f, +0.5f, + -0.5f, +0.5f, + -0.5f, -0.5f +}; +static GLfloat quadUVs[] = { + 0.0f, 1.0f, + 1.0f, 1.0f, + 1.0f, 0.0f, + 1.0f, 0.0f, + 0.0f, 0.0f, + 0.0f, 1.0f +}; // --------------------------------------------------------------------------- @@ -209,7 +258,6 @@ status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets, const int w = bitmapInfo.width; const int h = bitmapInfo.height; - GLint crop[4] = { 0, h, w, -h }; texture->w = w; texture->h = h; @@ -237,11 +285,10 @@ status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets, break; } - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); return NO_ERROR; } @@ -263,7 +310,6 @@ status_t BootAnimation::initTexture(FileMap* map, int* width, int* height) { const int w = bitmapInfo.width; const int h = bitmapInfo.height; - GLint crop[4] = { 0, h, w, -h }; int tw = 1 << (31 - __builtin_clz(w)); int th = 1 << (31 - __builtin_clz(h)); if (tw < w) tw <<= 1; @@ -297,7 +343,10 @@ status_t BootAnimation::initTexture(FileMap* map, int* width, int* height) { break; } - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); *width = w; *height = h; @@ -470,7 +519,9 @@ status_t BootAnimation::readyToRun() { eglInitialize(display, nullptr, nullptr); EGLConfig config = getEglConfig(display); EGLSurface surface = eglCreateWindowSurface(display, config, s.get(), nullptr); - EGLContext context = eglCreateContext(display, config, nullptr, nullptr); + // Initialize egl context with client version number 2.0. + EGLint contextAttributes[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE}; + EGLContext context = eglCreateContext(display, config, nullptr, contextAttributes); EGLint w, h; eglQuerySurface(display, surface, EGL_WIDTH, &w); eglQuerySurface(display, surface, EGL_HEIGHT, &h); @@ -503,11 +554,6 @@ status_t BootAnimation::readyToRun() { void BootAnimation::projectSceneToWindow() { glViewport(0, 0, mWidth, mHeight); glScissor(0, 0, mWidth, mHeight); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrthof(0, static_cast(mWidth), 0, static_cast(mHeight), -1, 1); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); } void BootAnimation::resizeSurface(int newWidth, int newHeight) { @@ -600,8 +646,68 @@ void BootAnimation::findBootAnimationFile() { } } +GLuint compileShader(GLenum shaderType, const GLchar *source) { + GLuint shader = glCreateShader(shaderType); + glShaderSource(shader, 1, &source, 0); + glCompileShader(shader); + GLint isCompiled = 0; + glGetShaderiv(shader, GL_COMPILE_STATUS, &isCompiled); + if (isCompiled == GL_FALSE) { + SLOGE("Compile shader failed. Shader type: %d", shaderType); + return 0; + } + return shader; +} + +GLuint linkShader(GLuint vertexShader, GLuint fragmentShader) { + GLuint program = glCreateProgram(); + glAttachShader(program, vertexShader); + glAttachShader(program, fragmentShader); + glLinkProgram(program); + GLint isLinked = 0; + glGetProgramiv(program, GL_LINK_STATUS, (int *)&isLinked); + if (isLinked == GL_FALSE) { + SLOGE("Linking shader failed. Shader handles: vert %d, frag %d", + vertexShader, fragmentShader); + return 0; + } + return program; +} + +void BootAnimation::initShaders() { + GLuint vertexShader = compileShader(GL_VERTEX_SHADER, (const GLchar *)VERTEX_SHADER_SOURCE); + GLuint imageFragmentShader = + compileShader(GL_FRAGMENT_SHADER, (const GLchar *)IMAGE_FRAG_SHADER_SOURCE); + GLuint textFragmentShader = + compileShader(GL_FRAGMENT_SHADER, (const GLchar *)TEXT_FRAG_SHADER_SOURCE); + + // Initialize image shader. + mImageShader = linkShader(vertexShader, imageFragmentShader); + GLint positionLocation = glGetAttribLocation(mImageShader, A_POSITION); + GLint uvLocation = glGetAttribLocation(mImageShader, A_UV); + mImageTextureLocation = glGetUniformLocation(mImageShader, U_TEXTURE); + mImageFadeLocation = glGetUniformLocation(mImageShader, U_FADE); + glEnableVertexAttribArray(positionLocation); + glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, quadPositions); + glVertexAttribPointer(uvLocation, 2, GL_FLOAT, GL_FALSE, 0, quadUVs); + glEnableVertexAttribArray(uvLocation); + + // Initialize text shader. + mTextShader = linkShader(vertexShader, textFragmentShader); + positionLocation = glGetAttribLocation(mTextShader, A_POSITION); + uvLocation = glGetAttribLocation(mTextShader, A_UV); + mTextTextureLocation = glGetUniformLocation(mTextShader, U_TEXTURE); + mTextCropAreaLocation = glGetUniformLocation(mTextShader, U_CROP_AREA); + glEnableVertexAttribArray(positionLocation); + glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, quadPositions); + glVertexAttribPointer(uvLocation, 2, GL_FLOAT, GL_FALSE, 0, quadUVs); + glEnableVertexAttribArray(uvLocation); +} + bool BootAnimation::threadLoop() { bool result; + initShaders(); + // We have no bootanimation file, so we use the stock android logo // animation. if (mZipFileName.isEmpty()) { @@ -623,6 +729,8 @@ bool BootAnimation::threadLoop() { } bool BootAnimation::android() { + glActiveTexture(GL_TEXTURE0); + SLOGD("%sAnimationShownTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot", elapsedRealtime()); initTexture(&mAndroid[0], mAssets, "images/android-logo-mask.png"); @@ -631,19 +739,14 @@ bool BootAnimation::android() { mCallbacks->init({}); // clear screen - glShadeModel(GL_FLAT); glDisable(GL_DITHER); glDisable(GL_SCISSOR_TEST); glClearColor(0,0,0,1); glClear(GL_COLOR_BUFFER_BIT); eglSwapBuffers(mDisplay, mSurface); - glEnable(GL_TEXTURE_2D); - glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - // Blend state glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); const nsecs_t startTime = systemTime(); do { @@ -666,12 +769,12 @@ bool BootAnimation::android() { glEnable(GL_SCISSOR_TEST); glDisable(GL_BLEND); glBindTexture(GL_TEXTURE_2D, mAndroid[1].name); - glDrawTexiOES(x, yc, 0, mAndroid[1].w, mAndroid[1].h); - glDrawTexiOES(x + mAndroid[1].w, yc, 0, mAndroid[1].w, mAndroid[1].h); + drawTexturedQuad(x, yc, mAndroid[1].w, mAndroid[1].h); + drawTexturedQuad(x + mAndroid[1].w, yc, mAndroid[1].w, mAndroid[1].h); glEnable(GL_BLEND); glBindTexture(GL_TEXTURE_2D, mAndroid[0].name); - glDrawTexiOES(xc, yc, 0, mAndroid[0].w, mAndroid[0].h); + drawTexturedQuad(xc, yc, mAndroid[0].w, mAndroid[0].h); EGLBoolean res = eglSwapBuffers(mDisplay, mSurface); if (res == EGL_FALSE) @@ -798,10 +901,10 @@ status_t BootAnimation::initFont(Font* font, const char* fallback) { status = initTexture(font->map, &font->texture.w, &font->texture.h); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } else if (fallback != nullptr) { status = initTexture(&font->texture, mAssets, fallback); } else { @@ -816,40 +919,11 @@ status_t BootAnimation::initFont(Font* font, const char* fallback) { return status; } -void BootAnimation::fadeFrame(const int frameLeft, const int frameBottom, const int frameWidth, - const int frameHeight, const Animation::Part& part, - const int fadedFramesCount) { - glEnable(GL_BLEND); - glEnableClientState(GL_VERTEX_ARRAY); - glDisable(GL_TEXTURE_2D); - // avoid creating a hole due to mixing result alpha with GL_REPLACE texture - glBlendFuncSeparateOES(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE); - - const float alpha = static_cast(fadedFramesCount) / part.framesToFadeCount; - glColor4f(part.backgroundColor[0], part.backgroundColor[1], part.backgroundColor[2], alpha); - - const float frameStartX = static_cast(frameLeft); - const float frameStartY = static_cast(frameBottom); - const float frameEndX = frameStartX + frameWidth; - const float frameEndY = frameStartY + frameHeight; - const GLfloat frameRect[] = { - frameStartX, frameStartY, - frameEndX, frameStartY, - frameEndX, frameEndY, - frameStartX, frameEndY - }; - glVertexPointer(2, GL_FLOAT, 0, frameRect); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_TEXTURE_2D); - glDisableClientState(GL_VERTEX_ARRAY); - glDisable(GL_BLEND); -} - void BootAnimation::drawText(const char* str, const Font& font, bool bold, int* x, int* y) { glEnable(GL_BLEND); // Allow us to draw on top of the animation glBindTexture(GL_TEXTURE_2D, font.texture.name); + glUseProgram(mTextShader); + glUniform1i(mTextTextureLocation, 0); const int len = strlen(str); const int strWidth = font.char_width * len; @@ -865,8 +939,6 @@ void BootAnimation::drawText(const char* str, const Font& font, bool bold, int* *y = mHeight + *y - font.char_height; } - int cropRect[4] = { 0, 0, font.char_width, -font.char_height }; - for (int i = 0; i < len; i++) { char c = str[i]; @@ -878,13 +950,13 @@ void BootAnimation::drawText(const char* str, const Font& font, bool bold, int* const int charPos = (c - FONT_BEGIN_CHAR); // Position in the list of valid characters const int row = charPos / FONT_NUM_COLS; const int col = charPos % FONT_NUM_COLS; - cropRect[0] = col * font.char_width; // Left of column - cropRect[1] = row * font.char_height * 2; // Top of row - // Move down to bottom of regular (one char_heigh) or bold (two char_heigh) line - cropRect[1] += bold ? 2 * font.char_height : font.char_height; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, cropRect); - - glDrawTexiOES(*x, *y, 0, font.char_width, font.char_height); + // Bold fonts are expected in the second half of each row. + float v0 = (row + (bold ? 0.5f : 0.0f)) / FONT_NUM_ROWS; + float u0 = ((float)col) / FONT_NUM_COLS; + float v1 = v0 + 1.0f / FONT_NUM_ROWS / 2; + float u1 = u0 + 1.0f / FONT_NUM_COLS; + glUniform4f(mTextCropAreaLocation, u0, v0, u1, v1); + drawTexturedQuad(*x, *y, font.char_width, font.char_height); *x += font.char_width; } @@ -1166,19 +1238,16 @@ bool BootAnimation::movie() { // Blend required to draw time on top of animation frames. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glShadeModel(GL_FLAT); glDisable(GL_DITHER); glDisable(GL_SCISSOR_TEST); glDisable(GL_BLEND); - glBindTexture(GL_TEXTURE_2D, 0); glEnable(GL_TEXTURE_2D); - glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - + glBindTexture(GL_TEXTURE_2D, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); bool clockFontInitialized = false; if (mClockEnabled) { clockFontInitialized = @@ -1218,6 +1287,34 @@ bool BootAnimation::shouldStopPlayingPart(const Animation::Part& part, (lastDisplayedProgress == 0 || lastDisplayedProgress == 100); } +// Linear mapping from range to range +float mapLinear(float x, float a1, float a2, float b1, float b2) { + return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 ); +} + +void BootAnimation::drawTexturedQuad(float xStart, float yStart, float width, float height) { + // Map coordinates from screen space to world space. + float x0 = mapLinear(xStart, 0, mWidth, -1, 1); + float y0 = mapLinear(yStart, 0, mHeight, -1, 1); + float x1 = mapLinear(xStart + width, 0, mWidth, -1, 1); + float y1 = mapLinear(yStart + height, 0, mHeight, -1, 1); + // Update quad vertex positions. + quadPositions[0] = x0; + quadPositions[1] = y0; + quadPositions[2] = x1; + quadPositions[3] = y0; + quadPositions[4] = x1; + quadPositions[5] = y1; + quadPositions[6] = x1; + quadPositions[7] = y1; + quadPositions[8] = x0; + quadPositions[9] = y1; + quadPositions[10] = x0; + quadPositions[11] = y0; + glDrawArrays(GL_TRIANGLES, 0, + sizeof(quadPositions) / sizeof(quadPositions[0]) / 2); +} + bool BootAnimation::playAnimation(const Animation& animation) { const size_t pcount = animation.parts.size(); nsecs_t frameDuration = s2ns(1) / animation.fps; @@ -1230,7 +1327,6 @@ bool BootAnimation::playAnimation(const Animation& animation) { for (size_t i=0 ; i 0) { glBindTexture(GL_TEXTURE_2D, frame.tid); } else { - if (part.count != 1) { - glGenTextures(1, &frame.tid); - glBindTexture(GL_TEXTURE_2D, frame.tid); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } + glGenTextures(1, &frame.tid); + glBindTexture(GL_TEXTURE_2D, frame.tid); int w, h; initTexture(frame.map, &w, &h); } @@ -1300,16 +1392,21 @@ bool BootAnimation::playAnimation(const Animation& animation) { // specify the y center as ceiling((mHeight - frame.trimHeight) / 2) // which is equivalent to mHeight - (yc + frame.trimHeight) const int frameDrawY = mHeight - (yc + frame.trimHeight); - glDrawTexiOES(xc, frameDrawY, 0, frame.trimWidth, frame.trimHeight); + float fade = 0; // if the part hasn't been stopped yet then continue fading if necessary if (exitPending() && part.hasFadingPhase()) { - fadeFrame(xc, frameDrawY, frame.trimWidth, frame.trimHeight, part, - ++fadedFramesCount); + fade = static_cast(++fadedFramesCount) / part.framesToFadeCount; if (fadedFramesCount >= part.framesToFadeCount) { fadedFramesCount = MAX_FADED_FRAMES_COUNT; // no more fading } } + glUseProgram(mImageShader); + glUniform1i(mImageTextureLocation, 0); + glUniform1f(mImageFadeLocation, fade); + glEnable(GL_BLEND); + drawTexturedQuad(xc, frameDrawY, frame.trimWidth, frame.trimHeight); + glDisable(GL_BLEND); if (mClockEnabled && mTimeIsAccurate && validClock(part)) { drawClock(animation.clockFont, part.clockPosX, part.clockPosY); diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h index f8a31c6d8790..7b616d91c58b 100644 --- a/cmds/bootanimation/BootAnimation.h +++ b/cmds/bootanimation/BootAnimation.h @@ -31,7 +31,7 @@ #include #include -#include +#include namespace android { @@ -166,6 +166,7 @@ private: status_t initTexture(Texture* texture, AssetManager& asset, const char* name); status_t initTexture(FileMap* map, int* width, int* height); status_t initFont(Font* font, const char* fallback); + void initShaders(); bool android(); bool movie(); void drawText(const char* str, const Font& font, bool bold, int* x, int* y); @@ -173,6 +174,7 @@ private: void drawProgress(int percent, const Font& font, const int xPos, const int yPos); void fadeFrame(int frameLeft, int frameBottom, int frameWidth, int frameHeight, const Animation::Part& part, int fadedFramesCount); + void drawTexturedQuad(float xStart, float yStart, float width, float height); bool validClock(const Animation::Part& part); Animation* loadAnimation(const String8&); bool playAnimation(const Animation&); @@ -218,6 +220,12 @@ private: sp mTimeCheckThread = nullptr; sp mCallbacks; Animation* mAnimation = nullptr; + GLuint mImageShader; + GLuint mTextShader; + GLuint mImageFadeLocation; + GLuint mImageTextureLocation; + GLuint mTextCropAreaLocation; + GLuint mTextTextureLocation; }; // --------------------------------------------------------------------------- -- cgit v1.2.3-59-g8ed1b From 79d079ea49866f2c5d3c02af2d19fb9cf2097dd4 Mon Sep 17 00:00:00 2001 From: Shan Huang Date: Mon, 9 Aug 2021 21:09:11 +0000 Subject: Implement dynamic colors for boot animation. This CL won't cause any visual change to the boot animation yet because the asset zips are yet to be udated. Next steps: - Update format.md to include documentation for dynamic coloring. - Update asset zip files. Test: Manual Bug: 190093578 Change-Id: I63fdb1983896f321288d595d06f46bcde7da1aab --- cmds/bootanimation/BootAnimation.cpp | 122 ++++++++++++++++++++++++++++++----- cmds/bootanimation/BootAnimation.h | 9 +++ 2 files changed, 116 insertions(+), 15 deletions(-) (limited to 'cmds/bootanimation/BootAnimation.cpp') diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index 6e27aff5ae7b..f55c497f06f4 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -107,9 +107,13 @@ static const char PROGRESS_PROP_NAME[] = "service.bootanim.progress"; static const char DISPLAYS_PROP_NAME[] = "persist.service.bootanim.displays"; static const int ANIM_ENTRY_NAME_MAX = ANIM_PATH_MAX + 1; static constexpr size_t TEXT_POS_LEN_MAX = 16; +static const int DYNAMIC_COLOR_COUNT = 4; static const char U_TEXTURE[] = "uTexture"; static const char U_FADE[] = "uFade"; static const char U_CROP_AREA[] = "uCropArea"; +static const char U_START_COLOR_PREFIX[] = "uStartColor"; +static const char U_END_COLOR_PREFIX[] = "uEndColor"; +static const char U_COLOR_PROGRESS[] = "uColorProgress"; static const char A_UV[] = "aUv"; static const char A_POSITION[] = "aPosition"; static const char VERTEX_SHADER_SOURCE[] = R"( @@ -121,6 +125,28 @@ static const char VERTEX_SHADER_SOURCE[] = R"( gl_Position = aPosition; vUv = aUv; })"; +static const char IMAGE_FRAG_DYNAMIC_COLORING_SHADER_SOURCE[] = R"( + precision mediump float; + uniform sampler2D uTexture; + uniform float uFade; + uniform float uColorProgress; + uniform vec4 uStartColor0; + uniform vec4 uStartColor1; + uniform vec4 uStartColor2; + uniform vec4 uStartColor3; + uniform vec4 uEndColor0; + uniform vec4 uEndColor1; + uniform vec4 uEndColor2; + uniform vec4 uEndColor3; + varying highp vec2 vUv; + void main() { + vec4 mask = texture2D(uTexture, vUv); + vec4 color = mask.r * mix(uStartColor0, uEndColor0, uColorProgress) + + mask.g * mix(uStartColor1, uEndColor1, uColorProgress) + + mask.b * mix(uStartColor2, uEndColor2, uColorProgress) + + mask.a * mix(uStartColor3, uEndColor3, uColorProgress); + gl_FragColor = vec4(color.x, color.y, color.z, (1.0 - uFade)) * color.a; + })"; static const char IMAGE_FRAG_SHADER_SOURCE[] = R"( precision mediump float; uniform sampler2D uTexture; @@ -128,7 +154,7 @@ static const char IMAGE_FRAG_SHADER_SOURCE[] = R"( varying highp vec2 vUv; void main() { vec4 color = texture2D(uTexture, vUv); - gl_FragColor = vec4(color.x, color.y, color.z, 1.0 - uFade); + gl_FragColor = vec4(color.x, color.y, color.z, (1.0 - uFade)) * color.a; })"; static const char TEXT_FRAG_SHADER_SOURCE[] = R"( precision mediump float; @@ -226,6 +252,10 @@ static void* decodeImage(const void* encodedData, size_t dataLength, AndroidBitm outInfo->stride = AImageDecoder_getMinimumStride(decoder); outInfo->flags = 0; + // Set decoding option to alpha unpremultiplied so that the R, G, B channels + // of transparent pixels are preserved. + AImageDecoder_setUnpremultipliedRequired(decoder, true); + const size_t size = outInfo->stride * outInfo->height; void* pixels = malloc(size); int result = AImageDecoder_decodeImage(decoder, pixels, outInfo->stride, size); @@ -677,7 +707,9 @@ GLuint linkShader(GLuint vertexShader, GLuint fragmentShader) { void BootAnimation::initShaders() { GLuint vertexShader = compileShader(GL_VERTEX_SHADER, (const GLchar *)VERTEX_SHADER_SOURCE); GLuint imageFragmentShader = - compileShader(GL_FRAGMENT_SHADER, (const GLchar *)IMAGE_FRAG_SHADER_SOURCE); + compileShader(GL_FRAGMENT_SHADER, mAnimation->dynamicColoringEnabled + ? (const GLchar *)IMAGE_FRAG_DYNAMIC_COLORING_SHADER_SOURCE + : (const GLchar *)IMAGE_FRAG_SHADER_SOURCE); GLuint textFragmentShader = compileShader(GL_FRAGMENT_SHADER, (const GLchar *)TEXT_FRAG_SHADER_SOURCE); @@ -687,11 +719,27 @@ void BootAnimation::initShaders() { GLint uvLocation = glGetAttribLocation(mImageShader, A_UV); mImageTextureLocation = glGetUniformLocation(mImageShader, U_TEXTURE); mImageFadeLocation = glGetUniformLocation(mImageShader, U_FADE); + mImageColorProgressLocation = glGetUniformLocation(mImageShader, U_COLOR_PROGRESS); glEnableVertexAttribArray(positionLocation); glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, quadPositions); glVertexAttribPointer(uvLocation, 2, GL_FLOAT, GL_FALSE, 0, quadUVs); glEnableVertexAttribArray(uvLocation); + if (mAnimation->dynamicColoringEnabled) { + glUseProgram(mImageShader); + SLOGI("[BootAnimation] Dynamically coloring boot animation."); + for (int i = 0; i < DYNAMIC_COLOR_COUNT; i++) { + float *startColor = mAnimation->startColors[i]; + float *endColor = mAnimation->endColors[i]; + glUniform4f(glGetUniformLocation(mImageShader, + (U_START_COLOR_PREFIX + std::to_string(i)).c_str()), + startColor[0], startColor[1], startColor[2], 1 /* alpha */); + glUniform4f(glGetUniformLocation(mImageShader, + (U_END_COLOR_PREFIX + std::to_string(i)).c_str()), + endColor[0], endColor[1], endColor[2], 1 /* alpha */); + } + } + // Initialize text shader. mTextShader = linkShader(vertexShader, textFragmentShader); positionLocation = glGetAttribLocation(mTextShader, A_POSITION); @@ -869,6 +917,20 @@ static bool parseColor(const char str[7], float color[3]) { return true; } +// Parse a color represented as a signed decimal int string. +// E.g. "-2757722" (whose hex 2's complement is 0xFFD5EBA6). +// If the input color string is empty, set color with values in defaultColor. +static void parseColorDecimalString(const std::string& colorString, + float color[3], float defaultColor[3]) { + if (colorString == "") { + memcpy(color, defaultColor, sizeof(float) * 3); + return; + } + int colorInt = atoi(colorString.c_str()); + color[0] = ((float)((colorInt >> 16) & 0xFF)) / 0xFF; // r + color[1] = ((float)((colorInt >> 8) & 0xFF)) / 0xFF; // g + color[2] = ((float)(colorInt & 0xFF)) / 0xFF; // b +} static bool readFile(ZipFileRO* zip, const char* name, String8& outString) { ZipEntryRO entry = zip->findEntryByName(name); @@ -1010,6 +1072,8 @@ bool BootAnimation::parseAnimationDesc(Animation& animation) { return false; } char const* s = desString.string(); + std::string dynamicColoringPartName = ""; + bool postDynamicColoring = false; // Parse the description file for (;;) { @@ -1028,7 +1092,13 @@ bool BootAnimation::parseAnimationDesc(Animation& animation) { char color[7] = "000000"; // default to black if unspecified char clockPos1[TEXT_POS_LEN_MAX + 1] = ""; char clockPos2[TEXT_POS_LEN_MAX + 1] = ""; + char dynamicColoringPartNameBuffer[ANIM_ENTRY_NAME_MAX]; char pathType; + // start colors default to black if unspecified + char start_color_0[7] = "000000"; + char start_color_1[7] = "000000"; + char start_color_2[7] = "000000"; + char start_color_3[7] = "000000"; int nextReadPos; @@ -1043,6 +1113,15 @@ bool BootAnimation::parseAnimationDesc(Animation& animation) { } else { animation.progressEnabled = false; } + } else if (sscanf(l, "dynamic_colors %" STRTO(ANIM_PATH_MAX) "s #%6s #%6s #%6s #%6s", + dynamicColoringPartNameBuffer, + start_color_0, start_color_1, start_color_2, start_color_3)) { + animation.dynamicColoringEnabled = true; + parseColor(start_color_0, animation.startColors[0]); + parseColor(start_color_1, animation.startColors[1]); + parseColor(start_color_2, animation.startColors[2]); + parseColor(start_color_3, animation.startColors[3]); + dynamicColoringPartName = std::string(dynamicColoringPartNameBuffer); } else if (sscanf(l, "%c %d %d %" STRTO(ANIM_PATH_MAX) "s%n", &pathType, &count, &pause, path, &nextReadPos) >= 4) { if (pathType == 'f') { @@ -1055,6 +1134,16 @@ bool BootAnimation::parseAnimationDesc(Animation& animation) { // "clockPos1=%s, clockPos2=%s", // pathType, count, pause, path, framesToFadeCount, color, clockPos1, clockPos2); Animation::Part part; + if (path == dynamicColoringPartName) { + // Part is specified to use dynamic coloring. + part.useDynamicColoring = true; + part.postDynamicColoring = false; + postDynamicColoring = true; + } else { + // Part does not use dynamic coloring. + part.useDynamicColoring = false; + part.postDynamicColoring = postDynamicColoring; + } part.playUntilComplete = pathType == 'c'; part.framesToFadeCount = framesToFadeCount; part.count = count; @@ -1086,6 +1175,12 @@ bool BootAnimation::parseAnimationDesc(Animation& animation) { s = ++endl; } + for (int i = 0; i < DYNAMIC_COLOR_COUNT; i++) { + parseColorDecimalString( + android::base::GetProperty("persist.bootanim.color" + std::to_string(i + 1), ""), + animation.endColors[i], animation.startColors[i]); + } + return true; } @@ -1357,6 +1452,14 @@ bool BootAnimation::playAnimation(const Animation& animation) { for (size_t j=0 ; j 0; @@ -105,6 +109,10 @@ public: ZipFileRO* zip; Font clockFont; Font progressFont; + // Controls if dynamic coloring is enabled for the whole animation. + bool dynamicColoringEnabled = false; + float startColors[4][3]; // Start colors of dynamic color transition. + float endColors[4][3]; // End colors of dynamic color transition. }; // All callbacks will be called from this class's internal thread. @@ -226,6 +234,7 @@ private: GLuint mImageTextureLocation; GLuint mTextCropAreaLocation; GLuint mTextTextureLocation; + GLuint mImageColorProgressLocation; }; // --------------------------------------------------------------------------- -- cgit v1.2.3-59-g8ed1b From 92aa9daa10ba767cccead3b875d1251dcf2a2a6b Mon Sep 17 00:00:00 2001 From: Ady Abraham Date: Thu, 12 Aug 2021 23:55:46 +0000 Subject: Revert "Implement dynamic colors for boot animation." This reverts commit 79d079ea49866f2c5d3c02af2d19fb9cf2097dd4. Reason for revert: DroidMonitor: Potential culprit for Bug b/196456395 - verifying through Forrest before revert submission. This is part of the standard investigation process, and does not mean your CL will be reverted. Change-Id: I6130e75ae174f68ddfaa6e1010d7979538311020 --- cmds/bootanimation/BootAnimation.cpp | 122 +++++------------------------------ cmds/bootanimation/BootAnimation.h | 9 --- 2 files changed, 15 insertions(+), 116 deletions(-) (limited to 'cmds/bootanimation/BootAnimation.cpp') diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index f55c497f06f4..6e27aff5ae7b 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -107,13 +107,9 @@ static const char PROGRESS_PROP_NAME[] = "service.bootanim.progress"; static const char DISPLAYS_PROP_NAME[] = "persist.service.bootanim.displays"; static const int ANIM_ENTRY_NAME_MAX = ANIM_PATH_MAX + 1; static constexpr size_t TEXT_POS_LEN_MAX = 16; -static const int DYNAMIC_COLOR_COUNT = 4; static const char U_TEXTURE[] = "uTexture"; static const char U_FADE[] = "uFade"; static const char U_CROP_AREA[] = "uCropArea"; -static const char U_START_COLOR_PREFIX[] = "uStartColor"; -static const char U_END_COLOR_PREFIX[] = "uEndColor"; -static const char U_COLOR_PROGRESS[] = "uColorProgress"; static const char A_UV[] = "aUv"; static const char A_POSITION[] = "aPosition"; static const char VERTEX_SHADER_SOURCE[] = R"( @@ -125,28 +121,6 @@ static const char VERTEX_SHADER_SOURCE[] = R"( gl_Position = aPosition; vUv = aUv; })"; -static const char IMAGE_FRAG_DYNAMIC_COLORING_SHADER_SOURCE[] = R"( - precision mediump float; - uniform sampler2D uTexture; - uniform float uFade; - uniform float uColorProgress; - uniform vec4 uStartColor0; - uniform vec4 uStartColor1; - uniform vec4 uStartColor2; - uniform vec4 uStartColor3; - uniform vec4 uEndColor0; - uniform vec4 uEndColor1; - uniform vec4 uEndColor2; - uniform vec4 uEndColor3; - varying highp vec2 vUv; - void main() { - vec4 mask = texture2D(uTexture, vUv); - vec4 color = mask.r * mix(uStartColor0, uEndColor0, uColorProgress) - + mask.g * mix(uStartColor1, uEndColor1, uColorProgress) - + mask.b * mix(uStartColor2, uEndColor2, uColorProgress) - + mask.a * mix(uStartColor3, uEndColor3, uColorProgress); - gl_FragColor = vec4(color.x, color.y, color.z, (1.0 - uFade)) * color.a; - })"; static const char IMAGE_FRAG_SHADER_SOURCE[] = R"( precision mediump float; uniform sampler2D uTexture; @@ -154,7 +128,7 @@ static const char IMAGE_FRAG_SHADER_SOURCE[] = R"( varying highp vec2 vUv; void main() { vec4 color = texture2D(uTexture, vUv); - gl_FragColor = vec4(color.x, color.y, color.z, (1.0 - uFade)) * color.a; + gl_FragColor = vec4(color.x, color.y, color.z, 1.0 - uFade); })"; static const char TEXT_FRAG_SHADER_SOURCE[] = R"( precision mediump float; @@ -252,10 +226,6 @@ static void* decodeImage(const void* encodedData, size_t dataLength, AndroidBitm outInfo->stride = AImageDecoder_getMinimumStride(decoder); outInfo->flags = 0; - // Set decoding option to alpha unpremultiplied so that the R, G, B channels - // of transparent pixels are preserved. - AImageDecoder_setUnpremultipliedRequired(decoder, true); - const size_t size = outInfo->stride * outInfo->height; void* pixels = malloc(size); int result = AImageDecoder_decodeImage(decoder, pixels, outInfo->stride, size); @@ -707,9 +677,7 @@ GLuint linkShader(GLuint vertexShader, GLuint fragmentShader) { void BootAnimation::initShaders() { GLuint vertexShader = compileShader(GL_VERTEX_SHADER, (const GLchar *)VERTEX_SHADER_SOURCE); GLuint imageFragmentShader = - compileShader(GL_FRAGMENT_SHADER, mAnimation->dynamicColoringEnabled - ? (const GLchar *)IMAGE_FRAG_DYNAMIC_COLORING_SHADER_SOURCE - : (const GLchar *)IMAGE_FRAG_SHADER_SOURCE); + compileShader(GL_FRAGMENT_SHADER, (const GLchar *)IMAGE_FRAG_SHADER_SOURCE); GLuint textFragmentShader = compileShader(GL_FRAGMENT_SHADER, (const GLchar *)TEXT_FRAG_SHADER_SOURCE); @@ -719,27 +687,11 @@ void BootAnimation::initShaders() { GLint uvLocation = glGetAttribLocation(mImageShader, A_UV); mImageTextureLocation = glGetUniformLocation(mImageShader, U_TEXTURE); mImageFadeLocation = glGetUniformLocation(mImageShader, U_FADE); - mImageColorProgressLocation = glGetUniformLocation(mImageShader, U_COLOR_PROGRESS); glEnableVertexAttribArray(positionLocation); glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, quadPositions); glVertexAttribPointer(uvLocation, 2, GL_FLOAT, GL_FALSE, 0, quadUVs); glEnableVertexAttribArray(uvLocation); - if (mAnimation->dynamicColoringEnabled) { - glUseProgram(mImageShader); - SLOGI("[BootAnimation] Dynamically coloring boot animation."); - for (int i = 0; i < DYNAMIC_COLOR_COUNT; i++) { - float *startColor = mAnimation->startColors[i]; - float *endColor = mAnimation->endColors[i]; - glUniform4f(glGetUniformLocation(mImageShader, - (U_START_COLOR_PREFIX + std::to_string(i)).c_str()), - startColor[0], startColor[1], startColor[2], 1 /* alpha */); - glUniform4f(glGetUniformLocation(mImageShader, - (U_END_COLOR_PREFIX + std::to_string(i)).c_str()), - endColor[0], endColor[1], endColor[2], 1 /* alpha */); - } - } - // Initialize text shader. mTextShader = linkShader(vertexShader, textFragmentShader); positionLocation = glGetAttribLocation(mTextShader, A_POSITION); @@ -917,20 +869,6 @@ static bool parseColor(const char str[7], float color[3]) { return true; } -// Parse a color represented as a signed decimal int string. -// E.g. "-2757722" (whose hex 2's complement is 0xFFD5EBA6). -// If the input color string is empty, set color with values in defaultColor. -static void parseColorDecimalString(const std::string& colorString, - float color[3], float defaultColor[3]) { - if (colorString == "") { - memcpy(color, defaultColor, sizeof(float) * 3); - return; - } - int colorInt = atoi(colorString.c_str()); - color[0] = ((float)((colorInt >> 16) & 0xFF)) / 0xFF; // r - color[1] = ((float)((colorInt >> 8) & 0xFF)) / 0xFF; // g - color[2] = ((float)(colorInt & 0xFF)) / 0xFF; // b -} static bool readFile(ZipFileRO* zip, const char* name, String8& outString) { ZipEntryRO entry = zip->findEntryByName(name); @@ -1072,8 +1010,6 @@ bool BootAnimation::parseAnimationDesc(Animation& animation) { return false; } char const* s = desString.string(); - std::string dynamicColoringPartName = ""; - bool postDynamicColoring = false; // Parse the description file for (;;) { @@ -1092,13 +1028,7 @@ bool BootAnimation::parseAnimationDesc(Animation& animation) { char color[7] = "000000"; // default to black if unspecified char clockPos1[TEXT_POS_LEN_MAX + 1] = ""; char clockPos2[TEXT_POS_LEN_MAX + 1] = ""; - char dynamicColoringPartNameBuffer[ANIM_ENTRY_NAME_MAX]; char pathType; - // start colors default to black if unspecified - char start_color_0[7] = "000000"; - char start_color_1[7] = "000000"; - char start_color_2[7] = "000000"; - char start_color_3[7] = "000000"; int nextReadPos; @@ -1113,15 +1043,6 @@ bool BootAnimation::parseAnimationDesc(Animation& animation) { } else { animation.progressEnabled = false; } - } else if (sscanf(l, "dynamic_colors %" STRTO(ANIM_PATH_MAX) "s #%6s #%6s #%6s #%6s", - dynamicColoringPartNameBuffer, - start_color_0, start_color_1, start_color_2, start_color_3)) { - animation.dynamicColoringEnabled = true; - parseColor(start_color_0, animation.startColors[0]); - parseColor(start_color_1, animation.startColors[1]); - parseColor(start_color_2, animation.startColors[2]); - parseColor(start_color_3, animation.startColors[3]); - dynamicColoringPartName = std::string(dynamicColoringPartNameBuffer); } else if (sscanf(l, "%c %d %d %" STRTO(ANIM_PATH_MAX) "s%n", &pathType, &count, &pause, path, &nextReadPos) >= 4) { if (pathType == 'f') { @@ -1134,16 +1055,6 @@ bool BootAnimation::parseAnimationDesc(Animation& animation) { // "clockPos1=%s, clockPos2=%s", // pathType, count, pause, path, framesToFadeCount, color, clockPos1, clockPos2); Animation::Part part; - if (path == dynamicColoringPartName) { - // Part is specified to use dynamic coloring. - part.useDynamicColoring = true; - part.postDynamicColoring = false; - postDynamicColoring = true; - } else { - // Part does not use dynamic coloring. - part.useDynamicColoring = false; - part.postDynamicColoring = postDynamicColoring; - } part.playUntilComplete = pathType == 'c'; part.framesToFadeCount = framesToFadeCount; part.count = count; @@ -1175,12 +1086,6 @@ bool BootAnimation::parseAnimationDesc(Animation& animation) { s = ++endl; } - for (int i = 0; i < DYNAMIC_COLOR_COUNT; i++) { - parseColorDecimalString( - android::base::GetProperty("persist.bootanim.color" + std::to_string(i + 1), ""), - animation.endColors[i], animation.startColors[i]); - } - return true; } @@ -1452,14 +1357,6 @@ bool BootAnimation::playAnimation(const Animation& animation) { for (size_t j=0 ; j 0; @@ -109,10 +105,6 @@ public: ZipFileRO* zip; Font clockFont; Font progressFont; - // Controls if dynamic coloring is enabled for the whole animation. - bool dynamicColoringEnabled = false; - float startColors[4][3]; // Start colors of dynamic color transition. - float endColors[4][3]; // End colors of dynamic color transition. }; // All callbacks will be called from this class's internal thread. @@ -234,7 +226,6 @@ private: GLuint mImageTextureLocation; GLuint mTextCropAreaLocation; GLuint mTextTextureLocation; - GLuint mImageColorProgressLocation; }; // --------------------------------------------------------------------------- -- cgit v1.2.3-59-g8ed1b From 9f1123cb0d7f342f5c5e26467e9b5aff529e48a4 Mon Sep 17 00:00:00 2001 From: Shan Huang Date: Fri, 13 Aug 2021 00:36:12 +0000 Subject: Revert "Revert "Implement dynamic colors for boot animation."" This reverts commit 92aa9daa10ba767cccead3b875d1251dcf2a2a6b. Reason for revert: Working on fixing the null pointer dereference that caused the build breakage. Test: Manual Bug: 190093578 Change-Id: I30e525bcc9f70f9bcba616aa9b7ad39c5d38b46d --- cmds/bootanimation/BootAnimation.cpp | 125 ++++++++++++++++++++++++++++++----- cmds/bootanimation/BootAnimation.h | 9 +++ 2 files changed, 119 insertions(+), 15 deletions(-) (limited to 'cmds/bootanimation/BootAnimation.cpp') diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index 6e27aff5ae7b..929e63e35dcc 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -107,9 +107,13 @@ static const char PROGRESS_PROP_NAME[] = "service.bootanim.progress"; static const char DISPLAYS_PROP_NAME[] = "persist.service.bootanim.displays"; static const int ANIM_ENTRY_NAME_MAX = ANIM_PATH_MAX + 1; static constexpr size_t TEXT_POS_LEN_MAX = 16; +static const int DYNAMIC_COLOR_COUNT = 4; static const char U_TEXTURE[] = "uTexture"; static const char U_FADE[] = "uFade"; static const char U_CROP_AREA[] = "uCropArea"; +static const char U_START_COLOR_PREFIX[] = "uStartColor"; +static const char U_END_COLOR_PREFIX[] = "uEndColor"; +static const char U_COLOR_PROGRESS[] = "uColorProgress"; static const char A_UV[] = "aUv"; static const char A_POSITION[] = "aPosition"; static const char VERTEX_SHADER_SOURCE[] = R"( @@ -121,6 +125,28 @@ static const char VERTEX_SHADER_SOURCE[] = R"( gl_Position = aPosition; vUv = aUv; })"; +static const char IMAGE_FRAG_DYNAMIC_COLORING_SHADER_SOURCE[] = R"( + precision mediump float; + uniform sampler2D uTexture; + uniform float uFade; + uniform float uColorProgress; + uniform vec4 uStartColor0; + uniform vec4 uStartColor1; + uniform vec4 uStartColor2; + uniform vec4 uStartColor3; + uniform vec4 uEndColor0; + uniform vec4 uEndColor1; + uniform vec4 uEndColor2; + uniform vec4 uEndColor3; + varying highp vec2 vUv; + void main() { + vec4 mask = texture2D(uTexture, vUv); + vec4 color = mask.r * mix(uStartColor0, uEndColor0, uColorProgress) + + mask.g * mix(uStartColor1, uEndColor1, uColorProgress) + + mask.b * mix(uStartColor2, uEndColor2, uColorProgress) + + mask.a * mix(uStartColor3, uEndColor3, uColorProgress); + gl_FragColor = vec4(color.x, color.y, color.z, (1.0 - uFade)) * color.a; + })"; static const char IMAGE_FRAG_SHADER_SOURCE[] = R"( precision mediump float; uniform sampler2D uTexture; @@ -128,7 +154,7 @@ static const char IMAGE_FRAG_SHADER_SOURCE[] = R"( varying highp vec2 vUv; void main() { vec4 color = texture2D(uTexture, vUv); - gl_FragColor = vec4(color.x, color.y, color.z, 1.0 - uFade); + gl_FragColor = vec4(color.x, color.y, color.z, (1.0 - uFade)) * color.a; })"; static const char TEXT_FRAG_SHADER_SOURCE[] = R"( precision mediump float; @@ -226,6 +252,10 @@ static void* decodeImage(const void* encodedData, size_t dataLength, AndroidBitm outInfo->stride = AImageDecoder_getMinimumStride(decoder); outInfo->flags = 0; + // Set decoding option to alpha unpremultiplied so that the R, G, B channels + // of transparent pixels are preserved. + AImageDecoder_setUnpremultipliedRequired(decoder, true); + const size_t size = outInfo->stride * outInfo->height; void* pixels = malloc(size); int result = AImageDecoder_decodeImage(decoder, pixels, outInfo->stride, size); @@ -675,9 +705,12 @@ GLuint linkShader(GLuint vertexShader, GLuint fragmentShader) { } void BootAnimation::initShaders() { + bool dynamicColoringEnabled = mAnimation != nullptr && mAnimation->dynamicColoringEnabled; GLuint vertexShader = compileShader(GL_VERTEX_SHADER, (const GLchar *)VERTEX_SHADER_SOURCE); GLuint imageFragmentShader = - compileShader(GL_FRAGMENT_SHADER, (const GLchar *)IMAGE_FRAG_SHADER_SOURCE); + compileShader(GL_FRAGMENT_SHADER, dynamicColoringEnabled + ? (const GLchar *)IMAGE_FRAG_DYNAMIC_COLORING_SHADER_SOURCE + : (const GLchar *)IMAGE_FRAG_SHADER_SOURCE); GLuint textFragmentShader = compileShader(GL_FRAGMENT_SHADER, (const GLchar *)TEXT_FRAG_SHADER_SOURCE); @@ -692,6 +725,22 @@ void BootAnimation::initShaders() { glVertexAttribPointer(uvLocation, 2, GL_FLOAT, GL_FALSE, 0, quadUVs); glEnableVertexAttribArray(uvLocation); + if (dynamicColoringEnabled) { + glUseProgram(mImageShader); + SLOGI("[BootAnimation] Dynamically coloring boot animation."); + for (int i = 0; i < DYNAMIC_COLOR_COUNT; i++) { + float *startColor = mAnimation->startColors[i]; + float *endColor = mAnimation->endColors[i]; + glUniform4f(glGetUniformLocation(mImageShader, + (U_START_COLOR_PREFIX + std::to_string(i)).c_str()), + startColor[0], startColor[1], startColor[2], 1 /* alpha */); + glUniform4f(glGetUniformLocation(mImageShader, + (U_END_COLOR_PREFIX + std::to_string(i)).c_str()), + endColor[0], endColor[1], endColor[2], 1 /* alpha */); + } + mImageColorProgressLocation = glGetUniformLocation(mImageShader, U_COLOR_PROGRESS); + } + // Initialize text shader. mTextShader = linkShader(vertexShader, textFragmentShader); positionLocation = glGetAttribLocation(mTextShader, A_POSITION); @@ -869,6 +918,20 @@ static bool parseColor(const char str[7], float color[3]) { return true; } +// Parse a color represented as a signed decimal int string. +// E.g. "-2757722" (whose hex 2's complement is 0xFFD5EBA6). +// If the input color string is empty, set color with values in defaultColor. +static void parseColorDecimalString(const std::string& colorString, + float color[3], float defaultColor[3]) { + if (colorString == "") { + memcpy(color, defaultColor, sizeof(float) * 3); + return; + } + int colorInt = atoi(colorString.c_str()); + color[0] = ((float)((colorInt >> 16) & 0xFF)) / 0xFF; // r + color[1] = ((float)((colorInt >> 8) & 0xFF)) / 0xFF; // g + color[2] = ((float)(colorInt & 0xFF)) / 0xFF; // b +} static bool readFile(ZipFileRO* zip, const char* name, String8& outString) { ZipEntryRO entry = zip->findEntryByName(name); @@ -1010,6 +1073,8 @@ bool BootAnimation::parseAnimationDesc(Animation& animation) { return false; } char const* s = desString.string(); + std::string dynamicColoringPartName = ""; + bool postDynamicColoring = false; // Parse the description file for (;;) { @@ -1028,7 +1093,13 @@ bool BootAnimation::parseAnimationDesc(Animation& animation) { char color[7] = "000000"; // default to black if unspecified char clockPos1[TEXT_POS_LEN_MAX + 1] = ""; char clockPos2[TEXT_POS_LEN_MAX + 1] = ""; + char dynamicColoringPartNameBuffer[ANIM_ENTRY_NAME_MAX]; char pathType; + // start colors default to black if unspecified + char start_color_0[7] = "000000"; + char start_color_1[7] = "000000"; + char start_color_2[7] = "000000"; + char start_color_3[7] = "000000"; int nextReadPos; @@ -1043,6 +1114,15 @@ bool BootAnimation::parseAnimationDesc(Animation& animation) { } else { animation.progressEnabled = false; } + } else if (sscanf(l, "dynamic_colors %" STRTO(ANIM_PATH_MAX) "s #%6s #%6s #%6s #%6s", + dynamicColoringPartNameBuffer, + start_color_0, start_color_1, start_color_2, start_color_3)) { + animation.dynamicColoringEnabled = true; + parseColor(start_color_0, animation.startColors[0]); + parseColor(start_color_1, animation.startColors[1]); + parseColor(start_color_2, animation.startColors[2]); + parseColor(start_color_3, animation.startColors[3]); + dynamicColoringPartName = std::string(dynamicColoringPartNameBuffer); } else if (sscanf(l, "%c %d %d %" STRTO(ANIM_PATH_MAX) "s%n", &pathType, &count, &pause, path, &nextReadPos) >= 4) { if (pathType == 'f') { @@ -1055,6 +1135,16 @@ bool BootAnimation::parseAnimationDesc(Animation& animation) { // "clockPos1=%s, clockPos2=%s", // pathType, count, pause, path, framesToFadeCount, color, clockPos1, clockPos2); Animation::Part part; + if (path == dynamicColoringPartName) { + // Part is specified to use dynamic coloring. + part.useDynamicColoring = true; + part.postDynamicColoring = false; + postDynamicColoring = true; + } else { + // Part does not use dynamic coloring. + part.useDynamicColoring = false; + part.postDynamicColoring = postDynamicColoring; + } part.playUntilComplete = pathType == 'c'; part.framesToFadeCount = framesToFadeCount; part.count = count; @@ -1086,6 +1176,12 @@ bool BootAnimation::parseAnimationDesc(Animation& animation) { s = ++endl; } + for (int i = 0; i < DYNAMIC_COLOR_COUNT; i++) { + parseColorDecimalString( + android::base::GetProperty("persist.bootanim.color" + std::to_string(i + 1), ""), + animation.endColors[i], animation.startColors[i]); + } + return true; } @@ -1357,6 +1453,14 @@ bool BootAnimation::playAnimation(const Animation& animation) { for (size_t j=0 ; j 0; @@ -105,6 +109,10 @@ public: ZipFileRO* zip; Font clockFont; Font progressFont; + // Controls if dynamic coloring is enabled for the whole animation. + bool dynamicColoringEnabled = false; + float startColors[4][3]; // Start colors of dynamic color transition. + float endColors[4][3]; // End colors of dynamic color transition. }; // All callbacks will be called from this class's internal thread. @@ -226,6 +234,7 @@ private: GLuint mImageTextureLocation; GLuint mTextCropAreaLocation; GLuint mTextTextureLocation; + GLuint mImageColorProgressLocation; }; // --------------------------------------------------------------------------- -- cgit v1.2.3-59-g8ed1b From ad9cf52df959489b615f30cbf072415b3352063b Mon Sep 17 00:00:00 2001 From: Shan Huang Date: Fri, 13 Aug 2021 23:50:39 +0000 Subject: Revert "Revert "Revert "Implement dynamic colors for boot animation.""" This reverts commit 9f1123cb0d7f342f5c5e26467e9b5aff529e48a4. Reason for revert: b/196642443 ATV DOA failure. Bug: 196642443 Change-Id: Iad16e5e8f43850ffa7bf1f26701d85da96fd2cdd --- cmds/bootanimation/BootAnimation.cpp | 125 +++++------------------------------ cmds/bootanimation/BootAnimation.h | 9 --- 2 files changed, 15 insertions(+), 119 deletions(-) (limited to 'cmds/bootanimation/BootAnimation.cpp') diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index 929e63e35dcc..6e27aff5ae7b 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -107,13 +107,9 @@ static const char PROGRESS_PROP_NAME[] = "service.bootanim.progress"; static const char DISPLAYS_PROP_NAME[] = "persist.service.bootanim.displays"; static const int ANIM_ENTRY_NAME_MAX = ANIM_PATH_MAX + 1; static constexpr size_t TEXT_POS_LEN_MAX = 16; -static const int DYNAMIC_COLOR_COUNT = 4; static const char U_TEXTURE[] = "uTexture"; static const char U_FADE[] = "uFade"; static const char U_CROP_AREA[] = "uCropArea"; -static const char U_START_COLOR_PREFIX[] = "uStartColor"; -static const char U_END_COLOR_PREFIX[] = "uEndColor"; -static const char U_COLOR_PROGRESS[] = "uColorProgress"; static const char A_UV[] = "aUv"; static const char A_POSITION[] = "aPosition"; static const char VERTEX_SHADER_SOURCE[] = R"( @@ -125,28 +121,6 @@ static const char VERTEX_SHADER_SOURCE[] = R"( gl_Position = aPosition; vUv = aUv; })"; -static const char IMAGE_FRAG_DYNAMIC_COLORING_SHADER_SOURCE[] = R"( - precision mediump float; - uniform sampler2D uTexture; - uniform float uFade; - uniform float uColorProgress; - uniform vec4 uStartColor0; - uniform vec4 uStartColor1; - uniform vec4 uStartColor2; - uniform vec4 uStartColor3; - uniform vec4 uEndColor0; - uniform vec4 uEndColor1; - uniform vec4 uEndColor2; - uniform vec4 uEndColor3; - varying highp vec2 vUv; - void main() { - vec4 mask = texture2D(uTexture, vUv); - vec4 color = mask.r * mix(uStartColor0, uEndColor0, uColorProgress) - + mask.g * mix(uStartColor1, uEndColor1, uColorProgress) - + mask.b * mix(uStartColor2, uEndColor2, uColorProgress) - + mask.a * mix(uStartColor3, uEndColor3, uColorProgress); - gl_FragColor = vec4(color.x, color.y, color.z, (1.0 - uFade)) * color.a; - })"; static const char IMAGE_FRAG_SHADER_SOURCE[] = R"( precision mediump float; uniform sampler2D uTexture; @@ -154,7 +128,7 @@ static const char IMAGE_FRAG_SHADER_SOURCE[] = R"( varying highp vec2 vUv; void main() { vec4 color = texture2D(uTexture, vUv); - gl_FragColor = vec4(color.x, color.y, color.z, (1.0 - uFade)) * color.a; + gl_FragColor = vec4(color.x, color.y, color.z, 1.0 - uFade); })"; static const char TEXT_FRAG_SHADER_SOURCE[] = R"( precision mediump float; @@ -252,10 +226,6 @@ static void* decodeImage(const void* encodedData, size_t dataLength, AndroidBitm outInfo->stride = AImageDecoder_getMinimumStride(decoder); outInfo->flags = 0; - // Set decoding option to alpha unpremultiplied so that the R, G, B channels - // of transparent pixels are preserved. - AImageDecoder_setUnpremultipliedRequired(decoder, true); - const size_t size = outInfo->stride * outInfo->height; void* pixels = malloc(size); int result = AImageDecoder_decodeImage(decoder, pixels, outInfo->stride, size); @@ -705,12 +675,9 @@ GLuint linkShader(GLuint vertexShader, GLuint fragmentShader) { } void BootAnimation::initShaders() { - bool dynamicColoringEnabled = mAnimation != nullptr && mAnimation->dynamicColoringEnabled; GLuint vertexShader = compileShader(GL_VERTEX_SHADER, (const GLchar *)VERTEX_SHADER_SOURCE); GLuint imageFragmentShader = - compileShader(GL_FRAGMENT_SHADER, dynamicColoringEnabled - ? (const GLchar *)IMAGE_FRAG_DYNAMIC_COLORING_SHADER_SOURCE - : (const GLchar *)IMAGE_FRAG_SHADER_SOURCE); + compileShader(GL_FRAGMENT_SHADER, (const GLchar *)IMAGE_FRAG_SHADER_SOURCE); GLuint textFragmentShader = compileShader(GL_FRAGMENT_SHADER, (const GLchar *)TEXT_FRAG_SHADER_SOURCE); @@ -725,22 +692,6 @@ void BootAnimation::initShaders() { glVertexAttribPointer(uvLocation, 2, GL_FLOAT, GL_FALSE, 0, quadUVs); glEnableVertexAttribArray(uvLocation); - if (dynamicColoringEnabled) { - glUseProgram(mImageShader); - SLOGI("[BootAnimation] Dynamically coloring boot animation."); - for (int i = 0; i < DYNAMIC_COLOR_COUNT; i++) { - float *startColor = mAnimation->startColors[i]; - float *endColor = mAnimation->endColors[i]; - glUniform4f(glGetUniformLocation(mImageShader, - (U_START_COLOR_PREFIX + std::to_string(i)).c_str()), - startColor[0], startColor[1], startColor[2], 1 /* alpha */); - glUniform4f(glGetUniformLocation(mImageShader, - (U_END_COLOR_PREFIX + std::to_string(i)).c_str()), - endColor[0], endColor[1], endColor[2], 1 /* alpha */); - } - mImageColorProgressLocation = glGetUniformLocation(mImageShader, U_COLOR_PROGRESS); - } - // Initialize text shader. mTextShader = linkShader(vertexShader, textFragmentShader); positionLocation = glGetAttribLocation(mTextShader, A_POSITION); @@ -918,20 +869,6 @@ static bool parseColor(const char str[7], float color[3]) { return true; } -// Parse a color represented as a signed decimal int string. -// E.g. "-2757722" (whose hex 2's complement is 0xFFD5EBA6). -// If the input color string is empty, set color with values in defaultColor. -static void parseColorDecimalString(const std::string& colorString, - float color[3], float defaultColor[3]) { - if (colorString == "") { - memcpy(color, defaultColor, sizeof(float) * 3); - return; - } - int colorInt = atoi(colorString.c_str()); - color[0] = ((float)((colorInt >> 16) & 0xFF)) / 0xFF; // r - color[1] = ((float)((colorInt >> 8) & 0xFF)) / 0xFF; // g - color[2] = ((float)(colorInt & 0xFF)) / 0xFF; // b -} static bool readFile(ZipFileRO* zip, const char* name, String8& outString) { ZipEntryRO entry = zip->findEntryByName(name); @@ -1073,8 +1010,6 @@ bool BootAnimation::parseAnimationDesc(Animation& animation) { return false; } char const* s = desString.string(); - std::string dynamicColoringPartName = ""; - bool postDynamicColoring = false; // Parse the description file for (;;) { @@ -1093,13 +1028,7 @@ bool BootAnimation::parseAnimationDesc(Animation& animation) { char color[7] = "000000"; // default to black if unspecified char clockPos1[TEXT_POS_LEN_MAX + 1] = ""; char clockPos2[TEXT_POS_LEN_MAX + 1] = ""; - char dynamicColoringPartNameBuffer[ANIM_ENTRY_NAME_MAX]; char pathType; - // start colors default to black if unspecified - char start_color_0[7] = "000000"; - char start_color_1[7] = "000000"; - char start_color_2[7] = "000000"; - char start_color_3[7] = "000000"; int nextReadPos; @@ -1114,15 +1043,6 @@ bool BootAnimation::parseAnimationDesc(Animation& animation) { } else { animation.progressEnabled = false; } - } else if (sscanf(l, "dynamic_colors %" STRTO(ANIM_PATH_MAX) "s #%6s #%6s #%6s #%6s", - dynamicColoringPartNameBuffer, - start_color_0, start_color_1, start_color_2, start_color_3)) { - animation.dynamicColoringEnabled = true; - parseColor(start_color_0, animation.startColors[0]); - parseColor(start_color_1, animation.startColors[1]); - parseColor(start_color_2, animation.startColors[2]); - parseColor(start_color_3, animation.startColors[3]); - dynamicColoringPartName = std::string(dynamicColoringPartNameBuffer); } else if (sscanf(l, "%c %d %d %" STRTO(ANIM_PATH_MAX) "s%n", &pathType, &count, &pause, path, &nextReadPos) >= 4) { if (pathType == 'f') { @@ -1135,16 +1055,6 @@ bool BootAnimation::parseAnimationDesc(Animation& animation) { // "clockPos1=%s, clockPos2=%s", // pathType, count, pause, path, framesToFadeCount, color, clockPos1, clockPos2); Animation::Part part; - if (path == dynamicColoringPartName) { - // Part is specified to use dynamic coloring. - part.useDynamicColoring = true; - part.postDynamicColoring = false; - postDynamicColoring = true; - } else { - // Part does not use dynamic coloring. - part.useDynamicColoring = false; - part.postDynamicColoring = postDynamicColoring; - } part.playUntilComplete = pathType == 'c'; part.framesToFadeCount = framesToFadeCount; part.count = count; @@ -1176,12 +1086,6 @@ bool BootAnimation::parseAnimationDesc(Animation& animation) { s = ++endl; } - for (int i = 0; i < DYNAMIC_COLOR_COUNT; i++) { - parseColorDecimalString( - android::base::GetProperty("persist.bootanim.color" + std::to_string(i + 1), ""), - animation.endColors[i], animation.startColors[i]); - } - return true; } @@ -1453,14 +1357,6 @@ bool BootAnimation::playAnimation(const Animation& animation) { for (size_t j=0 ; j 0; @@ -109,10 +105,6 @@ public: ZipFileRO* zip; Font clockFont; Font progressFont; - // Controls if dynamic coloring is enabled for the whole animation. - bool dynamicColoringEnabled = false; - float startColors[4][3]; // Start colors of dynamic color transition. - float endColors[4][3]; // End colors of dynamic color transition. }; // All callbacks will be called from this class's internal thread. @@ -234,7 +226,6 @@ private: GLuint mImageTextureLocation; GLuint mTextCropAreaLocation; GLuint mTextTextureLocation; - GLuint mImageColorProgressLocation; }; // --------------------------------------------------------------------------- -- cgit v1.2.3-59-g8ed1b From 2b31a36bea3466d4898a7f4384db4b95b65c9d85 Mon Sep 17 00:00:00 2001 From: Shan Huang Date: Mon, 16 Aug 2021 16:45:39 +0000 Subject: Revert "Revert "Revert "Revert "Implement dynamic colors for boot animation."""" This reverts commit ad9cf52df959489b615f30cbf072415b3352063b. Reason for revert: Fixing broken atv test Test: atv atp test tv/platform/simple_boot_test Change-Id: I9d6ecb6024ce49eef8007458b0d9bf0ff24906c7 --- cmds/bootanimation/BootAnimation.cpp | 143 ++++++++++++++++++++++++++++++----- cmds/bootanimation/BootAnimation.h | 19 ++++- 2 files changed, 137 insertions(+), 25 deletions(-) (limited to 'cmds/bootanimation/BootAnimation.cpp') diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index b225d5710b1e..13bbe556b8ee 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -107,9 +107,13 @@ static const char PROGRESS_PROP_NAME[] = "service.bootanim.progress"; static const char DISPLAYS_PROP_NAME[] = "persist.service.bootanim.displays"; static const int ANIM_ENTRY_NAME_MAX = ANIM_PATH_MAX + 1; static constexpr size_t TEXT_POS_LEN_MAX = 16; +static const int DYNAMIC_COLOR_COUNT = 4; static const char U_TEXTURE[] = "uTexture"; static const char U_FADE[] = "uFade"; static const char U_CROP_AREA[] = "uCropArea"; +static const char U_START_COLOR_PREFIX[] = "uStartColor"; +static const char U_END_COLOR_PREFIX[] = "uEndColor"; +static const char U_COLOR_PROGRESS[] = "uColorProgress"; static const char A_UV[] = "aUv"; static const char A_POSITION[] = "aPosition"; static const char VERTEX_SHADER_SOURCE[] = R"( @@ -121,6 +125,28 @@ static const char VERTEX_SHADER_SOURCE[] = R"( gl_Position = aPosition; vUv = aUv; })"; +static const char IMAGE_FRAG_DYNAMIC_COLORING_SHADER_SOURCE[] = R"( + precision mediump float; + uniform sampler2D uTexture; + uniform float uFade; + uniform float uColorProgress; + uniform vec4 uStartColor0; + uniform vec4 uStartColor1; + uniform vec4 uStartColor2; + uniform vec4 uStartColor3; + uniform vec4 uEndColor0; + uniform vec4 uEndColor1; + uniform vec4 uEndColor2; + uniform vec4 uEndColor3; + varying highp vec2 vUv; + void main() { + vec4 mask = texture2D(uTexture, vUv); + vec4 color = mask.r * mix(uStartColor0, uEndColor0, uColorProgress) + + mask.g * mix(uStartColor1, uEndColor1, uColorProgress) + + mask.b * mix(uStartColor2, uEndColor2, uColorProgress) + + mask.a * mix(uStartColor3, uEndColor3, uColorProgress); + gl_FragColor = vec4(color.x, color.y, color.z, (1.0 - uFade)) * color.a; + })"; static const char IMAGE_FRAG_SHADER_SOURCE[] = R"( precision mediump float; uniform sampler2D uTexture; @@ -128,7 +154,7 @@ static const char IMAGE_FRAG_SHADER_SOURCE[] = R"( varying highp vec2 vUv; void main() { vec4 color = texture2D(uTexture, vUv); - gl_FragColor = vec4(color.x, color.y, color.z, 1.0 - uFade); + gl_FragColor = vec4(color.x, color.y, color.z, (1.0 - uFade)) * color.a; })"; static const char TEXT_FRAG_SHADER_SOURCE[] = R"( precision mediump float; @@ -212,7 +238,8 @@ void BootAnimation::binderDied(const wp&) { requestExit(); } -static void* decodeImage(const void* encodedData, size_t dataLength, AndroidBitmapInfo* outInfo) { +static void* decodeImage(const void* encodedData, size_t dataLength, AndroidBitmapInfo* outInfo, + bool premultiplyAlpha) { AImageDecoder* decoder = nullptr; AImageDecoder_createFromBuffer(encodedData, dataLength, &decoder); if (!decoder) { @@ -226,6 +253,10 @@ static void* decodeImage(const void* encodedData, size_t dataLength, AndroidBitm outInfo->stride = AImageDecoder_getMinimumStride(decoder); outInfo->flags = 0; + if (!premultiplyAlpha) { + AImageDecoder_setUnpremultipliedRequired(decoder, true); + } + const size_t size = outInfo->stride * outInfo->height; void* pixels = malloc(size); int result = AImageDecoder_decodeImage(decoder, pixels, outInfo->stride, size); @@ -239,13 +270,14 @@ static void* decodeImage(const void* encodedData, size_t dataLength, AndroidBitm } status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets, - const char* name) { + const char* name, bool premultiplyAlpha) { Asset* asset = assets.open(name, Asset::ACCESS_BUFFER); if (asset == nullptr) return NO_INIT; AndroidBitmapInfo bitmapInfo; - void* pixels = decodeImage(asset->getBuffer(false), asset->getLength(), &bitmapInfo); + void* pixels = decodeImage(asset->getBuffer(false), asset->getLength(), &bitmapInfo, + premultiplyAlpha); auto pixelDeleter = std::unique_ptr{ pixels, free }; asset->close(); @@ -293,9 +325,11 @@ status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets, return NO_ERROR; } -status_t BootAnimation::initTexture(FileMap* map, int* width, int* height) { +status_t BootAnimation::initTexture(FileMap* map, int* width, int* height, + bool premultiplyAlpha) { AndroidBitmapInfo bitmapInfo; - void* pixels = decodeImage(map->getDataPtr(), map->getDataLength(), &bitmapInfo); + void* pixels = decodeImage(map->getDataPtr(), map->getDataLength(), &bitmapInfo, + premultiplyAlpha); auto pixelDeleter = std::unique_ptr{ pixels, free }; // FileMap memory is never released until application exit. @@ -674,9 +708,12 @@ GLuint linkShader(GLuint vertexShader, GLuint fragmentShader) { } void BootAnimation::initShaders() { + bool dynamicColoringEnabled = mAnimation != nullptr && mAnimation->dynamicColoringEnabled; GLuint vertexShader = compileShader(GL_VERTEX_SHADER, (const GLchar *)VERTEX_SHADER_SOURCE); GLuint imageFragmentShader = - compileShader(GL_FRAGMENT_SHADER, (const GLchar *)IMAGE_FRAG_SHADER_SOURCE); + compileShader(GL_FRAGMENT_SHADER, dynamicColoringEnabled + ? (const GLchar *)IMAGE_FRAG_DYNAMIC_COLORING_SHADER_SOURCE + : (const GLchar *)IMAGE_FRAG_SHADER_SOURCE); GLuint textFragmentShader = compileShader(GL_FRAGMENT_SHADER, (const GLchar *)TEXT_FRAG_SHADER_SOURCE); @@ -691,6 +728,22 @@ void BootAnimation::initShaders() { glVertexAttribPointer(uvLocation, 2, GL_FLOAT, GL_FALSE, 0, quadUVs); glEnableVertexAttribArray(uvLocation); + if (dynamicColoringEnabled) { + glUseProgram(mImageShader); + SLOGI("[BootAnimation] Dynamically coloring boot animation."); + for (int i = 0; i < DYNAMIC_COLOR_COUNT; i++) { + float *startColor = mAnimation->startColors[i]; + float *endColor = mAnimation->endColors[i]; + glUniform4f(glGetUniformLocation(mImageShader, + (U_START_COLOR_PREFIX + std::to_string(i)).c_str()), + startColor[0], startColor[1], startColor[2], 1 /* alpha */); + glUniform4f(glGetUniformLocation(mImageShader, + (U_END_COLOR_PREFIX + std::to_string(i)).c_str()), + endColor[0], endColor[1], endColor[2], 1 /* alpha */); + } + mImageColorProgressLocation = glGetUniformLocation(mImageShader, U_COLOR_PROGRESS); + } + // Initialize text shader. mTextShader = linkShader(vertexShader, textFragmentShader); positionLocation = glGetAttribLocation(mTextShader, A_POSITION); @@ -868,6 +921,20 @@ static bool parseColor(const char str[7], float color[3]) { return true; } +// Parse a color represented as a signed decimal int string. +// E.g. "-2757722" (whose hex 2's complement is 0xFFD5EBA6). +// If the input color string is empty, set color with values in defaultColor. +static void parseColorDecimalString(const std::string& colorString, + float color[3], float defaultColor[3]) { + if (colorString == "") { + memcpy(color, defaultColor, sizeof(float) * 3); + return; + } + int colorInt = atoi(colorString.c_str()); + color[0] = ((float)((colorInt >> 16) & 0xFF)) / 0xFF; // r + color[1] = ((float)((colorInt >> 8) & 0xFF)) / 0xFF; // g + color[2] = ((float)(colorInt & 0xFF)) / 0xFF; // b +} static bool readFile(ZipFileRO* zip, const char* name, String8& outString) { ZipEntryRO entry = zip->findEntryByName(name); @@ -1009,6 +1076,8 @@ bool BootAnimation::parseAnimationDesc(Animation& animation) { return false; } char const* s = desString.string(); + std::string dynamicColoringPartName = ""; + bool postDynamicColoring = false; // Parse the description file for (;;) { @@ -1027,7 +1096,13 @@ bool BootAnimation::parseAnimationDesc(Animation& animation) { char color[7] = "000000"; // default to black if unspecified char clockPos1[TEXT_POS_LEN_MAX + 1] = ""; char clockPos2[TEXT_POS_LEN_MAX + 1] = ""; + char dynamicColoringPartNameBuffer[ANIM_ENTRY_NAME_MAX]; char pathType; + // start colors default to black if unspecified + char start_color_0[7] = "000000"; + char start_color_1[7] = "000000"; + char start_color_2[7] = "000000"; + char start_color_3[7] = "000000"; int nextReadPos; @@ -1042,6 +1117,15 @@ bool BootAnimation::parseAnimationDesc(Animation& animation) { } else { animation.progressEnabled = false; } + } else if (sscanf(l, "dynamic_colors %" STRTO(ANIM_PATH_MAX) "s #%6s #%6s #%6s #%6s", + dynamicColoringPartNameBuffer, + start_color_0, start_color_1, start_color_2, start_color_3)) { + animation.dynamicColoringEnabled = true; + parseColor(start_color_0, animation.startColors[0]); + parseColor(start_color_1, animation.startColors[1]); + parseColor(start_color_2, animation.startColors[2]); + parseColor(start_color_3, animation.startColors[3]); + dynamicColoringPartName = std::string(dynamicColoringPartNameBuffer); } else if (sscanf(l, "%c %d %d %" STRTO(ANIM_PATH_MAX) "s%n", &pathType, &count, &pause, path, &nextReadPos) >= 4) { if (pathType == 'f') { @@ -1054,6 +1138,16 @@ bool BootAnimation::parseAnimationDesc(Animation& animation) { // "clockPos1=%s, clockPos2=%s", // pathType, count, pause, path, framesToFadeCount, color, clockPos1, clockPos2); Animation::Part part; + if (path == dynamicColoringPartName) { + // Part is specified to use dynamic coloring. + part.useDynamicColoring = true; + part.postDynamicColoring = false; + postDynamicColoring = true; + } else { + // Part does not use dynamic coloring. + part.useDynamicColoring = false; + part.postDynamicColoring = postDynamicColoring; + } part.playUntilComplete = pathType == 'c'; part.framesToFadeCount = framesToFadeCount; part.count = count; @@ -1085,6 +1179,12 @@ bool BootAnimation::parseAnimationDesc(Animation& animation) { s = ++endl; } + for (int i = 0; i < DYNAMIC_COLOR_COUNT; i++) { + parseColorDecimalString( + android::base::GetProperty("persist.bootanim.color" + std::to_string(i + 1), ""), + animation.endColors[i], animation.startColors[i]); + } + return true; } @@ -1356,6 +1456,14 @@ bool BootAnimation::playAnimation(const Animation& animation) { for (size_t j=0 ; j 0; @@ -105,6 +109,10 @@ public: ZipFileRO* zip; Font clockFont; Font progressFont; + // Controls if dynamic coloring is enabled for the whole animation. + bool dynamicColoringEnabled = false; + float startColors[4][3]; // Start colors of dynamic color transition. + float endColors[4][3]; // End colors of dynamic color transition. }; // All callbacks will be called from this class's internal thread. @@ -163,8 +171,10 @@ private: int displayEventCallback(int fd, int events, void* data); void processDisplayEvents(); - status_t initTexture(Texture* texture, AssetManager& asset, const char* name); - status_t initTexture(FileMap* map, int* width, int* height); + status_t initTexture(Texture* texture, AssetManager& asset, const char* name, + bool premultiplyAlpha = true); + status_t initTexture(FileMap* map, int* width, int* height, + bool premultiplyAlpha = true); status_t initFont(Font* font, const char* fallback); void initShaders(); bool android(); @@ -226,6 +236,7 @@ private: GLuint mImageTextureLocation; GLuint mTextCropAreaLocation; GLuint mTextTextureLocation; + GLuint mImageColorProgressLocation; }; // --------------------------------------------------------------------------- -- cgit v1.2.3-59-g8ed1b From 7fee35220794edd1b0700c25002df6e6719400bb Mon Sep 17 00:00:00 2001 From: Shan Huang Date: Wed, 18 Aug 2021 00:56:08 +0000 Subject: Move boot color sysprop parsing to after loading zips. Otherwise the sysprops would not be loaded yet and accessing them would return empty strings. Though unlikely, this is not 100% safe because boot color sysprops are not guaranteed to be loaded by the time zips are loaded. A TODO here is to understand boot steps and their timing implications so that we can fully avoid the race condition. Bug: 190093578 Test: adb shell setprop persist.bootanim.color(1-4), then reboot phone. Change-Id: I603da080b1732a436a10dbaca6f2be9f158124dc --- cmds/bootanimation/BootAnimation.cpp | 47 +++++++++++++++++++----------------- cmds/bootanimation/BootAnimation.h | 1 + 2 files changed, 26 insertions(+), 22 deletions(-) (limited to 'cmds/bootanimation/BootAnimation.cpp') diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index 13bbe556b8ee..7c81f0942f78 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -728,22 +728,6 @@ void BootAnimation::initShaders() { glVertexAttribPointer(uvLocation, 2, GL_FLOAT, GL_FALSE, 0, quadUVs); glEnableVertexAttribArray(uvLocation); - if (dynamicColoringEnabled) { - glUseProgram(mImageShader); - SLOGI("[BootAnimation] Dynamically coloring boot animation."); - for (int i = 0; i < DYNAMIC_COLOR_COUNT; i++) { - float *startColor = mAnimation->startColors[i]; - float *endColor = mAnimation->endColors[i]; - glUniform4f(glGetUniformLocation(mImageShader, - (U_START_COLOR_PREFIX + std::to_string(i)).c_str()), - startColor[0], startColor[1], startColor[2], 1 /* alpha */); - glUniform4f(glGetUniformLocation(mImageShader, - (U_END_COLOR_PREFIX + std::to_string(i)).c_str()), - endColor[0], endColor[1], endColor[2], 1 /* alpha */); - } - mImageColorProgressLocation = glGetUniformLocation(mImageShader, U_COLOR_PROGRESS); - } - // Initialize text shader. mTextShader = linkShader(vertexShader, textFragmentShader); positionLocation = glGetAttribLocation(mTextShader, A_POSITION); @@ -1179,12 +1163,6 @@ bool BootAnimation::parseAnimationDesc(Animation& animation) { s = ++endl; } - for (int i = 0; i < DYNAMIC_COLOR_COUNT; i++) { - parseColorDecimalString( - android::base::GetProperty("persist.bootanim.color" + std::to_string(i + 1), ""), - animation.endColors[i], animation.startColors[i]); - } - return true; } @@ -1361,6 +1339,10 @@ bool BootAnimation::movie() { mTimeCheckThread->run("BootAnimation::TimeCheckThread", PRIORITY_NORMAL); } + if (mAnimation != nullptr && mAnimation->dynamicColoringEnabled) { + initDynamicColors(); + } + playAnimation(*mAnimation); if (mTimeCheckThread != nullptr) { @@ -1414,6 +1396,27 @@ void BootAnimation::drawTexturedQuad(float xStart, float yStart, float width, fl sizeof(quadPositions) / sizeof(quadPositions[0]) / 2); } +void BootAnimation::initDynamicColors() { + for (int i = 0; i < DYNAMIC_COLOR_COUNT; i++) { + parseColorDecimalString( + android::base::GetProperty("persist.bootanim.color" + std::to_string(i + 1), ""), + mAnimation->endColors[i], mAnimation->startColors[i]); + } + glUseProgram(mImageShader); + SLOGI("[BootAnimation] Dynamically coloring boot animation."); + for (int i = 0; i < DYNAMIC_COLOR_COUNT; i++) { + float *startColor = mAnimation->startColors[i]; + float *endColor = mAnimation->endColors[i]; + glUniform4f(glGetUniformLocation(mImageShader, + (U_START_COLOR_PREFIX + std::to_string(i)).c_str()), + startColor[0], startColor[1], startColor[2], 1 /* alpha */); + glUniform4f(glGetUniformLocation(mImageShader, + (U_END_COLOR_PREFIX + std::to_string(i)).c_str()), + endColor[0], endColor[1], endColor[2], 1 /* alpha */); + } + mImageColorProgressLocation = glGetUniformLocation(mImageShader, U_COLOR_PROGRESS); +} + bool BootAnimation::playAnimation(const Animation& animation) { const size_t pcount = animation.parts.size(); nsecs_t frameDuration = s2ns(1) / animation.fps; diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h index 8bb3256543f4..0e29621f0326 100644 --- a/cmds/bootanimation/BootAnimation.h +++ b/cmds/bootanimation/BootAnimation.h @@ -204,6 +204,7 @@ private: void checkExit(); void handleViewport(nsecs_t timestep); + void initDynamicColors(); sp mSession; AssetManager mAssets; -- cgit v1.2.3-59-g8ed1b From 0f8e8110b10bc287d54fd608cae65a0b62eb8346 Mon Sep 17 00:00:00 2001 From: George Burgess IV Date: Mon, 23 Aug 2021 17:32:23 -0700 Subject: BootAnimation: remove superfluous null check for `mAnimation` The null check added in I603da080b1732a436a10dbaca6f2be9f158124dc makes our static analyzer suspect that the call to `playAnimation(*mAnimation)` dereferences null. The beginning of this function establishes a non-null value for `mAnimation`, which is used unconditionally throughout the function. Hence, this condition seems unnecessary. Bug: None Test: TreeHugger Change-Id: I0575df17df7f7e3018d99cafd9dcfcd3c10e5fbc --- cmds/bootanimation/BootAnimation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'cmds/bootanimation/BootAnimation.cpp') diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index 7c81f0942f78..90a5d49bf56b 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -1339,7 +1339,7 @@ bool BootAnimation::movie() { mTimeCheckThread->run("BootAnimation::TimeCheckThread", PRIORITY_NORMAL); } - if (mAnimation != nullptr && mAnimation->dynamicColoringEnabled) { + if (mAnimation->dynamicColoringEnabled) { initDynamicColors(); } -- cgit v1.2.3-59-g8ed1b From 08de4439ac20552c97d14171c20e82f43a5329ef Mon Sep 17 00:00:00 2001 From: ThiƩbaud Weksteen Date: Thu, 18 Nov 2021 13:25:59 +1100 Subject: Enable clock only when supported by product In 9748086, a detection for clock drifting was implemented. It relies on 2 files that must be provided by the product (/data/system/time/last_time_change and /data/system/time/time_is_accurate). Generally, these files are not available which triggers an SELinux denial error message. Introduce a new property ("persist.sys.bootanim.clock.enabled") which can be set by a product to enable this feature (default is false). For future reference, it is not sufficient to only enable this property, the product must also provide the files described above (see BootAnimation::updateIsTimeAccurate). Bug: 62954877 Test: lunch r11-userdebug && m Change-Id: Ia27e69547e3d898925029dc0c2be4ad717891c57 --- cmds/bootanimation/BootAnimation.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'cmds/bootanimation/BootAnimation.cpp') diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index 59f602c11247..a1569ce569d6 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -105,6 +105,7 @@ static const int TEXT_MISSING_VALUE = INT_MIN; static const char EXIT_PROP_NAME[] = "service.bootanim.exit"; static const char PROGRESS_PROP_NAME[] = "service.bootanim.progress"; static const char DISPLAYS_PROP_NAME[] = "persist.service.bootanim.displays"; +static const char CLOCK_ENABLED_PROP_NAME[] = "persist.sys.bootanim.clock.enabled"; static const int ANIM_ENTRY_NAME_MAX = ANIM_PATH_MAX + 1; static constexpr size_t TEXT_POS_LEN_MAX = 16; static const int DYNAMIC_COLOR_COUNT = 4; @@ -1320,6 +1321,8 @@ bool BootAnimation::movie() { } if (!anyPartHasClock) { mClockEnabled = false; + } else if (!android::base::GetBoolProperty(CLOCK_ENABLED_PROP_NAME, false)) { + mClockEnabled = false; } // Check if npot textures are supported -- cgit v1.2.3-59-g8ed1b From f95b2007a3fb27fb7e42728e6822f78b8ae9bf7f Mon Sep 17 00:00:00 2001 From: Josh Yang Date: Thu, 23 Dec 2021 14:32:28 -0800 Subject: Change the bootanim time file location. This change moves the bootanim time file location from /data/system/time to /data/bootanim/time. This change helps us remove the access to system_data_file from bootanim. Bug: 210757252 Test: Boot animation can show time. No SELinux violations. Change-Id: Ie61155f8976f3b8c6ad5ceac1826140c1455ad54 --- cmds/bootanimation/BootAnimation.cpp | 28 ++++++++++++++-------------- cmds/bootanimation/BootAnimation.h | 2 +- 2 files changed, 15 insertions(+), 15 deletions(-) (limited to 'cmds/bootanimation/BootAnimation.cpp') diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index 05a0661914dc..1f4a64f5c7f1 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -81,18 +81,18 @@ static constexpr const char* PRODUCT_USERSPACE_REBOOT_ANIMATION_FILE = "/product static constexpr const char* OEM_USERSPACE_REBOOT_ANIMATION_FILE = "/oem/media/userspace-reboot.zip"; static constexpr const char* SYSTEM_USERSPACE_REBOOT_ANIMATION_FILE = "/system/media/userspace-reboot.zip"; -static const char SYSTEM_DATA_DIR_PATH[] = "/data/system"; -static const char SYSTEM_TIME_DIR_NAME[] = "time"; -static const char SYSTEM_TIME_DIR_PATH[] = "/data/system/time"; +static const char BOOTANIM_DATA_DIR_PATH[] = "/data/bootanim"; +static const char BOOTANIM_TIME_DIR_NAME[] = "time"; +static const char BOOTANIM_TIME_DIR_PATH[] = "/data/bootanim/time"; static const char CLOCK_FONT_ASSET[] = "images/clock_font.png"; static const char CLOCK_FONT_ZIP_NAME[] = "clock_font.png"; static const char PROGRESS_FONT_ASSET[] = "images/progress_font.png"; static const char PROGRESS_FONT_ZIP_NAME[] = "progress_font.png"; static const char LAST_TIME_CHANGED_FILE_NAME[] = "last_time_change"; -static const char LAST_TIME_CHANGED_FILE_PATH[] = "/data/system/time/last_time_change"; +static const char LAST_TIME_CHANGED_FILE_PATH[] = "/data/bootanim/time/last_time_change"; static const char ACCURATE_TIME_FLAG_FILE_NAME[] = "time_is_accurate"; -static const char ACCURATE_TIME_FLAG_FILE_PATH[] = "/data/system/time/time_is_accurate"; -static const char TIME_FORMAT_12_HOUR_FLAG_FILE_PATH[] = "/data/system/time/time_format_12_hour"; +static const char ACCURATE_TIME_FLAG_FILE_PATH[] = "/data/bootanim/time/time_is_accurate"; +static const char TIME_FORMAT_12_HOUR_FLAG_FILE_PATH[] = "/data/bootanim/time/time_format_12_hour"; // Java timestamp format. Don't show the clock if the date is before 2000-01-01 00:00:00. static const long long ACCURATE_TIME_EPOCH = 946684800000; static constexpr char FONT_BEGIN_CHAR = ' '; @@ -1741,7 +1741,7 @@ bool BootAnimation::updateIsTimeAccurate() { } BootAnimation::TimeCheckThread::TimeCheckThread(BootAnimation* bootAnimation) : Thread(false), - mInotifyFd(-1), mSystemWd(-1), mTimeWd(-1), mBootAnimation(bootAnimation) {} + mInotifyFd(-1), mBootAnimWd(-1), mTimeWd(-1), mBootAnimation(bootAnimation) {} BootAnimation::TimeCheckThread::~TimeCheckThread() { // mInotifyFd may be -1 but that's ok since we're not at risk of attempting to close a valid FD. @@ -1784,7 +1784,7 @@ bool BootAnimation::TimeCheckThread::doThreadLoop() { const struct inotify_event *event; for (char* ptr = buff; ptr < buff + length; ptr += sizeof(struct inotify_event) + event->len) { event = (const struct inotify_event *) ptr; - if (event->wd == mSystemWd && strcmp(SYSTEM_TIME_DIR_NAME, event->name) == 0) { + if (event->wd == mBootAnimWd && strcmp(BOOTANIM_TIME_DIR_NAME, event->name) == 0) { addTimeDirWatch(); } else if (event->wd == mTimeWd && (strcmp(LAST_TIME_CHANGED_FILE_NAME, event->name) == 0 || strcmp(ACCURATE_TIME_FLAG_FILE_NAME, event->name) == 0)) { @@ -1796,12 +1796,12 @@ bool BootAnimation::TimeCheckThread::doThreadLoop() { } void BootAnimation::TimeCheckThread::addTimeDirWatch() { - mTimeWd = inotify_add_watch(mInotifyFd, SYSTEM_TIME_DIR_PATH, + mTimeWd = inotify_add_watch(mInotifyFd, BOOTANIM_TIME_DIR_PATH, IN_CLOSE_WRITE | IN_MOVED_TO | IN_ATTRIB); if (mTimeWd > 0) { // No need to watch for the time directory to be created if it already exists - inotify_rm_watch(mInotifyFd, mSystemWd); - mSystemWd = -1; + inotify_rm_watch(mInotifyFd, mBootAnimWd); + mBootAnimWd = -1; } } @@ -1812,11 +1812,11 @@ status_t BootAnimation::TimeCheckThread::readyToRun() { return NO_INIT; } - mSystemWd = inotify_add_watch(mInotifyFd, SYSTEM_DATA_DIR_PATH, IN_CREATE | IN_ATTRIB); - if (mSystemWd < 0) { + mBootAnimWd = inotify_add_watch(mInotifyFd, BOOTANIM_DATA_DIR_PATH, IN_CREATE | IN_ATTRIB); + if (mBootAnimWd < 0) { close(mInotifyFd); mInotifyFd = -1; - SLOGE("Could not add watch for %s: %s", SYSTEM_DATA_DIR_PATH, strerror(errno)); + SLOGE("Could not add watch for %s: %s", BOOTANIM_DATA_DIR_PATH, strerror(errno)); return NO_INIT; } diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h index 7a597da533ee..4c378cbc48bd 100644 --- a/cmds/bootanimation/BootAnimation.h +++ b/cmds/bootanimation/BootAnimation.h @@ -161,7 +161,7 @@ private: void addTimeDirWatch(); int mInotifyFd; - int mSystemWd; + int mBootAnimWd; int mTimeWd; BootAnimation* mBootAnimation; }; -- cgit v1.2.3-59-g8ed1b From cd25684a0cdd0f44312013527171002e0f104f7c Mon Sep 17 00:00:00 2001 From: Lucas Dupin Date: Tue, 29 Mar 2022 15:46:36 -0700 Subject: Reload color sysprops after failing During OTA, sysprops aren't load as fast as during regular boot. This causes the animation to not be able to pick up the dynamic colors. We can mitigate this issue by trying to reload the sysprops at the beginning of each animation part. Test: manual Bug: 227381265 Change-Id: I4397079aacc52acb5cda54a925f70e4f5c745b3f --- cmds/bootanimation/BootAnimation.cpp | 16 +++++++++++++--- cmds/bootanimation/BootAnimation.h | 1 + 2 files changed, 14 insertions(+), 3 deletions(-) (limited to 'cmds/bootanimation/BootAnimation.cpp') diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index f9317eba4e27..968be3e20791 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -1425,12 +1425,17 @@ void BootAnimation::drawTexturedQuad(float xStart, float yStart, float width, fl void BootAnimation::initDynamicColors() { for (int i = 0; i < DYNAMIC_COLOR_COUNT; i++) { - parseColorDecimalString( - android::base::GetProperty("persist.bootanim.color" + std::to_string(i + 1), ""), + const auto syspropName = "persist.bootanim.color" + std::to_string(i + 1); + const auto syspropValue = android::base::GetProperty(syspropName, ""); + if (syspropValue != "") { + SLOGI("Loaded dynamic color: %s -> %s", syspropName.c_str(), syspropValue.c_str()); + mDynamicColorsApplied = true; + } + parseColorDecimalString(syspropValue, mAnimation->endColors[i], mAnimation->startColors[i]); } glUseProgram(mImageShader); - SLOGI("[BootAnimation] Dynamically coloring boot animation."); + SLOGI("Dynamically coloring boot animation. Sysprops loaded? %i", mDynamicColorsApplied); for (int i = 0; i < DYNAMIC_COLOR_COUNT; i++) { float *startColor = mAnimation->startColors[i]; float *endColor = mAnimation->endColors[i]; @@ -1465,6 +1470,11 @@ bool BootAnimation::playAnimation(const Animation& animation) { continue; //to next part } + if (animation.dynamicColoringEnabled && part.useDynamicColoring && !mDynamicColorsApplied) { + SLOGD("Trying to load dynamic color sysprops."); + initDynamicColors(); + } + // process the part not only while the count allows but also if already fading for (int r=0 ; !part.count || r 0 ; r++) { if (shouldStopPlayingPart(part, fadedFramesCount, lastDisplayedProgress)) break; diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h index 4c378cbc48bd..a136ad0a90f2 100644 --- a/cmds/bootanimation/BootAnimation.h +++ b/cmds/bootanimation/BootAnimation.h @@ -228,6 +228,7 @@ private: bool mTimeIsAccurate; bool mTimeFormat12Hour; bool mShuttingDown; + bool mDynamicColorsApplied = false; String8 mZipFileName; SortedVector mLoadedFiles; sp mTimeCheckThread = nullptr; -- cgit v1.2.3-59-g8ed1b From 85b339fb246768d8ec34375463e4bfe8b968eaaf Mon Sep 17 00:00:00 2001 From: joenchen Date: Mon, 11 Apr 2022 23:58:34 +0800 Subject: bootanimation: correct logo position and size after resolution changed The resolution may be changed while the boot animation is playing. mInitWidth and mInitHeight store the original resolution, and then the animation coordinate and size are recalculated according to the ratio (mWidth/mInitWidth and mHeight/mInitHeight). Bug: 228605923 Test: change resolution and then reboot to check the animation Change-Id: Id09490ecf7fc4b3e1a6baf073c134f357e9b327f (cherry picked from commit 764ea0442141b4b961bb6c6af18e66cfaa617b7f) Merged-In: Id09490ecf7fc4b3e1a6baf073c134f357e9b327f --- cmds/bootanimation/BootAnimation.cpp | 23 +++++++++++++++-------- cmds/bootanimation/BootAnimation.h | 2 ++ 2 files changed, 17 insertions(+), 8 deletions(-) (limited to 'cmds/bootanimation/BootAnimation.cpp') diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index 968be3e20791..fb68c6d84d6a 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -577,8 +577,8 @@ status_t BootAnimation::readyToRun() { mDisplay = display; mContext = context; mSurface = surface; - mWidth = w; - mHeight = h; + mInitWidth = mWidth = w; + mInitHeight = mHeight = h; mFlingerSurfaceControl = control; mFlingerSurface = s; mTargetInset = -1; @@ -611,6 +611,7 @@ void BootAnimation::resizeSurface(int newWidth, int newHeight) { eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); eglDestroySurface(mDisplay, mSurface); + mFlingerSurfaceControl->updateDefaultBufferSize(newWidth, newHeight); const auto limitedSize = limitSurfaceSize(newWidth, newHeight); mWidth = limitedSize.width; mHeight = limitedSize.height; @@ -1515,8 +1516,10 @@ bool BootAnimation::playAnimation(const Animation& animation) { processDisplayEvents(); - const int animationX = (mWidth - animation.width) / 2; - const int animationY = (mHeight - animation.height) / 2; + const double ratio_w = static_cast(mWidth) / mInitWidth; + const double ratio_h = static_cast(mHeight) / mInitHeight; + const int animationX = (mWidth - animation.width * ratio_w) / 2; + const int animationY = (mHeight - animation.height * ratio_h) / 2; const Animation::Frame& frame(part.frames[j]); nsecs_t lastFrame = systemTime(); @@ -1532,12 +1535,16 @@ bool BootAnimation::playAnimation(const Animation& animation) { initTexture(frame.map, &w, &h, false /* don't premultiply alpha */); } - const int xc = animationX + frame.trimX; - const int yc = animationY + frame.trimY; + const int trimWidth = frame.trimWidth * ratio_w; + const int trimHeight = frame.trimHeight * ratio_h; + const int trimX = frame.trimX * ratio_w; + const int trimY = frame.trimY * ratio_h; + const int xc = animationX + trimX; + const int yc = animationY + trimY; glClear(GL_COLOR_BUFFER_BIT); // specify the y center as ceiling((mHeight - frame.trimHeight) / 2) // which is equivalent to mHeight - (yc + frame.trimHeight) - const int frameDrawY = mHeight - (yc + frame.trimHeight); + const int frameDrawY = mHeight - (yc + trimHeight); float fade = 0; // if the part hasn't been stopped yet then continue fading if necessary @@ -1554,7 +1561,7 @@ bool BootAnimation::playAnimation(const Animation& animation) { glUniform1f(mImageColorProgressLocation, colorProgress); } glEnable(GL_BLEND); - drawTexturedQuad(xc, frameDrawY, frame.trimWidth, frame.trimHeight); + drawTexturedQuad(xc, frameDrawY, trimWidth, trimHeight); glDisable(GL_BLEND); if (mClockEnabled && mTimeIsAccurate && validClock(part)) { diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h index a136ad0a90f2..86582053b4e1 100644 --- a/cmds/bootanimation/BootAnimation.h +++ b/cmds/bootanimation/BootAnimation.h @@ -213,6 +213,8 @@ private: Texture mAndroid[2]; int mWidth; int mHeight; + int mInitWidth; + int mInitHeight; int mMaxWidth = 0; int mMaxHeight = 0; int mCurrentInset; -- cgit v1.2.3-59-g8ed1b From bfd1812fcbcada2dfb1bc9846c0b131658ec2b85 Mon Sep 17 00:00:00 2001 From: Lucas Dupin Date: Mon, 25 Apr 2022 11:26:08 -0700 Subject: Try to load colors more frequently During OTA, sysprops aren't available as early in the boot process. This causes the boot animation to not have dynamic colors. This CL tries to load the colors more frequently, at every part loop. Before we'd only try on the first frame of each animation part. Test: adb shell bootanimation Fixes: 229029861 Change-Id: I1bbebf93b4fbc31d945c4181472576cf29f13bc7 --- cmds/bootanimation/BootAnimation.cpp | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) (limited to 'cmds/bootanimation/BootAnimation.cpp') diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index fb68c6d84d6a..50c8e933d25f 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -1459,6 +1459,8 @@ bool BootAnimation::playAnimation(const Animation& animation) { int fadedFramesCount = 0; int lastDisplayedProgress = 0; + int colorTransitionStart = animation.colorTransitionStart; + int colorTransitionEnd = animation.colorTransitionEnd; for (size_t i=0 ; i 0 ; r++) { if (shouldStopPlayingPart(part, fadedFramesCount, lastDisplayedProgress)) break; + // It's possible that the sysprops were not loaded yet at this boot phase. + // If that's the case, then we should keep trying until they are available. + if (animation.dynamicColoringEnabled && !mDynamicColorsApplied + && (part.useDynamicColoring || part.postDynamicColoring)) { + SLOGD("Trying to load dynamic color sysprops."); + initDynamicColors(); + if (mDynamicColorsApplied) { + // Sysprops were loaded. Next step is to adjust the animation if we loaded + // the colors after the animation should have started. + const int transitionLength = colorTransitionEnd - colorTransitionStart; + if (part.postDynamicColoring) { + colorTransitionStart = 0; + colorTransitionEnd = fmin(transitionLength, fcount - 1); + } + } + } + mCallbacks->playPart(i, part, r); glClearColor( @@ -1509,9 +1523,8 @@ bool BootAnimation::playAnimation(const Animation& animation) { // - 1 for parts that come after. float colorProgress = part.useDynamicColoring ? fmin(fmax( - ((float)j - animation.colorTransitionStart) / - fmax(animation.colorTransitionEnd - - animation.colorTransitionStart, 1.0f), 0.0f), 1.0f) + ((float)j - colorTransitionStart) / + fmax(colorTransitionEnd - colorTransitionStart, 1.0f), 0.0f), 1.0f) : (part.postDynamicColoring ? 1 : 0); processDisplayEvents(); -- cgit v1.2.3-59-g8ed1b