| OLD | NEW |
| 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 Loading... |
| 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::ReclaimResources( |
| 201 // The bounding box should be relative to the screen. | 265 const cc::ReturnedResourceArray& resources) { |
| 202 gfx::Point screen_offset = | 266 DCHECK_EQ(resources.size(), 1u); |
| 203 widget_->GetNativeView()->GetRootWindow()->GetBoundsInScreen().origin(); | |
| 204 | 267 |
| 205 // Expand the bounding box so that it includes the radius of the points on the | 268 auto it = resources_.find(resources.front().id); |
| 206 // edges. | 269 DCHECK(it != resources_.end()); |
| 207 gfx::Rect bounding_box; | 270 std::unique_ptr<LaserResource> resource = std::move(it->second); |
| 208 bounding_box = laser_points_.GetBoundingBox(); | 271 resources_.erase(it); |
| 209 bounding_box.Offset(-kPointInitialRadius, -kPointInitialRadius); | 272 |
| 210 bounding_box.Offset(screen_offset.x(), screen_offset.y()); | 273 gpu::gles2::GLES2Interface* gles2 = resource->context_provider->ContextGL(); |
| 211 bounding_box.set_width(bounding_box.width() + (kPointInitialRadius * 2)); | 274 if (resources.front().sync_token.HasData()) |
| 212 bounding_box.set_height(bounding_box.height() + (kPointInitialRadius * 2)); | 275 gles2->WaitSyncTokenCHROMIUM(resources.front().sync_token.GetConstData()); |
| 213 widget_->SetBounds(bounding_box); | 276 |
| 214 SchedulePaint(); | 277 if (!resources.front().lost) |
| 278 returned_resources_.push_back(std::move(resource)); |
| 215 } | 279 } |
| 216 | 280 |
| 217 void LaserPointerView::OnPaint(gfx::Canvas* canvas) { | 281 void LaserPointerView::WillDrawSurface( |
| 218 if (laser_points_.IsEmpty()) | 282 const cc::LocalSurfaceId& local_surface_id, |
| 283 const gfx::Rect& damage_rect) { |
| 284 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 285 FROM_HERE, base::Bind(&LaserPointerView::OnDidDrawSurface, |
| 286 weak_ptr_factory_.GetWeakPtr())); |
| 287 ; |
| 288 } |
| 289 |
| 290 gfx::Rect LaserPointerView::GetBoundingBox() { |
| 291 // Expand the bounding box so that it includes the radius of the points on the |
| 292 // edges and antialiasing. |
| 293 gfx::Rect bounding_box = laser_points_.GetBoundingBox(); |
| 294 const int kOutsetForAntialiasing = 1; |
| 295 int outset = kPointInitialRadius + kOutsetForAntialiasing; |
| 296 bounding_box.Inset(-outset, -outset); |
| 297 return bounding_box; |
| 298 } |
| 299 |
| 300 void LaserPointerView::OnPointsUpdated() { |
| 301 if (pending_update_buffer_) |
| 219 return; | 302 return; |
| 220 | 303 |
| 304 pending_update_buffer_ = true; |
| 305 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 306 FROM_HERE, base::Bind(&LaserPointerView::UpdateBuffer, |
| 307 weak_ptr_factory_.GetWeakPtr())); |
| 308 } |
| 309 |
| 310 void LaserPointerView::UpdateBuffer() { |
| 311 TRACE_EVENT2("ui", "LaserPointerView::UpdatedBuffer", "damage", |
| 312 buffer_damage_rect_.ToString(), "points", |
| 313 laser_points_.GetNumberOfPoints()); |
| 314 |
| 315 DCHECK(pending_update_buffer_); |
| 316 pending_update_buffer_ = false; |
| 317 |
| 318 gfx::Rect screen_bounds = widget_->GetNativeView()->GetBoundsInScreen(); |
| 319 gfx::Rect update_rect = buffer_damage_rect_; |
| 320 buffer_damage_rect_ = gfx::Rect(); |
| 321 |
| 322 // Create and map a single GPU memory buffer. The laser pointer will be |
| 323 // written into this buffer without any buffering. The result is that we |
| 324 // might be modifying the buffer while it's being displayed. This provides |
| 325 // minimal latency but potential tearing. Note that we have to draw into |
| 326 // a temporary surface and copy it into GPU memory buffer to avoid flicker. |
| 327 if (!gpu_memory_buffer_) { |
| 328 gpu_memory_buffer_ = |
| 329 aura::Env::GetInstance() |
| 330 ->context_factory() |
| 331 ->GetGpuMemoryBufferManager() |
| 332 ->CreateGpuMemoryBuffer( |
| 333 gfx::ScaleToCeiledSize(screen_bounds.size(), scale_factor_), |
| 334 SK_B32_SHIFT ? gfx::BufferFormat::RGBA_8888 |
| 335 : gfx::BufferFormat::BGRA_8888, |
| 336 gfx::BufferUsage::SCANOUT_CPU_READ_WRITE, |
| 337 gpu::kNullSurfaceHandle); |
| 338 if (!gpu_memory_buffer_) { |
| 339 LOG(ERROR) << "Failed to allocate GPU memory buffer"; |
| 340 return; |
| 341 } |
| 342 |
| 343 // Map buffer and keep it mapped until destroyed. |
| 344 bool rv = gpu_memory_buffer_->Map(); |
| 345 if (!rv) { |
| 346 LOG(ERROR) << "Failed to map GPU memory buffer"; |
| 347 return; |
| 348 } |
| 349 |
| 350 // Make sure the first update rectangle covers the whole buffer. |
| 351 update_rect = gfx::Rect(screen_bounds.size()); |
| 352 } |
| 353 |
| 354 // Constrain update rectangle to buffer size and early out if empty. |
| 355 update_rect.Intersect(gfx::Rect(screen_bounds.size())); |
| 356 if (update_rect.IsEmpty()) |
| 357 return; |
| 358 |
| 359 // Create a temporary canvas for update rectangle. |
| 360 gfx::Canvas canvas(update_rect.size(), scale_factor_, false); |
| 361 |
| 221 cc::PaintFlags flags; | 362 cc::PaintFlags flags; |
| 222 flags.setStyle(cc::PaintFlags::kFill_Style); | 363 flags.setStyle(cc::PaintFlags::kFill_Style); |
| 223 flags.setAntiAlias(true); | 364 flags.setAntiAlias(true); |
| 224 | 365 |
| 225 // Compute the offset of the current widget. | 366 // Compute the offset of the current widget. |
| 226 gfx::Vector2d widget_offset( | 367 gfx::Vector2d widget_offset( |
| 227 widget_->GetNativeView()->GetBoundsInRootWindow().origin().x(), | 368 widget_->GetNativeView()->GetBoundsInRootWindow().origin().x(), |
| 228 widget_->GetNativeView()->GetBoundsInRootWindow().origin().y()); | 369 widget_->GetNativeView()->GetBoundsInRootWindow().origin().y()); |
| 229 | 370 |
| 230 int num_points = laser_points_.GetNumberOfPoints(); | 371 int num_points = laser_points_.GetNumberOfPoints(); |
| 231 DCHECK(num_points > 0); | 372 if (num_points) { |
| 232 LaserPointerPoints::LaserPoint previous_point = laser_points_.GetOldest(); | 373 LaserPointerPoints::LaserPoint previous_point = laser_points_.GetOldest(); |
| 233 previous_point.location -= widget_offset; | 374 previous_point.location -= widget_offset + update_rect.OffsetFromOrigin(); |
| 234 LaserPointerPoints::LaserPoint current_point; | 375 LaserPointerPoints::LaserPoint current_point; |
| 235 std::vector<gfx::PointF> previous_segment_points; | 376 std::vector<gfx::PointF> previous_segment_points; |
| 236 float previous_radius; | 377 float previous_radius; |
| 237 int current_opacity; | 378 int current_opacity; |
| 238 | 379 |
| 239 for (int i = 0; i < num_points; ++i) { | 380 for (int i = 0; i < num_points; ++i) { |
| 240 current_point = laser_points_.laser_points()[i]; | 381 current_point = laser_points_.laser_points()[i]; |
| 241 current_point.location -= widget_offset; | 382 current_point.location -= widget_offset + update_rect.OffsetFromOrigin(); |
| 242 | 383 |
| 243 // Set the radius and opacity based on the distance. | 384 // Set the radius and opacity based on the distance. |
| 244 float current_radius = LinearInterpolate( | 385 float current_radius = LinearInterpolate( |
| 245 kPointInitialRadius, kPointFinalRadius, current_point.age); | 386 kPointInitialRadius, kPointFinalRadius, current_point.age); |
| 246 current_opacity = int{LinearInterpolate( | 387 current_opacity = int{LinearInterpolate( |
| 247 kPointInitialOpacity, kPointFinalOpacity, current_point.age)}; | 388 kPointInitialOpacity, kPointFinalOpacity, current_point.age)}; |
| 248 | 389 |
| 249 // If we draw laser_points_ that are within a stroke width of each other, | 390 // 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 | 391 // the result will be very jagged, unless we are on the last point, then |
| 251 // draw regardless. | 392 // we draw regardless. |
| 252 float distance_threshold = current_radius * 2.0f; | 393 float distance_threshold = current_radius * 2.0f; |
| 253 if (DistanceBetweenPoints(previous_point.location, | 394 if (DistanceBetweenPoints(previous_point.location, |
| 254 current_point.location) <= distance_threshold && | 395 current_point.location) <= distance_threshold && |
| 255 i != num_points - 1) { | 396 i != num_points - 1) { |
| 256 continue; | 397 continue; |
| 398 } |
| 399 |
| 400 LaserSegment current_segment( |
| 401 previous_segment_points, gfx::PointF(previous_point.location), |
| 402 gfx::PointF(current_point.location), previous_radius, current_radius, |
| 403 i == num_points - 1); |
| 404 |
| 405 SkPath path = current_segment.path(); |
| 406 flags.setColor(SkColorSetA(kPointColor, current_opacity)); |
| 407 canvas.DrawPath(path, flags); |
| 408 |
| 409 previous_segment_points = current_segment.path_points(); |
| 410 previous_radius = current_radius; |
| 411 previous_point = current_point; |
| 257 } | 412 } |
| 258 | 413 |
| 259 LaserSegment current_segment( | 414 // 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)); | 415 flags.setColor(SkColorSetA(kPointColor, current_opacity)); |
| 266 canvas->DrawPath(path, flags); | 416 flags.setStyle(cc::PaintFlags::kFill_Style); |
| 267 | 417 canvas.DrawCircle(current_point.location, kPointInitialRadius, flags); |
| 268 previous_segment_points = current_segment.path_points(); | 418 } |
| 269 previous_radius = current_radius; | 419 |
| 270 previous_point = current_point; | 420 // Copy result to GPU memory buffer. This is effectiely a memcpy and unlike |
| 271 } | 421 // drawing to the buffer directly this ensures that the buffer is never in a |
| 272 // Draw the last point as a circle. | 422 // state that would result in flicker. |
| 273 flags.setColor(SkColorSetA(kPointColor, current_opacity)); | 423 { |
| 274 flags.setStyle(cc::PaintFlags::kFill_Style); | 424 TRACE_EVENT0("ui", "LaserPointerView::OnPointsUpdated::Copy"); |
| 275 canvas->DrawCircle(current_point.location, kPointInitialRadius, flags); | 425 |
| 426 // Convert update rectangle to pixel coordinates. |
| 427 gfx::Rect pixel_rect = |
| 428 gfx::ScaleToEnclosingRect(update_rect, scale_factor_); |
| 429 uint8_t* data = static_cast<uint8_t*>(gpu_memory_buffer_->memory(0)); |
| 430 int stride = gpu_memory_buffer_->stride(0); |
| 431 canvas.sk_canvas()->readPixels( |
| 432 SkImageInfo::MakeN32Premul(pixel_rect.width(), pixel_rect.height()), |
| 433 data + pixel_rect.y() * stride + pixel_rect.x() * 4, stride, 0, 0); |
| 434 } |
| 435 |
| 436 // Update surface damage rectangle. |
| 437 surface_damage_rect_.Union(update_rect); |
| 438 |
| 439 needs_update_surface_ = true; |
| 440 |
| 441 // Early out if waiting for last surface update to be drawn. |
| 442 if (pending_draw_surface_) |
| 443 return; |
| 444 |
| 445 UpdateSurface(); |
| 276 } | 446 } |
| 447 |
| 448 void LaserPointerView::UpdateSurface() { |
| 449 TRACE_EVENT1("ui", "LaserPointerView::UpdatedSurface", "damage", |
| 450 surface_damage_rect_.ToString()); |
| 451 |
| 452 DCHECK(needs_update_surface_); |
| 453 needs_update_surface_ = false; |
| 454 |
| 455 std::unique_ptr<LaserResource> resource; |
| 456 // Reuse returned resource if available. |
| 457 if (!returned_resources_.empty()) { |
| 458 resource = std::move(returned_resources_.front()); |
| 459 returned_resources_.pop_front(); |
| 460 } |
| 461 |
| 462 // Create new resource if needed. |
| 463 if (!resource) |
| 464 resource = base::MakeUnique<LaserResource>(); |
| 465 |
| 466 // Acquire context provider for resource if needed. |
| 467 if (!resource->context_provider) { |
| 468 resource->context_provider = aura::Env::GetInstance() |
| 469 ->context_factory() |
| 470 ->SharedMainThreadContextProvider(); |
| 471 if (!resource->context_provider) { |
| 472 LOG(ERROR) << "Failed to acquire a context provider"; |
| 473 return; |
| 474 } |
| 475 } |
| 476 |
| 477 gpu::gles2::GLES2Interface* gles2 = resource->context_provider->ContextGL(); |
| 478 |
| 479 if (resource->texture) { |
| 480 gles2->ActiveTexture(GL_TEXTURE0); |
| 481 gles2->BindTexture(GL_TEXTURE_2D, resource->texture); |
| 482 } else { |
| 483 gles2->GenTextures(1, &resource->texture); |
| 484 gles2->ActiveTexture(GL_TEXTURE0); |
| 485 gles2->BindTexture(GL_TEXTURE_2D, resource->texture); |
| 486 gles2->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| 487 gles2->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
| 488 gles2->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| 489 gles2->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| 490 gles2->GenMailboxCHROMIUM(resource->mailbox.name); |
| 491 gles2->ProduceTextureCHROMIUM(GL_TEXTURE_2D, resource->mailbox.name); |
| 492 } |
| 493 |
| 494 gfx::Size buffer_size = gpu_memory_buffer_->GetSize(); |
| 495 |
| 496 if (resource->image) { |
| 497 gles2->ReleaseTexImage2DCHROMIUM(GL_TEXTURE_2D, resource->image); |
| 498 } else { |
| 499 resource->image = gles2->CreateImageCHROMIUM( |
| 500 gpu_memory_buffer_->AsClientBuffer(), buffer_size.width(), |
| 501 buffer_size.height(), SK_B32_SHIFT ? GL_RGBA : GL_BGRA_EXT); |
| 502 if (!resource->image) { |
| 503 LOG(ERROR) << "Failed to create image"; |
| 504 return; |
| 505 } |
| 506 } |
| 507 gles2->BindTexImage2DCHROMIUM(GL_TEXTURE_2D, resource->image); |
| 508 |
| 509 gpu::SyncToken sync_token; |
| 510 uint64_t fence_sync = gles2->InsertFenceSyncCHROMIUM(); |
| 511 gles2->OrderingBarrierCHROMIUM(); |
| 512 gles2->GenUnverifiedSyncTokenCHROMIUM(fence_sync, sync_token.GetData()); |
| 513 |
| 514 cc::TransferableResource transferable_resource; |
| 515 transferable_resource.id = next_resource_id_++; |
| 516 transferable_resource.format = cc::RGBA_8888; |
| 517 transferable_resource.filter = GL_LINEAR; |
| 518 transferable_resource.size = buffer_size; |
| 519 transferable_resource.mailbox_holder = |
| 520 gpu::MailboxHolder(resource->mailbox, sync_token, GL_TEXTURE_2D); |
| 521 transferable_resource.is_overlay_candidate = true; |
| 522 |
| 523 gfx::Rect quad_rect(widget_->GetNativeView()->GetBoundsInScreen().size()); |
| 524 |
| 525 const int kRenderPassId = 1; |
| 526 std::unique_ptr<cc::RenderPass> render_pass = cc::RenderPass::Create(); |
| 527 render_pass->SetNew(kRenderPassId, quad_rect, surface_damage_rect_, |
| 528 gfx::Transform()); |
| 529 surface_damage_rect_ = gfx::Rect(); |
| 530 |
| 531 cc::SharedQuadState* quad_state = |
| 532 render_pass->CreateAndAppendSharedQuadState(); |
| 533 quad_state->quad_layer_bounds = quad_rect.size(); |
| 534 quad_state->visible_quad_layer_rect = quad_rect; |
| 535 quad_state->opacity = 1.0f; |
| 536 |
| 537 cc::CompositorFrame frame; |
| 538 cc::TextureDrawQuad* texture_quad = |
| 539 render_pass->CreateAndAppendDrawQuad<cc::TextureDrawQuad>(); |
| 540 float vertex_opacity[4] = {1.0, 1.0, 1.0, 1.0}; |
| 541 gfx::PointF uv_top_left(0.f, 0.f); |
| 542 gfx::PointF uv_bottom_right(1.f, 1.f); |
| 543 texture_quad->SetNew(quad_state, quad_rect, gfx::Rect(), quad_rect, |
| 544 transferable_resource.id, true, uv_top_left, |
| 545 uv_bottom_right, SK_ColorTRANSPARENT, vertex_opacity, |
| 546 false, false, false); |
| 547 texture_quad->set_resource_size_in_pixels(transferable_resource.size); |
| 548 frame.resource_list.push_back(transferable_resource); |
| 549 frame.render_pass_list.push_back(std::move(render_pass)); |
| 550 |
| 551 // Set layer surface if this is the initial frame. |
| 552 if (!local_surface_id_.is_valid()) { |
| 553 local_surface_id_ = id_allocator_.GenerateId(); |
| 554 widget_->GetNativeView()->layer()->SetShowSurface( |
| 555 cc::SurfaceInfo(cc::SurfaceId(frame_sink_id_, local_surface_id_), 1.0f, |
| 556 quad_rect.size()), |
| 557 aura::Env::GetInstance() |
| 558 ->context_factory_private() |
| 559 ->GetSurfaceManager() |
| 560 ->reference_factory()); |
| 561 widget_->GetNativeView()->layer()->SetFillsBoundsOpaquely(false); |
| 562 } |
| 563 |
| 564 frame_sink_support_.SubmitCompositorFrame(local_surface_id_, |
| 565 std::move(frame)); |
| 566 |
| 567 resources_[transferable_resource.id] = std::move(resource); |
| 568 |
| 569 DCHECK(!pending_draw_surface_); |
| 570 pending_draw_surface_ = true; |
| 571 } |
| 572 |
| 573 void LaserPointerView::OnDidDrawSurface() { |
| 574 pending_draw_surface_ = false; |
| 575 if (needs_update_surface_) |
| 576 UpdateSurface(); |
| 577 } |
| 578 |
| 277 } // namespace ash | 579 } // namespace ash |
| OLD | NEW |