diff --git a/examples/basic/color_picker.c b/examples/basic/color_picker.c index d93c9cf..5390ca5 100644 --- a/examples/basic/color_picker.c +++ b/examples/basic/color_picker.c @@ -2,13 +2,33 @@ #include -int main() { - MwWidget w = MwVaCreateWidget(MwWindowClass, "main", NULL, MwDEFAULT, - MwDEFAULT, 640, 480, MwNtitle, "test", NULL); +MwWidget cpicker; +MwWidget window; +MwWidget button; - MwWidget cpicker = MwColorPicker(w, "cpicker"); +void color_callback(MwRGB rgb) { + char hexColor[8]; - (void)cpicker; - - MwLoop(w); + sprintf(hexColor, "#%02X%02X%02X", rgb.r, rgb.g, rgb.b); + MwSetText(window, MwNbackground, hexColor); +} + +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); } diff --git a/include/Mw/ColorPicker.h b/include/Mw/ColorPicker.h index 7cea187..51407a8 100644 --- a/include/Mw/ColorPicker.h +++ b/include/Mw/ColorPicker.h @@ -15,21 +15,16 @@ extern "C" { #endif typedef struct _MwRGB MwRGB; -typedef struct _MwHSV MwHSV; struct _MwRGB { - double r; - double g; - double b; + MwU32 r; + MwU32 g; + MwU32 b; }; -struct _MwHSV { - double h; // angle in degrees - double s; // a fraction between 0 and 1 - double v; // a fraction between 0 and 1 -}; +typedef void (*MwColorPickerCallback)(MwRGB rgb); -MWDECL MwWidget MwColorPicker(MwWidget handle, const char* title); +MWDECL MwWidget MwColorPicker(MwWidget handle, const char* title, MwColorPickerCallback cb); #ifdef __cplusplus } diff --git a/include/Mw/Draw.h b/include/Mw/Draw.h index 1c2dbcb..ef029a6 100644 --- a/include/Mw/Draw.h +++ b/include/Mw/Draw.h @@ -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); +/*! + * @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 * @param handle Widget diff --git a/include/Mw/LowLevel.h b/include/Mw/LowLevel.h index 4c8ed01..1775325 100644 --- a/include/Mw/LowLevel.h +++ b/include/Mw/LowLevel.h @@ -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 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 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 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 MwLLDrawPixmap(MwLL handle, MwRect* rect, MwLLPixmap pixmap); MWDECL void MwLLSetIcon(MwLL handle, MwLLPixmap pixmap); diff --git a/include/Mw/LowLevelMath.h b/include/Mw/LowLevelMath.h index fe885c3..84844e9 100644 --- a/include/Mw/LowLevelMath.h +++ b/include/Mw/LowLevelMath.h @@ -1,7 +1,7 @@ /* $Id$ */ /*! * @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. */ @@ -12,70 +12,123 @@ #include #if defined(__i386__) || defined(__x86_64__) || defined(__WATCOMC__) -#define MwLLMathMMX -#endif - -#if !defined(MwLLMathMMX) -// #warning LowLevelMath.h does not yet support this platform +#define MwLLMath_x86 #endif /*! - * @brief Generic vector type - * @warning Do not try to instantiate this yourself, use the appropriate functions instead. + * @brief SIMD vector */ - 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 -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; + MwLLVecType_Max, }; -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) -#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) -#define MwLLVecI16x4(a, b, c, d) _MwLLVecCreateGeneric(_MwLLVecTypeI16x4, a, b, c, d) -#define MwLLVecI32x2(a, b) _MwLLVecCreateGeneric(_MwLLVecTypeI32x2, a, b) +/*! + * @brief Destroy the given SIMD Vector + */ +MWDECL void MwLLVecDestroy(MwLLVec* vec); +/*! + * @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); +/*! + * @brief SIMD Vector multiply + */ MWDECL void MwLLMathMultiply(MwLLVec* a, MwLLVec* b, MwLLVec* out); +/*! + * @brief SIMD Vector subtract + */ MWDECL void MwLLMathSub(MwLLVec* a, MwLLVec* b, MwLLVec* out); +/*! + * @brief SIMD Vector reciprocal + */ MWDECL void MwLLMathReciprocal(MwLLVec* a, MwLLVec* out); +/*! + * @brief SIMD Vector square root + */ MWDECL void MwLLMathSquareRoot(MwLLVec* a, MwLLVec* out); +/*! + * @brief SIMD Vector bitwise and + */ MWDECL void MwLLMathAnd(MwLLVec* a, MwLLVec* b, MwLLVec* out); +/*! + * @brief SIMD Vector bitwise or + */ MWDECL void MwLLMathOr(MwLLVec* a, MwLLVec* b, MwLLVec* out); +/*! + * @brief SIMD Vector bitwise shift right + */ MWDECL void MwLLMathShiftRight(MwLLVec* a, MwLLVec* b, MwLLVec* out); +/*! + * @brief SIMD Vector bitwise shift left + */ MWDECL void MwLLMathShiftLeft(MwLLVec* a, MwLLVec* b, MwLLVec* out); +/*! + * @brief SIMD Vector bitwise equal + */ MWDECL void MwLLMathEqual(MwLLVec* a, MwLLVec* b, MwLLVec* out); +/*! + * @brief SIMD Vector greater then + */ MWDECL void MwLLMathGreaterThen(MwLLVec* a, MwLLVec* b, MwLLVec* out); +/*! + * @brief SIMD Vector lesser then + */ MWDECL void MwLLMathLesserThen(MwLLVec* a, MwLLVec* b, MwLLVec* out); #endif diff --git a/src/backend/gdi.h b/src/backend/gdi.h index c842f02..e01aec1 100644 --- a/src/backend/gdi.h +++ b/src/backend/gdi.h @@ -43,8 +43,9 @@ struct _MwLLColor { }; struct _MwLLPixmap { - int width; - int height; + int width; + int height; + unsigned char* data_scratch_buf; HBITMAP hBitmap; HBITMAP hMask; diff --git a/src/backend/x11.c b/src/backend/x11.c index 3d547b0..4d47109 100644 --- a/src/backend/x11.c +++ b/src/backend/x11.c @@ -233,6 +233,30 @@ MwLLColor MwLLAllocColor(MwLL handle, int r, int g, int b) { 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) { Window root; unsigned int border, depth; @@ -435,6 +459,9 @@ MwLLPixmap MwLLCreatePixmap(MwLL handle, unsigned char* data, int width, int hei int evbase, erbase; 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); 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->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++) { - for(x = 0; x < width; x++) { - unsigned char* px = &data[(y * width + x) * 4]; - MwLLColor c = MwLLAllocColor(handle, px[0], px[1], px[2]); - unsigned long p = c->pixel; + MwLLPixmapUpdate(handle, r); + return r; +} - 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); - *(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++) { - for(x = 0; x < width; x++) { - if(data[(y * width + x) * 4 + 3]) { + MwLLFreeColor(c); + + 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); } else { XPutPixel(r->mask, x, y, 0); } } } - - return r; } void MwLLDestroyPixmap(MwLLPixmap pixmap) { diff --git a/src/backend/x11.h b/src/backend/x11.h index b01c915..e7bd872 100644 --- a/src/backend/x11.h +++ b/src/backend/x11.h @@ -55,6 +55,7 @@ struct _MwLLPixmap { int width; int height; unsigned char* data; + unsigned char* data_buf; int depth; diff --git a/src/color_picker/color_picker.c b/src/color_picker/color_picker.c index 16658d9..6ba092b 100644 --- a/src/color_picker/color_picker.c +++ b/src/color_picker/color_picker.c @@ -4,126 +4,155 @@ #include "color_picker.h" #include -static MwRGB hsv2rgb(MwHSV in) { - MwRGB out; +static void hsv2rgb(MwU32 h, MwU32 s, MwU32 v, MwU32* r, MwU32* g, MwU32* b) { + uint8_t sextant = h >> 8; - int i = (int)(floor(in.h * 6)); - double f = in.h * 6 - i; - double p = in.v * (1 - in.s); - double q = in.v * (1 - f * in.s); - double t = in.v * (1 - (1 - f) * in.s); +#define HSV_SWAPPTR(a, b) \ + do { \ + MwU32* tmp = a; \ + a = b; \ + b = tmp; \ + } while(0) - switch(i % 6) { - case 0: - out.r = in.v, out.g = t, out.b = p; - break; - case 1: - out.r = q, out.g = in.v, out.b = p; - break; - case 2: - out.r = p, out.g = in.v, out.b = t; - break; - case 3: - out.r = p, out.g = q, out.b = in.v; - break; - case 4: - out.r = t, out.g = p, out.b = in.v; - break; - case 5: - out.r = in.v, out.g = p, out.b = q; - break; + if(sextant & 2) { + HSV_SWAPPTR(r, b); + } + if(sextant & 4) { + + HSV_SWAPPTR(g, b); + } + if(!(sextant & 6)) { + if(!(sextant & 1)) { + HSV_SWAPPTR(r, g); + } + } else { + if(sextant & 1) { + HSV_SWAPPTR(r, g); + } } - 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) { - int y, x; +static void color_picker_image_update(color_picker* picker) { + int y, x; + double h; for(y = 0; y < PICKER_SIZE; y++) { for(x = 0; x < PICKER_SIZE; x++) { int i = ((y * PICKER_SIZE) + x) * 4; int _x = x - (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.) { - picker->inner.color_picker_image_data[i] = 0; - picker->inner.color_picker_image_data[i + 1] = 0; - picker->inner.color_picker_image_data[i + 2] = 0; - picker->inner.color_picker_image_data[i + 3] = 0; + picker->color_picker_image_data[i] = 0; + picker->color_picker_image_data[i + 1] = 0; + picker->color_picker_image_data[i + 2] = 0; + picker->color_picker_image_data[i + 3] = 0; } 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; - 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) { - hue += 360; + float angle = atan2(yd, xd) - M_PI; + 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; - picker->inner.color_picker_image_data[i + 1] = color.g * 255; - picker->inner.color_picker_image_data[i + 2] = color.b * 255; + hsv_v = picker->hue_table[y][x]; + hsv_v.v = HSV_VAL_MAX - (picker->value * HSV_VAL_MAX); - 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) { - MwLLDestroyPixmap(picker->inner.color_picker_pixmap); + if(picker->color_picker_pixmap == NULL) { + 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( - 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); + MwVaApply(picker->color_picker_img, MwNpixmap, picker->color_picker_pixmap, NULL); } static void color_picker_click(MwWidget handle, void* user, void* call) { color_picker* picker = (color_picker*)user; MwLLMouse* mouse = (MwLLMouse*)call; - char* hexColor; - int i, r, g, b, a; - char* fgColor; + char hexColor[8]; + int i; + char fgColor[8]; int fr, fg, fb; (void)handle; (void)user; (void)call; - color_picker_wheel_image_update(picker); + color_picker_image_update(picker); i = ((mouse->point.y * PICKER_SIZE) + mouse->point.x) * 4; - r = picker->inner.color_picker_image_data[i]; - g = picker->inner.color_picker_image_data[i + 1]; - b = picker->inner.color_picker_image_data[i + 2]; - a = picker->inner.color_picker_image_data[i + 3]; + picker->chosen_color.r = picker->color_picker_image_data[i]; + picker->chosen_color.g = picker->color_picker_image_data[i + 1]; + picker->chosen_color.b = picker->color_picker_image_data[i + 2]; - (void)a; + sprintf(hexColor, "#%02X%02X%02X", picker->chosen_color.r, picker->chosen_color.g, picker->chosen_color.b); - hexColor = malloc(8); - fgColor = malloc(8); - sprintf(hexColor, "#%02X%02X%02X", r, g, b); - - fr = r > 128 ? 0 : 255; - fg = g > 128 ? 0 : 255; - fb = b > 128 ? 0 : 255; + fr = picker->chosen_color.r > 128 ? 0 : 255; + fg = picker->chosen_color.g > 128 ? 0 : 255; + fb = picker->chosen_color.b > 128 ? 0 : 255; sprintf(fgColor, "#%02X%02X%02X", fr, fg, fb); - MwSetText(picker->inner.color_display, MwNbackground, hexColor); - MwSetText(picker->inner.color_display_text, MwNforeground, fgColor); + MwSetText(picker->color_display, MwNbackground, hexColor); + MwSetText(picker->color_display_text, MwNforeground, fgColor); - MwSetText(picker->inner.color_display_text, MwNbackground, hexColor); - MwSetText(picker->inner.color_display_text, MwNtext, hexColor); - free(hexColor); + MwSetText(picker->color_display_text, MwNbackground, hexColor); + MwSetText(picker->color_display_text, MwNtext, hexColor); } static void color_picker_on_change_value(MwWidget handle, void* user, void* call) { @@ -135,48 +164,75 @@ static void color_picker_on_change_value(MwWidget handle, void* user, (void)diff; (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* picker = malloc(sizeof(color_picker)); memset(picker, 0, sizeof(color_picker)); - picker->inner.parent = parent; + picker->parent = parent; - picker->inner.color_picker_img = - MwVaCreateWidget(MwImageClass, "image", picker->inner.parent, IMG_POS_X(w), IMG_POS_Y(h), + picker->color_picker_img = + MwVaCreateWidget(MwImageClass, "image", picker->parent, IMG_POS_X(w), IMG_POS_Y(h), PICKER_SIZE, PICKER_SIZE, NULL); - picker->inner.color_picker_image_data = malloc(PICKER_SIZE * PICKER_SIZE * 4); - picker->inner.color_display_image_data = - malloc(PICKER_SIZE * COLOR_DISPLAY_HEIGHT * 4); + picker->color_picker_image_data = malloc(PICKER_SIZE * PICKER_SIZE * 4); - picker->inner.color_picker_pixmap = NULL; - picker->inner.color_display_pixmap = NULL; - picker->inner.value = 1; + picker->color_picker_pixmap = NULL; + picker->value = 0; - 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); - picker->inner.color_display = MwCreateWidget( - MwFrameClass, "colorDisplayFrame", picker->inner.parent, IMG_POS_X(w), - IMG_POS_Y(h) + PICKER_SIZE + MARGIN, PICKER_SIZE, PICKER_SIZE / 16); - MwSetText(picker->inner.color_display, MwNbackground, "#000000"); - MwSetInteger(picker->inner.color_display, MwnhasBorder, 1); - MwSetInteger(picker->inner.color_display, MwNinverted, 1); + picker->color_display = MwCreateWidget( + MwFrameClass, "colorDisplayFrame", picker->parent, IMG_POS_X(w), + IMG_POS_Y(h) - (PICKER_SIZE / 16) - MARGIN, PICKER_SIZE, PICKER_SIZE / 16); + MwSetText(picker->color_display, MwNbackground, "#FFFFFF"); + MwSetInteger(picker->color_display, MwnhasBorder, 1); + MwSetInteger(picker->color_display, MwNinverted, 1); - picker->inner.color_display_text = MwCreateWidget( - MwLabelClass, "colorDisplayFrameText", picker->inner.color_display, + picker->color_display_text = MwCreateWidget( + MwLabelClass, "colorDisplayFrameText", picker->color_display, MwDefaultBorderWidth(parent), MwDefaultBorderWidth(parent), PICKER_SIZE - MwDefaultBorderWidth(parent), (PICKER_SIZE / 16) - (MwDefaultBorderWidth(parent) * 2)); - picker->inner.value_slider = MwVaCreateWidget( - MwScrollBarClass, "value-slider", picker->inner.parent, + MwSetText(picker->color_display_text, MwNtext, "#FFFFFF"); + + picker->value_slider = MwVaCreateWidget( + MwScrollBarClass, "value-slider", picker->parent, // x 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); - MwAddUserHandler(picker->inner.value_slider, MwNchangedHandler, + MwAddUserHandler(picker->value_slider, MwNchangedHandler, 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; }; - -MwWidget MwColorPicker(MwWidget handle, const char* title) { +MwWidget MwColorPicker(MwWidget handle, const char* title, MwColorPickerCallback cb) { MwPoint p; color_picker* wheel; 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; 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); MwLLMakePopup(window->lowlevel, handle->lowlevel); + wheel->cb = cb; + return window; } diff --git a/src/color_picker/color_picker.h b/src/color_picker/color_picker.h index fc46714..cb35f21 100644 --- a/src/color_picker/color_picker.h +++ b/src/color_picker/color_picker.h @@ -6,6 +6,7 @@ #include #include +#define WIN_SIZE 512 #define PICKER_SIZE 360 #define IMG_POS_X(w) ((w - PICKER_SIZE) / 2) #define IMG_POS_Y(h) ((h - PICKER_SIZE) / 2) @@ -13,31 +14,42 @@ #define MARGIN (PICKER_SIZE / 32) #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_inner color_picker_inner; typedef struct _color_picker_vtable color_picker_vtable; +typedef struct _MwHSV MwHSV; -struct _color_picker_inner { - MwWidget parent; - MwWidget color_picker_img; - MwWidget value_slider; - MwWidget color_display; - 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 _MwHSV { + double h; // angle in degrees + double s; // a fraction between 0 and 1 + double v; // a fraction between 0 and 1 + MwBool generated; }; struct _color_picker { - color_picker_inner inner; - color_picker_vtable vtable; + MwWidget parent; + 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); diff --git a/src/draw.c b/src/draw.c index 0349696..989cef3 100644 --- a/src/draw.c +++ b/src/draw.c @@ -666,6 +666,34 @@ MwLLPixmap MwLoadRaw(MwWidget handle, unsigned char* rgb, int width, int height) 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) { *red = color->red; *green = color->green; diff --git a/src/math/default.c b/src/math/default.c index c5f2ae4..cf8fa73 100644 --- a/src/math/default.c +++ b/src/math/default.c @@ -1,424 +1,110 @@ /* $Id$ */ #include - #include "math_internal.h" -static void default_add_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_sub_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_multiply_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_reciprocal_u8(MwLLVec* a, MwLLVec* out) { - out->un.u8.a = pow(a->un.u8.a, -1); - out->un.u8.b = pow(a->un.u8.b, -1); - out->un.u8.c = pow(a->un.u8.c, -1); - out->un.u8.d = pow(a->un.u8.d, -1); - 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); - out->un.u8.h = pow(a->un.u8.h, -1); -}; -static void default_squareRoot_u8(MwLLVec* a, MwLLVec* out) { - 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); - out->un.u8.d = sqrt(a->un.u8.d); - out->un.u8.e = sqrt(a->un.u8.e); - out->un.u8.f = sqrt(a->un.u8.f); - out->un.u8.g = sqrt(a->un.u8.g); - out->un.u8.h = sqrt(a->un.u8.h); -} -static void default_shiftRight_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_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); -}; +#define MAKE_DEFAULT_TABLE(suffix, ty) \ + static void add_##suffix(MwLLVec* a, MwLLVec* b, MwLLVec* out) { \ + int i = 0; \ + for(; i < a->size; i++) { \ + ((ty*)out->buffer)[i] = ((ty*)a->buffer)[i] + ((ty*)b->buffer)[i]; \ + } \ + }; \ + static void sub_##suffix(MwLLVec* a, MwLLVec* b, MwLLVec* out) { \ + int i = 0; \ + for(; i < a->size; i++) { \ + ((ty*)out->buffer)[i] = ((ty*)a->buffer)[i] - ((ty*)b->buffer)[i]; \ + } \ + }; \ + static void multiply_##suffix(MwLLVec* a, MwLLVec* b, MwLLVec* out) { \ + int i = 0; \ + for(; i < a->size; i++) { \ + ((ty*)out->buffer)[i] = ((ty*)a->buffer)[i] * ((ty*)b->buffer)[i]; \ + } \ + }; \ + static void reciprocal_##suffix(MwLLVec* a, MwLLVec* out) { \ + int i = 0; \ + for(; i < a->size; i++) { \ + ((ty*)out->buffer)[i] = pow(((ty*)a->buffer)[i], -1); \ + } \ + }; \ + static void squareRoot_##suffix(MwLLVec* a, MwLLVec* out) { \ + int i = 0; \ + for(; i < a->size; i++) { \ + ((ty*)out->buffer)[i] = sqrt(((ty*)a->buffer)[i]); \ + } \ + } \ + static void shiftRight_##suffix(MwLLVec* a, MwLLVec* b, MwLLVec* out) { \ + int i = 0; \ + for(; i < a->size; i++) { \ + ((ty*)out->buffer)[i] = ((ty*)a->buffer)[i] >> ((ty*)b->buffer)[i]; \ + } \ + }; \ + static void shiftLeft_##suffix(MwLLVec* a, MwLLVec* b, MwLLVec* out) { \ + int i = 0; \ + for(; i < a->size; i++) { \ + ((ty*)out->buffer)[i] = ((ty*)a->buffer)[i] << ((ty*)b->buffer)[i]; \ + } \ + } \ + static void equal_##suffix(MwLLVec* a, MwLLVec* b, MwLLVec* out) { \ + int i = 0; \ + for(; i < a->size; i++) { \ + ((ty*)out->buffer)[i] = ((ty*)a->buffer)[i] == ((ty*)b->buffer)[i]; \ + } \ + }; \ + static void greaterThen_##suffix(MwLLVec* a, MwLLVec* b, MwLLVec* out) { \ + int i = 0; \ + for(; i < a->size; i++) { \ + ((ty*)out->buffer)[i] = ((ty*)a->buffer)[i] >= ((ty*)b->buffer)[i]; \ + } \ + }; \ + 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}; -static void default_shiftRight_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_shiftLeft_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_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}; +MAKE_DEFAULT_TABLE(u8, MwU8); +MAKE_DEFAULT_TABLE(u16, MwU16); +MAKE_DEFAULT_TABLE(u32, MwU32); +MAKE_DEFAULT_TABLE(u64, MwU64); +MAKE_DEFAULT_TABLE(i8, MwI8); +MAKE_DEFAULT_TABLE(i16, MwI16); +MAKE_DEFAULT_TABLE(i32, MwI32); +MAKE_DEFAULT_TABLE(i64, MwI64); -static void default_add_u32(MwLLVec* a, MwLLVec* b, MwLLVec* out) { - 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_sub_u32(MwLLVec* a, MwLLVec* b, MwLLVec* out) { - 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_multiply_u32(MwLLVec* a, MwLLVec* b, MwLLVec* out) { - 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 MwLLMathVTable* defaultMultiTable[MwLLVecType_Max] = { + &table_u8, /*MwLLVecTypeU8*/ + &table_u16, /*MwLLVecTypeU16*/ + &table_u32, /*MwLLVecTypeU32*/ + &table_u64, /*MwLLVecTypeU64*/ + &table_i8, /*MwLLVecTypeI8*/ + &table_i16, /*MwLLVecTypeI16*/ + &table_i32, /*MwLLVecTypeI32*/ + &table_i64, /*MwLLVecTypeI64*/ }; -static void default_squareRoot_u32(MwLLVec* a, MwLLVec* out) { - out->un.u32.a = sqrt(a->un.u32.a); - out->un.u32.b = sqrt(a->un.u32.b); -}; - -static void default_shiftRight_u32(MwLLVec* a, MwLLVec* b, MwLLVec* out) { - 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_shiftLeft_u32(MwLLVec* a, MwLLVec* b, MwLLVec* out) { - 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_equal_u32(MwLLVec* a, MwLLVec* b, MwLLVec* out) { - 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_greaterThen_u32(MwLLVec* a, MwLLVec* b, MwLLVec* out) { - 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 MwLLMathVTable table_u32 = { - default_add_u32, - default_multiply_u32, - default_sub_u32, - default_reciprocal_u32, - default_squareRoot_u32, - NULL, - 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; +void default_apply(MwLLVec* v) { + switch(v->ty) { + case MwLLVecTypeU8: + v->vtable = table_u8; + break; + case MwLLVecTypeU16: + v->vtable = table_u16; + break; + case MwLLVecTypeU32: + v->vtable = table_u32; + break; + case MwLLVecTypeU64: + v->vtable = table_u64; + break; + case MwLLVecTypeI8: + v->vtable = table_i8; + break; + case MwLLVecTypeI16: + v->vtable = table_i16; + break; + case MwLLVecTypeI32: + v->vtable = table_i32; + break; + case MwLLVecTypeI64: + v->vtable = table_i64; + break; + case MwLLVecType_Max: + break; + } } diff --git a/src/math/math.c b/src/math/math.c index 470ce46..6a00fd2 100644 --- a/src/math/math.c +++ b/src/math/math.c @@ -3,45 +3,17 @@ #include "math_internal.h" -MwLLVec _MwLLVecCreateGeneric(int ty, ...) { - MwLLVecUnion un; - MwLLVec vec; - va_list va; +#if defined(MwLLMath_x86) +struct x86Features { + MwBool mmx; + MwBool sse2; +}; - va_start(va, ty); - - // clang-format off -#define _A_B(ty) un.ty.a = va_arg(va, int); un.ty.b = va_arg(va, int); -#define _C_D(ty) un.ty.c = va_arg(va, int); un.ty.d = va_arg(va, int); -#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; +static struct x86Features +getCPUFeatures(void) { + MwU32 _eax = 1; + MwU32 _edx; + struct x86Features features; #ifdef __WATCOMC__ __asm { @@ -56,87 +28,159 @@ static MwU32 getCPUFeatures(void) { : "a"(1) : "ebx", "ecx"); #endif - return _edx; + if(_edx & FEATX86_MMX) { + features.mmx = MwTRUE; + } + if(_edx & FEATX86_SSE2) { + features.sse2 = MwTRUE; + } + return features; } #endif -static MwLLMathVTable** mwLLMultiTable; -static MwLLMathVTable* multiTableSetupAndGet(int ty); -static MwLLMathVTable* multiTableGet(int ty); - -static MwLLMathVTable* (*mwLLmathFunc)(int ty) = multiTableSetupAndGet; - -static MwLLMathVTable* getMultiTable(int ty) { - return mwLLmathFunc(ty); +static int round_multiple(int num, int mul) { + return ((num + mul - 1) / mul) * mul; } -static MwLLMathVTable* multiTableSetupAndGet(int ty) { -#if defined(MwLLMathMMX) - MwU32 features; -#endif +MwLLVec* MwLLVaVecCreate(int ty, MwU64 size, ...) { + struct x86Features features = getCPUFeatures(); + MwLLVec* vec = malloc(sizeof(MwLLVec)); + va_list va; + int i = 0; + int size_rounded = size; - mwLLMultiTable = default_multi_table(); + memset(vec, 0, sizeof(MwLLVec)); -#if defined(MwLLMathMMX) - 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"); + vec->size = size; - if(features & FEATX86_MMX) { - mmx_apply(mwLLMultiTable); +#ifdef MwLLMath_x86 + if(features.mmx) { + size_rounded = round_multiple(size, 64); } #endif - mwLLmathFunc = multiTableGet; + va_start(va, size); - return mwLLMultiTable[ty]; -} -static MwLLMathVTable* multiTableGet(int ty) { - return mwLLMultiTable[ty]; + switch(ty) { + case MwLLVecTypeU8: + case MwLLVecTypeI8: + 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) { - assert(a->ty == b->ty && a->ty == out->ty && b->ty == out->ty); - getMultiTable(a->ty)->Add(a, b, out); + dbg_assert(a->size == b->size && a->size == out->size && b->size && out->size); + a->vtable.add(a, b, out); } void MwLLMathSub(MwLLVec* a, MwLLVec* b, MwLLVec* out) { - assert(a->ty == b->ty && a->ty == out->ty && b->ty == out->ty); - getMultiTable(a->ty)->Sub(a, b, out); + dbg_assert(a->size == b->size && a->size == out->size && b->size && out->size); + a->vtable.sub(a, b, out); } void MwLLMathMultiply(MwLLVec* a, MwLLVec* b, MwLLVec* out) { - assert(a->ty == b->ty && a->ty == out->ty && b->ty == out->ty); - getMultiTable(a->ty)->Multiply(a, b, out); + dbg_assert(a->size == b->size && a->size == out->size && b->size && out->size); + a->vtable.multiply(a, b, out); } void MwLLMathReciprocal(MwLLVec* a, MwLLVec* out) { - assert(a->ty == out->ty); - getMultiTable(a->ty)->Reciprocal(a, out); + dbg_assert(a->size == out->size); + a->vtable.reciprocal(a, out); } void MwLLMathSquareRoot(MwLLVec* a, MwLLVec* out) { - assert(a->ty == out->ty); - getMultiTable(a->ty)->SquareRoot(a, out); + dbg_assert(a->size == out->size); + a->vtable.squareRoot(a, out); } void MwLLMathShiftRight(MwLLVec* a, MwLLVec* b, MwLLVec* out) { - assert(a->ty == b->ty && a->ty == out->ty && b->ty == out->ty); - getMultiTable(a->ty)->ShiftRight(a, b, out); + dbg_assert(a->size == b->size && a->size == out->size && b->size && out->size); + a->vtable.shiftRight(a, b, out); } void MwLLMathShiftLeft(MwLLVec* a, MwLLVec* b, MwLLVec* out) { - assert(a->ty == b->ty && a->ty == out->ty && b->ty == out->ty); - getMultiTable(a->ty)->ShiftLeft(a, b, out); + dbg_assert(a->ty == b->ty && a->ty == out->ty && b->ty == out->ty); + a->vtable.shiftLeft(a, b, out); } void MwLLMathEqual(MwLLVec* a, MwLLVec* b, MwLLVec* out) { - assert(a->ty == b->ty && a->ty == out->ty && b->ty == out->ty); - getMultiTable(a->ty)->Equal(a, b, out); + dbg_assert(a->size == b->size && a->size == out->size && b->size && out->size); } void MwLLMathGreaterThen(MwLLVec* a, MwLLVec* b, MwLLVec* out) { - assert(a->ty == b->ty && a->ty == out->ty && b->ty == out->ty); - getMultiTable(a->ty)->GreaterThen(a, b, out); + dbg_assert(a->size == b->size && a->size == out->size && b->size && out->size); + a->vtable.shiftRight(a, b, 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) { - 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]; +}; diff --git a/src/math/math_internal.h b/src/math/math_internal.h index 915092c..6011616 100644 --- a/src/math/math_internal.h +++ b/src/math/math_internal.h @@ -6,31 +6,38 @@ #include #include -/* 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; -MwLLMathVTable** default_multi_table(void); -void mmx_apply(MwLLMathVTable**); +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); +}; + +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 diff --git a/src/math/mmx.c b/src/math/mmx.c index 8acd85e..31743ce 100644 --- a/src/math/mmx.c +++ b/src/math/mmx.c @@ -1,111 +1,129 @@ /* $Id$ */ #include -#ifdef MwLLMathMMX +#ifdef MwLLMath_x86 #include "math_internal.h" #include -#define DO_MMX_INTRINSIC(intrin, _ty, _rty, _tyn) \ - __m64 m = intrin(*(__m64*)&a->un._ty, *(__m64*)&b->un._ty); \ - struct _tyn* t = (struct _tyn*)&m; \ - out->un._rty = *t; +#define DO_MMX_INTRINSIC(intrin, _ty, _cty) \ + int i = 0; \ + for(; i < a->size; i += 8) { \ + __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) { - 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) { - 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) { - 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) { - 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) { - 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) { - 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) { - 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) { - 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) { - 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) { - 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) { - 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) { - 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) { - 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) { - 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) { - 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) { - 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) { - 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) { - 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) { - 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) { - DO_MMX_INTRINSIC(_m_pcmpgtd, u32, u32, _MwLLVecDataU32x2); + DO_MMX_INTRINSIC(_m_pcmpgtd, i32, MwI16); } -void mmx_apply(MwLLMathVTable** t) { - t[_MwLLVecTypeU8x8]->Add = mmx_add8; - t[_MwLLVecTypeU8x8]->Sub = mmx_sub8; - // t[_MwLLVecTypeU8x8]->GreaterThen = mmx_greaterThen8; - t[_MwLLVecTypeU8x8]->Equal = mmx_equal8; - t[_MwLLVecTypeU16x4]->Add = mmx_add16; - t[_MwLLVecTypeU16x4]->Sub = mmx_sub16; - t[_MwLLVecTypeU16x4]->ShiftLeft = mmx_shiftLeft16; - t[_MwLLVecTypeU16x4]->ShiftRight = mmx_shiftRight16; - // t[_MwLLVecTypeU16x4]->GreaterThen = mmx_greaterThen16; - t[_MwLLVecTypeU16x4]->Equal = mmx_equal16; - t[_MwLLVecTypeU32x2]->Add = mmx_add32; - t[_MwLLVecTypeU32x2]->Sub = mmx_sub32; - t[_MwLLVecTypeU32x2]->ShiftLeft = mmx_shiftLeft32; - t[_MwLLVecTypeU32x2]->ShiftRight = mmx_shiftRight32; - // t[_MwLLVecTypeU32x2]->GreaterThen = mmx_greaterThen32; - t[_MwLLVecTypeU32x2]->Equal = mmx_equal32; - - t[_MwLLVecTypeU8x8]->Add = mmx_addi8; - t[_MwLLVecTypeU8x8]->Sub = mmx_subi8; - t[_MwLLVecTypeI8x8]->GreaterThen = mmx_greaterTheni8; - t[_MwLLVecTypeI8x8]->Equal = mmx_equal8; - t[_MwLLVecTypeU16x4]->Add = mmx_addi16; - t[_MwLLVecTypeU16x4]->Sub = mmx_subi16; - t[_MwLLVecTypeI16x4]->ShiftLeft = mmx_shiftLeft16; - t[_MwLLVecTypeI16x4]->ShiftRight = mmx_shiftRight16; - t[_MwLLVecTypeI16x4]->GreaterThen = mmx_greaterTheni16; - t[_MwLLVecTypeI16x4]->Equal = mmx_equal16; - t[_MwLLVecTypeI32x2]->Add = mmx_add32; - t[_MwLLVecTypeI32x2]->Sub = mmx_sub32; - t[_MwLLVecTypeI32x2]->ShiftLeft = mmx_shiftLeft32; - t[_MwLLVecTypeI32x2]->ShiftRight = mmx_shiftRight32; - t[_MwLLVecTypeI32x2]->GreaterThen = mmx_greaterTheni32; - t[_MwLLVecTypeI32x2]->Equal = mmx_equal32; +void mmx_apply(MwLLVec* vec) { + switch(vec->ty) { + case MwLLVecTypeU8: + vec->vtable.add = mmx_add8; + vec->vtable.sub = mmx_sub8; + vec->vtable.equal = mmx_equal8; + break; + case MwLLVecTypeU16: + vec->vtable.add = mmx_add16; + vec->vtable.sub = mmx_sub16; + vec->vtable.shiftLeft = mmx_shiftLeft16; + vec->vtable.shiftRight = mmx_shiftRight16; + vec->vtable.equal = mmx_equal16; + break; + case MwLLVecTypeU32: + vec->vtable.add = mmx_add32; + vec->vtable.sub = mmx_sub32; + vec->vtable.shiftLeft = mmx_shiftLeft32; + vec->vtable.shiftRight = mmx_shiftRight32; + vec->vtable.equal = mmx_equal32; + break; + case MwLLVecTypeU64: + break; + case MwLLVecTypeI8: + vec->vtable.add = mmx_addi8; + vec->vtable.sub = mmx_subi8; + vec->vtable.greaterThen = mmx_greaterTheni8; + vec->vtable.equal = mmx_equal8; + break; + case MwLLVecTypeI16: + vec->vtable.add = mmx_addi16; + vec->vtable.sub = mmx_subi16; + vec->vtable.shiftLeft = mmx_shiftLeft16; + 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