texture_layer_impl.cc revision 7dbb3d5cf0c15f500944d211057644d6a2f37371
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/strings/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      blend_background_color_(false),
23      flipped_(true),
24      uv_top_left_(0.f, 0.f),
25      uv_bottom_right_(1.f, 1.f),
26      uses_mailbox_(uses_mailbox),
27      own_mailbox_(false) {
28  vertex_opacity_[0] = 1.0f;
29  vertex_opacity_[1] = 1.0f;
30  vertex_opacity_[2] = 1.0f;
31  vertex_opacity_[3] = 1.0f;
32}
33
34TextureLayerImpl::~TextureLayerImpl() { FreeTextureMailbox(); }
35
36void TextureLayerImpl::SetTextureMailbox(const TextureMailbox& mailbox) {
37  DCHECK(uses_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
66bool TextureLayerImpl::WillDraw(DrawMode draw_mode,
67                                ResourceProvider* resource_provider) {
68  if (draw_mode == DRAW_MODE_RESOURCELESS_SOFTWARE)
69    return false;
70
71  if (uses_mailbox_) {
72    if (own_mailbox_) {
73      DCHECK(!external_texture_resource_);
74      if ((draw_mode == DRAW_MODE_HARDWARE && texture_mailbox_.IsTexture()) ||
75          (draw_mode == DRAW_MODE_SOFTWARE &&
76           texture_mailbox_.IsSharedMemory())) {
77        // TODO(piman): for shm mailboxes in HW mode, we could upload into a
78        // resource here.
79        external_texture_resource_ =
80            resource_provider->CreateResourceFromTextureMailbox(
81                texture_mailbox_);
82        DCHECK(external_texture_resource_);
83      }
84      if (external_texture_resource_)
85        own_mailbox_ = false;
86    }
87  } else if (texture_id_) {
88    DCHECK(!external_texture_resource_);
89    if (draw_mode == DRAW_MODE_HARDWARE) {
90      external_texture_resource_ =
91          resource_provider->CreateResourceFromExternalTexture(
92              GL_TEXTURE_2D,
93              texture_id_);
94    }
95  }
96  return external_texture_resource_ &&
97         LayerImpl::WillDraw(draw_mode, resource_provider);
98}
99
100void TextureLayerImpl::AppendQuads(QuadSink* quad_sink,
101                                   AppendQuadsData* append_quads_data) {
102  DCHECK(external_texture_resource_);
103
104  SharedQuadState* shared_quad_state =
105      quad_sink->UseSharedQuadState(CreateSharedQuadState());
106  AppendDebugBorderQuad(quad_sink, shared_quad_state, append_quads_data);
107
108  SkColor bg_color = blend_background_color_ ?
109      background_color() : SK_ColorTRANSPARENT;
110  bool opaque = contents_opaque() || (SkColorGetA(bg_color) == 0xFF);
111
112  gfx::Rect quad_rect(content_bounds());
113  gfx::Rect opaque_rect = opaque ? quad_rect : gfx::Rect();
114  scoped_ptr<TextureDrawQuad> quad = TextureDrawQuad::Create();
115  quad->SetNew(shared_quad_state,
116               quad_rect,
117               opaque_rect,
118               external_texture_resource_,
119               premultiplied_alpha_,
120               uv_top_left_,
121               uv_bottom_right_,
122               bg_color,
123               vertex_opacity_,
124               flipped_);
125
126  // Perform explicit clipping on a quad to avoid setting a scissor later.
127  if (shared_quad_state->is_clipped && quad->PerformClipping())
128    shared_quad_state->is_clipped = false;
129  if (!quad->rect.IsEmpty())
130    quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data);
131}
132
133void TextureLayerImpl::DidDraw(ResourceProvider* resource_provider) {
134  LayerImpl::DidDraw(resource_provider);
135  if (uses_mailbox_ || !external_texture_resource_)
136    return;
137  // TODO(danakj): the following assert will not be true when sending resources
138  // to a parent compositor. A synchronization scheme (double-buffering or
139  // pipelining of updates) for the client will need to exist to solve this.
140  DCHECK(!resource_provider->InUseByConsumer(external_texture_resource_));
141  resource_provider->DeleteResource(external_texture_resource_);
142  external_texture_resource_ = 0;
143}
144
145void TextureLayerImpl::DidLoseOutputSurface() {
146  if (external_texture_resource_ && !uses_mailbox_) {
147    ResourceProvider* resource_provider =
148        layer_tree_impl()->resource_provider();
149    resource_provider->DeleteResource(external_texture_resource_);
150  }
151  texture_id_ = 0;
152  external_texture_resource_ = 0;
153}
154
155const char* TextureLayerImpl::LayerTypeAsString() const {
156  return "cc::TextureLayerImpl";
157}
158
159bool TextureLayerImpl::CanClipSelf() const {
160  return true;
161}
162
163void TextureLayerImpl::FreeTextureMailbox() {
164  if (!uses_mailbox_)
165    return;
166  if (own_mailbox_) {
167    DCHECK(!external_texture_resource_);
168    texture_mailbox_.RunReleaseCallback(texture_mailbox_.sync_point(), false);
169  } else if (external_texture_resource_) {
170    DCHECK(!own_mailbox_);
171    ResourceProvider* resource_provider =
172        layer_tree_impl()->resource_provider();
173    resource_provider->DeleteResource(external_texture_resource_);
174    external_texture_resource_ = 0;
175  }
176}
177
178}  // namespace cc
179