… | |
… | |
23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
24 | *---------------------------------------------------------------------*/ |
24 | *---------------------------------------------------------------------*/ |
25 | |
25 | |
26 | #include "../config.h" /* NECESSARY */ |
26 | #include "../config.h" /* NECESSARY */ |
27 | #include "rxvt.h" /* NECESSARY */ |
27 | #include "rxvt.h" /* NECESSARY */ |
|
|
28 | |
|
|
29 | #define DO_TIMING_TEST 0 |
|
|
30 | |
|
|
31 | #if DO_TIMING_TEST |
|
|
32 | #define TIMING_TEST_START(id) \ |
|
|
33 | struct timeval timing_test_##id##_stv;\ |
|
|
34 | gettimeofday (&timing_test_##id##_stv, NULL); |
|
|
35 | |
|
|
36 | #define TIMING_TEST_PRINT_RESULT(id) \ |
|
|
37 | do{ struct timeval tv;gettimeofday (&tv, NULL); tv.tv_sec -= (timing_test_##id##_stv).tv_sec;\ |
|
|
38 | fprintf (stderr, "%s: %s: %d: elapsed %ld usec\n", #id, __FILE__, __LINE__,\ |
|
|
39 | tv.tv_sec * 1000000 + tv.tv_usec - (timing_test_##id##_stv).tv_usec);}while (0) |
|
|
40 | |
|
|
41 | #else |
|
|
42 | #define TIMING_TEST_START(id) do{}while (0) |
|
|
43 | #define TIMING_TEST_PRINT_RESULT(id) do{}while (0) |
|
|
44 | #endif |
28 | |
45 | |
29 | /* |
46 | /* |
30 | * Pixmap geometry string interpretation : |
47 | * Pixmap geometry string interpretation : |
31 | * Each geometry string contains zero or one scale/position |
48 | * Each geometry string contains zero or one scale/position |
32 | * adjustment and may optionally be followed by a colon and one or more |
49 | * adjustment and may optionally be followed by a colon and one or more |
… | |
… | |
376 | int x = 0; |
393 | int x = 0; |
377 | int y = 0; |
394 | int y = 0; |
378 | int w = h_scale * target_width / 100; |
395 | int w = h_scale * target_width / 100; |
379 | int h = v_scale * target_height / 100; |
396 | int h = v_scale * target_height / 100; |
380 | |
397 | |
|
|
398 | TIMING_TEST_START (asim); |
|
|
399 | |
381 | if (original_asim) |
400 | if (original_asim) |
382 | { |
401 | { |
383 | x = make_align_position (h_align, target_width, w > 0 ? w : (int)original_asim->width); |
402 | x = make_align_position (h_align, target_width, w > 0 ? w : (int)original_asim->width); |
384 | y = make_align_position (v_align, target_height, h > 0 ? h : (int)original_asim->height); |
403 | y = make_align_position (v_align, target_height, h > 0 ? h : (int)original_asim->height); |
385 | } |
404 | } |
… | |
… | |
489 | result = tmp; |
508 | result = tmp; |
490 | } |
509 | } |
491 | free (layers); |
510 | free (layers); |
492 | } |
511 | } |
493 | } |
512 | } |
|
|
513 | TIMING_TEST_PRINT_RESULT (asim); |
494 | |
514 | |
495 | if (pixmap) |
515 | if (pixmap) |
496 | { |
516 | { |
497 | if (result == NULL |
517 | if (result == NULL |
498 | || pmap_width != new_pmap_width |
518 | || pmap_width != new_pmap_width |
… | |
… | |
544 | |
564 | |
545 | if (result != background && result != original_asim) |
565 | if (result != background && result != original_asim) |
546 | destroy_asimage (&result); |
566 | destroy_asimage (&result); |
547 | |
567 | |
548 | XFreeGC (target->dpy, gc); |
568 | XFreeGC (target->dpy, gc); |
|
|
569 | TIMING_TEST_PRINT_RESULT (asim); |
549 | } |
570 | } |
550 | |
571 | |
551 | return true; |
572 | return true; |
552 | } |
573 | } |
553 | # endif /* HAVE_AFTERIMAGE */ |
574 | # endif /* HAVE_AFTERIMAGE */ |
… | |
… | |
590 | if (!(flags & isTransparent)) |
611 | if (!(flags & isTransparent)) |
591 | { |
612 | { |
592 | flags |= isTransparent; |
613 | flags |= isTransparent; |
593 | return true; |
614 | return true; |
594 | } |
615 | } |
|
|
616 | return false; |
595 | } |
617 | } |
596 | |
618 | |
597 | bool |
619 | bool |
598 | bgPixmap_t::set_blur_radius (const char *geom) |
620 | bgPixmap_t::set_blur_radius (const char *geom) |
599 | { |
621 | { |
… | |
… | |
625 | |
647 | |
626 | static inline unsigned long |
648 | static inline unsigned long |
627 | compute_tint_shade_flags (rxvt_color *tint, int shade) |
649 | compute_tint_shade_flags (rxvt_color *tint, int shade) |
628 | { |
650 | { |
629 | unsigned long flags = 0; |
651 | unsigned long flags = 0; |
|
|
652 | rgba c (rgba::MAX_CC,rgba::MAX_CC,rgba::MAX_CC); |
630 | |
653 | |
631 | if (shade > 0 && shade <100) |
654 | if (tint) |
|
|
655 | { |
|
|
656 | tint->get (c); |
|
|
657 | # define IS_COMPONENT_WHOLESOME(cmp) ((cmp) <= 0x000700 || (cmp) >= 0x00f700) |
|
|
658 | if (IS_COMPONENT_WHOLESOME (c.r) |
|
|
659 | && IS_COMPONENT_WHOLESOME (c.g) |
|
|
660 | && IS_COMPONENT_WHOLESOME (c.b)) |
|
|
661 | flags |= bgPixmap_t::tintWholesome; |
|
|
662 | # undef IS_COMPONENT_WHOLESOME |
|
|
663 | } |
|
|
664 | |
|
|
665 | if ((shade > 0 && shade < 100) || (shade > 100 && shade < 200)) |
632 | flags |= bgPixmap_t::tintNeeded; |
666 | flags |= bgPixmap_t::tintNeeded; |
633 | else if (tint) |
667 | else if (tint) |
634 | { |
668 | { |
635 | rgba c (rgba::MAX_CC,rgba::MAX_CC,rgba::MAX_CC); |
|
|
636 | tint->get (c); |
|
|
637 | |
|
|
638 | if ((c.r > 0x000700 || c.g > 0x000700 || c.b > 0x000700) |
669 | if ((c.r > 0x000700 || c.g > 0x000700 || c.b > 0x000700) |
639 | && (c.r < 0x00f700 || c.g < 0x00f700 || c.b < 0x00f700)) |
670 | && (c.r < 0x00f700 || c.g < 0x00f700 || c.b < 0x00f700)) |
640 | { |
671 | { |
641 | flags |= bgPixmap_t::tintNeeded; |
672 | flags |= bgPixmap_t::tintNeeded; |
642 | # define IS_COMPONENT_WHOLESOME(cmp) ((cmp) <= 0x000700 || (cmp) >= 0x00f700) |
|
|
643 | if (IS_COMPONENT_WHOLESOME (c.r) |
|
|
644 | && IS_COMPONENT_WHOLESOME (c.g) |
|
|
645 | && IS_COMPONENT_WHOLESOME (c.b)) |
|
|
646 | flags |= bgPixmap_t::tintServerSide; |
|
|
647 | # undef IS_COMPONENT_WHOLESOME |
|
|
648 | } |
673 | } |
649 | } |
674 | } |
|
|
675 | |
|
|
676 | if (flags & bgPixmap_t::tintNeeded) |
|
|
677 | { |
|
|
678 | if (flags & bgPixmap_t::tintWholesome) |
|
|
679 | flags |= bgPixmap_t::tintServerSide; |
|
|
680 | #if XFT |
|
|
681 | /* TODO: add logic for XRENDER tinting */ |
|
|
682 | flags |= bgPixmap_t::tintServerSide; |
|
|
683 | #endif |
|
|
684 | } |
|
|
685 | |
650 | return flags; |
686 | return flags; |
651 | } |
687 | } |
652 | |
688 | |
653 | bool |
689 | bool |
654 | bgPixmap_t::set_tint (rxvt_color &new_tint) |
690 | bgPixmap_t::set_tint (rxvt_color &new_tint) |
… | |
… | |
684 | if (new_shade == 100) |
720 | if (new_shade == 100) |
685 | new_shade = 0; |
721 | new_shade = 0; |
686 | |
722 | |
687 | if (new_shade != shade) |
723 | if (new_shade != shade) |
688 | { |
724 | { |
689 | unsigned long new_flags = compute_tint_shade_flags (&tint, new_shade); |
725 | unsigned long new_flags = compute_tint_shade_flags ((flags & tintSet) ? &tint : NULL, new_shade); |
690 | shade = new_shade; |
726 | shade = new_shade; |
691 | flags = (flags & ~tintFlags) | new_flags; |
727 | flags = (flags & ~tintFlags) | new_flags; |
692 | return true; |
728 | return true; |
693 | } |
729 | } |
694 | return false; |
730 | return false; |
… | |
… | |
720 | int window_width = target->szHint.width; |
756 | int window_width = target->szHint.width; |
721 | int window_height = target->szHint.height; |
757 | int window_height = target->szHint.height; |
722 | int sx, sy; |
758 | int sx, sy; |
723 | XGCValues gcv; |
759 | XGCValues gcv; |
724 | |
760 | |
|
|
761 | TIMING_TEST_START (tp); |
725 | target->get_window_origin (sx, sy); |
762 | target->get_window_origin (sx, sy); |
726 | |
763 | |
727 | /* check if we are outside of the visible part of the virtual screen : */ |
764 | /* check if we are outside of the visible part of the virtual screen : */ |
728 | if (sx + window_width <= 0 || sy + window_height <= 0 |
765 | if (sx + window_width <= 0 || sy + window_height <= 0 |
729 | || sx >= root_width || sy >= root_height) |
766 | || sx >= root_width || sy >= root_height) |
… | |
… | |
808 | { |
845 | { |
809 | XFillRectangle (dpy, tiled_root_pmap, gc, 0, 0, window_width, window_height); |
846 | XFillRectangle (dpy, tiled_root_pmap, gc, 0, 0, window_width, window_height); |
810 | result |= transpPmapTiled; |
847 | result |= transpPmapTiled; |
811 | } |
848 | } |
812 | } |
849 | } |
|
|
850 | TIMING_TEST_PRINT_RESULT (tp); |
813 | |
851 | |
814 | if (tiled_root_pmap != None) |
852 | if (tiled_root_pmap != None) |
815 | { |
853 | { |
816 | if (flags & tintNeeded && !need_client_side_rendering ()) |
854 | if ((flags & tintNeeded) && !need_client_side_rendering ()) |
|
|
855 | { |
|
|
856 | if (flags & tintWholesome) |
817 | { |
857 | { |
818 | /* In this case we can tint image server-side getting significant |
858 | /* In this case we can tint image server-side getting significant |
819 | * performance improvements, as we eliminate XImage transfer |
859 | * performance improvements, as we eliminate XImage transfer |
820 | */ |
860 | */ |
821 | gcv.foreground = Pixel (tint); |
861 | gcv.foreground = Pixel (tint); |
822 | gcv.function = GXand; |
862 | gcv.function = GXand; |
823 | gcv.fill_style = FillSolid; |
863 | gcv.fill_style = FillSolid; |
824 | if (gc) |
864 | if (gc) |
825 | XChangeGC (dpy, gc, GCFillStyle | GCForeground | GCFunction, &gcv); |
865 | XChangeGC (dpy, gc, GCFillStyle | GCForeground | GCFunction, &gcv); |
826 | else |
866 | else |
827 | gc = XCreateGC (dpy, root, GCFillStyle | GCForeground | GCFunction, &gcv); |
867 | gc = XCreateGC (dpy, root, GCFillStyle | GCForeground | GCFunction, &gcv); |
828 | if (gc) |
868 | if (gc) |
829 | { |
869 | { |
830 | XFillRectangle (dpy, tiled_root_pmap, gc, 0, 0, window_width, window_height); |
870 | XFillRectangle (dpy, tiled_root_pmap, gc, 0, 0, window_width, window_height); |
831 | result |= transpPmapTinted; |
871 | result |= transpPmapTinted; |
832 | } |
872 | } |
833 | } |
873 | } |
|
|
874 | else |
|
|
875 | { |
|
|
876 | #if XFT /* TODO : implement proper detection of XRENDER, as XFT may be present without XRENDER ! */ |
|
|
877 | rgba c (rgba::MAX_CC,rgba::MAX_CC,rgba::MAX_CC); |
|
|
878 | if (flags & tintSet) |
|
|
879 | tint.get (c); |
|
|
880 | if (shade > 0 && shade < 100) |
|
|
881 | { |
|
|
882 | c.r = (c.r * shade) / 100; |
|
|
883 | c.g = (c.g * shade) / 100; |
|
|
884 | c.b = (c.b * shade) / 100; |
|
|
885 | } |
|
|
886 | else if( shade > 100 && shade < 200) |
|
|
887 | { |
|
|
888 | c.r = (c.r * (200 - shade)) / 100; |
|
|
889 | c.g = (c.g * (200 - shade)) / 100; |
|
|
890 | c.b = (c.b * (200 - shade)) / 100; |
|
|
891 | } |
|
|
892 | |
|
|
893 | XRenderPictFormat pf; |
|
|
894 | pf.type = PictTypeDirect; |
|
|
895 | pf.depth = 32; |
|
|
896 | pf.direct.redMask = 0xff; |
|
|
897 | pf.direct.greenMask = 0xff; |
|
|
898 | pf.direct.blueMask = 0xff; |
|
|
899 | pf.direct.alphaMask = 0xff; |
|
|
900 | |
|
|
901 | XRenderPictFormat *solid_format = XRenderFindFormat (dpy, |
|
|
902 | (PictFormatType| |
|
|
903 | PictFormatDepth| |
|
|
904 | PictFormatRedMask| |
|
|
905 | PictFormatGreenMask| |
|
|
906 | PictFormatBlueMask| |
|
|
907 | PictFormatAlphaMask), |
|
|
908 | &pf, |
|
|
909 | 0); |
|
|
910 | XRenderPictFormat *root_format = XRenderFindVisualFormat (dpy, DefaultVisualOfScreen (ScreenOfDisplay (dpy, target->display->screen))); |
|
|
911 | XRenderPictureAttributes pa ; |
|
|
912 | |
|
|
913 | Picture back_pic = XRenderCreatePicture (dpy, tiled_root_pmap, root_format, 0, &pa); |
|
|
914 | |
|
|
915 | pa.repeat = True; |
|
|
916 | |
|
|
917 | Pixmap overlay_pmap = XCreatePixmap (dpy, root, 1, 1, 32); |
|
|
918 | Picture overlay_pic = XRenderCreatePicture (dpy, overlay_pmap, solid_format, CPRepeat, &pa); |
|
|
919 | XFreePixmap (dpy, overlay_pmap); |
|
|
920 | |
|
|
921 | pa.component_alpha = True; |
|
|
922 | Pixmap mask_pmap = XCreatePixmap (dpy, root, 1, 1, 32); |
|
|
923 | Picture mask_pic = XRenderCreatePicture (dpy, mask_pmap, solid_format, CPRepeat|CPComponentAlpha, &pa); |
|
|
924 | XFreePixmap (dpy, mask_pmap); |
|
|
925 | |
|
|
926 | if (mask_pic && overlay_pic && back_pic) |
|
|
927 | { |
|
|
928 | XRenderColor mask_c; |
|
|
929 | |
|
|
930 | memset (&mask_c, (shade > 100) ? 0xFF : 0x0, sizeof(mask_c)); |
|
|
931 | mask_c.alpha = 0xffff; |
|
|
932 | XRenderFillRectangle (dpy, PictOpSrc, overlay_pic, &mask_c, 0, 0, 1, 1); |
|
|
933 | memset (&mask_c, 0x0, sizeof(mask_c)); |
|
|
934 | mask_c.alpha = 0; |
|
|
935 | if (c.r == c.b && c.b == c.g) /* pure shading */ |
|
|
936 | { |
|
|
937 | mask_c.red = mask_c.green = mask_c.blue = 0xffff-c.r; |
|
|
938 | XRenderFillRectangle (dpy, PictOpSrc, mask_pic, &mask_c, 0, 0, 1, 1); |
|
|
939 | XRenderComposite (dpy, PictOpOver, overlay_pic, mask_pic, back_pic, 0, 0, 0, 0, 0, 0, window_width, window_height); |
|
|
940 | } |
|
|
941 | else |
|
|
942 | { |
|
|
943 | mask_c.red = 0xffff-c.r; |
|
|
944 | XRenderFillRectangle (dpy, PictOpSrc, mask_pic, &mask_c, 0, 0, 1, 1); |
|
|
945 | XRenderComposite (dpy, PictOpOver, overlay_pic, mask_pic, back_pic, 0, 0, 0, 0, 0, 0, window_width, window_height); |
|
|
946 | mask_c.red = 0; |
|
|
947 | mask_c.green = 0xffff-c.g; |
|
|
948 | XRenderFillRectangle (dpy, PictOpSrc, mask_pic, &mask_c, 0, 0, 1, 1); |
|
|
949 | XRenderComposite (dpy, PictOpOver, overlay_pic, mask_pic, back_pic, 0, 0, 0, 0, 0, 0, window_width, window_height); |
|
|
950 | mask_c.green = 0; |
|
|
951 | mask_c.blue = 0xffff-c.b; |
|
|
952 | XRenderFillRectangle (dpy, PictOpSrc, mask_pic, &mask_c, 0, 0, 1, 1); |
|
|
953 | XRenderComposite (dpy, PictOpOver, overlay_pic, mask_pic, back_pic, 0, 0, 0, 0, 0, 0, window_width, window_height); |
|
|
954 | } |
|
|
955 | result |= transpPmapTinted; |
|
|
956 | } |
|
|
957 | XRenderFreePicture (dpy, mask_pic); |
|
|
958 | XRenderFreePicture (dpy, overlay_pic); |
|
|
959 | XRenderFreePicture (dpy, back_pic); |
|
|
960 | #endif |
|
|
961 | } |
|
|
962 | } |
834 | if (pixmap) |
963 | if (pixmap) |
835 | XFreePixmap (dpy, pixmap); |
964 | XFreePixmap (dpy, pixmap); |
836 | pixmap = tiled_root_pmap; |
965 | pixmap = tiled_root_pmap; |
837 | pmap_width = window_width; |
966 | pmap_width = window_width; |
838 | pmap_height = window_height; |
967 | pmap_height = window_height; |
839 | pmap_depth = root_depth; |
968 | pmap_depth = root_depth; |
840 | } |
969 | } |
841 | |
970 | |
842 | if (gc) |
971 | if (gc) |
843 | XFreeGC (dpy, gc); |
972 | XFreeGC (dpy, gc); |
|
|
973 | |
|
|
974 | TIMING_TEST_PRINT_RESULT (tp); |
844 | |
975 | |
845 | return result; |
976 | return result; |
846 | } |
977 | } |
847 | |
978 | |
848 | bool |
979 | bool |
849 | bgPixmap_t::set_root_pixmap () |
980 | bgPixmap_t::set_root_pixmap () |
850 | { |
981 | { |
… | |
… | |
1155 | |
1286 | |
1156 | if (visual->c_class != TrueColor || srcImage->format != ZPixmap) return ; |
1287 | if (visual->c_class != TrueColor || srcImage->format != ZPixmap) return ; |
1157 | |
1288 | |
1158 | if (shade == 0) |
1289 | if (shade == 0) |
1159 | shade = 100; |
1290 | shade = 100; |
1160 | |
1291 | |
1161 | /* for convenience */ |
1292 | /* for convenience */ |
1162 | mask_r = visual->red_mask; |
1293 | mask_r = visual->red_mask; |
1163 | mask_g = visual->green_mask; |
1294 | mask_g = visual->green_mask; |
1164 | mask_b = visual->blue_mask; |
1295 | mask_b = visual->blue_mask; |
1165 | |
1296 | |
… | |
… | |
1387 | Window cr; |
1518 | Window cr; |
1388 | unsigned int rootpixmap_w = 0, rootpixmap_h = 0; |
1519 | unsigned int rootpixmap_w = 0, rootpixmap_h = 0; |
1389 | |
1520 | |
1390 | if (!option (Opt_transparent)) |
1521 | if (!option (Opt_transparent)) |
1391 | return; /* Don't try any more */ |
1522 | return; /* Don't try any more */ |
1392 | #if 0 |
|
|
1393 | struct timeval stv; |
|
|
1394 | gettimeofday (&stv,NULL); |
|
|
1395 | #define PRINT_BACKGROUND_OP_TIME do{ struct timeval tv;gettimeofday (&tv,NULL); tv.tv_sec-= stv.tv_sec;\ |
|
|
1396 | fprintf (stderr,"%d: elapsed %ld usec\n",__LINE__,\ |
|
|
1397 | tv.tv_sec*1000000+tv.tv_usec-stv.tv_usec );}while(0) |
|
|
1398 | #else |
|
|
1399 | #define PRINT_BACKGROUND_OP_TIME do{}while(0) |
|
|
1400 | #endif |
|
|
1401 | |
|
|
1402 | |
1523 | |
1403 | XGetWindowAttributes (dpy, display->root, &wrootattr); |
1524 | XGetWindowAttributes (dpy, display->root, &wrootattr); |
1404 | rootdepth = wrootattr.depth; |
1525 | rootdepth = wrootattr.depth; |
1405 | |
1526 | |
1406 | XGetWindowAttributes (dpy, parent[0], &wattr); |
1527 | XGetWindowAttributes (dpy, parent[0], &wattr); |
… | |
… | |
1540 | { |
1661 | { |
1541 | XImage *image = XGetImage (dpy, bgPixmap.pixmap, 0, 0, szHint.width, szHint.height, AllPlanes, ZPixmap); |
1662 | XImage *image = XGetImage (dpy, bgPixmap.pixmap, 0, 0, szHint.width, szHint.height, AllPlanes, ZPixmap); |
1542 | success = False; |
1663 | success = False; |
1543 | if (image != NULL) |
1664 | if (image != NULL) |
1544 | { |
1665 | { |
1545 | PRINT_BACKGROUND_OP_TIME; |
|
|
1546 | if (gc == NULL) |
1666 | if (gc == NULL) |
1547 | gc = XCreateGC (dpy, vt, 0UL, &gcvalue); |
1667 | gc = XCreateGC (dpy, vt, 0UL, &gcvalue); |
1548 | if (ISSET_PIXCOLOR (Color_tint) || shade != 100) |
1668 | if (ISSET_PIXCOLOR (Color_tint) || shade != 100) |
1549 | ShadeXImage (this, image, shade, c.r, c.g, c.b); |
1669 | ShadeXImage (this, image, shade, c.r, c.g, c.b); |
1550 | XPutImage (dpy, bgPixmap.pixmap, gc, image, 0, 0, 0, 0, image->width, image->height); |
1670 | XPutImage (dpy, bgPixmap.pixmap, gc, image, 0, 0, 0, 0, image->width, image->height); |
1551 | XDestroyImage (image); |
1671 | XDestroyImage (image); |
1552 | success = True; |
1672 | success = True; |
1553 | } |
1673 | } |
1554 | } |
1674 | } |
1555 | #endif /* HAVE_AFTERIMAGE */ |
1675 | #endif /* HAVE_AFTERIMAGE */ |
1556 | PRINT_BACKGROUND_OP_TIME; |
|
|
1557 | |
1676 | |
1558 | if (gc != NULL) |
1677 | if (gc != NULL) |
1559 | XFreeGC (dpy, gc); |
1678 | XFreeGC (dpy, gc); |
1560 | |
1679 | |
1561 | bgPixmap.apply(); |
1680 | bgPixmap.apply(); |