Share the popcount() fallback for MSVC

We use __builtin_popcount() in a couple of places, so it makes sense to
have it in one header.
This commit is contained in:
Emmanuele Bassi 2020-12-09 15:48:09 +00:00
parent c5dd34344f
commit b8a651df47
4 changed files with 58 additions and 47 deletions

View File

@ -169,6 +169,7 @@ private_headers = [
'gtkplacesviewprivate.h',
'gtkplacesviewrowprivate.h',
'gtkpointerfocusprivate.h',
'gtkpopcountprivate.h',
'gtkpopoverprivate.h',
'gtkprinterprivate.h',
'gtkprintoperation-private.h',

View File

@ -24,9 +24,7 @@
#include "gtkstyleproviderprivate.h"
#include "gtksettingsprivate.h"
#ifdef _MSC_VER
# include <intrin.h>
#endif
#include "gtkpopcountprivate.h"
/* repeated API */
@ -1453,39 +1451,6 @@ static const GtkCssValueClass GTK_CSS_VALUE_FONT_VARIANT_EAST_ASIAN = {
gtk_css_font_variant_east_asian_value_print
};
#ifdef _MSC_VER
/* __builtin_popcount is a GCC-only function
so we need to define it for ourselves somehow */
static inline guint
__msvc_compat_popcnt (guint32 value)
{
static gssize popcnt_checked = 0;
static gboolean have_popcnt = FALSE;
# if defined (_M_AMD64) || defined (_M_X64) || (_M_IX86)
if (g_once_init_enter (&popcnt_checked))
{
int cpuinfo[4] = {-1};
__cpuid (cpuinfo, 1);
have_popcnt = (cpuinfo[2] & 0x00800000) != 0;
g_once_init_leave (&popcnt_checked, 1);
}
# endif
if (have_popcnt)
return __popcnt (value);
else
/* http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel */
return (((value & 0xfff) * 0x1001001001001ULL & 0x84210842108421ULL) % 0x1f) +
((((value & 0xfff000) >> 12) * 0x1001001001001ULL & 0x84210842108421ULL) % 0x1f) +
(((value >> 24) * 0x1001001001001ULL & 0x84210842108421ULL) % 0x1f);
}
# define __builtin_popcount(v) __msvc_compat_popcnt(v)
#endif
static gboolean
east_asian_value_is_valid (GtkCssFontVariantEastAsian east_asian)
{
@ -1493,7 +1458,7 @@ east_asian_value_is_valid (GtkCssFontVariantEastAsian east_asian)
(east_asian != GTK_CSS_FONT_VARIANT_EAST_ASIAN_NORMAL))
return FALSE;
if (__builtin_popcount (east_asian & (GTK_CSS_FONT_VARIANT_EAST_ASIAN_JIS78 |
if (gtk_popcount (east_asian & (GTK_CSS_FONT_VARIANT_EAST_ASIAN_JIS78 |
GTK_CSS_FONT_VARIANT_EAST_ASIAN_JIS83 |
GTK_CSS_FONT_VARIANT_EAST_ASIAN_JIS90 |
GTK_CSS_FONT_VARIANT_EAST_ASIAN_JIS04 |
@ -1501,7 +1466,7 @@ east_asian_value_is_valid (GtkCssFontVariantEastAsian east_asian)
GTK_CSS_FONT_VARIANT_EAST_ASIAN_TRADITIONAL)) > 1)
return FALSE;
if (__builtin_popcount (east_asian & (GTK_CSS_FONT_VARIANT_EAST_ASIAN_FULL_WIDTH |
if (gtk_popcount (east_asian & (GTK_CSS_FONT_VARIANT_EAST_ASIAN_FULL_WIDTH |
GTK_CSS_FONT_VARIANT_EAST_ASIAN_PROPORTIONAL)) > 1)
return FALSE;

View File

@ -132,6 +132,7 @@
#include "gtkimmodule.h"
#include "gtkroot.h"
#include "gtknative.h"
#include "gtkpopcountprivate.h"
#include "inspector/window.h"
@ -1484,9 +1485,11 @@ handle_pointing_event (GdkEvent *event)
modifiers = gdk_event_get_modifier_state (event);
if (type == GDK_BUTTON_RELEASE &&
__builtin_popcount (modifiers &
(GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK |
GDK_BUTTON4_MASK | GDK_BUTTON5_MASK)) == 1)
gtk_popcount (modifiers & (GDK_BUTTON1_MASK |
GDK_BUTTON2_MASK |
GDK_BUTTON3_MASK |
GDK_BUTTON4_MASK |
GDK_BUTTON5_MASK)) == 1)
{
GtkWidget *new_target = gtk_widget_pick (native, x, y, GTK_PICK_DEFAULT);

42
gtk/gtkpopcountprivate.h Normal file
View File

@ -0,0 +1,42 @@
/* gtkpopcountprivate.h: Private implementation of popcount
*
* Copyright 2020 GNOME Foundation
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#if defined(_MSC_VER)
#include <intrin.h>
static inline guint
gtk_popcount (guint32 value)
{
return __popcnt (value);
}
#elif defined(__GNUC__) || defined(__clang__)
# define gtk_popcount(v) __builtin_popcount(v)
#else
static inline guint
gtk_popcount (guint32 value)
{
/* http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel */
return (((value & 0xfff) * 0x1001001001001ULL & 0x84210842108421ULL) % 0x1f) +
((((value & 0xfff000) >> 12) * 0x1001001001001ULL & 0x84210842108421ULL) % 0x1f) +
(((value >> 24) * 0x1001001001001ULL & 0x84210842108421ULL) % 0x1f);
}
#endif