1// Copyright (c) 2012 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 "gpu/command_buffer/service/mailbox_manager.h"
6
7#include <algorithm>
8
9#include "crypto/random.h"
10#include "gpu/command_buffer/service/mailbox_synchronizer.h"
11#include "gpu/command_buffer/service/texture_manager.h"
12
13namespace gpu {
14namespace gles2 {
15
16MailboxManager::MailboxManager()
17    : mailbox_to_textures_(std::ptr_fun(&MailboxManager::TargetNameLess)),
18      sync_(MailboxSynchronizer::GetInstance()) {
19}
20
21MailboxManager::~MailboxManager() {
22  DCHECK(mailbox_to_textures_.empty());
23  DCHECK(textures_to_mailboxes_.empty());
24}
25
26Texture* MailboxManager::ConsumeTexture(unsigned target,
27                                        const Mailbox& mailbox) {
28  TargetName target_name(target, mailbox);
29  MailboxToTextureMap::iterator it =
30      mailbox_to_textures_.find(target_name);
31  if (it != mailbox_to_textures_.end())
32    return it->second->first;
33
34  if (sync_) {
35    // See if it's visible in another mailbox manager, and if so make it visible
36    // here too.
37    Texture* texture = sync_->CreateTextureFromMailbox(target, mailbox);
38    if (texture) {
39      InsertTexture(target_name, texture);
40      DCHECK_EQ(0U, texture->refs_.size());
41    }
42    return texture;
43  }
44
45  return NULL;
46}
47
48void MailboxManager::ProduceTexture(unsigned target,
49                                    const Mailbox& mailbox,
50                                    Texture* texture) {
51  TargetName target_name(target, mailbox);
52  MailboxToTextureMap::iterator it = mailbox_to_textures_.find(target_name);
53  if (it != mailbox_to_textures_.end()) {
54    if (it->second->first == texture)
55      return;
56    TextureToMailboxMap::iterator texture_it = it->second;
57    mailbox_to_textures_.erase(it);
58    textures_to_mailboxes_.erase(texture_it);
59  }
60  InsertTexture(target_name, texture);
61}
62
63void MailboxManager::InsertTexture(TargetName target_name, Texture* texture) {
64  texture->SetMailboxManager(this);
65  TextureToMailboxMap::iterator texture_it =
66      textures_to_mailboxes_.insert(std::make_pair(texture, target_name));
67  mailbox_to_textures_.insert(std::make_pair(target_name, texture_it));
68  DCHECK_EQ(mailbox_to_textures_.size(), textures_to_mailboxes_.size());
69}
70
71void MailboxManager::TextureDeleted(Texture* texture) {
72  std::pair<TextureToMailboxMap::iterator,
73            TextureToMailboxMap::iterator> range =
74      textures_to_mailboxes_.equal_range(texture);
75  for (TextureToMailboxMap::iterator it = range.first;
76       it != range.second; ++it) {
77    size_t count = mailbox_to_textures_.erase(it->second);
78    DCHECK(count == 1);
79  }
80  textures_to_mailboxes_.erase(range.first, range.second);
81  DCHECK_EQ(mailbox_to_textures_.size(), textures_to_mailboxes_.size());
82
83  if (sync_)
84    sync_->TextureDeleted(texture);
85}
86
87void MailboxManager::PushTextureUpdates(uint32 sync_point) {
88  if (sync_)
89    sync_->PushTextureUpdates(this, sync_point);
90}
91
92void MailboxManager::PullTextureUpdates(uint32 sync_point) {
93  if (sync_)
94    sync_->PullTextureUpdates(this, sync_point);
95}
96
97MailboxManager::TargetName::TargetName(unsigned target, const Mailbox& mailbox)
98    : target(target),
99      mailbox(mailbox) {
100}
101
102bool MailboxManager::TargetNameLess(const MailboxManager::TargetName& lhs,
103                                    const MailboxManager::TargetName& rhs) {
104  if (lhs.target != rhs.target)
105    return lhs.target < rhs.target;
106  return lhs.mailbox < rhs.mailbox;
107}
108
109}  // namespace gles2
110}  // namespace gpu
111