blob: 311f1ecdfa33d4dce815dba805c941d37fa7f0d7 [file] [log] [blame]
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001// XGL tests
2//
3// Copyright (C) 2014 LunarG, Inc.
4//
5// Permission is hereby granted, free of charge, to any person obtaining a
6// copy of this software and associated documentation files (the "Software"),
7// to deal in the Software without restriction, including without limitation
8// the rights to use, copy, modify, merge, publish, distribute, sublicense,
9// and/or sell copies of the Software, and to permit persons to whom the
10// Software is furnished to do so, subject to the following conditions:
11//
12// The above copyright notice and this permission notice shall be included
13// in all copies or substantial portions of the Software.
14//
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21// DEALINGS IN THE SOFTWARE.
22
23#include "xgltestframework.h"
24#include "GL/freeglut_std.h"
25
26XglTestFramework::XglTestFramework() :
27 m_glut_initialized( false )
28{
29}
30
31// Define all the static elements
32bool XglTestFramework::m_show_images = false;
33bool XglTestFramework::m_save_images = false;
34int XglTestFramework::m_width = 0;
35int XglTestFramework::m_height = 0;
36int XglTestFramework::m_window = 0;
37std::list<XglTestImageRecord> XglTestFramework::m_images;
38std::list<XglTestImageRecord>::iterator XglTestFramework::m_display_image;
39int m_display_image_idx = 0;
40
41void XglTestFramework::InitArgs(int *argc, char *argv[])
42{
43 int i, n;
44
45 for (i=0, n=0; i< *argc; i++) {
46 if (strncmp("--show-images", argv[i], 13) == 0) {
47 m_show_images = true;
48 continue;
49 }
50 if (strncmp("--save-images", argv[i], 13) == 0) {
51 m_save_images = true;
52 continue;
53 }
54
55 /*
56 * Since the above "consume" inputs, update argv
57 * so that it contains the trimmed list of args for glutInit
58 */
59 argv[n] = argv[i];
60 n++;
61 }
62
63 if (m_show_images) {
64 glutInit(argc, argv);
65 }
66}
67
68void XglTestFramework::Reshape( int w, int h )
69{
70 if (!m_show_images) return; // Do nothing except save info if not enabled
71
72 // Resize window to be large enough to handle biggest image we've seen
73 // TODO: Probably need some sort of limits for the Window system.
74 if (w > m_width) {
75 m_width = w;
76 }
77 if (h > m_height) {
78 m_height = h;
79 }
80
81 glutReshapeWindow(m_width, m_height);
82
83 glViewport( 0, 0, m_width, m_height );
84 glMatrixMode( GL_PROJECTION );
85 glLoadIdentity();
86 glOrtho( 0.0, m_width, 0.0, m_height, 0.0, 2.0 );
87 glMatrixMode( GL_MODELVIEW );
88 glLoadIdentity();
89
90// glScissor(width/4, height/4, width/2, height/2);
91}
92
93void XglTestFramework::WritePPM( const char *basename, XglImage *image )
94{
95 string filename;
96 XGL_RESULT err;
97 int x, y;
98
99 filename.append(basename);
100 filename.append(".ppm");
101
102 const XGL_IMAGE_SUBRESOURCE sr = {
103 XGL_IMAGE_ASPECT_COLOR, 0, 0
104 };
105 XGL_SUBRESOURCE_LAYOUT sr_layout;
Jon Ashburne494a1a2014-09-25 14:36:58 -0600106 XGL_UINT data_size = sizeof(sr_layout);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600107
108 err = xglGetImageSubresourceInfo( image->image(), &sr,
109 XGL_INFO_TYPE_SUBRESOURCE_LAYOUT,
110 &data_size, &sr_layout);
111 ASSERT_XGL_SUCCESS( err );
112 ASSERT_EQ(data_size, sizeof(sr_layout));
113
114 const char *ptr;
115
116 err = xglMapMemory( image->memory(), 0, (XGL_VOID **) &ptr );
117 ASSERT_XGL_SUCCESS( err );
118
119 ptr += sr_layout.offset;
120
121 ofstream file (filename.c_str());
122 ASSERT_TRUE(file.is_open()) << "Unable to open file: " << filename;
123
124 file << "P6\n";
125 file << image->width() << "\n";
126 file << image->height() << "\n";
127 file << 255 << "\n";
128
129 for (y = 0; y < image->height(); y++) {
130 const char *row = ptr;
131
132 for (x = 0; x < image->width(); x++) {
133 file.write(row, 3);
134 row += 4;
135 }
136
137 ptr += sr_layout.rowPitch;
138 }
139
140 file.close();
141
142 err = xglUnmapMemory( image->memory() );
143 ASSERT_XGL_SUCCESS( err );
144}
145
146void XglTestFramework::InitGLUT(int w, int h)
147{
148
149 if (!m_show_images) return;
150
151 if (!m_glut_initialized) {
152 glutInitWindowSize(w, h);
153
154 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
155 m_window = glutCreateWindow(NULL);
156 m_glut_initialized = true;
157 }
158
159 Reshape(w, h);
160}
161
162void XglTestFramework::Show(const char *comment, XglImage *image)
163{
164 XGL_RESULT err;
165
166 const XGL_IMAGE_SUBRESOURCE sr = {
167 XGL_IMAGE_ASPECT_COLOR, 0, 0
168 };
169 XGL_SUBRESOURCE_LAYOUT sr_layout;
Jon Ashburne494a1a2014-09-25 14:36:58 -0600170 XGL_UINT data_size = sizeof(sr_layout);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600171
172 if (!m_show_images) return;
173
174 InitGLUT(image->width(), image->height());
175
176 err = xglGetImageSubresourceInfo( image->image(), &sr, XGL_INFO_TYPE_SUBRESOURCE_LAYOUT,
177 &data_size, &sr_layout);
178 ASSERT_XGL_SUCCESS( err );
179 ASSERT_EQ(data_size, sizeof(sr_layout));
180
181 const char *ptr;
182
183 err = image->MapMemory( (XGL_VOID **) &ptr );
184 ASSERT_XGL_SUCCESS( err );
185
186 ptr += sr_layout.offset;
187
188 XglTestImageRecord record;
189 record.m_title.append(comment);
190 record.m_width = image->width();
191 record.m_height = image->height();
192 // TODO: Need to make this more robust to handle different image formats
193 record.m_data_size = image->width()*image->height()*4;
194 record.m_data = malloc(record.m_data_size);
195 memcpy(record.m_data, ptr, record.m_data_size);
196 m_images.push_back(record);
197 m_display_image = --m_images.end();
198
199 Display();
200
201 err = image->UnmapMemory();
202 ASSERT_XGL_SUCCESS( err );
203}
204
205void XglTestFramework::RecordImage(XglImage *image)
206{
207 const ::testing::TestInfo* const test_info =
208 ::testing::UnitTest::GetInstance()->current_test_info();
209
210 if (m_save_images) {
211 WritePPM(test_info->test_case_name(), image);
212 }
213
214 if (m_show_images) {
215 Show(test_info->test_case_name(), image);
216 }
217}
218
219void XglTestFramework::Display()
220{
221 glutSetWindowTitle(m_display_image->m_title.c_str());
222
223 glClearColor(0, 0, 0, 0);
224 glClear(GL_COLOR_BUFFER_BIT);
225 glRasterPos3f(0, 0, 0);
226 glBitmap(0, 0, 0, 0, 0, 0, NULL);
227 glDrawPixels(m_display_image->m_width, m_display_image->m_height,
228 GL_RGBA, GL_UNSIGNED_BYTE, m_display_image->m_data);
229
230 glutSwapBuffers();
231}
232
233void XglTestFramework::Key( unsigned char key, int x, int y )
234{
235 (void) x;
236 (void) y;
237 switch (key) {
238 case 27:
239 glutDestroyWindow(m_window);
240 exit(0);
241 break;
242 }
243 glutPostRedisplay();
244}
245
246void XglTestFramework::SpecialKey( int key, int x, int y )
247{
248 (void) x;
249 (void) y;
250 switch (key) {
251 case GLUT_KEY_UP:
252 case GLUT_KEY_RIGHT:
253 ++m_display_image;
254 if (m_display_image == m_images.end()) {
255 m_display_image = m_images.begin();
256 }
257 break;
258 case GLUT_KEY_DOWN:
259 case GLUT_KEY_LEFT:
260 if (m_display_image == m_images.begin()) {
261 m_display_image = --m_images.end();
262 } else {
263 --m_display_image;
264 }
265
266 break;
267 }
268 glutPostRedisplay();
269}
270
271void XglTestFramework::Finish()
272{
273 if (m_images.size() == 0) return;
274
275 glutReshapeFunc( Reshape );
276 glutKeyboardFunc( Key );
277 glutSpecialFunc( SpecialKey );
278 glutDisplayFunc( Display );
279
280 glutMainLoop();
281}
282
283
284
285XglTestImageRecord::XglTestImageRecord() : // Constructor
286 m_width( 0 ),
287 m_height( 0 ),
288 m_data( NULL )
289{
290 m_data_size = 0;
291}
292
293XglTestImageRecord::~XglTestImageRecord()
294{
295
296}
297
298XglTestImageRecord::XglTestImageRecord(const XglTestImageRecord &copyin) // Copy constructor to handle pass by value.
299{
300 m_title = copyin.m_title;
301 m_width = copyin.m_width;
302 m_height = copyin.m_height;
303 m_data_size = copyin.m_data_size;
304 m_data = copyin.m_data; // TODO: Do we need to copy the data or is pointer okay?
305}
306
307ostream &operator<<(ostream &output, const XglTestImageRecord &XglTestImageRecord)
308{
309 output << XglTestImageRecord.m_title << " (" << XglTestImageRecord.m_width <<
310 "," << XglTestImageRecord.m_height << ")" << endl;
311 return output;
312}
313
314XglTestImageRecord& XglTestImageRecord::operator=(const XglTestImageRecord &rhs)
315{
316 m_title = rhs.m_title;
317 m_width = rhs.m_width;
318 m_height = rhs.m_height;
319 m_data_size = rhs.m_data_size;
320 m_data = rhs.m_data;
321 return *this;
322}
323
324int XglTestImageRecord::operator==(const XglTestImageRecord &rhs) const
325{
326 if( this->m_data != rhs.m_data) return 0;
327 return 1;
328}
329
330// This function is required for built-in STL list functions like sort
331int XglTestImageRecord::operator<(const XglTestImageRecord &rhs) const
332{
333 if( this->m_data_size < rhs.m_data_size ) return 1;
334 return 0;
335}
336