0

ゲームの Java 部分を呼び出してジョブを実行する C 言語のテクスチャ ロード ルーチンがあります。.png ファイルと .jpg ファイルを読み込んで、それらからテクスチャを作成できます。生成された textureID (glGenTextures で生成) を C に返します。フロントバッファを使い始めるまでは完璧に機能していました。

フロント バッファのテクスチャは空なので、C で直接作成しています。初めてゲームを実行すると問題なく動作します。フロント バッファ用に生成されたテクスチャ ID は、他のすべてのテクスチャ ID とは異なります。しかし、HOME キーを押すと、再びゲームに戻り、すべてのテクスチャをリロードしてフロント バッファを再作成します (コンテキストの損失から回復するため)。フロント バッファ用に生成されたテクスチャ ID が、テクスチャ用に生成されたテクスチャ ID の 1 つと衝突します2 つの ID ライン。フレームバッファを使用している画面が壊れています - フレームバッファの新しく割り当てられた ID と同じ ID を持つテクスチャが表示されます。

これはすべて、エミュレーターではなく、実際のデバイス (私の場合は Samsung Galaxy Tablet) でのみ発生します。

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 ルーチン

// 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);
}

誰も同じ問題に遭遇しましたか?

4

1 に答える 1

2

私は最終的に解決策を見つけました。コンテキストの損失が発生すると、すべてのテクスチャが削除されます。しかし、以前にソートされたIDで再作成する前に、自分でそれらを削除していました。次のオブジェクトを更新するときに、新しく生成された ID がすぐに削除されるため、プロセス中に混乱が生じました。

于 2013-03-17T18:17:11.440 に答える