Bug 70714 - [chromium] Encapsulate state machine parts of scheduling in CCSchedulerStateMachine
Summary: [chromium] Encapsulate state machine parts of scheduling in CCSchedulerStateM...
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: New Bugs (show other bugs)
Version: 528+ (Nightly build)
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Nat Duca
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-10-24 02:00 PDT by Nat Duca
Modified: 2011-10-27 12:33 PDT (History)
4 users (show)

See Also:


Attachments
Patch (22.75 KB, patch)
2011-10-24 02:00 PDT, Nat Duca
no flags Details | Formatted Diff | Diff
input enum -> real functions (24.08 KB, patch)
2011-10-25 21:54 PDT, Nat Duca
jamesr: review+
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Nat Duca 2011-10-24 02:00:05 PDT
[chromium] Encapsulate state machine parts of scheduling in CCSchedulerStateMachine
Comment 1 Nat Duca 2011-10-24 02:00:30 PDT
Created attachment 112163 [details]
Patch
Comment 2 Nat Duca 2011-10-24 02:39:48 PDT
This patch introduces the CCSchedulerStateMachine as a place to store the state machine that we typically keep inside render_widget. Goal #1 here was getting our scheduling algorithms in one place and well-covered by tests. Its integration with the rest of code will be a followup patch.

The first thing to notice in this code is how "actions" are taken by the scheduler. The obvious way to do this would be to have
  CCSchedulerClient {
     void draw();
  }
And in the code that calls draw, we'd write:
    if ( ... conditions leading to draw ...)
      m_client->draw();
       ... clear conditions that indicate drawing needed

The thing that has always caused me pain with such code is that it commingles "deciding what to do" with "advancing state." So, I switched to an "ACTION" model:
   Action getNextState() {
        if (... need to draw...)
           return draw;
   }
   void updateState(Action) {
       if (draw)
          clear conditions that lead to draw;
   }
This may have been a mistake. I'm open to feedback.

One key challenge was whether "we are on a vsync line" was state or not. Since the scheduler cannot directly affect vsync, I opted for it being ephemeral state: when one asks for a next state, you pass in whether you're on the vsync. The idea is that b70713's FrameRateController will be the source of that information.

Putting this all together, the rough way one uses the CCSchedulerStateMachine is:
  m_ssm.updateState(... something that we did outside the scheduler ...)
  reschedule();
I.e. anytime you tweak the scheduler state, reschedule.
Where:
  void reschedule() {
      while(true) {
          Action action = m_ssm->getNextAction();
          if (action == ACTION_NONE) break;
          handleAction(action);
      }
  }
  void handleAction(Action action) {
     if(action == DRAW) { drawLayersAndSwap(); }
     if(action == BEGIN_FRAME) { beginFrame(); }
     ...
     m_ssm->updateState(action);
  }


The last few tests in CCSchedulerStateMachineTest.cpp show how a frame runs through the machine. As a result, they might be a good place to start when looking through the code.

Have at it! :)
Comment 3 James Robinson 2011-10-24 13:27:10 PDT
Comment on attachment 112163 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=112163&action=review

> Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.cpp:33
> +    if (m_commitState == COMMIT_STATE_IDLE) {

would this be clearer as a switch statement? one advantage of switching on an enum value is that the compiler will yell if we're missing a case: instead of relying on a runtime ASSERT_NOT_REACHED()

> Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.cpp:46
> +        if (insideVSyncTick && m_needsRedraw)

nit: the other conditionals are (m_dlkfj && insideVSyncTick), why's this one the other way around?

> Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.cpp:61
> +    if (action == ACTION_NONE)

switch maybe?

> Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.cpp:71
> +        // Prevent another UPDATE_MORE_RESOURCES call until we draw again.

I can't really tell what an "UPDATE_MORE_RESOURCES call" is in this context

> Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.cpp:93
> +    if (input == INPUT_SET_NEEDS_REDRAW) {

switch?

> Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.h:31
> +/**
> + * The CCSchedulerStateMachine decides how to coordinates main thread activites

why is this a c-style comment? we normally only use that for license header blocks

> Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.h:39
> + * The scheduler seprates "what to do next" from the updating of its internal state to

seprates -> separates

> Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.h:78
> +    Action getNextAction(bool insideVSyncTick) const;

we would normally name this 'nextAction()' - or if you want to emphasize that this isn't just a simple getter maybe calculateNextAction()?

> Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.h:79
> +    void updateState(Action);

can you add some comments here (or possibly at the class-level comment) about how a caller is supposed to use these two functions?

> Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.h:82
> +        INPUT_SET_NEEDS_REDRAW = 1,

the other enums start at 0, why does this one start at 1?

do you need to provide explicit numerical values for these or could you just let the compiler do that?

> Source/WebKit/chromium/tests/CCSchedulerStateMachineTest.cpp:45
> +/* Exposes the protected state fields of the CCSchedulerStateMachine for testing */

use a // style comment for 1-liners
Comment 4 James Robinson 2011-10-25 17:46:49 PDT
Comment on attachment 112163 [details]
Patch

R- for pile of nits to remove this from pending-review queue, although this seems great overall.
Comment 5 Nat Duca 2011-10-25 21:38:29 PDT
(In reply to comment #4)
>  do you need to provide explicit numerical values for these or could you just let the compiler do that?

When gtests fail, they give a number. It helped my head debug those failures rather than having to count enums to recreate what the compiler did in my head. Its style I guess, I can yank it?
Comment 6 Nat Duca 2011-10-25 21:54:09 PDT
Created attachment 112448 [details]
input enum -> real functions
Comment 7 James Robinson 2011-10-25 22:54:28 PDT
I don't think there's anything horribly wrong with giving enums explicit values, but it isn't what we normally do unless the values are going to be used in a bitfield or the numeric values are part of the public API.  Seeing numeric values in the header makes me think that one of those two things is going to happen.

When debugging I can't remember finding explicit numeric values in the source very useful, since GDB can print out the numeric values and it's not too hard to count when looking at logs or other non-interactive debugging modes.
Comment 8 James Robinson 2011-10-25 23:01:51 PDT
Comment on attachment 112448 [details]
input enum -> real functions

View in context: https://bugs.webkit.org/attachment.cgi?id=112448&action=review

R=me, remaining nits are up to you

> Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.h:43
> +            : m_commitState(COMMIT_STATE_IDLE)

odd indentation - the : should be 4 spaces in from the previous line. Could you move the c'tor to the .cpp? there's a whole lotta lines to read here before we get to the API bits that a user of this class would be interested in

> Source/WebKit/chromium/tests/CCSchedulerStateMachineTest.cpp:180
> +TEST(CCSchedulerStateMachineTest, TestSetNeedsCommitIsntLost)

IsntLost->IsNotLost ? looks like a typo without the apostrophe (although you obviously can't put that in the function name)
Comment 9 Nat Duca 2011-10-26 02:47:23 PDT
Agreed with all remaining nits. Will land tomorrow morning.
Comment 10 Nat Duca 2011-10-27 11:29:53 PDT
Committed r98612: <http://trac.webkit.org/changeset/98612>
Comment 11 Nat Duca 2011-10-27 11:45:41 PDT
Reverted r98612 for reason:

Broke build

Committed r98613: <http://trac.webkit.org/changeset/98613>
Comment 12 Nat Duca 2011-10-27 12:33:54 PDT
Committed r98618: <http://trac.webkit.org/changeset/98618>