summaryrefslogtreecommitdiff
path: root/chromium/media/gpu/android/maybe_render_early_manager.h
blob: 002ea5ce8a2e39b2958b04d07652a00364312d54 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
// Copyright 2019 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.

#ifndef MEDIA_GPU_ANDROID_MAYBE_RENDER_EARLY_MANAGER_H_
#define MEDIA_GPU_ANDROID_MAYBE_RENDER_EARLY_MANAGER_H_

#include <memory>
#include <vector>

#include "base/memory/scoped_refptr.h"
#include "base/sequenced_task_runner.h"
#include "media/gpu/android/codec_image.h"  // For CodecImage::BlockingMode
#include "media/gpu/media_gpu_export.h"
#include "third_party/abseil-cpp/absl/types/optional.h"

namespace media {
class CodecImageHolder;
class CodecSurfaceBundle;

// Manager for rendering images speculatively.  Tries to advance images to the
// back buffer, then to the front buffer, once those slots are unoccupied.
class MEDIA_GPU_EXPORT MaybeRenderEarlyManager {
 public:
  MaybeRenderEarlyManager() = default;

  MaybeRenderEarlyManager(const MaybeRenderEarlyManager&) = delete;
  MaybeRenderEarlyManager& operator=(const MaybeRenderEarlyManager&) = delete;

  virtual ~MaybeRenderEarlyManager() = default;

  // Sets the surface bundle that future images will use.
  virtual void SetSurfaceBundle(
      scoped_refptr<CodecSurfaceBundle> surface_bundle) = 0;

  // Adds |codec_image_holder| and tries to render early.
  //
  // Note that CodecImage should be some other abstraction that handles
  // front / backbuffer rendering.  However, for now, CodecImage does that.
  virtual void AddCodecImage(
      scoped_refptr<CodecImageHolder> codec_image_holder) = 0;

  // Try to render codec images early.  It's okay if no work can be done.
  virtual void MaybeRenderEarly() = 0;

  // Create a default instance that uses |gpu_task_runner| to render early.
  // Note that the returned object should be accessed from the thread that
  // created it.
  static std::unique_ptr<MaybeRenderEarlyManager> Create(
      scoped_refptr<base::SequencedTaskRunner> gpu_task_runner,
      scoped_refptr<gpu::RefCountedLock> drdc_lock);
};

namespace internal {

// Tries to render CodecImages to their backing surfaces when it's valid to do
// so. This lets us release codec buffers back to their codecs as soon as
// possible so that decoding can progress smoothly.
// Templated on the image type for testing.
template <typename Image>
void MEDIA_GPU_EXPORT MaybeRenderEarly(std::vector<Image*>* image_vector_ptr) {
  auto& images = *image_vector_ptr;
  if (images.empty())
    return;

  // Find the latest image rendered to the front buffer (if any).
  absl::optional<size_t> front_buffer_index;
  for (int i = images.size() - 1; i >= 0; --i) {
    if (images[i]->was_rendered_to_front_buffer()) {
      front_buffer_index = i;
      break;
    }
  }

  // If there's no image in the front buffer we can safely render one.
  if (!front_buffer_index.has_value()) {
    // Iterate until we successfully render one to skip over invalidated images.
    for (size_t i = 0; i < images.size(); ++i) {
      if (images[i]->RenderToFrontBuffer()) {
        front_buffer_index = i;
        break;
      }
    }
    // If we couldn't render anything there's nothing more to do.
    if (!front_buffer_index.has_value())
      return;
  }

  // Try to render the image following the front buffer to the back buffer.
  size_t back_buffer_index = *front_buffer_index + 1;
  if (back_buffer_index < images.size() &&
      images[back_buffer_index]->is_texture_owner_backed()) {
    // Try to render to the back buffer, but don't wait for any previous frame.
    // While this does make it more likely that we'll have to wait the next time
    // we draw, it does prevent us from waiting on frames we don't plan to draw.
    images[back_buffer_index]->RenderToTextureOwnerBackBuffer();
  }
}

}  // namespace internal

}  // namespace media

#endif  // MEDIA_GPU_ANDROID_MAYBE_RENDER_EARLY_MANAGER_H_