JNIEXPORT void JNICALL Java_org_lwjgl_opengl_GL42_nglGetInternalformativ__IIIIJ(JNIEnv *__env, jclass clazz, jint target, jint internalformat, jint pname, jint bufSize, jlong paramsAddress) {
    glGetInternalformativPROC glGetInternalformativ = (glGetInternalformativPROC)tlsGetFunction(869);
    intptr_t params = (intptr_t)paramsAddress;
    UNUSED_PARAM(clazz)
    glGetInternalformativ(target, internalformat, pname, bufSize, params);
}
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
Texture2DContainer::Texture2DContainer(bool sparse, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei slices)
: mHandle(0)
, mWidth(width)
, mHeight(height)
, mLevels(levels)
, mSlices(slices)
, mXTileSize(0)
, mYTileSize(0)
{
    glGenTextures(1, &mTexId);
    glBindTexture(GL_TEXTURE_2D_ARRAY, mTexId);

    if (sparse) {
        glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_SPARSE_ARB, GL_TRUE);

        // TODO: This could be done once per internal format. For now, just do it every time.
        GLint indexCount = 0,
            xSize = 0,
            ySize = 0,
            zSize = 0;

        GLint bestIndex = -1,
            bestXSize = 0,
            bestYSize = 0;

        glGetInternalformativ(GL_TEXTURE_2D_ARRAY, internalformat, GL_NUM_VIRTUAL_PAGE_SIZES_ARB, 1, &indexCount);
        for (GLint i = 0; i < indexCount; ++i) {
            glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_VIRTUAL_PAGE_SIZE_INDEX_ARB, i);
            glGetInternalformativ(GL_TEXTURE_2D_ARRAY, internalformat, GL_VIRTUAL_PAGE_SIZE_X_ARB, 1, &xSize);
            glGetInternalformativ(GL_TEXTURE_2D_ARRAY, internalformat, GL_VIRTUAL_PAGE_SIZE_Y_ARB, 1, &ySize);
            glGetInternalformativ(GL_TEXTURE_2D_ARRAY, internalformat, GL_VIRTUAL_PAGE_SIZE_Z_ARB, 1, &zSize);

            // For our purposes, the "best" format is the one that winds up with Z=1 and the largest x and y sizes.
            if (zSize == 1) {
                if (xSize >= bestXSize && ySize >= bestYSize) {
                    bestIndex = i;
                    bestXSize = xSize;
                    bestYSize = ySize;
                }
            }
        }

        // This would mean the implementation has no valid sizes for us, or that this format doesn't actually support sparse
        // texture allocation. Need to implement the fallback. TODO: Implement that.
        assert(bestIndex != -1);

        mXTileSize = bestXSize;

        glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_VIRTUAL_PAGE_SIZE_INDEX_ARB, bestIndex);
    }

    // We've set all the necessary parameters, now it's time to create the sparse texture.
    glTexStorage3D(GL_TEXTURE_2D_ARRAY, levels, internalformat, width, height, mSlices);
    for (GLsizei i = 0; i < mSlices; ++i) {
        mFreeList.push(i);
    }

    if (sparse) {
        mHandle = glGetTextureHandleARB(mTexId);
        assert(mHandle != 0);
        glMakeTextureHandleResidentARB(mHandle);
    }
}