summaryrefslogtreecommitdiff
path: root/cc/surfaces/surface.cc
blob: 32e61c5ed778a1b49da97aaa18fb5bf955b9625b (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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// Copyright 2014 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.

#include "cc/surfaces/surface.h"

#include <algorithm>

#include "cc/output/compositor_frame.h"
#include "cc/output/copy_output_request.h"
#include "cc/surfaces/surface_factory.h"
#include "cc/surfaces/surface_manager.h"

namespace cc {

// The frame index starts at 2 so that empty frames will be treated as
// completely damaged the first time they're drawn from.
static const int kFrameIndexStart = 2;

Surface::Surface(SurfaceId id, const gfx::Size& size, SurfaceFactory* factory)
    : surface_id_(id),
      size_(size),
      factory_(factory->AsWeakPtr()),
      frame_index_(kFrameIndexStart) {
}

Surface::~Surface() {
  ClearCopyRequests();
  if (current_frame_ && factory_) {
    ReturnedResourceArray current_resources;
    TransferableResource::ReturnResources(
        current_frame_->delegated_frame_data->resource_list,
        &current_resources);
    factory_->UnrefResources(current_resources);
  }
}

void Surface::QueueFrame(scoped_ptr<CompositorFrame> frame,
                         const base::Closure& callback) {
  DCHECK(factory_);
  ClearCopyRequests();
  TakeLatencyInfo(&frame->metadata.latency_info);
  scoped_ptr<CompositorFrame> previous_frame = current_frame_.Pass();
  current_frame_ = frame.Pass();
  factory_->ReceiveFromChild(
      current_frame_->delegated_frame_data->resource_list);
  ++frame_index_;

  if (previous_frame) {
    ReturnedResourceArray previous_resources;
    TransferableResource::ReturnResources(
        previous_frame->delegated_frame_data->resource_list,
        &previous_resources);
    factory_->UnrefResources(previous_resources);
  }
  if (!draw_callback_.is_null())
    draw_callback_.Run();
  draw_callback_ = callback;
  factory_->manager()->DidSatisfySequences(
      surface_id_, &current_frame_->metadata.satisfies_sequences);
}

void Surface::RequestCopyOfOutput(scoped_ptr<CopyOutputRequest> copy_request) {
  if (current_frame_ &&
      !current_frame_->delegated_frame_data->render_pass_list.empty())
    current_frame_->delegated_frame_data->render_pass_list.back()
        ->copy_requests.push_back(copy_request.Pass());
  else
    copy_request->SendEmptyResult();
}

void Surface::TakeCopyOutputRequests(
    std::multimap<RenderPassId, CopyOutputRequest*>* copy_requests) {
  DCHECK(copy_requests->empty());
  if (current_frame_) {
    for (const auto& render_pass :
         current_frame_->delegated_frame_data->render_pass_list) {
      while (!render_pass->copy_requests.empty()) {
        scoped_ptr<CopyOutputRequest> request =
            render_pass->copy_requests.take_back();
        render_pass->copy_requests.pop_back();
        copy_requests->insert(
            std::make_pair(render_pass->id, request.release()));
      }
    }
  }
}

const CompositorFrame* Surface::GetEligibleFrame() {
  return current_frame_.get();
}

void Surface::TakeLatencyInfo(std::vector<ui::LatencyInfo>* latency_info) {
  if (!current_frame_)
    return;
  if (latency_info->empty()) {
    current_frame_->metadata.latency_info.swap(*latency_info);
    return;
  }
  std::copy(current_frame_->metadata.latency_info.begin(),
            current_frame_->metadata.latency_info.end(),
            std::back_inserter(*latency_info));
  current_frame_->metadata.latency_info.clear();
}

void Surface::RunDrawCallbacks() {
  if (!draw_callback_.is_null()) {
    base::Closure callback = draw_callback_;
    draw_callback_ = base::Closure();
    callback.Run();
  }
}

void Surface::ClearCopyRequests() {
  if (current_frame_) {
    for (const auto& render_pass :
         current_frame_->delegated_frame_data->render_pass_list) {
      for (const auto& copy_request : render_pass->copy_requests)
        copy_request->SendEmptyResult();
    }
  }
}

}  // namespace cc