1 /*
2 -----------------------------------------------------------------------------
3 This source file is part of OGRE
4 (Object-oriented Graphics Rendering Engine)
5 For the latest info, see http://www.ogre3d.org/
6
7 Copyright (c) 2000-2013 Torus Knot Software Ltd
8
9 Permission is hereby granted, free of charge, to any person obtaining a copy
10 of this software and associated documentation files (the "Software"), to deal
11 in the Software without restriction, including without limitation the rights
12 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom the Software is
14 furnished to do so, subject to the following conditions:
15
16 The above copyright notice and this permission notice shall be included in
17 all copies or substantial portions of the Software.
18
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 THE SOFTWARE.
26 -----------------------------------------------------------------------------
27 */
28 #include "PixelFormatTests.h"
29 #include <cstdlib>
30
31 // Register the suite
32 CPPUNIT_TEST_SUITE_REGISTRATION( PixelFormatTests );
33
setUp()34 void PixelFormatTests::setUp()
35 {
36 size = 4096;
37 randomData = new uint8[size];
38 temp = new uint8[size];
39 temp2 = new uint8[size];
40 // Generate reproducible random data
41 srand(0);
42 for(unsigned int x=0; x<(unsigned int)size; x++)
43 randomData[x] = (uint8)rand();
44 }
45
tearDown()46 void PixelFormatTests::tearDown()
47 {
48 delete [] randomData;
49 delete [] temp;
50 delete [] temp2;
51 }
52
53
testIntegerPackUnpack()54 void PixelFormatTests::testIntegerPackUnpack()
55 {
56
57 }
58
testFloatPackUnpack()59 void PixelFormatTests::testFloatPackUnpack()
60 {
61 // Float32
62 float data[4] = {1.0f, 2.0f, 3.0f, 4.0f};
63 float r,g,b,a;
64 PixelUtil::unpackColour(&r, &g, &b, &a, PF_FLOAT32_RGBA, data);
65 CPPUNIT_ASSERT_EQUAL(r, 1.0f);
66 CPPUNIT_ASSERT_EQUAL(g, 2.0f);
67 CPPUNIT_ASSERT_EQUAL(b, 3.0f);
68 CPPUNIT_ASSERT_EQUAL(a, 4.0f);
69
70 // Float16
71 setupBoxes(PF_A8B8G8R8, PF_FLOAT16_RGBA);
72 dst2.format = PF_A8B8G8R8;
73 unsigned int eob = src.getWidth()*4;
74
75 PixelUtil::bulkPixelConversion(src, dst1);
76 PixelUtil::bulkPixelConversion(dst1, dst2);
77
78 // Locate errors
79 std::stringstream s;
80 unsigned int x;
81 for(x=0; x<eob; x++) {
82 if(temp2[x] != randomData[x])
83 s << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) randomData[x]
84 << "!= " << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) temp2[x] << " ";
85 }
86
87 // src and dst2 should match
88 CPPUNIT_ASSERT_MESSAGE("PF_FLOAT16_RGBA<->PF_A8B8G8R8 conversion was not lossless "+s.str(),
89 memcmp(src.data, dst2.data, eob) == 0);
90 }
91
92 // Pure 32 bit float precision brute force pixel conversion; for comparison
naiveBulkPixelConversion(const PixelBox & src,const PixelBox & dst)93 void naiveBulkPixelConversion(const PixelBox &src, const PixelBox &dst)
94 {
95 uint8 *srcptr = static_cast<uint8*>(src.data);
96 uint8 *dstptr = static_cast<uint8*>(dst.data);
97 unsigned int srcPixelSize = PixelUtil::getNumElemBytes(src.format);
98 unsigned int dstPixelSize = PixelUtil::getNumElemBytes(dst.format);
99
100 // Calculate pitches+skips in bytes
101 int srcRowSkipBytes = src.getRowSkip()*srcPixelSize;
102 int srcSliceSkipBytes = src.getSliceSkip()*srcPixelSize;
103
104 int dstRowSkipBytes = dst.getRowSkip()*dstPixelSize;
105 int dstSliceSkipBytes = dst.getSliceSkip()*dstPixelSize;
106
107 // The brute force fallback
108 float r,g,b,a;
109 for(size_t z=src.front; z<src.back; z++)
110 {
111 for(size_t y=src.top; y<src.bottom; y++)
112 {
113 for(size_t x=src.left; x<src.right; x++)
114 {
115 PixelUtil::unpackColour(&r, &g, &b, &a, src.format, srcptr);
116 PixelUtil::packColour(r, g, b, a, dst.format, dstptr);
117 srcptr += srcPixelSize;
118 dstptr += dstPixelSize;
119 }
120 srcptr += srcRowSkipBytes;
121 dstptr += dstRowSkipBytes;
122 }
123 srcptr += srcSliceSkipBytes;
124 dstptr += dstSliceSkipBytes;
125 }
126
127 }
128
setupBoxes(PixelFormat srcFormat,PixelFormat dstFormat)129 void PixelFormatTests::setupBoxes(PixelFormat srcFormat, PixelFormat dstFormat)
130 {
131 unsigned int width = (size-4) / PixelUtil::getNumElemBytes(srcFormat);
132 unsigned int width2 = (size-4) / PixelUtil::getNumElemBytes(dstFormat);
133 if(width > width2)
134 width = width2;
135
136 src = PixelBox(width, 1, 1, srcFormat, randomData);
137 dst1 = PixelBox(width, 1, 1, dstFormat, temp);
138 dst2 = PixelBox(width, 1, 1, dstFormat, temp2);
139
140 }
141
testCase(PixelFormat srcFormat,PixelFormat dstFormat)142 void PixelFormatTests::testCase(PixelFormat srcFormat, PixelFormat dstFormat)
143 {
144 setupBoxes(srcFormat, dstFormat);
145 // Check end of buffer
146 unsigned int eob = dst1.getWidth()*PixelUtil::getNumElemBytes(dstFormat);
147 temp[eob] = (unsigned char)0x56;
148 temp[eob+1] = (unsigned char)0x23;
149
150 //std::cerr << "["+PixelUtil::getFormatName(srcFormat)+"->"+PixelUtil::getFormatName(dstFormat)+"]" << " " << eob << std::endl;
151
152 // Do pack/unpacking with both naive and optimized version
153 PixelUtil::bulkPixelConversion(src, dst1);
154 naiveBulkPixelConversion(src, dst2);
155
156 CPPUNIT_ASSERT_EQUAL(temp[eob], (unsigned char)0x56);
157 CPPUNIT_ASSERT_EQUAL(temp[eob+1], (unsigned char)0x23);
158
159 std::stringstream s;
160 int x;
161 s << "src=";
162 for(x=0; x<16; x++)
163 s << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) randomData[x];
164 s << " dst=";
165 for(x=0; x<16; x++)
166 s << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) temp[x];
167 s << " dstRef=";
168 for(x=0; x<16; x++)
169 s << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) temp2[x];
170 s << " ";
171
172 // Compare result
173 StringUtil::StrStreamType msg;
174 msg << "Conversion mismatch [" << PixelUtil::getFormatName(srcFormat) <<
175 "->" << PixelUtil::getFormatName(dstFormat) << "] " << s.str();
176 CPPUNIT_ASSERT_MESSAGE(msg.str().c_str(),
177 memcmp(dst1.data, dst2.data, eob) == 0);
178 }
179
testBulkConversion()180 void PixelFormatTests::testBulkConversion()
181 {
182 // Self match
183 testCase(PF_A8R8G8B8, PF_A8R8G8B8);
184 // Optimized
185 testCase(PF_A8R8G8B8,PF_A8B8G8R8);
186 testCase(PF_A8R8G8B8,PF_B8G8R8A8);
187 testCase(PF_A8R8G8B8,PF_R8G8B8A8);
188 testCase(PF_A8B8G8R8,PF_A8R8G8B8);
189 testCase(PF_A8B8G8R8,PF_B8G8R8A8);
190 testCase(PF_A8B8G8R8,PF_R8G8B8A8);
191 testCase(PF_B8G8R8A8,PF_A8R8G8B8);
192 testCase(PF_B8G8R8A8,PF_A8B8G8R8);
193 testCase(PF_B8G8R8A8,PF_R8G8B8A8);
194 testCase(PF_R8G8B8A8,PF_A8R8G8B8);
195 testCase(PF_R8G8B8A8,PF_A8B8G8R8);
196 testCase(PF_R8G8B8A8,PF_B8G8R8A8);
197
198 testCase(PF_A8B8G8R8, PF_L8);
199 testCase(PF_L8, PF_A8B8G8R8);
200 testCase(PF_A8R8G8B8, PF_L8);
201 testCase(PF_L8, PF_A8R8G8B8);
202 testCase(PF_B8G8R8A8, PF_L8);
203 testCase(PF_L8, PF_B8G8R8A8);
204 testCase(PF_L8, PF_L16);
205 testCase(PF_L16, PF_L8);
206 testCase(PF_R8G8B8, PF_B8G8R8);
207 testCase(PF_B8G8R8, PF_R8G8B8);
208 testCase(PF_B8G8R8, PF_R8G8B8);
209 testCase(PF_R8G8B8, PF_B8G8R8);
210 testCase(PF_R8G8B8, PF_A8R8G8B8);
211 testCase(PF_B8G8R8, PF_A8R8G8B8);
212 testCase(PF_R8G8B8, PF_A8B8G8R8);
213 testCase(PF_B8G8R8, PF_A8B8G8R8);
214 testCase(PF_R8G8B8, PF_B8G8R8A8);
215 testCase(PF_B8G8R8, PF_B8G8R8A8);
216 testCase(PF_A8R8G8B8, PF_R8G8B8);
217 testCase(PF_A8R8G8B8, PF_B8G8R8);
218 testCase(PF_X8R8G8B8, PF_A8R8G8B8);
219 testCase(PF_X8R8G8B8, PF_A8B8G8R8);
220 testCase(PF_X8R8G8B8, PF_B8G8R8A8);
221 testCase(PF_X8R8G8B8, PF_R8G8B8A8);
222 testCase(PF_X8B8G8R8, PF_A8R8G8B8);
223 testCase(PF_X8B8G8R8, PF_A8B8G8R8);
224 testCase(PF_X8B8G8R8, PF_B8G8R8A8);
225 testCase(PF_X8B8G8R8, PF_R8G8B8A8);
226
227 //CPPUNIT_ASSERT_MESSAGE("Conversion mismatch", false);
228 }
229
230