2013-02-24 24 views
1

我試圖使用NDK在全屏幕上顯示位圖。這個要求迫使我用完全原生的代碼進行開發。我用Skia來畫一個SkBitmap,然後用Opengl APIs來顯示它。當我的應用程序第一次運行在真正的Android設備上時,它總是運行良好。但是,在我多次打開和關閉程序後,它會顯示一個錯誤的圖像。爲什麼會發生?爲什麼我的android原生活動有時會在渲染位圖時顯示錯誤的圖像?

函數engine_init_display是初始化OpenGL ES和EGL,創建位圖和加載紋理。

static int engine_init_display(struct engine* engine){ 
// initialize OpenGL ES and EGL 

/* 
* Here specify the attributes of the desired configuration. 
* Below, we select an EGLConfig with at least 8 bits per color 
* component compatible with on-screen windows 
*/ 
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); 

/* Here, the application chooses the configuration it desires. In this 
* sample, we have a very simplified selection process, where we pick 
* the first EGLConfig that matches our criteria */ 
eglChooseConfig(display, attribs, &config, 1, &numConfigs); 

/* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is 
* guaranteed to be accepted by ANativeWindow_setBuffersGeometry(). 
* As soon as we picked a EGLConfig, we can safely reconfigure the 
* ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. */ 
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; 
     } 
    } 
} 
} 

回答

1

我自己修復它,使用exit(0)代替return完全完成的活動。

if (state->destroyRequested != 0) { 
     engine_term_display(&engine); 
     exit(0); 
    } 
+0

伊西。你基本上把膝上型計算機停下來,並且讓你的整個過程失敗。 – Bostwickenator 2013-05-27 04:53:04

相關問題