function ZRTextureAtlasSurface (opt) {

    opt = opt || {};
    opt.width = opt.width || 512;
    opt.height = opt.height || 512;
    opt.devicePixelRatio = opt.devicePixelRatio || 1;
    opt.gap = opt.gap == null ? 2 : opt.gap;

    var canvas = document.createElement('canvas');
    canvas.width = opt.width * opt.devicePixelRatio;
    canvas.height = opt.height * opt.devicePixelRatio;

    this._canvas = canvas;

    this._texture = new src_Texture2D({
        image: canvas,
        flipY: false
    });

    var self = this;
    /**
     * zrender instance in the Chart
     * @type {zrender~ZRender}
     */
    this._zr = external_echarts_.zrender.init(canvas);
    var oldRefreshImmediately = this._zr.refreshImmediately;
    this._zr.refreshImmediately = function () {
        oldRefreshImmediately.call(this);
        self._texture.dirty();
        self.onupdate && self.onupdate();
    };

    this._dpr = opt.devicePixelRatio;

    /**
     * Texture coords map for each sprite image
     * @type {Object}
     */
    this._coords = {};

    this.onupdate = opt.onupdate;

    this._gap = opt.gap;

    // Left sub atlas.
    this._textureAtlasNodes = [new ZRTextureAtlasSurfaceNode(
        this._zr, 0, 0, opt.width, opt.height, this._gap, this._dpr
    )];

    this._nodeWidth = opt.width;
    this._nodeHeight = opt.height;

    this._currentNodeIdx = 0;
}
constructor
@alias module:echarts-gl/util/ZRTextureAtlasSurface
@param {number} opt.width
@param {number} opt.height
@param {number} opt.devicePixelRatio
@param {number} opt.gap Gap for safe.
@param {Function} opt.onupdate