scheduler.dart 2.9 KB
Newer Older
1 2 3 4
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5
import 'dart:collection';
6 7 8 9
import 'dart:sky' as sky;

import 'package:sky/base/debug.dart';

Adam Barth's avatar
Adam Barth committed
10 11 12 13 14 15 16
/// A callback from the scheduler
///
/// The timeStamp is the number of milliseconds since the beginning of the
/// scheduler's epoch. Use timeStamp to determine how far to advance animation
/// timelines so that all the animations in the system are synchronized to a
/// common time base.
typedef void SchedulerCallback(double timeStamp);
17 18 19 20

bool _haveScheduledVisualUpdate = false;
int _nextCallbackId = 1;

Adam Barth's avatar
Adam Barth committed
21 22
final List<SchedulerCallback> _persistentCallbacks = new List<SchedulerCallback>();
Map<int, SchedulerCallback> _transientCallbacks = new LinkedHashMap<int, SchedulerCallback>();
23
final Set<int> _removedIds = new Set<int>();
24

Adam Barth's avatar
Adam Barth committed
25 26 27 28 29
/// Called by the engine to produce a new frame.
///
/// This function first calls all the callbacks registered by
/// [requestAnimationFrame] and then calls all the callbacks registered by
/// [addPersistentFrameCallback], which typically drive the rendering pipeline.
30
void beginFrame(double timeStamp) {
31 32 33 34
  timeStamp /= timeDilation;

  _haveScheduledVisualUpdate = false;

Adam Barth's avatar
Adam Barth committed
35 36
  Map<int, SchedulerCallback> callbacks = _transientCallbacks;
  _transientCallbacks = new Map<int, SchedulerCallback>();
37 38

  callbacks.forEach((id, callback) {
39 40
    if (!_removedIds.contains(id))
      callback(timeStamp);
41
  });
42
  _removedIds.clear();
43

Adam Barth's avatar
Adam Barth committed
44
  for (SchedulerCallback callback in _persistentCallbacks)
45 46 47
    callback(timeStamp);
}

Adam Barth's avatar
Adam Barth committed
48
/// Registers [beginFrame] callback with the engine.
49
void init() {
50
  sky.view.setFrameCallback(beginFrame);
51 52
}

Adam Barth's avatar
Adam Barth committed
53 54
/// Call callback every frame.
void addPersistentFrameCallback(SchedulerCallback callback) {
55 56 57
  _persistentCallbacks.add(callback);
}

Adam Barth's avatar
Adam Barth committed
58 59 60 61 62 63 64 65 66 67 68 69
/// Schedule a callback for the next frame.
///
/// The callback will be run prior to flushing the main rendering pipeline.
/// Typically, requestAnimationFrame is used to throttle writes into the
/// rendering pipeline until the system is ready to accept a new frame. For
/// example, if you wanted to tick through an animation, you should use
/// requestAnimation frame to determine when to tick the animation. The callback
/// is passed a timeStamp that you can use to determine how far along the
/// timeline to advance your animation.
///
/// Returns an id that can be used to unschedule this callback.
int requestAnimationFrame(SchedulerCallback callback) {
70 71 72 73 74 75
  int id = _nextCallbackId++;
  _transientCallbacks[id] = callback;
  ensureVisualUpdate();
  return id;
}

Adam Barth's avatar
Adam Barth committed
76
/// Cancel the callback identified by id.
77 78
void cancelAnimationFrame(int id) {
  _transientCallbacks.remove(id);
79
  _removedIds.add(id);
80 81
}

Adam Barth's avatar
Adam Barth committed
82
/// Ensure that a frame will be produced after this function is called.
83 84 85 86 87 88
void ensureVisualUpdate() {
  if (_haveScheduledVisualUpdate)
    return;
  sky.view.scheduleFrame();
  _haveScheduledVisualUpdate = true;
}