blob: d18f59abac52dc61527380a5f3db41cf1f26390b [file] [log] [blame]
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001/*
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#define LOG_TAG "BootAnimation"
18
19#include <stdint.h>
20#include <sys/types.h>
21#include <math.h>
22#include <fcntl.h>
23#include <utils/misc.h>
24
25#include <utils/threads.h>
26#include <utils/Atomic.h>
27#include <utils/Errors.h>
28#include <utils/Log.h>
29#include <utils/AssetManager.h>
30
31#include <ui/PixelFormat.h>
32#include <ui/Rect.h>
33#include <ui/Region.h>
34#include <ui/DisplayInfo.h>
35#include <ui/ISurfaceComposer.h>
36#include <ui/ISurfaceFlingerClient.h>
37#include <ui/EGLNativeWindowSurface.h>
38
The Android Open Source Project27629322009-01-09 17:51:23 -080039#include <core/SkBitmap.h>
40#include <images/SkImageDecoder.h>
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070041
42#include <GLES/egl.h>
43
44#include "BootAnimation.h"
45
46namespace android {
47
48// ---------------------------------------------------------------------------
49
50BootAnimation::BootAnimation(const sp<ISurfaceComposer>& composer)
51: Thread(false)
52{
53 mSession = SurfaceComposerClient::clientForConnection(
54 composer->createConnection()->asBinder());
55}
56
57BootAnimation::~BootAnimation()
58{
59}
60
61void BootAnimation::onFirstRef()
62{
63 run("BootAnimation", PRIORITY_DISPLAY);
64}
65
66const sp<SurfaceComposerClient>& BootAnimation::session() const
67{
68 return mSession;
69}
70
71status_t BootAnimation::initTexture(
72 Texture* texture, AssetManager& assets, const char* name)
73{
74 Asset* asset = assets.open(name, Asset::ACCESS_BUFFER);
75 if (!asset) return NO_INIT;
76 SkBitmap bitmap;
77 SkImageDecoder::DecodeMemory(asset->getBuffer(false), asset->getLength(),
78 &bitmap, SkBitmap::kNo_Config, SkImageDecoder::kDecodePixels_Mode);
79 asset->close();
80 delete asset;
81
82 // ensure we can call getPixels(). No need to call unlock, since the
83 // bitmap will go out of scope when we return from this method.
84 bitmap.lockPixels();
85
86 const int w = bitmap.width();
87 const int h = bitmap.height();
88 const void* p = bitmap.getPixels();
89
90 GLint crop[4] = { 0, h, w, -h };
91 texture->w = w;
92 texture->h = h;
93
94 glGenTextures(1, &texture->name);
95 glBindTexture(GL_TEXTURE_2D, texture->name);
96
97 switch(bitmap.getConfig()) {
98 case SkBitmap::kA8_Config:
99 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0,
100 GL_ALPHA, GL_UNSIGNED_BYTE, p);
101 break;
102 case SkBitmap::kARGB_4444_Config:
103 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0,
104 GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, p);
105 break;
106 case SkBitmap::kARGB_8888_Config:
107 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0,
108 GL_RGBA, GL_UNSIGNED_BYTE, p);
109 break;
110 case SkBitmap::kRGB_565_Config:
111 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0,
112 GL_RGB, GL_UNSIGNED_SHORT_5_6_5, p);
113 break;
114 default:
115 break;
116 }
117
118 glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop);
119 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
120 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
121 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
122 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
123 return NO_ERROR;
124}
125
126status_t BootAnimation::readyToRun()
127{
128 mAssets.addDefaultAssets();
129
130 DisplayInfo dinfo;
131 status_t status = session()->getDisplayInfo(0, &dinfo);
132 if (status)
133 return -1;
134
135 // create the native surface
136 sp<Surface> s = session()->createSurface(getpid(), 0,
137 dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565);
138 session()->openTransaction();
139 s->setLayer(0x40000000);
140 session()->closeTransaction();
141
142 // initialize opengl and egl
143 const EGLint attribs[] = {
144 EGL_RED_SIZE, 5,
145 EGL_GREEN_SIZE, 6,
146 EGL_BLUE_SIZE, 5,
147 EGL_DEPTH_SIZE, 0,
148 EGL_NONE
149 };
150 EGLint w, h, dummy;
151 EGLint numConfigs;
152 EGLConfig config;
153 EGLSurface surface;
154 EGLContext context;
155 EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
156 eglInitialize(display, NULL, NULL);
157 eglChooseConfig(display, attribs, &config, 1, &numConfigs);
158
159 surface = eglCreateWindowSurface(
160 display, config, new EGLNativeWindowSurface(s), NULL);
161
162 context = eglCreateContext(display, config, NULL, NULL);
163 eglQuerySurface(display, surface, EGL_WIDTH, &w);
164 eglQuerySurface(display, surface, EGL_HEIGHT, &h);
165 eglMakeCurrent(display, surface, surface, context);
166 mDisplay = display;
167 mContext = context;
168 mSurface = surface;
169 mWidth = w;
170 mHeight= h;
171 mFlingerSurface = s;
172
173 // initialize GL
174 glShadeModel(GL_FLAT);
175 glEnable(GL_DITHER);
176 glEnable(GL_TEXTURE_2D);
177 glEnable(GL_SCISSOR_TEST);
178 glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
179
180 return NO_ERROR;
181}
182
183void BootAnimation::requestExit()
184{
185 mBarrier.open();
186 Thread::requestExit();
187}
188
189bool BootAnimation::threadLoop()
190{
191 bool r = android();
192 eglMakeCurrent(mDisplay, 0, 0, 0);
193 eglDestroyContext(mDisplay, mContext);
194 eglDestroySurface(mDisplay, mSurface);
195 eglTerminate(mDisplay);
196 return r;
197}
198
199
200bool BootAnimation::android()
201{
202 initTexture(&mAndroid[0], mAssets, "images/android_320x480.png");
203 initTexture(&mAndroid[1], mAssets, "images/boot_robot.png");
204 initTexture(&mAndroid[2], mAssets, "images/boot_robot_glow.png");
205
206 // erase screen
207 glDisable(GL_SCISSOR_TEST);
208 glBindTexture(GL_TEXTURE_2D, mAndroid[0].name);
209
210 // clear screen
211 glClear(GL_COLOR_BUFFER_BIT);
212 eglSwapBuffers(mDisplay, mSurface);
213
214 // wait ~1s
215 usleep(800000);
216
217 // fade in
218 glEnable(GL_BLEND);
219 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
220 glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
221 const int steps = 8;
222 for (int i=1 ; i<steps ; i++) {
223 float fade = i / float(steps);
224 glColor4f(1, 1, 1, fade*fade);
225 glClear(GL_COLOR_BUFFER_BIT);
226 glDrawTexiOES(0, 0, 0, mAndroid[0].w, mAndroid[0].h);
227 eglSwapBuffers(mDisplay, mSurface);
228 }
229
230 // draw last frame
231 glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
232 glDisable(GL_BLEND);
233 glDrawTexiOES(0, 0, 0, mAndroid[0].w, mAndroid[0].h);
234 eglSwapBuffers(mDisplay, mSurface);
235
236
237 // update rect for the robot
238 const int x = mWidth - mAndroid[1].w - 33;
239 const int y = (mHeight - mAndroid[1].h)/2 - 1;
240 const Rect updateRect(x, y, x+mAndroid[1].w, y+mAndroid[1].h);
241
242 // draw and update only what we need
243 eglSwapRectangleANDROID(mDisplay, mSurface,
244 updateRect.left, updateRect.top,
245 updateRect.width(), updateRect.height());
246
247 glEnable(GL_SCISSOR_TEST);
248 glScissor(updateRect.left, mHeight-updateRect.bottom,
249 updateRect.width(), updateRect.height());
250
251 const nsecs_t startTime = systemTime();
252 do
253 {
254 // glow speed and shape
255 nsecs_t time = systemTime() - startTime;
256 float t = ((4.0f/(360.0f*us2ns(16667))) * time);
257 t = t - floorf(t);
258 const float fade = 0.5f + 0.5f*sinf(t * 2*M_PI);
259
260 // fade the glow in and out
261 glDisable(GL_BLEND);
262 glBindTexture(GL_TEXTURE_2D, mAndroid[2].name);
263 glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
264 glColor4f(fade, fade, fade, fade);
265 glDrawTexiOES(updateRect.left, mHeight-updateRect.bottom, 0,
266 updateRect.width(), updateRect.height());
267
268 // draw the robot
269 glEnable(GL_BLEND);
270 glBindTexture(GL_TEXTURE_2D, mAndroid[1].name);
271 glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
272 glDrawTexiOES(updateRect.left, mHeight-updateRect.bottom, 0,
273 updateRect.width(), updateRect.height());
274
275 // make sure sleep a lot to not take too much CPU away from
276 // the boot process. With this "glow" animation there is no
277 // visible difference.
278 usleep(16667*4);
279
280 eglSwapBuffers(mDisplay, mSurface);
281 } while (!exitPending());
282
283
284 glDeleteTextures(1, &mAndroid[0].name);
285 glDeleteTextures(1, &mAndroid[1].name);
286 glDeleteTextures(1, &mAndroid[2].name);
287 return false;
288}
289
290
291bool BootAnimation::cylon()
292{
293 // initialize the textures...
294 initTexture(&mLeftTrail, mAssets, "images/cylon_left.png");
295 initTexture(&mRightTrail, mAssets, "images/cylon_right.png");
296 initTexture(&mBrightSpot, mAssets, "images/cylon_dot.png");
297
298 int w = mWidth;
299 int h = mHeight;
300
301 const Point c(w/2 , h/2);
302 const GLint amplitude = 60;
303 const int scx = c.x - amplitude - mBrightSpot.w/2;
304 const int scy = c.y - mBrightSpot.h/2;
305 const int scw = amplitude*2 + mBrightSpot.w;
306 const int sch = mBrightSpot.h;
307 const Rect updateRect(scx, h-scy-sch, scx+scw, h-scy);
308
309 // erase screen
310 glDisable(GL_SCISSOR_TEST);
311 glClear(GL_COLOR_BUFFER_BIT);
312
313 eglSwapBuffers(mDisplay, mSurface);
314
315 glClear(GL_COLOR_BUFFER_BIT);
316
317 eglSwapRectangleANDROID(mDisplay, mSurface,
318 updateRect.left, updateRect.top,
319 updateRect.width(), updateRect.height());
320
321 glEnable(GL_SCISSOR_TEST);
322 glEnable(GL_BLEND);
323 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
324
325
326 // clear the screen to white
327 Point p;
328 float t = 0;
329 float alpha = 1.0f;
330 const nsecs_t startTime = systemTime();
331 nsecs_t fadeTime = 0;
332
333 do
334 {
335 // Set scissor in interesting area
336 glScissor(scx, scy, scw, sch);
337
338 // erase screen
339 glClear(GL_COLOR_BUFFER_BIT);
340
341
342 // compute wave
343 const float a = (t * 2*M_PI) - M_PI/2;
344 const float sn = sinf(a);
345 const float cs = cosf(a);
346 GLint x = GLint(amplitude * sn);
347 float derivative = cs;
348
349 glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
350
351 if (derivative > 0) {
352 // vanishing trail...
353 p.x = (-amplitude + c.x) - mBrightSpot.w/2;
354 p.y = c.y-mLeftTrail.h/2;
355 float fade = 2.0f*(0.5f-t);
356 //fade *= fade;
357 glColor4f(fade, fade, fade, fade);
358 glBindTexture(GL_TEXTURE_2D, mLeftTrail.name);
359 glDrawTexiOES(p.x, p.y, 0, mLeftTrail.w, mLeftTrail.h);
360
361 // trail...
362 p.x = (x + c.x) - (mRightTrail.w + mBrightSpot.w/2) + 16;
363 p.y = c.y-mRightTrail.h/2;
364 fade = t<0.25f ? t*4.0f : 1.0f;
365 fade *= fade;
366 glColor4f(fade, fade, fade, fade);
367 glBindTexture(GL_TEXTURE_2D, mRightTrail.name);
368 glDrawTexiOES(p.x, p.y, 0, mRightTrail.w, mRightTrail.h);
369 } else {
370 // vanishing trail..
371 p.x = (amplitude + c.x) - (mRightTrail.w + mBrightSpot.w/2) + 16;
372 p.y = c.y-mRightTrail.h/2;
373 float fade = 2.0f*(0.5f-(t-0.5f));
374 //fade *= fade;
375 glColor4f(fade, fade, fade, fade);
376 glBindTexture(GL_TEXTURE_2D, mRightTrail.name);
377 glDrawTexiOES(p.x, p.y, 0, mRightTrail.w, mRightTrail.h);
378
379 // trail...
380 p.x = (x + c.x) - mBrightSpot.w/2;
381 p.y = c.y-mLeftTrail.h/2;
382 fade = t<0.5f+0.25f ? (t-0.5f)*4.0f : 1.0f;
383 fade *= fade;
384 glColor4f(fade, fade, fade, fade);
385 glBindTexture(GL_TEXTURE_2D, mLeftTrail.name);
386 glDrawTexiOES(p.x, p.y, 0, mLeftTrail.w, mLeftTrail.h);
387 }
388
389 const Point p( x + c.x-mBrightSpot.w/2, c.y-mBrightSpot.h/2 );
390 glBindTexture(GL_TEXTURE_2D, mBrightSpot.name);
391 glColor4f(1,0.5,0.5,1);
392 glDrawTexiOES(p.x, p.y, 0, mBrightSpot.w, mBrightSpot.h);
393
394 // update animation
395 nsecs_t time = systemTime() - startTime;
396 t = ((4.0f/(360.0f*us2ns(16667))) * time);
397 t = t - floorf(t);
398
399 eglSwapBuffers(mDisplay, mSurface);
400
401 if (exitPending()) {
402 if (fadeTime == 0) {
403 fadeTime = time;
404 }
405 time -= fadeTime;
406 alpha = 1.0f - ((float(time) * 6.0f) / float(s2ns(1)));
407
408 session()->openTransaction();
409 mFlingerSurface->setAlpha(alpha*alpha);
410 session()->closeTransaction();
411 }
412 } while (alpha > 0);
413
414 // cleanup
415 glFinish();
416 glDeleteTextures(1, &mLeftTrail.name);
417 glDeleteTextures(1, &mRightTrail.name);
418 glDeleteTextures(1, &mBrightSpot.name);
419 return false;
420}
421
422// ---------------------------------------------------------------------------
423
424}; // namespace android