Android native 层用OpenGL ES在屏幕模拟流水灯

2023-11-12

Android native 层用OpenGL ES在屏幕模拟流水灯

Native C开发OpenGL

 参照Android开机动画,自己实现了在native层模拟led流水灯的代码。
 Android本身OpenGL的参考代码在/frameworks/native/opengl/tests下,
 但是做出来的效果不是自己想要的,参考网友资料,特记录如下;

源码实现如下

Simled.cpp

#define LOG_NDEBUG 0
#define LOG_TAG "Simled"

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

#include <cutils/properties.h>

#include <androidfw/AssetManager.h>
#include <binder/IPCThreadState.h>
#include <utils/Atomic.h>
#include <utils/Errors.h>
#include <utils/Log.h>

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

#include <gui/ISurfaceComposer.h>
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>

#include <SkBitmap.h>
#include <SkStream.h>
#include <SkImageDecoder.h>

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

#include "Simled.h"

#define EXIT_PROP_NAME "service.bootanim.exit"

#define SIMLED_W 30
#define SIMLED_H 40

extern "C" int clock_nanosleep(clockid_t clock_id, int flags,
                           const struct timespec *request,
                           struct timespec *remain);

namespace android {


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

Simled::Simled() : Thread(false)
{
    mSession = new SurfaceComposerClient();
}

Simled::~Simled() {
}

void Simled::onFirstRef() {
    status_t err = mSession->linkToComposerDeath(this);
    ALOGE_IF(err, "linkToComposerDeath failed (%s) ", strerror(-err));
    if (err == NO_ERROR) {
        run("Simled", PRIORITY_DISPLAY);
    }
}

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


void Simled::binderDied(const wp<IBinder>&)
{
    // woah, surfaceflinger died!
    ALOGD("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();
}

status_t Simled::readyToRun() {
    // initialize opengl and egl
    const EGLint attribs[] = {
            EGL_ALPHA_SIZE, 8,
            EGL_RED_SIZE,   8,
            EGL_GREEN_SIZE, 8,
            EGL_BLUE_SIZE,  8,
            EGL_DEPTH_SIZE, 0,
            EGL_NONE
    };
    EGLint numConfigs;
    EGLConfig config;
    EGLContext context;

    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);

    eglInitialize(display, 0, 0);
    eglChooseConfig(display, attribs, &config, 1, &numConfigs);
    context = eglCreateContext(display, config, NULL, NULL);

    mDisplay = display;
    mContext = context;

    // init the leds
    for(int i = 0; i < 4; i++){
        // create the native surface
        String8 name("Simled");
        const char index = '0'+(char)i;
        name.append(&index);
        sp<SurfaceControl> control = session()->createSurface(name,
                SIMLED_W, SIMLED_H, PIXEL_FORMAT_RGBA_8888);

        SurfaceComposerClient::openGlobalTransaction();
        control->setLayer(0x40000000);
        // set led position
        control->setPosition(i * SIMLED_W * 2, 0);
        SurfaceComposerClient::closeGlobalTransaction();

        sp<Surface> s = control->getSurface();

        EGLSurface surface;
        EGLint w, h;
        surface = eglCreateWindowSurface(display, config, s.get(), NULL);
        eglQuerySurface(display, surface, EGL_WIDTH, &w);
        eglQuerySurface(display, surface, EGL_HEIGHT, &h);

        mWidth = w;
        mHeight = h;


        // set led color
        mLeds[i].r = i==0 ? 1.0f : 0.0f;
        mLeds[i].g = i==1 ? 1.0f : 0.0f;
        mLeds[i].b = i==2 ? 1.0f : 0.0f;

        mLeds[i].surface = surface;
        mLeds[i].flingerSurfaceControl = control;
        mLeds[i].flingerSurface = s;
    }

    return NO_ERROR;
}

bool Simled::threadLoop()
{
    bool r;
    drawLeds();
    for(int i = 0; i < 2; i++){
        r = test();
    }

    // exit
    requestExit();
    eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
    eglDestroyContext(mDisplay, mContext);
    for(int i = 0; i < 4; i++){
        eglDestroySurface(mDisplay, mLeds[i].surface);
        mLeds[i].flingerSurface.clear();
        mLeds[i].flingerSurfaceControl.clear();
    }
    eglTerminate(mDisplay);
    IPCThreadState::self()->stopProcess();
    return r;
}

bool Simled::drawLeds()
{
    for(int i = 0; i < 4; i++){
        if (eglMakeCurrent(mDisplay, mLeds[i].surface, mLeds[i].surface, mContext) == EGL_FALSE)
            return false;

        // clear screen
        glShadeModel(GL_FLAT);
        glDisable(GL_DITHER);
        glDisable(GL_SCISSOR_TEST);
        glDisable(GL_BLEND);
        glClearColor(
            mLeds[i].r,
            mLeds[i].g,
            mLeds[i].b,
            1);
        glClear(GL_COLOR_BUFFER_BIT);

        eglSwapBuffers(mDisplay, mLeds[i].surface);
    }

    return false;
}

bool Simled::showLed(int index){
        SurfaceComposerClient::openGlobalTransaction();
        mLeds[index].flingerSurfaceControl->show();
        SurfaceComposerClient::closeGlobalTransaction();
    return true;
}

bool Simled::hideLed(int index){
        SurfaceComposerClient::openGlobalTransaction();
        mLeds[index].flingerSurfaceControl->hide();
        SurfaceComposerClient::closeGlobalTransaction();
    return true;
}

bool Simled::test()
{
    for(int i = 0; i < 4; i++){
        hideLed(i);
        usleep(1*1000000);
        showLed(i);
    }
    return false;
}
// ---------------------------------------------------------------------------

}
; // namespace android

Simled_main.cpp:


#define LOG_TAG "Simled"

#include <cutils/properties.h>

#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>

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

#if defined(HAVE_PTHREADS)
# include <pthread.h>
# include <sys/resource.h>
#endif

#include "Simled.h"

using namespace android;

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

int main(int argc, char** argv)
{
#if defined(HAVE_PTHREADS)
    setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_DISPLAY);
#endif

    sp<ProcessState> proc(ProcessState::self());
    ProcessState::self()->startThreadPool();

    sp<Simled> led = new Simled();

    IPCThreadState::self()->joinThreadPool();

    return 0;
}

Simled.h:



#ifndef ANDROID_SIMLED_H
#define ANDROID_SIMLED_H

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

#include <androidfw/AssetManager.h>
#include <utils/Thread.h>

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

class SkBitmap;

namespace android {

class Surface;
class SurfaceComposerClient;
class SurfaceControl;

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

class Simled : public Thread, public IBinder::DeathRecipient
{
public:
    enum {
        eOrientationDefault     = 0,
        eOrientation90          = 1,
        eOrientation180         = 2,
        eOrientation270         = 3,
    };
                Simled();
    virtual     ~Simled();

    sp<SurfaceComposerClient> session() const;

private:
    virtual bool        threadLoop();
    virtual status_t    readyToRun();
    virtual void        onFirstRef();
    virtual void        binderDied(const wp<IBinder>& who);

    struct Led {
        GLclampf r;
        GLclampf g;
        GLclampf b;
        EGLSurface  surface;
        sp<SurfaceControl> flingerSurfaceControl;
        sp<Surface> flingerSurface;
    };

    bool drawLeds();
    bool showLed(int index);
    bool hideLed(int index);
    bool test();

    sp<SurfaceComposerClient>       mSession;
    int         mWidth;
    int         mHeight;
    EGLDisplay  mDisplay;
    EGLContext  mContext;
    Led         mLeds[4];
};

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

}; // namespace android

#endif // ANDROID_SIMLED_H

Android.mk:


LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= \
	simled_main.cpp \
	Simled.cpp

LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES

LOCAL_C_INCLUDES += external/tinyalsa/include

LOCAL_SHARED_LIBRARIES := \
	libcutils \
	liblog \
	libandroidfw \
	libutils \
	libbinder \
    libui \
	libskia \
    libEGL \
    libGLESv1_CM \
    libgui \
    libtinyalsa \
    libmedia

LOCAL_MODULE:= simled

ifdef TARGET_32_BIT_SURFACEFLINGER
LOCAL_32_BIT_ONLY := true
endif

include $(BUILD_EXECUTABLE)

源码中涉及了Android-Binder进程间通讯机制 ,本人小白,刚入门Android学习,等学有所成再补上这部分知识。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android native 层用OpenGL ES在屏幕模拟流水灯 的相关文章

随机推荐