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

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: adding missing file Created 6 years, 9 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 TryRestoreSurfaceInterval = 0.5;
80 static const unsigned MaxTryRestoreSurfaceAttemps = 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_stateStack(1) 89 , m_stateStack(1)
83 , m_usesCSSCompatibilityParseMode(usesCSSCompatibilityParseMode) 90 , m_usesCSSCompatibilityParseMode(usesCSSCompatibilityParseMode)
84 , m_hasAlpha(!attrs || attrs->alpha()) 91 , m_hasAlpha(!attrs || attrs->alpha())
92 , m_isContextLost(false)
93 , m_contextRestorable(true)
94 , m_storageMode(!attrs ? PersistentStorage : attrs->parsedStorage())
95 , m_tryRestoreSurfaceAttemptCount(0)
96 , m_dispatchContextLostEventTimer(this, &CanvasRenderingContext2D::dispatchC ontextLostEvent)
97 , m_dispatchContextRestoredEventTimer(this, &CanvasRenderingContext2D::dispa tchContextRestoredEvent)
98 , m_tryRestoreSurfaceEventTimer(this, &CanvasRenderingContext2D::tryRestoreS urfaceEvent)
85 { 99 {
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.
94 if (size_t stackSize = m_stateStack.size()) { 108 if (size_t stackSize = m_stateStack.size()) {
(...skipping 12 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_tryRestoreSurfaceAttemptCount = 0;
177 m_tryRestoreSurfaceEventTimer.startRepeating(TryRestoreSurfaceInterval, FROM_HERE);
178 }
179 }
180
181 void CanvasRenderingContext2D::tryRestoreSurfaceEvent(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_tryRestoreSurfaceEventTimer.stop();
186 return;
187 }
188 if (canvas()->hasImageBuffer() && canvas()->buffer()->restoreSurface()) {
189 m_tryRestoreSurfaceEventTimer.stop();
190 dispatchContextRestoredEvent(0);
191 }
192
193 if (++m_tryRestoreSurfaceAttemptCount > MaxTryRestoreSurfaceAttemps)
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() = State(); 220 m_stateStack.first() = 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 1531 matching lines...) Expand 10 before | Expand all | Expand 10 after
1658 canvas()->notifyObserversCanvasChanged(dirtyRect); 1757 canvas()->notifyObserversCanvasChanged(dirtyRect);
1659 return; 1758 return;
1660 } 1759 }
1661 } 1760 }
1662 1761
1663 canvas()->didDraw(dirtyRect); 1762 canvas()->didDraw(dirtyRect);
1664 } 1763 }
1665 1764
1666 GraphicsContext* CanvasRenderingContext2D::drawingContext() const 1765 GraphicsContext* CanvasRenderingContext2D::drawingContext() const
1667 { 1766 {
1767 if (isContextLost())
1768 return 0;
1668 return canvas()->drawingContext(); 1769 return canvas()->drawingContext();
1669 } 1770 }
1670 1771
1671 static PassRefPtr<ImageData> createEmptyImageData(const IntSize& size) 1772 static PassRefPtr<ImageData> createEmptyImageData(const IntSize& size)
1672 { 1773 {
1673 if (RefPtr<ImageData> data = ImageData::create(size)) { 1774 if (RefPtr<ImageData> data = ImageData::create(size)) {
1674 data->data()->zeroFill(); 1775 data->data()->zeroFill();
1675 return data.release(); 1776 return data.release();
1676 } 1777 }
1677 1778
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
1748 FloatRect logicalRect(sx, sy, sw, sh); 1849 FloatRect logicalRect(sx, sy, sw, sh);
1749 if (logicalRect.width() < 1) 1850 if (logicalRect.width() < 1)
1750 logicalRect.setWidth(1); 1851 logicalRect.setWidth(1);
1751 if (logicalRect.height() < 1) 1852 if (logicalRect.height() < 1)
1752 logicalRect.setHeight(1); 1853 logicalRect.setHeight(1);
1753 if (!logicalRect.isExpressibleAsIntRect()) 1854 if (!logicalRect.isExpressibleAsIntRect())
1754 return nullptr; 1855 return nullptr;
1755 1856
1756 IntRect imageDataRect = enclosingIntRect(logicalRect); 1857 IntRect imageDataRect = enclosingIntRect(logicalRect);
1757 ImageBuffer* buffer = canvas()->buffer(); 1858 ImageBuffer* buffer = canvas()->buffer();
1758 if (!buffer) 1859 if (!buffer || isContextLost())
1759 return createEmptyImageData(imageDataRect.size()); 1860 return createEmptyImageData(imageDataRect.size());
1760 1861
1761 RefPtr<Uint8ClampedArray> byteArray = buffer->getUnmultipliedImageData(image DataRect); 1862 RefPtr<Uint8ClampedArray> byteArray = buffer->getUnmultipliedImageData(image DataRect);
1762 if (!byteArray) 1863 if (!byteArray)
1763 return nullptr; 1864 return nullptr;
1764 1865
1765 return ImageData::create(imageDataRect.size(), byteArray.release()); 1866 return ImageData::create(imageDataRect.size(), byteArray.release());
1766 } 1867 }
1767 1868
1768 void CanvasRenderingContext2D::putImageData(ImageData* data, float dx, float dy, ExceptionState& exceptionState) 1869 void CanvasRenderingContext2D::putImageData(ImageData* data, float dx, float dy, ExceptionState& exceptionState)
(...skipping 531 matching lines...) Expand 10 before | Expand all | Expand 10 after
2300 c->setAlphaAsFloat(1.0); 2401 c->setAlphaAsFloat(1.0);
2301 c->clearShadow(); 2402 c->clearShadow();
2302 c->setCompositeOperation(CompositeSourceOver, blink::WebBlendModeNormal); 2403 c->setCompositeOperation(CompositeSourceOver, blink::WebBlendModeNormal);
2303 c->drawFocusRing(path, focusRingWidth, focusRingOutline, focusRingColor); 2404 c->drawFocusRing(path, focusRingWidth, focusRingOutline, focusRingColor);
2304 c->restore(); 2405 c->restore();
2305 2406
2306 didDraw(dirtyRect); 2407 didDraw(dirtyRect);
2307 } 2408 }
2308 2409
2309 } // namespace WebCore 2410 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698