const TEXTURE_PARAMS = @map Symbol, GLenum {
    depth_mode   = GL_DEPTH_STENCIL_TEXTURE_MODE,
    base_level   = GL_TEXTURE_BASE_LEVEL,
    compare_func = GL_TEXTURE_COMPARE_FUNC,
    compare_mode = GL_TEXTURE_COMPARE_MODE,
    lod_bias     = GL_TEXTURE_LOD_BIAS,
    min_filter   = GL_TEXTURE_MIN_FILTER,
    mag_filter   = GL_TEXTURE_MAG_FILTER,
    min_lod      = GL_TEXTURE_MIN_LOD,
    max_lod      = GL_TEXTURE_MAX_LOD,
    max_level    = GL_TEXTURE_MAX_LEVEL,
    swizzle_r    = GL_TEXTURE_SWIZZLE_R,
    swizzle_g    = GL_TEXTURE_SWIZZLE_G,
    swizzle_b    = GL_TEXTURE_SWIZZLE_B,
    swizzle_a    = GL_TEXTURE_SWIZZLE_A,
    wrap_s       = GL_TEXTURE_WRAP_S,
    wrap_t       = GL_TEXTURE_WRAP_T,
    wrap_r       = GL_TEXTURE_WRAP_R,
}

function texture2D(pixels::Union{AbstractArray, Ptr}, width::Integer, height::Integer)
    texture, type = GLuint'[], g"TEXTURE 2D"
    glGenTextures(1, texture)
    glBindTexture(type, texture')
    glTexImage2D(type, 0, g"RGB", width, height, 0, g"RGB", g"UNSIGNED BYTE", pixels)
    glGenerateMipmap(g"texture 2d")
    return texture'
end

function texture2D(pixels::Union{AbstractArray, Ptr}, width::Integer, height::Integer, params::Dict{Symbol, GLenum})
    texture = texture2D(pixels, width, height)
    for (param, value) in params
        param ∉ keys(TEXTURE_PARAMS) && error("Unkown texture parameter '$param'")
        glTexParameteri(g"TEXTURE 2D", TEXTURE_PARAMS[param], value)
    end
    return texture
end