OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2009 Apple Inc. All rights reserved. | 2 * Copyright (C) 2009 Apple Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
55 #include "WebGLRenderbuffer.h" | 55 #include "WebGLRenderbuffer.h" |
56 #include "WebGLShader.h" | 56 #include "WebGLShader.h" |
57 #include "WebGLTexture.h" | 57 #include "WebGLTexture.h" |
58 #include "WebGLUniformLocation.h" | 58 #include "WebGLUniformLocation.h" |
59 | 59 |
60 #include <wtf/ByteArray.h> | 60 #include <wtf/ByteArray.h> |
61 #include <wtf/OwnArrayPtr.h> | 61 #include <wtf/OwnArrayPtr.h> |
62 | 62 |
63 namespace WebCore { | 63 namespace WebCore { |
64 | 64 |
| 65 const double secondsBetweenRestoreAttempts = 1.0; |
| 66 |
65 static inline Platform3DObject objectOrZero(WebGLObject* object) | 67 static inline Platform3DObject objectOrZero(WebGLObject* object) |
66 { | 68 { |
67 return object ? object->object() : 0; | 69 return object ? object->object() : 0; |
68 } | 70 } |
69 | 71 |
70 class WebGLStateRestorer { | 72 class WebGLStateRestorer { |
71 public: | 73 public: |
72 WebGLStateRestorer(WebGLRenderingContext* context, | 74 WebGLStateRestorer(WebGLRenderingContext* context, |
73 bool changed) | 75 bool changed) |
74 : m_context(context) | 76 : m_context(context) |
75 , m_changed(changed) | 77 , m_changed(changed) |
76 { | 78 { |
77 } | 79 } |
78 | 80 |
79 ~WebGLStateRestorer() | 81 ~WebGLStateRestorer() |
80 { | 82 { |
81 m_context->cleanupAfterGraphicsCall(m_changed); | 83 m_context->cleanupAfterGraphicsCall(m_changed); |
82 } | 84 } |
83 | 85 |
84 private: | 86 private: |
85 WebGLRenderingContext* m_context; | 87 WebGLRenderingContext* m_context; |
86 bool m_changed; | 88 bool m_changed; |
87 }; | 89 }; |
88 | 90 |
| 91 void WebGLRenderingContext::WebGLRenderingContextRestoreTimer::fired() |
| 92 { |
| 93 // Timer is started when m_contextLost is false. It will first call |
| 94 // loseContext, which will set m_contextLost to true. Then it will keep |
| 95 // calling restoreContext and reschedule itself until m_contextLost is back |
| 96 // to false. |
| 97 if (!m_context->m_contextLost) { |
| 98 m_context->loseContext(); |
| 99 startOneShot(secondsBetweenRestoreAttempts); |
| 100 } else { |
| 101 // The rendering context is not restored if there is no handler for |
| 102 // the context restored event. |
| 103 if (!m_context->canvas()->hasEventListeners(eventNames().webglcontextres
toredEvent)) |
| 104 return; |
| 105 |
| 106 m_context->restoreContext(); |
| 107 if (m_context->m_contextLost) |
| 108 startOneShot(secondsBetweenRestoreAttempts); |
| 109 } |
| 110 } |
| 111 |
89 PassOwnPtr<WebGLRenderingContext> WebGLRenderingContext::create(HTMLCanvasElemen
t* canvas, WebGLContextAttributes* attrs) | 112 PassOwnPtr<WebGLRenderingContext> WebGLRenderingContext::create(HTMLCanvasElemen
t* canvas, WebGLContextAttributes* attrs) |
90 { | 113 { |
91 HostWindow* hostWindow = canvas->document()->view()->root()->hostWindow(); | 114 HostWindow* hostWindow = canvas->document()->view()->root()->hostWindow(); |
92 GraphicsContext3D::Attributes emptyAttributes; | 115 GraphicsContext3D::Attributes attributes = attrs ? attrs->attributes() : Gra
phicsContext3D::Attributes(); |
93 RefPtr<GraphicsContext3D> context(GraphicsContext3D::create(attrs ? attrs->a
ttributes() : emptyAttributes, hostWindow)); | 116 RefPtr<GraphicsContext3D> context(GraphicsContext3D::create(attributes, host
Window)); |
94 | 117 |
95 if (!context) { | 118 if (!context) { |
96 canvas->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontex
tcreationerrorEvent, false, true, "Could not create a WebGL context.")); | 119 canvas->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontex
tcreationerrorEvent, false, true, "Could not create a WebGL context.")); |
97 return 0; | 120 return 0; |
98 } | 121 } |
99 | 122 |
100 return new WebGLRenderingContext(canvas, context); | 123 return new WebGLRenderingContext(canvas, context, attributes); |
101 } | 124 } |
102 | 125 |
103 WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, Pa
ssRefPtr<GraphicsContext3D> context) | 126 WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, Pa
ssRefPtr<GraphicsContext3D> context, |
| 127 GraphicsContext3D::Attributes attri
butes) |
104 : CanvasRenderingContext(passedCanvas) | 128 : CanvasRenderingContext(passedCanvas) |
105 , m_context(context) | 129 , m_context(context) |
| 130 , m_restoreTimer(this) |
106 , m_videoCache(4) | 131 , m_videoCache(4) |
107 , m_contextLost(false) | 132 , m_contextLost(false) |
| 133 , m_attributes(attributes) |
108 { | 134 { |
109 ASSERT(m_context); | 135 ASSERT(m_context); |
110 setupFlags(); | 136 setupFlags(); |
111 initializeNewContext(); | 137 initializeNewContext(); |
112 } | 138 } |
113 | 139 |
114 void WebGLRenderingContext::initializeNewContext() | 140 void WebGLRenderingContext::initializeNewContext() |
115 { | 141 { |
116 m_needsUpdate = true; | 142 m_needsUpdate = true; |
117 m_markedCanvasDirty = false; | 143 m_markedCanvasDirty = false; |
(...skipping 1965 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2083 { | 2109 { |
2084 if (!buffer || isContextLost()) | 2110 if (!buffer || isContextLost()) |
2085 return false; | 2111 return false; |
2086 | 2112 |
2087 if (!buffer->hasEverBeenBound()) | 2113 if (!buffer->hasEverBeenBound()) |
2088 return false; | 2114 return false; |
2089 | 2115 |
2090 return m_context->isBuffer(buffer->object()); | 2116 return m_context->isBuffer(buffer->object()); |
2091 } | 2117 } |
2092 | 2118 |
2093 bool WebGLRenderingContext::isContextLost() const | 2119 bool WebGLRenderingContext::isContextLost() |
2094 { | 2120 { |
| 2121 if (m_restoreTimer.isActive()) |
| 2122 return true; |
| 2123 |
| 2124 bool newContextLost = m_context->getExtensions()->getGraphicsResetStatusARB(
) != GraphicsContext3D::NO_ERROR; |
| 2125 |
| 2126 if (newContextLost != m_contextLost) |
| 2127 m_restoreTimer.startOneShot(secondsBetweenRestoreAttempts); |
| 2128 |
2095 return m_contextLost; | 2129 return m_contextLost; |
2096 } | 2130 } |
2097 | 2131 |
2098 bool WebGLRenderingContext::isEnabled(unsigned long cap) | 2132 bool WebGLRenderingContext::isEnabled(unsigned long cap) |
2099 { | 2133 { |
2100 if (!validateCapability(cap) || isContextLost()) | 2134 if (!validateCapability(cap) || isContextLost()) |
2101 return false; | 2135 return false; |
2102 return m_context->isEnabled(cap); | 2136 return m_context->isEnabled(cap); |
2103 } | 2137 } |
2104 | 2138 |
(...skipping 1133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3238 if (isnan(width)) | 3272 if (isnan(width)) |
3239 width = 100; | 3273 width = 100; |
3240 if (isnan(height)) | 3274 if (isnan(height)) |
3241 height = 100; | 3275 height = 100; |
3242 m_context->viewport(x, y, width, height); | 3276 m_context->viewport(x, y, width, height); |
3243 cleanupAfterGraphicsCall(false); | 3277 cleanupAfterGraphicsCall(false); |
3244 } | 3278 } |
3245 | 3279 |
3246 void WebGLRenderingContext::loseContext() | 3280 void WebGLRenderingContext::loseContext() |
3247 { | 3281 { |
3248 if (isContextLost()) | |
3249 return; | |
3250 | |
3251 m_contextLost = true; | 3282 m_contextLost = true; |
3252 | 3283 |
3253 detachAndRemoveAllObjects(); | 3284 detachAndRemoveAllObjects(); |
3254 | 3285 |
3255 // There is no direct way to clear errors from a GL implementation and | 3286 // There is no direct way to clear errors from a GL implementation and |
3256 // looping until getError() becomes NO_ERROR might cause an infinite loop if | 3287 // looping until getError() becomes NO_ERROR might cause an infinite loop if |
3257 // the driver or context implementation had a bug. So, loop a reasonably | 3288 // the driver or context implementation had a bug. So, loop a reasonably |
3258 // large number of times to clear any existing errors. | 3289 // large number of times to clear any existing errors. |
3259 for (int i = 0; i < 100; ++i) { | 3290 for (int i = 0; i < 100; ++i) { |
3260 if (m_context->getError() == GraphicsContext3D::NO_ERROR) | 3291 if (m_context->getError() == GraphicsContext3D::NO_ERROR) |
3261 break; | 3292 break; |
3262 } | 3293 } |
3263 m_context->synthesizeGLError(GraphicsContext3D::CONTEXT_LOST_WEBGL); | 3294 m_context->synthesizeGLError(GraphicsContext3D::CONTEXT_LOST_WEBGL); |
3264 | 3295 |
3265 canvas()->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextl
ostEvent, false, true, "")); | 3296 canvas()->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextl
ostEvent, false, true, "")); |
3266 } | 3297 } |
3267 | 3298 |
3268 void WebGLRenderingContext::restoreContext() | 3299 void WebGLRenderingContext::restoreContext() |
3269 { | 3300 { |
3270 if (!isContextLost()) | 3301 RefPtr<GraphicsContext3D> context(GraphicsContext3D::create(m_attributes, ca
nvas()->document()->view()->root()->hostWindow())); |
| 3302 if (!context) |
3271 return; | 3303 return; |
3272 | 3304 |
3273 // The rendering context is not restored if there is no handler for | 3305 m_context = context; |
3274 // the context restored event. | 3306 initializeNewContext(); |
3275 if (!canvas()->hasEventListeners(eventNames().webglcontextrestoredEvent)) | |
3276 return; | |
3277 | |
3278 m_contextLost = false; | 3307 m_contextLost = false; |
3279 initializeNewContext(); | |
3280 | |
3281 canvas()->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextr
estoredEvent, false, true, "")); | 3308 canvas()->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextr
estoredEvent, false, true, "")); |
3282 } | 3309 } |
3283 | 3310 |
3284 void WebGLRenderingContext::removeObject(WebGLObject* object) | 3311 void WebGLRenderingContext::removeObject(WebGLObject* object) |
3285 { | 3312 { |
3286 m_canvasObjects.remove(object); | 3313 m_canvasObjects.remove(object); |
3287 } | 3314 } |
3288 | 3315 |
3289 void WebGLRenderingContext::addObject(WebGLObject* object) | 3316 void WebGLRenderingContext::addObject(WebGLObject* object) |
3290 { | 3317 { |
(...skipping 793 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4084 | 4111 |
4085 void WebGLRenderingContext::LRUImageBufferCache::bubbleToFront(int idx) | 4112 void WebGLRenderingContext::LRUImageBufferCache::bubbleToFront(int idx) |
4086 { | 4113 { |
4087 for (int i = idx; i > 0; --i) | 4114 for (int i = idx; i > 0; --i) |
4088 m_buffers[i].swap(m_buffers[i-1]); | 4115 m_buffers[i].swap(m_buffers[i-1]); |
4089 } | 4116 } |
4090 | 4117 |
4091 } // namespace WebCore | 4118 } // namespace WebCore |
4092 | 4119 |
4093 #endif // ENABLE(3D_CANVAS) | 4120 #endif // ENABLE(3D_CANVAS) |
OLD | NEW |