android编译opengl gles api测试

MainActivity.java

package pbbadd.opengl.gles30;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

public class MainActivity extends AppCompatActivity {
    private GLSurfaceView mGLSurfaceView;
    private GLES3Renderer mRenderer;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 1. 创建GLES3渲染视图(核心载体)
        mGLSurfaceView = new GLSurfaceView(this);
        // 2. 明确指定使用GLES 3.0版本(必加)
        mGLSurfaceView.setEGLContextClientVersion(3);
        // 3. 设置自定义渲染器,核心GLES3调用在渲染器中执行
        mRenderer = new GLES3Renderer();
        mGLSurfaceView.setRenderer(mRenderer);
        // 4. 设置渲染模式:仅绘制一次(满足「调用一次glBindBuffer」需求)
        mGLSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
        // 5. 显示渲染视图
        setContentView(mGLSurfaceView);


    }

    // ✅ 重写Activity销毁方法【时机2:兜底释放】
    // Activity退出时,主动触发渲染器的销毁逻辑,双重保障
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mGLSurfaceView != null) {
            // 终止GLES渲染线程,释放资源
            mGLSurfaceView.onPause();
            // 主动调用渲染器的销毁方法(在GL线程执行deinit)
            mRenderer.onDestroy();
        }
    }

    // ✅ 重写Activity暂停方法(规范GLES生命周期)
    @Override
    protected void onPause() {
        super.onPause();
        if (mGLSurfaceView != null) {
            mGLSurfaceView.onPause();
        }
    }

    // ✅ 重写Activity恢复方法(规范GLES生命周期)
    @Override
    protected void onResume() {
        super.onResume();
        if (mGLSurfaceView != null) {
            mGLSurfaceView.onResume();
        }
    }

    // 自定义GLES3渲染器,实现GLSurfaceView.Renderer接口
    private class GLES3Renderer implements GLSurfaceView.Renderer {
        // 回调1:GLES上下文创建时执行(仅执行一次,核心初始化入口)
        @Override
        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
            // 调用Native层C++代码,执行GLES3核心操作(含glBindBuffer)
            nativeTestInit();
            nativeTest2();
        }

        // 回调2:视图尺寸变化时执行
        @Override
        public void onSurfaceChanged(GL10 gl, int width, int height) {
            // 设置GLES视口大小
            nativeGLES3SetViewport(width/2, height/2);
        }

        // 回调3:每帧绘制时执行
        @Override
        public void onDrawFrame(GL10 gl) {
            nativeGLES3DrawFrame();
        }

        public void onDestroy() {
            // 用GLSurfaceView的队列,在GL线程执行释放(保证线程安全)
            mGLSurfaceView.queueEvent(MainActivity.this::nativeTestDeinit);
        }
    }

    // 声明Native方法(与C++层JNI绑定)
    static {
        System.loadLibrary("gles3copydemo"); // 加载CMake编译的so库
    }

    private native void nativeTestInit();
    private native void nativeTestDeinit();
    private native void nativeTest2();
    private native void nativeGLES3SetViewport(int width, int height);
    private native void nativeGLES3DrawFrame();
}

native-lib.cpp

#include <jni.h>
#include <string>
#include <GLES3/gl3.h> // GLES3.0核心头文件(必加)
#include <android/log.h>
#include <__random/mersenne_twister_engine.h>
#include <__random/uniform_real_distribution.h>
#include <__random/random_device.h>

// 日志宏定义,方便调试
#define TAG "GLES3_COPY_DEMO"
#define LOGE(fmt,...) __android_log_print(ANDROID_LOG_ERROR, TAG, "pbbadd,bufferwriterandomtest,%d," fmt, __LINE__, ##__VA_ARGS__)
#define LOGW(fmt,...) __android_log_print(ANDROID_LOG_WARN, TAG, "pbbadd,bufferwriterandomtest,%d," fmt, __LINE__, ##__VA_ARGS__)
#define LOGI(fmt,...) __android_log_print(ANDROID_LOG_INFO, TAG, "pbbadd,bufferwriterandomtest,%d," fmt, __LINE__, ##__VA_ARGS__)

static GLuint srcBufferNo = 9999;
static GLuint dstBufferNo=9999;
static GLenum err;
#define print_error_indent {err = glGetError(); if(GL_NO_ERROR!=err) LOGE("err=0x%x",err);}

// 全局变量:存储COPY_READ_BUFFER的缓冲ID
static GLuint g_copyReadBufferId = 0;

#define MIN_SIZE 12    // 整数随机最小值
#define MAX_SIZE 32*1024  // 整数随机最大值
static std::random_device rd;
static std::mt19937 gen(rd());
// 浮点数分布器:固定生成 0.0f ~ 1.0f 浮点数
static std::uniform_real_distribution<float> dis_f(0.0f, 1.0f);
// 整数分布器:生成 [MIN_SIZE, MAX_SIZE] 范围内的整数
static std::uniform_int_distribution<int> sizeDist(MIN_SIZE, MAX_SIZE);

void generateRandomData(GLubyte* data, int size) {
    for (int i = 0; i < size; i++) {
        data[i] = static_cast<GLubyte>(dis_f(gen) * 256.0f);
    }
}

static float getRandomFloat01() {
    return dis_f(gen);
}

static float getRandomFloat(float min, float max) {
    std::uniform_real_distribution<float> dis(min, max);
    return dis(gen);
}

static int getRandomSize() {
    return sizeDist(gen);
}

// ------------------------ JNI方法:GLES3初始化 ------------------------
// ------------------------ 适配新包名:pbbadd.opengl.gles30 ------------------------
extern "C" JNIEXPORT void JNICALL
Java_pbbadd_opengl_gles30_MainActivity_nativeGLES3Init(JNIEnv *env, jobject thiz) {
    LOGI("=== enter ==="); print_error_indent;

    glGenBuffers(1, &g_copyReadBufferId); print_error_indent;
    LOGI("id=%d",g_copyReadBufferId);

    glBindBuffer(GL_COPY_READ_BUFFER, g_copyReadBufferId); print_error_indent;

    GLsizeiptr bufferSize = 1024 * sizeof(GLfloat);
    glBufferData(GL_COPY_READ_BUFFER, bufferSize, nullptr, GL_STATIC_READ); print_error_indent;
    LOGI("bufferSize=%ld", bufferSize);

    glDeleteBuffers(1,&g_copyReadBufferId);

    LOGI("=== finish ===");
}

extern "C" JNIEXPORT void JNICALL
Java_pbbadd_opengl_gles30_MainActivity_nativeTestInit(JNIEnv *env, jobject thiz) {
    glGenBuffers(1,&srcBufferNo); print_error_indent;
    glGenBuffers(1,&dstBufferNo); print_error_indent;
    LOGW("glGenBuffers done");
}

extern "C" JNIEXPORT void JNICALL
Java_pbbadd_opengl_gles30_MainActivity_nativeTestDeinit(JNIEnv *env, jobject thiz) {
    glDeleteBuffers(1,&srcBufferNo); print_error_indent;
    glDeleteBuffers(1,&dstBufferNo); print_error_indent;
    LOGW("glDeleteBuffers done");
}

extern "C" JNIEXPORT void JNICALL
Java_pbbadd_opengl_gles30_MainActivity_nativeTest2(JNIEnv *env, jobject thiz) {
    int srcSize = sizeDist(gen);
    int dstSize = srcSize;
    GLubyte *srcData = new GLubyte[srcSize]();
    GLubyte *dstData = new GLubyte[dstSize]();
    generateRandomData(srcData,srcSize);

    glBindBuffer(GL_COPY_READ_BUFFER, srcBufferNo); print_error_indent;
    glBufferData(GL_COPY_READ_BUFFER,srcSize,srcData,GL_STREAM_DRAW); print_error_indent;

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,srcBufferNo); print_error_indent;
    glBufferSubData(GL_ELEMENT_ARRAY_BUFFER,0,srcSize,srcData); print_error_indent;
    glBufferSubData(GL_ELEMENT_ARRAY_BUFFER,0,srcSize,srcData); print_error_indent;
    glBindBuffer(GL_ARRAY_BUFFER,srcBufferNo); print_error_indent;
    glBufferSubData(GL_ARRAY_BUFFER,0,srcSize,srcData); print_error_indent;
    glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER,srcBufferNo); print_error_indent;
    glBufferSubData(GL_TRANSFORM_FEEDBACK_BUFFER,0,srcSize,srcData); print_error_indent;
    glBindBuffer(GL_UNIFORM_BUFFER,srcBufferNo); print_error_indent;
    glBufferSubData(GL_UNIFORM_BUFFER,0,srcSize,srcData); print_error_indent;
    glBindBuffer(GL_PIXEL_UNPACK_BUFFER,srcBufferNo); print_error_indent;
    glBufferSubData(GL_PIXEL_UNPACK_BUFFER,0,srcSize,srcData); print_error_indent;

    LOGI("finish");
};

extern "C" JNIEXPORT void JNICALL
Java_pbbadd_opengl_gles30_MainActivity_nativeGLES3SetViewport(JNIEnv *env, jobject thiz, jint width, jint height) {
    glViewport(0, 0, width, height); print_error_indent;
    LOGI("w=%d, h=%d", width, height);
}

extern "C" JNIEXPORT void JNICALL
Java_pbbadd_opengl_gles30_MainActivity_nativeGLES3DrawFrame(JNIEnv *env, jobject thiz) {
    glClearColor(0.5f, 0.5f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    print_error_indent;
    LOGI("=== clear background ===");
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.22.1)
project("gles3copydemo")

# 1. 添加C++源文件编译成共享库
add_library(
        gles3copydemo # so库名称,与Java层System.loadLibrary对应
        SHARED
        native-lib.cpp) # 核心C++源文件

# 2. 链接GLES3.0库(必加,否则无法调用gl3.h接口)
find_library(
        GLES3-lib
        GLESv3)

# 3. 链接日志库(打印调试信息)
find_library(
        log-lib
        log)

# 4. 关联库文件
target_link_libraries(
        gles3copydemo
        ${GLES3-lib}
        ${log-lib})

# 适配Android15 16KB设备 + 解决LLD编译报错,兼容NDK23/25/26/27+
if(${ANDROID_ABI} STREQUAL "arm64-v8a")
    set_target_properties(gles3copydemo PROPERTIES
            # LLD专用参数:实现16KB(0x4000)页面对齐(替代废弃的--page-size)
            LINK_FLAGS "-z common-page-size=0x4000 -z max-page-size=0x4000 -Wl,--emit-relocs"
    )
endif()

# 全局加固配置(保留,提升SO库安全性)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,-z,relro,-z,now")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,relro,-z,now")

build.gradle

plugins {
    alias(libs.plugins.android.application)
}

android {
    namespace 'pbbadd.opengl.gles30'
    compileSdk 36

    defaultConfig {
        applicationId "pbbadd.opengl.gles30"
        minSdk 34
        targetSdk 36
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

        // 1. 配置NDK,指定支持的架构
        ndk {
            abiFilters 'arm64-v8a', 'armeabi-v7a'
        }
        // 2. 配置CMake构建
        externalNativeBuild {
            cmake {
                cppFlags '-std=c++17' // C++17标准
                arguments "-DANDROID_PLATFORM=android-26", "-DANDROID_STL=c++_shared"
            }
        }
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_11
        targetCompatibility JavaVersion.VERSION_11
    }
    // 3. 指定CMake脚本路径
    externalNativeBuild {
        cmake {
            path file('src/main/cpp/CMakeLists.txt')
            version '3.22.1'
        }
    }
}

dependencies {

    implementation libs.appcompat
    implementation libs.material
    implementation libs.activity
    implementation libs.constraintlayout
    testImplementation libs.junit
    androidTestImplementation libs.ext.junit
    androidTestImplementation libs.espresso.core
}

gitee链接

https://gitee.com/ampbb/opengl-gles3-api-test

posted @ 2026-01-12 10:51  cacarrot  阅读(12)  评论(0)    收藏  举报