blob: eb57327ce10e682e248d379ef70a7c7d58477e08 [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"
Chia-I Wua6bc0ce2014-12-29 14:38:28 +080024#include "xglrenderframework.h"
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -060025#include "GL/freeglut_std.h"
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060026//#include "ShaderLang.h"
Steve Kc1638cc2015-03-17 09:40:23 -060027#include "GlslangToSpv.h"
Tony Barbour4ab45422014-12-10 17:00:20 -070028#include <limits.h>
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060029#include <math.h>
Chia-I Wuec664fa2014-12-02 11:54:24 +080030#include <wand/MagickWand.h>
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060031
32// Command-line options
33enum TOptions {
34 EOptionNone = 0x000,
35 EOptionIntermediate = 0x001,
36 EOptionSuppressInfolog = 0x002,
37 EOptionMemoryLeakMode = 0x004,
38 EOptionRelaxedErrors = 0x008,
39 EOptionGiveWarnings = 0x010,
40 EOptionLinkProgram = 0x020,
41 EOptionMultiThreaded = 0x040,
42 EOptionDumpConfig = 0x080,
43 EOptionDumpReflection = 0x100,
44 EOptionSuppressWarnings = 0x200,
45 EOptionDumpVersions = 0x400,
Cody Northrop3bfd27c2015-03-17 15:55:58 -060046 EOptionSpv = 0x800,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060047 EOptionDefaultDesktop = 0x1000,
48};
49
50#ifndef _WIN32
51
52#include <errno.h>
53
54int fopen_s(
55 FILE** pFile,
56 const char* filename,
57 const char* mode
58)
59{
60 if (!pFile || !filename || !mode) {
61 return EINVAL;
62 }
63
64 FILE* f = fopen(filename, mode);
65 if (! f) {
66 if (errno != 0) {
67 return errno;
68 } else {
69 return ENOENT;
70 }
71 }
72 *pFile = f;
73
74 return 0;
75}
76
77#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -060078
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -060079// Set up environment for GLSL compiler
80// Must be done once per process
81void TestEnvironment::SetUp()
82{
Cody Northrop3bfd27c2015-03-17 15:55:58 -060083 // Initialize GLSL to SPV compiler utility
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -060084 glslang::InitializeProcess();
Chia-I Wub76e0fa2014-12-28 14:27:28 +080085
86 xgl_testing::set_error_callback(test_error_callback);
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -060087}
88
89void TestEnvironment::TearDown()
90{
91 glslang::FinalizeProcess();
92}
93
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -060094XglTestFramework::XglTestFramework() :
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060095 m_compile_options( 0 ),
96 m_num_shader_strings( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -060097{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -060098
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060099}
100
101XglTestFramework::~XglTestFramework()
102{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600103
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600104}
105
106// Define all the static elements
107bool XglTestFramework::m_show_images = false;
108bool XglTestFramework::m_save_images = false;
Tony Barbour247bf372014-10-30 14:29:04 -0600109bool XglTestFramework::m_compare_images = false;
Tony Barbour0dd968a2015-04-02 15:48:24 -0600110#ifdef _WIN32
111bool XglTestFramework::m_use_spv = false;
112#else
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600113bool XglTestFramework::m_use_spv = true;
Tony Barbour0dd968a2015-04-02 15:48:24 -0600114#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600115int XglTestFramework::m_width = 0;
116int XglTestFramework::m_height = 0;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600117std::list<XglTestImageRecord> XglTestFramework::m_images;
118std::list<XglTestImageRecord>::iterator XglTestFramework::m_display_image;
119int m_display_image_idx = 0;
120
121void XglTestFramework::InitArgs(int *argc, char *argv[])
122{
123 int i, n;
124
125 for (i=0, n=0; i< *argc; i++) {
126 if (strncmp("--show-images", argv[i], 13) == 0) {
127 m_show_images = true;
128 continue;
129 }
130 if (strncmp("--save-images", argv[i], 13) == 0) {
131 m_save_images = true;
132 continue;
133 }
134
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600135 if (strncmp("--use-SPV", argv[i], 13) == 0) {
136 m_use_spv = true;
Courtney Goeltzenleuchterb666dc62014-10-09 09:13:56 -0600137 continue;
138 }
139
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600140 if (strncmp("--no-SPV", argv[i], 13) == 0) {
141 m_use_spv = false;
Courtney Goeltzenleuchterc44e3ee2014-10-31 14:13:33 -0600142 continue;
143 }
144
Tony Barbour247bf372014-10-30 14:29:04 -0600145 if (strncmp("--compare-images", argv[i], 16) == 0) {
146 m_compare_images = true;
147 continue;
148 }
149
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600150 /*
151 * Since the above "consume" inputs, update argv
152 * so that it contains the trimmed list of args for glutInit
153 */
Tony Barboura98d3932014-12-11 09:52:49 -0700154 if (strncmp("--help", argv[i], 6) == 0 || strncmp("-h", argv[i], 2) == 0) {
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700155 printf("\nOther options:\n");
156 printf("\t--show-images\n"
157 "\t\tDisplay test images in viewer after tests complete.\n");
158 printf("\t--save-images\n"
159 "\t\tSave tests images as ppm files in current working directory.\n"
160 "\t\tUsed to generate golden images for compare-images.\n");
161 printf("\t--compare-images\n"
162 "\t\tCompare test images to 'golden' image in golden folder.\n"
Tony Barboura98d3932014-12-11 09:52:49 -0700163 "\t\tAlso saves the generated test image in current working\n"
164 "\t\t\tdirectory but only if the image is different from the golden\n"
165 "\t\tSetting RENDERTEST_GOLDEN_DIR environment variable can specify\n"
166 "\t\t\tdifferent directory for golden images\n"
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700167 "\t\tSignal test failure if different.\n");
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600168 printf("\t--use-SPV\n"
169 "\t\tUse SPV code path (default).\n");
170 printf("\t--no-SPV\n"
171 "\t\tUse built-in GLSL compiler rather than SPV code path.\n");
Tony Barbour4ab45422014-12-10 17:00:20 -0700172 exit(0);
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700173 }
174
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600175 argv[n] = argv[i];
176 n++;
177 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600178}
179
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600180void XglTestFramework::WritePPM( const char *basename, XglImage *image )
181{
182 string filename;
183 XGL_RESULT err;
Tony Barbour84d448c2015-04-02 14:02:33 -0600184 int x, y;
185 XglImage displayImage(image->device());
186
187 displayImage.init(image->extent().width, image->extent().height, image->format(), 0, XGL_LINEAR_TILING);
188 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600189
190 filename.append(basename);
191 filename.append(".ppm");
192
193 const XGL_IMAGE_SUBRESOURCE sr = {
194 XGL_IMAGE_ASPECT_COLOR, 0, 0
195 };
196 XGL_SUBRESOURCE_LAYOUT sr_layout;
Chia-I Wu99ff89d2014-12-27 14:14:50 +0800197 size_t data_size = sizeof(sr_layout);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600198
199 err = xglGetImageSubresourceInfo( image->image(), &sr,
200 XGL_INFO_TYPE_SUBRESOURCE_LAYOUT,
201 &data_size, &sr_layout);
202 ASSERT_XGL_SUCCESS( err );
203 ASSERT_EQ(data_size, sizeof(sr_layout));
204
Tony Barbour84d448c2015-04-02 14:02:33 -0600205 char *ptr;
206 ptr = (char *) displayImage.map();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600207 ptr += sr_layout.offset;
208
209 ofstream file (filename.c_str());
210 ASSERT_TRUE(file.is_open()) << "Unable to open file: " << filename;
211
212 file << "P6\n";
Tony Barbour84d448c2015-04-02 14:02:33 -0600213 file << displayImage.width() << "\n";
214 file << displayImage.height() << "\n";
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600215 file << 255 << "\n";
216
Tony Barbour84d448c2015-04-02 14:02:33 -0600217 for (y = 0; y < displayImage.height(); y++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700218 const int *row = (const int *) ptr;
219 int swapped;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600220
Tony Barbour84d448c2015-04-02 14:02:33 -0600221 if (displayImage.format() == XGL_FMT_B8G8R8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700222 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600223 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700224 swapped = (*row & 0xff00ff00) | (*row & 0x000000ff) << 16 | (*row & 0x00ff0000) >> 16;
225 file.write((char *) &swapped, 3);
226 row++;
227 }
228 }
Tony Barbour84d448c2015-04-02 14:02:33 -0600229 else if (displayImage.format() == XGL_FMT_R8G8B8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700230 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600231 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700232 file.write((char *) row, 3);
233 row++;
234 }
235 }
236 else {
237 printf("Unrecognized image format - will not write image files");
238 break;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600239 }
240
241 ptr += sr_layout.rowPitch;
242 }
243
244 file.close();
Tony Barbour84d448c2015-04-02 14:02:33 -0600245 displayImage.unmap();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600246}
247
Tony Barbour247bf372014-10-30 14:29:04 -0600248void XglTestFramework::Compare(const char *basename, XglImage *image )
249{
250
251 MagickWand *magick_wand_1;
252 MagickWand *magick_wand_2;
253 MagickWand *compare_wand;
254 MagickBooleanType status;
Tony Barbour4ab45422014-12-10 17:00:20 -0700255 char testimage[256],golden[PATH_MAX+256],golddir[PATH_MAX] = "./golden";
Tony Barbour247bf372014-10-30 14:29:04 -0600256 double differenz;
257
Tony Barbour4ab45422014-12-10 17:00:20 -0700258 if (getenv("RENDERTEST_GOLDEN_DIR"))
259 {
260 strcpy(golddir,getenv("RENDERTEST_GOLDEN_DIR"));
261 }
262
Tony Barbour247bf372014-10-30 14:29:04 -0600263 MagickWandGenesis();
264 magick_wand_1=NewMagickWand();
265 sprintf(testimage,"%s.ppm",basename);
266 status=MagickReadImage(magick_wand_1,testimage);
267 ASSERT_TRUE(status) << "Unable to open file: " << testimage;
268
269
270 MagickWandGenesis();
271 magick_wand_2=NewMagickWand();
Tony Barbour4ab45422014-12-10 17:00:20 -0700272 sprintf(golden,"%s/%s.ppm",golddir,basename);
Tony Barbour247bf372014-10-30 14:29:04 -0600273 status=MagickReadImage(magick_wand_2,golden);
274 ASSERT_TRUE(status) << "Unable to open file: " << golden;
275
Tony Barbour247bf372014-10-30 14:29:04 -0600276 compare_wand=MagickCompareImages(magick_wand_1,magick_wand_2, MeanAbsoluteErrorMetric, &differenz);
277 if (differenz != 0.0)
278 {
279 char difference[256];
280
281 sprintf(difference,"%s-diff.ppm",basename);
282 status = MagickWriteImage(compare_wand, difference);
283 ASSERT_TRUE(differenz == 0.0) << "Image comparison failed - diff file written";
284 }
285 DestroyMagickWand(compare_wand);
286
287 DestroyMagickWand(magick_wand_1);
288 DestroyMagickWand(magick_wand_2);
289 MagickWandTerminus();
Courtney Goeltzenleuchterfcda72d2014-12-05 15:41:02 -0700290
291 if (differenz == 0.0)
292 {
293 /*
294 * If test image and golden image match, we do not need to
295 * keep around the test image.
296 */
297 remove(testimage);
298 }
Tony Barbour247bf372014-10-30 14:29:04 -0600299}
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600300
301void XglTestFramework::Show(const char *comment, XglImage *image)
302{
303 XGL_RESULT err;
304
305 const XGL_IMAGE_SUBRESOURCE sr = {
306 XGL_IMAGE_ASPECT_COLOR, 0, 0
307 };
308 XGL_SUBRESOURCE_LAYOUT sr_layout;
Chia-I Wu99ff89d2014-12-27 14:14:50 +0800309 size_t data_size = sizeof(sr_layout);
Tony Barbour96db8822015-02-25 12:28:39 -0700310 XglTestImageRecord record;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600311
312 if (!m_show_images) return;
313
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600314 err = xglGetImageSubresourceInfo( image->image(), &sr, XGL_INFO_TYPE_SUBRESOURCE_LAYOUT,
315 &data_size, &sr_layout);
316 ASSERT_XGL_SUCCESS( err );
317 ASSERT_EQ(data_size, sizeof(sr_layout));
318
Tony Barbour96db8822015-02-25 12:28:39 -0700319 char *ptr;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600320
Mark Lobodzinski17caf572015-01-29 08:55:56 -0600321 err = image->MapMemory( (void **) &ptr );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600322 ASSERT_XGL_SUCCESS( err );
323
324 ptr += sr_layout.offset;
325
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600326 record.m_title.append(comment);
327 record.m_width = image->width();
328 record.m_height = image->height();
329 // TODO: Need to make this more robust to handle different image formats
330 record.m_data_size = image->width()*image->height()*4;
331 record.m_data = malloc(record.m_data_size);
332 memcpy(record.m_data, ptr, record.m_data_size);
333 m_images.push_back(record);
334 m_display_image = --m_images.end();
335
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600336 err = image->UnmapMemory();
337 ASSERT_XGL_SUCCESS( err );
Tony Barbour96db8822015-02-25 12:28:39 -0700338
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600339}
340
Tony Barbour247bf372014-10-30 14:29:04 -0600341void XglTestFramework::RecordImage(XglImage *image, char *tag)
342{
343 const ::testing::TestInfo* const test_info =
344 ::testing::UnitTest::GetInstance()->current_test_info();
345 ostringstream filestream;
346 string filename;
347
348 filestream << test_info->name() << "-" << tag;
349 filename = filestream.str();
350 // ToDo - scrub string for bad characters
351
352 if (m_save_images || m_compare_images) {
353 WritePPM(filename.c_str(), image);
354 if (m_compare_images) {
355 Compare(filename.c_str(), image);
356 }
357 }
358
359 if (m_show_images) {
360 Show(test_info->name(), image);
361 }
362}
363
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600364void XglTestFramework::RecordImage(XglImage *image)
365{
366 const ::testing::TestInfo* const test_info =
367 ::testing::UnitTest::GetInstance()->current_test_info();
Tony Barbour247bf372014-10-30 14:29:04 -0600368 ostringstream filestream;
369 string filename;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600370
Tony Barbour247bf372014-10-30 14:29:04 -0600371 m_width = 40;
372
373 if (strcmp(test_info->name(), m_testName.c_str())) {
374 filestream << test_info->name();
375 m_testName.assign(test_info->name());
Tony Barboura0e2ee82014-11-18 17:02:36 -0700376 m_frameNum = 2;
377 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600378 }
379 else {
380 filestream << test_info->name() << "-" << m_frameNum;
381 m_frameNum++;
Tony Barboura0e2ee82014-11-18 17:02:36 -0700382 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600383 }
384
385
386 // ToDo - scrub string for bad characters
387
388 if (m_save_images || m_compare_images) {
389 WritePPM(filename.c_str(), image);
390 if (m_compare_images) {
391 Compare(filename.c_str(), image);
392 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600393 }
394
395 if (m_show_images) {
Courtney Goeltzenleuchter02d33c12014-10-08 14:26:40 -0600396 Show(test_info->name(), image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600397 }
398}
399
Tony Barbour96db8822015-02-25 12:28:39 -0700400static xgl_testing::Environment *environment;
401
402TestFrameworkXglPresent::TestFrameworkXglPresent() :
403m_device(environment->default_device()),
404m_queue(*m_device.graphics_queues()[0]),
405m_cmdbuf(m_device, xgl_testing::CmdBuffer::create_info(XGL_QUEUE_TYPE_GRAPHICS))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600406{
Tony Barbour96db8822015-02-25 12:28:39 -0700407 m_quit = false;
408 m_pause = false;
409 m_width = 0;
410 m_height = 0;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600411}
412
Tony Barbour96db8822015-02-25 12:28:39 -0700413void TestFrameworkXglPresent::Display()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600414{
Tony Barbour96db8822015-02-25 12:28:39 -0700415 XGL_RESULT err;
416
Tony Barbourbdf0a312015-04-01 17:10:07 -0600417 XGL_WSI_X11_PRESENT_INFO present = {};
418 present.destWindow = m_window;
419 present.srcImage = m_display_image->m_presentableImage;
Tony Barbour96db8822015-02-25 12:28:39 -0700420
421 xcb_change_property (environment->m_connection,
422 XCB_PROP_MODE_REPLACE,
423 m_window,
424 XCB_ATOM_WM_NAME,
425 XCB_ATOM_STRING,
426 8,
427 m_display_image->m_title.size(),
428 m_display_image->m_title.c_str());
429
430 err = xglWsiX11QueuePresent(m_queue.obj(), &present, NULL);
431 assert(!err);
432
433 m_queue.wait();
434
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600435}
436
Tony Barbour96db8822015-02-25 12:28:39 -0700437void TestFrameworkXglPresent::HandleEvent(xcb_generic_event_t *event)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600438{
Tony Barbour0dd968a2015-04-02 15:48:24 -0600439 uint8_t event_code = event->response_type & 0x7f;
Tony Barbour96db8822015-02-25 12:28:39 -0700440 switch (event_code) {
441 case XCB_EXPOSE:
442 Display(); // TODO: handle resize
443 break;
444 case XCB_CLIENT_MESSAGE:
445 if((*(xcb_client_message_event_t*)event).data.data32[0] ==
446 (m_atom_wm_delete_window)->atom) {
447 m_quit = true;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600448 }
449 break;
Tony Barbour96db8822015-02-25 12:28:39 -0700450 case XCB_KEY_RELEASE:
451 {
452 const xcb_key_release_event_t *key =
453 (const xcb_key_release_event_t *) event;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600454
Tony Barbour96db8822015-02-25 12:28:39 -0700455 switch (key->detail) {
456 case 0x9: // Escape
457 m_quit = true;
458 break;
459 case 0x71: // left arrow key
460 if (m_display_image == m_images.begin()) {
461 m_display_image = --m_images.end();
462 } else {
463 --m_display_image;
464 }
465 break;
466 case 0x72: // right arrow key
467 ++m_display_image;
468 if (m_display_image == m_images.end()) {
469 m_display_image = m_images.begin();
470 }
471 break;
472 case 0x41:
473 m_pause = !m_pause;
474 break;
475 }
476 Display();
477 }
478 break;
479 default:
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600480 break;
481 }
Tony Barbour96db8822015-02-25 12:28:39 -0700482}
483
484void TestFrameworkXglPresent::Run()
485{
486 xcb_flush(environment->m_connection);
487
488 while (! m_quit) {
489 xcb_generic_event_t *event;
490
491 if (m_pause) {
492 event = xcb_wait_for_event(environment->m_connection);
493 } else {
494 event = xcb_poll_for_event(environment->m_connection);
495 }
496 if (event) {
497 HandleEvent(event);
498 free(event);
499 }
500 }
501}
502
503void TestFrameworkXglPresent::CreatePresentableImages()
504{
505 XGL_RESULT err;
506
507 m_display_image = m_images.begin();
508
509 for (int x=0; x < m_images.size(); x++)
510 {
Tony Barbourbdf0a312015-04-01 17:10:07 -0600511 XGL_WSI_X11_PRESENTABLE_IMAGE_CREATE_INFO presentable_image_info = {};
512 presentable_image_info.format = XGL_FMT_B8G8R8A8_UNORM;
513 presentable_image_info.usage = XGL_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
514 presentable_image_info.extent.width = m_display_image->m_width;
515 presentable_image_info.extent.height = m_display_image->m_height;
516 presentable_image_info.flags = 0;
Tony Barbour96db8822015-02-25 12:28:39 -0700517
518 void *dest_ptr;
519
520 err = xglWsiX11CreatePresentableImage(m_device.obj(), &presentable_image_info,
521 &m_display_image->m_presentableImage, &m_display_image->m_presentableMemory);
522 assert(!err);
523
524 xgl_testing::Buffer buf;
525 buf.init(m_device, (XGL_GPU_SIZE) m_display_image->m_data_size);
526 dest_ptr = buf.map();
527 memcpy(dest_ptr,m_display_image->m_data, m_display_image->m_data_size);
528 buf.unmap();
529
530 m_cmdbuf.begin();
531
532 XGL_BUFFER_IMAGE_COPY region = {};
533 region.imageExtent.height = m_display_image->m_height;
534 region.imageExtent.width = m_display_image->m_width;
535 region.imageExtent.depth = 1;
536
537 xglCmdCopyBufferToImage(m_cmdbuf.obj(), buf.obj(), m_display_image->m_presentableImage, 1, &region);
538 m_cmdbuf.end();
539
540 uint32_t numMemRefs=2;
541 XGL_MEMORY_REF memRefs[2];
542 memRefs[0].flags = 0;
543 memRefs[0].mem = m_display_image->m_presentableMemory;
544 memRefs[1].flags = 0;
545 memRefs[1].mem = buf.memories()[0];
546
547 XGL_CMD_BUFFER cmdBufs[1];
548 cmdBufs[0] = m_cmdbuf.obj();
549
550 xglQueueSubmit(m_queue.obj(), 1, cmdBufs, numMemRefs, memRefs, NULL);
551 m_queue.wait();
552
553
554 if (m_display_image->m_width > m_width)
555 m_width = m_display_image->m_width;
556
557 if (m_display_image->m_height > m_height)
558 m_height = m_display_image->m_height;
559
560
561 ++m_display_image;
562
563 }
564
565 m_display_image = m_images.begin();
566}
567
568void TestFrameworkXglPresent::InitPresentFramework(std::list<XglTestImageRecord> &imagesIn)
569{
570 m_images = imagesIn;
571}
572
573void TestFrameworkXglPresent::CreateWindow()
574{
575 uint32_t value_mask, value_list[32];
576
577 m_window = xcb_generate_id(environment->m_connection);
578
579 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
580 value_list[0] = environment->m_screen->black_pixel;
581 value_list[1] = XCB_EVENT_MASK_KEY_RELEASE |
582 XCB_EVENT_MASK_EXPOSURE |
583 XCB_EVENT_MASK_STRUCTURE_NOTIFY;
584
585 xcb_create_window(environment->m_connection,
586 XCB_COPY_FROM_PARENT,
587 m_window, environment->m_screen->root,
588 0, 0, m_width, m_height, 0,
589 XCB_WINDOW_CLASS_INPUT_OUTPUT,
590 environment->m_screen->root_visual,
591 value_mask, value_list);
592
593 /* Magic code that will send notification when window is destroyed */
594 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(environment->m_connection, 1, 12,
595 "WM_PROTOCOLS");
596 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(environment->m_connection, cookie, 0);
597
598 xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(environment->m_connection, 0, 16, "WM_DELETE_WINDOW");
599 m_atom_wm_delete_window = xcb_intern_atom_reply(environment->m_connection, cookie2, 0);
600
601 xcb_change_property(environment->m_connection, XCB_PROP_MODE_REPLACE,
602 m_window, (*reply).atom, 4, 32, 1,
603 &(*m_atom_wm_delete_window).atom);
604 free(reply);
605
606 xcb_map_window(environment->m_connection, m_window);
607}
608
609void TestFrameworkXglPresent::TearDown()
610{
611 xcb_destroy_window(environment->m_connection, m_window);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600612}
613
614void XglTestFramework::Finish()
615{
616 if (m_images.size() == 0) return;
617
Tony Barbour96db8822015-02-25 12:28:39 -0700618 environment = new xgl_testing::Environment();
619 ::testing::AddGlobalTestEnvironment(environment);
620 environment->X11SetUp();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600621
Tony Barbour96db8822015-02-25 12:28:39 -0700622 {
623 TestFrameworkXglPresent xglPresent;
624
625 xglPresent.InitPresentFramework(m_images);
626 xglPresent.CreatePresentableImages();
627 xglPresent.CreateWindow();
628 xglPresent.Run();
629 xglPresent.TearDown();
630 }
631 environment->TearDown();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600632}
633
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600634//
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600635// These are the default resources for TBuiltInResources, used for both
636// - parsing this string for the case where the user didn't supply one
637// - dumping out a template for user construction of a config file
638//
639static const char* DefaultConfig =
640 "MaxLights 32\n"
641 "MaxClipPlanes 6\n"
642 "MaxTextureUnits 32\n"
643 "MaxTextureCoords 32\n"
644 "MaxVertexAttribs 64\n"
645 "MaxVertexUniformComponents 4096\n"
646 "MaxVaryingFloats 64\n"
647 "MaxVertexTextureImageUnits 32\n"
648 "MaxCombinedTextureImageUnits 80\n"
649 "MaxTextureImageUnits 32\n"
650 "MaxFragmentUniformComponents 4096\n"
651 "MaxDrawBuffers 32\n"
652 "MaxVertexUniformVectors 128\n"
653 "MaxVaryingVectors 8\n"
654 "MaxFragmentUniformVectors 16\n"
655 "MaxVertexOutputVectors 16\n"
656 "MaxFragmentInputVectors 15\n"
657 "MinProgramTexelOffset -8\n"
658 "MaxProgramTexelOffset 7\n"
659 "MaxClipDistances 8\n"
660 "MaxComputeWorkGroupCountX 65535\n"
661 "MaxComputeWorkGroupCountY 65535\n"
662 "MaxComputeWorkGroupCountZ 65535\n"
663 "MaxComputeWorkGroupSizeX 1024\n"
664 "MaxComputeWorkGroupSizeY 1024\n"
665 "MaxComputeWorkGroupSizeZ 64\n"
666 "MaxComputeUniformComponents 1024\n"
667 "MaxComputeTextureImageUnits 16\n"
668 "MaxComputeImageUniforms 8\n"
669 "MaxComputeAtomicCounters 8\n"
670 "MaxComputeAtomicCounterBuffers 1\n"
671 "MaxVaryingComponents 60\n"
672 "MaxVertexOutputComponents 64\n"
673 "MaxGeometryInputComponents 64\n"
674 "MaxGeometryOutputComponents 128\n"
675 "MaxFragmentInputComponents 128\n"
676 "MaxImageUnits 8\n"
677 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
678 "MaxCombinedShaderOutputResources 8\n"
679 "MaxImageSamples 0\n"
680 "MaxVertexImageUniforms 0\n"
681 "MaxTessControlImageUniforms 0\n"
682 "MaxTessEvaluationImageUniforms 0\n"
683 "MaxGeometryImageUniforms 0\n"
684 "MaxFragmentImageUniforms 8\n"
685 "MaxCombinedImageUniforms 8\n"
686 "MaxGeometryTextureImageUnits 16\n"
687 "MaxGeometryOutputVertices 256\n"
688 "MaxGeometryTotalOutputComponents 1024\n"
689 "MaxGeometryUniformComponents 1024\n"
690 "MaxGeometryVaryingComponents 64\n"
691 "MaxTessControlInputComponents 128\n"
692 "MaxTessControlOutputComponents 128\n"
693 "MaxTessControlTextureImageUnits 16\n"
694 "MaxTessControlUniformComponents 1024\n"
695 "MaxTessControlTotalOutputComponents 4096\n"
696 "MaxTessEvaluationInputComponents 128\n"
697 "MaxTessEvaluationOutputComponents 128\n"
698 "MaxTessEvaluationTextureImageUnits 16\n"
699 "MaxTessEvaluationUniformComponents 1024\n"
700 "MaxTessPatchComponents 120\n"
701 "MaxPatchVertices 32\n"
702 "MaxTessGenLevel 64\n"
703 "MaxViewports 16\n"
704 "MaxVertexAtomicCounters 0\n"
705 "MaxTessControlAtomicCounters 0\n"
706 "MaxTessEvaluationAtomicCounters 0\n"
707 "MaxGeometryAtomicCounters 0\n"
708 "MaxFragmentAtomicCounters 8\n"
709 "MaxCombinedAtomicCounters 8\n"
710 "MaxAtomicCounterBindings 1\n"
711 "MaxVertexAtomicCounterBuffers 0\n"
712 "MaxTessControlAtomicCounterBuffers 0\n"
713 "MaxTessEvaluationAtomicCounterBuffers 0\n"
714 "MaxGeometryAtomicCounterBuffers 0\n"
715 "MaxFragmentAtomicCounterBuffers 1\n"
716 "MaxCombinedAtomicCounterBuffers 1\n"
717 "MaxAtomicCounterBufferSize 16384\n"
718 "MaxTransformFeedbackBuffers 4\n"
719 "MaxTransformFeedbackInterleavedComponents 64\n"
720 "MaxCullDistances 8\n"
721 "MaxCombinedClipAndCullDistances 8\n"
722 "MaxSamples 4\n"
723
724 "nonInductiveForLoops 1\n"
725 "whileLoops 1\n"
726 "doWhileLoops 1\n"
727 "generalUniformIndexing 1\n"
728 "generalAttributeMatrixVectorIndexing 1\n"
729 "generalVaryingIndexing 1\n"
730 "generalSamplerIndexing 1\n"
731 "generalVariableIndexing 1\n"
732 "generalConstantMatrixVectorIndexing 1\n"
733 ;
734
735//
736// *.conf => this is a config file that can set limits/resources
737//
738bool XglTestFramework::SetConfigFile(const std::string& name)
739{
740 if (name.size() < 5)
741 return false;
742
743 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
744 ConfigFile = name;
745 return true;
746 }
747
748 return false;
749}
750
751//
752// Parse either a .conf file provided by the user or the default string above.
753//
754void XglTestFramework::ProcessConfigFile()
755{
756 char** configStrings = 0;
757 char* config = 0;
758 if (ConfigFile.size() > 0) {
759 configStrings = ReadFileData(ConfigFile.c_str());
760 if (configStrings)
761 config = *configStrings;
762 else {
763 printf("Error opening configuration file; will instead use the default configuration\n");
764 }
765 }
766
767 if (config == 0) {
768 config = new char[strlen(DefaultConfig) + 1];
769 strcpy(config, DefaultConfig);
770 }
771
772 const char* delims = " \t\n\r";
773 const char* token = strtok(config, delims);
774 while (token) {
775 const char* valueStr = strtok(0, delims);
776 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
777 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
778 return;
779 }
780 int value = atoi(valueStr);
781
782 if (strcmp(token, "MaxLights") == 0)
783 Resources.maxLights = value;
784 else if (strcmp(token, "MaxClipPlanes") == 0)
785 Resources.maxClipPlanes = value;
786 else if (strcmp(token, "MaxTextureUnits") == 0)
787 Resources.maxTextureUnits = value;
788 else if (strcmp(token, "MaxTextureCoords") == 0)
789 Resources.maxTextureCoords = value;
790 else if (strcmp(token, "MaxVertexAttribs") == 0)
791 Resources.maxVertexAttribs = value;
792 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
793 Resources.maxVertexUniformComponents = value;
794 else if (strcmp(token, "MaxVaryingFloats") == 0)
795 Resources.maxVaryingFloats = value;
796 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
797 Resources.maxVertexTextureImageUnits = value;
798 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
799 Resources.maxCombinedTextureImageUnits = value;
800 else if (strcmp(token, "MaxTextureImageUnits") == 0)
801 Resources.maxTextureImageUnits = value;
802 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
803 Resources.maxFragmentUniformComponents = value;
804 else if (strcmp(token, "MaxDrawBuffers") == 0)
805 Resources.maxDrawBuffers = value;
806 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
807 Resources.maxVertexUniformVectors = value;
808 else if (strcmp(token, "MaxVaryingVectors") == 0)
809 Resources.maxVaryingVectors = value;
810 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
811 Resources.maxFragmentUniformVectors = value;
812 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
813 Resources.maxVertexOutputVectors = value;
814 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
815 Resources.maxFragmentInputVectors = value;
816 else if (strcmp(token, "MinProgramTexelOffset") == 0)
817 Resources.minProgramTexelOffset = value;
818 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
819 Resources.maxProgramTexelOffset = value;
820 else if (strcmp(token, "MaxClipDistances") == 0)
821 Resources.maxClipDistances = value;
822 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
823 Resources.maxComputeWorkGroupCountX = value;
824 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
825 Resources.maxComputeWorkGroupCountY = value;
826 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
827 Resources.maxComputeWorkGroupCountZ = value;
828 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
829 Resources.maxComputeWorkGroupSizeX = value;
830 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
831 Resources.maxComputeWorkGroupSizeY = value;
832 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
833 Resources.maxComputeWorkGroupSizeZ = value;
834 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
835 Resources.maxComputeUniformComponents = value;
836 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
837 Resources.maxComputeTextureImageUnits = value;
838 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
839 Resources.maxComputeImageUniforms = value;
840 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
841 Resources.maxComputeAtomicCounters = value;
842 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
843 Resources.maxComputeAtomicCounterBuffers = value;
844 else if (strcmp(token, "MaxVaryingComponents") == 0)
845 Resources.maxVaryingComponents = value;
846 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
847 Resources.maxVertexOutputComponents = value;
848 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
849 Resources.maxGeometryInputComponents = value;
850 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
851 Resources.maxGeometryOutputComponents = value;
852 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
853 Resources.maxFragmentInputComponents = value;
854 else if (strcmp(token, "MaxImageUnits") == 0)
855 Resources.maxImageUnits = value;
856 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
857 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
858 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
859 Resources.maxCombinedShaderOutputResources = value;
860 else if (strcmp(token, "MaxImageSamples") == 0)
861 Resources.maxImageSamples = value;
862 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
863 Resources.maxVertexImageUniforms = value;
864 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
865 Resources.maxTessControlImageUniforms = value;
866 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
867 Resources.maxTessEvaluationImageUniforms = value;
868 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
869 Resources.maxGeometryImageUniforms = value;
870 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
871 Resources.maxFragmentImageUniforms = value;
872 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
873 Resources.maxCombinedImageUniforms = value;
874 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
875 Resources.maxGeometryTextureImageUnits = value;
876 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
877 Resources.maxGeometryOutputVertices = value;
878 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
879 Resources.maxGeometryTotalOutputComponents = value;
880 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
881 Resources.maxGeometryUniformComponents = value;
882 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
883 Resources.maxGeometryVaryingComponents = value;
884 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
885 Resources.maxTessControlInputComponents = value;
886 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
887 Resources.maxTessControlOutputComponents = value;
888 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
889 Resources.maxTessControlTextureImageUnits = value;
890 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
891 Resources.maxTessControlUniformComponents = value;
892 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
893 Resources.maxTessControlTotalOutputComponents = value;
894 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
895 Resources.maxTessEvaluationInputComponents = value;
896 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
897 Resources.maxTessEvaluationOutputComponents = value;
898 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
899 Resources.maxTessEvaluationTextureImageUnits = value;
900 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
901 Resources.maxTessEvaluationUniformComponents = value;
902 else if (strcmp(token, "MaxTessPatchComponents") == 0)
903 Resources.maxTessPatchComponents = value;
904 else if (strcmp(token, "MaxPatchVertices") == 0)
905 Resources.maxPatchVertices = value;
906 else if (strcmp(token, "MaxTessGenLevel") == 0)
907 Resources.maxTessGenLevel = value;
908 else if (strcmp(token, "MaxViewports") == 0)
909 Resources.maxViewports = value;
910 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
911 Resources.maxVertexAtomicCounters = value;
912 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
913 Resources.maxTessControlAtomicCounters = value;
914 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
915 Resources.maxTessEvaluationAtomicCounters = value;
916 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
917 Resources.maxGeometryAtomicCounters = value;
918 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
919 Resources.maxFragmentAtomicCounters = value;
920 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
921 Resources.maxCombinedAtomicCounters = value;
922 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
923 Resources.maxAtomicCounterBindings = value;
924 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
925 Resources.maxVertexAtomicCounterBuffers = value;
926 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
927 Resources.maxTessControlAtomicCounterBuffers = value;
928 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
929 Resources.maxTessEvaluationAtomicCounterBuffers = value;
930 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
931 Resources.maxGeometryAtomicCounterBuffers = value;
932 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
933 Resources.maxFragmentAtomicCounterBuffers = value;
934 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
935 Resources.maxCombinedAtomicCounterBuffers = value;
936 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
937 Resources.maxAtomicCounterBufferSize = value;
938 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
939 Resources.maxTransformFeedbackBuffers = value;
940 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
941 Resources.maxTransformFeedbackInterleavedComponents = value;
942 else if (strcmp(token, "MaxCullDistances") == 0)
943 Resources.maxCullDistances = value;
944 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
945 Resources.maxCombinedClipAndCullDistances = value;
946 else if (strcmp(token, "MaxSamples") == 0)
947 Resources.maxSamples = value;
948
949 else if (strcmp(token, "nonInductiveForLoops") == 0)
950 Resources.limits.nonInductiveForLoops = (value != 0);
951 else if (strcmp(token, "whileLoops") == 0)
952 Resources.limits.whileLoops = (value != 0);
953 else if (strcmp(token, "doWhileLoops") == 0)
954 Resources.limits.doWhileLoops = (value != 0);
955 else if (strcmp(token, "generalUniformIndexing") == 0)
956 Resources.limits.generalUniformIndexing = (value != 0);
957 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
958 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
959 else if (strcmp(token, "generalVaryingIndexing") == 0)
960 Resources.limits.generalVaryingIndexing = (value != 0);
961 else if (strcmp(token, "generalSamplerIndexing") == 0)
962 Resources.limits.generalSamplerIndexing = (value != 0);
963 else if (strcmp(token, "generalVariableIndexing") == 0)
964 Resources.limits.generalVariableIndexing = (value != 0);
965 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
966 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
967 else
968 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
969
970 token = strtok(0, delims);
971 }
972 if (configStrings)
973 FreeFileData(configStrings);
974}
975
976void XglTestFramework::SetMessageOptions(EShMessages& messages)
977{
978 if (m_compile_options & EOptionRelaxedErrors)
979 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
980 if (m_compile_options & EOptionIntermediate)
981 messages = (EShMessages)(messages | EShMsgAST);
982 if (m_compile_options & EOptionSuppressWarnings)
983 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
984}
985
986//
987// Malloc a string of sufficient size and read a string into it.
988//
989char** XglTestFramework::ReadFileData(const char* fileName)
990{
991 FILE *in;
992 #if defined(_WIN32) && defined(__GNUC__)
993 in = fopen(fileName, "r");
994 int errorCode = in ? 0 : 1;
995 #else
996 int errorCode = fopen_s(&in, fileName, "r");
997 #endif
998
999 char *fdata;
1000 int count = 0;
1001 const int maxSourceStrings = 5;
1002 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
1003
1004 if (errorCode) {
1005 printf("Error: unable to open input file: %s\n", fileName);
1006 return 0;
1007 }
1008
1009 while (fgetc(in) != EOF)
1010 count++;
1011
1012 fseek(in, 0, SEEK_SET);
1013
1014 if (!(fdata = (char*)malloc(count+2))) {
1015 printf("Error allocating memory\n");
1016 return 0;
1017 }
1018 if (fread(fdata,1,count, in)!=count) {
1019 printf("Error reading input file: %s\n", fileName);
1020 return 0;
1021 }
1022 fdata[count] = '\0';
1023 fclose(in);
1024 if (count == 0) {
1025 return_data[0]=(char*)malloc(count+2);
1026 return_data[0][0]='\0';
1027 m_num_shader_strings = 0;
1028 return return_data;
1029 } else
1030 m_num_shader_strings = 1;
1031
1032 int len = (int)(ceil)((float)count/(float)m_num_shader_strings);
1033 int ptr_len=0,i=0;
1034 while(count>0){
1035 return_data[i]=(char*)malloc(len+2);
1036 memcpy(return_data[i],fdata+ptr_len,len);
1037 return_data[i][len]='\0';
1038 count-=(len);
1039 ptr_len+=(len);
1040 if(count<len){
1041 if(count==0){
1042 m_num_shader_strings=(i+1);
1043 break;
1044 }
1045 len = count;
1046 }
1047 ++i;
1048 }
1049 return return_data;
1050}
1051
1052void XglTestFramework::FreeFileData(char** data)
1053{
1054 for(int i=0;i<m_num_shader_strings;i++)
1055 free(data[i]);
1056}
1057
1058//
1059// Deduce the language from the filename. Files must end in one of the
1060// following extensions:
1061//
1062// .vert = vertex
1063// .tesc = tessellation control
1064// .tese = tessellation evaluation
1065// .geom = geometry
1066// .frag = fragment
1067// .comp = compute
1068//
1069EShLanguage XglTestFramework::FindLanguage(const std::string& name)
1070{
1071 size_t ext = name.rfind('.');
1072 if (ext == std::string::npos) {
1073 return EShLangVertex;
1074 }
1075
1076 std::string suffix = name.substr(ext + 1, std::string::npos);
1077 if (suffix == "vert")
1078 return EShLangVertex;
1079 else if (suffix == "tesc")
1080 return EShLangTessControl;
1081 else if (suffix == "tese")
1082 return EShLangTessEvaluation;
1083 else if (suffix == "geom")
1084 return EShLangGeometry;
1085 else if (suffix == "frag")
1086 return EShLangFragment;
1087 else if (suffix == "comp")
1088 return EShLangCompute;
1089
1090 return EShLangVertex;
1091}
1092
1093//
1094// Convert XGL shader type to compiler's
1095//
1096EShLanguage XglTestFramework::FindLanguage(const XGL_PIPELINE_SHADER_STAGE shader_type)
1097{
1098 switch (shader_type) {
1099 case XGL_SHADER_STAGE_VERTEX:
1100 return EShLangVertex;
1101
1102 case XGL_SHADER_STAGE_TESS_CONTROL:
1103 return EShLangTessControl;
1104
1105 case XGL_SHADER_STAGE_TESS_EVALUATION:
1106 return EShLangTessEvaluation;
1107
1108 case XGL_SHADER_STAGE_GEOMETRY:
1109 return EShLangGeometry;
1110
1111 case XGL_SHADER_STAGE_FRAGMENT:
1112 return EShLangFragment;
1113
1114 case XGL_SHADER_STAGE_COMPUTE:
1115 return EShLangCompute;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001116
Chia-I Wub4c2aa42014-12-15 23:50:11 +08001117 default:
1118 return EShLangVertex;
1119 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001120}
1121
1122
1123//
Cody Northrop3bfd27c2015-03-17 15:55:58 -06001124// Compile a given string containing GLSL into SPV for use by XGL
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001125// Return value of false means an error was encountered.
1126//
Cody Northrop3bfd27c2015-03-17 15:55:58 -06001127bool XglTestFramework::GLSLtoSPV(const XGL_PIPELINE_SHADER_STAGE shader_type,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001128 const char *pshader,
Cody Northrop3bfd27c2015-03-17 15:55:58 -06001129 std::vector<unsigned int> &spv)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001130{
1131 glslang::TProgram& program = *new glslang::TProgram;
1132 const char *shaderStrings[1];
1133
1134 // TODO: Do we want to load a special config file depending on the
1135 // shader source? Optional name maybe?
1136 // SetConfigFile(fileName);
1137
1138 ProcessConfigFile();
1139
1140 EShMessages messages = EShMsgDefault;
1141 SetMessageOptions(messages);
1142
1143 EShLanguage stage = FindLanguage(shader_type);
1144 glslang::TShader* shader = new glslang::TShader(stage);
1145
1146 shaderStrings[0] = pshader;
1147 shader->setStrings(shaderStrings, 1);
1148
1149 if (! shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
1150
Cody Northrop195d6622014-11-03 12:54:37 -07001151 if (! (m_compile_options & EOptionSuppressInfolog)) {
1152 puts(shader->getInfoLog());
1153 puts(shader->getInfoDebugLog());
1154 }
1155
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001156 return false; // something didn't work
1157 }
1158
1159 program.addShader(shader);
1160
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001161
1162 //
1163 // Program-level processing...
1164 //
1165
Cody Northrop195d6622014-11-03 12:54:37 -07001166 if (! program.link(messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001167
Cody Northrop195d6622014-11-03 12:54:37 -07001168 if (! (m_compile_options & EOptionSuppressInfolog)) {
1169 puts(shader->getInfoLog());
1170 puts(shader->getInfoDebugLog());
1171 }
1172
1173 return false;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001174 }
1175
1176 if (m_compile_options & EOptionDumpReflection) {
1177 program.buildReflection();
1178 program.dumpReflection();
1179 }
1180
Cody Northrop3bfd27c2015-03-17 15:55:58 -06001181 glslang::GlslangToSpv(*program.getIntermediate(stage), spv);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001182
1183 return true;
1184}
1185
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001186
1187
1188XglTestImageRecord::XglTestImageRecord() : // Constructor
1189 m_width( 0 ),
1190 m_height( 0 ),
Chia-I Wu837f9952014-12-15 23:29:34 +08001191 m_data( NULL ),
Tony Barbour96db8822015-02-25 12:28:39 -07001192 m_presentableImage( NULL ),
1193 m_presentableMemory( NULL),
Chia-I Wu837f9952014-12-15 23:29:34 +08001194 m_data_size( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001195{
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001196}
1197
1198XglTestImageRecord::~XglTestImageRecord()
1199{
1200
1201}
1202
1203XglTestImageRecord::XglTestImageRecord(const XglTestImageRecord &copyin) // Copy constructor to handle pass by value.
1204{
1205 m_title = copyin.m_title;
1206 m_width = copyin.m_width;
1207 m_height = copyin.m_height;
1208 m_data_size = copyin.m_data_size;
1209 m_data = copyin.m_data; // TODO: Do we need to copy the data or is pointer okay?
Tony Barbour96db8822015-02-25 12:28:39 -07001210 m_presentableImage = copyin.m_presentableImage;
1211 m_presentableMemory = copyin.m_presentableMemory;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001212}
1213
1214ostream &operator<<(ostream &output, const XglTestImageRecord &XglTestImageRecord)
1215{
1216 output << XglTestImageRecord.m_title << " (" << XglTestImageRecord.m_width <<
1217 "," << XglTestImageRecord.m_height << ")" << endl;
1218 return output;
1219}
1220
1221XglTestImageRecord& XglTestImageRecord::operator=(const XglTestImageRecord &rhs)
1222{
1223 m_title = rhs.m_title;
1224 m_width = rhs.m_width;
1225 m_height = rhs.m_height;
1226 m_data_size = rhs.m_data_size;
1227 m_data = rhs.m_data;
Tony Barbour96db8822015-02-25 12:28:39 -07001228 m_presentableImage = rhs.m_presentableImage;
1229 m_presentableMemory = rhs.m_presentableMemory;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001230 return *this;
1231}
1232
1233int XglTestImageRecord::operator==(const XglTestImageRecord &rhs) const
1234{
1235 if( this->m_data != rhs.m_data) return 0;
1236 return 1;
1237}
1238
1239// This function is required for built-in STL list functions like sort
1240int XglTestImageRecord::operator<(const XglTestImageRecord &rhs) const
1241{
1242 if( this->m_data_size < rhs.m_data_size ) return 1;
1243 return 0;
1244}
1245