天天看點

android渲染是skia與egl,opengl-es - 為什麼渲染位圖時我的android native活動有時會顯示錯誤的圖像? - 堆棧記憶體溢出...

我正在嘗試使用NDK在全屏上顯示位圖。 該要求迫使我使用完全本機代碼進行開發。 我使用Skia繪制SkBitmap ,然後通過Opengl APIs将其顯示。 當我的應用程式首次在真正的android裝置上運作時,它始終可以正常運作。 但是,在我多次打開和關閉程式之後,它将顯示出不好的圖像。 為什麼會這樣?

功能engine_init_display用于初始化OpenGL ES和EGL,建立位圖并加載紋理。

static int engine_init_display(struct engine* engine){

// initialize OpenGL ES and EGL

const EGLint attribs[] = {

EGL_SURFACE_TYPE, EGL_WINDOW_BIT,

EGL_DEPTH_SIZE, 16,

EGL_BLUE_SIZE, 8,

EGL_GREEN_SIZE, 8,

EGL_RED_SIZE, 8,

EGL_NONE

};

EGLint w, h, dummy, format;

EGLint numConfigs;

EGLConfig config;

EGLSurface surface;

EGLContext context;

EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);

eglInitialize(display, 0, 0);

eglChooseConfig(display, attribs, &config, 1, &numConfigs);

eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);

ANativeWindow_setBuffersGeometry(engine->app->window, 0, 0, format);

surface = eglCreateWindowSurface(display, config, engine->app->window, NULL);

context = eglCreateContext(display, config, NULL, NULL);

if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) {

LOGW("Unable to eglMakeCurrent");

return -1;

}

eglQuerySurface(display, surface, EGL_WIDTH, &w);

eglQuerySurface(display, surface, EGL_HEIGHT, &h);

engine->display = display;

engine->context = context;

engine->surface = surface;

engine->width = w;

engine->height = h;

engine->state.angle = 0;

engine->format=format;

// Initialize GL state.

glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);

glEnable(GL_CULL_FACE);

glShadeModel(GL_SMOOTH);

glDisable(GL_DEPTH_TEST);

SkBitmap bitmap;

GLvoid* bitmapBuffer;

createBitmap(bitmap,bitmapBuffer,width,height);

drawBitmap(bitmap,width,height);

glEnable(GL_TEXTURE_2D);

glGenTextures(1,&sTexture);

glBindTexture(GL_TEXTURE_2D,sTexture);

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)bitmapBuffer);

glDisable(GL_TEXTURE_2D);

glFinish();

clearBitmapBuffer(bitmap,bitmapBuffer);

//engine_draw_frame(engine);

return 0;

}

功能render是顯示位圖

void render(struct engine* engine, int width, int height){

glViewport((engine->width-width)/2, (engine->height-height)/2, width, height);

glClearColorx((GLfixed)(0.1f * 65536),(GLfixed)(0.2f * 65536),(GLfixed)(0.3f * 65536), 0x10000);

glClear(GL_COLOR_BUFFER_BIT);

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

glMatrixMode(GL_TEXTURE);

glLoadIdentity();

glEnable(GL_TEXTURE_2D);

glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

glEnableClientState(GL_VERTEX_ARRAY);

glEnableClientState(GL_TEXTURE_COORD_ARRAY);

glBindTexture(GL_TEXTURE_2D,sTexture);

glFrontFace(GL_CW);

glTexCoordPointer(2, GL_FLOAT, 0, textureCoords);

glVertexPointer(3, GL_FLOAT, 0, vertices);

glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

glDisable(GL_TEXTURE_2D);

glDisableClientState(GL_VERTEX_ARRAY);

glDisableClientState(GL_TEXTURE_COORD_ARRAY);

glFlush();

eglSwapBuffers(engine->display, engine->surface);

}

當視窗關閉時,将調用engine_term_display

static void engine_term_display(struct engine* engine) {

if (engine->display != EGL_NO_DISPLAY) {

eglMakeCurrent(engine->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);

if (engine->context != EGL_NO_CONTEXT) {

eglDestroyContext(engine->display, engine->context);

}

if (engine->surface != EGL_NO_SURFACE) {

eglDestroySurface(engine->display, engine->surface);

}

eglTerminate(engine->display);

}

engine->display = EGL_NO_DISPLAY;

engine->context = EGL_NO_CONTEXT;

engine->surface = EGL_NO_SURFACE;

}

更新

android_main是本機應用程式的主要入口點。 我發現當此主要功能傳回時,整個應用程式仍在運作。

void android_main(struct android_app* state) {

struct engine engine;

// Make sure glue isn't stripped.

app_dummy();

memset(&engine, 0, sizeof(engine));

state->userData = &engine;

state->onAppCmd = engine_handle_cmd;

state->onInputEvent = engine_handle_input;

engine.app = state;

ANativeActivity_setWindowFlags(engine.app->activity, AWINDOW_FLAG_FULLSCREEN, 0);

if (state->savedState != NULL) {

// We are starting with a previous saved state; restore from it.

engine.state = *(struct saved_state*)state->savedState;

}

while(1){

int ident;

int events;

struct android_poll_source* source;

if((ident=ALooper_pollAll(-1, NULL, &events,(void**)&source))>=0){

// Process this event.

if (source != NULL) {

source->process(state, source);

}

if (state->destroyRequested != 0) {

engine_term_display(&engine);

return;

}

}

}

}