GLUtils.texImage 2 Dの最下位呼び出しプロセス

4667 ワード

本書では、メンテナンスされているAndroidプロジェクトでSDKパッケージの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;
    }
}