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_impl.h"
15 #include "cc/trees/layer_tree_impl.h"
16 #include "cc/trees/occlusion.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
<SingleReleaseCallbackImpl
> 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());
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_
= nullptr;
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::TextureHintImmutable
,
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(RenderPass
* render_pass
,
143 const Occlusion
& occlusion_in_content_space
,
144 AppendQuadsData
* append_quads_data
) {
145 DCHECK(external_texture_resource_
|| valid_texture_copy_
);
147 SharedQuadState
* shared_quad_state
=
148 render_pass
->CreateAndAppendSharedQuadState();
149 PopulateSharedQuadState(shared_quad_state
);
151 AppendDebugBorderQuad(
152 render_pass
, content_bounds(), shared_quad_state
, append_quads_data
);
154 SkColor bg_color
= blend_background_color_
?
155 background_color() : SK_ColorTRANSPARENT
;
156 bool opaque
= contents_opaque() || (SkColorGetA(bg_color
) == 0xFF);
158 gfx::Rect
quad_rect(content_bounds());
159 gfx::Rect opaque_rect
= opaque
? quad_rect
: gfx::Rect();
160 gfx::Rect visible_quad_rect
=
161 occlusion_in_content_space
.GetUnoccludedContentRect(quad_rect
);
162 if (visible_quad_rect
.IsEmpty())
165 TextureDrawQuad
* quad
=
166 render_pass
->CreateAndAppendDrawQuad
<TextureDrawQuad
>();
167 ResourceProvider::ResourceId id
=
168 valid_texture_copy_
? texture_copy_
->id() : external_texture_resource_
;
169 quad
->SetNew(shared_quad_state
,
174 premultiplied_alpha_
,
182 SimpleEnclosedRegion
TextureLayerImpl::VisibleContentOpaqueRegion() const {
183 if (contents_opaque())
184 return SimpleEnclosedRegion(visible_content_rect());
186 if (blend_background_color_
&& (SkColorGetA(background_color()) == 0xFF))
187 return SimpleEnclosedRegion(visible_content_rect());
189 return SimpleEnclosedRegion();
192 void TextureLayerImpl::ReleaseResources() {
193 FreeTextureMailbox();
194 texture_copy_
= nullptr;
195 external_texture_resource_
= 0;
196 valid_texture_copy_
= false;
199 void TextureLayerImpl::SetPremultipliedAlpha(bool premultiplied_alpha
) {
200 premultiplied_alpha_
= premultiplied_alpha
;
201 SetNeedsPushProperties();
204 void TextureLayerImpl::SetBlendBackgroundColor(bool blend
) {
205 blend_background_color_
= blend
;
206 SetNeedsPushProperties();
209 void TextureLayerImpl::SetFlipped(bool flipped
) {
211 SetNeedsPushProperties();
214 void TextureLayerImpl::SetUVTopLeft(const gfx::PointF top_left
) {
215 uv_top_left_
= top_left
;
216 SetNeedsPushProperties();
219 void TextureLayerImpl::SetUVBottomRight(const gfx::PointF bottom_right
) {
220 uv_bottom_right_
= bottom_right
;
221 SetNeedsPushProperties();
227 void TextureLayerImpl::SetVertexOpacity(const float vertex_opacity
[4]) {
228 vertex_opacity_
[0] = vertex_opacity
[0];
229 vertex_opacity_
[1] = vertex_opacity
[1];
230 vertex_opacity_
[2] = vertex_opacity
[2];
231 vertex_opacity_
[3] = vertex_opacity
[3];
232 SetNeedsPushProperties();
235 const char* TextureLayerImpl::LayerTypeAsString() const {
236 return "cc::TextureLayerImpl";
239 void TextureLayerImpl::FreeTextureMailbox() {
241 DCHECK(!external_texture_resource_
);
242 if (release_callback_
) {
243 release_callback_
->Run(texture_mailbox_
.sync_point(),
245 layer_tree_impl()->BlockingMainThreadTaskRunner());
247 texture_mailbox_
= TextureMailbox();
248 release_callback_
= nullptr;
249 } else if (external_texture_resource_
) {
250 DCHECK(!own_mailbox_
);
251 ResourceProvider
* resource_provider
=
252 layer_tree_impl()->resource_provider();
253 resource_provider
->DeleteResource(external_texture_resource_
);
254 external_texture_resource_
= 0;