BootAnimation.cpp revision 317a6280cc109e873646e4652be1582d870eedfd
1/* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <stdint.h> 18#include <sys/types.h> 19#include <math.h> 20#include <fcntl.h> 21#include <utils/misc.h> 22 23#include <binder/IPCThreadState.h> 24#include <utils/threads.h> 25#include <utils/Atomic.h> 26#include <utils/Errors.h> 27#include <utils/Log.h> 28#include <utils/AssetManager.h> 29 30#include <ui/PixelFormat.h> 31#include <ui/Rect.h> 32#include <ui/Region.h> 33#include <ui/DisplayInfo.h> 34#include <ui/ISurfaceComposer.h> 35#include <ui/ISurfaceFlingerClient.h> 36#include <ui/FramebufferNativeWindow.h> 37#include <ui/EGLUtils.h> 38 39#include <core/SkBitmap.h> 40#include <images/SkImageDecoder.h> 41 42#include <GLES/gl.h> 43#include <GLES/glext.h> 44#include <EGL/eglext.h> 45 46#include "BootAnimation.h" 47 48namespace android { 49 50// --------------------------------------------------------------------------- 51 52BootAnimation::BootAnimation() : Thread(false) 53{ 54 mSession = new SurfaceComposerClient(); 55} 56 57BootAnimation::~BootAnimation() { 58} 59 60void BootAnimation::onFirstRef() { 61 run("BootAnimation", PRIORITY_DISPLAY); 62} 63 64const sp<SurfaceComposerClient>& BootAnimation::session() const { 65 return mSession; 66} 67 68status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets, 69 const char* name) { 70 Asset* asset = assets.open(name, Asset::ACCESS_BUFFER); 71 if (!asset) 72 return NO_INIT; 73 SkBitmap bitmap; 74 SkImageDecoder::DecodeMemory(asset->getBuffer(false), asset->getLength(), 75 &bitmap, SkBitmap::kNo_Config, SkImageDecoder::kDecodePixels_Mode); 76 asset->close(); 77 delete asset; 78 79 // ensure we can call getPixels(). No need to call unlock, since the 80 // bitmap will go out of scope when we return from this method. 81 bitmap.lockPixels(); 82 83 const int w = bitmap.width(); 84 const int h = bitmap.height(); 85 const void* p = bitmap.getPixels(); 86 87 GLint crop[4] = { 0, h, w, -h }; 88 texture->w = w; 89 texture->h = h; 90 91 glGenTextures(1, &texture->name); 92 glBindTexture(GL_TEXTURE_2D, texture->name); 93 94 switch (bitmap.getConfig()) { 95 case SkBitmap::kA8_Config: 96 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_ALPHA, 97 GL_UNSIGNED_BYTE, p); 98 break; 99 case SkBitmap::kARGB_4444_Config: 100 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, 101 GL_UNSIGNED_SHORT_4_4_4_4, p); 102 break; 103 case SkBitmap::kARGB_8888_Config: 104 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, 105 GL_UNSIGNED_BYTE, p); 106 break; 107 case SkBitmap::kRGB_565_Config: 108 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, 109 GL_UNSIGNED_SHORT_5_6_5, p); 110 break; 111 default: 112 break; 113 } 114 115 glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop); 116 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 117 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 118 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 119 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 120 return NO_ERROR; 121} 122 123status_t BootAnimation::readyToRun() { 124 mAssets.addDefaultAssets(); 125 126 DisplayInfo dinfo; 127 status_t status = session()->getDisplayInfo(0, &dinfo); 128 if (status) 129 return -1; 130 131 // create the native surface 132 sp<SurfaceControl> control = session()->createSurface( 133 getpid(), 0, dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565); 134 session()->openTransaction(); 135 control->setLayer(0x40000000); 136 session()->closeTransaction(); 137 138 sp<Surface> s = control->getSurface(); 139 140 // initialize opengl and egl 141 const EGLint attribs[] = { 142 EGL_DEPTH_SIZE, 0, 143 EGL_NONE 144 }; 145 EGLint w, h, dummy; 146 EGLint numConfigs; 147 EGLConfig config; 148 EGLSurface surface; 149 EGLContext context; 150 151 EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); 152 153 eglInitialize(display, 0, 0); 154 EGLUtils::selectConfigForNativeWindow(display, attribs, s.get(), &config); 155 surface = eglCreateWindowSurface(display, config, s.get(), NULL); 156 context = eglCreateContext(display, config, NULL, NULL); 157 eglQuerySurface(display, surface, EGL_WIDTH, &w); 158 eglQuerySurface(display, surface, EGL_HEIGHT, &h); 159 160 if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) 161 return NO_INIT; 162 163 mDisplay = display; 164 mContext = context; 165 mSurface = surface; 166 mWidth = w; 167 mHeight = h; 168 mFlingerSurfaceControl = control; 169 mFlingerSurface = s; 170 171 // initialize GL 172 glShadeModel(GL_FLAT); 173 glEnable(GL_TEXTURE_2D); 174 glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 175 176 return NO_ERROR; 177} 178 179bool BootAnimation::threadLoop() { 180 bool r = android(); 181 eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 182 eglDestroyContext(mDisplay, mContext); 183 eglDestroySurface(mDisplay, mSurface); 184 mFlingerSurface.clear(); 185 mFlingerSurfaceControl.clear(); 186 eglTerminate(mDisplay); 187 IPCThreadState::self()->stopProcess(); 188 return r; 189} 190 191bool BootAnimation::android() { 192 initTexture(&mAndroid[0], mAssets, "images/android-logo-mask.png"); 193 initTexture(&mAndroid[1], mAssets, "images/android-logo-shine.png"); 194 195 // clear screen 196 glDisable(GL_DITHER); 197 glDisable(GL_SCISSOR_TEST); 198 glClear(GL_COLOR_BUFFER_BIT); 199 eglSwapBuffers(mDisplay, mSurface); 200 201 const GLint xc = (mWidth - mAndroid[0].w) / 2; 202 const GLint yc = (mHeight - mAndroid[0].h) / 2; 203 const Rect updateRect(xc, yc, xc + mAndroid[0].w, yc + mAndroid[0].h); 204 205 // draw and update only what we need 206 mFlingerSurface->setSwapRectangle(updateRect); 207 208 glScissor(updateRect.left, mHeight - updateRect.bottom, updateRect.width(), 209 updateRect.height()); 210 211 // Blend state 212 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 213 glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 214 215 const nsecs_t startTime = systemTime(); 216 do { 217 nsecs_t now = systemTime(); 218 double time = now - startTime; 219 float t = 4.0f * float(time / us2ns(16667)) / mAndroid[1].w; 220 GLint offset = (1 - (t - floorf(t))) * mAndroid[1].w; 221 GLint x = xc - offset; 222 223 glDisable(GL_SCISSOR_TEST); 224 glClear(GL_COLOR_BUFFER_BIT); 225 226 glEnable(GL_SCISSOR_TEST); 227 glDisable(GL_BLEND); 228 glBindTexture(GL_TEXTURE_2D, mAndroid[1].name); 229 glDrawTexiOES(x, yc, 0, mAndroid[1].w, mAndroid[1].h); 230 glDrawTexiOES(x + mAndroid[1].w, yc, 0, mAndroid[1].w, mAndroid[1].h); 231 232 glEnable(GL_BLEND); 233 glBindTexture(GL_TEXTURE_2D, mAndroid[0].name); 234 glDrawTexiOES(xc, yc, 0, mAndroid[0].w, mAndroid[0].h); 235 236 EGLBoolean res = eglSwapBuffers(mDisplay, mSurface); 237 if (res == EGL_FALSE) 238 break; 239 240 // 12fps: don't animate too fast to preserve CPU 241 const nsecs_t sleepTime = 83333 - ns2us(systemTime() - now); 242 if (sleepTime > 0) 243 usleep(sleepTime); 244 } while (!exitPending()); 245 246 glDeleteTextures(1, &mAndroid[0].name); 247 glDeleteTextures(1, &mAndroid[1].name); 248 return false; 249} 250 251// --------------------------------------------------------------------------- 252 253} 254; // namespace android 255