texture_layer_impl.cc revision a93a17c8d99d686bd4a1511e5504e5e6cc9fcadf
1// Copyright 2011 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 "cc/layers/texture_layer_impl.h"
6
7#include "base/stringprintf.h"
8#include "cc/layers/quad_sink.h"
9#include "cc/output/renderer.h"
10#include "cc/quads/texture_draw_quad.h"
11#include "cc/trees/layer_tree_impl.h"
12
13namespace cc {
14
15TextureLayerImpl::TextureLayerImpl(LayerTreeImpl* tree_impl,
16                                   int id,
17                                   bool uses_mailbox)
18    : LayerImpl(tree_impl, id),
19      texture_id_(0),
20      external_texture_resource_(0),
21      premultiplied_alpha_(true),
22      flipped_(true),
23      uv_top_left_(0.f, 0.f),
24      uv_bottom_right_(1.f, 1.f),
25      uses_mailbox_(uses_mailbox),
26      own_mailbox_(false) {
27  vertex_opacity_[0] = 1.0f;
28  vertex_opacity_[1] = 1.0f;
29  vertex_opacity_[2] = 1.0f;
30  vertex_opacity_[3] = 1.0f;
31}
32
33TextureLayerImpl::~TextureLayerImpl() { FreeTextureMailbox(); }
34
35void TextureLayerImpl::SetTextureMailbox(const TextureMailbox& mailbox) {
36  DCHECK(uses_mailbox_);
37  DCHECK(mailbox.IsEmpty() || !mailbox.Equals(texture_mailbox_));
38  FreeTextureMailbox();
39  texture_mailbox_ = mailbox;
40  own_mailbox_ = true;
41}
42
43scoped_ptr<LayerImpl> TextureLayerImpl::CreateLayerImpl(
44    LayerTreeImpl* tree_impl) {
45  return TextureLayerImpl::Create(tree_impl, id(), uses_mailbox_).
46      PassAs<LayerImpl>();
47}
48
49void TextureLayerImpl::PushPropertiesTo(LayerImpl* layer) {
50  LayerImpl::PushPropertiesTo(layer);
51
52  TextureLayerImpl* texture_layer = static_cast<TextureLayerImpl*>(layer);
53  texture_layer->set_flipped(flipped_);
54  texture_layer->set_uv_top_left(uv_top_left_);
55  texture_layer->set_uv_bottom_right(uv_bottom_right_);
56  texture_layer->set_vertex_opacity(vertex_opacity_);
57  texture_layer->set_premultiplied_alpha(premultiplied_alpha_);
58  if (uses_mailbox_ && own_mailbox_) {
59    texture_layer->SetTextureMailbox(texture_mailbox_);
60    own_mailbox_ = false;
61  } else {
62    texture_layer->set_texture_id(texture_id_);
63  }
64}
65
66void TextureLayerImpl::WillDraw(ResourceProvider* resource_provider) {
67  if (uses_mailbox_ || !texture_id_)
68    return;
69  DCHECK(!external_texture_resource_);
70  external_texture_resource_ =
71      resource_provider->CreateResourceFromExternalTexture(
72          GL_TEXTURE_2D,
73          texture_id_);
74}
75
76void TextureLayerImpl::AppendQuads(QuadSink* quad_sink,
77                                   AppendQuadsData* append_quads_data) {
78  if (!external_texture_resource_)
79    return;
80
81  SharedQuadState* shared_quad_state =
82      quad_sink->UseSharedQuadState(CreateSharedQuadState());
83  AppendDebugBorderQuad(quad_sink, shared_quad_state, append_quads_data);
84
85  gfx::Rect quad_rect(content_bounds());
86  gfx::Rect opaque_rect(contents_opaque() ? quad_rect : gfx::Rect());
87  scoped_ptr<TextureDrawQuad> quad = TextureDrawQuad::Create();
88  quad->SetNew(shared_quad_state,
89               quad_rect,
90               opaque_rect,
91               external_texture_resource_,
92               premultiplied_alpha_,
93               uv_top_left_,
94               uv_bottom_right_,
95               vertex_opacity_,
96               flipped_);
97
98  // Perform explicit clipping on a quad to avoid setting a scissor later.
99  if (shared_quad_state->is_clipped && quad->PerformClipping())
100    shared_quad_state->is_clipped = false;
101  if (!quad->rect.IsEmpty())
102    quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data);
103}
104
105void TextureLayerImpl::DidDraw(ResourceProvider* resource_provider) {
106  if (uses_mailbox_ || !external_texture_resource_)
107    return;
108  // FIXME: the following assert will not be true when sending resources to a
109  // parent compositor. A synchronization scheme (double-buffering or
110  // pipelining of updates) for the client will need to exist to solve this.
111  DCHECK(!resource_provider->InUseByConsumer(external_texture_resource_));
112  resource_provider->DeleteResource(external_texture_resource_);
113  external_texture_resource_ = 0;
114}
115
116void TextureLayerImpl::DumpLayerProperties(std::string* str, int indent) const {
117  str->append(IndentString(indent));
118  base::StringAppendF(str,
119                      "texture layer texture id: %u premultiplied: %d\n",
120                      texture_id_,
121                      premultiplied_alpha_);
122  LayerImpl::DumpLayerProperties(str, indent);
123}
124
125void TextureLayerImpl::DidLoseOutputSurface() {
126  texture_id_ = 0;
127  external_texture_resource_ = 0;
128}
129
130const char* TextureLayerImpl::LayerTypeAsString() const {
131  return "cc::TextureLayerImpl";
132}
133
134bool TextureLayerImpl::CanClipSelf() const {
135  return true;
136}
137
138void TextureLayerImpl::DidBecomeActive() {
139  if (!own_mailbox_)
140    return;
141  DCHECK(!external_texture_resource_);
142  ResourceProvider* resource_provider = layer_tree_impl()->resource_provider();
143  if (!texture_mailbox_.IsEmpty()) {
144    external_texture_resource_ =
145        resource_provider->CreateResourceFromTextureMailbox(texture_mailbox_);
146  }
147  own_mailbox_ = false;
148}
149
150void TextureLayerImpl::FreeTextureMailbox() {
151  if (!uses_mailbox_)
152    return;
153  if (own_mailbox_) {
154    DCHECK(!external_texture_resource_);
155    texture_mailbox_.RunReleaseCallback(texture_mailbox_.sync_point(), false);
156  } else if (external_texture_resource_) {
157    DCHECK(!own_mailbox_);
158    ResourceProvider* resource_provider =
159        layer_tree_impl()->resource_provider();
160    resource_provider->DeleteResource(external_texture_resource_);
161    external_texture_resource_ = 0;
162  }
163}
164
165}  // namespace cc
166