• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  ** Copyright 2011, The Android Open Source Project
3  **
4  ** Licensed under the Apache License, Version 2.0 (the "License");
5  ** you may not use this file except in compliance with the License.
6  ** You may obtain a copy of the License at
7  **
8  **     http://www.apache.org/licenses/LICENSE-2.0
9  **
10  ** Unless required by applicable law or agreed to in writing, software
11  ** distributed under the License is distributed on an "AS IS" BASIS,
12  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  ** See the License for the specific language governing permissions and
14  ** limitations under the License.
15  */
16 
17 package com.android.glesv2debugger;
18 
19 import com.google.protobuf.ByteString;
20 
21 import org.eclipse.jface.dialogs.MessageDialog;
22 import org.eclipse.swt.graphics.ImageData;
23 import org.eclipse.swt.graphics.PaletteData;
24 
25 import java.nio.ByteBuffer;
26 import java.util.Arrays;
27 
28 public class MessageProcessor {
showError(final String message)29     static void showError(final String message) {
30         // need to call SWT from UI thread
31         MessageDialog.openError(null, "MessageProcessor", message);
32     }
33 
34     /**
35      * data layout: uint32 total decompressed length, (chunks: uint32 chunk
36      * decompressed size, uint32 chunk compressed size, chunk data)+. 0 chunk
37      * compressed size means chunk is not compressed
38      */
lzfDecompressChunks(final ByteString data)39     public static byte[] lzfDecompressChunks(final ByteString data) {
40         ByteBuffer in = data.asReadOnlyByteBuffer();
41         in.order(SampleView.targetByteOrder);
42         ByteBuffer out = ByteBuffer.allocate(in.getInt());
43         byte[] inChunk = new byte[0];
44         byte[] outChunk = new byte[0];
45         while (in.remaining() > 0) {
46             int decompressed = in.getInt();
47             int compressed = in.getInt();
48             if (decompressed > outChunk.length)
49                 outChunk = new byte[decompressed];
50             if (compressed == 0) {
51                 in.get(outChunk, 0, decompressed);
52                 out.put(outChunk, 0, decompressed);
53             } else {
54                 if (compressed > inChunk.length)
55                     inChunk = new byte[compressed];
56                 in.get(inChunk, 0, compressed);
57                 int size = org.liblzf.CLZF
58                         .lzf_decompress(inChunk, compressed, outChunk, outChunk.length);
59                 assert size == decompressed;
60                 out.put(outChunk, 0, size);
61             }
62         }
63         assert !out.hasRemaining();
64         return out.array();
65     }
66 
67     /** same data layout as LZFDecompressChunks */
lzfCompressChunks(final byte[] in, final int inSize)68     public static byte[] lzfCompressChunks(final byte[] in, final int inSize) {
69         byte[] chunk = new byte[256 * 1024]; // chunk size is arbitrary
70         final ByteBuffer out = ByteBuffer.allocate(4 + (inSize + chunk.length - 1)
71                 / chunk.length * (chunk.length + 4 * 2));
72         out.order(SampleView.targetByteOrder);
73         out.putInt(inSize);
74         for (int i = 0; i < inSize; i += chunk.length) {
75             int chunkIn = chunk.length;
76             if (i + chunkIn > inSize)
77                 chunkIn = inSize - i;
78             final byte[] inChunk = java.util.Arrays.copyOfRange(in, i, i + chunkIn);
79             final int chunkOut = org.liblzf.CLZF
80                     .lzf_compress(inChunk, chunkIn, chunk, chunk.length);
81             out.putInt(chunkIn);
82             out.putInt(chunkOut);
83             if (chunkOut == 0) // compressed bigger than chunk (uncompressed)
84                 out.put(inChunk);
85             else
86                 out.put(chunk, 0, chunkOut);
87         }
88         return Arrays.copyOf(out.array(), out.position());
89     }
90 
91     /**
92      * returns new ref, which is also the decoded image; ref could be bigger
93      * than pixels, in which case the first pixels.length bytes form the image
94      */
decodeReferencedImage(byte[] ref, byte[] pixels)95     public static byte[] decodeReferencedImage(byte[] ref, byte[] pixels) {
96         if (ref.length < pixels.length)
97             ref = new byte[pixels.length];
98         for (int i = 0; i < pixels.length; i++)
99             ref[i] ^= pixels[i];
100         for (int i = pixels.length; i < ref.length; i++)
101             ref[i] = 0; // clear unused ref to maintain consistency
102         return ref;
103     }
104 
receiveImage(int width, int height, int format, int type, final ByteString data)105     public static ImageData receiveImage(int width, int height, int format,
106             int type, final ByteString data) {
107         assert width > 0 && height > 0;
108         int bpp = 0;
109         int redMask = 0, blueMask = 0, greenMask = 0;
110         switch (GLEnum.valueOf(type)) {
111             case GL_UNSIGNED_SHORT_5_6_5:
112             case GL_UNSIGNED_SHORT_4_4_4_4:
113             case GL_UNSIGNED_SHORT_5_5_5_1:
114                 format = type;
115                 break;
116             case GL_UNSIGNED_BYTE:
117                 break;
118             default:
119                 showError("unsupported texture type " + type);
120                 return null;
121         }
122 
123         switch (GLEnum.valueOf(format)) {
124             case GL_ALPHA:
125             case GL_LUMINANCE:
126                 redMask = blueMask = greenMask = 0xff;
127                 bpp = 8;
128                 break;
129             case GL_LUMINANCE_ALPHA:
130                 blueMask = 0xff;
131                 redMask = 0xff00;
132                 bpp = 16;
133                 break;
134             case GL_RGB:
135                 blueMask = 0xff;
136                 greenMask = 0xff00;
137                 redMask = 0xff0000;
138                 bpp = 24;
139                 break;
140             case GL_RGBA:
141                 blueMask = 0xff00;
142                 greenMask = 0xff0000;
143                 redMask = 0xff000000;
144                 bpp = 32;
145                 break;
146             case GL_UNSIGNED_SHORT_5_6_5:
147                 blueMask = ((1 << 5) - 1) << 0;
148                 greenMask = ((1 << 6) - 1) << 5;
149                 redMask = ((1 << 5) - 1) << 11;
150                 bpp = 16;
151                 break;
152             case GL_UNSIGNED_SHORT_4_4_4_4:
153                 blueMask = ((1 << 4) - 1) << 4;
154                 greenMask = ((1 << 4) - 1) << 8;
155                 redMask = ((1 << 4) - 1) << 12;
156                 bpp = 16;
157                 break;
158             case GL_UNSIGNED_SHORT_5_5_5_1:
159                 blueMask = ((1 << 5) - 1) << 1;
160                 greenMask = ((1 << 5) - 1) << 6;
161                 redMask = ((1 << 5) - 1) << 11;
162                 bpp = 16;
163                 break;
164             default:
165                 showError("unsupported texture format: " + format);
166                 return null;
167         }
168         byte[] pixels = lzfDecompressChunks(data);
169         assert pixels.length == width * height * (bpp / 8);
170         PaletteData palette = new PaletteData(redMask, greenMask, blueMask);
171         return new ImageData(width, height, bpp, palette, 1, pixels);
172     }
173 }
174