Merge "Revert "Revert "Migrate boot animation from GLES 1.0 to GLES2.0.""" into sc-qpr1-dev am: 185741e47d am: 3fc58c5c78
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15585669 Change-Id: I75740f11796dec0ed0dd9fd3e1d547cf431b557c
This commit is contained in:
@@ -71,7 +71,7 @@ cc_library_shared {
|
|||||||
"libui",
|
"libui",
|
||||||
"libjnigraphics",
|
"libjnigraphics",
|
||||||
"libEGL",
|
"libEGL",
|
||||||
"libGLESv1_CM",
|
"libGLESv2",
|
||||||
"libgui",
|
"libgui",
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,9 +52,8 @@
|
|||||||
#include <gui/DisplayEventReceiver.h>
|
#include <gui/DisplayEventReceiver.h>
|
||||||
#include <gui/Surface.h>
|
#include <gui/Surface.h>
|
||||||
#include <gui/SurfaceComposerClient.h>
|
#include <gui/SurfaceComposerClient.h>
|
||||||
|
#include <GLES2/gl2.h>
|
||||||
#include <GLES/gl.h>
|
#include <GLES2/gl2ext.h>
|
||||||
#include <GLES/glext.h>
|
|
||||||
#include <EGL/eglext.h>
|
#include <EGL/eglext.h>
|
||||||
|
|
||||||
#include "BootAnimation.h"
|
#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 char DISPLAYS_PROP_NAME[] = "persist.service.bootanim.displays";
|
||||||
static const int ANIM_ENTRY_NAME_MAX = ANIM_PATH_MAX + 1;
|
static const int ANIM_ENTRY_NAME_MAX = ANIM_PATH_MAX + 1;
|
||||||
static constexpr size_t TEXT_POS_LEN_MAX = 16;
|
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 w = bitmapInfo.width;
|
||||||
const int h = bitmapInfo.height;
|
const int h = bitmapInfo.height;
|
||||||
|
|
||||||
GLint crop[4] = { 0, h, w, -h };
|
|
||||||
texture->w = w;
|
texture->w = w;
|
||||||
texture->h = h;
|
texture->h = h;
|
||||||
|
|
||||||
@@ -237,11 +285,10 @@ status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
|
||||||
|
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
@@ -263,7 +310,6 @@ status_t BootAnimation::initTexture(FileMap* map, int* width, int* height) {
|
|||||||
const int w = bitmapInfo.width;
|
const int w = bitmapInfo.width;
|
||||||
const int h = bitmapInfo.height;
|
const int h = bitmapInfo.height;
|
||||||
|
|
||||||
GLint crop[4] = { 0, h, w, -h };
|
|
||||||
int tw = 1 << (31 - __builtin_clz(w));
|
int tw = 1 << (31 - __builtin_clz(w));
|
||||||
int th = 1 << (31 - __builtin_clz(h));
|
int th = 1 << (31 - __builtin_clz(h));
|
||||||
if (tw < w) tw <<= 1;
|
if (tw < w) tw <<= 1;
|
||||||
@@ -297,7 +343,10 @@ status_t BootAnimation::initTexture(FileMap* map, int* width, int* height) {
|
|||||||
break;
|
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;
|
*width = w;
|
||||||
*height = h;
|
*height = h;
|
||||||
@@ -470,7 +519,9 @@ status_t BootAnimation::readyToRun() {
|
|||||||
eglInitialize(display, nullptr, nullptr);
|
eglInitialize(display, nullptr, nullptr);
|
||||||
EGLConfig config = getEglConfig(display);
|
EGLConfig config = getEglConfig(display);
|
||||||
EGLSurface surface = eglCreateWindowSurface(display, config, s.get(), nullptr);
|
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;
|
EGLint w, h;
|
||||||
eglQuerySurface(display, surface, EGL_WIDTH, &w);
|
eglQuerySurface(display, surface, EGL_WIDTH, &w);
|
||||||
eglQuerySurface(display, surface, EGL_HEIGHT, &h);
|
eglQuerySurface(display, surface, EGL_HEIGHT, &h);
|
||||||
@@ -503,11 +554,6 @@ status_t BootAnimation::readyToRun() {
|
|||||||
void BootAnimation::projectSceneToWindow() {
|
void BootAnimation::projectSceneToWindow() {
|
||||||
glViewport(0, 0, mWidth, mHeight);
|
glViewport(0, 0, mWidth, mHeight);
|
||||||
glScissor(0, 0, mWidth, mHeight);
|
glScissor(0, 0, mWidth, mHeight);
|
||||||
glMatrixMode(GL_PROJECTION);
|
|
||||||
glLoadIdentity();
|
|
||||||
glOrthof(0, static_cast<float>(mWidth), 0, static_cast<float>(mHeight), -1, 1);
|
|
||||||
glMatrixMode(GL_MODELVIEW);
|
|
||||||
glLoadIdentity();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BootAnimation::resizeSurface(int newWidth, int newHeight) {
|
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 BootAnimation::threadLoop() {
|
||||||
bool result;
|
bool result;
|
||||||
|
initShaders();
|
||||||
|
|
||||||
// We have no bootanimation file, so we use the stock android logo
|
// We have no bootanimation file, so we use the stock android logo
|
||||||
// animation.
|
// animation.
|
||||||
if (mZipFileName.isEmpty()) {
|
if (mZipFileName.isEmpty()) {
|
||||||
@@ -623,6 +729,8 @@ bool BootAnimation::threadLoop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool BootAnimation::android() {
|
bool BootAnimation::android() {
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
|
||||||
SLOGD("%sAnimationShownTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot",
|
SLOGD("%sAnimationShownTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot",
|
||||||
elapsedRealtime());
|
elapsedRealtime());
|
||||||
initTexture(&mAndroid[0], mAssets, "images/android-logo-mask.png");
|
initTexture(&mAndroid[0], mAssets, "images/android-logo-mask.png");
|
||||||
@@ -631,19 +739,14 @@ bool BootAnimation::android() {
|
|||||||
mCallbacks->init({});
|
mCallbacks->init({});
|
||||||
|
|
||||||
// clear screen
|
// clear screen
|
||||||
glShadeModel(GL_FLAT);
|
|
||||||
glDisable(GL_DITHER);
|
glDisable(GL_DITHER);
|
||||||
glDisable(GL_SCISSOR_TEST);
|
glDisable(GL_SCISSOR_TEST);
|
||||||
glClearColor(0,0,0,1);
|
glClearColor(0,0,0,1);
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
eglSwapBuffers(mDisplay, mSurface);
|
eglSwapBuffers(mDisplay, mSurface);
|
||||||
|
|
||||||
glEnable(GL_TEXTURE_2D);
|
|
||||||
glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
|
||||||
|
|
||||||
// Blend state
|
// Blend state
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
|
||||||
|
|
||||||
const nsecs_t startTime = systemTime();
|
const nsecs_t startTime = systemTime();
|
||||||
do {
|
do {
|
||||||
@@ -666,12 +769,12 @@ bool BootAnimation::android() {
|
|||||||
glEnable(GL_SCISSOR_TEST);
|
glEnable(GL_SCISSOR_TEST);
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
glBindTexture(GL_TEXTURE_2D, mAndroid[1].name);
|
glBindTexture(GL_TEXTURE_2D, mAndroid[1].name);
|
||||||
glDrawTexiOES(x, yc, 0, mAndroid[1].w, mAndroid[1].h);
|
drawTexturedQuad(x, yc, mAndroid[1].w, mAndroid[1].h);
|
||||||
glDrawTexiOES(x + mAndroid[1].w, yc, 0, mAndroid[1].w, mAndroid[1].h);
|
drawTexturedQuad(x + mAndroid[1].w, yc, mAndroid[1].w, mAndroid[1].h);
|
||||||
|
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBindTexture(GL_TEXTURE_2D, mAndroid[0].name);
|
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);
|
EGLBoolean res = eglSwapBuffers(mDisplay, mSurface);
|
||||||
if (res == EGL_FALSE)
|
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);
|
status = initTexture(font->map, &font->texture.w, &font->texture.h);
|
||||||
|
|
||||||
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
} else if (fallback != nullptr) {
|
} else if (fallback != nullptr) {
|
||||||
status = initTexture(&font->texture, mAssets, fallback);
|
status = initTexture(&font->texture, mAssets, fallback);
|
||||||
} else {
|
} else {
|
||||||
@@ -816,40 +919,11 @@ status_t BootAnimation::initFont(Font* font, const char* fallback) {
|
|||||||
return status;
|
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<float>(fadedFramesCount) / part.framesToFadeCount;
|
|
||||||
glColor4f(part.backgroundColor[0], part.backgroundColor[1], part.backgroundColor[2], alpha);
|
|
||||||
|
|
||||||
const float frameStartX = static_cast<float>(frameLeft);
|
|
||||||
const float frameStartY = static_cast<float>(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) {
|
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
|
glEnable(GL_BLEND); // Allow us to draw on top of the animation
|
||||||
glBindTexture(GL_TEXTURE_2D, font.texture.name);
|
glBindTexture(GL_TEXTURE_2D, font.texture.name);
|
||||||
|
glUseProgram(mTextShader);
|
||||||
|
glUniform1i(mTextTextureLocation, 0);
|
||||||
|
|
||||||
const int len = strlen(str);
|
const int len = strlen(str);
|
||||||
const int strWidth = font.char_width * len;
|
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;
|
*y = mHeight + *y - font.char_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cropRect[4] = { 0, 0, font.char_width, -font.char_height };
|
|
||||||
|
|
||||||
for (int i = 0; i < len; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
char c = str[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 charPos = (c - FONT_BEGIN_CHAR); // Position in the list of valid characters
|
||||||
const int row = charPos / FONT_NUM_COLS;
|
const int row = charPos / FONT_NUM_COLS;
|
||||||
const int col = charPos % FONT_NUM_COLS;
|
const int col = charPos % FONT_NUM_COLS;
|
||||||
cropRect[0] = col * font.char_width; // Left of column
|
// Bold fonts are expected in the second half of each row.
|
||||||
cropRect[1] = row * font.char_height * 2; // Top of row
|
float v0 = (row + (bold ? 0.5f : 0.0f)) / FONT_NUM_ROWS;
|
||||||
// Move down to bottom of regular (one char_heigh) or bold (two char_heigh) line
|
float u0 = ((float)col) / FONT_NUM_COLS;
|
||||||
cropRect[1] += bold ? 2 * font.char_height : font.char_height;
|
float v1 = v0 + 1.0f / FONT_NUM_ROWS / 2;
|
||||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, cropRect);
|
float u1 = u0 + 1.0f / FONT_NUM_COLS;
|
||||||
|
glUniform4f(mTextCropAreaLocation, u0, v0, u1, v1);
|
||||||
glDrawTexiOES(*x, *y, 0, font.char_width, font.char_height);
|
drawTexturedQuad(*x, *y, font.char_width, font.char_height);
|
||||||
|
|
||||||
*x += font.char_width;
|
*x += font.char_width;
|
||||||
}
|
}
|
||||||
@@ -1166,19 +1238,16 @@ bool BootAnimation::movie() {
|
|||||||
|
|
||||||
// Blend required to draw time on top of animation frames.
|
// Blend required to draw time on top of animation frames.
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
glShadeModel(GL_FLAT);
|
|
||||||
glDisable(GL_DITHER);
|
glDisable(GL_DITHER);
|
||||||
glDisable(GL_SCISSOR_TEST);
|
glDisable(GL_SCISSOR_TEST);
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
|
||||||
glEnable(GL_TEXTURE_2D);
|
glEnable(GL_TEXTURE_2D);
|
||||||
glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
bool clockFontInitialized = false;
|
bool clockFontInitialized = false;
|
||||||
if (mClockEnabled) {
|
if (mClockEnabled) {
|
||||||
clockFontInitialized =
|
clockFontInitialized =
|
||||||
@@ -1218,6 +1287,34 @@ bool BootAnimation::shouldStopPlayingPart(const Animation::Part& part,
|
|||||||
(lastDisplayedProgress == 0 || lastDisplayedProgress == 100);
|
(lastDisplayedProgress == 0 || lastDisplayedProgress == 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Linear mapping from range <a1, a2> to range <b1, b2>
|
||||||
|
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) {
|
bool BootAnimation::playAnimation(const Animation& animation) {
|
||||||
const size_t pcount = animation.parts.size();
|
const size_t pcount = animation.parts.size();
|
||||||
nsecs_t frameDuration = s2ns(1) / animation.fps;
|
nsecs_t frameDuration = s2ns(1) / animation.fps;
|
||||||
@@ -1230,7 +1327,6 @@ bool BootAnimation::playAnimation(const Animation& animation) {
|
|||||||
for (size_t i=0 ; i<pcount ; i++) {
|
for (size_t i=0 ; i<pcount ; i++) {
|
||||||
const Animation::Part& part(animation.parts[i]);
|
const Animation::Part& part(animation.parts[i]);
|
||||||
const size_t fcount = part.frames.size();
|
const size_t fcount = part.frames.size();
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
|
||||||
|
|
||||||
// Handle animation package
|
// Handle animation package
|
||||||
if (part.animation != nullptr) {
|
if (part.animation != nullptr) {
|
||||||
@@ -1272,12 +1368,8 @@ bool BootAnimation::playAnimation(const Animation& animation) {
|
|||||||
if (r > 0) {
|
if (r > 0) {
|
||||||
glBindTexture(GL_TEXTURE_2D, frame.tid);
|
glBindTexture(GL_TEXTURE_2D, frame.tid);
|
||||||
} else {
|
} else {
|
||||||
if (part.count != 1) {
|
|
||||||
glGenTextures(1, &frame.tid);
|
glGenTextures(1, &frame.tid);
|
||||||
glBindTexture(GL_TEXTURE_2D, 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;
|
int w, h;
|
||||||
initTexture(frame.map, &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)
|
// specify the y center as ceiling((mHeight - frame.trimHeight) / 2)
|
||||||
// which is equivalent to mHeight - (yc + frame.trimHeight)
|
// which is equivalent to mHeight - (yc + frame.trimHeight)
|
||||||
const int frameDrawY = 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 the part hasn't been stopped yet then continue fading if necessary
|
||||||
if (exitPending() && part.hasFadingPhase()) {
|
if (exitPending() && part.hasFadingPhase()) {
|
||||||
fadeFrame(xc, frameDrawY, frame.trimWidth, frame.trimHeight, part,
|
fade = static_cast<float>(++fadedFramesCount) / part.framesToFadeCount;
|
||||||
++fadedFramesCount);
|
|
||||||
if (fadedFramesCount >= part.framesToFadeCount) {
|
if (fadedFramesCount >= part.framesToFadeCount) {
|
||||||
fadedFramesCount = MAX_FADED_FRAMES_COUNT; // no more fading
|
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)) {
|
if (mClockEnabled && mTimeIsAccurate && validClock(part)) {
|
||||||
drawClock(animation.clockFont, part.clockPosX, part.clockPosY);
|
drawClock(animation.clockFont, part.clockPosX, part.clockPosY);
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
#include <binder/IBinder.h>
|
#include <binder/IBinder.h>
|
||||||
|
|
||||||
#include <EGL/egl.h>
|
#include <EGL/egl.h>
|
||||||
#include <GLES/gl.h>
|
#include <GLES2/gl2.h>
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
@@ -166,6 +166,7 @@ private:
|
|||||||
status_t initTexture(Texture* texture, AssetManager& asset, const char* name);
|
status_t initTexture(Texture* texture, AssetManager& asset, const char* name);
|
||||||
status_t initTexture(FileMap* map, int* width, int* height);
|
status_t initTexture(FileMap* map, int* width, int* height);
|
||||||
status_t initFont(Font* font, const char* fallback);
|
status_t initFont(Font* font, const char* fallback);
|
||||||
|
void initShaders();
|
||||||
bool android();
|
bool android();
|
||||||
bool movie();
|
bool movie();
|
||||||
void drawText(const char* str, const Font& font, bool bold, int* x, int* y);
|
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 drawProgress(int percent, const Font& font, const int xPos, const int yPos);
|
||||||
void fadeFrame(int frameLeft, int frameBottom, int frameWidth, int frameHeight,
|
void fadeFrame(int frameLeft, int frameBottom, int frameWidth, int frameHeight,
|
||||||
const Animation::Part& part, int fadedFramesCount);
|
const Animation::Part& part, int fadedFramesCount);
|
||||||
|
void drawTexturedQuad(float xStart, float yStart, float width, float height);
|
||||||
bool validClock(const Animation::Part& part);
|
bool validClock(const Animation::Part& part);
|
||||||
Animation* loadAnimation(const String8&);
|
Animation* loadAnimation(const String8&);
|
||||||
bool playAnimation(const Animation&);
|
bool playAnimation(const Animation&);
|
||||||
@@ -218,6 +220,12 @@ private:
|
|||||||
sp<TimeCheckThread> mTimeCheckThread = nullptr;
|
sp<TimeCheckThread> mTimeCheckThread = nullptr;
|
||||||
sp<Callbacks> mCallbacks;
|
sp<Callbacks> mCallbacks;
|
||||||
Animation* mAnimation = nullptr;
|
Animation* mAnimation = nullptr;
|
||||||
|
GLuint mImageShader;
|
||||||
|
GLuint mTextShader;
|
||||||
|
GLuint mImageFadeLocation;
|
||||||
|
GLuint mImageTextureLocation;
|
||||||
|
GLuint mTextCropAreaLocation;
|
||||||
|
GLuint mTextTextureLocation;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user