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

Side by Side Diff: content/renderer/render_widget.cc

Issue 23694031: Fix race conditions in window snapshot code. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 3 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 | Annotate | Revision Log
OLDNEW
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/renderer/render_widget.h" 5 #include "content/renderer/render_widget.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/command_line.h" 8 #include "base/command_line.h"
9 #include "base/debug/trace_event.h" 9 #include "base/debug/trace_event.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after
361 } 361 }
362 362
363 bool RenderWidget::UsingSynchronousRendererCompositor() const { 363 bool RenderWidget::UsingSynchronousRendererCompositor() const {
364 #if defined(OS_ANDROID) 364 #if defined(OS_ANDROID)
365 return SynchronousCompositorFactory::GetInstance() != NULL; 365 return SynchronousCompositorFactory::GetInstance() != NULL;
366 #else 366 #else
367 return false; 367 return false;
368 #endif 368 #endif
369 } 369 }
370 370
371 void RenderWidget::ScheduleCompositeWithForcedRedraw() {
372 ScheduleCompositeImpl(true);
373 }
374
375 void RenderWidget::ScheduleCompositeImpl(bool force_redraw) {
376 if (compositor_ && force_redraw) {
377 // Regardless of whether threaded compositing is enabled, always
378 // use this mechanism to force the compositor to redraw. However,
379 // the invalidation code path below is still needed for the
380 // non-threaded case.
381 compositor_->SetNeedsForcedRedraw();
382 }
383
384 if (RenderThreadImpl::current()->compositor_message_loop_proxy().get() &&
385 compositor_) {
386 if (!force_redraw) {
387 compositor_->setNeedsRedraw();
388 }
389 } else {
390 // TODO(nduca): replace with something a little less hacky. The reason this
391 // hack is still used is because the Invalidate-DoDeferredUpdate loop
392 // contains a lot of host-renderer synchronization logic that is still
393 // important for the accelerated compositing case. The option of simply
394 // duplicating all that code is less desirable than "faking out" the
395 // invalidation path using a magical damage rect.
396 didInvalidateRect(WebRect(0, 0, 1, 1));
397 }
398 }
399
371 bool RenderWidget::OnMessageReceived(const IPC::Message& message) { 400 bool RenderWidget::OnMessageReceived(const IPC::Message& message) {
372 bool handled = true; 401 bool handled = true;
373 IPC_BEGIN_MESSAGE_MAP(RenderWidget, message) 402 IPC_BEGIN_MESSAGE_MAP(RenderWidget, message)
374 IPC_MESSAGE_HANDLER(InputMsg_HandleInputEvent, OnHandleInputEvent) 403 IPC_MESSAGE_HANDLER(InputMsg_HandleInputEvent, OnHandleInputEvent)
375 IPC_MESSAGE_HANDLER(InputMsg_CursorVisibilityChange, 404 IPC_MESSAGE_HANDLER(InputMsg_CursorVisibilityChange,
376 OnCursorVisibilityChange) 405 OnCursorVisibilityChange)
377 IPC_MESSAGE_HANDLER(InputMsg_MouseCaptureLost, OnMouseCaptureLost) 406 IPC_MESSAGE_HANDLER(InputMsg_MouseCaptureLost, OnMouseCaptureLost)
378 IPC_MESSAGE_HANDLER(InputMsg_SetFocus, OnSetFocus) 407 IPC_MESSAGE_HANDLER(InputMsg_SetFocus, OnSetFocus)
379 IPC_MESSAGE_HANDLER(ViewMsg_Close, OnClose) 408 IPC_MESSAGE_HANDLER(ViewMsg_Close, OnClose)
380 IPC_MESSAGE_HANDLER(ViewMsg_CreatingNew_ACK, OnCreatingNewAck) 409 IPC_MESSAGE_HANDLER(ViewMsg_CreatingNew_ACK, OnCreatingNewAck)
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after
609 // If we sent an UpdateRect message with a zero-sized bitmap, then we should 638 // If we sent an UpdateRect message with a zero-sized bitmap, then we should
610 // have no current paint buffer. 639 // have no current paint buffer.
611 if (current_paint_buf_) { 640 if (current_paint_buf_) {
612 RenderProcess::current()->ReleaseTransportDIB(current_paint_buf_); 641 RenderProcess::current()->ReleaseTransportDIB(current_paint_buf_);
613 current_paint_buf_ = NULL; 642 current_paint_buf_ = NULL;
614 } 643 }
615 644
616 // If swapbuffers is still pending, then defer the update until the 645 // If swapbuffers is still pending, then defer the update until the
617 // swapbuffers occurs. 646 // swapbuffers occurs.
618 if (num_swapbuffers_complete_pending_ >= kMaxSwapBuffersPending) { 647 if (num_swapbuffers_complete_pending_ >= kMaxSwapBuffersPending) {
648 LOG(INFO) << "EarlyOut_SwapStillPending";
619 TRACE_EVENT0("renderer", "EarlyOut_SwapStillPending"); 649 TRACE_EVENT0("renderer", "EarlyOut_SwapStillPending");
620 return; 650 return;
621 } 651 }
622 652
623 // Notify subclasses that software rendering was flushed to the screen. 653 // Notify subclasses that software rendering was flushed to the screen.
624 if (!is_accelerated_compositing_active_) { 654 if (!is_accelerated_compositing_active_) {
625 DidFlushPaint(); 655 DidFlushPaint();
626 } 656 }
627 657
628 // Continue painting if necessary... 658 // Continue painting if necessary...
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
761 791
762 void RenderWidget::OnViewContextSwapBuffersComplete() { 792 void RenderWidget::OnViewContextSwapBuffersComplete() {
763 TRACE_EVENT0("renderer", "RenderWidget::OnSwapBuffersComplete"); 793 TRACE_EVENT0("renderer", "RenderWidget::OnSwapBuffersComplete");
764 794
765 // Notify subclasses that composited rendering was flushed to the screen. 795 // Notify subclasses that composited rendering was flushed to the screen.
766 DidFlushPaint(); 796 DidFlushPaint();
767 797
768 // When compositing deactivates, we reset the swapbuffers pending count. The 798 // When compositing deactivates, we reset the swapbuffers pending count. The
769 // swapbuffers acks may still arrive, however. 799 // swapbuffers acks may still arrive, however.
770 if (num_swapbuffers_complete_pending_ == 0) { 800 if (num_swapbuffers_complete_pending_ == 0) {
801 LOG(INFO) << "EarlyOut_ZeroSwapbuffersPending";
771 TRACE_EVENT0("renderer", "EarlyOut_ZeroSwapbuffersPending"); 802 TRACE_EVENT0("renderer", "EarlyOut_ZeroSwapbuffersPending");
772 return; 803 return;
773 } 804 }
774 DCHECK(!updates_pending_swap_.empty()); 805 DCHECK(!updates_pending_swap_.empty());
775 ViewHostMsg_UpdateRect* msg = updates_pending_swap_.front(); 806 ViewHostMsg_UpdateRect* msg = updates_pending_swap_.front();
776 updates_pending_swap_.pop_front(); 807 updates_pending_swap_.pop_front();
777 // msg can be NULL if the swap doesn't correspond to an DoDeferredUpdate 808 // msg can be NULL if the swap doesn't correspond to an DoDeferredUpdate
778 // compositing pass, hence doesn't require an UpdateRect message. 809 // compositing pass, hence doesn't require an UpdateRect message.
779 if (msg) 810 if (msg)
780 Send(msg); 811 Send(msg);
781 num_swapbuffers_complete_pending_--; 812 num_swapbuffers_complete_pending_--;
782 813
783 // If update reply is still pending, then defer the update until that reply 814 // If update reply is still pending, then defer the update until that reply
784 // occurs. 815 // occurs.
785 if (update_reply_pending_) { 816 if (update_reply_pending_) {
817 LOG(INFO) << "EarlyOut_UpdateReplyPending";
786 TRACE_EVENT0("renderer", "EarlyOut_UpdateReplyPending"); 818 TRACE_EVENT0("renderer", "EarlyOut_UpdateReplyPending");
787 return; 819 return;
788 } 820 }
789 821
790 // If we are not accelerated rendering, then this is a stale swapbuffers from 822 // If we are not accelerated rendering, then this is a stale swapbuffers from
791 // when we were previously rendering. However, if an invalidation task is not 823 // when we were previously rendering. However, if an invalidation task is not
792 // posted, there may be software rendering work pending. In that case, don't 824 // posted, there may be software rendering work pending. In that case, don't
793 // early out. 825 // early out.
794 if (!is_accelerated_compositing_active_ && invalidation_task_posted_) { 826 if (!is_accelerated_compositing_active_ && invalidation_task_posted_) {
827 LOG(INFO) << "EarlyOut_AcceleratedCompositingOff";
795 TRACE_EVENT0("renderer", "EarlyOut_AcceleratedCompositingOff"); 828 TRACE_EVENT0("renderer", "EarlyOut_AcceleratedCompositingOff");
796 return; 829 return;
797 } 830 }
798 831
799 // Do not call DoDeferredUpdate unless there's animation work to be done or 832 // Do not call DoDeferredUpdate unless there's animation work to be done or
800 // a real invalidation. This prevents rendering in response to a swapbuffers 833 // a real invalidation. This prevents rendering in response to a swapbuffers
801 // callback coming back after we've navigated away from the page that 834 // callback coming back after we've navigated away from the page that
802 // generated it. 835 // generated it.
803 if (!animation_update_pending_ && !paint_aggregator_.HasPendingUpdate()) { 836 if (!animation_update_pending_ && !paint_aggregator_.HasPendingUpdate()) {
837 LOG(INFO) << "EarlyOut_NoPendingUpdate";
804 TRACE_EVENT0("renderer", "EarlyOut_NoPendingUpdate"); 838 TRACE_EVENT0("renderer", "EarlyOut_NoPendingUpdate");
805 return; 839 return;
806 } 840 }
807 841
808 // Continue painting if necessary... 842 // Continue painting if necessary...
809 DoDeferredUpdateAndSendInputAck(); 843 DoDeferredUpdateAndSendInputAck();
810 } 844 }
811 845
812 void RenderWidget::OnHandleInputEvent(const WebKit::WebInputEvent* input_event, 846 void RenderWidget::OnHandleInputEvent(const WebKit::WebInputEvent* input_event,
813 const ui::LatencyInfo& latency_info, 847 const ui::LatencyInfo& latency_info,
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after
1078 paint.setStrokeWidth(1); 1112 paint.setStrokeWidth(1);
1079 1113
1080 SkIRect irect; 1114 SkIRect irect;
1081 irect.set(rect.x(), rect.y(), rect.right() - 1, rect.bottom() - 1); 1115 irect.set(rect.x(), rect.y(), rect.right() - 1, rect.bottom() - 1);
1082 canvas->drawIRect(irect, paint); 1116 canvas->drawIRect(irect, paint);
1083 } 1117 }
1084 1118
1085 void RenderWidget::AnimationCallback() { 1119 void RenderWidget::AnimationCallback() {
1086 TRACE_EVENT0("renderer", "RenderWidget::AnimationCallback"); 1120 TRACE_EVENT0("renderer", "RenderWidget::AnimationCallback");
1087 if (!animation_update_pending_) { 1121 if (!animation_update_pending_) {
1122 LOG(INFO) << "EarlyOut_NoAnimationUpdatePending";
1088 TRACE_EVENT0("renderer", "EarlyOut_NoAnimationUpdatePending"); 1123 TRACE_EVENT0("renderer", "EarlyOut_NoAnimationUpdatePending");
1089 return; 1124 return;
1090 } 1125 }
1091 if (!animation_floor_time_.is_null() && IsRenderingVSynced()) { 1126 if (!animation_floor_time_.is_null() && IsRenderingVSynced()) {
1092 // Record when we fired (according to base::Time::Now()) relative to when 1127 // Record when we fired (according to base::Time::Now()) relative to when
1093 // we posted the task to quantify how much the base::Time/base::TimeTicks 1128 // we posted the task to quantify how much the base::Time/base::TimeTicks
1094 // skew is affecting animations. 1129 // skew is affecting animations.
1095 base::TimeDelta animation_callback_delay = base::Time::Now() - 1130 base::TimeDelta animation_callback_delay = base::Time::Now() -
1096 (animation_floor_time_ - base::TimeDelta::FromMilliseconds(16)); 1131 (animation_floor_time_ - base::TimeDelta::FromMilliseconds(16));
1097 UMA_HISTOGRAM_CUSTOM_TIMES("Renderer4.AnimationCallbackDelayTime", 1132 UMA_HISTOGRAM_CUSTOM_TIMES("Renderer4.AnimationCallbackDelayTime",
(...skipping 30 matching lines...) Expand all
1128 animation_update_pending_ = false; 1163 animation_update_pending_ = false;
1129 if (is_accelerated_compositing_active_ && compositor_) { 1164 if (is_accelerated_compositing_active_ && compositor_) {
1130 compositor_->Animate(base::TimeTicks::Now()); 1165 compositor_->Animate(base::TimeTicks::Now());
1131 } else { 1166 } else {
1132 double frame_begin_time = 1167 double frame_begin_time =
1133 (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF(); 1168 (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF();
1134 webwidget_->animate(frame_begin_time); 1169 webwidget_->animate(frame_begin_time);
1135 } 1170 }
1136 return; 1171 return;
1137 } 1172 }
1173 LOG(INFO) << "EarlyOut_AnimatedTooRecently";
1138 TRACE_EVENT0("renderer", "EarlyOut_AnimatedTooRecently"); 1174 TRACE_EVENT0("renderer", "EarlyOut_AnimatedTooRecently");
1139 if (!animation_timer_.IsRunning()) { 1175 if (!animation_timer_.IsRunning()) {
1140 // This code uses base::Time::Now() to calculate the floor and next fire 1176 // This code uses base::Time::Now() to calculate the floor and next fire
1141 // time because javascript's Date object uses base::Time::Now(). The 1177 // time because javascript's Date object uses base::Time::Now(). The
1142 // message loop uses base::TimeTicks, which on windows can have a 1178 // message loop uses base::TimeTicks, which on windows can have a
1143 // different granularity than base::Time. 1179 // different granularity than base::Time.
1144 // The upshot of all this is that this function might be called before 1180 // The upshot of all this is that this function might be called before
1145 // base::Time::Now() has advanced past the animation_floor_time_. To 1181 // base::Time::Now() has advanced past the animation_floor_time_. To
1146 // avoid exposing this delay to javascript, we keep posting delayed 1182 // avoid exposing this delay to javascript, we keep posting delayed
1147 // tasks until base::Time::Now() has advanced far enough. 1183 // tasks until base::Time::Now() has advanced far enough.
(...skipping 25 matching lines...) Expand all
1173 } 1209 }
1174 1210
1175 void RenderWidget::DoDeferredUpdate() { 1211 void RenderWidget::DoDeferredUpdate() {
1176 TRACE_EVENT0("renderer", "RenderWidget::DoDeferredUpdate"); 1212 TRACE_EVENT0("renderer", "RenderWidget::DoDeferredUpdate");
1177 TRACE_EVENT_SCOPED_SAMPLING_STATE("Chrome", "Paint"); 1213 TRACE_EVENT_SCOPED_SAMPLING_STATE("Chrome", "Paint");
1178 1214
1179 if (!webwidget_) 1215 if (!webwidget_)
1180 return; 1216 return;
1181 1217
1182 if (!init_complete_) { 1218 if (!init_complete_) {
1219 LOG(INFO) << "EarlyOut_InitNotComplete";
1183 TRACE_EVENT0("renderer", "EarlyOut_InitNotComplete"); 1220 TRACE_EVENT0("renderer", "EarlyOut_InitNotComplete");
1184 return; 1221 return;
1185 } 1222 }
1186 if (update_reply_pending_) { 1223 if (update_reply_pending_) {
1224 LOG(INFO) << "EarlyOut_UpdateReplyPending";
1187 TRACE_EVENT0("renderer", "EarlyOut_UpdateReplyPending"); 1225 TRACE_EVENT0("renderer", "EarlyOut_UpdateReplyPending");
1188 return; 1226 return;
1189 } 1227 }
1190 if (is_accelerated_compositing_active_ && 1228 if (is_accelerated_compositing_active_ &&
1191 num_swapbuffers_complete_pending_ >= kMaxSwapBuffersPending) { 1229 num_swapbuffers_complete_pending_ >= kMaxSwapBuffersPending) {
1230 LOG(INFO) << "EarlyOut_MaxSwapBuffersPending";
1192 TRACE_EVENT0("renderer", "EarlyOut_MaxSwapBuffersPending"); 1231 TRACE_EVENT0("renderer", "EarlyOut_MaxSwapBuffersPending");
1193 return; 1232 return;
1194 } 1233 }
1195 1234
1196 // Suppress updating when we are hidden. 1235 // Suppress updating when we are hidden.
1197 if (is_hidden_ || size_.IsEmpty() || is_swapped_out_) { 1236 if (is_hidden_ || size_.IsEmpty() || is_swapped_out_) {
1198 paint_aggregator_.ClearPendingUpdate(); 1237 paint_aggregator_.ClearPendingUpdate();
1199 needs_repainting_on_restore_ = true; 1238 needs_repainting_on_restore_ = true;
1239 LOG(INFO) << "EarlyOut_NotVisible";
1200 TRACE_EVENT0("renderer", "EarlyOut_NotVisible"); 1240 TRACE_EVENT0("renderer", "EarlyOut_NotVisible");
1201 return; 1241 return;
1202 } 1242 }
1203 1243
1204 // Tracking of frame rate jitter 1244 // Tracking of frame rate jitter
1205 base::TimeTicks frame_begin_ticks = base::TimeTicks::Now(); 1245 base::TimeTicks frame_begin_ticks = base::TimeTicks::Now();
1206 InstrumentWillBeginFrame(); 1246 InstrumentWillBeginFrame();
1207 AnimateIfNeeded(); 1247 AnimateIfNeeded();
1208 1248
1209 // Layout may generate more invalidation. It may also enable the 1249 // Layout may generate more invalidation. It may also enable the
1210 // GPU acceleration, so make sure to run layout before we send the 1250 // GPU acceleration, so make sure to run layout before we send the
1211 // GpuRenderingActivated message. 1251 // GpuRenderingActivated message.
1212 webwidget_->layout(); 1252 webwidget_->layout();
1213 1253
1214 // Check for whether we need to track swap buffers. We need to do that after 1254 // Check for whether we need to track swap buffers. We need to do that after
1215 // layout() because it may have switched us to accelerated compositing. 1255 // layout() because it may have switched us to accelerated compositing.
1216 if (is_accelerated_compositing_active_) 1256 if (is_accelerated_compositing_active_)
1217 using_asynchronous_swapbuffers_ = SupportsAsynchronousSwapBuffers(); 1257 using_asynchronous_swapbuffers_ = SupportsAsynchronousSwapBuffers();
1218 1258
1219 // The following two can result in further layout and possibly 1259 // The following two can result in further layout and possibly
1220 // enable GPU acceleration so they need to be called before any painting 1260 // enable GPU acceleration so they need to be called before any painting
1221 // is done. 1261 // is done.
1222 UpdateTextInputType(); 1262 UpdateTextInputType();
1223 UpdateSelectionBounds(); 1263 UpdateSelectionBounds();
1224 1264
1225 // Suppress painting if nothing is dirty. This has to be done after updating 1265 // Suppress painting if nothing is dirty. This has to be done after updating
1226 // animations running layout as these may generate further invalidations. 1266 // animations running layout as these may generate further invalidations.
1227 if (!paint_aggregator_.HasPendingUpdate()) { 1267 if (!paint_aggregator_.HasPendingUpdate()) {
1268 LOG(INFO) << "EarlyOut_NoPendingUpdate";
1228 TRACE_EVENT0("renderer", "EarlyOut_NoPendingUpdate"); 1269 TRACE_EVENT0("renderer", "EarlyOut_NoPendingUpdate");
1229 InstrumentDidCancelFrame(); 1270 InstrumentDidCancelFrame();
1230 return; 1271 return;
1231 } 1272 }
1232 1273
1233 if (!is_accelerated_compositing_active_ && 1274 if (!is_accelerated_compositing_active_ &&
1234 !is_threaded_compositing_enabled_ && 1275 !is_threaded_compositing_enabled_ &&
1235 ForceCompositingModeEnabled()) { 1276 ForceCompositingModeEnabled()) {
1236 webwidget_->enterForceCompositingMode(true); 1277 webwidget_->enterForceCompositingMode(true);
1237 } 1278 }
(...skipping 411 matching lines...) Expand 10 before | Expand all | Expand 10 after
1649 params.scroll_offset = GetScrollOffset(); 1690 params.scroll_offset = GetScrollOffset();
1650 params.needs_ack = false; 1691 params.needs_ack = false;
1651 params.scale_factor = device_scale_factor_; 1692 params.scale_factor = device_scale_factor_;
1652 1693
1653 Send(new ViewHostMsg_UpdateRect(routing_id_, params)); 1694 Send(new ViewHostMsg_UpdateRect(routing_id_, params));
1654 next_paint_flags_ = 0; 1695 next_paint_flags_ = 0;
1655 need_update_rect_for_auto_resize_ = false; 1696 need_update_rect_for_auto_resize_ = false;
1656 } 1697 }
1657 1698
1658 void RenderWidget::scheduleComposite() { 1699 void RenderWidget::scheduleComposite() {
1659 if (RenderThreadImpl::current()->compositor_message_loop_proxy().get() && 1700 ScheduleCompositeImpl(false);
1660 compositor_) {
1661 compositor_->setNeedsRedraw();
1662 } else {
1663 // TODO(nduca): replace with something a little less hacky. The reason this
1664 // hack is still used is because the Invalidate-DoDeferredUpdate loop
1665 // contains a lot of host-renderer synchronization logic that is still
1666 // important for the accelerated compositing case. The option of simply
1667 // duplicating all that code is less desirable than "faking out" the
1668 // invalidation path using a magical damage rect.
1669 didInvalidateRect(WebRect(0, 0, 1, 1));
1670 }
1671 } 1701 }
1672 1702
1673 void RenderWidget::scheduleAnimation() { 1703 void RenderWidget::scheduleAnimation() {
1674 if (animation_update_pending_) 1704 if (animation_update_pending_)
1675 return; 1705 return;
1676 1706
1677 TRACE_EVENT0("gpu", "RenderWidget::scheduleAnimation"); 1707 TRACE_EVENT0("gpu", "RenderWidget::scheduleAnimation");
1678 animation_update_pending_ = true; 1708 animation_update_pending_ = true;
1679 if (!animation_timer_.IsRunning()) { 1709 if (!animation_timer_.IsRunning()) {
1680 animation_timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(0), this, 1710 animation_timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(0), this,
(...skipping 844 matching lines...) Expand 10 before | Expand all | Expand 10 after
2525 2555
2526 if (!context->InitializeWithDefaultBufferSizes( 2556 if (!context->InitializeWithDefaultBufferSizes(
2527 attributes, 2557 attributes,
2528 false /* bind generates resources */, 2558 false /* bind generates resources */,
2529 CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE) ) 2559 CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE) )
2530 return scoped_ptr<WebGraphicsContext3DCommandBufferImpl>(); 2560 return scoped_ptr<WebGraphicsContext3DCommandBufferImpl>();
2531 return context.Pass(); 2561 return context.Pass();
2532 } 2562 }
2533 2563
2534 } // namespace content 2564 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698