2013-03-17 71 views
0

我在C中调用了纹理加载例程,它调用我的游戏的Java部分来完成这项工作。它可以加载.png以及.jpg文件并从中创建纹理。它返回C生成的textureID(用glGenTextures生成)。它工作完美,直到我开始使用前缓冲区。OpenGL纹理ID不止一次生成

由于前缓冲区的纹理是空的,我直接在C中创建它。当我第一次运行游戏时,它可以正常工作 - 为前缓冲区生成的纹理ID与所有其他纹理ID不同。但是当按HOME键时,再次跳回到游戏中,我重新加载所有纹理并再次重新创建前缓冲区(从上下文丢失中恢复),为前缓冲区生成的纹理ID与为纹理生成的纹理ID之一发生冲突 - 两条ID线。使用帧缓冲区的屏幕已损坏 - 显示ID等于新分配的帧缓冲区ID的纹理。

这一切都只发生在真实设备(我的情况下是三星Galaxy平板电脑),而不是仿真器。

的C装载程序:

void Texture::construct(AssetLoader* aLoader, s32 aIdx) 
{ 
    const c8* fileName = aLoader->getFileName(); 

    // load texture 
    SBC::System::Application* app = &Game::getGame().getApplication(); 

    JNIEnv *env; 

    bool shouldDetach = false; 
    JavaVM* vm = gJavaVM; 
    jint rc = vm->GetEnv((void **)&env, JNI_VERSION_1_6); 
    if (rc != JNI_OK) 
    { 
     shouldDetach = true; 
     vm->AttachCurrentThread(&env, NULL); 
    } 
    jclass& activityClass = gJavaActivityClass; 

    jmethodID mid = env->GetStaticMethodID(activityClass, "loadTexture", "(Ljava/lang/String;I)I"); 
    jstring mystr = env->NewStringUTF(fileName); 
    jint ret = env->CallStaticIntMethod(activityClass, mid, mystr, aIdx); 
    env->DeleteLocalRef(mystr); 

    // store information on ID, width and height of texture 
    mTextureID = ret; 

    LOGE("textureID = %i", mTextureID); 

    mid = env->GetStaticMethodID(activityClass, "getTextureWidth", "()I"); 
    mWidth = env->CallStaticIntMethod(activityClass, mid); 
    mid = env->GetStaticMethodID(activityClass, "getTextureHeight", "()I"); 
    mHeight = env->CallStaticIntMethod(activityClass, mid); 

    if (shouldDetach) 
     vm->DetachCurrentThread(); 

    LOGI("texture ID %i, width %i, height %i", mTextureID, mWidth, mHeight); 
} 

Java方法

//----------------------------------------------------- 
/* fname = asset file name 
* id >= 0 ... position in compound file 
* id < 0 ... single file (no compound) 
*/ 
public static int loadTexture(String fname, int id) 
{ 
    // clear last texture parameters 
    txtID = width = height = -1; 

    Log.d("Helper", "Loading texture from asset file " + fname + " with id " + id); 

    final BitmapFactory.Options options = new BitmapFactory.Options(); 
    options.inScaled = false;  // No pre-scaling 
    AssetManager am = SBCEngine.getSBCEngine().getAssets(); 
    Bitmap bitmap = null; 

    try 
    { 
     InputStream stream = am.open(fname); 

     // loading from compound file? 
     if (id >= 0) 
     { 
      DataInputStream input = new DataInputStream(stream); 

      // skip header 
      input.skip(3); 
      // skip to entry offset 
      input.skip(id * 4); 
      // read entry beginning 
      int dataStart = input.readInt(); 
      // read data length 
      int dataLen = input.readInt() - dataStart; 
      // skip to start of subfile 
      // offsets are without header (3) bytes 
      // we already skipped id * 4 bytes 
      // we already have read 2 offset by 4 bytes = 8 in total 
      input.skip(dataStart - (id * 4) - 8); 

      // get data from correct position 
      byte[] data = new byte[dataLen]; 
      input.read(data); 

      bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, options); 
     } 
     else // no compound 
     { 
      Log.d("Helper", "Loading from stream"); 
      bitmap = BitmapFactory.decodeStream(stream, null, options); 
     } 


     // test returned bitmap for success 
     if (bitmap == null) 
     { 
      Log.e("Helper", "Failed to load texture " + fname + " with id " + id); 
     } 

     // check whether the loaded bitmap has width and height equal to power of 2 
     int w = bitmap.getWidth(); 
     int h = bitmap.getHeight(); 
     if (getNearestPOT(w) != w || getNearestPOT(h) != h) 
     { 
      Log.w("Helper", "Texture " + fname + " with id " + id + 
        " has not either width or height power of 2"); 

      // new dimensions 
      w = getNearestPOT(w); 
      h = getNearestPOT(h); 

      // get actual bitmap config 
      Bitmap.Config bitmapConfig = bitmap.getConfig(); 
      // check for null 
      if (bitmapConfig == null) 
      { 
       bitmapConfig = Bitmap.Config.ARGB_8888; 
       Log.w("Helper", "Unknown bitmap config. Setting to ARGB_8888"); 
      } 
      // redraw bitmap into POT bitmap 
      Bitmap newBitmap = Bitmap.createBitmap(w, h, bitmapConfig); 
      Canvas canvas = new Canvas(newBitmap); 
      canvas.drawBitmap(bitmap, 0.0f, 0.0f, null); 
      bitmap.recycle(); 
      canvas = null; 
      bitmap = newBitmap; 

      Log.w("Helper", "Texture " + fname + " rebuilded into texture with POT"); 
     } 

     // generate textureID 
     int[] textures = new int[1]; 
     GLES20.glGenTextures(1, textures, 0); 
     int textureID = textures[0]; 

     // create texture 
     GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureID); 
     GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR); 
     GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); 
     GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); 
     GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); 
     GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0); 

     // destroy bitmap 
     bitmap.recycle(); 

     txtID = textureID; 
     width = w; 
     height = h; 

     Log.d("Helper", "Loaded texture ID:" + textureID + ", width:" + w + ", height:" + h); 
     return textureID; 
    } 
    catch (IOException e) 
    { 
     Log.e("Helper", "Failed to load texture " + fname + " with id " + id); 
     return 0; 
    } 
} 

//------------------------------------------------------------------------ 
public static int getTextureWidth() 
{ 
    return width; 
} 

//------------------------------------------------------------------------ 
public static int getTextureHeight() 
{ 
    return height; 
} 

//------------------------------------------------------------------------ 
private static int getNearestPOT(int val) 
{ 
    int newDim = 1; 
    while(val > newDim) newDim *= 2; 
    return newDim; 
} 

最后C例程创建纹理frontbuffer

// create empty texture 
void Texture::construct(u32 aTextureWidth, u32 aTextureHeight) 
{ 
    // get power of 2 dimensions 
    mWidth = getNearestPOT(aTextureWidth); 
    mHeight = getNearestPOT(aTextureHeight); 

    glGenTextures(1, &mTextureID); 
    glBindTexture(GL_TEXTURE_2D, mTextureID); 
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, mWidth, mHeight, 0, 
      GL_RGB, GL_UNSIGNED_SHORT_5_6_5, null); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 

    LOGE("textureID = %i", mTextureID); 
} 

任何encoutered同样的问题?

回答

2

我终于找到了解决方案。当上下文丢失发生时,所有纹理都被删除。但是在重新创建以前的s ID之前,我自己删除了它们。在过程中导致混乱,因为一些新生成的ID在更新下一个对象时立即被删除。