Home | History | Annotate | Download | only in layers
      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/resources/platform_color.h"
     12 #include "cc/resources/scoped_resource.h"
     13 #include "cc/trees/layer_tree_impl.h"
     14 
     15 namespace cc {
     16 
     17 TextureLayerImpl::TextureLayerImpl(LayerTreeImpl* tree_impl,
     18                                    int id,
     19                                    bool uses_mailbox)
     20     : LayerImpl(tree_impl, id),
     21       texture_id_(0),
     22       external_texture_resource_(0),
     23       premultiplied_alpha_(true),
     24       blend_background_color_(false),
     25       flipped_(true),
     26       uv_top_left_(0.f, 0.f),
     27       uv_bottom_right_(1.f, 1.f),
     28       uses_mailbox_(uses_mailbox),
     29       own_mailbox_(false),
     30       valid_texture_copy_(false) {
     31   vertex_opacity_[0] = 1.0f;
     32   vertex_opacity_[1] = 1.0f;
     33   vertex_opacity_[2] = 1.0f;
     34   vertex_opacity_[3] = 1.0f;
     35 }
     36 
     37 TextureLayerImpl::~TextureLayerImpl() { FreeTextureMailbox(); }
     38 
     39 void TextureLayerImpl::SetTextureMailbox(const TextureMailbox& mailbox) {
     40   DCHECK(uses_mailbox_);
     41   FreeTextureMailbox();
     42   texture_mailbox_ = mailbox;
     43   own_mailbox_ = true;
     44   valid_texture_copy_ = false;
     45 }
     46 
     47 scoped_ptr<LayerImpl> TextureLayerImpl::CreateLayerImpl(
     48     LayerTreeImpl* tree_impl) {
     49   return TextureLayerImpl::Create(tree_impl, id(), uses_mailbox_).
     50       PassAs<LayerImpl>();
     51 }
     52 
     53 void TextureLayerImpl::PushPropertiesTo(LayerImpl* layer) {
     54   LayerImpl::PushPropertiesTo(layer);
     55 
     56   TextureLayerImpl* texture_layer = static_cast<TextureLayerImpl*>(layer);
     57   texture_layer->set_flipped(flipped_);
     58   texture_layer->set_uv_top_left(uv_top_left_);
     59   texture_layer->set_uv_bottom_right(uv_bottom_right_);
     60   texture_layer->set_vertex_opacity(vertex_opacity_);
     61   texture_layer->set_premultiplied_alpha(premultiplied_alpha_);
     62   if (uses_mailbox_ && own_mailbox_) {
     63     texture_layer->SetTextureMailbox(texture_mailbox_);
     64     own_mailbox_ = false;
     65   } else {
     66     texture_layer->set_texture_id(texture_id_);
     67   }
     68 }
     69 
     70 bool TextureLayerImpl::WillDraw(DrawMode draw_mode,
     71                                 ResourceProvider* resource_provider) {
     72   if (draw_mode == DRAW_MODE_RESOURCELESS_SOFTWARE)
     73     return false;
     74 
     75   if (uses_mailbox_) {
     76     if (own_mailbox_) {
     77       DCHECK(!external_texture_resource_);
     78       if ((draw_mode == DRAW_MODE_HARDWARE && texture_mailbox_.IsTexture()) ||
     79           (draw_mode == DRAW_MODE_SOFTWARE &&
     80            texture_mailbox_.IsSharedMemory())) {
     81         external_texture_resource_ =
     82             resource_provider->CreateResourceFromTextureMailbox(
     83                 texture_mailbox_);
     84         DCHECK(external_texture_resource_);
     85         texture_copy_.reset();
     86         valid_texture_copy_ = false;
     87       }
     88       if (external_texture_resource_)
     89         own_mailbox_ = false;
     90     }
     91 
     92     if (!valid_texture_copy_ && draw_mode == DRAW_MODE_HARDWARE &&
     93         texture_mailbox_.IsSharedMemory()) {
     94       DCHECK(!external_texture_resource_);
     95       // Have to upload a copy to a texture for it to be used in a
     96       // hardware draw.
     97       if (!texture_copy_)
     98         texture_copy_ = ScopedResource::create(resource_provider);
     99       if (texture_copy_->size() != texture_mailbox_.shared_memory_size() ||
    100           resource_provider->InUseByConsumer(texture_copy_->id()))
    101         texture_copy_->Free();
    102 
    103       if (!texture_copy_->id()) {
    104         texture_copy_->Allocate(texture_mailbox_.shared_memory_size(),
    105                                 resource_provider->best_texture_format(),
    106                                 ResourceProvider::TextureUsageAny);
    107       }
    108 
    109       if (texture_copy_->id()) {
    110         std::vector<uint8> swizzled;
    111         uint8* pixels =
    112             static_cast<uint8*>(texture_mailbox_.shared_memory()->memory());
    113 
    114         if (!PlatformColor::SameComponentOrder(texture_copy_->format())) {
    115           // Swizzle colors. This is slow, but should be really uncommon.
    116           swizzled.resize(texture_mailbox_.shared_memory_size_in_bytes());
    117           for (size_t i = 0; i < texture_mailbox_.shared_memory_size_in_bytes();
    118                i += 4) {
    119             swizzled[i] = pixels[i + 2];
    120             swizzled[i + 1] = pixels[i + 1];
    121             swizzled[i + 2] = pixels[i];
    122             swizzled[i + 3] = pixels[i + 3];
    123           }
    124           pixels = &swizzled[0];
    125         }
    126 
    127         resource_provider->SetPixels(
    128             texture_copy_->id(),
    129             pixels,
    130             gfx::Rect(texture_mailbox_.shared_memory_size()),
    131             gfx::Rect(texture_mailbox_.shared_memory_size()),
    132             gfx::Vector2d());
    133 
    134         valid_texture_copy_ = true;
    135       }
    136     }
    137   } else if (texture_id_) {
    138     DCHECK(!external_texture_resource_);
    139     if (draw_mode == DRAW_MODE_HARDWARE) {
    140       external_texture_resource_ =
    141           resource_provider->CreateResourceFromExternalTexture(
    142               GL_TEXTURE_2D,
    143               texture_id_);
    144     }
    145   }
    146   return (external_texture_resource_ || valid_texture_copy_) &&
    147          LayerImpl::WillDraw(draw_mode, resource_provider);
    148 }
    149 
    150 void TextureLayerImpl::AppendQuads(QuadSink* quad_sink,
    151                                    AppendQuadsData* append_quads_data) {
    152   DCHECK(external_texture_resource_ || valid_texture_copy_);
    153 
    154   SharedQuadState* shared_quad_state =
    155       quad_sink->UseSharedQuadState(CreateSharedQuadState());
    156   AppendDebugBorderQuad(quad_sink, shared_quad_state, append_quads_data);
    157 
    158   SkColor bg_color = blend_background_color_ ?
    159       background_color() : SK_ColorTRANSPARENT;
    160   bool opaque = contents_opaque() || (SkColorGetA(bg_color) == 0xFF);
    161 
    162   gfx::Rect quad_rect(content_bounds());
    163   gfx::Rect opaque_rect = opaque ? quad_rect : gfx::Rect();
    164   scoped_ptr<TextureDrawQuad> quad = TextureDrawQuad::Create();
    165   ResourceProvider::ResourceId id =
    166       valid_texture_copy_ ? texture_copy_->id() : external_texture_resource_;
    167   quad->SetNew(shared_quad_state,
    168                quad_rect,
    169                opaque_rect,
    170                id,
    171                premultiplied_alpha_,
    172                uv_top_left_,
    173                uv_bottom_right_,
    174                bg_color,
    175                vertex_opacity_,
    176                flipped_);
    177 
    178   // Perform explicit clipping on a quad to avoid setting a scissor later.
    179   if (shared_quad_state->is_clipped && quad->PerformClipping())
    180     shared_quad_state->is_clipped = false;
    181   if (!quad->rect.IsEmpty())
    182     quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data);
    183 }
    184 
    185 void TextureLayerImpl::DidDraw(ResourceProvider* resource_provider) {
    186   LayerImpl::DidDraw(resource_provider);
    187   if (uses_mailbox_ || !external_texture_resource_)
    188     return;
    189   // TODO(danakj): the following assert will not be true when sending resources
    190   // to a parent compositor. A synchronization scheme (double-buffering or
    191   // pipelining of updates) for the client will need to exist to solve this.
    192   DCHECK(!resource_provider->InUseByConsumer(external_texture_resource_));
    193   resource_provider->DeleteResource(external_texture_resource_);
    194   external_texture_resource_ = 0;
    195 }
    196 
    197 Region TextureLayerImpl::VisibleContentOpaqueRegion() const {
    198   if (contents_opaque())
    199     return visible_content_rect();
    200 
    201   if (blend_background_color_ && (SkColorGetA(background_color()) == 0xFF))
    202     return visible_content_rect();
    203 
    204   return Region();
    205 }
    206 
    207 void TextureLayerImpl::DidLoseOutputSurface() {
    208   if (external_texture_resource_ && !uses_mailbox_) {
    209     ResourceProvider* resource_provider =
    210         layer_tree_impl()->resource_provider();
    211     resource_provider->DeleteResource(external_texture_resource_);
    212   }
    213   texture_copy_.reset();
    214   texture_id_ = 0;
    215   external_texture_resource_ = 0;
    216   valid_texture_copy_ = false;
    217 }
    218 
    219 const char* TextureLayerImpl::LayerTypeAsString() const {
    220   return "cc::TextureLayerImpl";
    221 }
    222 
    223 bool TextureLayerImpl::CanClipSelf() const {
    224   return true;
    225 }
    226 
    227 void TextureLayerImpl::FreeTextureMailbox() {
    228   if (!uses_mailbox_)
    229     return;
    230   if (own_mailbox_) {
    231     DCHECK(!external_texture_resource_);
    232     texture_mailbox_.RunReleaseCallback(texture_mailbox_.sync_point(), false);
    233   } else if (external_texture_resource_) {
    234     DCHECK(!own_mailbox_);
    235     ResourceProvider* resource_provider =
    236         layer_tree_impl()->resource_provider();
    237     resource_provider->DeleteResource(external_texture_resource_);
    238     external_texture_resource_ = 0;
    239   }
    240 }
    241 
    242 }  // namespace cc
    243