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 nearest_neighbor_(false),
27 uv_top_left_(0.f
, 0.f
),
28 uv_bottom_right_(1.f
, 1.f
),
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
;
37 TextureLayerImpl::~TextureLayerImpl() { FreeTextureMailbox(); }
39 void TextureLayerImpl::SetTextureMailbox(
40 const TextureMailbox
& mailbox
,
41 scoped_ptr
<SingleReleaseCallbackImpl
> release_callback
) {
42 DCHECK_EQ(mailbox
.IsValid(), !!release_callback
);
44 texture_mailbox_
= mailbox
;
45 release_callback_
= release_callback
.Pass();
47 valid_texture_copy_
= false;
48 SetNeedsPushProperties();
51 scoped_ptr
<LayerImpl
> TextureLayerImpl::CreateLayerImpl(
52 LayerTreeImpl
* tree_impl
) {
53 return TextureLayerImpl::Create(tree_impl
, id());
56 void TextureLayerImpl::PushPropertiesTo(LayerImpl
* layer
) {
57 LayerImpl::PushPropertiesTo(layer
);
59 TextureLayerImpl
* texture_layer
= static_cast<TextureLayerImpl
*>(layer
);
60 texture_layer
->SetFlipped(flipped_
);
61 texture_layer
->SetUVTopLeft(uv_top_left_
);
62 texture_layer
->SetUVBottomRight(uv_bottom_right_
);
63 texture_layer
->SetVertexOpacity(vertex_opacity_
);
64 texture_layer
->SetPremultipliedAlpha(premultiplied_alpha_
);
65 texture_layer
->SetBlendBackgroundColor(blend_background_color_
);
66 texture_layer
->SetNearestNeighbor(nearest_neighbor_
);
68 texture_layer
->SetTextureMailbox(texture_mailbox_
,
69 release_callback_
.Pass());
74 bool TextureLayerImpl::WillDraw(DrawMode draw_mode
,
75 ResourceProvider
* resource_provider
) {
76 if (draw_mode
== DRAW_MODE_RESOURCELESS_SOFTWARE
)
80 DCHECK(!external_texture_resource_
);
81 if ((draw_mode
== DRAW_MODE_HARDWARE
&& texture_mailbox_
.IsTexture()) ||
82 (draw_mode
== DRAW_MODE_SOFTWARE
&&
83 texture_mailbox_
.IsSharedMemory())) {
84 external_texture_resource_
=
85 resource_provider
->CreateResourceFromTextureMailbox(
86 texture_mailbox_
, release_callback_
.Pass());
87 DCHECK(external_texture_resource_
);
88 texture_copy_
= nullptr;
89 valid_texture_copy_
= false;
91 if (external_texture_resource_
)
95 if (!valid_texture_copy_
&& draw_mode
== DRAW_MODE_HARDWARE
&&
96 texture_mailbox_
.IsSharedMemory()) {
97 DCHECK(!external_texture_resource_
);
98 // Have to upload a copy to a texture for it to be used in a
101 texture_copy_
= ScopedResource::Create(resource_provider
);
102 if (texture_copy_
->size() != texture_mailbox_
.shared_memory_size() ||
103 resource_provider
->InUseByConsumer(texture_copy_
->id()))
104 texture_copy_
->Free();
106 if (!texture_copy_
->id()) {
107 texture_copy_
->Allocate(texture_mailbox_
.shared_memory_size(),
108 ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
109 resource_provider
->best_texture_format());
112 if (texture_copy_
->id()) {
113 std::vector
<uint8
> swizzled
;
114 uint8
* pixels
= texture_mailbox_
.shared_bitmap()->pixels();
116 if (!PlatformColor::SameComponentOrder(texture_copy_
->format())) {
117 // Swizzle colors. This is slow, but should be really uncommon.
118 size_t bytes
= texture_mailbox_
.SharedMemorySizeInBytes();
119 swizzled
.resize(bytes
);
120 for (size_t i
= 0; i
< bytes
; i
+= 4) {
121 swizzled
[i
] = pixels
[i
+ 2];
122 swizzled
[i
+ 1] = pixels
[i
+ 1];
123 swizzled
[i
+ 2] = pixels
[i
];
124 swizzled
[i
+ 3] = pixels
[i
+ 3];
126 pixels
= &swizzled
[0];
129 resource_provider
->SetPixels(
132 gfx::Rect(texture_mailbox_
.shared_memory_size()),
133 gfx::Rect(texture_mailbox_
.shared_memory_size()),
136 valid_texture_copy_
= true;
139 return (external_texture_resource_
|| valid_texture_copy_
) &&
140 LayerImpl::WillDraw(draw_mode
, resource_provider
);
143 void TextureLayerImpl::AppendQuads(RenderPass
* render_pass
,
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 draw_properties().occlusion_in_content_space
.GetUnoccludedContentRect(
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 // TODO(danakj): crbug.com/455931
171 layer_tree_impl()->resource_provider()->ValidateResource(id
);
172 quad
->SetNew(shared_quad_state
,
177 premultiplied_alpha_
,
186 SimpleEnclosedRegion
TextureLayerImpl::VisibleContentOpaqueRegion() const {
187 if (contents_opaque())
188 return SimpleEnclosedRegion(visible_content_rect());
190 if (blend_background_color_
&& (SkColorGetA(background_color()) == 0xFF))
191 return SimpleEnclosedRegion(visible_content_rect());
193 return SimpleEnclosedRegion();
196 void TextureLayerImpl::ReleaseResources() {
197 FreeTextureMailbox();
198 texture_copy_
= nullptr;
199 external_texture_resource_
= 0;
200 valid_texture_copy_
= false;
203 void TextureLayerImpl::SetPremultipliedAlpha(bool premultiplied_alpha
) {
204 premultiplied_alpha_
= premultiplied_alpha
;
205 SetNeedsPushProperties();
208 void TextureLayerImpl::SetBlendBackgroundColor(bool blend
) {
209 blend_background_color_
= blend
;
210 SetNeedsPushProperties();
213 void TextureLayerImpl::SetFlipped(bool flipped
) {
215 SetNeedsPushProperties();
218 void TextureLayerImpl::SetNearestNeighbor(bool nearest_neighbor
) {
219 nearest_neighbor_
= nearest_neighbor
;
220 SetNeedsPushProperties();
223 void TextureLayerImpl::SetUVTopLeft(const gfx::PointF top_left
) {
224 uv_top_left_
= top_left
;
225 SetNeedsPushProperties();
228 void TextureLayerImpl::SetUVBottomRight(const gfx::PointF bottom_right
) {
229 uv_bottom_right_
= bottom_right
;
230 SetNeedsPushProperties();
236 void TextureLayerImpl::SetVertexOpacity(const float vertex_opacity
[4]) {
237 vertex_opacity_
[0] = vertex_opacity
[0];
238 vertex_opacity_
[1] = vertex_opacity
[1];
239 vertex_opacity_
[2] = vertex_opacity
[2];
240 vertex_opacity_
[3] = vertex_opacity
[3];
241 SetNeedsPushProperties();
244 const char* TextureLayerImpl::LayerTypeAsString() const {
245 return "cc::TextureLayerImpl";
248 void TextureLayerImpl::FreeTextureMailbox() {
250 DCHECK(!external_texture_resource_
);
251 if (release_callback_
) {
252 release_callback_
->Run(texture_mailbox_
.sync_point(),
254 layer_tree_impl()->BlockingMainThreadTaskRunner());
256 texture_mailbox_
= TextureMailbox();
257 release_callback_
= nullptr;
258 } else if (external_texture_resource_
) {
259 DCHECK(!own_mailbox_
);
260 ResourceProvider
* resource_provider
=
261 layer_tree_impl()->resource_provider();
262 resource_provider
->DeleteResource(external_texture_resource_
);
263 external_texture_resource_
= 0;