/* babl - dynamically extendable universal pixel conversion library.
* Copyright (C) 2005, Øyvind Kolås.
*
* 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 3 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
* .
*/
#include "config.h"
#include "babl-internal.h"
#include "babl-base.h"
static int ref_count = 0;
#ifdef _WIN32
static HMODULE libbabl_dll = NULL;
/* Minimal DllMain that just stores the handle to this DLL */
/* Avoid silly "no previous prototype" gcc warning */
BOOL WINAPI
DllMain (HINSTANCE hinstDLL,
DWORD fdwReason,
LPVOID lpvReserved);
BOOL WINAPI
DllMain (HINSTANCE hinstDLL,
DWORD fdwReason,
LPVOID lpvReserved)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
libbabl_dll = hinstDLL;
break;
}
return TRUE;
}
#else
#define BABL_PATH LIBDIR BABL_DIR_SEPARATOR BABL_LIBRARY
#endif /* _WIN32 */
/*
* Returns a list of directories if the environment variable $BABL_PATH
* is set, or the installation library directory by default.
* This directory will be based on the compilation-time prefix for UNIX
* and an actual DLL path for Windows.
*
* Returns: a string which must be freed after usage.
*/
static char *
babl_dir_list (void)
{
char *ret;
ret = getenv ("BABL_PATH");
if (!ret)
{
#ifdef _WIN32
/* Figure it out from the location of this DLL */
char *filename;
int filename_size;
char *sep1, *sep2;
wchar_t w_filename[MAX_PATH];
DWORD nSize = sizeof (w_filename) / sizeof ((w_filename)[0]);
if (GetModuleFileNameW (libbabl_dll, w_filename, nSize) == 0)
babl_fatal ("GetModuleFilenameW failed");
filename_size = WideCharToMultiByte (CP_UTF8, 0, w_filename, -1, NULL, 0,
NULL, NULL);
filename = babl_malloc (sizeof (char) * filename_size);
if (!WideCharToMultiByte (CP_UTF8, 0, w_filename, -1,
filename, filename_size, NULL, NULL))
babl_fatal ("Converting module filename to UTF-8 failed");
/* If the DLL file name is of the format
* \bin\*.dll, use \lib\{BABL_LIBRARY}.
* Otherwise, use the directory where the DLL is.
*/
sep1 = strrchr (filename, BABL_DIR_SEPARATOR[0]);
*sep1 = '\0';
sep2 = strrchr (filename, BABL_DIR_SEPARATOR[0]);
if (sep2 != NULL)
{
if (strcasecmp (sep2 + 1, "bin") == 0)
{
char* filename_tmp;
*(++sep2) = '\0';
filename_tmp = babl_malloc (sizeof (char) * (strlen (filename) +
strlen (BABL_DIR_SEPARATOR BABL_LIBRARY) + 4));
strcpy (filename_tmp, filename);
babl_free (filename);
strcat (filename_tmp, "lib" BABL_DIR_SEPARATOR BABL_LIBRARY);
filename = filename_tmp;
}
}
ret = filename;
#else
ret = babl_malloc (sizeof (char) * (strlen (BABL_PATH) + 1));
strcpy (ret, BABL_PATH);
#endif
}
else
{
char* ret_tmp = babl_malloc (sizeof (char) * (strlen (ret) + 1));
strcpy (ret_tmp, ret);
ret = ret_tmp;
}
return ret;
}
static void simd_init (void);
void
babl_init (void)
{
babl_cpu_accel_set_use (1);
simd_init ();
if (ref_count++ == 0)
{
char * dir_list;
babl_internal_init ();
babl_sampling_class_init ();
babl_type_db ();
babl_trc_class_init ();
babl_space_class_init ();
babl_component_db ();
babl_model_db ();
babl_format_db ();
babl_conversion_db ();
babl_extension_db ();
babl_fish_db ();
babl_core_init ();
babl_sanity ();
babl_extension_base ();
babl_sanity ();
dir_list = babl_dir_list ();
babl_extension_load_dir_list (dir_list);
babl_free (dir_list);
babl_init_db ();
}
}
void
babl_exit (void)
{
if (!-- ref_count)
{
babl_store_db ();
babl_extension_deinit ();
babl_free (babl_extension_db ());;
babl_free (babl_fish_db ());;
babl_free (babl_conversion_db ());;
babl_free (babl_format_db ());;
babl_free (babl_model_db ());;
babl_free (babl_component_db ());;
babl_free (babl_type_db ());;
babl_internal_destroy ();
#if BABL_DEBUG_MEM
babl_memory_sanity ();
#endif
}
}
#undef babl_model_is
int
babl_model_is (const Babl *babl,
const char *model)
{
return babl && ((babl)==babl_model_with_space(model, babl));
}
#include "babl-cpuaccel.h"
void (*babl_base_init) (void) = babl_base_init_generic;
const Babl * babl_trc_lookup_by_name_generic (const char *name);
const Babl *
babl_trc_new_generic (const char *name,
BablTRCType type,
double gamma,
int n_lut,
float *lut);
void _babl_space_add_universal_rgb_generic (const Babl *space);
void (*_babl_space_add_universal_rgb) (const Babl *space) =
_babl_space_add_universal_rgb_generic;
const Babl *
(*babl_trc_lookup_by_name) (const char *name) = babl_trc_lookup_by_name_generic;
const Babl *
(*babl_trc_new) (const char *name,
BablTRCType type,
double gamma,
int n_lut,
float *lut) = babl_trc_new_generic;
#ifdef ARCH_X86_64
void babl_base_init_x86_64_v2 (void);
void babl_base_init_x86_64_v3 (void);
void _babl_space_add_universal_rgb_x86_64_v2 (const Babl *space);
void _babl_space_add_universal_rgb_x86_64_v3 (const Babl *space);
const Babl *
babl_trc_lookup_by_name_x86_64_v2 (const char *name);
const Babl *
babl_trc_lookup_by_name_x86_64_v3 (const char *name);
const Babl *
babl_trc_new_x86_64_v2 (const char *name,
BablTRCType type,
double gamma,
int n_lut,
float *lut);
const Babl *
babl_trc_new_x86_64_v3 (const char *name,
BablTRCType type,
double gamma,
int n_lut,
float *lut);
#endif
#ifdef ARCH_ARM
void babl_base_init_arm_neon (void);
void _babl_space_add_universal_rgb_arm_neon (const Babl *space);
const Babl *
babl_trc_lookup_by_name_arm_neon (const char *name);
const Babl *
babl_trc_new_arm_neon (const char *name,
BablTRCType type,
double gamma,
int n_lut,
float *lut);
#endif
static void simd_init (void)
{
#ifdef ARCH_X86_64
BablCpuAccelFlags accel = babl_cpu_accel_get_support ();
if ((accel & BABL_CPU_ACCEL_X86_64_V3) == BABL_CPU_ACCEL_X86_64_V3)
{
babl_base_init = babl_base_init_x86_64_v2; /// !!
// this is correct,
// it performs better
// as observed in benchmarking
babl_trc_new = babl_trc_new_x86_64_v2;
babl_trc_lookup_by_name = babl_trc_lookup_by_name_x86_64_v2;
_babl_space_add_universal_rgb = _babl_space_add_universal_rgb_x86_64_v3;
}
else if ((accel & BABL_CPU_ACCEL_X86_64_V2) == BABL_CPU_ACCEL_X86_64_V2)
{
babl_base_init = babl_base_init_x86_64_v2;
babl_trc_new = babl_trc_new_x86_64_v2;
babl_trc_lookup_by_name = babl_trc_lookup_by_name_x86_64_v2;
_babl_space_add_universal_rgb = _babl_space_add_universal_rgb_x86_64_v2;
}
#endif
#ifdef ARCH_ARM
BablCpuAccelFlags accel = babl_cpu_accel_get_support ();
if ((accel & BABL_CPU_ACCEL_ARM_NEON) == BABL_CPU_ACCEL_ARM_NEON)
{
babl_base_init = babl_base_init_arm_neon;
babl_trc_new = babl_trc_new_arm_neon;
babl_trc_lookup_by_name = babl_trc_lookup_by_name_arm_neon;
_babl_space_add_universal_rgb = _babl_space_add_universal_rgb_arm_neon;
}
#endif
}