diff options
author | Jyri Sarha | 2018-01-05 07:39:48 -0600 |
---|---|---|
committer | Tomi Valkeinen | 2018-01-05 07:48:53 -0600 |
commit | eafc32efc0a6292678f7542e36b78a433ad8770a (patch) | |
tree | 396fceb999ec1e1162ad49e7f7fe455a3ad6a890 | |
parent | 141d80881d1c759d43276375e6381537cdf8d0a4 (diff) | |
download | external-libkmsxx-eafc32efc0a6292678f7542e36b78a433ad8770a.tar.gz external-libkmsxx-eafc32efc0a6292678f7542e36b78a433ad8770a.tar.xz external-libkmsxx-eafc32efc0a6292678f7542e36b78a433ad8770a.zip |
kmstest: Separate reservation phase from command line parsing
In the new order the planes are not reserved before the whole command
line is parsed. This way we know the color format of the framebuffer
that is going to be on the reserved plane and we can select a plane
that supports the format. After this patch kmstest makes no distinction
between primary and overlay planes if atomic mode setting is
supported. If no plane is specified then a default plane, matching the
screen size is created.
Signed-off-by: Jyri Sarha <jsarha@ti.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
-rw-r--r-- | utils/kmstest.cpp | 224 |
1 files changed, 97 insertions, 127 deletions
diff --git a/utils/kmstest.cpp b/utils/kmstest.cpp index 0f763c0..62b103f 100644 --- a/utils/kmstest.cpp +++ b/utils/kmstest.cpp | |||
@@ -19,9 +19,10 @@ using namespace std; | |||
19 | using namespace kms; | 19 | using namespace kms; |
20 | 20 | ||
21 | struct PropInfo { | 21 | struct PropInfo { |
22 | PropInfo(Property *p, uint64_t v) : prop(p), val(v) {} | 22 | PropInfo(string n, uint64_t v) : prop(NULL), name(n), val(v) {} |
23 | 23 | ||
24 | Property *prop; | 24 | Property *prop; |
25 | string name; | ||
25 | uint64_t val; | 26 | uint64_t val; |
26 | }; | 27 | }; |
27 | 28 | ||
@@ -49,10 +50,8 @@ struct OutputInfo | |||
49 | Connector* connector; | 50 | Connector* connector; |
50 | 51 | ||
51 | Crtc* crtc; | 52 | Crtc* crtc; |
52 | Plane* primary_plane; | ||
53 | Videomode mode; | 53 | Videomode mode; |
54 | bool user_set_crtc; | 54 | vector<Framebuffer*> legacy_fbs; |
55 | vector<Framebuffer*> fbs; | ||
56 | 55 | ||
57 | vector<PlaneInfo> planes; | 56 | vector<PlaneInfo> planes; |
58 | 57 | ||
@@ -101,6 +100,16 @@ static void get_default_crtc(ResourceManager& resman, OutputInfo& output) | |||
101 | EXIT("Could not find available crtc"); | 100 | EXIT("Could not find available crtc"); |
102 | } | 101 | } |
103 | 102 | ||
103 | |||
104 | static PlaneInfo *add_default_planeinfo(OutputInfo* output) | ||
105 | { | ||
106 | output->planes.push_back(PlaneInfo { }); | ||
107 | PlaneInfo *ret = &output->planes.back(); | ||
108 | ret->w = output->mode.hdisplay; | ||
109 | ret->h = output->mode.vdisplay; | ||
110 | return ret; | ||
111 | } | ||
112 | |||
104 | static void parse_crtc(ResourceManager& resman, Card& card, const string& crtc_str, OutputInfo& output) | 113 | static void parse_crtc(ResourceManager& resman, Card& card, const string& crtc_str, OutputInfo& output) |
105 | { | 114 | { |
106 | // @12:1920x1200i@60 | 115 | // @12:1920x1200i@60 |
@@ -259,14 +268,11 @@ static void parse_plane(ResourceManager& resman, Card& card, const string& plane | |||
259 | pinfo.plane = planes[num]; | 268 | pinfo.plane = planes[num]; |
260 | } | 269 | } |
261 | 270 | ||
262 | pinfo.plane = resman.reserve_plane(pinfo.plane); | 271 | auto plane = resman.reserve_plane(pinfo.plane); |
263 | } else { | 272 | if (!plane) |
264 | pinfo.plane = resman.reserve_overlay_plane(output.crtc); | 273 | EXIT("Plane id %u is not available", pinfo.plane->id()); |
265 | } | 274 | } |
266 | 275 | ||
267 | if (!pinfo.plane) | ||
268 | EXIT("Failed to find available plane"); | ||
269 | |||
270 | pinfo.w = stoul(sm[5]); | 276 | pinfo.w = stoul(sm[5]); |
271 | pinfo.h = stoul(sm[6]); | 277 | pinfo.h = stoul(sm[6]); |
272 | 278 | ||
@@ -281,10 +287,9 @@ static void parse_plane(ResourceManager& resman, Card& card, const string& plane | |||
281 | pinfo.y = output.mode.vdisplay / 2 - pinfo.h / 2; | 287 | pinfo.y = output.mode.vdisplay / 2 - pinfo.h / 2; |
282 | } | 288 | } |
283 | 289 | ||
284 | static void parse_prop(Card& card, const string& prop_str, vector<PropInfo> &props, const DrmPropObject* propobj) | 290 | static void parse_prop(const string& prop_str, vector<PropInfo> &props) |
285 | { | 291 | { |
286 | string name, val; | 292 | string name, val; |
287 | Property* prop; | ||
288 | 293 | ||
289 | size_t split = prop_str.find("="); | 294 | size_t split = prop_str.find("="); |
290 | 295 | ||
@@ -293,9 +298,14 @@ static void parse_prop(Card& card, const string& prop_str, vector<PropInfo> &pro | |||
293 | 298 | ||
294 | name = prop_str.substr(0, split); | 299 | name = prop_str.substr(0, split); |
295 | val = prop_str.substr(split+1); | 300 | val = prop_str.substr(split+1); |
296 | prop = propobj->get_prop(name); | ||
297 | 301 | ||
298 | props.push_back(PropInfo(prop, stoull(val, 0, 0))); | 302 | props.push_back(PropInfo(name, stoull(val, 0, 0))); |
303 | } | ||
304 | |||
305 | static void get_props(Card& card, vector<PropInfo> &props, const DrmPropObject* propobj) | ||
306 | { | ||
307 | for (auto& pi : props) | ||
308 | pi.prop = propobj->get_prop(pi.name); | ||
299 | } | 309 | } |
300 | 310 | ||
301 | static vector<Framebuffer*> get_default_fb(Card& card, unsigned width, unsigned height) | 311 | static vector<Framebuffer*> get_default_fb(Card& card, unsigned width, unsigned height) |
@@ -308,12 +318,19 @@ static vector<Framebuffer*> get_default_fb(Card& card, unsigned width, unsigned | |||
308 | return v; | 318 | return v; |
309 | } | 319 | } |
310 | 320 | ||
311 | static vector<Framebuffer*> parse_fb(Card& card, const string& fb_str, unsigned def_w, unsigned def_h) | 321 | static void parse_fb(Card& card, const string& fb_str, OutputInfo* output, PlaneInfo* pinfo) |
312 | { | 322 | { |
313 | unsigned w = def_w; | 323 | unsigned w, h; |
314 | unsigned h = def_h; | ||
315 | PixelFormat format = PixelFormat::XRGB8888; | 324 | PixelFormat format = PixelFormat::XRGB8888; |
316 | 325 | ||
326 | if (pinfo) { | ||
327 | w = pinfo->w; | ||
328 | h = pinfo->h; | ||
329 | } else { | ||
330 | w = output->mode.hdisplay; | ||
331 | h = output->mode.vdisplay; | ||
332 | } | ||
333 | |||
317 | if (!fb_str.empty()) { | 334 | if (!fb_str.empty()) { |
318 | // XXX the regexp is not quite correct | 335 | // XXX the regexp is not quite correct |
319 | // 400x400-NV12 | 336 | // 400x400-NV12 |
@@ -338,7 +355,10 @@ static vector<Framebuffer*> parse_fb(Card& card, const string& fb_str, unsigned | |||
338 | for (unsigned i = 0; i < s_num_buffers; ++i) | 355 | for (unsigned i = 0; i < s_num_buffers; ++i) |
339 | v.push_back(new DumbFramebuffer(card, w, h, format)); | 356 | v.push_back(new DumbFramebuffer(card, w, h, format)); |
340 | 357 | ||
341 | return v; | 358 | if (pinfo) |
359 | pinfo->fbs = v; | ||
360 | else | ||
361 | output->legacy_fbs = v; | ||
342 | } | 362 | } |
343 | 363 | ||
344 | static void parse_view(const string& view_str, PlaneInfo& pinfo) | 364 | static void parse_view(const string& view_str, PlaneInfo& pinfo) |
@@ -509,27 +529,6 @@ static vector<OutputInfo> setups_to_outputs(Card& card, ResourceManager& resman, | |||
509 | { | 529 | { |
510 | vector<OutputInfo> outputs; | 530 | vector<OutputInfo> outputs; |
511 | 531 | ||
512 | if (output_args.size() == 0) { | ||
513 | // no output args, show a pattern on all screens | ||
514 | for (Connector* conn : card.get_connectors()) { | ||
515 | if (!conn->connected()) | ||
516 | continue; | ||
517 | |||
518 | OutputInfo output = { }; | ||
519 | output.connector = resman.reserve_connector(conn); | ||
520 | EXIT_IF(!output.connector, "Failed to reserve connector %s", conn->fullname().c_str()); | ||
521 | output.crtc = resman.reserve_crtc(conn); | ||
522 | EXIT_IF(!output.crtc, "Failed to reserve crtc for %s", conn->fullname().c_str()); | ||
523 | output.mode = output.connector->get_default_mode(); | ||
524 | |||
525 | output.fbs = get_default_fb(card, output.mode.hdisplay, output.mode.vdisplay); | ||
526 | |||
527 | outputs.push_back(output); | ||
528 | } | ||
529 | |||
530 | return outputs; | ||
531 | } | ||
532 | |||
533 | OutputInfo* current_output = 0; | 532 | OutputInfo* current_output = 0; |
534 | PlaneInfo* current_plane = 0; | 533 | PlaneInfo* current_plane = 0; |
535 | 534 | ||
@@ -558,8 +557,6 @@ static vector<OutputInfo> setups_to_outputs(Card& card, ResourceManager& resman, | |||
558 | 557 | ||
559 | parse_crtc(resman, card, arg.arg, *current_output); | 558 | parse_crtc(resman, card, arg.arg, *current_output); |
560 | 559 | ||
561 | current_output->user_set_crtc = true; | ||
562 | |||
563 | current_plane = 0; | 560 | current_plane = 0; |
564 | 561 | ||
565 | break; | 562 | break; |
@@ -578,8 +575,7 @@ static vector<OutputInfo> setups_to_outputs(Card& card, ResourceManager& resman, | |||
578 | if (!current_output->crtc) | 575 | if (!current_output->crtc) |
579 | get_default_crtc(resman, *current_output); | 576 | get_default_crtc(resman, *current_output); |
580 | 577 | ||
581 | current_output->planes.push_back(PlaneInfo { }); | 578 | current_plane = add_default_planeinfo(current_output); |
582 | current_plane = ¤t_output->planes.back(); | ||
583 | 579 | ||
584 | parse_plane(resman, card, arg.arg, *current_output, *current_plane); | 580 | parse_plane(resman, card, arg.arg, *current_output, *current_plane); |
585 | 581 | ||
@@ -599,22 +595,10 @@ static vector<OutputInfo> setups_to_outputs(Card& card, ResourceManager& resman, | |||
599 | if (!current_output->crtc) | 595 | if (!current_output->crtc) |
600 | get_default_crtc(resman, *current_output); | 596 | get_default_crtc(resman, *current_output); |
601 | 597 | ||
602 | int def_w, def_h; | 598 | if (!current_plane && card.has_atomic()) |
599 | current_plane = add_default_planeinfo(current_output); | ||
603 | 600 | ||
604 | if (current_plane) { | 601 | parse_fb(card, arg.arg, current_output, current_plane); |
605 | def_w = current_plane->w; | ||
606 | def_h = current_plane->h; | ||
607 | } else { | ||
608 | def_w = current_output->mode.hdisplay; | ||
609 | def_h = current_output->mode.vdisplay; | ||
610 | } | ||
611 | |||
612 | auto fbs = parse_fb(card, arg.arg, def_w, def_h); | ||
613 | |||
614 | if (current_plane) | ||
615 | current_plane->fbs = fbs; | ||
616 | else | ||
617 | current_output->fbs = fbs; | ||
618 | 602 | ||
619 | break; | 603 | break; |
620 | } | 604 | } |
@@ -634,16 +618,11 @@ static vector<OutputInfo> setups_to_outputs(Card& card, ResourceManager& resman, | |||
634 | EXIT("No object to which set the property"); | 618 | EXIT("No object to which set the property"); |
635 | 619 | ||
636 | if (current_plane) | 620 | if (current_plane) |
637 | parse_prop(card, arg.arg, current_plane->props, | 621 | parse_prop(arg.arg, current_plane->props); |
638 | current_plane->plane); | ||
639 | else if (current_output->crtc) | 622 | else if (current_output->crtc) |
640 | parse_prop(card, arg.arg, | 623 | parse_prop(arg.arg, current_output->crtc_props); |
641 | current_output->crtc_props, | ||
642 | current_output->crtc); | ||
643 | else if (current_output->connector) | 624 | else if (current_output->connector) |
644 | parse_prop(card, arg.arg, | 625 | parse_prop(arg.arg, current_output->conn_props); |
645 | current_output->conn_props, | ||
646 | current_output->connector); | ||
647 | else | 626 | else |
648 | EXIT("no object"); | 627 | EXIT("no object"); |
649 | 628 | ||
@@ -652,20 +631,56 @@ static vector<OutputInfo> setups_to_outputs(Card& card, ResourceManager& resman, | |||
652 | } | 631 | } |
653 | } | 632 | } |
654 | 633 | ||
655 | // create default framebuffers if needed | 634 | if (outputs.empty()) { |
635 | // no outputs defined, show a pattern on all screens | ||
636 | for (Connector* conn : card.get_connectors()) { | ||
637 | if (!conn->connected()) | ||
638 | continue; | ||
639 | |||
640 | OutputInfo output = { }; | ||
641 | output.connector = resman.reserve_connector(conn); | ||
642 | EXIT_IF(!output.connector, "Failed to reserve connector %s", conn->fullname().c_str()); | ||
643 | output.crtc = resman.reserve_crtc(conn); | ||
644 | EXIT_IF(!output.crtc, "Failed to reserve crtc for %s", conn->fullname().c_str()); | ||
645 | output.mode = output.connector->get_default_mode(); | ||
646 | |||
647 | outputs.push_back(output); | ||
648 | } | ||
649 | } | ||
650 | |||
656 | for (OutputInfo& o : outputs) { | 651 | for (OutputInfo& o : outputs) { |
657 | if (!o.crtc) { | 652 | get_props(card, o.conn_props, o.connector); |
653 | |||
654 | if (!o.crtc) | ||
658 | get_default_crtc(resman, o); | 655 | get_default_crtc(resman, o); |
659 | o.user_set_crtc = true; | ||
660 | } | ||
661 | 656 | ||
662 | if (o.fbs.empty() && o.user_set_crtc) | 657 | get_props(card, o.crtc_props, o.crtc); |
663 | o.fbs = get_default_fb(card, o.mode.hdisplay, o.mode.vdisplay); | 658 | |
659 | if (card.has_atomic()) { | ||
660 | if (o.planes.empty()) | ||
661 | add_default_planeinfo(&o); | ||
662 | } else { | ||
663 | if (o.legacy_fbs.empty()) | ||
664 | o.legacy_fbs = get_default_fb(card, o.mode.hdisplay, o.mode.vdisplay); | ||
665 | } | ||
664 | 666 | ||
665 | for (PlaneInfo &p : o.planes) { | 667 | for (PlaneInfo &p : o.planes) { |
666 | if (p.fbs.empty()) | 668 | if (p.fbs.empty()) |
667 | p.fbs = get_default_fb(card, p.w, p.h); | 669 | p.fbs = get_default_fb(card, p.w, p.h); |
668 | } | 670 | } |
671 | |||
672 | for (PlaneInfo& p : o.planes) { | ||
673 | if (!p.plane) { | ||
674 | if (card.has_atomic()) | ||
675 | p.plane = resman.reserve_generic_plane(o.crtc, p.fbs[0]->format()); | ||
676 | else | ||
677 | p.plane = resman.reserve_overlay_plane(o.crtc, p.fbs[0]->format()); | ||
678 | |||
679 | if (!p.plane) | ||
680 | EXIT("Failed to find available plane"); | ||
681 | } | ||
682 | get_props(card, p.props, p.plane); | ||
683 | } | ||
669 | } | 684 | } |
670 | 685 | ||
671 | return outputs; | 686 | return outputs; |
@@ -703,13 +718,11 @@ static void print_outputs(const vector<OutputInfo>& outputs) | |||
703 | printf(" %s=%" PRIu64, prop.prop->name().c_str(), | 718 | printf(" %s=%" PRIu64, prop.prop->name().c_str(), |
704 | prop.val); | 719 | prop.val); |
705 | 720 | ||
706 | if (o.primary_plane) | ||
707 | printf(" (plane %u/@%u)", o.primary_plane->idx(), o.primary_plane->id()); | ||
708 | printf(": %s\n", videomode_to_string(o.mode).c_str()); | 721 | printf(": %s\n", videomode_to_string(o.mode).c_str()); |
709 | if (!o.fbs.empty()) { | 722 | |
710 | auto fb = o.fbs[0]; | 723 | if (!o.legacy_fbs.empty()) { |
711 | printf(" Fb %u %ux%u-%s\n", fb->id(), fb->width(), fb->height(), | 724 | auto fb = o.legacy_fbs[0]; |
712 | PixelFormatToFourCC(fb->format()).c_str()); | 725 | printf(" (Fb %u %ux%u-%s)", fb->id(), fb->width(), fb->height(), PixelFormatToFourCC(fb->format()).c_str()); |
713 | } | 726 | } |
714 | 727 | ||
715 | for (unsigned j = 0; j < o.planes.size(); ++j) { | 728 | for (unsigned j = 0; j < o.planes.size(); ++j) { |
@@ -731,7 +744,7 @@ static void print_outputs(const vector<OutputInfo>& outputs) | |||
731 | static void draw_test_patterns(const vector<OutputInfo>& outputs) | 744 | static void draw_test_patterns(const vector<OutputInfo>& outputs) |
732 | { | 745 | { |
733 | for (const OutputInfo& o : outputs) { | 746 | for (const OutputInfo& o : outputs) { |
734 | for (auto fb : o.fbs) | 747 | for (auto fb : o.legacy_fbs) |
735 | draw_test_pattern(*fb); | 748 | draw_test_pattern(*fb); |
736 | 749 | ||
737 | for (const PlaneInfo& p : o.planes) | 750 | for (const PlaneInfo& p : o.planes) |
@@ -757,8 +770,8 @@ static void set_crtcs_n_planes_legacy(Card& card, const vector<OutputInfo>& outp | |||
757 | if (!o.conn_props.empty() || !o.crtc_props.empty()) | 770 | if (!o.conn_props.empty() || !o.crtc_props.empty()) |
758 | printf("WARNING: properties not set without atomic modesetting"); | 771 | printf("WARNING: properties not set without atomic modesetting"); |
759 | 772 | ||
760 | if (!o.fbs.empty()) { | 773 | if (!o.legacy_fbs.empty()) { |
761 | auto fb = o.fbs[0]; | 774 | auto fb = o.legacy_fbs[0]; |
762 | int r = crtc->set_mode(conn, *fb, o.mode); | 775 | int r = crtc->set_mode(conn, *fb, o.mode); |
763 | if (r) | 776 | if (r) |
764 | printf("crtc->set_mode() failed for crtc %u: %s\n", | 777 | printf("crtc->set_mode() failed for crtc %u: %s\n", |
@@ -800,15 +813,11 @@ static void set_crtcs_n_planes_atomic(Card& card, const vector<OutputInfo>& outp | |||
800 | } | 813 | } |
801 | 814 | ||
802 | // Disable unused planes | 815 | // Disable unused planes |
803 | for (Plane* plane : card.get_planes()) { | 816 | for (Plane* plane : card.get_planes()) |
804 | //if (find_if(outputs.begin(), outputs.end(), [plane](const OutputInfo& o) { return o.primary_plane == plane; }) != outputs.end()) | ||
805 | // continue; | ||
806 | |||
807 | disable_req.add(plane, { | 817 | disable_req.add(plane, { |
808 | { "FB_ID", 0 }, | 818 | { "FB_ID", 0 }, |
809 | { "CRTC_ID", 0 }, | 819 | { "CRTC_ID", 0 }, |
810 | }); | 820 | }); |
811 | } | ||
812 | 821 | ||
813 | r = disable_req.commit_sync(true); | 822 | r = disable_req.commit_sync(true); |
814 | if (r) | 823 | if (r) |
@@ -842,23 +851,6 @@ static void set_crtcs_n_planes_atomic(Card& card, const vector<OutputInfo>& outp | |||
842 | for (const PropInfo &prop: o.crtc_props) | 851 | for (const PropInfo &prop: o.crtc_props) |
843 | req.add(crtc, prop.prop, prop.val); | 852 | req.add(crtc, prop.prop, prop.val); |
844 | 853 | ||
845 | if (!o.fbs.empty()) { | ||
846 | auto fb = o.fbs[0]; | ||
847 | |||
848 | req.add(o.primary_plane, { | ||
849 | { "FB_ID", fb->id() }, | ||
850 | { "CRTC_ID", crtc->id() }, | ||
851 | { "SRC_X", 0 << 16 }, | ||
852 | { "SRC_Y", 0 << 16 }, | ||
853 | { "SRC_W", fb->width() << 16 }, | ||
854 | { "SRC_H", fb->height() << 16 }, | ||
855 | { "CRTC_X", 0 }, | ||
856 | { "CRTC_Y", 0 }, | ||
857 | { "CRTC_W", fb->width() }, | ||
858 | { "CRTC_H", fb->height() }, | ||
859 | }); | ||
860 | } | ||
861 | |||
862 | for (const PlaneInfo& p : o.planes) { | 854 | for (const PlaneInfo& p : o.planes) { |
863 | auto fb = p.fbs[0]; | 855 | auto fb = p.fbs[0]; |
864 | 856 | ||
@@ -968,16 +960,6 @@ private: | |||
968 | { | 960 | { |
969 | unsigned cur = frame_num % s_num_buffers; | 961 | unsigned cur = frame_num % s_num_buffers; |
970 | 962 | ||
971 | if (!o.fbs.empty()) { | ||
972 | auto fb = o.fbs[cur]; | ||
973 | |||
974 | draw_bar(fb, frame_num); | ||
975 | |||
976 | req.add(o.primary_plane, { | ||
977 | { "FB_ID", fb->id() }, | ||
978 | }); | ||
979 | } | ||
980 | |||
981 | for (const PlaneInfo& p : o.planes) { | 963 | for (const PlaneInfo& p : o.planes) { |
982 | auto fb = p.fbs[cur]; | 964 | auto fb = p.fbs[cur]; |
983 | 965 | ||
@@ -993,8 +975,8 @@ private: | |||
993 | { | 975 | { |
994 | unsigned cur = frame_num % s_num_buffers; | 976 | unsigned cur = frame_num % s_num_buffers; |
995 | 977 | ||
996 | if (!o.fbs.empty()) { | 978 | if (!o.legacy_fbs.empty()) { |
997 | auto fb = o.fbs[cur]; | 979 | auto fb = o.legacy_fbs[cur]; |
998 | 980 | ||
999 | draw_bar(fb, frame_num); | 981 | draw_bar(fb, frame_num); |
1000 | 982 | ||
@@ -1110,18 +1092,6 @@ int main(int argc, char **argv) | |||
1110 | 1092 | ||
1111 | vector<OutputInfo> outputs = setups_to_outputs(card, resman, output_args); | 1093 | vector<OutputInfo> outputs = setups_to_outputs(card, resman, output_args); |
1112 | 1094 | ||
1113 | if (card.has_atomic()) { | ||
1114 | for (OutputInfo& o : outputs) { | ||
1115 | if (o.fbs.empty()) | ||
1116 | continue; | ||
1117 | |||
1118 | o.primary_plane = resman.reserve_primary_plane(o.crtc, o.fbs[0]->format()); | ||
1119 | |||
1120 | if (!o.primary_plane) | ||
1121 | EXIT("Could not get primary plane for crtc '%u'", o.crtc->id()); | ||
1122 | } | ||
1123 | } | ||
1124 | |||
1125 | if (!s_flip_mode) | 1095 | if (!s_flip_mode) |
1126 | draw_test_patterns(outputs); | 1096 | draw_test_patterns(outputs); |
1127 | 1097 | ||