git-svn-id: http://svn2.nishi.boats/svn/milsko/trunk@570 b9cfdab3-6d41-4d17-bbe4-086880011989
This commit is contained in:
NishiOwO
2025-11-02 19:15:38 +00:00
parent 92db649bda
commit 971ef1b827
15 changed files with 767 additions and 796 deletions

View File

@@ -2,13 +2,33 @@
#include <Mw/Milsko.h> #include <Mw/Milsko.h>
int main() { MwWidget cpicker;
MwWidget w = MwVaCreateWidget(MwWindowClass, "main", NULL, MwDEFAULT, MwWidget window;
MwDEFAULT, 640, 480, MwNtitle, "test", NULL); MwWidget button;
MwWidget cpicker = MwColorPicker(w, "cpicker"); void color_callback(MwRGB rgb) {
char hexColor[8];
(void)cpicker; sprintf(hexColor, "#%02X%02X%02X", rgb.r, rgb.g, rgb.b);
MwSetText(window, MwNbackground, hexColor);
MwLoop(w); }
void color_picker(MwWidget handle, void* user_data, void* call_data) {
MwWidget cpicker = MwColorPicker(window, "cpicker", color_callback);
MwSetText(cpicker, MwNbackground, MwDefaultBackground);
}
int main() {
window = MwVaCreateWidget(MwWindowClass, "main", NULL, MwDEFAULT,
MwDEFAULT, 640, 480, MwNtitle, "color picker", NULL);
MwSetText(window, MwNbackground, "#000000");
button = MwVaCreateWidget(MwButtonClass, "button", window, 160, 180, 320, 120,
MwNtext, "change window background",
NULL);
MwSetText(button, MwNbackground, MwDefaultBackground);
MwAddUserHandler(button, MwNactivateHandler, color_picker, NULL);
MwLoop(window);
} }

View File

@@ -15,21 +15,16 @@ extern "C" {
#endif #endif
typedef struct _MwRGB MwRGB; typedef struct _MwRGB MwRGB;
typedef struct _MwHSV MwHSV;
struct _MwRGB { struct _MwRGB {
double r; MwU32 r;
double g; MwU32 g;
double b; MwU32 b;
}; };
struct _MwHSV { typedef void (*MwColorPickerCallback)(MwRGB rgb);
double h; // angle in degrees
double s; // a fraction between 0 and 1
double v; // a fraction between 0 and 1
};
MWDECL MwWidget MwColorPicker(MwWidget handle, const char* title); MWDECL MwWidget MwColorPicker(MwWidget handle, const char* title, MwColorPickerCallback cb);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -143,6 +143,16 @@ MWDECL void MwGetColor(MwLLColor color, int* red, int* green, int* blue);
*/ */
MWDECL MwLLPixmap MwLoadRaw(MwWidget handle, unsigned char* rgb, int width, int height); MWDECL MwLLPixmap MwLoadRaw(MwWidget handle, unsigned char* rgb, int width, int height);
/*!
* @brief Creates a pixmap from raw data
* @param handle Widget
* @param rgb RGBA data
* @param width Width
* @param height Height
* @return Pixmap
*/
MWDECL void MwReloadRaw(MwWidget handle, unsigned char* rgb, int width, int height, MwLLPixmap pixmap);
/*! /*!
* @brief Creates a pixmap from XPM data * @brief Creates a pixmap from XPM data
* @param handle Widget * @param handle Widget

View File

@@ -92,6 +92,7 @@ MWDECL void MwLLPolygon(MwLL handle, MwPoint* points, int points_count, MwLLColo
MWDECL void MwLLLine(MwLL handle, MwPoint* points, MwLLColor color); MWDECL void MwLLLine(MwLL handle, MwPoint* points, MwLLColor color);
MWDECL MwLLColor MwLLAllocColor(MwLL handle, int r, int g, int b); MWDECL MwLLColor MwLLAllocColor(MwLL handle, int r, int g, int b);
MWDECL void MwLLColorUpdate(MwLL handle, int r, int g, int b, MwLLColor c);
MWDECL void MwLLFreeColor(MwLLColor color); MWDECL void MwLLFreeColor(MwLLColor color);
MWDECL void MwLLGetXYWH(MwLL handle, int* x, int* y, unsigned int* w, unsigned int* h); MWDECL void MwLLGetXYWH(MwLL handle, int* x, int* y, unsigned int* w, unsigned int* h);
@@ -105,6 +106,7 @@ MWDECL void MwLLNextEvent(MwLL handle);
MWDECL void MwLLSleep(int ms); MWDECL void MwLLSleep(int ms);
MWDECL MwLLPixmap MwLLCreatePixmap(MwLL handle, unsigned char* data, int width, int height); MWDECL MwLLPixmap MwLLCreatePixmap(MwLL handle, unsigned char* data, int width, int height);
MWDECL void MwLLPixmapUpdate(MwLL handle, MwLLPixmap pixmap);
MWDECL void MwLLDestroyPixmap(MwLLPixmap pixmap); MWDECL void MwLLDestroyPixmap(MwLLPixmap pixmap);
MWDECL void MwLLDrawPixmap(MwLL handle, MwRect* rect, MwLLPixmap pixmap); MWDECL void MwLLDrawPixmap(MwLL handle, MwRect* rect, MwLLPixmap pixmap);
MWDECL void MwLLSetIcon(MwLL handle, MwLLPixmap pixmap); MWDECL void MwLLSetIcon(MwLL handle, MwLLPixmap pixmap);

View File

@@ -1,7 +1,7 @@
/* $Id$ */ /* $Id$ */
/*! /*!
* @file Mw/LowLevelMath.h * @file Mw/LowLevelMath.h
* @brief A few portable functions for supporting simultaneously supporting SIMD and not supporting it * @brief A few portable functions for simultaneously supporting SIMD and not supporting it
* @warning This is mostly used internally. Anything undocumented, and/or anything with an _ prefix (that doesn't have a corresponding typedef) should be avoided. * @warning This is mostly used internally. Anything undocumented, and/or anything with an _ prefix (that doesn't have a corresponding typedef) should be avoided.
*/ */
@@ -12,70 +12,123 @@
#include <Mw/MachDep.h> #include <Mw/MachDep.h>
#if defined(__i386__) || defined(__x86_64__) || defined(__WATCOMC__) #if defined(__i386__) || defined(__x86_64__) || defined(__WATCOMC__)
#define MwLLMathMMX #define MwLLMath_x86
#endif
#if !defined(MwLLMathMMX)
// #warning LowLevelMath.h does not yet support this platform
#endif #endif
/*! /*!
* @brief Generic vector type * @brief SIMD vector
* @warning Do not try to instantiate this yourself, use the appropriate functions instead.
*/ */
typedef struct _MwLLVec MwLLVec; typedef struct _MwLLVec MwLLVec;
typedef union _MwLLVecUnion MwLLVecUnion; /*!
* @brief SIMD vector type
* @warning Not exhaustive, enums subject to be added later.
*/
enum MwLLVecType {
MwLLVecTypeU8 = 0,
MwLLVecTypeU16,
MwLLVecTypeU32,
MwLLVecTypeU64,
MwLLVecTypeI8,
MwLLVecTypeI16,
MwLLVecTypeI32,
MwLLVecTypeI64,
// clang-format off MwLLVecType_Max,
struct _MwLLVecDataU8x8 { MwU8 a; MwU8 b; MwU8 c; MwU8 d; MwU8 e; MwU8 f; MwU8 g; MwU8 h;};
struct _MwLLVecDataU16x4 { MwU16 a; MwU16 b; MwU16 c; MwU16 d;};
struct _MwLLVecDataU32x2 { MwU32 a; MwU32 b;};
struct _MwLLVecDataI8x8 { MwI8 a; MwI8 b; MwI8 c; MwI8 d; MwI8 e; MwI8 f; MwI8 g; MwI8 h;};
struct _MwLLVecDataI16x4 { MwI16 a; MwI16 b; MwI16 c; MwI16 d;};
struct _MwLLVecDataI32x2 { MwI32 a; MwI32 b;};
union _MwLLVecUnion {
struct _MwLLVecDataU8x8 u8; struct _MwLLVecDataU16x4 u16; struct _MwLLVecDataU32x2 u32;
struct _MwLLVecDataI8x8 i8; struct _MwLLVecDataI16x4 i16; struct _MwLLVecDataI32x2 i32;
MwU64 all;
};
// clang-format on
enum _MwLLVecType {
_MwLLVecTypeU8x8 = 0,
_MwLLVecTypeU16x4 = 1,
_MwLLVecTypeU32x2 = 2,
_MwLLVecTypeI8x8 = 3,
_MwLLVecTypeI16x4 = 4,
_MwLLVecTypeI32x2 = 5,
_MwLLVecType_Max,
};
struct _MwLLVec {
int ty;
MwLLVecUnion un;
}; };
MWDECL MwLLVec _MwLLVecCreateGeneric(int ty, ...); /*!
* @brief Create a SIMD Vector (variadic)
* @warning Prefer using the macro version.
*/
MWDECL MwLLVec* MwLLVaVecCreate(int ty, MwU64 size, ...);
#define MwLLVecU8x8(a, b, c, d, e, f, g, h) _MwLLVecCreateGeneric(_MwLLVecTypeU8x8, a, b, c, d, e, f, g, h) /*!
#define MwLLVecU16x4(a, b, c, d) _MwLLVecCreateGeneric(_MwLLVecTypeU16x4, a, b, c, d) * @brief Destroy the given SIMD Vector
#define MwLLVecU32x2(a, b) _MwLLVecCreateGeneric(_MwLLVecTypeU32x2, a, b) */
#define MwLLVecI8x8(a, b, c, d, e, f, g, h) _MwLLVecCreateGeneric(_MwLLVecTypeI8x8, a, b, c, d, e, f, g, h) MWDECL void MwLLVecDestroy(MwLLVec* vec);
#define MwLLVecI16x4(a, b, c, d) _MwLLVecCreateGeneric(_MwLLVecTypeI16x4, a, b, c, d)
#define MwLLVecI32x2(a, b) _MwLLVecCreateGeneric(_MwLLVecTypeI32x2, a, b)
/*!
* @brief index the given SIMD Vector (u8)
*/
MWDECL MwU8 MwLLVecIndexU8(MwLLVec* vec, MwU64 index);
/*!
* @brief index the given SIMD Vector (u16)
*/
MWDECL MwU16 MwLLVecIndexU16(MwLLVec* vec, MwU64 index);
/*!
* @brief index the given SIMD Vector (u32)
*/
MWDECL MwU32 MwLLVecIndexU32(MwLLVec* vec, MwU64 index);
/*!
* @brief index the given SIMD Vector (u64)
*/
MWDECL MwU64 MwLLVecIndexU64(MwLLVec* vec, MwU64 index);
/*!
* @brief index the given SIMD Vector (i8)
*/
MWDECL MwI8 MwLLVecIndexI8(MwLLVec* vec, MwU64 index);
/*!
* @brief index the given SIMD Vector (i16)
*/
MWDECL MwI16 MwLLVecIndexI16(MwLLVec* vec, MwU64 index);
/*!
* @brief index the given SIMD Vector (i32)
*/
MWDECL MwI32 MwLLVecIndexI32(MwLLVec* vec, MwU64 index);
/*!
* @brief index the given SIMD Vector (i64)
*/
MWDECL MwI64 MwLLVecIndexI64(MwLLVec* vec, MwU64 index);
/*!
* @brief SIMD Vector add
*/
MWDECL void MwLLMathAdd(MwLLVec* a, MwLLVec* b, MwLLVec* out); MWDECL void MwLLMathAdd(MwLLVec* a, MwLLVec* b, MwLLVec* out);
/*!
* @brief SIMD Vector multiply
*/
MWDECL void MwLLMathMultiply(MwLLVec* a, MwLLVec* b, MwLLVec* out); MWDECL void MwLLMathMultiply(MwLLVec* a, MwLLVec* b, MwLLVec* out);
/*!
* @brief SIMD Vector subtract
*/
MWDECL void MwLLMathSub(MwLLVec* a, MwLLVec* b, MwLLVec* out); MWDECL void MwLLMathSub(MwLLVec* a, MwLLVec* b, MwLLVec* out);
/*!
* @brief SIMD Vector reciprocal
*/
MWDECL void MwLLMathReciprocal(MwLLVec* a, MwLLVec* out); MWDECL void MwLLMathReciprocal(MwLLVec* a, MwLLVec* out);
/*!
* @brief SIMD Vector square root
*/
MWDECL void MwLLMathSquareRoot(MwLLVec* a, MwLLVec* out); MWDECL void MwLLMathSquareRoot(MwLLVec* a, MwLLVec* out);
/*!
* @brief SIMD Vector bitwise and
*/
MWDECL void MwLLMathAnd(MwLLVec* a, MwLLVec* b, MwLLVec* out); MWDECL void MwLLMathAnd(MwLLVec* a, MwLLVec* b, MwLLVec* out);
/*!
* @brief SIMD Vector bitwise or
*/
MWDECL void MwLLMathOr(MwLLVec* a, MwLLVec* b, MwLLVec* out); MWDECL void MwLLMathOr(MwLLVec* a, MwLLVec* b, MwLLVec* out);
/*!
* @brief SIMD Vector bitwise shift right
*/
MWDECL void MwLLMathShiftRight(MwLLVec* a, MwLLVec* b, MwLLVec* out); MWDECL void MwLLMathShiftRight(MwLLVec* a, MwLLVec* b, MwLLVec* out);
/*!
* @brief SIMD Vector bitwise shift left
*/
MWDECL void MwLLMathShiftLeft(MwLLVec* a, MwLLVec* b, MwLLVec* out); MWDECL void MwLLMathShiftLeft(MwLLVec* a, MwLLVec* b, MwLLVec* out);
/*!
* @brief SIMD Vector bitwise equal
*/
MWDECL void MwLLMathEqual(MwLLVec* a, MwLLVec* b, MwLLVec* out); MWDECL void MwLLMathEqual(MwLLVec* a, MwLLVec* b, MwLLVec* out);
/*!
* @brief SIMD Vector greater then
*/
MWDECL void MwLLMathGreaterThen(MwLLVec* a, MwLLVec* b, MwLLVec* out); MWDECL void MwLLMathGreaterThen(MwLLVec* a, MwLLVec* b, MwLLVec* out);
/*!
* @brief SIMD Vector lesser then
*/
MWDECL void MwLLMathLesserThen(MwLLVec* a, MwLLVec* b, MwLLVec* out); MWDECL void MwLLMathLesserThen(MwLLVec* a, MwLLVec* b, MwLLVec* out);
#endif #endif

View File

@@ -43,8 +43,9 @@ struct _MwLLColor {
}; };
struct _MwLLPixmap { struct _MwLLPixmap {
int width; int width;
int height; int height;
unsigned char* data_scratch_buf;
HBITMAP hBitmap; HBITMAP hBitmap;
HBITMAP hMask; HBITMAP hMask;

View File

@@ -233,6 +233,30 @@ MwLLColor MwLLAllocColor(MwLL handle, int r, int g, int b) {
return c; return c;
} }
void MwLLColorUpdate(MwLL handle, int r, int g, int b, MwLLColor c) {
XColor xc;
if(handle->red_mask == 0) {
if(r > 255) r = 255;
if(g > 255) g = 255;
if(b > 255) b = 255;
if(r < 0) r = 0;
if(g < 0) g = 0;
if(b < 0) b = 0;
xc.red = 256 * r;
xc.green = 256 * g;
xc.blue = 256 * b;
XAllocColor(handle->display, handle->colormap, &xc);
c->pixel = xc.pixel;
} else {
c->pixel = generate_color(handle, r, g, b);
}
c->red = r;
c->green = g;
c->blue = b;
}
void MwLLGetXYWH(MwLL handle, int* x, int* y, unsigned int* w, unsigned int* h) { void MwLLGetXYWH(MwLL handle, int* x, int* y, unsigned int* w, unsigned int* h) {
Window root; Window root;
unsigned int border, depth; unsigned int border, depth;
@@ -435,6 +459,9 @@ MwLLPixmap MwLLCreatePixmap(MwLL handle, unsigned char* data, int width, int hei
int evbase, erbase; int evbase, erbase;
XWindowAttributes attr; XWindowAttributes attr;
r->data_buf = malloc(sizeof(unsigned long) * width * height);
memcpy(r->data_buf, data, sizeof(unsigned long) * width * height);
XGetWindowAttributes(handle->display, handle->window, &attr); XGetWindowAttributes(handle->display, handle->window, &attr);
r->depth = attr.depth; r->depth = attr.depth;
@@ -448,29 +475,38 @@ MwLLPixmap MwLLCreatePixmap(MwLL handle, unsigned char* data, int width, int hei
r->image = XCreateImage(handle->display, DefaultVisual(handle->display, DefaultScreen(handle->display)), r->depth, ZPixmap, 0, di, width, height, 32, width * 4); r->image = XCreateImage(handle->display, DefaultVisual(handle->display, DefaultScreen(handle->display)), r->depth, ZPixmap, 0, di, width, height, 32, width * 4);
r->mask = XCreateImage(handle->display, DefaultVisual(handle->display, DefaultScreen(handle->display)), 1, ZPixmap, 0, dm, width, height, 32, width * 4); r->mask = XCreateImage(handle->display, DefaultVisual(handle->display, DefaultScreen(handle->display)), 1, ZPixmap, 0, dm, width, height, 32, width * 4);
for(y = 0; y < height; y++) { MwLLPixmapUpdate(handle, r);
for(x = 0; x < width; x++) { return r;
unsigned char* px = &data[(y * width + x) * 4]; }
MwLLColor c = MwLLAllocColor(handle, px[0], px[1], px[2]);
unsigned long p = c->pixel;
MwLLFreeColor(c); void MwLLPixmapUpdate(MwLL handle, MwLLPixmap r) {
int y, x;
MwLLColor c = NULL;
for(y = 0; y < r->height; y++) {
for(x = 0; x < r->width; x++) {
unsigned char* px = &r->data_buf[(y * r->width + x) * 4];
if(c == NULL) {
c = MwLLAllocColor(handle, px[0], px[1], px[2]);
} else {
MwLLColorUpdate(handle, px[0], px[1], px[2], c);
}
unsigned long p = c->pixel;
XPutPixel(r->image, x, y, p); XPutPixel(r->image, x, y, p);
*(unsigned long*)(&r->data[(y * width + x) * sizeof(unsigned long)]) = (px[3] << 24) | p; *(unsigned long*)(&r->data[(y * r->width + x) * sizeof(unsigned long)]) = (px[3] << 24) | p;
} }
} }
for(y = 0; y < height; y++) { MwLLFreeColor(c);
for(x = 0; x < width; x++) {
if(data[(y * width + x) * 4 + 3]) { for(y = 0; y < r->height; y++) {
for(x = 0; x < r->width; x++) {
if(r->data_buf[(y * r->width + x) * 4 + 3]) {
XPutPixel(r->mask, x, y, 1); XPutPixel(r->mask, x, y, 1);
} else { } else {
XPutPixel(r->mask, x, y, 0); XPutPixel(r->mask, x, y, 0);
} }
} }
} }
return r;
} }
void MwLLDestroyPixmap(MwLLPixmap pixmap) { void MwLLDestroyPixmap(MwLLPixmap pixmap) {

View File

@@ -55,6 +55,7 @@ struct _MwLLPixmap {
int width; int width;
int height; int height;
unsigned char* data; unsigned char* data;
unsigned char* data_buf;
int depth; int depth;

View File

@@ -4,126 +4,155 @@
#include "color_picker.h" #include "color_picker.h"
#include <Mw/LowLevelMath.h> #include <Mw/LowLevelMath.h>
static MwRGB hsv2rgb(MwHSV in) { static void hsv2rgb(MwU32 h, MwU32 s, MwU32 v, MwU32* r, MwU32* g, MwU32* b) {
MwRGB out; uint8_t sextant = h >> 8;
int i = (int)(floor(in.h * 6)); #define HSV_SWAPPTR(a, b) \
double f = in.h * 6 - i; do { \
double p = in.v * (1 - in.s); MwU32* tmp = a; \
double q = in.v * (1 - f * in.s); a = b; \
double t = in.v * (1 - (1 - f) * in.s); b = tmp; \
} while(0)
switch(i % 6) { if(sextant & 2) {
case 0: HSV_SWAPPTR(r, b);
out.r = in.v, out.g = t, out.b = p; }
break; if(sextant & 4) {
case 1:
out.r = q, out.g = in.v, out.b = p; HSV_SWAPPTR(g, b);
break; }
case 2: if(!(sextant & 6)) {
out.r = p, out.g = in.v, out.b = t; if(!(sextant & 1)) {
break; HSV_SWAPPTR(r, g);
case 3: }
out.r = p, out.g = q, out.b = in.v; } else {
break; if(sextant & 1) {
case 4: HSV_SWAPPTR(r, g);
out.r = t, out.g = p, out.b = in.v; }
break;
case 5:
out.r = in.v, out.g = p, out.b = q;
break;
} }
return out; *g = v; // Top level
// Perform actual calculations
/*
* Bottom level: v * (1.0 - s)
* --> (v * (255 - s) + error_corr + 1) / 256
*/
uint16_t ww; // Intermediate result
ww = v * (255 - (s)); // We don't use ~s to prevent size-promotion side effects
ww += 1; // Error correction
ww += ww >> 8; // Error correction
*b = ww >> 8;
MwU32 h_fraction = h & 0xff; // 0...255
MwU32 d; // Intermediate result
if(!(sextant & 1)) {
// *r = ...slope_up...;
d = v * (MwU32)((0xff << 8) - (MwU16)(s * (0xff - h_fraction)));
*r = d >> 16;
} else {
// *r = ...slope_down...;
d = v * (MwU32)((0xff << 8) - (MwU16)(s * h_fraction));
*r = d >> 16;
}
return;
} }
static void color_picker_wheel_image_update(color_picker* picker) { static void color_picker_image_update(color_picker* picker) {
int y, x; int y, x;
double h;
for(y = 0; y < PICKER_SIZE; y++) { for(y = 0; y < PICKER_SIZE; y++) {
for(x = 0; x < PICKER_SIZE; x++) { for(x = 0; x < PICKER_SIZE; x++) {
int i = ((y * PICKER_SIZE) + x) * 4; int i = ((y * PICKER_SIZE) + x) * 4;
int _x = x - (PICKER_SIZE / 2); int _x = x - (PICKER_SIZE / 2);
int _y = y - (PICKER_SIZE / 2); int _y = y - (PICKER_SIZE / 2);
double dist = sqrt(_x * _x + _y * _y); if(picker->dist_table[y][x] == 0) {
picker->dist_table[y][x] = sqrt(_x * _x + _y * _y);
}
double dist = picker->dist_table[y][x];
if(dist >= 180.) { if(dist >= 180.) {
picker->inner.color_picker_image_data[i] = 0; picker->color_picker_image_data[i] = 0;
picker->inner.color_picker_image_data[i + 1] = 0; picker->color_picker_image_data[i + 1] = 0;
picker->inner.color_picker_image_data[i + 2] = 0; picker->color_picker_image_data[i + 2] = 0;
picker->inner.color_picker_image_data[i + 3] = 0; picker->color_picker_image_data[i + 3] = 0;
} else { } else {
double xd = (M_PI / 180.) * ((double)_x);
double yd = (M_PI / 180.) * ((double)_y);
float angle = atan2(yd, xd) - M_PI;
float hue = (angle * 180.) / M_PI;
MwHSV hsv_v; MwHSV hsv_v;
MwRGB color; if(picker->hue_table[y][x].generated == 0) {
double xd = (M_PI / 180.) * ((double)_x);
double yd = (M_PI / 180.) * ((double)_y);
if(hue < 0.0) { float angle = atan2(yd, xd) - M_PI;
hue += 360; float hue = (angle * 180.) / M_PI;
if(hue < 0.0) {
hue += 360;
}
hsv_v.h = (hue) * (HSV_HUE_STEPS / 360.);
hsv_v.s = (dist) * (HSV_SAT_MAX / 180.);
picker->hue_table[y][x] = hsv_v;
picker->hue_table[y][x].generated = 1;
} }
hsv_v.h = hue / 360.;
hsv_v.s = (dist / 179.61);
hsv_v.v = picker->inner.value;
color = hsv2rgb(hsv_v);
picker->inner.color_picker_image_data[i] = color.r * 255; hsv_v = picker->hue_table[y][x];
picker->inner.color_picker_image_data[i + 1] = color.g * 255; hsv_v.v = HSV_VAL_MAX - (picker->value * HSV_VAL_MAX);
picker->inner.color_picker_image_data[i + 2] = color.b * 255;
picker->inner.color_picker_image_data[i + 3] = 255; MwRGB color;
hsv2rgb(hsv_v.h, hsv_v.s, hsv_v.v, &color.r, &color.g, &color.b);
picker->color_picker_image_data[i] = color.r;
picker->color_picker_image_data[i + 1] = color.g;
picker->color_picker_image_data[i + 2] = color.b;
picker->color_picker_image_data[i + 3] = 255;
} }
} }
} }
if(picker->inner.color_picker_pixmap != NULL) { if(picker->color_picker_pixmap == NULL) {
MwLLDestroyPixmap(picker->inner.color_picker_pixmap); picker->color_picker_pixmap = MwLoadRaw(
picker->parent, picker->color_picker_image_data, PICKER_SIZE, PICKER_SIZE);
} else {
MwReloadRaw(
picker->parent, picker->color_picker_image_data, PICKER_SIZE, PICKER_SIZE, picker->color_picker_pixmap);
} }
picker->inner.color_picker_pixmap = MwLoadRaw( MwVaApply(picker->color_picker_img, MwNpixmap, picker->color_picker_pixmap, NULL);
picker->inner.parent, picker->inner.color_picker_image_data, PICKER_SIZE, PICKER_SIZE);
MwVaApply(picker->inner.color_picker_img, MwNpixmap, picker->inner.color_picker_pixmap, NULL);
} }
static void color_picker_click(MwWidget handle, void* user, void* call) { static void color_picker_click(MwWidget handle, void* user, void* call) {
color_picker* picker = (color_picker*)user; color_picker* picker = (color_picker*)user;
MwLLMouse* mouse = (MwLLMouse*)call; MwLLMouse* mouse = (MwLLMouse*)call;
char* hexColor; char hexColor[8];
int i, r, g, b, a; int i;
char* fgColor; char fgColor[8];
int fr, fg, fb; int fr, fg, fb;
(void)handle; (void)handle;
(void)user; (void)user;
(void)call; (void)call;
color_picker_wheel_image_update(picker); color_picker_image_update(picker);
i = ((mouse->point.y * PICKER_SIZE) + mouse->point.x) * 4; i = ((mouse->point.y * PICKER_SIZE) + mouse->point.x) * 4;
r = picker->inner.color_picker_image_data[i]; picker->chosen_color.r = picker->color_picker_image_data[i];
g = picker->inner.color_picker_image_data[i + 1]; picker->chosen_color.g = picker->color_picker_image_data[i + 1];
b = picker->inner.color_picker_image_data[i + 2]; picker->chosen_color.b = picker->color_picker_image_data[i + 2];
a = picker->inner.color_picker_image_data[i + 3];
(void)a; sprintf(hexColor, "#%02X%02X%02X", picker->chosen_color.r, picker->chosen_color.g, picker->chosen_color.b);
hexColor = malloc(8); fr = picker->chosen_color.r > 128 ? 0 : 255;
fgColor = malloc(8); fg = picker->chosen_color.g > 128 ? 0 : 255;
sprintf(hexColor, "#%02X%02X%02X", r, g, b); fb = picker->chosen_color.b > 128 ? 0 : 255;
fr = r > 128 ? 0 : 255;
fg = g > 128 ? 0 : 255;
fb = b > 128 ? 0 : 255;
sprintf(fgColor, "#%02X%02X%02X", fr, fg, fb); sprintf(fgColor, "#%02X%02X%02X", fr, fg, fb);
MwSetText(picker->inner.color_display, MwNbackground, hexColor); MwSetText(picker->color_display, MwNbackground, hexColor);
MwSetText(picker->inner.color_display_text, MwNforeground, fgColor); MwSetText(picker->color_display_text, MwNforeground, fgColor);
MwSetText(picker->inner.color_display_text, MwNbackground, hexColor); MwSetText(picker->color_display_text, MwNbackground, hexColor);
MwSetText(picker->inner.color_display_text, MwNtext, hexColor); MwSetText(picker->color_display_text, MwNtext, hexColor);
free(hexColor);
} }
static void color_picker_on_change_value(MwWidget handle, void* user, static void color_picker_on_change_value(MwWidget handle, void* user,
void* call) { void* call) {
@@ -135,48 +164,75 @@ static void color_picker_on_change_value(MwWidget handle, void* user,
(void)diff; (void)diff;
(void)call; (void)call;
picker->inner.value = 1.0 - ((double)value / 1024.); picker->value = ((double)value / 1024.);
color_picker_wheel_image_update(picker); color_picker_image_update(picker);
} }
static void color_picker_destroy(color_picker* picker) {
free(picker->color_picker_image_data);
MwLLDestroyPixmap(picker->color_picker_pixmap);
MwDestroyWidget(picker->color_display_text);
MwDestroyWidget(picker->color_display);
MwDestroyWidget(picker->value_slider);
MwDestroyWidget(picker->color_picker_img);
}
static void color_picker_close(MwWidget handle, void* user,
void* call) {
color_picker* picker = (color_picker*)user;
color_picker_destroy(picker);
MwDestroyWidget(handle);
}
static void color_picker_finish(MwWidget handle, void* user,
void* call) {
color_picker* picker = (color_picker*)user;
picker->cb(picker->chosen_color);
color_picker_destroy(picker);
MwDestroyWidget(handle->parent);
}
color_picker* color_picker_setup(MwWidget parent, int w, int h) { color_picker* color_picker_setup(MwWidget parent, int w, int h) {
color_picker* picker = malloc(sizeof(color_picker)); color_picker* picker = malloc(sizeof(color_picker));
memset(picker, 0, sizeof(color_picker)); memset(picker, 0, sizeof(color_picker));
picker->inner.parent = parent; picker->parent = parent;
picker->inner.color_picker_img = picker->color_picker_img =
MwVaCreateWidget(MwImageClass, "image", picker->inner.parent, IMG_POS_X(w), IMG_POS_Y(h), MwVaCreateWidget(MwImageClass, "image", picker->parent, IMG_POS_X(w), IMG_POS_Y(h),
PICKER_SIZE, PICKER_SIZE, NULL); PICKER_SIZE, PICKER_SIZE, NULL);
picker->inner.color_picker_image_data = malloc(PICKER_SIZE * PICKER_SIZE * 4); picker->color_picker_image_data = malloc(PICKER_SIZE * PICKER_SIZE * 4);
picker->inner.color_display_image_data =
malloc(PICKER_SIZE * COLOR_DISPLAY_HEIGHT * 4);
picker->inner.color_picker_pixmap = NULL; picker->color_picker_pixmap = NULL;
picker->inner.color_display_pixmap = NULL; picker->value = 0;
picker->inner.value = 1;
color_picker_wheel_image_update(picker); color_picker_image_update(picker);
MwAddUserHandler(picker->inner.color_picker_img, MwNmouseDownHandler, MwAddUserHandler(picker->color_picker_img, MwNmouseDownHandler,
color_picker_click, picker); color_picker_click, picker);
picker->inner.color_display = MwCreateWidget( picker->color_display = MwCreateWidget(
MwFrameClass, "colorDisplayFrame", picker->inner.parent, IMG_POS_X(w), MwFrameClass, "colorDisplayFrame", picker->parent, IMG_POS_X(w),
IMG_POS_Y(h) + PICKER_SIZE + MARGIN, PICKER_SIZE, PICKER_SIZE / 16); IMG_POS_Y(h) - (PICKER_SIZE / 16) - MARGIN, PICKER_SIZE, PICKER_SIZE / 16);
MwSetText(picker->inner.color_display, MwNbackground, "#000000"); MwSetText(picker->color_display, MwNbackground, "#FFFFFF");
MwSetInteger(picker->inner.color_display, MwnhasBorder, 1); MwSetInteger(picker->color_display, MwnhasBorder, 1);
MwSetInteger(picker->inner.color_display, MwNinverted, 1); MwSetInteger(picker->color_display, MwNinverted, 1);
picker->inner.color_display_text = MwCreateWidget( picker->color_display_text = MwCreateWidget(
MwLabelClass, "colorDisplayFrameText", picker->inner.color_display, MwLabelClass, "colorDisplayFrameText", picker->color_display,
MwDefaultBorderWidth(parent), MwDefaultBorderWidth(parent), MwDefaultBorderWidth(parent), MwDefaultBorderWidth(parent),
PICKER_SIZE - MwDefaultBorderWidth(parent), PICKER_SIZE - MwDefaultBorderWidth(parent),
(PICKER_SIZE / 16) - (MwDefaultBorderWidth(parent) * 2)); (PICKER_SIZE / 16) - (MwDefaultBorderWidth(parent) * 2));
picker->inner.value_slider = MwVaCreateWidget( MwSetText(picker->color_display_text, MwNtext, "#FFFFFF");
MwScrollBarClass, "value-slider", picker->inner.parent,
picker->value_slider = MwVaCreateWidget(
MwScrollBarClass, "value-slider", picker->parent,
// x // x
IMG_POS_X(w) + PICKER_SIZE + MARGIN, IMG_POS_X(w) + PICKER_SIZE + MARGIN,
@@ -191,40 +247,42 @@ color_picker* color_picker_setup(MwWidget parent, int w, int h) {
MwNorientation, MwVERTICAL, MwNminValue, 0, MwNmaxValue, 1024, NULL); MwNorientation, MwVERTICAL, MwNminValue, 0, MwNmaxValue, 1024, NULL);
MwAddUserHandler(picker->inner.value_slider, MwNchangedHandler, MwAddUserHandler(picker->value_slider, MwNchangedHandler,
color_picker_on_change_value, picker); color_picker_on_change_value, picker);
picker->finish = MwCreateWidget(
MwButtonClass, "colorPickerFinish", picker->parent, IMG_POS_X(w),
IMG_POS_Y(h) + PICKER_SIZE + MARGIN, PICKER_SIZE, PICKER_SIZE / 8);
MwSetText(picker->finish, MwNtext, "Select");
MwSetInteger(picker->finish, MwnhasBorder, 1);
MwSetInteger(picker->finish, MwNinverted, 1);
MwAddUserHandler(picker->finish, MwNactivateHandler,
color_picker_finish, picker);
memset(picker->dist_table, 0, sizeof(picker->dist_table));
memset(picker->hue_table, 0, sizeof(picker->hue_table));
return picker; return picker;
}; };
MwWidget MwColorPicker(MwWidget handle, const char* title, MwColorPickerCallback cb) {
MwWidget MwColorPicker(MwWidget handle, const char* title) {
MwPoint p; MwPoint p;
color_picker* wheel; color_picker* wheel;
MwWidget window; MwWidget window;
int ww, wh;
// remove later
MwLLVec test_1 = MwLLVecU32x2(2, 5);
MwLLVec test_2 = MwLLVecU32x2(2, 12);
MwLLVec test_out = MwLLVecU32x2(0, 0);
MwLLMathAdd(&test_1, &test_2, &test_out);
printf("simd result:\n");
printf("%d + %d = %d\n", test_1.un.u32.a, test_2.un.u32.a, test_out.un.u32.a);
printf("%d + %d = %d\n", test_1.un.u32.b, test_2.un.u32.b, test_out.un.u32.b);
ww = MwGetInteger(handle, MwNwidth);
wh = MwGetInteger(handle, MwNheight);
p.x = p.y = 0; p.x = p.y = 0;
window = MwVaCreateWidget(MwWindowClass, "main", handle, MwDEFAULT, MwDEFAULT, window = MwVaCreateWidget(MwWindowClass, "main", handle, MwDEFAULT, MwDEFAULT,
ww, wh, MwNtitle, title, NULL); WIN_SIZE, WIN_SIZE, MwNtitle, title, NULL);
wheel = color_picker_setup(window, ww, wh); wheel = color_picker_setup(window, WIN_SIZE, WIN_SIZE);
MwAddUserHandler(window, MwNcloseHandler, color_picker_close, wheel);
MwLLDetach(window->lowlevel, &p); MwLLDetach(window->lowlevel, &p);
MwLLMakePopup(window->lowlevel, handle->lowlevel); MwLLMakePopup(window->lowlevel, handle->lowlevel);
wheel->cb = cb;
return window; return window;
} }

View File

@@ -6,6 +6,7 @@
#include <Mw/ColorPicker.h> #include <Mw/ColorPicker.h>
#include <Mw/Milsko.h> #include <Mw/Milsko.h>
#define WIN_SIZE 512
#define PICKER_SIZE 360 #define PICKER_SIZE 360
#define IMG_POS_X(w) ((w - PICKER_SIZE) / 2) #define IMG_POS_X(w) ((w - PICKER_SIZE) / 2)
#define IMG_POS_Y(h) ((h - PICKER_SIZE) / 2) #define IMG_POS_Y(h) ((h - PICKER_SIZE) / 2)
@@ -13,31 +14,42 @@
#define MARGIN (PICKER_SIZE / 32) #define MARGIN (PICKER_SIZE / 32)
#define COLOR_DISPLAY_HEIGHT 12 #define COLOR_DISPLAY_HEIGHT 12
#define HSV_HUE_SEXTANT 256.
#define HSV_HUE_STEPS (6. * HSV_HUE_SEXTANT)
#define HSV_HUE_MIN 0.
#define HSV_HUE_MAX (HSV_HUE_STEPS - 1.)
#define HSV_SAT_MIN 0.
#define HSV_SAT_MAX 255.
#define HSV_VAL_MIN 0.
#define HSV_VAL_MAX 255.
typedef struct _color_picker color_picker; typedef struct _color_picker color_picker;
typedef struct _color_picker_inner color_picker_inner;
typedef struct _color_picker_vtable color_picker_vtable; typedef struct _color_picker_vtable color_picker_vtable;
typedef struct _MwHSV MwHSV;
struct _color_picker_inner { struct _MwHSV {
MwWidget parent; double h; // angle in degrees
MwWidget color_picker_img; double s; // a fraction between 0 and 1
MwWidget value_slider; double v; // a fraction between 0 and 1
MwWidget color_display; MwBool generated;
MwWidget color_display_text;
MwLLPixmap color_picker_pixmap;
MwLLPixmap color_display_pixmap;
double value;
unsigned char* color_picker_image_data;
unsigned char* color_display_image_data;
MwPoint point;
};
struct _color_picker_vtable {
void* reserved;
}; };
struct _color_picker { struct _color_picker {
color_picker_inner inner; MwWidget parent;
color_picker_vtable vtable; MwWidget color_picker_img;
MwWidget value_slider;
MwWidget color_display;
MwWidget color_display_text;
MwWidget finish;
MwLLPixmap color_picker_pixmap;
double value;
unsigned char* color_picker_image_data;
MwPoint point;
double dist_table[PICKER_SIZE][PICKER_SIZE];
MwHSV hue_table[PICKER_SIZE][PICKER_SIZE];
MwColorPickerCallback cb;
MwRGB chosen_color;
}; };
color_picker* color_picker_setup(MwWidget parent, int w, int h); color_picker* color_picker_setup(MwWidget parent, int w, int h);

View File

@@ -666,6 +666,34 @@ MwLLPixmap MwLoadRaw(MwWidget handle, unsigned char* rgb, int width, int height)
return px; return px;
} }
void MwReloadRaw(MwWidget handle, unsigned char* rgb, int width, int height, MwLLPixmap px) {
int i;
MwLLColor base = handle->bgcolor == NULL ? MwParseColor(handle, MwGetText(handle, MwNbackground)) : handle->bgcolor;
memset(px->data_buf, 0, width * height * 4);
for(i = 0; i < width * height; i++) {
unsigned char* pin = &rgb[i * 4];
unsigned char* pout = &px->data_buf[i * 4];
double a = pin[3];
a /= 255;
if(a != 0) {
pout[0] = pin[0] * a;
pout[1] = pin[1] * a;
pout[2] = pin[2] * a;
pout[0] += base->red * (1 - a);
pout[1] += base->green * (1 - a);
pout[2] += base->blue * (1 - a);
pout[3] = 255;
}
}
if(handle->bgcolor == NULL) MwLLFreeColor(base);
MwLLPixmapUpdate(handle->lowlevel, px);
}
void MwGetColor(MwLLColor color, int* red, int* green, int* blue) { void MwGetColor(MwLLColor color, int* red, int* green, int* blue) {
*red = color->red; *red = color->red;
*green = color->green; *green = color->green;

View File

@@ -1,424 +1,110 @@
/* $Id$ */ /* $Id$ */
#include <Mw/LowLevelMath.h> #include <Mw/LowLevelMath.h>
#include "math_internal.h" #include "math_internal.h"
static void default_add_u8(MwLLVec* a, MwLLVec* b, MwLLVec* out) { #define MAKE_DEFAULT_TABLE(suffix, ty) \
out->un.u8.a = a->un.u8.a + b->un.u8.a; static void add_##suffix(MwLLVec* a, MwLLVec* b, MwLLVec* out) { \
out->un.u8.b = a->un.u8.b + b->un.u8.b; int i = 0; \
out->un.u8.c = a->un.u8.c + b->un.u8.c; for(; i < a->size; i++) { \
out->un.u8.d = a->un.u8.d + b->un.u8.d; ((ty*)out->buffer)[i] = ((ty*)a->buffer)[i] + ((ty*)b->buffer)[i]; \
out->un.u8.e = a->un.u8.e + b->un.u8.e; } \
out->un.u8.f = a->un.u8.f + b->un.u8.f; }; \
out->un.u8.g = a->un.u8.g + b->un.u8.g; static void sub_##suffix(MwLLVec* a, MwLLVec* b, MwLLVec* out) { \
out->un.u8.h = a->un.u8.h + b->un.u8.h; int i = 0; \
}; for(; i < a->size; i++) { \
static void default_sub_u8(MwLLVec* a, MwLLVec* b, MwLLVec* out) { ((ty*)out->buffer)[i] = ((ty*)a->buffer)[i] - ((ty*)b->buffer)[i]; \
out->un.u8.a = a->un.u8.a - b->un.u8.a; } \
out->un.u8.b = a->un.u8.b - b->un.u8.b; }; \
out->un.u8.c = a->un.u8.c - b->un.u8.c; static void multiply_##suffix(MwLLVec* a, MwLLVec* b, MwLLVec* out) { \
out->un.u8.d = a->un.u8.d - b->un.u8.d; int i = 0; \
out->un.u8.e = a->un.u8.e - b->un.u8.e; for(; i < a->size; i++) { \
out->un.u8.f = a->un.u8.f - b->un.u8.f; ((ty*)out->buffer)[i] = ((ty*)a->buffer)[i] * ((ty*)b->buffer)[i]; \
out->un.u8.g = a->un.u8.g - b->un.u8.g; } \
out->un.u8.h = a->un.u8.h - b->un.u8.h; }; \
}; static void reciprocal_##suffix(MwLLVec* a, MwLLVec* out) { \
static void default_multiply_u8(MwLLVec* a, MwLLVec* b, MwLLVec* out) { int i = 0; \
out->un.u8.a = a->un.u8.a * b->un.u8.a; for(; i < a->size; i++) { \
out->un.u8.b = a->un.u8.b * b->un.u8.b; ((ty*)out->buffer)[i] = pow(((ty*)a->buffer)[i], -1); \
out->un.u8.c = a->un.u8.c * b->un.u8.c; } \
out->un.u8.d = a->un.u8.d * b->un.u8.d; }; \
out->un.u8.e = a->un.u8.e * b->un.u8.e; static void squareRoot_##suffix(MwLLVec* a, MwLLVec* out) { \
out->un.u8.f = a->un.u8.f * b->un.u8.f; int i = 0; \
out->un.u8.g = a->un.u8.g * b->un.u8.g; for(; i < a->size; i++) { \
out->un.u8.h = a->un.u8.h * b->un.u8.h; ((ty*)out->buffer)[i] = sqrt(((ty*)a->buffer)[i]); \
}; } \
static void default_reciprocal_u8(MwLLVec* a, MwLLVec* out) { } \
out->un.u8.a = pow(a->un.u8.a, -1); static void shiftRight_##suffix(MwLLVec* a, MwLLVec* b, MwLLVec* out) { \
out->un.u8.b = pow(a->un.u8.b, -1); int i = 0; \
out->un.u8.c = pow(a->un.u8.c, -1); for(; i < a->size; i++) { \
out->un.u8.d = pow(a->un.u8.d, -1); ((ty*)out->buffer)[i] = ((ty*)a->buffer)[i] >> ((ty*)b->buffer)[i]; \
out->un.u8.e = pow(a->un.u8.e, -1); } \
out->un.u8.f = pow(a->un.u8.f, -1); }; \
out->un.u8.g = pow(a->un.u8.g, -1); static void shiftLeft_##suffix(MwLLVec* a, MwLLVec* b, MwLLVec* out) { \
out->un.u8.h = pow(a->un.u8.h, -1); int i = 0; \
}; for(; i < a->size; i++) { \
static void default_squareRoot_u8(MwLLVec* a, MwLLVec* out) { ((ty*)out->buffer)[i] = ((ty*)a->buffer)[i] << ((ty*)b->buffer)[i]; \
out->un.u8.a = sqrt(a->un.u8.a); } \
out->un.u8.b = sqrt(a->un.u8.b); } \
out->un.u8.c = sqrt(a->un.u8.c); static void equal_##suffix(MwLLVec* a, MwLLVec* b, MwLLVec* out) { \
out->un.u8.d = sqrt(a->un.u8.d); int i = 0; \
out->un.u8.e = sqrt(a->un.u8.e); for(; i < a->size; i++) { \
out->un.u8.f = sqrt(a->un.u8.f); ((ty*)out->buffer)[i] = ((ty*)a->buffer)[i] == ((ty*)b->buffer)[i]; \
out->un.u8.g = sqrt(a->un.u8.g); } \
out->un.u8.h = sqrt(a->un.u8.h); }; \
} static void greaterThen_##suffix(MwLLVec* a, MwLLVec* b, MwLLVec* out) { \
static void default_shiftRight_u8(MwLLVec* a, MwLLVec* b, MwLLVec* out) { int i = 0; \
out->un.u8.a = a->un.u8.a >> b->un.u8.a; for(; i < a->size; i++) { \
out->un.u8.b = a->un.u8.b >> b->un.u8.b; ((ty*)out->buffer)[i] = ((ty*)a->buffer)[i] >= ((ty*)b->buffer)[i]; \
out->un.u8.c = a->un.u8.c >> b->un.u8.c; } \
out->un.u8.d = a->un.u8.d >> b->un.u8.d; }; \
out->un.u8.e = a->un.u8.e >> b->un.u8.e; static MwLLMathVTable table_##suffix = {add_##suffix, multiply_##suffix, sub_##suffix, reciprocal_##suffix, squareRoot_##suffix, NULL, NULL, shiftRight_##suffix, shiftLeft_##suffix, equal_##suffix, greaterThen_##suffix, NULL};
out->un.u8.f = a->un.u8.f >> b->un.u8.f;
out->un.u8.g = a->un.u8.g >> b->un.u8.g;
out->un.u8.h = a->un.u8.h >> b->un.u8.h;
};
static void default_shiftLeft_u8(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.u8.a = a->un.u8.a << b->un.u8.a;
out->un.u8.b = a->un.u8.b << b->un.u8.b;
out->un.u8.c = a->un.u8.c << b->un.u8.c;
out->un.u8.d = a->un.u8.d << b->un.u8.d;
out->un.u8.e = a->un.u8.e << b->un.u8.e;
out->un.u8.f = a->un.u8.f << b->un.u8.f;
out->un.u8.g = a->un.u8.g << b->un.u8.g;
out->un.u8.h = a->un.u8.h << b->un.u8.h;
}
static void default_equal_u8(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.u8.a = a->un.u8.a == b->un.u8.a;
out->un.u8.b = a->un.u8.b == b->un.u8.b;
out->un.u8.c = a->un.u8.c == b->un.u8.c;
out->un.u8.d = a->un.u8.d == b->un.u8.d;
out->un.u8.e = a->un.u8.e == b->un.u8.e;
out->un.u8.f = a->un.u8.f == b->un.u8.f;
out->un.u8.g = a->un.u8.g == b->un.u8.g;
out->un.u8.h = a->un.u8.h == b->un.u8.h;
};
static void default_greaterThen_u8(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.u8.a = a->un.u8.a >= b->un.u8.a;
out->un.u8.b = a->un.u8.b >= b->un.u8.b;
out->un.u8.c = a->un.u8.c >= b->un.u8.c;
out->un.u8.d = a->un.u8.d >= b->un.u8.d;
out->un.u8.e = a->un.u8.e >= b->un.u8.e;
out->un.u8.f = a->un.u8.f >= b->un.u8.f;
out->un.u8.g = a->un.u8.g >= b->un.u8.g;
out->un.u8.h = a->un.u8.h >= b->un.u8.h;
};
static MwLLMathVTable table_u8 = {
default_add_u8,
default_multiply_u8,
default_sub_u8,
default_reciprocal_u8,
default_squareRoot_u8,
NULL,
NULL,
default_shiftRight_u8,
default_shiftLeft_u8,
default_equal_u8,
default_greaterThen_u8,
NULL};
static void default_add_u16(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.u16.a = a->un.u16.a + b->un.u16.a;
out->un.u16.b = a->un.u16.b + b->un.u16.b;
out->un.u16.c = a->un.u16.c + b->un.u16.c;
out->un.u16.d = a->un.u16.d + b->un.u16.d;
}
static void default_sub_u16(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.u16.a = a->un.u16.a - b->un.u16.a;
out->un.u16.b = a->un.u16.b - b->un.u16.b;
out->un.u16.c = a->un.u16.c - b->un.u16.c;
out->un.u16.d = a->un.u16.d - b->un.u16.d;
}
static void default_multiply_u16(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.u16.a = a->un.u16.a * b->un.u16.a;
out->un.u16.b = a->un.u16.b * b->un.u16.b;
out->un.u16.c = a->un.u16.c * b->un.u16.c;
out->un.u16.d = a->un.u16.d * b->un.u16.d;
}
static void default_reciprocal_u16(MwLLVec* a, MwLLVec* out) {
out->un.u16.a = pow(a->un.u16.a, -1);
out->un.u16.b = pow(a->un.u16.b, -1);
out->un.u16.c = pow(a->un.u16.c, -1);
out->un.u16.d = pow(a->un.u16.d, -1);
};
static void default_squareRoot_u16(MwLLVec* a, MwLLVec* out) {
out->un.u16.a = sqrt(a->un.u16.a);
out->un.u16.b = sqrt(a->un.u16.b);
out->un.u16.c = sqrt(a->un.u16.c);
out->un.u16.d = sqrt(a->un.u16.d);
};
static void default_shiftRight_u16(MwLLVec* a, MwLLVec* b, MwLLVec* out) { MAKE_DEFAULT_TABLE(u8, MwU8);
out->un.u16.a = a->un.u16.a >> b->un.u16.a; MAKE_DEFAULT_TABLE(u16, MwU16);
out->un.u16.b = a->un.u16.b >> b->un.u16.b; MAKE_DEFAULT_TABLE(u32, MwU32);
out->un.u16.c = a->un.u16.c >> b->un.u16.c; MAKE_DEFAULT_TABLE(u64, MwU64);
out->un.u16.d = a->un.u16.d >> b->un.u16.d; MAKE_DEFAULT_TABLE(i8, MwI8);
}; MAKE_DEFAULT_TABLE(i16, MwI16);
static void default_shiftLeft_u16(MwLLVec* a, MwLLVec* b, MwLLVec* out) { MAKE_DEFAULT_TABLE(i32, MwI32);
out->un.u16.a = a->un.u16.a << b->un.u16.a; MAKE_DEFAULT_TABLE(i64, MwI64);
out->un.u16.b = a->un.u16.b << b->un.u16.b;
out->un.u16.c = a->un.u16.c << b->un.u16.c;
out->un.u16.d = a->un.u16.d << b->un.u16.d;
}
static void default_equal_u16(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.u16.a = a->un.u16.a == b->un.u16.a;
out->un.u16.b = a->un.u16.b == b->un.u16.b;
out->un.u16.c = a->un.u16.c == b->un.u16.c;
out->un.u16.d = a->un.u16.d == b->un.u16.d;
}
static void default_greaterThen_u16(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.u16.a = a->un.u16.a >= b->un.u16.a;
out->un.u16.b = a->un.u16.b >= b->un.u16.b;
out->un.u16.c = a->un.u16.c >= b->un.u16.c;
out->un.u16.d = a->un.u16.d >= b->un.u16.d;
}
static MwLLMathVTable table_u16 = {
default_add_u16,
default_multiply_u16,
default_sub_u16,
default_reciprocal_u16,
default_squareRoot_u16,
NULL,
NULL,
default_shiftRight_u16,
default_shiftLeft_u16,
default_equal_u16,
default_greaterThen_u16,
NULL};
static void default_add_u32(MwLLVec* a, MwLLVec* b, MwLLVec* out) { static MwLLMathVTable* defaultMultiTable[MwLLVecType_Max] = {
out->un.u32.a = a->un.u32.a + b->un.u32.a; &table_u8, /*MwLLVecTypeU8*/
out->un.u32.b = a->un.u32.b + b->un.u32.b; &table_u16, /*MwLLVecTypeU16*/
} &table_u32, /*MwLLVecTypeU32*/
static void default_sub_u32(MwLLVec* a, MwLLVec* b, MwLLVec* out) { &table_u64, /*MwLLVecTypeU64*/
out->un.u32.a = a->un.u32.a - b->un.u32.a; &table_i8, /*MwLLVecTypeI8*/
out->un.u32.b = a->un.u32.b - b->un.u32.b; &table_i16, /*MwLLVecTypeI16*/
} &table_i32, /*MwLLVecTypeI32*/
static void default_multiply_u32(MwLLVec* a, MwLLVec* b, MwLLVec* out) { &table_i64, /*MwLLVecTypeI64*/
out->un.u32.a = a->un.u32.a * b->un.u32.a;
out->un.u32.b = a->un.u32.b * b->un.u32.b;
}
static void default_reciprocal_u32(MwLLVec* a, MwLLVec* out) {
out->un.u32.a = pow(a->un.u32.a, -1);
out->un.u32.b = pow(a->un.u32.b, -1);
}; };
static void default_squareRoot_u32(MwLLVec* a, MwLLVec* out) { void default_apply(MwLLVec* v) {
out->un.u32.a = sqrt(a->un.u32.a); switch(v->ty) {
out->un.u32.b = sqrt(a->un.u32.b); case MwLLVecTypeU8:
}; v->vtable = table_u8;
break;
static void default_shiftRight_u32(MwLLVec* a, MwLLVec* b, MwLLVec* out) { case MwLLVecTypeU16:
out->un.u32.a = a->un.u32.a >> b->un.u32.a; v->vtable = table_u16;
out->un.u32.b = a->un.u32.b >> b->un.u32.b; break;
}; case MwLLVecTypeU32:
static void default_shiftLeft_u32(MwLLVec* a, MwLLVec* b, MwLLVec* out) { v->vtable = table_u32;
out->un.u32.a = a->un.u32.a << b->un.u32.a; break;
out->un.u32.b = a->un.u32.b << b->un.u32.b; case MwLLVecTypeU64:
} v->vtable = table_u64;
static void default_equal_u32(MwLLVec* a, MwLLVec* b, MwLLVec* out) { break;
out->un.u32.a = a->un.u32.a == b->un.u32.a; case MwLLVecTypeI8:
out->un.u32.b = a->un.u32.b == b->un.u32.b; v->vtable = table_i8;
} break;
static void default_greaterThen_u32(MwLLVec* a, MwLLVec* b, MwLLVec* out) { case MwLLVecTypeI16:
out->un.u32.a = a->un.u32.a >= b->un.u32.a; v->vtable = table_i16;
out->un.u32.b = a->un.u32.b >= b->un.u32.b; break;
} case MwLLVecTypeI32:
static MwLLMathVTable table_u32 = { v->vtable = table_i32;
default_add_u32, break;
default_multiply_u32, case MwLLVecTypeI64:
default_sub_u32, v->vtable = table_i64;
default_reciprocal_u32, break;
default_squareRoot_u32, case MwLLVecType_Max:
NULL, break;
NULL, }
default_shiftRight_u32,
default_shiftLeft_u32,
default_equal_u32,
default_greaterThen_u32,
NULL};
static void default_add_i8(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.i8.a = a->un.i8.a + b->un.i8.a;
out->un.i8.b = a->un.i8.b + b->un.i8.b;
out->un.i8.c = a->un.i8.c + b->un.i8.c;
out->un.i8.d = a->un.i8.d + b->un.i8.d;
out->un.i8.e = a->un.i8.e + b->un.i8.e;
out->un.i8.f = a->un.i8.f + b->un.i8.f;
out->un.i8.g = a->un.i8.g + b->un.i8.g;
out->un.i8.h = a->un.i8.h + b->un.i8.h;
};
static void default_sub_i8(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.i8.a = a->un.i8.a - b->un.i8.a;
out->un.i8.b = a->un.i8.b - b->un.i8.b;
out->un.i8.c = a->un.i8.c - b->un.i8.c;
out->un.i8.d = a->un.i8.d - b->un.i8.d;
out->un.i8.e = a->un.i8.e - b->un.i8.e;
out->un.i8.f = a->un.i8.f - b->un.i8.f;
out->un.i8.g = a->un.i8.g - b->un.i8.g;
out->un.i8.h = a->un.i8.h - b->un.i8.h;
};
static void default_multiply_i8(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.i8.a = a->un.i8.a * b->un.i8.a;
out->un.i8.b = a->un.i8.b * b->un.i8.b;
out->un.i8.c = a->un.i8.c * b->un.i8.c;
out->un.i8.d = a->un.i8.d * b->un.i8.d;
out->un.i8.e = a->un.i8.e * b->un.i8.e;
out->un.i8.f = a->un.i8.f * b->un.i8.f;
out->un.i8.g = a->un.i8.g * b->un.i8.g;
out->un.i8.h = a->un.i8.h * b->un.i8.h;
};
static void default_reciprocal_i8(MwLLVec* a, MwLLVec* out) {
out->un.i8.a = pow(a->un.i8.a, -1);
out->un.i8.b = pow(a->un.i8.b, -1);
out->un.i8.c = pow(a->un.i8.c, -1);
out->un.i8.d = pow(a->un.i8.d, -1);
out->un.i8.e = pow(a->un.i8.e, -1);
out->un.i8.f = pow(a->un.i8.f, -1);
out->un.i8.g = pow(a->un.i8.g, -1);
out->un.i8.h = pow(a->un.i8.h, -1);
};
static void default_squareRoot_i8(MwLLVec* a, MwLLVec* out) {
out->un.i8.a = sqrt(a->un.i8.a);
out->un.i8.b = sqrt(a->un.i8.b);
out->un.i8.c = sqrt(a->un.i8.c);
out->un.i8.d = sqrt(a->un.i8.d);
out->un.i8.e = sqrt(a->un.i8.e);
out->un.i8.f = sqrt(a->un.i8.f);
out->un.i8.g = sqrt(a->un.i8.g);
out->un.i8.h = sqrt(a->un.i8.h);
}
static void default_equal_i8(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.i8.a = a->un.i8.a == b->un.i8.a;
out->un.i8.b = a->un.i8.b == b->un.i8.b;
out->un.i8.c = a->un.i8.c == b->un.i8.c;
out->un.i8.d = a->un.i8.d == b->un.i8.d;
out->un.i8.e = a->un.i8.e == b->un.i8.e;
out->un.i8.f = a->un.i8.f == b->un.i8.f;
out->un.i8.g = a->un.i8.g == b->un.i8.g;
out->un.i8.h = a->un.i8.h == b->un.i8.h;
};
static void default_greaterThen_i8(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.i8.a = a->un.i8.a >= b->un.i8.a;
out->un.i8.b = a->un.i8.b >= b->un.i8.b;
out->un.i8.c = a->un.i8.c >= b->un.i8.c;
out->un.i8.d = a->un.i8.d >= b->un.i8.d;
out->un.i8.e = a->un.i8.e >= b->un.i8.e;
out->un.i8.f = a->un.i8.f >= b->un.i8.f;
out->un.i8.g = a->un.i8.g >= b->un.i8.g;
out->un.i8.h = a->un.i8.h >= b->un.i8.h;
};
static MwLLMathVTable table_i8 = {
default_add_i8,
default_multiply_i8,
default_sub_i8,
default_reciprocal_i8,
default_squareRoot_i8,
NULL,
NULL,
default_shiftRight_u8,
default_shiftLeft_u8,
default_equal_i8,
default_greaterThen_i8,
NULL};
static void default_add_i16(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.i16.a = a->un.i16.a + b->un.i16.a;
out->un.i16.b = a->un.i16.b + b->un.i16.b;
out->un.i16.c = a->un.i16.c + b->un.i16.c;
out->un.i16.d = a->un.i16.d + b->un.i16.d;
}
static void default_sub_i16(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.i16.a = a->un.i16.a - b->un.i16.a;
out->un.i16.b = a->un.i16.b - b->un.i16.b;
out->un.i16.c = a->un.i16.c - b->un.i16.c;
out->un.i16.d = a->un.i16.d - b->un.i16.d;
}
static void default_multiply_i16(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.i16.a = a->un.i16.a * b->un.i16.a;
out->un.i16.b = a->un.i16.b * b->un.i16.b;
out->un.i16.c = a->un.i16.c * b->un.i16.c;
out->un.i16.d = a->un.i16.d * b->un.i16.d;
}
static void default_reciprocal_i16(MwLLVec* a, MwLLVec* out) {
out->un.i16.a = pow(a->un.i16.a, -1);
out->un.i16.b = pow(a->un.i16.b, -1);
out->un.i16.c = pow(a->un.i16.c, -1);
out->un.i16.d = pow(a->un.i16.d, -1);
};
static void default_squareRoot_i16(MwLLVec* a, MwLLVec* out) {
out->un.i16.a = sqrt(a->un.i16.a);
out->un.i16.b = sqrt(a->un.i16.b);
out->un.i16.c = sqrt(a->un.i16.c);
out->un.i16.d = sqrt(a->un.i16.d);
};
static void default_equal_i16(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.i16.a = a->un.i16.a == b->un.i16.a;
out->un.i16.b = a->un.i16.b == b->un.i16.b;
out->un.i16.c = a->un.i16.c == b->un.i16.c;
out->un.i16.d = a->un.i16.d == b->un.i16.d;
}
static void default_greaterThen_i16(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.i16.a = a->un.i16.a >= b->un.i16.a;
out->un.i16.b = a->un.i16.b >= b->un.i16.b;
out->un.i16.c = a->un.i16.c >= b->un.i16.c;
out->un.i16.d = a->un.i16.d >= b->un.i16.d;
}
static MwLLMathVTable table_i16 = {
default_add_i16,
default_multiply_i16,
default_sub_i16,
default_reciprocal_i16,
default_squareRoot_i16,
NULL,
NULL,
default_shiftRight_u16,
default_shiftLeft_u16,
default_equal_i16,
default_greaterThen_i16,
NULL};
static void default_add_i32(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.i32.a = a->un.i32.a + b->un.i32.a;
out->un.i32.b = a->un.i32.b + b->un.i32.b;
}
static void default_sub_i32(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.i32.a = a->un.i32.a - b->un.i32.a;
out->un.i32.b = a->un.i32.b - b->un.i32.b;
}
static void default_multiply_i32(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.i32.a = a->un.i32.a * b->un.i32.a;
out->un.i32.b = a->un.i32.b * b->un.i32.b;
}
static void default_reciprocal_i32(MwLLVec* a, MwLLVec* out) {
out->un.i32.a = pow(a->un.i32.a, -1);
out->un.i32.b = pow(a->un.i32.b, -1);
};
static void default_squareRoot_i32(MwLLVec* a, MwLLVec* out) {
out->un.i32.a = sqrt(a->un.i32.a);
out->un.i32.b = sqrt(a->un.i32.b);
};
static void default_equal_i32(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.i32.a = a->un.i32.a == b->un.i32.a;
out->un.i32.b = a->un.i32.b == b->un.i32.b;
}
static void default_greaterThen_i32(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.i32.a = a->un.i32.a >= b->un.i32.a;
out->un.i32.b = a->un.i32.b >= b->un.i32.b;
}
static MwLLMathVTable table_i32 = {
default_add_i32,
default_multiply_i32,
default_sub_i32,
default_reciprocal_i32,
default_squareRoot_i32,
NULL,
NULL,
default_shiftRight_u32,
default_shiftLeft_u32,
default_equal_i32,
default_greaterThen_i32,
NULL};
static MwLLMathVTable* defaultMultiTable[_MwLLVecType_Max] = {
&table_u8, // _MwLLVecTypeU8x8
&table_u16, // _MwLLVecTypeU16x4
&table_u32, // _MwLLVecTypeU32x2
&table_i8, // _MwLLVecTypeI8x8
&table_i16, // _MwLLVecTypeI16x4
&table_i32, // _MwLLVecTypeI32x2
};
MwLLMathVTable** default_multi_table(void) {
return defaultMultiTable;
} }

View File

@@ -3,45 +3,17 @@
#include "math_internal.h" #include "math_internal.h"
MwLLVec _MwLLVecCreateGeneric(int ty, ...) { #if defined(MwLLMath_x86)
MwLLVecUnion un; struct x86Features {
MwLLVec vec; MwBool mmx;
va_list va; MwBool sse2;
};
va_start(va, ty); static struct x86Features
getCPUFeatures(void) {
// clang-format off MwU32 _eax = 1;
#define _A_B(ty) un.ty.a = va_arg(va, int); un.ty.b = va_arg(va, int); MwU32 _edx;
#define _C_D(ty) un.ty.c = va_arg(va, int); un.ty.d = va_arg(va, int); struct x86Features features;
#define _E_F(ty) un.ty.e = va_arg(va, int); un.ty.f = va_arg(va, int);
#define _G_H(ty) un.ty.g = va_arg(va, int); un.ty.h = va_arg(va, int);
switch(ty) {
case _MwLLVecTypeU8x8: _A_B(u8); _C_D(u8); _E_F(u8); _G_H(u8); break;
case _MwLLVecTypeU16x4: _A_B(u16); _C_D(u16); break;
case _MwLLVecTypeU32x2: _A_B(u32); break;
case _MwLLVecTypeI8x8: _A_B(i8); _C_D(i8); _E_F(i8); _G_H(i8); break;
case _MwLLVecTypeI16x4: _A_B(i16); _C_D(i16); break;
case _MwLLVecTypeI32x2: _A_B(i32); break;
case _MwLLVecType_Max: break;
}
#undef _A_B
#undef _C_D
#undef _E_F
#undef _G_H
// clang-format on
va_end(va);
vec.ty = ty;
vec.un = un;
return vec;
}
#if defined(MwLLMathMMX)
static MwU32 getCPUFeatures(void) {
MwU32 _eax = 1;
MwU32 _edx;
#ifdef __WATCOMC__ #ifdef __WATCOMC__
__asm { __asm {
@@ -56,87 +28,159 @@ static MwU32 getCPUFeatures(void) {
: "a"(1) : "ebx", "ecx"); : "a"(1) : "ebx", "ecx");
#endif #endif
return _edx; if(_edx & FEATX86_MMX) {
features.mmx = MwTRUE;
}
if(_edx & FEATX86_SSE2) {
features.sse2 = MwTRUE;
}
return features;
} }
#endif #endif
static MwLLMathVTable** mwLLMultiTable; static int round_multiple(int num, int mul) {
static MwLLMathVTable* multiTableSetupAndGet(int ty); return ((num + mul - 1) / mul) * mul;
static MwLLMathVTable* multiTableGet(int ty);
static MwLLMathVTable* (*mwLLmathFunc)(int ty) = multiTableSetupAndGet;
static MwLLMathVTable* getMultiTable(int ty) {
return mwLLmathFunc(ty);
} }
static MwLLMathVTable* multiTableSetupAndGet(int ty) { MwLLVec* MwLLVaVecCreate(int ty, MwU64 size, ...) {
#if defined(MwLLMathMMX) struct x86Features features = getCPUFeatures();
MwU32 features; MwLLVec* vec = malloc(sizeof(MwLLVec));
#endif va_list va;
int i = 0;
int size_rounded = size;
mwLLMultiTable = default_multi_table(); memset(vec, 0, sizeof(MwLLVec));
#if defined(MwLLMathMMX) vec->size = size;
features = getCPUFeatures();
printf("Avaliable x86_64 Features:\n");
printf("\tMMX: %s\n", features & FEATX86_MMX ? "true" : "false");
printf("\tSSE: %s\n", features & FEATX86_SSE ? "true" : "false");
printf("\tSSE2: %s\n", features & FEATX86_SSE2 ? "true" : "false");
if(features & FEATX86_MMX) { #ifdef MwLLMath_x86
mmx_apply(mwLLMultiTable); if(features.mmx) {
size_rounded = round_multiple(size, 64);
} }
#endif #endif
mwLLmathFunc = multiTableGet; va_start(va, size);
return mwLLMultiTable[ty]; switch(ty) {
} case MwLLVecTypeU8:
static MwLLMathVTable* multiTableGet(int ty) { case MwLLVecTypeI8:
return mwLLMultiTable[ty]; vec->buffer = malloc(size_rounded * sizeof(MwU8));
memset(vec->buffer, 0, size_rounded);
for(; i < size; i++) {
((MwU8*)vec->buffer)[i] = va_arg(va, int);
}
break;
case MwLLVecTypeU16:
case MwLLVecTypeI16:
vec->buffer = malloc(size_rounded * sizeof(MwU16));
memset(vec->buffer, 0, size_rounded);
for(; i < size; i++) {
((MwU16*)vec->buffer)[i] = va_arg(va, int);
}
break;
case MwLLVecTypeU32:
case MwLLVecTypeI32:
vec->buffer = malloc(size_rounded * sizeof(MwU32));
memset(vec->buffer, 0, size_rounded);
for(; i < size; i++) {
((MwU32*)vec->buffer)[i] = va_arg(va, int);
}
break;
case MwLLVecTypeU64:
case MwLLVecTypeI64:
vec->buffer = malloc(size_rounded * sizeof(MwU64));
memset(vec->buffer, 0, size_rounded);
for(; i < size; i++) {
((MwU64*)vec->buffer)[i] = va_arg(va, int);
}
break;
default:
printf("Unknown MwLLVecType %d\n", ty);
break;
}
va_end(va);
default_apply(vec);
#ifdef MwLLMath_x86
if(features.mmx) {
mmx_apply(vec);
}
#endif
return vec;
} }
// TODO: Flag for telling debug builds so we can selectively take this out
#define dbg_assert(a) assert(a)
void MwLLMathAdd(MwLLVec* a, MwLLVec* b, MwLLVec* out) { void MwLLMathAdd(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
assert(a->ty == b->ty && a->ty == out->ty && b->ty == out->ty); dbg_assert(a->size == b->size && a->size == out->size && b->size && out->size);
getMultiTable(a->ty)->Add(a, b, out); a->vtable.add(a, b, out);
} }
void MwLLMathSub(MwLLVec* a, MwLLVec* b, MwLLVec* out) { void MwLLMathSub(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
assert(a->ty == b->ty && a->ty == out->ty && b->ty == out->ty); dbg_assert(a->size == b->size && a->size == out->size && b->size && out->size);
getMultiTable(a->ty)->Sub(a, b, out); a->vtable.sub(a, b, out);
} }
void MwLLMathMultiply(MwLLVec* a, MwLLVec* b, MwLLVec* out) { void MwLLMathMultiply(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
assert(a->ty == b->ty && a->ty == out->ty && b->ty == out->ty); dbg_assert(a->size == b->size && a->size == out->size && b->size && out->size);
getMultiTable(a->ty)->Multiply(a, b, out); a->vtable.multiply(a, b, out);
} }
void MwLLMathReciprocal(MwLLVec* a, MwLLVec* out) { void MwLLMathReciprocal(MwLLVec* a, MwLLVec* out) {
assert(a->ty == out->ty); dbg_assert(a->size == out->size);
getMultiTable(a->ty)->Reciprocal(a, out); a->vtable.reciprocal(a, out);
} }
void MwLLMathSquareRoot(MwLLVec* a, MwLLVec* out) { void MwLLMathSquareRoot(MwLLVec* a, MwLLVec* out) {
assert(a->ty == out->ty); dbg_assert(a->size == out->size);
getMultiTable(a->ty)->SquareRoot(a, out); a->vtable.squareRoot(a, out);
} }
void MwLLMathShiftRight(MwLLVec* a, MwLLVec* b, MwLLVec* out) { void MwLLMathShiftRight(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
assert(a->ty == b->ty && a->ty == out->ty && b->ty == out->ty); dbg_assert(a->size == b->size && a->size == out->size && b->size && out->size);
getMultiTable(a->ty)->ShiftRight(a, b, out); a->vtable.shiftRight(a, b, out);
} }
void MwLLMathShiftLeft(MwLLVec* a, MwLLVec* b, MwLLVec* out) { void MwLLMathShiftLeft(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
assert(a->ty == b->ty && a->ty == out->ty && b->ty == out->ty); dbg_assert(a->ty == b->ty && a->ty == out->ty && b->ty == out->ty);
getMultiTable(a->ty)->ShiftLeft(a, b, out); a->vtable.shiftLeft(a, b, out);
} }
void MwLLMathEqual(MwLLVec* a, MwLLVec* b, MwLLVec* out) { void MwLLMathEqual(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
assert(a->ty == b->ty && a->ty == out->ty && b->ty == out->ty); dbg_assert(a->size == b->size && a->size == out->size && b->size && out->size);
getMultiTable(a->ty)->Equal(a, b, out);
} }
void MwLLMathGreaterThen(MwLLVec* a, MwLLVec* b, MwLLVec* out) { void MwLLMathGreaterThen(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
assert(a->ty == b->ty && a->ty == out->ty && b->ty == out->ty); dbg_assert(a->size == b->size && a->size == out->size && b->size && out->size);
getMultiTable(a->ty)->GreaterThen(a, b, out); a->vtable.shiftRight(a, b, out);
} }
void MwLLMathAnd(MwLLVec* a, MwLLVec* b, MwLLVec* out) { void MwLLMathAnd(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.all = a->un.all & b->un.all; dbg_assert(a->size == b->size && a->size == out->size && b->size && out->size);
a->vtable.and (a, b, out);
} }
void MwLLMathOr(MwLLVec* a, MwLLVec* b, MwLLVec* out) { void MwLLMathOr(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.all = a->un.all | b->un.all; dbg_assert(a->size == b->size && a->size == out->size && b->size && out->size);
a->vtable.or (a, b, out);
} }
MWDECL MwU8 MwLLVecIndexU8(MwLLVec* vec, MwU64 index) {
return ((MwU8*)vec->buffer)[index];
};
MWDECL MwU16 MwLLVecIndexU16(MwLLVec* vec, MwU64 index) {
return ((MwU16*)vec->buffer)[index];
};
MWDECL MwU32 MwLLVecIndexU32(MwLLVec* vec, MwU64 index) {
return ((MwU32*)vec->buffer)[index];
};
MWDECL MwU64 MwLLVecIndexU64(MwLLVec* vec, MwU64 index) {
return ((MwU64*)vec->buffer)[index];
};
MWDECL MwI8 MwLLVecIndexI8(MwLLVec* vec, MwU64 index) {
return ((MwI8*)vec->buffer)[index];
};
MWDECL MwI16 MwLLVecIndexI16(MwLLVec* vec, MwU64 index) {
return ((MwI16*)vec->buffer)[index];
};
MWDECL MwI32 MwLLVecIndexI32(MwLLVec* vec, MwU64 index) {
return ((MwI32*)vec->buffer)[index];
};
MWDECL MwI64 MwLLVecIndexI64(MwLLVec* vec, MwU64 index) {
return ((MwI64*)vec->buffer)[index];
};

View File

@@ -6,31 +6,38 @@
#include <Mw/BaseTypes.h> #include <Mw/BaseTypes.h>
#include <Mw/LowLevelMath.h> #include <Mw/LowLevelMath.h>
/* Bitfield of cpu features we get from x86's CPUID */
#if defined(MwLLMathMMX)
#define FEATX86_MMX (1 << 23)
#define FEATX86_SSE (1 << 25)
#define FEATX86_SSE2 (1 << 26)
#endif
struct _MwLLMathVTable {
void (*Add)(MwLLVec* a, MwLLVec* b, MwLLVec* out);
void (*Multiply)(MwLLVec* a, MwLLVec* b, MwLLVec* out);
void (*Sub)(MwLLVec* a, MwLLVec* b, MwLLVec* out);
void (*Reciprocal)(MwLLVec* a, MwLLVec* out);
void (*SquareRoot)(MwLLVec* a, MwLLVec* out);
void (*And)(MwLLVec* a, MwLLVec* b, MwLLVec* out);
void (*Or)(MwLLVec* a, MwLLVec* b, MwLLVec* out);
void (*ShiftRight)(MwLLVec* a, MwLLVec* b, MwLLVec* out);
void (*ShiftLeft)(MwLLVec* a, MwLLVec* b, MwLLVec* out);
void (*Equal)(MwLLVec* a, MwLLVec* b, MwLLVec* out);
void (*GreaterThen)(MwLLVec* a, MwLLVec* b, MwLLVec* out);
void (*LesserThen)(MwLLVec* a, MwLLVec* b, MwLLVec* out);
};
typedef struct _MwLLMathVTable MwLLMathVTable; typedef struct _MwLLMathVTable MwLLMathVTable;
MwLLMathVTable** default_multi_table(void); struct _MwLLMathVTable {
void mmx_apply(MwLLMathVTable**); void (*add)(MwLLVec* a, MwLLVec* b, MwLLVec* out);
void (*multiply)(MwLLVec* a, MwLLVec* b, MwLLVec* out);
void (*sub)(MwLLVec* a, MwLLVec* b, MwLLVec* out);
void (*reciprocal)(MwLLVec* a, MwLLVec* out);
void (*squareRoot)(MwLLVec* a, MwLLVec* out);
void (*and)(MwLLVec* a, MwLLVec* b, MwLLVec* out);
void (*or)(MwLLVec* a, MwLLVec* b, MwLLVec* out);
void (*shiftRight)(MwLLVec* a, MwLLVec* b, MwLLVec* out);
void (*shiftLeft)(MwLLVec* a, MwLLVec* b, MwLLVec* out);
void (*equal)(MwLLVec* a, MwLLVec* b, MwLLVec* out);
void (*greaterThen)(MwLLVec* a, MwLLVec* b, MwLLVec* out);
void (*lesserThen)(MwLLVec* a, MwLLVec* b, MwLLVec* out);
};
struct _MwLLVec {
void* buffer;
int ty;
MwU64 size;
MwLLMathVTable vtable;
};
void default_apply(MwLLVec*);
/* Bitfield of cpu features we get from x86's CPUID */
#if defined(MwLLMath_x86)
#define FEATX86_MMX (1 << 23)
// #define FEATX86_SSE (1 << 25)
#define FEATX86_SSE2 (1 << 26)
void mmx_apply(MwLLVec*);
#endif
#endif #endif

View File

@@ -1,111 +1,129 @@
/* $Id$ */ /* $Id$ */
#include <Mw/LowLevelMath.h> #include <Mw/LowLevelMath.h>
#ifdef MwLLMathMMX #ifdef MwLLMath_x86
#include "math_internal.h" #include "math_internal.h"
#include <mmintrin.h> #include <mmintrin.h>
#define DO_MMX_INTRINSIC(intrin, _ty, _rty, _tyn) \ #define DO_MMX_INTRINSIC(intrin, _ty, _cty) \
__m64 m = intrin(*(__m64*)&a->un._ty, *(__m64*)&b->un._ty); \ int i = 0; \
struct _tyn* t = (struct _tyn*)&m; \ for(; i < a->size; i += 8) { \
out->un._rty = *t; __m64 m = intrin(*(__m64*)&a->buffer[i], *(__m64*)&b->buffer[i]); \
memcpy(&((_cty*)out->buffer)[i], &m, sizeof(m)); \
}
static void mmx_add8(MwLLVec* a, MwLLVec* b, MwLLVec* out) { static void mmx_add8(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
DO_MMX_INTRINSIC(_m_paddb, u8, u8, _MwLLVecDataU8x8); DO_MMX_INTRINSIC(_m_paddb, u8, MwU8)
} }
static void mmx_sub8(MwLLVec* a, MwLLVec* b, MwLLVec* out) { static void mmx_sub8(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
DO_MMX_INTRINSIC(_m_psubb, u8, u8, _MwLLVecDataU8x8); DO_MMX_INTRINSIC(_m_psubb, u8, MwU8);
} }
static void mmx_equal8(MwLLVec* a, MwLLVec* b, MwLLVec* out) { static void mmx_equal8(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
DO_MMX_INTRINSIC(_m_pcmpeqb, u8, u8, _MwLLVecDataU8x8); DO_MMX_INTRINSIC(_m_pcmpeqb, u8, MwU8);
} }
static void mmx_add16(MwLLVec* a, MwLLVec* b, MwLLVec* out) { static void mmx_add16(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
DO_MMX_INTRINSIC(_m_paddw, u16, u16, _MwLLVecDataU16x4); DO_MMX_INTRINSIC(_m_paddw, u16, MwU16);
} }
static void mmx_sub16(MwLLVec* a, MwLLVec* b, MwLLVec* out) { static void mmx_sub16(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
DO_MMX_INTRINSIC(_m_psubw, u16, u16, _MwLLVecDataU16x4); DO_MMX_INTRINSIC(_m_psubw, u16, MwU16);
} }
static void mmx_shiftRight16(MwLLVec* a, MwLLVec* b, MwLLVec* out) { static void mmx_shiftRight16(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
DO_MMX_INTRINSIC(_m_psrlw, u16, u16, _MwLLVecDataU16x4); DO_MMX_INTRINSIC(_m_psrlw, u16, MwU16);
} }
static void mmx_shiftLeft16(MwLLVec* a, MwLLVec* b, MwLLVec* out) { static void mmx_shiftLeft16(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
DO_MMX_INTRINSIC(_m_psllw, u16, u16, _MwLLVecDataU16x4); DO_MMX_INTRINSIC(_m_psllw, u16, MwU16);
} }
static void mmx_equal16(MwLLVec* a, MwLLVec* b, MwLLVec* out) { static void mmx_equal16(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
DO_MMX_INTRINSIC(_m_pcmpeqw, u16, u16, _MwLLVecDataU16x4); DO_MMX_INTRINSIC(_m_pcmpeqw, u16, MwU16);
} }
static void mmx_add32(MwLLVec* a, MwLLVec* b, MwLLVec* out) { static void mmx_add32(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
DO_MMX_INTRINSIC(_m_paddd, u32, u32, _MwLLVecDataU32x2); DO_MMX_INTRINSIC(_m_paddd, u32, MwU32);
} }
static void mmx_sub32(MwLLVec* a, MwLLVec* b, MwLLVec* out) { static void mmx_sub32(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
DO_MMX_INTRINSIC(_m_psubd, u32, u32, _MwLLVecDataU32x2); DO_MMX_INTRINSIC(_m_psubd, u32, MwU32);
} }
static void mmx_shiftRight32(MwLLVec* a, MwLLVec* b, MwLLVec* out) { static void mmx_shiftRight32(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
DO_MMX_INTRINSIC(_m_psrld, u32, u32, _MwLLVecDataU32x2); DO_MMX_INTRINSIC(_m_psrld, u32, MwU32);
} }
static void mmx_shiftLeft32(MwLLVec* a, MwLLVec* b, MwLLVec* out) { static void mmx_shiftLeft32(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
DO_MMX_INTRINSIC(_m_pslld, u32, u32, _MwLLVecDataU32x2); DO_MMX_INTRINSIC(_m_pslld, u32, MwU32);
} }
static void mmx_equal32(MwLLVec* a, MwLLVec* b, MwLLVec* out) { static void mmx_equal32(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
DO_MMX_INTRINSIC(_m_pcmpeqw, u32, u32, _MwLLVecDataU32x2); DO_MMX_INTRINSIC(_m_pcmpeqw, u32, MwU32);
} }
static void mmx_addi8(MwLLVec* a, MwLLVec* b, MwLLVec* out) { static void mmx_addi8(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
DO_MMX_INTRINSIC(_m_paddsb, u8, u8, _MwLLVecDataU8x8); DO_MMX_INTRINSIC(_m_paddsb, i8, MwI8);
} }
static void mmx_subi8(MwLLVec* a, MwLLVec* b, MwLLVec* out) { static void mmx_subi8(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
DO_MMX_INTRINSIC(_m_psubsb, u8, u8, _MwLLVecDataU8x8); DO_MMX_INTRINSIC(_m_psubsb, i8, MwI8);
} }
static void mmx_addi16(MwLLVec* a, MwLLVec* b, MwLLVec* out) { static void mmx_addi16(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
DO_MMX_INTRINSIC(_m_paddsw, u16, u16, _MwLLVecDataU16x4); DO_MMX_INTRINSIC(_m_paddsw, i16, MwI16);
} }
static void mmx_subi16(MwLLVec* a, MwLLVec* b, MwLLVec* out) { static void mmx_subi16(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
DO_MMX_INTRINSIC(_m_psubsw, u16, u16, _MwLLVecDataU16x4); DO_MMX_INTRINSIC(_m_psubsw, i16, MwI16);
} }
static void mmx_greaterTheni8(MwLLVec* a, MwLLVec* b, MwLLVec* out) { static void mmx_greaterTheni8(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
DO_MMX_INTRINSIC(_m_pcmpgtb, u8, u8, _MwLLVecDataU8x8); DO_MMX_INTRINSIC(_m_pcmpgtb, i8, MwI8);
} }
static void mmx_greaterTheni16(MwLLVec* a, MwLLVec* b, MwLLVec* out) { static void mmx_greaterTheni16(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
DO_MMX_INTRINSIC(_m_pcmpgtw, u16, u16, _MwLLVecDataU16x4); DO_MMX_INTRINSIC(_m_pcmpgtw, i16, MwI16);
} }
static void mmx_greaterTheni32(MwLLVec* a, MwLLVec* b, MwLLVec* out) { static void mmx_greaterTheni32(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
DO_MMX_INTRINSIC(_m_pcmpgtd, u32, u32, _MwLLVecDataU32x2); DO_MMX_INTRINSIC(_m_pcmpgtd, i32, MwI16);
} }
void mmx_apply(MwLLMathVTable** t) { void mmx_apply(MwLLVec* vec) {
t[_MwLLVecTypeU8x8]->Add = mmx_add8; switch(vec->ty) {
t[_MwLLVecTypeU8x8]->Sub = mmx_sub8; case MwLLVecTypeU8:
// t[_MwLLVecTypeU8x8]->GreaterThen = mmx_greaterThen8; vec->vtable.add = mmx_add8;
t[_MwLLVecTypeU8x8]->Equal = mmx_equal8; vec->vtable.sub = mmx_sub8;
t[_MwLLVecTypeU16x4]->Add = mmx_add16; vec->vtable.equal = mmx_equal8;
t[_MwLLVecTypeU16x4]->Sub = mmx_sub16; break;
t[_MwLLVecTypeU16x4]->ShiftLeft = mmx_shiftLeft16; case MwLLVecTypeU16:
t[_MwLLVecTypeU16x4]->ShiftRight = mmx_shiftRight16; vec->vtable.add = mmx_add16;
// t[_MwLLVecTypeU16x4]->GreaterThen = mmx_greaterThen16; vec->vtable.sub = mmx_sub16;
t[_MwLLVecTypeU16x4]->Equal = mmx_equal16; vec->vtable.shiftLeft = mmx_shiftLeft16;
t[_MwLLVecTypeU32x2]->Add = mmx_add32; vec->vtable.shiftRight = mmx_shiftRight16;
t[_MwLLVecTypeU32x2]->Sub = mmx_sub32; vec->vtable.equal = mmx_equal16;
t[_MwLLVecTypeU32x2]->ShiftLeft = mmx_shiftLeft32; break;
t[_MwLLVecTypeU32x2]->ShiftRight = mmx_shiftRight32; case MwLLVecTypeU32:
// t[_MwLLVecTypeU32x2]->GreaterThen = mmx_greaterThen32; vec->vtable.add = mmx_add32;
t[_MwLLVecTypeU32x2]->Equal = mmx_equal32; vec->vtable.sub = mmx_sub32;
vec->vtable.shiftLeft = mmx_shiftLeft32;
t[_MwLLVecTypeU8x8]->Add = mmx_addi8; vec->vtable.shiftRight = mmx_shiftRight32;
t[_MwLLVecTypeU8x8]->Sub = mmx_subi8; vec->vtable.equal = mmx_equal32;
t[_MwLLVecTypeI8x8]->GreaterThen = mmx_greaterTheni8; break;
t[_MwLLVecTypeI8x8]->Equal = mmx_equal8; case MwLLVecTypeU64:
t[_MwLLVecTypeU16x4]->Add = mmx_addi16; break;
t[_MwLLVecTypeU16x4]->Sub = mmx_subi16; case MwLLVecTypeI8:
t[_MwLLVecTypeI16x4]->ShiftLeft = mmx_shiftLeft16; vec->vtable.add = mmx_addi8;
t[_MwLLVecTypeI16x4]->ShiftRight = mmx_shiftRight16; vec->vtable.sub = mmx_subi8;
t[_MwLLVecTypeI16x4]->GreaterThen = mmx_greaterTheni16; vec->vtable.greaterThen = mmx_greaterTheni8;
t[_MwLLVecTypeI16x4]->Equal = mmx_equal16; vec->vtable.equal = mmx_equal8;
t[_MwLLVecTypeI32x2]->Add = mmx_add32; break;
t[_MwLLVecTypeI32x2]->Sub = mmx_sub32; case MwLLVecTypeI16:
t[_MwLLVecTypeI32x2]->ShiftLeft = mmx_shiftLeft32; vec->vtable.add = mmx_addi16;
t[_MwLLVecTypeI32x2]->ShiftRight = mmx_shiftRight32; vec->vtable.sub = mmx_subi16;
t[_MwLLVecTypeI32x2]->GreaterThen = mmx_greaterTheni32; vec->vtable.shiftLeft = mmx_shiftLeft16;
t[_MwLLVecTypeI32x2]->Equal = mmx_equal32; vec->vtable.shiftRight = mmx_shiftRight16;
vec->vtable.greaterThen = mmx_greaterTheni16;
vec->vtable.equal = mmx_equal16;
break;
case MwLLVecTypeI32:
vec->vtable.add = mmx_add32;
vec->vtable.sub = mmx_sub32;
vec->vtable.shiftLeft = mmx_shiftLeft32;
vec->vtable.shiftRight = mmx_shiftRight32;
vec->vtable.greaterThen = mmx_greaterTheni32;
vec->vtable.equal = mmx_equal32;
break;
case MwLLVecTypeI64:
break;
case MwLLVecType_Max:
break;
}
} }
#endif #endif