src/cpuinfo/SDL_cpuinfo.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 22 Jun 2015 23:36:06 -0700
changeset 9776 952ff8a5076f
parent 9619 b94b6d0bff0f
child 9987 d64783aac765
permissions -rw-r--r--
Fixed bug 3030 - SDL_RecreateWindow fails to restore title, icon, etc.

Adam M.

It loses the title and icon when window recreation fails. For instance, this may happen when trying to create an OpenGL ES window on a system that doesn't support it. But at that point, the title and icon have already been lost.
slouken@739
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@9619
     3
  Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
slouken@739
     4
slouken@5535
     5
  This software is provided 'as-is', without any express or implied
slouken@5535
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@5535
     7
  arising from the use of this software.
slouken@739
     8
slouken@5535
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@5535
    10
  including commercial applications, and to alter it and redistribute it
slouken@5535
    11
  freely, subject to the following restrictions:
slouken@739
    12
slouken@5535
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@5535
    14
     claim that you wrote the original software. If you use this software
slouken@5535
    15
     in a product, an acknowledgment in the product documentation would be
slouken@5535
    16
     appreciated but is not required.
slouken@5535
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@5535
    18
     misrepresented as being the original software.
slouken@5535
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@739
    20
*/
slouken@8148
    21
#ifdef TEST_MAIN
slouken@8148
    22
#include "SDL_config.h"
slouken@8148
    23
#else
icculus@8093
    24
#include "../SDL_internal.h"
slouken@8148
    25
#endif
slouken@739
    26
slouken@7828
    27
#if defined(__WIN32__)
slouken@7828
    28
#include "../core/windows/SDL_windows.h"
slouken@7828
    29
#endif
slouken@7828
    30
slouken@739
    31
/* CPU feature detection for SDL */
slouken@739
    32
slouken@1361
    33
#include "SDL_cpuinfo.h"
slouken@1361
    34
slouken@3586
    35
#ifdef HAVE_SYSCONF
slouken@3586
    36
#include <unistd.h>
slouken@3586
    37
#endif
slouken@3579
    38
#ifdef HAVE_SYSCTLBYNAME
slouken@3579
    39
#include <sys/types.h>
slouken@3579
    40
#include <sys/sysctl.h>
slouken@3579
    41
#endif
slouken@5389
    42
#if defined(__MACOSX__) && (defined(__ppc__) || defined(__ppc64__))
slouken@5389
    43
#include <sys/sysctl.h>         /* For AltiVec check */
slouken@6363
    44
#elif defined(__OpenBSD__) && defined(__powerpc__)
slouken@6363
    45
#include <sys/param.h>
slouken@6363
    46
#include <sys/sysctl.h> /* For AltiVec check */
slouken@6363
    47
#include <machine/cpu.h>
slouken@5389
    48
#elif SDL_ALTIVEC_BLITTERS && HAVE_SETJMP
slouken@5389
    49
#include <signal.h>
slouken@5389
    50
#include <setjmp.h>
slouken@5389
    51
#endif
slouken@793
    52
slouken@3579
    53
#define CPU_HAS_RDTSC   0x00000001
slouken@5389
    54
#define CPU_HAS_ALTIVEC 0x00000002
slouken@5389
    55
#define CPU_HAS_MMX     0x00000004
slouken@5389
    56
#define CPU_HAS_3DNOW   0x00000008
slouken@5259
    57
#define CPU_HAS_SSE     0x00000010
slouken@5259
    58
#define CPU_HAS_SSE2    0x00000020
slouken@5259
    59
#define CPU_HAS_SSE3    0x00000040
slouken@5389
    60
#define CPU_HAS_SSE41   0x00000100
slouken@5389
    61
#define CPU_HAS_SSE42   0x00000200
slouken@8148
    62
#define CPU_HAS_AVX     0x00000400
slouken@9003
    63
#define CPU_HAS_AVX2    0x00000800
slouken@745
    64
slouken@6363
    65
#if SDL_ALTIVEC_BLITTERS && HAVE_SETJMP && !__MACOSX__ && !__OpenBSD__
slouken@5389
    66
/* This is the brute force way of detecting instruction sets...
slouken@5389
    67
   the idea is borrowed from the libmpeg2 library - thanks!
slouken@5389
    68
 */
slouken@5389
    69
static jmp_buf jmpbuf;
slouken@5389
    70
static void
slouken@5389
    71
illegal_instruction(int sig)
slouken@5389
    72
{
slouken@5389
    73
    longjmp(jmpbuf, 1);
slouken@5389
    74
}
slouken@5389
    75
#endif /* HAVE_SETJMP */
slouken@793
    76
slouken@9003
    77
static int
slouken@1895
    78
CPU_haveCPUID(void)
slouken@745
    79
{
slouken@1895
    80
    int has_CPUID = 0;
slouken@1895
    81
/* *INDENT-OFF* */
icculus@9278
    82
#ifndef SDL_CPUINFO_DISABLED
slouken@745
    83
#if defined(__GNUC__) && defined(i386)
slouken@3579
    84
    __asm__ (
slouken@745
    85
"        pushfl                      # Get original EFLAGS             \n"
slouken@745
    86
"        popl    %%eax                                                 \n"
slouken@745
    87
"        movl    %%eax,%%ecx                                           \n"
slouken@745
    88
"        xorl    $0x200000,%%eax     # Flip ID bit in EFLAGS           \n"
slouken@745
    89
"        pushl   %%eax               # Save new EFLAGS value on stack  \n"
slouken@745
    90
"        popfl                       # Replace current EFLAGS value    \n"
slouken@745
    91
"        pushfl                      # Get new EFLAGS                  \n"
slouken@745
    92
"        popl    %%eax               # Store new EFLAGS in EAX         \n"
slouken@745
    93
"        xorl    %%ecx,%%eax         # Can not toggle ID bit,          \n"
slouken@745
    94
"        jz      1f                  # Processor=80486                 \n"
slouken@745
    95
"        movl    $1,%0               # We have CPUID support           \n"
slouken@745
    96
"1:                                                                    \n"
slouken@3579
    97
    : "=m" (has_CPUID)
slouken@3579
    98
    :
slouken@3579
    99
    : "%eax", "%ecx"
slouken@3579
   100
    );
slouken@881
   101
#elif defined(__GNUC__) && defined(__x86_64__)
slouken@881
   102
/* Technically, if this is being compiled under __x86_64__ then it has 
slouken@8241
   103
   CPUid by definition.  But it's nice to be able to prove it.  :)      */
slouken@3579
   104
    __asm__ (
slouken@881
   105
"        pushfq                      # Get original EFLAGS             \n"
slouken@881
   106
"        popq    %%rax                                                 \n"
slouken@881
   107
"        movq    %%rax,%%rcx                                           \n"
slouken@881
   108
"        xorl    $0x200000,%%eax     # Flip ID bit in EFLAGS           \n"
slouken@881
   109
"        pushq   %%rax               # Save new EFLAGS value on stack  \n"
slouken@881
   110
"        popfq                       # Replace current EFLAGS value    \n"
slouken@881
   111
"        pushfq                      # Get new EFLAGS                  \n"
slouken@881
   112
"        popq    %%rax               # Store new EFLAGS in EAX         \n"
slouken@881
   113
"        xorl    %%ecx,%%eax         # Can not toggle ID bit,          \n"
slouken@881
   114
"        jz      1f                  # Processor=80486                 \n"
slouken@881
   115
"        movl    $1,%0               # We have CPUID support           \n"
slouken@881
   116
"1:                                                                    \n"
slouken@3579
   117
    : "=m" (has_CPUID)
slouken@3579
   118
    :
slouken@3579
   119
    : "%rax", "%rcx"
slouken@3579
   120
    );
slouken@1442
   121
#elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
slouken@3579
   122
    __asm {
slouken@745
   123
        pushfd                      ; Get original EFLAGS
slouken@745
   124
        pop     eax
slouken@745
   125
        mov     ecx, eax
slouken@745
   126
        xor     eax, 200000h        ; Flip ID bit in EFLAGS
slouken@745
   127
        push    eax                 ; Save new EFLAGS value on stack
slouken@745
   128
        popfd                       ; Replace current EFLAGS value
slouken@745
   129
        pushfd                      ; Get new EFLAGS
slouken@745
   130
        pop     eax                 ; Store new EFLAGS in EAX
slouken@745
   131
        xor     eax, ecx            ; Can not toggle ID bit,
slouken@745
   132
        jz      done                ; Processor=80486
slouken@745
   133
        mov     has_CPUID,1         ; We have CPUID support
slouken@745
   134
done:
slouken@3579
   135
    }
slouken@8241
   136
#elif defined(_MSC_VER) && defined(_M_X64)
slouken@8241
   137
    has_CPUID = 1;
slouken@1864
   138
#elif defined(__sun) && defined(__i386)
slouken@3579
   139
    __asm (
icculus@1229
   140
"       pushfl                 \n"
slouken@3584
   141
"       popl    %eax           \n"
slouken@3584
   142
"       movl    %eax,%ecx      \n"
slouken@3584
   143
"       xorl    $0x200000,%eax \n"
slouken@3584
   144
"       pushl   %eax           \n"
slouken@3584
   145
"       popfl                  \n"
slouken@3584
   146
"       pushfl                 \n"
slouken@3584
   147
"       popl    %eax           \n"
slouken@3584
   148
"       xorl    %ecx,%eax      \n"
slouken@3584
   149
"       jz      1f             \n"
slouken@3584
   150
"       movl    $1,-8(%ebp)    \n"
icculus@1229
   151
"1:                            \n"
slouken@3579
   152
    );
icculus@1229
   153
#elif defined(__sun) && defined(__amd64)
slouken@3579
   154
    __asm (
icculus@1229
   155
"       pushfq                 \n"
icculus@1229
   156
"       popq    %rax           \n"
icculus@1229
   157
"       movq    %rax,%rcx      \n"
icculus@1229
   158
"       xorl    $0x200000,%eax \n"
icculus@1229
   159
"       pushq   %rax           \n"
icculus@1229
   160
"       popfq                  \n"
icculus@1229
   161
"       pushfq                 \n"
icculus@1229
   162
"       popq    %rax           \n"
icculus@1229
   163
"       xorl    %ecx,%eax      \n"
icculus@1229
   164
"       jz      1f             \n"
icculus@1229
   165
"       movl    $1,-8(%rbp)    \n"
icculus@1229
   166
"1:                            \n"
slouken@3579
   167
    );
slouken@745
   168
#endif
icculus@9278
   169
#endif
slouken@1895
   170
/* *INDENT-ON* */
slouken@1895
   171
    return has_CPUID;
slouken@745
   172
}
slouken@739
   173
slouken@3587
   174
#if defined(__GNUC__) && defined(i386)
slouken@3580
   175
#define cpuid(func, a, b, c, d) \
slouken@3584
   176
    __asm__ __volatile__ ( \
slouken@3584
   177
"        pushl %%ebx        \n" \
slouken@9003
   178
"        xorl %%ecx,%%ecx   \n" \
slouken@3584
   179
"        cpuid              \n" \
slouken@3584
   180
"        movl %%ebx, %%esi  \n" \
slouken@3584
   181
"        popl %%ebx         \n" : \
slouken@3584
   182
            "=a" (a), "=S" (b), "=c" (c), "=d" (d) : "a" (func))
slouken@3587
   183
#elif defined(__GNUC__) && defined(__x86_64__)
slouken@3587
   184
#define cpuid(func, a, b, c, d) \
slouken@3587
   185
    __asm__ __volatile__ ( \
slouken@3587
   186
"        pushq %%rbx        \n" \
slouken@9003
   187
"        xorq %%rcx,%%rcx   \n" \
slouken@3587
   188
"        cpuid              \n" \
slouken@3587
   189
"        movq %%rbx, %%rsi  \n" \
slouken@3587
   190
"        popq %%rbx         \n" : \
slouken@3587
   191
            "=a" (a), "=S" (b), "=c" (c), "=d" (d) : "a" (func))
slouken@3579
   192
#elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
slouken@3580
   193
#define cpuid(func, a, b, c, d) \
slouken@3580
   194
    __asm { \
slouken@3580
   195
        __asm mov eax, func \
slouken@9003
   196
        __asm xor ecx, ecx \
slouken@3580
   197
        __asm cpuid \
slouken@3580
   198
        __asm mov a, eax \
slouken@3580
   199
        __asm mov b, ebx \
slouken@3580
   200
        __asm mov c, ecx \
slouken@3580
   201
        __asm mov d, edx \
slouken@8241
   202
}
slouken@8241
   203
#elif defined(_MSC_VER) && defined(_M_X64)
slouken@8241
   204
#define cpuid(func, a, b, c, d) \
slouken@8241
   205
{ \
slouken@8241
   206
    int CPUInfo[4]; \
slouken@8241
   207
    __cpuid(CPUInfo, func); \
slouken@8241
   208
    a = CPUInfo[0]; \
slouken@8241
   209
    b = CPUInfo[1]; \
slouken@8241
   210
    c = CPUInfo[2]; \
slouken@8241
   211
    d = CPUInfo[3]; \
slouken@8241
   212
}
slouken@3579
   213
#else
slouken@3580
   214
#define cpuid(func, a, b, c, d) \
slouken@3580
   215
    a = b = c = d = 0
slouken@3579
   216
#endif
slouken@3579
   217
slouken@9003
   218
static int
slouken@1895
   219
CPU_getCPUIDFeatures(void)
slouken@745
   220
{
slouken@1895
   221
    int features = 0;
slouken@3580
   222
    int a, b, c, d;
slouken@3579
   223
slouken@3580
   224
    cpuid(0, a, b, c, d);
slouken@3580
   225
    if (a >= 1) {
slouken@3580
   226
        cpuid(1, a, b, c, d);
slouken@3580
   227
        features = d;
slouken@3579
   228
    }
slouken@1895
   229
    return features;
slouken@745
   230
}
slouken@745
   231
slouken@9003
   232
static SDL_bool
slouken@9003
   233
CPU_OSSavesYMM(void)
slouken@9003
   234
{
slouken@9003
   235
    int a, b, c, d;
slouken@9003
   236
slouken@9003
   237
    /* Check to make sure we can call xgetbv */
slouken@9003
   238
    cpuid(0, a, b, c, d);
slouken@9003
   239
    if (a < 1) {
slouken@9003
   240
        return SDL_FALSE;
slouken@9003
   241
    }
slouken@9003
   242
    cpuid(1, a, b, c, d);
slouken@9003
   243
    if (!(c & 0x08000000)) {
slouken@9003
   244
        return SDL_FALSE;
slouken@9003
   245
    }
slouken@9003
   246
slouken@9003
   247
    /* Call xgetbv to see if YMM register state is saved */
slouken@9003
   248
    a = 0;
slouken@9003
   249
#if defined(__GNUC__) && (defined(i386) || defined(__x86_64__))
slouken@9003
   250
    asm(".byte 0x0f, 0x01, 0xd0" : "=a" (a) : "c" (0) : "%edx");
dludwig@9047
   251
#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) && (_MSC_FULL_VER >= 160040219) /* VS2010 SP1 */
slouken@9003
   252
    a = (int)_xgetbv(0);
slouken@9003
   253
#elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
slouken@9003
   254
    __asm
slouken@9003
   255
    {
slouken@9003
   256
        xor ecx, ecx
slouken@9003
   257
        _asm _emit 0x0f _asm _emit 0x01 _asm _emit 0xd0
slouken@9005
   258
        mov a, eax
slouken@9003
   259
    }
slouken@9003
   260
#endif
slouken@9003
   261
    return ((a & 6) == 6) ? SDL_TRUE : SDL_FALSE;
slouken@9003
   262
}
slouken@9003
   263
slouken@9003
   264
static int
slouken@1895
   265
CPU_haveRDTSC(void)
slouken@745
   266
{
slouken@1895
   267
    if (CPU_haveCPUID()) {
slouken@1895
   268
        return (CPU_getCPUIDFeatures() & 0x00000010);
slouken@1895
   269
    }
slouken@1895
   270
    return 0;
slouken@745
   271
}
slouken@739
   272
slouken@9003
   273
static int
slouken@5389
   274
CPU_haveAltiVec(void)
slouken@5389
   275
{
slouken@5389
   276
    volatile int altivec = 0;
icculus@9278
   277
#ifndef SDL_CPUINFO_DISABLED
slouken@6363
   278
#if (defined(__MACOSX__) && (defined(__ppc__) || defined(__ppc64__))) || (defined(__OpenBSD__) && defined(__powerpc__))
slouken@6363
   279
#ifdef __OpenBSD__
slouken@6363
   280
    int selectors[2] = { CTL_MACHDEP, CPU_ALTIVEC };
slouken@6363
   281
#else
slouken@5389
   282
    int selectors[2] = { CTL_HW, HW_VECTORUNIT };
slouken@6363
   283
#endif
slouken@5389
   284
    int hasVectorUnit = 0;
slouken@5389
   285
    size_t length = sizeof(hasVectorUnit);
slouken@5389
   286
    int error = sysctl(selectors, 2, &hasVectorUnit, &length, NULL, 0);
slouken@5389
   287
    if (0 == error)
slouken@5389
   288
        altivec = (hasVectorUnit != 0);
slouken@5389
   289
#elif SDL_ALTIVEC_BLITTERS && HAVE_SETJMP
slouken@5389
   290
    void (*handler) (int sig);
slouken@5389
   291
    handler = signal(SIGILL, illegal_instruction);
slouken@5389
   292
    if (setjmp(jmpbuf) == 0) {
slouken@5389
   293
        asm volatile ("mtspr 256, %0\n\t" "vand %%v0, %%v0, %%v0"::"r" (-1));
slouken@5389
   294
        altivec = 1;
slouken@5389
   295
    }
slouken@5389
   296
    signal(SIGILL, handler);
slouken@5389
   297
#endif
icculus@9278
   298
#endif
slouken@5389
   299
    return altivec;
slouken@5389
   300
}
slouken@5389
   301
slouken@9003
   302
static int
slouken@1895
   303
CPU_haveMMX(void)
slouken@745
   304
{
slouken@1895
   305
    if (CPU_haveCPUID()) {
slouken@1895
   306
        return (CPU_getCPUIDFeatures() & 0x00800000);
slouken@1895
   307
    }
slouken@1895
   308
    return 0;
slouken@745
   309
}
slouken@745
   310
slouken@9003
   311
static int
slouken@5389
   312
CPU_have3DNow(void)
slouken@5389
   313
{
slouken@5389
   314
    if (CPU_haveCPUID()) {
slouken@5389
   315
        int a, b, c, d;
slouken@5389
   316
slouken@5389
   317
        cpuid(0x80000000, a, b, c, d);
slouken@5389
   318
        if (a >= 0x80000001) {
slouken@5389
   319
            cpuid(0x80000001, a, b, c, d);
slouken@5389
   320
            return (d & 0x80000000);
slouken@5389
   321
        }
slouken@5389
   322
    }
slouken@5389
   323
    return 0;
slouken@5389
   324
}
slouken@5389
   325
slouken@9003
   326
static int
slouken@1895
   327
CPU_haveSSE(void)
slouken@745
   328
{
slouken@1895
   329
    if (CPU_haveCPUID()) {
slouken@1895
   330
        return (CPU_getCPUIDFeatures() & 0x02000000);
slouken@1895
   331
    }
slouken@1895
   332
    return 0;
slouken@785
   333
}
slouken@785
   334
slouken@9003
   335
static int
slouken@1895
   336
CPU_haveSSE2(void)
slouken@778
   337
{
slouken@1895
   338
    if (CPU_haveCPUID()) {
slouken@1895
   339
        return (CPU_getCPUIDFeatures() & 0x04000000);
slouken@1895
   340
    }
slouken@1895
   341
    return 0;
slouken@1895
   342
}
slouken@1895
   343
slouken@9003
   344
static int
slouken@5259
   345
CPU_haveSSE3(void)
slouken@1895
   346
{
slouken@5259
   347
    if (CPU_haveCPUID()) {
slouken@5259
   348
        int a, b, c, d;
slouken@5259
   349
slouken@5259
   350
        cpuid(0, a, b, c, d);
slouken@5259
   351
        if (a >= 1) {
slouken@5259
   352
            cpuid(1, a, b, c, d);
slouken@5259
   353
            return (c & 0x00000001);
slouken@5259
   354
        }
slouken@1895
   355
    }
slouken@5259
   356
    return 0;
slouken@5259
   357
}
slouken@5259
   358
slouken@9003
   359
static int
slouken@5263
   360
CPU_haveSSE41(void)
slouken@5259
   361
{
slouken@5259
   362
    if (CPU_haveCPUID()) {
slouken@5259
   363
        int a, b, c, d;
slouken@5259
   364
slouken@9003
   365
        cpuid(0, a, b, c, d);
slouken@5259
   366
        if (a >= 1) {
slouken@5259
   367
            cpuid(1, a, b, c, d);
slouken@5263
   368
            return (c & 0x00080000);
slouken@5263
   369
        }
slouken@5263
   370
    }
slouken@5263
   371
    return 0;
slouken@5263
   372
}
slouken@5263
   373
slouken@9003
   374
static int
slouken@5263
   375
CPU_haveSSE42(void)
slouken@5263
   376
{
slouken@5263
   377
    if (CPU_haveCPUID()) {
slouken@5263
   378
        int a, b, c, d;
slouken@5263
   379
slouken@9003
   380
        cpuid(0, a, b, c, d);
slouken@5263
   381
        if (a >= 1) {
slouken@5263
   382
            cpuid(1, a, b, c, d);
slouken@5263
   383
            return (c & 0x00100000);
slouken@5259
   384
        }
slouken@5259
   385
    }
slouken@5259
   386
    return 0;
slouken@778
   387
}
slouken@778
   388
slouken@9003
   389
static int
slouken@8148
   390
CPU_haveAVX(void)
slouken@8148
   391
{
slouken@9003
   392
    if (CPU_haveCPUID() && CPU_OSSavesYMM()) {
slouken@8148
   393
        int a, b, c, d;
slouken@8148
   394
slouken@9003
   395
        cpuid(0, a, b, c, d);
slouken@8148
   396
        if (a >= 1) {
slouken@8148
   397
            cpuid(1, a, b, c, d);
slouken@8148
   398
            return (c & 0x10000000);
slouken@8148
   399
        }
slouken@8148
   400
    }
slouken@8148
   401
    return 0;
slouken@8148
   402
}
slouken@8148
   403
slouken@9003
   404
static int
slouken@9003
   405
CPU_haveAVX2(void)
slouken@9003
   406
{
slouken@9003
   407
    if (CPU_haveCPUID() && CPU_OSSavesYMM()) {
slouken@9003
   408
        int a, b, c, d;
slouken@9003
   409
slouken@9003
   410
        cpuid(0, a, b, c, d);
slouken@9003
   411
        if (a >= 7) {
slouken@9003
   412
            cpuid(7, a, b, c, d);
slouken@9003
   413
            return (b & 0x00000020);
slouken@9003
   414
        }
slouken@9003
   415
    }
slouken@9003
   416
    return 0;
slouken@9003
   417
}
slouken@9003
   418
slouken@3579
   419
static int SDL_CPUCount = 0;
slouken@3579
   420
slouken@3579
   421
int
slouken@5120
   422
SDL_GetCPUCount(void)
slouken@3579
   423
{
slouken@3579
   424
    if (!SDL_CPUCount) {
icculus@9278
   425
#ifndef SDL_CPUINFO_DISABLED
slouken@3606
   426
#if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
slouken@3586
   427
        if (SDL_CPUCount <= 0) {
slouken@3586
   428
            SDL_CPUCount = (int)sysconf(_SC_NPROCESSORS_ONLN);
slouken@3586
   429
        }
slouken@3586
   430
#endif
slouken@3579
   431
#ifdef HAVE_SYSCTLBYNAME
slouken@3586
   432
        if (SDL_CPUCount <= 0) {
slouken@3580
   433
            size_t size = sizeof(SDL_CPUCount);
slouken@3580
   434
            sysctlbyname("hw.ncpu", &SDL_CPUCount, &size, NULL, 0);
slouken@3580
   435
        }
slouken@3580
   436
#endif
slouken@5086
   437
#ifdef __WIN32__
slouken@3586
   438
        if (SDL_CPUCount <= 0) {
slouken@3580
   439
            SYSTEM_INFO info;
slouken@3580
   440
            GetSystemInfo(&info);
slouken@3580
   441
            SDL_CPUCount = info.dwNumberOfProcessors;
slouken@3580
   442
        }
slouken@3579
   443
#endif
icculus@9278
   444
#endif
slouken@3579
   445
        /* There has to be at least 1, right? :) */
slouken@3586
   446
        if (SDL_CPUCount <= 0) {
slouken@3579
   447
            SDL_CPUCount = 1;
slouken@3579
   448
        }
slouken@3579
   449
    }
slouken@3579
   450
    return SDL_CPUCount;
slouken@3579
   451
}
slouken@3579
   452
slouken@3579
   453
/* Oh, such a sweet sweet trick, just not very useful. :) */
slouken@4472
   454
static const char *
slouken@5120
   455
SDL_GetCPUType(void)
slouken@3579
   456
{
slouken@5115
   457
    static char SDL_CPUType[13];
slouken@3579
   458
slouken@3579
   459
    if (!SDL_CPUType[0]) {
slouken@3579
   460
        int i = 0;
slouken@3579
   461
slouken@3579
   462
        if (CPU_haveCPUID()) {
icculus@9300
   463
            int a, b, c, d;
slouken@5115
   464
            cpuid(0x00000000, a, b, c, d);
icculus@9300
   465
            (void) a;
slouken@5115
   466
            SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
slouken@5115
   467
            SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
slouken@5115
   468
            SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
icculus@8642
   469
            SDL_CPUType[i++] = (char)(b & 0xff);
icculus@8642
   470
slouken@5115
   471
            SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
slouken@5115
   472
            SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
slouken@5115
   473
            SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
icculus@8642
   474
            SDL_CPUType[i++] = (char)(d & 0xff);
icculus@8642
   475
slouken@5115
   476
            SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
slouken@5115
   477
            SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
slouken@5115
   478
            SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
icculus@8642
   479
            SDL_CPUType[i++] = (char)(c & 0xff);
slouken@5115
   480
        }
slouken@5115
   481
        if (!SDL_CPUType[0]) {
slouken@5115
   482
            SDL_strlcpy(SDL_CPUType, "Unknown", sizeof(SDL_CPUType));
slouken@5115
   483
        }
slouken@5115
   484
    }
slouken@5115
   485
    return SDL_CPUType;
slouken@5115
   486
}
slouken@5115
   487
icculus@5981
   488
icculus@5981
   489
#ifdef TEST_MAIN  /* !!! FIXME: only used for test at the moment. */
slouken@5115
   490
static const char *
slouken@5120
   491
SDL_GetCPUName(void)
slouken@5115
   492
{
slouken@5115
   493
    static char SDL_CPUName[48];
slouken@5115
   494
slouken@5115
   495
    if (!SDL_CPUName[0]) {
slouken@5115
   496
        int i = 0;
slouken@5115
   497
        int a, b, c, d;
slouken@5115
   498
slouken@5115
   499
        if (CPU_haveCPUID()) {
slouken@3580
   500
            cpuid(0x80000000, a, b, c, d);
slouken@3580
   501
            if (a >= 0x80000004) {
slouken@3580
   502
                cpuid(0x80000002, a, b, c, d);
slouken@5115
   503
                SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
slouken@5115
   504
                SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
slouken@5115
   505
                SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
slouken@5115
   506
                SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
slouken@5115
   507
                SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
slouken@5115
   508
                SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
slouken@5115
   509
                SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
slouken@5115
   510
                SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
slouken@5115
   511
                SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
slouken@5115
   512
                SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
slouken@5115
   513
                SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
slouken@5115
   514
                SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
slouken@5115
   515
                SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
slouken@5115
   516
                SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
slouken@5115
   517
                SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
slouken@5115
   518
                SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
slouken@3580
   519
                cpuid(0x80000003, a, b, c, d);
slouken@5115
   520
                SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
slouken@5115
   521
                SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
slouken@5115
   522
                SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
slouken@5115
   523
                SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
slouken@5115
   524
                SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
slouken@5115
   525
                SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
slouken@5115
   526
                SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
slouken@5115
   527
                SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
slouken@5115
   528
                SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
slouken@5115
   529
                SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
slouken@5115
   530
                SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
slouken@5115
   531
                SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
slouken@5115
   532
                SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
slouken@5115
   533
                SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
slouken@5115
   534
                SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
slouken@5115
   535
                SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
slouken@3580
   536
                cpuid(0x80000004, a, b, c, d);
slouken@5115
   537
                SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
slouken@5115
   538
                SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
slouken@5115
   539
                SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
slouken@5115
   540
                SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
slouken@5115
   541
                SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
slouken@5115
   542
                SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
slouken@5115
   543
                SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
slouken@5115
   544
                SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
slouken@5115
   545
                SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
slouken@5115
   546
                SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
slouken@5115
   547
                SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
slouken@5115
   548
                SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
slouken@5115
   549
                SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
slouken@5115
   550
                SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
slouken@5115
   551
                SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
slouken@5115
   552
                SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
slouken@3579
   553
            }
slouken@3579
   554
        }
slouken@5115
   555
        if (!SDL_CPUName[0]) {
slouken@5115
   556
            SDL_strlcpy(SDL_CPUName, "Unknown", sizeof(SDL_CPUName));
slouken@3579
   557
        }
slouken@3579
   558
    }
slouken@5115
   559
    return SDL_CPUName;
slouken@5115
   560
}
icculus@5981
   561
#endif
slouken@5115
   562
slouken@5120
   563
int
slouken@5120
   564
SDL_GetCPUCacheLineSize(void)
slouken@5115
   565
{
slouken@5115
   566
    const char *cpuType = SDL_GetCPUType();
icculus@9300
   567
    int a, b, c, d;
icculus@9300
   568
    (void) a; (void) b; (void) c; (void) d;
slouken@5115
   569
    if (SDL_strcmp(cpuType, "GenuineIntel") == 0) {
slouken@5115
   570
        cpuid(0x00000001, a, b, c, d);
slouken@5115
   571
        return (((b >> 8) & 0xff) * 8);
slouken@5115
   572
    } else if (SDL_strcmp(cpuType, "AuthenticAMD") == 0) {
slouken@5115
   573
        cpuid(0x80000005, a, b, c, d);
slouken@5115
   574
        return (c & 0xff);
slouken@5115
   575
    } else {
slouken@5115
   576
        /* Just make a guess here... */
slouken@5115
   577
        return SDL_CACHELINE_SIZE;
slouken@5115
   578
    }
slouken@3579
   579
}
slouken@3579
   580
slouken@739
   581
static Uint32 SDL_CPUFeatures = 0xFFFFFFFF;
slouken@739
   582
slouken@1895
   583
static Uint32
slouken@1895
   584
SDL_GetCPUFeatures(void)
slouken@739
   585
{
slouken@1895
   586
    if (SDL_CPUFeatures == 0xFFFFFFFF) {
slouken@1895
   587
        SDL_CPUFeatures = 0;
slouken@1895
   588
        if (CPU_haveRDTSC()) {
slouken@1895
   589
            SDL_CPUFeatures |= CPU_HAS_RDTSC;
slouken@1895
   590
        }
slouken@5389
   591
        if (CPU_haveAltiVec()) {
slouken@5389
   592
            SDL_CPUFeatures |= CPU_HAS_ALTIVEC;
slouken@5389
   593
        }
slouken@1895
   594
        if (CPU_haveMMX()) {
slouken@1895
   595
            SDL_CPUFeatures |= CPU_HAS_MMX;
slouken@1895
   596
        }
slouken@5389
   597
        if (CPU_have3DNow()) {
slouken@5389
   598
            SDL_CPUFeatures |= CPU_HAS_3DNOW;
slouken@5389
   599
        }
slouken@1895
   600
        if (CPU_haveSSE()) {
slouken@1895
   601
            SDL_CPUFeatures |= CPU_HAS_SSE;
slouken@1895
   602
        }
slouken@1895
   603
        if (CPU_haveSSE2()) {
slouken@1895
   604
            SDL_CPUFeatures |= CPU_HAS_SSE2;
slouken@1895
   605
        }
slouken@5259
   606
        if (CPU_haveSSE3()) {
slouken@5259
   607
            SDL_CPUFeatures |= CPU_HAS_SSE3;
slouken@5259
   608
        }
slouken@5263
   609
        if (CPU_haveSSE41()) {
slouken@5263
   610
            SDL_CPUFeatures |= CPU_HAS_SSE41;
slouken@5263
   611
        }
slouken@5263
   612
        if (CPU_haveSSE42()) {
slouken@5263
   613
            SDL_CPUFeatures |= CPU_HAS_SSE42;
slouken@1895
   614
        }
slouken@8148
   615
        if (CPU_haveAVX()) {
slouken@8148
   616
            SDL_CPUFeatures |= CPU_HAS_AVX;
slouken@8148
   617
        }
slouken@9003
   618
        if (CPU_haveAVX2()) {
slouken@9003
   619
            SDL_CPUFeatures |= CPU_HAS_AVX2;
slouken@9003
   620
        }
slouken@1895
   621
    }
slouken@1895
   622
    return SDL_CPUFeatures;
slouken@739
   623
}
slouken@739
   624
slouken@1895
   625
SDL_bool
slouken@1895
   626
SDL_HasRDTSC(void)
slouken@745
   627
{
slouken@1895
   628
    if (SDL_GetCPUFeatures() & CPU_HAS_RDTSC) {
slouken@1895
   629
        return SDL_TRUE;
slouken@1895
   630
    }
slouken@1895
   631
    return SDL_FALSE;
slouken@1895
   632
}
slouken@1895
   633
slouken@1895
   634
SDL_bool
slouken@5389
   635
SDL_HasAltiVec(void)
slouken@5389
   636
{
slouken@5389
   637
    if (SDL_GetCPUFeatures() & CPU_HAS_ALTIVEC) {
slouken@5389
   638
        return SDL_TRUE;
slouken@5389
   639
    }
slouken@5389
   640
    return SDL_FALSE;
slouken@5389
   641
}
slouken@5389
   642
slouken@5389
   643
SDL_bool
slouken@1895
   644
SDL_HasMMX(void)
slouken@1895
   645
{
slouken@1895
   646
    if (SDL_GetCPUFeatures() & CPU_HAS_MMX) {
slouken@1895
   647
        return SDL_TRUE;
slouken@1895
   648
    }
slouken@1895
   649
    return SDL_FALSE;
slouken@745
   650
}
slouken@745
   651
slouken@1895
   652
SDL_bool
slouken@5389
   653
SDL_Has3DNow(void)
slouken@5389
   654
{
slouken@5389
   655
    if (SDL_GetCPUFeatures() & CPU_HAS_3DNOW) {
slouken@5389
   656
        return SDL_TRUE;
slouken@5389
   657
    }
slouken@5389
   658
    return SDL_FALSE;
slouken@5389
   659
}
slouken@5389
   660
slouken@5389
   661
SDL_bool
slouken@1895
   662
SDL_HasSSE(void)
slouken@739
   663
{
slouken@1895
   664
    if (SDL_GetCPUFeatures() & CPU_HAS_SSE) {
slouken@1895
   665
        return SDL_TRUE;
slouken@1895
   666
    }
slouken@1895
   667
    return SDL_FALSE;
slouken@739
   668
}
slouken@739
   669
slouken@1895
   670
SDL_bool
slouken@1895
   671
SDL_HasSSE2(void)
slouken@804
   672
{
slouken@1895
   673
    if (SDL_GetCPUFeatures() & CPU_HAS_SSE2) {
slouken@1895
   674
        return SDL_TRUE;
slouken@1895
   675
    }
slouken@1895
   676
    return SDL_FALSE;
slouken@804
   677
}
slouken@804
   678
slouken@1895
   679
SDL_bool
slouken@5259
   680
SDL_HasSSE3(void)
slouken@778
   681
{
slouken@5259
   682
    if (SDL_GetCPUFeatures() & CPU_HAS_SSE3) {
slouken@5259
   683
        return SDL_TRUE;
slouken@5259
   684
    }
slouken@5259
   685
    return SDL_FALSE;
slouken@5259
   686
}
slouken@5259
   687
slouken@5259
   688
SDL_bool
slouken@5263
   689
SDL_HasSSE41(void)
slouken@5259
   690
{
slouken@5263
   691
    if (SDL_GetCPUFeatures() & CPU_HAS_SSE41) {
slouken@5263
   692
        return SDL_TRUE;
slouken@5263
   693
    }
slouken@5263
   694
    return SDL_FALSE;
slouken@5263
   695
}
slouken@5263
   696
slouken@5263
   697
SDL_bool
slouken@5263
   698
SDL_HasSSE42(void)
slouken@5263
   699
{
slouken@5263
   700
    if (SDL_GetCPUFeatures() & CPU_HAS_SSE42) {
slouken@1895
   701
        return SDL_TRUE;
slouken@1895
   702
    }
slouken@1895
   703
    return SDL_FALSE;
slouken@778
   704
}
slouken@778
   705
slouken@8148
   706
SDL_bool
slouken@8148
   707
SDL_HasAVX(void)
slouken@8148
   708
{
slouken@8148
   709
    if (SDL_GetCPUFeatures() & CPU_HAS_AVX) {
slouken@8148
   710
        return SDL_TRUE;
slouken@8148
   711
    }
slouken@8148
   712
    return SDL_FALSE;
slouken@8148
   713
}
slouken@8148
   714
slouken@9003
   715
SDL_bool
slouken@9003
   716
SDL_HasAVX2(void)
slouken@9003
   717
{
slouken@9003
   718
    if (SDL_GetCPUFeatures() & CPU_HAS_AVX2) {
slouken@9003
   719
        return SDL_TRUE;
slouken@9003
   720
    }
slouken@9003
   721
    return SDL_FALSE;
slouken@9003
   722
}
slouken@9003
   723
slouken@7821
   724
static int SDL_SystemRAM = 0;
slouken@7821
   725
slouken@7821
   726
int
slouken@7821
   727
SDL_GetSystemRAM(void)
slouken@7821
   728
{
slouken@7821
   729
    if (!SDL_SystemRAM) {
icculus@9278
   730
#ifndef SDL_CPUINFO_DISABLED
slouken@7821
   731
#if defined(HAVE_SYSCONF) && defined(_SC_PHYS_PAGES) && defined(_SC_PAGESIZE)
slouken@7821
   732
        if (SDL_SystemRAM <= 0) {
slouken@7821
   733
            SDL_SystemRAM = (int)((Sint64)sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGESIZE) / (1024*1024));
slouken@7821
   734
        }
slouken@7821
   735
#endif
slouken@7821
   736
#ifdef HAVE_SYSCTLBYNAME
slouken@7821
   737
        if (SDL_SystemRAM <= 0) {
slouken@8240
   738
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
slouken@7826
   739
#ifdef HW_REALMEM
slouken@7826
   740
            int mib[2] = {CTL_HW, HW_REALMEM};
slouken@7826
   741
#else
slouken@7826
   742
            /* might only report up to 2 GiB */
slouken@7826
   743
            int mib[2] = {CTL_HW, HW_PHYSMEM};
slouken@7826
   744
#endif /* HW_REALMEM */
slouken@7826
   745
#else
slouken@7821
   746
            int mib[2] = {CTL_HW, HW_MEMSIZE};
slouken@8240
   747
#endif /* __FreeBSD__ || __FreeBSD_kernel__ */
slouken@7823
   748
            Uint64 memsize = 0;
slouken@7821
   749
            size_t len = sizeof(memsize);
slouken@7821
   750
            
slouken@7821
   751
            if (sysctl(mib, 2, &memsize, &len, NULL, 0) == 0) {
slouken@7821
   752
                SDL_SystemRAM = (int)(memsize / (1024*1024));
slouken@7821
   753
            }
slouken@7821
   754
        }
slouken@7821
   755
#endif
slouken@7821
   756
#ifdef __WIN32__
slouken@7821
   757
        if (SDL_SystemRAM <= 0) {
slouken@7821
   758
            MEMORYSTATUSEX stat;
icculus@7889
   759
            stat.dwLength = sizeof(stat);
slouken@7821
   760
            if (GlobalMemoryStatusEx(&stat)) {
slouken@7821
   761
                SDL_SystemRAM = (int)(stat.ullTotalPhys / (1024 * 1024));
slouken@7821
   762
            }
slouken@7821
   763
        }
slouken@7821
   764
#endif
icculus@9278
   765
#endif
slouken@7821
   766
    }
slouken@7821
   767
    return SDL_SystemRAM;
slouken@7821
   768
}
slouken@7821
   769
slouken@7821
   770
slouken@739
   771
#ifdef TEST_MAIN
slouken@739
   772
slouken@739
   773
#include <stdio.h>
slouken@739
   774
slouken@1895
   775
int
slouken@1895
   776
main()
slouken@739
   777
{
slouken@3579
   778
    printf("CPU count: %d\n", SDL_GetCPUCount());
slouken@5115
   779
    printf("CPU type: %s\n", SDL_GetCPUType());
slouken@5115
   780
    printf("CPU name: %s\n", SDL_GetCPUName());
slouken@5115
   781
    printf("CacheLine size: %d\n", SDL_GetCPUCacheLineSize());
slouken@1895
   782
    printf("RDTSC: %d\n", SDL_HasRDTSC());
slouken@5389
   783
    printf("Altivec: %d\n", SDL_HasAltiVec());
slouken@1895
   784
    printf("MMX: %d\n", SDL_HasMMX());
slouken@5389
   785
    printf("3DNow: %d\n", SDL_Has3DNow());
slouken@1895
   786
    printf("SSE: %d\n", SDL_HasSSE());
slouken@1895
   787
    printf("SSE2: %d\n", SDL_HasSSE2());
slouken@5259
   788
    printf("SSE3: %d\n", SDL_HasSSE3());
slouken@5263
   789
    printf("SSE4.1: %d\n", SDL_HasSSE41());
slouken@5263
   790
    printf("SSE4.2: %d\n", SDL_HasSSE42());
slouken@8148
   791
    printf("AVX: %d\n", SDL_HasAVX());
slouken@9003
   792
    printf("AVX2: %d\n", SDL_HasAVX2());
slouken@7821
   793
    printf("RAM: %d MB\n", SDL_GetSystemRAM());
slouken@1895
   794
    return 0;
slouken@739
   795
}
slouken@739
   796
slouken@739
   797
#endif /* TEST_MAIN */
slouken@1895
   798
slouken@1895
   799
/* vi: set ts=4 sw=4 expandtab: */