GLUtils.texImage 2 Dの最下位呼び出しプロセス
4667 ワード
本書では、メンテナンスされているAndroidプロジェクトでSDKパッケージのOpenGLインタフェースを使用しているだけなので、下層部でどのような操作が行われているのか、純粋に記録されています.
AndroidXRefソースリファレンスサイトによると、/frameworks/base/core/jni/android/opengl/util.cppのファイルはnative_texImage 2 Dをutil_にマッピングtexImage2D.
util_texImage 2 D関数は、bitmap情報に基づいてglCompressedTexImage 2 DまたはglTexImage 2 Dを介してOpenGLサーバ側に画像データをアップロードすることを決定する.
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
// native_texImage2D
// native_texImage2D(target, level/*0*/, /*internalformat*/-1, bitmap, /*type*/-1, border/*0*/);
AndroidXRefソースリファレンスサイトによると、/frameworks/base/core/jni/android/opengl/util.cppのファイルはnative_texImage 2 Dをutil_にマッピングtexImage2D.
static JNINativeMethod gUtilsMethods[] = {
{ "native_getInternalFormat", "(Landroid/graphics/Bitmap;)I", (void*) util_getInternalFormat },
{ "native_getType", "(Landroid/graphics/Bitmap;)I", (void*) util_getType },
{ "native_texImage2D", "(IIILandroid/graphics/Bitmap;II)I", (void*)util_texImage2D },
{ "native_texSubImage2D", "(IIIILandroid/graphics/Bitmap;II)I", (void*)util_texSubImage2D },
{ "setTracingLevel", "(I)V", (void*)setTracingLevel },
};
util_texImage 2 D関数は、bitmap情報に基づいてglCompressedTexImage 2 DまたはglTexImage 2 Dを介してOpenGLサーバ側に画像データをアップロードすることを決定する.
static jint util_texImage2D(JNIEnv *env, jclass clazz,
jint target, jint level, jint internalformat,
jobject jbitmap, jint type, jint border)
{
SkBitmap bitmap;
GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
SkColorType colorType = bitmap.colorType();
if (internalformat < 0) {
internalformat = getInternalFormat(colorType);
}
if (type < 0) {
type = getType(colorType);
}
int err = checkFormat(colorType, internalformat, type);
if (err)
return err;
bitmap.lockPixels();
const int w = bitmap.width();
const int h = bitmap.height();
const void* p = bitmap.getPixels();
if (internalformat == GL_PALETTE8_RGBA8_OES) {
if (sizeof(SkPMColor) != sizeof(uint32_t)) {
err = -1;
goto error;
}
const size_t size = bitmap.getSize();
const size_t palette_size = 256*sizeof(SkPMColor);
const size_t imageSize = size + palette_size;
void* const data = malloc(imageSize);
if (data) {
void* const pixels = (char*)data + palette_size;
SkColorTable* ctable = bitmap.getColorTable();
memcpy(data, ctable->readColors(), ctable->count() * sizeof(SkPMColor));
memcpy(pixels, p, size);
glCompressedTexImage2D(target, level, internalformat, w, h, border, imageSize, data);
free(data);
} else {
err = -1;
}
} else {
glTexImage2D(target, level, internalformat, w, h, border, internalformat, type, p);
}
error:
bitmap.unlockPixels();
return err;
}
static int getInternalFormat(SkColorType colorType)
{
switch(colorType) {
case kAlpha_8_SkColorType:
return GL_ALPHA;
case kARGB_4444_SkColorType:
return GL_RGBA;
case kN32_SkColorType:
return GL_RGBA;
case kIndex_8_SkColorType:
return GL_PALETTE8_RGBA8_OES;
case kRGB_565_SkColorType:
return GL_RGB;
default:
return -1;
}
}
static int checkFormat(SkColorType colorType, int format, int type)
{
switch(colorType) {
case kIndex_8_SkColorType:
if (format == GL_PALETTE8_RGBA8_OES)
return 0;
case kN32_SkColorType:
case kAlpha_8_SkColorType:
if (type == GL_UNSIGNED_BYTE)
return 0;
case kARGB_4444_SkColorType:
case kRGB_565_SkColorType:
switch (type) {
case GL_UNSIGNED_SHORT_4_4_4_4:
case GL_UNSIGNED_SHORT_5_6_5:
case GL_UNSIGNED_SHORT_5_5_5_1:
return 0;
case GL_UNSIGNED_BYTE:
if (format == GL_LUMINANCE_ALPHA)
return 0;
}
break;
default:
break;
}
return -1;
}
static int getType(SkColorType colorType)
{
switch(colorType) {
case kAlpha_8_SkColorType:
return GL_UNSIGNED_BYTE;
case kARGB_4444_SkColorType:
return GL_UNSIGNED_SHORT_4_4_4_4;
case kN32_SkColorType:
return GL_UNSIGNED_BYTE;
case kIndex_8_SkColorType:
return -1; // No type for compressed data.
case kRGB_565_SkColorType:
return GL_UNSIGNED_SHORT_5_6_5;
default:
return -1;
}
}