OLD | NEW |
| (Empty) |
1 // Copyright 2015 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. | |
4 | |
5 #include "components/bitmap_uploader/bitmap_uploader.h" | |
6 | |
7 #include <stddef.h> | |
8 #include <utility> | |
9 | |
10 #include "base/bind.h" | |
11 #include "base/callback.h" | |
12 #include "cc/ipc/compositor_frame.mojom.h" | |
13 #include "cc/quads/render_pass.h" | |
14 #include "cc/quads/solid_color_draw_quad.h" | |
15 #include "cc/quads/texture_draw_quad.h" | |
16 #include "services/ui/public/cpp/gles2_context.h" | |
17 #include "services/ui/public/cpp/window.h" | |
18 #include "services/ui/public/cpp/window_surface.h" | |
19 | |
20 namespace bitmap_uploader { | |
21 namespace { | |
22 | |
23 const uint32_t g_transparent_color = 0x00000000; | |
24 | |
25 } // namespace | |
26 | |
27 const char kBitmapUploaderForAcceleratedWidget[] = | |
28 "__BITMAP_UPLOADER_ACCELERATED_WIDGET__"; | |
29 | |
30 BitmapUploader::BitmapUploader(ui::Window* window) | |
31 : window_(window), | |
32 color_(g_transparent_color), | |
33 width_(0), | |
34 height_(0), | |
35 format_(BGRA), | |
36 next_resource_id_(1u), | |
37 id_namespace_(0u) {} | |
38 | |
39 BitmapUploader::~BitmapUploader() { | |
40 } | |
41 | |
42 void BitmapUploader::Init(shell::Connector* connector) { | |
43 surface_ = window_->RequestSurface(ui::mojom::SurfaceType::DEFAULT); | |
44 surface_->BindToThread(); | |
45 surface_->set_client(this); | |
46 | |
47 gles2_context_ = ui::GLES2Context::CreateOffscreenContext( | |
48 std::vector<int32_t>(), connector); | |
49 // CreateOffscreenContext() may return null. | |
50 } | |
51 | |
52 // Sets the color which is RGBA. | |
53 void BitmapUploader::SetColor(uint32_t color) { | |
54 if (color_ == color) | |
55 return; | |
56 color_ = color; | |
57 if (surface_) | |
58 Upload(); | |
59 } | |
60 | |
61 // Sets a bitmap. | |
62 void BitmapUploader::SetBitmap(int width, | |
63 int height, | |
64 std::unique_ptr<std::vector<unsigned char>> data, | |
65 Format format) { | |
66 width_ = width; | |
67 height_ = height; | |
68 bitmap_ = std::move(data); | |
69 format_ = format; | |
70 if (surface_) | |
71 Upload(); | |
72 } | |
73 | |
74 void BitmapUploader::Upload() { | |
75 if (!gles2_context_) | |
76 return; | |
77 | |
78 const gfx::Rect bounds(window_->bounds().size()); | |
79 | |
80 cc::CompositorFrame frame; | |
81 // TODO(rjkroege): Support device scale factors other than 1. | |
82 frame.metadata.device_scale_factor = 1.0f; | |
83 frame.delegated_frame_data.reset(new cc::DelegatedFrameData()); | |
84 frame.delegated_frame_data->resource_list.resize(0u); | |
85 | |
86 const cc::RenderPassId render_pass_id(1, 1); | |
87 std::unique_ptr<cc::RenderPass> pass = cc::RenderPass::Create(); | |
88 pass->SetAll(render_pass_id, bounds, bounds, gfx::Transform(), | |
89 true /* has_transparent_background */); | |
90 | |
91 // The SharedQuadState is owned by the SharedQuadStateList | |
92 // shared_quad_state_list. | |
93 cc::SharedQuadState* sqs = pass->CreateAndAppendSharedQuadState(); | |
94 sqs->SetAll(gfx::Transform(), bounds.size(), bounds, bounds, | |
95 false /* is_clipped */, 1.f /* opacity */, SkXfermode::kSrc_Mode, | |
96 0 /* sorting_context_id */); | |
97 | |
98 if (bitmap_.get()) { | |
99 gpu::gles2::GLES2Interface* gl = gles2_context_->interface(); | |
100 gfx::Size bitmap_size(width_, height_); | |
101 GLuint texture_id = BindTextureForSize(bitmap_size); | |
102 gl->TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bitmap_size.width(), | |
103 bitmap_size.height(), TextureFormat(), GL_UNSIGNED_BYTE, | |
104 &((*bitmap_)[0])); | |
105 | |
106 gpu::Mailbox mailbox; | |
107 gl->GenMailboxCHROMIUM(mailbox.name); | |
108 gl->ProduceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name); | |
109 | |
110 const GLuint64 fence_sync = gl->InsertFenceSyncCHROMIUM(); | |
111 gl->ShallowFlushCHROMIUM(); | |
112 | |
113 gpu::SyncToken sync_token; | |
114 gl->GenSyncTokenCHROMIUM(fence_sync, sync_token.GetData()); | |
115 | |
116 cc::TransferableResource resource; | |
117 resource.id = next_resource_id_++; | |
118 resource_to_texture_id_map_[resource.id] = texture_id; | |
119 resource.format = cc::ResourceFormat::RGBA_8888; | |
120 resource.filter = GL_LINEAR; | |
121 resource.size = bitmap_size; | |
122 resource.mailbox_holder = | |
123 gpu::MailboxHolder(mailbox, sync_token, GL_TEXTURE_2D); | |
124 resource.read_lock_fences_enabled = false; | |
125 resource.is_software = false; | |
126 resource.is_overlay_candidate = false; | |
127 frame.delegated_frame_data->resource_list.push_back(std::move(resource)); | |
128 | |
129 cc::TextureDrawQuad* quad = | |
130 pass->CreateAndAppendDrawQuad<cc::TextureDrawQuad>(); | |
131 | |
132 gfx::Size rect_size; | |
133 if (width_ <= bounds.width() && height_ <= bounds.height()) { | |
134 rect_size.SetSize(width_, height_); | |
135 } else { | |
136 // The source bitmap is larger than the viewport. Resize it while | |
137 // maintaining the aspect ratio. | |
138 float width_ratio = static_cast<float>(width_) / bounds.width(); | |
139 float height_ratio = static_cast<float>(height_) / bounds.height(); | |
140 if (width_ratio > height_ratio) { | |
141 rect_size.SetSize(bounds.width(), height_ / width_ratio); | |
142 } else { | |
143 rect_size.SetSize(width_ / height_ratio, bounds.height()); | |
144 } | |
145 } | |
146 gfx::Rect rect(rect_size); | |
147 const bool needs_blending = true; | |
148 const bool premultiplied_alpha = true; | |
149 const gfx::PointF uv_top_left(0.f, 0.f); | |
150 const gfx::PointF uv_bottom_right(1.f, 1.f); | |
151 float vertex_opacity[4] = {1.f, 1.f, 1.f, 1.f}; | |
152 const bool y_flipped = false; | |
153 const bool nearest_neighbor = false; | |
154 quad->SetAll(sqs, rect, rect, rect, needs_blending, resource.id, | |
155 gfx::Size(), premultiplied_alpha, uv_top_left, uv_bottom_right, | |
156 g_transparent_color, vertex_opacity, y_flipped, | |
157 nearest_neighbor, false); | |
158 } | |
159 | |
160 if (color_ != g_transparent_color) { | |
161 cc::SolidColorDrawQuad* quad = | |
162 pass->CreateAndAppendDrawQuad<cc::SolidColorDrawQuad>(); | |
163 const bool force_antialiasing_off = false; | |
164 const gfx::Rect opaque_rect(0, 0, 0, 0); | |
165 const bool needs_blending = true; | |
166 quad->SetAll(sqs, bounds, opaque_rect, bounds, needs_blending, color_, | |
167 force_antialiasing_off); | |
168 } | |
169 | |
170 frame.delegated_frame_data->render_pass_list.push_back(std::move(pass)); | |
171 | |
172 // TODO(rjkroege, fsamuel): We should throttle frames. | |
173 surface_->SubmitCompositorFrame(std::move(frame), base::Closure()); | |
174 } | |
175 | |
176 uint32_t BitmapUploader::BindTextureForSize(const gfx::Size& size) { | |
177 gpu::gles2::GLES2Interface* gl = gles2_context_->interface(); | |
178 // TODO(jamesr): Recycle textures. | |
179 GLuint texture = 0u; | |
180 gl->GenTextures(1, &texture); | |
181 gl->BindTexture(GL_TEXTURE_2D, texture); | |
182 gl->TexImage2D(GL_TEXTURE_2D, 0, TextureFormat(), size.width(), size.height(), | |
183 0, TextureFormat(), GL_UNSIGNED_BYTE, 0); | |
184 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |
185 return texture; | |
186 } | |
187 | |
188 void BitmapUploader::SetIdNamespace(uint32_t id_namespace) { | |
189 id_namespace_ = id_namespace; | |
190 if (color_ != g_transparent_color || bitmap_.get()) | |
191 Upload(); | |
192 } | |
193 | |
194 void BitmapUploader::OnResourcesReturned( | |
195 ui::WindowSurface* surface, | |
196 mojo::Array<cc::ReturnedResource> resources) { | |
197 gpu::gles2::GLES2Interface* gl = gles2_context_->interface(); | |
198 // TODO(jamesr): Recycle. | |
199 for (size_t i = 0; i < resources.size(); ++i) { | |
200 cc::ReturnedResource resource = std::move(resources[i]); | |
201 DCHECK_EQ(1, resource.count); | |
202 gl->WaitSyncTokenCHROMIUM(resource.sync_token.GetConstData()); | |
203 uint32_t texture_id = resource_to_texture_id_map_[resource.id]; | |
204 DCHECK_NE(0u, texture_id); | |
205 resource_to_texture_id_map_.erase(resource.id); | |
206 gl->DeleteTextures(1, &texture_id); | |
207 } | |
208 } | |
209 | |
210 } // namespace bitmap_uploader | |
OLD | NEW |