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