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_
.size_in_pixels() ||
103 resource_provider
->InUseByConsumer(texture_copy_
->id()))
104 texture_copy_
->Free();
106 if (!texture_copy_
->id()) {
107 texture_copy_
->Allocate(texture_mailbox_
.size_in_pixels(),
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
->CopyToResource(texture_copy_
->id(), pixels
,
130 texture_mailbox_
.size_in_pixels());
132 valid_texture_copy_
= true;
135 return (external_texture_resource_
|| valid_texture_copy_
) &&
136 LayerImpl::WillDraw(draw_mode
, resource_provider
);
139 void TextureLayerImpl::AppendQuads(RenderPass
* render_pass
,
140 AppendQuadsData
* append_quads_data
) {
141 DCHECK(external_texture_resource_
|| valid_texture_copy_
);
143 SharedQuadState
* shared_quad_state
=
144 render_pass
->CreateAndAppendSharedQuadState();
145 PopulateSharedQuadState(shared_quad_state
);
147 AppendDebugBorderQuad(render_pass
, bounds(), shared_quad_state
,
150 SkColor bg_color
= blend_background_color_
?
151 background_color() : SK_ColorTRANSPARENT
;
152 bool opaque
= contents_opaque() || (SkColorGetA(bg_color
) == 0xFF);
154 gfx::Rect
quad_rect(bounds());
155 gfx::Rect opaque_rect
= opaque
? quad_rect
: gfx::Rect();
156 gfx::Rect visible_quad_rect
=
157 draw_properties().occlusion_in_content_space
.GetUnoccludedContentRect(
159 if (visible_quad_rect
.IsEmpty())
162 TextureDrawQuad
* quad
=
163 render_pass
->CreateAndAppendDrawQuad
<TextureDrawQuad
>();
165 valid_texture_copy_
? texture_copy_
->id() : external_texture_resource_
;
166 quad
->SetNew(shared_quad_state
,
171 premultiplied_alpha_
,
178 if (!valid_texture_copy_
) {
179 quad
->set_resource_size_in_pixels(texture_mailbox_
.size_in_pixels());
180 quad
->set_allow_overlay(texture_mailbox_
.allow_overlay());
182 ValidateQuadResources(quad
);
185 SimpleEnclosedRegion
TextureLayerImpl::VisibleOpaqueRegion() const {
186 if (contents_opaque())
187 return SimpleEnclosedRegion(visible_layer_rect());
189 if (blend_background_color_
&& (SkColorGetA(background_color()) == 0xFF))
190 return SimpleEnclosedRegion(visible_layer_rect());
192 return SimpleEnclosedRegion();
195 void TextureLayerImpl::ReleaseResources() {
196 FreeTextureMailbox();
197 texture_copy_
= nullptr;
198 external_texture_resource_
= 0;
199 valid_texture_copy_
= false;
202 void TextureLayerImpl::SetPremultipliedAlpha(bool premultiplied_alpha
) {
203 premultiplied_alpha_
= premultiplied_alpha
;
204 SetNeedsPushProperties();
207 void TextureLayerImpl::SetBlendBackgroundColor(bool blend
) {
208 blend_background_color_
= blend
;
209 SetNeedsPushProperties();
212 void TextureLayerImpl::SetFlipped(bool flipped
) {
214 SetNeedsPushProperties();
217 void TextureLayerImpl::SetNearestNeighbor(bool nearest_neighbor
) {
218 nearest_neighbor_
= nearest_neighbor
;
219 SetNeedsPushProperties();
222 void TextureLayerImpl::SetUVTopLeft(const gfx::PointF
& top_left
) {
223 uv_top_left_
= top_left
;
224 SetNeedsPushProperties();
227 void TextureLayerImpl::SetUVBottomRight(const gfx::PointF
& bottom_right
) {
228 uv_bottom_right_
= bottom_right
;
229 SetNeedsPushProperties();
235 void TextureLayerImpl::SetVertexOpacity(const float vertex_opacity
[4]) {
236 vertex_opacity_
[0] = vertex_opacity
[0];
237 vertex_opacity_
[1] = vertex_opacity
[1];
238 vertex_opacity_
[2] = vertex_opacity
[2];
239 vertex_opacity_
[3] = vertex_opacity
[3];
240 SetNeedsPushProperties();
243 const char* TextureLayerImpl::LayerTypeAsString() const {
244 return "cc::TextureLayerImpl";
247 void TextureLayerImpl::FreeTextureMailbox() {
249 DCHECK(!external_texture_resource_
);
250 if (release_callback_
) {
251 release_callback_
->Run(texture_mailbox_
.sync_point(),
253 layer_tree_impl()->BlockingMainThreadTaskRunner());
255 texture_mailbox_
= TextureMailbox();
256 release_callback_
= nullptr;
257 } else if (external_texture_resource_
) {
258 DCHECK(!own_mailbox_
);
259 ResourceProvider
* resource_provider
=
260 layer_tree_impl()->resource_provider();
261 resource_provider
->DeleteResource(external_texture_resource_
);
262 external_texture_resource_
= 0;