1# Copyright 2018 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import os
6
7from page_sets.rendering import rendering_shared_state as shared_state
8from page_sets.rendering import rendering_story
9from page_sets.rendering import story_tags
10from page_sets.system_health import platforms
11
12from telemetry import story
13
14from py_utils import discover
15
16
17class RenderingStorySet(story.StorySet):
18  """Stories related to rendering."""
19  def __init__(self, platform, scroll_forever=False):
20    super(RenderingStorySet, self).__init__(
21        archive_data_file=('../data/rendering_%s.json' % platform),
22        cloud_storage_bucket=story.PARTNER_BUCKET)
23
24    assert platform in platforms.ALL_PLATFORMS
25    self._platform = platform
26
27    if platform == platforms.MOBILE:
28      shared_page_state_class = shared_state.MobileRenderingSharedState
29    elif platform == platforms.DESKTOP:
30      shared_page_state_class = shared_state.DesktopRenderingSharedState
31    else:
32      shared_page_state_class = shared_state.RenderingSharedState
33
34    self.scroll_forever = scroll_forever
35
36    # For pinch zoom page sets, set default to desktop scale factor
37    self.target_scale_factor = 4.0
38
39    for story_class in _IterAllRenderingStoryClasses():
40      if (story_class.ABSTRACT_STORY or
41          platform not in story_class.SUPPORTED_PLATFORMS):
42        continue
43
44      required_args = []
45      name_suffix = ''
46      if (story_class.TAGS and
47          story_tags.USE_FAKE_CAMERA_DEVICE in story_class.TAGS):
48        required_args += [
49            # Use a fake camera showing a placeholder video.
50            '--use-fake-device-for-media-stream',
51            # Don't prompt for camera access. (Conveniently,
52            # this takes precedent over --deny-permission-prompts.)
53            '--use-fake-ui-for-media-stream',
54        ]
55
56      if story_class.TAGS and story_tags.BACKDROP_FILTER in story_class.TAGS:
57        # Experimental web platform features must be enabled in order for the
58        # 'backdrop-filter' CSS property to work.
59        required_args.append('--enable-experimental-web-platform-features')
60
61      # TODO(crbug.com/968125): We must run without out-of-process rasterization
62      # until that branch is implemented for YUV decoding.
63      if (story_class.TAGS and
64          story_tags.IMAGE_DECODING in story_class.TAGS and
65          story_tags.GPU_RASTERIZATION in story_class.TAGS):
66        required_args += ['--enable-gpu-rasterization']
67        # Run RGB decoding with GPU rasterization (to be most comparable to YUV)
68        self.AddStory(story_class(
69            page_set=self,
70            extra_browser_args=required_args +
71                ['--disable-yuv-image-decoding'],
72            shared_page_state_class=shared_page_state_class,
73            name_suffix='_rgb_and_gpu_rasterization'))
74        # Also run YUV decoding story with GPU rasterization.
75        name_suffix = '_yuv_and_gpu_rasterization'
76
77      self.AddStory(story_class(
78          page_set=self,
79          extra_browser_args=required_args,
80          shared_page_state_class=shared_page_state_class,
81          name_suffix=name_suffix))
82
83  def GetAbridgedStorySetTagFilter(self):
84    if self._platform == platforms.DESKTOP:
85      if os.name == 'nt':
86        return 'representative_win_desktop'
87      else:
88        # There is no specific tag for linux, cros, etc,
89        # so just use mac's.
90        return 'representative_mac_desktop'
91    elif self._platform == platforms.MOBILE:
92      return 'representative_mobile'
93    raise RuntimeError('Platform {} is not in the list of expected platforms.')
94
95
96class DesktopRenderingStorySet(RenderingStorySet):
97  """Desktop stories related to rendering.
98
99  Note: This story set is only intended to be used for recording stories via
100  tools/perf/record_wpr. If you would like to use it in a benchmark, please use
101  the generic RenderingStorySet class instead (you'll need to override the
102  CreateStorySet method of your benchmark).
103  """
104  def __init__(self):
105    super(DesktopRenderingStorySet, self).__init__(platform='desktop')
106
107
108def _IterAllRenderingStoryClasses():
109  start_dir = os.path.dirname(os.path.abspath(__file__))
110  # Sort the classes by their names so that their order is stable and
111  # deterministic.
112  for _, cls in sorted(discover.DiscoverClasses(
113      start_dir=start_dir,
114      top_level_dir=os.path.dirname(start_dir),
115      base_class=rendering_story.RenderingStory).iteritems()):
116    yield cls
117