Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 11313922 authored by Android (Google) Code Review's avatar Android (Google) Code Review
Browse files

Merge change 2292 into donut

* changes:
  split boot animation out of SurfaceFlinger
parents 156f418a a1ecca92
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -6,7 +6,6 @@ LOCAL_SRC_FILES:= \
    DisplayHardware/DisplayHardware.cpp \
    DisplayHardware/DisplayHardwareBase.cpp \
    GPUHardware/GPUHardware.cpp \
    BootAnimation.cpp \
    BlurFilter.cpp.arm \
    CPUGauge.cpp \
    Layer.cpp \
+0 −246
Original line number Diff line number Diff line
/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_TAG "BootAnimation"

#include <stdint.h>
#include <sys/types.h>
#include <math.h>
#include <fcntl.h>
#include <utils/misc.h>

#include <utils/threads.h>
#include <utils/Atomic.h>
#include <utils/Errors.h>
#include <utils/Log.h>
#include <utils/AssetManager.h>

#include <ui/PixelFormat.h>
#include <ui/Rect.h>
#include <ui/Region.h>
#include <ui/DisplayInfo.h>
#include <ui/ISurfaceComposer.h>
#include <ui/ISurfaceFlingerClient.h>
#include <ui/EGLNativeWindowSurface.h>

#include <core/SkBitmap.h>
#include <images/SkImageDecoder.h>

#include <GLES/gl.h>
#include <GLES/glext.h>
#include <EGL/eglext.h>

#include "BootAnimation.h"

namespace android {

// ---------------------------------------------------------------------------

BootAnimation::BootAnimation(const sp<ISurfaceComposer>& composer) :
    Thread(false) {
    mSession = SurfaceComposerClient::clientForConnection(
            composer->createConnection()->asBinder());
}

BootAnimation::~BootAnimation() {
}

void BootAnimation::onFirstRef() {
    run("BootAnimation", PRIORITY_DISPLAY);
}

const sp<SurfaceComposerClient>& BootAnimation::session() const {
    return mSession;
}

status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets,
        const char* name) {
    Asset* asset = assets.open(name, Asset::ACCESS_BUFFER);
    if (!asset)
        return NO_INIT;
    SkBitmap bitmap;
    SkImageDecoder::DecodeMemory(asset->getBuffer(false), asset->getLength(),
            &bitmap, SkBitmap::kNo_Config, SkImageDecoder::kDecodePixels_Mode);
    asset->close();
    delete asset;

    // ensure we can call getPixels(). No need to call unlock, since the
    // bitmap will go out of scope when we return from this method.
    bitmap.lockPixels();

    const int w = bitmap.width();
    const int h = bitmap.height();
    const void* p = bitmap.getPixels();

    GLint crop[4] = { 0, h, w, -h };
    texture->w = w;
    texture->h = h;

    glGenTextures(1, &texture->name);
    glBindTexture(GL_TEXTURE_2D, texture->name);

    switch (bitmap.getConfig()) {
        case SkBitmap::kA8_Config:
            glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_ALPHA,
                    GL_UNSIGNED_BYTE, p);
            break;
        case SkBitmap::kARGB_4444_Config:
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA,
                    GL_UNSIGNED_SHORT_4_4_4_4, p);
            break;
        case SkBitmap::kARGB_8888_Config:
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA,
                    GL_UNSIGNED_BYTE, p);
            break;
        case SkBitmap::kRGB_565_Config:
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB,
                    GL_UNSIGNED_SHORT_5_6_5, p);
            break;
        default:
            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);
    return NO_ERROR;
}

status_t BootAnimation::readyToRun() {
    mAssets.addDefaultAssets();

    DisplayInfo dinfo;
    status_t status = session()->getDisplayInfo(0, &dinfo);
    if (status)
        return -1;

    // create the native surface
    sp<Surface> s = session()->createSurface(getpid(), 0, dinfo.w, dinfo.h,
            PIXEL_FORMAT_RGB_565);
    session()->openTransaction();
    s->setLayer(0x40000000);
    session()->closeTransaction();

    // initialize opengl and egl
    const EGLint attribs[] = { EGL_RED_SIZE, 5, EGL_GREEN_SIZE, 6,
            EGL_BLUE_SIZE, 5, EGL_DEPTH_SIZE, 0, EGL_NONE };
    EGLint w, h, dummy;
    EGLint numConfigs;
    EGLConfig config;
    EGLSurface surface;
    EGLContext context;
    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    eglChooseConfig(display, attribs, &config, 1, &numConfigs);

    mNativeWindowSurface = new EGLNativeWindowSurface(s);
    surface = eglCreateWindowSurface(display, config, 
            mNativeWindowSurface.get(), NULL);

    context = eglCreateContext(display, config, NULL, NULL);
    eglQuerySurface(display, surface, EGL_WIDTH, &w);
    eglQuerySurface(display, surface, EGL_HEIGHT, &h);
    eglMakeCurrent(display, surface, surface, context);
    mDisplay = display;
    mContext = context;
    mSurface = surface;
    mWidth = w;
    mHeight = h;
    mFlingerSurface = s;

    // initialize GL
    glShadeModel(GL_FLAT);
    glEnable(GL_TEXTURE_2D);
    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

    return NO_ERROR;
}

void BootAnimation::requestExit() {
    mBarrier.open();
    Thread::requestExit();
}

bool BootAnimation::threadLoop() {
    bool r = android();
    eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
    eglDestroyContext(mDisplay, mContext);
    eglDestroySurface(mDisplay, mSurface);
    mNativeWindowSurface.clear();
    return r;
}

bool BootAnimation::android() {
    initTexture(&mAndroid[0], mAssets, "images/android-logo-mask.png");
    initTexture(&mAndroid[1], mAssets, "images/android-logo-shine.png");

    // clear screen
    glDisable(GL_DITHER);
    glDisable(GL_SCISSOR_TEST);
    glClear(GL_COLOR_BUFFER_BIT);
    eglSwapBuffers(mDisplay, mSurface);

    const GLint xc = (mWidth  - mAndroid[0].w) / 2;
    const GLint yc = (mHeight - mAndroid[0].h) / 2;
    const Rect updateRect(xc, yc, xc + mAndroid[0].w, yc + mAndroid[0].h);

    // draw and update only what we need
    mNativeWindowSurface->setSwapRectangle(updateRect.left,
            updateRect.top, updateRect.width(), updateRect.height());

    glEnable(GL_SCISSOR_TEST);
    glScissor(updateRect.left, mHeight - updateRect.bottom, updateRect.width(),
            updateRect.height());

    // 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 {
        nsecs_t now = systemTime();
        double time = now - startTime;
        float t = 4.0f * float(time / us2ns(16667)) / mAndroid[1].w;
        GLint offset = (1 - (t - floorf(t))) * mAndroid[1].w;
        GLint x = xc - offset;

        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);

        glEnable(GL_BLEND);
        glBindTexture(GL_TEXTURE_2D, mAndroid[0].name);
        glDrawTexiOES(xc, yc, 0, mAndroid[0].w, mAndroid[0].h);

        eglSwapBuffers(mDisplay, mSurface);
        
        // 12fps: don't animate too fast to preserve CPU
        const nsecs_t sleepTime = 83333 - ns2us(systemTime() - now);
        if (sleepTime > 0)
            usleep(sleepTime); 
    } while (!exitPending());

    glDeleteTextures(1, &mAndroid[0].name);
    glDeleteTextures(1, &mAndroid[1].name);
    return false;
}

// ---------------------------------------------------------------------------

}
; // namespace android
+0 −83
Original line number Diff line number Diff line
/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ANDROID_BOOTANIMATION_H
#define ANDROID_BOOTANIMATION_H

#include <stdint.h>
#include <sys/types.h>

#include <utils/threads.h>
#include <utils/AssetManager.h>

#include <ui/ISurfaceComposer.h>
#include <ui/SurfaceComposerClient.h>

#include <EGL/egl.h>
#include <GLES/gl.h>

#include "Barrier.h"

class SkBitmap;

namespace android {

class AssetManager;
class EGLNativeWindowSurface;

// ---------------------------------------------------------------------------

class BootAnimation : public Thread
{
public:
                BootAnimation(const sp<ISurfaceComposer>& composer);
    virtual     ~BootAnimation();

    const sp<SurfaceComposerClient>& session() const;
    virtual void        requestExit();

private:
    virtual bool        threadLoop();
    virtual status_t    readyToRun();
    virtual void        onFirstRef();

    struct Texture {
        GLint   w;
        GLint   h;
        GLuint  name;
    };

    status_t initTexture(Texture* texture, AssetManager& asset, const char* name);
    bool android();

    sp<SurfaceComposerClient>       mSession;
    AssetManager mAssets;
    Texture     mAndroid[2];
    int         mWidth;
    int         mHeight;
    EGLDisplay  mDisplay;
    EGLDisplay  mContext;
    EGLDisplay  mSurface;
    sp<Surface> mFlingerSurface;
    sp<EGLNativeWindowSurface> mNativeWindowSurface;
    Barrier mBarrier;
};

// ---------------------------------------------------------------------------

}; // namespace android

#endif // ANDROID_BOOTANIMATION_H
+15 −15
Original line number Diff line number Diff line
@@ -61,6 +61,13 @@
#include "GPUHardware/GPUHardware.h"


/* ideally AID_GRAPHICS would be in a semi-public header
 * or there would be a way to map a user/group name to its id
 */
#ifndef AID_GRAPHICS
#define AID_GRAPHICS 1003
#endif

#define DISPLAY_COUNT       1

namespace android {
@@ -184,7 +191,6 @@ SurfaceFlinger::SurfaceFlinger()
        mDebugCpu(0),
        mDebugFps(0),
        mDebugBackground(0),
        mDebugNoBootAnimation(0),
        mSyncObject(),
        mDeplayedTransactionPending(0),
        mConsoleSignals(0),
@@ -207,14 +213,11 @@ void SurfaceFlinger::init()
    mDebugBackground = atoi(value);
    property_get("debug.sf.showfps", value, "0");
    mDebugFps = atoi(value);
    property_get("debug.sf.nobootanimation", value, "0");
    mDebugNoBootAnimation = atoi(value);

    LOGI_IF(mDebugRegion,           "showupdates enabled");
    LOGI_IF(mDebugCpu,              "showcpu enabled");
    LOGI_IF(mDebugBackground,       "showbackground enabled");
    LOGI_IF(mDebugFps,              "showfps enabled");
    LOGI_IF(mDebugNoBootAnimation,  "boot animation disabled");
}

SurfaceFlinger::~SurfaceFlinger()
@@ -325,10 +328,7 @@ void SurfaceFlinger::bootFinished()
    const nsecs_t now = systemTime();
    const nsecs_t duration = now - mBootTime;
    LOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );  
    if (mBootAnimation != 0) {
        mBootAnimation->requestExit();
        mBootAnimation.clear();
    }
    property_set("ctl.stop", "bootanim");
}

void SurfaceFlinger::onFirstRef()
@@ -456,9 +456,9 @@ status_t SurfaceFlinger::readyToRun()
    if (mDebugCpu)
        mCpuGauge = new CPUGauge(this, ms2ns(500));

    // the boot animation!
    if (mDebugNoBootAnimation == false)
        mBootAnimation = new BootAnimation(this);
    
    // start boot animation
    property_set("ctl.start", "bootanim");
    
    return NO_ERROR;
}
@@ -1543,13 +1543,13 @@ status_t SurfaceFlinger::onTransact(
            // codes that require permission check
            IPCThreadState* ipc = IPCThreadState::self();
            const int pid = ipc->getCallingPid();
            const int uid = ipc->getCallingUid();
            const int self_pid = getpid();
            if (UNLIKELY(pid != self_pid)) {
            if (UNLIKELY(pid != self_pid && uid != AID_GRAPHICS)) {
                // we're called from a different process, do the real check
                if (!checkCallingPermission(
                        String16("android.permission.ACCESS_SURFACE_FLINGER")))
                {
                    const int uid = ipc->getCallingUid();
                    LOGE("Permission Denial: "
                            "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid);
                    return PERMISSION_DENIED;
+0 −3
Original line number Diff line number Diff line
@@ -36,7 +36,6 @@
#include <private/ui/SurfaceFlingerSynchro.h>

#include "Barrier.h"
#include "BootAnimation.h"
#include "CPUGauge.h"
#include "Layer.h"
#include "Tokenizer.h"
@@ -347,7 +346,6 @@ private:
                sp<SurfaceHeapManager>      mSurfaceHeapManager;
                sp<GPUHardwareInterface>    mGPU;
                GLuint                      mWormholeTexName;
                sp<BootAnimation>           mBootAnimation;
                nsecs_t                     mBootTime;
                
                // Can only accessed from the main thread, these members
@@ -374,7 +372,6 @@ private:
                int                         mDebugCpu;
                int                         mDebugFps;
                int                         mDebugBackground;
                int                         mDebugNoBootAnimation;

                // these are thread safe
    mutable     Barrier                     mReadyToRunBarrier;
Loading