zoukankan      html  css  js  c++  java
  • 最近工作中的问题笔记

    调试GLES, 发现某平台有各种问题,

    1.用三星手机测试和iphone测试, 在drawcall以后不调用glDisableVertexAttribArray, 没有问题. 但在某平台下,后续的draw call会花屏.

    实际问题主要是因为shader会优化掉某些不用的attrib, 这种情况下, 要根据shader内的信息, disable掉不用的attrib.

    这个问题还可能好说,虽然还没找到GLES spec上怎么说, 但是配对使用是最保险的, 不配对可能是undefined behavior, 已知GL下确实有可能会有问题.

    2.最奇葩的问题是该平台的shader, GL/ES的spec说生成program以后, 可以detach/delete shader, 但是在某平台上, 如果删除shader竟然也会渲染出错.

    由于引擎的代码过于复杂, 为了排除其他因素, 专门用NativeActivity简化才最终确定这个问题.下面代码画了三个cube, 如果使用detach sader/delete shader, 只显示第一个cube (line130).

      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  *
     16  */
     17 
     18 //BEGIN_INCLUDE(all)
     19 #include <jni.h>
     20 #include <errno.h>
     21 
     22 #include <EGL/egl.h>
     23 #include <GLES/gl.h>
     24 #include <GLES2/gl2.h>
     25 
     26 #include <android/sensor.h>
     27 #include <android/log.h>
     28 #include <android_native_app_glue.h>
     29 
     30 #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "native-activity", __VA_ARGS__))
     31 #define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "native-activity", __VA_ARGS__))
     32 
     33 /**
     34  * Our saved state data.
     35  */
     36 struct saved_state {
     37     float angle;
     38     int32_t x;
     39     int32_t y;
     40 };
     41 
     42 /**
     43  * Shared state for our app.
     44  */
     45 struct engine {
     46     struct android_app* app;
     47 
     48     ASensorManager* sensorManager;
     49     const ASensor* accelerometerSensor;
     50     ASensorEventQueue* sensorEventQueue;
     51 
     52     int animating;
     53     EGLDisplay display;
     54     EGLSurface surface;
     55     EGLContext context;
     56     int32_t width;
     57     int32_t height;
     58     GLuint program[3];
     59     struct saved_state state;
     60 };
     61 
     62 GLuint    Position = 1;
     63 GLuint    UV = 2;
     64 
     65 //////////////////////////////////////////////////////////////////////////
     66 GLuint LoadShader(GLenum shaderType, const char* pSource) {
     67 
     68     GLuint shader = glCreateShader(shaderType);
     69 
     70     if (shader != 0) {
     71         glShaderSource(shader, 1, &pSource, NULL);
     72         glCompileShader(shader);
     73         GLint compiled = 0;
     74         glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
     75         if (compiled == 0) {
     76             GLint infoLen = 0;
     77             glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
     78             if (infoLen != 0) {
     79                 char* buf = (char*)alloca(infoLen);
     80                 if (buf != NULL) {
     81                     glGetShaderInfoLog(shader, infoLen, NULL, buf);
     82                     LOGW( "Could not compile shader %d:
    %s
    ", shaderType,  buf );
     83                 }
     84                 glDeleteShader(shader);
     85                 shader = 0;
     86             }
     87         }
     88     }
     89     return shader;
     90 }
     91 
     92 //////////////////////////////////////////////////////////////////////////
     93 GLuint CreateProgram(const char* pVertexSource, const char* pFragmentSource) {
     94 
     95     GLuint vertexShader = LoadShader(GL_VERTEX_SHADER, pVertexSource);
     96     if (vertexShader == 0) {
     97         return 0;
     98     }
     99 
    100     GLuint pixelShader = LoadShader(GL_FRAGMENT_SHADER, pFragmentSource);
    101     if (pixelShader == 0) {
    102         return 0;
    103     }
    104 
    105     GLuint program = glCreateProgram();
    106     if (program != 0) {
    107         glAttachShader(program, vertexShader);
    108         glAttachShader(program, pixelShader);
    109 
    110         glBindAttribLocation(program, Position, "vsin_POSITION0");
    111         glBindAttribLocation(program, UV, "vsin_TEXCOORD0");
    112 
    113         glLinkProgram(program);
    114         GLint linkStatus = GL_FALSE;
    115         glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
    116         if (linkStatus != GL_TRUE) {
    117             GLint bufLength = 0;
    118             glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
    119             if (bufLength != 0) {
    120                 char* buf = (char*)alloca(bufLength);
    121                 if (buf != NULL) {
    122                     glGetProgramInfoLog(program, bufLength, NULL, buf);
    123                     LOGW( "Could not link program:
    %s
    ", buf );
    124                 }
    125             }
    126             glDeleteProgram(program);
    127             program = 0;
    128         }
    129 
    130         //uncomment this will get weird problems
    131         glDetachShader(program, vertexShader);
    132         glDetachShader(program, pixelShader);
    133         glDeleteShader(vertexShader);
    134         glDeleteShader(pixelShader);
    135     }
    136     return program;
    137 }
    138 
    139 
    140 /**
    141  * Initialize an EGL context for the current display.
    142  */
    143 static int engine_init_display(struct engine* engine) {
    144     // initialize OpenGL ES and EGL
    145 
    146     /*
    147      * Here specify the attributes of the desired configuration.
    148      * Below, we select an EGLConfig with at least 8 bits per color
    149      * component compatible with on-screen windows
    150      */
    151     const EGLint attribs[] = {
    152             EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
    153             EGL_BLUE_SIZE, 8,
    154             EGL_GREEN_SIZE, 8,
    155             EGL_RED_SIZE, 8,
    156             EGL_DEPTH_SIZE, 24,
    157             EGL_STENCIL_SIZE, 8,
    158             EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,    //GLES 2.0
    159             EGL_CONFORMANT, EGL_OPENGL_ES2_BIT,
    160             EGL_NONE
    161     };
    162     EGLint w, h, dummy, format;
    163     EGLint numConfigs;
    164     EGLConfig config;
    165     EGLSurface surface;
    166     EGLContext context;
    167 
    168     EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    169 
    170     eglInitialize(display, 0, 0);
    171 
    172     /* Here, the application chooses the configuration it desires. In this
    173      * sample, we have a very simplified selection process, where we pick
    174      * the first EGLConfig that matches our criteria */
    175     eglChooseConfig(display, attribs, &config, 1, &numConfigs);
    176 
    177     /* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is
    178      * guaranteed to be accepted by ANativeWindow_setBuffersGeometry().
    179      * As soon as we picked a EGLConfig, we can safely reconfigure the
    180      * ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. */
    181     eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);
    182 
    183     ANativeWindow_setBuffersGeometry(engine->app->window, 0, 0, format);
    184 
    185     surface = eglCreateWindowSurface(display, config, engine->app->window, NULL);
    186 
    187     const EGLint ContextAttribs[] = {
    188         EGL_CONTEXT_CLIENT_VERSION, 2,
    189         EGL_NONE,
    190     };
    191     context = eglCreateContext(display, config, EGL_NO_CONTEXT, ContextAttribs);
    192 
    193     if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) {
    194         LOGW("Unable to eglMakeCurrent");
    195         return -1;
    196     }
    197 
    198     eglQuerySurface(display, surface, EGL_WIDTH, &w);
    199     eglQuerySurface(display, surface, EGL_HEIGHT, &h);
    200 
    201     engine->display = display;
    202     engine->context = context;
    203     engine->surface = surface;
    204     engine->width = w;
    205     engine->height = h;
    206     engine->state.angle = 0;
    207 
    208     // Initialize GL state.
    209     glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
    210     glDisable(GL_CULL_FACE);
    211     //glShadeModel(GL_SMOOTH);
    212     //glDisable(GL_DEPTH_TEST);
    213 
    214     //create shader
    215     const char* vertexShaders[3] = {
    216 "#version 100 
    
    217 //#extension GL_OES_standard_derivatives : enable 
    
    218 //uniform vec4 WORLD_POS; 
    
    219 uniform vec4 _WORLD2PROJECTED_ROW3; 
    
    220 uniform vec4 _WORLD2PROJECTED_ROW2; 
    
    221 uniform vec4 _WORLD2PROJECTED_ROW1; 
    
    222 uniform vec4 _WORLD2PROJECTED_ROW0; 
    
    223 attribute vec3 vsin_POSITION0; 
    
    224 attribute vec4 vsin_TEXCOORD0; 
    
    225 varying mediump vec4 vsout_TEXCOORD0; 
    
    226 varying mediump vec4 vsout_COLOR0; 
    
    227 void main () 
    
    228 { 
    
    229     vec4 r_6 = vec4(vsin_POSITION0,1);// + WORLD_POS; 
    
    230     mediump vec4 r_8;  
    
    231     r_8.x = dot (r_6, _WORLD2PROJECTED_ROW0); 
    
    232     r_8.y = dot (r_6, _WORLD2PROJECTED_ROW1); 
    
    233     r_8.z = dot (r_6, _WORLD2PROJECTED_ROW2); 
    
    234     r_8.w = dot (r_6, _WORLD2PROJECTED_ROW3); 
    
    235     gl_Position = r_8; 
    
    236     vsout_TEXCOORD0 = vsin_TEXCOORD0; 
    
    237     vsout_COLOR0 = vec4( normalize(vsin_POSITION0-vec3(5,5,5) ),1); 
    
    238 }",
    239 
    240 "#version 100 
    
    241 //#extension GL_OES_standard_derivatives : enable 
    
    242 //uniform vec4 WORLD_POS; 
    
    243 uniform vec4 _WORLD2PROJECTED_ROW3; 
    
    244 uniform vec4 _WORLD2PROJECTED_ROW2; 
    
    245 uniform vec4 _WORLD2PROJECTED_ROW1; 
    
    246 uniform vec4 _WORLD2PROJECTED_ROW0; 
    
    247 attribute vec3 vsin_POSITION0; 
    
    248 attribute vec4 vsin_TEXCOORD0; 
    
    249 varying mediump vec4 vsout_TEXCOORD0; 
    
    250 varying mediump vec4 vsout_COLOR0; 
    
    251 void main () 
    
    252 { 
    
    253     vec4 r_6 = vec4(vsin_POSITION0,1) + vec4(20,0,0,0);// + WORLD_POS; 
    
    254     mediump vec4 r_8;  
    
    255     r_8.x = dot (r_6, _WORLD2PROJECTED_ROW0); 
    
    256     r_8.y = dot (r_6, _WORLD2PROJECTED_ROW1); 
    
    257     r_8.z = dot (r_6, _WORLD2PROJECTED_ROW2); 
    
    258     r_8.w = dot (r_6, _WORLD2PROJECTED_ROW3); 
    
    259     gl_Position = r_8; 
    
    260     vsout_TEXCOORD0 = vsin_TEXCOORD0; 
    
    261     vsout_COLOR0 = vec4( vec3(1,1,1) - normalize(vsin_POSITION0-vec3(5,5,5) ),1); 
    
    262 }",
    263 
    264 "#version 100 
    
    265 //#extension GL_OES_standard_derivatives : enable 
    
    266 //uniform vec4 WORLD_POS; 
    
    267 uniform vec4 _WORLD2PROJECTED_ROW3; 
    
    268 uniform vec4 _WORLD2PROJECTED_ROW2; 
    
    269 uniform vec4 _WORLD2PROJECTED_ROW1; 
    
    270 uniform vec4 _WORLD2PROJECTED_ROW0; 
    
    271 attribute vec3 vsin_POSITION0; 
    
    272 attribute vec4 vsin_TEXCOORD0; 
    
    273 varying mediump vec4 vsout_TEXCOORD0; 
    
    274 varying mediump vec4 vsout_COLOR0; 
    
    275 void main () 
    
    276 { 
    
    277     vec4 r_6 = vec4(vsin_POSITION0,1) + vec4(-20,0,0,0);// + WORLD_POS; 
    
    278     mediump vec4 r_8;  
    
    279     r_8.x = dot (r_6, _WORLD2PROJECTED_ROW0); 
    
    280     r_8.y = dot (r_6, _WORLD2PROJECTED_ROW1); 
    
    281     r_8.z = dot (r_6, _WORLD2PROJECTED_ROW2); 
    
    282     r_8.w = dot (r_6, _WORLD2PROJECTED_ROW3); 
    
    283     gl_Position = r_8; 
    
    284     vsout_TEXCOORD0 = vsin_TEXCOORD0; 
    
    285     vsout_COLOR0 = vec4(1,1,1,1); 
    
    286 }",    };
    287 
    288     const char* fragmentShader[3] = {
    289 
    290 "#version 100 
    
    291 precision mediump float; 
    
    292 #extension GL_OES_standard_derivatives : enable 
    
    293 //uniform mediump sampler2D AlbedoSampler; 
    
    294 varying mediump  vec4 vsout_TEXCOORD0; 
    
    295 varying mediump  vec4 vsout_COLOR0; 
    
    296 void main () 
    
    297 { 
    
    298     //gl_FragColor = texture2D (AlbedoSampler, vsout_TEXCOORD0.xy) + vsout_COLOR0; 
    
    299     //gl_FragColor = vsout_COLOR0; 
    
    300     gl_FragColor = vsout_COLOR0; 
    
    301 }",
    302 
    303 
    304 "#version 100 
    
    305 precision mediump float; 
    
    306 #extension GL_OES_standard_derivatives : enable 
    
    307 //uniform mediump sampler2D AlbedoSampler; 
    
    308 varying mediump  vec4 vsout_TEXCOORD0; 
    
    309 varying mediump  vec4 vsout_COLOR0; 
    
    310 void main () 
    
    311 { 
    
    312     //gl_FragColor = texture2D (AlbedoSampler, vsout_TEXCOORD0.xy); 
    
    313     //gl_FragColor = texture2D (AlbedoSampler, vsout_TEXCOORD0.xy) + vsout_COLOR0; 
    
    314     gl_FragColor = vsout_COLOR0; 
    
    315 }",
    316 
    317 
    318 "#version 100 
    
    319 precision mediump float; 
    
    320 #extension GL_OES_standard_derivatives : enable 
    
    321 //uniform mediump sampler2D AlbedoSampler; 
    
    322 varying mediump  vec4 vsout_TEXCOORD0; 
    
    323 varying mediump  vec4 vsout_COLOR0; 
    
    324 void main () 
    
    325 { 
    
    326     //gl_FragColor = texture2D (AlbedoSampler, vsout_TEXCOORD0.xy); 
    
    327     //gl_FragColor = texture2D (AlbedoSampler, vsout_TEXCOORD0.xy) + vsout_COLOR0; 
    
    328     gl_FragColor = vsout_COLOR0; 
    
    329 }",
    330 
    331     };
    332 
    333     engine->program[0] = CreateProgram(vertexShaders[0], fragmentShader[0]);
    334     engine->program[1] = CreateProgram(vertexShaders[1], fragmentShader[1]);
    335     engine->program[2] = CreateProgram(vertexShaders[2], fragmentShader[2]);
    336 
    337     return 0;
    338 }
    339 
    340 /**
    341  * Just the current frame in the display.
    342  */
    343 static void engine_draw_frame(struct engine* engine) {
    344     if (engine->display == NULL) {
    345         // No display.
    346         return;
    347     }
    348 
    349     // Just fill the screen with a color.
    350     //glClearColor(((float)engine->state.x)/engine->width, engine->state.angle,
    351     //        ((float)engine->state.y)/engine->height, 1);
    352 
    353     glClearColor( 0.5, 0.5, 0.5, 1);
    354     glClearDepthf(1.0f);
    355     glClear(GL_COLOR_BUFFER_BIT);
    356     
    357 
    358 
    359 #define Scale 10.0f
    360 
    361     static const GLfloat CubeVertices[36][3] = { 
    362         Scale, Scale,   Scale, 
    363         Scale, Scale,   0,
    364         Scale, 0,       0,
    365 
    366         Scale, Scale,   Scale,
    367         Scale, 0,       0,
    368         Scale, 0,       Scale,
    369 
    370         0,     0,       0,
    371         Scale, 0,       0,
    372         Scale, Scale,   0,
    373 
    374         0,     0,       0,
    375         Scale, Scale,   0,
    376         0,     Scale,   0,
    377 
    378         0,     Scale,   0,
    379         Scale, Scale,   0,
    380         Scale, Scale,   Scale,
    381 
    382         0,     Scale,   0,
    383         Scale, Scale,   Scale,
    384         0,     Scale,   Scale,
    385 
    386         0,     Scale,   0,
    387         0,     0,       Scale,
    388         0,     0,       0,
    389 
    390         0,     Scale,   0,
    391         0,     Scale,   Scale,
    392         0,     0,       Scale,
    393 
    394         0,     0,       Scale,
    395         0,     0,       0,
    396         Scale, 0,       0,
    397 
    398         0,     0,       Scale,
    399         Scale, 0,       0,
    400         Scale, 0,       Scale,
    401 
    402         0,     Scale,   Scale,
    403         Scale, 0,       Scale,
    404         0,     0,       Scale,
    405 
    406         0,     Scale,   Scale,
    407         Scale, Scale,   Scale,
    408         Scale, 0,       Scale,
    409     };
    410 
    411     static const GLfloat CubeUV[36][2] = { 
    412         0, 0, 
    413         0, 1, 
    414         1, 1, 
    415                       
    416         0, 0, 
    417         1, 1, 
    418         1, 0, 
    419                       
    420         1, 0, 
    421         1, 1, 
    422         0, 1, 
    423                       
    424         1, 0, 
    425         0, 1, 
    426         0, 0, 
    427                       
    428         0, 0, 
    429         0, 1, 
    430         1, 1, 
    431                       
    432         0, 0, 
    433         1, 1, 
    434         1, 0, 
    435                       
    436         0, 0, 
    437         1, 1, 
    438         1, 0,
    439     };
    440 
    441     //for simplification, this view-projection matrix is copied from engine using  matrix utility
    442     GLfloat viewporj[4][4] = 
    443     {
    444         1.73217857,0,-3.09281524e-011,0,
    445         -3.49910968e-011, 1.95973194, -1.95973027, 0,
    446         -1.26294461e-011, -0.707330883, -0.707331479, 52.8758965,
    447         -1.26254051e-011, -0.707104564, -0.70710516, 84.8589783
    448     };
    449 
    450     int i = 0;
    451     for(i = 0; i < 3; ++i)
    452     {
    453         glUseProgram(engine->program[i]);
    454         glUniform4fv( glGetUniformLocation(engine->program[i], "_WORLD2PROJECTED_ROW0"), 1, viewporj[0]);
    455         glUniform4fv( glGetUniformLocation(engine->program[i], "_WORLD2PROJECTED_ROW1"), 1, viewporj[1]);
    456         glUniform4fv( glGetUniformLocation(engine->program[i], "_WORLD2PROJECTED_ROW2"), 1, viewporj[2]);
    457         glUniform4fv( glGetUniformLocation(engine->program[i], "_WORLD2PROJECTED_ROW3"), 1, viewporj[3]);
    458         glEnableVertexAttribArray( Position );
    459         glVertexAttribPointer(Position, 3, GL_FLOAT, GL_FALSE, 0, CubeVertices);
    460         //setup vertex UV buffer
    461         glEnableVertexAttribArray(UV);
    462         glVertexAttribPointer(UV, 2, GL_FLOAT, GL_FALSE, 0, CubeUV);
    463         //draw call & swap
    464         glDrawArrays(GL_TRIANGLES, 0, 36);
    465 
    466         glDisableVertexAttribArray(Position);
    467         glDisableVertexAttribArray(UV);
    468     }
    469 
    470 
    471     eglSwapBuffers(engine->display, engine->surface);
    472 }
    473 
    474 /**
    475  * Tear down the EGL context currently associated with the display.
    476  */
    477 static void engine_term_display(struct engine* engine) {
    478     if (engine->display != EGL_NO_DISPLAY) {
    479         eglMakeCurrent(engine->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
    480         if (engine->context != EGL_NO_CONTEXT) {
    481             eglDestroyContext(engine->display, engine->context);
    482         }
    483         if (engine->surface != EGL_NO_SURFACE) {
    484             eglDestroySurface(engine->display, engine->surface);
    485         }
    486         eglTerminate(engine->display);
    487     }
    488     engine->animating = 0;
    489     engine->display = EGL_NO_DISPLAY;
    490     engine->context = EGL_NO_CONTEXT;
    491     engine->surface = EGL_NO_SURFACE;
    492 }
    493 
    494 /**
    495  * Process the next input event.
    496  */
    497 static int32_t engine_handle_input(struct android_app* app, AInputEvent* event) {
    498     struct engine* engine = (struct engine*)app->userData;
    499     if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) {
    500         engine->animating = 1;
    501         engine->state.x = AMotionEvent_getX(event, 0);
    502         engine->state.y = AMotionEvent_getY(event, 0);
    503         return 1;
    504     }
    505     return 0;
    506 }
    507 
    508 /**
    509  * Process the next main command.
    510  */
    511 static void engine_handle_cmd(struct android_app* app, int32_t cmd) {
    512     struct engine* engine = (struct engine*)app->userData;
    513     switch (cmd) {
    514         case APP_CMD_SAVE_STATE:
    515             // The system has asked us to save our current state.  Do so.
    516             engine->app->savedState = malloc(sizeof(struct saved_state));
    517             *((struct saved_state*)engine->app->savedState) = engine->state;
    518             engine->app->savedStateSize = sizeof(struct saved_state);
    519             break;
    520         case APP_CMD_INIT_WINDOW:
    521             // The window is being shown, get it ready.
    522             if (engine->app->window != NULL) {
    523                 engine_init_display(engine);
    524                 engine_draw_frame(engine);
    525             }
    526             break;
    527         case APP_CMD_TERM_WINDOW:
    528             // The window is being hidden or closed, clean it up.
    529             engine_term_display(engine);
    530             break;
    531         case APP_CMD_GAINED_FOCUS:
    532             // When our app gains focus, we start monitoring the accelerometer.
    533             if (engine->accelerometerSensor != NULL) {
    534                 ASensorEventQueue_enableSensor(engine->sensorEventQueue,
    535                         engine->accelerometerSensor);
    536                 // We'd like to get 60 events per second (in us).
    537                 ASensorEventQueue_setEventRate(engine->sensorEventQueue,
    538                         engine->accelerometerSensor, (1000L/60)*1000);
    539             }
    540             break;
    541         case APP_CMD_LOST_FOCUS:
    542             // When our app loses focus, we stop monitoring the accelerometer.
    543             // This is to avoid consuming battery while not being used.
    544             if (engine->accelerometerSensor != NULL) {
    545                 ASensorEventQueue_disableSensor(engine->sensorEventQueue,
    546                         engine->accelerometerSensor);
    547             }
    548             // Also stop animating.
    549             engine->animating = 0;
    550             engine_draw_frame(engine);
    551             break;
    552     }
    553 }
    554 
    555 /**
    556  * This is the main entry point of a native application that is using
    557  * android_native_app_glue.  It runs in its own thread, with its own
    558  * event loop for receiving input events and doing other things.
    559  */
    560 void android_main(struct android_app* state) {
    561     struct engine engine;
    562 
    563     // Make sure glue isn't stripped.
    564     app_dummy();
    565 
    566     memset(&engine, 0, sizeof(engine));
    567     state->userData = &engine;
    568     state->onAppCmd = engine_handle_cmd;
    569     state->onInputEvent = engine_handle_input;
    570     engine.app = state;
    571 
    572     // Prepare to monitor accelerometer
    573     engine.sensorManager = ASensorManager_getInstance();
    574     engine.accelerometerSensor = ASensorManager_getDefaultSensor(engine.sensorManager,
    575             ASENSOR_TYPE_ACCELEROMETER);
    576     engine.sensorEventQueue = ASensorManager_createEventQueue(engine.sensorManager,
    577             state->looper, LOOPER_ID_USER, NULL, NULL);
    578 
    579     if (state->savedState != NULL) {
    580         // We are starting with a previous saved state; restore from it.
    581         engine.state = *(struct saved_state*)state->savedState;
    582     }
    583 
    584     // loop waiting for stuff to do.
    585 
    586     while (1) {
    587         // Read all pending events.
    588         int ident;
    589         int events;
    590         struct android_poll_source* source;
    591 
    592         // If not animating, we will block forever waiting for events.
    593         // If animating, we loop until all events are read, then continue
    594         // to draw the next frame of animation.
    595         while ((ident=ALooper_pollAll(engine.animating ? 0 : -1, NULL, &events,
    596                 (void**)&source)) >= 0) {
    597 
    598             // Process this event.
    599             if (source != NULL) {
    600                 source->process(state, source);
    601             }
    602 
    603             // If a sensor has data, process it now.
    604             if (ident == LOOPER_ID_USER) {
    605                 if (engine.accelerometerSensor != NULL) {
    606                     ASensorEvent event;
    607                     while (ASensorEventQueue_getEvents(engine.sensorEventQueue,
    608                             &event, 1) > 0) {
    609                         //LOGI("accelerometer: x=%f y=%f z=%f",
    610                         //       event.acceleration.x, event.acceleration.y,
    611                         //        event.acceleration.z);
    612                     }
    613                 }
    614             }
    615 
    616             // Check if we are exiting.
    617             if (state->destroyRequested != 0) {
    618                 engine_term_display(&engine);
    619                 return;
    620             }
    621         }
    622 
    623         if (engine.animating) {
    624             // Done with events; draw next animation frame.
    625             engine.state.angle += .01f;
    626             if (engine.state.angle > 1) {
    627                 engine.state.angle = 0;
    628             }
    629 
    630             // Drawing is throttled to the screen update rate, so there
    631             // is no need to do timing here.
    632             engine_draw_frame(&engine);
    633         }
    634     }
    635 }
    636 //END_INCLUDE(all)
    View Code

    主要是对GL/ES不太熟悉, 而且bug比较诡异, 根本没想到会出这种问题. 代码贴出来, 或许是别的地方有问题, 希望有大大看到帮忙瞧一眼.

    顺便, 该平台的GLES是2.0, build version是1.8, 可以正常显式的三星手机也是GLES2.0, build version是1.9rc.


    另外, 之前OBB的问题, 使用40M+的OBB, 运行时基本不会报错了, 但是现在OBB单个文件夹内的文件数太少了, 打包时会抛出异常.

    http://stackoverflow.com/questions/13562617/using-jobb-tool-in-android

    SO上说,内置的OBB格式是FAT16,单个文件夹内只能有512个项...想起来自己引擎新写的pacakge,应该算没有白写.
    公司的项目, 考虑使用多文件夹来重新组织数据, 但是太繁琐,太不可控, 一不小心就会超了, 或者考虑也得写自定义的package.

    工作很忙, 暂时写这么多吧.


    对于OBB, 目前最快的方案是使用子文件夹, 这样根目录的限制就没有了, mount以后把子文件夹的路径加上, 作为data的根路径, 应该最简单了.

  • 相关阅读:
    经典SQL语句大全
    主键,外键,主键表,外间表
    一个不错的shell 脚本教程 入门级
    初窥Linux 之 我最常用的20条命令
    try catch finally 用法
    一个初学者对于MVC架构的理解
    第二次阶段冲刺2(6月1号)
    第二次阶段冲刺1(5月31号)
    学习进度条十三(第14周)
    学习进度条十二(第13周)
  • 原文地址:https://www.cnblogs.com/crazii/p/3653633.html
Copyright © 2011-2022 走看看