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

Side by Side Diff: Source/core/html/canvas/CanvasRenderingContext2D.cpp

Issue 211503006: Implementation of 2D canvas context lost/restored events (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: rebase Created 6 years, 8 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 /* 1 /*
2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved. 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved.
3 * Copyright (C) 2008, 2010 Nokia Corporation and/or its subsidiary(-ies) 3 * Copyright (C) 2008, 2010 Nokia Corporation and/or its subsidiary(-ies)
4 * Copyright (C) 2007 Alp Toker <alp@atoker.com> 4 * Copyright (C) 2007 Alp Toker <alp@atoker.com>
5 * Copyright (C) 2008 Eric Seidel <eric@webkit.org> 5 * Copyright (C) 2008 Eric Seidel <eric@webkit.org>
6 * Copyright (C) 2008 Dirk Schulze <krit@webkit.org> 6 * Copyright (C) 2008 Dirk Schulze <krit@webkit.org>
7 * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved. 7 * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved.
8 * Copyright (C) 2012, 2013 Intel Corporation. All rights reserved. 8 * Copyright (C) 2012, 2013 Intel Corporation. All rights reserved.
9 * Copyright (C) 2013 Adobe Systems Incorporated. All rights reserved. 9 * Copyright (C) 2013 Adobe Systems Incorporated. All rights reserved.
10 * 10 *
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
69 #include "wtf/Uint8ClampedArray.h" 69 #include "wtf/Uint8ClampedArray.h"
70 #include "wtf/text/StringBuilder.h" 70 #include "wtf/text/StringBuilder.h"
71 71
72 using namespace std; 72 using namespace std;
73 73
74 namespace WebCore { 74 namespace WebCore {
75 75
76 static const int defaultFontSize = 10; 76 static const int defaultFontSize = 10;
77 static const char defaultFontFamily[] = "sans-serif"; 77 static const char defaultFontFamily[] = "sans-serif";
78 static const char defaultFont[] = "10px sans-serif"; 78 static const char defaultFont[] = "10px sans-serif";
79 static const double TryRestoreContextInterval = 0.5;
80 static const unsigned MaxTryRestoreContextAttempts = 4;
81
82 static bool contextLostRestoredEventsEnabled()
83 {
84 return RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled();
85 }
79 86
80 CanvasRenderingContext2D::CanvasRenderingContext2D(HTMLCanvasElement* canvas, co nst Canvas2DContextAttributes* attrs, bool usesCSSCompatibilityParseMode) 87 CanvasRenderingContext2D::CanvasRenderingContext2D(HTMLCanvasElement* canvas, co nst Canvas2DContextAttributes* attrs, bool usesCSSCompatibilityParseMode)
81 : CanvasRenderingContext(canvas) 88 : CanvasRenderingContext(canvas)
82 , m_usesCSSCompatibilityParseMode(usesCSSCompatibilityParseMode) 89 , m_usesCSSCompatibilityParseMode(usesCSSCompatibilityParseMode)
83 , m_hasAlpha(!attrs || attrs->alpha()) 90 , m_hasAlpha(!attrs || attrs->alpha())
91 , m_isContextLost(false)
92 , m_contextRestorable(true)
93 , m_storageMode(!attrs ? PersistentStorage : attrs->parsedStorage())
94 , m_tryRestoreContextAttemptCount(0)
95 , m_dispatchContextLostEventTimer(this, &CanvasRenderingContext2D::dispatchC ontextLostEvent)
96 , m_dispatchContextRestoredEventTimer(this, &CanvasRenderingContext2D::dispa tchContextRestoredEvent)
97 , m_tryRestoreContextEventTimer(this, &CanvasRenderingContext2D::tryRestoreC ontextEvent)
84 { 98 {
85 m_stateStack.append(adoptPtrWillBeNoop(new State())); 99 m_stateStack.append(adoptPtrWillBeNoop(new State()));
86 ScriptWrappable::init(this); 100 ScriptWrappable::init(this);
87 } 101 }
88 102
89 void CanvasRenderingContext2D::unwindStateStack() 103 void CanvasRenderingContext2D::unwindStateStack()
90 { 104 {
91 // Ensure that the state stack in the ImageBuffer's context 105 // Ensure that the state stack in the ImageBuffer's context
92 // is cleared before destruction, to avoid assertions in the 106 // is cleared before destruction, to avoid assertions in the
93 // GraphicsContext dtor. 107 // GraphicsContext dtor.
(...skipping 13 matching lines...) Expand all
107 } 121 }
108 122
109 bool CanvasRenderingContext2D::isAccelerated() const 123 bool CanvasRenderingContext2D::isAccelerated() const
110 { 124 {
111 if (!canvas()->hasImageBuffer()) 125 if (!canvas()->hasImageBuffer())
112 return false; 126 return false;
113 GraphicsContext* context = drawingContext(); 127 GraphicsContext* context = drawingContext();
114 return context && context->isAccelerated(); 128 return context && context->isAccelerated();
115 } 129 }
116 130
131 bool CanvasRenderingContext2D::isContextLost() const
132 {
133 return m_isContextLost;
134 }
135
136 void CanvasRenderingContext2D::loseContext()
137 {
138 if (m_isContextLost)
139 return;
140 m_isContextLost = true;
141 m_dispatchContextLostEventTimer.startOneShot(0, FROM_HERE);
142 }
143
144 void CanvasRenderingContext2D::restoreContext()
145 {
146 if (!m_contextRestorable)
147 return;
148 // This code path is for restoring from an eviction
149 // Restoring from surface failure is handled internally
150 ASSERT(m_isContextLost && !canvas()->hasImageBuffer());
151
152 if (canvas()->buffer()) {
153 if (contextLostRestoredEventsEnabled()) {
154 m_dispatchContextRestoredEventTimer.startOneShot(0, FROM_HERE);
155 } else {
156 // legacy synchronous context restoration.
157 reset();
158 m_isContextLost = false;
159 }
160 }
161 }
162
163 void CanvasRenderingContext2D::dispatchContextLostEvent(Timer<CanvasRenderingCon text2D>*)
164 {
165 if (contextLostRestoredEventsEnabled()) {
166 RefPtr<Event> event(Event::createCancelable(EventTypeNames::contextlost) );
167 canvas()->dispatchEvent(event);
168 if (event->defaultPrevented()) {
169 m_contextRestorable = false;
170 }
171 }
172
173 // If an image buffer is present, it means the context was not lost due to
174 // an eviction, but rather due to a surface failure (gpu context lost?)
175 if (m_contextRestorable && canvas()->hasImageBuffer()) {
176 m_tryRestoreContextAttemptCount = 0;
177 m_tryRestoreContextEventTimer.startRepeating(TryRestoreContextInterval, FROM_HERE);
178 }
179 }
180
181 void CanvasRenderingContext2D::tryRestoreContextEvent(Timer<CanvasRenderingConte xt2D>* timer)
182 {
183 if (!m_isContextLost) {
184 // Canvas was already restored (possibly thanks to a resize), so stop tr ying.
185 m_tryRestoreContextEventTimer.stop();
186 return;
187 }
188 if (canvas()->hasImageBuffer() && canvas()->buffer()->restoreSurface()) {
189 m_tryRestoreContextEventTimer.stop();
190 dispatchContextRestoredEvent(0);
191 }
192
193 if (++m_tryRestoreContextAttemptCount > MaxTryRestoreContextAttempts)
194 canvas()->discardImageBuffer();
195
196 if (!canvas()->hasImageBuffer()) {
197 // final attempt: allocate a brand new image buffer instead of restoring
198 timer->stop();
199 if (canvas()->buffer())
200 dispatchContextRestoredEvent(0);
201 }
202 }
203
204 void CanvasRenderingContext2D::dispatchContextRestoredEvent(Timer<CanvasRenderin gContext2D>*)
205 {
206 if (!m_isContextLost)
207 return;
208 reset();
209 m_isContextLost = false;
210 if (contextLostRestoredEventsEnabled()) {
211 RefPtr<Event> event(Event::create(EventTypeNames::contextrestored));
212 canvas()->dispatchEvent(event);
213 }
214 }
215
117 void CanvasRenderingContext2D::reset() 216 void CanvasRenderingContext2D::reset()
118 { 217 {
119 unwindStateStack(); 218 unwindStateStack();
120 m_stateStack.resize(1); 219 m_stateStack.resize(1);
121 m_stateStack.first() = adoptPtrWillBeNoop(new State()); 220 m_stateStack.first() = adoptPtrWillBeNoop(new State());
122 m_path.clear(); 221 m_path.clear();
123 } 222 }
124 223
125 // Important: Several of these properties are also stored in GraphicsContext's 224 // Important: Several of these properties are also stored in GraphicsContext's
126 // StrokeData. The default values that StrokeData uses may not the same values 225 // StrokeData. The default values that StrokeData uses may not the same values
(...skipping 1530 matching lines...) Expand 10 before | Expand all | Expand 10 after
1657 canvas()->notifyObserversCanvasChanged(dirtyRect); 1756 canvas()->notifyObserversCanvasChanged(dirtyRect);
1658 return; 1757 return;
1659 } 1758 }
1660 } 1759 }
1661 1760
1662 canvas()->didDraw(dirtyRect); 1761 canvas()->didDraw(dirtyRect);
1663 } 1762 }
1664 1763
1665 GraphicsContext* CanvasRenderingContext2D::drawingContext() const 1764 GraphicsContext* CanvasRenderingContext2D::drawingContext() const
1666 { 1765 {
1766 if (isContextLost())
1767 return 0;
1667 return canvas()->drawingContext(); 1768 return canvas()->drawingContext();
1668 } 1769 }
1669 1770
1670 static PassRefPtrWillBeRawPtr<ImageData> createEmptyImageData(const IntSize& siz e) 1771 static PassRefPtrWillBeRawPtr<ImageData> createEmptyImageData(const IntSize& siz e)
1671 { 1772 {
1672 if (RefPtrWillBeRawPtr<ImageData> data = ImageData::create(size)) { 1773 if (RefPtrWillBeRawPtr<ImageData> data = ImageData::create(size)) {
1673 data->data()->zeroFill(); 1774 data->data()->zeroFill();
1674 return data.release(); 1775 return data.release();
1675 } 1776 }
1676 1777
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
1742 FloatRect logicalRect(sx, sy, sw, sh); 1843 FloatRect logicalRect(sx, sy, sw, sh);
1743 if (logicalRect.width() < 1) 1844 if (logicalRect.width() < 1)
1744 logicalRect.setWidth(1); 1845 logicalRect.setWidth(1);
1745 if (logicalRect.height() < 1) 1846 if (logicalRect.height() < 1)
1746 logicalRect.setHeight(1); 1847 logicalRect.setHeight(1);
1747 if (!logicalRect.isExpressibleAsIntRect()) 1848 if (!logicalRect.isExpressibleAsIntRect())
1748 return nullptr; 1849 return nullptr;
1749 1850
1750 IntRect imageDataRect = enclosingIntRect(logicalRect); 1851 IntRect imageDataRect = enclosingIntRect(logicalRect);
1751 ImageBuffer* buffer = canvas()->buffer(); 1852 ImageBuffer* buffer = canvas()->buffer();
1752 if (!buffer) 1853 if (!buffer || isContextLost())
1753 return createEmptyImageData(imageDataRect.size()); 1854 return createEmptyImageData(imageDataRect.size());
1754 1855
1755 RefPtr<Uint8ClampedArray> byteArray = buffer->getUnmultipliedImageData(image DataRect); 1856 RefPtr<Uint8ClampedArray> byteArray = buffer->getUnmultipliedImageData(image DataRect);
1756 if (!byteArray) 1857 if (!byteArray)
1757 return nullptr; 1858 return nullptr;
1758 1859
1759 return ImageData::create(imageDataRect.size(), byteArray.release()); 1860 return ImageData::create(imageDataRect.size(), byteArray.release());
1760 } 1861 }
1761 1862
1762 void CanvasRenderingContext2D::putImageData(ImageData* data, float dx, float dy, ExceptionState& exceptionState) 1863 void CanvasRenderingContext2D::putImageData(ImageData* data, float dx, float dy, ExceptionState& exceptionState)
(...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after
2296 c->setAlphaAsFloat(1.0); 2397 c->setAlphaAsFloat(1.0);
2297 c->clearShadow(); 2398 c->clearShadow();
2298 c->setCompositeOperation(CompositeSourceOver, blink::WebBlendModeNormal); 2399 c->setCompositeOperation(CompositeSourceOver, blink::WebBlendModeNormal);
2299 c->drawFocusRing(path, focusRingWidth, focusRingOutline, focusRingColor); 2400 c->drawFocusRing(path, focusRingWidth, focusRingOutline, focusRingColor);
2300 c->restore(); 2401 c->restore();
2301 2402
2302 didDraw(dirtyRect); 2403 didDraw(dirtyRect);
2303 } 2404 }
2304 2405
2305 } // namespace WebCore 2406 } // namespace WebCore
OLDNEW
« no previous file with comments | « Source/core/html/canvas/CanvasRenderingContext2D.h ('k') | Source/core/html/canvas/CanvasRenderingContext2D.idl » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698