ゲームの 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);
}
誰も同じ問題に遭遇しましたか?