1// Copyright 2013 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
5#include "content/browser/renderer_host/software_frame_manager.h"
6
7#include "base/bind.h"
8#include "base/callback_helpers.h"
9#include "base/debug/alias.h"
10#include "base/numerics/safe_math.h"
11#include "cc/resources/shared_bitmap.h"
12#include "content/browser/renderer_host/dip_util.h"
13#include "content/common/host_shared_bitmap_manager.h"
14#include "content/public/browser/user_metrics.h"
15
16namespace {
17
18void ReleaseMailbox(scoped_refptr<content::SoftwareFrame> frame,
19                    uint32 sync_point,
20                    bool lost_resource) {}
21
22}  // namespace
23
24namespace content {
25
26////////////////////////////////////////////////////////////////////////////////
27// SoftwareFrame
28
29class CONTENT_EXPORT SoftwareFrame : public base::RefCounted<SoftwareFrame> {
30 private:
31  friend class base::RefCounted<SoftwareFrame>;
32  friend class SoftwareFrameManager;
33
34  SoftwareFrame(base::WeakPtr<SoftwareFrameManagerClient> frame_manager_client,
35                uint32 output_surface_id,
36                unsigned frame_id,
37                float frame_device_scale_factor,
38                gfx::Size frame_size_pixels,
39                scoped_ptr<cc::SharedBitmap> shared_bitmap);
40  ~SoftwareFrame();
41
42  base::WeakPtr<SoftwareFrameManagerClient> frame_manager_client_;
43  const uint32 output_surface_id_;
44  const unsigned frame_id_;
45  float frame_device_scale_factor_;
46  const gfx::Size frame_size_pixels_;
47  scoped_ptr<cc::SharedBitmap> shared_bitmap_;
48
49  DISALLOW_COPY_AND_ASSIGN(SoftwareFrame);
50};
51
52SoftwareFrame::SoftwareFrame(
53    base::WeakPtr<SoftwareFrameManagerClient> frame_manager_client,
54    uint32 output_surface_id,
55    unsigned frame_id,
56    float frame_device_scale_factor,
57    gfx::Size frame_size_pixels,
58    scoped_ptr<cc::SharedBitmap> shared_bitmap)
59    : frame_manager_client_(frame_manager_client),
60      output_surface_id_(output_surface_id),
61      frame_id_(frame_id),
62      frame_device_scale_factor_(frame_device_scale_factor),
63      frame_size_pixels_(frame_size_pixels),
64      shared_bitmap_(shared_bitmap.Pass()) {}
65
66SoftwareFrame::~SoftwareFrame() {
67  if (frame_manager_client_) {
68    frame_manager_client_->SoftwareFrameWasFreed(
69        output_surface_id_, frame_id_);
70  }
71}
72
73////////////////////////////////////////////////////////////////////////////////
74// SoftwareFrameManager
75
76SoftwareFrameManager::SoftwareFrameManager(
77    base::WeakPtr<SoftwareFrameManagerClient> client)
78      : client_(client) {}
79
80SoftwareFrameManager::~SoftwareFrameManager() {
81  DiscardCurrentFrame();
82}
83
84bool SoftwareFrameManager::SwapToNewFrame(
85    uint32 output_surface_id,
86    const cc::SoftwareFrameData* frame_data,
87    float frame_device_scale_factor,
88    base::ProcessHandle process_handle) {
89  scoped_ptr<cc::SharedBitmap> shared_bitmap =
90      HostSharedBitmapManager::current()->GetSharedBitmapFromId(
91          frame_data->size, frame_data->bitmap_id);
92
93  if (!shared_bitmap) {
94    RecordAction(
95        base::UserMetricsAction("BadMessageTerminate_SharedMemoryManager1"));
96    return false;
97  }
98
99  scoped_refptr<SoftwareFrame> next_frame(
100      new SoftwareFrame(client_,
101                        output_surface_id,
102                        frame_data->id,
103                        frame_device_scale_factor,
104                        frame_data->size,
105                        shared_bitmap.Pass()));
106  current_frame_.swap(next_frame);
107  return true;
108}
109
110bool SoftwareFrameManager::HasCurrentFrame() const {
111  return current_frame_.get() ? true : false;
112}
113
114void SoftwareFrameManager::DiscardCurrentFrame() {
115  if (!HasCurrentFrame())
116    return;
117  current_frame_ = NULL;
118  RendererFrameManager::GetInstance()->RemoveFrame(this);
119}
120
121void SoftwareFrameManager::SwapToNewFrameComplete(bool visible) {
122  DCHECK(HasCurrentFrame());
123  RendererFrameManager::GetInstance()->AddFrame(this, visible);
124}
125
126void SoftwareFrameManager::SetVisibility(bool visible) {
127  if (HasCurrentFrame()) {
128    if (visible) {
129      RendererFrameManager::GetInstance()->LockFrame(this);
130    } else {
131      RendererFrameManager::GetInstance()->UnlockFrame(this);
132    }
133  }
134}
135
136uint32 SoftwareFrameManager::GetCurrentFrameOutputSurfaceId() const {
137  DCHECK(HasCurrentFrame());
138  return current_frame_->output_surface_id_;
139}
140
141void SoftwareFrameManager::GetCurrentFrameMailbox(
142    cc::TextureMailbox* mailbox,
143    scoped_ptr<cc::SingleReleaseCallback>* callback) {
144  DCHECK(HasCurrentFrame());
145  *mailbox = cc::TextureMailbox(current_frame_->shared_bitmap_->memory(),
146                                current_frame_->frame_size_pixels_);
147  *callback = cc::SingleReleaseCallback::Create(
148      base::Bind(ReleaseMailbox, current_frame_));
149}
150
151void* SoftwareFrameManager::GetCurrentFramePixels() const {
152  DCHECK(HasCurrentFrame());
153  DCHECK(current_frame_->shared_bitmap_);
154  return current_frame_->shared_bitmap_->pixels();
155}
156
157float SoftwareFrameManager::GetCurrentFrameDeviceScaleFactor() const {
158  DCHECK(HasCurrentFrame());
159  return current_frame_->frame_device_scale_factor_;
160}
161
162gfx::Size SoftwareFrameManager::GetCurrentFrameSizeInPixels() const {
163  DCHECK(HasCurrentFrame());
164  return current_frame_->frame_size_pixels_;
165}
166
167gfx::Size SoftwareFrameManager::GetCurrentFrameSizeInDIP() const {
168  DCHECK(HasCurrentFrame());
169  return ConvertSizeToDIP(current_frame_->frame_device_scale_factor_,
170                          current_frame_->frame_size_pixels_);
171}
172
173void SoftwareFrameManager::EvictCurrentFrame() {
174  DCHECK(HasCurrentFrame());
175  DiscardCurrentFrame();
176  if (client_)
177    client_->ReleaseReferencesToSoftwareFrame();
178}
179
180}  // namespace content
181