linux gles+egl+wayland demo

代码直接用安卓开机动画源码修改的,将surfaceflinger修改为wayland

头文件.h

/*

 * 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 BootAnimation_wayland_H

#define BootAnimation_wayland_H

#include <vector>

#include <queue>

#include <stdint.h>

#include <sys/types.h>

extern "C"{

#include <EGL/egl.h>

#include <GLES2/gl2.h>

}

#if defined(ANDROID)|| defined(__ANDROID__)

#include <androidfw/AssetManager.h>

#include <gui/DisplayEventReceiver.h>

#include <utils/Looper.h>

#include <utils/Thread.h>

#include <binder/IBinder.h>

class SkBitmap;

#else

#include <string>

#include <set>

#include <thread>

#include "ZipFileRO.h"

#include "FileMap.h"

#include "../utils/Errors.h"

#include "../utils/Timers.h"

using namespace std;

#endif




 

namespace android {


 

#if defined(ANDROID)|| defined(__ANDROID__)

class Surface;

class SurfaceComposerClient;

class SurfaceControl;

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

class BootAnimation : public Thread, public IBinder::DeathRecipient

#else

class BootAnimation_wayland

#endif

{

public:

    struct Texture {

        GLint   w;

        GLint   h;

        GLuint  name;

    };

    struct Font {

        FileMap* map;

        Texture texture;

        int char_width;

        int char_height;

    };

    struct Animation {

        struct Frame {

            string name;

            FileMap* map;

            int trimX;

            int trimY;

            int trimWidth;

            int trimHeight;

            mutable GLuint tid;

            bool tidDie =true;

            bool operator < (const Frame& rhs) const {

                return name < rhs.name;

            }

        };

        struct Part {

            int count;  // The number of times this part should repeat, 0 for infinite

            int pause;  // The number of frames to pause for at the end of this part

            int clockPosX;  // The x position of the clock, in pixels. Positive values offset from

                            // the left of the screen, negative values offset from the right.

            int clockPosY;  // The y position of the clock, in pixels. Positive values offset from

                            // the bottom of the screen, negative values offset from the top.

                            // If either of the above are INT_MIN the clock is disabled, if INT_MAX

                            // the clock is centred on that axis.

            string path;

            string trimData;

            set<Frame> frames;

            bool playUntilComplete;

            float backgroundColor[3];

            uint8_t* audioData;

            int audioLength;

            Animation* animation;

            bool useDynamicColoring = false;

        };

        int fps;

        int width;

        int height;

        vector<Part> parts;

        string audioConf;

        string fileName;

        ZipFileRO* zip;

       

        Font clockFont;

        bool dynamicColoringEnabled = false;

        int colorTransitionStart = 0; // Start frame of dynamic color transition.

        int colorTransitionEnd = 0; // End frame of dynamic color transition.

        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.

    class Callbacks  {

    public:

        // Will be called during initialization after we have loaded

        // the animation and be provided with all parts in animation.

        virtual void init(const vector<Animation::Part>& /*parts*/) {}

        // Will be called while animation is playing before each part is

        // played. It will be provided with the part and play count for it.

        // It will be provided with the partNumber for the part about to be played,

        // as well as a reference to the part itself. It will also be provided with

        // which play of that part is about to start, some parts are repeated

        // multiple times.

        virtual void playPart(int /*partNumber*/, const Animation::Part& /*part*/,

                              int /*playNumber*/) {}

        // Will be called when animation is done and thread is shutting down.

        virtual void shutdown() {}

    };

    explicit BootAnimation_wayland(Callbacks* callbacks);

    virtual ~BootAnimation_wayland();

    void* session() const;

    virtual bool        threadLoop();

private:

    void initShaders();

    void initDynamicColors();

    void drawTexturedQuad(float xStart, float yStart, float width, float height);

    bool exitPending() const;

    bool mExitPending = false;

    thread mAnimTid;

   

    virtual status_t    readyToRun(void* _display ,void*  _window);

    virtual void        onFirstRef();

    virtual void        binderDied();

    bool                updateIsTimeAccurate();

   

    class TimeCheckThread  {

    public:

        explicit TimeCheckThread(BootAnimation_wayland* bootAnimation);

        virtual ~TimeCheckThread();

    private:

        thread mChkTimTid;

        virtual status_t    readyToRun();

        virtual bool        threadLoop();

        bool                doThreadLoop();

        void                addTimeDirWatch();

        int mInotifyFd;

        int mSystemWd;

        int mTimeWd;

        BootAnimation_wayland* mBootAnimation;

    };

    // Display event handling

   // class DisplayEventCallback;

    int displayEventCallback(int fd, int events, void* data);

    void processDisplayEvents();

   

    status_t initTexture(FileMap* map, int* width, int* height);

    status_t initFont(Font* font, const char* fallback);

    bool android();

    bool movie();

    void drawText(const char* str, const Font& font, bool bold, int* x, int* y);

    void drawClock(const Font& font, const int xPos, const int yPos);

    bool validClock(const Animation::Part& part);

    Animation* loadAnimation(const string&);

    bool playAnimation(const Animation&);

    void releaseAnimation(Animation*) const;

    bool parseAnimationDesc(Animation&);

    bool preloadZip(Animation &animation);

    void findBootAnimationFile();

    bool findBootAnimationFileInternal(const std::vector<std::string>& files);

    bool preloadAnimation();

    EGLConfig getEglConfig(const EGLDisplay&);

    ui_Size limitSurfaceSize(int width, int height) const;

    void resizeSurface(int newWidth, int newHeight);

    void requestExit();

    void checkExit();

    void handleViewport(nsecs_t timestep);

   // sp<SurfaceComposerClient>       mSession;

   // AssetManager mAssets;

    Texture     mAndroid[2];

    int         mWidth;

    int         mHeight;

    int         mMaxWidth = 0;

    int         mMaxHeight = 0;

    int         mCurrentInset;

    int         mTargetInset;

    bool        mUseNpotTextures = false;

    EGLDisplay  mDisplay;

    EGLDisplay  mContext;

    EGLDisplay  mSurface;

   // sp<IBinder> mDisplayToken;

   // sp<SurfaceControl> mFlingerSurfaceControl;

  //  sp<Surface> mFlingerSurface;

    bool        mClockEnabled;

    bool        mTimeIsAccurate;

    bool        mTimeFormat12Hour;

    bool        mShuttingDown = false;

    string     mZipFileName;

    set<string> mLoadedFiles;

  //  sp<TimeCheckThread> mTimeCheckThread = nullptr;

  //  sp<Callbacks> mCallbacks;

    Animation* mAnimation = nullptr;

   

    GLuint mImageShader;

    GLuint mTextShader;

    GLuint mImageFadeLocation;

    GLuint mImageTextureLocation;

    GLuint mTextCropAreaLocation;

    GLuint mTextTextureLocation;

    GLuint mImageColorProgressLocation;

};

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

}; // namespace android

#endif // B_BOOTANIMATION_H

源码.cpp

/*

 * 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_NDEBUG 0

#define LOG_TAG "BootAnimation"

#include <vector>

#include <stdint.h>

#include <inttypes.h>

#include <sys/inotify.h>

#include <sys/poll.h>

#include <sys/stat.h>

#include <sys/types.h>

#include <math.h>

#include <fcntl.h>

#include <signal.h>

#include <time.h>

#if defined(ANDROID)|| defined(__ANDROID__)

#include <utils/misc.h>

#include <cutils/atomic.h>

#include <cutils/properties.h>

#include <androidfw/AssetManager.h>

#include <binder/IPCThreadState.h>

#include <utils/Errors.h>

#include <utils/Log.h>

#include <utils/SystemClock.h>

#include <android-base/properties.h>

#include <ui/DisplayConfig.h>

#include <ui/PixelFormat.h>

#include <ui/Rect.h>

#include <ui/Region.h>

#include <gui/ISurfaceComposer.h>

#include <gui/DisplayEventReceiver.h>

#include <gui/Surface.h>

#include <gui/SurfaceComposerClient.h>

// TODO: Fix Skia.

#pragma GCC diagnostic push

#pragma GCC diagnostic ignored "-Wunused-parameter"

#include <SkBitmap.h>

#include <SkImage.h>

#include <SkStream.h>

#pragma GCC diagnostic pop

#else

extern "C"{

   #include "config.h"

    #include <wayland-client.h>

    #include <wayland-egl.h>

    #include <wayland-cursor.h>

    //#include <GLES2/gl2.h>

   

   

   

    #include "xdg-shell-client-protocol.h"

   // #include "shared/helpers.h"

    #include "shared/platform.h"

    #include "shared/weston-egl-ext.h"

}

#endif

#define GL_GLEXT_PROTOTYPES

#define EGL_EGLEXT_PROTOTYPES

#define

#include <GLES2/gl2.h>

#include <EGL/egl.h>

#include <EGL/eglext.h>

#else

#include <GLES/gl.h>

#include <GLES/glext.h>

#include <EGL/eglext.h>

#endif

#include "RectByCf.h"

#include <errno.h>

#include <string.h>

#include <limits.h>

#include "BootAnimation_wayland.h"

#include "SkBitmap.h"

#ifndef MIN

#define MIN(x,y) (((x) < (y)) ? (x) : (y))

#endif

#ifndef MAX

#define MAX(x,y) (((x) > (y)) ? (x) : (y))

#endif

#ifndef ARRAY_LENGTH

#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])

#endif

#define ANIM_PATH_MAX 255

#define STR(x)   #x

#define STRTO(x) STR(x)

namespace android {

static const char OEM_BOOTANIMATION_FILE[] = "/oem/media/bootanimation.zip";

static const char PRODUCT_BOOTANIMATION_DARK_FILE[] = "/product/media/bootanimation-dark.zip";

static const char PRODUCT_BOOTANIMATION_FILE[] = "/product/media/bootanimation.zip";

static const char SYSTEM_BOOTANIMATION_FILE[] = "/system/media/bootanimation.zip";

static const char APEX_BOOTANIMATION_FILE[] = "/apex/com.android.bootanimation/etc/bootanimation.zip";

static const char PRODUCT_ENCRYPTED_BOOTANIMATION_FILE[] = "/product/media/bootanimation-encrypted.zip";

static const char SYSTEM_ENCRYPTED_BOOTANIMATION_FILE[] = "/system/media/bootanimation-encrypted.zip";

static const char OEM_SHUTDOWNANIMATION_FILE[] = "/oem/media/shutdownanimation.zip";

static const char PRODUCT_SHUTDOWNANIMATION_FILE[] = "/product/media/shutdownanimation.zip";

static const char SYSTEM_SHUTDOWNANIMATION_FILE[] = "/system/media/shutdownanimation.zip";

static constexpr const char* PRODUCT_USERSPACE_REBOOT_ANIMATION_FILE = "/product/media/userspace-reboot.zip";

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 CLOCK_FONT_ASSET[] = "images/clock_font.png";

static const char CLOCK_FONT_ZIP_NAME[] = "clock_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 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";

// 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 = ' ';

static constexpr char FONT_END_CHAR = '~' + 1;

static constexpr size_t FONT_NUM_CHARS = FONT_END_CHAR - FONT_BEGIN_CHAR + 1;

static constexpr size_t FONT_NUM_COLS = 16;

static constexpr size_t FONT_NUM_ROWS = FONT_NUM_CHARS / FONT_NUM_COLS;

static const int TEXT_CENTER_VALUE = INT_MAX;

static const int TEXT_MISSING_VALUE = INT_MIN;

static const char EXIT_PROP_NAME[] = "service.bootanim.exit";

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"(

    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_DYNAMIC_COLORING_SHADER_SOURCE[] = R"(

    precision mediump float;

    const float cWhiteMaskThreshold = 0.05;

    uniform sampler2D uTexture;

    uniform float uFade;

    uniform float uColorProgress;

    uniform vec3 uStartColor0;

    uniform vec3 uStartColor1;

    uniform vec3 uStartColor2;

    uniform vec3 uStartColor3;

    uniform vec3 uEndColor0;

    uniform vec3 uEndColor1;

    uniform vec3 uEndColor2;

    uniform vec3 uEndColor3;

    varying highp vec2 vUv;

    void main() {

        vec4 mask = texture2D(uTexture, vUv);

        float r = mask.r;

        float g = mask.g;

        float b = mask.b;

        float a = mask.a;

        // If all channels have values, render pixel as a shade of white.

        float useWhiteMask = step(cWhiteMaskThreshold, r)

            * step(cWhiteMaskThreshold, g)

            * step(cWhiteMaskThreshold, b)

            * step(cWhiteMaskThreshold, a);

        vec3 color = r * mix(uStartColor0, uEndColor0, uColorProgress)

                + g * mix(uStartColor1, uEndColor1, uColorProgress)

                + b * mix(uStartColor2, uEndColor2, uColorProgress)

                + a * mix(uStartColor3, uEndColor3, uColorProgress);

        color = mix(color, vec3((r + g + b + a) * 0.25), useWhiteMask);

        gl_FragColor = vec4(color.x, color.y, color.z, (1.0 - uFade));

    })";

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((1.0 - uFade)*color.x, (1.0 - uFade)*color.y,  (1.0 - uFade)*color.z,  1.0) *color.a;

    })";

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

};


 

BootAnimation_wayland::BootAnimation_wayland(Callbacks* callbacks)

        : mClockEnabled(false), mTimeIsAccurate(false), mTimeFormat12Hour(false){

   // mSession = new SurfaceComposerClient();

    FileMap::mapC = FileMap::unmapC = 0;

   

    onFirstRef();

}

BootAnimation_wayland::~BootAnimation_wayland() {

    if (mAnimation != nullptr) {

        releaseAnimation(mAnimation);

        mAnimation = nullptr;

    }

    if(FileMap::mapC != FileMap::unmapC)

        LOGE(TAG,"MEM LEAK %d %d",FileMap::mapC , FileMap::unmapC);

}

void BootAnimation_wayland::onFirstRef() {

   // status_t err = mSession->linkToComposerDeath(this);

    //SLOGE_IF(err, "linkToComposerDeath failed (%s) ", strerror(-err));

   

        preloadAnimation();

       

}

void* BootAnimation_wayland::session() const {

    return nullptr;

}

void BootAnimation_wayland::binderDied() {

    // woah, surfaceflinger died!

    LOGD(TAG,"SurfaceFlinger died, exiting...");

    // calling requestExit() is not enough here because the Surface code

    // might be blocked on a condition variable that will never be updated.

    kill( getpid(), SIGKILL );

    requestExit();

}

#include "etc1.h"

#include <GLES2/gl2ext.h>

struct CompressedTextureInfo {

 bool is_valid; // 是否为一个有效的压缩纹理信息

 GLsizei width;

 GLsizei height;

 GLsizei size;

 GLenum internal_format;

 GLvoid *data;

};

#define ETC1_PKM_HEADER_SIZE 16

status_t BootAnimation_wayland::initTexture(FileMap* map, int* width_, int* height_) {

    SkBitmap bitmap(map);

   

    // FileMap memory is never released until application exit.

    // Release it now as the texture is already loaded and the memory used for

    // the packed resource can be released.

   

   

    unsigned char * data =(unsigned char*) map->getDataPtr();

    CompressedTextureInfo textureInfo;

    textureInfo.is_valid = false;

    const etc1_byte *header = data;

    if (!etc1_pkm_is_valid(header)) {

        LOGE(TAG,"LoadTexture: etc1_pkm is not valid");

       // return textureInfo;

    }

    unsigned int w = etc1_pkm_get_width(header);

    unsigned int h = etc1_pkm_get_height(header);

    GLuint size = 8 * ((w + 3) >> 2) * ((h + 3) >> 2);

    GLvoid *texture_data = data + ETC1_PKM_HEADER_SIZE;

    textureInfo.is_valid = true;

    textureInfo.width = w;

    textureInfo.height = h;

    textureInfo.size = size;

    textureInfo.internal_format = GL_ETC1_RGB8_OES;

    void* p  = textureInfo.data = texture_data;

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

    if (th < h) th <<= 1;

    switch (bitmap.colorType()) {

        case 6:

            if (!mUseNpotTextures && (tw != w || th != h)) {

               

                glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tw, th, 0, GL_RGBA,

                        GL_UNSIGNED_BYTE, nullptr);

                glTexSubImage2D(GL_TEXTURE_2D, 0,

                        0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, p);

                       

            } else {

               

                glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA,

                        GL_UNSIGNED_BYTE, p);

                       

            }

            break;

        case 2:

            if (!mUseNpotTextures && (tw != w || th != h)) {

                glCompressedTexImage2D(GL_TEXTURE_2D, 0,

                GL_ETC1_RGB8_OES,

                    textureInfo.width, textureInfo.height, 0,textureInfo.size, textureInfo.data);

            } else {

               

                glCompressedTexImage2D(GL_TEXTURE_2D, 0,

                GL_ETC1_RGB8_OES,

                    textureInfo.width, textureInfo.height, 0,textureInfo.size, textureInfo.data);

                   

            }

            break;

        case 0://kRGB_565_SkColorType

            if (!mUseNpotTextures && (tw != w || th != h)) {

                glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tw, th, 0, GL_ALPHA,

                        GL_UNSIGNED_BYTE, nullptr);

                glTexSubImage2D(GL_TEXTURE_2D, 0,

                        0, 0, w, h, GL_ALPHA, GL_UNSIGNED_BYTE, p);

            } else {

                glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGB,

                        GL_UNSIGNED_BYTE, p);

            }

            break;

        default:

            LOGD(TAG,"this should never happen");

            break;

    }

    delete map;

#if gles2_

    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

    glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop);

    #endif

    *width_ = w;

    *height_ = h;

    return NO_ERROR;

}



 

EGLConfig BootAnimation_wayland::getEglConfig(const EGLDisplay& display) {

    const EGLint attribs[] = {

        EGL_RED_SIZE,   8,

        EGL_GREEN_SIZE, 8,

        EGL_BLUE_SIZE,  8,

        EGL_DEPTH_SIZE, 0,

        EGL_NONE

    };

    EGLint numConfigs;

    EGLConfig config;

    eglChooseConfig(display, attribs, &config, 1, &numConfigs);

    return config;

}

ui_Size BootAnimation_wayland::limitSurfaceSize(int width, int height) const {

    ui_Size limited(width, height);

    bool wasLimited = false;

    const float aspectRatio = float(width) / float(height);

    if (mMaxWidth != 0 && width > mMaxWidth) {

        limited.h = mMaxWidth / aspectRatio;

        limited.w= mMaxWidth;

        wasLimited = true;

    }

    if (mMaxHeight != 0 && limited.h > mMaxHeight) {

        limited.h = mMaxHeight;

        limited.w = mMaxHeight * aspectRatio;

        wasLimited = true;

    }

    if(wasLimited)

        LOGD(TAG, "Surface size has been limited to [%dx%d] from [%dx%d]",

             limited.w, limited.h, width, height);

    return limited;

}

extern "C"{

struct window_b

struct seat;

struct display_b {

    struct wl_display *display;

    struct wl_registry *registry;

    struct wl_compositor *compositor;

    struct xdg_wm_base *wm_base;

    struct wl_seat *seat;

    struct wl_pointer *pointer;

    struct wl_touch *touch;

    struct wl_keyboard *keyboard;

    struct wl_shm *shm;

    struct wl_cursor_theme *cursor_theme;

    struct wl_cursor *default_cursor;

    struct wl_surface *cursor_surface;

    struct {

        EGLDisplay dpy;

        EGLContext ctx;

        EGLConfig conf;

    } egl;

    struct window_ *window;

    PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC swap_buffers_with_damage;

};

struct geometry {

    int width, height;

};

struct window {

    struct display_yd *display;

    struct geometry geometry, window_size;

    struct {

        GLuint rotation_uniform;

        GLuint pos;

        GLuint col;

    } gl;

    uint32_t benchmark_time, frames;

    struct wl_egl_window *native;

    struct wl_surface *surface;

    struct xdg_surface *xdg_surface;

    struct xdg_toplevel *xdg_toplevel;

    EGLSurface egl_surface;

    struct wl_callback *callback;

    int fullscreen, maximized, opaque, buffer_size, frame_sync, delay;

    bool wait_for_configure;

};

static int running = 1;

static GLuint

create_shader(struct window_ *window, const char *source, GLenum shader_type)

{

   

    GLuint shader;

    #if gles2_by

    GLint status;

    shader = glCreateShader(shader_type);

    assert(shader != 0);

    glShaderSource(shader, 1, (const char **) &source, NULL);

    glCompileShader(shader);

    glGetShaderiv(shader, GL_COMPILE_STATUS, &status);

    if (!status) {

        char log[1000];

        GLsizei len;

        glGetShaderInfoLog(shader, 1000, &len, log);

        fprintf(stderr, "Error: compiling %s: %.*s\n",

            shader_type == GL_VERTEX_SHADER ? "vertex" : "fragment",

            len, log);

        exit(1);

    }

    #endif

    return shader;

}

static const char *vert_shader_text =

    "uniform mat4 rotation;\n"

    "attribute vec4 pos;\n"

    "attribute vec4 color;\n"

    "varying vec4 v_color;\n"

    "void main() {\n"

    "  gl_Position = rotation * pos;\n"

    "  v_color = color;\n"

    "}\n";

static const char *frag_shader_text =

    "precision mediump float;\n"

    "varying vec4 v_color;\n"

    "void main() {\n"

    "  gl_FragColor = v_color;\n"

    "}\n";


 

static void

init_egl(struct display_ *display, struct window_b*window)

{

    static const struct {

        char *extension, *entrypoint;

    } swap_damage_ext_to_entrypoint[] = {

        {

            .extension = "EGL_EXT_swap_buffers_with_damage",

            .entrypoint = "eglSwapBuffersWithDamageEXT",

        },

        {

            .extension = "EGL_KHR_swap_buffers_with_damage",

            .entrypoint = "eglSwapBuffersWithDamageKHR",

        },

    };

    static const EGLint context_attribs[] = {

        EGL_CONTEXT_CLIENT_VERSION, 2,

        EGL_NONE

    };

    const char *extensions;

    EGLint config_attribs[] = {

        EGL_SURFACE_TYPE, EGL_WINDOW_BIT,

        EGL_RED_SIZE, 8,

        EGL_GREEN_SIZE, 8,

        EGL_BLUE_SIZE, 8,

        EGL_ALPHA_SIZE, 8,

        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,

        EGL_NONE

    };

    EGLint major, minor, n, count, i, size;

    EGLConfig *configs;

    EGLBoolean ret;

    if (window->opaque || window->buffer_size == 16)

        config_attribs[9] = 0;

    display->egl.dpy =

        weston_platform_get_egl_display(EGL_PLATFORM_WAYLAND_KHR,

                        display->display, NULL);

    assert(display->egl.dpy);

    ret = eglInitialize(display->egl.dpy, &major, &minor);

    assert(ret == EGL_TRUE);

    ret = eglBindAPI(EGL_OPENGL_ES_API);

    assert(ret == EGL_TRUE);

    if (!eglGetConfigs(display->egl.dpy, NULL, 0, &count) || count < 1)

        assert(0);

    configs = (EGLConfig *)calloc(count, sizeof *configs);

    assert(configs);

    ret = eglChooseConfig(display->egl.dpy, config_attribs,

                  configs, count, &n);

    assert(ret && n >= 1);

    for (i = 0; i < n; i++) {

        eglGetConfigAttrib(display->egl.dpy,

                   configs[i], EGL_BUFFER_SIZE, &size);

        if (window->buffer_size == size) {

            display->egl.conf = configs[i];

            break;

        }

    }

    free(configs);

    if (display->egl.conf == NULL) {

        fprintf(stderr, "did not find config with buffer size %d\n",

            window->buffer_size);

        exit(EXIT_FAILURE);

    }

    display->egl.ctx = eglCreateContext(display->egl.dpy,

                        display->egl.conf,

                        EGL_NO_CONTEXT, context_attribs);

    assert(display->egl.ctx);

    display->swap_buffers_with_damage = NULL;

    extensions = eglQueryString(display->egl.dpy, EGL_EXTENSIONS);

    if (extensions &&

        weston_check_egl_extension(extensions, "EGL_EXT_buffer_age")) {

        for (i = 0; i < (int) ARRAY_LENGTH(swap_damage_ext_to_entrypoint); i++) {

            if (weston_check_egl_extension(extensions,

                               swap_damage_ext_to_entrypoint[i].extension)) {

                /* The EXTPROC is identical to the KHR one */

                display->swap_buffers_with_damage =

                    (PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC)

                    eglGetProcAddress(swap_damage_ext_to_entrypoint[i].entrypoint);

                break;

            }

        }

    }

    if (display->swap_buffers_with_damage)

        printf("has EGL_EXT_buffer_age and %s\n", swap_damage_ext_to_entrypoint[i].extension);

}

static void

handle_surface_configure(void *data, struct xdg_surface *surface,

             uint32_t serial)

{

    struct window_b*window = (struct window_ *)data;

    xdg_surface_ack_configure(surface, serial);

    window->wait_for_configure = false;

}

static const struct xdg_surface_listener xdg_surface_listener = {

    handle_surface_configure

};

static void

handle_toplevel_configure(void *data, struct xdg_toplevel *toplevel,

              int32_t width, int32_t height,

              struct wl_array *states)

{

    struct window_b*window = (struct window_ *)data;

    uint32_t *p;

    window->fullscreen = 0;

    window->maximized = 0;

    for (p = (uint32_t*)(states->data);                 \

         (const char *) p < ((const char *) (states)->data + (states)->size); \

         p++) {

        uint32_t state = *(uint32_t*)p;

        switch (state) {

        case XDG_TOPLEVEL_STATE_FULLSCREEN:

            window->fullscreen = 1;

            break;

        case XDG_TOPLEVEL_STATE_MAXIMIZED:

            window->maximized = 1;

            break;

        }

    }

    LOGI(TAG,"toplevel_configure %d  %d %d %d",width,height,window->fullscreen,window->maximized);

    if (width > 0 && height > 0) {

        if (!window->fullscreen && !window->maximized) {

            window->window_size.width = width;

            window->window_size.height = height;

        }

        window->geometry.width = width;

        window->geometry.height = height;

    } else if (!window->fullscreen && !window->maximized) {

        window->geometry = window->window_size;

    }

    if (window->native)

        wl_egl_window_resize(window->native,

                     window->geometry.width,

                     window->geometry.height, 0, 0);

}

static void

handle_toplevel_close(void *data, struct xdg_toplevel *xdg_toplevel)

{

    running = 0;

}

static const struct xdg_toplevel_listener xdg_toplevel_listener = {

    handle_toplevel_configure,

    handle_toplevel_close,

};

static void

create_surface(struct window_ *window)

{

     

    struct display_d *display = window->display;

    EGLBoolean ret;

    window->surface = wl_compositor_create_surface(display->compositor);

    window->native =

        wl_egl_window_create(window->surface,

                     window->geometry.width,

                     window->geometry.height);

     

    window->egl_surface =

        weston_platform_create_egl_surface(display->egl.dpy,

                           display->egl.conf,

                           window->native, NULL);

     

    window->xdg_surface = xdg_wm_base_get_xdg_surface(display->wm_base,

                              window->surface);

    xdg_surface_add_listener(window->xdg_surface,

                 &xdg_surface_listener, window);

     

    window->xdg_toplevel =

        xdg_surface_get_toplevel(window->xdg_surface);

    xdg_toplevel_add_listener(window->xdg_toplevel,

                  &xdg_toplevel_listener, window);

    xdg_toplevel_set_title(window->xdg_toplevel, "simple-egl");

    window->wait_for_configure = true;

    wl_surface_commit(window->surface);

     

    ret = eglMakeCurrent(window->display->egl.dpy, window->egl_surface,

                 window->egl_surface, window->display->egl.ctx);

    assert(ret == EGL_TRUE);

     

    if (!window->frame_sync)

        eglSwapInterval(display->egl.dpy, 0);

     

    if (!display->wm_base)

        return;

    if (window->fullscreen)

        xdg_toplevel_set_fullscreen(window->xdg_toplevel, NULL);

}

static void

destroy_surface(struct window_ *window)

{

    /* Required, otherwise segfault in egl_dri2.c: dri2_make_current()

     * on eglReleaseThread(). */

    eglMakeCurrent(window->display->egl.dpy, EGL_NO_SURFACE, EGL_NO_SURFACE,

               EGL_NO_CONTEXT);

    weston_platform_destroy_egl_surface(window->display->egl.dpy,

                        window->egl_surface);

    wl_egl_window_destroy(window->native);

    if (window->xdg_toplevel)

        xdg_toplevel_destroy(window->xdg_toplevel);

    if (window->xdg_surface)

        xdg_surface_destroy(window->xdg_surface);

    wl_surface_destroy(window->surface);

    if (window->callback)

        wl_callback_destroy(window->callback);

}

static const struct wl_keyboard_listener keyboard_listener = {

    nullptr

};

static const struct wl_pointer_listener pointer_listener = {

    nullptr

};

static const struct wl_touch_listener touch_listener = {

    nullptr

};

static void

seat_handle_capabilities(void *data, struct wl_seat *seat,

             uint32_t _caps)

{

    enum wl_seat_capability caps = (enum wl_seat_capability)_caps;

    struct display_b *d = (struct display_b *)data;

    if ((caps & WL_SEAT_CAPABILITY_POINTER) && !d->pointer) {

        d->pointer = wl_seat_get_pointer(seat);

        wl_pointer_add_listener(d->pointer, &pointer_listener, d);

    } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && d->pointer) {

        wl_pointer_destroy(d->pointer);

        d->pointer = NULL;

    }

    if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !d->keyboard) {

        d->keyboard = wl_seat_get_keyboard(seat);

        wl_keyboard_add_listener(d->keyboard, &keyboard_listener, d);

    } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && d->keyboard) {

        wl_keyboard_destroy(d->keyboard);

        d->keyboard = NULL;

    }

    if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !d->touch) {

        d->touch = wl_seat_get_touch(seat);

        wl_touch_set_user_data(d->touch, d);

        wl_touch_add_listener(d->touch, &touch_listener, d);

    } else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && d->touch) {

        wl_touch_destroy(d->touch);

        d->touch = NULL;

    }

}

static const struct wl_seat_listener seat_listener = {

    seat_handle_capabilities,

};

static void

xdg_wm_base_ping(void *data, struct xdg_wm_base *shell, uint32_t serial)

{

    xdg_wm_base_pong(shell, serial);

}

static const struct xdg_wm_base_listener wm_base_listener = {

    xdg_wm_base_ping,

};

static void

registry_handle_global(void *data, struct wl_registry *registry,

               uint32_t name, const char *interface, uint32_t version)

{

    struct display_by *d = (struct display_by *)data;

 //   LOGD(TAG,"INTERFACE is %s",interface);

    if (strcmp(interface, "wl_compositor") == 0) {

        d->compositor =(struct wl_compositor *)

            wl_registry_bind(registry, name,

                     &wl_compositor_interface,

                     MIN(version, 4));

    } else if (strcmp(interface, "xdg_wm_base") == 0) {

        d->wm_base = (struct xdg_wm_base *)wl_registry_bind(registry, name,

                          &xdg_wm_base_interface, 1);

        xdg_wm_base_add_listener(d->wm_base, &wm_base_listener, d);

    } else if (strcmp(interface, "wl_seat") == 0) {

        d->seat = (struct wl_seat *)wl_registry_bind(registry, name,

                       &wl_seat_interface, 1);

        //wl_seat_add_listener(d->seat, &seat_listener, d);

    } else if (strcmp(interface, "wl_shm") == 0) {

        d->shm = (struct wl_shm *)wl_registry_bind(registry, name,

                      &wl_shm_interface, 1);

        d->cursor_theme = (struct wl_cursor_theme *)wl_cursor_theme_load(NULL, 32, d->shm);

        if (!d->cursor_theme) {

            fprintf(stderr, "unable to load default theme\n");

            return;

        }

        d->default_cursor =

            (struct wl_cursor *)wl_cursor_theme_get_cursor(d->cursor_theme, "left_ptr");

        if (!d->default_cursor) {

            fprintf(stderr, "unable to load default left pointer\n");

            // TODO: abort ?

        }

    }

}

static void

registry_handle_global_remove(void *data, struct wl_registry *registry,

                  uint32_t name)

{

}

static const struct wl_registry_listener registry_listener = {

    registry_handle_global,

    registry_handle_global_remove

};

static void

fini_egl(struct display_by *display)

{

    eglTerminate(display->egl.dpy);

    eglReleaseThread();

}

//cfcfcfcf

static 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) {

         LOGE(TAG,"Compile shader failed. Shader type: %d", shaderType);

         GLint maxLength = 0;

          glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength);

         std::vector<GLchar> errorLog(maxLength);

          glGetShaderInfoLog(shader, maxLength, &maxLength, &errorLog[0]);

          LOGE(TAG,"Shader compilation error: %s", &errorLog[0]);

          return 0;

     }

      return shader;

  }

  static 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) {

          LOGE(TAG,"Linking shader failed. Shader handles: vert %d, frag %d",

              vertexShader, fragmentShader);

          return 0;

      }

      return program;

  }

}//cccccc

  void BootAnimation_wayland::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);

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

  }

extern volatile int  by_cf_ori;

status_t BootAnimation_wayland::readyToRun(void* _display ,void*  _window ) {

     

    int i, ret = 0;

    struct display_by* display = (struct display_by*)_display;

    struct window_bd * window = (struct window_bd *)_window;

    window->display = (struct display_bd*)display;

    display->window = window;

    window->geometry.width  = 100;

    window->geometry.height = 100;

    window->window_size = window->geometry;

    window->buffer_size = 32;

    window->frame_sync = 1;

    window->delay = 0;

    window->fullscreen = 1;//by cf

    mMaxWidth = 0;

    mMaxHeight = 0;

   

   

     

    while(true){

        display->display = wl_display_connect(NULL);

        if(display->display)

            break;

        static int cnt = 0;

        if(cnt>=40){

            cnt = 0;

            LOGI(TAG,"waiting wayland");

        }

        usleep(30000);

        cnt++;

    }

   

    display->registry = wl_display_get_registry(display->display);

    wl_registry_add_listener(display->registry,

                 &registry_listener, display);

    wl_display_roundtrip(display->display);

   

   

   

   

    init_egl(display, window);

     

    create_surface(window);

   

    #if gles2_bdcy

    initShaders();

    #endif

    window->gl.pos = 0;

    window->gl.col = 1;

    display->cursor_surface =

        wl_compositor_create_surface(display->compositor);

     

    EGLint w, h;

    eglQuerySurface(display->egl.dpy, window->egl_surface, EGL_WIDTH, &w);

    eglQuerySurface(display->egl.dpy, window->egl_surface, EGL_HEIGHT, &h);

     

    mWidth = w;

    mHeight = h;

   

    mTargetInset = -1;

   

    return NO_ERROR;

}

void BootAnimation_wayland::resizeSurface(int newWidth, int newHeight) {

   

}

bool BootAnimation_wayland::preloadAnimation() {

    findBootAnimationFile();

    if (!mZipFileName.empty()) {

        mAnimation = loadAnimation(mZipFileName);

        return (mAnimation != nullptr);

    }

    else

        LOGE(TAG,"no anim file found %s",mZipFileName.c_str());

    return false;

}

bool BootAnimation_wayland::findBootAnimationFileInternal(const std::vector<std::string> &files) {

    for (const std::string& f : files) {

      //  LOGD(TAG,"CHK %s",f.c_str());

        if (access(f.c_str(), R_OK) == 0) {

            mZipFileName = f.c_str();

            return true;

        }else{

            LOGE(TAG,"ACCESS err %d %s",errno,strerror(errno));

        }

    }

    return false;

}

void BootAnimation_wayland::findBootAnimationFile() {

    static const std::vector<std::string> bootFiles = {

        "/data/bootanimation.zip"

    };

   

    findBootAnimationFileInternal(bootFiles);

   

}

static float mapLinear(float x, float a1, float a2, float b1, float b2) {

    return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 );

}

void BootAnimation_wayland::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);

}


 

static struct window_bd  window  = { 0 };

bool BootAnimation_wayland::threadLoop() {

    struct display_bd display = { 0 };

    int ret = 0;

rst:

    readyToRun(&display,&window);

   

    bool result;

    // We have no bootanimation file, so we use the stock android logo

    // animation.

    if (mZipFileName.empty()) {

      //  result = android();

    } else {

        LOGD(TAG,"STRAT MOVIE");

        result = movie();

    }

    destroy_surface(&window);

    fini_egl(&display);

    wl_surface_destroy(display.cursor_surface);

    if (display.cursor_theme)

        wl_cursor_theme_destroy(display.cursor_theme);

    if (display.wm_base)

        xdg_wm_base_destroy(display.wm_base);

    if (display.compositor)

        wl_compositor_destroy(display.compositor);

    wl_registry_destroy(display.registry);

    wl_display_flush(display.display);

    wl_display_disconnect(display.display);

   

    return result;

}

bool BootAnimation_wayland::android() {

    return false;

}

void BootAnimation_wayland::requestExit(){

    mExitPending = true;

}

void BootAnimation_wayland::checkExit() {

    // Allow surface flinger to gracefully request shutdown

   

    requestExit();

     

}

bool BootAnimation_wayland::validClock(const Animation::Part& part) {

    return part.clockPosX != TEXT_MISSING_VALUE && part.clockPosY != TEXT_MISSING_VALUE;

}

static bool parseTextCoord(const char* str, int* dest) {

    if (strcmp("c", str) == 0) {

        *dest = TEXT_CENTER_VALUE;

        return true;

    }

    char* end;

    int val = (int) strtol(str, &end, 0);

    if (end == str || *end != '\0' || val == INT_MAX || val == INT_MIN) {

        return false;

    }

    *dest = val;

    return true;

}

// Parse two position coordinates. If only string is non-empty, treat it as the y value.

static void parsePosition(const char* str1, const char* str2, int* x, int* y) {

    bool success = false;

    if (strlen(str1) == 0) {  // No values were specified

        // success = false

    } else if (strlen(str2) == 0) {  // we have only one value

        if (parseTextCoord(str1, y)) {

            *x = TEXT_CENTER_VALUE;

            success = true;

        }

    } else {

        if (parseTextCoord(str1, x) && parseTextCoord(str2, y)) {

            success = true;

        }

    }

    if (!success) {

        *x = TEXT_MISSING_VALUE;

        *y = TEXT_MISSING_VALUE;

    }

}

// Parse a color represented as an HTML-style 'RRGGBB' string: each pair of

// characters in str is a hex number in [0, 255], which are converted to

// floating point values in the range [0.0, 1.0] and placed in the

// corresponding elements of color.

//

// If the input string isn't valid, parseColor returns false and color is

// left unchanged.

static bool parseColor(const char str[7], float color[3]) {

    float tmpColor[3];

    for (int i = 0; i < 3; i++) {

        int val = 0;

        for (int j = 0; j < 2; j++) {

            val *= 16;

            char c = str[2*i + j];

            if      (c >= '0' && c <= '9') val += c - '0';

            else if (c >= 'A' && c <= 'F') val += (c - 'A') + 10;

            else if (c >= 'a' && c <= 'f') val += (c - 'a') + 10;

            else                           return false;

        }

        tmpColor[i] = static_cast<float>(val) / 255.0f;

    }

    memcpy(color, tmpColor, sizeof(tmpColor));

    return true;

}


 

static bool readFile(ZipFileRO* zip, const char* name, string& outString) {

    ZipEntryRO entry = (ZipEntryRO)zip->findEntryByName(name);

   

    if (!entry) {

        LOGE(TAG, "couldn't find %s", name);

        return false;

    }

    FileMap* entryMap = zip->createEntryFileMap(entry);

    zip->releaseEntry(entry);

   

    if (!entryMap) {

        LOGE(TAG, "entryMap is null");

        return false;

    }

   // string str((char const*)entryMap->getDataPtr(), entryMap->getDataLength());

    outString = string((char const*)entryMap->getDataPtr(), entryMap->getDataLength());

    delete entryMap;

    return true;

}

// The font image should be a 96x2 array of character images.  The

// columns are the printable ASCII characters 0x20 - 0x7f.  The

// top row is regular text; the bottom row is bold.

status_t BootAnimation_wayland::initFont(Font* font, const char* fallback) {

    status_t status = NO_ERROR;

   

    return status;

}

void BootAnimation_wayland::drawText(const char* str, const Font& font, bool bold, int* x, int* y) {

   

}

// We render 12 or 24 hour time.

void BootAnimation_wayland::drawClock(const Font& font, const int xPos, const int yPos) {

   

}

bool BootAnimation_wayland::parseAnimationDesc(Animation& animation)  {

    string desString;

    if (!readFile(animation.zip, "desc.txt", desString)) {

        return false;

    }

    char const* s = desString.c_str();

   

    // Parse the description file

    for (;;) {

        const char* endl = strstr(s, "\n");

        if (endl == nullptr) break;

        string line(s, endl - s);

        const char* l = line.c_str();

        LOGD(TAG,"line IS %s",l);

        int fps = 0;

        int width = 0;

        int height = 0;

        int count = 0;

        int pause = 0;

        char path[ANIM_ENTRY_NAME_MAX];

        char color[7] = "000000"; // default to black if unspecified

        char clockPos1[TEXT_POS_LEN_MAX + 1] = "";

        char clockPos2[TEXT_POS_LEN_MAX + 1] = "";

        char pathType;

        if (sscanf(l, "%d %d %d", &width, &height, &fps) == 3) {

            LOGD(TAG,"> w=%d, h=%d, fps=%d", width, height, fps);

            animation.width = width;

           // height = 512;

            animation.height = height;

            animation.fps = fps;

        } else if (sscanf(l, " %c %d %d %" STRTO(ANIM_PATH_MAX) "s #%6s %16s %16s",

                          &pathType, &count, &pause, path, color, clockPos1, clockPos2) >= 4) {

            //SLOGD("> type=%c, count=%d, pause=%d, path=%s, color=%s, clockPos1=%s, clockPos2=%s",

            //    pathType, count, pause, path, color, clockPos1, clockPos2);

            Animation::Part part;

            part.playUntilComplete = pathType == 'c';

            part.count = count;

            part.pause = pause;

            part.path = path;

            part.audioData = nullptr;

            part.animation = nullptr;

            if (!parseColor(color, part.backgroundColor)) {

                LOGE(TAG,"> invalid color '#%s'", color);

                part.backgroundColor[0] = 0.0f;

                part.backgroundColor[1] = 0.0f;

                part.backgroundColor[2] = 0.0f;

            }

            parsePosition(clockPos1, clockPos2, &part.clockPosX, &part.clockPosY);

            animation.parts.push_back(part);

        }

        else if (strcmp(l, "$SYSTEM") == 0) {

            // SLOGD("> SYSTEM");

            Animation::Part part;

            part.playUntilComplete = false;

            part.count = 1;

            part.pause = 0;

            part.audioData = nullptr;

            part.animation = loadAnimation(string(SYSTEM_BOOTANIMATION_FILE));

            if (part.animation != nullptr)

                animation.parts.push_back(part);

        }

        s = ++endl;

    }

    return true;

}

bool BootAnimation_wayland::preloadZip(Animation& animation) {

    // read all the data structures

    const size_t pcount = animation.parts.size();

    uint32_t cookie = 0;

    ZipFileRO* zip = animation.zip;

    if (!zip->startIteration((void**)&cookie)) {

        return false;

    }

    ZipEntryRO entry;

    char name[ANIM_ENTRY_NAME_MAX];

    while ((entry = zip->nextEntry((void*)&cookie)) != nullptr) {

        cookie++;//bd cf

        const int foundEntryName = zip->getEntryFileName(entry, name, ANIM_ENTRY_NAME_MAX);

        if (foundEntryName > ANIM_ENTRY_NAME_MAX || foundEntryName == -1) {

            LOGE(TAG,"Error fetching entry file name");

            continue;

        }

        const string entryName(name);

        const char* cp;

       // LOGD(TAG,"enName is %s",entryName.c_str());

        cp = strrchr(entryName.c_str(), OS_PATH_SEPARATOR);

        string path;

        string leaf;

        if (cp == nullptr){

            path = "";

            leaf = entryName;

        }

        else{

            path = string(entryName.c_str(),cp-entryName.c_str());

            leaf = cp+1;

        }

       

     //   LOGD(TAG,"pl is %s %s",leaf.c_str(),path.c_str());

        if (leaf.size() > 0) {

            if (entryName == CLOCK_FONT_ZIP_NAME) {

                FileMap* map = zip->createEntryFileMap(entry);

                if (map) {

                    animation.clockFont.map = map;

                }

                continue;

            }

            for (size_t j = 0; j < pcount; j++) {

           //     LOGD(TAG,"PPATH=%s",animation.parts[j].path.c_str());

                if (path == animation.parts[j].path) {

                    uint16_t method;

                    // supports only stored png files

                    if (zip->getEntryInfo(entry, &method, nullptr, nullptr, nullptr, nullptr, nullptr)) {

                        if (method == 0) {

                            FileMap* map = zip->createEntryFileMap(entry);

                            if (map) {

                                Animation::Part& part(animation.parts[j]);

                                if (leaf == "audio.wav") {

                                    // a part may have at most one audio file

                                    part.audioData = (uint8_t *)map->getDataPtr();

                                    part.audioLength = map->getDataLength();

                                } else if (leaf == "trim.txt") {

                                   // part.trimData.setTo((char const*)map->getDataPtr(),

                                                    //    map->getDataLength());

                                } else {

                                    Animation::Frame frame;

                                    frame.name = leaf;

                                //    LOGD(TAG,"FRAME NAME is %s",leaf.c_str());

                                    frame.map = map;

                                    frame.trimWidth = animation.width;

                                    frame.trimHeight = animation.height;

                                    frame.trimX = 0;

                                    frame.trimY = 0;

                                    part.frames.insert(frame);

                                }

                            }

                        } else {

                            LOGE(TAG,"bootanimation.zip is compressed; must be only stored");

                        }

                    }

                }

            }

        }

    }

   

    return true;

}

bool BootAnimation_wayland::movie() {

    if (mAnimation == nullptr) {

        mAnimation = loadAnimation(mZipFileName);

    }

    if (mAnimation == nullptr)

        return false;

   

    bool anyPartHasClock = false;

    for (size_t i=0; i < mAnimation->parts.size(); i++) {

        if(validClock(mAnimation->parts[i])) {

            anyPartHasClock = true;

            break;

        }

    }

    if (!anyPartHasClock) {

        mClockEnabled = false;

    }

    // Check if npot textures are supported

    mUseNpotTextures = false;

    string gl_extensions;

    const char* exts = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));

    if (!exts) {

        glGetError();

    } else {

        gl_extensions = exts;

        if ((gl_extensions.find("GL_ARB_texture_non_power_of_two") != string::npos) ||

            (gl_extensions.find("GL_OES_texture_npot") != string::npos)) {

            mUseNpotTextures = true;

        }

       

        if (gl_extensions.find("GL_OES_compressed_ETC1_RGB8_texture")!= string::npos) {

            LOGD(TAG,"SUPPORT ETC1");

        }

        if (gl_extensions.find("GL_OES_texture_compression_astc") != string::npos) {

            LOGD(TAG,"SUPPORT astc");

        }

    }

    // Blend required to draw time on top of animation frames.

    #if gles2_bdcy

    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

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

    #else

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

    #endif

    playAnimation(*mAnimation);

   

   

    releaseAnimation(mAnimation);

    mAnimation = nullptr;

    return false;

}

bool BootAnimation_wayland::exitPending() const

{

   

    return mExitPending;

}

void BootAnimation_wayland::initDynamicColors() {

   

}

bool BootAnimation_wayland::playAnimation(const Animation& animation) {

    const size_t pcount = animation.parts.size();

    nsecs_t frameDuration = s2ns(1) / animation.fps;

    LOGD(TAG,"%sAnimationShownTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot",

           110);

    int  ret = 0;

    for (size_t i=0 ; i<pcount ; i++) {

      //  LOGI(TAG,"PCNT IS %d",i);

        const Animation::Part& part(animation.parts[i]);

        const size_t fcount = part.frames.size();

        glViewport(0, 0, mWidth, mHeight);

        glScissor(0, 0, mWidth, mHeight);

        glBindTexture(GL_TEXTURE_2D, 0);

        // Handle animation package

        if (part.animation != nullptr) {

            playAnimation(*part.animation);

            if (exitPending())

                break;

            continue; //to next part

        }

         glClearColor(

                    part.backgroundColor[0],

                   part.backgroundColor[1],

                    part.backgroundColor[2],

                    1.0f);

       

        for (int r=0 ; !part.count || r<part.count ; r++) {

           

            // Exit any non playuntil complete parts immediately

            if(exitPending() && !part.playUntilComplete)

                break;

           // part.backgroundColor[0]

           

           

            for (auto it = part.frames.begin() ; it != part.frames.end() && (!exitPending() || part.playUntilComplete) ; it++) {

                if (window.wait_for_configure) {

                    ret = wl_display_dispatch(window.display->display);//todo

                  //  continue;

                } else {

                    ret = wl_display_dispatch_pending(window.display->display);

                   

                }

                //

                if(mExitPending||ret == -1){

                    mExitPending = true;

                    if(ret ==-1)

                        LOGE(TAG,"wl_display_dispatch_pending ERR %d %s",errno,strerror(errno));

                    break;

                }

                if(mWidth != window.geometry.width || mHeight != window.geometry.height){

                    mWidth = window.geometry.width;

                    mHeight = window.geometry.height;

                    glViewport(0, 0, mWidth, mHeight);

                    glScissor(0, 0, mWidth, mHeight);

                }

                const int animationX = (mWidth - animation.width) / 2;

                const int animationY = (mHeight - animation.height) / 2;

                const Animation::Frame& frame(*it);

                nsecs_t lastFrame = systemTime();

                if (r > 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);

                  //  }

                    int w, h;

                 //  LOGD(TAG,"%d %d %d %d %s",mWidth,mHeight,frame.trimHeight,frame.trimWidth,frame.name.c_str());

                    initTexture(frame.map, &w, &h);

                    bool* ttt= (bool*)&(frame.tidDie);

                    *ttt = false;

                }

                const int xc = animationX + frame.trimX;

                const int yc = animationY + frame.trimY;

                #if gles2_bycy

                glClear(GL_COLOR_BUFFER_BIT);

                static float fade = 0.f;

                if(part.count ==0){

                    static bool shouldAdd = true;

                    if(shouldAdd){

                        fade += 0.01f;

                        if(fade>0.5f)

                            shouldAdd = false;

                    }else

                    {

                        fade -=0.01f;

                        if(fade<=0.f)

                            shouldAdd = true;

                    }

                }

               

                glUseProgram(mImageShader);

                  glUniform1i(mImageTextureLocation, 0);

                 glUniform1f(mImageFadeLocation, fade);

                //  if (animation.dynamicColoringEnabled) {

                    // glUniform1f(mImageColorProgressLocation, colorProgress);

               //   }

                  const int frameDrawY = mHeight - (yc + frame.trimHeight);

                  glEnable(GL_BLEND);

                  drawTexturedQuad(xc, frameDrawY, frame.trimWidth, frame.trimHeight);

                 glDisable(GL_BLEND);

                #else

               

                vector<RectBdCf> rects;

                if(xc>0)

                    rects.push_back(RectByCf(0,0,xc,mHeight));

                if( (xc+frame.trimWidth) < mWidth)

                    rects.push_back(RectBdCf(xc+frame.trimWidth,0,mWidth,mHeight));

                if(yc>0)

                    rects.push_back(RectBdCf(xc,0,xc+frame.trimWidth,yc));

                if( (yc+frame.trimHeight) < mHeight)

                    rects.push_back(RectBdCf(xc,yc+frame.trimHeight,xc+frame.trimWidth,mHeight));

                glEnable(GL_SCISSOR_TEST);

                for(int i = 0;i<rects.size();i++){

                    RectydCf& r2 = rects[i];

                    glScissor(r2.left, mHeight - r2.bottom, r2.width(), r2.height());

                    glClear(GL_COLOR_BUFFER_BIT);

                }

                glDisable(GL_SCISSOR_TEST);

               

               

                // specify the y center as ceiling((mHeight - frame.trimHeight) / 2)

                // which is equivalent to mHeight - (yc + frame.trimHeight)

                LOGD(TAG,"%d %d %d %d",mWidth,mHeight,frame.trimHeight,frame.trimWidth);

                glDrawTexiOES(xc, mHeight - (yc + frame.trimHeight),

                              0, frame.trimWidth, frame.trimHeight);

                if (mClockEnabled && mTimeIsAccurate && validClock(part)) {

                    drawClock(animation.clockFont, part.clockPosX, part.clockPosY);

                }

                handleViewport(frameDuration);

                #endif

           //     LOGI(TAG,"fCNT IS %d",i);

                eglSwapBuffers(window.display->egl.dpy, window.egl_surface);

                if(part.count!=0&&frame.tidDie==false){

                    glDeleteTextures(1, &frame.tid);

                    bool* ttt= (bool*)&(frame.tidDie);

                    *ttt = true;

                }

                nsecs_t now = systemTime();

                nsecs_t delay = frameDuration - (now - lastFrame);

                //SLOGD("%lld, %lld", ns2ms(now - lastFrame), ns2ms(delay));

                lastFrame = now;

                if (delay > 0) {

                    LOGD(TAG,"nanosleep %" PRId64,delay);

                    struct timespec spec;

                    spec.tv_sec  = (now + delay) / 1000000000;

                    spec.tv_nsec = (now + delay) % 1000000000;

                    int err;

                    do {

                        err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, nullptr);

                    } while (err<0 && errno == EINTR);

                }

               // LOGI(TAG,"chk exit %d",i);

               // checkExit();

            }

            usleep(part.pause * ns2us(frameDuration));

            // For infinite parts, we've now played them at least once, so perhaps exit

            if(exitPending() && !part.count && mCurrentInset >= mTargetInset)

                break;

        }

    }

    // Free textures created for looping parts now that the animation is done.

    for (const Animation::Part& part : animation.parts) {

       // if (part.count != 1) {

         

            for (auto it = part.frames.begin(); it != part.frames.end(); it++) {

                const Animation::Frame& frame(*it);

                if(frame.tidDie==false)

                    glDeleteTextures(1, &frame.tid);

            }

        //}

    }

    return true;

}

void BootAnimation_wayland::processDisplayEvents() {

    // This will poll mDisplayEventReceiver and if there are new events it'll call

    // displayEventCallback synchronously.

   // mLooper->pollOnce(0);

}

void BootAnimation_wayland::handleViewport(nsecs_t timestep) {

   

}

void BootAnimation_wayland::releaseAnimation(Animation* animation) const {

    for (vector<Animation::Part>::iterator it = animation->parts.begin();

        it != animation->parts.end(); ++it) {

        if (it->animation)

            releaseAnimation(it->animation);

    }

    if (animation->zip){

        delete animation->zip;

        animation->zip = nullptr;

    }

    delete animation;

}

BootAnimation_wayland::Animation* BootAnimation_wayland::loadAnimation(const string& fn) {

    if (mLoadedFiles.find(fn) != mLoadedFiles.end()) {

        LOGE(TAG,"File \"%s\" is already loaded. Cyclic ref is not allowed",

            fn.c_str());

        return nullptr;

    }

    ZipFileRO *zip = ZipFileRO::open(fn);

    if (zip == nullptr) {

        LOGE(TAG,"Failed to open animation zip \"%s\": %s",

            fn.c_str(), strerror(errno));

        return nullptr;

    }

    Animation *animation =  new Animation;

    animation->fileName = fn;

    animation->zip = zip;

    animation->clockFont.map = nullptr;

    mLoadedFiles.insert(animation->fileName);

    parseAnimationDesc(*animation);

   

    if (!preloadZip(*animation)) {

        releaseAnimation(animation);

        return nullptr;

    }

   

    mLoadedFiles.erase(fn);

   

    return animation;

}

bool BootAnimation_wayland::updateIsTimeAccurate() {

   

    return true;

}



 

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

} // namespace android

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无v邪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值