Esempio n. 1
0
enum piglit_result
run_test(GLenum test_format, GLenum test_type, float *time_out)
{
	bool pass = true;
	int64_t time;
	GLuint tex;
	int i, Bpp, channels;
	float *tmp, *expected, *observed;
	void *data;

	glGenTextures(1, &tex);
	glBindTexture(GL_TEXTURE_2D, tex);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

	channels = num_channels(test_format);
	Bpp = bytes_per_pixel(test_format, test_type);

	if (test_type == GL_FLOAT) {
		/* Sanatize so we don't get invalid floating point values */
		tmp = malloc(texture_size * texture_size * channels * sizeof(float));
		for (i = 0; i < texture_size * texture_size * channels; ++i)
			tmp[i] = sn_to_float(32, ((GLint *)rand_data)[i]);
		data = tmp;
	} else {
		tmp = NULL;
		data = rand_data;
	}

	expected = malloc(texture_size * texture_size * 4 * sizeof(float));
	for (i = 0; i < texture_size * texture_size; ++i)
		to_expected(test_format, test_type, (GLubyte *)data + (i * Bpp),
			    expected + 4 * i);

	if (benchmark) {
		time = piglit_get_microseconds();
		for (i = 0; i < BENCHMARK_ITERATIONS; ++i)
			glTexImage2D(GL_TEXTURE_2D, 0, format->internal_format,
				     texture_size, texture_size, 0,
				     test_format, test_type, data);
		time = piglit_get_microseconds() - time;
		*time_out = (double)time / (double)BENCHMARK_ITERATIONS;
	} else {
		glTexImage2D(GL_TEXTURE_2D, 0, format->internal_format,
			     texture_size, texture_size, 0,
			     test_format, test_type, data);
	}
	pass &= piglit_check_gl_error(GL_NO_ERROR);

	if (is_format_signed(format->internal_format)) {
		glUseProgram(signed_prog);

		for (i = 0; i < texture_size * texture_size * 4; ++i)
			expected[i] = 0.5 + 0.5 * expected[i];
	} else {
		glUseProgram(unsigned_prog);
	}

	piglit_draw_rect_tex(0, 0, texture_size, texture_size, 0, 0, 1, 1);

	observed = malloc(texture_size * texture_size * 4 * sizeof(float));
	glReadPixels(0, 0, texture_size, texture_size,
		     GL_RGBA, GL_FLOAT, observed);
	pass &= piglit_check_gl_error(GL_NO_ERROR);

	pass &= piglit_compare_images_color(0, 0, texture_size, texture_size, 4,
					    tolerance, expected, observed);

	free(observed);
	free(expected);
	free(tmp);

	piglit_report_subtest_result(pass ? PIGLIT_PASS : PIGLIT_FAIL,
				     "%s texture with %s and %s",
				     piglit_get_gl_enum_name(format->internal_format),
				     piglit_get_gl_enum_name(test_format),
				     piglit_get_gl_enum_name(test_type));

	glDeleteTextures(1, &tex);

	return pass;
}
Esempio n. 2
0
static enum piglit_result
draw(Display *dpy)
{
    enum piglit_result result = PIGLIT_PASS;
    int64_t last_ust = 0xd0, last_msc = 0xd0, last_sbc = 0xd0;
    int64_t last_timestamp = -1;
    struct stats msc_wallclock_duration_stats = {};
    struct stats msc_ust_duration_stats = {};
    double expected_msc_wallclock_duration = 0.0;
    int32_t rate_num, rate_den;
    unsigned int i;

    if (!glXGetSyncValuesOML(dpy, win, &last_ust, &last_msc, &last_sbc)) {
        fprintf(stderr, "Initial glXGetSyncValuesOML failed\n");
        return PIGLIT_FAIL;
    }

    /* Check that the window is fresh */
    if (last_sbc != 0) {
        fprintf(stderr, "Initial SBC for the window should be 0, was "
                "%" PRId64 "\n",
                last_sbc);
        piglit_merge_result(&result, PIGLIT_WARN);
    }

    if (!glXGetMscRateOML(dpy, win, &rate_num, &rate_den)) {
        fprintf(stderr,
                "glXGetMscRateOML failed, can't test MSC duration\n");
        piglit_merge_result(&result, PIGLIT_WARN);
    } else {
        expected_msc_wallclock_duration = 1e6 * rate_den / rate_num;
    }

    piglit_set_timeout(5, PIGLIT_FAIL);


    for (i = 0; i < loops; i++) {
        int64_t new_ust = 0xd0, new_msc = 0xd0, new_sbc = 0xd0;
        int64_t check_ust = 0xd0, check_msc = 0xd0, check_sbc = 0xd0;
        int64_t new_timestamp;
        int64_t expected_msc, target_sbc;
        int64_t target_msc = 0;

        if (target_msc_delta) {
            target_msc = last_msc + target_msc_delta;
        }

        if (use_swapbuffers) {
            glClearColor(0.0, 1.0, 0.0, 0.0);
            glClear(GL_COLOR_BUFFER_BIT);

            target_sbc = glXSwapBuffersMscOML(dpy, win,
                                              target_msc, divisor, msc_remainder);
            if(target_sbc <= 0) {
                fprintf(stderr, "SwapBuffersMscOML failed\n");
                return PIGLIT_FAIL;
            }
            if(target_sbc != last_sbc + 1) {
                fprintf(stderr,
                        "glXSwapBuffersMscOML calculated the"
                        " wrong target sbc: expected %"PRId64
                        " but got %"PRId64"\n",
                        last_sbc + 1, target_sbc);
                result = PIGLIT_FAIL;
            }

            if(!glXWaitForSbcOML(dpy, win, target_sbc,
                                 &new_ust, &new_msc, &new_sbc))
            {
                fprintf(stderr, "glXWaitForSbcOML failed\n");
                result = PIGLIT_FAIL;
            }
        } else {
            target_sbc = last_sbc;

            if(!glXWaitForMscOML(dpy, win, target_msc, divisor,
                                 msc_remainder, &new_ust,
                                 &new_msc, &new_sbc))
            {
                fprintf(stderr, "glXWaitForSbcOML failed\n");
                result = PIGLIT_FAIL;
            }
        }
        new_timestamp = piglit_get_microseconds();

        if (!glXGetSyncValuesOML(dpy, win,
                                 &check_ust, &check_msc, &check_sbc))
        {
            fprintf(stderr, "Follow-up GetSyncValuesOML failed\n");
            return PIGLIT_FAIL;
        }

        if (new_ust < last_ust) {
            fprintf(stderr, "iteration %u: non-monotonic UST went "
                    "backward by %"PRId64" during Wait\n",
                    i, last_ust - new_ust);
            result = PIGLIT_FAIL;
            /* Wait returned something bogus, but GetSyncValues
             * usually works, so try evaluating the rest of the
             * tests using the check values. */
            new_ust = check_ust;
        }

        if (check_ust < new_ust) {
            fprintf(stderr, "iteration %u: non-monotonic UST went "
                    "backward by %"PRId64" across GetSyncValues\n",
                    i, last_ust - check_ust);
            result = PIGLIT_FAIL;
        }

        if (new_msc < last_msc) {
            fprintf(stderr, "iteration %u: non-monotonic MSC went "
                    "backward by %"PRId64" during Wait\n",
                    i, last_msc - new_msc);
            result = PIGLIT_FAIL;
            /* Wait returned something bogus, but GetSyncValues
             * usually works, so try evaluating the rest of the
             * tests using the check values. */
            new_msc = check_msc;
        }

        if (check_msc < new_msc) {
            fprintf(stderr, "iteration %u: non-monotonic MSC went "
                    "backward by %"PRId64" across GetSyncValues\n",
                    i, last_msc - check_msc);
            result = PIGLIT_FAIL;
        }

        if (new_sbc != target_sbc) {
            fprintf(stderr, "iteration %u: Wait should have "
                    "returned at SBC %"PRId64" but returned at "
                    "%"PRId64"\n",
                    i, target_sbc, new_sbc);
            result = PIGLIT_FAIL;
        }

        if (check_sbc != new_sbc) {
            fprintf(stderr, "iteration %u: GetSyncValues "
                    "returned SBC %"PRId64" but Wait returned "
                    "%"PRId64"\n",
                    i, check_sbc, new_sbc);
            result = PIGLIT_FAIL;
        }

        if (new_msc > last_msc) {
            int64_t delta_msc = new_msc - last_msc;
            update_stats(&msc_ust_duration_stats,
                         (new_ust - last_ust) / delta_msc);

            if (last_timestamp >= 0) {
                if (new_timestamp < 0) {
                    fprintf(stderr,
                            "no monotonic clock\n");
                    piglit_merge_result(&result,
                                        PIGLIT_WARN);
                } else {
                    update_stats(
                        &msc_wallclock_duration_stats,
                        (new_timestamp - last_timestamp)
                        / delta_msc);
                }
            }
        }

        expected_msc = target_msc;
        if (!target_msc) {
            /* If there is a divisor, the expected MSC is the
             * next MSC after last_msc such that
             * MSC % divisor == remainder
             */
            int64_t last_remainder = last_msc % divisor;
            expected_msc = last_msc - last_remainder + msc_remainder;
            if (expected_msc <= last_msc)
                expected_msc += divisor;
        }

        if (new_msc < expected_msc) {
            fprintf(stderr, "iteration %u woke up %"PRId64
                    " MSCs early\n",
                    i, expected_msc - new_msc);
            result = PIGLIT_FAIL;
        }

        if (new_msc > expected_msc) {
            fprintf(stderr, "iteration %u woke up %"PRId64
                    " MSCs later than expected\n",
                    i, new_msc - expected_msc);
            piglit_merge_result(&result, PIGLIT_WARN);
        }

        if (new_msc % divisor != msc_remainder) {
            fprintf(stderr, "iteration %u woke up at wrong MSC"
                    " remainder %"PRId64", not requested remainder"
                    " %"PRId64"\n",
                    i, new_msc % divisor, msc_remainder);
            result = PIGLIT_FAIL;
        }

        last_ust = new_ust;
        last_msc = new_msc;
        last_sbc = new_sbc;
        last_timestamp = new_timestamp;
    }

    if (msc_ust_duration_stats.n < 2) {
        fprintf(stderr, "Not enough UST timing samples\n");
        piglit_merge_result(&result, PIGLIT_WARN);
    } else if (expected_msc_wallclock_duration > 0.0) {
        double apparent_ust_rate = msc_ust_duration_stats.mean /
                                   expected_msc_wallclock_duration;
        if (get_stddev(&msc_ust_duration_stats) / apparent_ust_rate > 100)
        {
            fprintf(stderr, "UST duration per MSC is surprisingly"
                    " variable (stddev %f USTs), but then it only"
                    " has to be monotonic\n",
                    get_stddev(&msc_ust_duration_stats));
            piglit_merge_result(&result, PIGLIT_WARN);
        }
    }

    if (msc_wallclock_duration_stats.n < 2) {
        fprintf(stderr, "Not enough wallclock timing samples\n");
        piglit_merge_result(&result, PIGLIT_WARN);
    } else if (get_stddev(&msc_wallclock_duration_stats) > 1000) {
        fprintf(stderr, "Wallclock time between MSCs has stddev > 1ms"
                " (%fus), driver is probably not syncing to"
                " vblank\n",
                get_stddev(&msc_wallclock_duration_stats));
        result = PIGLIT_FAIL;
    } else if (expected_msc_wallclock_duration > 0.0) {
        if (fabs(expected_msc_wallclock_duration -
                 msc_wallclock_duration_stats.mean) > 50)
        {
            fprintf(stderr, "Wallclock time between MSCs %fus"
                    " does not match glXGetMscRateOML %fus\n",
                    msc_wallclock_duration_stats.mean,
                    expected_msc_wallclock_duration);
            result = PIGLIT_FAIL;
        }
    }

    return result;
}