1 : /*
2 : * Copyright (C) 2010 Apple Inc. All rights reserved.
3 : * Copyright (C) 2010 Google Inc. All rights reserved.
4 : * Copyright (C) 2010 Mozilla Corporation. All rights reserved.
5 : *
6 : * Redistribution and use in source and binary forms, with or without
7 : * modification, are permitted provided that the following conditions
8 : * are met:
9 : * 1. Redistributions of source code must retain the above copyright
10 : * notice, this list of conditions and the following disclaimer.
11 : * 2. Redistributions in binary form must reproduce the above copyright
12 : * notice, this list of conditions and the following disclaimer in the
13 : * documentation and/or other materials provided with the distribution.
14 : *
15 : * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
16 : * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 : * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
19 : * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 : * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 : * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 : * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23 : * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 : * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 : */
27 :
28 : // the pixel conversions code here is originally from this file:
29 : // http://trac.webkit.org/browser/trunk/WebCore/platform/graphics/GraphicsContext3D.cpp
30 :
31 : // Keep as much as possible unchanged to ease sharing code with the WebKit guys.
32 : // Changes:
33 : // * added BGR8 path, we need it in Mozilla to load textures from DOMElements
34 : // * enclosing in a namespace WebGLTexelConversions to make it clear it is, in profilers and in symbol table dumps
35 : // * added __restrict keywords. Although non-standard, this is very well supported across all compilers
36 : // that I know of (GCC/LLVM/MSC/ICC/XLC...)
37 : // * optimized scaleFactor computation in Unmultiply functions (1 div instead of 2)
38 :
39 : #ifndef WEBGLTEXELCONVERSIONS_H_
40 : #define WEBGLTEXELCONVERSIONS_H_
41 :
42 : #ifdef __SUNPRO_CC
43 : #define __restrict
44 : #endif
45 :
46 : #include "WebGLContext.h"
47 :
48 : #if defined _MSC_VER
49 : #define FORCE_INLINE __forceinline
50 : #elif defined __GNUC__
51 : #define FORCE_INLINE __attribute__((always_inline)) inline
52 : #else
53 : #define FORCE_INLINE inline
54 : #endif
55 :
56 : namespace mozilla {
57 :
58 : typedef PRUint8 uint8_t;
59 : typedef PRUint16 uint16_t;
60 :
61 : namespace WebGLTexelConversions {
62 :
63 : /****** BEGIN CODE SHARED WITH WEBKIT ******/
64 :
65 : //----------------------------------------------------------------------
66 : // Pixel unpacking routines.
67 :
68 : FORCE_INLINE void unpackRGBA8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
69 : {
70 0 : destination[0] = source[0];
71 0 : destination[1] = source[1];
72 0 : destination[2] = source[2];
73 0 : destination[3] = source[3];
74 : }
75 :
76 : FORCE_INLINE void unpackRGB8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
77 : {
78 0 : destination[0] = source[0];
79 0 : destination[1] = source[1];
80 0 : destination[2] = source[2];
81 0 : destination[3] = 0xFF;
82 : }
83 :
84 : FORCE_INLINE void unpackBGRA8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
85 : {
86 0 : destination[0] = source[2];
87 0 : destination[1] = source[1];
88 0 : destination[2] = source[0];
89 0 : destination[3] = source[3];
90 : }
91 :
92 : FORCE_INLINE void unpackBGR8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
93 : {
94 0 : destination[0] = source[2];
95 0 : destination[1] = source[1];
96 0 : destination[2] = source[0];
97 0 : destination[3] = 0xFF;
98 : }
99 :
100 : FORCE_INLINE void unpackRGBA5551ToRGBA8(const uint16_t* __restrict source, uint8_t* __restrict destination)
101 : {
102 0 : uint16_t packedValue = source[0];
103 0 : uint8_t r = packedValue >> 11;
104 0 : uint8_t g = (packedValue >> 6) & 0x1F;
105 0 : uint8_t b = (packedValue >> 1) & 0x1F;
106 0 : destination[0] = (r << 3) | (r & 0x7);
107 0 : destination[1] = (g << 3) | (g & 0x7);
108 0 : destination[2] = (b << 3) | (b & 0x7);
109 0 : destination[3] = (packedValue & 0x1) ? 0xFF : 0x0;
110 : }
111 :
112 : FORCE_INLINE void unpackRGBA4444ToRGBA8(const uint16_t* __restrict source, uint8_t* __restrict destination)
113 : {
114 0 : uint16_t packedValue = source[0];
115 0 : uint8_t r = packedValue >> 12;
116 0 : uint8_t g = (packedValue >> 8) & 0x0F;
117 0 : uint8_t b = (packedValue >> 4) & 0x0F;
118 0 : uint8_t a = packedValue & 0x0F;
119 0 : destination[0] = r << 4 | r;
120 0 : destination[1] = g << 4 | g;
121 0 : destination[2] = b << 4 | b;
122 0 : destination[3] = a << 4 | a;
123 : }
124 :
125 : FORCE_INLINE void unpackRGB565ToRGBA8(const uint16_t* __restrict source, uint8_t* __restrict destination)
126 : {
127 0 : uint16_t packedValue = source[0];
128 0 : uint8_t r = packedValue >> 11;
129 0 : uint8_t g = (packedValue >> 5) & 0x3F;
130 0 : uint8_t b = packedValue & 0x1F;
131 0 : destination[0] = (r << 3) | (r & 0x7);
132 0 : destination[1] = (g << 2) | (g & 0x3);
133 0 : destination[2] = (b << 3) | (b & 0x7);
134 0 : destination[3] = 0xFF;
135 : }
136 :
137 : FORCE_INLINE void unpackR8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
138 : {
139 0 : destination[0] = source[0];
140 0 : destination[1] = source[0];
141 0 : destination[2] = source[0];
142 0 : destination[3] = 0xFF;
143 : }
144 :
145 : FORCE_INLINE void unpackRA8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
146 : {
147 0 : destination[0] = source[0];
148 0 : destination[1] = source[0];
149 0 : destination[2] = source[0];
150 0 : destination[3] = source[1];
151 : }
152 :
153 : FORCE_INLINE void unpackA8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
154 : {
155 0 : destination[0] = 0x0;
156 0 : destination[1] = 0x0;
157 0 : destination[2] = 0x0;
158 0 : destination[3] = source[0];
159 : }
160 :
161 : FORCE_INLINE void unpackRGB32FToRGBA32F(const float* __restrict source, float* __restrict destination)
162 : {
163 0 : destination[0] = source[0];
164 0 : destination[1] = source[1];
165 0 : destination[2] = source[2];
166 0 : destination[3] = 1;
167 : }
168 :
169 : FORCE_INLINE void unpackR32FToRGBA32F(const float* __restrict source, float* __restrict destination)
170 : {
171 0 : destination[0] = source[0];
172 0 : destination[1] = source[0];
173 0 : destination[2] = source[0];
174 0 : destination[3] = 1;
175 : }
176 :
177 : FORCE_INLINE void unpackRA32FToRGBA32F(const float* __restrict source, float* __restrict destination)
178 : {
179 0 : destination[0] = source[0];
180 0 : destination[1] = source[0];
181 0 : destination[2] = source[0];
182 0 : destination[3] = source[1];
183 : }
184 :
185 : FORCE_INLINE void unpackA32FToRGBA32F(const float* __restrict source, float* __restrict destination)
186 : {
187 0 : destination[0] = 0;
188 0 : destination[1] = 0;
189 0 : destination[2] = 0;
190 0 : destination[3] = source[0];
191 : }
192 :
193 : //----------------------------------------------------------------------
194 : // Pixel packing routines.
195 : //
196 :
197 : FORCE_INLINE void packRGBA8ToA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
198 : {
199 0 : destination[0] = source[3];
200 : }
201 :
202 : FORCE_INLINE void packRGBA8ToR8(const uint8_t* __restrict source, uint8_t* __restrict destination)
203 : {
204 0 : destination[0] = source[0];
205 : }
206 :
207 : FORCE_INLINE void packRGBA8ToR8Premultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
208 : {
209 0 : float scaleFactor = source[3] / 255.0f;
210 0 : uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
211 0 : destination[0] = sourceR;
212 : }
213 :
214 : // FIXME: this routine is lossy and must be removed.
215 : FORCE_INLINE void packRGBA8ToR8Unmultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
216 : {
217 0 : float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
218 0 : uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
219 0 : destination[0] = sourceR;
220 : }
221 :
222 : FORCE_INLINE void packRGBA8ToRA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
223 : {
224 0 : destination[0] = source[0];
225 0 : destination[1] = source[3];
226 : }
227 :
228 : FORCE_INLINE void packRGBA8ToRA8Premultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
229 : {
230 0 : float scaleFactor = source[3] / 255.0f;
231 0 : uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
232 0 : destination[0] = sourceR;
233 0 : destination[1] = source[3];
234 : }
235 :
236 : // FIXME: this routine is lossy and must be removed.
237 : FORCE_INLINE void packRGBA8ToRA8Unmultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
238 : {
239 0 : float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
240 0 : uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
241 0 : destination[0] = sourceR;
242 0 : destination[1] = source[3];
243 : }
244 :
245 : FORCE_INLINE void packRGBA8ToRGB8(const uint8_t* __restrict source, uint8_t* __restrict destination)
246 : {
247 0 : destination[0] = source[0];
248 0 : destination[1] = source[1];
249 0 : destination[2] = source[2];
250 : }
251 :
252 : FORCE_INLINE void packRGBA8ToRGB8Premultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
253 : {
254 0 : float scaleFactor = source[3] / 255.0f;
255 0 : uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
256 0 : uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
257 0 : uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
258 0 : destination[0] = sourceR;
259 0 : destination[1] = sourceG;
260 0 : destination[2] = sourceB;
261 : }
262 :
263 : // FIXME: this routine is lossy and must be removed.
264 : FORCE_INLINE void packRGBA8ToRGB8Unmultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
265 : {
266 0 : float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
267 0 : uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
268 0 : uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
269 0 : uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
270 0 : destination[0] = sourceR;
271 0 : destination[1] = sourceG;
272 0 : destination[2] = sourceB;
273 : }
274 :
275 : // This is only used when the source format is different than kSourceFormatRGBA8.
276 : FORCE_INLINE void packRGBA8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
277 : {
278 0 : destination[0] = source[0];
279 0 : destination[1] = source[1];
280 0 : destination[2] = source[2];
281 0 : destination[3] = source[3];
282 : }
283 :
284 : FORCE_INLINE void packRGBA8ToRGBA8Premultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
285 : {
286 0 : float scaleFactor = source[3] / 255.0f;
287 0 : uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
288 0 : uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
289 0 : uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
290 0 : destination[0] = sourceR;
291 0 : destination[1] = sourceG;
292 0 : destination[2] = sourceB;
293 0 : destination[3] = source[3];
294 : }
295 :
296 : // FIXME: this routine is lossy and must be removed.
297 : FORCE_INLINE void packRGBA8ToRGBA8Unmultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
298 : {
299 0 : float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
300 0 : uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
301 0 : uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
302 0 : uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
303 0 : destination[0] = sourceR;
304 0 : destination[1] = sourceG;
305 0 : destination[2] = sourceB;
306 0 : destination[3] = source[3];
307 : }
308 :
309 : FORCE_INLINE void packRGBA8ToUnsignedShort4444(const uint8_t* __restrict source, uint16_t* __restrict destination)
310 : {
311 0 : *destination = (((source[0] & 0xF0) << 8)
312 0 : | ((source[1] & 0xF0) << 4)
313 0 : | (source[2] & 0xF0)
314 0 : | (source[3] >> 4));
315 : }
316 :
317 : FORCE_INLINE void packRGBA8ToUnsignedShort4444Premultiply(const uint8_t* __restrict source, uint16_t* __restrict destination)
318 : {
319 0 : float scaleFactor = source[3] / 255.0f;
320 0 : uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
321 0 : uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
322 0 : uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
323 : *destination = (((sourceR & 0xF0) << 8)
324 : | ((sourceG & 0xF0) << 4)
325 : | (sourceB & 0xF0)
326 0 : | (source[3] >> 4));
327 : }
328 :
329 : // FIXME: this routine is lossy and must be removed.
330 : FORCE_INLINE void packRGBA8ToUnsignedShort4444Unmultiply(const uint8_t* __restrict source, uint16_t* __restrict destination)
331 : {
332 0 : float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
333 0 : uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
334 0 : uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
335 0 : uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
336 : *destination = (((sourceR & 0xF0) << 8)
337 : | ((sourceG & 0xF0) << 4)
338 : | (sourceB & 0xF0)
339 0 : | (source[3] >> 4));
340 : }
341 :
342 : FORCE_INLINE void packRGBA8ToUnsignedShort5551(const uint8_t* __restrict source, uint16_t* __restrict destination)
343 : {
344 0 : *destination = (((source[0] & 0xF8) << 8)
345 0 : | ((source[1] & 0xF8) << 3)
346 0 : | ((source[2] & 0xF8) >> 2)
347 0 : | (source[3] >> 7));
348 : }
349 :
350 : FORCE_INLINE void packRGBA8ToUnsignedShort5551Premultiply(const uint8_t* __restrict source, uint16_t* __restrict destination)
351 : {
352 0 : float scaleFactor = source[3] / 255.0f;
353 0 : uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
354 0 : uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
355 0 : uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
356 : *destination = (((sourceR & 0xF8) << 8)
357 : | ((sourceG & 0xF8) << 3)
358 : | ((sourceB & 0xF8) >> 2)
359 0 : | (source[3] >> 7));
360 : }
361 :
362 : // FIXME: this routine is lossy and must be removed.
363 : FORCE_INLINE void packRGBA8ToUnsignedShort5551Unmultiply(const uint8_t* __restrict source, uint16_t* __restrict destination)
364 : {
365 0 : float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
366 0 : uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
367 0 : uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
368 0 : uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
369 : *destination = (((sourceR & 0xF8) << 8)
370 : | ((sourceG & 0xF8) << 3)
371 : | ((sourceB & 0xF8) >> 2)
372 0 : | (source[3] >> 7));
373 : }
374 :
375 : FORCE_INLINE void packRGBA8ToUnsignedShort565(const uint8_t* __restrict source, uint16_t* __restrict destination)
376 : {
377 0 : *destination = (((source[0] & 0xF8) << 8)
378 0 : | ((source[1] & 0xFC) << 3)
379 0 : | ((source[2] & 0xF8) >> 3));
380 : }
381 :
382 : FORCE_INLINE void packRGBA8ToUnsignedShort565Premultiply(const uint8_t* __restrict source, uint16_t* __restrict destination)
383 : {
384 0 : float scaleFactor = source[3] / 255.0f;
385 0 : uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
386 0 : uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
387 0 : uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
388 : *destination = (((sourceR & 0xF8) << 8)
389 : | ((sourceG & 0xFC) << 3)
390 0 : | ((sourceB & 0xF8) >> 3));
391 : }
392 :
393 : // FIXME: this routine is lossy and must be removed.
394 : FORCE_INLINE void packRGBA8ToUnsignedShort565Unmultiply(const uint8_t* __restrict source, uint16_t* __restrict destination)
395 : {
396 0 : float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
397 0 : uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
398 0 : uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
399 0 : uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
400 : *destination = (((sourceR & 0xF8) << 8)
401 : | ((sourceG & 0xFC) << 3)
402 0 : | ((sourceB & 0xF8) >> 3));
403 : }
404 :
405 : FORCE_INLINE void packRGBA32FToRGB32F(const float* __restrict source, float* __restrict destination)
406 : {
407 0 : destination[0] = source[0];
408 0 : destination[1] = source[1];
409 0 : destination[2] = source[2];
410 : }
411 :
412 : FORCE_INLINE void packRGBA32FToRGB32FPremultiply(const float* __restrict source, float* __restrict destination)
413 : {
414 0 : float scaleFactor = source[3];
415 0 : destination[0] = source[0] * scaleFactor;
416 0 : destination[1] = source[1] * scaleFactor;
417 0 : destination[2] = source[2] * scaleFactor;
418 : }
419 :
420 : FORCE_INLINE void packRGBA32FToRGBA32FPremultiply(const float* __restrict source, float* __restrict destination)
421 : {
422 : float scaleFactor = source[3];
423 : destination[0] = source[0] * scaleFactor;
424 : destination[1] = source[1] * scaleFactor;
425 : destination[2] = source[2] * scaleFactor;
426 : destination[3] = source[3];
427 : }
428 :
429 : FORCE_INLINE void packRGBA32FToA32F(const float* __restrict source, float* __restrict destination)
430 : {
431 0 : destination[0] = source[3];
432 : }
433 :
434 : // identical to above, to avoid special-casing
435 : FORCE_INLINE void packRGBA32FToA32FPremultiply(const float* __restrict source, float* __restrict destination)
436 : {
437 0 : destination[0] = source[3];
438 : }
439 :
440 : FORCE_INLINE void packRGBA32FToR32F(const float* __restrict source, float* __restrict destination)
441 : {
442 0 : destination[0] = source[0];
443 : }
444 :
445 : FORCE_INLINE void packRGBA32FToR32FPremultiply(const float* __restrict source, float* __restrict destination)
446 : {
447 0 : float scaleFactor = source[3];
448 0 : destination[0] = source[0] * scaleFactor;
449 : }
450 :
451 :
452 : FORCE_INLINE void packRGBA32FToRA32F(const float* __restrict source, float* __restrict destination)
453 : {
454 0 : destination[0] = source[0];
455 0 : destination[1] = source[3];
456 : }
457 :
458 : FORCE_INLINE void packRGBA32FToRA32FPremultiply(const float* __restrict source, float* __restrict destination)
459 : {
460 0 : float scaleFactor = source[3];
461 0 : destination[0] = source[0] * scaleFactor;
462 0 : destination[1] = scaleFactor;
463 : }
464 :
465 : /****** END CODE SHARED WITH WEBKIT ******/
466 :
467 : } // end namespace WebGLTexelConversions
468 :
469 : } // end namespace mozilla
470 :
471 : #endif // WEBGLTEXELCONVERSIONS_H_
|