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/output/renderer.h"
11 #include "cc/quads/texture_draw_quad.h"
12 #include "cc/resources/platform_color.h"
13 #include "cc/resources/scoped_resource.h"
14 #include "cc/resources/single_release_callback.h"
15 #include "cc/trees/layer_tree_impl.h"
16 #include "cc/trees/occlusion_tracker.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(
143 RenderPass
* render_pass
,
144 const OcclusionTracker
<LayerImpl
>& occlusion_tracker
,
145 AppendQuadsData
* append_quads_data
) {
146 DCHECK(external_texture_resource_
|| valid_texture_copy_
);
148 SharedQuadState
* shared_quad_state
=
149 render_pass
->CreateAndAppendSharedQuadState();
150 PopulateSharedQuadState(shared_quad_state
);
152 AppendDebugBorderQuad(
153 render_pass
, content_bounds(), shared_quad_state
, append_quads_data
);
155 SkColor bg_color
= blend_background_color_
?
156 background_color() : SK_ColorTRANSPARENT
;
157 bool opaque
= contents_opaque() || (SkColorGetA(bg_color
) == 0xFF);
159 gfx::Rect
quad_rect(content_bounds());
160 gfx::Rect opaque_rect
= opaque
? quad_rect
: gfx::Rect();
161 gfx::Rect visible_quad_rect
= occlusion_tracker
.UnoccludedContentRect(
162 quad_rect
, draw_properties().target_space_transform
);
163 if (visible_quad_rect
.IsEmpty())
166 TextureDrawQuad
* quad
=
167 render_pass
->CreateAndAppendDrawQuad
<TextureDrawQuad
>();
168 ResourceProvider::ResourceId id
=
169 valid_texture_copy_
? texture_copy_
->id() : external_texture_resource_
;
170 quad
->SetNew(shared_quad_state
,
175 premultiplied_alpha_
,
183 Region
TextureLayerImpl::VisibleContentOpaqueRegion() const {
184 if (contents_opaque())
185 return visible_content_rect();
187 if (blend_background_color_
&& (SkColorGetA(background_color()) == 0xFF))
188 return visible_content_rect();
193 void TextureLayerImpl::ReleaseResources() {
194 FreeTextureMailbox();
195 texture_copy_
.reset();
196 external_texture_resource_
= 0;
197 valid_texture_copy_
= false;
200 void TextureLayerImpl::SetPremultipliedAlpha(bool premultiplied_alpha
) {
201 premultiplied_alpha_
= premultiplied_alpha
;
202 SetNeedsPushProperties();
205 void TextureLayerImpl::SetBlendBackgroundColor(bool blend
) {
206 blend_background_color_
= blend
;
207 SetNeedsPushProperties();
210 void TextureLayerImpl::SetFlipped(bool flipped
) {
212 SetNeedsPushProperties();
215 void TextureLayerImpl::SetUVTopLeft(const gfx::PointF top_left
) {
216 uv_top_left_
= top_left
;
217 SetNeedsPushProperties();
220 void TextureLayerImpl::SetUVBottomRight(const gfx::PointF bottom_right
) {
221 uv_bottom_right_
= bottom_right
;
222 SetNeedsPushProperties();
228 void TextureLayerImpl::SetVertexOpacity(const float vertex_opacity
[4]) {
229 vertex_opacity_
[0] = vertex_opacity
[0];
230 vertex_opacity_
[1] = vertex_opacity
[1];
231 vertex_opacity_
[2] = vertex_opacity
[2];
232 vertex_opacity_
[3] = vertex_opacity
[3];
233 SetNeedsPushProperties();
236 const char* TextureLayerImpl::LayerTypeAsString() const {
237 return "cc::TextureLayerImpl";
240 void TextureLayerImpl::FreeTextureMailbox() {
242 DCHECK(!external_texture_resource_
);
243 if (release_callback_
)
244 release_callback_
->Run(texture_mailbox_
.sync_point(), false);
245 texture_mailbox_
= TextureMailbox();
246 release_callback_
.reset();
247 } else if (external_texture_resource_
) {
248 DCHECK(!own_mailbox_
);
249 ResourceProvider
* resource_provider
=
250 layer_tree_impl()->resource_provider();
251 resource_provider
->DeleteResource(external_texture_resource_
);
252 external_texture_resource_
= 0;