OLD | NEW |
| (Empty) |
1 <!-- | |
2 Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
3 Use of this source code is governed by a BSD-style license that can be | |
4 found in the LICENSE file. | |
5 --> | |
6 <!DOCTYPE html> | |
7 <html> | |
8 <head> | |
9 <meta charset="utf-8"> | |
10 <link rel="stylesheet" href="../resources/js-test-style.css"/> | |
11 <script src="../resources/js-test-pre.js"></script> | |
12 <script src="resources/pnglib.js"></script> | |
13 <script src="resources/webgl-test.js"></script> | |
14 <script src="resources/webgl-test-utils.js"></script> | |
15 | |
16 <script> | |
17 var wtu = WebGLTestUtils; | |
18 var gl = null; | |
19 var textureLoc = null; | |
20 var successfullyParsed = false; | |
21 | |
22 //---------------------------------------------------------------------- | |
23 // Harness | |
24 | |
25 var testCases = []; | |
26 | |
27 var DataMode = { | |
28 IMAGE: 0, | |
29 IMAGE_DATA: 1, | |
30 | |
31 NUM_HTML_MODES: 2, | |
32 | |
33 RAW_DATA: 2, | |
34 | |
35 // This must remain the last mode. | |
36 NUM_MODES: 3 | |
37 }; | |
38 | |
39 function init() | |
40 { | |
41 if (window.initNonKhronosFramework) { | |
42 window.initNonKhronosFramework(true); | |
43 } | |
44 | |
45 description('Verify texImage2D and texSubImage2D code paths taking both HTML
and user-specified data with all format/type combinations'); | |
46 | |
47 var canvas = document.getElementById("example"); | |
48 gl = wtu.create3DContext(canvas); | |
49 var program = wtu.setupTexturedQuad(gl); | |
50 | |
51 gl.clearColor(0,0,0,1); | |
52 gl.clearDepth(1); | |
53 gl.disable(gl.BLEND); | |
54 | |
55 textureLoc = gl.getUniformLocation(program, "tex"); | |
56 | |
57 initializeTests(); | |
58 } | |
59 | |
60 function initializeTests() | |
61 { | |
62 // Verify that uploading to packed pixel formats performs the | |
63 // required conversion and associated loss of precision. | |
64 for (var dataMode = 0; dataMode < DataMode.NUM_HTML_MODES; ++dataMode) { | |
65 for (var useTexSubImage2D = 0; useTexSubImage2D < 2; ++useTexSubImage2D)
{ | |
66 testCases.push({ | |
67 dataMode: dataMode, | |
68 useTexSubImage2D: !!useTexSubImage2D, | |
69 width: 256, | |
70 height: 1, | |
71 generator: generateOpaqueGrayscaleRamp, | |
72 premultiplyAlpha: false, | |
73 format: gl.RGBA, | |
74 type: gl.UNSIGNED_BYTE, | |
75 verifier: allChannelsIncreaseByNoMoreThan, | |
76 threshold: 1, | |
77 numOccurrences: 1, | |
78 description: "RGBA/UNSIGNED_BYTE should maintain full precision
of data" | |
79 }); | |
80 testCases.push({ | |
81 dataMode: dataMode, | |
82 useTexSubImage2D: !!useTexSubImage2D, | |
83 width: 256, | |
84 height: 1, | |
85 generator: generateOpaqueGrayscaleRamp, | |
86 premultiplyAlpha: false, | |
87 format: gl.RGBA, | |
88 type: gl.UNSIGNED_SHORT_4_4_4_4, | |
89 verifier: allChannelsIncreaseByAtLeast, | |
90 threshold: 15, | |
91 numOccurrences: 10, | |
92 description: "RGBA/UNSIGNED_SHORT_4_4_4_4 must drop low four bit
s of precision" | |
93 }); | |
94 testCases.push({ | |
95 dataMode: dataMode, | |
96 useTexSubImage2D: !!useTexSubImage2D, | |
97 width: 256, | |
98 height: 1, | |
99 generator: generateOpaqueGrayscaleRamp, | |
100 premultiplyAlpha: false, | |
101 format: gl.RGBA, | |
102 type: gl.UNSIGNED_SHORT_5_5_5_1, | |
103 verifier: allChannelsIncreaseByAtLeast, | |
104 threshold: 7, | |
105 numOccurrences: 20, | |
106 description: "RGBA/UNSIGNED_SHORT_5_5_5_1 must drop low three bi
ts of precision" | |
107 }); | |
108 testCases.push({ | |
109 dataMode: dataMode, | |
110 useTexSubImage2D: !!useTexSubImage2D, | |
111 width: 256, | |
112 height: 1, | |
113 generator: generateOpaqueGrayscaleRamp, | |
114 premultiplyAlpha: false, | |
115 format: gl.RGB, | |
116 type: gl.UNSIGNED_BYTE, | |
117 verifier: allChannelsIncreaseByNoMoreThan, | |
118 threshold: 1, | |
119 numOccurrences: 1, | |
120 description: "RGB/UNSIGNED_BYTE should maintain full precision o
f data" | |
121 }); | |
122 testCases.push({ | |
123 dataMode: dataMode, | |
124 useTexSubImage2D: !!useTexSubImage2D, | |
125 width: 256, | |
126 height: 1, | |
127 generator: generateOpaqueGrayscaleRamp, | |
128 premultiplyAlpha: false, | |
129 format: gl.RGB, | |
130 type: gl.UNSIGNED_SHORT_5_6_5, | |
131 verifier: allChannelsIncreaseByAtLeast, | |
132 threshold: 3, | |
133 numOccurrences: 20, | |
134 description: "RGB/UNSIGNED_SHORT_5_6_5 must drop low two or thre
e bits of precision" | |
135 }); | |
136 testCases.push({ | |
137 dataMode: dataMode, | |
138 useTexSubImage2D: !!useTexSubImage2D, | |
139 width: 256, | |
140 height: 1, | |
141 generator: generateTranslucentGrayscaleRamp, | |
142 premultiplyAlpha: false, | |
143 format: gl.ALPHA, | |
144 type: gl.UNSIGNED_BYTE, | |
145 verifier: alphaChannelIncreasesByNoMoreThan, | |
146 threshold: 1, | |
147 numOccurrences: 1, | |
148 description: "ALPHA/UNSIGNED_BYTE should maintain full precision
of data" | |
149 }); | |
150 testCases.push({ | |
151 dataMode: dataMode, | |
152 useTexSubImage2D: !!useTexSubImage2D, | |
153 width: 256, | |
154 height: 1, | |
155 generator: generateOpaqueGrayscaleRamp, | |
156 premultiplyAlpha: false, | |
157 format: gl.LUMINANCE, | |
158 type: gl.UNSIGNED_BYTE, | |
159 verifier: allChannelsIncreaseByNoMoreThan, | |
160 threshold: 1, | |
161 numOccurrences: 1, | |
162 description: "LUMINANCE/UNSIGNED_BYTE should maintain full preci
sion of data" | |
163 }); | |
164 testCases.push({ | |
165 dataMode: dataMode, | |
166 useTexSubImage2D: !!useTexSubImage2D, | |
167 width: 256, | |
168 height: 1, | |
169 generator: generateOpaqueGrayscaleRamp, | |
170 premultiplyAlpha: false, | |
171 format: gl.LUMINANCE_ALPHA, | |
172 type: gl.UNSIGNED_BYTE, | |
173 verifier: allChannelsIncreaseByNoMoreThan, | |
174 threshold: 1, | |
175 numOccurrences: 1, | |
176 description: "LUMINANCE_ALPHA/UNSIGNED_BYTE should maintain full
precision of data" | |
177 }); | |
178 } | |
179 } | |
180 | |
181 // Verify that setting the UNPACK_PREMULTIPLY_ALPHA_WEBGL pixel | |
182 // store parameter and sending down a zero alpha causes the color | |
183 // channels to go to zero. | |
184 for (var dataMode = 0; dataMode < DataMode.NUM_MODES; ++dataMode) { | |
185 for (var useTexSubImage2D = 0; useTexSubImage2D < 2; ++useTexSubImage2D)
{ | |
186 testCases.push({ | |
187 dataMode: dataMode, | |
188 useTexSubImage2D: !!useTexSubImage2D, | |
189 width: 256, | |
190 height: 1, | |
191 generator: generateTransparentGrayscaleRamp, | |
192 premultiplyAlpha: true, | |
193 format: gl.RGBA, | |
194 type: gl.UNSIGNED_BYTE, | |
195 verifier: colorChannelsAreZero, | |
196 description: "UNPACK_PREMULTIPLY_ALPHA_WEBGL with RGBA/UNSIGNED_
BYTE" | |
197 }); | |
198 testCases.push({ | |
199 dataMode: dataMode, | |
200 useTexSubImage2D: !!useTexSubImage2D, | |
201 width: 256, | |
202 height: 1, | |
203 generator: generateTransparentGrayscaleRamp, | |
204 premultiplyAlpha: true, | |
205 format: gl.RGBA, | |
206 type: gl.UNSIGNED_SHORT_4_4_4_4, | |
207 verifier: colorChannelsAreZero, | |
208 description: "UNPACK_PREMULTIPLY_ALPHA_WEBGL with RGBA/UNSIGNED_
SHORT_4_4_4_4" | |
209 }); | |
210 testCases.push({ | |
211 dataMode: dataMode, | |
212 useTexSubImage2D: !!useTexSubImage2D, | |
213 width: 256, | |
214 height: 1, | |
215 generator: generateTransparentGrayscaleRamp, | |
216 premultiplyAlpha: true, | |
217 format: gl.RGBA, | |
218 type: gl.UNSIGNED_SHORT_5_5_5_1, | |
219 verifier: colorChannelsAreZero, | |
220 description: "UNPACK_PREMULTIPLY_ALPHA_WEBGL with RGBA/UNSIGNED_
SHORT_5_5_5_1" | |
221 }); | |
222 // The following few tests are invalid for the raw data | |
223 // mode because there is either no alpha channel or no | |
224 // separate alpha channel. | |
225 if (dataMode != DataMode.RAW_DATA) { | |
226 testCases.push({ | |
227 dataMode: dataMode, | |
228 useTexSubImage2D: !!useTexSubImage2D, | |
229 width: 256, | |
230 height: 1, | |
231 generator: generateTransparentGrayscaleRamp, | |
232 premultiplyAlpha: true, | |
233 format: gl.RGB, | |
234 type: gl.UNSIGNED_BYTE, | |
235 verifier: colorChannelsAreZero, | |
236 description: "UNPACK_PREMULTIPLY_ALPHA_WEBGL with RGB/UNSIGN
ED_BYTE" | |
237 }); | |
238 testCases.push({ | |
239 dataMode: dataMode, | |
240 useTexSubImage2D: !!useTexSubImage2D, | |
241 width: 256, | |
242 height: 1, | |
243 generator: generateTransparentGrayscaleRamp, | |
244 premultiplyAlpha: true, | |
245 format: gl.RGB, | |
246 type: gl.UNSIGNED_SHORT_5_6_5, | |
247 verifier: colorChannelsAreZero, | |
248 description: "UNPACK_PREMULTIPLY_ALPHA_WEBGL with RGB/UNSIGN
ED_SHORT_5_6_5" | |
249 }); | |
250 testCases.push({ | |
251 dataMode: dataMode, | |
252 useTexSubImage2D: !!useTexSubImage2D, | |
253 width: 256, | |
254 height: 1, | |
255 generator: generateTransparentGrayscaleRamp, | |
256 premultiplyAlpha: true, | |
257 format: gl.ALPHA, | |
258 type: gl.UNSIGNED_BYTE, | |
259 verifier: colorChannelsAreZero, | |
260 description: "UNPACK_PREMULTIPLY_ALPHA_WEBGL with ALPHA/UNSI
GNED_BYTE" | |
261 }); | |
262 testCases.push({ | |
263 dataMode: dataMode, | |
264 useTexSubImage2D: !!useTexSubImage2D, | |
265 width: 256, | |
266 height: 1, | |
267 generator: generateTransparentGrayscaleRamp, | |
268 premultiplyAlpha: true, | |
269 format: gl.LUMINANCE, | |
270 type: gl.UNSIGNED_BYTE, | |
271 verifier: colorChannelsAreZero, | |
272 description: "UNPACK_PREMULTIPLY_ALPHA_WEBGL with LUMINANCE/
UNSIGNED_BYTE" | |
273 }); | |
274 } | |
275 testCases.push({ | |
276 dataMode: dataMode, | |
277 useTexSubImage2D: !!useTexSubImage2D, | |
278 width: 256, | |
279 height: 1, | |
280 generator: generateTransparentGrayscaleRamp, | |
281 premultiplyAlpha: true, | |
282 format: gl.LUMINANCE_ALPHA, | |
283 type: gl.UNSIGNED_BYTE, | |
284 verifier: colorChannelsAreZero, | |
285 description: "UNPACK_PREMULTIPLY_ALPHA_WEBGL with LUMINANCE_ALPH
A/UNSIGNED_BYTE" | |
286 }); | |
287 } | |
288 } | |
289 | |
290 // Produce data for all testcases. Because we load images, some of | |
291 // these may generate their data asynchronously. | |
292 generateTestData(); | |
293 } | |
294 | |
295 function generateTestData() | |
296 { | |
297 for (var i = 0; i < testCases.length; i++) { | |
298 var testCase = testCases[i]; | |
299 var wrapper = null; | |
300 switch (testCase.dataMode) { | |
301 case DataMode.IMAGE: | |
302 wrapper = new ImageWrapper(testCase.width, testCase.height); | |
303 break; | |
304 case DataMode.IMAGE_DATA: | |
305 wrapper = new ImageDataWrapper(testCase.width, testCase.height); | |
306 break; | |
307 case DataMode.RAW_DATA: | |
308 switch (testCase.type) { | |
309 case gl.UNSIGNED_BYTE: | |
310 switch (testCase.format) { | |
311 case gl.RGBA: | |
312 wrapper = new RGBA8DataWrapper(testCase.width, testCase.heig
ht); | |
313 break; | |
314 case gl.RGB: | |
315 wrapper = new RGB8DataWrapper(testCase.width, testCase.heigh
t); | |
316 break; | |
317 case gl.ALPHA: | |
318 wrapper = new A8DataWrapper(testCase.width, testCase.height)
; | |
319 break; | |
320 case gl.LUMINANCE: | |
321 wrapper = new L8DataWrapper(testCase.width, testCase.height)
; | |
322 break; | |
323 case gl.LUMINANCE_ALPHA: | |
324 wrapper = new LA8DataWrapper(testCase.width, testCase.height
); | |
325 break; | |
326 } | |
327 break; | |
328 case gl.UNSIGNED_SHORT_4_4_4_4: | |
329 wrapper = new RGBA4444DataWrapper(testCase.width, testCase.heigh
t); | |
330 break; | |
331 case gl.UNSIGNED_SHORT_5_5_5_1: | |
332 wrapper = new RGBA5551DataWrapper(testCase.width, testCase.heigh
t); | |
333 break; | |
334 case gl.UNSIGNED_SHORT_5_6_5: | |
335 wrapper = new RGB565DataWrapper(testCase.width, testCase.height)
; | |
336 break; | |
337 } | |
338 } | |
339 testCase.wrapper = wrapper; | |
340 testCase.generator(wrapper); | |
341 testCase.wrapper.generateData(); | |
342 } | |
343 | |
344 // See whether we need to run the tests, in case all of them | |
345 // generated their results synchronously. | |
346 maybeRunTests(); | |
347 } | |
348 | |
349 var ranTests = false; | |
350 | |
351 function maybeRunTests() | |
352 { | |
353 if (!ranTests) | |
354 for (var i = 0; i < testCases.length; ++i) | |
355 if (!testCases[i].wrapper || !testCases[i].wrapper.data) | |
356 return; | |
357 | |
358 ranTests = true; | |
359 | |
360 for (var i = 0; i < testCases.length; ++i) | |
361 runOneTest(testCases[i]); | |
362 | |
363 finishTest(); | |
364 } | |
365 | |
366 function testCaseToString(testCase) | |
367 { | |
368 var mode; | |
369 switch (testCase.dataMode) { | |
370 case DataMode.IMAGE: | |
371 mode = "Image"; | |
372 break; | |
373 case DataMode.IMAGE_DATA: | |
374 mode = "ImageData"; | |
375 break; | |
376 case DataMode.RAW_DATA: | |
377 mode = "raw data"; | |
378 break; | |
379 } | |
380 return (testCase.useTexSubImage2D ? "texSubImage2D" : "texImage2D") + | |
381 " with " + mode + " at " + testCase.width + "x" + testCase.height; | |
382 } | |
383 | |
384 function runOneTest(testCase) | |
385 { | |
386 debug("Testing " + testCaseToString(testCase)); | |
387 var data = testCase.wrapper.data; | |
388 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); | |
389 var texture = gl.createTexture(); | |
390 // Bind the texture to texture unit 0. | |
391 gl.bindTexture(gl.TEXTURE_2D, texture); | |
392 // Set up texture parameters. | |
393 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); | |
394 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); | |
395 // Set up pixel store parameters. | |
396 gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, testCase.premultiplyAlpha)
; | |
397 // Upload the image into the texture. | |
398 if (testCase.useTexSubImage2D) { | |
399 // Initialize the texture to black first. | |
400 gl.texImage2D(gl.TEXTURE_2D, 0, testCase.format, testCase.width, testCas
e.height, 0, | |
401 testCase.format, testCase.type, null); | |
402 } | |
403 switch (testCase.dataMode) { | |
404 case DataMode.IMAGE: | |
405 case DataMode.IMAGE_DATA: | |
406 if (testCase.useTexSubImage2D) | |
407 gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, testCase.format, testCase.t
ype, data); | |
408 else | |
409 gl.texImage2D(gl.TEXTURE_2D, 0, testCase.format, testCase.format, te
stCase.type, data); | |
410 break; | |
411 case DataMode.RAW_DATA: | |
412 if (testCase.useTexSubImage2D) | |
413 gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, testCase.width, testCase.he
ight, testCase.format, testCase.type, data); | |
414 else | |
415 gl.texImage2D(gl.TEXTURE_2D, 0, testCase.format, testCase.width, tes
tCase.height, 0, testCase.format, testCase.type, data); | |
416 break; | |
417 } | |
418 // Point the uniform sampler to texture unit 0. | |
419 gl.uniform1i(textureLoc, 0); | |
420 // Draw the triangles. | |
421 gl.drawArrays(gl.TRIANGLES, 0, 6); | |
422 // Clean up the texture. | |
423 gl.deleteTexture(texture); | |
424 | |
425 // Read back the rendering results. | |
426 buf = new Uint8Array(testCase.width * testCase.height * 4); | |
427 gl.readPixels(0, 0, testCase.width, testCase.height, gl.RGBA, gl.UNSIGNED_BY
TE, buf); | |
428 // Run the verification routine. | |
429 if (testCase.verifier(buf, testCase.threshold, testCase.numOccurrences)) | |
430 testPassed(testCase.description); | |
431 else | |
432 testFailed(testCase.description); | |
433 } | |
434 | |
435 //---------------------------------------------------------------------- | |
436 // Wrappers for programmatic construction of Image, ImageData and raw texture da
ta | |
437 // | |
438 | |
439 function ImageWrapper(width, height) | |
440 { | |
441 this.pngBuilder_ = new PNGlib(width, height, 256); | |
442 } | |
443 | |
444 ImageWrapper.prototype.getWidth = function() { | |
445 return this.pngBuilder_.width; | |
446 }; | |
447 | |
448 ImageWrapper.prototype.getHeight = function() { | |
449 return this.pngBuilder_.height; | |
450 }; | |
451 | |
452 ImageWrapper.prototype.setPixel = function(x, y, r, g, b, a) { | |
453 this.pngBuilder_.buffer[this.pngBuilder_.index(x, y)] = this.pngBuilder_.col
or(r, g, b, a); | |
454 }; | |
455 | |
456 // Generates data into "data" property, possibly asynchronously. | |
457 ImageWrapper.prototype.generateData = function() { | |
458 var that = this; | |
459 var img = new Image(); | |
460 img.onload = function() { | |
461 that.data = img; | |
462 maybeRunTests(); | |
463 }; | |
464 img.src = "data:image/png;base64," + this.pngBuilder_.getBase64(); | |
465 }; | |
466 | |
467 function ImageDataWrapper(width, height) | |
468 { | |
469 if (!ImageDataWrapper.tempCanvas) { | |
470 ImageDataWrapper.tempCanvas = document.createElement("canvas"); | |
471 } | |
472 this.imageData_ = ImageDataWrapper.tempCanvas.getContext("2d").createImageDa
ta(width, height); | |
473 } | |
474 | |
475 ImageDataWrapper.tempCanvas = null; | |
476 | |
477 ImageDataWrapper.prototype.getWidth = function() { | |
478 return this.imageData_.width; | |
479 }; | |
480 | |
481 ImageDataWrapper.prototype.getHeight = function() { | |
482 return this.imageData_.height; | |
483 }; | |
484 | |
485 ImageDataWrapper.prototype.setPixel = function(x, y, r, g, b, a) { | |
486 var index = 4 * (this.imageData_.width * y + x); | |
487 this.imageData_.data[index] = r; | |
488 this.imageData_.data[index + 1] = g; | |
489 this.imageData_.data[index + 2] = b; | |
490 this.imageData_.data[index + 3] = a; | |
491 }; | |
492 | |
493 ImageDataWrapper.prototype.generateData = function() { | |
494 this.data = this.imageData_; | |
495 maybeRunTests(); | |
496 }; | |
497 | |
498 function TextureDataWrapper(width, height) | |
499 { | |
500 this.width_ = width; | |
501 this.height_ = height; | |
502 } | |
503 | |
504 TextureDataWrapper.prototype.getWidth = function() { | |
505 return this.width_; | |
506 }; | |
507 | |
508 TextureDataWrapper.prototype.getHeight = function() { | |
509 return this.height_; | |
510 }; | |
511 | |
512 TextureDataWrapper.prototype.generateData = function() { | |
513 this.data = this.data_; | |
514 maybeRunTests(); | |
515 }; | |
516 | |
517 function RGBA8DataWrapper(width, height) | |
518 { | |
519 TextureDataWrapper.call(this, width, height); | |
520 this.data_ = new Uint8Array(4 * width * height); | |
521 } | |
522 | |
523 RGBA8DataWrapper.prototype = new TextureDataWrapper; | |
524 | |
525 RGBA8DataWrapper.prototype.setPixel = function(x, y, r, g, b, a) { | |
526 var index = 4 * (this.width_ * y + x); | |
527 this.data_[index] = r; | |
528 this.data_[index + 1] = g; | |
529 this.data_[index + 2] = b; | |
530 this.data_[index + 3] = a; | |
531 }; | |
532 | |
533 function RGBA5551DataWrapper(width, height) | |
534 { | |
535 TextureDataWrapper.call(this, width, height); | |
536 this.data_ = new Uint16Array(width * height); | |
537 } | |
538 | |
539 RGBA5551DataWrapper.prototype = new TextureDataWrapper; | |
540 | |
541 RGBA5551DataWrapper.prototype.setPixel = function(x, y, r, g, b, a) { | |
542 var value = (((r & 0xF8) << 8) | |
543 | ((g & 0xF8) << 3) | |
544 | ((b & 0xF8) >> 2) | |
545 | (a >> 7)); | |
546 this.data_[this.width_ * y + x] = value; | |
547 }; | |
548 | |
549 function RGBA4444DataWrapper(width, height) | |
550 { | |
551 TextureDataWrapper.call(this, width, height); | |
552 this.data_ = new Uint16Array(width * height); | |
553 } | |
554 | |
555 RGBA4444DataWrapper.prototype = new TextureDataWrapper; | |
556 | |
557 RGBA4444DataWrapper.prototype.setPixel = function(x, y, r, g, b, a) { | |
558 var value = (((r & 0xF0) << 8) | |
559 | ((g & 0xF0) << 4) | |
560 | (b & 0xF0) | |
561 | (a >> 4)); | |
562 this.data_[this.width_ * y + x] = value; | |
563 }; | |
564 | |
565 function RGB8DataWrapper(width, height) | |
566 { | |
567 TextureDataWrapper.call(this, width, height); | |
568 this.data_ = new Uint8Array(3 * width * height); | |
569 } | |
570 | |
571 RGB8DataWrapper.prototype = new TextureDataWrapper; | |
572 | |
573 RGB8DataWrapper.prototype.setPixel = function(x, y, r, g, b, a) { | |
574 var index = 3 * (this.width_ * y + x); | |
575 this.data_[index] = r; | |
576 this.data_[index + 1] = g; | |
577 this.data_[index + 2] = b; | |
578 }; | |
579 | |
580 function RGB565DataWrapper(width, height) | |
581 { | |
582 TextureDataWrapper.call(this, width, height); | |
583 this.data_ = new Uint16Array(width * height); | |
584 } | |
585 | |
586 RGB565DataWrapper.prototype = new TextureDataWrapper; | |
587 | |
588 RGB565DataWrapper.prototype.setPixel = function(x, y, r, g, b, a) { | |
589 var value = (((r & 0xF8) << 8) | |
590 | ((g & 0xFC) << 3) | |
591 | ((b & 0xF8) >> 3)); | |
592 this.data_[this.width_ * y + x] = value; | |
593 }; | |
594 | |
595 function A8DataWrapper(width, height) | |
596 { | |
597 TextureDataWrapper.call(this, width, height); | |
598 this.data_ = new Uint8Array(width * height); | |
599 } | |
600 | |
601 A8DataWrapper.prototype = new TextureDataWrapper; | |
602 | |
603 A8DataWrapper.prototype.setPixel = function(x, y, r, g, b, a) { | |
604 this.data_[this.width_ * y + x] = a; | |
605 }; | |
606 | |
607 function L8DataWrapper(width, height) | |
608 { | |
609 TextureDataWrapper.call(this, width, height); | |
610 this.data_ = new Uint8Array(width * height); | |
611 } | |
612 | |
613 L8DataWrapper.prototype = new TextureDataWrapper; | |
614 | |
615 L8DataWrapper.prototype.setPixel = function(x, y, r, g, b, a) { | |
616 this.data_[this.width_ * y + x] = r; | |
617 }; | |
618 | |
619 function LA8DataWrapper(width, height) | |
620 { | |
621 TextureDataWrapper.call(this, width, height); | |
622 this.data_ = new Uint8Array(2 * width * height); | |
623 } | |
624 | |
625 LA8DataWrapper.prototype = new TextureDataWrapper; | |
626 | |
627 LA8DataWrapper.prototype.setPixel = function(x, y, r, g, b, a) { | |
628 var index = 2 * (this.width_ * y + x); | |
629 this.data_[index] = r; | |
630 this.data_[index + 1] = a; | |
631 }; | |
632 | |
633 //---------------------------------------------------------------------- | |
634 // Color ramp generation functions | |
635 // | |
636 | |
637 function generateOpaqueGrayscaleRamp(wrapper) | |
638 { | |
639 var width = wrapper.getWidth(); | |
640 var height = wrapper.getHeight(); | |
641 for (var x = 0; x < width; ++x) { | |
642 var value = Math.round(255.0 * x / width); | |
643 for (var y = 0; y < height; ++y) | |
644 wrapper.setPixel(x, y, value, value, value, 255); | |
645 } | |
646 } | |
647 | |
648 function generateTranslucentGrayscaleRamp(wrapper) | |
649 { | |
650 var width = wrapper.getWidth(); | |
651 var height = wrapper.getHeight(); | |
652 for (var x = 0; x < width; ++x) { | |
653 var value = Math.round(255.0 * x / width); | |
654 for (var y = 0; y < height; ++y) | |
655 wrapper.setPixel(x, y, value, value, value, value); | |
656 } | |
657 } | |
658 | |
659 function generateTransparentGrayscaleRamp(wrapper) | |
660 { | |
661 var width = wrapper.getWidth(); | |
662 var height = wrapper.getHeight(); | |
663 for (var x = 0; x < width; ++x) { | |
664 var value = Math.round(255.0 * x / width); | |
665 for (var y = 0; y < height; ++y) | |
666 wrapper.setPixel(x, y, value, value, value, 0); | |
667 } | |
668 } | |
669 | |
670 //---------------------------------------------------------------------- | |
671 // Verification routines | |
672 // | |
673 | |
674 function allChannelsIncreaseByNoMoreThan(array, threshold, numOccurrences) { | |
675 var numFound = 0; | |
676 for (var i = 4; i < array.length; i += 4) | |
677 for (var j = 0; j < 4; j++) | |
678 if (array[i + j] - array[i + j - 4] > threshold) | |
679 ++numFound; | |
680 | |
681 return numFound < numOccurrences; | |
682 } | |
683 | |
684 function alphaChannelIncreasesByNoMoreThan(array, threshold, numOccurrences) { | |
685 var numFound = 0; | |
686 for (var i = 7; i < array.length; i += 4) | |
687 if (array[i] - array[i - 4] > threshold) | |
688 ++numFound; | |
689 | |
690 return numFound < numOccurrences; | |
691 } | |
692 | |
693 function allChannelsIncreaseByAtLeast(array, threshold, numOccurrences) { | |
694 var numFound = 0; | |
695 for (var i = 4; i < array.length; i += 4) | |
696 for (var j = 0; j < 4; ++j) | |
697 if (array[i + j] - array[i + j - 4] > threshold) | |
698 ++numFound; | |
699 | |
700 return numFound > numOccurrences; | |
701 } | |
702 | |
703 function colorChannelsAreZero(array, threshold, numOccurrences) { | |
704 var passed = true; | |
705 var numFailures = 0; | |
706 | |
707 for (var i = 4; i < array.length; i += 4) | |
708 for (var j = 0; j < 3; ++j) | |
709 if (array[i + j] != 0) { | |
710 passed = false; | |
711 if (++numFailures <= 5) | |
712 debug(" array[" + (i + j) + "] should have been 0, was " +
array[i + j]); | |
713 } | |
714 | |
715 return passed; | |
716 } | |
717 | |
718 </script> | |
719 </head> | |
720 <body onload="init()"> | |
721 <canvas id="example" width="256px" height="1px"></canvas> | |
722 <div id="description"></div> | |
723 <div id="console"></div> | |
724 </body> | |
725 </html> | |
OLD | NEW |