• Android下基于SDL的位图渲染(二)理论篇


    理论篇

    上一篇中介绍了如何将SDL2源码应用到Android渲染中,实际上SDL本身提供的android-project实现了基于android的c运行时环境,通过上面实践篇的介绍,就是完成这个环境搭建的过程。
    这样就不需要过多关注Android的Activity框架及图像渲染机制。
    更加详细关于这部分的介绍建议参考Building SDL2 for Android
    其中最关键的部分在于org.libsdl.app.SDLActivity的实现,当然涉及视频渲染需要SurfaceView支持,所有代码位于SDLActivity.java,SDLSurface就是继承与此。我们的最终的main函数的调用时通过class SDLMain实现的。
    其基本调用流程是SDLSurface.surfaceChanged()启动SDLMain线程,SDLMain的线程函数执行SDLActivity的nativeInit()。这样就把java层的代码和渲染工作转交给c/c++层去实现,其他Android事件处理由SDL完成。
    我们看下SDLActivity.nativeInit()的代码(位于SDL2-src/src/main/android/SDL_android_main.c中)

    #include <jni.h>
    
    /* Called before SDL_main() to initialize JNI bindings in SDL library */
    extern void SDL_Android_Init(JNIEnv* env, jclass cls);
    
    /* Start up the SDL app */
    JNIEXPORT int JNICALL Java_org_libsdl_app_SDLActivity_nativeInit(JNIEnv* env, jclass cls, jobject array)
    {
        int i;
        int argc;
        int status;
    
        /* This interface could expand with ABI negotiation, callbacks, etc. */
        SDL_Android_Init(env, cls);
    
        SDL_SetMainReady();
    
        /* Prepare the arguments. */
    
        int len = (*env)->GetArrayLength(env, array);
        char* argv[1 + len + 1];
        argc = 0;
        /* Use the name "app_process" so PHYSFS_platformCalcBaseDir() works.
           https://bitbucket.org/MartinFelis/love-android-sdl2/issue/23/release-build-crash-on-start
         */
        argv[argc++] = SDL_strdup("app_process");
        for (i = 0; i < len; ++i) {
            const char* utf;
            char* arg = NULL;
            jstring string = (*env)->GetObjectArrayElement(env, array, i);
            if (string) {
                utf = (*env)->GetStringUTFChars(env, string, 0);
                if (utf) {
                    arg = SDL_strdup(utf);
                    (*env)->ReleaseStringUTFChars(env, string, utf);
                }
                (*env)->DeleteLocalRef(env, string);
            }
            if (!arg) {
                arg = SDL_strdup("");
            }
            argv[argc++] = arg;
        }
        argv[argc] = NULL;
    
    
        /* Run the application. */
    
        status = SDL_main(argc, argv);
    
        /* Release the arguments. */
    
        for (i = 0; i < argc; ++i) {
            SDL_free(argv[i]);
        }
    
        /* Do not issue an exit or the whole application will terminate instead of just the SDL thread */
        /* exit(status); */
    
        return status;
    }
    

    功能很简单,初始化SDL在Android下的参数,获取命令行参数,执行SDL_main()。
    也许大家会感觉比较奇怪,在main.c中命名写的main函数啊,SDL_main为何物?
    这个问题我也纠结了一段时间,直接找不到SDL_main的实现,哪就源码中全局搜索SDL_main吧。看看结果:

    sdl2/CMakeLists.txt:1146:    set(SDL_CFLAGS "${SDL_CFLAGS} -Dmain=SDL_main")
    sdl2/configure.in:3123:        SDL_CFLAGS="$SDL_CFLAGS -Dmain=SDL_main"
    

    其他全是关于SDL_main的调用或者声明,只有这两个靠谱点。查查GCC的命令,-Dmain=SDL_main,这个就是编译的时候定义宏,等价于:
    #define SDL_main main

    好了,到这里就搞清楚了,SDL2提供的android-project如何把Activity和c的main通过JNI串联起来的。

    最后说一点,为什么我们写的c的main函数退出了,对应的Activity也退出了呢?
    这就是SDL_Quit通过内部消息机制,主动通知Activity退出的。当然具体的实现可能涉及太多SDL内部的内容,有兴趣的可以直接查看SDL_Quit的实现部分。

    关于SDL渲染BMP的原理,我之前写过windows下的使用SDL实现BMP渲染,原理是类似的。这里不赘述了,代码也相对简单。

    附加说明

    本文主要参考以下部分:

    源码下载

    本文中涉及所有源码可以从我的git@OSC,下载之后需要切换到bmp_render的tag即可。

  • 相关阅读:
    聊聊tcpdump与Wireshark抓包分析
    TCP三次握手与Tcpdump抓包分析过程
    grep 同时满足多个关键字和满足任意关键字
    java监听器原理理解与实现
    Linux下如何查看哪些端口处于监听状态
    netstat命令怎么查看端口是否占用
    jQuery Mobile 入门基础教程
    用U盘与移动硬盘制作WIN7启动盘(亲自实践)
    【iOS】用Layer创建一个三维模型以及拖动
    Java中的位运算符、移位运算
  • 原文地址:https://www.cnblogs.com/tocy/p/android-sdl-bitmap-render-theory.html
Copyright © 2020-2023  润新知