Re: [Intel-gfx] Pixel-perfect frame checks in IGT Chamelium tests and CRC
On Thu, 2017-06-15 at 13:37 -0400, Lyude Paul wrote: > JFYI: Hardcoded CRCs are fine I'm pretty sure, but I might be wrong. As > well, put the chamelium in a metal box. The way the IO board is hooked > up is not really the way something running DP should be hooked up, so > it's very susceptible to electromagnetic interference. This will > usually cause CRC mismatches with DP. I don't think that is the case here, as pixel-to-pixel comparison succeeds reliably. I also get the same hashes (that don't match the hardcoded ones) everytime I run the test. I think the reference picture I have is just different from the one you hardcoded the CRCs for, as I pointed out (font rendering cannot be trusted, among other things that can change). This is why I think we should calculate the CRC instead of using hardcoded ones. > This being said however, I think we should have some better functions > for the chamelium for doing frame comparisons, mainly something that > does fuzzy frame comparisons for stuff like VGA. Agreed. I will most likely look into that next week. > On Thu, 2017-06-15 at 16:57 +0300, Paul Kocialkowski wrote: > > Hi, > > > > So far, there are two ways of testing for pixel-perfect frames using > > the > > Chamelium that are in IGT. The first one grabs a full frame from the > > Chamelium > > and compares it pixel-to-pixel with the cairo reference, which works > > well for > > DP/HDMI. > > > > For VGA, this is probably not the case (because the link is > > analogue). In that > > case, I will look into implementing some fuzzy testing, probably > > inspired by > > what piglit (probably) does to compare output frames with references. > > > > For pixel-perfect testing, grabbing a full frame and testing it with > > memcmp > > comes with a significant time penalty (about 2 seconds for 1080p). > > The Chamelium > > also provides a CRC mechanism that is faster and does not require > > retrieving the > > frame, that IGT currently also supports. It compares the CRC > > calculated by the > > Chamelium (implemented in the HDL) with a hardcoded reference value. > > > > This approach currently fails for me (the values I get don't match > > the hardcoded > > reference). There are reasons why it is not really reasonable: fonts > > rendering > > may change between machines (e.g. use of anti-aliasing) and cairo > > version > > changes could introduce slight rendering changes too (not to mention > > changes in > > the test pattern itself). So instead of comparing the CRC with a > > hardcoded > > reference value, I think it would make a lot more sense to actually > > calculate > > the CRC based on the cairo image that is the actual reference (and > > that we > > should assume may change between runs/machines). > > > > I am currently looking into the CRC calculation mechanism used by the > > Chamelium > > and trying to reproduce it in C code. Is this a known algorithm for > > which a > > reference/optimized implementation exists, or something custom that > > the folks > > over at Google came up with? > > > > Any thoughts, comments or suggestions? > > > > Cheers! > > -- Paul Kocialkowski Intel Finland Oy - BIC 0357606-4 - Westendinkatu 7, 02160 Espoo ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] Pixel-perfect frame checks in IGT Chamelium tests and CRC
Hi, On Thu, 2017-06-15 at 21:08 -0700, chihch...@google.com wrote: > Paul Kocialkowski於 2017年6月15日星期四 UTC+8下午9時57分09秒寫道: > > Hi, > > > > So far, there are two ways of testing for pixel-perfect frames using the > > Chamelium that are in IGT. The first one grabs a full frame from the > > Chamelium > > and compares it pixel-to-pixel with the cairo reference, which works well > > for > > DP/HDMI. > > > > For VGA, this is probably not the case (because the link is analogue). In > > that > > case, I will look into implementing some fuzzy testing, probably inspired > > by > > what piglit (probably) does to compare output frames with references. > > > > For pixel-perfect testing, grabbing a full frame and testing it with memcmp > > comes with a significant time penalty (about 2 seconds for 1080p). The > > Chamelium > > also provides a CRC mechanism that is faster and does not require retrieving > > the > > frame, that IGT currently also supports. It compares the CRC calculated by > > the > > Chamelium (implemented in the HDL) with a hardcoded reference value. > > > > This approach currently fails for me (the values I get don't match the > > hardcoded > > reference). There are reasons why it is not really reasonable: fonts > > rendering > > may change between machines (e.g. use of anti-aliasing) and cairo version > > changes could introduce slight rendering changes too (not to mention changes > > in > > the test pattern itself). So instead of comparing the CRC with a hardcoded > > reference value, I think it would make a lot more sense to actually > > calculate > > the CRC based on the cairo image that is the actual reference (and that we > > should assume may change between runs/machines). > > > > I am currently looking into the CRC calculation mechanism used by the > > Chamelium > > and trying to reproduce it in C code. Is this a known algorithm for which a > > reference/optimized implementation exists, or something custom that the > > folks > > over at Google came up with? > > > > Any thoughts, comments or suggestions? > > I feel bad about the stupid hash algorithm I came up with, but here is the > document: > https://docs.google.com/document/d/1_HjEMA8fBoHkUbpUZq-OXtITfiomCb1HBKN07T-POl > Y/edit#heading=h.jqek3kkh9qjm > You can also ask it to hash just part of the frame instead of the whole frame > (i.e. cropping before hashing). Thanks for the link to the relevant documentation! I have been following it closely and came up with the following implementation, which does not produce the same result. Would you have any idea of what I'm doing wrong? That function is called with m = 4 and k = { 0, 1, 2, 3 }. I am using a single- color-frame and the 4 hash16 I get from the Chamelium are identical. They are however different from the 4 (also identical) that I get from : int hash16(unsigned char *buffer, int width, int height, int k, int m) { unsigned char r, g, b; long int sum = 0; int count = 0; int index; int hash; int value; int i; for (i=0; i < width * height; i++) { if ((i % m) != k) continue; index = i * 3; r = buffer[index + 0]; g = buffer[index + 1]; b = buffer[index + 2]; value = r | (g << 8) | (b << 16); sum += ++count * value; } hash = ((sum >> 48) ^ (sum >> 32) ^ (sum >> 16) ^ (sum >> 0)) & 0x; return hash; } I am certain that the r, g, b values are correct. Thanks! -- Paul Kocialkowski Intel Finland Oy - BIC 0357606-4 - Westendinkatu 7, 02160 Espoo ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] Pixel-perfect frame checks in IGT Chamelium tests and CRC
Hey, On Fri, 2017-06-16 at 18:09 +0800, Chih-Chung Chang wrote: > On Fri, Jun 16, 2017 at 5:28 PM, Paul Kocialkowski > wrote: > > Hi, > > > > On Thu, 2017-06-15 at 21:08 -0700, chihch...@google.com wrote: > > > Paul Kocialkowski於 2017年6月15日星期四 UTC+8下午9時57分09秒寫道: > > > > Hi, > > > > > > > > So far, there are two ways of testing for pixel-perfect frames using the > > > > Chamelium that are in IGT. The first one grabs a full frame from the > > > > Chamelium > > > > and compares it pixel-to-pixel with the cairo reference, which works > > well > > > > for > > > > DP/HDMI. > > > > > > > > For VGA, this is probably not the case (because the link is analogue). > > In > > > > that > > > > case, I will look into implementing some fuzzy testing, probably > > inspired > > > > by > > > > what piglit (probably) does to compare output frames with references. > > > > > > > > For pixel-perfect testing, grabbing a full frame and testing it with > > memcmp > > > > comes with a significant time penalty (about 2 seconds for 1080p). The > > > > Chamelium > > > > also provides a CRC mechanism that is faster and does not require > > retrieving > > > > the > > > > frame, that IGT currently also supports. It compares the CRC calculated > > by > > > > the > > > > Chamelium (implemented in the HDL) with a hardcoded reference value. > > > > > > > > This approach currently fails for me (the values I get don't match the > > > > hardcoded > > > > reference). There are reasons why it is not really reasonable: fonts > > > > rendering > > > > may change between machines (e.g. use of anti-aliasing) and cairo > > version > > > > changes could introduce slight rendering changes too (not to mention > > changes > > > > in > > > > the test pattern itself). So instead of comparing the CRC with a > > hardcoded > > > > reference value, I think it would make a lot more sense to actually > > > > calculate > > > > the CRC based on the cairo image that is the actual reference (and that > > we > > > > should assume may change between runs/machines). > > > > > > > > I am currently looking into the CRC calculation mechanism used by the > > > > Chamelium > > > > and trying to reproduce it in C code. Is this a known algorithm for > > which a > > > > reference/optimized implementation exists, or something custom that the > > > > folks > > > > over at Google came up with? > > > > > > > > Any thoughts, comments or suggestions? > > > > > > I feel bad about the stupid hash algorithm I came up with, but here is the > > > document: > > > https://docs.google.com/document/d/1_HjEMA8fBoHkUbpUZq-OXtITfiomCb1HBKN07T > > -POl > > > Y/edit#heading=h.jqek3kkh9qjm > > > You can also ask it to hash just part of the frame instead of the whole > > frame > > > (i.e. cropping before hashing). > > > > Thanks for the link to the relevant documentation! I have been following it > > closely and came up with the following implementation, which does not > > produce > > the same result. Would you have any idea of what I'm doing wrong? > > > > That function is called with m = 4 and k = { 0, 1, 2, 3 }. I am using a > > single- > > color-frame and the 4 hash16 I get from the Chamelium are identical. They > > are > > however different from the 4 (also identical) that I get from : > > > > int hash16(unsigned char *buffer, int width, int height, int k, int m) > > { > > unsigned char r, g, b; > > long int sum = 0; > > int count = 0; > > int index; > > int hash; > > int value; > > int i; > > > > for (i=0; i < width * height; i++) { > > if ((i % m) != k) > > continue; > > > > index = i * 3; > > > > r = buffer[index + 0]; > > g = buffer[index + 1]; > > b = buffer[index + 2]; > > > > value = r | (g << 8) | (b << 16); > > sum += ++count * value; > > Maybe this multiplication overflows? Good pick, that was it! Now the CRC is the same as the one obtained from
[Intel-gfx] [PATCH i-g-t] tests/chamelium: Add common suspend and hibernate tests for DP and HDMI
This adds two new tests: common-hpd-after-suspend and common-hpd-after-hibernate that are aimed at testing HPD change during suspend/hibernate for both DP and HDMI, at the same time. The interest in bringing this test up is to reduce the time spent in testing, with the downside of less precision regarding the test's outcome. The per-connector tests are still available to get a more precise idea of which connector causes a failure, when that happens. Signed-off-by: Paul Kocialkowski --- tests/chamelium.c | 86 +++ 1 file changed, 86 insertions(+) diff --git a/tests/chamelium.c b/tests/chamelium.c index 76b14e95..d569c8ee 100644 --- a/tests/chamelium.c +++ b/tests/chamelium.c @@ -241,6 +241,80 @@ test_suspend_resume_hpd(data_t *data, struct chamelium_port *port, } static void +test_suspend_resume_hpd_common(data_t *data, enum igt_suspend_state state, + enum igt_suspend_test test) +{ + struct udev_monitor *mon = igt_watch_hotplug(); + struct chamelium_port *port; + int p; + + for (p = 0; p < data->port_count; p++) { + port = data->ports[p]; + if (chamelium_port_get_type(port) == DRM_MODE_CONNECTOR_VGA) + continue; + + reset_state(data, port); + + igt_debug("Testing port %s\n", chamelium_port_get_name(port)); + } + + igt_set_autoresume_delay(SUSPEND_RESUME_DELAY); + igt_flush_hotplugs(mon); + + /* Make sure we notice new connectors after resuming */ + for (p = 0; p < data->port_count; p++) { + port = data->ports[p]; + if (chamelium_port_get_type(port) == DRM_MODE_CONNECTOR_VGA) + continue; + + chamelium_async_hpd_pulse_start(data->chamelium, port, false, + SUSPEND_RESUME_DELAY / 2); + } + + igt_system_suspend_autoresume(state, test); + chamelium_async_hpd_pulse_finish(data->chamelium); + + igt_assert(igt_hotplug_detected(mon, HOTPLUG_TIMEOUT)); + + for (p = 0; p < data->port_count; p++) { + port = data->ports[p]; + if (chamelium_port_get_type(port) == DRM_MODE_CONNECTOR_VGA) + continue; + + igt_assert_eq(reprobe_connector(data, port), + DRM_MODE_CONNECTED); + } + + igt_flush_hotplugs(mon); + + /* Now make sure we notice disconnected connectors after resuming */ + for (p = 0; p < data->port_count; p++) { + port = data->ports[p]; + if (chamelium_port_get_type(port) == DRM_MODE_CONNECTOR_VGA) + continue; + + chamelium_async_hpd_pulse_start(data->chamelium, port, true, + SUSPEND_RESUME_DELAY / 2); + } + + igt_system_suspend_autoresume(state, test); + chamelium_async_hpd_pulse_finish(data->chamelium); + + igt_assert(igt_hotplug_detected(mon, HOTPLUG_TIMEOUT)); + + for (p = 0; p < data->port_count; p++) { + port = data->ports[p]; + if (chamelium_port_get_type(port) == DRM_MODE_CONNECTOR_VGA) + continue; + + igt_assert_eq(reprobe_connector(data, port), + DRM_MODE_DISCONNECTED); + } + + igt_cleanup_hotplug(mon); +} + +static void test_suspend_resume_edid_change(data_t *data, struct chamelium_port *port, enum igt_suspend_state state, enum igt_suspend_test test, @@ -750,6 +824,18 @@ igt_main test_hpd_without_ddc(&data, port); } + igt_subtest_group { + igt_subtest("common-hpd-after-suspend") + test_suspend_resume_hpd_common(&data, + SUSPEND_STATE_MEM, + SUSPEND_TEST_NONE); + + igt_subtest("common-hpd-after-hibernate") + test_suspend_resume_hpd_common(&data, + SUSPEND_STATE_DISK, + SUSPEND_TEST_DEVICES); + } + igt_fixture { close(data.drm_fd); } -- 2.13.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH i-g-t v2] tests/chamelium: Add common suspend and hibernate tests for DP and HDMI
This adds two new tests: common-hpd-after-suspend and common-hpd-after-hibernate that are aimed at testing HPD change during suspend/hibernate for both DP and HDMI, at the same time. The interest in bringing this test up is to reduce the time spent in testing, with the downside of less precision regarding the test's outcome. The per-connector tests are still available to get a more precise idea of which connector causes a failure, when that happens. VGA is explicitly excluded from this test as there is currently no way of doing delayed hpd pulses for it. Signed-off-by: Paul Kocialkowski --- tests/chamelium.c | 86 +++ 1 file changed, 86 insertions(+) diff --git a/tests/chamelium.c b/tests/chamelium.c index 76b14e95..d569c8ee 100644 --- a/tests/chamelium.c +++ b/tests/chamelium.c @@ -241,6 +241,80 @@ test_suspend_resume_hpd(data_t *data, struct chamelium_port *port, } static void +test_suspend_resume_hpd_common(data_t *data, enum igt_suspend_state state, + enum igt_suspend_test test) +{ + struct udev_monitor *mon = igt_watch_hotplug(); + struct chamelium_port *port; + int p; + + for (p = 0; p < data->port_count; p++) { + port = data->ports[p]; + if (chamelium_port_get_type(port) == DRM_MODE_CONNECTOR_VGA) + continue; + + reset_state(data, port); + + igt_debug("Testing port %s\n", chamelium_port_get_name(port)); + } + + igt_set_autoresume_delay(SUSPEND_RESUME_DELAY); + igt_flush_hotplugs(mon); + + /* Make sure we notice new connectors after resuming */ + for (p = 0; p < data->port_count; p++) { + port = data->ports[p]; + if (chamelium_port_get_type(port) == DRM_MODE_CONNECTOR_VGA) + continue; + + chamelium_async_hpd_pulse_start(data->chamelium, port, false, + SUSPEND_RESUME_DELAY / 2); + } + + igt_system_suspend_autoresume(state, test); + chamelium_async_hpd_pulse_finish(data->chamelium); + + igt_assert(igt_hotplug_detected(mon, HOTPLUG_TIMEOUT)); + + for (p = 0; p < data->port_count; p++) { + port = data->ports[p]; + if (chamelium_port_get_type(port) == DRM_MODE_CONNECTOR_VGA) + continue; + + igt_assert_eq(reprobe_connector(data, port), + DRM_MODE_CONNECTED); + } + + igt_flush_hotplugs(mon); + + /* Now make sure we notice disconnected connectors after resuming */ + for (p = 0; p < data->port_count; p++) { + port = data->ports[p]; + if (chamelium_port_get_type(port) == DRM_MODE_CONNECTOR_VGA) + continue; + + chamelium_async_hpd_pulse_start(data->chamelium, port, true, + SUSPEND_RESUME_DELAY / 2); + } + + igt_system_suspend_autoresume(state, test); + chamelium_async_hpd_pulse_finish(data->chamelium); + + igt_assert(igt_hotplug_detected(mon, HOTPLUG_TIMEOUT)); + + for (p = 0; p < data->port_count; p++) { + port = data->ports[p]; + if (chamelium_port_get_type(port) == DRM_MODE_CONNECTOR_VGA) + continue; + + igt_assert_eq(reprobe_connector(data, port), + DRM_MODE_DISCONNECTED); + } + + igt_cleanup_hotplug(mon); +} + +static void test_suspend_resume_edid_change(data_t *data, struct chamelium_port *port, enum igt_suspend_state state, enum igt_suspend_test test, @@ -750,6 +824,18 @@ igt_main test_hpd_without_ddc(&data, port); } + igt_subtest_group { + igt_subtest("common-hpd-after-suspend") + test_suspend_resume_hpd_common(&data, + SUSPEND_STATE_MEM, + SUSPEND_TEST_NONE); + + igt_subtest("common-hpd-after-hibernate") + test_suspend_resume_hpd_common(&data, + SUSPEND_STATE_DISK, + SUSPEND_TEST_DEVICES); + } + igt_fixture { close(data.drm_fd); } -- 2.13.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH i-g-t] lib/igt_chamelium: Create pixman image with bytes per pixel, not bits
The pixman_image_create_bits function expects bytes per pixels as fifth argument, not bits per pixels. This divides the PIXMAN_FORMAT_BPP macro's result by 8 to get it in bytes per pixels instead of bits per pixels. Signed-off-by: Paul Kocialkowski --- lib/igt_chamelium.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c index 2315ce60..4a2af796 100644 --- a/lib/igt_chamelium.c +++ b/lib/igt_chamelium.c @@ -967,7 +967,7 @@ static pixman_image_t *convert_frame_format(pixman_image_t *src, int w = pixman_image_get_width(src), h = pixman_image_get_height(src); converted = pixman_image_create_bits(format, w, h, NULL, -PIXMAN_FORMAT_BPP(format) * w); +PIXMAN_FORMAT_BPP(format) / 8 * w); pixman_image_composite(PIXMAN_OP_ADD, src, NULL, converted, 0, 0, 0, 0, 0, 0, w, h); -- 2.13.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH i-g-t v2] tests/chamelium: Add common suspend and hibernate tests for DP and HDMI
Hi, On Fri, 2017-06-16 at 19:28 -0400, Lyude Paul wrote: > On Fri, 2017-06-16 at 17:17 +0300, Paul Kocialkowski wrote: > > This adds two new tests: common-hpd-after-suspend and > > common-hpd-after-hibernate that are aimed at testing HPD change during > > suspend/hibernate for both DP and HDMI, at the same time. > > > > The interest in bringing this test up is to reduce the time spent in > > testing, with the downside of less precision regarding the test's > > outcome. The per-connector tests are still available to get a more > > precise idea of which connector causes a failure, when that happens. > > > > VGA is explicitly excluded from this test as there is currently no > > way of doing delayed hpd pulses for it. > > > > > Signed-off-by: Paul Kocialkowski > > > > --- > > tests/chamelium.c | 86 > > +++ > > 1 file changed, 86 insertions(+) > > > > diff --git a/tests/chamelium.c b/tests/chamelium.c > > index 76b14e95..d569c8ee 100644 > > --- a/tests/chamelium.c > > +++ b/tests/chamelium.c > > @@ -241,6 +241,80 @@ test_suspend_resume_hpd(data_t *data, struct > > chamelium_port *port, > > } > > > > static void > > +test_suspend_resume_hpd_common(data_t *data, enum igt_suspend_state state, > > + enum igt_suspend_test test) > > +{ > > + struct udev_monitor *mon = igt_watch_hotplug(); > > + struct chamelium_port *port; > > + int p; > > + > > + for (p = 0; p < data->port_count; p++) { > > + port = data->ports[p]; > > + if (chamelium_port_get_type(port) == > > DRM_MODE_CONNECTOR_VGA) > > + continue; > > + > > + reset_state(data, port); > > + > > + igt_debug("Testing port %s\n", > > chamelium_port_get_name(port)); > > + } > > + > > + igt_set_autoresume_delay(SUSPEND_RESUME_DELAY); > > + igt_flush_hotplugs(mon); > > + > > + /* Make sure we notice new connectors after resuming */ > > + for (p = 0; p < data->port_count; p++) { > > + port = data->ports[p]; > > + if (chamelium_port_get_type(port) == > > DRM_MODE_CONNECTOR_VGA) > > + continue; > > + > > + chamelium_async_hpd_pulse_start(data->chamelium, port, > > false, > > + SUSPEND_RESUME_DELAY / 2); > > + } > > + > > + igt_system_suspend_autoresume(state, test); > > + chamelium_async_hpd_pulse_finish(data->chamelium); > > + > > + igt_assert(igt_hotplug_detected(mon, HOTPLUG_TIMEOUT)); > > + > > + for (p = 0; p < data->port_count; p++) { > > + port = data->ports[p]; > > + if (chamelium_port_get_type(port) == > > DRM_MODE_CONNECTOR_VGA) > > + continue; > > + > > + igt_assert_eq(reprobe_connector(data, port), > > + DRM_MODE_CONNECTED); > > + } > > + > > + igt_flush_hotplugs(mon); > > + > > + /* Now make sure we notice disconnected connectors after resuming > > */ > > + for (p = 0; p < data->port_count; p++) { > > + port = data->ports[p]; > > + if (chamelium_port_get_type(port) == > > DRM_MODE_CONNECTOR_VGA) > > + continue; > > + > > + chamelium_async_hpd_pulse_start(data->chamelium, port, > > true, > > + SUSPEND_RESUME_DELAY / 2); > > + } > > + > > + igt_system_suspend_autoresume(state, test); > > + chamelium_async_hpd_pulse_finish(data->chamelium); > > + > > + igt_assert(igt_hotplug_detected(mon, HOTPLUG_TIMEOUT)); > > + > > + for (p = 0; p < data->port_count; p++) { > > + port = data->ports[p]; > > + if (chamelium_port_get_type(port) == > > DRM_MODE_CONNECTOR_VGA) > > + continue; > > + > > + igt_assert_eq(reprobe_connector(data, port), > > + DRM_MODE_DISCONNECTED); > > + } > > + > > + igt_cleanup_hotplug(mon); > > +} > > + > > +static void > > For smaller bits of code this isn't a big deal since we're talking > about tests here, but this is a lot of code to have for a single > function like this. Mind splitting this into something like (feel free > to take some liberty with the
[Intel-gfx] [PATCH i-g-t v3] tests/chamelium: Add common suspend and hibernate tests for DP and HDMI
This adds two new tests: common-hpd-after-suspend and common-hpd-after-hibernate that are aimed at testing HPD change during suspend/hibernate for both DP and HDMI, at the same time. The interest in bringing this test up is to reduce the time spent in testing, with the downside of less precision regarding the test's outcome. The per-connector tests are still available to get a more precise idea of which connector causes a failure, when that happens. VGA is explicitly excluded from this test as there is currently no way of doing delayed hpd pulses for it. The generic hpd suspend/resume test code is split in a dedicated function, that allow testing one or all possible ports. Signed-off-by: Paul Kocialkowski --- tests/chamelium.c | 118 +- 1 file changed, 100 insertions(+), 18 deletions(-) diff --git a/tests/chamelium.c b/tests/chamelium.c index 76b14e95..3cf9f3b5 100644 --- a/tests/chamelium.c +++ b/tests/chamelium.c @@ -143,8 +143,18 @@ wait_for_connector(data_t *data, struct chamelium_port *port, static void reset_state(data_t *data, struct chamelium_port *port) { + int p; + chamelium_reset(data->chamelium); - wait_for_connector(data, port, DRM_MODE_DISCONNECTED); + + if (port) { + wait_for_connector(data, port, DRM_MODE_DISCONNECTED); + } else { + for (p = 0; p < data->port_count; p++) { + port = data->ports[p]; + wait_for_connector(data, port, DRM_MODE_DISCONNECTED); + } + } } static void @@ -206,36 +216,96 @@ test_edid_read(data_t *data, struct chamelium_port *port, } static void -test_suspend_resume_hpd(data_t *data, struct chamelium_port *port, - enum igt_suspend_state state, - enum igt_suspend_test test) +try_suspend_resume_hpd(data_t *data, struct chamelium_port *port, + enum igt_suspend_state state, enum igt_suspend_test test, + struct udev_monitor *mon, bool connected) { - struct udev_monitor *mon = igt_watch_hotplug(); - - reset_state(data, port); + int p; igt_set_autoresume_delay(SUSPEND_RESUME_DELAY); igt_flush_hotplugs(mon); - /* Make sure we notice new connectors after resuming */ - chamelium_async_hpd_pulse_start(data->chamelium, port, false, - SUSPEND_RESUME_DELAY / 2); + if (port) { + chamelium_async_hpd_pulse_start(data->chamelium, port, + connected, + SUSPEND_RESUME_DELAY / 2); + } else { + for (p = 0; p < data->port_count; p++) { + port = data->ports[p]; + if (chamelium_port_get_type(port) == DRM_MODE_CONNECTOR_VGA) + continue; + + chamelium_async_hpd_pulse_start(data->chamelium, port, + connected, + SUSPEND_RESUME_DELAY / 2); + } + + port = NULL; + } + igt_system_suspend_autoresume(state, test); chamelium_async_hpd_pulse_finish(data->chamelium); igt_assert(igt_hotplug_detected(mon, HOTPLUG_TIMEOUT)); - igt_assert_eq(reprobe_connector(data, port), DRM_MODE_CONNECTED); + if (port) { + igt_assert_eq(reprobe_connector(data, port), connected ? + DRM_MODE_DISCONNECTED : DRM_MODE_CONNECTED); + } else { + for (p = 0; p < data->port_count; p++) { + port = data->ports[p]; + if (chamelium_port_get_type(port) == DRM_MODE_CONNECTOR_VGA) + continue; + + igt_assert_eq(reprobe_connector(data, port), connected ? + DRM_MODE_DISCONNECTED : + DRM_MODE_CONNECTED); + } - igt_flush_hotplugs(mon); + port = NULL; + } +} + +static void +test_suspend_resume_hpd(data_t *data, struct chamelium_port *port, + enum igt_suspend_state state, + enum igt_suspend_test test) +{ + struct udev_monitor *mon = igt_watch_hotplug(); + + reset_state(data, port); + + /* Make sure we notice new connectors after resuming */ + try_suspend_resume_hpd(data, port, state, test, mon, false); /* Now make sure we notice disconnected connectors after resuming */ - chamelium_async_hpd_pulse_start(data->chamelium, port, true, - SUSPEND_RESUME_DELAY / 2); - igt_system_suspend_autoresume(state, test); -
[Intel-gfx] [PATCH i-g-t] lib/igt_aux: Use provided autoresume delay for rtc wake
This stores the autoresume delay provided via igt_set_autoresume_delay for use during suspend via rtc wake scheduling. This delay was previously only used for pm_test suspendm while the function suggests it should be applied to all autoresume cases. There is also definitely a use case for configuring the rtc wake delay, so this implements it. Signed-off-by: Paul Kocialkowski --- lib/igt_aux.c | 9 - 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/igt_aux.c b/lib/igt_aux.c index eb563f72..882dba06 100644 --- a/lib/igt_aux.c +++ b/lib/igt_aux.c @@ -680,6 +680,8 @@ void igt_cleanup_aperture_trashers(void) free(trash_bos); } +static int autoresume_delay; + static const char *suspend_state_name[] = { [SUSPEND_STATE_FREEZE] = "freeze", [SUSPEND_STATE_STANDBY] = "standby", @@ -746,7 +748,10 @@ static void suspend_via_rtcwake(enum igt_suspend_state state) igt_assert(state < SUSPEND_STATE_NUM); - delay = state == SUSPEND_STATE_DISK ? 30 : 15; + if (autoresume_delay) + delay = autoresume_delay; + else + delay = state == SUSPEND_STATE_DISK ? 30 : 15; /* * Skip if rtcwake would fail for a reason not related to the kernel's @@ -889,6 +894,8 @@ void igt_set_autoresume_delay(int delay_secs) igt_require(write(delay_fd, delay_str, strlen(delay_str))); close(delay_fd); + + autoresume_delay = delay_secs; } /** -- 2.13.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH i-g-t 5/5] tests/chamelium: Also test VGA for common suspend and hibernate tests
Now that HPD toggle during suspend and hibernate can be tested for VGA as well, there is no need to exclude it in the common tests. Signed-off-by: Paul Kocialkowski --- tests/chamelium.c | 9 - 1 file changed, 9 deletions(-) diff --git a/tests/chamelium.c b/tests/chamelium.c index 07dc4849..b7eaa2fa 100644 --- a/tests/chamelium.c +++ b/tests/chamelium.c @@ -232,9 +232,6 @@ try_suspend_resume_hpd(data_t *data, struct chamelium_port *port, } else { for (p = 0; p < data->port_count; p++) { port = data->ports[p]; - if (chamelium_port_get_type(port) == DRM_MODE_CONNECTOR_VGA) - continue; - chamelium_schedule_hpd_toggle(data->chamelium, port, SUSPEND_RESUME_DELAY * 1000 / 2, !connected); @@ -252,9 +249,6 @@ try_suspend_resume_hpd(data_t *data, struct chamelium_port *port, } else { for (p = 0; p < data->port_count; p++) { port = data->ports[p]; - if (chamelium_port_get_type(port) == DRM_MODE_CONNECTOR_VGA) - continue; - igt_assert_eq(reprobe_connector(data, port), connected ? DRM_MODE_DISCONNECTED : DRM_MODE_CONNECTED); @@ -292,9 +286,6 @@ test_suspend_resume_hpd_common(data_t *data, enum igt_suspend_state state, for (p = 0; p < data->port_count; p++) { port = data->ports[p]; - if (chamelium_port_get_type(port) == DRM_MODE_CONNECTOR_VGA) - continue; - igt_debug("Testing port %s\n", chamelium_port_get_name(port)); } -- 2.13.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH i-g-t 2/5] tests/chamelium: Use HPD toggle scheduling instead of async pulses
This switches over to HPD toggle scheduling instead of starting pulses with an asynchronous call, suspending and dealing with the result at resume. The XMLRPC library does not guarantee that the call will be made before caring for its outcome and this is in fact what was happening: the call was being delayed until resume time, as can be seen from the Chamelium's logs. The quite generous timeout for HPD event detection would then catch the toggle, that was sent after resume. Thus, HPD toggle during suspend was not properly tested before and this changes fixes that. Signed-off-by: Paul Kocialkowski --- tests/chamelium.c | 13 ++--- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/tests/chamelium.c b/tests/chamelium.c index 3cf9f3b5..c7114987 100644 --- a/tests/chamelium.c +++ b/tests/chamelium.c @@ -226,25 +226,24 @@ try_suspend_resume_hpd(data_t *data, struct chamelium_port *port, igt_flush_hotplugs(mon); if (port) { - chamelium_async_hpd_pulse_start(data->chamelium, port, - connected, - SUSPEND_RESUME_DELAY / 2); + chamelium_schedule_hpd_toggle(data->chamelium, port, + SUSPEND_RESUME_DELAY * 1000 / 2, + !connected); } else { for (p = 0; p < data->port_count; p++) { port = data->ports[p]; if (chamelium_port_get_type(port) == DRM_MODE_CONNECTOR_VGA) continue; - chamelium_async_hpd_pulse_start(data->chamelium, port, - connected, - SUSPEND_RESUME_DELAY / 2); + chamelium_schedule_hpd_toggle(data->chamelium, port, + SUSPEND_RESUME_DELAY * 1000 / 2, + !connected); } port = NULL; } igt_system_suspend_autoresume(state, test); - chamelium_async_hpd_pulse_finish(data->chamelium); igt_assert(igt_hotplug_detected(mon, HOTPLUG_TIMEOUT)); if (port) { -- 2.13.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH i-g-t 3/5] lib/igt_chamelium: Get rid of async hpd pulse functions
This removes the functions related to async hpd pulse handling, that were used for hpd toggle during suspend testing. Since the XMLRPC library does not guarantee that the call will be made before caring for its result, this function did not work properly. These functions are deprecated in favor of HPD toggle scheduling, that was recently added to the Chamelium's XMLRPC API and IGT. Signed-off-by: Paul Kocialkowski --- lib/igt_chamelium.c | 72 - lib/igt_chamelium.h | 4 --- 2 files changed, 76 deletions(-) diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c index 523cc853..225f98c3 100644 --- a/lib/igt_chamelium.c +++ b/lib/igt_chamelium.c @@ -469,78 +469,6 @@ void chamelium_schedule_hpd_toggle(struct chamelium *chamelium, "(iii)", port->id, delay_ms, rising_edge)); } -static void async_rpc_handler(const char *server_url, const char *method_name, - xmlrpc_value *param_array, void *user_data, - xmlrpc_env *fault, xmlrpc_value *result) -{ - /* We don't care about the responses */ -} - -/** - * chamelium_async_hpd_pulse_start: - * @chamelium: The Chamelium instance to use - * @port: The port to fire the HPD pulses on - * @high: Whether to fire a high pulse (e.g. simulate a connect), or a low - * pulse (e.g. simulate a disconnect) - * @delay_secs: How long to wait before sending the HPD pulse. - * - * Instructs the chamelium to send an hpd pulse after @delay_secs seconds have - * passed, without waiting for the chamelium to finish. This is useful for - * testing things such as hpd after a suspend/resume cycle, since we can't tell - * the chamelium to send a hotplug at the same time that our system is - * suspended. - * - * It is required that the user eventually call - * #chamelium_async_hpd_pulse_finish, to clean up the leftover XML-RPC - * responses from the chamelium. - */ -void chamelium_async_hpd_pulse_start(struct chamelium *chamelium, -struct chamelium_port *port, -bool high, int delay_secs) -{ - xmlrpc_value *pulse_widths = xmlrpc_array_new(&chamelium->env), *width; - - /* TODO: Actually implement something in the chameleon server to allow -* for delayed actions such as hotplugs. This would work a bit better -* and allow us to test suspend/resume on ports without hpd like VGA -*/ - - igt_debug("Sending HPD pulse (%s) on %s with %d second delay\n", - high ? "high->low" : "low->high", port->name, delay_secs); - - /* If we're starting at high, make the first pulse width 0 so we keep -* the port connected */ - if (high) { - width = xmlrpc_int_new(&chamelium->env, 0); - xmlrpc_array_append_item(&chamelium->env, pulse_widths, width); - xmlrpc_DECREF(width); - } - - width = xmlrpc_int_new(&chamelium->env, delay_secs * 1000); - xmlrpc_array_append_item(&chamelium->env, pulse_widths, width); - xmlrpc_DECREF(width); - - xmlrpc_client_start_rpcf(&chamelium->env, chamelium->client, -chamelium->url, -"FireMixedHpdPulses", async_rpc_handler, NULL, -"(iA)", port->id, pulse_widths); - xmlrpc_DECREF(pulse_widths); -} - -/** - * chamelium_async_hpd_pulse_finish: - * @chamelium: The Chamelium instance to use - * - * Waits for any asynchronous RPC started by #chamelium_async_hpd_pulse_start - * to complete, and then cleans up any leftover responses from the chamelium. - * If all of the RPC calls have already completed, this function returns - * immediately. - */ -void chamelium_async_hpd_pulse_finish(struct chamelium *chamelium) -{ - xmlrpc_client_event_loop_finish(chamelium->client); -} - /** * chamelium_new_edid: * @chamelium: The Chamelium instance to use diff --git a/lib/igt_chamelium.h b/lib/igt_chamelium.h index 408a4b85..81322ad2 100644 --- a/lib/igt_chamelium.h +++ b/lib/igt_chamelium.h @@ -64,10 +64,6 @@ void chamelium_fire_hpd_pulses(struct chamelium *chamelium, void chamelium_schedule_hpd_toggle(struct chamelium *chamelium, struct chamelium_port *port, int delay_ms, bool rising_edge); -void chamelium_async_hpd_pulse_start(struct chamelium *chamelium, -struct chamelium_port *port, -bool high, int delay_secs); -void chamelium_async_hpd_pulse_finish(struct chamelium *chamelium); int chamelium_new_edid(struct chamelium *chamelium, const unsigned char *edid); void chamelium_port_set_edid(struct chamelium *chamelium,
[Intel-gfx] [PATCH i-g-t 4/5] tests/chamelium: Test HPD toggle after suspend and hibernate for VGA
This adds HPD toggle after suspend and hibernate testing for VGA, in the same fashion as currently done for DP and HDMI. --- tests/chamelium.c | 13 + 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/tests/chamelium.c b/tests/chamelium.c index c7114987..07dc4849 100644 --- a/tests/chamelium.c +++ b/tests/chamelium.c @@ -810,10 +810,15 @@ igt_main igt_kms_get_alt_edid()); } - /* FIXME: Right now there isn't a way to do any sort of delayed -* psuedo-hotplug with VGA, so testing detection after a -* suspend/resume cycle isn't possible yet -*/ + connector_subtest("vga-hpd-after-suspend", VGA) + test_suspend_resume_hpd(&data, port, + SUSPEND_STATE_MEM, + SUSPEND_TEST_NONE); + + connector_subtest("vga-hpd-after-hibernate", VGA) + test_suspend_resume_hpd(&data, port, + SUSPEND_STATE_DISK, + SUSPEND_TEST_DEVICES); connector_subtest("vga-hpd-without-ddc", VGA) test_hpd_without_ddc(&data, port); -- 2.13.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH i-g-t 1/5] lib/igt_chamelium: Add support for HPD toggle scheduling
This adds support for the newly-introduced ScheduleHpdToggle XMLRPC method of the Chamelium's interface. It allows scheduling an HPD toggle, for which the call will return immediately. This is especially useful for testing HPD during suspend/resume. Signed-off-by: Paul Kocialkowski --- lib/igt_chamelium.c | 22 ++ lib/igt_chamelium.h | 3 +++ 2 files changed, 25 insertions(+) diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c index 4a2af796..523cc853 100644 --- a/lib/igt_chamelium.c +++ b/lib/igt_chamelium.c @@ -447,6 +447,28 @@ void chamelium_fire_mixed_hpd_pulses(struct chamelium *chamelium, xmlrpc_DECREF(pulse_widths); } +/** + * chamelium_schedule_hpd_toggle: + * @chamelium: The Chamelium instance to use + * @port: The port to fire the HPD pulses on + * @delay_ms: Delay in milli-second before the toggle takes place + * @rising_edge: Whether the toggle should be a rising edge or a falling edge + * + * Instructs the chamelium to schedule an hpd toggle (either a rising edge or + * a falling edge, depending on @rising_edg) after @delay_ms have passed. + * This is useful for testing things such as hpd after a suspend/resume cycle. + */ +void chamelium_schedule_hpd_toggle(struct chamelium *chamelium, + struct chamelium_port *port, int delay_ms, + bool rising_edge) +{ + igt_debug("Scheduling HPD toggle on %s in %d ms\n", port->name, + delay_ms); + + xmlrpc_DECREF(chamelium_rpc(chamelium, NULL, "ScheduleHpdToggle", + "(iii)", port->id, delay_ms, rising_edge)); +} + static void async_rpc_handler(const char *server_url, const char *method_name, xmlrpc_value *param_array, void *user_data, xmlrpc_env *fault, xmlrpc_value *result) diff --git a/lib/igt_chamelium.h b/lib/igt_chamelium.h index 15f60246..408a4b85 100644 --- a/lib/igt_chamelium.h +++ b/lib/igt_chamelium.h @@ -61,6 +61,9 @@ void chamelium_fire_mixed_hpd_pulses(struct chamelium *chamelium, void chamelium_fire_hpd_pulses(struct chamelium *chamelium, struct chamelium_port *port, int width_msec, int count); +void chamelium_schedule_hpd_toggle(struct chamelium *chamelium, + struct chamelium_port *port, int delay_ms, + bool rising_edge); void chamelium_async_hpd_pulse_start(struct chamelium *chamelium, struct chamelium_port *port, bool high, int delay_secs); -- 2.13.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH] drm/i915: Synchronize connectors states when switching from poll to irq
After detecting an IRQ storm, hotplug detection will switch from irq-based detection to poll-based detection. After a short delay or when resetting storm detection from debugfs, detection will switch back to being irq-based. However, it may occur that polling does not have enough time to detect the current connector state when that second switch takes place. Thus, this sets the appropriate hotplug event bits for the concerned connectors and schedules the hotplug work, that will ensure the connectors states are in sync when switching back to irq. Without this, no irq will be triggered and the hpd change will be lost. Signed-off-by: Paul Kocialkowski --- drivers/gpu/drm/i915/intel_hotplug.c | 8 +++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_hotplug.c b/drivers/gpu/drm/i915/intel_hotplug.c index f1200272a699..29f55480b0bb 100644 --- a/drivers/gpu/drm/i915/intel_hotplug.c +++ b/drivers/gpu/drm/i915/intel_hotplug.c @@ -218,9 +218,13 @@ static void intel_hpd_irq_storm_reenable_work(struct work_struct *work) struct intel_connector *intel_connector = to_intel_connector(connector); if (intel_connector->encoder->hpd_pin == i) { - if (connector->polled != intel_connector->polled) + if (connector->polled != intel_connector->polled) { DRM_DEBUG_DRIVER("Reenabling HPD on connector %s\n", connector->name); + + dev_priv->hotplug.event_bits |= (1 << i); + } + connector->polled = intel_connector->polled; if (!connector->polled) connector->polled = DRM_CONNECTOR_POLL_HPD; @@ -232,6 +236,8 @@ static void intel_hpd_irq_storm_reenable_work(struct work_struct *work) dev_priv->display.hpd_irq_setup(dev_priv); spin_unlock_irq(&dev_priv->irq_lock); + schedule_work(&dev_priv->hotplug.hotplug_work); + intel_runtime_pm_put(dev_priv); } -- 2.13.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH i-g-t 4/7] lib/igt_chamelium: Add support for configurable DUT suspend/resume delay
This adds support for reading a SuspendResumeDelay property (under [DUT]) in the IGT configuration (igtrc) and exposing it through a chamelium_get_suspend_resume_delay function. Signed-off-by: Paul Kocialkowski --- lib/igt_chamelium.c | 31 ++- lib/igt_chamelium.h | 1 + 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c index 225f98c3..a1aaf405 100644 --- a/lib/igt_chamelium.c +++ b/lib/igt_chamelium.c @@ -58,7 +58,7 @@ * [Chamelium] * URL=http://chameleon:9992 # The URL used for connecting to the Chamelium's RPC server * - * # The rest of the sections are used for defining connector mappings. + * # The following sections are used for defining connector mappings. * # This is required so any tests using the Chamelium know which connector * # on the test machine should be connected to each Chamelium port. * # @@ -70,12 +70,19 @@ * * [Chamelium:HDMI-A-1] * ChameliumPortID=3 + * + * # The following section is used for configuring the Device Under Test. + * # It is not mandatory and allows overriding default values. + * [DUT] + * SuspendResumeDelay=10 * ]| * * By default, this file is expected to exist in ~/.igtrc . The directory for * this can be overriden by setting the environment variable %IGT_CONFIG_PATH. */ +#define SUSPEND_RESUME_DELAY_DEFAULT 20 /* seconds */ + struct chamelium_edid { int id; struct igt_list link; @@ -100,6 +107,7 @@ struct chamelium { xmlrpc_env env; xmlrpc_client *client; char *url; + int suspend_resume_delay; /* Indicates the last port to have been used for capturing video */ struct chamelium_port *capturing_port; @@ -114,6 +122,20 @@ struct chamelium { static struct chamelium *cleanup_instance; /** + * chamelium_get_suspend_resume_delay: + * @chamelium: The Chamelium instance to use + * + * Retrieves the suspend/resume delay as specified in the configuration or + * its default value. + * + * Returns: the suspend/resume delay in seconds + */ +int chamelium_get_suspend_resume_delay(struct chamelium *chamelium) +{ + return chamelium->suspend_resume_delay; +} + +/** * chamelium_get_ports: * @chamelium: The Chamelium instance to use * @count: Where to store the number of ports @@ -1157,6 +1179,13 @@ static bool chamelium_read_config(struct chamelium *chamelium, int drm_fd) goto out; } + rc = g_key_file_get_integer(key_file, "DUT", "SuspendResumeDelay", + &error); + if (rc == 0) + chamelium->suspend_resume_delay = SUSPEND_RESUME_DELAY_DEFAULT; + else + chamelium->suspend_resume_delay = rc; + ret = chamelium_read_port_mappings(chamelium, drm_fd, key_file); out: diff --git a/lib/igt_chamelium.h b/lib/igt_chamelium.h index 81322ad2..380f9b36 100644 --- a/lib/igt_chamelium.h +++ b/lib/igt_chamelium.h @@ -41,6 +41,7 @@ struct chamelium *chamelium_init(int drm_fd); void chamelium_deinit(struct chamelium *chamelium); void chamelium_reset(struct chamelium *chamelium); +int chamelium_get_suspend_resume_delay(struct chamelium *chamelium); struct chamelium_port **chamelium_get_ports(struct chamelium *chamelium, int *count); unsigned int chamelium_port_get_type(const struct chamelium_port *port); -- 2.13.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH i-g-t 3/7] tests/chamelium: Use 50 ms delay to wait for connector change
Using a 1 s delay seems too large for detecting a connector change, that may happen faster than this. Since the constraints on execution time are high, it is preferable to use a much smaller sleep time. Signed-off-by: Paul Kocialkowski --- tests/chamelium.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/chamelium.c b/tests/chamelium.c index 5075a52f..15ed0f28 100644 --- a/tests/chamelium.c +++ b/tests/chamelium.c @@ -135,7 +135,7 @@ wait_for_connector(data_t *data, struct chamelium_port *port, return; } - sleep(1); + usleep(5); } igt_assert(finished); -- 2.13.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH i-g-t 2/7] tests/chamelium: Check all connectors state for basic hotplug
Without doing a full reprobe, hpd toggles are sent without much delay between them. With a VGA connector attached, the reset occurring before the test will toggle its state, with a delay (inherent to hpd detection on VGA). It often occurs that this VGA state toggle is detected in the middle of the current connector test, triggering a hotplug event unrelated to the current connector and thus causing the test to fail. Thus, the state of all connectors is checked (and waited for) before running the basic hotplug test. Signed-off-by: Paul Kocialkowski --- tests/chamelium.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/chamelium.c b/tests/chamelium.c index e1f21fb8..5075a52f 100644 --- a/tests/chamelium.c +++ b/tests/chamelium.c @@ -165,7 +165,7 @@ test_basic_hotplug(data_t *data, struct chamelium_port *port) struct udev_monitor *mon = igt_watch_hotplug(); int i; - reset_state(data, port); + reset_state(data, NULL); igt_hpd_storm_set_threshold(data->drm_fd, 0); for (i = 0; i < 15; i++) { -- 2.13.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH i-g-t 7/7] tests/chamelium: Disconnect connectors without extra reset
This removes the reset call from the reset_state function and renames it to disconnect_connector. Since a call to reset is already done in chamelium_init, there is no need to do an extra reset in each test. This allows reducing the execution time a bit. Signed-off-by: Paul Kocialkowski --- tests/chamelium.c | 22 +++--- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/chamelium.c b/tests/chamelium.c index 01ae4cd7..7d6893da 100644 --- a/tests/chamelium.c +++ b/tests/chamelium.c @@ -144,17 +144,17 @@ wait_for_connector(data_t *data, struct chamelium_port *port, } static void -reset_state(data_t *data, struct chamelium_port *port) +disconnect_connector(data_t *data, struct chamelium_port *port) { int p; - chamelium_reset(data->chamelium); - if (port) { + chamelium_unplug(data->chamelium, port); wait_for_connector(data, port, DRM_MODE_DISCONNECTED, false); } else { for (p = 0; p < data->port_count; p++) { port = data->ports[p]; + chamelium_unplug(data->chamelium, port); wait_for_connector(data, port, DRM_MODE_DISCONNECTED, false); } @@ -167,7 +167,7 @@ test_basic_hotplug(data_t *data, struct chamelium_port *port, int toggle_count) struct udev_monitor *mon = igt_watch_hotplug(); int i; - reset_state(data, NULL); + disconnect_connector(data, NULL); igt_hpd_storm_set_threshold(data->drm_fd, 0); for (i = 0; i < toggle_count; i++) { @@ -201,7 +201,7 @@ test_edid_read(data_t *data, struct chamelium_port *port, data->chamelium, port, false); uint64_t edid_blob_id; - reset_state(data, port); + disconnect_connector(data, port); chamelium_port_set_edid(data->chamelium, port, edid_id); chamelium_plug(data->chamelium, port); @@ -270,7 +270,7 @@ test_suspend_resume_hpd(data_t *data, struct chamelium_port *port, { struct udev_monitor *mon = igt_watch_hotplug(); - reset_state(data, port); + disconnect_connector(data, port); /* Make sure we notice new connectors after resuming */ try_suspend_resume_hpd(data, port, state, test, mon, false); @@ -294,7 +294,7 @@ test_suspend_resume_hpd_common(data_t *data, enum igt_suspend_state state, igt_debug("Testing port %s\n", chamelium_port_get_name(port)); } - reset_state(data, NULL); + disconnect_connector(data, NULL); /* Make sure we notice new connectors after resuming */ try_suspend_resume_hpd(data, NULL, state, test, mon, false); @@ -315,7 +315,7 @@ test_suspend_resume_edid_change(data_t *data, struct chamelium_port *port, struct udev_monitor *mon = igt_watch_hotplug(); int delay = chamelium_get_suspend_resume_delay(data->chamelium); - reset_state(data, port); + disconnect_connector(data, port); igt_set_autoresume_delay(delay); @@ -585,7 +585,7 @@ test_hpd_without_ddc(data_t *data, struct chamelium_port *port) { struct udev_monitor *mon = igt_watch_hotplug(); - reset_state(data, port); + disconnect_connector(data, port); igt_flush_hotplugs(mon); /* Disable the DDC on the connector and make sure we still get a @@ -607,7 +607,7 @@ test_hpd_storm_detect(data_t *data, struct chamelium_port *port, int width) int count = 0; igt_require_hpd_storm_ctl(data->drm_fd); - reset_state(data, port); + disconnect_connector(data, port); igt_hpd_storm_set_threshold(data->drm_fd, 1); chamelium_fire_hpd_pulses(data->chamelium, port, width, 10); @@ -632,7 +632,7 @@ static void test_hpd_storm_disable(data_t *data, struct chamelium_port *port, int width) { igt_require_hpd_storm_ctl(data->drm_fd); - reset_state(data, port); + disconnect_connector(data, port); igt_hpd_storm_set_threshold(data->drm_fd, 0); chamelium_fire_hpd_pulses(data->chamelium, port, -- 2.13.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH i-g-t 5/7] tests/chamelium: Use configurable DUT suspend/resume delay
Now that the suspend/resume delay can be configured in the IGT configuration (igtrc), use it in the chamelium suspend/resume tests. Signed-off-by: Paul Kocialkowski --- tests/chamelium.c | 15 +-- 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/tests/chamelium.c b/tests/chamelium.c index 15ed0f28..3ee57af6 100644 --- a/tests/chamelium.c +++ b/tests/chamelium.c @@ -42,7 +42,6 @@ typedef struct { } data_t; #define HOTPLUG_TIMEOUT 20 /* seconds */ -#define SUSPEND_RESUME_DELAY 20 /* seconds */ #define HPD_STORM_PULSE_INTERVAL_DP 100 /* ms */ #define HPD_STORM_PULSE_INTERVAL_HDMI 200 /* ms */ @@ -222,21 +221,22 @@ try_suspend_resume_hpd(data_t *data, struct chamelium_port *port, enum igt_suspend_state state, enum igt_suspend_test test, struct udev_monitor *mon, bool connected) { + int delay = chamelium_get_suspend_resume_delay(data->chamelium); int p; - igt_set_autoresume_delay(SUSPEND_RESUME_DELAY); + igt_set_autoresume_delay(delay); igt_flush_hotplugs(mon); + delay = delay * 1000 / 2; + if (port) { - chamelium_schedule_hpd_toggle(data->chamelium, port, - SUSPEND_RESUME_DELAY * 1000 / 2, + chamelium_schedule_hpd_toggle(data->chamelium, port, delay, !connected); } else { for (p = 0; p < data->port_count; p++) { port = data->ports[p]; chamelium_schedule_hpd_toggle(data->chamelium, port, - SUSPEND_RESUME_DELAY * 1000 / 2, - !connected); + delay, !connected); } port = NULL; @@ -310,9 +310,12 @@ test_suspend_resume_edid_change(data_t *data, struct chamelium_port *port, int alt_edid_id) { struct udev_monitor *mon = igt_watch_hotplug(); + int delay = chamelium_get_suspend_resume_delay(data->chamelium); reset_state(data, port); + igt_set_autoresume_delay(delay); + /* First plug in the port */ chamelium_port_set_edid(data->chamelium, port, edid_id); chamelium_plug(data->chamelium, port); -- 2.13.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH i-g-t 6/7] tests/chamelium: Reduce the simple hotplug test toggle count for VGA
Since VGA hpd detection is done through RGB lines load detection and nowadays often goes through a bridge to some digital interface, HPD detection usually takes a while (up to a couple seconds). Thus, it is not as relevant to stress it as many as 15 times. This brings the toggle count down to 5 times, which makes the test run a lot faster without really changing the outcome much. Signed-off-by: Paul Kocialkowski --- tests/chamelium.c | 15 ++- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/tests/chamelium.c b/tests/chamelium.c index 3ee57af6..01ae4cd7 100644 --- a/tests/chamelium.c +++ b/tests/chamelium.c @@ -46,6 +46,9 @@ typedef struct { #define HPD_STORM_PULSE_INTERVAL_DP 100 /* ms */ #define HPD_STORM_PULSE_INTERVAL_HDMI 200 /* ms */ +#define HPD_TOGGLE_COUNT_VGA 5 +#define HPD_TOGGLE_COUNT_DP_HDMI 15 + /* Pre-calculated CRCs for the pattern fb, for all the modes in the default * chamelium edid */ @@ -159,7 +162,7 @@ reset_state(data_t *data, struct chamelium_port *port) } static void -test_basic_hotplug(data_t *data, struct chamelium_port *port) +test_basic_hotplug(data_t *data, struct chamelium_port *port, int toggle_count) { struct udev_monitor *mon = igt_watch_hotplug(); int i; @@ -167,7 +170,7 @@ test_basic_hotplug(data_t *data, struct chamelium_port *port) reset_state(data, NULL); igt_hpd_storm_set_threshold(data->drm_fd, 0); - for (i = 0; i < 15; i++) { + for (i = 0; i < toggle_count; i++) { igt_flush_hotplugs(mon); /* Check if we get a sysfs hotplug event */ @@ -685,7 +688,8 @@ igt_main } connector_subtest("dp-hpd", DisplayPort) - test_basic_hotplug(&data, port); + test_basic_hotplug(&data, port, + HPD_TOGGLE_COUNT_DP_HDMI); connector_subtest("dp-edid-read", DisplayPort) { test_edid_read(&data, port, edid_id, @@ -741,7 +745,8 @@ igt_main } connector_subtest("hdmi-hpd", HDMIA) - test_basic_hotplug(&data, port); + test_basic_hotplug(&data, port, + HPD_TOGGLE_COUNT_DP_HDMI); connector_subtest("hdmi-edid-read", HDMIA) { test_edid_read(&data, port, edid_id, @@ -797,7 +802,7 @@ igt_main } connector_subtest("vga-hpd", VGA) - test_basic_hotplug(&data, port); + test_basic_hotplug(&data, port, HPD_TOGGLE_COUNT_VGA); connector_subtest("vga-edid-read", VGA) { test_edid_read(&data, port, edid_id, -- 2.13.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH i-g-t 1/7] tests/chamelium: Update connector state without reprobe when possible
This renames the reprobe_connector function to update_connector and ensures that full reprobe of the connector is only done when really necessary (e.g. when changing the EDID). A full reprobe takes time and is not required for updating the connector state. Thus, this allows executing tests faster. Signed-off-by: Paul Kocialkowski --- tests/chamelium.c | 34 ++ 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/tests/chamelium.c b/tests/chamelium.c index b7eaa2fa..e1f21fb8 100644 --- a/tests/chamelium.c +++ b/tests/chamelium.c @@ -100,13 +100,14 @@ require_connector_present(data_t *data, unsigned int type) } static drmModeConnection -reprobe_connector(data_t *data, struct chamelium_port *port) +update_connector(data_t *data, struct chamelium_port *port, bool reprobe) { drmModeConnector *connector; drmModeConnection status; - igt_debug("Reprobing %s...\n", chamelium_port_get_name(port)); - connector = chamelium_port_get_connector(data->chamelium, port, true); + igt_debug("Updating %s...\n", chamelium_port_get_name(port)); + connector = chamelium_port_get_connector(data->chamelium, port, +reprobe); igt_assert(connector); status = connector->connection; @@ -116,7 +117,7 @@ reprobe_connector(data_t *data, struct chamelium_port *port) static void wait_for_connector(data_t *data, struct chamelium_port *port, - drmModeConnection status) + drmModeConnection status, bool reprobe) { bool finished = false; @@ -129,7 +130,7 @@ wait_for_connector(data_t *data, struct chamelium_port *port, * that hpd events work in the event that hpd doesn't work on the system */ igt_until_timeout(HOTPLUG_TIMEOUT) { - if (reprobe_connector(data, port) == status) { + if (update_connector(data, port, reprobe) == status) { finished = true; return; } @@ -148,11 +149,12 @@ reset_state(data_t *data, struct chamelium_port *port) chamelium_reset(data->chamelium); if (port) { - wait_for_connector(data, port, DRM_MODE_DISCONNECTED); + wait_for_connector(data, port, DRM_MODE_DISCONNECTED, false); } else { for (p = 0; p < data->port_count; p++) { port = data->ports[p]; - wait_for_connector(data, port, DRM_MODE_DISCONNECTED); + wait_for_connector(data, port, DRM_MODE_DISCONNECTED, + false); } } } @@ -172,7 +174,7 @@ test_basic_hotplug(data_t *data, struct chamelium_port *port) /* Check if we get a sysfs hotplug event */ chamelium_plug(data->chamelium, port); igt_assert(igt_hotplug_detected(mon, HOTPLUG_TIMEOUT)); - igt_assert_eq(reprobe_connector(data, port), + igt_assert_eq(update_connector(data, port, false), DRM_MODE_CONNECTED); igt_flush_hotplugs(mon); @@ -180,7 +182,7 @@ test_basic_hotplug(data_t *data, struct chamelium_port *port) /* Now check if we get a hotplug from disconnection */ chamelium_unplug(data->chamelium, port); igt_assert(igt_hotplug_detected(mon, HOTPLUG_TIMEOUT)); - igt_assert_eq(reprobe_connector(data, port), + igt_assert_eq(update_connector(data, port, false), DRM_MODE_DISCONNECTED); } @@ -201,7 +203,7 @@ test_edid_read(data_t *data, struct chamelium_port *port, chamelium_port_set_edid(data->chamelium, port, edid_id); chamelium_plug(data->chamelium, port); - wait_for_connector(data, port, DRM_MODE_CONNECTED); + wait_for_connector(data, port, DRM_MODE_CONNECTED, true); igt_assert(kmstest_get_property(data->drm_fd, connector->connector_id, DRM_MODE_OBJECT_CONNECTOR, "EDID", NULL, @@ -244,13 +246,13 @@ try_suspend_resume_hpd(data_t *data, struct chamelium_port *port, igt_assert(igt_hotplug_detected(mon, HOTPLUG_TIMEOUT)); if (port) { - igt_assert_eq(reprobe_connector(data, port), connected ? + igt_assert_eq(update_connector(data, port, false), connected ? DRM_MODE_DISCONNECTED : DRM_MODE_CONNECTED); } else { for (p = 0; p < data->port_count; p++) { port = data->ports[p]; - igt_assert_eq(reprobe_connector(data, port), connected ? - DRM_MODE_DISCONNECTED : + igt_assert_eq(update_connector(data, po
Re: [Intel-gfx] [PATCH i-g-t 4/7] lib/igt_chamelium: Add support for configurable DUT suspend/resume delay
On Mon, 2017-06-26 at 17:25 +0300, Martin Peres wrote: > On 26/06/17 16:59, Paul Kocialkowski wrote: > > This adds support for reading a SuspendResumeDelay property (under > > [DUT]) in the IGT configuration (igtrc) and exposing it through a > > chamelium_get_suspend_resume_delay function. > > > > Signed-off-by: Paul Kocialkowski > > --- > > lib/igt_chamelium.c | 31 ++- > > lib/igt_chamelium.h | 1 + > > 2 files changed, 31 insertions(+), 1 deletion(-) > > > > diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c > > index 225f98c3..a1aaf405 100644 > > --- a/lib/igt_chamelium.c > > +++ b/lib/igt_chamelium.c > > @@ -58,7 +58,7 @@ > >*[Chamelium] > >*URL=http://chameleon:9992 # The URL used for connecting to the > > Chamelium's RPC server > >* > > - * # The rest of the sections are used for defining connector > > mappings. > > + * # The following sections are used for defining connector > > mappings. > >*# This is required so any tests using the Chamelium know which > > connector > >*# on the test machine should be connected to each Chamelium > > port. > >*# > > @@ -70,12 +70,19 @@ > >* > >*[Chamelium:HDMI-A-1] > >*ChameliumPortID=3 > > + * > > + * # The following section is used for configuring the Device Under > > Test. > > + * # It is not mandatory and allows overriding default values. > > + * [DUT] > > + * SuspendResumeDelay=10 > >* ]| > >* > >* By default, this file is expected to exist in ~/.igtrc . The directory > > for > >* this can be overriden by setting the environment variable > > %IGT_CONFIG_PATH. > >*/ > > > > +#define SUSPEND_RESUME_DELAY_DEFAULT 20 /* seconds */ > > + > > struct chamelium_edid { > > int id; > > struct igt_list link; > > @@ -100,6 +107,7 @@ struct chamelium { > > xmlrpc_env env; > > xmlrpc_client *client; > > char *url; > > + int suspend_resume_delay; > > > > /* Indicates the last port to have been used for capturing video > > */ > > struct chamelium_port *capturing_port; > > @@ -114,6 +122,20 @@ struct chamelium { > > static struct chamelium *cleanup_instance; > > Why do you make this part of the chamelium configuration? This should be > common to all the suspend tests. Fair enough, but at this point, only lib/igt_chamelium.c is using igtrc and all the parsing is implemented there. So one course of action here would be to move igtrc parsing outside of igt_chamelium (maybe to igt_core?) and use some global variable for storing this value. What do you think? -- Paul Kocialkowski Intel Finland Oy - BIC 0357606-4 - Westendinkatu 7, 02160 Espoo ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH i-g-t 7/7] tests/chamelium: Disconnect connectors without extra reset
Hey, On Mon, 2017-06-26 at 18:17 -0400, Lyude Paul wrote: > On Mon, 2017-06-26 at 16:59 +0300, Paul Kocialkowski wrote: > > This removes the reset call from the reset_state function and renames > > it > > to disconnect_connector. Since a call to reset is already done in > > chamelium_init, there is no need to do an extra reset in each test. > > > > This allows reducing the execution time a bit. > > > > Signed-off-by: Paul Kocialkowski > > NAK > It's annoying that we have to reset the connectors so much, but > unfortunately there is a reason in this case. The problem is that > chamelium_init() does not get called once per test. At first glance > when running through ./scripts/run_tests.sh this might appear to be the > case, however if you run the test by manually calling the built > chamelium binary (generally useful for debugging the tests themselves > with gdb) it won't actually get called in-between tests. I am well aware of that situation and made sure that it works correctly in that case too. Disconnecting the connector is really all that should be needed, and resetting the whole chamelium seems overkill. There was one occurence where not fully resetting caused an issue when running the whole test binary on i915 (when switching from poll-based detection to irq after hpd storm testing), which was definitely a kernel bug. I submitted a patch to fix it already. So this can even help discover new kernel bugs! > This being said, I'm all for getting rid of a couple extraneous hotplug > resets if possible, but I'd prefer to avoid breaking the ability to run > the chamelium test binary manually. Yeah, the real problem was that when running tests standalone, two resets are done in a row. So worst case, we could ditch the reset at init and make sure each test calls it. Thanks for the review! > > --- > > tests/chamelium.c | 22 +++--- > > 1 file changed, 11 insertions(+), 11 deletions(-) > > > > diff --git a/tests/chamelium.c b/tests/chamelium.c > > index 01ae4cd7..7d6893da 100644 > > --- a/tests/chamelium.c > > +++ b/tests/chamelium.c > > @@ -144,17 +144,17 @@ wait_for_connector(data_t *data, struct > > chamelium_port *port, > > } > > > > static void > > -reset_state(data_t *data, struct chamelium_port *port) > > +disconnect_connector(data_t *data, struct chamelium_port *port) > > { > > int p; > > > > - chamelium_reset(data->chamelium); > > - > > if (port) { > > + chamelium_unplug(data->chamelium, port); > > wait_for_connector(data, port, > > DRM_MODE_DISCONNECTED, false); > > } else { > > for (p = 0; p < data->port_count; p++) { > > port = data->ports[p]; > > + chamelium_unplug(data->chamelium, port); > > wait_for_connector(data, port, > > DRM_MODE_DISCONNECTED, > >false); > > } > > @@ -167,7 +167,7 @@ test_basic_hotplug(data_t *data, struct > > chamelium_port *port, int toggle_count) > > struct udev_monitor *mon = igt_watch_hotplug(); > > int i; > > > > - reset_state(data, NULL); > > + disconnect_connector(data, NULL); > > igt_hpd_storm_set_threshold(data->drm_fd, 0); > > > > for (i = 0; i < toggle_count; i++) { > > @@ -201,7 +201,7 @@ test_edid_read(data_t *data, struct > > chamelium_port *port, > > data->chamelium, port, false); > > uint64_t edid_blob_id; > > > > - reset_state(data, port); > > + disconnect_connector(data, port); > > > > chamelium_port_set_edid(data->chamelium, port, edid_id); > > chamelium_plug(data->chamelium, port); > > @@ -270,7 +270,7 @@ test_suspend_resume_hpd(data_t *data, struct > > chamelium_port *port, > > { > > struct udev_monitor *mon = igt_watch_hotplug(); > > > > - reset_state(data, port); > > + disconnect_connector(data, port); > > > > /* Make sure we notice new connectors after resuming */ > > try_suspend_resume_hpd(data, port, state, test, mon, false); > > @@ -294,7 +294,7 @@ test_suspend_resume_hpd_common(data_t *data, enum > > igt_suspend_state state, > > igt_debug("Testing port %s\n", > > chamelium_port_get_name(port)); > > } > > > > - reset_state(data, NULL); > > + disconnect_connector(data, NULL); > > > > /* Make sure we notice new connectors after resuming */ > > try_suspend_resume_hpd(data, NULL,
Re: [Intel-gfx] [PATCH i-g-t 1/5] lib/igt_chamelium: Add support for HPD toggle scheduling
On Mon, 2017-06-26 at 17:07 -0400, Lyude Paul wrote: > This all looks great! I'm happy to see us finally getting rid of the > very hacky workaround I had to make async hotplugging work (to be fair, > it was only partly broken ;). Thanks for dealing with chameleond > upstream too, I couldn't stand how ugly the code in that thing is... Sure, my pleasure :) > Anyway, this whole patchset looks good. The only thing I ask is that > you condense the patches a bit, mainly: > > 1-3 can all be one patch for adding real async HPD > 4-5 can be another single patch for enabling VGA tests Okay then, I will prepare v2 that way (and rebased on top of current master). Thanks for the review! > On Mon, 2017-06-26 at 10:22 +0300, Paul Kocialkowski wrote: > > This adds support for the newly-introduced ScheduleHpdToggle XMLRPC > > method of the Chamelium's interface. It allows scheduling an HPD > > toggle, > > for which the call will return immediately. > > > > This is especially useful for testing HPD during suspend/resume. > > > > Signed-off-by: Paul Kocialkowski > > --- > > lib/igt_chamelium.c | 22 ++ > > lib/igt_chamelium.h | 3 +++ > > 2 files changed, 25 insertions(+) > > > > diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c > > index 4a2af796..523cc853 100644 > > --- a/lib/igt_chamelium.c > > +++ b/lib/igt_chamelium.c > > @@ -447,6 +447,28 @@ void chamelium_fire_mixed_hpd_pulses(struct > > chamelium *chamelium, > > xmlrpc_DECREF(pulse_widths); > > } > > > > +/** > > + * chamelium_schedule_hpd_toggle: > > + * @chamelium: The Chamelium instance to use > > + * @port: The port to fire the HPD pulses on > > + * @delay_ms: Delay in milli-second before the toggle takes place > > + * @rising_edge: Whether the toggle should be a rising edge or a > > falling edge > > + * > > + * Instructs the chamelium to schedule an hpd toggle (either a > > rising edge or > > + * a falling edge, depending on @rising_edg) after @delay_ms have > > passed. > > + * This is useful for testing things such as hpd after a > > suspend/resume cycle. > > + */ > > +void chamelium_schedule_hpd_toggle(struct chamelium *chamelium, > > + struct chamelium_port *port, int > > delay_ms, > > + bool rising_edge) > > +{ > > + igt_debug("Scheduling HPD toggle on %s in %d ms\n", port- > > > name, > > > > + delay_ms); > > + > > + xmlrpc_DECREF(chamelium_rpc(chamelium, NULL, > > "ScheduleHpdToggle", > > + "(iii)", port->id, delay_ms, > > rising_edge)); > > +} > > + > > static void async_rpc_handler(const char *server_url, const char > > *method_name, > > xmlrpc_value *param_array, void > > *user_data, > > xmlrpc_env *fault, xmlrpc_value > > *result) > > diff --git a/lib/igt_chamelium.h b/lib/igt_chamelium.h > > index 15f60246..408a4b85 100644 > > --- a/lib/igt_chamelium.h > > +++ b/lib/igt_chamelium.h > > @@ -61,6 +61,9 @@ void chamelium_fire_mixed_hpd_pulses(struct > > chamelium *chamelium, > > void chamelium_fire_hpd_pulses(struct chamelium *chamelium, > >struct chamelium_port *port, > >int width_msec, int count); > > +void chamelium_schedule_hpd_toggle(struct chamelium *chamelium, > > + struct chamelium_port *port, int > > delay_ms, > > + bool rising_edge); > > void chamelium_async_hpd_pulse_start(struct chamelium *chamelium, > > struct chamelium_port *port, > > bool high, int delay_secs); -- Paul Kocialkowski Intel Finland Oy - BIC 0357606-4 - Westendinkatu 7, 02160 Espoo ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH i-g-t 4/7] lib/igt_chamelium: Add support for configurable DUT suspend/resume delay
On Mon, 2017-06-26 at 18:15 +0300, Martin Peres wrote: > On 26/06/17 17:33, Paul Kocialkowski wrote: > > On Mon, 2017-06-26 at 17:25 +0300, Martin Peres wrote: > > > On 26/06/17 16:59, Paul Kocialkowski wrote: > > > > This adds support for reading a SuspendResumeDelay property (under > > > > [DUT]) in the IGT configuration (igtrc) and exposing it through a > > > > chamelium_get_suspend_resume_delay function. > > > > > > > > Signed-off-by: Paul Kocialkowski > > > > --- > > > >lib/igt_chamelium.c | 31 ++- > > > >lib/igt_chamelium.h | 1 + > > > >2 files changed, 31 insertions(+), 1 deletion(-) > > > > > > > > diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c > > > > index 225f98c3..a1aaf405 100644 > > > > --- a/lib/igt_chamelium.c > > > > +++ b/lib/igt_chamelium.c > > > > @@ -58,7 +58,7 @@ > > > > * [Chamelium] > > > > * URL=http://chameleon:9992 # The URL used for connecting to > > > > the > > > > Chamelium's RPC server > > > > * > > > > - * # The rest of the sections are used for defining connector > > > > mappings. > > > > + * # The following sections are used for defining connector > > > > mappings. > > > > * # This is required so any tests using the Chamelium know > > > > which > > > > connector > > > > * # on the test machine should be connected to each Chamelium > > > > port. > > > > * # > > > > @@ -70,12 +70,19 @@ > > > > * > > > > * [Chamelium:HDMI-A-1] > > > > * ChameliumPortID=3 > > > > + * > > > > + * # The following section is used for configuring the Device > > > > Under > > > > Test. > > > > + * # It is not mandatory and allows overriding default values. > > > > + * [DUT] > > > > + * SuspendResumeDelay=10 > > > > * ]| > > > > * > > > > * By default, this file is expected to exist in ~/.igtrc . The > > > > directory > > > > for > > > > * this can be overriden by setting the environment variable > > > > %IGT_CONFIG_PATH. > > > > */ > > > > > > > > +#define SUSPEND_RESUME_DELAY_DEFAULT 20 /* seconds */ > > > > + > > > >struct chamelium_edid { > > > > int id; > > > > struct igt_list link; > > > > @@ -100,6 +107,7 @@ struct chamelium { > > > > xmlrpc_env env; > > > > xmlrpc_client *client; > > > > char *url; > > > > + int suspend_resume_delay; > > > > > > > > /* Indicates the last port to have been used for capturing > > > > video > > > > */ > > > > struct chamelium_port *capturing_port; > > > > @@ -114,6 +122,20 @@ struct chamelium { > > > >static struct chamelium *cleanup_instance; > > > > > > Why do you make this part of the chamelium configuration? This should be > > > common to all the suspend tests. > > > > Fair enough, but at this point, only lib/igt_chamelium.c is using igtrc and > > all > > the parsing is implemented there. > > > > So one course of action here would be to move igtrc parsing outside of > > igt_chamelium (maybe to igt_core?) and use some global variable for storing > > this > > value. What do you think? > > > > That seems like a plan, except you can just call a function that will do > the parsing for you and return a structure with all the parameters. If > it is called a second time, just return the cached value. Thinking about it twice, I think it would make a lot more sense to delegate (at least some of) the parsing to specific parts of the code. For instance for chamelium, the data structures are really only defined in igt_chamelium and I don't think it would make a lot of sense to make those common just for the sake of returning a common configuration structure. We could also have some intermediate representation of that data for that structure, which isn't very straightforward either. So I would suggest making GKeyFile *igt_key_file; a global (instead of the parsed parameters) so that specific parts of IGT can use it to get the keys they want. Then, having a common parsing function for common things (suspend/resume delay would fit well there). Also, we already have igt_set_autoresume_delay so no extra global variable would be needed for that (or rather, it already exists). Does that seem agreeable? -- Paul Kocialkowski Intel Finland Oy - BIC 0357606-4 - Westendinkatu 7, 02160 Espoo ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH i-g-t 4/7] lib/igt_chamelium: Add support for configurable DUT suspend/resume delay
On Tue, 2017-06-27 at 10:33 +0300, Paul Kocialkowski wrote: > On Mon, 2017-06-26 at 18:15 +0300, Martin Peres wrote: > > On 26/06/17 17:33, Paul Kocialkowski wrote: > > > On Mon, 2017-06-26 at 17:25 +0300, Martin Peres wrote: > > > > On 26/06/17 16:59, Paul Kocialkowski wrote: > > > > > This adds support for reading a SuspendResumeDelay property (under > > > > > [DUT]) in the IGT configuration (igtrc) and exposing it through a > > > > > chamelium_get_suspend_resume_delay function. > > > > > > > > > > Signed-off-by: Paul Kocialkowski > > > > > --- > > > > >lib/igt_chamelium.c | 31 ++- > > > > >lib/igt_chamelium.h | 1 + > > > > >2 files changed, 31 insertions(+), 1 deletion(-) > > > > > > > > > > diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c > > > > > index 225f98c3..a1aaf405 100644 > > > > > --- a/lib/igt_chamelium.c > > > > > +++ b/lib/igt_chamelium.c > > > > > @@ -58,7 +58,7 @@ > > > > > * [Chamelium] > > > > > * URL=http://chameleon:9992 # The URL used for connecting > > > > > to > > > > > the > > > > > Chamelium's RPC server > > > > > * > > > > > - * # The rest of the sections are used for defining connector > > > > > mappings. > > > > > + * # The following sections are used for defining connector > > > > > mappings. > > > > > * # This is required so any tests using the Chamelium know > > > > > which > > > > > connector > > > > > * # on the test machine should be connected to each > > > > > Chamelium > > > > > port. > > > > > * # > > > > > @@ -70,12 +70,19 @@ > > > > > * > > > > > * [Chamelium:HDMI-A-1] > > > > > * ChameliumPortID=3 > > > > > + * > > > > > + * # The following section is used for configuring the Device > > > > > Under > > > > > Test. > > > > > + * # It is not mandatory and allows overriding default values. > > > > > + * [DUT] > > > > > + * SuspendResumeDelay=10 > > > > > * ]| > > > > > * > > > > > * By default, this file is expected to exist in ~/.igtrc . The > > > > > directory > > > > > for > > > > > * this can be overriden by setting the environment variable > > > > > %IGT_CONFIG_PATH. > > > > > */ > > > > > > > > > > +#define SUSPEND_RESUME_DELAY_DEFAULT 20 /* seconds */ > > > > > + > > > > >struct chamelium_edid { > > > > > int id; > > > > > struct igt_list link; > > > > > @@ -100,6 +107,7 @@ struct chamelium { > > > > > xmlrpc_env env; > > > > > xmlrpc_client *client; > > > > > char *url; > > > > > + int suspend_resume_delay; > > > > > > > > > > /* Indicates the last port to have been used for capturing > > > > > video > > > > > */ > > > > > struct chamelium_port *capturing_port; > > > > > @@ -114,6 +122,20 @@ struct chamelium { > > > > >static struct chamelium *cleanup_instance; > > > > > > > > Why do you make this part of the chamelium configuration? This should be > > > > common to all the suspend tests. > > > > > > Fair enough, but at this point, only lib/igt_chamelium.c is using igtrc > > > and > > > all > > > the parsing is implemented there. > > > > > > So one course of action here would be to move igtrc parsing outside of > > > igt_chamelium (maybe to igt_core?) and use some global variable for > > > storing > > > this > > > value. What do you think? > > > > > > > That seems like a plan, except you can just call a function that will do > > the parsing for you and return a structure with all the parameters. If > > it is called a second time, just return the cached value. > > Thinking about it twice, I think it would make a lot more sense to delegate > (at > least some of) the parsing to specific parts of the code. For instance for > chamelium, the data structures are really only defined in igt_chamelium and I > don't think it would make a lot of sense to make those common just for the > sake > of returning a common configuration structure. We could also have some > intermediate representation of that data for that structure, which isn't very > straightforward either. > > So I would suggest making GKeyFile *igt_key_file; a global (instead of the > parsed parameters) so that specific parts of IGT can use it to get the keys > they > want. > > Then, having a common parsing function for common things (suspend/resume delay > would fit well there). Also, we already have igt_set_autoresume_delay so no > extra global variable would be needed for that (or rather, it already exists). > > Does that seem agreeable? By the way, I suggest sending this as a follow-up patch, since moving the config out of IGT is a separate topic in itself. Would that make sense? -- Paul Kocialkowski Intel Finland Oy - BIC 0357606-4 - Westendinkatu 7, 02160 Espoo ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH i-g-t 4/7] lib/igt_chamelium: Add support for configurable DUT suspend/resume delay
On Tue, 2017-06-27 at 10:45 +0300, Paul Kocialkowski wrote: > On Tue, 2017-06-27 at 10:33 +0300, Paul Kocialkowski wrote: > > On Mon, 2017-06-26 at 18:15 +0300, Martin Peres wrote: > > > On 26/06/17 17:33, Paul Kocialkowski wrote: > > > > On Mon, 2017-06-26 at 17:25 +0300, Martin Peres wrote: > > > > > On 26/06/17 16:59, Paul Kocialkowski wrote: > > > > > > This adds support for reading a SuspendResumeDelay property (under > > > > > > [DUT]) in the IGT configuration (igtrc) and exposing it through a > > > > > > chamelium_get_suspend_resume_delay function. > > > > > > > > > > > > Signed-off-by: Paul Kocialkowski > > > > > > --- > > > > > >lib/igt_chamelium.c | 31 ++- > > > > > >lib/igt_chamelium.h | 1 + > > > > > >2 files changed, 31 insertions(+), 1 deletion(-) > > > > > > > > > > > > diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c > > > > > > index 225f98c3..a1aaf405 100644 > > > > > > --- a/lib/igt_chamelium.c > > > > > > +++ b/lib/igt_chamelium.c > > > > > > @@ -58,7 +58,7 @@ > > > > > > * [Chamelium] > > > > > > * URL=http://chameleon:9992 # The URL used for connecting > > > > > > to > > > > > > the > > > > > > Chamelium's RPC server > > > > > > * > > > > > > - * # The rest of the sections are used for defining > > > > > > connector > > > > > > mappings. > > > > > > + * # The following sections are used for defining connector > > > > > > mappings. > > > > > > * # This is required so any tests using the Chamelium > > > > > > know > > > > > > which > > > > > > connector > > > > > > * # on the test machine should be connected to each > > > > > > Chamelium > > > > > > port. > > > > > > * # > > > > > > @@ -70,12 +70,19 @@ > > > > > > * > > > > > > * [Chamelium:HDMI-A-1] > > > > > > * ChameliumPortID=3 > > > > > > + * > > > > > > + * # The following section is used for configuring the > > > > > > Device > > > > > > Under > > > > > > Test. > > > > > > + * # It is not mandatory and allows overriding default > > > > > > values. > > > > > > + * [DUT] > > > > > > + * SuspendResumeDelay=10 > > > > > > * ]| > > > > > > * > > > > > > * By default, this file is expected to exist in ~/.igtrc . The > > > > > > directory > > > > > > for > > > > > > * this can be overriden by setting the environment variable > > > > > > %IGT_CONFIG_PATH. > > > > > > */ > > > > > > > > > > > > +#define SUSPEND_RESUME_DELAY_DEFAULT 20 /* seconds */ > > > > > > + > > > > > >struct chamelium_edid { > > > > > > int id; > > > > > > struct igt_list link; > > > > > > @@ -100,6 +107,7 @@ struct chamelium { > > > > > > xmlrpc_env env; > > > > > > xmlrpc_client *client; > > > > > > char *url; > > > > > > + int suspend_resume_delay; > > > > > > > > > > > > /* Indicates the last port to have been used for > > > > > > capturing > > > > > > video > > > > > > */ > > > > > > struct chamelium_port *capturing_port; > > > > > > @@ -114,6 +122,20 @@ struct chamelium { > > > > > >static struct chamelium *cleanup_instance; > > > > > > > > > > Why do you make this part of the chamelium configuration? This should > > > > > be > > > > > common to all the suspend tests. > > > > > > > > Fair enough, but at this point, only lib/igt_chamelium.c is using igtrc > > > > and > > > > all > > > > the parsing is implemented there. > > > > > > > > So one course of action here would
[Intel-gfx] [PATCH i-g-t v2 1/7] lib/igt_aux: Use provided autoresume delay for rtc wake
This stores the autoresume delay provided via igt_set_autoresume_delay for use during suspend via rtc wake scheduling. This delay was previously only used for pm_test suspendm while the function suggests it should be applied to all autoresume cases. There is also definitely a use case for configuring the rtc wake delay, so this implements it. Signed-off-by: Paul Kocialkowski --- lib/igt_aux.c | 9 - 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/igt_aux.c b/lib/igt_aux.c index eb563f72..882dba06 100644 --- a/lib/igt_aux.c +++ b/lib/igt_aux.c @@ -680,6 +680,8 @@ void igt_cleanup_aperture_trashers(void) free(trash_bos); } +static int autoresume_delay; + static const char *suspend_state_name[] = { [SUSPEND_STATE_FREEZE] = "freeze", [SUSPEND_STATE_STANDBY] = "standby", @@ -746,7 +748,10 @@ static void suspend_via_rtcwake(enum igt_suspend_state state) igt_assert(state < SUSPEND_STATE_NUM); - delay = state == SUSPEND_STATE_DISK ? 30 : 15; + if (autoresume_delay) + delay = autoresume_delay; + else + delay = state == SUSPEND_STATE_DISK ? 30 : 15; /* * Skip if rtcwake would fail for a reason not related to the kernel's @@ -889,6 +894,8 @@ void igt_set_autoresume_delay(int delay_secs) igt_require(write(delay_fd, delay_str, strlen(delay_str))); close(delay_fd); + + autoresume_delay = delay_secs; } /** -- 2.13.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH i-g-t v2 4/7] tests/chamelium: Reduce the simple hotplug test toggle count for VGA
Since VGA hpd detection is done through RGB lines load detection and nowadays often goes through a bridge to some digital interface, HPD detection usually takes a while (up to a couple seconds). Thus, it is not as relevant to stress it as many as 15 times. This brings the toggle count down to 5 times, which makes the test run a lot faster without really changing the outcome much. Signed-off-by: Paul Kocialkowski --- tests/chamelium.c | 15 ++- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/tests/chamelium.c b/tests/chamelium.c index 835c3282..b412c6a7 100644 --- a/tests/chamelium.c +++ b/tests/chamelium.c @@ -47,6 +47,9 @@ typedef struct { #define HPD_STORM_PULSE_INTERVAL_DP 100 /* ms */ #define HPD_STORM_PULSE_INTERVAL_HDMI 200 /* ms */ +#define HPD_TOGGLE_COUNT_VGA 5 +#define HPD_TOGGLE_COUNT_DP_HDMI 15 + /* Pre-calculated CRCs for the pattern fb, for all the modes in the default * chamelium edid */ @@ -158,7 +161,7 @@ reset_state(data_t *data, struct chamelium_port *port) } static void -test_basic_hotplug(data_t *data, struct chamelium_port *port) +test_basic_hotplug(data_t *data, struct chamelium_port *port, int toggle_count) { struct udev_monitor *mon = igt_watch_hotplug(); int i; @@ -166,7 +169,7 @@ test_basic_hotplug(data_t *data, struct chamelium_port *port) reset_state(data, NULL); igt_hpd_storm_set_threshold(data->drm_fd, 0); - for (i = 0; i < 15; i++) { + for (i = 0; i < toggle_count; i++) { igt_flush_hotplugs(mon); /* Check if we get a sysfs hotplug event */ @@ -680,7 +683,8 @@ igt_main } connector_subtest("dp-hpd", DisplayPort) - test_basic_hotplug(&data, port); + test_basic_hotplug(&data, port, + HPD_TOGGLE_COUNT_DP_HDMI); connector_subtest("dp-edid-read", DisplayPort) { test_edid_read(&data, port, edid_id, @@ -736,7 +740,8 @@ igt_main } connector_subtest("hdmi-hpd", HDMIA) - test_basic_hotplug(&data, port); + test_basic_hotplug(&data, port, + HPD_TOGGLE_COUNT_DP_HDMI); connector_subtest("hdmi-edid-read", HDMIA) { test_edid_read(&data, port, edid_id, @@ -792,7 +797,7 @@ igt_main } connector_subtest("vga-hpd", VGA) - test_basic_hotplug(&data, port); + test_basic_hotplug(&data, port, HPD_TOGGLE_COUNT_VGA); connector_subtest("vga-edid-read", VGA) { test_edid_read(&data, port, edid_id, -- 2.13.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH i-g-t v2 2/7] chamelium: Add support for HPD toggle scheduling instead of async pulses
This adds support for the newly-introduced ScheduleHpdToggle XMLRPC method of the Chamelium's interface and makes use of it instead of starting pulses with an asynchronous call, suspending and dealing with the result at resume. The XMLRPC library does not guarantee that the call will be made before caring for its outcome and this is in fact what was happening: the call was being delayed until resume time, as can be seen from the Chamelium's logs. The quite generous timeout for HPD event detection would then catch the toggle, that was sent after resume. This is especially useful for testing HPD during suspend/resume. Signed-off-by: Paul Kocialkowski --- lib/igt_chamelium.c | 78 ++--- lib/igt_chamelium.h | 7 +++-- tests/chamelium.c | 13 + 3 files changed, 23 insertions(+), 75 deletions(-) diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c index 4a2af796..225f98c3 100644 --- a/lib/igt_chamelium.c +++ b/lib/igt_chamelium.c @@ -447,76 +447,26 @@ void chamelium_fire_mixed_hpd_pulses(struct chamelium *chamelium, xmlrpc_DECREF(pulse_widths); } -static void async_rpc_handler(const char *server_url, const char *method_name, - xmlrpc_value *param_array, void *user_data, - xmlrpc_env *fault, xmlrpc_value *result) -{ - /* We don't care about the responses */ -} - /** - * chamelium_async_hpd_pulse_start: + * chamelium_schedule_hpd_toggle: * @chamelium: The Chamelium instance to use * @port: The port to fire the HPD pulses on - * @high: Whether to fire a high pulse (e.g. simulate a connect), or a low - * pulse (e.g. simulate a disconnect) - * @delay_secs: How long to wait before sending the HPD pulse. - * - * Instructs the chamelium to send an hpd pulse after @delay_secs seconds have - * passed, without waiting for the chamelium to finish. This is useful for - * testing things such as hpd after a suspend/resume cycle, since we can't tell - * the chamelium to send a hotplug at the same time that our system is - * suspended. - * - * It is required that the user eventually call - * #chamelium_async_hpd_pulse_finish, to clean up the leftover XML-RPC - * responses from the chamelium. - */ -void chamelium_async_hpd_pulse_start(struct chamelium *chamelium, -struct chamelium_port *port, -bool high, int delay_secs) -{ - xmlrpc_value *pulse_widths = xmlrpc_array_new(&chamelium->env), *width; - - /* TODO: Actually implement something in the chameleon server to allow -* for delayed actions such as hotplugs. This would work a bit better -* and allow us to test suspend/resume on ports without hpd like VGA -*/ - - igt_debug("Sending HPD pulse (%s) on %s with %d second delay\n", - high ? "high->low" : "low->high", port->name, delay_secs); - - /* If we're starting at high, make the first pulse width 0 so we keep -* the port connected */ - if (high) { - width = xmlrpc_int_new(&chamelium->env, 0); - xmlrpc_array_append_item(&chamelium->env, pulse_widths, width); - xmlrpc_DECREF(width); - } - - width = xmlrpc_int_new(&chamelium->env, delay_secs * 1000); - xmlrpc_array_append_item(&chamelium->env, pulse_widths, width); - xmlrpc_DECREF(width); - - xmlrpc_client_start_rpcf(&chamelium->env, chamelium->client, -chamelium->url, -"FireMixedHpdPulses", async_rpc_handler, NULL, -"(iA)", port->id, pulse_widths); - xmlrpc_DECREF(pulse_widths); -} - -/** - * chamelium_async_hpd_pulse_finish: - * @chamelium: The Chamelium instance to use + * @delay_ms: Delay in milli-second before the toggle takes place + * @rising_edge: Whether the toggle should be a rising edge or a falling edge * - * Waits for any asynchronous RPC started by #chamelium_async_hpd_pulse_start - * to complete, and then cleans up any leftover responses from the chamelium. - * If all of the RPC calls have already completed, this function returns - * immediately. + * Instructs the chamelium to schedule an hpd toggle (either a rising edge or + * a falling edge, depending on @rising_edg) after @delay_ms have passed. + * This is useful for testing things such as hpd after a suspend/resume cycle. */ -void chamelium_async_hpd_pulse_finish(struct chamelium *chamelium) +void chamelium_schedule_hpd_toggle(struct chamelium *chamelium, + struct chamelium_port *port, int delay_ms, + bool rising_edge) { - xmlrpc_client_event_loop_finish(chamelium->client); + igt_debug("Scheduling H
[Intel-gfx] [PATCH i-g-t v2 6/7] tests/chamelium: Disconnect connectors without extra reset
This removes the reset call from the reset_state function and renames it to disconnect_connector. Since a call to reset is already done in chamelium_init, there is no need to do an extra reset in each test. This allows reducing the execution time a bit. Signed-off-by: Paul Kocialkowski --- tests/chamelium.c | 22 +++--- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/chamelium.c b/tests/chamelium.c index 346018a5..41e0e89b 100644 --- a/tests/chamelium.c +++ b/tests/chamelium.c @@ -145,17 +145,17 @@ wait_for_connector(data_t *data, struct chamelium_port *port, } static void -reset_state(data_t *data, struct chamelium_port *port) +disconnect_connector(data_t *data, struct chamelium_port *port) { int p; - chamelium_reset(data->chamelium); - if (port) { + chamelium_unplug(data->chamelium, port); wait_for_connector(data, port, DRM_MODE_DISCONNECTED, false); } else { for (p = 0; p < data->port_count; p++) { port = data->ports[p]; + chamelium_unplug(data->chamelium, port); wait_for_connector(data, port, DRM_MODE_DISCONNECTED, false); } @@ -168,7 +168,7 @@ test_basic_hotplug(data_t *data, struct chamelium_port *port, int toggle_count) struct udev_monitor *mon = igt_watch_hotplug(); int i; - reset_state(data, NULL); + disconnect_connector(data, NULL); igt_hpd_storm_set_threshold(data->drm_fd, 0); for (i = 0; i < toggle_count; i++) { @@ -202,7 +202,7 @@ test_edid_read(data_t *data, struct chamelium_port *port, data->chamelium, port, false); uint64_t edid_blob_id; - reset_state(data, port); + disconnect_connector(data, port); chamelium_port_set_edid(data->chamelium, port, edid_id); chamelium_plug(data->chamelium, port); @@ -270,7 +270,7 @@ test_suspend_resume_hpd(data_t *data, struct chamelium_port *port, { struct udev_monitor *mon = igt_watch_hotplug(); - reset_state(data, port); + disconnect_connector(data, port); /* Make sure we notice new connectors after resuming */ try_suspend_resume_hpd(data, port, state, test, mon, false); @@ -294,7 +294,7 @@ test_suspend_resume_hpd_common(data_t *data, enum igt_suspend_state state, igt_debug("Testing port %s\n", chamelium_port_get_name(port)); } - reset_state(data, NULL); + disconnect_connector(data, NULL); /* Make sure we notice new connectors after resuming */ try_suspend_resume_hpd(data, NULL, state, test, mon, false); @@ -314,7 +314,7 @@ test_suspend_resume_edid_change(data_t *data, struct chamelium_port *port, { struct udev_monitor *mon = igt_watch_hotplug(); - reset_state(data, port); + disconnect_connector(data, port); /* First plug in the port */ chamelium_port_set_edid(data->chamelium, port, edid_id); @@ -582,7 +582,7 @@ test_hpd_without_ddc(data_t *data, struct chamelium_port *port) { struct udev_monitor *mon = igt_watch_hotplug(); - reset_state(data, port); + disconnect_connector(data, port); igt_flush_hotplugs(mon); /* Disable the DDC on the connector and make sure we still get a @@ -604,7 +604,7 @@ test_hpd_storm_detect(data_t *data, struct chamelium_port *port, int width) int count = 0; igt_require_hpd_storm_ctl(data->drm_fd); - reset_state(data, port); + disconnect_connector(data, port); igt_hpd_storm_set_threshold(data->drm_fd, 1); chamelium_fire_hpd_pulses(data->chamelium, port, width, 10); @@ -629,7 +629,7 @@ static void test_hpd_storm_disable(data_t *data, struct chamelium_port *port, int width) { igt_require_hpd_storm_ctl(data->drm_fd); - reset_state(data, port); + disconnect_connector(data, port); igt_hpd_storm_set_threshold(data->drm_fd, 0); chamelium_fire_hpd_pulses(data->chamelium, port, -- 2.13.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH i-g-t v2 7/7] Make igtrc configuration common, with configurable suspend/resume delay
This adds support for configurable suspend/resume delay and takes the occasion to move igtrc configuation from igt_chamelium to igt_core. This way, suspend/resume delay configuration can be used for all tests. Signed-off-by: Paul Kocialkowski --- lib/Makefile.am | 2 ++ lib/igt_aux.c | 27 ++ lib/igt_aux.h | 1 + lib/igt_chamelium.c | 49 +--- lib/igt_core.c | 64 + lib/igt_core.h | 2 ++ tests/Makefile.am | 4 ++-- tests/chamelium.c | 11 + tools/Makefile.am | 4 ++-- 9 files changed, 112 insertions(+), 52 deletions(-) diff --git a/lib/Makefile.am b/lib/Makefile.am index 91e72c44..d4f41128 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -41,6 +41,7 @@ AM_CFLAGS = \ $(XMLRPC_CFLAGS) \ $(LIBUDEV_CFLAGS) \ $(PIXMAN_CFLAGS) \ + $(GLIB_CFLAGS) \ $(VALGRIND_CFLAGS) \ -DIGT_SRCDIR=\""$(abs_top_srcdir)/tests"\" \ -DIGT_DATADIR=\""$(pkgdatadir)"\" \ @@ -61,5 +62,6 @@ libintel_tools_la_LIBADD = \ $(XMLRPC_LIBS) \ $(LIBUDEV_LIBS) \ $(PIXMAN_LIBS) \ + $(GLIB_LIBS) \ -lm diff --git a/lib/igt_aux.c b/lib/igt_aux.c index 882dba06..86a213c2 100644 --- a/lib/igt_aux.c +++ b/lib/igt_aux.c @@ -748,10 +748,7 @@ static void suspend_via_rtcwake(enum igt_suspend_state state) igt_assert(state < SUSPEND_STATE_NUM); - if (autoresume_delay) - delay = autoresume_delay; - else - delay = state == SUSPEND_STATE_DISK ? 30 : 15; + delay = igt_get_autoresume_delay(state); /* * Skip if rtcwake would fail for a reason not related to the kernel's @@ -899,6 +896,28 @@ void igt_set_autoresume_delay(int delay_secs) } /** + * igt_get_autoresume_delay: + * @state: an #igt_suspend_state, the target suspend state + * + * Retrieves how long we wait to resume the system after suspending it. + * This can either be set through igt_set_autoresume_delay or be a default + * value that depends on the suspend state. + * + * Returns: The autoresume delay, in seconds. + */ +int igt_get_autoresume_delay(enum igt_suspend_state state) +{ + int delay; + + if (autoresume_delay) + delay = autoresume_delay; + else + delay = state == SUSPEND_STATE_DISK ? 30 : 15; + + return delay; +} + +/** * igt_drop_root: * * Drop root privileges and make sure it actually worked. Useful for tests diff --git a/lib/igt_aux.h b/lib/igt_aux.h index 54b97164..499a1679 100644 --- a/lib/igt_aux.h +++ b/lib/igt_aux.h @@ -192,6 +192,7 @@ enum igt_suspend_test { void igt_system_suspend_autoresume(enum igt_suspend_state state, enum igt_suspend_test test); void igt_set_autoresume_delay(int delay_secs); +int igt_get_autoresume_delay(enum igt_suspend_state state); /* dropping priviledges */ void igt_drop_root(void); diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c index 225f98c3..345c44d6 100644 --- a/lib/igt_chamelium.c +++ b/lib/igt_chamelium.c @@ -51,8 +51,8 @@ * [on the ChromeOS project page](https://www.chromium.org/chromium-os/testing/chamelium). * * In order to run tests using the Chamelium, a valid configuration file must be - * present. The configuration file is a normal Glib keyfile (similar to Windows - * INI) structured like so: + * present. It must contain Chamelium-specific keys as shown with the following + * example: * * |[ * [Chamelium] @@ -72,8 +72,6 @@ * ChameliumPortID=3 * ]| * - * By default, this file is expected to exist in ~/.igtrc . The directory for - * this can be overriden by setting the environment variable %IGT_CONFIG_PATH. */ struct chamelium_edid { @@ -1034,7 +1032,7 @@ static unsigned int chamelium_get_port_type(struct chamelium *chamelium, } static bool chamelium_read_port_mappings(struct chamelium *chamelium, -int drm_fd, GKeyFile *key_file) +int drm_fd) { drmModeRes *res; drmModeConnector *connector; @@ -1045,7 +1043,7 @@ static bool chamelium_read_port_mappings(struct chamelium *chamelium, int port_i, i, j; bool ret = true; - group_list = g_key_file_get_groups(key_file, NULL); + group_list = g_key_file_get_groups(igt_key_file, NULL); /* Count how many connector mappings are specified in the config */ for (i = 0; group_list[i] != NULL; i++) { @@ -1068,7 +1066,7 @@ static bool chamelium_read_port_mappings(struct chamelium *chamelium, port = &chamelium->ports[port_i++]; port->name = strdup(map_name); - port->id = g_key_file_get_integer(key_file, group, +
[Intel-gfx] [PATCH i-g-t v2 5/7] tests/chamelium: Update connector state without reprobe when possible
This renames the reprobe_connector function to update_connector and ensures that full reprobe of the connector is only done when really necessary (e.g. when changing the EDID). A full reprobe takes time and is not required for updating the connector state. Thus, this allows executing tests faster. Signed-off-by: Paul Kocialkowski --- tests/chamelium.c | 34 ++ 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/tests/chamelium.c b/tests/chamelium.c index b412c6a7..346018a5 100644 --- a/tests/chamelium.c +++ b/tests/chamelium.c @@ -103,13 +103,14 @@ require_connector_present(data_t *data, unsigned int type) } static drmModeConnection -reprobe_connector(data_t *data, struct chamelium_port *port) +update_connector(data_t *data, struct chamelium_port *port, bool reprobe) { drmModeConnector *connector; drmModeConnection status; - igt_debug("Reprobing %s...\n", chamelium_port_get_name(port)); - connector = chamelium_port_get_connector(data->chamelium, port, true); + igt_debug("Updating %s...\n", chamelium_port_get_name(port)); + connector = chamelium_port_get_connector(data->chamelium, port, +reprobe); igt_assert(connector); status = connector->connection; @@ -119,7 +120,7 @@ reprobe_connector(data_t *data, struct chamelium_port *port) static void wait_for_connector(data_t *data, struct chamelium_port *port, - drmModeConnection status) + drmModeConnection status, bool reprobe) { bool finished = false; @@ -132,7 +133,7 @@ wait_for_connector(data_t *data, struct chamelium_port *port, * that hpd events work in the event that hpd doesn't work on the system */ igt_until_timeout(HOTPLUG_TIMEOUT) { - if (reprobe_connector(data, port) == status) { + if (update_connector(data, port, reprobe) == status) { finished = true; return; } @@ -151,11 +152,12 @@ reset_state(data_t *data, struct chamelium_port *port) chamelium_reset(data->chamelium); if (port) { - wait_for_connector(data, port, DRM_MODE_DISCONNECTED); + wait_for_connector(data, port, DRM_MODE_DISCONNECTED, false); } else { for (p = 0; p < data->port_count; p++) { port = data->ports[p]; - wait_for_connector(data, port, DRM_MODE_DISCONNECTED); + wait_for_connector(data, port, DRM_MODE_DISCONNECTED, + false); } } } @@ -175,7 +177,7 @@ test_basic_hotplug(data_t *data, struct chamelium_port *port, int toggle_count) /* Check if we get a sysfs hotplug event */ chamelium_plug(data->chamelium, port); igt_assert(igt_hotplug_detected(mon, HOTPLUG_TIMEOUT)); - igt_assert_eq(reprobe_connector(data, port), + igt_assert_eq(update_connector(data, port, false), DRM_MODE_CONNECTED); igt_flush_hotplugs(mon); @@ -183,7 +185,7 @@ test_basic_hotplug(data_t *data, struct chamelium_port *port, int toggle_count) /* Now check if we get a hotplug from disconnection */ chamelium_unplug(data->chamelium, port); igt_assert(igt_hotplug_detected(mon, HOTPLUG_TIMEOUT)); - igt_assert_eq(reprobe_connector(data, port), + igt_assert_eq(update_connector(data, port, false), DRM_MODE_DISCONNECTED); } @@ -204,7 +206,7 @@ test_edid_read(data_t *data, struct chamelium_port *port, chamelium_port_set_edid(data->chamelium, port, edid_id); chamelium_plug(data->chamelium, port); - wait_for_connector(data, port, DRM_MODE_CONNECTED); + wait_for_connector(data, port, DRM_MODE_CONNECTED, true); igt_assert(kmstest_get_property(data->drm_fd, connector->connector_id, DRM_MODE_OBJECT_CONNECTOR, "EDID", NULL, @@ -247,13 +249,13 @@ try_suspend_resume_hpd(data_t *data, struct chamelium_port *port, igt_assert(igt_hotplug_detected(mon, HOTPLUG_TIMEOUT)); if (port) { - igt_assert_eq(reprobe_connector(data, port), connected ? + igt_assert_eq(update_connector(data, port, false), connected ? DRM_MODE_DISCONNECTED : DRM_MODE_CONNECTED); } else { for (p = 0; p < data->port_count; p++) { port = data->ports[p]; - igt_assert_eq(reprobe_connector(data, port), connected ? - DRM_MODE_DISCONNECTED : + igt_assert_eq(u
[Intel-gfx] [PATCH i-g-t v2 3/7] tests/chamelium: Add VGA HPD toggle tests after suspend and hibernate
This adds HPD toggle after suspend and hibernate testing for VGA, in the same fashion as currently done for DP and HDMI and includes VGA in the common suspend and hibernate test. Signed-off-by: Paul Kocialkowski --- tests/chamelium.c | 22 +- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/tests/chamelium.c b/tests/chamelium.c index 04e7e379..835c3282 100644 --- a/tests/chamelium.c +++ b/tests/chamelium.c @@ -232,9 +232,6 @@ try_suspend_resume_hpd(data_t *data, struct chamelium_port *port, } else { for (p = 0; p < data->port_count; p++) { port = data->ports[p]; - if (chamelium_port_get_type(port) == DRM_MODE_CONNECTOR_VGA) - continue; - chamelium_schedule_hpd_toggle(data->chamelium, port, SUSPEND_RESUME_DELAY * 1000 / 2, !connected); @@ -252,9 +249,6 @@ try_suspend_resume_hpd(data_t *data, struct chamelium_port *port, } else { for (p = 0; p < data->port_count; p++) { port = data->ports[p]; - if (chamelium_port_get_type(port) == DRM_MODE_CONNECTOR_VGA) - continue; - igt_assert_eq(reprobe_connector(data, port), connected ? DRM_MODE_DISCONNECTED : DRM_MODE_CONNECTED); @@ -292,9 +286,6 @@ test_suspend_resume_hpd_common(data_t *data, enum igt_suspend_state state, for (p = 0; p < data->port_count; p++) { port = data->ports[p]; - if (chamelium_port_get_type(port) == DRM_MODE_CONNECTOR_VGA) - continue; - igt_debug("Testing port %s\n", chamelium_port_get_name(port)); } @@ -810,10 +801,15 @@ igt_main igt_kms_get_alt_edid()); } - /* FIXME: Right now there isn't a way to do any sort of delayed -* psuedo-hotplug with VGA, so testing detection after a -* suspend/resume cycle isn't possible yet -*/ + connector_subtest("vga-hpd-after-suspend", VGA) + test_suspend_resume_hpd(&data, port, + SUSPEND_STATE_MEM, + SUSPEND_TEST_NONE); + + connector_subtest("vga-hpd-after-hibernate", VGA) + test_suspend_resume_hpd(&data, port, + SUSPEND_STATE_DISK, + SUSPEND_TEST_DEVICES); connector_subtest("vga-hpd-without-ddc", VGA) test_hpd_without_ddc(&data, port); -- 2.13.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH i-g-t v2 7/7] Make igtrc configuration common, with configurable suspend/resume delay
On Tue, 2017-06-27 at 17:11 -0400, Lyude Paul wrote: > > > On Tue, 2017-06-27 at 13:53 +0300, Paul Kocialkowski wrote: > > This adds support for configurable suspend/resume delay and takes the > > occasion to move igtrc configuation from igt_chamelium to igt_core. > > This way, suspend/resume delay configuration can be used for all > > tests. > > > > Signed-off-by: Paul Kocialkowski > > --- > > lib/Makefile.am | 2 ++ > > lib/igt_aux.c | 27 ++ > > lib/igt_aux.h | 1 + > > lib/igt_chamelium.c | 49 +--- > > lib/igt_core.c | 64 > > + > > lib/igt_core.h | 2 ++ > > tests/Makefile.am | 4 ++-- > > tests/chamelium.c | 11 + > > tools/Makefile.am | 4 ++-- > > 9 files changed, 112 insertions(+), 52 deletions(-) > > > > diff --git a/lib/Makefile.am b/lib/Makefile.am > > index 91e72c44..d4f41128 100644 > > --- a/lib/Makefile.am > > +++ b/lib/Makefile.am > > @@ -41,6 +41,7 @@ AM_CFLAGS = \ > > $(XMLRPC_CFLAGS) \ > > $(LIBUDEV_CFLAGS) \ > > $(PIXMAN_CFLAGS) \ > > + $(GLIB_CFLAGS) \ > > $(VALGRIND_CFLAGS) \ > > -DIGT_SRCDIR=\""$(abs_top_srcdir)/tests"\" \ > > -DIGT_DATADIR=\""$(pkgdatadir)"\" \ > > @@ -61,5 +62,6 @@ libintel_tools_la_LIBADD = \ > > $(XMLRPC_LIBS) \ > > $(LIBUDEV_LIBS) \ > > $(PIXMAN_LIBS) \ > > + $(GLIB_LIBS) \ > > -lm > > > > diff --git a/lib/igt_aux.c b/lib/igt_aux.c > > index 882dba06..86a213c2 100644 > > --- a/lib/igt_aux.c > > +++ b/lib/igt_aux.c > > @@ -748,10 +748,7 @@ static void suspend_via_rtcwake(enum > > igt_suspend_state state) > > > > igt_assert(state < SUSPEND_STATE_NUM); > > > > - if (autoresume_delay) > > - delay = autoresume_delay; > > - else > > - delay = state == SUSPEND_STATE_DISK ? 30 : 15; > > + delay = igt_get_autoresume_delay(state); > > > > /* > > * Skip if rtcwake would fail for a reason not related to > > the kernel's > > @@ -899,6 +896,28 @@ void igt_set_autoresume_delay(int delay_secs) > > } > > > > /** > > + * igt_get_autoresume_delay: > > + * @state: an #igt_suspend_state, the target suspend state > > + * > > + * Retrieves how long we wait to resume the system after suspending > > it. > > + * This can either be set through igt_set_autoresume_delay or be a > > default > > + * value that depends on the suspend state. > > + * > > + * Returns: The autoresume delay, in seconds. > > + */ > > +int igt_get_autoresume_delay(enum igt_suspend_state state) > > +{ > > + int delay; > > + > > + if (autoresume_delay) > > + delay = autoresume_delay; > > + else > > + delay = state == SUSPEND_STATE_DISK ? 30 : 15; > > + > > + return delay; > > +} > > + > > +/** > > * igt_drop_root: > > * > > * Drop root privileges and make sure it actually worked. Useful for > > tests > > diff --git a/lib/igt_aux.h b/lib/igt_aux.h > > index 54b97164..499a1679 100644 > > --- a/lib/igt_aux.h > > +++ b/lib/igt_aux.h > > @@ -192,6 +192,7 @@ enum igt_suspend_test { > > void igt_system_suspend_autoresume(enum igt_suspend_state state, > >enum igt_suspend_test test); > > void igt_set_autoresume_delay(int delay_secs); > > +int igt_get_autoresume_delay(enum igt_suspend_state state); > > > > /* dropping priviledges */ > > void igt_drop_root(void); > > diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c > > index 225f98c3..345c44d6 100644 > > --- a/lib/igt_chamelium.c > > +++ b/lib/igt_chamelium.c > > @@ -51,8 +51,8 @@ > > * [on the ChromeOS project page](https://www.chromium.org/chromium- > > os/testing/chamelium). > > * > > * In order to run tests using the Chamelium, a valid configuration > > file must be > > - * present. The configuration file is a normal Glib keyfile > > (similar to Windows > > - * INI) structured like so: > > + * present. It must contain Chamelium-specific keys as shown with > > the following > > + * example: > > * > > * |[ > > * [Chamelium] > > @@ -72,8 +72,6 @@ > > * ChameliumPortID=3 > > * ]| > > * > > - * By default, this f
Re: [Intel-gfx] [PATCH i-g-t v2 5/7] tests/chamelium: Update connector state without reprobe when possible
On Tue, 2017-06-27 at 17:26 -0400, Lyude Paul wrote: > I -think- this one might be okay but I just got reminded of a rather > not-obvious part of the DRM spec for hotplugging, and I need to check > that this doesn't actually break that. will get back to you in a bit > with an actual review :) Martin was really expecting this to come around, so I hope it is in accordance with the DRM spec. At least, it works properly with i915 on SKL. Thanks for double-checking! > On Tue, 2017-06-27 at 13:53 +0300, Paul Kocialkowski wrote: > > This renames the reprobe_connector function to update_connector and > > ensures that full reprobe of the connector is only done when really > > necessary (e.g. when changing the EDID). > > > > A full reprobe takes time and is not required for updating the > > connector > > state. Thus, this allows executing tests faster. > > > > Signed-off-by: Paul Kocialkowski > > --- > > tests/chamelium.c | 34 ++ > > 1 file changed, 18 insertions(+), 16 deletions(-) > > > > diff --git a/tests/chamelium.c b/tests/chamelium.c > > index b412c6a7..346018a5 100644 > > --- a/tests/chamelium.c > > +++ b/tests/chamelium.c > > @@ -103,13 +103,14 @@ require_connector_present(data_t *data, > > unsigned int type) > > } > > > > static drmModeConnection > > -reprobe_connector(data_t *data, struct chamelium_port *port) > > +update_connector(data_t *data, struct chamelium_port *port, bool > > reprobe) > > { > > drmModeConnector *connector; > > drmModeConnection status; > > > > - igt_debug("Reprobing %s...\n", > > chamelium_port_get_name(port)); > > - connector = chamelium_port_get_connector(data->chamelium, > > port, true); > > + igt_debug("Updating %s...\n", > > chamelium_port_get_name(port)); > > + connector = chamelium_port_get_connector(data->chamelium, > > port, > > +reprobe); > > igt_assert(connector); > > status = connector->connection; > > > > @@ -119,7 +120,7 @@ reprobe_connector(data_t *data, struct > > chamelium_port *port) > > > > static void > > wait_for_connector(data_t *data, struct chamelium_port *port, > > - drmModeConnection status) > > + drmModeConnection status, bool reprobe) > > { > > bool finished = false; > > > > @@ -132,7 +133,7 @@ wait_for_connector(data_t *data, struct > > chamelium_port *port, > > * that hpd events work in the event that hpd doesn't work > > on the system > > */ > > igt_until_timeout(HOTPLUG_TIMEOUT) { > > - if (reprobe_connector(data, port) == status) { > > + if (update_connector(data, port, reprobe) == status) > > { > > finished = true; > > return; > > } > > @@ -151,11 +152,12 @@ reset_state(data_t *data, struct chamelium_port > > *port) > > chamelium_reset(data->chamelium); > > > > if (port) { > > - wait_for_connector(data, port, > > DRM_MODE_DISCONNECTED); > > + wait_for_connector(data, port, > > DRM_MODE_DISCONNECTED, false); > > } else { > > for (p = 0; p < data->port_count; p++) { > > port = data->ports[p]; > > - wait_for_connector(data, port, > > DRM_MODE_DISCONNECTED); > > + wait_for_connector(data, port, > > DRM_MODE_DISCONNECTED, > > + false); > > } > > } > > } > > @@ -175,7 +177,7 @@ test_basic_hotplug(data_t *data, struct > > chamelium_port *port, int toggle_count) > > /* Check if we get a sysfs hotplug event */ > > chamelium_plug(data->chamelium, port); > > igt_assert(igt_hotplug_detected(mon, > > HOTPLUG_TIMEOUT)); > > - igt_assert_eq(reprobe_connector(data, port), > > + igt_assert_eq(update_connector(data, port, false), > > DRM_MODE_CONNECTED); > > > > igt_flush_hotplugs(mon); > > @@ -183,7 +185,7 @@ test_basic_hotplug(data_t *data, struct > > chamelium_port *port, int toggle_count) > > /* Now check if we get a hotplug from disconnection > > */ > > chamelium_unplug(data->chamelium, port); > > igt_assert(igt_hotplug_detected(mon, > > HOTPLUG_TIMEOUT)); > > -
Re: [Intel-gfx] [PATCH i-g-t v2 6/7] tests/chamelium: Disconnect connectors without extra reset
On Tue, 2017-06-27 at 17:21 -0400, Lyude Paul wrote: > NAK, I'd rather just go with the idea you had with removing the > connector reset in chamelium_init() Okay then, I'll craft v3 in that directon. This is not a big overhead anyways, and it does not change anything when running subtests separately (which is what most test infrastructures using igt seem to be doing). > On Tue, 2017-06-27 at 13:53 +0300, Paul Kocialkowski wrote: > > This removes the reset call from the reset_state function and renames > > it > > to disconnect_connector. Since a call to reset is already done in > > chamelium_init, there is no need to do an extra reset in each test. > > > > This allows reducing the execution time a bit. > > > > Signed-off-by: Paul Kocialkowski > > --- > > tests/chamelium.c | 22 +++--- > > 1 file changed, 11 insertions(+), 11 deletions(-) > > > > diff --git a/tests/chamelium.c b/tests/chamelium.c > > index 346018a5..41e0e89b 100644 > > --- a/tests/chamelium.c > > +++ b/tests/chamelium.c > > @@ -145,17 +145,17 @@ wait_for_connector(data_t *data, struct > > chamelium_port *port, > > } > > > > static void > > -reset_state(data_t *data, struct chamelium_port *port) > > +disconnect_connector(data_t *data, struct chamelium_port *port) > > { > > int p; > > > > - chamelium_reset(data->chamelium); > > - > > if (port) { > > + chamelium_unplug(data->chamelium, port); > > wait_for_connector(data, port, > > DRM_MODE_DISCONNECTED, false); > > } else { > > for (p = 0; p < data->port_count; p++) { > > port = data->ports[p]; > > + chamelium_unplug(data->chamelium, port); > > wait_for_connector(data, port, > > DRM_MODE_DISCONNECTED, > >false); > > } > > @@ -168,7 +168,7 @@ test_basic_hotplug(data_t *data, struct > > chamelium_port *port, int toggle_count) > > struct udev_monitor *mon = igt_watch_hotplug(); > > int i; > > > > - reset_state(data, NULL); > > + disconnect_connector(data, NULL); > > igt_hpd_storm_set_threshold(data->drm_fd, 0); > > > > for (i = 0; i < toggle_count; i++) { > > @@ -202,7 +202,7 @@ test_edid_read(data_t *data, struct > > chamelium_port *port, > > data->chamelium, port, false); > > uint64_t edid_blob_id; > > > > - reset_state(data, port); > > + disconnect_connector(data, port); > > > > chamelium_port_set_edid(data->chamelium, port, edid_id); > > chamelium_plug(data->chamelium, port); > > @@ -270,7 +270,7 @@ test_suspend_resume_hpd(data_t *data, struct > > chamelium_port *port, > > { > > struct udev_monitor *mon = igt_watch_hotplug(); > > > > - reset_state(data, port); > > + disconnect_connector(data, port); > > > > /* Make sure we notice new connectors after resuming */ > > try_suspend_resume_hpd(data, port, state, test, mon, false); > > @@ -294,7 +294,7 @@ test_suspend_resume_hpd_common(data_t *data, enum > > igt_suspend_state state, > > igt_debug("Testing port %s\n", > > chamelium_port_get_name(port)); > > } > > > > - reset_state(data, NULL); > > + disconnect_connector(data, NULL); > > > > /* Make sure we notice new connectors after resuming */ > > try_suspend_resume_hpd(data, NULL, state, test, mon, false); > > @@ -314,7 +314,7 @@ test_suspend_resume_edid_change(data_t *data, > > struct chamelium_port *port, > > { > > struct udev_monitor *mon = igt_watch_hotplug(); > > > > - reset_state(data, port); > > + disconnect_connector(data, port); > > > > /* First plug in the port */ > > chamelium_port_set_edid(data->chamelium, port, edid_id); > > @@ -582,7 +582,7 @@ test_hpd_without_ddc(data_t *data, struct > > chamelium_port *port) > > { > > struct udev_monitor *mon = igt_watch_hotplug(); > > > > - reset_state(data, port); > > + disconnect_connector(data, port); > > igt_flush_hotplugs(mon); > > > > /* Disable the DDC on the connector and make sure we still > > get a > > @@ -604,7 +604,7 @@ test_hpd_storm_detect(data_t *data, struct > > chamelium_port *port, int width) > > int count = 0; > > > > igt_require_hpd_storm_ctl(data->drm_fd); > > - reset_state(data,
[Intel-gfx] [PATCH i-g-t v3 2/3] chamelium: Remove init reset duplicate in favor of per-test reset
Since most tests are already doing a reset, there is no need to duplicate it at init time. This removes that duplicate reset and adds a call to reset_state where in-test resets where not done previously. Signed-off-by: Paul Kocialkowski --- lib/igt_chamelium.c | 2 -- tests/chamelium.c | 6 ++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c index 225f98c3..624f448b 100644 --- a/lib/igt_chamelium.c +++ b/lib/igt_chamelium.c @@ -1233,8 +1233,6 @@ struct chamelium *chamelium_init(int drm_fd) if (!chamelium_read_config(chamelium, drm_fd)) goto error; - chamelium_reset(chamelium); - cleanup_instance = chamelium; igt_install_exit_handler(chamelium_exit_handler); diff --git a/tests/chamelium.c b/tests/chamelium.c index 346018a5..6247d537 100644 --- a/tests/chamelium.c +++ b/tests/chamelium.c @@ -431,6 +431,8 @@ test_display_crc_single(data_t *data, struct chamelium_port *port) drmModeConnector *connector; int fb_id, i; + reset_state(data, port); + output = prepare_output(data, &display, port); connector = chamelium_port_get_connector(data->chamelium, port, false); primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY); @@ -485,6 +487,8 @@ test_display_crc_multiple(data_t *data, struct chamelium_port *port) drmModeConnector *connector; int fb_id, i, j, captured_frame_count; + reset_state(data, port); + output = prepare_output(data, &display, port); connector = chamelium_port_get_connector(data->chamelium, port, false); primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY); @@ -544,6 +548,8 @@ test_display_frame_dump(data_t *data, struct chamelium_port *port) drmModeConnector *connector; int fb_id, i, j; + reset_state(data, port); + output = prepare_output(data, &display, port); connector = chamelium_port_get_connector(data->chamelium, port, false); primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY); -- 2.13.2 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH i-g-t v3 3/3] Make igtrc configuration common, with configurable suspend/resume delay
This adds support for configurable suspend/resume delay and takes the occasion to move igtrc configuation from igt_chamelium to igt_core. This way, suspend/resume delay configuration can be used for all tests. Signed-off-by: Paul Kocialkowski --- lib/Makefile.am | 2 ++ lib/igt_aux.c | 27 + lib/igt_aux.h | 1 + lib/igt_chamelium.c | 49 + lib/igt_core.c | 69 + lib/igt_core.h | 2 ++ tests/Makefile.am | 4 ++-- tests/chamelium.c | 11 - tools/Makefile.am | 4 ++-- 9 files changed, 117 insertions(+), 52 deletions(-) diff --git a/lib/Makefile.am b/lib/Makefile.am index 91e72c44..d4f41128 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -41,6 +41,7 @@ AM_CFLAGS = \ $(XMLRPC_CFLAGS) \ $(LIBUDEV_CFLAGS) \ $(PIXMAN_CFLAGS) \ + $(GLIB_CFLAGS) \ $(VALGRIND_CFLAGS) \ -DIGT_SRCDIR=\""$(abs_top_srcdir)/tests"\" \ -DIGT_DATADIR=\""$(pkgdatadir)"\" \ @@ -61,5 +62,6 @@ libintel_tools_la_LIBADD = \ $(XMLRPC_LIBS) \ $(LIBUDEV_LIBS) \ $(PIXMAN_LIBS) \ + $(GLIB_LIBS) \ -lm diff --git a/lib/igt_aux.c b/lib/igt_aux.c index 882dba06..86a213c2 100644 --- a/lib/igt_aux.c +++ b/lib/igt_aux.c @@ -748,10 +748,7 @@ static void suspend_via_rtcwake(enum igt_suspend_state state) igt_assert(state < SUSPEND_STATE_NUM); - if (autoresume_delay) - delay = autoresume_delay; - else - delay = state == SUSPEND_STATE_DISK ? 30 : 15; + delay = igt_get_autoresume_delay(state); /* * Skip if rtcwake would fail for a reason not related to the kernel's @@ -899,6 +896,28 @@ void igt_set_autoresume_delay(int delay_secs) } /** + * igt_get_autoresume_delay: + * @state: an #igt_suspend_state, the target suspend state + * + * Retrieves how long we wait to resume the system after suspending it. + * This can either be set through igt_set_autoresume_delay or be a default + * value that depends on the suspend state. + * + * Returns: The autoresume delay, in seconds. + */ +int igt_get_autoresume_delay(enum igt_suspend_state state) +{ + int delay; + + if (autoresume_delay) + delay = autoresume_delay; + else + delay = state == SUSPEND_STATE_DISK ? 30 : 15; + + return delay; +} + +/** * igt_drop_root: * * Drop root privileges and make sure it actually worked. Useful for tests diff --git a/lib/igt_aux.h b/lib/igt_aux.h index 54b97164..499a1679 100644 --- a/lib/igt_aux.h +++ b/lib/igt_aux.h @@ -192,6 +192,7 @@ enum igt_suspend_test { void igt_system_suspend_autoresume(enum igt_suspend_state state, enum igt_suspend_test test); void igt_set_autoresume_delay(int delay_secs); +int igt_get_autoresume_delay(enum igt_suspend_state state); /* dropping priviledges */ void igt_drop_root(void); diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c index 624f448b..bff08c0e 100644 --- a/lib/igt_chamelium.c +++ b/lib/igt_chamelium.c @@ -51,8 +51,8 @@ * [on the ChromeOS project page](https://www.chromium.org/chromium-os/testing/chamelium). * * In order to run tests using the Chamelium, a valid configuration file must be - * present. The configuration file is a normal Glib keyfile (similar to Windows - * INI) structured like so: + * present. It must contain Chamelium-specific keys as shown with the following + * example: * * |[ * [Chamelium] @@ -72,8 +72,6 @@ * ChameliumPortID=3 * ]| * - * By default, this file is expected to exist in ~/.igtrc . The directory for - * this can be overriden by setting the environment variable %IGT_CONFIG_PATH. */ struct chamelium_edid { @@ -1034,7 +1032,7 @@ static unsigned int chamelium_get_port_type(struct chamelium *chamelium, } static bool chamelium_read_port_mappings(struct chamelium *chamelium, -int drm_fd, GKeyFile *key_file) +int drm_fd) { drmModeRes *res; drmModeConnector *connector; @@ -1045,7 +1043,7 @@ static bool chamelium_read_port_mappings(struct chamelium *chamelium, int port_i, i, j; bool ret = true; - group_list = g_key_file_get_groups(key_file, NULL); + group_list = g_key_file_get_groups(igt_key_file, NULL); /* Count how many connector mappings are specified in the config */ for (i = 0; group_list[i] != NULL; i++) { @@ -1068,7 +1066,7 @@ static bool chamelium_read_port_mappings(struct chamelium *chamelium, port = &chamelium->ports[port_i++]; port->name = strdup(map_name); - port->id = g_key_file_get_integer(key_file, group, +
[Intel-gfx] [PATCH i-g-t v3 1/3] tests/chamelium: Update connector state without reprobe when possible
This renames the reprobe_connector function to update_connector and ensures that full reprobe of the connector is only done when really necessary (e.g. when changing the EDID). A full reprobe takes time and is not required for updating the connector state. Thus, this allows executing tests faster. Signed-off-by: Paul Kocialkowski --- tests/chamelium.c | 34 ++ 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/tests/chamelium.c b/tests/chamelium.c index b412c6a7..346018a5 100644 --- a/tests/chamelium.c +++ b/tests/chamelium.c @@ -103,13 +103,14 @@ require_connector_present(data_t *data, unsigned int type) } static drmModeConnection -reprobe_connector(data_t *data, struct chamelium_port *port) +update_connector(data_t *data, struct chamelium_port *port, bool reprobe) { drmModeConnector *connector; drmModeConnection status; - igt_debug("Reprobing %s...\n", chamelium_port_get_name(port)); - connector = chamelium_port_get_connector(data->chamelium, port, true); + igt_debug("Updating %s...\n", chamelium_port_get_name(port)); + connector = chamelium_port_get_connector(data->chamelium, port, +reprobe); igt_assert(connector); status = connector->connection; @@ -119,7 +120,7 @@ reprobe_connector(data_t *data, struct chamelium_port *port) static void wait_for_connector(data_t *data, struct chamelium_port *port, - drmModeConnection status) + drmModeConnection status, bool reprobe) { bool finished = false; @@ -132,7 +133,7 @@ wait_for_connector(data_t *data, struct chamelium_port *port, * that hpd events work in the event that hpd doesn't work on the system */ igt_until_timeout(HOTPLUG_TIMEOUT) { - if (reprobe_connector(data, port) == status) { + if (update_connector(data, port, reprobe) == status) { finished = true; return; } @@ -151,11 +152,12 @@ reset_state(data_t *data, struct chamelium_port *port) chamelium_reset(data->chamelium); if (port) { - wait_for_connector(data, port, DRM_MODE_DISCONNECTED); + wait_for_connector(data, port, DRM_MODE_DISCONNECTED, false); } else { for (p = 0; p < data->port_count; p++) { port = data->ports[p]; - wait_for_connector(data, port, DRM_MODE_DISCONNECTED); + wait_for_connector(data, port, DRM_MODE_DISCONNECTED, + false); } } } @@ -175,7 +177,7 @@ test_basic_hotplug(data_t *data, struct chamelium_port *port, int toggle_count) /* Check if we get a sysfs hotplug event */ chamelium_plug(data->chamelium, port); igt_assert(igt_hotplug_detected(mon, HOTPLUG_TIMEOUT)); - igt_assert_eq(reprobe_connector(data, port), + igt_assert_eq(update_connector(data, port, false), DRM_MODE_CONNECTED); igt_flush_hotplugs(mon); @@ -183,7 +185,7 @@ test_basic_hotplug(data_t *data, struct chamelium_port *port, int toggle_count) /* Now check if we get a hotplug from disconnection */ chamelium_unplug(data->chamelium, port); igt_assert(igt_hotplug_detected(mon, HOTPLUG_TIMEOUT)); - igt_assert_eq(reprobe_connector(data, port), + igt_assert_eq(update_connector(data, port, false), DRM_MODE_DISCONNECTED); } @@ -204,7 +206,7 @@ test_edid_read(data_t *data, struct chamelium_port *port, chamelium_port_set_edid(data->chamelium, port, edid_id); chamelium_plug(data->chamelium, port); - wait_for_connector(data, port, DRM_MODE_CONNECTED); + wait_for_connector(data, port, DRM_MODE_CONNECTED, true); igt_assert(kmstest_get_property(data->drm_fd, connector->connector_id, DRM_MODE_OBJECT_CONNECTOR, "EDID", NULL, @@ -247,13 +249,13 @@ try_suspend_resume_hpd(data_t *data, struct chamelium_port *port, igt_assert(igt_hotplug_detected(mon, HOTPLUG_TIMEOUT)); if (port) { - igt_assert_eq(reprobe_connector(data, port), connected ? + igt_assert_eq(update_connector(data, port, false), connected ? DRM_MODE_DISCONNECTED : DRM_MODE_CONNECTED); } else { for (p = 0; p < data->port_count; p++) { port = data->ports[p]; - igt_assert_eq(reprobe_connector(data, port), connected ? - DRM_MODE_DISCONNECTED : + igt_assert_eq(u
[Intel-gfx] [PATCH i-g-t 4/4] chamelium: Dump obtained and reference frames to png on crc error
When a CRC comparison error occurs, it is quite useful to get a dump of both the frame obtained from the chamelium and the reference in order to compare them. This implements the frame dump, with a configurable path that enables the use of this feature. Signed-off-by: Paul Kocialkowski --- lib/igt_chamelium.c | 21 +++ lib/igt_chamelium.h | 1 + lib/igt_debugfs.c | 20 ++ lib/igt_debugfs.h | 1 + tests/chamelium.c | 105 +++- 5 files changed, 82 insertions(+), 66 deletions(-) diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c index c8719f4d..ad4a2827 100644 --- a/lib/igt_chamelium.c +++ b/lib/igt_chamelium.c @@ -57,6 +57,7 @@ * |[ * [Chamelium] * URL=http://chameleon:9992 # The URL used for connecting to the Chamelium's RPC server + * FrameDumpPath=/tmp # The path to dump frames that fail comparison checks * * # The rest of the sections are used for defining connector mappings. * # This is required so any tests using the Chamelium know which connector @@ -115,11 +116,26 @@ struct chamelium { struct chamelium_edid *edids; struct chamelium_port *ports; int port_count; + + char *frame_dump_path; }; static struct chamelium *cleanup_instance; /** + * chamelium_get_frame_dump_path: + * @chamelium: The Chamelium instance to use + * + * Retrieves the path to dump frames to. + * + * Returns: a string with the frame dump path + */ +char *chamelium_get_frame_dump_path(struct chamelium *chamelium) +{ + return chamelium->frame_dump_path; +} + +/** * chamelium_get_ports: * @chamelium: The Chamelium instance to use * @count: Where to store the number of ports @@ -1330,6 +1346,11 @@ static bool chamelium_read_config(struct chamelium *chamelium, int drm_fd) return false; } + chamelium->frame_dump_path = g_key_file_get_string(igt_key_file, + "Chamelium", + "FrameDumpPath", + &error); + return chamelium_read_port_mappings(chamelium, drm_fd); } diff --git a/lib/igt_chamelium.h b/lib/igt_chamelium.h index 908e03d1..aa881971 100644 --- a/lib/igt_chamelium.h +++ b/lib/igt_chamelium.h @@ -42,6 +42,7 @@ struct chamelium *chamelium_init(int drm_fd); void chamelium_deinit(struct chamelium *chamelium); void chamelium_reset(struct chamelium *chamelium); +char *chamelium_get_frame_dump_path(struct chamelium *chamelium); struct chamelium_port **chamelium_get_ports(struct chamelium *chamelium, int *count); unsigned int chamelium_port_get_type(const struct chamelium_port *port); diff --git a/lib/igt_debugfs.c b/lib/igt_debugfs.c index 80f25c61..dcb4e0a7 100644 --- a/lib/igt_debugfs.c +++ b/lib/igt_debugfs.c @@ -282,6 +282,26 @@ bool igt_debugfs_search(int device, const char *filename, const char *substring) */ /** + * igt_check_crc_equal: + * @a: first pipe CRC value + * @b: second pipe CRC value + * + * Compares two CRC values and return whether they match. + * + * Returns: A boolean indicating whether the CRC values match + */ +bool igt_check_crc_equal(const igt_crc_t *a, const igt_crc_t *b) +{ + int i; + + for (i = 0; i < a->n_words; i++) + if (a->crc[i] != b->crc[i]) + return false; + + return true; +} + +/** * igt_assert_crc_equal: * @a: first pipe CRC value * @b: second pipe CRC value diff --git a/lib/igt_debugfs.h b/lib/igt_debugfs.h index 7b846a83..2695cbda 100644 --- a/lib/igt_debugfs.h +++ b/lib/igt_debugfs.h @@ -113,6 +113,7 @@ enum intel_pipe_crc_source { INTEL_PIPE_CRC_SOURCE_MAX, }; +bool igt_check_crc_equal(const igt_crc_t *a, const igt_crc_t *b); void igt_assert_crc_equal(const igt_crc_t *a, const igt_crc_t *b); char *igt_crc_to_string(igt_crc_t *crc); diff --git a/tests/chamelium.c b/tests/chamelium.c index 29835c75..4f69ccc4 100644 --- a/tests/chamelium.c +++ b/tests/chamelium.c @@ -381,7 +381,7 @@ disable_output(data_t *data, } static void -test_display_crc_single(data_t *data, struct chamelium_port *port) +test_display_crc(data_t *data, struct chamelium_port *port, int count) { igt_display_t display; igt_output_t *output; @@ -390,9 +390,14 @@ test_display_crc_single(data_t *data, struct chamelium_port *port) igt_crc_t *expected_crc; struct chamelium_fb_crc *fb_crc; struct igt_fb fb; + struct chamelium_frame_dump *frame; drmModeModeInfo *mode; drmModeConnector *connector; - int fb_id, i; + int fb_id, i, j, captured_frame_count; + const char *connector_name; + char *frame_dump_path; + char path[PATH_MAX]; + bool eq; reset_state(data, port); @@ -401,6
[Intel-gfx] [PATCH i-g-t 2/4] tests/ chamelium: Remove the frame dump tests
The frame dump tests provide no additional functionality over CRC tests and are considerably slower. Thus, these tests should be considered as poorer duplicates and removed. Signed-off-by: Paul Kocialkowski --- tests/chamelium.c | 53 - 1 file changed, 53 deletions(-) diff --git a/tests/chamelium.c b/tests/chamelium.c index 661d0f60..29835c75 100644 --- a/tests/chamelium.c +++ b/tests/chamelium.c @@ -498,53 +498,6 @@ next: } static void -test_display_frame_dump(data_t *data, struct chamelium_port *port) -{ - igt_display_t display; - igt_output_t *output; - igt_plane_t *primary; - struct igt_fb fb; - struct chamelium_frame_dump *frame; - drmModeModeInfo *mode; - drmModeConnector *connector; - int fb_id, i, j; - - reset_state(data, port); - - output = prepare_output(data, &display, port); - connector = chamelium_port_get_connector(data->chamelium, port, false); - primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY); - igt_assert(primary); - - for (i = 0; i < connector->count_modes; i++) { - mode = &connector->modes[i]; - fb_id = igt_create_color_pattern_fb(data->drm_fd, - mode->hdisplay, mode->vdisplay, - DRM_FORMAT_XRGB, - LOCAL_DRM_FORMAT_MOD_NONE, - 0, 0, 0, &fb); - igt_assert(fb_id > 0); - - enable_output(data, port, output, mode, &fb); - - igt_debug("Reading frame dumps from Chamelium...\n"); - chamelium_capture(data->chamelium, port, 0, 0, 0, 0, 5); - for (j = 0; j < 5; j++) { - frame = chamelium_read_captured_frame( - data->chamelium, j); - chamelium_assert_frame_eq(data->chamelium, frame, &fb); - chamelium_destroy_frame_dump(frame); - } - - disable_output(data, port, output); - igt_remove_fb(data->drm_fd, &fb); - } - - drmModeFreeConnector(connector); - igt_display_fini(&display); -} - -static void test_hpd_without_ddc(data_t *data, struct chamelium_port *port) { struct udev_monitor *mon = igt_watch_hotplug(); @@ -697,9 +650,6 @@ igt_main connector_subtest("dp-crc-multiple", DisplayPort) test_display_crc_multiple(&data, port); - - connector_subtest("dp-frame-dump", DisplayPort) - test_display_frame_dump(&data, port); } igt_subtest_group { @@ -754,9 +704,6 @@ igt_main connector_subtest("hdmi-crc-multiple", HDMIA) test_display_crc_multiple(&data, port); - - connector_subtest("hdmi-frame-dump", HDMIA) - test_display_frame_dump(&data, port); } igt_subtest_group { -- 2.13.2 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH i-g-t 1/4] chamelium: Calculate CRC from framebuffer instead of hardcoding it
This introduces CRC calculation for reference frames, instead of using hardcoded values for them. The rendering of reference frames may differ from machine to machine, especially due to font rendering, and the frame itself may change with subsequent IGT changes. These differences would cause the CRC checks to fail on different setups. This allows them to pass regardless of the setup. Signed-off-by: Paul Kocialkowski --- lib/igt_chamelium.c | 160 lib/igt_chamelium.h | 5 ++ tests/chamelium.c | 74 ++-- 3 files changed, 183 insertions(+), 56 deletions(-) diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c index bff08c0e..b9d80b6b 100644 --- a/lib/igt_chamelium.c +++ b/lib/igt_chamelium.c @@ -94,6 +94,14 @@ struct chamelium_frame_dump { struct chamelium_port *port; }; +struct chamelium_fb_crc { + int fd; + struct igt_fb *fb; + + pthread_t thread_id; + igt_crc_t *ret; +}; + struct chamelium { xmlrpc_env env; xmlrpc_client *client; @@ -1003,6 +1011,158 @@ int chamelium_get_frame_limit(struct chamelium *chamelium, return ret; } +static uint32_t chamelium_xrgb_hash16(unsigned char *buffer, int width, + int height, int k, int m) +{ + unsigned char r, g, b; + uint64_t sum = 0; + uint64_t count = 0; + uint64_t value; + uint32_t hash; + int index; + int i; + + for (i=0; i < width * height; i++) { + if ((i % m) != k) + continue; + + index = i * 4; + + r = buffer[index + 2]; + g = buffer[index + 1]; + b = buffer[index + 0]; + + value = r | (g << 8) | (b << 16); + sum += ++count * value; + } + + hash = ((sum >> 0) ^ (sum >> 16) ^ (sum >> 32) ^ (sum >> 48)) & 0x; + + return hash; +} + +/** + * chamelium_calculate_fb_crc: + * @fd: The drm file descriptor + * @fb: The framebuffer to calculate the CRC for + * + * Calculates a CRC for the provided framebuffer, the same way as the Chamelium. + * This calculates the CRC in a non-threaded fashion. + * + * Returns: The calculated CRC + */ +igt_crc_t *chamelium_calculate_fb_crc(int fd, struct igt_fb *fb) +{ + igt_crc_t *ret; + cairo_t *cr; + cairo_surface_t *fb_surface; + unsigned char *buffer; + int n = 4; + int w, h; + int i, j; + + ret = calloc(1, sizeof(igt_crc_t)); + + /* Get the cairo surface for the framebuffer */ + cr = igt_get_cairo_ctx(fd, fb); + fb_surface = cairo_get_target(cr); + cairo_surface_reference(fb_surface); + cairo_destroy(cr); + + buffer = cairo_image_surface_get_data(fb_surface); + w = fb->width; + h = fb->height; + + for (i = 0; i < n; i++) { + j = n - i - 1; + ret->crc[i] = chamelium_xrgb_hash16(buffer, w, h, j, n); + } + + ret->n_words = n; + cairo_surface_destroy(fb_surface); + + return ret; +} + +static void *chamelium_calculate_fb_crc_thread(void *data) +{ + struct chamelium_fb_crc *fb_crc = (struct chamelium_fb_crc *) data; + cairo_t *cr; + cairo_surface_t *fb_surface; + unsigned char *buffer; + int n = 4; + int w, h; + int i, j; + + /* Get the cairo surface for the framebuffer */ + cr = igt_get_cairo_ctx(fb_crc->fd, fb_crc->fb); + fb_surface = cairo_get_target(cr); + cairo_surface_reference(fb_surface); + cairo_destroy(cr); + + buffer = cairo_image_surface_get_data(fb_surface); + w = fb_crc->fb->width; + h = fb_crc->fb->height; + + for (i = 0; i < n; i++) { + j = n - i - 1; + fb_crc->ret->crc[i] = chamelium_xrgb_hash16(buffer, w, h, j, n); + } + + fb_crc->ret->n_words = n; + cairo_surface_destroy(fb_surface); + + return NULL; +} + +/** + * chamelium_calculate_fb_crc_launch: + * @fd: The drm file descriptor + * @fb: The framebuffer to calculate the CRC for + * + * Launches the CRC calculation for the provided framebuffer, the same way as + * the Chamelium. This calculates the CRC in a threaded fashion. + * Thread-related information is returned and should be passed to a subsequent + * call to chamelium_calculate_fb_crc_result. It should not be freed. + * + * Returns: An intermediate structure with thread-related information + */ +struct chamelium_fb_crc *chamelium_calculate_fb_crc_launch(int fd, + struct igt_fb *fb) +{ + struct chamelium_fb_crc *fb_crc; + + fb_crc = calloc(1, sizeof(struct chamelium_fb_crc)); + fb_crc->ret = calloc(1, sizeof(igt_crc_t)); +
[Intel-gfx] [PATCH i-g-t 3/4] lib/igt_chamelium: Add support for dumping chamelium frames to a png
This introduces a chamelium_write_frame_to_png function that saves a Chamelium frame dump to a png file. This should be useful when a frame comparison with a reference fails. --- lib/igt_chamelium.c | 32 lib/igt_chamelium.h | 3 +++ 2 files changed, 35 insertions(+) diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c index b9d80b6b..c8719f4d 100644 --- a/lib/igt_chamelium.c +++ b/lib/igt_chamelium.c @@ -978,6 +978,38 @@ void chamelium_assert_frame_eq(const struct chamelium *chamelium, "Chamelium frame dump didn't match reference image\n"); } +void chamelium_write_frame_to_png(const struct chamelium *chamelium, + const struct chamelium_frame_dump *dump, + const char *filename) +{ + cairo_surface_t *dump_surface; + pixman_image_t *image_bgr; + pixman_image_t *image_argb; + int w = dump->width, h = dump->height; + uint32_t *bits_bgr = (uint32_t *) dump->bgr; + unsigned char *bits_argb; + cairo_status_t status; + + image_bgr = pixman_image_create_bits( + PIXMAN_b8g8r8, w, h, bits_bgr, + PIXMAN_FORMAT_BPP(PIXMAN_b8g8r8) / 8 * w); + image_argb = convert_frame_format(image_bgr, PIXMAN_x8r8g8b8); + pixman_image_unref(image_bgr); + + bits_argb = (unsigned char *) pixman_image_get_data(image_argb); + + dump_surface = cairo_image_surface_create_for_data( + bits_argb, CAIRO_FORMAT_ARGB32, w, h, + PIXMAN_FORMAT_BPP(PIXMAN_x8r8g8b8) / 8 * w); + + status = cairo_surface_write_to_png(dump_surface, filename); + cairo_surface_destroy(dump_surface); + + pixman_image_unref(image_argb); + + igt_assert(status == CAIRO_STATUS_SUCCESS); +} + /** * chamelium_get_frame_limit: * @chamelium: The Chamelium instance to use diff --git a/lib/igt_chamelium.h b/lib/igt_chamelium.h index e51cf4f9..908e03d1 100644 --- a/lib/igt_chamelium.h +++ b/lib/igt_chamelium.h @@ -105,6 +105,9 @@ int chamelium_get_frame_limit(struct chamelium *chamelium, void chamelium_assert_frame_eq(const struct chamelium *chamelium, const struct chamelium_frame_dump *dump, struct igt_fb *fb); +void chamelium_write_frame_to_png(const struct chamelium *chamelium, + const struct chamelium_frame_dump *dump, + const char *filename); void chamelium_destroy_frame_dump(struct chamelium_frame_dump *dump); #endif /* IGT_CHAMELIUM_H */ -- 2.13.2 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH i-g-t v3 3/3] Make igtrc configuration common, with configurable suspend/resume delay
On Mon, 2017-07-03 at 15:01 +0300, Paul Kocialkowski wrote: > This adds support for configurable suspend/resume delay and takes the > occasion to move igtrc configuation from igt_chamelium to igt_core. > This way, suspend/resume delay configuration can be used for all tests. > > Signed-off-by: Paul Kocialkowski > --- > lib/Makefile.am | 2 ++ > lib/igt_aux.c | 27 + > lib/igt_aux.h | 1 + > lib/igt_chamelium.c | 49 + > lib/igt_core.c | 69 > + > lib/igt_core.h | 2 ++ > tests/Makefile.am | 4 ++-- > tests/chamelium.c | 11 - > tools/Makefile.am | 4 ++-- > 9 files changed, 117 insertions(+), 52 deletions(-) > > diff --git a/lib/Makefile.am b/lib/Makefile.am > index 91e72c44..d4f41128 100644 > --- a/lib/Makefile.am > +++ b/lib/Makefile.am > @@ -41,6 +41,7 @@ AM_CFLAGS = \ > $(XMLRPC_CFLAGS) \ > $(LIBUDEV_CFLAGS) \ > $(PIXMAN_CFLAGS) \ > + $(GLIB_CFLAGS) \ > $(VALGRIND_CFLAGS) \ > -DIGT_SRCDIR=\""$(abs_top_srcdir)/tests"\" \ > -DIGT_DATADIR=\""$(pkgdatadir)"\" \ > @@ -61,5 +62,6 @@ libintel_tools_la_LIBADD = \ > $(XMLRPC_LIBS) \ > $(LIBUDEV_LIBS) \ > $(PIXMAN_LIBS) \ > + $(GLIB_LIBS) \ > -lm > > diff --git a/lib/igt_aux.c b/lib/igt_aux.c > index 882dba06..86a213c2 100644 > --- a/lib/igt_aux.c > +++ b/lib/igt_aux.c > @@ -748,10 +748,7 @@ static void suspend_via_rtcwake(enum igt_suspend_state > state) > > igt_assert(state < SUSPEND_STATE_NUM); > > - if (autoresume_delay) > - delay = autoresume_delay; > - else > - delay = state == SUSPEND_STATE_DISK ? 30 : 15; > + delay = igt_get_autoresume_delay(state); > > /* >* Skip if rtcwake would fail for a reason not related to the > kernel's > @@ -899,6 +896,28 @@ void igt_set_autoresume_delay(int delay_secs) > } > > /** > + * igt_get_autoresume_delay: > + * @state: an #igt_suspend_state, the target suspend state > + * > + * Retrieves how long we wait to resume the system after suspending it. > + * This can either be set through igt_set_autoresume_delay or be a default > + * value that depends on the suspend state. > + * > + * Returns: The autoresume delay, in seconds. > + */ > +int igt_get_autoresume_delay(enum igt_suspend_state state) > +{ > + int delay; > + > + if (autoresume_delay) > + delay = autoresume_delay; > + else > + delay = state == SUSPEND_STATE_DISK ? 30 : 15; > + > + return delay; > +} > + > +/** > * igt_drop_root: > * > * Drop root privileges and make sure it actually worked. Useful for tests > diff --git a/lib/igt_aux.h b/lib/igt_aux.h > index 54b97164..499a1679 100644 > --- a/lib/igt_aux.h > +++ b/lib/igt_aux.h > @@ -192,6 +192,7 @@ enum igt_suspend_test { > void igt_system_suspend_autoresume(enum igt_suspend_state state, > enum igt_suspend_test test); > void igt_set_autoresume_delay(int delay_secs); > +int igt_get_autoresume_delay(enum igt_suspend_state state); > > /* dropping priviledges */ > void igt_drop_root(void); > diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c > index 624f448b..bff08c0e 100644 > --- a/lib/igt_chamelium.c > +++ b/lib/igt_chamelium.c > @@ -51,8 +51,8 @@ > * [on the ChromeOS project page](https://www.chromium.org/chromium-os/testin > g/chamelium). > * > * In order to run tests using the Chamelium, a valid configuration file must > be > - * present. The configuration file is a normal Glib keyfile (similar to > Windows > - * INI) structured like so: > + * present. It must contain Chamelium-specific keys as shown with the > following > + * example: > * > * |[ > * [Chamelium] > @@ -72,8 +72,6 @@ > * ChameliumPortID=3 > * ]| > * > - * By default, this file is expected to exist in ~/.igtrc . The directory for > - * this can be overriden by setting the environment variable > %IGT_CONFIG_PATH. > */ > > struct chamelium_edid { > @@ -1034,7 +1032,7 @@ static unsigned int chamelium_get_port_type(struct > chamelium *chamelium, > } > > static bool chamelium_read_port_mappings(struct chamelium *chamelium, > - int drm_fd, GKeyFile *key_file) > + int drm_fd) > { > drmModeRes *res; > drmModeConnector *connector; > @@ -1045,7 +1043,7 @@ static bool chameli
[Intel-gfx] [PATCH i-g-t v4 3/3] Make igtrc configuration common, with configurable suspend/resume delay
This adds support for configurable suspend/resume delay and takes the occasion to move igtrc configuation from igt_chamelium to igt_core. This way, suspend/resume delay configuration can be used for all tests. Signed-off-by: Paul Kocialkowski --- lib/Makefile.am | 2 ++ lib/igt_aux.c | 27 + lib/igt_aux.h | 1 + lib/igt_chamelium.c | 49 + lib/igt_core.c | 69 + lib/igt_core.h | 2 ++ tests/Makefile.am | 4 ++-- tests/chamelium.c | 11 - tools/Makefile.am | 4 ++-- 9 files changed, 117 insertions(+), 52 deletions(-) diff --git a/lib/Makefile.am b/lib/Makefile.am index 91e72c44..d4f41128 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -41,6 +41,7 @@ AM_CFLAGS = \ $(XMLRPC_CFLAGS) \ $(LIBUDEV_CFLAGS) \ $(PIXMAN_CFLAGS) \ + $(GLIB_CFLAGS) \ $(VALGRIND_CFLAGS) \ -DIGT_SRCDIR=\""$(abs_top_srcdir)/tests"\" \ -DIGT_DATADIR=\""$(pkgdatadir)"\" \ @@ -61,5 +62,6 @@ libintel_tools_la_LIBADD = \ $(XMLRPC_LIBS) \ $(LIBUDEV_LIBS) \ $(PIXMAN_LIBS) \ + $(GLIB_LIBS) \ -lm diff --git a/lib/igt_aux.c b/lib/igt_aux.c index 882dba06..86a213c2 100644 --- a/lib/igt_aux.c +++ b/lib/igt_aux.c @@ -748,10 +748,7 @@ static void suspend_via_rtcwake(enum igt_suspend_state state) igt_assert(state < SUSPEND_STATE_NUM); - if (autoresume_delay) - delay = autoresume_delay; - else - delay = state == SUSPEND_STATE_DISK ? 30 : 15; + delay = igt_get_autoresume_delay(state); /* * Skip if rtcwake would fail for a reason not related to the kernel's @@ -899,6 +896,28 @@ void igt_set_autoresume_delay(int delay_secs) } /** + * igt_get_autoresume_delay: + * @state: an #igt_suspend_state, the target suspend state + * + * Retrieves how long we wait to resume the system after suspending it. + * This can either be set through igt_set_autoresume_delay or be a default + * value that depends on the suspend state. + * + * Returns: The autoresume delay, in seconds. + */ +int igt_get_autoresume_delay(enum igt_suspend_state state) +{ + int delay; + + if (autoresume_delay) + delay = autoresume_delay; + else + delay = state == SUSPEND_STATE_DISK ? 30 : 15; + + return delay; +} + +/** * igt_drop_root: * * Drop root privileges and make sure it actually worked. Useful for tests diff --git a/lib/igt_aux.h b/lib/igt_aux.h index 54b97164..499a1679 100644 --- a/lib/igt_aux.h +++ b/lib/igt_aux.h @@ -192,6 +192,7 @@ enum igt_suspend_test { void igt_system_suspend_autoresume(enum igt_suspend_state state, enum igt_suspend_test test); void igt_set_autoresume_delay(int delay_secs); +int igt_get_autoresume_delay(enum igt_suspend_state state); /* dropping priviledges */ void igt_drop_root(void); diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c index 624f448b..bff08c0e 100644 --- a/lib/igt_chamelium.c +++ b/lib/igt_chamelium.c @@ -51,8 +51,8 @@ * [on the ChromeOS project page](https://www.chromium.org/chromium-os/testing/chamelium). * * In order to run tests using the Chamelium, a valid configuration file must be - * present. The configuration file is a normal Glib keyfile (similar to Windows - * INI) structured like so: + * present. It must contain Chamelium-specific keys as shown with the following + * example: * * |[ * [Chamelium] @@ -72,8 +72,6 @@ * ChameliumPortID=3 * ]| * - * By default, this file is expected to exist in ~/.igtrc . The directory for - * this can be overriden by setting the environment variable %IGT_CONFIG_PATH. */ struct chamelium_edid { @@ -1034,7 +1032,7 @@ static unsigned int chamelium_get_port_type(struct chamelium *chamelium, } static bool chamelium_read_port_mappings(struct chamelium *chamelium, -int drm_fd, GKeyFile *key_file) +int drm_fd) { drmModeRes *res; drmModeConnector *connector; @@ -1045,7 +1043,7 @@ static bool chamelium_read_port_mappings(struct chamelium *chamelium, int port_i, i, j; bool ret = true; - group_list = g_key_file_get_groups(key_file, NULL); + group_list = g_key_file_get_groups(igt_key_file, NULL); /* Count how many connector mappings are specified in the config */ for (i = 0; group_list[i] != NULL; i++) { @@ -1068,7 +1066,7 @@ static bool chamelium_read_port_mappings(struct chamelium *chamelium, port = &chamelium->ports[port_i++]; port->name = strdup(map_name); - port->id = g_key_file_get_integer(key_file, group, +
[Intel-gfx] [PATCH i-g-t v4 1/3] tests/chamelium: Update connector state without reprobe when possible
This renames the reprobe_connector function to update_connector and ensures that full reprobe of the connector is only done when really necessary (e.g. when changing the EDID). A full reprobe takes time and is not required for updating the connector state. Thus, this allows executing tests faster. Signed-off-by: Paul Kocialkowski --- tests/chamelium.c | 34 ++ 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/tests/chamelium.c b/tests/chamelium.c index b412c6a7..346018a5 100644 --- a/tests/chamelium.c +++ b/tests/chamelium.c @@ -103,13 +103,14 @@ require_connector_present(data_t *data, unsigned int type) } static drmModeConnection -reprobe_connector(data_t *data, struct chamelium_port *port) +update_connector(data_t *data, struct chamelium_port *port, bool reprobe) { drmModeConnector *connector; drmModeConnection status; - igt_debug("Reprobing %s...\n", chamelium_port_get_name(port)); - connector = chamelium_port_get_connector(data->chamelium, port, true); + igt_debug("Updating %s...\n", chamelium_port_get_name(port)); + connector = chamelium_port_get_connector(data->chamelium, port, +reprobe); igt_assert(connector); status = connector->connection; @@ -119,7 +120,7 @@ reprobe_connector(data_t *data, struct chamelium_port *port) static void wait_for_connector(data_t *data, struct chamelium_port *port, - drmModeConnection status) + drmModeConnection status, bool reprobe) { bool finished = false; @@ -132,7 +133,7 @@ wait_for_connector(data_t *data, struct chamelium_port *port, * that hpd events work in the event that hpd doesn't work on the system */ igt_until_timeout(HOTPLUG_TIMEOUT) { - if (reprobe_connector(data, port) == status) { + if (update_connector(data, port, reprobe) == status) { finished = true; return; } @@ -151,11 +152,12 @@ reset_state(data_t *data, struct chamelium_port *port) chamelium_reset(data->chamelium); if (port) { - wait_for_connector(data, port, DRM_MODE_DISCONNECTED); + wait_for_connector(data, port, DRM_MODE_DISCONNECTED, false); } else { for (p = 0; p < data->port_count; p++) { port = data->ports[p]; - wait_for_connector(data, port, DRM_MODE_DISCONNECTED); + wait_for_connector(data, port, DRM_MODE_DISCONNECTED, + false); } } } @@ -175,7 +177,7 @@ test_basic_hotplug(data_t *data, struct chamelium_port *port, int toggle_count) /* Check if we get a sysfs hotplug event */ chamelium_plug(data->chamelium, port); igt_assert(igt_hotplug_detected(mon, HOTPLUG_TIMEOUT)); - igt_assert_eq(reprobe_connector(data, port), + igt_assert_eq(update_connector(data, port, false), DRM_MODE_CONNECTED); igt_flush_hotplugs(mon); @@ -183,7 +185,7 @@ test_basic_hotplug(data_t *data, struct chamelium_port *port, int toggle_count) /* Now check if we get a hotplug from disconnection */ chamelium_unplug(data->chamelium, port); igt_assert(igt_hotplug_detected(mon, HOTPLUG_TIMEOUT)); - igt_assert_eq(reprobe_connector(data, port), + igt_assert_eq(update_connector(data, port, false), DRM_MODE_DISCONNECTED); } @@ -204,7 +206,7 @@ test_edid_read(data_t *data, struct chamelium_port *port, chamelium_port_set_edid(data->chamelium, port, edid_id); chamelium_plug(data->chamelium, port); - wait_for_connector(data, port, DRM_MODE_CONNECTED); + wait_for_connector(data, port, DRM_MODE_CONNECTED, true); igt_assert(kmstest_get_property(data->drm_fd, connector->connector_id, DRM_MODE_OBJECT_CONNECTOR, "EDID", NULL, @@ -247,13 +249,13 @@ try_suspend_resume_hpd(data_t *data, struct chamelium_port *port, igt_assert(igt_hotplug_detected(mon, HOTPLUG_TIMEOUT)); if (port) { - igt_assert_eq(reprobe_connector(data, port), connected ? + igt_assert_eq(update_connector(data, port, false), connected ? DRM_MODE_DISCONNECTED : DRM_MODE_CONNECTED); } else { for (p = 0; p < data->port_count; p++) { port = data->ports[p]; - igt_assert_eq(reprobe_connector(data, port), connected ? - DRM_MODE_DISCONNECTED : + igt_assert_eq(u
[Intel-gfx] [PATCH i-g-t v4 2/3] chamelium: Remove init reset duplicate in favor of per-test reset
Since most tests are already doing a reset, there is no need to duplicate it at init time. This removes that duplicate reset and adds a call to reset_state where in-test resets where not done previously. Signed-off-by: Paul Kocialkowski --- lib/igt_chamelium.c | 2 -- tests/chamelium.c | 6 ++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c index 225f98c3..624f448b 100644 --- a/lib/igt_chamelium.c +++ b/lib/igt_chamelium.c @@ -1233,8 +1233,6 @@ struct chamelium *chamelium_init(int drm_fd) if (!chamelium_read_config(chamelium, drm_fd)) goto error; - chamelium_reset(chamelium); - cleanup_instance = chamelium; igt_install_exit_handler(chamelium_exit_handler); diff --git a/tests/chamelium.c b/tests/chamelium.c index 346018a5..6247d537 100644 --- a/tests/chamelium.c +++ b/tests/chamelium.c @@ -431,6 +431,8 @@ test_display_crc_single(data_t *data, struct chamelium_port *port) drmModeConnector *connector; int fb_id, i; + reset_state(data, port); + output = prepare_output(data, &display, port); connector = chamelium_port_get_connector(data->chamelium, port, false); primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY); @@ -485,6 +487,8 @@ test_display_crc_multiple(data_t *data, struct chamelium_port *port) drmModeConnector *connector; int fb_id, i, j, captured_frame_count; + reset_state(data, port); + output = prepare_output(data, &display, port); connector = chamelium_port_get_connector(data->chamelium, port, false); primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY); @@ -544,6 +548,8 @@ test_display_frame_dump(data_t *data, struct chamelium_port *port) drmModeConnector *connector; int fb_id, i, j; + reset_state(data, port); + output = prepare_output(data, &display, port); connector = chamelium_port_get_connector(data->chamelium, port, false); primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY); -- 2.13.2 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH i-g-t v2 1/4] chamelium: Calculate CRC from framebuffer instead of hardcoding it
This introduces CRC calculation for reference frames, instead of using hardcoded values for them. The rendering of reference frames may differ from machine to machine, especially due to font rendering, and the frame itself may change with subsequent IGT changes. These differences would cause the CRC checks to fail on different setups. This allows them to pass regardless of the setup. Signed-off-by: Paul Kocialkowski --- lib/igt_chamelium.c | 160 lib/igt_chamelium.h | 5 ++ tests/chamelium.c | 76 ++--- 3 files changed, 183 insertions(+), 58 deletions(-) diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c index bff08c0e..b9d80b6b 100644 --- a/lib/igt_chamelium.c +++ b/lib/igt_chamelium.c @@ -94,6 +94,14 @@ struct chamelium_frame_dump { struct chamelium_port *port; }; +struct chamelium_fb_crc { + int fd; + struct igt_fb *fb; + + pthread_t thread_id; + igt_crc_t *ret; +}; + struct chamelium { xmlrpc_env env; xmlrpc_client *client; @@ -1003,6 +1011,158 @@ int chamelium_get_frame_limit(struct chamelium *chamelium, return ret; } +static uint32_t chamelium_xrgb_hash16(unsigned char *buffer, int width, + int height, int k, int m) +{ + unsigned char r, g, b; + uint64_t sum = 0; + uint64_t count = 0; + uint64_t value; + uint32_t hash; + int index; + int i; + + for (i=0; i < width * height; i++) { + if ((i % m) != k) + continue; + + index = i * 4; + + r = buffer[index + 2]; + g = buffer[index + 1]; + b = buffer[index + 0]; + + value = r | (g << 8) | (b << 16); + sum += ++count * value; + } + + hash = ((sum >> 0) ^ (sum >> 16) ^ (sum >> 32) ^ (sum >> 48)) & 0x; + + return hash; +} + +/** + * chamelium_calculate_fb_crc: + * @fd: The drm file descriptor + * @fb: The framebuffer to calculate the CRC for + * + * Calculates a CRC for the provided framebuffer, the same way as the Chamelium. + * This calculates the CRC in a non-threaded fashion. + * + * Returns: The calculated CRC + */ +igt_crc_t *chamelium_calculate_fb_crc(int fd, struct igt_fb *fb) +{ + igt_crc_t *ret; + cairo_t *cr; + cairo_surface_t *fb_surface; + unsigned char *buffer; + int n = 4; + int w, h; + int i, j; + + ret = calloc(1, sizeof(igt_crc_t)); + + /* Get the cairo surface for the framebuffer */ + cr = igt_get_cairo_ctx(fd, fb); + fb_surface = cairo_get_target(cr); + cairo_surface_reference(fb_surface); + cairo_destroy(cr); + + buffer = cairo_image_surface_get_data(fb_surface); + w = fb->width; + h = fb->height; + + for (i = 0; i < n; i++) { + j = n - i - 1; + ret->crc[i] = chamelium_xrgb_hash16(buffer, w, h, j, n); + } + + ret->n_words = n; + cairo_surface_destroy(fb_surface); + + return ret; +} + +static void *chamelium_calculate_fb_crc_thread(void *data) +{ + struct chamelium_fb_crc *fb_crc = (struct chamelium_fb_crc *) data; + cairo_t *cr; + cairo_surface_t *fb_surface; + unsigned char *buffer; + int n = 4; + int w, h; + int i, j; + + /* Get the cairo surface for the framebuffer */ + cr = igt_get_cairo_ctx(fb_crc->fd, fb_crc->fb); + fb_surface = cairo_get_target(cr); + cairo_surface_reference(fb_surface); + cairo_destroy(cr); + + buffer = cairo_image_surface_get_data(fb_surface); + w = fb_crc->fb->width; + h = fb_crc->fb->height; + + for (i = 0; i < n; i++) { + j = n - i - 1; + fb_crc->ret->crc[i] = chamelium_xrgb_hash16(buffer, w, h, j, n); + } + + fb_crc->ret->n_words = n; + cairo_surface_destroy(fb_surface); + + return NULL; +} + +/** + * chamelium_calculate_fb_crc_launch: + * @fd: The drm file descriptor + * @fb: The framebuffer to calculate the CRC for + * + * Launches the CRC calculation for the provided framebuffer, the same way as + * the Chamelium. This calculates the CRC in a threaded fashion. + * Thread-related information is returned and should be passed to a subsequent + * call to chamelium_calculate_fb_crc_result. It should not be freed. + * + * Returns: An intermediate structure with thread-related information + */ +struct chamelium_fb_crc *chamelium_calculate_fb_crc_launch(int fd, + struct igt_fb *fb) +{ + struct chamelium_fb_crc *fb_crc; + + fb_crc = calloc(1, sizeof(struct chamelium_fb_crc)); + fb_crc->ret = calloc(1, sizeof(igt_crc_t)); +
[Intel-gfx] [PATCH i-g-t v2 3/4] lib/igt_chamelium: Add support for dumping chamelium frames to a png
This introduces a chamelium_write_frame_to_png function that saves a Chamelium frame dump to a png file. This should be useful when a frame comparison with a reference fails. --- lib/igt_chamelium.c | 32 lib/igt_chamelium.h | 3 +++ 2 files changed, 35 insertions(+) diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c index b9d80b6b..c8719f4d 100644 --- a/lib/igt_chamelium.c +++ b/lib/igt_chamelium.c @@ -978,6 +978,38 @@ void chamelium_assert_frame_eq(const struct chamelium *chamelium, "Chamelium frame dump didn't match reference image\n"); } +void chamelium_write_frame_to_png(const struct chamelium *chamelium, + const struct chamelium_frame_dump *dump, + const char *filename) +{ + cairo_surface_t *dump_surface; + pixman_image_t *image_bgr; + pixman_image_t *image_argb; + int w = dump->width, h = dump->height; + uint32_t *bits_bgr = (uint32_t *) dump->bgr; + unsigned char *bits_argb; + cairo_status_t status; + + image_bgr = pixman_image_create_bits( + PIXMAN_b8g8r8, w, h, bits_bgr, + PIXMAN_FORMAT_BPP(PIXMAN_b8g8r8) / 8 * w); + image_argb = convert_frame_format(image_bgr, PIXMAN_x8r8g8b8); + pixman_image_unref(image_bgr); + + bits_argb = (unsigned char *) pixman_image_get_data(image_argb); + + dump_surface = cairo_image_surface_create_for_data( + bits_argb, CAIRO_FORMAT_ARGB32, w, h, + PIXMAN_FORMAT_BPP(PIXMAN_x8r8g8b8) / 8 * w); + + status = cairo_surface_write_to_png(dump_surface, filename); + cairo_surface_destroy(dump_surface); + + pixman_image_unref(image_argb); + + igt_assert(status == CAIRO_STATUS_SUCCESS); +} + /** * chamelium_get_frame_limit: * @chamelium: The Chamelium instance to use diff --git a/lib/igt_chamelium.h b/lib/igt_chamelium.h index e51cf4f9..908e03d1 100644 --- a/lib/igt_chamelium.h +++ b/lib/igt_chamelium.h @@ -105,6 +105,9 @@ int chamelium_get_frame_limit(struct chamelium *chamelium, void chamelium_assert_frame_eq(const struct chamelium *chamelium, const struct chamelium_frame_dump *dump, struct igt_fb *fb); +void chamelium_write_frame_to_png(const struct chamelium *chamelium, + const struct chamelium_frame_dump *dump, + const char *filename); void chamelium_destroy_frame_dump(struct chamelium_frame_dump *dump); #endif /* IGT_CHAMELIUM_H */ -- 2.13.2 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH i-g-t v2 4/4] chamelium: Dump obtained and reference frames to png on crc error
When a CRC comparison error occurs, it is quite useful to get a dump of both the frame obtained from the chamelium and the reference in order to compare them. This implements the frame dump, with a configurable path that enables the use of this feature. Signed-off-by: Paul Kocialkowski --- lib/igt_chamelium.c | 21 +++ lib/igt_chamelium.h | 1 + lib/igt_debugfs.c | 20 ++ lib/igt_debugfs.h | 1 + tests/chamelium.c | 104 5 files changed, 82 insertions(+), 65 deletions(-) diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c index c8719f4d..ad4a2827 100644 --- a/lib/igt_chamelium.c +++ b/lib/igt_chamelium.c @@ -57,6 +57,7 @@ * |[ * [Chamelium] * URL=http://chameleon:9992 # The URL used for connecting to the Chamelium's RPC server + * FrameDumpPath=/tmp # The path to dump frames that fail comparison checks * * # The rest of the sections are used for defining connector mappings. * # This is required so any tests using the Chamelium know which connector @@ -115,11 +116,26 @@ struct chamelium { struct chamelium_edid *edids; struct chamelium_port *ports; int port_count; + + char *frame_dump_path; }; static struct chamelium *cleanup_instance; /** + * chamelium_get_frame_dump_path: + * @chamelium: The Chamelium instance to use + * + * Retrieves the path to dump frames to. + * + * Returns: a string with the frame dump path + */ +char *chamelium_get_frame_dump_path(struct chamelium *chamelium) +{ + return chamelium->frame_dump_path; +} + +/** * chamelium_get_ports: * @chamelium: The Chamelium instance to use * @count: Where to store the number of ports @@ -1330,6 +1346,11 @@ static bool chamelium_read_config(struct chamelium *chamelium, int drm_fd) return false; } + chamelium->frame_dump_path = g_key_file_get_string(igt_key_file, + "Chamelium", + "FrameDumpPath", + &error); + return chamelium_read_port_mappings(chamelium, drm_fd); } diff --git a/lib/igt_chamelium.h b/lib/igt_chamelium.h index 908e03d1..aa881971 100644 --- a/lib/igt_chamelium.h +++ b/lib/igt_chamelium.h @@ -42,6 +42,7 @@ struct chamelium *chamelium_init(int drm_fd); void chamelium_deinit(struct chamelium *chamelium); void chamelium_reset(struct chamelium *chamelium); +char *chamelium_get_frame_dump_path(struct chamelium *chamelium); struct chamelium_port **chamelium_get_ports(struct chamelium *chamelium, int *count); unsigned int chamelium_port_get_type(const struct chamelium_port *port); diff --git a/lib/igt_debugfs.c b/lib/igt_debugfs.c index 80f25c61..dcb4e0a7 100644 --- a/lib/igt_debugfs.c +++ b/lib/igt_debugfs.c @@ -282,6 +282,26 @@ bool igt_debugfs_search(int device, const char *filename, const char *substring) */ /** + * igt_check_crc_equal: + * @a: first pipe CRC value + * @b: second pipe CRC value + * + * Compares two CRC values and return whether they match. + * + * Returns: A boolean indicating whether the CRC values match + */ +bool igt_check_crc_equal(const igt_crc_t *a, const igt_crc_t *b) +{ + int i; + + for (i = 0; i < a->n_words; i++) + if (a->crc[i] != b->crc[i]) + return false; + + return true; +} + +/** * igt_assert_crc_equal: * @a: first pipe CRC value * @b: second pipe CRC value diff --git a/lib/igt_debugfs.h b/lib/igt_debugfs.h index 7b846a83..2695cbda 100644 --- a/lib/igt_debugfs.h +++ b/lib/igt_debugfs.h @@ -113,6 +113,7 @@ enum intel_pipe_crc_source { INTEL_PIPE_CRC_SOURCE_MAX, }; +bool igt_check_crc_equal(const igt_crc_t *a, const igt_crc_t *b); void igt_assert_crc_equal(const igt_crc_t *a, const igt_crc_t *b); char *igt_crc_to_string(igt_crc_t *crc); diff --git a/tests/chamelium.c b/tests/chamelium.c index 5cf8b3af..3d95c05c 100644 --- a/tests/chamelium.c +++ b/tests/chamelium.c @@ -381,7 +381,7 @@ disable_output(data_t *data, } static void -test_display_crc_single(data_t *data, struct chamelium_port *port) +test_display_crc(data_t *data, struct chamelium_port *port, int count) { igt_display_t display; igt_output_t *output; @@ -390,9 +390,14 @@ test_display_crc_single(data_t *data, struct chamelium_port *port) igt_crc_t *expected_crc; struct chamelium_fb_crc *fb_crc; struct igt_fb fb; + struct chamelium_frame_dump *frame; drmModeModeInfo *mode; drmModeConnector *connector; - int fb_id, i; + int fb_id, i, j, captured_frame_count; + const char *connector_name; + char *frame_dump_path; + char path[PATH_MAX]; + bool eq; reset_state(data, port); @@ -401,6
[Intel-gfx] [PATCH i-g-t v2 2/4] tests/ chamelium: Remove the frame dump tests
The frame dump tests provide no additional functionality over CRC tests and are considerably slower. Thus, these tests should be considered as poorer duplicates and removed. Signed-off-by: Paul Kocialkowski --- tests/chamelium.c | 53 - 1 file changed, 53 deletions(-) diff --git a/tests/chamelium.c b/tests/chamelium.c index 3fd2b02c..5cf8b3af 100644 --- a/tests/chamelium.c +++ b/tests/chamelium.c @@ -496,53 +496,6 @@ test_display_crc_multiple(data_t *data, struct chamelium_port *port) } static void -test_display_frame_dump(data_t *data, struct chamelium_port *port) -{ - igt_display_t display; - igt_output_t *output; - igt_plane_t *primary; - struct igt_fb fb; - struct chamelium_frame_dump *frame; - drmModeModeInfo *mode; - drmModeConnector *connector; - int fb_id, i, j; - - reset_state(data, port); - - output = prepare_output(data, &display, port); - connector = chamelium_port_get_connector(data->chamelium, port, false); - primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY); - igt_assert(primary); - - for (i = 0; i < connector->count_modes; i++) { - mode = &connector->modes[i]; - fb_id = igt_create_color_pattern_fb(data->drm_fd, - mode->hdisplay, mode->vdisplay, - DRM_FORMAT_XRGB, - LOCAL_DRM_FORMAT_MOD_NONE, - 0, 0, 0, &fb); - igt_assert(fb_id > 0); - - enable_output(data, port, output, mode, &fb); - - igt_debug("Reading frame dumps from Chamelium...\n"); - chamelium_capture(data->chamelium, port, 0, 0, 0, 0, 5); - for (j = 0; j < 5; j++) { - frame = chamelium_read_captured_frame( - data->chamelium, j); - chamelium_assert_frame_eq(data->chamelium, frame, &fb); - chamelium_destroy_frame_dump(frame); - } - - disable_output(data, port, output); - igt_remove_fb(data->drm_fd, &fb); - } - - drmModeFreeConnector(connector); - igt_display_fini(&display); -} - -static void test_hpd_without_ddc(data_t *data, struct chamelium_port *port) { struct udev_monitor *mon = igt_watch_hotplug(); @@ -695,9 +648,6 @@ igt_main connector_subtest("dp-crc-multiple", DisplayPort) test_display_crc_multiple(&data, port); - - connector_subtest("dp-frame-dump", DisplayPort) - test_display_frame_dump(&data, port); } igt_subtest_group { @@ -752,9 +702,6 @@ igt_main connector_subtest("hdmi-crc-multiple", HDMIA) test_display_crc_multiple(&data, port); - - connector_subtest("hdmi-frame-dump", HDMIA) - test_display_frame_dump(&data, port); } igt_subtest_group { -- 2.13.2 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH i-g-t v3 1/4] chamelium: Calculate CRC from framebuffer instead of hardcoding it
This introduces CRC calculation for reference frames, instead of using hardcoded values for them. The rendering of reference frames may differ from machine to machine, especially due to font rendering, and the frame itself may change with subsequent IGT changes. These differences would cause the CRC checks to fail on different setups. This allows them to pass regardless of the setup. Signed-off-by: Paul Kocialkowski --- lib/igt_chamelium.c | 160 lib/igt_chamelium.h | 5 ++ tests/chamelium.c | 76 ++--- 3 files changed, 183 insertions(+), 58 deletions(-) diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c index bff08c0e..b9d80b6b 100644 --- a/lib/igt_chamelium.c +++ b/lib/igt_chamelium.c @@ -94,6 +94,14 @@ struct chamelium_frame_dump { struct chamelium_port *port; }; +struct chamelium_fb_crc { + int fd; + struct igt_fb *fb; + + pthread_t thread_id; + igt_crc_t *ret; +}; + struct chamelium { xmlrpc_env env; xmlrpc_client *client; @@ -1003,6 +1011,158 @@ int chamelium_get_frame_limit(struct chamelium *chamelium, return ret; } +static uint32_t chamelium_xrgb_hash16(unsigned char *buffer, int width, + int height, int k, int m) +{ + unsigned char r, g, b; + uint64_t sum = 0; + uint64_t count = 0; + uint64_t value; + uint32_t hash; + int index; + int i; + + for (i=0; i < width * height; i++) { + if ((i % m) != k) + continue; + + index = i * 4; + + r = buffer[index + 2]; + g = buffer[index + 1]; + b = buffer[index + 0]; + + value = r | (g << 8) | (b << 16); + sum += ++count * value; + } + + hash = ((sum >> 0) ^ (sum >> 16) ^ (sum >> 32) ^ (sum >> 48)) & 0x; + + return hash; +} + +/** + * chamelium_calculate_fb_crc: + * @fd: The drm file descriptor + * @fb: The framebuffer to calculate the CRC for + * + * Calculates a CRC for the provided framebuffer, the same way as the Chamelium. + * This calculates the CRC in a non-threaded fashion. + * + * Returns: The calculated CRC + */ +igt_crc_t *chamelium_calculate_fb_crc(int fd, struct igt_fb *fb) +{ + igt_crc_t *ret; + cairo_t *cr; + cairo_surface_t *fb_surface; + unsigned char *buffer; + int n = 4; + int w, h; + int i, j; + + ret = calloc(1, sizeof(igt_crc_t)); + + /* Get the cairo surface for the framebuffer */ + cr = igt_get_cairo_ctx(fd, fb); + fb_surface = cairo_get_target(cr); + cairo_surface_reference(fb_surface); + cairo_destroy(cr); + + buffer = cairo_image_surface_get_data(fb_surface); + w = fb->width; + h = fb->height; + + for (i = 0; i < n; i++) { + j = n - i - 1; + ret->crc[i] = chamelium_xrgb_hash16(buffer, w, h, j, n); + } + + ret->n_words = n; + cairo_surface_destroy(fb_surface); + + return ret; +} + +static void *chamelium_calculate_fb_crc_thread(void *data) +{ + struct chamelium_fb_crc *fb_crc = (struct chamelium_fb_crc *) data; + cairo_t *cr; + cairo_surface_t *fb_surface; + unsigned char *buffer; + int n = 4; + int w, h; + int i, j; + + /* Get the cairo surface for the framebuffer */ + cr = igt_get_cairo_ctx(fb_crc->fd, fb_crc->fb); + fb_surface = cairo_get_target(cr); + cairo_surface_reference(fb_surface); + cairo_destroy(cr); + + buffer = cairo_image_surface_get_data(fb_surface); + w = fb_crc->fb->width; + h = fb_crc->fb->height; + + for (i = 0; i < n; i++) { + j = n - i - 1; + fb_crc->ret->crc[i] = chamelium_xrgb_hash16(buffer, w, h, j, n); + } + + fb_crc->ret->n_words = n; + cairo_surface_destroy(fb_surface); + + return NULL; +} + +/** + * chamelium_calculate_fb_crc_launch: + * @fd: The drm file descriptor + * @fb: The framebuffer to calculate the CRC for + * + * Launches the CRC calculation for the provided framebuffer, the same way as + * the Chamelium. This calculates the CRC in a threaded fashion. + * Thread-related information is returned and should be passed to a subsequent + * call to chamelium_calculate_fb_crc_result. It should not be freed. + * + * Returns: An intermediate structure with thread-related information + */ +struct chamelium_fb_crc *chamelium_calculate_fb_crc_launch(int fd, + struct igt_fb *fb) +{ + struct chamelium_fb_crc *fb_crc; + + fb_crc = calloc(1, sizeof(struct chamelium_fb_crc)); + fb_crc->ret = calloc(1, sizeof(igt_crc_t)); +
[Intel-gfx] [PATCH i-g-t v3 2/4] tests/ chamelium: Remove the frame dump tests
The frame dump tests provide no additional functionality over CRC tests and are considerably slower. Thus, these tests should be considered as poorer duplicates and removed. Signed-off-by: Paul Kocialkowski --- tests/chamelium.c | 53 - 1 file changed, 53 deletions(-) diff --git a/tests/chamelium.c b/tests/chamelium.c index 3fd2b02c..5cf8b3af 100644 --- a/tests/chamelium.c +++ b/tests/chamelium.c @@ -496,53 +496,6 @@ test_display_crc_multiple(data_t *data, struct chamelium_port *port) } static void -test_display_frame_dump(data_t *data, struct chamelium_port *port) -{ - igt_display_t display; - igt_output_t *output; - igt_plane_t *primary; - struct igt_fb fb; - struct chamelium_frame_dump *frame; - drmModeModeInfo *mode; - drmModeConnector *connector; - int fb_id, i, j; - - reset_state(data, port); - - output = prepare_output(data, &display, port); - connector = chamelium_port_get_connector(data->chamelium, port, false); - primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY); - igt_assert(primary); - - for (i = 0; i < connector->count_modes; i++) { - mode = &connector->modes[i]; - fb_id = igt_create_color_pattern_fb(data->drm_fd, - mode->hdisplay, mode->vdisplay, - DRM_FORMAT_XRGB, - LOCAL_DRM_FORMAT_MOD_NONE, - 0, 0, 0, &fb); - igt_assert(fb_id > 0); - - enable_output(data, port, output, mode, &fb); - - igt_debug("Reading frame dumps from Chamelium...\n"); - chamelium_capture(data->chamelium, port, 0, 0, 0, 0, 5); - for (j = 0; j < 5; j++) { - frame = chamelium_read_captured_frame( - data->chamelium, j); - chamelium_assert_frame_eq(data->chamelium, frame, &fb); - chamelium_destroy_frame_dump(frame); - } - - disable_output(data, port, output); - igt_remove_fb(data->drm_fd, &fb); - } - - drmModeFreeConnector(connector); - igt_display_fini(&display); -} - -static void test_hpd_without_ddc(data_t *data, struct chamelium_port *port) { struct udev_monitor *mon = igt_watch_hotplug(); @@ -695,9 +648,6 @@ igt_main connector_subtest("dp-crc-multiple", DisplayPort) test_display_crc_multiple(&data, port); - - connector_subtest("dp-frame-dump", DisplayPort) - test_display_frame_dump(&data, port); } igt_subtest_group { @@ -752,9 +702,6 @@ igt_main connector_subtest("hdmi-crc-multiple", HDMIA) test_display_crc_multiple(&data, port); - - connector_subtest("hdmi-frame-dump", HDMIA) - test_display_frame_dump(&data, port); } igt_subtest_group { -- 2.13.2 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH i-g-t v3 3/4] lib/igt_chamelium: Add support for dumping chamelium frames to a png
This introduces a chamelium_write_frame_to_png function that saves a Chamelium frame dump to a png file. This should be useful when a frame comparison with a reference fails. Signed-off-by: Paul Kocialkowski --- lib/igt_chamelium.c | 40 lib/igt_chamelium.h | 3 +++ 2 files changed, 43 insertions(+) diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c index b9d80b6b..ef51ef68 100644 --- a/lib/igt_chamelium.c +++ b/lib/igt_chamelium.c @@ -979,6 +979,46 @@ void chamelium_assert_frame_eq(const struct chamelium *chamelium, } /** + * chamelium_write_frame_to_png: + * @chamelium: The Chamelium instance to use + * @dump: The chamelium frame dump to save + * @filename: The file name to dump the frame to + * + * Writes a chamelium frame dump into a png image stored at @filename. + */ +void chamelium_write_frame_to_png(const struct chamelium *chamelium, + const struct chamelium_frame_dump *dump, + const char *filename) +{ + cairo_surface_t *dump_surface; + pixman_image_t *image_bgr; + pixman_image_t *image_argb; + int w = dump->width, h = dump->height; + uint32_t *bits_bgr = (uint32_t *) dump->bgr; + unsigned char *bits_argb; + cairo_status_t status; + + image_bgr = pixman_image_create_bits( + PIXMAN_b8g8r8, w, h, bits_bgr, + PIXMAN_FORMAT_BPP(PIXMAN_b8g8r8) / 8 * w); + image_argb = convert_frame_format(image_bgr, PIXMAN_x8r8g8b8); + pixman_image_unref(image_bgr); + + bits_argb = (unsigned char *) pixman_image_get_data(image_argb); + + dump_surface = cairo_image_surface_create_for_data( + bits_argb, CAIRO_FORMAT_ARGB32, w, h, + PIXMAN_FORMAT_BPP(PIXMAN_x8r8g8b8) / 8 * w); + + status = cairo_surface_write_to_png(dump_surface, filename); + cairo_surface_destroy(dump_surface); + + pixman_image_unref(image_argb); + + igt_assert(status == CAIRO_STATUS_SUCCESS); +} + +/** * chamelium_get_frame_limit: * @chamelium: The Chamelium instance to use * @port: The port to check the frame limit on diff --git a/lib/igt_chamelium.h b/lib/igt_chamelium.h index e51cf4f9..908e03d1 100644 --- a/lib/igt_chamelium.h +++ b/lib/igt_chamelium.h @@ -105,6 +105,9 @@ int chamelium_get_frame_limit(struct chamelium *chamelium, void chamelium_assert_frame_eq(const struct chamelium *chamelium, const struct chamelium_frame_dump *dump, struct igt_fb *fb); +void chamelium_write_frame_to_png(const struct chamelium *chamelium, + const struct chamelium_frame_dump *dump, + const char *filename); void chamelium_destroy_frame_dump(struct chamelium_frame_dump *dump); #endif /* IGT_CHAMELIUM_H */ -- 2.13.2 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH i-g-t v3 4/4] chamelium: Dump obtained and reference frames to png on crc error
When a CRC comparison error occurs, it is quite useful to get a dump of both the frame obtained from the chamelium and the reference in order to compare them. This implements the frame dump, with a configurable path that enables the use of this feature. Signed-off-by: Paul Kocialkowski --- lib/igt_chamelium.c | 21 +++ lib/igt_chamelium.h | 1 + lib/igt_debugfs.c | 20 ++ lib/igt_debugfs.h | 1 + tests/chamelium.c | 104 5 files changed, 82 insertions(+), 65 deletions(-) diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c index ef51ef68..9aca6842 100644 --- a/lib/igt_chamelium.c +++ b/lib/igt_chamelium.c @@ -57,6 +57,7 @@ * |[ * [Chamelium] * URL=http://chameleon:9992 # The URL used for connecting to the Chamelium's RPC server + * FrameDumpPath=/tmp # The path to dump frames that fail comparison checks * * # The rest of the sections are used for defining connector mappings. * # This is required so any tests using the Chamelium know which connector @@ -115,11 +116,26 @@ struct chamelium { struct chamelium_edid *edids; struct chamelium_port *ports; int port_count; + + char *frame_dump_path; }; static struct chamelium *cleanup_instance; /** + * chamelium_get_frame_dump_path: + * @chamelium: The Chamelium instance to use + * + * Retrieves the path to dump frames to. + * + * Returns: a string with the frame dump path + */ +char *chamelium_get_frame_dump_path(struct chamelium *chamelium) +{ + return chamelium->frame_dump_path; +} + +/** * chamelium_get_ports: * @chamelium: The Chamelium instance to use * @count: Where to store the number of ports @@ -1338,6 +1354,11 @@ static bool chamelium_read_config(struct chamelium *chamelium, int drm_fd) return false; } + chamelium->frame_dump_path = g_key_file_get_string(igt_key_file, + "Chamelium", + "FrameDumpPath", + &error); + return chamelium_read_port_mappings(chamelium, drm_fd); } diff --git a/lib/igt_chamelium.h b/lib/igt_chamelium.h index 908e03d1..aa881971 100644 --- a/lib/igt_chamelium.h +++ b/lib/igt_chamelium.h @@ -42,6 +42,7 @@ struct chamelium *chamelium_init(int drm_fd); void chamelium_deinit(struct chamelium *chamelium); void chamelium_reset(struct chamelium *chamelium); +char *chamelium_get_frame_dump_path(struct chamelium *chamelium); struct chamelium_port **chamelium_get_ports(struct chamelium *chamelium, int *count); unsigned int chamelium_port_get_type(const struct chamelium_port *port); diff --git a/lib/igt_debugfs.c b/lib/igt_debugfs.c index 80f25c61..dcb4e0a7 100644 --- a/lib/igt_debugfs.c +++ b/lib/igt_debugfs.c @@ -282,6 +282,26 @@ bool igt_debugfs_search(int device, const char *filename, const char *substring) */ /** + * igt_check_crc_equal: + * @a: first pipe CRC value + * @b: second pipe CRC value + * + * Compares two CRC values and return whether they match. + * + * Returns: A boolean indicating whether the CRC values match + */ +bool igt_check_crc_equal(const igt_crc_t *a, const igt_crc_t *b) +{ + int i; + + for (i = 0; i < a->n_words; i++) + if (a->crc[i] != b->crc[i]) + return false; + + return true; +} + +/** * igt_assert_crc_equal: * @a: first pipe CRC value * @b: second pipe CRC value diff --git a/lib/igt_debugfs.h b/lib/igt_debugfs.h index 7b846a83..2695cbda 100644 --- a/lib/igt_debugfs.h +++ b/lib/igt_debugfs.h @@ -113,6 +113,7 @@ enum intel_pipe_crc_source { INTEL_PIPE_CRC_SOURCE_MAX, }; +bool igt_check_crc_equal(const igt_crc_t *a, const igt_crc_t *b); void igt_assert_crc_equal(const igt_crc_t *a, const igt_crc_t *b); char *igt_crc_to_string(igt_crc_t *crc); diff --git a/tests/chamelium.c b/tests/chamelium.c index 5cf8b3af..3d95c05c 100644 --- a/tests/chamelium.c +++ b/tests/chamelium.c @@ -381,7 +381,7 @@ disable_output(data_t *data, } static void -test_display_crc_single(data_t *data, struct chamelium_port *port) +test_display_crc(data_t *data, struct chamelium_port *port, int count) { igt_display_t display; igt_output_t *output; @@ -390,9 +390,14 @@ test_display_crc_single(data_t *data, struct chamelium_port *port) igt_crc_t *expected_crc; struct chamelium_fb_crc *fb_crc; struct igt_fb fb; + struct chamelium_frame_dump *frame; drmModeModeInfo *mode; drmModeConnector *connector; - int fb_id, i; + int fb_id, i, j, captured_frame_count; + const char *connector_name; + char *frame_dump_path; + char path[PATH_MAX]; + bool eq; reset_state(data, port); @@ -401,6
Re: [Intel-gfx] [PATCH i-g-t v3 1/4] chamelium: Calculate CRC from framebuffer instead of hardcoding it
Hi, On Wed, 2017-07-05 at 16:34 -0400, Lyude Paul wrote: > So a couple of notes here that will make it a lot easier for me to > review these in the future > > * When you're doing a new revision of a patch series, it's helpful to >keep it in the same email thread as the original v1 so it's easier >to keep track of in people's mail clients (as well as avoiding >accidentally reviewing older patch versions. I usually do something >like this (other projects might request you do this slightly >differently, but this should be fine here): > * [PATCH 0/2] Cleaning up the alignment of various foos >* [PATCH 1/2] Foo the bar, not the baz >* [PATCH 2/2] Introduce the amazing new foo_bar >* [PATCH v2 0/2] Cleaning up the alignment of various foos > * [PATCH v2 1/2] Foo the bar, not the baz > * [PATCH v2 2/2] Introduce the amazing new foo_bar >* [PATCH v3 0/2] Cleaning up the alignment of various foos > * [PATCH v3 1/2] Foo the bar, not the baz > * [PATCH v3 2/2] Introduce the amazing new foo_bar > * Try not to group unrelated patches together in the same thread. This >also makes sorting through all of them a little more difficult. > * When you make new revisions of patches, it's very useful if you also >include a list of changes you made to the patch since the last >revision. It doesn't need to be very finely detailed, something like >this would suffice: > * Various style fixes > * Rename baz to moo, add cow noises > * Split init_cow() into init_white_cow() and init_black_cow() > instead of handling both kinds of cows in the same function > * Fix documentation > For intel-gpu-tools, it's fine to just stick this in the commit > message. Other projects may request you put the changelog below the > - right above the diff stats (this allows the comments not to > get included in the final commit message) > * Unless they are all very small and less important fixes, including >cover letters helps as well since it lets patchwork group together >patch series like this. Thanks for clarifying these guidelines. I must admit that I have been too lazy to craft cover letters so far, but I'll definitely do it in the future. As for grouping unrelated patches in the same series, I mostly did that to clarify in what order the (unrelated) patches should be applied, but I will specify these dependencies in the cover letters from now on. > Anyway, back to the actual patch: > A good start! Will need a couple of changes though I agree with yout comments and will craft v4 in that direction. Thanks a lot for the review! > On Wed, 2017-07-05 at 11:04 +0300, Paul Kocialkowski wrote: > > This introduces CRC calculation for reference frames, instead of > > using > > hardcoded values for them. The rendering of reference frames may > > differ > > from machine to machine, especially due to font rendering, and the > > frame itself may change with subsequent IGT changes. > > > > These differences would cause the CRC checks to fail on different > > setups. This allows them to pass regardless of the setup. > > > > Signed-off-by: Paul Kocialkowski > > --- > > lib/igt_chamelium.c | 160 > > > > lib/igt_chamelium.h | 5 ++ > > tests/chamelium.c | 76 ++--- > > 3 files changed, 183 insertions(+), 58 deletions(-) > > > > diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c > > index bff08c0e..b9d80b6b 100644 > > --- a/lib/igt_chamelium.c > > +++ b/lib/igt_chamelium.c > > @@ -94,6 +94,14 @@ struct chamelium_frame_dump { > > struct chamelium_port *port; > > }; > > > > +struct chamelium_fb_crc { > > + int fd; > > + struct igt_fb *fb; > > + > > + pthread_t thread_id; > > + igt_crc_t *ret; > > +}; > > + > > The name of this structure is a little misleading, because now we have > an API that exposes both a struct chamelium_fb_crc struct in addition > to the igt_crc_t struct. Rename this to something like struct > chamelium_fb_crc_work > > > struct chamelium { > > xmlrpc_env env; > > xmlrpc_client *client; > > @@ -1003,6 +1011,158 @@ int chamelium_get_frame_limit(struct > > chamelium *chamelium, > > return ret; > > } > > > > +static uint32_t chamelium_xrgb_hash16(unsigned char *buffer, int > > width, > > + int height, int k, int m) > > +{ > > We're not modifying buffer, so make it a const
Re: [Intel-gfx] [PATCH i-g-t v3 4/4] chamelium: Dump obtained and reference frames to png on crc error
Hi, On Wed, 2017-07-05 at 17:44 -0400, Lyude Paul wrote: > On Wed, 2017-07-05 at 11:04 +0300, Paul Kocialkowski wrote: > > When a CRC comparison error occurs, it is quite useful to get a dump > > of both the frame obtained from the chamelium and the reference in > > order > > to compare them. > > > > This implements the frame dump, with a configurable path that enables > > the use of this feature. > > > > Signed-off-by: Paul Kocialkowski > > --- > > lib/igt_chamelium.c | 21 +++ > > lib/igt_chamelium.h | 1 + > > lib/igt_debugfs.c | 20 ++ > > lib/igt_debugfs.h | 1 + > > tests/chamelium.c | 104 > > > > 5 files changed, 82 insertions(+), 65 deletions(-) > > > > diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c > > index ef51ef68..9aca6842 100644 > > --- a/lib/igt_chamelium.c > > +++ b/lib/igt_chamelium.c > > @@ -57,6 +57,7 @@ > > * |[ > > * [Chamelium] > > * URL=http://chameleon:9992 # The URL used for connecting to > > the Chamelium's RPC server > > + * FrameDumpPath=/tmp # The path to dump frames that fail > > comparison checks > > While no one else really cares about creating frame dumps yet, it's > possible someone else may in the future if we ever end up taking more > advantage of automated testing systems like this. So I'd stick this in > the generic non-chamelium specific section in the config file That definitely makes sense. By the way, what approach would you recommend for thishandling? Mupuf was suggesting to have a common configuration structure instead of declaring either global variables or static ones with getters/setters. This is probably becoming more and more of a necessity as we add more common config options. However, I think we should still allow specific parts of IGT to do the parsing themselves (especially in the case of chamelium) so that the common config structure only has common fields (and does not, for instance, contain the chamelium port configuration). > > * > > * # The rest of the sections are used for defining connector > > mappings. > > * # This is required so any tests using the Chamelium know > > which connector > > @@ -115,11 +116,26 @@ struct chamelium { > > struct chamelium_edid *edids; > > struct chamelium_port *ports; > > int port_count; > > + > > + char *frame_dump_path; > > }; > > > > static struct chamelium *cleanup_instance; > > > > /** > > + * chamelium_get_frame_dump_path: > > + * @chamelium: The Chamelium instance to use > > + * > > + * Retrieves the path to dump frames to. > > + * > > + * Returns: a string with the frame dump path > > + */ > > +char *chamelium_get_frame_dump_path(struct chamelium *chamelium) > > +{ > > + return chamelium->frame_dump_path; > > +} > > + > > +/** > > * chamelium_get_ports: > > * @chamelium: The Chamelium instance to use > > * @count: Where to store the number of ports > > @@ -1338,6 +1354,11 @@ static bool chamelium_read_config(struct > > chamelium *chamelium, int drm_fd) > > return false; > > } > > > > + chamelium->frame_dump_path = > > g_key_file_get_string(igt_key_file, > > + "Chameliu > > m", > > + "FrameDum > > pPath", > > + &error); > > + > > return chamelium_read_port_mappings(chamelium, drm_fd); > > } > > > > diff --git a/lib/igt_chamelium.h b/lib/igt_chamelium.h > > index 908e03d1..aa881971 100644 > > --- a/lib/igt_chamelium.h > > +++ b/lib/igt_chamelium.h > > @@ -42,6 +42,7 @@ struct chamelium *chamelium_init(int drm_fd); > > void chamelium_deinit(struct chamelium *chamelium); > > void chamelium_reset(struct chamelium *chamelium); > > > > +char *chamelium_get_frame_dump_path(struct chamelium *chamelium); > > struct chamelium_port **chamelium_get_ports(struct chamelium > > *chamelium, > > int *count); > > unsigned int chamelium_port_get_type(const struct chamelium_port > > *port); > > diff --git a/lib/igt_debugfs.c b/lib/igt_debugfs.c > > index 80f25c61..dcb4e0a7 100644 > > --- a/lib/igt_debugfs.c > > +++ b/lib/igt_debugfs.c > > @@ -282,6 +282,26 @@ bool igt_debugfs_search(int device, const char > > *filename
Re: [Intel-gfx] [PATCH i-g-t v3 4/4] chamelium: Dump obtained and reference frames to png on crc error
On Thu, 2017-07-06 at 10:41 +0300, Martin Peres wrote: > On 06/07/17 00:44, Lyude Paul wrote: > > On Wed, 2017-07-05 at 11:04 +0300, Paul Kocialkowski wrote: > > > When a CRC comparison error occurs, it is quite useful to get a dump > > > of both the frame obtained from the chamelium and the reference in > > > order > > > to compare them. > > > > > > This implements the frame dump, with a configurable path that enables > > > the use of this feature. > > > > > > Signed-off-by: Paul Kocialkowski > > > --- > > > lib/igt_chamelium.c | 21 +++ > > > lib/igt_chamelium.h | 1 + > > > lib/igt_debugfs.c | 20 ++ > > > lib/igt_debugfs.h | 1 + > > > tests/chamelium.c | 104 > > > > > > 5 files changed, 82 insertions(+), 65 deletions(-) > > > > > > diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c > > > index ef51ef68..9aca6842 100644 > > > --- a/lib/igt_chamelium.c > > > +++ b/lib/igt_chamelium.c > > > @@ -57,6 +57,7 @@ > > >* |[ > > >* [Chamelium] > > >* URL=http://chameleon:9992 # The URL used for connecting to > > > the Chamelium's RPC server > > > + * FrameDumpPath=/tmp # The path to dump frames that fail > > > comparison checks > > > > While no one else really cares about creating frame dumps yet, it's > > possible someone else may in the future if we ever end up taking more > > advantage of automated testing systems like this. So I'd stick this in > > the generic non-chamelium specific section in the config file > > > > >* > > >* # The rest of the sections are used for defining connector > > > mappings. > > >* # This is required so any tests using the Chamelium know > > > which connector > > > @@ -115,11 +116,26 @@ struct chamelium { > > > struct chamelium_edid *edids; > > > struct chamelium_port *ports; > > > int port_count; > > > + > > > + char *frame_dump_path; > > > }; > > > > > > static struct chamelium *cleanup_instance; > > > > > > /** > > > + * chamelium_get_frame_dump_path: > > > + * @chamelium: The Chamelium instance to use > > > + * > > > + * Retrieves the path to dump frames to. > > > + * > > > + * Returns: a string with the frame dump path > > > + */ > > > +char *chamelium_get_frame_dump_path(struct chamelium *chamelium) > > > +{ > > > + return chamelium->frame_dump_path; > > > +} > > > + > > > +/** > > >* chamelium_get_ports: > > >* @chamelium: The Chamelium instance to use > > >* @count: Where to store the number of ports > > > @@ -1338,6 +1354,11 @@ static bool chamelium_read_config(struct > > > chamelium *chamelium, int drm_fd) > > > return false; > > > } > > > > > > + chamelium->frame_dump_path = > > > g_key_file_get_string(igt_key_file, > > > +"Chameliu > > > m", > > > +"FrameDum > > > pPath", > > > + &error); > > > + > > > return chamelium_read_port_mappings(chamelium, drm_fd); > > > } > > > > > > diff --git a/lib/igt_chamelium.h b/lib/igt_chamelium.h > > > index 908e03d1..aa881971 100644 > > > --- a/lib/igt_chamelium.h > > > +++ b/lib/igt_chamelium.h > > > @@ -42,6 +42,7 @@ struct chamelium *chamelium_init(int drm_fd); > > > void chamelium_deinit(struct chamelium *chamelium); > > > void chamelium_reset(struct chamelium *chamelium); > > > > > > +char *chamelium_get_frame_dump_path(struct chamelium *chamelium); > > > struct chamelium_port **chamelium_get_ports(struct chamelium > > > *chamelium, > > > int *count); > > > unsigned int chamelium_port_get_type(const struct chamelium_port > > > *port); > > > diff --git a/lib/igt_debugfs.c b/lib/igt_debugfs.c > > > index 80f25c61..dcb4e0a7 100644 > > > --- a/lib/igt_debugfs.c > > > +++ b/lib/igt_debugfs.c > > > @@ -282,6 +282,26 @@ bool igt_d
Re: [Intel-gfx] [PATCH i-g-t v3 1/4] chamelium: Calculate CRC from framebuffer instead of hardcoding it
On Wed, 2017-07-05 at 16:34 -0400, Lyude Paul wrote: > So a couple of notes here that will make it a lot easier for me to > review these in the future > > * When you're doing a new revision of a patch series, it's helpful to >keep it in the same email thread as the original v1 so it's easier >to keep track of in people's mail clients (as well as avoiding >accidentally reviewing older patch versions. I usually do something >like this (other projects might request you do this slightly >differently, but this should be fine here): > * [PATCH 0/2] Cleaning up the alignment of various foos >* [PATCH 1/2] Foo the bar, not the baz >* [PATCH 2/2] Introduce the amazing new foo_bar >* [PATCH v2 0/2] Cleaning up the alignment of various foos > * [PATCH v2 1/2] Foo the bar, not the baz > * [PATCH v2 2/2] Introduce the amazing new foo_bar >* [PATCH v3 0/2] Cleaning up the alignment of various foos > * [PATCH v3 1/2] Foo the bar, not the baz > * [PATCH v3 2/2] Introduce the amazing new foo_bar > * Try not to group unrelated patches together in the same thread. > This >also makes sorting through all of them a little more difficult. > * When you make new revisions of patches, it's very useful if you > also >include a list of changes you made to the patch since the last >revision. It doesn't need to be very finely detailed, something > like >this would suffice: > * Various style fixes > * Rename baz to moo, add cow noises > * Split init_cow() into init_white_cow() and init_black_cow() > instead of handling both kinds of cows in the same function > * Fix documentation > For intel-gpu-tools, it's fine to just stick this in the commit > message. Other projects may request you put the changelog below > the > - right above the diff stats (this allows the comments not to > get included in the final commit message) > * Unless they are all very small and less important fixes, including >cover letters helps as well since it lets patchwork group together >patch series like this. What would you prefer that I do regarding follow-up versions to this patchset (and the other one that is still under review)? I could split the series per-topic (crc, frame save, time improvements) and keep those in the same parent thread as their v1. > Anyway, back to the actual patch: > A good start! Will need a couple of changes though > > On Wed, 2017-07-05 at 11:04 +0300, Paul Kocialkowski wrote: > > This introduces CRC calculation for reference frames, instead of > > using > > hardcoded values for them. The rendering of reference frames may > > differ > > from machine to machine, especially due to font rendering, and the > > frame itself may change with subsequent IGT changes. > > > > These differences would cause the CRC checks to fail on different > > setups. This allows them to pass regardless of the setup. > > > > Signed-off-by: Paul Kocialkowski > > --- > > lib/igt_chamelium.c | 160 > > > > lib/igt_chamelium.h | 5 ++ > > tests/chamelium.c | 76 ++--- > > 3 files changed, 183 insertions(+), 58 deletions(-) > > > > diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c > > index bff08c0e..b9d80b6b 100644 > > --- a/lib/igt_chamelium.c > > +++ b/lib/igt_chamelium.c > > @@ -94,6 +94,14 @@ struct chamelium_frame_dump { > > struct chamelium_port *port; > > }; > > > > +struct chamelium_fb_crc { > > + int fd; > > + struct igt_fb *fb; > > + > > + pthread_t thread_id; > > + igt_crc_t *ret; > > +}; > > + > > The name of this structure is a little misleading, because now we have > an API that exposes both a struct chamelium_fb_crc struct in addition > to the igt_crc_t struct. Rename this to something like struct > chamelium_fb_crc_work > > > struct chamelium { > > xmlrpc_env env; > > xmlrpc_client *client; > > @@ -1003,6 +1011,158 @@ int chamelium_get_frame_limit(struct > > chamelium *chamelium, > > return ret; > > } > > > > +static uint32_t chamelium_xrgb_hash16(unsigned char *buffer, int > > width, > > + int height, int k, int m) > > +{ > > We're not modifying buffer, so make it a const. As well, feel free to > mark this function as inline. > > > + unsigned char r, g, b; > > + uint64_t sum = 0; > > + uint64_t count = 0; > > + uint64_t value;
[Intel-gfx] [PATCH i-g-t 0/1] chamelium: Add support for VGA frame comparison testing
I am only sending this for comments at this point, since this will need to be reworked according to the changes made on previous series still under review. Especially, it will benefit from making the frame save mechanism common. ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH i-g-t] chamelium: Add support for VGA frame comparison testing
This adds support for VGA frame comparison check. Since VGA uses a DAC-ADC chain, its data cannot be expected to be pixel perfect. Thus, it is impossible to uses a CRC check and full frames have to be analyzed instead. Such an analysis is implemented, based on both an absolute error threshold and a correlation with the expected error trend for a DAC-ADC chain. It was tested with a couple encoders and provides reliable error detection with few false positives. In case the frame does not match, it is dumped to a file in a similar fashion as CRC tests. Signed-off-by: Paul Kocialkowski --- configure.ac| 5 +- lib/Makefile.am | 2 + lib/igt_chamelium.c | 235 +++- lib/igt_chamelium.h | 6 +- tests/chamelium.c | 82 ++ 5 files changed, 325 insertions(+), 5 deletions(-) diff --git a/configure.ac b/configure.ac index 0418e605..e7c3603b 100644 --- a/configure.ac +++ b/configure.ac @@ -182,8 +182,9 @@ PKG_CHECK_MODULES(GLIB, glib-2.0) # for chamelium PKG_CHECK_MODULES(XMLRPC, xmlrpc_client, [xmlrpc=yes], [xmlrpc=no]) PKG_CHECK_MODULES(PIXMAN, pixman-1, [pixman=yes], [pixman=no]) -AM_CONDITIONAL(HAVE_CHAMELIUM, [test "x$xmlrpc$pixman" = xyesyes]) -if test x"$xmlrpc$pixman" = xyesyes; then +PKG_CHECK_MODULES(GSL, gsl, [gsl=yes], [gsl=no]) +AM_CONDITIONAL(HAVE_CHAMELIUM, [test "x$xmlrpc$pixman$gsl" = xyesyesyes]) +if test x"$xmlrpc$pixman$gsl" = xyesyesyes; then AC_DEFINE(HAVE_CHAMELIUM, 1, [Enable Chamelium support]) fi diff --git a/lib/Makefile.am b/lib/Makefile.am index d4f41128..fb922ced 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -35,6 +35,7 @@ AM_CFLAGS = \ $(DRM_CFLAGS) \ $(PCIACCESS_CFLAGS) \ $(LIBUNWIND_CFLAGS) \ + $(GSL_CFLAGS) \ $(KMOD_CFLAGS) \ $(PROCPS_CFLAGS) \ $(DEBUG_CFLAGS) \ @@ -54,6 +55,7 @@ libintel_tools_la_LIBADD = \ $(DRM_LIBS) \ $(PCIACCESS_LIBS) \ $(PROCPS_LIBS) \ + $(GSL_LIBS) \ $(KMOD_LIBS) \ $(CAIRO_LIBS) \ $(LIBUDEV_LIBS) \ diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c index 9aca6842..79ea8b4f 100644 --- a/lib/igt_chamelium.c +++ b/lib/igt_chamelium.c @@ -34,6 +34,8 @@ #include #include #include +#include +#include #include "igt.h" @@ -1035,6 +1037,235 @@ void chamelium_write_frame_to_png(const struct chamelium *chamelium, } /** + * chamelium_analogue_frame_crop: + * @chamelium: The Chamelium instance to use + * @dump: The chamelium frame dump to crop + * @width: The cropped frame width + * @height: The cropped frame height + * + * Detects the corners of a chamelium frame and crops it to the requested + * width/height. This is useful for VGA frame dumps that also contain the + * pixels dumped during the blanking intervals. + * + * The detection is done on a brightness-threshold-basis, that is adapted + * to the reference frame used by i-g-t. It may not be as relevant for other + * frames. + */ +void chamelium_crop_analogue_frame(struct chamelium_frame_dump *dump, int width, + int height) +{ + unsigned char *bgr; + unsigned char *p; + unsigned char *q; + int top, left; + int x, y, xx, yy; + int score; + + if (dump->width == width && dump->height == height) + return; + + /* Start with the most bottom-right position. */ + top = dump->height - height; + left = dump->width - width; + + igt_assert(top >= 0 && left >= 0); + + igt_debug("Cropping analogue frame from %dx%d to %dx%d\n", dump->width, + dump->height, width, height); + + /* Detect the top-left corner of the frame. */ + for (x = 0; x < dump->width; x++) { + for (y = 0; y < dump->height; y++) { + p = &dump->bgr[(x + y * dump->width) * 3]; + + /* Detect significantly bright pixels. */ + if (p[0] < 50 && p[1] < 50 && p[2] < 50) + continue; + + /* +* Make sure close-by pixels are also significantly +* bright. +*/ + score = 0; + for (xx = x; xx < x + 10; xx++) { + for (yy = y; yy < y + 10; yy++) { + p = &dump->bgr[(xx + yy * dump->width) * 3]; + + if (p[0] > 50 && p[1] > 50 && p[2] > 50) + score++; + } + } + + /* Not enough pixels are significantly bright. */ +
[Intel-gfx] [PATCH i-g-t 0/1] tests/chamelium: Detect analogue bridges and handle EDID accordingly
This patch applies on top of: chamelium: Add support for VGA frame comparison testing. ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH i-g-t] tests/chamelium: Detect analogue bridges and handle EDID accordingly
Nowadays, many VGA connectors are not actually native VGA but use a discrete bridge to a digital connector. These bridges usually enforce their own EDID instead of the one supplied by the chamelium. Thus, the EDID read test for VGA is not relevant in that case and should be skipped. Reported modes may also go beyond what the chamelium can support. Thus, only supported resolutions should be tested for the frame dump test and others should be pruned. Signed-off-by: Paul Kocialkowski --- tests/chamelium.c | 78 +++ 1 file changed, 78 insertions(+) diff --git a/tests/chamelium.c b/tests/chamelium.c index 5ccdee7c..d26846ba 100644 --- a/tests/chamelium.c +++ b/tests/chamelium.c @@ -106,6 +106,76 @@ wait_for_connector(data_t *data, struct chamelium_port *port, igt_assert(finished); } +static int chamelium_vga_modes[][2] = { + { 1600, 1200 }, + { 1920, 1200 }, + { 1920, 1080 }, + { 1680, 1050 }, + { 1280, 1024 }, + { 1280, 960 }, + { 1440, 900 }, + { 1280, 800 }, + { 1024, 768 }, + { 1360, 768 }, + { 1280, 720 }, + { 800, 600 }, + { 640, 480 }, + { -1, -1 }, +}; + +static bool +prune_vga_mode(data_t *data, drmModeModeInfo *mode) +{ + int i = 0; + + while (chamelium_vga_modes[i][0] != -1) { + if (mode->hdisplay == chamelium_vga_modes[i][0] && + mode->vdisplay == chamelium_vga_modes[i][1]) + return false; + + i++; + } + + return true; +} + +static bool +check_analogue_bridge(data_t *data, struct chamelium_port *port) +{ + drmModePropertyBlobPtr edid_blob = NULL; + drmModeConnector *connector = chamelium_port_get_connector( + data->chamelium, port, false); + uint64_t edid_blob_id; + unsigned char *edid; + char edid_vendor[3]; + + if (chamelium_port_get_type(port) != DRM_MODE_CONNECTOR_VGA) + return false; + + igt_assert(kmstest_get_property(data->drm_fd, connector->connector_id, + DRM_MODE_OBJECT_CONNECTOR, "EDID", NULL, + &edid_blob_id, NULL)); + igt_assert(edid_blob = drmModeGetPropertyBlob(data->drm_fd, + edid_blob_id)); + + edid = (unsigned char *) edid_blob->data; + + edid_vendor[0] = ((edid[8] & 0x7c) >> 2) + '@'; + edid_vendor[1] = (((edid[8] & 0x03) << 3) | + ((edid[9] & 0xe0) >> 5)) + '@'; + edid_vendor[2] = (edid[9] & 0x1f) + '@'; + + /* Analogue bridges provide their own EDID */ + if (edid_vendor[0] != 'I' || edid_vendor[1] != 'G' || + edid_vendor[0] != 'T') + return true; + + drmModeFreePropertyBlob(edid_blob); + drmModeFreeConnector(connector); + + return false; +} + static void reset_state(data_t *data, struct chamelium_port *port) { @@ -170,6 +240,8 @@ test_edid_read(data_t *data, struct chamelium_port *port, chamelium_plug(data->chamelium, port); wait_for_connector(data, port, DRM_MODE_CONNECTED, true); + igt_skip_on(check_analogue_bridge(data, port)); + igt_assert(kmstest_get_property(data->drm_fd, connector->connector_id, DRM_MODE_OBJECT_CONNECTOR, "EDID", NULL, &edid_blob_id, NULL)); @@ -487,6 +559,7 @@ test_analogue_frame_dump(data_t *data, struct chamelium_port *port) const char *connector_name; char *frame_dump_path; char path[PATH_MAX]; + bool bridge; bool eq; output = prepare_output(data, &display, port); @@ -497,9 +570,14 @@ test_analogue_frame_dump(data_t *data, struct chamelium_port *port) connector_name = kmstest_connector_type_str(connector->connector_type); frame_dump_path = chamelium_get_frame_dump_path(data->chamelium); + bridge = check_analogue_bridge(data, port); + for (i = 0; i < connector->count_modes; i++) { mode = &connector->modes[i]; + if (bridge && prune_vga_mode(data, mode)) + continue; + fb_id = igt_create_color_pattern_fb(data->drm_fd, mode->hdisplay, mode->vdisplay, DRM_FORMAT_XRGB, -- 2.13.2 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH i-g-t v3 2/4] tests/ chamelium: Remove the frame dump tests
On Wed, 2017-07-05 at 16:53 -0400, Lyude Paul wrote: > NAK. You're right that these don't actually give us any advantage over > just using CRCs and are just slower, however I left these tests in > here > moreso just so we had something to actually test the frame dumping > functions so that we could avoid regressing them by accident since > we're the only users of those functions right now. Also, note that the VGA testing patch (that I just sent to the list) does make use of these functions (maybe not all of them though), since using the CRC is not possible for VGA. > If I recall properly, isn't there a list of tests in igt's source that > they use for determining which tests to run on the CI? I think a > better > solution would be to just disable this for CI runs, and maybe add some > comments pointing out that this test is only really useful for > developers making changes to the chamelium library. > > On Wed, 2017-07-05 at 11:04 +0300, Paul Kocialkowski wrote: > > The frame dump tests provide no additional functionality over CRC > > tests > > and are considerably slower. Thus, these tests should be considered > > as > > poorer duplicates and removed. > > > > Signed-off-by: Paul Kocialkowski > > --- > > tests/chamelium.c | 53 --- > > -- > > 1 file changed, 53 deletions(-) > > > > diff --git a/tests/chamelium.c b/tests/chamelium.c > > index 3fd2b02c..5cf8b3af 100644 > > --- a/tests/chamelium.c > > +++ b/tests/chamelium.c > > @@ -496,53 +496,6 @@ test_display_crc_multiple(data_t *data, struct > > chamelium_port *port) > > } > > > > static void > > -test_display_frame_dump(data_t *data, struct chamelium_port *port) > > -{ > > - igt_display_t display; > > - igt_output_t *output; > > - igt_plane_t *primary; > > - struct igt_fb fb; > > - struct chamelium_frame_dump *frame; > > - drmModeModeInfo *mode; > > - drmModeConnector *connector; > > - int fb_id, i, j; > > - > > - reset_state(data, port); > > - > > - output = prepare_output(data, &display, port); > > - connector = chamelium_port_get_connector(data->chamelium, > > port, false); > > - primary = igt_output_get_plane_type(output, > > DRM_PLANE_TYPE_PRIMARY); > > - igt_assert(primary); > > - > > - for (i = 0; i < connector->count_modes; i++) { > > - mode = &connector->modes[i]; > > - fb_id = igt_create_color_pattern_fb(data->drm_fd, > > - mode->hdisplay, > > mode->vdisplay, > > - DRM_FORMAT_XRGB > > 8 > > 888, > > - LOCAL_DRM_FORMA > > T > > _MOD_NONE, > > - 0, 0, 0, &fb); > > - igt_assert(fb_id > 0); > > - > > - enable_output(data, port, output, mode, &fb); > > - > > - igt_debug("Reading frame dumps from > > Chamelium...\n"); > > - chamelium_capture(data->chamelium, port, 0, 0, 0, > > 0, > > 5); > > - for (j = 0; j < 5; j++) { > > - frame = chamelium_read_captured_frame( > > - data->chamelium, j); > > - chamelium_assert_frame_eq(data->chamelium, > > frame, &fb); > > - chamelium_destroy_frame_dump(frame); > > - } > > - > > - disable_output(data, port, output); > > - igt_remove_fb(data->drm_fd, &fb); > > - } > > - > > - drmModeFreeConnector(connector); > > - igt_display_fini(&display); > > -} > > - > > -static void > > test_hpd_without_ddc(data_t *data, struct chamelium_port *port) > > { > > struct udev_monitor *mon = igt_watch_hotplug(); > > @@ -695,9 +648,6 @@ igt_main > > > > connector_subtest("dp-crc-multiple", DisplayPort) > > test_display_crc_multiple(&data, port); > > - > > - connector_subtest("dp-frame-dump", DisplayPort) > > - test_display_frame_dump(&data, port); > > } > > > > igt_subtest_group { > > @@ -752,9 +702,6 @@ igt_main > > > > connector_subtest("hdmi-crc-multiple", HDMIA) > > test_display_crc_multiple(&data, port); > > - > > - connector_subtest("hdmi-frame-dump", HDMIA) > > - test_display_frame_dump(&data, port); > > } > > > > igt_subtest_group { -- Paul Kocialkowski Intel Finland Oy - BIC 0357606-4 - Westendinkatu 7, 02160 Espoo, Finland ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH i-g-t v3 4/4] chamelium: Dump obtained and reference frames to png on crc error
On Thu, 2017-07-06 at 14:31 +0300, Paul Kocialkowski wrote: > Hi, > > On Wed, 2017-07-05 at 17:44 -0400, Lyude Paul wrote: > > On Wed, 2017-07-05 at 11:04 +0300, Paul Kocialkowski wrote: > > > When a CRC comparison error occurs, it is quite useful to get a > > > dump > > > of both the frame obtained from the chamelium and the reference in > > > order > > > to compare them. > > > > > > This implements the frame dump, with a configurable path that > > > enables > > > the use of this feature. > > > > > > Signed-off-by: Paul Kocialkowski > > m> > > > --- > > > lib/igt_chamelium.c | 21 +++ > > > lib/igt_chamelium.h | 1 + > > > lib/igt_debugfs.c | 20 ++ > > > lib/igt_debugfs.h | 1 + > > > tests/chamelium.c | 104 --- > > > - > > > > > > 5 files changed, 82 insertions(+), 65 deletions(-) > > > > > > diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c > > > index ef51ef68..9aca6842 100644 > > > --- a/lib/igt_chamelium.c > > > +++ b/lib/igt_chamelium.c > > > @@ -57,6 +57,7 @@ > > > * |[ > > > * [Chamelium] > > > * URL=http://chameleon:9992 # The URL used for connecting > > > to > > > the Chamelium's RPC server > > > + * FrameDumpPath=/tmp # The path to dump frames that fail > > > comparison checks > > > > While no one else really cares about creating frame dumps yet, it's > > possible someone else may in the future if we ever end up taking > > more > > advantage of automated testing systems like this. So I'd stick this > > in > > the generic non-chamelium specific section in the config file > > That definitely makes sense. By the way, what approach would you > recommend for > thishandling? Mupuf was suggesting to have a common configuration > structure > instead of declaring either global variables or static ones with > getters/setters. This is probably becoming more and more of a > necessity as we > add more common config options. > > However, I think we should still allow specific parts of IGT to do the > parsing > themselves (especially in the case of chamelium) so that the common > config > structure only has common fields (and does not, for instance, contain > the > chamelium port configuration). > > > > * > > > * # The rest of the sections are used for defining > > > connector > > > mappings. > > > * # This is required so any tests using the Chamelium > > > know > > > which connector > > > @@ -115,11 +116,26 @@ struct chamelium { > > > struct chamelium_edid *edids; > > > struct chamelium_port *ports; > > > int port_count; > > > + > > > + char *frame_dump_path; > > > }; > > > > > > static struct chamelium *cleanup_instance; > > > > > > /** > > > + * chamelium_get_frame_dump_path: > > > + * @chamelium: The Chamelium instance to use > > > + * > > > + * Retrieves the path to dump frames to. > > > + * > > > + * Returns: a string with the frame dump path > > > + */ > > > +char *chamelium_get_frame_dump_path(struct chamelium *chamelium) > > > +{ > > > + return chamelium->frame_dump_path; > > > +} > > > + > > > +/** > > > * chamelium_get_ports: > > > * @chamelium: The Chamelium instance to use > > > * @count: Where to store the number of ports > > > @@ -1338,6 +1354,11 @@ static bool chamelium_read_config(struct > > > chamelium *chamelium, int drm_fd) > > > return false; > > > } > > > > > > + chamelium->frame_dump_path = > > > g_key_file_get_string(igt_key_file, > > > +"Chame > > > liu > > > m", > > > +"Frame > > > Dum > > > pPath", > > > + &erro > > > r); > > > + > > > return chamelium_read_port_mappings(chamelium, drm_fd); > > > } > > > > > > diff --git a/lib/igt_chamelium.h b/lib/igt_chamelium.h > > > index 908e03d1..aa881971 100644 > > > --- a/lib/igt_chamelium.h > > > +++ b/lib/igt_chamelium.h > > > @@ -42,6 +42,7 @@ s
Re: [Intel-gfx] [PATCH i-g-t v3 4/4] chamelium: Dump obtained and reference frames to png on crc error
On Thu, 2017-07-06 at 18:23 -0400, Lyude Paul wrote: > On Thu, 2017-07-06 at 14:35 +0300, Paul Kocialkowski wrote: > > On Thu, 2017-07-06 at 10:41 +0300, Martin Peres wrote: > > > On 06/07/17 00:44, Lyude Paul wrote: > > > > On Wed, 2017-07-05 at 11:04 +0300, Paul Kocialkowski wrote: > > > > > When a CRC comparison error occurs, it is quite useful to get > > > > > a > > > > > dump > > > > > of both the frame obtained from the chamelium and the > > > > > reference > > > > > in > > > > > order > > > > > to compare them. > > > > > > > > > > This implements the frame dump, with a configurable path that > > > > > enables > > > > > the use of this feature. > > > > > > > > > > Signed-off-by: Paul Kocialkowski > > > > l > > > > > .com> > > > > > --- > > > > > lib/igt_chamelium.c | 21 +++ > > > > > lib/igt_chamelium.h | 1 + > > > > > lib/igt_debugfs.c | 20 ++ > > > > > lib/igt_debugfs.h | 1 + > > > > > tests/chamelium.c | 104 > > > > > --- > > > > > - > > > > > > > > > > 5 files changed, 82 insertions(+), 65 deletions(-) > > > > > > > > > > diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c > > > > > index ef51ef68..9aca6842 100644 > > > > > --- a/lib/igt_chamelium.c > > > > > +++ b/lib/igt_chamelium.c > > > > > @@ -57,6 +57,7 @@ > > > > >* |[ > > > > >* [Chamelium] > > > > >* URL=http://chameleon:9992 # The URL used for > > > > > connecting to > > > > > the Chamelium's RPC server > > > > > + * FrameDumpPath=/tmp # The path to dump frames that > > > > > fail > > > > > comparison checks > > > > > > > > While no one else really cares about creating frame dumps yet, > > > > it's > > > > possible someone else may in the future if we ever end up taking > > > > more > > > > advantage of automated testing systems like this. So I'd stick > > > > this in > > > > the generic non-chamelium specific section in the config file > > > > > > > > >* > > > > >* # The rest of the sections are used for defining > > > > > connector > > > > > mappings. > > > > >* # This is required so any tests using the > > > > > Chamelium > > > > > know > > > > > which connector > > > > > @@ -115,11 +116,26 @@ struct chamelium { > > > > > struct chamelium_edid *edids; > > > > > struct chamelium_port *ports; > > > > > int port_count; > > > > > + > > > > > + char *frame_dump_path; > > > > > }; > > > > > > > > > > static struct chamelium *cleanup_instance; > > > > > > > > > > /** > > > > > + * chamelium_get_frame_dump_path: > > > > > + * @chamelium: The Chamelium instance to use > > > > > + * > > > > > + * Retrieves the path to dump frames to. > > > > > + * > > > > > + * Returns: a string with the frame dump path > > > > > + */ > > > > > +char *chamelium_get_frame_dump_path(struct chamelium > > > > > *chamelium) > > > > > +{ > > > > > + return chamelium->frame_dump_path; > > > > > +} > > > > > + > > > > > +/** > > > > >* chamelium_get_ports: > > > > >* @chamelium: The Chamelium instance to use > > > > >* @count: Where to store the number of ports > > > > > @@ -1338,6 +1354,11 @@ static bool > > > > > chamelium_read_config(struct > > > > > chamelium *chamelium, int drm_fd) > > > > > return false; > > > > > } > > > > > > > > > > + chamelium->frame_dump_path = > > > > > g_key_file_get_string(igt_key_file, > > > > > +"
Re: [Intel-gfx] [PATCH i-g-t v3 4/4] chamelium: Dump obtained and reference frames to png on crc error
On Thu, 2017-07-06 at 17:57 -0400, Lyude Paul wrote: > --snip-- > (also sorry this one took a while to get to, had to do a lot of > thinking because I never really solved the problems mentioned here > when > I tried working on this...) > > On Thu, 2017-07-06 at 16:33 +0300, Paul Kocialkowski wrote: > > On Thu, 2017-07-06 at 14:31 +0300, Paul Kocialkowski wrote: > > > > > > > > There's lots of potential here for copy pasta to form in the > > > > future, > > > > since the API here puts a lot of work on the caller to set > > > > things > > > > up > > > > for frame dumping. IMO, it would be worth it to teach the CRC > > > > checking > > > > functions to automatically do frame dumps on mismatch if the CRC > > > > source > > > > supports it. This will save us from having to have separate > > > > frame > > > > dump > > > > APIs in the future if we ever end up adding support for other > > > > kinds > > > > of > > > > automated test equipment. > > > > > > I don't think it makes so much sense to do this in the CRC > > > checking > > > functions, > > > just because they are semantically expected to do one thing: CRC > > > checking, and > > > doing frame dumps seems like going overboard. > > > > > > On the other hand, I do agree that the dumping and saving part can > > > and > > > should be > > > made common, but maybe as a separate function. So that would be > > > two > > > calls for > > > the tests: one to check the crc and one to dump and save the > > > frame. > > > > A strong case to support this vision: in VGA frame testing, we have > > already dumped the frame and don't do CRC checking, yet we also need > > to > > save the frames if there is a mismatch. > > > > It would be a shame that the dumping logic becomes part of the CRC > > functions, since that would mean duplicating that logic for VGA > > testing > > (as it's currently done in the version I just sent out). > > That is a good point, but there's some things I think you might want > to > consider. Mainly that in a test that passes, we of course don't write > any framedumps back to the disk since nothing failed. IMO, I would > -think- that we care a bit more about the performance hit that happens > on passing tests vs. failing tests, since tests aren't really supposed > to fail under ideal conditions anyway. Might be better to verify with > the mupuf and the other people actually running Intel's CI though, > since I'm not one of them. > > As well, one advantage we do have here from the chamelium end is that > you can only really be screen grabbing from one port at a time. So you > could actually just track stuff internally in the igt_chamelium API > and > when a user tries to download a framedump that we've already > downloaded, we can just hand them back a cached copy of it. Either way, it is definitely okay to take the time to dump the frame when a mismatch occurs if we don't have it already (in the CRC case). > > > > In spite of that, I think having a common function, called from the > > test > > itself is probably the best approach here. > > Not sure if I misspoke here but I didn't mean to imply that I'm > against > having functions for doing frame dumping exposed to the callers. I had > already figured there'd probably be situations where just having the > CRC checking do the frame dumping wouldn't be enough. > > This being said though, your viewpoint does make me realize it might > not be a great idea to do autoframe dumping in -all- crc checking > functions necessarily, but also makes me realize that this might even > be a requirement if we still want to try keeping around > igt_assert_crc_equal() and not just replace it outright with a > function > that doesn't fail the whole test (if we fail the test, there isn't > really a way we can do a framedump from it afterwards). So I would > think we can at least exclude igt_check_crc_equal() from doing > automatic framedumping, but I still think it would be a good idea to > implement igt_assert_crc_equal(). igt_assert_crc_equal already exists and is used by many other tests, so we really cannot embed the frame dumping logic there, since these tests have nothing to do with the chamelium. That's another reason to really keep the frame dump and crc comparison logic separate. > As for the what you're talking about, e.g. doing frame dump > com
Re: [Intel-gfx] [PATCH i-g-t v3 4/4] chamelium: Dump obtained and reference frames to png on crc error
On Thu, 2017-07-06 at 17:57 -0400, Lyude Paul wrote: > --snip-- > (also sorry this one took a while to get to, had to do a lot of > thinking because I never really solved the problems mentioned here > when > I tried working on this...) > > On Thu, 2017-07-06 at 16:33 +0300, Paul Kocialkowski wrote: > > On Thu, 2017-07-06 at 14:31 +0300, Paul Kocialkowski wrote: > > > > > > > > There's lots of potential here for copy pasta to form in the > > > > future, > > > > since the API here puts a lot of work on the caller to set > > > > things > > > > up > > > > for frame dumping. IMO, it would be worth it to teach the CRC > > > > checking > > > > functions to automatically do frame dumps on mismatch if the CRC > > > > source > > > > supports it. This will save us from having to have separate > > > > frame > > > > dump > > > > APIs in the future if we ever end up adding support for other > > > > kinds > > > > of > > > > automated test equipment. > > > > > > I don't think it makes so much sense to do this in the CRC > > > checking > > > functions, > > > just because they are semantically expected to do one thing: CRC > > > checking, and > > > doing frame dumps seems like going overboard. > > > > > > On the other hand, I do agree that the dumping and saving part can > > > and > > > should be > > > made common, but maybe as a separate function. So that would be > > > two > > > calls for > > > the tests: one to check the crc and one to dump and save the > > > frame. > > > > A strong case to support this vision: in VGA frame testing, we have > > already dumped the frame and don't do CRC checking, yet we also need > > to > > save the frames if there is a mismatch. > > > > It would be a shame that the dumping logic becomes part of the CRC > > functions, since that would mean duplicating that logic for VGA > > testing > > (as it's currently done in the version I just sent out). > > That is a good point, but there's some things I think you might want > to > consider. Mainly that in a test that passes, we of course don't write > any framedumps back to the disk since nothing failed. IMO, I would > -think- that we care a bit more about the performance hit that happens > on passing tests vs. failing tests, since tests aren't really supposed > to fail under ideal conditions anyway. Might be better to verify with > the mupuf and the other people actually running Intel's CI though, > since I'm not one of them. > > As well, one advantage we do have here from the chamelium end is that > you can only really be screen grabbing from one port at a time. So you > could actually just track stuff internally in the igt_chamelium API > and when a user tries to download a framedump that we've already > downloaded, we can just hand them back a cached copy of it. I forgot to answer this point. I think this bring way too much overhead and is not really necessary anyway. With the solution I proposed in my previous email on this thread, the two wrapper functions (one for CRC, one for analogue frame comparison) will either dump the frame for CRC comparison (because it was never dumped before) or use the provided one for analogue comparison, so there is no particular need to track what was or wasn't dumped before. > > In spite of that, I think having a common function, called from the > > test > > itself is probably the best approach here. > > Not sure if I misspoke here but I didn't mean to imply that I'm > against > having functions for doing frame dumping exposed to the callers. I had > already figured there'd probably be situations where just having the > CRC checking do the frame dumping wouldn't be enough. > > This being said though, your viewpoint does make me realize it might > not be a great idea to do autoframe dumping in -all- crc checking > functions necessarily, but also makes me realize that this might even > be a requirement if we still want to try keeping around > igt_assert_crc_equal() and not just replace it outright with a > function > that doesn't fail the whole test (if we fail the test, there isn't > really a way we can do a framedump from it afterwards). So I would > think we can at least exclude igt_check_crc_equal() from doing > automatic framedumping, but I still think it would be a good idea to > implement igt_assert_crc_equal(). > > As for the what you're talking about,
Re: [Intel-gfx] [PATCH i-g-t v3 4/4] chamelium: Dump obtained and reference frames to png on crc error
On Mon, 2017-07-10 at 13:33 +0300, Martin Peres wrote: > On 10/07/17 13:31, Paul Kocialkowski wrote: > > On Thu, 2017-07-06 at 17:57 -0400, Lyude Paul wrote: > > > > > > As well, one advantage we do have here from the chamelium end is > > > that > > > you can only really be screen grabbing from one port at a time. So > > > you > > > could actually just track stuff internally in the igt_chamelium > > > API > > > and when a user tries to download a framedump that we've already > > > downloaded, we can just hand them back a cached copy of it. > > > > I forgot to answer this point. I think this bring way too much > > overhead > > and is not really necessary anyway. With the solution I proposed in > > my > > previous email on this thread, the two wrapper functions (one for > > CRC, > > one for analogue frame comparison) will either dump the frame for > > CRC > > comparison (because it was never dumped before) or use the provided > > one > > for analogue comparison, so there is no particular need to track > > what > > was or wasn't dumped before. > > No need to track, just encode it in the filename: > $test-$subtest-error-crc-$crc.png > > Just do not override existing files, and you are done :) I suppose it would be best to have predictible filenames (so not including the crc) to make it easier to grab the frame for an automated testing framework, right? So what about: frame-$test-$subtest-$qualifier.png, with $qualifier being either "reference" or "dump". I don't think it's necessary to indicate whether the error comes from crc or analogue frame testing: this will already be contained in the subtest name. -- Paul Kocialkowski Intel Finland Oy - BIC 0357606-4 - Westendinkatu 7, 02160 Espoo, Finland ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH i-g-t v3 4/4] chamelium: Dump obtained and reference frames to png on crc error
On Mon, 2017-07-10 at 16:56 +0300, Martin Peres wrote: > On 10/07/17 15:06, Paul Kocialkowski wrote: > > On Mon, 2017-07-10 at 13:33 +0300, Martin Peres wrote: > > > On 10/07/17 13:31, Paul Kocialkowski wrote: > > > > On Thu, 2017-07-06 at 17:57 -0400, Lyude Paul wrote: > > > > > > > > > > As well, one advantage we do have here from the chamelium end > > > > > is > > > > > that > > > > > you can only really be screen grabbing from one port at a > > > > > time. So > > > > > you > > > > > could actually just track stuff internally in the > > > > > igt_chamelium > > > > > API > > > > > and when a user tries to download a framedump that we've > > > > > already > > > > > downloaded, we can just hand them back a cached copy of it. > > > > > > > > I forgot to answer this point. I think this bring way too much > > > > overhead > > > > and is not really necessary anyway. With the solution I proposed > > > > in > > > > my > > > > previous email on this thread, the two wrapper functions (one > > > > for > > > > CRC, > > > > one for analogue frame comparison) will either dump the frame > > > > for > > > > CRC > > > > comparison (because it was never dumped before) or use the > > > > provided > > > > one > > > > for analogue comparison, so there is no particular need to track > > > > what > > > > was or wasn't dumped before. > > > > > > No need to track, just encode it in the filename: > > > $test-$subtest-error-crc-$crc.png > > > > > > Just do not override existing files, and you are done :) > > > > I suppose it would be best to have predictible filenames (so not > > including the crc) to make it easier to grab the frame for an > > automated > > testing framework, right? > > > So what about: frame-$test-$subtest-$qualifier.png, with $qualifier > > being either "reference" or "dump". I don't think it's necessary to > > indicate whether the error comes from crc or analogue frame testing: > > this will already be contained in the subtest name. > > > > Well, predictable is actually problematic, since automated systems > try > to reproduce issues, and your idea will lead to overriding (which is > only not a problem if the CRC is the same). That is, unless the automated system moves the file around from the predictable name to whatever suits it best (that may include which run the result is part of). > In the end, what we want is to say in the logs what are the files > (reference and dump). We'll need to agree on a format, so as an > automated system can pick it up :) Parsing logs sound like a hackish way to do things quite honestly. Just having a predictable name and moving the file wherever relevant seems a lot easier on all sides. Also, since we're making the code for frame dumping independent from whether it comes from crc or full frame testing, it doesn't play out too well to carry the crc result until the point of writing the png file. -- Paul Kocialkowski Intel Finland Oy - BIC 0357606-4 - Westendinkatu 7, 02160 Espoo, Finland ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH i-g-t v4 1/7] lib/igt_fb: Export the cairo surface instead of writing to a png
This removes the igt_write_fb_to_png function (that was unused thus far) and exports the igt_get_cairo_surface function to grab the matching cairo surface. Writing to a png is now handled by the common frame handling code in lib/igt_frame. This also fixes how the surface is retreived in chamelium code, which avoids destroying it too early. Signed-off-by: Paul Kocialkowski --- lib/igt_chamelium.c | 7 +-- lib/igt_fb.c| 36 +--- lib/igt_fb.h| 2 +- 3 files changed, 15 insertions(+), 30 deletions(-) diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c index bff08c0e..93392af7 100644 --- a/lib/igt_chamelium.c +++ b/lib/igt_chamelium.c @@ -936,17 +936,13 @@ void chamelium_assert_frame_eq(const struct chamelium *chamelium, const struct chamelium_frame_dump *dump, struct igt_fb *fb) { - cairo_t *cr; cairo_surface_t *fb_surface; pixman_image_t *reference_src, *reference_bgr; int w = dump->width, h = dump->height; bool eq; /* Get the cairo surface for the framebuffer */ - cr = igt_get_cairo_ctx(chamelium->drm_fd, fb); - fb_surface = cairo_get_target(cr); - cairo_surface_reference(fb_surface); - cairo_destroy(cr); + fb_surface = igt_get_cairo_surface(chamelium->drm_fd, fb); /* * Convert the reference image into the same format as the chamelium @@ -964,7 +960,6 @@ void chamelium_assert_frame_eq(const struct chamelium *chamelium, dump->size) == 0; pixman_image_unref(reference_bgr); - cairo_surface_destroy(fb_surface); igt_fail_on_f(!eq, "Chamelium frame dump didn't match reference image\n"); diff --git a/lib/igt_fb.c b/lib/igt_fb.c index d2b7e9e3..93e21c17 100644 --- a/lib/igt_fb.c +++ b/lib/igt_fb.c @@ -1124,7 +1124,18 @@ static void create_cairo_surface__gtt(int fd, struct igt_fb *fb) fb, destroy_cairo_surface__gtt); } -static cairo_surface_t *get_cairo_surface(int fd, struct igt_fb *fb) +/** + * igt_get_cairo_surface: + * @fd: open drm file descriptor + * @fb: pointer to an #igt_fb structure + * + * This function stores the contents of the supplied framebuffer into a cairo + * surface and returns it. + * + * Returns: + * A pointer to a cairo surface with the contents of the framebuffer. + */ +cairo_surface_t *igt_get_cairo_surface(int fd, struct igt_fb *fb) { if (fb->cairo_surface == NULL) { if (fb->tiling == LOCAL_I915_FORMAT_MOD_Y_TILED || @@ -1160,7 +1171,7 @@ cairo_t *igt_get_cairo_ctx(int fd, struct igt_fb *fb) cairo_surface_t *surface; cairo_t *cr; - surface = get_cairo_surface(fd, fb); + surface = igt_get_cairo_surface(fd, fb); cr = cairo_create(surface); cairo_surface_destroy(surface); igt_assert(cairo_status(cr) == CAIRO_STATUS_SUCCESS); @@ -1173,27 +1184,6 @@ cairo_t *igt_get_cairo_ctx(int fd, struct igt_fb *fb) } /** - * igt_write_fb_to_png: - * @fd: open i915 drm file descriptor - * @fb: pointer to an #igt_fb structure - * @filename: target name for the png image - * - * This function stores the contents of the supplied framebuffer into a png - * image stored at @filename. - */ -void igt_write_fb_to_png(int fd, struct igt_fb *fb, const char *filename) -{ - cairo_surface_t *surface; - cairo_status_t status; - - surface = get_cairo_surface(fd, fb); - status = cairo_surface_write_to_png(surface, filename); - cairo_surface_destroy(surface); - - igt_assert(status == CAIRO_STATUS_SUCCESS); -} - -/** * igt_remove_fb: * @fd: open i915 drm file descriptor * @fb: pointer to an #igt_fb structure diff --git a/lib/igt_fb.h b/lib/igt_fb.h index 4a680cef..f8a845cc 100644 --- a/lib/igt_fb.h +++ b/lib/igt_fb.h @@ -132,6 +132,7 @@ int igt_create_bo_with_dimensions(int fd, int width, int height, uint32_t format uint64_t igt_fb_mod_to_tiling(uint64_t modifier); /* cairo-based painting */ +cairo_surface_t *igt_get_cairo_surface(int fd, struct igt_fb *fb); cairo_t *igt_get_cairo_ctx(int fd, struct igt_fb *fb); void igt_paint_color(cairo_t *cr, int x, int y, int w, int h, double r, double g, double b); @@ -145,7 +146,6 @@ void igt_paint_color_gradient_range(cairo_t *cr, int x, int y, int w, int h, void igt_paint_test_pattern(cairo_t *cr, int width, int height); void igt_paint_image(cairo_t *cr, const char *filename, int dst_x, int dst_y, int dst_width, int dst_height); -void igt_write_fb_to_png(int fd, struct igt_fb *fb, const char *filename); int igt_cairo_printf_line(cairo_t *cr, enum igt_text_align align, double yspacing, const char *fmt, ...) __attribute__((format (printf, 4, 5))); -- 2.13.2 _
[Intel-gfx] [PATCH i-g-t v4 4/7] Introduce common frame dumping configuration and helpers
This introduces a common FrameDumpPath configuration field, as well as helper functions in dedicated igt_frame for writing cairo surfaces to png files. Signed-off-by: Paul Kocialkowski --- lib/Makefile.sources | 2 + lib/igt.h| 1 + lib/igt_core.c | 12 + lib/igt_core.h | 2 +- lib/igt_frame.c | 137 +++ lib/igt_frame.h | 43 6 files changed, 196 insertions(+), 1 deletion(-) create mode 100644 lib/igt_frame.c create mode 100644 lib/igt_frame.h diff --git a/lib/Makefile.sources b/lib/Makefile.sources index 53fdb54c..c2e58809 100644 --- a/lib/Makefile.sources +++ b/lib/Makefile.sources @@ -83,6 +83,8 @@ lib_source_list = \ uwildmat/uwildmat.c \ igt_kmod.c \ igt_kmod.h \ + igt_frame.c \ + igt_frame.h \ $(NULL) .PHONY: version.h.tmp diff --git a/lib/igt.h b/lib/igt.h index a069deb3..d16a4991 100644 --- a/lib/igt.h +++ b/lib/igt.h @@ -34,6 +34,7 @@ #include "igt_draw.h" #include "igt_dummyload.h" #include "igt_fb.h" +#include "igt_frame.h" #include "igt_gt.h" #include "igt_kms.h" #include "igt_pm.h" diff --git a/lib/igt_core.c b/lib/igt_core.c index 1ba79361..5a3b00e8 100644 --- a/lib/igt_core.c +++ b/lib/igt_core.c @@ -235,6 +235,10 @@ * An example configuration follows: * * |[ + * # The common configuration secton follows. + * [Common] + * FrameDumpPath=/tmp # The path to dump frames that fail comparison checks + * * # The following section is used for configuring the Device Under Test. * # It is not mandatory and allows overriding default values. * [DUT] @@ -290,6 +294,7 @@ static struct { static pthread_mutex_t log_buffer_mutex = PTHREAD_MUTEX_INITIALIZER; GKeyFile *igt_key_file; +char *frame_dump_path; const char *igt_test_name(void) { @@ -621,6 +626,13 @@ static int config_parse(void) if (!igt_key_file) return 0; + frame_dump_path = getenv("IGT_FRAME_DUMP_PATH"); + + if (!frame_dump_path) + frame_dump_path = g_key_file_get_string(igt_key_file, "Common", + "FrameDumpPath", + &error); + rc = g_key_file_get_integer(igt_key_file, "DUT", "SuspendResumeDelay", &error); if (error && error->code == G_KEY_FILE_ERROR_INVALID_VALUE) diff --git a/lib/igt_core.h b/lib/igt_core.h index 0739ca83..1619a9d6 100644 --- a/lib/igt_core.h +++ b/lib/igt_core.h @@ -50,7 +50,7 @@ extern const char* __igt_test_description __attribute__((weak)); extern bool __igt_plain_output; extern GKeyFile *igt_key_file; - +extern char *frame_dump_path; /** * IGT_TEST_DESCRIPTION: diff --git a/lib/igt_frame.c b/lib/igt_frame.c new file mode 100644 index ..dfafe53d --- /dev/null +++ b/lib/igt_frame.c @@ -0,0 +1,137 @@ +/* + * Copyright © 2017 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Paul Kocialkowski + */ + +#include "config.h" + +#include +#include +#include + +#include "igt.h" + +/** + * SECTION:igt_frame + * @short_description: Library for frame-related tests + * @title: Frame + * @include: igt_frame.h + * + * This library contains helpers for frame-related tests. This includes common + * frame dumping as well as frame comparison helpers. + */ + +/** + * igt_frame_dump_is_enabled: + * + * Get whether frame dumping is enabled. + * + * Returns: A boolean indicating whether frame dumping is enabled + */ +bool igt_frame_dump_is_enabled(void) +{ + retu
[Intel-gfx] [PATCH i-g-t v4 2/7] chamelium: Calculate CRC from framebuffer instead of hardcoding it
This introduces CRC calculation for reference frames, instead of using hardcoded values for them. The rendering of reference frames may differ from machine to machine, especially due to font rendering, and the frame itself may change with subsequent IGT changes. These differences would cause the CRC checks to fail on different setups. This allows them to pass regardless of the setup. Signed-off-by: Paul Kocialkowski --- lib/igt_chamelium.c | 143 lib/igt_chamelium.h | 5 ++ tests/chamelium.c | 77 +++- 3 files changed, 167 insertions(+), 58 deletions(-) diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c index 93392af7..baa6399c 100644 --- a/lib/igt_chamelium.c +++ b/lib/igt_chamelium.c @@ -94,6 +94,14 @@ struct chamelium_frame_dump { struct chamelium_port *port; }; +struct chamelium_fb_crc_async_data { + int fd; + struct igt_fb *fb; + + pthread_t thread_id; + igt_crc_t *ret; +}; + struct chamelium { xmlrpc_env env; xmlrpc_client *client; @@ -998,6 +1006,141 @@ int chamelium_get_frame_limit(struct chamelium *chamelium, return ret; } +static uint32_t chamelium_xrgb_hash16(const unsigned char *buffer, int width, + int height, int k, int m) +{ + unsigned char r, g, b; + uint64_t sum = 0; + uint64_t count = 0; + uint64_t value; + uint32_t hash; + int index; + int i; + + for (i=0; i < width * height; i++) { + if ((i % m) != k) + continue; + + index = i * 4; + + r = buffer[index + 2]; + g = buffer[index + 1]; + b = buffer[index + 0]; + + value = r | (g << 8) | (b << 16); + sum += ++count * value; + } + + hash = ((sum >> 0) ^ (sum >> 16) ^ (sum >> 32) ^ (sum >> 48)) & 0x; + + return hash; +} + +static void chamelium_do_calculate_fb_crc(int fd, struct igt_fb *fb, + igt_crc_t *out) +{ + unsigned char *buffer; + cairo_surface_t *fb_surface; + int n = 4; + int w, h; + int i, j; + + /* Get the cairo surface for the framebuffer */ + fb_surface = igt_get_cairo_surface(fd, fb); + + buffer = cairo_image_surface_get_data(fb_surface); + w = fb->width; + h = fb->height; + + for (i = 0; i < n; i++) { + j = n - i - 1; + out->crc[i] = chamelium_xrgb_hash16(buffer, w, h, j, n); + } + + out->n_words = n; +} + +/** + * chamelium_calculate_fb_crc: + * @fd: The drm file descriptor + * @fb: The framebuffer to calculate the CRC for + * + * Calculates the CRC for the provided framebuffer, using the Chamelium's CRC + * algorithm. This calculates the CRC in a synchronous fashion. + * + * Returns: The calculated CRC + */ +igt_crc_t *chamelium_calculate_fb_crc(int fd, struct igt_fb *fb) +{ + igt_crc_t *ret = calloc(1, sizeof(igt_crc_t)); + + chamelium_do_calculate_fb_crc(fd, fb, ret); + + return ret; +} + +static void *chamelium_calculate_fb_crc_async_work(void *data) +{ + struct chamelium_fb_crc_async_data *fb_crc; + + fb_crc = (struct chamelium_fb_crc_async_data *) data; + + chamelium_do_calculate_fb_crc(fb_crc->fd, fb_crc->fb, fb_crc->ret); + + return NULL; +} + +/** + * chamelium_calculate_fb_crc_launch: + * @fd: The drm file descriptor + * @fb: The framebuffer to calculate the CRC for + * + * Launches the CRC calculation for the provided framebuffer, using the + * Chamelium's CRC algorithm. This calculates the CRC in an asynchronous + * fashion. + * + * The returned structure should be passed to a subsequent call to + * chamelium_calculate_fb_crc_result. It should not be freed. + * + * Returns: An intermediate structure for the CRC calculation work. + */ +struct chamelium_fb_crc_async_data *chamelium_calculate_fb_crc_async_start(int fd, + struct igt_fb *fb) +{ + struct chamelium_fb_crc_async_data *fb_crc; + + fb_crc = calloc(1, sizeof(struct chamelium_fb_crc_async_data)); + fb_crc->ret = calloc(1, sizeof(igt_crc_t)); + fb_crc->fd = fd; + fb_crc->fb = fb; + + pthread_create(&fb_crc->thread_id, NULL, + chamelium_calculate_fb_crc_async_work, fb_crc); + + return fb_crc; +} + +/** + * chamelium_calculate_fb_crc_result: + * @fb_crc: An intermediate structure with thread-related information + * + * Blocks until the asynchronous CRC calculation is finished, and then returns + * its result. + * + * Returns: The calculated CRC + */ +igt_crc_t *chamelium_calculate_fb_crc_async_finish(struct chamelium_fb_crc_async_data *fb_crc) +{ + igt_crc_t *ret; + +
[Intel-gfx] [PATCH i-g-t v4 7/7] tests/chamelium: Merge the crc testing functions into one
This merges the two test_display_crc_single and test_display_crc_multiple functions into one, with a variable number of frames to capture. This reduces code duplication. Signed-off-by: Paul Kocialkowski --- tests/chamelium.c | 72 +++ 1 file changed, 8 insertions(+), 64 deletions(-) diff --git a/tests/chamelium.c b/tests/chamelium.c index f93ff7ee..89a3bde0 100644 --- a/tests/chamelium.c +++ b/tests/chamelium.c @@ -379,65 +379,7 @@ disable_output(data_t *data, } static void -test_display_crc_single(data_t *data, struct chamelium_port *port) -{ - igt_display_t display; - igt_output_t *output; - igt_plane_t *primary; - igt_crc_t *crc; - igt_crc_t *expected_crc; - struct chamelium_fb_crc_async_data *fb_crc; - struct igt_fb fb; - drmModeModeInfo *mode; - drmModeConnector *connector; - int fb_id, i, captured_frame_count; - - reset_state(data, port); - - output = prepare_output(data, &display, port); - connector = chamelium_port_get_connector(data->chamelium, port, false); - primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY); - igt_assert(primary); - - for (i = 0; i < connector->count_modes; i++) { - mode = &connector->modes[i]; - fb_id = igt_create_color_pattern_fb(data->drm_fd, - mode->hdisplay, - mode->vdisplay, - DRM_FORMAT_XRGB, - LOCAL_DRM_FORMAT_MOD_NONE, - 0, 0, 0, &fb); - igt_assert(fb_id > 0); - - fb_crc = chamelium_calculate_fb_crc_async_start(data->drm_fd, - &fb); - enable_output(data, port, output, mode, &fb); - - igt_debug("Testing single CRC fetch\n"); - - chamelium_capture(data->chamelium, port, 0, 0, 0, 0, 1); - crc = chamelium_read_captured_crcs(data->chamelium, - &captured_frame_count); - - expected_crc = chamelium_calculate_fb_crc_async_finish(fb_crc); - - chamelium_assert_crc_eq_or_dump(data->chamelium, expected_crc, - crc, &fb, 0); - - igt_assert_crc_equal(crc, expected_crc); - free(expected_crc); - free(crc); - - disable_output(data, port, output); - igt_remove_fb(data->drm_fd, &fb); - } - - drmModeFreeConnector(connector); - igt_display_fini(&display); -} - -static void -test_display_crc_multiple(data_t *data, struct chamelium_port *port) +test_display_crc(data_t *data, struct chamelium_port *port, int count) { igt_display_t display; igt_output_t *output; @@ -476,10 +418,12 @@ test_display_crc_multiple(data_t *data, struct chamelium_port *port) * there's always the potential the driver isn't able to keep * the display running properly for very long */ - chamelium_capture(data->chamelium, port, 0, 0, 0, 0, 3); + chamelium_capture(data->chamelium, port, 0, 0, 0, 0, count); crc = chamelium_read_captured_crcs(data->chamelium, &captured_frame_count); + igt_assert(captured_frame_count == count); + igt_debug("Captured %d frames\n", captured_frame_count); expected_crc = chamelium_calculate_fb_crc_async_finish(fb_crc); @@ -696,10 +640,10 @@ igt_main edid_id, alt_edid_id); connector_subtest("dp-crc-single", DisplayPort) - test_display_crc_single(&data, port); + test_display_crc(&data, port, 1); connector_subtest("dp-crc-multiple", DisplayPort) - test_display_crc_multiple(&data, port); + test_display_crc(&data, port, 3); connector_subtest("dp-frame-dump", DisplayPort) test_display_frame_dump(&data, port); @@ -753,10 +697,10 @@ igt_main edid_id, alt_edid_id); connector_subtest("hdmi-crc-single", HDMIA) - test_display_crc_single(&data, port); + test_display_crc(&data, port, 1); connector_subtest("hdmi-crc-multiple&
[Intel-gfx] [PATCH i-g-t v4 3/7] lib/igt_debugfs: Introduce CRC check function, with logic made common
This introduces an igt_check_crc_equal function in addition to igt_assert_crc_equal and makes the CRC comparison logic from the latter common. In particular, an igt_find_crc_mismatch function indicates whether there is a mistmatch and at what index, so that the calling functions can print the diverging values. Signed-off-by: Paul Kocialkowski --- lib/igt_debugfs.c | 53 ++--- lib/igt_debugfs.h | 1 + 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/lib/igt_debugfs.c b/lib/igt_debugfs.c index 80f25c61..78c22e67 100644 --- a/lib/igt_debugfs.c +++ b/lib/igt_debugfs.c @@ -281,6 +281,26 @@ bool igt_debugfs_search(int device, const char *filename, const char *substring) * Pipe CRC */ +static bool igt_find_crc_mismatch(const igt_crc_t *a, const igt_crc_t *b, + int *index) +{ + int i; + + if (a->n_words != b->n_words) + return true; + + for (i = 0; i < a->n_words; i++) { + if (a->crc[i] != b->crc[i]) { + if (index) + *index = i; + + return true; + } + } + + return false; +} + /** * igt_assert_crc_equal: * @a: first pipe CRC value @@ -294,10 +314,37 @@ bool igt_debugfs_search(int device, const char *filename, const char *substring) */ void igt_assert_crc_equal(const igt_crc_t *a, const igt_crc_t *b) { - int i; + int index; + bool mismatch; + + mismatch = igt_find_crc_mismatch(a, b, &index); + if (mismatch) + igt_debug("CRC mismatch at index %d: 0x%x != 0x%x\n", index, + a->crc[index], b->crc[index]); + + igt_assert(!mismatch); +} + +/** + * igt_check_crc_equal: + * @a: first pipe CRC value + * @b: second pipe CRC value + * + * Compares two CRC values and return whether they match. + * + * Returns: A boolean indicating whether the CRC values match + */ +bool igt_check_crc_equal(const igt_crc_t *a, const igt_crc_t *b) +{ + int index; + bool mismatch; + + mismatch = igt_find_crc_mismatch(a, b, &index); + if (mismatch) + igt_debug("CRC mismatch at index %d: 0x%x != 0x%x\n", index, + a->crc[index], b->crc[index]); - for (i = 0; i < a->n_words; i++) - igt_assert_eq_u32(a->crc[i], b->crc[i]); + return !mismatch; } /** diff --git a/lib/igt_debugfs.h b/lib/igt_debugfs.h index 7b846a83..fe355919 100644 --- a/lib/igt_debugfs.h +++ b/lib/igt_debugfs.h @@ -114,6 +114,7 @@ enum intel_pipe_crc_source { }; void igt_assert_crc_equal(const igt_crc_t *a, const igt_crc_t *b); +bool igt_check_crc_equal(const igt_crc_t *a, const igt_crc_t *b); char *igt_crc_to_string(igt_crc_t *crc); void igt_require_pipe_crc(int fd); -- 2.13.2 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH i-g-t v4 0/7] CRC testing with Chamelium improvements
Changes since v3: * Renamed structure used by async crc calculation for more clarity * Used const qualifier for untouched buffer when hashing * Split actual calculation to a dedicated function * Reworked async functions names for more clarity * Reworked descriptions for better accuracy * Exported framebuffer cairo surface and use it directly instead of (unused) png dumping * Fix how the framebuffer cairo surface is obtained to avoid destroying it too early ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH i-g-t v4 6/7] chamelium: Dump captured and reference frames to png on crc error
This adds support for dumping both the frame capture from the chamelium and the reference frame generated by cairo when the captured crc does not match the crc calculated from the reference, using common helpers. Getting a dump of the frames is quite useful in order to compare them. Signed-off-by: Paul Kocialkowski --- lib/igt_chamelium.c | 81 + lib/igt_chamelium.h | 4 +++ tests/chamelium.c | 14 ++--- 3 files changed, 95 insertions(+), 4 deletions(-) diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c index baa6399c..df49936b 100644 --- a/lib/igt_chamelium.c +++ b/lib/igt_chamelium.c @@ -930,6 +930,32 @@ static pixman_image_t *convert_frame_format(pixman_image_t *src, return converted; } +static cairo_surface_t *convert_frame_dump_argb32(const struct chamelium_frame_dump *dump) +{ + cairo_surface_t *dump_surface; + pixman_image_t *image_bgr; + pixman_image_t *image_argb; + int w = dump->width, h = dump->height; + uint32_t *bits_bgr = (uint32_t *) dump->bgr; + unsigned char *bits_argb; + + image_bgr = pixman_image_create_bits( + PIXMAN_b8g8r8, w, h, bits_bgr, + PIXMAN_FORMAT_BPP(PIXMAN_b8g8r8) / 8 * w); + image_argb = convert_frame_format(image_bgr, PIXMAN_x8r8g8b8); + pixman_image_unref(image_bgr); + + bits_argb = (unsigned char *) pixman_image_get_data(image_argb); + + dump_surface = cairo_image_surface_create_for_data( + bits_argb, CAIRO_FORMAT_ARGB32, w, h, + PIXMAN_FORMAT_BPP(PIXMAN_x8r8g8b8) / 8 * w); + + pixman_image_unref(image_argb); + + return dump_surface; +} + /** * chamelium_assert_frame_eq: * @chamelium: The chamelium instance the frame dump belongs to @@ -974,6 +1000,61 @@ void chamelium_assert_frame_eq(const struct chamelium *chamelium, } /** + * chamelium_assert_crc_eq_or_dump: + * @chamelium: The chamelium instance the frame dump belongs to + * @reference_crc: The CRC for the reference frame + * @capture_crc: The CRC for the captured frame + * @fb: pointer to an #igt_fb structure + * + * Asserts that the CRC provided for both the reference and the captured frame + * are identical. If they are not, this grabs the captured frame and saves it + * along with the reference to a png file. + */ +void chamelium_assert_crc_eq_or_dump(struct chamelium *chamelium, +igt_crc_t *reference_crc, +igt_crc_t *capture_crc, struct igt_fb *fb, +int index) +{ + struct chamelium_frame_dump *frame; + cairo_surface_t *reference; + cairo_surface_t *capture; + char *reference_suffix; + char *capture_suffix; + bool eq; + + eq = igt_check_crc_equal(reference_crc, capture_crc); + if (!eq && igt_frame_dump_is_enabled()) { + /* Grab the reference frame from framebuffer */ + reference = igt_get_cairo_surface(chamelium->drm_fd, fb); + + /* Grab the captured frame from chamelium */ + frame = chamelium_read_captured_frame(chamelium, index); + igt_assert(frame); + + capture = convert_frame_dump_argb32(frame); + + reference_suffix = igt_crc_to_string_extended(reference_crc, + '-', 2); + capture_suffix = igt_crc_to_string_extended(capture_crc, '-', + 2); + + /* Write reference and capture frames to png */ + igt_write_compared_frames_to_png(reference, capture, +reference_suffix, +capture_suffix); + + free(reference_suffix); + free(capture_suffix); + + chamelium_destroy_frame_dump(frame); + + cairo_surface_destroy(capture); + } + + igt_assert(eq); +} + +/** * chamelium_get_frame_limit: * @chamelium: The Chamelium instance to use * @port: The port to check the frame limit on diff --git a/lib/igt_chamelium.h b/lib/igt_chamelium.h index 2bfbfdc7..80afcafa 100644 --- a/lib/igt_chamelium.h +++ b/lib/igt_chamelium.h @@ -105,6 +105,10 @@ int chamelium_get_frame_limit(struct chamelium *chamelium, void chamelium_assert_frame_eq(const struct chamelium *chamelium, const struct chamelium_frame_dump *dump, struct igt_fb *fb); +void chamelium_assert_crc_eq_or_dump(struct chamelium *chamelium, +igt_crc_t *reference_crc, +igt_crc_t *capture_crc, struct igt_fb *fb, +int index); void chamelium_destroy_frame_dump(struct chamelium_frame_dump *dump); #endif
[Intel-gfx] [PATCH i-g-t v4 5/7] lib/igt_debugfs: Add extended helper to format crc to string
This introduces a igt_crc_to_string_extended helper that allows formatting a crc to a string with a given delimiter and size to print per crc word. Signed-off-by: Paul Kocialkowski --- lib/igt_debugfs.c | 28 lib/igt_debugfs.h | 1 + 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/lib/igt_debugfs.c b/lib/igt_debugfs.c index 78c22e67..005f99b1 100644 --- a/lib/igt_debugfs.c +++ b/lib/igt_debugfs.c @@ -348,26 +348,46 @@ bool igt_check_crc_equal(const igt_crc_t *a, const igt_crc_t *b) } /** - * igt_crc_to_string: + * igt_crc_to_string_extended: * @crc: pipe CRC value to print + * @delimiter: The delimiter to use between crc words + * @crc_size: the number of bytes to print per crc word (either 4 or 2) * - * This formats @crc into a string buffer which is owned by igt_crc_to_string(). + * This formats @crc into a string buffer, depending on @delimiter and @crc_size + * which is owned by igt_crc_to_string_extended(). * The next call will override the buffer again, which makes this multithreading * unsafe. * * This should only ever be used for diagnostic debug output. */ -char *igt_crc_to_string(igt_crc_t *crc) +char *igt_crc_to_string_extended(igt_crc_t *crc, char delimiter, int crc_size) { int i; char buf[128] = { 0 }; + const char *format[2] = { "%08x%c", "%04x%c" }; for (i = 0; i < crc->n_words; i++) - sprintf(buf + strlen(buf), "%08x ", crc->crc[i]); + sprintf(buf + strlen(buf), format[crc_size == 2], crc->crc[i], + i == (crc->n_words - 1) ? '\0' : delimiter); return strdup(buf); } +/** + * igt_crc_to_string: + * @crc: pipe CRC value to print + * + * This formats @crc into a string buffer which is owned by igt_crc_to_string(). + * The next call will override the buffer again, which makes this multithreading + * unsafe. + * + * This should only ever be used for diagnostic debug output. + */ +char *igt_crc_to_string(igt_crc_t *crc) +{ + return igt_crc_to_string_extended(crc, ' ', 4); +} + #define MAX_CRC_ENTRIES 10 #define MAX_LINE_LEN (10 + 11 * MAX_CRC_ENTRIES + 1) diff --git a/lib/igt_debugfs.h b/lib/igt_debugfs.h index fe355919..f1a76406 100644 --- a/lib/igt_debugfs.h +++ b/lib/igt_debugfs.h @@ -115,6 +115,7 @@ enum intel_pipe_crc_source { void igt_assert_crc_equal(const igt_crc_t *a, const igt_crc_t *b); bool igt_check_crc_equal(const igt_crc_t *a, const igt_crc_t *b); +char *igt_crc_to_string_extended(igt_crc_t *crc, char delimiter, int crc_size); char *igt_crc_to_string(igt_crc_t *crc); void igt_require_pipe_crc(int fd); -- 2.13.2 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH i-g-t v4 0/7] CRC testing with Chamelium improvements
On Wed, 2017-07-12 at 17:50 +0300, Paul Kocialkowski wrote: > Changes since v3: > * Renamed structure used by async crc calculation for more clarity > * Used const qualifier for untouched buffer when hashing > * Split actual calculation to a dedicated function > * Reworked async functions names for more clarity > * Reworked descriptions for better accuracy > * Exported framebuffer cairo surface and use it directly instead of > (unused) png dumping > * Fix how the framebuffer cairo surface is obtained to avoid > destroying > it too early This also contains the following changes that I forgot to mention: Changes since v3: * Made CRC checking logic common * Added a check for the same number of words * Made frame dumping configuration and helpers common * Added an extended crc to string helper * Added a chamelium helper for crc checking and frame dumping * Split the merging of crc functions to a separate patch * Added support for frame dump path global variable * Added listing the dumped images in a file, possibly identified with an id global variable The latter allows having one "dump report" file per run, possibly identified with the id global variable, that indicates which files are the output, while keeping the possibility to have the same files for different runs. This allows saving significant disk space when the images are identified with e.g. their crc, so that duplicate results only lead to duplicate dump reports and not duplicate images. -- Paul Kocialkowski Intel Finland Oy - BIC 0357606-4 - Westendinkatu 7, 02160 Espoo, Finland ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH i-g-t v2 0/2] Analogue/VGA frame comparison support
Changes since v1: * Split analogue frame comparison to igt_frame, using cairo surfaces * Added a chamelium helper for analogue frame checking and frame dumping There's nothing holding off this series on my side anymore, so it can now be merged as-is. ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH i-g-t v2 2/2] chamelium: Add support for VGA frame comparison testing
This adds support for VGA frame comparison testing with the reference generated from cairo. The retrieved frame from the chamelium is first cropped, as it contains the blanking intervals, through a dedicated helper. Another helper function asserts that the analogue frame matches or dump it to png if not. Signed-off-by: Paul Kocialkowski --- lib/igt_chamelium.c | 164 ++-- lib/igt_chamelium.h | 7 ++- lib/igt_frame.c | 6 +- tests/chamelium.c | 57 ++ 4 files changed, 225 insertions(+), 9 deletions(-) diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c index df49936b..8701192e 100644 --- a/lib/igt_chamelium.c +++ b/lib/igt_chamelium.c @@ -938,6 +938,8 @@ static cairo_surface_t *convert_frame_dump_argb32(const struct chamelium_frame_d int w = dump->width, h = dump->height; uint32_t *bits_bgr = (uint32_t *) dump->bgr; unsigned char *bits_argb; + unsigned char *bits_target; + int size; image_bgr = pixman_image_create_bits( PIXMAN_b8g8r8, w, h, bits_bgr, @@ -947,9 +949,13 @@ static cairo_surface_t *convert_frame_dump_argb32(const struct chamelium_frame_d bits_argb = (unsigned char *) pixman_image_get_data(image_argb); - dump_surface = cairo_image_surface_create_for_data( - bits_argb, CAIRO_FORMAT_ARGB32, w, h, - PIXMAN_FORMAT_BPP(PIXMAN_x8r8g8b8) / 8 * w); + dump_surface = cairo_image_surface_create( + CAIRO_FORMAT_ARGB32, w, h); + + bits_target = cairo_image_surface_get_data(dump_surface); + size = cairo_image_surface_get_stride(dump_surface) * h; + memcpy(bits_target, bits_argb, size); + cairo_surface_mark_dirty(dump_surface); pixman_image_unref(image_argb); @@ -1055,6 +1061,154 @@ void chamelium_assert_crc_eq_or_dump(struct chamelium *chamelium, } /** + * chamelium_assert_analogue_frame_match_or_dump: + * @chamelium: The chamelium instance the frame dump belongs to + * @frame: The chamelium frame dump to match + * @fb: pointer to an #igt_fb structure + * + * Asserts that the provided captured frame matches the reference frame from + * the framebuffer. If they do not, this saves the reference and captured frames + * to a png file. + */ +void chamelium_assert_analogue_frame_match_or_dump(struct chamelium *chamelium, + struct chamelium_port *port, + const struct chamelium_frame_dump *frame, + struct igt_fb *fb) +{ + cairo_surface_t *reference; + cairo_surface_t *capture; + igt_crc_t *reference_crc; + igt_crc_t *capture_crc; + char *reference_suffix; + char *capture_suffix; + bool match; + + /* Grab the reference frame from framebuffer */ + reference = igt_get_cairo_surface(chamelium->drm_fd, fb); + + /* Grab the captured frame from chamelium */ + capture = convert_frame_dump_argb32(frame); + + match = igt_check_analogue_frame_match(reference, capture); + if (!match && igt_frame_dump_is_enabled()) { + reference_crc = chamelium_calculate_fb_crc(chamelium->drm_fd, + fb); + capture_crc = chamelium_get_crc_for_area(chamelium, port, 0, 0, +0, 0); + + reference_suffix = igt_crc_to_string_extended(reference_crc, + '-', 2); + capture_suffix = igt_crc_to_string_extended(capture_crc, '-', + 2); + + /* Write reference and capture frames to png */ + igt_write_compared_frames_to_png(reference, capture, +reference_suffix, +capture_suffix); + + free(reference_suffix); + free(capture_suffix); + } + + cairo_surface_destroy(capture); + + igt_assert(match); +} + + +/** + * chamelium_analogue_frame_crop: + * @chamelium: The Chamelium instance to use + * @dump: The chamelium frame dump to crop + * @width: The cropped frame width + * @height: The cropped frame height + * + * Detects the corners of a chamelium frame and crops it to the requested + * width/height. This is useful for VGA frame dumps that also contain the + * pixels dumped during the blanking intervals. + * + * The detection is done on a brightness-threshold-basis, that is adapted + * to the reference frame used by i-g-t. It may not be as relevant for other + * frames. + */ +void chamelium_crop_analogue_frame(struct chamelium_frame_dump *dump, int width, + int height) +{ + u
[Intel-gfx] [PATCH i-g-t v2 1/2] lib/igt_frame: Add support for analogue frame comparison testing
This adds support for analogue frame comparison check, as used in VGA. Since VGA uses a DAC-ADC chain, its data cannot be expected to be pixel perfect. Thus, it is impossible to uses a CRC check and full frames have to be analyzed instead. Such an analysis is implemented, based on both an absolute error threshold and a correlation with the expected error trend for a DAC-ADC chain. It was tested with a couple encoders and provides reliable error detection with few false positives. Signed-off-by: Paul Kocialkowski --- configure.ac| 1 + lib/Makefile.am | 2 + lib/igt_frame.c | 131 lib/igt_frame.h | 2 + 4 files changed, 136 insertions(+) diff --git a/configure.ac b/configure.ac index bf09927c..63ed4d27 100644 --- a/configure.ac +++ b/configure.ac @@ -178,6 +178,7 @@ if test x"$udev" = xyes; then AC_DEFINE(HAVE_UDEV,1,[Enable udev-based monitor hotplug detection]) fi PKG_CHECK_MODULES(GLIB, glib-2.0) +PKG_CHECK_MODULES(GSL, gsl) # for chamelium PKG_CHECK_MODULES(XMLRPC, xmlrpc_client, [xmlrpc=yes], [xmlrpc=no]) diff --git a/lib/Makefile.am b/lib/Makefile.am index d4f41128..fb922ced 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -35,6 +35,7 @@ AM_CFLAGS = \ $(DRM_CFLAGS) \ $(PCIACCESS_CFLAGS) \ $(LIBUNWIND_CFLAGS) \ + $(GSL_CFLAGS) \ $(KMOD_CFLAGS) \ $(PROCPS_CFLAGS) \ $(DEBUG_CFLAGS) \ @@ -54,6 +55,7 @@ libintel_tools_la_LIBADD = \ $(DRM_LIBS) \ $(PCIACCESS_LIBS) \ $(PROCPS_LIBS) \ + $(GSL_LIBS) \ $(KMOD_LIBS) \ $(CAIRO_LIBS) \ $(LIBUDEV_LIBS) \ diff --git a/lib/igt_frame.c b/lib/igt_frame.c index dfafe53d..dc84fe01 100644 --- a/lib/igt_frame.c +++ b/lib/igt_frame.c @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include "igt.h" @@ -135,3 +137,132 @@ void igt_write_compared_frames_to_png(cairo_surface_t *reference, close(fd); } + +/** + * igt_check_analogue_frame_match: + * @reference: The reference cairo surface + * @capture: The captured cairo surface + * + * Checks that the analogue image contained in the chamelium frame dump matches + * the given framebuffer. + * + * In order to determine whether the frame matches the reference, the following + * reasoning is implemented: + * 1. The absolute error for each color value of the reference is collected. + * 2. The average absolute error is calculated for each color value of the + *reference and must not go above 60 (23.5 % of the total range). + * 3. A linear fit for the average absolute error from the pixel value is + *calculated, as a DAC-ADC chain is expected to have a linear error curve. + * 4. The linear fit is correlated with the actual average absolute error for + *the frame and the correlation coefficient is checked to be > 0.985, + *indicating a match with the expected error trend. + * + * Most errors (e.g. due to scaling, rotation, color space, etc) can be + * reliably detected this way, with a minimized number of false-positives. + * However, the brightest values (250 and up) are ignored as the error trend + * is often not linear there in practice due to clamping. + * + * Returns: a boolean indicating whether the frames match + */ + +bool igt_check_analogue_frame_match(cairo_surface_t *reference, + cairo_surface_t *capture) +{ + pixman_image_t *reference_src, *capture_src; + int w, h; + int error_count[3][256][2] = { 0 }; + double error_average[4][250]; + double error_trend[250]; + double c0, c1, cov00, cov01, cov11, sumsq; + double correlation; + unsigned char *reference_pixels, *capture_pixels; + unsigned char *p; + unsigned char *q; + bool match = true; + int diff; + int x, y; + int i, j; + + w = cairo_image_surface_get_width(reference); + h = cairo_image_surface_get_height(reference); + + reference_src = pixman_image_create_bits( + PIXMAN_x8r8g8b8, w, h, + (void*)cairo_image_surface_get_data(reference), + cairo_image_surface_get_stride(reference)); + reference_pixels = (unsigned char *) pixman_image_get_data(reference_src); + + capture_src = pixman_image_create_bits( + PIXMAN_x8r8g8b8, w, h, + (void*)cairo_image_surface_get_data(capture), + cairo_image_surface_get_stride(capture)); + capture_pixels = (unsigned char *) pixman_image_get_data(capture_src); + + /* Collect the absolute error for each color value */ + for (x = 0; x < w; x++) { + for (y = 0; y < h; y++) { + p = &capture_pixels[(x + y * w) * 4]; + q = &reference_pixels[(x + y * w) * 4]; + + for (i = 1; i < 4; i++) { +
[Intel-gfx] [PATCH i-g-t v2 0/1] tests/chamelium: Detect analogue bridges and handle EDID accordingly
Changes since v1: * Rebased on top of the new revisions of the series this depends on ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH i-g-t v2] tests/chamelium: Detect analogue bridges and handle EDID accordingly
Nowadays, many VGA connectors are not actually native VGA but use a discrete bridge to a digital connector. These bridges usually enforce their own EDID instead of the one supplied by the chamelium. Thus, the EDID read test for VGA is not relevant in that case and should be skipped. Reported modes may also go beyond what the chamelium can support. Thus, only supported resolutions should be tested for the frame dump test and others should be pruned. Signed-off-by: Paul Kocialkowski --- tests/chamelium.c | 78 +++ 1 file changed, 78 insertions(+) diff --git a/tests/chamelium.c b/tests/chamelium.c index baaa424b..499672eb 100644 --- a/tests/chamelium.c +++ b/tests/chamelium.c @@ -105,6 +105,76 @@ wait_for_connector(data_t *data, struct chamelium_port *port, igt_assert(finished); } +static int chamelium_vga_modes[][2] = { + { 1600, 1200 }, + { 1920, 1200 }, + { 1920, 1080 }, + { 1680, 1050 }, + { 1280, 1024 }, + { 1280, 960 }, + { 1440, 900 }, + { 1280, 800 }, + { 1024, 768 }, + { 1360, 768 }, + { 1280, 720 }, + { 800, 600 }, + { 640, 480 }, + { -1, -1 }, +}; + +static bool +prune_vga_mode(data_t *data, drmModeModeInfo *mode) +{ + int i = 0; + + while (chamelium_vga_modes[i][0] != -1) { + if (mode->hdisplay == chamelium_vga_modes[i][0] && + mode->vdisplay == chamelium_vga_modes[i][1]) + return false; + + i++; + } + + return true; +} + +static bool +check_analogue_bridge(data_t *data, struct chamelium_port *port) +{ + drmModePropertyBlobPtr edid_blob = NULL; + drmModeConnector *connector = chamelium_port_get_connector( + data->chamelium, port, false); + uint64_t edid_blob_id; + unsigned char *edid; + char edid_vendor[3]; + + if (chamelium_port_get_type(port) != DRM_MODE_CONNECTOR_VGA) + return false; + + igt_assert(kmstest_get_property(data->drm_fd, connector->connector_id, + DRM_MODE_OBJECT_CONNECTOR, "EDID", NULL, + &edid_blob_id, NULL)); + igt_assert(edid_blob = drmModeGetPropertyBlob(data->drm_fd, + edid_blob_id)); + + edid = (unsigned char *) edid_blob->data; + + edid_vendor[0] = ((edid[8] & 0x7c) >> 2) + '@'; + edid_vendor[1] = (((edid[8] & 0x03) << 3) | + ((edid[9] & 0xe0) >> 5)) + '@'; + edid_vendor[2] = (edid[9] & 0x1f) + '@'; + + /* Analogue bridges provide their own EDID */ + if (edid_vendor[0] != 'I' || edid_vendor[1] != 'G' || + edid_vendor[0] != 'T') + return true; + + drmModeFreePropertyBlob(edid_blob); + drmModeFreeConnector(connector); + + return false; +} + static void reset_state(data_t *data, struct chamelium_port *port) { @@ -168,6 +238,8 @@ test_edid_read(data_t *data, struct chamelium_port *port, chamelium_plug(data->chamelium, port); wait_for_connector(data, port, DRM_MODE_CONNECTED); + igt_skip_on(check_analogue_bridge(data, port)); + igt_assert(kmstest_get_property(data->drm_fd, connector->connector_id, DRM_MODE_OBJECT_CONNECTOR, "EDID", NULL, &edid_blob_id, NULL)); @@ -506,15 +578,21 @@ test_analogue_frame_dump(data_t *data, struct chamelium_port *port) drmModeModeInfo *mode; drmModeConnector *connector; int fb_id, i; + bool bridge; output = prepare_output(data, &display, port); connector = chamelium_port_get_connector(data->chamelium, port, false); primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY); igt_assert(primary); + bridge = check_analogue_bridge(data, port); + for (i = 0; i < connector->count_modes; i++) { mode = &connector->modes[i]; + if (bridge && prune_vga_mode(data, mode)) + continue; + fb_id = igt_create_color_pattern_fb(data->drm_fd, mode->hdisplay, mode->vdisplay, DRM_FORMAT_XRGB, -- 2.13.2 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH] drm/i915: Explicit the connector name for DP link training result
This adds the connector name when printing a debug message about the DP link training result. It is useful to figure out what connector is failing when multiple DP connectors are used. Signed-off-by: Paul Kocialkowski --- drivers/gpu/drm/i915/intel_dp_link_training.c | 10 ++ 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp_link_training.c b/drivers/gpu/drm/i915/intel_dp_link_training.c index b79c1c0e404c..75a411c94ce5 100644 --- a/drivers/gpu/drm/i915/intel_dp_link_training.c +++ b/drivers/gpu/drm/i915/intel_dp_link_training.c @@ -321,13 +321,15 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) if (!intel_dp_link_training_channel_equalization(intel_dp)) goto failure_handling; - DRM_DEBUG_KMS("Link Training Passed at Link Rate = %d, Lane count = %d", - intel_dp->link_rate, intel_dp->lane_count); + DRM_DEBUG_KMS("Link Training Passed at Link Rate = %d, Lane count = %d for connector %s", + intel_dp->link_rate, intel_dp->lane_count, + intel_connector->base.name); return; failure_handling: - DRM_DEBUG_KMS("Link Training failed at link rate = %d, lane count = %d", - intel_dp->link_rate, intel_dp->lane_count); + DRM_DEBUG_KMS("Link Training failed at link rate = %d, lane count = %d for connector %s", + intel_dp->link_rate, intel_dp->lane_count, + intel_connector->base.name); if (!intel_dp_get_link_train_fallback_values(intel_dp, intel_dp->link_rate, intel_dp->lane_count)) -- 2.13.2 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH] drm/i915: Explicit the connector name for DP link training result
Hey, On Tue, 2017-07-18 at 10:38 +0300, Jani Nikula wrote: > On Mon, 17 Jul 2017, Paul Kocialkowski com> wrote: > > This adds the connector name when printing a debug message about the > > DP > > link training result. It is useful to figure out what connector is > > failing when multiple DP connectors are used. > > Perhaps more consistent would be using a prefix like this: > > DRM_DEBUG_KMS("[CONNECTOR:%d:%s] bla bla blaa\n", > connector->base.base.id, connector->base.name); You are definitely right, this is what is used all over the place in the driver, so I should stick to it. Thanks for the suggestion, I will send out v2 in that direction shortly. Cheers, Paul > > Signed-off-by: Paul Kocialkowski > > --- > > drivers/gpu/drm/i915/intel_dp_link_training.c | 10 ++ > > 1 file changed, 6 insertions(+), 4 deletions(-) > > > > diff --git a/drivers/gpu/drm/i915/intel_dp_link_training.c > > b/drivers/gpu/drm/i915/intel_dp_link_training.c > > index b79c1c0e404c..75a411c94ce5 100644 > > --- a/drivers/gpu/drm/i915/intel_dp_link_training.c > > +++ b/drivers/gpu/drm/i915/intel_dp_link_training.c > > @@ -321,13 +321,15 @@ intel_dp_start_link_train(struct intel_dp > > *intel_dp) > > if (!intel_dp_link_training_channel_equalization(intel_dp)) > > goto failure_handling; > > > > - DRM_DEBUG_KMS("Link Training Passed at Link Rate = %d, Lane > > count = %d", > > - intel_dp->link_rate, intel_dp->lane_count); > > + DRM_DEBUG_KMS("Link Training Passed at Link Rate = %d, Lane > > count = %d for connector %s", > > + intel_dp->link_rate, intel_dp->lane_count, > > + intel_connector->base.name); > > return; > > > > failure_handling: > > - DRM_DEBUG_KMS("Link Training failed at link rate = %d, lane > > count = %d", > > - intel_dp->link_rate, intel_dp->lane_count); > > + DRM_DEBUG_KMS("Link Training failed at link rate = %d, lane > > count = %d for connector %s", > > + intel_dp->link_rate, intel_dp->lane_count, > > + intel_connector->base.name); > > if (!intel_dp_get_link_train_fallback_values(intel_dp, > > intel_dp- > > >link_rate, > > intel_dp- > > >lane_count)) > > -- Paul Kocialkowski Intel Finland Oy - BIC 0357606-4 - Westendinkatu 7, 02160 Espoo, Finland ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH] drm/i915: Synchronize connectors states when switching from poll to irq
On Mon, 2017-06-26 at 15:32 +0300, Paul Kocialkowski wrote: > After detecting an IRQ storm, hotplug detection will switch from > irq-based detection to poll-based detection. After a short delay or > when resetting storm detection from debugfs, detection will switch > back to being irq-based. > > However, it may occur that polling does not have enough time to detect > the current connector state when that second switch takes place. Thus, > this sets the appropriate hotplug event bits for the concerned > connectors and schedules the hotplug work, that will ensure the > connectors states are in sync when switching back to irq. > > Without this, no irq will be triggered and the hpd change will be > lost. Does anyone have feedback to provide on this? It looks like it should be a no-brainer. Cheers, Paul > Signed-off-by: Paul Kocialkowski > --- > drivers/gpu/drm/i915/intel_hotplug.c | 8 +++- > 1 file changed, 7 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/i915/intel_hotplug.c > b/drivers/gpu/drm/i915/intel_hotplug.c > index f1200272a699..29f55480b0bb 100644 > --- a/drivers/gpu/drm/i915/intel_hotplug.c > +++ b/drivers/gpu/drm/i915/intel_hotplug.c > @@ -218,9 +218,13 @@ static void > intel_hpd_irq_storm_reenable_work(struct work_struct *work) > struct intel_connector *intel_connector = > to_intel_connector(connector); > > if (intel_connector->encoder->hpd_pin == i) { > - if (connector->polled != > intel_connector->polled) > + if (connector->polled != > intel_connector->polled) { > DRM_DEBUG_DRIVER("Reenabling > HPD on connector %s\n", >connector- > >name); > + > + dev_priv->hotplug.event_bits > |= (1 << i); > + } > + > connector->polled = intel_connector- > >polled; > if (!connector->polled) > connector->polled = > DRM_CONNECTOR_POLL_HPD; > @@ -232,6 +236,8 @@ static void > intel_hpd_irq_storm_reenable_work(struct work_struct *work) > dev_priv->display.hpd_irq_setup(dev_priv); > spin_unlock_irq(&dev_priv->irq_lock); > > + schedule_work(&dev_priv->hotplug.hotplug_work); > + > intel_runtime_pm_put(dev_priv); > } > -- Paul Kocialkowski Intel Finland Oy - BIC 0357606-4 - Westendinkatu 7, 02160 Espoo, Finland ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH v2] drm/i915: Explicit the connector name for DP link training result
This adds the connector name when printing a debug message about the DP link training result. It is useful to figure out what connector is failing when multiple DP connectors are used. Signed-off-by: Paul Kocialkowski --- drivers/gpu/drm/i915/intel_dp_link_training.c | 8 ++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp_link_training.c b/drivers/gpu/drm/i915/intel_dp_link_training.c index b79c1c0e404c..05907fa8a553 100644 --- a/drivers/gpu/drm/i915/intel_dp_link_training.c +++ b/drivers/gpu/drm/i915/intel_dp_link_training.c @@ -321,12 +321,16 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) if (!intel_dp_link_training_channel_equalization(intel_dp)) goto failure_handling; - DRM_DEBUG_KMS("Link Training Passed at Link Rate = %d, Lane count = %d", + DRM_DEBUG_KMS("[CONNECTOR:%d:%s] Link Training Passed at Link Rate = %d, Lane count = %d", + intel_connector->base.base.id, + intel_connector->base.name, intel_dp->link_rate, intel_dp->lane_count); return; failure_handling: - DRM_DEBUG_KMS("Link Training failed at link rate = %d, lane count = %d", + DRM_DEBUG_KMS("[CONNECTOR:%d:%s] Link Training failed at link rate = %d, lane count = %d", + intel_connector->base.base.id, + intel_connector->base.name, intel_dp->link_rate, intel_dp->lane_count); if (!intel_dp_get_link_train_fallback_values(intel_dp, intel_dp->link_rate, -- 2.13.2 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH i-g-t 0/2] Unrelated hotplug uevent masking out actual test result
This patch introduces a workaround for a case where a uevent is issued by the kernel because of DP link training failing on a connector unrelated to the current test. Since the test depends on receiving a hotplug uevent, it previously passed even though it should not have. False positives also occur due to the plug/unplug events being delayed and issued at resume time. This is mitigated by catching and flushing hotplugs everytime a change is made on connectors, but it is not enough to ensure that all hotplug events were caught and not delayed. The problem here is that it is not possible to find out the exact reason why a uevent is issued by the kernel. A possible way to fix this would be to introduce more fields (the connector name and some reason why the event is triggered would probably be sufficient). ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH i-g-t 1/2] tests/chamelium: Skip suspend/resume test with unreliable hotplug event
It may occur that a hotplug uevent is detected at resume, even though it does not indicate that an actual hotplug happened. This is the case when link training fails on any other connector. There is currently no way to distinguish what connector caused a hotplug uevent, nor what the reason for that uevent really is. This makes it impossible to find out whether the test actually passed or not. To circumvent this problem, the link status of each connector is collected before and after suspend and compared to skip the test if the state was good before and turned to bad after resume. This only concerns the EDID change test, where we cannot check the connector state (that is not supposed to have changed). For actual hotplug tests, the tests should be safe since they check each connector's state after receiving the uevent. The situation described here happens with DP-VGA bridges that fail link training after resume, as they need some more time to response on their AUX channel. Signed-off-by: Paul Kocialkowski --- tests/chamelium.c | 35 +++ 1 file changed, 35 insertions(+) diff --git a/tests/chamelium.c b/tests/chamelium.c index e26f0557..8af33aaa 100644 --- a/tests/chamelium.c +++ b/tests/chamelium.c @@ -87,6 +87,31 @@ get_precalculated_crc(struct chamelium_port *port, int w, int h) } static void +get_connectors_link_status_failed(data_t *data, bool *link_status_failed) +{ + drmModeConnector *connector; + uint64_t link_status; + drmModePropertyPtr prop; + int p; + + for (p = 0; p < data->port_count; p++) { + connector = chamelium_port_get_connector(data->chamelium, +data->ports[p], false); + + igt_assert(kmstest_get_property(data->drm_fd, + connector->connector_id, + DRM_MODE_OBJECT_CONNECTOR, + "link-status", NULL, + &link_status, &prop)); + + link_status_failed[p] = link_status == DRM_MODE_LINK_STATUS_BAD; + + drmModeFreeProperty(prop); + drmModeFreeConnector(connector); + } +} + +static void require_connector_present(data_t *data, unsigned int type) { int i; @@ -310,6 +335,8 @@ test_suspend_resume_edid_change(data_t *data, struct chamelium_port *port, int alt_edid_id) { struct udev_monitor *mon = igt_watch_hotplug(); + bool link_status_failed[2][data->port_count]; + int p; reset_state(data, port); @@ -326,8 +353,16 @@ test_suspend_resume_edid_change(data_t *data, struct chamelium_port *port, */ chamelium_port_set_edid(data->chamelium, port, alt_edid_id); + get_connectors_link_status_failed(data, link_status_failed[0]); + igt_system_suspend_autoresume(state, test); + igt_assert(igt_hotplug_detected(mon, HOTPLUG_TIMEOUT)); + + get_connectors_link_status_failed(data, link_status_failed[1]); + + for (p = 0; p < data->port_count; p++) + igt_skip_on(!link_status_failed[0][p] && link_status_failed[1][p]); } static igt_output_t * -- 2.13.2 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH i-g-t 2/2] tests/chamelium: Catch and flush hotplug uevents after each plug
This adds calls to igt_hotplug_detected and igt_flush_hotplugs to catch and flush hotplugs from connector unplug (due to chamelium reset) and plug. These need to be intercepted so that they are not delayed and issued after resume, providing a false positive for the test result. In addition, the final hotplug uevent flush is brought closer to the suspend call, to decrease the likeliness of false positive. However, false positives still do happen, because it is not possible to make sure that the uevent caused by each connector's state change was caught instead of being delayed and issued at resume time. Signed-off-by: Paul Kocialkowski --- tests/chamelium.c | 10 -- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/chamelium.c b/tests/chamelium.c index 8af33aaa..0528ffb3 100644 --- a/tests/chamelium.c +++ b/tests/chamelium.c @@ -340,12 +340,16 @@ test_suspend_resume_edid_change(data_t *data, struct chamelium_port *port, reset_state(data, port); + /* Catch the event and flush all remaining ones. */ + igt_assert(igt_hotplug_detected(mon, HOTPLUG_TIMEOUT)); + igt_flush_hotplugs(mon); + /* First plug in the port */ chamelium_port_set_edid(data->chamelium, port, edid_id); chamelium_plug(data->chamelium, port); - wait_for_connector(data, port, DRM_MODE_CONNECTED); + igt_assert(igt_hotplug_detected(mon, HOTPLUG_TIMEOUT)); - igt_flush_hotplugs(mon); + wait_for_connector(data, port, DRM_MODE_CONNECTED); /* * Change the edid before we suspend. On resume, the machine should @@ -355,6 +359,8 @@ test_suspend_resume_edid_change(data_t *data, struct chamelium_port *port, get_connectors_link_status_failed(data, link_status_failed[0]); + igt_flush_hotplugs(mon); + igt_system_suspend_autoresume(state, test); igt_assert(igt_hotplug_detected(mon, HOTPLUG_TIMEOUT)); -- 2.13.2 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH i-g-t 1/2] tests/chamelium: Skip suspend/resume test with unreliable hotplug event
It may occur that a hotplug uevent is detected at resume, even though it does not indicate that an actual hotplug happened. This is the case when link training fails on any other connector. There is currently no way to distinguish what connector caused a hotplug uevent, nor what the reason for that uevent really is. This makes it impossible to find out whether the test actually passed or not. To circumvent this problem, the link status of each connector is collected before and after suspend and compared to skip the test if the state was good before and turned to bad after resume. This only concerns the EDID change test, where we cannot check the connector state (that is not supposed to have changed). For actual hotplug tests, the tests should be safe since they check each connector's state after receiving the uevent. The situation described here happens with DP-VGA bridges that fail link training after resume, as they need some more time to response on their AUX channel. Signed-off-by: Paul Kocialkowski --- tests/chamelium.c | 35 +++ 1 file changed, 35 insertions(+) diff --git a/tests/chamelium.c b/tests/chamelium.c index e26f0557..8af33aaa 100644 --- a/tests/chamelium.c +++ b/tests/chamelium.c @@ -87,6 +87,31 @@ get_precalculated_crc(struct chamelium_port *port, int w, int h) } static void +get_connectors_link_status_failed(data_t *data, bool *link_status_failed) +{ + drmModeConnector *connector; + uint64_t link_status; + drmModePropertyPtr prop; + int p; + + for (p = 0; p < data->port_count; p++) { + connector = chamelium_port_get_connector(data->chamelium, +data->ports[p], false); + + igt_assert(kmstest_get_property(data->drm_fd, + connector->connector_id, + DRM_MODE_OBJECT_CONNECTOR, + "link-status", NULL, + &link_status, &prop)); + + link_status_failed[p] = link_status == DRM_MODE_LINK_STATUS_BAD; + + drmModeFreeProperty(prop); + drmModeFreeConnector(connector); + } +} + +static void require_connector_present(data_t *data, unsigned int type) { int i; @@ -310,6 +335,8 @@ test_suspend_resume_edid_change(data_t *data, struct chamelium_port *port, int alt_edid_id) { struct udev_monitor *mon = igt_watch_hotplug(); + bool link_status_failed[2][data->port_count]; + int p; reset_state(data, port); @@ -326,8 +353,16 @@ test_suspend_resume_edid_change(data_t *data, struct chamelium_port *port, */ chamelium_port_set_edid(data->chamelium, port, alt_edid_id); + get_connectors_link_status_failed(data, link_status_failed[0]); + igt_system_suspend_autoresume(state, test); + igt_assert(igt_hotplug_detected(mon, HOTPLUG_TIMEOUT)); + + get_connectors_link_status_failed(data, link_status_failed[1]); + + for (p = 0; p < data->port_count; p++) + igt_skip_on(!link_status_failed[0][p] && link_status_failed[1][p]); } static igt_output_t * -- 2.13.2 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH i-g-t 1/2] tests/chamelium: Skip suspend/resume test with unreliable hotplug event
On Tue, 2017-07-18 at 22:21 +0100, Chris Wilson wrote: > Quoting Paul Kocialkowski (2017-07-18 16:16:26) > > It may occur that a hotplug uevent is detected at resume, even > > though it > > does not indicate that an actual hotplug happened. This is the case > > when > > link training fails on any other connector. > > > > There is currently no way to distinguish what connector caused a > > hotplug > > uevent, nor what the reason for that uevent really is. This makes it > > impossible to find out whether the test actually passed or not. > > And you may get more than one and then this skips even though the test > passed. Looks like the patch is overcompensating. What you can do is > repeat the test a few times, and then look at all the different errors > you get. If the connector remains (no mst disappareance) once it goes > bad, it should remain bad and so not generate any new uevent. Or you > only repeat the test whilst link_status[old] != link_status[new]. I am not sure it is really desirable to repeat the test until we are fairly certain it succeeds. This involves suspend/resume, that is already long enough as it is. Also, a uevent will be generated everytime link training fails, regardless of whether it was already failing before (I just tested that to make sure). In my case, it's due to a DP-VGA bridge that will consistently fail link training in the first seconds after resume. So this is actually even worse that I thought, because there is no way to find out that this is why a uevent was generated if the link status was already bad before. So I don't see how we can manage with the current information at disposal. My main point here is that we need more information about what's going on than simply "HOTPLUG=1". These patches demonstrate that working around the lack of information is a pain for testing purposes and can only leads to semi-working hackish workarounds. Do you agree that this is what the problem really is? -- Paul Kocialkowski Intel Finland Oy - BIC 0357606-4 - Westendinkatu 7, 02160 Espoo, Finland ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH v2] drm/i915: Explicit the connector name for DP link training result
On Tue, 2017-07-18 at 12:20 -0700, Manasi Navare wrote: > On Tue, Jul 18, 2017 at 05:25:36PM +0300, Paul Kocialkowski wrote: > > This adds the connector name when printing a debug message about the > > DP > > link training result. It is useful to figure out what connector is > > failing when multiple DP connectors are used. > > > > Thanks for the patch, this does make sense during the link training > failure debugging to know the connector name. > While at it feel free to change "Failed", "Link Rate, Lane Count", to > upper case > in the failure_handling case to be consistent with the pass case. Thanks for the review! Now that the patch was merged, do you feel like I should make a follow- up patch to fix consistency in the upper case use or is it enough of a detail that we can just forget about it? > Reviewed-by: Manasi Navare > > Manasi > > > Signed-off-by: Paul Kocialkowski > > --- > > drivers/gpu/drm/i915/intel_dp_link_training.c | 8 ++-- > > 1 file changed, 6 insertions(+), 2 deletions(-) > > > > diff --git a/drivers/gpu/drm/i915/intel_dp_link_training.c > > b/drivers/gpu/drm/i915/intel_dp_link_training.c > > index b79c1c0e404c..05907fa8a553 100644 > > --- a/drivers/gpu/drm/i915/intel_dp_link_training.c > > +++ b/drivers/gpu/drm/i915/intel_dp_link_training.c > > @@ -321,12 +321,16 @@ intel_dp_start_link_train(struct intel_dp > > *intel_dp) > > if (!intel_dp_link_training_channel_equalization(intel_dp)) > > goto failure_handling; > > > > - DRM_DEBUG_KMS("Link Training Passed at Link Rate = %d, Lane > > count = %d", > > + DRM_DEBUG_KMS("[CONNECTOR:%d:%s] Link Training Passed at > > Link Rate = %d, Lane count = %d", > > + intel_connector->base.base.id, > > + intel_connector->base.name, > > intel_dp->link_rate, intel_dp->lane_count); > > return; > > > > failure_handling: > > - DRM_DEBUG_KMS("Link Training failed at link rate = %d, lane > > count = %d", > > + DRM_DEBUG_KMS("[CONNECTOR:%d:%s] Link Training failed at > > link rate = %d, lane count = %d", > > + intel_connector->base.base.id, > > + intel_connector->base.name, > > intel_dp->link_rate, intel_dp->lane_count); > > if (!intel_dp_get_link_train_fallback_values(intel_dp, > > intel_dp- > > >link_rate, > > -- > > 2.13.2 > > -- Paul Kocialkowski Intel Finland Oy - BIC 0357606-4 - Westendinkatu 7, 02160 Espoo, Finland ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH i-g-t v4 2/7] chamelium: Calculate CRC from framebuffer instead of hardcoding it
On Mon, 2017-07-17 at 12:29 -0400, Lyude Paul wrote: > On Wed, 2017-07-12 at 17:50 +0300, Paul Kocialkowski wrote: > > This introduces CRC calculation for reference frames, instead of > > using > > hardcoded values for them. The rendering of reference frames may > > differ > > from machine to machine, especially due to font rendering, and the > > frame itself may change with subsequent IGT changes. > > > > These differences would cause the CRC checks to fail on different > > setups. This allows them to pass regardless of the setup. > > Just one question before I push this since I didn't think of testing > this previously and don't have access to my chamelium at the moment. > Have you made sure that this doesn't break things with igt if a test > gets interrupted due to failure in the middle of an asynchronous CRC > calculation? So I have now tested that a failed assert (in the main thread) in the middle of the threaded calculation will not cause any segfault. There is no reason why it should, because none of the ressources used for the calculation are liberated prior to the end of the process. Everything is really cleaned up when the process dies. On the other hand, it may happen, due to the call to igt_get_cairo_surface that an igt_assert fails in the calculation thread, which definitely causes a segfault. I will rework the patches so that the call to the function is made prior to starting the thread, thus avoiding any possibility of hitting a failed igt_assert in the thread itself. > Other then that, everything here looks good. > > > > Signed-off-by: Paul Kocialkowski > > --- > > lib/igt_chamelium.c | 143 > > > > lib/igt_chamelium.h | 5 ++ > > tests/chamelium.c | 77 +++- > > 3 files changed, 167 insertions(+), 58 deletions(-) > > > > diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c > > index 93392af7..baa6399c 100644 > > --- a/lib/igt_chamelium.c > > +++ b/lib/igt_chamelium.c > > @@ -94,6 +94,14 @@ struct chamelium_frame_dump { > > struct chamelium_port *port; > > }; > > > > +struct chamelium_fb_crc_async_data { > > + int fd; > > + struct igt_fb *fb; > > + > > + pthread_t thread_id; > > + igt_crc_t *ret; > > +}; > > + > > struct chamelium { > > xmlrpc_env env; > > xmlrpc_client *client; > > @@ -998,6 +1006,141 @@ int chamelium_get_frame_limit(struct > > chamelium > > *chamelium, > > return ret; > > } > > > > +static uint32_t chamelium_xrgb_hash16(const unsigned char *buffer, > > int width, > > + int height, int k, int m) > > +{ > > + unsigned char r, g, b; > > + uint64_t sum = 0; > > + uint64_t count = 0; > > + uint64_t value; > > + uint32_t hash; > > + int index; > > + int i; > > + > > + for (i=0; i < width * height; i++) { > > + if ((i % m) != k) > > + continue; > > + > > + index = i * 4; > > + > > + r = buffer[index + 2]; > > + g = buffer[index + 1]; > > + b = buffer[index + 0]; > > + > > + value = r | (g << 8) | (b << 16); > > + sum += ++count * value; > > + } > > + > > + hash = ((sum >> 0) ^ (sum >> 16) ^ (sum >> 32) ^ (sum >> > > 48)) & 0x; > > + > > + return hash; > > +} > > + > > +static void chamelium_do_calculate_fb_crc(int fd, struct igt_fb > > *fb, > > + igt_crc_t *out) > > +{ > > + unsigned char *buffer; > > + cairo_surface_t *fb_surface; > > + int n = 4; > > + int w, h; > > + int i, j; > > + > > + /* Get the cairo surface for the framebuffer */ > > + fb_surface = igt_get_cairo_surface(fd, fb); > > + > > + buffer = cairo_image_surface_get_data(fb_surface); > > + w = fb->width; > > + h = fb->height; > > + > > + for (i = 0; i < n; i++) { > > + j = n - i - 1; > > + out->crc[i] = chamelium_xrgb_hash16(buffer, w, h, > > j, > > n); > > + } > > + > > + out->n_words = n; > > +} > > + > > +/** > > + * chamelium_calculate_fb_crc: > > + * @fd: The drm file descriptor > > + * @fb: The framebuffer to calculate the CRC for > > + * > > + * Calculates the CRC for the provided framebuffer, using the > > Chamelium'
Re: [Intel-gfx] [PATCH i-g-t v2 2/2] chamelium: Add support for VGA frame comparison testing
On Mon, 2017-07-17 at 13:35 -0400, Lyude Paul wrote: > Just one change for this patch below > > On Wed, 2017-07-12 at 17:57 +0300, Paul Kocialkowski wrote: > > This adds support for VGA frame comparison testing with the > > reference > > generated from cairo. The retrieved frame from the chamelium is > > first > > cropped, as it contains the blanking intervals, through a dedicated > > helper. Another helper function asserts that the analogue frame > > matches or dump it to png if not. > > > > Signed-off-by: Paul Kocialkowski > > --- > > lib/igt_chamelium.c | 164 > > ++-- > > lib/igt_chamelium.h | 7 ++- > > lib/igt_frame.c | 6 +- > > tests/chamelium.c | 57 ++ > > 4 files changed, 225 insertions(+), 9 deletions(-) > > > > diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c > > index df49936b..8701192e 100644 > > --- a/lib/igt_chamelium.c > > +++ b/lib/igt_chamelium.c > > @@ -938,6 +938,8 @@ static cairo_surface_t > > *convert_frame_dump_argb32(const struct chamelium_frame_d > > int w = dump->width, h = dump->height; > > uint32_t *bits_bgr = (uint32_t *) dump->bgr; > > unsigned char *bits_argb; > > + unsigned char *bits_target; > > + int size; > > > > image_bgr = pixman_image_create_bits( > > PIXMAN_b8g8r8, w, h, bits_bgr, > > @@ -947,9 +949,13 @@ static cairo_surface_t > > *convert_frame_dump_argb32(const struct chamelium_frame_d > > > > bits_argb = (unsigned char *) > > pixman_image_get_data(image_argb); > > > > - dump_surface = cairo_image_surface_create_for_data( > > - bits_argb, CAIRO_FORMAT_ARGB32, w, h, > > - PIXMAN_FORMAT_BPP(PIXMAN_x8r8g8b8) / 8 * w); > > + dump_surface = cairo_image_surface_create( > > + CAIRO_FORMAT_ARGB32, w, h); > > + > > + bits_target = cairo_image_surface_get_data(dump_surface); > > + size = cairo_image_surface_get_stride(dump_surface) * h; > > + memcpy(bits_target, bits_argb, size); > > + cairo_surface_mark_dirty(dump_surface); > > > > pixman_image_unref(image_argb); > > > > @@ -1055,6 +1061,154 @@ void chamelium_assert_crc_eq_or_dump(struct > > chamelium *chamelium, > > } > > > > /** > > + * chamelium_assert_analogue_frame_match_or_dump: > > + * @chamelium: The chamelium instance the frame dump belongs to > > + * @frame: The chamelium frame dump to match > > + * @fb: pointer to an #igt_fb structure > > + * > > + * Asserts that the provided captured frame matches the reference > > frame from > > + * the framebuffer. If they do not, this saves the reference and > > captured frames > > + * to a png file. > > + */ > > +void chamelium_assert_analogue_frame_match_or_dump(struct chamelium > > *chamelium, > > + struct > > chamelium_port *port, > > + const struct > > chamelium_frame_dump *frame, > > + struct igt_fb > > *fb) > > +{ > > + cairo_surface_t *reference; > > + cairo_surface_t *capture; > > + igt_crc_t *reference_crc; > > + igt_crc_t *capture_crc; > > + char *reference_suffix; > > + char *capture_suffix; > > + bool match; > > + > > + /* Grab the reference frame from framebuffer */ > > + reference = igt_get_cairo_surface(chamelium->drm_fd, fb); > > + > > + /* Grab the captured frame from chamelium */ > > + capture = convert_frame_dump_argb32(frame); > > + > > + match = igt_check_analogue_frame_match(reference, capture); > > + if (!match && igt_frame_dump_is_enabled()) { > > + reference_crc = > > chamelium_calculate_fb_crc(chamelium- > > > drm_fd, > > > > + fb); > > + capture_crc = chamelium_get_crc_for_area(chamelium, > > port, 0, 0, > > +0, 0); > > + > > + reference_suffix = > > igt_crc_to_string_extended(reference_crc, > > + '-', > > 2); > > + capture_suffix = > > igt_crc_to_string_extended(capture_crc, '-', > &
[Intel-gfx] [PATCH i-g-t v5 4/7] Introduce common frame dumping configuration and helpers
This introduces a common FrameDumpPath configuration field, as well as helper functions in dedicated igt_frame for writing cairo surfaces to png files. Signed-off-by: Paul Kocialkowski --- lib/Makefile.sources | 2 + lib/igt.h| 1 + lib/igt_core.c | 12 + lib/igt_core.h | 2 +- lib/igt_frame.c | 137 +++ lib/igt_frame.h | 43 6 files changed, 196 insertions(+), 1 deletion(-) create mode 100644 lib/igt_frame.c create mode 100644 lib/igt_frame.h diff --git a/lib/Makefile.sources b/lib/Makefile.sources index 53fdb54c..c2e58809 100644 --- a/lib/Makefile.sources +++ b/lib/Makefile.sources @@ -83,6 +83,8 @@ lib_source_list = \ uwildmat/uwildmat.c \ igt_kmod.c \ igt_kmod.h \ + igt_frame.c \ + igt_frame.h \ $(NULL) .PHONY: version.h.tmp diff --git a/lib/igt.h b/lib/igt.h index a069deb3..d16a4991 100644 --- a/lib/igt.h +++ b/lib/igt.h @@ -34,6 +34,7 @@ #include "igt_draw.h" #include "igt_dummyload.h" #include "igt_fb.h" +#include "igt_frame.h" #include "igt_gt.h" #include "igt_kms.h" #include "igt_pm.h" diff --git a/lib/igt_core.c b/lib/igt_core.c index 1ba79361..5a3b00e8 100644 --- a/lib/igt_core.c +++ b/lib/igt_core.c @@ -235,6 +235,10 @@ * An example configuration follows: * * |[ + * # The common configuration secton follows. + * [Common] + * FrameDumpPath=/tmp # The path to dump frames that fail comparison checks + * * # The following section is used for configuring the Device Under Test. * # It is not mandatory and allows overriding default values. * [DUT] @@ -290,6 +294,7 @@ static struct { static pthread_mutex_t log_buffer_mutex = PTHREAD_MUTEX_INITIALIZER; GKeyFile *igt_key_file; +char *frame_dump_path; const char *igt_test_name(void) { @@ -621,6 +626,13 @@ static int config_parse(void) if (!igt_key_file) return 0; + frame_dump_path = getenv("IGT_FRAME_DUMP_PATH"); + + if (!frame_dump_path) + frame_dump_path = g_key_file_get_string(igt_key_file, "Common", + "FrameDumpPath", + &error); + rc = g_key_file_get_integer(igt_key_file, "DUT", "SuspendResumeDelay", &error); if (error && error->code == G_KEY_FILE_ERROR_INVALID_VALUE) diff --git a/lib/igt_core.h b/lib/igt_core.h index 0739ca83..1619a9d6 100644 --- a/lib/igt_core.h +++ b/lib/igt_core.h @@ -50,7 +50,7 @@ extern const char* __igt_test_description __attribute__((weak)); extern bool __igt_plain_output; extern GKeyFile *igt_key_file; - +extern char *frame_dump_path; /** * IGT_TEST_DESCRIPTION: diff --git a/lib/igt_frame.c b/lib/igt_frame.c new file mode 100644 index ..dfafe53d --- /dev/null +++ b/lib/igt_frame.c @@ -0,0 +1,137 @@ +/* + * Copyright © 2017 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Paul Kocialkowski + */ + +#include "config.h" + +#include +#include +#include + +#include "igt.h" + +/** + * SECTION:igt_frame + * @short_description: Library for frame-related tests + * @title: Frame + * @include: igt_frame.h + * + * This library contains helpers for frame-related tests. This includes common + * frame dumping as well as frame comparison helpers. + */ + +/** + * igt_frame_dump_is_enabled: + * + * Get whether frame dumping is enabled. + * + * Returns: A boolean indicating whether frame dumping is enabled + */ +bool igt_frame_dump_is_enabled(void) +{ + retu
[Intel-gfx] [PATCH i-g-t v5 0/7] CRC testing with Chamelium improvements
Changes since v4: * Moved igt_get_cairo_surface out of the thread function to properly handle assert failure * Rebased on top of current master Changes since v3: * Renamed structure used by async crc calculation for more clarity * Used const qualifier for untouched buffer when hashing * Split actual calculation to a dedicated function * Reworked async functions names for more clarity * Reworked descriptions for better accuracy * Exported framebuffer cairo surface and use it directly instead of (unused) png dumping * Fix how the framebuffer cairo surface is obtained to avoid destroying it too early * Made CRC checking logic common * Added a check for the same number of words * Made frame dumping configuration and helpers common * Added an extended crc to string helper * Added a chamelium helper for crc checking and frame dumping * Split the merging of crc functions to a separate patch * Added support for frame dump path global variable * Added listing the dumped images in a file, possibly identified with an id global variable The latter allows having one "dump report" file per run, possibly identified with the id global variable, that indicates which files are the output, while keeping the possibility to have the same files for different runs. This allows saving significant disk space when the images are identified with e.g. their crc, so that duplicate results only lead to duplicate dump reports and not duplicate images. ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx