简体   繁体   English

Native Activity,GLES2.0:将像素阵列上传到屏幕

[英]Native Activity, GLES2.0: Uploading pixel array to screen

I created a pixmap using, for example, this code 我使用例如此代码创建了一个像素图

//...
// Native Activity

#define HEIGHT 600
#define WIDTH 600
uint32_t texDat[WIDTH*HEIGHT*4];
static double it = 0;
uint8_t color = sin(it)*256;

for (int i = 0; i < WIDTH; i++) for (int j = 0; j < HEIGHT; j++)
texDat [ i + j*WIDTH ] = (i << 16)  | (j << 8) | (color<< 0);
it+=0.01;
if(it >= M_PI) it = 0;

On my Linux pc this pixmap can be shown with glDrawPixels or with glTexImage2D. 在我的Linux电脑上,这个像素图可以用glDrawPixels或glTexImage2D显示。 But I can't find glDrawPixels or something same on Android GLES. 但我在Android GLES上找不到glDrawPixels或类似内容。 I tried to copy image to screen with this 我尝试将图像复制到屏幕上

ANativeWindow_Buffer pbuffer;
if (ANativeWindow_lock(engine->app->window, &pbuffer, NULL) == 0) {
    memcpy(pbuffer.bits, texDat,  WIDTH*HEIGHT);
    ANativeWindow_unlockAndPost(engine->app->window);
}

But it fails even if copying size is set to 1. How can I upload pixmap to screen? 但即使复制大小设置为1,它也会失败。如何将pixmap上传到屏幕?

Thanks. 谢谢。

I think I found something I need... It works perfect for me. 我想我找到了我需要的东西......它对我来说很完美。

#include <android/log.h>
#include <android_native_app_glue.h>
#define LOG(...) __android_log_print(ANDROID_LOG_VERBOSE, "lll", __VA_ARGS__);
ANativeWindow_Buffer buffer;

uint32_t pixel_color(uint8_t r, uint8_t g, uint8_t b)
{
    return (r<<16) | (g<<8) | (b<<0);
}

void Out( int x, int y, uint32_t color ) {
    uint32_t * pPixel = buffer.bits;
    /* Compute correct x,y */
    pPixel += ( x + ( y * buffer.stride ) );
    /* put a white pixel there */
    *pPixel = color;
}

void drawscreen( struct android_app * app ) {
    unsigned u, i, j, w, h;
    LOG("Android window width = %d", w=ANativeWindow_getWidth(app->window));
    LOG("Android window height = %d", h=ANativeWindow_getHeight(app->window));

    for ( i = 0; i < w; i++ )
    for ( j = 0; j < h; j++ ) {
        Out(i, j, pixel_color(i, j, 0));
    }
}

static void android_handle_cmd( struct android_app * app, int32_t cmd ) {
    switch ( cmd ) {
        case APP_CMD_INIT_WINDOW:
            // The window is being shown.
            if ( NULL == app->window ) {
                return;
            }
            int32_t w = ANativeWindow_getWidth(app->window);
            int32_t h = ANativeWindow_getHeight(app->window);
            ANativeWindow_setBuffersGeometry(app->window, w, h, WINDOW_FORMAT_RGBX_8888);
            if ( 0 > ANativeWindow_lock( app->window, &buffer, NULL ) ) {
                return;
            }
            drawscreen(app);
            ANativeWindow_unlockAndPost( app->window );
            break;
    }
}

void android_main( struct android_app * app ) {
    app_dummy();
    app->onAppCmd     = android_handle_cmd;
    for ( ;; ) {
        int events;
        int iRet;
        struct android_poll_source * source;
        iRet = ALooper_pollAll( -1, NULL, &events, (void**)&source );
        if ( NULL != source ) {
            source->process( app, source );
            continue;
        }
    }
}

GLES shader-based solution. GLES基于着色器的解决方案。 Based on Android test 基于Android测试

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <EGL/egl.h>
#include <GLES2/gl2.h>

#define LOGI(...) (printf("(I): " __VA_ARGS__))
#define LOGW(...) (printf("(W): " __VA_ARGS__))
#define LOGE(...) (printf("(E): " __VA_ARGS__))

static GLuint gTextureProgram;
static GLuint gvTexturePositionHandle;
static GLuint gvTextureTexCoordsHandle;
static GLuint gvTextureSamplerHandle;

static const char gSimpleVS[] =
    "attribute vec4 position;\n"
    "attribute vec2 texCoords;\n"
    "varying vec2 outTexCoords;\n"
    "\nvoid main(void) {\n"
    "   outTexCoords = texCoords;\n"
    "   gl_Position = position;\n"
    "}\n\n";
static const char gSimpleFS[] =
    "precision mediump float;\n\n"
    "varying vec2 outTexCoords;\n"
    "uniform sampler2D texture;\n"
    "\nvoid main(void) {\n"
    "   gl_FragColor = texture2D(texture, outTexCoords);\n"
    "}\n\n";

static void checkGlError(const char* op) {
    GLint error;
    for (error = glGetError(); error; error = glGetError()) {
        LOGE("after %s() glError (0x%x)\n", op, error);
    }
}
static GLuint loadShader(GLenum shaderType, const char* pSource) {
    GLuint shader = glCreateShader(shaderType);
    if (shader) {
        glShaderSource(shader, 1, &pSource, NULL);
        glCompileShader(shader);
        GLint compiled = 0;
        glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
        if (!compiled) {
            GLint infoLen = 0;
            glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
            if (infoLen) {
                char* buf = (char*) malloc(infoLen);
                if (buf) {
                    glGetShaderInfoLog(shader, infoLen, NULL, buf);
                    LOGE("Could not compile shader %d:\n%s\n",
                            shaderType, buf);
                    free(buf);
                }
                glDeleteShader(shader);
                shader = 0;
            }
        }
    }
    return shader;
}

GLuint createProgram(const char* pVertexSource, const char* pFragmentSource) {
    GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource);
    if (!vertexShader) {
        return 0;
    }

    GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource);
    if (!pixelShader) {
        return 0;
    }

    GLuint program = glCreateProgram();
    if (program) {
        glAttachShader(program, vertexShader);
        checkGlError("glAttachShader");
        glAttachShader(program, pixelShader);
        checkGlError("glAttachShader");
        glLinkProgram(program);
        GLint linkStatus = GL_FALSE;
        glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
        if (linkStatus != GL_TRUE) {
            GLint bufLength = 0;
            glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
            if (bufLength) {
                char* buf = (char*) malloc(bufLength);
                if (buf) {
                    glGetProgramInfoLog(program, bufLength, NULL, buf);
                    LOGE("Could not link program:\n%s\n", buf);
                    free(buf);
                }
            }
            glDeleteProgram(program);
            program = 0;
        }
    }
    return program;
}

bool setupGraphics(void) {

    gTextureProgram = createProgram(gSimpleVS, gSimpleFS);
    if (!gTextureProgram) {
        return false;
    }
    gvTexturePositionHandle = glGetAttribLocation(gTextureProgram, "position"); checkGlError("glGetAttribLocation");
    gvTextureTexCoordsHandle = glGetAttribLocation(gTextureProgram, "texCoords"); checkGlError("glGetAttribLocation");
    gvTextureSamplerHandle = glGetUniformLocation(gTextureProgram, "texture"); checkGlError("glGetAttribLocation");

    return true;
}

const GLfloat gTriangleVertices[] = { 0.0f, 0.5f, -0.5f, -0.5f,
        0.5f, -0.5f };

#define FLOAT_SIZE_BYTES 4;
const GLint TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES;
const GLfloat gTriangleVerticesData[] = {
    // X, Y, Z, U, V
    -1.0f, -1.0f, 0, 0.f, 0.f,
    1.0f, -1.0f, 0, 1.f, 0.f,
    -1.0f,  1.0f, 0, 0.f, 1.f,
    1.0f,   1.0f, 0, 1.f, 1.f,
};

void glDrawTex(void) {
    if (!gTextureProgram) {
        if(!setupGraphics()) {
            LOGE("Could not set up graphics.\n");
            return;
        }
    }
    glUseProgram(gTextureProgram); checkGlError("glUseProgram");

    glVertexAttribPointer(gvTexturePositionHandle, 3, GL_FLOAT, GL_FALSE,
            TRIANGLE_VERTICES_DATA_STRIDE_BYTES, gTriangleVerticesData);
    checkGlError("glVertexAttribPointer");
    glVertexAttribPointer(gvTextureTexCoordsHandle, 2, GL_FLOAT, GL_FALSE,
            TRIANGLE_VERTICES_DATA_STRIDE_BYTES, &gTriangleVerticesData[3]);
    checkGlError("glVertexAttribPointer");
    glEnableVertexAttribArray(gvTexturePositionHandle);
    glEnableVertexAttribArray(gvTextureTexCoordsHandle);
    checkGlError("glEnableVertexAttribArray");
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    checkGlError("glDrawArrays");

    glUseProgram(0); checkGlError("glUseProgram");
}

static GLuint gPixelsTexture;

void glDrawPixels(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid * data){
    if(!gPixelsTexture) glGenTextures(1, &gPixelsTexture);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, gPixelsTexture);
    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);

    glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, GL_RGBA, type, data);
    glDrawTex();
    glBindTexture(GL_TEXTURE_2D, 0);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM