26
|
1 /*
|
|
2 * Copyright 2010, Google Inc.
|
|
3 * All rights reserved.
|
|
4 *
|
|
5 * Redistribution and use in source and binary forms, with or without
|
|
6 * modification, are permitted provided that the following conditions are
|
|
7 * met:
|
|
8 *
|
|
9 * * Redistributions of source code must retain the above copyright
|
|
10 * notice, this list of conditions and the following disclaimer.
|
|
11 * * Redistributions in binary form must reproduce the above
|
|
12 * copyright notice, this list of conditions and the following disclaimer
|
|
13 * in the documentation and/or other materials provided with the
|
|
14 * distribution.
|
|
15 * * Neither the name of Google Inc. nor the names of its
|
|
16 * contributors may be used to endorse or promote products derived from
|
|
17 * this software without specific prior written permission.
|
|
18 *
|
|
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
30 */
|
|
31
|
|
32
|
|
33 /**
|
|
34 * @fileoverview This file contains functions every webgl program will need
|
|
35 * a version of one way or another.
|
|
36 *
|
|
37 * Instead of setting up a context manually it is recommended to
|
|
38 * use. This will check for success or failure. On failure it
|
|
39 * will attempt to present an approriate message to the user.
|
|
40 *
|
|
41 * gl = WebGLUtils.setupWebGL(canvas);
|
|
42 *
|
|
43 * For animated WebGL apps use of setTimeout or setInterval are
|
|
44 * discouraged. It is recommended you structure your rendering
|
|
45 * loop like this.
|
|
46 *
|
|
47 * function render() {
|
|
48 * WebGLUtils.requestAnimationFrame(canvas, render);
|
|
49 *
|
|
50 * // do rendering
|
|
51 * ...
|
|
52 * }
|
|
53 * render();
|
|
54 *
|
|
55 * This will call your rendering function up to the refresh rate
|
|
56 * of your display but will stop rendering if your app is not
|
|
57 * visible.
|
|
58 *
|
|
59 * To get an animationTime call
|
|
60 *
|
|
61 * timeInMilliSeconds = WebGLUtils.animationFrame();
|
|
62 */
|
|
63
|
|
64 WebGLUtils = function() {
|
|
65
|
|
66 var requestAnimationFrameImpl_;
|
|
67 var getAnimationTimeImpl_;
|
|
68
|
|
69 /**
|
|
70 * Creates the HTLM for a failure message
|
|
71 * @param {string} canvasContainerId id of container of th
|
|
72 * canvas.
|
|
73 * @return {string} The html.
|
|
74 */
|
|
75 var makeFailHTML = function(msg) {
|
|
76 return '' +
|
|
77 '<table style="background-color: #8CE; width: 100%; height: 100%;"><tr>' +
|
|
78 '<td align="center">' +
|
|
79 '<div style="display: table-cell; vertical-align: middle;">' +
|
|
80 '<div style="">' + msg + '</div>' +
|
|
81 '</div>' +
|
|
82 '</td></tr></table>';
|
|
83 };
|
|
84
|
|
85 /**
|
|
86 * Mesasge for getting a webgl browser
|
|
87 * @type {string}
|
|
88 */
|
|
89 var GET_A_WEBGL_BROWSER = '' +
|
|
90 'This page requires a browser that supports WebGL.<br/>' +
|
|
91 '<a href="http://get.webgl.org">Click here to upgrade your browser.</a>';
|
|
92
|
|
93 /**
|
|
94 * Mesasge for need better hardware
|
|
95 * @type {string}
|
|
96 */
|
|
97 var OTHER_PROBLEM = '' +
|
|
98 "It doesn't appear your computer can support WebGL.<br/>" +
|
|
99 '<a href="http://get.webgl.org/troubleshooting/">Click here for more information.</a>';
|
|
100
|
|
101 /**
|
|
102 * Creates a webgl context. If creation fails it will
|
|
103 * change the contents of the container of the <canvas>
|
|
104 * tag to an error message with the correct links for WebGL.
|
|
105 * @param {Element} canvas. The canvas element to create a
|
|
106 * context from.
|
|
107 * @param {WebGLContextCreationAttirbutes} opt_attribs Any
|
|
108 * creation attributes you want to pass in.
|
|
109 * @param {function:(msg)} opt_onError An function to call
|
|
110 * if there is an error during creation.
|
|
111 * @return {WebGLRenderingContext} The created context.
|
|
112 */
|
|
113 var setupWebGL = function(canvas, opt_attribs, opt_onError) {
|
|
114 function handleCreationError(msg) {
|
|
115 var container = canvas.parentNode;
|
|
116 if (container) {
|
|
117 var str = window.WebGLRenderingContext ?
|
|
118 OTHER_PROBLEM :
|
|
119 GET_A_WEBGL_BROWSER;
|
|
120 if (msg) {
|
|
121 str += "<br/><br/>Status: " + msg;
|
|
122 }
|
|
123 container.innerHTML = makeFailHTML(str);
|
|
124 }
|
|
125 };
|
|
126
|
|
127 opt_onError = opt_onError || handleCreationError;
|
|
128
|
|
129 if (canvas.addEventListener) {
|
|
130 canvas.addEventListener("webglcontextcreationerror", function(event) {
|
|
131 opt_onError(event.statusMessage);
|
|
132 }, false);
|
|
133 }
|
|
134 var context = create3DContext(canvas, opt_attribs);
|
|
135 if (!context) {
|
|
136 if (!window.WebGLRenderingContext) {
|
|
137 opt_onError("");
|
|
138 }
|
|
139 }
|
|
140 return context;
|
|
141 };
|
|
142
|
|
143 /**
|
|
144 * Creates a webgl context.
|
|
145 * @param {!Canvas} canvas The canvas tag to get context
|
|
146 * from. If one is not passed in one will be created.
|
|
147 * @return {!WebGLContext} The created context.
|
|
148 */
|
|
149 var create3DContext = function(canvas, opt_attribs) {
|
|
150 var names = ["webgl", "experimental-webgl", "webkit-3d", "moz-webgl"];
|
|
151 var context = null;
|
|
152 for (var ii = 0; ii < names.length; ++ii) {
|
|
153 try {
|
|
154 context = canvas.getContext(names[ii], opt_attribs);
|
|
155 } catch(e) {}
|
|
156 if (context) {
|
|
157 break;
|
|
158 }
|
|
159 }
|
|
160 return context;
|
|
161 }
|
|
162
|
|
163 /**
|
|
164 * Returns the animationTime in a cross browser way.
|
|
165 * @return {number} The current animationTime
|
|
166 */
|
|
167 var animationTime = function() {
|
|
168 if (!getAnimationTimeImpl_) {
|
|
169 getAnimationTimeImpl_ = function() {
|
|
170 var attribNames = [
|
|
171 "animationTime",
|
|
172 "webkitAnimationTime",
|
|
173 "mozAnimationTime",
|
|
174 "operaAnimationTime",
|
|
175 "msAnimationTime"
|
|
176 ];
|
|
177 for (var ii = 0; ii < attribNames.length; ++ii) {
|
|
178 var name = attribNames[ii];
|
|
179 if (window[name]) {
|
|
180 return function() {
|
|
181 return window[name];
|
|
182 };
|
|
183 }
|
|
184 }
|
|
185 return function() {
|
|
186 return (new Date()).getTime();
|
|
187 }
|
|
188 }();
|
|
189 }
|
|
190 return getAnimationTimeImpl_();
|
|
191 };
|
|
192
|
|
193 /**
|
|
194 * Provides requestAnimationFrame in a cross browser
|
|
195 * way.
|
|
196 *
|
|
197 * @param {!Element} element Element to request an animation frame for.
|
|
198 * @param {function(): void} callback. Callback that will be
|
|
199 * called when a frame is ready.
|
|
200 */
|
|
201 var requestAnimationFrame = function(element, callback) {
|
|
202 if (!requestAnimationFrameImpl_) {
|
|
203 requestAnimationFrameImpl_ = function() {
|
|
204 var objects = [element, window];
|
|
205 var functionNames = [
|
|
206 "requestAnimationFrame",
|
|
207 "webkitRequestAnimationFrame",
|
|
208 "mozRequestAnimationFrame",
|
|
209 "operaRequestAnimationFrame",
|
|
210 "msRequestAnimationFrame"
|
|
211 ];
|
|
212 var functions = [
|
|
213 function (name) {
|
|
214 return function(element, callback) {
|
|
215 element[name].call(element, callback);
|
|
216 };
|
|
217 },
|
|
218 function (name) {
|
|
219 return function(element, callback) {
|
|
220 window[name].call(window, callback);
|
|
221 };
|
|
222 }
|
|
223 ];
|
|
224 for (var ii = 0; ii < objects.length; ++ii) {
|
|
225 var obj = objects[ii];
|
|
226 for (var jj = 0; jj < functionNames.length; ++jj) {
|
|
227 var functionName = functionNames[jj];
|
|
228 if (obj[functionName]) {
|
|
229 return functions[ii](functionName);
|
|
230 }
|
|
231 }
|
|
232 }
|
|
233 return function(element, callback) {
|
|
234 window.setTimeout(callback, 1000 / 70);
|
|
235 };
|
|
236 }();
|
|
237 }
|
|
238
|
|
239 requestAnimationFrameImpl_(element, callback)
|
|
240 };
|
|
241
|
|
242 return {
|
|
243 animationTime: animationTime,
|
|
244 create3DContext: create3DContext,
|
|
245 requestAnimationFrame: requestAnimationFrame,
|
|
246 setupWebGL: setupWebGL
|
|
247 };
|
|
248 }();
|