texture_layer_impl.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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(texture_id_);
72}
73
74void TextureLayerImpl::AppendQuads(QuadSink* quad_sink,
75                                   AppendQuadsData* append_quads_data) {
76  if (!external_texture_resource_)
77    return;
78
79  SharedQuadState* shared_quad_state =
80      quad_sink->UseSharedQuadState(CreateSharedQuadState());
81  AppendDebugBorderQuad(quad_sink, shared_quad_state, append_quads_data);
82
83  gfx::Rect quad_rect(content_bounds());
84  gfx::Rect opaque_rect(contents_opaque() ? quad_rect : gfx::Rect());
85  scoped_ptr<TextureDrawQuad> quad = TextureDrawQuad::Create();
86  quad->SetNew(shared_quad_state,
87               quad_rect,
88               opaque_rect,
89               external_texture_resource_,
90               premultiplied_alpha_,
91               uv_top_left_,
92               uv_bottom_right_,
93               vertex_opacity_,
94               flipped_);
95
96  // Perform explicit clipping on a quad to avoid setting a scissor later.
97  if (shared_quad_state->is_clipped && quad->PerformClipping())
98    shared_quad_state->is_clipped = false;
99  if (!quad->rect.IsEmpty())
100    quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data);
101}
102
103void TextureLayerImpl::DidDraw(ResourceProvider* resource_provider) {
104  if (uses_mailbox_ || !external_texture_resource_)
105    return;
106  // FIXME: the following assert will not be true when sending resources to a
107  // parent compositor. A synchronization scheme (double-buffering or
108  // pipelining of updates) for the client will need to exist to solve this.
109  DCHECK(!resource_provider->InUseByConsumer(external_texture_resource_));
110  resource_provider->DeleteResource(external_texture_resource_);
111  external_texture_resource_ = 0;
112}
113
114void TextureLayerImpl::DumpLayerProperties(std::string* str, int indent) const {
115  str->append(IndentString(indent));
116  base::StringAppendF(str,
117                      "texture layer texture id: %u premultiplied: %d\n",
118                      texture_id_,
119                      premultiplied_alpha_);
120  LayerImpl::DumpLayerProperties(str, indent);
121}
122
123void TextureLayerImpl::DidLoseOutputSurface() {
124  texture_id_ = 0;
125  external_texture_resource_ = 0;
126}
127
128const char* TextureLayerImpl::LayerTypeAsString() const {
129  return "TextureLayer";
130}
131
132bool TextureLayerImpl::CanClipSelf() const {
133  return true;
134}
135
136void TextureLayerImpl::DidBecomeActive() {
137  if (!own_mailbox_)
138    return;
139  DCHECK(!external_texture_resource_);
140  ResourceProvider* resource_provider = layer_tree_impl()->resource_provider();
141  if (!texture_mailbox_.IsEmpty()) {
142    external_texture_resource_ =
143        resource_provider->CreateResourceFromTextureMailbox(texture_mailbox_);
144  }
145  own_mailbox_ = false;
146}
147
148void TextureLayerImpl::FreeTextureMailbox() {
149  if (!uses_mailbox_)
150    return;
151  if (own_mailbox_) {
152    DCHECK(!external_texture_resource_);
153    texture_mailbox_.RunReleaseCallback(texture_mailbox_.sync_point());
154  } else if (external_texture_resource_) {
155    DCHECK(!own_mailbox_);
156    ResourceProvider* resource_provider =
157        layer_tree_impl()->resource_provider();
158    resource_provider->DeleteResource(external_texture_resource_);
159    external_texture_resource_ = 0;
160  }
161}
162
163}  // namespace cc
164