Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(373)

Side by Side Diff: ash/laser/laser_pointer_view.cc

Issue 2714393002: ash: Low-latency laser pointer. (Closed)
Patch Set: fix deps Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ash/laser/laser_pointer_view.h ('k') | mash/BUILD.gn » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ash/laser/laser_pointer_view.h" 5 #include "ash/laser/laser_pointer_view.h"
6 6
7 #include <GLES2/gl2.h>
8 #include <GLES2/gl2ext.h>
9 #include <GLES2/gl2extchromium.h>
10
7 #include <memory> 11 #include <memory>
8 12
9 #include "ash/laser/laser_pointer_points.h" 13 #include "ash/laser/laser_pointer_points.h"
10 #include "ash/laser/laser_segment_utils.h" 14 #include "ash/laser/laser_segment_utils.h"
11 #include "ash/public/cpp/shell_window_ids.h" 15 #include "ash/public/cpp/shell_window_ids.h"
12 #include "ash/shell.h" 16 #include "ash/shell.h"
17 #include "base/threading/thread_task_runner_handle.h"
13 #include "base/timer/timer.h" 18 #include "base/timer/timer.h"
19 #include "base/trace_event/trace_event.h"
20 #include "cc/output/context_provider.h"
21 #include "cc/quads/texture_draw_quad.h"
22 #include "cc/resources/transferable_resource.h"
23 #include "cc/surfaces/surface.h"
24 #include "cc/surfaces/surface_manager.h"
25 #include "gpu/command_buffer/client/context_support.h"
26 #include "gpu/command_buffer/client/gles2_interface.h"
27 #include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
14 #include "third_party/skia/include/core/SkColor.h" 28 #include "third_party/skia/include/core/SkColor.h"
29 #include "third_party/skia/include/core/SkTypes.h"
30 #include "ui/aura/env.h"
15 #include "ui/aura/window.h" 31 #include "ui/aura/window.h"
32 #include "ui/display/display.h"
33 #include "ui/display/screen.h"
16 #include "ui/events/event.h" 34 #include "ui/events/event.h"
17 #include "ui/gfx/canvas.h" 35 #include "ui/gfx/canvas.h"
36 #include "ui/gfx/gpu_memory_buffer.h"
18 #include "ui/views/widget/widget.h" 37 #include "ui/views/widget/widget.h"
19 38
20 namespace ash { 39 namespace ash {
21 namespace { 40 namespace {
22 41
23 // Variables for rendering the laser. Radius in DIP. 42 // Variables for rendering the laser. Radius in DIP.
24 const float kPointInitialRadius = 5.0f; 43 const float kPointInitialRadius = 5.0f;
25 const float kPointFinalRadius = 0.25f; 44 const float kPointFinalRadius = 0.25f;
26 const int kPointInitialOpacity = 200; 45 const int kPointInitialOpacity = 200;
27 const int kPointFinalOpacity = 10; 46 const int kPointFinalOpacity = 10;
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
150 SkPath path() const { return path_; } 169 SkPath path() const { return path_; }
151 std::vector<gfx::PointF> path_points() const { return path_points_; } 170 std::vector<gfx::PointF> path_points() const { return path_points_; }
152 171
153 private: 172 private:
154 SkPath path_; 173 SkPath path_;
155 std::vector<gfx::PointF> path_points_; 174 std::vector<gfx::PointF> path_points_;
156 175
157 DISALLOW_COPY_AND_ASSIGN(LaserSegment); 176 DISALLOW_COPY_AND_ASSIGN(LaserSegment);
158 }; 177 };
159 178
179 // This struct contains the resources associated with a laser pointer frame.
180 struct LaserResource {
181 LaserResource() {}
182 ~LaserResource() {
183 if (context_provider) {
184 gpu::gles2::GLES2Interface* gles2 = context_provider->ContextGL();
185 if (texture)
186 gles2->DeleteTextures(1, &texture);
187 if (image)
188 gles2->DestroyImageCHROMIUM(image);
189 }
190 }
191 scoped_refptr<cc::ContextProvider> context_provider;
192 uint32_t texture = 0;
193 uint32_t image = 0;
194 gpu::Mailbox mailbox;
195 };
196
160 // LaserPointerView 197 // LaserPointerView
161 LaserPointerView::LaserPointerView(base::TimeDelta life_duration, 198 LaserPointerView::LaserPointerView(base::TimeDelta life_duration,
162 aura::Window* root_window) 199 aura::Window* root_window)
163 : laser_points_(life_duration) { 200 : laser_points_(life_duration),
201 frame_sink_id_(aura::Env::GetInstance()
202 ->context_factory_private()
203 ->AllocateFrameSinkId()),
204 frame_sink_support_(this,
205 aura::Env::GetInstance()
206 ->context_factory_private()
207 ->GetSurfaceManager(),
208 frame_sink_id_,
209 false /* is_root */,
210 true /* handles_frame_sink_id_invalidation */,
211 true /* needs_sync_points */),
212 weak_ptr_factory_(this) {
164 widget_.reset(new views::Widget); 213 widget_.reset(new views::Widget);
165 views::Widget::InitParams params; 214 views::Widget::InitParams params;
166 params.type = views::Widget::InitParams::TYPE_WINDOW_FRAMELESS; 215 params.type = views::Widget::InitParams::TYPE_WINDOW_FRAMELESS;
167 params.name = "LaserOverlay"; 216 params.name = "LaserOverlay";
168 params.accept_events = false; 217 params.accept_events = false;
169 params.activatable = views::Widget::InitParams::ACTIVATABLE_NO; 218 params.activatable = views::Widget::InitParams::ACTIVATABLE_NO;
170 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 219 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
171 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; 220 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
172 params.parent = 221 params.parent =
173 Shell::GetContainer(root_window, kShellWindowId_OverlayContainer); 222 Shell::GetContainer(root_window, kShellWindowId_OverlayContainer);
223 params.layer_type = ui::LAYER_SOLID_COLOR;
174 224
175 widget_->Init(params); 225 widget_->Init(params);
176 widget_->Show(); 226 widget_->Show();
177 widget_->SetContentsView(this); 227 widget_->SetContentsView(this);
228 widget_->SetBounds(root_window->GetBoundsInScreen());
178 set_owned_by_client(); 229 set_owned_by_client();
230
231 scale_factor_ = display::Screen::GetScreen()
232 ->GetDisplayNearestWindow(widget_->GetNativeView())
233 .device_scale_factor();
179 } 234 }
180 235
181 LaserPointerView::~LaserPointerView() {} 236 LaserPointerView::~LaserPointerView() {
237 // Make sure GPU memory buffer is unmapped before being destroyed.
238 if (gpu_memory_buffer_)
239 gpu_memory_buffer_->Unmap();
240 }
182 241
183 void LaserPointerView::Stop() { 242 void LaserPointerView::Stop() {
243 buffer_damage_rect_.Union(GetBoundingBox());
184 laser_points_.Clear(); 244 laser_points_.Clear();
185 SchedulePaint(); 245 OnPointsUpdated();
186 } 246 }
187 247
188 void LaserPointerView::AddNewPoint(const gfx::Point& new_point) { 248 void LaserPointerView::AddNewPoint(const gfx::Point& new_point) {
249 buffer_damage_rect_.Union(GetBoundingBox());
189 laser_points_.AddPoint(new_point); 250 laser_points_.AddPoint(new_point);
251 buffer_damage_rect_.Union(GetBoundingBox());
190 OnPointsUpdated(); 252 OnPointsUpdated();
191 } 253 }
192 254
193 void LaserPointerView::UpdateTime() { 255 void LaserPointerView::UpdateTime() {
256 buffer_damage_rect_.Union(GetBoundingBox());
194 // Do not add the point but advance the time if the view is in process of 257 // Do not add the point but advance the time if the view is in process of
195 // fading away. 258 // fading away.
196 laser_points_.MoveForwardToTime(base::Time::Now()); 259 laser_points_.MoveForwardToTime(base::Time::Now());
260 buffer_damage_rect_.Union(GetBoundingBox());
197 OnPointsUpdated(); 261 OnPointsUpdated();
198 } 262 }
199 263
200 void LaserPointerView::OnPointsUpdated() { 264 void LaserPointerView::SetNeedsBeginFrame(bool needs_begin_frame) {
201 // The bounding box should be relative to the screen. 265 frame_sink_support_.SetNeedsBeginFrame(needs_begin_frame);
202 gfx::Point screen_offset =
203 widget_->GetNativeView()->GetRootWindow()->GetBoundsInScreen().origin();
204
205 // Expand the bounding box so that it includes the radius of the points on the
206 // edges.
207 gfx::Rect bounding_box;
208 bounding_box = laser_points_.GetBoundingBox();
209 bounding_box.Offset(-kPointInitialRadius, -kPointInitialRadius);
210 bounding_box.Offset(screen_offset.x(), screen_offset.y());
211 bounding_box.set_width(bounding_box.width() + (kPointInitialRadius * 2));
212 bounding_box.set_height(bounding_box.height() + (kPointInitialRadius * 2));
213 widget_->SetBounds(bounding_box);
214 SchedulePaint();
215 } 266 }
216 267
217 void LaserPointerView::OnPaint(gfx::Canvas* canvas) { 268 void LaserPointerView::SubmitCompositorFrame(
218 if (laser_points_.IsEmpty()) 269 const cc::LocalSurfaceId& local_surface_id,
270 cc::CompositorFrame frame) {
271 frame_sink_support_.SubmitCompositorFrame(local_surface_id, std::move(frame));
272 }
273
274 void LaserPointerView::EvictFrame() {
275 frame_sink_support_.EvictFrame();
276 }
277
278 void LaserPointerView::Require(const cc::LocalSurfaceId& local_surface_id,
279 const cc::SurfaceSequence& sequence) {
280 frame_sink_support_.Require(local_surface_id, sequence);
281 }
282
283 void LaserPointerView::Satisfy(const cc::SurfaceSequence& sequence) {
284 frame_sink_support_.Satisfy(sequence);
285 }
286
287 void LaserPointerView::ReclaimResources(
288 const cc::ReturnedResourceArray& resources) {
289 DCHECK_EQ(resources.size(), 1u);
290
291 auto it = resources_.find(resources.front().id);
292 DCHECK(it != resources_.end());
293 std::unique_ptr<LaserResource> resource = std::move(it->second);
294 resources_.erase(it);
295
296 gpu::gles2::GLES2Interface* gles2 = resource->context_provider->ContextGL();
297 if (resources.front().sync_token.HasData())
298 gles2->WaitSyncTokenCHROMIUM(resources.front().sync_token.GetConstData());
299
300 if (!resources.front().lost)
301 returned_resources_.push_back(std::move(resource));
302 }
303
304 void LaserPointerView::WillDrawSurface(
305 const cc::LocalSurfaceId& local_surface_id,
306 const gfx::Rect& damage_rect) {
jbauman 2017/03/01 01:12:01 On think this should be triggered by DidReceiveCom
reveman 2017/03/01 18:57:15 Done. Will throttle frames more aggressively. This
307 base::ThreadTaskRunnerHandle::Get()->PostTask(
308 FROM_HERE, base::Bind(&LaserPointerView::OnDidDrawSurface,
309 weak_ptr_factory_.GetWeakPtr()));
310 ;
311 }
312
313 gfx::Rect LaserPointerView::GetBoundingBox() {
314 // Expand the bounding box so that it includes the radius of the points on the
315 // edges and antialiasing.
316 gfx::Rect bounding_box = laser_points_.GetBoundingBox();
317 const int kOutsetForAntialiasing = 1;
318 int outset = kPointInitialRadius + kOutsetForAntialiasing;
319 bounding_box.Inset(-outset, -outset);
320 return bounding_box;
321 }
322
323 void LaserPointerView::OnPointsUpdated() {
324 if (pending_update_buffer_)
219 return; 325 return;
220 326
327 pending_update_buffer_ = true;
328 base::ThreadTaskRunnerHandle::Get()->PostTask(
329 FROM_HERE, base::Bind(&LaserPointerView::UpdateBuffer,
330 weak_ptr_factory_.GetWeakPtr()));
331 }
332
333 void LaserPointerView::UpdateBuffer() {
334 TRACE_EVENT2("ui", "LaserPointerView::UpdatedBuffer", "damage",
335 buffer_damage_rect_.ToString(), "points",
336 laser_points_.GetNumberOfPoints());
337
338 DCHECK(pending_update_buffer_);
339 pending_update_buffer_ = false;
340
341 gfx::Rect screen_bounds = widget_->GetNativeView()->GetBoundsInScreen();
342 gfx::Rect update_rect = buffer_damage_rect_;
343 buffer_damage_rect_ = gfx::Rect();
344
345 // Create and map a single GPU memory buffer. The laser pointer will be
346 // written into this buffer without any buffering. The result is that we
347 // might be modifying the buffer while it's being displayed. This provides
348 // minimal latency but potential tearing. Note that we have to draw into
349 // a temporary surface and copy it into GPU memory buffer to avoid flicker.
350 if (!gpu_memory_buffer_) {
351 gpu_memory_buffer_ =
352 aura::Env::GetInstance()
353 ->context_factory()
354 ->GetGpuMemoryBufferManager()
jbauman 2017/03/01 01:12:01 I think we need to listen to ContextFactoryObserve
reveman 2017/03/01 18:57:15 GpuMemoryBuffers survive GPU process crashes. The
355 ->CreateGpuMemoryBuffer(
356 gfx::ScaleToCeiledSize(screen_bounds.size(), scale_factor_),
357 SK_B32_SHIFT ? gfx::BufferFormat::RGBA_8888
358 : gfx::BufferFormat::BGRA_8888,
359 gfx::BufferUsage::SCANOUT_CPU_READ_WRITE,
360 gpu::kNullSurfaceHandle);
361 if (!gpu_memory_buffer_) {
362 LOG(ERROR) << "Failed to allocate GPU memory buffer";
363 return;
364 }
365
366 // Map buffer and keep it mapped until destroyed.
367 bool rv = gpu_memory_buffer_->Map();
368 if (!rv) {
369 LOG(ERROR) << "Failed to map GPU memory buffer";
370 return;
371 }
372
373 // Make sure the first update rectangle covers the whole buffer.
374 update_rect = gfx::Rect(screen_bounds.size());
375 }
376
377 // Constrain update rectangle to buffer size and early out if empty.
378 update_rect.Intersect(gfx::Rect(screen_bounds.size()));
379 if (update_rect.IsEmpty())
380 return;
381
382 // Create a temporary canvas for update rectangle.
383 gfx::Canvas canvas(update_rect.size(), scale_factor_, false);
jbauman 2017/03/01 01:12:01 You might want to have a cache for this to avoid t
reveman 2017/03/01 18:57:15 I considered that but with a good system allocator
384
221 cc::PaintFlags flags; 385 cc::PaintFlags flags;
222 flags.setStyle(cc::PaintFlags::kFill_Style); 386 flags.setStyle(cc::PaintFlags::kFill_Style);
223 flags.setAntiAlias(true); 387 flags.setAntiAlias(true);
224 388
225 // Compute the offset of the current widget. 389 // Compute the offset of the current widget.
226 gfx::Vector2d widget_offset( 390 gfx::Vector2d widget_offset(
227 widget_->GetNativeView()->GetBoundsInRootWindow().origin().x(), 391 widget_->GetNativeView()->GetBoundsInRootWindow().origin().x(),
228 widget_->GetNativeView()->GetBoundsInRootWindow().origin().y()); 392 widget_->GetNativeView()->GetBoundsInRootWindow().origin().y());
229 393
230 int num_points = laser_points_.GetNumberOfPoints(); 394 int num_points = laser_points_.GetNumberOfPoints();
231 DCHECK(num_points > 0); 395 if (num_points) {
232 LaserPointerPoints::LaserPoint previous_point = laser_points_.GetOldest(); 396 LaserPointerPoints::LaserPoint previous_point = laser_points_.GetOldest();
233 previous_point.location -= widget_offset; 397 previous_point.location -= widget_offset + update_rect.OffsetFromOrigin();
jbauman 2017/03/01 01:12:01 Might be easier to just translate the canvas rathe
reveman 2017/03/01 18:57:15 Good idea. I'll keep it as is in current patch to
234 LaserPointerPoints::LaserPoint current_point; 398 LaserPointerPoints::LaserPoint current_point;
235 std::vector<gfx::PointF> previous_segment_points; 399 std::vector<gfx::PointF> previous_segment_points;
236 float previous_radius; 400 float previous_radius;
237 int current_opacity; 401 int current_opacity;
238 402
239 for (int i = 0; i < num_points; ++i) { 403 for (int i = 0; i < num_points; ++i) {
240 current_point = laser_points_.laser_points()[i]; 404 current_point = laser_points_.laser_points()[i];
241 current_point.location -= widget_offset; 405 current_point.location -= widget_offset + update_rect.OffsetFromOrigin();
242 406
243 // Set the radius and opacity based on the distance. 407 // Set the radius and opacity based on the distance.
244 float current_radius = LinearInterpolate( 408 float current_radius = LinearInterpolate(
245 kPointInitialRadius, kPointFinalRadius, current_point.age); 409 kPointInitialRadius, kPointFinalRadius, current_point.age);
246 current_opacity = int{LinearInterpolate( 410 current_opacity = int{LinearInterpolate(
247 kPointInitialOpacity, kPointFinalOpacity, current_point.age)}; 411 kPointInitialOpacity, kPointFinalOpacity, current_point.age)};
248 412
249 // If we draw laser_points_ that are within a stroke width of each other, 413 // If we draw laser_points_ that are within a stroke width of each other,
250 // the result will be very jagged, unless we are on the last point, then we 414 // the result will be very jagged, unless we are on the last point, then
251 // draw regardless. 415 // we draw regardless.
252 float distance_threshold = current_radius * 2.0f; 416 float distance_threshold = current_radius * 2.0f;
253 if (DistanceBetweenPoints(previous_point.location, 417 if (DistanceBetweenPoints(previous_point.location,
254 current_point.location) <= distance_threshold && 418 current_point.location) <= distance_threshold &&
255 i != num_points - 1) { 419 i != num_points - 1) {
256 continue; 420 continue;
421 }
422
423 LaserSegment current_segment(
424 previous_segment_points, gfx::PointF(previous_point.location),
425 gfx::PointF(current_point.location), previous_radius, current_radius,
426 i == num_points - 1);
427
428 SkPath path = current_segment.path();
429 flags.setColor(SkColorSetA(kPointColor, current_opacity));
430 canvas.DrawPath(path, flags);
431
432 previous_segment_points = current_segment.path_points();
433 previous_radius = current_radius;
434 previous_point = current_point;
257 } 435 }
258 436
259 LaserSegment current_segment( 437 // Draw the last point as a circle.
260 previous_segment_points, gfx::PointF(previous_point.location),
261 gfx::PointF(current_point.location), previous_radius, current_radius,
262 i == num_points - 1);
263
264 SkPath path = current_segment.path();
265 flags.setColor(SkColorSetA(kPointColor, current_opacity)); 438 flags.setColor(SkColorSetA(kPointColor, current_opacity));
266 canvas->DrawPath(path, flags); 439 flags.setStyle(cc::PaintFlags::kFill_Style);
267 440 canvas.DrawCircle(current_point.location, kPointInitialRadius, flags);
268 previous_segment_points = current_segment.path_points(); 441 }
269 previous_radius = current_radius; 442
270 previous_point = current_point; 443 // Copy result to GPU memory buffer. This is effectiely a memcpy and unlike
271 } 444 // drawing to the buffer directly this ensures that the buffer is never in a
272 // Draw the last point as a circle. 445 // state that would result in flicker.
273 flags.setColor(SkColorSetA(kPointColor, current_opacity)); 446 {
274 flags.setStyle(cc::PaintFlags::kFill_Style); 447 TRACE_EVENT0("ui", "LaserPointerView::OnPointsUpdated::Copy");
275 canvas->DrawCircle(current_point.location, kPointInitialRadius, flags); 448
449 // Convert update rectangle to pixel coordinates.
450 gfx::Rect pixel_rect =
451 gfx::ScaleToEnclosingRect(update_rect, scale_factor_);
452 uint8_t* data = static_cast<uint8_t*>(gpu_memory_buffer_->memory(0));
453 int stride = gpu_memory_buffer_->stride(0);
454 canvas.sk_canvas()->readPixels(
455 SkImageInfo::MakeN32Premul(pixel_rect.width(), pixel_rect.height()),
456 data + pixel_rect.y() * stride + pixel_rect.x() * 4, stride, 0, 0);
457 }
458
459 // Update surface damage rectangle.
460 surface_damage_rect_.Union(update_rect);
461
462 needs_update_surface_ = true;
463
464 // Early out if waiting for last surface update to be drawn.
465 if (pending_draw_surface_)
466 return;
467
468 UpdateSurface();
276 } 469 }
470
471 void LaserPointerView::UpdateSurface() {
jbauman 2017/03/01 01:12:01 We'd normally want to trigger this from OnBeginFra
reveman 2017/03/01 18:57:15 That's another good follow up that I also consider
472 TRACE_EVENT1("ui", "LaserPointerView::UpdatedSurface", "damage",
473 surface_damage_rect_.ToString());
474
475 DCHECK(needs_update_surface_);
476 needs_update_surface_ = false;
477
478 std::unique_ptr<LaserResource> resource;
479 // Reuse returned resource if available.
480 if (!returned_resources_.empty()) {
481 resource = std::move(returned_resources_.front());
482 returned_resources_.pop_front();
483 }
484
485 // Create new resource if needed.
486 if (!resource)
487 resource = base::MakeUnique<LaserResource>();
488
489 // Acquire context provider for resource if needed.
490 if (!resource->context_provider) {
jbauman 2017/03/01 01:12:01 Check if ContextGL()->GetGraphicsResetStatusKHR()
reveman 2017/03/01 18:57:15 As I mentioned in the other comment. We don't worr
491 resource->context_provider = aura::Env::GetInstance()
492 ->context_factory()
493 ->SharedMainThreadContextProvider();
494 if (!resource->context_provider) {
495 LOG(ERROR) << "Failed to acquire a context provider";
496 return;
497 }
498 }
499
500 gpu::gles2::GLES2Interface* gles2 = resource->context_provider->ContextGL();
501
502 if (resource->texture) {
503 gles2->ActiveTexture(GL_TEXTURE0);
504 gles2->BindTexture(GL_TEXTURE_2D, resource->texture);
505 } else {
506 gles2->GenTextures(1, &resource->texture);
507 gles2->ActiveTexture(GL_TEXTURE0);
508 gles2->BindTexture(GL_TEXTURE_2D, resource->texture);
509 gles2->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
510 gles2->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
511 gles2->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
512 gles2->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
513 gles2->GenMailboxCHROMIUM(resource->mailbox.name);
514 gles2->ProduceTextureCHROMIUM(GL_TEXTURE_2D, resource->mailbox.name);
515 }
516
517 gfx::Size buffer_size = gpu_memory_buffer_->GetSize();
518
519 if (resource->image) {
520 gles2->ReleaseTexImage2DCHROMIUM(GL_TEXTURE_2D, resource->image);
521 } else {
522 resource->image = gles2->CreateImageCHROMIUM(
523 gpu_memory_buffer_->AsClientBuffer(), buffer_size.width(),
524 buffer_size.height(), SK_B32_SHIFT ? GL_RGBA : GL_BGRA_EXT);
525 if (!resource->image) {
526 LOG(ERROR) << "Failed to create image";
527 return;
528 }
529 }
530 gles2->BindTexImage2DCHROMIUM(GL_TEXTURE_2D, resource->image);
531
532 gpu::SyncToken sync_token;
533 uint64_t fence_sync = gles2->InsertFenceSyncCHROMIUM();
534 gles2->OrderingBarrierCHROMIUM();
535 gles2->GenUnverifiedSyncTokenCHROMIUM(fence_sync, sync_token.GetData());
536
537 cc::TransferableResource transferable_resource;
538 transferable_resource.id = next_resource_id_++;
539 transferable_resource.format = cc::RGBA_8888;
540 transferable_resource.filter = GL_LINEAR;
541 transferable_resource.size = buffer_size;
542 transferable_resource.mailbox_holder =
543 gpu::MailboxHolder(resource->mailbox, sync_token, GL_TEXTURE_2D);
544 transferable_resource.is_overlay_candidate = true;
545
546 gfx::Rect quad_rect(widget_->GetNativeView()->GetBoundsInScreen().size());
547
548 const int kRenderPassId = 1;
549 std::unique_ptr<cc::RenderPass> render_pass = cc::RenderPass::Create();
550 render_pass->SetNew(kRenderPassId, quad_rect, surface_damage_rect_,
551 gfx::Transform());
552 surface_damage_rect_ = gfx::Rect();
553
554 cc::SharedQuadState* quad_state =
555 render_pass->CreateAndAppendSharedQuadState();
556 quad_state->quad_layer_bounds = quad_rect.size();
557 quad_state->visible_quad_layer_rect = quad_rect;
558 quad_state->opacity = 1.0f;
559
560 cc::CompositorFrame frame;
561 cc::TextureDrawQuad* texture_quad =
562 render_pass->CreateAndAppendDrawQuad<cc::TextureDrawQuad>();
563 float vertex_opacity[4] = {1.0, 1.0, 1.0, 1.0};
564 gfx::PointF uv_top_left(0.f, 0.f);
565 gfx::PointF uv_bottom_right(1.f, 1.f);
566 texture_quad->SetNew(quad_state, quad_rect, gfx::Rect(), quad_rect,
567 transferable_resource.id, true, uv_top_left,
568 uv_bottom_right, SK_ColorTRANSPARENT, vertex_opacity,
569 false, false, false);
570 texture_quad->set_resource_size_in_pixels(transferable_resource.size);
571 frame.resource_list.push_back(transferable_resource);
572 frame.render_pass_list.push_back(std::move(render_pass));
573
574 // Set layer surface if this is the initial frame.
575 if (!local_surface_id_.is_valid()) {
576 local_surface_id_ = id_allocator_.GenerateId();
577 widget_->GetNativeView()->layer()->SetShowSurface(
578 cc::SurfaceInfo(cc::SurfaceId(frame_sink_id_, local_surface_id_), 1.0f,
579 quad_rect.size()),
580 aura::Env::GetInstance()
581 ->context_factory_private()
582 ->GetSurfaceManager()
583 ->reference_factory());
584 widget_->GetNativeView()->layer()->SetFillsBoundsOpaquely(false);
585 }
586
587 SubmitCompositorFrame(local_surface_id_, std::move(frame));
588
589 resources_[transferable_resource.id] = std::move(resource);
590
591 DCHECK(!pending_draw_surface_);
592 pending_draw_surface_ = true;
593 }
594
595 void LaserPointerView::OnDidDrawSurface() {
596 pending_draw_surface_ = false;
597 if (needs_update_surface_)
598 UpdateSurface();
599 }
600
277 } // namespace ash 601 } // namespace ash
OLDNEW
« no previous file with comments | « ash/laser/laser_pointer_view.h ('k') | mash/BUILD.gn » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698