opengl图像处理

复制代码
#ifndef ADVANCED_OPENGL_PROCESSOR_H
#define ADVANCED_OPENGL_PROCESSOR_H

#include <android/native_window.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES3/gl3.h>
#include <GLES3/gl3ext.h>
#include <vector>
#include <atomic>
#include <mutex>
#include <functional>
#include <memory>

// 图像格式定义
enum class PixelFormat {
    RGBA8,      // 32位RGBA
    RGB8,       // 24位RGB
    RGBA16F,    // 半精度浮点
    RGBA32F,    // 单精度浮点
    YUV_NV21,   // Android相机格式
    YUV_NV12
};

// 变换参数
struct TransformParams {
    float rotationAngle = 0.0f;      // 旋转角度(度数)
    float scaleX = 1.0f;             // X轴缩放
    float scaleY = 1.0f;             // Y轴缩放
    float pivotX = 0.5f;             // 旋转中心X(0-1)
    float pivotY = 0.5f;             // 旋转中心Y(0-1)
    float translateX = 0.0f;         // X轴平移
    float translateY = 0.0f;         // Y轴平移
    bool keepAspectRatio = true;     // 保持宽高比
    bool bilinearFilter = true;      // 双线性过滤
    bool cropToInputSize = false;    // 裁剪到输入尺寸
};

// 性能统计
struct PerformanceMetrics {
    double gpuTimeMs = 0.0;          // GPU处理时间
    double uploadTimeMs = 0.0;       // 数据上传时间
    double downloadTimeMs = 0.0;     // 数据下载时间
    double totalTimeMs = 0.0;        // 总处理时间
    int32_t frameCount = 0;          // 处理帧数
    double averageFps = 0.0;         // 平均帧率
    size_t memoryUsedMB = 0;         // 显存使用量
    int32_t lastOutputWidth = 0;     // 上次输出宽度
    int32_t lastOutputHeight = 0;    // 上次输出高度
};

// 计算包围盒结果
struct BoundingBox {
    int32_t width;
    int32_t height;
    float offsetX;
    float offsetY;
};

class AdvancedOpenGLProcessor {
public:
    using FrameCallback = std::function<void(const uint8_t* data, int width, int height, 
                                            PixelFormat format)>;
    
    AdvancedOpenGLProcessor();
    ~AdvancedOpenGLProcessor();
    
    // 初始化
    bool initialize(ANativeWindow* window, PixelFormat format = PixelFormat::RGBA8);
    
    // 单帧处理
    bool processFrame(const uint8_t* inputData, int inputWidth, int inputHeight,
                     uint8_t* outputData, int* outputWidth, int* outputHeight);
    
    // 连续处理
    void startContinuousProcessing(FrameCallback callback);
    void stopContinuousProcessing();
    
    // 批量处理
    bool processBatch(const std::vector<const uint8_t*>& inputFrames,
                     int width, int height,
                     std::vector<uint8_t*>& outputFrames);
    
    // 设置变换参数
    void setTransformParams(const TransformParams& params);
    
    // 设置输出尺寸(自动或手动)
    void setOutputSize(int width, int height, bool autoCrop = false);
    
    // 性能优化接口
    void enableAsyncProcessing(bool enable);
    void enableGPUTiming(bool enable);
    void setMaxTextureSize(int maxSize);
    void setUsePBO(bool use) { mUsePBO = use; }
    
    // 资源管理
    void trimMemory();
    void flushPipeline();
    
    // 查询信息
    PerformanceMetrics getPerformanceMetrics() const;
    bool isInitialized() const { return mInitialized; }
    
    // 获取变换后的包围盒
    BoundingBox calculateBoundingBox(int inputWidth, int inputHeight) const;
    
    // 清理
    void cleanup();

private:
    // EGL资源
    EGLDisplay mEglDisplay;
    EGLSurface mEglSurface;
    EGLContext mEglContext;
    ANativeWindow* mNativeWindow;
    bool mInitialized;
    bool mUsePBO;
    
    // OpenGL资源
    GLuint mProgram;
    GLuint mFramebuffer;
    GLuint mInputTexture;
    GLuint mOutputTexture;
    GLuint mVAO;
    GLuint mVBO;
    GLuint mEBO;
    GLuint mPBO[2];
    int mCurrentPBOIndex;
    
    // 着色器变量位置
    struct {
        GLint transformMatrix;
        GLint textureSize;
        GLint pivotPoint;
        GLint useBilinear;
        GLint cropEnabled;
        GLint cropRect;
    } mUniformLocations;
    
    // 变换参数
    TransformParams mTransformParams;
    mutable std::mutex mTransformMutex;
    
    // 输出尺寸
    int mOutputWidth;
    int mOutputHeight;
    bool mAutoCalculateSize;
    
    // 性能统计
    PerformanceMetrics mPerformanceMetrics;
    mutable std::mutex mStatsMutex;
    
    // 内部方法
    bool compileShaders();
    bool createFramebuffer(int width, int height);
    bool createPBOs(int width, int height);
    GLuint createTexture(int width, int height, PixelFormat format);
    void updateUniforms(int inputWidth, int inputHeight);
    void calculateTransformMatrix(float matrix[16], int inputWidth, int inputHeight) const;
    void readPixelsAsync(uint8_t* outputData, int width, int height);
    void readPixelsSync(uint8_t* outputData, int width, int height);
    void updatePerformanceMetrics(int64_t uploadTime, int64_t processTime, int64_t downloadTime);
    
    // 时间测量
    class Timer {
    public:
        void start() { 
            clock_gettime(CLOCK_MONOTONIC, &mStartTime); 
        }
        
        int64_t elapsedMicroseconds() const {
            timespec endTime;
            clock_gettime(CLOCK_MONOTONIC, &endTime);
            return (endTime.tv_sec - mStartTime.tv_sec) * 1000000LL +
                   (endTime.tv_nsec - mStartTime.tv_nsec) / 1000LL;
        }
        
    private:
        timespec mStartTime;
    };
};

#endif // ADVANCED_OPENGL_PROCESSOR_H

#include "advanced_opengl_processor.h"
#include <android/log.h>
#include <cmath>
#include <cstring>
#include <unistd.h>
#include <time.h>

#define LOG_TAG "GLProcessor"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)

// 着色器代码
const char* VERTEX_SHADER_SOURCE = R"(
    #version 300 es
    precision highp float;
    
    layout(location = 0) in vec2 aPosition;
    layout(location = 1) in vec2 aTexCoord;
    
    out vec2 vTexCoord;
    
    uniform mat4 uTransformMatrix;
    uniform vec2 uTextureSize;
    uniform vec2 uPivotPoint;
    uniform int uCropEnabled;
    uniform vec4 uCropRect; // x, y, width, height
    
    void main() {
        // 应用变换矩阵
        vec4 transformedPos = uTransformMatrix * vec4(aPosition, 0.0, 1.0);
        
        // 处理裁剪
        if (uCropEnabled == 1) {
            // 将裁剪区域映射到[-1, 1]
            vec2 normalizedPos = (transformedPos.xy + 1.0) * 0.5;
            normalizedPos = (normalizedPos - uCropRect.xy) / uCropRect.zw;
            normalizedPos = normalizedPos * 2.0 - 1.0;
            gl_Position = vec4(normalizedPos, 0.0, 1.0);
        } else {
            gl_Position = transformedPos;
        }
        
        vTexCoord = aTexCoord;
    }
)";

const char* FRAGMENT_SHADER_SOURCE = R"(
    #version 300 es
    precision highp float;
    
    in vec2 vTexCoord;
    out vec4 fragColor;
    
    uniform sampler2D uTexture;
    uniform vec2 uTextureSize;
    uniform int uUseBilinear;
    
    // 双线性插值
    vec4 texture2DBilinear(sampler2D tex, vec2 uv, vec2 texSize) {
        vec2 texelCoord = uv * texSize - 0.5;
        vec2 f = fract(texelCoord);
        vec2 baseCoord = floor(texelCoord);
        
        vec4 tex00 = texture(tex, (baseCoord + vec2(0.5, 0.5)) / texSize);
        vec4 tex10 = texture(tex, (baseCoord + vec2(1.5, 0.5)) / texSize);
        vec4 tex01 = texture(tex, (baseCoord + vec2(0.5, 1.5)) / texSize);
        vec4 tex11 = texture(tex, (baseCoord + vec2(1.5, 1.5)) / texSize);
        
        vec4 tex0 = mix(tex00, tex10, f.x);
        vec4 tex1 = mix(tex01, tex11, f.x);
        
        return mix(tex0, tex1, f.y);
    }
    
    // Lanczos滤波(高质量缩放)
    vec4 texture2DLanczos(sampler2D tex, vec2 uv, vec2 texSize) {
        const float PI = 3.14159265359;
        const int TAPS = 2; // Lanczos窗口大小
        
        vec2 texelCoord = uv * texSize;
        vec2 fractCoord = fract(texelCoord);
        vec2 baseCoord = floor(texelCoord) - float(TAPS - 1);
        
        vec4 sum = vec4(0.0);
        float totalWeight = 0.0;
        
        for (int i = 0; i < TAPS * 2; i++) {
            for (int j = 0; j < TAPS * 2; j++) {
                vec2 sampleCoord = baseCoord + vec2(float(i), float(j));
                vec2 sampleUV = sampleCoord / texSize;
                
                if (sampleUV.x >= 0.0 && sampleUV.x <= 1.0 && 
                    sampleUV.y >= 0.0 && sampleUV.y <= 1.0) {
                    
                    float dx = (sampleCoord.x + 0.5) - texelCoord.x;
                    float dy = (sampleCoord.y + 0.5) - texelCoord.y;
                    
                    // Lanczos函数
                    float lanczos(float x) {
                        if (x == 0.0) return 1.0;
                        if (abs(x) >= float(TAPS)) return 0.0;
                        float pix = PI * x;
                        return (TAPS * sin(pix) * sin(pix / float(TAPS))) / (pix * pix);
                    }
                    
                    float weight = lanczos(dx) * lanczos(dy);
                    sum += texture(tex, sampleUV) * weight;
                    totalWeight += weight;
                }
            }
        }
        
        return totalWeight > 0.0 ? sum / totalWeight : texture(tex, uv);
    }
    
    void main() {
        vec2 clampedCoord = clamp(vTexCoord, 0.0, 1.0);
        
        if (uUseBilinear == 1) {
            fragColor = texture2DBilinear(uTexture, clampedCoord, uTextureSize);
        } else if (uUseBilinear == 2) {
            // 高质量缩放模式
            fragColor = texture2DLanczos(uTexture, clampedCoord, uTextureSize);
        } else {
            fragColor = texture(uTexture, clampedCoord);
        }
        
        // Alpha预乘(如果使用RGBA)
        fragColor.rgb *= fragColor.a;
    }
)";

AdvancedOpenGLProcessor::AdvancedOpenGLProcessor()
    : mEglDisplay(EGL_NO_DISPLAY)
    , mEglSurface(EGL_NO_SURFACE)
    , mEglContext(EGL_NO_CONTEXT)
    , mNativeWindow(nullptr)
    , mInitialized(false)
    , mUsePBO(true)
    , mProgram(0)
    , mFramebuffer(0)
    , mInputTexture(0)
    , mOutputTexture(0)
    , mVAO(0)
    , mVBO(0)
    , mEBO(0)
    , mCurrentPBOIndex(0)
    , mOutputWidth(0)
    , mOutputHeight(0)
    , mAutoCalculateSize(true) {
    
    memset(mPBO, 0, sizeof(mPBO));
    memset(&mUniformLocations, 0, sizeof(mUniformLocations));
    
    // 默认变换参数
    mTransformParams = TransformParams();
}

AdvancedOpenGLProcessor::~AdvancedOpenGLProcessor() {
    cleanup();
}

bool AdvancedOpenGLProcessor::initialize(ANativeWindow* window, PixelFormat format) {
    if (!window) {
        LOGE("Invalid window");
        return false;
    }
    
    mNativeWindow = window;
    
    // 1. 获取EGL显示
    mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    if (mEglDisplay == EGL_NO_DISPLAY) {
        LOGE("Failed to get EGL display");
        return false;
    }
    
    // 2. 初始化EGL
    EGLint major, minor;
    if (!eglInitialize(mEglDisplay, &major, &minor)) {
        LOGE("Failed to initialize EGL");
        return false;
    }
    
    // 3. 选择配置
    EGLint configAttribs[] = {
        EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT,
        EGL_RED_SIZE, 8,
        EGL_GREEN_SIZE, 8,
        EGL_BLUE_SIZE, 8,
        EGL_ALPHA_SIZE, 8,
        EGL_DEPTH_SIZE, 0,
        EGL_STENCIL_SIZE, 0,
        EGL_NONE
    };
    
    EGLConfig config;
    EGLint numConfigs;
    if (!eglChooseConfig(mEglDisplay, configAttribs, &config, 1, &numConfigs)) {
        LOGE("Failed to choose EGL config");
        return false;
    }
    
    // 4. 创建EGL表面
    mEglSurface = eglCreateWindowSurface(mEglDisplay, config, window, nullptr);
    if (mEglSurface == EGL_NO_SURFACE) {
        LOGE("Failed to create EGL surface");
        return false;
    }
    
    // 5. 创建OpenGL ES 3.0上下文
    EGLint contextAttribs[] = {
        EGL_CONTEXT_CLIENT_VERSION, 3,
        EGL_NONE
    };
    
    mEglContext = eglCreateContext(mEglDisplay, config, EGL_NO_CONTEXT, contextAttribs);
    if (mEglContext == EGL_NO_CONTEXT) {
        LOGE("Failed to create EGL context");
        return false;
    }
    
    // 6. 绑定上下文
    if (!eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
        LOGE("Failed to make EGL context current");
        return false;
    }
    
    // 7. 设置交换间隔为0以获得最大性能
    eglSwapInterval(mEglDisplay, 0);
    
    // 8. 编译着色器
    if (!compileShaders()) {
        LOGE("Failed to compile shaders");
        return false;
    }
    
    mInitialized = true;
    LOGI("OpenGL ES 3.0 initialized successfully");
    return true;
}

bool AdvancedOpenGLProcessor::compileShaders() {
    // 创建顶点着色器
    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &VERTEX_SHADER_SOURCE, nullptr);
    glCompileShader(vertexShader);
    
    GLint success;
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
    if (!success) {
        GLchar infoLog[512];
        glGetShaderInfoLog(vertexShader, 512, nullptr, infoLog);
        LOGE("Vertex shader compilation failed: %s", infoLog);
        return false;
    }
    
    // 创建片段着色器
    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &FRAGMENT_SHADER_SOURCE, nullptr);
    glCompileShader(fragmentShader);
    
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
    if (!success) {
        GLchar infoLog[512];
        glGetShaderInfoLog(fragmentShader, 512, nullptr, infoLog);
        LOGE("Fragment shader compilation failed: %s", infoLog);
        return false;
    }
    
    // 创建着色器程序
    mProgram = glCreateProgram();
    glAttachShader(mProgram, vertexShader);
    glAttachShader(mProgram, fragmentShader);
    glLinkProgram(mProgram);
    
    glGetProgramiv(mProgram, GL_LINK_STATUS, &success);
    if (!success) {
        GLchar infoLog[512];
        glGetProgramInfoLog(mProgram, 512, nullptr, infoLog);
        LOGE("Shader program linking failed: %s", infoLog);
        return false;
    }
    
    // 删除着色器对象
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);
    
    // 获取uniform位置
    glUseProgram(mProgram);
    mUniformLocations.transformMatrix = glGetUniformLocation(mProgram, "uTransformMatrix");
    mUniformLocations.textureSize = glGetUniformLocation(mProgram, "uTextureSize");
    mUniformLocations.pivotPoint = glGetUniformLocation(mProgram, "uPivotPoint");
    mUniformLocations.useBilinear = glGetUniformLocation(mProgram, "uUseBilinear");
    mUniformLocations.cropEnabled = glGetUniformLocation(mProgram, "uCropEnabled");
    mUniformLocations.cropRect = glGetUniformLocation(mProgram, "uCropRect");
    
    // 创建顶点数据
    float vertices[] = {
        // 位置           // 纹理坐标
        -1.0f, -1.0f,    0.0f, 0.0f,  // 左下
         1.0f, -1.0f,    1.0f, 0.0f,  // 右下
        -1.0f,  1.0f,    0.0f, 1.0f,  // 左上
         1.0f,  1.0f,    1.0f, 1.0f   // 右上
    };
    
    unsigned int indices[] = {
        0, 1, 2,  // 第一个三角形
        1, 3, 2   // 第二个三角形
    };
    
    // 创建VAO、VBO和EBO
    glGenVertexArrays(1, &mVAO);
    glGenBuffers(1, &mVBO);
    glGenBuffers(1, &mEBO);
    
    glBindVertexArray(mVAO);
    
    glBindBuffer(GL_ARRAY_BUFFER, mVBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mEBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
    
    // 位置属性
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);
    
    // 纹理坐标属性
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 
                         (void*)(2 * sizeof(float)));
    glEnableVertexAttribArray(1);
    
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);
    
    LOGI("Shaders compiled successfully");
    return true;
}

BoundingBox AdvancedOpenGLProcessor::calculateBoundingBox(int inputWidth, int inputHeight) const {
    // 计算旋转后的包围盒
    float angleRad = mTransformParams.rotationAngle * M_PI / 180.0f;
    float cosA = cos(angleRad);
    float sinA = sin(angleRad);
    
    // 原始矩形四个角点(以旋转中心为原点)
    float hw = inputWidth * 0.5f;
    float hh = inputHeight * 0.5f;
    float pivotX = mTransformParams.pivotX * inputWidth - hw;
    float pivotY = mTransformParams.pivotY * inputHeight - hh;
    
    // 四个角点(相对于旋转中心)
    float corners[4][2] = {
        {-hw - pivotX, -hh - pivotY},  // 左下
        { hw - pivotX, -hh - pivotY},  // 右下
        {-hw - pivotX,  hh - pivotY},  // 左上
        { hw - pivotX,  hh - pivotY}   // 右上
    };
    
    // 应用旋转
    float minX = INFINITY, maxX = -INFINITY;
    float minY = INFINITY, maxY = -INFINITY;
    
    for (int i = 0; i < 4; i++) {
        float x = corners[i][0] * cosA - corners[i][1] * sinA;
        float y = corners[i][0] * sinA + corners[i][1] * cosA;
        
        // 应用缩放
        x *= mTransformParams.scaleX;
        y *= mTransformParams.scaleY;
        
        // 应用平移
        x += mTransformParams.translateX * inputWidth;
        y += mTransformParams.translateY * inputHeight;
        
        // 更新边界
        minX = fmin(minX, x);
        maxX = fmax(maxX, x);
        minY = fmin(minY, y);
        maxY = fmax(maxY, y);
    }
    
    // 计算尺寸和偏移
    BoundingBox bbox;
    bbox.width = static_cast<int>(ceilf(maxX - minX));
    bbox.height = static_cast<int>(ceilf(maxY - minY));
    bbox.offsetX = -minX - bbox.width * 0.5f;
    bbox.offsetY = -minY - bbox.height * 0.5f;
    
    return bbox;
}

void AdvancedOpenGLProcessor::calculateTransformMatrix(float matrix[16], int inputWidth, int inputHeight) const {
    // 单位矩阵
    memset(matrix, 0, sizeof(float) * 16);
    matrix[0] = matrix[5] = matrix[10] = matrix[15] = 1.0f;
    
    // 将角度转换为弧度
    float angleRad = mTransformParams.rotationAngle * M_PI / 180.0f;
    float cosA = cos(angleRad);
    float sinA = sin(angleRad);
    
    // 计算旋转中心(归一化坐标转换为NDC坐标)
    float pivotX = mTransformParams.pivotX * 2.0f - 1.0f;
    float pivotY = mTransformParams.pivotY * 2.0f - 1.0f;
    
    // 构建变换矩阵(列主序):
    // 1. 平移到旋转中心
    // 2. 应用旋转
    // 3. 应用缩放
    // 4. 平移回原位置并应用用户平移
    
    // 缩放矩阵
    float scaleMatrix[16] = {
        mTransformParams.scaleX, 0, 0, 0,
        0, mTransformParams.scaleY, 0, 0,
        0, 0, 1, 0,
        0, 0, 0, 1
    };
    
    // 旋转矩阵
    float rotationMatrix[16] = {
        cosA, -sinA, 0, 0,
        sinA,  cosA, 0, 0,
        0, 0, 1, 0,
        0, 0, 0, 1
    };
    
    // 平移矩阵(到旋转中心)
    float translateToPivot[16] = {
        1, 0, 0, -pivotX,
        0, 1, 0, -pivotY,
        0, 0, 1, 0,
        0, 0, 0, 1
    };
    
    // 平移矩阵(从旋转中心)
    float translateFromPivot[16] = {
        1, 0, 0, pivotX,
        0, 1, 0, pivotY,
        0, 0, 1, 0,
        0, 0, 0, 1
    };
    
    // 用户平移矩阵
    float userTranslate[16] = {
        1, 0, 0, mTransformParams.translateX * 2.0f,
        0, 1, 0, mTransformParams.translateY * 2.0f,
        0, 0, 1, 0,
        0, 0, 0, 1
    };
    
    // 矩阵乘法:M = T_user * T_from * R * S * T_to
    // 为了简化,我们直接计算最终矩阵
    
    // 组合变换:先缩放,再旋转
    matrix[0] = cosA * mTransformParams.scaleX;
    matrix[1] = sinA * mTransformParams.scaleX;
    matrix[4] = -sinA * mTransformParams.scaleY;
    matrix[5] = cosA * mTransformParams.scaleY;
    
    // 应用平移(包括旋转中心调整和用户平移)
    float tx = pivotX - (matrix[0] * pivotX + matrix[4] * pivotY) + mTransformParams.translateX * 2.0f;
    float ty = pivotY - (matrix[1] * pivotX + matrix[5] * pivotY) + mTransformParams.translateY * 2.0f;
    
    matrix[12] = tx;
    matrix[13] = ty;
}

bool AdvancedOpenGLProcessor::createFramebuffer(int width, int height) {
    // 如果尺寸没变且已存在,则复用
    if (mFramebuffer != 0 && mOutputTexture != 0 && 
        width == mOutputWidth && height == mOutputHeight) {
        return true;
    }
    
    // 清理旧的资源
    if (mFramebuffer != 0) {
        glDeleteFramebuffers(1, &mFramebuffer);
        mFramebuffer = 0;
    }
    
    if (mOutputTexture != 0) {
        glDeleteTextures(1, &mOutputTexture);
        mOutputTexture = 0;
    }
    
    // 创建帧缓冲
    glGenFramebuffers(1, &mFramebuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
    
    // 创建输出纹理
    mOutputTexture = createTexture(width, height, PixelFormat::RGBA8);
    
    // 将纹理附加到帧缓冲
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 
                          GL_TEXTURE_2D, mOutputTexture, 0);
    
    // 检查帧缓冲完整性
    if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
        LOGE("Framebuffer is not complete");
        glDeleteFramebuffers(1, &mFramebuffer);
        glDeleteTextures(1, &mOutputTexture);
        mFramebuffer = 0;
        mOutputTexture = 0;
        return false;
    }
    
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    
    mOutputWidth = width;
    mOutputHeight = height;
    
    LOGI("Created framebuffer %dx%d", width, height);
    return true;
}

bool AdvancedOpenGLProcessor::createPBOs(int width, int height) {
    if (!mUsePBO) return true;
    
    size_t bufferSize = width * height * 4; // RGBA
    
    if (mPBO[0] == 0) {
        glGenBuffers(2, mPBO);
    }
    
    for (int i = 0; i < 2; i++) {
        glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO[i]);
        glBufferData(GL_PIXEL_PACK_BUFFER, bufferSize, nullptr, GL_STREAM_READ);
    }
    
    glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
    mCurrentPBOIndex = 0;
    
    return true;
}

GLuint AdvancedOpenGLProcessor::createTexture(int width, int height, PixelFormat format) {
    GLuint texture;
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    
    // 设置纹理参数
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    
    // 根据过滤模式设置
    if (mTransformParams.bilinearFilter) {
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    } else {
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    }
    
    // 分配纹理内存
    GLenum internalFormat, dataFormat, dataType;
    
    switch (format) {
        case PixelFormat::RGBA8:
            internalFormat = GL_RGBA8;
            dataFormat = GL_RGBA;
            dataType = GL_UNSIGNED_BYTE;
            break;
        case PixelFormat::RGB8:
            internalFormat = GL_RGB8;
            dataFormat = GL_RGB;
            dataType = GL_UNSIGNED_BYTE;
            break;
        case PixelFormat::RGBA16F:
            internalFormat = GL_RGBA16F;
            dataFormat = GL_RGBA;
            dataType = GL_HALF_FLOAT;
            break;
        case PixelFormat::RGBA32F:
            internalFormat = GL_RGBA32F;
            dataFormat = GL_RGBA;
            dataType = GL_FLOAT;
            break;
        default:
            internalFormat = GL_RGBA8;
            dataFormat = GL_RGBA;
            dataType = GL_UNSIGNED_BYTE;
    }
    
    glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 
                 0, dataFormat, dataType, nullptr);
    
    glBindTexture(GL_TEXTURE_2D, 0);
    return texture;
}

void AdvancedOpenGLProcessor::updateUniforms(int inputWidth, int inputHeight) {
    glUseProgram(mProgram);
    
    // 计算并设置变换矩阵
    float transformMatrix[16];
    calculateTransformMatrix(transformMatrix, inputWidth, inputHeight);
    glUniformMatrix4fv(mUniformLocations.transformMatrix, 1, GL_FALSE, transformMatrix);
    
    // 设置纹理尺寸
    glUniform2f(mUniformLocations.textureSize, static_cast<float>(inputWidth), 
                static_cast<float>(inputHeight));
    
    // 设置旋转中心
    glUniform2f(mUniformLocations.pivotPoint, mTransformParams.pivotX, mTransformParams.pivotY);
    
    // 设置过滤模式
    glUniform1i(mUniformLocations.useBilinear, mTransformParams.bilinearFilter ? 1 : 0);
    
    // 设置裁剪
    glUniform1i(mUniformLocations.cropEnabled, mTransformParams.cropToInputSize ? 1 : 0);
    
    if (mTransformParams.cropToInputSize) {
        // 计算裁剪矩形(归一化坐标)
        BoundingBox bbox = calculateBoundingBox(inputWidth, inputHeight);
        float cropRect[4] = {
            0.5f - static_cast<float>(inputWidth) / (2.0f * bbox.width),
            0.5f - static_cast<float>(inputHeight) / (2.0f * bbox.height),
            static_cast<float>(inputWidth) / bbox.width,
            static_cast<float>(inputHeight) / bbox.height
        };
        glUniform4f(mUniformLocations.cropRect, cropRect[0], cropRect[1], cropRect[2], cropRect[3]);
    }
}

bool AdvancedOpenGLProcessor::processFrame(const uint8_t* inputData, int inputWidth, int inputHeight,
                                         uint8_t* outputData, int* outputWidth, int* outputHeight) {
    if (!mInitialized || !inputData) {
        LOGE("Processor not initialized or invalid input");
        return false;
    }
    
    Timer totalTimer;
    totalTimer.start();
    
    Timer uploadTimer;
    uploadTimer.start();
    
    // 1. 计算输出尺寸
    BoundingBox bbox = calculateBoundingBox(inputWidth, inputHeight);
    int targetWidth = mAutoCalculateSize ? bbox.width : mOutputWidth;
    int targetHeight = mAutoCalculateSize ? bbox.height : mOutputHeight;
    
    if (targetWidth <= 0 || targetHeight <= 0) {
        LOGE("Invalid output dimensions: %dx%d", targetWidth, targetHeight);
        return false;
    }
    
    // 2. 创建或更新帧缓冲
    if (!createFramebuffer(targetWidth, targetHeight)) {
        LOGE("Failed to create framebuffer");
        return false;
    }
    
    // 3. 创建或更新输入纹理
    if (mInputTexture == 0) {
        mInputTexture = createTexture(inputWidth, inputHeight, PixelFormat::RGBA8);
    }
    
    // 4. 上传输入数据到纹理
    glBindTexture(GL_TEXTURE_2D, mInputTexture);
    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, inputWidth, inputHeight,
                   GL_RGBA, GL_UNSIGNED_BYTE, inputData);
    
    int64_t uploadTime = uploadTimer.elapsedMicroseconds();
    
    Timer processTimer;
    processTimer.start();
    
    // 5. 绑定帧缓冲
    glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
    glViewport(0, 0, targetWidth, targetHeight);
    
    // 6. 清除颜色缓冲
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    
    // 7. 更新uniform变量
    updateUniforms(inputWidth, inputHeight);
    
    // 8. 绑定纹理和VAO
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, mInputTexture);
    glUniform1i(glGetUniformLocation(mProgram, "uTexture"), 0);
    
    glBindVertexArray(mVAO);
    
    // 9. 绘制
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    
    int64_t processTime = processTimer.elapsedMicroseconds();
    
    Timer downloadTimer;
    downloadTimer.start();
    
    // 10. 读取结果
    if (outputData) {
        if (mUsePBO) {
            readPixelsAsync(outputData, targetWidth, targetHeight);
        } else {
            readPixelsSync(outputData, targetWidth, targetHeight);
        }
    }
    
    int64_t downloadTime = downloadTimer.elapsedMicroseconds();
    
    // 11. 清理状态
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glBindVertexArray(0);
    glBindTexture(GL_TEXTURE_2D, 0);
    
    // 12. 如果绑定到窗口,显示结果
    if (mNativeWindow) {
        int windowWidth = ANativeWindow_getWidth(mNativeWindow);
        int windowHeight = ANativeWindow_getHeight(mNativeWindow);
        
        if (windowWidth > 0 && windowHeight > 0) {
            glViewport(0, 0, windowWidth, windowHeight);
            glClear(GL_COLOR_BUFFER_BIT);
            
            // 使用简单着色器显示结果
            glBindTexture(GL_TEXTURE_2D, mOutputTexture);
            glBindVertexArray(mVAO);
            glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
            
            eglSwapBuffers(mEglDisplay, mEglSurface);
        }
    }
    
    // 13. 更新输出尺寸
    if (outputWidth) *outputWidth = targetWidth;
    if (outputHeight) *outputHeight = targetHeight;
    
    // 14. 更新性能统计
    updatePerformanceMetrics(uploadTime, processTime, downloadTime);
    
    LOGI("Processed frame %dx%d -> %dx%d in %.2f ms", 
         inputWidth, inputHeight, targetWidth, targetHeight,
         totalTimer.elapsedMicroseconds() / 1000.0);
    
    return true;
}

void AdvancedOpenGLProcessor::readPixelsAsync(uint8_t* outputData, int width, int height) {
    size_t bufferSize = width * height * 4;
    
    // 绑定PBO用于读取
    glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO[mCurrentPBOIndex]);
    
    // 异步读取到当前PBO
    glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, 0);
    
    // 绑定另一个PBO并映射之前的数据
    int nextPBO = (mCurrentPBOIndex + 1) % 2;
    glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO[nextPBO]);
    
    void* mappedData = glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, bufferSize, GL_MAP_READ_BIT);
    if (mappedData) {
        memcpy(outputData, mappedData, bufferSize);
        glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
    }
    
    // 交换PBO
    mCurrentPBOIndex = nextPBO;
    glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
}

void AdvancedOpenGLProcessor::readPixelsSync(uint8_t* outputData, int width, int height) {
    // 同步读取
    glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, outputData);
}

void AdvancedOpenGLProcessor::setTransformParams(const TransformParams& params) {
    std::lock_guard<std::mutex> lock(mTransformMutex);
    mTransformParams = params;
}

void AdvancedOpenGLProcessor::setOutputSize(int width, int height, bool autoCrop) {
    mOutputWidth = width;
    mOutputHeight = height;
    mAutoCalculateSize = !autoCrop;
    
    if (autoCrop) {
        mTransformParams.cropToInputSize = true;
    }
}

void AdvancedOpenGLProcessor::updatePerformanceMetrics(int64_t uploadTime, int64_t processTime, int64_t downloadTime) {
    std::lock_guard<std::mutex> lock(mStatsMutex);
    
    mPerformanceMetrics.uploadTimeMs = uploadTime / 1000.0;
    mPerformanceMetrics.gpuTimeMs = processTime / 1000.0;
    mPerformanceMetrics.downloadTimeMs = downloadTime / 1000.0;
    mPerformanceMetrics.totalTimeMs = (uploadTime + processTime + downloadTime) / 1000.0;
    mPerformanceMetrics.frameCount++;
    
    // 计算平均FPS(基于最近10帧)
    static const int FRAME_HISTORY = 10;
    static double frameTimes[FRAME_HISTORY] = {0};
    static int frameIndex = 0;
    
    frameTimes[frameIndex] = mPerformanceMetrics.totalTimeMs;
    frameIndex = (frameIndex + 1) % FRAME_HISTORY;
    
    double sum = 0;
    int count = 0;
    for (int i = 0; i < FRAME_HISTORY; i++) {
        if (frameTimes[i] > 0) {
            sum += frameTimes[i];
            count++;
        }
    }
    
    if (count > 0 && sum > 0) {
        mPerformanceMetrics.averageFps = 1000.0 / (sum / count);
    }
    
    // 估计内存使用
    size_t textureMemory = (mOutputWidth * mOutputHeight * 4) / (1024 * 1024);
    size_t bufferMemory = (mUsePBO ? mOutputWidth * mOutputHeight * 4 * 2 : 0) / (1024 * 1024);
    mPerformanceMetrics.memoryUsedMB = textureMemory + bufferMemory;
    mPerformanceMetrics.lastOutputWidth = mOutputWidth;
    mPerformanceMetrics.lastOutputHeight = mOutputHeight;
}

PerformanceMetrics AdvancedOpenGLProcessor::getPerformanceMetrics() const {
    std::lock_guard<std::mutex> lock(mStatsMutex);
    return mPerformanceMetrics;
}

void AdvancedOpenGLProcessor::trimMemory() {
    if (!mInitialized) return;
    
    LOGI("Trimming memory");
    
    // 释放PBO
    if (mPBO[0] != 0) {
        glDeleteBuffers(2, mPBO);
        memset(mPBO, 0, sizeof(mPBO));
    }
    
    // 缩小输出纹理
    if (mOutputTexture != 0 && (mOutputWidth > 256 || mOutputHeight > 256)) {
        glBindTexture(GL_TEXTURE_2D, mOutputTexture);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 256, 0, 
                    GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
        glBindTexture(GL_TEXTURE_2D, 0);
    }
    
    glFinish();
}

void AdvancedOpenGLProcessor::flushPipeline() {
    if (!mInitialized) return;
    glFlush();
}

void AdvancedOpenGLProcessor::cleanup() {
    if (!mInitialized) return;
    
    // 清理OpenGL资源
    if (mProgram) {
        glDeleteProgram(mProgram);
        mProgram = 0;
    }
    
    if (mFramebuffer) {
        glDeleteFramebuffers(1, &mFramebuffer);
        mFramebuffer = 0;
    }
    
    if (mInputTexture) {
        glDeleteTextures(1, &mInputTexture);
        mInputTexture = 0;
    }
    
    if (mOutputTexture) {
        glDeleteTextures(1, &mOutputTexture);
        mOutputTexture = 0;
    }
    
    if (mVAO) {
        glDeleteVertexArrays(1, &mVAO);
        mVAO = 0;
    }
    
    if (mVBO) {
        glDeleteBuffers(1, &mVBO);
        mVBO = 0;
    }
    
    if (mEBO) {
        glDeleteBuffers(1, &mEBO);
        mEBO = 0;
    }
    
    if (mPBO[0] != 0) {
        glDeleteBuffers(2, mPBO);
        memset(mPBO, 0, sizeof(mPBO));
    }
    
    // 清理EGL资源
    if (mEglDisplay != EGL_NO_DISPLAY) {
        eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
        
        if (mEglContext != EGL_NO_CONTEXT) {
            eglDestroyContext(mEglDisplay, mEglContext);
            mEglContext = EGL_NO_CONTEXT;
        }
        
        if (mEglSurface != EGL_NO_SURFACE) {
            eglDestroySurface(mEglDisplay, mEglSurface);
            mEglSurface = EGL_NO_SURFACE;
        }
        
        eglTerminate(mEglDisplay);
        mEglDisplay = EGL_NO_DISPLAY;
    }
    
    mNativeWindow = nullptr;
    mInitialized = false;
    
    LOGI("OpenGL processor cleaned up");
}

// main.cpp - Native Activity入口
#include <android_native_app_glue.h>
#include "advanced_opengl_processor.h"
#include <chrono>
#include <thread>

struct Engine {
    struct android_app* app;
    AdvancedOpenGLProcessor* processor;
    bool initialized;
    bool animating;
    int32_t width;
    int32_t height;
    TransformParams transform;
    uint8_t* testImage;
    int testWidth;
    int testHeight;
};

static void engine_init_display(Engine* engine) {
    if (engine->initialized) return;
    
    // 获取窗口
    ANativeWindow* window = engine->app->window;
    if (!window) return;
    
    // 初始化处理器
    engine->processor = new AdvancedOpenGLProcessor();
    if (!engine->processor->initialize(window)) {
        LOGE("Failed to initialize OpenGL processor");
        delete engine->processor;
        engine->processor = nullptr;
        return;
    }
    
    // 设置初始变换参数
    engine->transform.rotationAngle = 30.0f; // 30度旋转
    engine->transform.scaleX = 1.2f;
    engine->transform.scaleY = 0.8f;
    engine->transform.pivotX = 0.3f;
    engine->transform.pivotY = 0.7f;
    engine->transform.bilinearFilter = true;
    engine->processor->setTransformParams(engine->transform);
    
    // 创建测试图像
    engine->testWidth = 1920;
    engine->testHeight = 1080;
    size_t imageSize = engine->testWidth * engine->testHeight * 4;
    engine->testImage = new uint8_t[imageSize];
    
    // 生成测试图像(渐变+棋盘格)
    for (int y = 0; y < engine->testHeight; y++) {
        for (int x = 0; x < engine->testWidth; x++) {
            int idx = (y * engine->testWidth + x) * 4;
            
            // RGBA格式
            engine->testImage[idx] = (x * 255) / engine->testWidth;     // R
            engine->testImage[idx + 1] = (y * 255) / engine->testHeight; // G
            
            // 棋盘格图案
            bool isWhite = ((x / 64) % 2) ^ ((y / 64) % 2);
            engine->testImage[idx + 2] = isWhite ? 255 : 128;           // B
            engine->testImage[idx + 3] = 255;                           // A
        }
    }
    
    engine->width = ANativeWindow_getWidth(window);
    engine->height = ANativeWindow_getHeight(window);
    engine->initialized = true;
    engine->animating = true;
    
    LOGI("Engine initialized with window size %dx%d", engine->width, engine->height);
}

static void engine_draw_frame(Engine* engine) {
    if (!engine->processor || !engine->initialized) return;
    
    // 处理测试图像
    uint8_t* outputData = nullptr;
    int outputWidth = 0, outputHeight = 0;
    
    // 为输出分配缓冲区(实际应用中应该复用缓冲区)
    size_t maxOutputSize = engine->testWidth * engine->testHeight * 4 * 4; // 最大可能尺寸
    outputData = new uint8_t[maxOutputSize];
    
    // 处理帧
    bool success = engine->processor->processFrame(
        engine->testImage, engine->testWidth, engine->testHeight,
        outputData, &outputWidth, &outputHeight
    );
    
    if (success) {
        // 获取性能统计
        PerformanceMetrics metrics = engine->processor->getPerformanceMetrics();
        LOGI("Processed: %dx%d -> %dx%d, Time: %.2f ms, FPS: %.1f",
             engine->testWidth, engine->testHeight, outputWidth, outputHeight,
             metrics.totalTimeMs, metrics.averageFps);
    }
    
    // 清理输出缓冲区
    delete[] outputData;
    
    // 更新变换参数(动画效果)
    static float angle = 0.0f;
    angle += 1.0f;
    if (angle >= 360.0f) angle -= 360.0f;
    
    engine->transform.rotationAngle = angle;
    engine->processor->setTransformParams(engine->transform);
}

static void engine_term_display(Engine* engine) {
    if (engine->processor) {
        engine->processor->cleanup();
        delete engine->processor;
        engine->processor = nullptr;
    }
    
    if (engine->testImage) {
        delete[] engine->testImage;
        engine->testImage = nullptr;
    }
    
    engine->initialized = false;
}

static void engine_handle_cmd(struct android_app* app, int32_t cmd) {
    Engine* engine = (Engine*)app->userData;
    
    switch (cmd) {
        case APP_CMD_SAVE_STATE:
            // 保存状态
            break;
        case APP_CMD_INIT_WINDOW:
            if (engine->app->window) {
                engine_init_display(engine);
                engine_draw_frame(engine);
            }
            break;
        case APP_CMD_TERM_WINDOW:
            engine_term_display(engine);
            break;
        case APP_CMD_GAINED_FOCUS:
            engine->animating = true;
            break;
        case APP_CMD_LOST_FOCUS:
            engine->animating = false;
            break;
        case APP_CMD_LOW_MEMORY:
            if (engine->processor) {
                engine->processor->trimMemory();
            }
            break;
        case APP_CMD_RESUME:
        case APP_CMD_PAUSE:
            // 处理暂停/恢复
            break;
        case APP_CMD_CONFIG_CHANGED:
            // 配置变化
            if (engine->processor && engine->app->window) {
                engine->width = ANativeWindow_getWidth(engine->app->window);
                engine->height = ANativeWindow_getHeight(engine->app->window);
            }
            break;
    }
}

static int32_t engine_handle_input(struct android_app* app, AInputEvent* event) {
    Engine* engine = (Engine*)app->userData;
    
    if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) {
        int32_t action = AMotionEvent_getAction(event);
        
        if (action == AMOTION_EVENT_ACTION_DOWN) {
            // 点击屏幕更新旋转中心
            float x = AMotionEvent_getX(event, 0) / engine->width;
            float y = AMotionEvent_getY(event, 0) / engine->height;
            
            engine->transform.pivotX = x;
            engine->transform.pivotY = y;
            
            if (engine->processor) {
                engine->processor->setTransformParams(engine->transform);
            }
            
            return 1;
        }
    }
    
    return 0;
}

void android_main(struct android_app* state) {
    Engine engine;
    memset(&engine, 0, sizeof(engine));
    
    state->userData = &engine;
    state->onAppCmd = engine_handle_cmd;
    state->onInputEvent = engine_handle_input;
    engine.app = state;
    
    // 主循环
    while (true) {
        int ident;
        int events;
        struct android_poll_source* source;
        
        // 处理所有事件
        while ((ident = ALooper_pollAll(engine.animating ? 0 : -1, NULL, &events, 
                                       (void**)&source)) >= 0) {
            if (source) {
                source->process(state, source);
            }
            
            // 检查是否要退出
            if (state->destroyRequested) {
                engine_term_display(&engine);
                return;
            }
        }
        
        // 渲染帧
        if (engine.initialized && engine.animating) {
            engine_draw_frame(&engine);
            
            // 限制帧率
            std::this_thread::sleep_for(std::chrono::milliseconds(16)); // ~60 FPS
        }
    }
}

cmake_minimum_required(VERSION 3.18.1)
project("AdvancedOpenGLProcessor")

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# 设置编译标志
add_definitions(-DLOG_TAG=\"GLProcessor\")
add_definitions(-DGL_GLEXT_PROTOTYPES)

# 查找库
find_library(log-lib log)
find_library(android-lib android)
find_library(egl-lib EGL)
find_library(glesv3-lib GLESv3)

# 添加原生应用胶水库
add_library(app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c)
target_include_directories(app-glue PRIVATE ${ANDROID_NDK}/sources/android/native_app_glue)

# 源文件
set(SOURCE_FILES
    src/main/cpp/main.cpp
    src/main/cpp/advanced_opengl_processor.cpp
)

# 创建共享库
add_library(opengl_processor SHARED ${SOURCE_FILES})

# 包含目录
target_include_directories(opengl_processor PRIVATE
    ${CMAKE_SOURCE_DIR}/src/main/cpp
    ${ANDROID_NDK}/sources/android/native_app_glue
)

# 链接库
target_link_libraries(opengl_processor
    app-glue
    ${log-lib}
    ${android-lib}
    ${egl-lib}
    ${glesv3-lib}
)

# 设置输出属性
set_target_properties(opengl_processor PROPERTIES
    LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/lib
    ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/lib
)

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.advancedopengl">
    
    <uses-feature android:glEsVersion="0x00030000" android:required="true" />
    <uses-feature android:name="android.hardware.touchscreen" android:required="false" />
    
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="Advanced OpenGL Processor"
        android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
        
        <activity android:name="android.app.NativeActivity"
            android:label="OpenGL Processor"
            android:configChanges="orientation|keyboardHidden|screenSize">
            
            <meta-data android:name="android.app.lib_name"
                android:value="opengl_processor" />
            
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

主要特性

1. 任意角度旋转

  • 支持0-360度任意角度旋转

  • 可自定义旋转中心(归一化坐标)

  • 精确的旋转矩阵计算

2. 任意分辨率支持

  • 输入输出分辨率完全动态

  • 自动计算变换后的包围盒

  • 智能内存分配和重用

3. RGBA格式支持

  • 完整的32位RGBA处理

  • Alpha通道正确处理

  • 支持预乘Alpha

4. 高性能优化

  • PBO异步传输

  • 帧缓冲复用

  • 智能资源管理

  • 详细的性能统计

5. 高质量滤波

  • 双线性滤波

  • Lanczos高质量缩放(可选)

  • 边缘处理

6. 完整生命周期管理

  • Native Activity集成

  • 内存管理回调

  • 配置变化处理

这个实现提供了完整的、高性能的2D图像任意角度旋转处理,适用于Android平台的实时图像处理应用。

相关推荐
Loo国昌几秒前
【大模型应用开发】第三阶段:深度解析检索增强生成(RAG)原理
人工智能·后端·深度学习·自然语言处理·transformer
ONLYOFFICE几秒前
ONLYOFFICE AI 插件新功能:轻松创建专属 AI 助手
人工智能·onlyoffice
audyxiao0011 分钟前
AI一周重要会议和活动概览(2.2-2.8)
人工智能·大模型·iclr·ccf·一周会议与活动
柠萌f2 分钟前
2026 素材趋势报告:为什么“素材工程能力”,正在决定品牌的投放天花板?
人工智能
莽撞的大地瓜4 分钟前
连获国内多行业认可、入选全球AI全景图谱 彰显蜜度智能校对的硬核实力
人工智能·ai·语言模型·新媒体运营·知识图谱
ATM0066 分钟前
专其利AI | 专利撰写的救赎:AI工具为何成为知识产权保护的神兵利器
人工智能·大模型·专利撰写
海天一色y11 分钟前
使用 PyTorch RNN 识别手写数字
人工智能·pytorch·rnn
百***074515 分钟前
OpenClaw+一步API实战:本地化AI自动化助手从部署到落地全指南
大数据·人工智能·python
临水逸15 分钟前
OpenClaw WebUI 的外网访问配置
人工智能·策略模式
yuanyuan2o220 分钟前
【深度学习】AlexNet
人工智能·深度学习