OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "remoting/host/capturer.h" | 5 #include "remoting/host/capturer.h" |
6 | 6 |
7 #include <ApplicationServices/ApplicationServices.h> | 7 #include <ApplicationServices/ApplicationServices.h> |
8 #include <OpenGL/CGLMacro.h> | 8 #include <OpenGL/CGLMacro.h> |
9 #include <OpenGL/OpenGL.h> | 9 #include <OpenGL/OpenGL.h> |
10 | 10 |
(...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
370 // the invalid region from the previous capture in the current buffer. | 370 // the invalid region from the previous capture in the current buffer. |
371 // TODO(hclam): We can reduce the amount of copying here by subtracting | 371 // TODO(hclam): We can reduce the amount of copying here by subtracting |
372 // |capturer_helper_|s region from |last_invalid_region_|. | 372 // |capturer_helper_|s region from |last_invalid_region_|. |
373 // http://crbug.com/92354 | 373 // http://crbug.com/92354 |
374 | 374 |
375 // Since the image obtained from OpenGL is upside-down, need to do some | 375 // Since the image obtained from OpenGL is upside-down, need to do some |
376 // magic here to copy the correct rectangle. | 376 // magic here to copy the correct rectangle. |
377 const int y_offset = (buffer_height - 1) * buffer.bytes_per_row(); | 377 const int y_offset = (buffer_height - 1) * buffer.bytes_per_row(); |
378 for(SkRegion::Iterator i(last_invalid_region_); !i.done(); i.next()) { | 378 for(SkRegion::Iterator i(last_invalid_region_); !i.done(); i.next()) { |
379 SkIRect copy_rect = i.rect(); | 379 SkIRect copy_rect = i.rect(); |
380 copy_rect.intersect(clip_rect); | 380 if (copy_rect.intersect(clip_rect)) { |
381 CopyRect(last_buffer_ + y_offset, | 381 CopyRect(last_buffer_ + y_offset, |
382 -buffer.bytes_per_row(), | 382 -buffer.bytes_per_row(), |
383 buffer.ptr() + y_offset, | 383 buffer.ptr() + y_offset, |
384 -buffer.bytes_per_row(), | 384 -buffer.bytes_per_row(), |
385 4, // Bytes for pixel for RGBA. | 385 4, // Bytes for pixel for RGBA. |
386 copy_rect); | 386 copy_rect); |
| 387 } |
387 } | 388 } |
388 } | 389 } |
389 last_buffer_ = buffer.ptr(); | 390 last_buffer_ = buffer.ptr(); |
390 last_invalid_region_ = region; | 391 last_invalid_region_ = region; |
391 | 392 |
392 CGLContextObj CGL_MACRO_CONTEXT = cgl_context_; | 393 CGLContextObj CGL_MACRO_CONTEXT = cgl_context_; |
393 glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pixel_buffer_object_.get()); | 394 glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pixel_buffer_object_.get()); |
394 glReadPixels(0, 0, buffer_width, buffer_height, GL_BGRA, GL_UNSIGNED_BYTE, 0); | 395 glReadPixels(0, 0, buffer_width, buffer_height, GL_BGRA, GL_UNSIGNED_BYTE, 0); |
395 GLubyte* ptr = static_cast<GLubyte*>( | 396 GLubyte* ptr = static_cast<GLubyte*>( |
396 glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB)); | 397 glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB)); |
397 if (ptr == NULL) { | 398 if (ptr == NULL) { |
398 // If the buffer can't be mapped, assume that it's no longer valid and | 399 // If the buffer can't be mapped, assume that it's no longer valid and |
399 // release it. | 400 // release it. |
400 pixel_buffer_object_.Release(); | 401 pixel_buffer_object_.Release(); |
401 } else { | 402 } else { |
402 // Copy only from the dirty rects. Since the image obtained from OpenGL is | 403 // Copy only from the dirty rects. Since the image obtained from OpenGL is |
403 // upside-down we need to do some magic here to copy the correct rectangle. | 404 // upside-down we need to do some magic here to copy the correct rectangle. |
404 const int y_offset = (buffer_height - 1) * buffer.bytes_per_row(); | 405 const int y_offset = (buffer_height - 1) * buffer.bytes_per_row(); |
405 for(SkRegion::Iterator i(region); !i.done(); i.next()) { | 406 for(SkRegion::Iterator i(region); !i.done(); i.next()) { |
406 SkIRect copy_rect = i.rect(); | 407 SkIRect copy_rect = i.rect(); |
407 copy_rect.intersect(clip_rect); | 408 if (copy_rect.intersect(clip_rect)) { |
408 CopyRect(ptr + y_offset, | 409 CopyRect(ptr + y_offset, |
409 -buffer.bytes_per_row(), | 410 -buffer.bytes_per_row(), |
410 buffer.ptr() + y_offset, | 411 buffer.ptr() + y_offset, |
411 -buffer.bytes_per_row(), | 412 -buffer.bytes_per_row(), |
412 4, // Bytes for pixel for RGBA. | 413 4, // Bytes for pixel for RGBA. |
413 copy_rect); | 414 copy_rect); |
| 415 } |
414 } | 416 } |
415 } | 417 } |
416 if (!glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB)) { | 418 if (!glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB)) { |
417 // If glUnmapBuffer returns false, then the contents of the data store are | 419 // If glUnmapBuffer returns false, then the contents of the data store are |
418 // undefined. This might be because the screen mode has changed, in which | 420 // undefined. This might be because the screen mode has changed, in which |
419 // case it will be recreated in ScreenConfigurationChanged, but releasing | 421 // case it will be recreated in ScreenConfigurationChanged, but releasing |
420 // the object here is the best option. Capturing will fall back on | 422 // the object here is the best option. Capturing will fall back on |
421 // GlBlitSlow until such time as the pixel buffer object is recreated. | 423 // GlBlitSlow until such time as the pixel buffer object is recreated. |
422 pixel_buffer_object_.Release(); | 424 pixel_buffer_object_.Release(); |
423 } | 425 } |
(...skipping 29 matching lines...) Expand all Loading... |
453 CGDirectDisplayID main_display = CGMainDisplayID(); | 455 CGDirectDisplayID main_display = CGMainDisplayID(); |
454 uint8* display_base_address = | 456 uint8* display_base_address = |
455 reinterpret_cast<uint8*>(CGDisplayBaseAddress(main_display)); | 457 reinterpret_cast<uint8*>(CGDisplayBaseAddress(main_display)); |
456 int src_bytes_per_row = CGDisplayBytesPerRow(main_display); | 458 int src_bytes_per_row = CGDisplayBytesPerRow(main_display); |
457 int src_bytes_per_pixel = CGDisplayBitsPerPixel(main_display) / 8; | 459 int src_bytes_per_pixel = CGDisplayBitsPerPixel(main_display) / 8; |
458 // TODO(hclam): We can reduce the amount of copying here by subtracting | 460 // TODO(hclam): We can reduce the amount of copying here by subtracting |
459 // |capturer_helper_|s region from |last_invalid_region_|. | 461 // |capturer_helper_|s region from |last_invalid_region_|. |
460 // http://crbug.com/92354 | 462 // http://crbug.com/92354 |
461 for(SkRegion::Iterator i(region); !i.done(); i.next()) { | 463 for(SkRegion::Iterator i(region); !i.done(); i.next()) { |
462 SkIRect copy_rect = i.rect(); | 464 SkIRect copy_rect = i.rect(); |
463 copy_rect.intersect(clip_rect); | 465 if (copy_rect.intersect(clip_rect)) { |
464 CopyRect(display_base_address, | 466 CopyRect(display_base_address, |
465 src_bytes_per_row, | 467 src_bytes_per_row, |
466 buffer.ptr(), | 468 buffer.ptr(), |
467 buffer.bytes_per_row(), | 469 buffer.bytes_per_row(), |
468 src_bytes_per_pixel, | 470 src_bytes_per_pixel, |
469 copy_rect); | 471 copy_rect); |
| 472 } |
470 } | 473 } |
471 } | 474 } |
472 | 475 |
473 const gfx::Size& CapturerMac::size_most_recent() const { | 476 const gfx::Size& CapturerMac::size_most_recent() const { |
474 return helper_.size_most_recent(); | 477 return helper_.size_most_recent(); |
475 } | 478 } |
476 | 479 |
477 void CapturerMac::ScreenRefresh(CGRectCount count, const CGRect *rect_array) { | 480 void CapturerMac::ScreenRefresh(CGRectCount count, const CGRect *rect_array) { |
478 SkIRect skirect_array[count]; | 481 SkIRect skirect_array[count]; |
479 for (CGRectCount i = 0; i < count; ++i) { | 482 for (CGRectCount i = 0; i < count; ++i) { |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
545 Capturer* Capturer::Create() { | 548 Capturer* Capturer::Create() { |
546 CapturerMac* capturer = new CapturerMac(); | 549 CapturerMac* capturer = new CapturerMac(); |
547 if (!capturer->Init()) { | 550 if (!capturer->Init()) { |
548 delete capturer; | 551 delete capturer; |
549 capturer = NULL; | 552 capturer = NULL; |
550 } | 553 } |
551 return capturer; | 554 return capturer; |
552 } | 555 } |
553 | 556 |
554 } // namespace remoting | 557 } // namespace remoting |
OLD | NEW |