| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "content/browser/renderer_host/compositing_iosurface_mac.h" | 5 #include "content/browser/renderer_host/compositing_iosurface_mac.h" |
| 6 | 6 |
| 7 #include <OpenGL/CGLRenderers.h> | 7 #include <OpenGL/CGLRenderers.h> |
| 8 #include <OpenGL/OpenGL.h> | 8 #include <OpenGL/OpenGL.h> |
| 9 #include <vector> | |
| 10 | 9 |
| 11 #include "base/bind.h" | 10 #include "base/bind.h" |
| 12 #include "base/bind_helpers.h" | 11 #include "base/bind_helpers.h" |
| 13 #include "base/command_line.h" | 12 #include "base/command_line.h" |
| 14 #include "base/debug/trace_event.h" | 13 #include "base/debug/trace_event.h" |
| 15 #include "base/logging.h" | 14 #include "base/logging.h" |
| 16 #include "base/mac/mac_util.h" | 15 #include "base/mac/mac_util.h" |
| 17 #include "base/message_loop.h" | 16 #include "base/message_loop.h" |
| 18 #include "base/threading/platform_thread.h" | 17 #include "base/threading/platform_thread.h" |
| 19 #include "content/browser/renderer_host/compositing_iosurface_context_mac.h" | 18 #include "content/browser/renderer_host/compositing_iosurface_context_mac.h" |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 156 const CVTimeStamp* output_time, | 155 const CVTimeStamp* output_time, |
| 157 CVOptionFlags flags_in, | 156 CVOptionFlags flags_in, |
| 158 CVOptionFlags* flags_out, | 157 CVOptionFlags* flags_out, |
| 159 void* context) { | 158 void* context) { |
| 160 CompositingIOSurfaceMac* surface = | 159 CompositingIOSurfaceMac* surface = |
| 161 static_cast<CompositingIOSurfaceMac*>(context); | 160 static_cast<CompositingIOSurfaceMac*>(context); |
| 162 surface->DisplayLinkTick(display_link, output_time); | 161 surface->DisplayLinkTick(display_link, output_time); |
| 163 return kCVReturnSuccess; | 162 return kCVReturnSuccess; |
| 164 } | 163 } |
| 165 | 164 |
| 166 CompositingIOSurfaceMac::CopyContext::CopyContext() | 165 CompositingIOSurfaceMac::CopyContext::CopyContext( |
| 167 : num_outputs(0), | 166 const scoped_refptr<CompositingIOSurfaceContext>& context) |
| 167 : transformer(new CompositingIOSurfaceTransformer( |
| 168 GL_TEXTURE_RECTANGLE_ARB, true, context->shader_program_cache())), |
| 169 num_outputs(0), |
| 168 fence(0), | 170 fence(0), |
| 169 cycles_elapsed(0) { | 171 cycles_elapsed(0) { |
| 170 memset(output_textures, 0, sizeof(output_textures)); | 172 memset(output_textures, 0, sizeof(output_textures)); |
| 171 memset(frame_buffers, 0, sizeof(frame_buffers)); | 173 memset(frame_buffers, 0, sizeof(frame_buffers)); |
| 172 memset(pixel_buffers, 0, sizeof(pixel_buffers)); | 174 memset(pixel_buffers, 0, sizeof(pixel_buffers)); |
| 173 } | 175 } |
| 174 | 176 |
| 175 CompositingIOSurfaceMac::CopyContext::~CopyContext() { | 177 CompositingIOSurfaceMac::CopyContext::~CopyContext() { |
| 178 DCHECK_EQ(frame_buffers[0], 0u) << "Failed to call ReleaseCachedGLObjects()."; |
| 176 } | 179 } |
| 177 | 180 |
| 178 void CompositingIOSurfaceMac::CopyContext::CleanUp() { | 181 void CompositingIOSurfaceMac::CopyContext::ReleaseCachedGLObjects() { |
| 179 glDeleteFramebuffersEXT(num_outputs, frame_buffers); CHECK_GL_ERROR(); | 182 // No outstanding callbacks should be pending. |
| 180 glDeleteTextures(num_outputs, output_textures); | 183 DCHECK(map_buffer_callback.is_null()); |
| 181 CHECK_GL_ERROR(); | 184 DCHECK(done_callback.is_null()); |
| 182 | 185 |
| 183 // For an asynchronous read-back, there are more objects to delete: | 186 // For an asynchronous read-back, there are more objects to delete: |
| 184 if (fence) { | 187 if (fence) { |
| 185 glDeleteBuffers(num_outputs, pixel_buffers); | 188 glDeleteBuffers(arraysize(pixel_buffers), pixel_buffers); CHECK_GL_ERROR(); |
| 186 CHECK_GL_ERROR(); | 189 memset(pixel_buffers, 0, sizeof(pixel_buffers)); |
| 187 glDeleteFencesAPPLE(1, &fence); CHECK_GL_ERROR(); | 190 glDeleteFencesAPPLE(1, &fence); CHECK_GL_ERROR(); |
| 191 fence = 0; |
| 192 } |
| 193 |
| 194 glDeleteFramebuffersEXT(arraysize(frame_buffers), frame_buffers); |
| 195 CHECK_GL_ERROR(); |
| 196 memset(frame_buffers, 0, sizeof(frame_buffers)); |
| 197 |
| 198 // Note: |output_textures| are owned by the transformer. |
| 199 if (transformer) |
| 200 transformer->ReleaseCachedGLObjects(); |
| 201 } |
| 202 |
| 203 void CompositingIOSurfaceMac::CopyContext::PrepareReadbackFramebuffers() { |
| 204 for (int i = 0; i < num_outputs; ++i) { |
| 205 if (!frame_buffers[i]) { |
| 206 glGenFramebuffersEXT(1, &frame_buffers[i]); CHECK_GL_ERROR(); |
| 207 } |
| 188 } | 208 } |
| 189 } | 209 } |
| 190 | 210 |
| 211 void CompositingIOSurfaceMac::CopyContext::PrepareForAsynchronousReadback() { |
| 212 PrepareReadbackFramebuffers(); |
| 213 if (!fence) { |
| 214 glGenFencesAPPLE(1, &fence); CHECK_GL_ERROR(); |
| 215 } |
| 216 for (int i = 0; i < num_outputs; ++i) { |
| 217 if (!pixel_buffers[i]) { |
| 218 glGenBuffersARB(1, &pixel_buffers[i]); CHECK_GL_ERROR(); |
| 219 } |
| 220 } |
| 221 } |
| 222 |
| 223 |
| 191 // static | 224 // static |
| 192 CompositingIOSurfaceMac* CompositingIOSurfaceMac::Create( | 225 CompositingIOSurfaceMac* CompositingIOSurfaceMac::Create( |
| 193 int window_number, | 226 int window_number, |
| 194 SurfaceOrder surface_order) { | 227 SurfaceOrder surface_order) { |
| 195 TRACE_EVENT0("browser", "CompositingIOSurfaceMac::Create"); | 228 TRACE_EVENT0("browser", "CompositingIOSurfaceMac::Create"); |
| 196 IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize(); | 229 IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize(); |
| 197 if (!io_surface_support) { | 230 if (!io_surface_support) { |
| 198 LOG(WARNING) << "No IOSurface support"; | 231 LOG(WARNING) << "No IOSurface support"; |
| 199 return NULL; | 232 return NULL; |
| 200 } | 233 } |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 257 | 290 |
| 258 // Stop display link for now, it will be started when needed during Draw. | 291 // Stop display link for now, it will be started when needed during Draw. |
| 259 StopDisplayLink(); | 292 StopDisplayLink(); |
| 260 } | 293 } |
| 261 | 294 |
| 262 void CompositingIOSurfaceMac::SwitchToContextOnNewWindow(int window_number) { | 295 void CompositingIOSurfaceMac::SwitchToContextOnNewWindow(int window_number) { |
| 263 if (window_number == context_->window_number()) | 296 if (window_number == context_->window_number()) |
| 264 return; | 297 return; |
| 265 | 298 |
| 266 // Asynchronous copies must complete in the same context they started in, | 299 // Asynchronous copies must complete in the same context they started in, |
| 267 // defer updating the GL context to the new window until the copy finishes. | 300 // defer updating the GL context to the new window until the copy finishes and |
| 301 // all outstanding CopyContexts are destroyed. |
| 268 if (!copy_requests_.empty()) | 302 if (!copy_requests_.empty()) |
| 269 return; | 303 return; |
| 304 if (!copy_context_pool_.empty()) { |
| 305 CGLSetCurrentContext(context_->cgl_context()); |
| 306 DestroyAllCopyContextsWithinContext(); |
| 307 CGLSetCurrentContext(0); |
| 308 } |
| 270 | 309 |
| 271 scoped_refptr<CompositingIOSurfaceContext> new_context = | 310 scoped_refptr<CompositingIOSurfaceContext> new_context = |
| 272 CompositingIOSurfaceContext::Get(window_number, | 311 CompositingIOSurfaceContext::Get(window_number, |
| 273 context_->surface_order()); | 312 context_->surface_order()); |
| 274 if (!new_context) | 313 if (!new_context) |
| 275 return; | 314 return; |
| 276 | 315 |
| 277 transformer_.reset(nil); | |
| 278 context_ = new_context; | 316 context_ = new_context; |
| 279 } | 317 } |
| 280 | 318 |
| 281 bool CompositingIOSurfaceMac::is_vsync_disabled() const { | 319 bool CompositingIOSurfaceMac::is_vsync_disabled() const { |
| 282 return context_->is_vsync_disabled(); | 320 return context_->is_vsync_disabled(); |
| 283 } | 321 } |
| 284 | 322 |
| 285 void CompositingIOSurfaceMac::GetVSyncParameters(base::TimeTicks* timebase, | 323 void CompositingIOSurfaceMac::GetVSyncParameters(base::TimeTicks* timebase, |
| 286 uint32* interval_numerator, | 324 uint32* interval_numerator, |
| 287 uint32* interval_denominator) { | 325 uint32* interval_denominator) { |
| 288 base::AutoLock lock(lock_); | 326 base::AutoLock lock(lock_); |
| 289 *timebase = vsync_timebase_; | 327 *timebase = vsync_timebase_; |
| 290 *interval_numerator = vsync_interval_numerator_; | 328 *interval_numerator = vsync_interval_numerator_; |
| 291 *interval_denominator = vsync_interval_denominator_; | 329 *interval_denominator = vsync_interval_denominator_; |
| 292 } | 330 } |
| 293 | 331 |
| 294 CompositingIOSurfaceMac::~CompositingIOSurfaceMac() { | 332 CompositingIOSurfaceMac::~CompositingIOSurfaceMac() { |
| 295 FailAllCopies(); | 333 FailAllCopies(); |
| 296 CVDisplayLinkRelease(display_link_); | 334 CVDisplayLinkRelease(display_link_); |
| 297 CGLSetCurrentContext(context_->cgl_context()); | 335 CGLSetCurrentContext(context_->cgl_context()); |
| 298 CleanupAllCopiesWithinContext(); | 336 DestroyAllCopyContextsWithinContext(); |
| 299 UnrefIOSurfaceWithContextCurrent(); | 337 UnrefIOSurfaceWithContextCurrent(); |
| 300 CGLSetCurrentContext(0); | 338 CGLSetCurrentContext(0); |
| 301 context_ = nil; | 339 context_ = nil; |
| 302 } | 340 } |
| 303 | 341 |
| 304 void CompositingIOSurfaceMac::SetIOSurface(uint64 io_surface_handle, | 342 void CompositingIOSurfaceMac::SetIOSurface(uint64 io_surface_handle, |
| 305 const gfx::Size& size) { | 343 const gfx::Size& size) { |
| 306 pixel_io_surface_size_ = size; | 344 pixel_io_surface_size_ = size; |
| 307 CGLSetCurrentContext(context_->cgl_context()); | 345 CGLSetCurrentContext(context_->cgl_context()); |
| 308 MapIOSurfaceToTexture(io_surface_handle); | 346 MapIOSurfaceToTexture(io_surface_handle); |
| (...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 717 DCHECK(!done_callback.is_null()); | 755 DCHECK(!done_callback.is_null()); |
| 718 | 756 |
| 719 // TODO(miu): Forcing synchronous copy for M27. Will work on fixing the | 757 // TODO(miu): Forcing synchronous copy for M27. Will work on fixing the |
| 720 // desired asynchronous method for M28. http://crbug.com/223326 | 758 // desired asynchronous method for M28. http://crbug.com/223326 |
| 721 const bool async_copy = false; | 759 const bool async_copy = false; |
| 722 TRACE_EVENT2( | 760 TRACE_EVENT2( |
| 723 "browser", "CompositingIOSurfaceMac::CopyToSelectedOutputWithinContext", | 761 "browser", "CompositingIOSurfaceMac::CopyToSelectedOutputWithinContext", |
| 724 "output", bitmap_output ? "SkBitmap (ARGB)" : "VideoFrame (YV12)", | 762 "output", bitmap_output ? "SkBitmap (ARGB)" : "VideoFrame (YV12)", |
| 725 "async_readback", async_copy); | 763 "async_readback", async_copy); |
| 726 | 764 |
| 765 CopyContext* copy_context; |
| 766 if (copy_context_pool_.empty()) { |
| 767 // TODO(miu): Determine appropriate limit once new async copy approach is |
| 768 // put in place. |
| 769 if (copy_requests_.size() >= 3) |
| 770 return base::Bind(done_callback, false); |
| 771 copy_context = new CopyContext(context_); |
| 772 } else { |
| 773 copy_context = copy_context_pool_.back(); |
| 774 copy_context_pool_.pop_back(); |
| 775 } |
| 776 |
| 727 // Set up source texture, bound to the GL_TEXTURE_RECTANGLE_ARB target. | 777 // Set up source texture, bound to the GL_TEXTURE_RECTANGLE_ARB target. |
| 728 if (!MapIOSurfaceToTexture(io_surface_handle_)) | 778 if (!MapIOSurfaceToTexture(io_surface_handle_)) |
| 729 return base::Bind(done_callback, false); | 779 return base::Bind(done_callback, false); |
| 730 | 780 |
| 731 // Create the transformer_ on first use. | |
| 732 if (!transformer_) { | |
| 733 transformer_.reset(new CompositingIOSurfaceTransformer( | |
| 734 GL_TEXTURE_RECTANGLE_ARB, | |
| 735 true, | |
| 736 context_->shader_program_cache())); | |
| 737 } | |
| 738 | |
| 739 // Send transform commands to the GPU. | 781 // Send transform commands to the GPU. |
| 740 const gfx::Rect src_rect = IntersectWithIOSurface(src_pixel_subrect, | 782 const gfx::Rect src_rect = IntersectWithIOSurface(src_pixel_subrect, |
| 741 src_scale_factor); | 783 src_scale_factor); |
| 742 CopyContext copy_context; | 784 copy_context->num_outputs = 0; |
| 743 if (bitmap_output) { | 785 if (bitmap_output) { |
| 744 if (transformer_->ResizeBilinear(texture_, src_rect, dst_pixel_rect.size(), | 786 if (copy_context->transformer->ResizeBilinear( |
| 745 ©_context.output_textures[0])) { | 787 texture_, src_rect, dst_pixel_rect.size(), |
| 746 copy_context.num_outputs = 1; | 788 ©_context->output_textures[0])) { |
| 747 copy_context.output_texture_sizes[0] = dst_pixel_rect.size(); | 789 copy_context->num_outputs = 1; |
| 790 copy_context->output_texture_sizes[0] = dst_pixel_rect.size(); |
| 748 } | 791 } |
| 749 } else { | 792 } else { |
| 750 if (transformer_->TransformRGBToYV12( | 793 if (copy_context->transformer->TransformRGBToYV12( |
| 751 texture_, src_rect, dst_pixel_rect.size(), | 794 texture_, src_rect, dst_pixel_rect.size(), |
| 752 ©_context.output_textures[0], | 795 ©_context->output_textures[0], |
| 753 ©_context.output_textures[1], | 796 ©_context->output_textures[1], |
| 754 ©_context.output_textures[2], | 797 ©_context->output_textures[2], |
| 755 ©_context.output_texture_sizes[0], | 798 ©_context->output_texture_sizes[0], |
| 756 ©_context.output_texture_sizes[1])) { | 799 ©_context->output_texture_sizes[1])) { |
| 757 copy_context.num_outputs = 3; | 800 copy_context->num_outputs = 3; |
| 758 copy_context.output_texture_sizes[2] = | 801 copy_context->output_texture_sizes[2] = |
| 759 copy_context.output_texture_sizes[1]; | 802 copy_context->output_texture_sizes[1]; |
| 760 } | 803 } |
| 761 } | 804 } |
| 762 if (!copy_context.num_outputs) | 805 if (!copy_context->num_outputs) |
| 763 return base::Bind(done_callback, false); | 806 return base::Bind(done_callback, false); |
| 764 | 807 |
| 765 // In the asynchronous case, issue commands to the GPU and return a null | 808 // In the asynchronous case, issue commands to the GPU and return a null |
| 766 // closure here. In the synchronous case, perform a blocking readback and | 809 // closure here. In the synchronous case, perform a blocking readback and |
| 767 // return a callback to be run outside the CGL context to indicate success. | 810 // return a callback to be run outside the CGL context to indicate success. |
| 768 if (async_copy) { | 811 if (async_copy) { |
| 769 copy_context.done_callback = done_callback; | 812 copy_context->done_callback = done_callback; |
| 770 AsynchronousReadbackForCopy( | 813 AsynchronousReadbackForCopy( |
| 771 dst_pixel_rect, called_within_draw, ©_context, bitmap_output, | 814 dst_pixel_rect, called_within_draw, copy_context, bitmap_output, |
| 772 video_frame_output); | 815 video_frame_output); |
| 773 copy_requests_.push_back(copy_context); | 816 copy_requests_.push_back(copy_context); |
| 774 if (!finish_copy_timer_.IsRunning()) | 817 if (!finish_copy_timer_.IsRunning()) |
| 775 finish_copy_timer_.Reset(); | 818 finish_copy_timer_.Reset(); |
| 776 return base::Closure(); | 819 return base::Closure(); |
| 777 } else { | 820 } else { |
| 778 const bool success = SynchronousReadbackForCopy( | 821 const bool success = SynchronousReadbackForCopy( |
| 779 dst_pixel_rect, ©_context, bitmap_output, video_frame_output); | 822 dst_pixel_rect, copy_context, bitmap_output, video_frame_output); |
| 780 return base::Bind(done_callback, success); | 823 return base::Bind(done_callback, success); |
| 781 } | 824 } |
| 782 } | 825 } |
| 783 | 826 |
| 784 void CompositingIOSurfaceMac::AsynchronousReadbackForCopy( | 827 void CompositingIOSurfaceMac::AsynchronousReadbackForCopy( |
| 785 const gfx::Rect& dst_pixel_rect, | 828 const gfx::Rect& dst_pixel_rect, |
| 786 bool called_within_draw, | 829 bool called_within_draw, |
| 787 CopyContext* copy_context, | 830 CopyContext* copy_context, |
| 788 const SkBitmap* bitmap_output, | 831 const SkBitmap* bitmap_output, |
| 789 const scoped_refptr<media::VideoFrame>& video_frame_output) { | 832 const scoped_refptr<media::VideoFrame>& video_frame_output) { |
| 790 glGenFencesAPPLE(1, ©_context->fence); CHECK_GL_ERROR(); | 833 copy_context->PrepareForAsynchronousReadback(); |
| 791 | 834 |
| 792 // Copy the textures to a PBO. | 835 // Copy the textures to their corresponding PBO. |
| 793 glGenFramebuffersEXT(copy_context->num_outputs, copy_context->frame_buffers); | |
| 794 CHECK_GL_ERROR(); | |
| 795 glGenBuffersARB(copy_context->num_outputs, copy_context->pixel_buffers); | |
| 796 CHECK_GL_ERROR(); | |
| 797 for (int i = 0; i < copy_context->num_outputs; ++i) { | 836 for (int i = 0; i < copy_context->num_outputs; ++i) { |
| 798 TRACE_EVENT1( | 837 TRACE_EVENT1( |
| 799 "browser", "CompositingIOSurfaceMac::AsynchronousReadbackForCopy", | 838 "browser", "CompositingIOSurfaceMac::AsynchronousReadbackForCopy", |
| 800 "plane", i); | 839 "plane", i); |
| 801 | 840 |
| 802 // Attach the output texture to the FBO. | 841 // Attach the output texture to the FBO. |
| 803 glBindFramebufferEXT( | 842 glBindFramebufferEXT( |
| 804 GL_READ_FRAMEBUFFER_EXT, copy_context->frame_buffers[i]); | 843 GL_READ_FRAMEBUFFER_EXT, copy_context->frame_buffers[i]); |
| 805 glFramebufferTexture2DEXT( | 844 glFramebufferTexture2DEXT( |
| 806 GL_READ_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, | 845 GL_READ_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, |
| (...skipping 10 matching lines...) Expand all Loading... |
| 817 glReadPixels(0, 0, | 856 glReadPixels(0, 0, |
| 818 copy_context->output_texture_sizes[i].width(), | 857 copy_context->output_texture_sizes[i].width(), |
| 819 copy_context->output_texture_sizes[i].height(), | 858 copy_context->output_texture_sizes[i].height(), |
| 820 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0); CHECK_GL_ERROR(); | 859 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0); CHECK_GL_ERROR(); |
| 821 } | 860 } |
| 822 | 861 |
| 823 glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0); CHECK_GL_ERROR(); | 862 glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0); CHECK_GL_ERROR(); |
| 824 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); CHECK_GL_ERROR(); | 863 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); CHECK_GL_ERROR(); |
| 825 | 864 |
| 826 glSetFenceAPPLE(copy_context->fence); CHECK_GL_ERROR(); | 865 glSetFenceAPPLE(copy_context->fence); CHECK_GL_ERROR(); |
| 866 copy_context->cycles_elapsed = 0; |
| 827 | 867 |
| 828 // When this asynchronous copy happens in a draw operaton there is not need | 868 // When this asynchronous copy happens in a draw operaton there is no need |
| 829 // to explicitly flush because there will be a swap buffer and this flush | 869 // to explicitly flush because there will be a swap buffer and this flush |
| 830 // hurts performance. | 870 // hurts performance. |
| 831 if (!called_within_draw) { | 871 if (!called_within_draw) { |
| 832 glFlush(); CHECK_GL_ERROR(); | 872 glFlush(); CHECK_GL_ERROR(); |
| 833 } | 873 } |
| 834 | 874 |
| 835 copy_context->map_buffer_callback = bitmap_output ? | 875 copy_context->map_buffer_callback = bitmap_output ? |
| 836 base::Bind(&MapBufferToSkBitmap, bitmap_output) : | 876 base::Bind(&MapBufferToSkBitmap, bitmap_output) : |
| 837 base::Bind(&MapBufferToVideoFrame, video_frame_output, dst_pixel_rect); | 877 base::Bind(&MapBufferToVideoFrame, video_frame_output, dst_pixel_rect); |
| 838 } | 878 } |
| 839 | 879 |
| 840 void CompositingIOSurfaceMac::FinishAllCopies() { | 880 void CompositingIOSurfaceMac::FinishAllCopies() { |
| 841 std::vector<base::Closure> done_callbacks; | 881 std::vector<base::Closure> done_callbacks; |
| 842 CGLSetCurrentContext(context_->cgl_context()); | 882 CGLSetCurrentContext(context_->cgl_context()); |
| 843 FinishAllCopiesWithinContext(&done_callbacks); | 883 FinishAllCopiesWithinContext(&done_callbacks); |
| 844 CGLSetCurrentContext(0); | 884 CGLSetCurrentContext(0); |
| 845 for (size_t i = 0; i < done_callbacks.size(); ++i) | 885 for (size_t i = 0; i < done_callbacks.size(); ++i) |
| 846 done_callbacks[i].Run(); | 886 done_callbacks[i].Run(); |
| 847 } | 887 } |
| 848 | 888 |
| 849 void CompositingIOSurfaceMac::FinishAllCopiesWithinContext( | 889 void CompositingIOSurfaceMac::FinishAllCopiesWithinContext( |
| 850 std::vector<base::Closure>* done_callbacks) { | 890 std::vector<base::Closure>* done_callbacks) { |
| 851 while (!copy_requests_.empty()) { | 891 while (!copy_requests_.empty()) { |
| 852 CopyContext& copy_context = copy_requests_.front(); | 892 CopyContext* const copy_context = copy_requests_.front(); |
| 853 | 893 |
| 854 if (copy_context.fence) { | 894 if (copy_context->fence) { |
| 855 const bool copy_completed = glTestFenceAPPLE(copy_context.fence); | 895 const bool copy_completed = glTestFenceAPPLE(copy_context->fence); |
| 856 CHECK_GL_ERROR(); | 896 CHECK_GL_ERROR(); |
| 857 | 897 |
| 858 if (!copy_completed && | 898 if (!copy_completed && |
| 859 copy_context.cycles_elapsed < kFinishCopyRetryCycles) { | 899 copy_context->cycles_elapsed < kFinishCopyRetryCycles) { |
| 860 ++copy_context.cycles_elapsed; | 900 ++copy_context->cycles_elapsed; |
| 861 // This copy has not completed there is no need to test subsequent | 901 // This copy has not completed there is no need to test subsequent |
| 862 // requests. | 902 // requests. |
| 863 break; | 903 break; |
| 864 } | 904 } |
| 865 } | 905 } |
| 866 | 906 |
| 867 bool success = true; | 907 bool success = true; |
| 868 for (int i = 0; success && i < copy_context.num_outputs; ++i) { | 908 for (int i = 0; success && i < copy_context->num_outputs; ++i) { |
| 869 TRACE_EVENT1( | 909 TRACE_EVENT1( |
| 870 "browser", "CompositingIOSurfaceMac::FinishAllCopyWithinContext", | 910 "browser", "CompositingIOSurfaceMac::FinishAllCopyWithinContext", |
| 871 "plane", i); | 911 "plane", i); |
| 872 | 912 |
| 873 glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, copy_context.pixel_buffers[i]); | 913 glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, copy_context->pixel_buffers[i]); |
| 874 CHECK_GL_ERROR(); | 914 CHECK_GL_ERROR(); |
| 875 | 915 |
| 876 void* buf = glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB); | 916 void* buf = glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB); |
| 877 CHECK_GL_ERROR(); | 917 CHECK_GL_ERROR(); |
| 878 success &= copy_context.map_buffer_callback.Run(buf, i); | 918 success &= copy_context->map_buffer_callback.Run(buf, i); |
| 879 glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB); CHECK_GL_ERROR(); | 919 glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB); CHECK_GL_ERROR(); |
| 880 } | 920 } |
| 921 copy_context->map_buffer_callback.Reset(); |
| 922 glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0); CHECK_GL_ERROR(); |
| 881 | 923 |
| 882 glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0); CHECK_GL_ERROR(); | |
| 883 copy_context.CleanUp(); | |
| 884 done_callbacks->push_back(base::Bind(copy_context.done_callback, success)); | |
| 885 copy_requests_.pop_front(); | 924 copy_requests_.pop_front(); |
| 925 done_callbacks->push_back(base::Bind(copy_context->done_callback, success)); |
| 926 copy_context->done_callback.Reset(); |
| 927 copy_context_pool_.push_back(copy_context); |
| 886 } | 928 } |
| 887 if (copy_requests_.empty()) | 929 if (copy_requests_.empty()) |
| 888 finish_copy_timer_.Stop(); | 930 finish_copy_timer_.Stop(); |
| 889 } | 931 } |
| 890 | 932 |
| 891 bool CompositingIOSurfaceMac::SynchronousReadbackForCopy( | 933 bool CompositingIOSurfaceMac::SynchronousReadbackForCopy( |
| 892 const gfx::Rect& dst_pixel_rect, | 934 const gfx::Rect& dst_pixel_rect, |
| 893 CopyContext* copy_context, | 935 CopyContext* copy_context, |
| 894 const SkBitmap* bitmap_output, | 936 const SkBitmap* bitmap_output, |
| 895 const scoped_refptr<media::VideoFrame>& video_frame_output) { | 937 const scoped_refptr<media::VideoFrame>& video_frame_output) { |
| 896 bool success = true; | 938 bool success = true; |
| 897 glGenFramebuffersEXT(copy_context->num_outputs, copy_context->frame_buffers); | 939 copy_context->PrepareReadbackFramebuffers(); |
| 898 CHECK_GL_ERROR(); | |
| 899 for (int i = 0; i < copy_context->num_outputs; ++i) { | 940 for (int i = 0; i < copy_context->num_outputs; ++i) { |
| 900 TRACE_EVENT1( | 941 TRACE_EVENT1( |
| 901 "browser", "CompositingIOSurfaceMac::SynchronousReadbackForCopy", | 942 "browser", "CompositingIOSurfaceMac::SynchronousReadbackForCopy", |
| 902 "plane", i); | 943 "plane", i); |
| 903 | 944 |
| 904 // Attach the output texture to the FBO. | 945 // Attach the output texture to the FBO. |
| 905 glBindFramebufferEXT( | 946 glBindFramebufferEXT( |
| 906 GL_READ_FRAMEBUFFER_EXT, copy_context->frame_buffers[i]); | 947 GL_READ_FRAMEBUFFER_EXT, copy_context->frame_buffers[i]); |
| 907 glFramebufferTexture2DEXT( | 948 glFramebufferTexture2DEXT( |
| 908 GL_READ_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, | 949 GL_READ_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 955 media::LetterboxYUV(video_frame_output, dst_pixel_rect); | 996 media::LetterboxYUV(video_frame_output, dst_pixel_rect); |
| 956 } else { | 997 } else { |
| 957 // Copy from temporary buffer and fully render the VideoFrame. | 998 // Copy from temporary buffer and fully render the VideoFrame. |
| 958 success &= MapBufferToVideoFrame(video_frame_output, dst_pixel_rect, | 999 success &= MapBufferToVideoFrame(video_frame_output, dst_pixel_rect, |
| 959 temp_readback_buffer.get(), i); | 1000 temp_readback_buffer.get(), i); |
| 960 } | 1001 } |
| 961 } | 1002 } |
| 962 } | 1003 } |
| 963 | 1004 |
| 964 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0); CHECK_GL_ERROR(); | 1005 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0); CHECK_GL_ERROR(); |
| 965 copy_context->CleanUp(); | 1006 copy_context_pool_.push_back(copy_context); |
| 966 return success; | 1007 return success; |
| 967 } | 1008 } |
| 968 | 1009 |
| 969 void CompositingIOSurfaceMac::CleanupAllCopiesWithinContext() { | 1010 void CompositingIOSurfaceMac::FailAllCopies() { |
| 970 for (size_t i = 0; i < copy_requests_.size(); ++i) | 1011 for (size_t i = 0; i < copy_requests_.size(); ++i) { |
| 971 copy_requests_[i].CleanUp(); | 1012 copy_requests_[i]->map_buffer_callback.Reset(); |
| 972 copy_requests_.clear(); | 1013 |
| 1014 base::Callback<void(bool)>& done_callback = |
| 1015 copy_requests_[i]->done_callback; |
| 1016 if (!done_callback.is_null()) { |
| 1017 done_callback.Run(false); |
| 1018 done_callback.Reset(); |
| 1019 } |
| 1020 } |
| 973 } | 1021 } |
| 974 | 1022 |
| 975 void CompositingIOSurfaceMac::FailAllCopies() { | 1023 void CompositingIOSurfaceMac::DestroyAllCopyContextsWithinContext() { |
| 976 for (size_t i = 0; i < copy_requests_.size(); ++i) | 1024 // Move all in-flight copies, if any, back into the pool. Then, destroy all |
| 977 copy_requests_[i].done_callback.Run(false); | 1025 // the CopyContexts in the pool. |
| 1026 copy_context_pool_.insert(copy_context_pool_.end(), |
| 1027 copy_requests_.begin(), copy_requests_.end()); |
| 1028 copy_requests_.clear(); |
| 1029 while (!copy_context_pool_.empty()) { |
| 1030 scoped_ptr<CopyContext> copy_context(copy_context_pool_.back()); |
| 1031 copy_context_pool_.pop_back(); |
| 1032 copy_context->ReleaseCachedGLObjects(); |
| 1033 } |
| 978 } | 1034 } |
| 979 | 1035 |
| 980 gfx::Rect CompositingIOSurfaceMac::IntersectWithIOSurface( | 1036 gfx::Rect CompositingIOSurfaceMac::IntersectWithIOSurface( |
| 981 const gfx::Rect& rect, float scale_factor) const { | 1037 const gfx::Rect& rect, float scale_factor) const { |
| 982 return gfx::IntersectRects(rect, | 1038 return gfx::IntersectRects(rect, |
| 983 gfx::ToEnclosingRect(gfx::ScaleRect(gfx::Rect(io_surface_size_), | 1039 gfx::ToEnclosingRect(gfx::ScaleRect(gfx::Rect(io_surface_size_), |
| 984 scale_factor))); | 1040 scale_factor))); |
| 985 } | 1041 } |
| 986 | 1042 |
| 987 } // namespace content | 1043 } // namespace content |
| OLD | NEW |