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 |