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.
5 #include "cc/layers/texture_layer_impl.h"
9 #include "base/strings/stringprintf.h"
10 #include "cc/layers/quad_sink.h"
11 #include "cc/output/renderer.h"
12 #include "cc/quads/texture_draw_quad.h"
13 #include "cc/resources/platform_color.h"
14 #include "cc/resources/scoped_resource.h"
15 #include "cc/resources/single_release_callback.h"
16 #include "cc/trees/layer_tree_impl.h"
20 TextureLayerImpl::TextureLayerImpl(LayerTreeImpl
* tree_impl
, int id
)
21 : LayerImpl(tree_impl
, id
),
22 external_texture_resource_(0),
23 premultiplied_alpha_(true),
24 blend_background_color_(false),
26 uv_top_left_(0.f
, 0.f
),
27 uv_bottom_right_(1.f
, 1.f
),
29 valid_texture_copy_(false) {
30 vertex_opacity_
[0] = 1.0f
;
31 vertex_opacity_
[1] = 1.0f
;
32 vertex_opacity_
[2] = 1.0f
;
33 vertex_opacity_
[3] = 1.0f
;
36 TextureLayerImpl::~TextureLayerImpl() { FreeTextureMailbox(); }
38 void TextureLayerImpl::SetTextureMailbox(
39 const TextureMailbox
& mailbox
,
40 scoped_ptr
<SingleReleaseCallback
> release_callback
) {
41 DCHECK_EQ(mailbox
.IsValid(), !!release_callback
);
43 texture_mailbox_
= mailbox
;
44 release_callback_
= release_callback
.Pass();
46 valid_texture_copy_
= false;
47 SetNeedsPushProperties();
50 scoped_ptr
<LayerImpl
> TextureLayerImpl::CreateLayerImpl(
51 LayerTreeImpl
* tree_impl
) {
52 return TextureLayerImpl::Create(tree_impl
, id()).PassAs
<LayerImpl
>();
55 void TextureLayerImpl::PushPropertiesTo(LayerImpl
* layer
) {
56 LayerImpl::PushPropertiesTo(layer
);
58 TextureLayerImpl
* texture_layer
= static_cast<TextureLayerImpl
*>(layer
);
59 texture_layer
->SetFlipped(flipped_
);
60 texture_layer
->SetUVTopLeft(uv_top_left_
);
61 texture_layer
->SetUVBottomRight(uv_bottom_right_
);
62 texture_layer
->SetVertexOpacity(vertex_opacity_
);
63 texture_layer
->SetPremultipliedAlpha(premultiplied_alpha_
);
64 texture_layer
->SetBlendBackgroundColor(blend_background_color_
);
66 texture_layer
->SetTextureMailbox(texture_mailbox_
,
67 release_callback_
.Pass());
72 bool TextureLayerImpl::WillDraw(DrawMode draw_mode
,
73 ResourceProvider
* resource_provider
) {
74 if (draw_mode
== DRAW_MODE_RESOURCELESS_SOFTWARE
)
78 DCHECK(!external_texture_resource_
);
79 if ((draw_mode
== DRAW_MODE_HARDWARE
&& texture_mailbox_
.IsTexture()) ||
80 (draw_mode
== DRAW_MODE_SOFTWARE
&&
81 texture_mailbox_
.IsSharedMemory())) {
82 external_texture_resource_
=
83 resource_provider
->CreateResourceFromTextureMailbox(
84 texture_mailbox_
, release_callback_
.Pass());
85 DCHECK(external_texture_resource_
);
86 texture_copy_
.reset();
87 valid_texture_copy_
= false;
89 if (external_texture_resource_
)
93 if (!valid_texture_copy_
&& draw_mode
== DRAW_MODE_HARDWARE
&&
94 texture_mailbox_
.IsSharedMemory()) {
95 DCHECK(!external_texture_resource_
);
96 // Have to upload a copy to a texture for it to be used in a
99 texture_copy_
= ScopedResource::Create(resource_provider
);
100 if (texture_copy_
->size() != texture_mailbox_
.shared_memory_size() ||
101 resource_provider
->InUseByConsumer(texture_copy_
->id()))
102 texture_copy_
->Free();
104 if (!texture_copy_
->id()) {
105 texture_copy_
->Allocate(texture_mailbox_
.shared_memory_size(),
106 ResourceProvider::TextureUsageAny
,
107 resource_provider
->best_texture_format());
110 if (texture_copy_
->id()) {
111 std::vector
<uint8
> swizzled
;
113 static_cast<uint8
*>(texture_mailbox_
.shared_memory()->memory());
115 if (!PlatformColor::SameComponentOrder(texture_copy_
->format())) {
116 // Swizzle colors. This is slow, but should be really uncommon.
117 size_t bytes
= texture_mailbox_
.SharedMemorySizeInBytes();
118 swizzled
.resize(bytes
);
119 for (size_t i
= 0; i
< bytes
; i
+= 4) {
120 swizzled
[i
] = pixels
[i
+ 2];
121 swizzled
[i
+ 1] = pixels
[i
+ 1];
122 swizzled
[i
+ 2] = pixels
[i
];
123 swizzled
[i
+ 3] = pixels
[i
+ 3];
125 pixels
= &swizzled
[0];
128 resource_provider
->SetPixels(
131 gfx::Rect(texture_mailbox_
.shared_memory_size()),
132 gfx::Rect(texture_mailbox_
.shared_memory_size()),
135 valid_texture_copy_
= true;
138 return (external_texture_resource_
|| valid_texture_copy_
) &&
139 LayerImpl::WillDraw(draw_mode
, resource_provider
);
142 void TextureLayerImpl::AppendQuads(QuadSink
* quad_sink
,
143 AppendQuadsData
* append_quads_data
) {
144 DCHECK(external_texture_resource_
|| valid_texture_copy_
);
146 SharedQuadState
* shared_quad_state
= quad_sink
->CreateSharedQuadState();
147 PopulateSharedQuadState(shared_quad_state
);
149 AppendDebugBorderQuad(quad_sink
, shared_quad_state
, append_quads_data
);
151 SkColor bg_color
= blend_background_color_
?
152 background_color() : SK_ColorTRANSPARENT
;
153 bool opaque
= contents_opaque() || (SkColorGetA(bg_color
) == 0xFF);
155 gfx::Rect
quad_rect(content_bounds());
156 gfx::Rect opaque_rect
= opaque
? quad_rect
: gfx::Rect();
157 gfx::Rect visible_quad_rect
= quad_sink
->UnoccludedContentRect(
158 quad_rect
, draw_properties().target_space_transform
);
159 if (visible_quad_rect
.IsEmpty())
162 scoped_ptr
<TextureDrawQuad
> quad
= TextureDrawQuad::Create();
163 ResourceProvider::ResourceId id
=
164 valid_texture_copy_
? texture_copy_
->id() : external_texture_resource_
;
165 quad
->SetNew(shared_quad_state
,
170 premultiplied_alpha_
,
176 quad_sink
->Append(quad
.PassAs
<DrawQuad
>());
179 Region
TextureLayerImpl::VisibleContentOpaqueRegion() const {
180 if (contents_opaque())
181 return visible_content_rect();
183 if (blend_background_color_
&& (SkColorGetA(background_color()) == 0xFF))
184 return visible_content_rect();
189 void TextureLayerImpl::ReleaseResources() {
190 FreeTextureMailbox();
191 texture_copy_
.reset();
192 external_texture_resource_
= 0;
193 valid_texture_copy_
= false;
196 void TextureLayerImpl::SetPremultipliedAlpha(bool premultiplied_alpha
) {
197 premultiplied_alpha_
= premultiplied_alpha
;
198 SetNeedsPushProperties();
201 void TextureLayerImpl::SetBlendBackgroundColor(bool blend
) {
202 blend_background_color_
= blend
;
203 SetNeedsPushProperties();
206 void TextureLayerImpl::SetFlipped(bool flipped
) {
208 SetNeedsPushProperties();
211 void TextureLayerImpl::SetUVTopLeft(const gfx::PointF top_left
) {
212 uv_top_left_
= top_left
;
213 SetNeedsPushProperties();
216 void TextureLayerImpl::SetUVBottomRight(const gfx::PointF bottom_right
) {
217 uv_bottom_right_
= bottom_right
;
218 SetNeedsPushProperties();
224 void TextureLayerImpl::SetVertexOpacity(const float vertex_opacity
[4]) {
225 vertex_opacity_
[0] = vertex_opacity
[0];
226 vertex_opacity_
[1] = vertex_opacity
[1];
227 vertex_opacity_
[2] = vertex_opacity
[2];
228 vertex_opacity_
[3] = vertex_opacity
[3];
229 SetNeedsPushProperties();
232 const char* TextureLayerImpl::LayerTypeAsString() const {
233 return "cc::TextureLayerImpl";
236 void TextureLayerImpl::FreeTextureMailbox() {
238 DCHECK(!external_texture_resource_
);
239 if (release_callback_
)
240 release_callback_
->Run(texture_mailbox_
.sync_point(), false);
241 texture_mailbox_
= TextureMailbox();
242 release_callback_
.reset();
243 } else if (external_texture_resource_
) {
244 DCHECK(!own_mailbox_
);
245 ResourceProvider
* resource_provider
=
246 layer_tree_impl()->resource_provider();
247 resource_provider
->DeleteResource(external_texture_resource_
);
248 external_texture_resource_
= 0;